From c47231c0885510fd8edfa3d36d8e3840d837835f Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Mon, 21 Sep 2026 18:02:13 +0000 Subject: [PATCH 01/11] Import complete markovprocess proof development --- LeanPool.lean | 1 + LeanPool/MarkovProcess.lean | 282 +++++ LeanPool/MarkovProcess/MarkovProcess.lean | 254 ++++ .../MarkovProcess/MarkovProcess/Analysis.lean | 14 + .../MarkovProcess/Analysis/ExpPrimitive.lean | 472 +++++++ .../MarkovProcess/Analysis/PaleyZygmund.lean | 134 ++ .../MarkovProcess/Continuity.lean | 25 + .../DenseTimeContinuousExtension.lean | 116 ++ .../Continuity/DenseTimeContinuousLaw.lean | 95 ++ .../DenseTimeContinuousSupport.lean | 57 + .../Continuity/DyadicChaining.lean | 345 +++++ .../MarkovProcess/Continuity/DyadicFloor.lean | 781 ++++++++++++ .../Continuity/DyadicIncrements.lean | 246 ++++ .../Continuity/DyadicPathChaining.lean | 314 +++++ .../GlobalDyadicFloorModification.lean | 259 ++++ .../KolmogorovDenseTimeContinuousSupport.lean | 74 ++ .../Continuity/KolmogorovTimeShift.lean | 100 ++ .../MarkovProcess/Continuity/PathModulus.lean | 276 ++++ .../Continuity/PathTightness.lean | 336 +++++ .../Continuity/ShiftedUnitModification.lean | 104 ++ .../MarkovProcess/DenseTime.lean | 26 + .../DenseTime/CanonicalDiscreteLaw.lean | 78 ++ .../DenseTime/CanonicalDiscretePath.lean | 111 ++ .../DenseTime/CemeteryDenseTimeMarginals.lean | 42 + .../DenseTime/CemeteryExtension.lean | 150 +++ .../DenseTime/CemeterySemigroup.lean | 206 +++ .../DenseTime/ConditionalKernel.lean | 139 ++ .../PhysicalCompactTestTransport.lean | 145 +++ .../DenseTime/PhysicalReindex.lean | 86 ++ .../MarkovProcess/DenseTime/PrefixKernel.lean | 119 ++ .../DenseTime/PrefixRecursion.lean | 187 +++ .../MarkovProcess/DenseTime/Shift.lean | 89 ++ .../MarkovProcess/DenseTime/Trajectory.lean | 353 ++++++ .../DenseTime/TrajectoryMarginals.lean | 110 ++ .../DenseTime/TwoPointMarginals.lean | 336 +++++ .../MarkovProcess/MarkovProcess/Examples.lean | 18 + .../Examples/BrownianMotion.lean | 429 +++++++ .../MarkovProcess/Examples/Drift.lean | 244 ++++ .../MarkovProcess/Examples/HeatGenerator.lean | 426 +++++++ .../MarkovProcess/Examples/HeatOnePoint.lean | 169 +++ .../MarkovProcess/Examples/HeatSemigroup.lean | 539 ++++++++ .../MarkovProcess/Examples/Identity.lean | 194 +++ .../MarkovProcess/MarkovProcess/Feller.lean | 28 + .../Feller/BackwardC0Convergence.lean | 93 ++ .../Feller/BackwardC0Integral.lean | 127 ++ .../Feller/BackwardC0Recursion.lean | 87 ++ .../CoordinatePolynomialContinuity.lean | 119 ++ .../Feller/CoordinateProductContinuity.lean | 117 ++ .../DensePhysicalFiniteSetContinuity.lean | 79 ++ .../FiniteDenseApproximationContinuity.lean | 61 + .../FiniteSetCompactTestContinuity.lean | 39 + .../Feller/FiniteSetConvergence.lean | 87 ++ .../FiniteTimeCompactTestContinuity.lean | 209 +++ .../Feller/FiniteTimeContinuityBase.lean | 43 + .../Feller/FiniteTimeConvergence.lean | 375 ++++++ .../FiniteTimeJointCompactTestContinuity.lean | 359 ++++++ .../Feller/FiniteTimeKernelContinuity.lean | 110 ++ .../MarkovProcess/Feller/Resolvent.lean | 173 +++ .../MarkovProcess/Feller/Semigroup.lean | 99 ++ .../MarkovProcess/FiniteTime.lean | 30 + .../CoordinateProductActiveReduction.lean | 106 ++ .../CoordinateProductNormalization.lean | 122 ++ .../DenseTimeFiniteSetKernelShift.lean | 72 ++ .../FiniteTime/DenseTimeFiniteShift.lean | 91 ++ ...iteProductCompactSupportApproximation.lean | 126 ++ .../FiniteProductCoordinateNormalForm.lean | 163 +++ .../FiniteProductStoneWeierstrass.lean | 132 ++ .../FiniteSetKernelCompactTestTransport.lean | 142 +++ .../FiniteTime/FiniteSetKernelShift.lean | 183 +++ .../MarkovProcess/FiniteTime/Kernel.lean | 124 ++ .../FiniteTime/KernelConcatenation.lean | 429 +++++++ .../FiniteTime/KernelDeletion.lean | 169 +++ .../FiniteTime/KernelEquivariance.lean | 306 +++++ .../FiniteTime/KernelMixedPullback.lean | 81 ++ .../FiniteTime/KernelRestriction.lean | 87 ++ .../MarkovProcess/FiniteTime/KernelShift.lean | 56 + ...easureFiniteRestrictionIdentification.lean | 47 + .../FiniteTime/ProjectiveFamily.lean | 128 ++ .../MarkovProcess/MarkovProcess/Kernel.lean | 42 + .../MarkovProcess/Kernel/Basic.lean | 75 ++ .../MarkovProcess/Kernel/C0.lean | 139 ++ .../Kernel/C0SemigroupJoint.lean | 44 + .../MarkovProcess/Kernel/CompProdReindex.lean | 96 ++ .../Kernel/ConservativeResolvent.lean | 155 +++ .../Kernel/ConservativityAE.lean | 96 ++ .../FiniteRestrictionIdentification.lean | 50 + .../MarkovProcess/Kernel/Integral.lean | 59 + .../MarkovProcess/Kernel/KernelSemigroup.lean | 127 ++ .../Kernel/KolmogorovMoments.lean | 75 ++ .../MarkovProcess/Kernel/Lp.lean | 216 ++++ .../MarkovProcess/Kernel/LpConsistency.lean | 63 + .../MarkovProcess/Kernel/LpFinite.lean | 123 ++ .../MarkovProcess/Kernel/LpTop.lean | 69 + .../Kernel/MeasurableRadonFamily.lean | 165 +++ .../Kernel/OnePointConservative.lean | 82 ++ .../Kernel/OnePointExtension.lean | 593 +++++++++ .../MarkovProcess/Kernel/OnePointKilled.lean | 784 ++++++++++++ .../Kernel/OnePointKolmogorov.lean | 537 ++++++++ .../MarkovProcess/Kernel/Operator.lean | 109 ++ .../Kernel/OperatorSemigroup.lean | 149 +++ .../Kernel/PositiveC0OperatorKernel.lean | 158 +++ .../Kernel/PositiveC0OperatorMass.lean | 71 ++ .../Kernel/PositiveC0OperatorMeasure.lean | 119 ++ .../Kernel/PositiveC0Resolvent.lean | 124 ++ .../Kernel/PositiveC0SemigroupFeller.lean | 92 ++ .../Kernel/PositiveC0SemigroupKernel.lean | 119 ++ .../MarkovProcess/Kernel/Resolvent.lean | 156 +++ .../Kernel/ResolventUniqueness.lean | 351 ++++++ .../MarkovProcess/Kernel/WeakConvergence.lean | 135 ++ .../MarkovProcess/MarkovProcess/Killed.lean | 30 + .../Killed/ExitTimeIdentification.lean | 210 +++ .../MarkovProcess/Killed/GluingC0.lean | 266 ++++ .../MarkovProcess/Killed/GluingLinearity.lean | 152 +++ .../MarkovProcess/Killed/GluingLocal.lean | 287 +++++ .../MarkovProcess/Killed/GluingMeasure.lean | 157 +++ .../MarkovProcess/Killed/GluingMinimal.lean | 343 +++++ .../MarkovProcess/Killed/GluingPotential.lean | 281 +++++ .../Killed/GluingRealResolvent.lean | 406 ++++++ .../Killed/GluingResolventEquation.lean | 280 ++++ .../MarkovProcess/Killed/GluingTransfer.lean | 133 ++ .../MarkovProcess/Killed/Kernel.lean | 242 ++++ .../MarkovProcess/Killed/KillAtExit.lean | 210 +++ .../MarkovProcess/Killed/Marginals.lean | 403 ++++++ .../MarkovProcess/Killed/Minimal.lean | 115 ++ .../MarkovProcess/Killed/Nested.lean | 267 ++++ .../MarkovProcess/Killed/Process.lean | 152 +++ .../MarkovProcess/Killed/Resolvent.lean | 130 ++ .../MarkovProcess/Killed/Semigroup.lean | 178 +++ .../MarkovProcess/MarkovProcess/Lifetime.lean | 22 + .../MarkovProcess/Lifetime/Basic.lean | 235 ++++ .../Lifetime/CountablySeparated.lean | 126 ++ .../MarkovProcess/Lifetime/ExitTime.lean | 110 ++ .../Lifetime/ExitTimeStopping.lean | 307 +++++ .../MarkovProcess/Lifetime/Filtration.lean | 89 ++ .../MarkovProcess/Lifetime/Killing.lean | 110 ++ .../MarkovProcess/Lifetime/Law.lean | 80 ++ .../MarkovProcess/Lifetime/Nonexplosion.lean | 94 ++ .../Lifetime/NonexplosiveTransport.lean | 159 +++ .../MarkovProcess/Lifetime/Shift.lean | 137 ++ .../MarkovProcess/MarkovProcess/Main.lean | 405 ++++++ .../MarkovProcess/Parameterized.lean | 28 + .../MarkovProcess/Parameterized/Annealed.lean | 135 ++ .../CemeteryDenseTimeMarginals.lean | 44 + .../CemeteryDenseTimeSupport.lean | 64 + .../Parameterized/CemeterySemigroup.lean | 85 ++ .../Parameterized/ContinuousProcess.lean | 273 ++++ .../ContinuousProcessProperties.lean | 265 ++++ .../DenseTimeConditionalKernel.lean | 103 ++ .../Parameterized/DenseTimePrefixKernel.lean | 102 ++ .../Parameterized/DenseTimeTrajectory.lean | 548 ++++++++ .../DenseTimeTrajectoryMarginals.lean | 72 ++ .../Parameterized/Equivariance.lean | 195 +++ .../Parameterized/FiniteTimeKernel.lean | 194 +++ .../FiniteTimeProjectiveFamily.lean | 107 ++ .../MarkovProcess/Parameterized/Killed.lean | 111 ++ .../Parameterized/OrderedGrid.lean | 111 ++ .../Parameterized/Semigroup.lean | 156 +++ .../MarkovProcess/MarkovProcess/Path.lean | 33 + .../MarkovProcess/Path/Basic.lean | 87 ++ .../Path/ClosedSetDetection.lean | 324 +++++ .../MarkovProcess/Path/DenseFiltration.lean | 109 ++ .../Path/DenseRestrictionIntegral.lean | 39 + .../MarkovProcess/Path/Exhaustion.lean | 98 ++ .../MarkovProcess/Path/ExitTime.lean | 284 +++++ .../MarkovProcess/Path/ExitTimeShift.lean | 126 ++ .../Path/KernelIdentification.lean | 79 ++ .../Path/MeasureIdentification.lean | 63 + .../Path/MixedFiniteMarginals.lean | 75 ++ .../MarkovProcess/Path/OptionalStopping.lean | 311 +++++ .../MarkovProcess/Path/Polish.lean | 37 + .../Path/RandomShiftMeasurability.lean | 71 ++ .../RandomTimeCompactTestConvergence.lean | 86 ++ .../MarkovProcess/Path/RelativeHitting.lean | 200 +++ .../MarkovProcess/Path/Sampling.lean | 175 +++ .../MarkovProcess/Path/Shift.lean | 94 ++ .../Path/ShiftCompactTestConvergence.lean | 86 ++ .../Path/StoppedValueMeasurability.lean | 51 + .../MarkovProcess/Path/Stopping.lean | 76 ++ .../Path/StoppingTimeDyadicCeiling.lean | 177 +++ .../MarkovProcess/MarkovProcess/Restart.lean | 21 + .../Restart/ConditionalExpectation.lean | 81 ++ .../Restart/ConditionalMarkov.lean | 67 + .../Restart/CountableStoppingRestart.lean | 189 +++ .../CountableStoppingRestartMeasure.lean | 122 ++ .../Restart/FinitePastRestart.lean | 112 ++ .../Restart/MixedPastFuture.lean | 1122 +++++++++++++++++ .../Restart/RationalRestart.lean | 535 ++++++++ .../Restart/RationalRestrictedRestart.lean | 94 ++ .../Restart/RestrictedRestartOfJoint.lean | 54 + .../MarkovProcess/Semigroup.lean | 37 + .../MarkovProcess/Semigroup/Basic.lean | 103 ++ .../Semigroup/CompactStrongConvergence.lean | 75 ++ .../Semigroup/ContractiveResolvent.lean | 146 +++ .../Semigroup/DenseCoreConvergence.lean | 102 ++ .../MarkovProcess/Semigroup/Duhamel.lean | 119 ++ .../Semigroup/ExponentialBounds.lean | 102 ++ .../Semigroup/ExponentialComparison.lean | 229 ++++ .../MarkovProcess/Semigroup/Generation.lean | 99 ++ .../MarkovProcess/Semigroup/Generator.lean | 471 +++++++ .../Semigroup/GeneratorClosed.lean | 101 ++ .../Semigroup/GeneratorInjectivity.lean | 117 ++ .../Semigroup/GeneratorResolvent.lean | 179 +++ .../Semigroup/GeneratorUniqueness.lean | 148 +++ .../MarkovProcess/Semigroup/InvariantSet.lean | 164 +++ .../Semigroup/OrbitContinuity.lean | 102 ++ .../Semigroup/OrbitProductRule.lean | 88 ++ .../Semigroup/PoissonInvariant.lean | 194 +++ .../Semigroup/PositiveShift.lean | 61 + .../MarkovProcess/Semigroup/Resolvent.lean | 314 +++++ .../Semigroup/ResolventComparison.lean | 140 ++ .../Semigroup/ResolventGeneration.lean | 86 ++ .../Semigroup/StrongOperatorLimit.lean | 122 ++ .../MarkovProcess/Semigroup/TrotterKato.lean | 224 ++++ .../Semigroup/YosidaApproximation.lean | 152 +++ .../Semigroup/YosidaStrongLimit.lean | 174 +++ .../MarkovProcess/MarkovProcess/Time.lean | 20 + .../Time/CountableDenseTime.lean | 146 +++ .../Time/DenseTimeApproximationFromAbove.lean | 37 + .../MarkovProcess/Time/DenseTimeHistory.lean | 97 ++ .../Time/FiniteDenseApproximationOrdered.lean | 118 ++ .../Time/FiniteGridIncrement.lean | 93 ++ .../Time/FiniteOrderEmbedding.lean | 65 + .../Time/FiniteOrderedTimes.lean | 145 +++ .../MarkovProcess/Time/OrderedGrid.lean | 128 ++ .../MarkovProcess/Trajectory.lean | 54 + .../Trajectory/AllTimeFiniteMarginals.lean | 342 +++++ .../Trajectory/AllTimeMarginals.lean | 140 ++ .../MarkovProcess/Trajectory/Basic.lean | 134 ++ .../Trajectory/ClampedCoordinate.lean | 43 + .../MarkovProcess/Trajectory/Convergence.lean | 96 ++ .../Trajectory/CylinderAlgebra.lean | 208 +++ .../Trajectory/DenseRestrictionIntegral.lean | 85 ++ .../Trajectory/DenseRestrictionMarginals.lean | 71 ++ .../Trajectory/DenseStoppingRestart.lean | 78 ++ .../Trajectory/DiscountedDynkin.lean | 628 +++++++++ .../MarkovProcess/Trajectory/Dynkin.lean | 164 +++ .../Trajectory/DynkinMartingale.lean | 376 ++++++ .../Trajectory/DynkinStopping.lean | 290 +++++ .../Trajectory/Equivariance.lean | 296 +++++ .../Trajectory/ExcessiveStopping.lean | 424 +++++++ .../MarkovProcess/Trajectory/ExitLaw.lean | 225 ++++ .../Trajectory/ExitTimeExponentialMoment.lean | 517 ++++++++ .../Trajectory/ExitTimeLaplace.lean | 253 ++++ .../Trajectory/ExpectedExitTime.lean | 153 +++ .../Trajectory/FellerConditional.lean | 62 + .../FellerCountableStoppingRestart.lean | 67 + .../Trajectory/FellerFiniteMarginals.lean | 61 + .../Trajectory/FellerRestrictedRestart.lean | 196 +++ .../MarkovProcess/Trajectory/FellerShift.lean | 116 ++ .../Trajectory/FellerStoppingConditional.lean | 73 ++ .../Trajectory/FellerStoppingRestart.lean | 132 ++ .../MarkovProcess/Trajectory/FeynmanKac.lean | 17 + .../Trajectory/FeynmanKacFunctional.lean | 649 ++++++++++ .../Trajectory/FeynmanKacRealResolvent.lean | 750 +++++++++++ .../Trajectory/FeynmanKacResolvent.lean | 748 +++++++++++ .../Trajectory/FiniteMarginals.lean | 194 +++ .../Trajectory/HarmonicRepresentation.lean | 187 +++ .../MarkovProcess/Trajectory/PathModulus.lean | 175 +++ .../Trajectory/PathTightness.lean | 108 ++ .../Trajectory/PenalizationDomination.lean | 109 ++ .../Trajectory/RationalConditional.lean | 125 ++ .../Trajectory/RationalShift.lean | 116 ++ .../ResolventExitDecomposition.lean | 308 +++++ .../Trajectory/StartingPointContinuity.lean | 211 ++++ .../Trajectory/StoppingLtTop.lean | 590 +++++++++ .../Trajectory/WeakContinuity.lean | 203 +++ .../Trajectory/WeakConvergence.lean | 223 ++++ LeanPool/projects.yml | 33 + 268 files changed, 46968 insertions(+) create mode 100644 LeanPool/MarkovProcess.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Analysis.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Analysis/ExpPrimitive.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Analysis/PaleyZygmund.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousExtension.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousLaw.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousSupport.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicChaining.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicFloor.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicIncrements.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicPathChaining.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/GlobalDyadicFloorModification.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovDenseTimeContinuousSupport.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/PathModulus.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/PathTightness.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Continuity/ShiftedUnitModification.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscreteLaw.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscretePath.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryDenseTimeMarginals.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryExtension.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeterySemigroup.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/ConditionalKernel.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalReindex.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/Shift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/TrajectoryMarginals.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/DenseTime/TwoPointMarginals.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Examples.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Examples/Drift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Examples/HeatGenerator.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Examples/HeatSemigroup.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Examples/Identity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Convergence.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Recursion.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinateProductContinuity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/DensePhysicalFiniteSetContinuity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteDenseApproximationContinuity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetCompactTestContinuity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetConvergence.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeCompactTestContinuity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeContinuityBase.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeKernelContinuity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/Resolvent.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductActiveReduction.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductNormalization.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteSetKernelShift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteShift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductStoneWeierstrass.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelShift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/Kernel.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelDeletion.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelEquivariance.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelMixedPullback.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelRestriction.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelShift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/MeasureFiniteRestrictionIdentification.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/ProjectiveFamily.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/Basic.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/C0.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/C0SemigroupJoint.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/CompProdReindex.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativeResolvent.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativityAE.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/FiniteRestrictionIdentification.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/Integral.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/KernelSemigroup.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/KolmogorovMoments.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/LpConsistency.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/LpTop.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/MeasurableRadonFamily.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointConservative.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKilled.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/Operator.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorKernel.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMass.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMeasure.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0Resolvent.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupFeller.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupKernel.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/Resolvent.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/ResolventUniqueness.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Kernel/WeakConvergence.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/ExitTimeIdentification.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/GluingC0.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLinearity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLocal.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMeasure.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMinimal.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/GluingPotential.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/GluingRealResolvent.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/GluingResolventEquation.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/GluingTransfer.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/Kernel.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/KillAtExit.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/Minimal.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/Resolvent.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Killed/Semigroup.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Lifetime.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Lifetime/Basic.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Lifetime/CountablySeparated.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTime.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTimeStopping.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Lifetime/Killing.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Lifetime/Law.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Lifetime/Nonexplosion.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Lifetime/NonexplosiveTransport.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Main.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeMarginals.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeSupport.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeterySemigroup.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcess.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcessProperties.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeConditionalKernel.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimePrefixKernel.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectoryMarginals.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/Equivariance.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeKernel.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeProjectiveFamily.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/Killed.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/OrderedGrid.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Parameterized/Semigroup.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/Basic.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/DenseFiltration.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/DenseRestrictionIntegral.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/Exhaustion.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/ExitTime.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/ExitTimeShift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/KernelIdentification.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/MeasureIdentification.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/MixedFiniteMarginals.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/OptionalStopping.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/Polish.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/RandomShiftMeasurability.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/RandomTimeCompactTestConvergence.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/RelativeHitting.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/Sampling.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/ShiftCompactTestConvergence.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/StoppedValueMeasurability.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/Stopping.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Path/StoppingTimeDyadicCeiling.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Restart.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalExpectation.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalMarkov.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestart.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestartMeasure.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Restart/FinitePastRestart.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Restart/MixedPastFuture.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestart.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestrictedRestart.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Restart/RestrictedRestartOfJoint.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/Basic.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/CompactStrongConvergence.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/ContractiveResolvent.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/DenseCoreConvergence.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/Duhamel.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialBounds.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialComparison.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generation.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generator.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorClosed.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorInjectivity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorResolvent.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorUniqueness.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitContinuity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitProductRule.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/PoissonInvariant.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/PositiveShift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/Resolvent.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventComparison.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventGeneration.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/StrongOperatorLimit.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/TrotterKato.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaStrongLimit.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Time.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeApproximationFromAbove.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeHistory.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Time/FiniteDenseApproximationOrdered.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Time/FiniteGridIncrement.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderEmbedding.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Time/OrderedGrid.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeMarginals.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/Basic.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/ClampedCoordinate.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/Convergence.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/CylinderAlgebra.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionIntegral.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionMarginals.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseStoppingRestart.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/DiscountedDynkin.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/Dynkin.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinMartingale.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinStopping.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExcessiveStopping.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitLaw.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeExponentialMoment.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeLaplace.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExpectedExitTime.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerConditional.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerCountableStoppingRestart.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerFiniteMarginals.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerRestrictedRestart.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerShift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingConditional.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingRestart.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKac.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacFunctional.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacRealResolvent.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacResolvent.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/FiniteMarginals.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/HarmonicRepresentation.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathModulus.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathTightness.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/PenalizationDomination.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalConditional.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalShift.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/ResolventExitDecomposition.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/StartingPointContinuity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakContinuity.lean create mode 100644 LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakConvergence.lean diff --git a/LeanPool.lean b/LeanPool.lean index 50fa6e5b30..68ac6936df 100644 --- a/LeanPool.lean +++ b/LeanPool.lean @@ -3549,6 +3549,7 @@ import LeanPool.MRiscX.Tactics.SpecificationTactics import LeanPool.MRiscX.Tactics.SplitLastSeq import LeanPool.MRiscX.Tactics.TacticUtil import LeanPool.MRiscX.Util.BasicTheorems +import LeanPool.MarkovProcess import LeanPool.MassFormula import LeanPool.MassFormula.Convergence import LeanPool.MassFormula.Defs diff --git a/LeanPool/MarkovProcess.lean b/LeanPool/MarkovProcess.lean new file mode 100644 index 0000000000..f91e9bfc06 --- /dev/null +++ b/LeanPool/MarkovProcess.lean @@ -0,0 +1,282 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess +import LeanPool.MarkovProcess.MarkovProcess.Analysis +import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive +import LeanPool.MarkovProcess.MarkovProcess.Analysis.PaleyZygmund +import LeanPool.MarkovProcess.MarkovProcess.Continuity +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining +import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification +import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport +import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift +import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus +import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness +import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification +import LeanPool.MarkovProcess.MarkovProcess.DenseTime +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscreteLaw +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryDenseTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals +import LeanPool.MarkovProcess.MarkovProcess.Examples +import LeanPool.MarkovProcess.MarkovProcess.Examples.BrownianMotion +import LeanPool.MarkovProcess.MarkovProcess.Examples.Drift +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatGenerator +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatOnePoint +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Examples.Identity +import LeanPool.MarkovProcess.MarkovProcess.Feller +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion +import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeContinuityBase +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +import LeanPool.MarkovProcess.MarkovProcess.Kernel +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 +import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint +import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativityAE +import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpConsistency +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop +import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OperatorSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness +import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence +import LeanPool.MarkovProcess.MarkovProcess.Killed +import LeanPool.MarkovProcess.MarkovProcess.Killed.ExitTimeIdentification +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingC0 +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer +import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel +import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit +import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals +import LeanPool.MarkovProcess.MarkovProcess.Killed.Minimal +import LeanPool.MarkovProcess.MarkovProcess.Killed.Nested +import LeanPool.MarkovProcess.MarkovProcess.Killed.Process +import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Lifetime +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.CountablySeparated +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Killing +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Nonexplosion +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.NonexplosiveTransport +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift +import LeanPool.MarkovProcess.MarkovProcess.Main +import LeanPool.MarkovProcess.MarkovProcess.Parameterized +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Annealed +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeSupport +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Equivariance +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Killed +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Path +import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration +import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral +import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift +import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification +import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +import LeanPool.MarkovProcess.MarkovProcess.Path.Polish +import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability +import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence +import LeanPool.MarkovProcess.MarkovProcess.Path.RelativeHitting +import LeanPool.MarkovProcess.MarkovProcess.Path.Sampling +import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence +import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability +import LeanPool.MarkovProcess.MarkovProcess.Path.Stopping +import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling +import LeanPool.MarkovProcess.MarkovProcess.Restart +import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation +import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov +import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure +import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture +import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint +import LeanPool.MarkovProcess.MarkovProcess.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialComparison +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit +import LeanPool.MarkovProcess.MarkovProcess.Time +import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove +import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes +import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid +import LeanPool.MarkovProcess.MarkovProcess.Trajectory +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExcessiveStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeExponentialMoment +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKac +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalShift +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakConvergence + +/-! +# MarkovProcess + +Source: url:https://github.com/scottnarmstrong/markovprocess +Authors: Scott Armstrong +Status: verified +Main declarations: `MarkovProcess.SubMarkovKernelSemigroup.IsFellerKernelSemigroup.existsUnique_continuousProcess_of_hasKolmogorovMoments` +Tags: probability +MSC: 60J25, 60J35, 60G17 +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess.lean b/LeanPool/MarkovProcess/MarkovProcess.lean new file mode 100644 index 0000000000..c0252e3c2d --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess.lean @@ -0,0 +1,254 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive +import LeanPool.MarkovProcess.MarkovProcess.Analysis.PaleyZygmund +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining +import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification +import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport +import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift +import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus +import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness +import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscreteLaw +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryDenseTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals +import LeanPool.MarkovProcess.MarkovProcess.Examples.BrownianMotion +import LeanPool.MarkovProcess.MarkovProcess.Examples.Drift +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatGenerator +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatOnePoint +import LeanPool.MarkovProcess.MarkovProcess.Examples.Identity +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion +import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeContinuityBase +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 +import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint +import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativityAE +import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpConsistency +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop +import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OperatorSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness +import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence +import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel +import LeanPool.MarkovProcess.MarkovProcess.Killed.ExitTimeIdentification +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingC0 +import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit +import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals +import LeanPool.MarkovProcess.MarkovProcess.Killed.Minimal +import LeanPool.MarkovProcess.MarkovProcess.Killed.Nested +import LeanPool.MarkovProcess.MarkovProcess.Killed.Process +import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.CountablySeparated +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Killing +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Nonexplosion +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.NonexplosiveTransport +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift +import LeanPool.MarkovProcess.MarkovProcess.Main +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Annealed +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeSupport +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Equivariance +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Killed +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration +import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral +import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift +import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification +import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +import LeanPool.MarkovProcess.MarkovProcess.Path.Polish +import LeanPool.MarkovProcess.MarkovProcess.Path.Sampling +import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability +import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence +import LeanPool.MarkovProcess.MarkovProcess.Path.RelativeHitting +import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence +import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability +import LeanPool.MarkovProcess.MarkovProcess.Path.Stopping +import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling +import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation +import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov +import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure +import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture +import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialComparison +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit +import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove +import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes +import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExcessiveStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeExponentialMoment +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKac +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalShift +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakConvergence diff --git a/LeanPool/MarkovProcess/MarkovProcess/Analysis.lean b/LeanPool/MarkovProcess/MarkovProcess/Analysis.lean new file mode 100644 index 0000000000..7305dfd612 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Analysis.lean @@ -0,0 +1,14 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive +import LeanPool.MarkovProcess.MarkovProcess.Analysis.PaleyZygmund + +/-! +# Analysis + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Analysis/ExpPrimitive.lean b/LeanPool/MarkovProcess/MarkovProcess/Analysis/ExpPrimitive.lean new file mode 100644 index 0000000000..f0962f30b8 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Analysis/ExpPrimitive.lean @@ -0,0 +1,472 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Analysis.SpecialFunctions.Exp +import Mathlib.MeasureTheory.Integral.DominatedConvergence +import Mathlib.MeasureTheory.Integral.Prod +import Mathlib.MeasureTheory.Group.Prod + +/-! +# Exponential of an integral primitive + +This file proves the integral identity for the exponential of the primitive of a bounded +nonnegative integrable real function. The proof compares the integral with left and right sums +on uniform partitions; in particular, it does not require pointwise differentiability of the +primitive. + +Main results: `intervalIntegral.integral_mul_exp_primitive`, +`intervalIntegral.lintegral_timeTriangle_sub`, and `intervalIntegral.integral_timeTriangle_sub`. + +No probabilistic structure is used or asserted. +-/ + +open MeasureTheory Set +open scoped ENNReal + +namespace intervalIntegral + +noncomputable section + +-- The namespace placement is upstream-facing: this is a pure companion to interval integrals. +/-- Tonelli's theorem on the time triangle, followed by the volume-preserving shear +`(s, u) ↦ (s, s + u)`. -/ +theorem lintegral_timeTriangle_sub {h : ℝ × ℝ → ℝ≥0∞} (hh : Measurable h) : + (∫⁻ t in Ioi (0 : ℝ), ∫⁻ s in Ioo (0 : ℝ) t, h (s, t - s)) = + ∫⁻ s in Ioi (0 : ℝ), ∫⁻ u in Ioi (0 : ℝ), h (s, u) := by + let S : Set (ℝ × ℝ) := {p | 0 < p.1 ∧ p.1 < p.2} + let F : ℝ × ℝ → ℝ≥0∞ := fun p ↦ S.indicator (fun z ↦ h (z.1, z.2 - z.1)) p + have hS : MeasurableSet S := + (measurableSet_lt measurable_const measurable_fst).inter + (measurableSet_lt measurable_fst measurable_snd) + have hF : Measurable F := by + exact (hh.comp (measurable_fst.prodMk (measurable_snd.sub measurable_fst))).indicator hS + have hleft : (∫⁻ t in Ioi (0 : ℝ), ∫⁻ s in Ioo (0 : ℝ) t, h (s, t - s)) = + ∫⁻ t, ∫⁻ s, F (s, t) := by + rw [← lintegral_indicator measurableSet_Ioi] + apply lintegral_congr + intro t + by_cases ht : t ∈ Ioi (0 : ℝ) + · rw [indicator_of_mem ht, ← lintegral_indicator measurableSet_Ioo] + apply lintegral_congr + intro s + by_cases hs : s ∈ Ioo (0 : ℝ) t + · rw [indicator_of_mem hs] + dsimp only [F] + rw [indicator_of_mem] + exact hs + · rw [indicator_of_notMem hs] + dsimp only [F] + rw [indicator_of_notMem] + exact fun hst ↦ hs hst + · rw [indicator_of_notMem ht] + have hzero : ∀ s : ℝ, F (s, t) = 0 := fun s ↦ by + dsimp only [F] + rw [indicator_of_notMem] + exact fun hs ↦ ht (hs.1.trans hs.2) + simp_rw [hzero] + exact lintegral_zero.symm + have hright : (∫⁻ s in Ioi (0 : ℝ), ∫⁻ u in Ioi (0 : ℝ), h (s, u)) = + ∫⁻ s, ∫⁻ u, F (s, s + u) := by + rw [← lintegral_indicator measurableSet_Ioi] + apply lintegral_congr + intro s + by_cases hs : s ∈ Ioi (0 : ℝ) + · rw [indicator_of_mem hs, ← lintegral_indicator measurableSet_Ioi] + apply lintegral_congr + intro u + by_cases hu : u ∈ Ioi (0 : ℝ) + · rw [indicator_of_mem hu] + dsimp only [F] + rw [indicator_of_mem] + · ring_nf + · exact ⟨hs, lt_add_of_pos_right s hu⟩ + · rw [indicator_of_notMem hu] + dsimp only [F] + rw [indicator_of_notMem] + intro hsu + change 0 < s ∧ s < s + u at hsu + have hu0 : u ≤ 0 := le_of_not_gt hu + linarith only [hsu.2, hu0] + · rw [indicator_of_notMem hs] + have hzero : ∀ u : ℝ, F (s, s + u) = 0 := fun u ↦ by + dsimp only [F] + rw [indicator_of_notMem] + exact fun hsu ↦ hs hsu.1 + simp_rw [hzero] + exact lintegral_zero.symm + rw [hleft, hright] + have hFswap : Measurable fun p : ℝ × ℝ ↦ F (p.2, p.1) := + hF.comp measurable_swap + calc + (∫⁻ t, ∫⁻ s, F (s, t)) = ∫⁻ s, ∫⁻ t, F (s, t) := + lintegral_lintegral_swap hFswap.aemeasurable + _ = ∫⁻ p, F p ∂volume.prod volume := + (lintegral_prod F hF.aemeasurable).symm + _ = ∫⁻ p, F (p.1, p.1 + p.2) ∂volume.prod volume := by + exact ((measurePreserving_prod_add volume volume).lintegral_comp_emb + (MeasurableEquiv.shearAddRight ℝ).measurableEmbedding F).symm + _ = ∫⁻ s, ∫⁻ u, F (s, s + u) := lintegral_prod _ (hF.comp + (measurable_fst.prodMk measurable_add)).aemeasurable + +/-- Fubini's theorem on the time triangle, followed by the volume-preserving shear +`(s, u) ↦ (s, s + u)`, for an integrable real-valued function on the positive quadrant. -/ +theorem integral_timeTriangle_sub {h : ℝ × ℝ → ℝ} (hh : Measurable h) + (hint : Integrable ((Ioi (0 : ℝ) ×ˢ Ioi (0 : ℝ)).indicator h) + (volume.prod volume)) : + (∫ t in Ioi (0 : ℝ), ∫ s in Ioo (0 : ℝ) t, h (s, t - s)) = + ∫ s in Ioi (0 : ℝ), ∫ u in Ioi (0 : ℝ), h (s, u) := by + let Q : Set (ℝ × ℝ) := Ioi (0 : ℝ) ×ˢ Ioi (0 : ℝ) + let S : Set (ℝ × ℝ) := {p | 0 < p.1 ∧ p.1 < p.2} + let G : ℝ × ℝ → ℝ := fun p ↦ Q.indicator h p + let F : ℝ × ℝ → ℝ := fun p ↦ S.indicator (fun z ↦ h (z.1, z.2 - z.1)) p + have hQ : MeasurableSet Q := measurableSet_Ioi.prod measurableSet_Ioi + have hS : MeasurableSet S := + (measurableSet_lt measurable_const measurable_fst).inter + (measurableSet_lt measurable_fst measurable_snd) + have hG : Measurable G := hh.indicator hQ + have hF : Measurable F := + (hh.comp (measurable_fst.prodMk (measurable_snd.sub measurable_fst))).indicator hS + have hFG : (fun p : ℝ × ℝ ↦ F (p.1, p.1 + p.2)) = G := by + funext p + by_cases hp : p ∈ Q + · dsimp only [F, G] + rw [indicator_of_mem, indicator_of_mem hp] + · ring_nf + · exact ⟨hp.1, lt_add_of_pos_right p.1 hp.2⟩ + · dsimp only [F, G] + rw [indicator_of_notMem, indicator_of_notMem hp] + intro hmem + have hp2 : 0 < p.2 := by linarith only [hmem.2] + exact hp ⟨hmem.1, hp2⟩ + have hGint : Integrable G (volume.prod volume) := by simpa only [G, Q] using hint + have hFint : Integrable F (volume.prod volume) := by + have hcomp := (measurePreserving_prod_add volume volume).integrable_comp + hF.aestronglyMeasurable + apply hcomp.mp + rw [Function.comp_def, hFG] + exact hGint + have hleft : (∫ t in Ioi (0 : ℝ), ∫ s in Ioo (0 : ℝ) t, h (s, t - s)) = + ∫ t, ∫ s, F (s, t) := by + rw [← MeasureTheory.integral_indicator measurableSet_Ioi] + apply MeasureTheory.integral_congr_ae + exact Filter.Eventually.of_forall fun t ↦ by + by_cases ht : t ∈ Ioi (0 : ℝ) + · rw [indicator_of_mem ht, ← MeasureTheory.integral_indicator measurableSet_Ioo] + apply MeasureTheory.integral_congr_ae + exact Filter.Eventually.of_forall fun s ↦ by + by_cases hs : s ∈ Ioo (0 : ℝ) t + · rw [indicator_of_mem hs] + dsimp only [F] + rw [indicator_of_mem] + exact hs + · rw [indicator_of_notMem hs] + dsimp only [F] + rw [indicator_of_notMem] + exact fun hst ↦ hs hst + · rw [indicator_of_notMem ht] + have hzero : ∀ s : ℝ, F (s, t) = 0 := fun s ↦ by + dsimp only [F] + rw [indicator_of_notMem] + exact fun hs ↦ ht (hs.1.trans hs.2) + simp_rw [hzero] + simp only [MeasureTheory.integral_zero] + have hright : (∫ s in Ioi (0 : ℝ), ∫ u in Ioi (0 : ℝ), h (s, u)) = + ∫ s, ∫ u, G (s, u) := by + rw [← MeasureTheory.integral_indicator measurableSet_Ioi] + apply MeasureTheory.integral_congr_ae + exact Filter.Eventually.of_forall fun s ↦ by + by_cases hs : s ∈ Ioi (0 : ℝ) + · rw [indicator_of_mem hs, ← MeasureTheory.integral_indicator measurableSet_Ioi] + apply MeasureTheory.integral_congr_ae + exact Filter.Eventually.of_forall fun u ↦ by + by_cases hu : u ∈ Ioi (0 : ℝ) + · rw [indicator_of_mem hu] + dsimp only [G, Q] + rw [indicator_of_mem] + exact ⟨hs, hu⟩ + · rw [indicator_of_notMem hu] + dsimp only [G, Q] + rw [indicator_of_notMem] + exact fun hsu ↦ hu hsu.2 + · rw [indicator_of_notMem hs] + have hzero : ∀ u : ℝ, G (s, u) = 0 := fun u ↦ by + dsimp only [G, Q] + rw [indicator_of_notMem] + exact fun hsu ↦ hs hsu.1 + simp_rw [hzero] + simp only [MeasureTheory.integral_zero] + rw [hleft, hright] + calc + (∫ t, ∫ s, F (s, t)) = ∫ s, ∫ t, F (s, t) := + (integral_integral_swap hFint).symm + _ = ∫ p, F p ∂volume.prod volume := + (MeasureTheory.integral_prod F hFint).symm + _ = ∫ p, F (p.1, p.1 + p.2) ∂volume.prod volume := by + exact ((measurePreserving_prod_add volume volume).integral_comp' + (f := MeasurableEquiv.shearAddRight ℝ) F).symm + _ = ∫ p, G p ∂volume.prod volume := by rw [hFG] + _ = ∫ s, ∫ u, G (s, u) := MeasureTheory.integral_prod G hGint + +private theorem exp_mul_sub_le_sub_exp {x y : ℝ} : + Real.exp x * (y - x) ≤ Real.exp y - Real.exp x := by + rw [le_sub_iff_add_le] + calc + Real.exp x * (y - x) + Real.exp x = Real.exp x * ((y - x) + 1) := by ring + _ ≤ Real.exp x * Real.exp (y - x) := + mul_le_mul_of_nonneg_left (Real.add_one_le_exp (y - x)) (Real.exp_pos x).le + _ = Real.exp y := by + rw [← Real.exp_add] + congr 1 + ring + +private theorem sub_exp_le_exp_mul_sub {x y : ℝ} : + Real.exp y - Real.exp x ≤ Real.exp y * (y - x) := by + have h := mul_le_mul_of_nonneg_left (Real.add_one_le_exp (x - y)) (Real.exp_pos y).le + have h' : Real.exp y * ((x - y) + 1) ≤ Real.exp x := by + calc + Real.exp y * ((x - y) + 1) ≤ Real.exp y * Real.exp (x - y) := h + _ = Real.exp x := by + rw [← Real.exp_add] + congr 1 + ring + rw [sub_le_iff_le_add] + calc + Real.exp y = Real.exp y * ((x - y) + 1) + Real.exp y * (y - x) := by ring + _ ≤ Real.exp x + Real.exp y * (y - x) := by + simpa only [add_comm] using add_le_add_right h' (Real.exp y * (y - x)) + _ = Real.exp y * (y - x) + Real.exp x := add_comm _ _ + +/-- For a bounded nonnegative integrable function on `[0, T]`, integrating the function times the +exponential of its integral primitive gives the exponential increment. The upper bound is used +only to control the mesh error in the derivative-free uniform-partition proof. -/ +theorem integral_mul_exp_primitive {a : ℝ → ℝ} {C T t : ℝ} + (ht : t ∈ Icc (0 : ℝ) T) + (ha : IntegrableOn a (Icc (0 : ℝ) T)) + (ha_nonneg : ∀ s ∈ Icc (0 : ℝ) T, 0 ≤ a s) + (ha_le : ∀ s ∈ Icc (0 : ℝ) T, a s ≤ C) : + (∫ s in (0 : ℝ)..t, a s * Real.exp (∫ r in (0 : ℝ)..s, a r)) = + Real.exp (∫ r in (0 : ℝ)..t, a r) - 1 := by + have hT : 0 ≤ T := ht.1.trans ht.2 + have hC : 0 ≤ C := (ha_nonneg 0 ⟨le_rfl, hT⟩).trans (ha_le 0 ⟨le_rfl, hT⟩) + let A : ℝ → ℝ := fun s ↦ ∫ r in (0 : ℝ)..s, a r + have hInt0T : IntervalIntegrable a volume (0 : ℝ) T := by + rw [intervalIntegrable_iff, uIoc_of_le hT] + exact ha.mono_set Ioc_subset_Icc_self + have hInt (u v : ℝ) (hu : u ∈ Icc (0 : ℝ) T) (hv : v ∈ Icc (0 : ℝ) T) : + IntervalIntegrable a volume u v := by + apply hInt0T.mono_set + rw [uIcc_of_le hT] + intro z hz + rw [mem_uIcc] at hz + rcases hz with hz | hz + · exact ⟨hu.1.trans hz.1, hz.2.trans hv.2⟩ + · exact ⟨hv.1.trans hz.1, hz.2.trans hu.2⟩ + have hA_sub (u v : ℝ) (hu : u ∈ Icc (0 : ℝ) T) (hv : v ∈ Icc (0 : ℝ) T) : + A v - A u = ∫ r in u..v, a r := by + exact integral_interval_sub_left (hInt 0 v ⟨le_rfl, hT⟩ hv) + (hInt 0 u ⟨le_rfl, hT⟩ hu) + have hA_mono (u v : ℝ) (hu : u ∈ Icc (0 : ℝ) T) (hv : v ∈ Icc (0 : ℝ) T) + (huv : u ≤ v) : A u ≤ A v := by + rw [← sub_nonneg, hA_sub u v hu hv] + exact integral_nonneg huv fun s hs ↦ ha_nonneg s ⟨hu.1.trans hs.1, hs.2.trans hv.2⟩ + have hA_inc_le (u v : ℝ) (hu : u ∈ Icc (0 : ℝ) T) (hv : v ∈ Icc (0 : ℝ) T) + (huv : u ≤ v) : A v - A u ≤ C * (v - u) := by + rw [hA_sub u v hu hv] + calc + (∫ r in u..v, a r) ≤ ∫ _r in u..v, C := by + apply integral_mono_on huv (hInt u v hu hv) + (continuousOn_const.intervalIntegrable) + intro s hs + exact ha_le s ⟨hu.1.trans hs.1, hs.2.trans hv.2⟩ + _ = C * (v - u) := by + rw [integral_const, smul_eq_mul] + ring + have hAcont : ContinuousOn A (Icc (0 : ℝ) T) := by + rw [← uIcc_of_le hT] + exact continuousOn_primitive_interval' hInt0T left_mem_uIcc + have hExpAcont : ContinuousOn (fun s ↦ Real.exp (A s)) (Icc (0 : ℝ) T) := + Real.continuous_exp.comp_continuousOn hAcont + have hTargetInt : IntervalIntegrable (fun s ↦ a s * Real.exp (A s)) volume 0 t := by + exact (hInt 0 t ⟨le_rfl, hT⟩ ht).mul_continuousOn + (hExpAcont.mono (by + rw [uIcc_of_le ht.1] + exact Icc_subset_Icc le_rfl ht.2)) + have hA0 : A 0 = 0 := integral_same + have hExpIncNonneg : 0 ≤ Real.exp (A t) - 1 := by + rw [← Real.exp_zero, sub_nonneg, Real.exp_le_exp] + rw [← hA0] + exact hA_mono 0 t ⟨le_rfl, hT⟩ ht ht.1 + let B : ℝ := C * t * (Real.exp (A t) - 1) + have hB : 0 ≤ B := mul_nonneg (mul_nonneg hC ht.1) hExpIncNonneg + have hApprox (N : ℕ) (hN : 0 < N) : + (∫ s in (0 : ℝ)..t, a s * Real.exp (A s)) ≤ + Real.exp (A t) - 1 + B / N ∧ + Real.exp (A t) - 1 ≤ + (∫ s in (0 : ℝ)..t, a s * Real.exp (A s)) + B / N := by + let p : ℕ → ℝ := fun j ↦ (j : ℝ) * t / N + have hNreal : (0 : ℝ) < N := by exact_mod_cast hN + have hp0 : p 0 = 0 := by simp only [CharP.cast_eq_zero, zero_mul, zero_div, p] + have hpN : p N = t := by + simp only [ne_eq, Nat.cast_eq_zero, hN.ne', not_false_eq_true, + mul_div_cancel_left₀, p] + have hp_le_t (j : ℕ) (hj : j ≤ N) : p j ≤ t := by + rw [div_le_iff₀ hNreal] + calc + (j : ℝ) * t ≤ (N : ℝ) * t := + mul_le_mul_of_nonneg_right (by exact_mod_cast hj) ht.1 + _ = t * N := mul_comm _ _ + have hp_mem (j : ℕ) (hj : j ≤ N) : p j ∈ Icc (0 : ℝ) T := by + constructor + · exact div_nonneg (mul_nonneg (Nat.cast_nonneg j) ht.1) hNreal.le + · exact (hp_le_t j hj).trans ht.2 + have hp_mono (j : ℕ) (hj : j < N) : p j ≤ p (j + 1) := by + rw [div_le_div_iff_of_pos_right hNreal] + exact mul_le_mul_of_nonneg_right (by exact_mod_cast Nat.le_succ j) ht.1 + have hp_succ_mem (j : ℕ) (hj : j < N) : p (j + 1) ∈ Icc (0 : ℝ) T := + hp_mem (j + 1) hj + let I : ℕ → ℝ := fun j ↦ ∫ s in p j..p (j + 1), a s + let L : ℝ := ∑ j ∈ Finset.range N, Real.exp (A (p j)) * I j + let R : ℝ := ∑ j ∈ Finset.range N, Real.exp (A (p (j + 1))) * I j + have hI_eq (j : ℕ) (hj : j < N) : I j = A (p (j + 1)) - A (p j) := by + simp only [I] + exact (hA_sub (p j) (p (j + 1)) (hp_mem j hj.le) (hp_succ_mem j hj)).symm + have hI_nonneg (j : ℕ) (hj : j < N) : 0 ≤ I j := by + rw [hI_eq j hj, sub_nonneg] + exact hA_mono (p j) (p (j + 1)) (hp_mem j hj.le) (hp_succ_mem j hj) + (hp_mono j hj) + have hI_le (j : ℕ) (hj : j < N) : I j ≤ C * (t / N) := by + rw [hI_eq j hj] + calc + A (p (j + 1)) - A (p j) ≤ C * (p (j + 1) - p j) := + hA_inc_le (p j) (p (j + 1)) (hp_mem j hj.le) (hp_succ_mem j hj) + (hp_mono j hj) + _ = C * (t / N) := by + dsimp only [p] + rw [Nat.cast_add, Nat.cast_one] + ring + have hTel : (∑ j ∈ Finset.range N, + (Real.exp (A (p (j + 1))) - Real.exp (A (p j)))) = Real.exp (A t) - 1 := by + calc + (∑ j ∈ Finset.range N, + (Real.exp (A (p (j + 1))) - Real.exp (A (p j)))) = + Real.exp (A (p N)) - Real.exp (A (p 0)) := + Finset.sum_range_sub (fun j ↦ Real.exp (A (p j))) N + _ = Real.exp (A t) - 1 := by rw [hpN, hp0, hA0, Real.exp_zero] + have hL_center : L ≤ Real.exp (A t) - 1 := by + simp only [L] + rw [← hTel] + apply Finset.sum_le_sum + intro j hj + rw [Finset.mem_range] at hj + rw [hI_eq j hj] + exact exp_mul_sub_le_sub_exp + have hCenter_R : Real.exp (A t) - 1 ≤ R := by + simp only [R] + rw [← hTel] + apply Finset.sum_le_sum + intro j hj + rw [Finset.mem_range] at hj + rw [hI_eq j hj] + exact sub_exp_le_exp_mul_sub + have hCellInt (j : ℕ) (hj : j < N) : + IntervalIntegrable (fun s ↦ a s * Real.exp (A s)) volume (p j) (p (j + 1)) := + hTargetInt.mono_set (by + rw [uIcc_of_le (hp_mono j hj), uIcc_of_le ht.1] + exact Icc_subset_Icc (hp_mem j hj.le).1 (hp_le_t (j + 1) hj)) + have hL_target : L ≤ ∫ s in (0 : ℝ)..t, a s * Real.exp (A s) := by + simp only [L] + rw [← hp0, ← hpN] + rw [← sum_integral_adjacent_intervals (fun j hj ↦ hCellInt j hj)] + apply Finset.sum_le_sum + intro j hj + rw [Finset.mem_range] at hj + rw [← integral_const_mul] + apply integral_mono_on (hp_mono j hj) + · exact (hInt (p j) (p (j + 1)) (hp_mem j hj.le) (hp_succ_mem j hj)).const_mul _ + · exact hCellInt j hj + intro s hs + simpa only [mul_comm] using mul_le_mul_of_nonneg_left + (Real.exp_le_exp.mpr (hA_mono (p j) s (hp_mem j hj.le) + ⟨(hp_mem j hj.le).1.trans hs.1, hs.2.trans (hp_succ_mem j hj).2⟩ hs.1)) + (ha_nonneg s ⟨(hp_mem j hj.le).1.trans hs.1, + hs.2.trans (hp_succ_mem j hj).2⟩) + have hTarget_R : (∫ s in (0 : ℝ)..t, a s * Real.exp (A s)) ≤ R := by + simp only [R] + rw [← hp0, ← hpN] + rw [← sum_integral_adjacent_intervals (fun j hj ↦ hCellInt j hj)] + apply Finset.sum_le_sum + intro j hj + rw [Finset.mem_range] at hj + rw [← integral_const_mul] + apply integral_mono_on (hp_mono j hj) + · exact hCellInt j hj + · exact (hInt (p j) (p (j + 1)) (hp_mem j hj.le) (hp_succ_mem j hj)).const_mul _ + intro s hs + simpa only [mul_comm] using mul_le_mul_of_nonneg_left + (Real.exp_le_exp.mpr (hA_mono s (p (j + 1)) + ⟨(hp_mem j hj.le).1.trans hs.1, hs.2.trans (hp_succ_mem j hj).2⟩ + (hp_succ_mem j hj) hs.2)) + (ha_nonneg s ⟨(hp_mem j hj.le).1.trans hs.1, + hs.2.trans (hp_succ_mem j hj).2⟩) + have hGap : R - L ≤ B / N := by + simp only [R, L] + rw [← Finset.sum_sub_distrib] + calc + (∑ j ∈ Finset.range N, + (Real.exp (A (p (j + 1))) * I j - Real.exp (A (p j)) * I j)) = + ∑ j ∈ Finset.range N, + (Real.exp (A (p (j + 1))) - Real.exp (A (p j))) * I j := by + apply Finset.sum_congr rfl + intro j _ + ring + _ ≤ ∑ j ∈ Finset.range N, + (Real.exp (A (p (j + 1))) - Real.exp (A (p j))) * (C * (t / N)) := by + apply Finset.sum_le_sum + intro j hj + rw [Finset.mem_range] at hj + exact mul_le_mul_of_nonneg_left (hI_le j hj) + (sub_nonneg.mpr (Real.exp_le_exp.mpr + (hA_mono (p j) (p (j + 1)) (hp_mem j hj.le) + (hp_succ_mem j hj) (hp_mono j hj)))) + _ = B / N := by + rw [← Finset.sum_mul, hTel] + dsimp only [B] + ring + have hR_le : R ≤ L + B / N := by linarith only [hGap] + constructor + · calc + (∫ s in (0 : ℝ)..t, a s * Real.exp (A s)) ≤ R := hTarget_R + _ ≤ L + B / N := hR_le + _ ≤ Real.exp (A t) - 1 + B / N := by + simpa only [add_comm] using add_le_add_right hL_center (B / N) + · calc + Real.exp (A t) - 1 ≤ R := hCenter_R + _ ≤ L + B / N := hR_le + _ ≤ (∫ s in (0 : ℝ)..t, a s * Real.exp (A s)) + B / N := by + simpa only [add_comm] using add_le_add_right hL_target (B / N) + change (∫ s in (0 : ℝ)..t, a s * Real.exp (A s)) = Real.exp (A t) - 1 + apply le_antisymm + · refine le_of_forall_pos_le_add fun epsilon hepsilon ↦ ?_ + obtain ⟨N, hN⟩ := exists_nat_gt (B / epsilon) + have hNposReal : (0 : ℝ) < N := (div_nonneg hB hepsilon.le).trans_lt hN + have hNpos : 0 < N := by exact_mod_cast hNposReal + have hBN : B / N < epsilon := by + rw [div_lt_iff₀ hNposReal] + have := (div_lt_iff₀ hepsilon).mp hN + nlinarith only [this] + exact (hApprox N hNpos).1.trans (add_le_add_right hBN.le _) + · refine le_of_forall_pos_le_add fun epsilon hepsilon ↦ ?_ + obtain ⟨N, hN⟩ := exists_nat_gt (B / epsilon) + have hNposReal : (0 : ℝ) < N := (div_nonneg hB hepsilon.le).trans_lt hN + have hNpos : 0 < N := by exact_mod_cast hNposReal + have hBN : B / N < epsilon := by + rw [div_lt_iff₀ hNposReal] + have := (div_lt_iff₀ hepsilon).mp hN + nlinarith only [this] + exact (hApprox N hNpos).2.trans (add_le_add_right hBN.le _) + +end + +end intervalIntegral diff --git a/LeanPool/MarkovProcess/MarkovProcess/Analysis/PaleyZygmund.lean b/LeanPool/MarkovProcess/MarkovProcess/Analysis/PaleyZygmund.lean new file mode 100644 index 0000000000..66fb3227fb --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Analysis/PaleyZygmund.lean @@ -0,0 +1,134 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.MeasureTheory.Integral.MeanInequalities +import Mathlib.MeasureTheory.Measure.Typeclasses.Probability + +/-! +# The Paley--Zygmund inequality + +For a nonnegative extended-real random variable `Z` with finite mean on a probability space and a +level `rho`, the mass above `rho * E Z` is bounded below by the second-moment ratio, + + `(1 - rho) ^ 2 * (E Z) ^ 2 ≤ E (Z ^ 2) * mu {rho * E Z ≤ Z}`. + +The subtraction is the truncated one of `ℝ≥0∞`, so a level `rho ≥ 1` leaves the trivial bound and +needs no separate hypothesis. The primary form +(`MeasureTheory.lintegral_sq_mul_measure_ge_le`) is division-free, so it needs neither positivity +nor finiteness of the second moment; the divided form +(`MeasureTheory.le_measure_ge_of_lintegral_sq_ne_top`) is the familiar +`(1 - rho) ^ 2 (E Z) ^ 2 / E (Z ^ 2) ≤ mu {rho * E Z ≤ Z}`, whose finite-mean hypothesis is +supplied by the second moment through the Cauchy--Schwarz inequality +(`MeasureTheory.lintegral_le_rpow_lintegral_sq`). + +Everything is stated for `ℝ≥0∞`-valued functions and carries no integrability side condition. +-/ + +open scoped ENNReal NNReal + +-- The namespace placement is upstream-facing: this is pure measure theory, with no process +-- structure and no state space. +namespace MeasureTheory + +variable {Omega : Type*} [MeasurableSpace Omega] + +/-- Cauchy--Schwarz on a measurable set: the integral of a nonnegative extended-real function over +`A` is at most the square root of its second moment times the square root of the mass of `A`. -/ +theorem setLIntegral_le_rpow_lintegral_sq_mul_rpow (mu : Measure Omega) {Z : Omega → ℝ≥0∞} + (hZ : AEMeasurable Z mu) {A : Set Omega} (hA : MeasurableSet A) : + ∫⁻ omega in A, Z omega ∂mu ≤ + (∫⁻ omega, Z omega ^ 2 ∂mu) ^ (1 / 2 : ℝ) * (mu A) ^ (1 / 2 : ℝ) := by + have hindicator : AEMeasurable (A.indicator (fun _ ↦ (1 : ℝ≥0∞))) mu := + (measurable_const.indicator hA).aemeasurable + have hsplit : ∫⁻ omega in A, Z omega ∂mu = + ∫⁻ omega, (Z * A.indicator (fun _ ↦ (1 : ℝ≥0∞))) omega ∂mu := by + rw [← lintegral_indicator hA] + refine lintegral_congr fun omega ↦ ?_ + by_cases homega : omega ∈ A + · simp only [Pi.mul_apply, Set.indicator_of_mem homega, mul_one] + · simp only [Pi.mul_apply, Set.indicator_of_notMem homega, mul_zero] + have hholder := ENNReal.lintegral_mul_le_Lp_mul_Lq mu Real.HolderConjugate.two_two hZ hindicator + have hsquare : ∀ omega : Omega, Z omega ^ (2 : ℝ) = Z omega ^ (2 : ℕ) := by + intro omega + rw [← ENNReal.rpow_natCast (Z omega) 2] + norm_num + have hind : ∀ omega : Omega, + A.indicator (fun _ ↦ (1 : ℝ≥0∞)) omega ^ (2 : ℝ) = + A.indicator (fun _ ↦ (1 : ℝ≥0∞)) omega := by + intro omega + by_cases homega : omega ∈ A + · simp only [Set.indicator_of_mem homega, ENNReal.one_rpow] + · simp only [Set.indicator_of_notMem homega] + exact ENNReal.zero_rpow_of_pos (by norm_num) + rw [hsplit] + refine hholder.trans (le_of_eq ?_) + rw [lintegral_congr hsquare, lintegral_congr hind, lintegral_indicator_const hA (1 : ℝ≥0∞), + one_mul] + +/-- A finite second moment on a probability space forces a finite mean. -/ +theorem lintegral_le_rpow_lintegral_sq (mu : Measure Omega) [IsProbabilityMeasure mu] + {Z : Omega → ℝ≥0∞} (hZ : AEMeasurable Z mu) : + ∫⁻ omega, Z omega ∂mu ≤ (∫⁻ omega, Z omega ^ 2 ∂mu) ^ (1 / 2 : ℝ) := by + have h := setLIntegral_le_rpow_lintegral_sq_mul_rpow mu hZ MeasurableSet.univ + rwa [Measure.restrict_univ, measure_univ, ENNReal.one_rpow, mul_one] at h + +/-- **The Paley--Zygmund inequality**, in division-free form: on a probability space the mass of +the event `{rho * E Z ≤ Z}` obeys +`(1 - rho) ^ 2 * (E Z) ^ 2 ≤ E (Z ^ 2) * mu {rho * E Z ≤ Z}`. The subtraction is the truncated one +of `ℝ≥0∞`, so a level `rho ≥ 1` gives the trivial bound `0 ≤ …`. -/ +theorem lintegral_sq_mul_measure_ge_le (mu : Measure Omega) [IsProbabilityMeasure mu] + {Z : Omega → ℝ≥0∞} (hZ : Measurable Z) (hfin : ∫⁻ omega, Z omega ∂mu ≠ ⊤) (rho : ℝ≥0) : + ((1 : ℝ≥0∞) - rho) ^ 2 * (∫⁻ omega, Z omega ∂mu) ^ 2 ≤ + (∫⁻ omega, Z omega ^ 2 ∂mu) * + mu {omega | (rho : ℝ≥0∞) * ∫⁻ omega, Z omega ∂mu ≤ Z omega} := by + set m : ℝ≥0∞ := ∫⁻ omega, Z omega ∂mu + set a : ℝ≥0∞ := (rho : ℝ≥0∞) * m with ha + set A : Set Omega := {omega | a ≤ Z omega} + have hA : MeasurableSet A := measurableSet_le measurable_const hZ + have hcompl : ∫⁻ omega in Aᶜ, Z omega ∂mu ≤ a := by + calc + ∫⁻ omega in Aᶜ, Z omega ∂mu ≤ ∫⁻ _omega in Aᶜ, a ∂mu := by + refine setLIntegral_mono' hA.compl fun omega homega ↦ ?_ + exact le_of_lt (not_le.mp homega) + _ = a * mu Aᶜ := setLIntegral_const _ _ + _ ≤ a * 1 := mul_le_mul_right prob_le_one a + _ = a := mul_one a + have hsum : m = ∫⁻ omega in A, Z omega ∂mu + ∫⁻ omega in Aᶜ, Z omega ∂mu := + (lintegral_add_compl _ hA).symm + have hsub : m - a ≤ ∫⁻ omega in A, Z omega ∂mu := by + refine tsub_le_iff_right.mpr ?_ + calc + m = ∫⁻ omega in A, Z omega ∂mu + ∫⁻ omega in Aᶜ, Z omega ∂mu := hsum + _ ≤ ∫⁻ omega in A, Z omega ∂mu + a := add_le_add le_rfl hcompl + have hlin : ((1 : ℝ≥0∞) - rho) * m = m - a := by + rw [ENNReal.sub_mul fun _ _ ↦ hfin, one_mul, ha] + have hCS := setLIntegral_le_rpow_lintegral_sq_mul_rpow mu hZ.aemeasurable hA + have hkey : ((1 : ℝ≥0∞) - rho) * m ≤ + (∫⁻ omega, Z omega ^ 2 ∂mu) ^ (1 / 2 : ℝ) * (mu A) ^ (1 / 2 : ℝ) := by + rw [hlin] + exact hsub.trans hCS + calc + ((1 : ℝ≥0∞) - rho) ^ 2 * m ^ 2 = (((1 : ℝ≥0∞) - rho) * m) ^ 2 := (mul_pow _ _ 2).symm + _ ≤ ((∫⁻ omega, Z omega ^ 2 ∂mu) ^ (1 / 2 : ℝ) * (mu A) ^ (1 / 2 : ℝ)) ^ 2 := + pow_le_pow_left' hkey 2 + _ = (∫⁻ omega, Z omega ^ 2 ∂mu) * mu A := by + rw [mul_pow, ← ENNReal.rpow_natCast ((∫⁻ omega, Z omega ^ 2 ∂mu) ^ (1 / 2 : ℝ)) 2, + ← ENNReal.rpow_natCast ((mu A) ^ (1 / 2 : ℝ)) 2, ← ENNReal.rpow_mul, ← ENNReal.rpow_mul] + norm_num + +/-- **The Paley--Zygmund inequality**, in divided form. The finite-mean hypothesis of the +division-free version is supplied by the finite second moment. -/ +theorem le_measure_ge_of_lintegral_sq_ne_top (mu : Measure Omega) [IsProbabilityMeasure mu] + {Z : Omega → ℝ≥0∞} (hZ : Measurable Z) (hsq : ∫⁻ omega, Z omega ^ 2 ∂mu ≠ ⊤) + (rho : ℝ≥0) : + ((1 : ℝ≥0∞) - rho) ^ 2 * (∫⁻ omega, Z omega ∂mu) ^ 2 / (∫⁻ omega, Z omega ^ 2 ∂mu) ≤ + mu {omega | (rho : ℝ≥0∞) * ∫⁻ omega, Z omega ∂mu ≤ Z omega} := by + have hfin : ∫⁻ omega, Z omega ∂mu ≠ ⊤ := by + refine ne_top_of_le_ne_top ?_ (lintegral_le_rpow_lintegral_sq mu hZ.aemeasurable) + exact ENNReal.rpow_ne_top_of_nonneg (by norm_num) hsq + exact ENNReal.div_le_of_le_mul + ((lintegral_sq_mul_measure_ge_le mu hZ hfin rho).trans_eq (mul_comm _ _)) + +end MeasureTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity.lean new file mode 100644 index 0000000000..6084ea45ad --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity.lean @@ -0,0 +1,25 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining +import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification +import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport +import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift +import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus +import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness +import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification + +/-! +# Continuity + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousExtension.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousExtension.lean new file mode 100644 index 0000000000..c3156436a2 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousExtension.lean @@ -0,0 +1,116 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +import Mathlib.MeasureTheory.Constructions.Polish.Basic + +/-! +# Continuous extension from dense-time paths + +This file embeds ordinary continuous paths into paths on the fixed dense time carrier. It proves +that the image is measurable and supplies a measurable total inverse. The inverse is the genuine +continuous extension on the image and is arbitrarily equal to a caller-supplied default path away +from the image. + +No probability law is shown to be supported on this image, and no continuous modification, +stochastic-process association, or path-regularity claim is made here. +-/ + +open MeasureTheory Set + +namespace MarkovProcess + +noncomputable section + +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- Restriction of a continuous path to the fixed dense time carrier. -/ +def denseRestriction (omega : ContinuousPath alpha) : DenseTime → alpha := + fun q ↦ omega (DenseTime.castOrderEmbedding q) + +@[simp] +theorem denseRestriction_apply (omega : ContinuousPath alpha) (q : DenseTime) : + denseRestriction omega q = omega (DenseTime.castOrderEmbedding q) := rfl + +/-- The nonnegative rational times are dense in nonnegative real time. -/ +theorem denseRange_castOrderEmbedding : DenseRange DenseTime.castOrderEmbedding := by + rw [DenseRange] + apply dense_of_exists_between + intro a b hab + obtain ⟨q, haq, hqb⟩ := DenseTime.exists_cast_btwn hab + exact ⟨DenseTime.castOrderEmbedding q, ⟨q, rfl⟩, haq, hqb⟩ + +/-- A continuous path is determined by its values at the dense times. -/ +theorem denseRestriction_injective [T2Space alpha] : + Function.Injective (denseRestriction (alpha := alpha)) := by + intro omega eta h + apply ContinuousMap.ext + have heq : (omega : NNReal → alpha) = eta := + denseRange_castOrderEmbedding.equalizer omega.continuous eta.continuous h + exact congrFun heq + +/-- A total extension, equal to the inverse on the restriction range and arbitrarily equal to +`default` away from that range. -/ +def continuousExtension (default : ContinuousPath alpha) : + (DenseTime → alpha) → ContinuousPath alpha := + Function.extend denseRestriction id (fun _ ↦ default) + +@[simp] +theorem continuousExtension_denseRestriction [T2Space alpha] + (default omega : ContinuousPath alpha) : + continuousExtension (alpha := alpha) default (denseRestriction omega) = omega := by + exact Function.Injective.extend_apply denseRestriction_injective _ _ _ + +theorem denseRestriction_continuousExtension_of_mem_range [T2Space alpha] + (default : ContinuousPath alpha) {x : DenseTime → alpha} + (hx : x ∈ Set.range (denseRestriction (alpha := alpha))) : + denseRestriction (continuousExtension (alpha := alpha) default x) = x := by + obtain ⟨omega, rfl⟩ := hx + rw [continuousExtension_denseRestriction] + +@[simp] +theorem continuousExtension_of_notMem_range (default : ContinuousPath alpha) + {x : DenseTime → alpha} (hx : x ∉ Set.range (denseRestriction (alpha := alpha))) : + continuousExtension (alpha := alpha) default x = default := by + exact Function.extend_apply' id (fun _ ↦ default) x hx + +section Measurable + +variable [MeasurableSpace alpha] [BorelSpace alpha] + +/-- Dense-time restriction is coordinatewise Borel measurable. -/ +theorem measurable_denseRestriction : Measurable (denseRestriction (alpha := alpha)) := by + rw [measurable_pi_iff] + intro q + exact + (continuous_eval (alpha := alpha) (DenseTime.castOrderEmbedding q)).borel_measurable.mono + le_rfl (le_of_eq BorelSpace.measurable_eq) + +variable [T2Space alpha] [StandardBorelSpace (ContinuousPath alpha)] + [MeasurableSpace.CountablySeparated (DenseTime → alpha)] + +/-- Dense-time restriction is a measurable embedding. -/ +theorem measurableEmbedding_denseRestriction : + MeasurableEmbedding (denseRestriction (alpha := alpha)) := + measurable_denseRestriction.measurableEmbedding denseRestriction_injective + +/-- The set of dense-time paths admitting a continuous extension is measurable. -/ +theorem measurableSet_range_denseRestriction : + MeasurableSet (Set.range (denseRestriction (alpha := alpha))) := + measurableEmbedding_denseRestriction.measurableSet_range + +/-- The total extension is measurable; away from the measurable restriction range its value is +the arbitrary path `default`. -/ +theorem measurable_continuousExtension (default : ContinuousPath alpha) : + Measurable (continuousExtension (alpha := alpha) default) := + measurableEmbedding_denseRestriction.measurable_extend measurable_id measurable_const + +end Measurable +end ContinuousPath +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousLaw.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousLaw.lean new file mode 100644 index 0000000000..f5a1e150d5 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousLaw.lean @@ -0,0 +1,95 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +import Mathlib.Probability.Kernel.Composition.MapComap + +/-! +# Transporting dense-time laws to continuous paths + +This file transports a kernel on dense-time trajectories to ordinary continuous paths under an +explicit support-on-the-continuous-range hypothesis. It does not prove that support hypothesis. +-/ + +open MeasureTheory ProbabilityTheory Set + +namespace MarkovProcess + +noncomputable section + +namespace Kernel + +variable {β alpha : Type*} [MeasurableSpace β] [TopologicalSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [T2Space alpha] + +variable [StandardBorelSpace (ContinuousPath alpha)] + [MeasurableSpace.CountablySeparated (DenseTime → alpha)] + +/-- A dense-time kernel is almost surely supported on restrictions of continuous paths. -/ +def IsSupportedOnContinuousPaths (κ : Kernel β (DenseTime → alpha)) : Prop := + ∀ x, ∀ᵐ path ∂κ x, path ∈ Set.range (ContinuousPath.denseRestriction (alpha := alpha)) + +/-- Transport a dense-time kernel to continuous paths by the measurable extension map. -/ +def toContinuousPathKernel (κ : Kernel β (DenseTime → alpha)) + (default : ContinuousPath alpha) : Kernel β (ContinuousPath alpha) := + Kernel.mapOfMeasurable κ (ContinuousPath.continuousExtension default) + (ContinuousPath.measurable_continuousExtension default) + +/-- The continuous-path transport agrees with the ordinary kernel map. -/ +theorem toContinuousPathKernel_eq_map (κ : Kernel β (DenseTime → alpha)) + (default : ContinuousPath alpha) : + toContinuousPathKernel κ default = + κ.map (ContinuousPath.continuousExtension default) := + Kernel.mapOfMeasurable_eq_map _ + (ContinuousPath.measurable_continuousExtension default) + +/-- A Markov dense-time kernel transports to a Markov continuous-path kernel. -/ +theorem isMarkovKernel_toContinuousPathKernel (κ : Kernel β (DenseTime → alpha)) + [IsMarkovKernel κ] (default : ContinuousPath alpha) : + IsMarkovKernel (toContinuousPathKernel κ default) := by + rw [toContinuousPathKernel_eq_map] + exact Kernel.IsMarkovKernel.map _ + (ContinuousPath.measurable_continuousExtension default) + +/-- Under the support hypothesis, the transported kernel is independent of the arbitrary +off-range default path. -/ +theorem IsSupportedOnContinuousPaths.toContinuousPathKernel_eq + (κ : Kernel β (DenseTime → alpha)) (hκ : IsSupportedOnContinuousPaths κ) + (default₁ default₂ : ContinuousPath alpha) : + toContinuousPathKernel κ default₁ = toContinuousPathKernel κ default₂ := by + rw [toContinuousPathKernel_eq_map, toContinuousPathKernel_eq_map] + ext x s hs + rw [Kernel.map_apply' _ (ContinuousPath.measurable_continuousExtension default₁) x hs, + Kernel.map_apply' _ (ContinuousPath.measurable_continuousExtension default₂) x hs] + have hfun : ContinuousPath.continuousExtension default₁ =ᵐ[κ x] + ContinuousPath.continuousExtension default₂ := + (hκ x).mono fun path hpath ↦ by + obtain ⟨omega, rfl⟩ := hpath + rw [ContinuousPath.continuousExtension_denseRestriction, + ContinuousPath.continuousExtension_denseRestriction] + exact measure_congr (hfun.preimage s) + +/-- On the continuous restriction range, extension followed by restriction is the identity. -/ +theorem IsSupportedOnContinuousPaths.map_denseRestriction + (κ : Kernel β (DenseTime → alpha)) (hκ : IsSupportedOnContinuousPaths κ) + (default : ContinuousPath alpha) : + (toContinuousPathKernel κ default).map ContinuousPath.denseRestriction = κ := by + rw [toContinuousPathKernel_eq_map, ← Kernel.map_comp_right] + · ext x s hs + rw [Kernel.map_apply' _ + ((ContinuousPath.measurable_denseRestriction).comp + (ContinuousPath.measurable_continuousExtension default)) x hs] + have hfun : + ContinuousPath.denseRestriction ∘ ContinuousPath.continuousExtension default + =ᵐ[κ x] id := + (hκ x).mono fun path hpath ↦ + ContinuousPath.denseRestriction_continuousExtension_of_mem_range default hpath + simpa only [Set.preimage_id] using measure_congr (hfun.preimage s) + · exact ContinuousPath.measurable_continuousExtension default + · exact ContinuousPath.measurable_denseRestriction + +end Kernel +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousSupport.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousSupport.lean new file mode 100644 index 0000000000..fbec35a11b --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousSupport.lean @@ -0,0 +1,57 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw + +/-! +# Continuous support from a continuous modification + +This file turns a continuous-time modification of the coordinate process of a dense-time law +into almost-sure support on restrictions of continuous paths. The only measure-theoretic step is +the simultaneous choice of all dense-time modification identities, which is valid because +`DenseTime` is countable. + +The continuous modification itself is not constructed here: it is the Kolmogorov--Chentsov +argument of `Continuity/GlobalDyadicFloorModification.lean`, applied to dense-time trajectory +kernels in `Continuity/KolmogorovDenseTimeContinuousSupport.lean`. +-/ + +open MeasureTheory ProbabilityTheory Set + +namespace MarkovProcess + +noncomputable section + +namespace Kernel + +variable {beta alpha : Type*} [MeasurableSpace beta] [TopologicalSpace alpha] + [MeasurableSpace alpha] + +/-- A continuous-time modification of every coordinate law implies that the original dense-time +law is almost surely the restriction of a continuous path. The modification may depend on the +kernel parameter `b`; no measurable choice of modifications in `b` is required for this +pointwise support conclusion. -/ +theorem IsSupportedOnContinuousPaths.of_continuousModification + (kappa : Kernel beta (DenseTime → alpha)) + (hmod : ∀ b, ∃ Y : NNReal → (DenseTime → alpha) → alpha, + (∀ omega, Continuous (fun t ↦ Y t omega)) ∧ + ∀ q, (fun omega : DenseTime → alpha ↦ omega q) =ᵐ[kappa b] + Y (DenseTime.castOrderEmbedding q)) : + IsSupportedOnContinuousPaths kappa := by + intro b + obtain ⟨Y, hYcont, hYmod⟩ := hmod b + have hmod_all : ∀ᵐ omega ∂kappa b, ∀ q, + omega q = Y (DenseTime.castOrderEmbedding q) omega := + ae_all_iff.2 hYmod + filter_upwards [hmod_all] with omega homega + let path : ContinuousPath alpha := + ⟨fun t ↦ Y t omega, hYcont omega⟩ + refine ⟨path, ?_⟩ + funext q + exact (homega q).symm + +end Kernel +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicChaining.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicChaining.lean new file mode 100644 index 0000000000..dad71b4b64 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicChaining.lean @@ -0,0 +1,345 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements + +/-! +# Chaining across unit dyadic grids + +This file merges the following former modules, one section each: + +* `DyadicGridChaining`: Same-level chaining on dyadic grids +* `DyadicMultiscale`: Refinement and parent comparison for unit dyadic grids +* `DyadicAncestorChaining`: Finite chains of dyadic ancestors +* `DyadicAncestorTail`: Uniform tail bounds for finite dyadic ancestor chains +-/ + +namespace MarkovProcess + +section DyadicGridChaining + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] + +/-- Uniform control of adjacent increments on one unit dyadic grid controls the increment +between any two ordered grid points by the number of intervening cells. -/ +theorem edist_unitDyadicGrid_le_natCast_mul_of_adjacent_le + {X : NNRat → Ω → E} {n : ℕ} {ε : ℝ≥0∞} {ω : Ω} + (hadj : ∀ k : Fin (2 ^ n), + edist (X (unitDyadicGrid n k.castSucc) ω) + (X (unitDyadicGrid n k.succ) ω) ≤ ε) + (i j : Fin (2 ^ n + 1)) (hij : (i : ℕ) ≤ j) : + edist (X (unitDyadicGrid n i) ω) (X (unitDyadicGrid n j) ω) ≤ + (j.val - i.val : ℕ) * ε := by + let f : ℕ → E := fun k ↦ + if hk : k < 2 ^ n + 1 then X (unitDyadicGrid n ⟨k, hk⟩) ω + else X (unitDyadicGrid n i) ω + have hf (k : ℕ) (hk : k < 2 ^ n + 1) : + f k = X (unitDyadicGrid n ⟨k, hk⟩) ω := by + simp only [f, dif_pos hk] + calc + edist (X (unitDyadicGrid n i) ω) (X (unitDyadicGrid n j) ω) = + edist (f i) (f j) := by rw [hf i i.isLt, hf j j.isLt] + _ ≤ ∑ _k ∈ Finset.Ico i.val j.val, ε := by + apply edist_le_Ico_sum_of_edist_le hij + intro k hik hkj + have hkpow : k < 2 ^ n := lt_of_lt_of_le hkj (Nat.le_of_lt_succ j.isLt) + have hksucc : k + 1 < 2 ^ n + 1 := Nat.add_lt_add_right hkpow 1 + rw [hf k (lt_trans hkpow (Nat.lt_succ_self _)), hf (k + 1) hksucc] + simpa only [Fin.val_castSucc, Fin.val_succ] using! hadj ⟨k, hkpow⟩ + _ = (j.val - i.val : ℕ) * ε := by + simp only [Finset.sum_const, Nat.card_Ico, nsmul_eq_mul] + +/-- Almost surely, on every sufficiently fine unit dyadic grid, the increment between +ordered grid points is bounded by their number of intervening cells times the level's +Kolmogorov--Chentsov threshold. -/ +theorem IsKolmogorovProcess.ae_eventually_edist_unitDyadicGrid_le_natCast_mul_threshold + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ᶠ n in Filter.atTop, ∀ i j : Fin (2 ^ n + 1), + (i : ℕ) ≤ j → + edist (X (unitDyadicGrid n i) ω) (X (unitDyadicGrid n j) ω) ≤ + (j.val - i.val : ℕ) * dyadicIncrementThreshold γ n := by + filter_upwards + [IsKolmogorovProcess.ae_eventually_edist_unitDyadicGrid_adjacent_lt_threshold + hX hγ hγq] with ω hω + filter_upwards [hω] with n hn + intro i j hij + exact edist_unitDyadicGrid_le_natCast_mul_of_adjacent_le + (fun k ↦ (hn k).le) i j hij + +end DyadicGridChaining + +section DyadicMultiscale + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] + +/-- The canonical inclusion of the level-`n` unit dyadic grid into level `n + 1`. +Its value is twice the old grid index. -/ +def unitDyadicRefineIndex (n : ℕ) (i : Fin (2 ^ n + 1)) : Fin (2 ^ (n + 1) + 1) := + ⟨2 * i.val, by + have hi : i.val ≤ 2 ^ n := Nat.le_of_lt_succ i.isLt + rw [pow_succ] + omega⟩ + +@[simp] +theorem unitDyadicRefineIndex_val (n : ℕ) (i : Fin (2 ^ n + 1)) : + (unitDyadicRefineIndex n i).val = 2 * i.val := + rfl + +/-- Refinement does not change the represented nonnegative rational time. -/ +theorem unitDyadicGrid_refineIndex (n : ℕ) (i : Fin (2 ^ n + 1)) : + unitDyadicGrid (n + 1) (unitDyadicRefineIndex n i) = unitDyadicGrid n i := by + simp only [unitDyadicGrid, unitDyadicRefineIndex_val] + rw [pow_succ] + push_cast + field_simp + +/-- The canonical level-`n` parent of a point on the level-`n + 1` unit dyadic grid. +It is obtained by rounding the fine-grid index down after division by two. -/ +def unitDyadicParentIndex (n : ℕ) (i : Fin (2 ^ (n + 1) + 1)) : Fin (2 ^ n + 1) := + ⟨i.val / 2, by + have hi : i.val ≤ 2 ^ (n + 1) := Nat.le_of_lt_succ i.isLt + have hi' : i.val ≤ 2 ^ n * 2 := by simpa only [pow_succ] using hi + omega⟩ + +@[simp] +theorem unitDyadicParentIndex_val (n : ℕ) (i : Fin (2 ^ (n + 1) + 1)) : + (unitDyadicParentIndex n i).val = i.val / 2 := + rfl + +/-- Refining the parent lies weakly to the left of its child. -/ +theorem unitDyadicRefineIndex_parent_le (n : ℕ) (i : Fin (2 ^ (n + 1) + 1)) : + (unitDyadicRefineIndex n (unitDyadicParentIndex n i)).val ≤ i.val := by + simp only [unitDyadicRefineIndex_val, unitDyadicParentIndex_val] + omega + +/-- A child is at most one fine-grid cell to the right of its refined parent. -/ +theorem unitDyadic_child_sub_refineIndex_parent_le_one + (n : ℕ) (i : Fin (2 ^ (n + 1) + 1)) : + i.val - (unitDyadicRefineIndex n (unitDyadicParentIndex n i)).val ≤ 1 := by + simp only [unitDyadicRefineIndex_val, unitDyadicParentIndex_val] + omega + +/-- The coarse-grid parent represents the same time as its refinement on the fine grid. -/ +theorem unitDyadicGrid_parent_eq_refineIndex + (n : ℕ) (i : Fin (2 ^ (n + 1) + 1)) : + unitDyadicGrid n (unitDyadicParentIndex n i) = + unitDyadicGrid (n + 1) (unitDyadicRefineIndex n (unitDyadicParentIndex n i)) := by + exact (unitDyadicGrid_refineIndex n (unitDyadicParentIndex n i)).symm + +/-- Adjacent-increment control on level `n + 1` controls every child-to-parent increment +by the same threshold. -/ +theorem edist_unitDyadicGrid_child_parent_le_of_adjacent_le + {X : NNRat → Ω → E} {n : ℕ} {ε : ℝ≥0∞} {ω : Ω} + (hadj : ∀ k : Fin (2 ^ (n + 1)), + edist (X (unitDyadicGrid (n + 1) k.castSucc) ω) + (X (unitDyadicGrid (n + 1) k.succ) ω) ≤ ε) + (i : Fin (2 ^ (n + 1) + 1)) : + edist (X (unitDyadicGrid (n + 1) i) ω) + (X (unitDyadicGrid n (unitDyadicParentIndex n i)) ω) ≤ ε := by + let j := unitDyadicRefineIndex n (unitDyadicParentIndex n i) + have hji : j.val ≤ i.val := unitDyadicRefineIndex_parent_le n i + have hsub : i.val - j.val ≤ 1 := + unitDyadic_child_sub_refineIndex_parent_le_one n i + calc + edist (X (unitDyadicGrid (n + 1) i) ω) + (X (unitDyadicGrid n (unitDyadicParentIndex n i)) ω) = + edist (X (unitDyadicGrid (n + 1) j) ω) + (X (unitDyadicGrid (n + 1) i) ω) := by + rw [edist_comm, unitDyadicGrid_parent_eq_refineIndex] + _ ≤ (i.val - j.val : ℕ) * ε := + edist_unitDyadicGrid_le_natCast_mul_of_adjacent_le hadj j i hji + _ ≤ (1 : ℝ≥0∞) * ε := by + have hcast : ((i.val - j.val : ℕ) : ℝ≥0∞) ≤ 1 := by exact_mod_cast hsub + exact mul_le_mul_of_nonneg_right hcast bot_le + _ = ε := one_mul ε + +/-- Almost surely, on all sufficiently fine consecutive dyadic levels, every child is +within the fine level's Kolmogorov--Chentsov threshold of its canonical parent. -/ +theorem IsKolmogorovProcess.ae_eventually_edist_unitDyadicGrid_child_parent_le_threshold + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ᶠ n in Filter.atTop, ∀ i : Fin (2 ^ (n + 1) + 1), + edist (X (unitDyadicGrid (n + 1) i) ω) + (X (unitDyadicGrid n (unitDyadicParentIndex n i)) ω) ≤ + dyadicIncrementThreshold γ (n + 1) := by + filter_upwards + [IsKolmogorovProcess.ae_eventually_edist_unitDyadicGrid_adjacent_lt_threshold + hX hγ hγq] with ω hω + rw [Filter.eventually_atTop] at hω ⊢ + obtain ⟨N, hN⟩ := hω + refine ⟨N, fun n hn i ↦ ?_⟩ + apply edist_unitDyadicGrid_child_parent_le_of_adjacent_le + intro k + exact (hN (n + 1) (hn.trans (Nat.le_succ n)) k).le + +end DyadicMultiscale + +section DyadicAncestorChaining + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] + +/-- The canonical level-`n` ancestor of a point lying `r` dyadic refinements above it. -/ +def unitDyadicAncestorIndex (n : ℕ) : + (r : ℕ) → Fin (2 ^ (n + r) + 1) → Fin (2 ^ n + 1) + | 0, i => i + | r + 1, i => + unitDyadicAncestorIndex n r (unitDyadicParentIndex (n + r) i) + +@[simp] +theorem unitDyadicAncestorIndex_zero (n : ℕ) (i : Fin (2 ^ n + 1)) : + unitDyadicAncestorIndex n 0 i = i := + rfl + +@[simp] +theorem unitDyadicAncestorIndex_succ + (n r : ℕ) (i : Fin (2 ^ (n + (r + 1)) + 1)) : + unitDyadicAncestorIndex n (r + 1) i = + unitDyadicAncestorIndex n r (unitDyadicParentIndex (n + r) i) := + rfl + +/-- Iterating child-to-parent bounds controls the increment from a fine-grid point to its +canonical ancestor by the corresponding finite sum. -/ +theorem edist_unitDyadicGrid_ancestor_le_sum_of_child_parent_le + {X : NNRat → Ω → E} {n r : ℕ} {δ : ℕ → ℝ≥0∞} {ω : Ω} + (hparent : ∀ s < r, ∀ i : Fin (2 ^ (n + s + 1) + 1), + edist (X (unitDyadicGrid (n + s + 1) i) ω) + (X (unitDyadicGrid (n + s) (unitDyadicParentIndex (n + s) i)) ω) ≤ + δ (n + s + 1)) + (i : Fin (2 ^ (n + r) + 1)) : + edist (X (unitDyadicGrid (n + r) i) ω) + (X (unitDyadicGrid n (unitDyadicAncestorIndex n r i)) ω) ≤ + ∑ s ∈ Finset.range r, δ (n + s + 1) := by + induction r with + | zero => + simp only [Nat.add_zero, unitDyadicAncestorIndex_zero, Finset.range_zero, + Finset.sum_empty, edist_self] + exact le_rfl + | succ r ihr => + let j := unitDyadicParentIndex (n + r) i + have hlast : + edist (X (unitDyadicGrid (n + r + 1) i) ω) + (X (unitDyadicGrid (n + r) j) ω) ≤ δ (n + r + 1) := + hparent r (Nat.lt_succ_self r) i + have hprevious : + edist (X (unitDyadicGrid (n + r) j) ω) + (X (unitDyadicGrid n (unitDyadicAncestorIndex n r j)) ω) ≤ + ∑ s ∈ Finset.range r, δ (n + s + 1) := by + apply ihr + intro s hs k + exact hparent s (hs.trans (Nat.lt_succ_self r)) k + calc + edist (X (unitDyadicGrid (n + (r + 1)) i) ω) + (X (unitDyadicGrid n (unitDyadicAncestorIndex n (r + 1) i)) ω) = + edist (X (unitDyadicGrid (n + r + 1) i) ω) + (X (unitDyadicGrid n (unitDyadicAncestorIndex n r j)) ω) := by + rfl + _ ≤ edist (X (unitDyadicGrid (n + r + 1) i) ω) + (X (unitDyadicGrid (n + r) j) ω) + + edist (X (unitDyadicGrid (n + r) j) ω) + (X (unitDyadicGrid n (unitDyadicAncestorIndex n r j)) ω) := + edist_triangle _ _ _ + _ ≤ δ (n + r + 1) + ∑ s ∈ Finset.range r, δ (n + s + 1) := + add_le_add hlast hprevious + _ = ∑ s ∈ Finset.range (r + 1), δ (n + s + 1) := by + rw [Finset.sum_range_succ] + exact add_comm _ _ + +/-- Almost surely, every sufficiently fine base level admits all finite canonical ancestor +chains, with total increment bounded by the finite sum of dyadic thresholds along the chain. -/ +theorem IsKolmogorovProcess.ae_eventually_edist_unitDyadicGrid_ancestor_le_sum_threshold + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ᶠ n in Filter.atTop, ∀ r (i : Fin (2 ^ (n + r) + 1)), + edist (X (unitDyadicGrid (n + r) i) ω) + (X (unitDyadicGrid n (unitDyadicAncestorIndex n r i)) ω) ≤ + ∑ s ∈ Finset.range r, dyadicIncrementThreshold γ (n + s + 1) := by + filter_upwards + [IsKolmogorovProcess.ae_eventually_edist_unitDyadicGrid_child_parent_le_threshold + hX hγ hγq] with ω hω + rw [Filter.eventually_atTop] at hω ⊢ + obtain ⟨N, hN⟩ := hω + refine ⟨N, fun n hn r i ↦ ?_⟩ + apply edist_unitDyadicGrid_ancestor_le_sum_of_child_parent_le + intro s _hs j + exact hN (n + s) (hn.trans (Nat.le_add_right n s)) j + +end DyadicAncestorChaining + +section DyadicAncestorTail + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] + +/-- Every finite sum of thresholds above base level `n` is bounded by the exact infinite +tail beginning at level `n + 1`. -/ +theorem sum_dyadicIncrementThreshold_ancestor_le_tail (γ : ℝ) (n r : ℕ) : + ∑ s ∈ Finset.range r, dyadicIncrementThreshold γ (n + s + 1) ≤ + dyadicIncrementThreshold γ (n + 1) * + (1 - dyadicIncrementThresholdRatio γ)⁻¹ := by + simpa only [Nat.add_assoc, Nat.add_left_comm, Nat.add_comm] using + sum_dyadicIncrementThreshold_add_le γ (n + 1) r + +/-- Almost surely, above every sufficiently fine base level, all finite canonical ancestor +chains are bounded uniformly in their depth and endpoint by the exact infinite threshold +tail. -/ +theorem IsKolmogorovProcess.ae_eventually_edist_unitDyadicGrid_ancestor_le_tail + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ᶠ n in atTop, ∀ r (i : Fin (2 ^ (n + r) + 1)), + edist (X (unitDyadicGrid (n + r) i) ω) + (X (unitDyadicGrid n (unitDyadicAncestorIndex n r i)) ω) ≤ + dyadicIncrementThreshold γ (n + 1) * + (1 - dyadicIncrementThresholdRatio γ)⁻¹ := by + filter_upwards + [IsKolmogorovProcess.ae_eventually_edist_unitDyadicGrid_ancestor_le_sum_threshold + hX hγ hγq] with ω hω + filter_upwards [hω] with n hn + intro r i + exact (hn r i).trans (sum_dyadicIncrementThreshold_ancestor_le_tail γ n r) + +/-- For a positive exponent, the exact infinite threshold-tail bound above level `n` +tends to zero as `n` tends to infinity. -/ +theorem tendsto_dyadicIncrementThreshold_ancestor_tail_zero + {γ : ℝ} (hγ : 0 < γ) : + Tendsto + (fun n : ℕ ↦ dyadicIncrementThreshold γ (n + 1) * + (1 - dyadicIncrementThresholdRatio γ)⁻¹) + atTop (nhds 0) := by + have hratio : dyadicIncrementThresholdRatio γ < 1 := + dyadicIncrementThresholdRatio_lt_one hγ + have hpow : Tendsto (fun n : ℕ ↦ dyadicIncrementThresholdRatio γ ^ n) + atTop (nhds 0) := + ENNReal.tendsto_pow_atTop_nhds_zero_of_lt_one hratio + have hpow_succ : Tendsto (fun n : ℕ ↦ dyadicIncrementThresholdRatio γ ^ (n + 1)) + atTop (nhds 0) := + (tendsto_add_atTop_iff_nat 1).mpr hpow + have htail_ne_top : (1 - dyadicIncrementThresholdRatio γ)⁻¹ ≠ ∞ := + ENNReal.inv_ne_top.mpr (tsub_pos_iff_lt.mpr hratio).ne' + simpa only [dyadicIncrementThreshold_eq_ratio_pow, zero_mul] using + ENNReal.Tendsto.mul_const hpow_succ (Or.inr htail_ne_top) + +end DyadicAncestorTail + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicFloor.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicFloor.lean new file mode 100644 index 0000000000..6045e7f1a9 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicFloor.lean @@ -0,0 +1,781 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining +import Mathlib.Algebra.Order.Floor.Semiring +import Mathlib.MeasureTheory.Function.ConvergenceInMeasure +import Mathlib.MeasureTheory.Integral.Lebesgue.Markov + +/-! +# Dyadic floor approximation and the unit-interval continuous modification + +This file merges the following former modules, one section each: + +* `DyadicFloorApproximation`: Left dyadic approximations of unit-interval times +* `DyadicFloorPair`: Comparing two dyadic floor approximations +* `DyadicFloorSampleCauchy`: Cauchy control of dyadic floor samples +* `DyadicFloorDenseTime`: Dyadic floor samples at dyadic times +* `DyadicFloorSampleLimit`: Limits of dyadic floor samples +* `DyadicFloorLimitControl`: Uniform control of dyadic floor-sample limits +* `DyadicFloorLimitPath`: The canonical unit-interval dyadic-floor limit path +* `DyadicFloorConvergenceInMeasure`: Convergence in measure of dyadic floor samples +* `DyadicFloorUnitModification`: A continuous modification on the unit interval +-/ + +namespace MarkovProcess + +section DyadicFloorApproximation + + +noncomputable section + +/-- The index of the left endpoint of the level-`n` dyadic cell containing `t ∈ [0, 1]`. -/ +def unitDyadicFloorIndex (n : ℕ) (t : Set.Icc (0 : ℝ) 1) : Fin (2 ^ n + 1) := + ⟨⌊(2 ^ n : ℝ) * t.1⌋₊, by + have hnonneg : 0 ≤ (2 ^ n : ℝ) * t.1 := + mul_nonneg (by positivity) t.2.1 + have hfloor_real : (⌊(2 ^ n : ℝ) * t.1⌋₊ : ℝ) ≤ (2 ^ n : ℝ) * t.1 := + Nat.floor_le hnonneg + have hscaled_le : (2 ^ n : ℝ) * t.1 ≤ (2 ^ n : ℝ) := by + simpa only [mul_one] using mul_le_mul_of_nonneg_left t.2.2 (by positivity) + have hfloor_nat : ⌊(2 ^ n : ℝ) * t.1⌋₊ ≤ 2 ^ n := by + exact_mod_cast hfloor_real.trans hscaled_le + omega⟩ + +@[simp] +theorem unitDyadicFloorIndex_val (n : ℕ) (t : Set.Icc (0 : ℝ) 1) : + (unitDyadicFloorIndex n t).val = ⌊(2 ^ n : ℝ) * t.1⌋₊ := + rfl + +/-- The rational level-`n` left dyadic approximation of `t`. -/ +def unitDyadicFloorValue (n : ℕ) (t : Set.Icc (0 : ℝ) 1) : NNRat := + unitDyadicGrid n (unitDyadicFloorIndex n t) + +/-- The left dyadic approximation does not exceed the represented real time. -/ +theorem unitDyadicFloorValue_le (n : ℕ) (t : Set.Icc (0 : ℝ) 1) : + (unitDyadicFloorValue n t : ℝ) ≤ t.1 := by + have hnonneg : 0 ≤ (2 ^ n : ℝ) * t.1 := + mul_nonneg (by positivity) t.2.1 + have hfloor := Nat.floor_le hnonneg + unfold unitDyadicFloorValue unitDyadicGrid + simp only [unitDyadicFloorIndex_val] + push_cast + exact (div_le_iff₀' (by positivity)).2 (by simpa only [mul_comm] using hfloor) + +/-- The gap from `t` to its level-`n` left approximation is at most one dyadic cell. -/ +theorem sub_unitDyadicFloorValue_le (n : ℕ) (t : Set.Icc (0 : ℝ) 1) : + t.1 - (unitDyadicFloorValue n t : ℝ) ≤ ((2 : ℝ) ^ n)⁻¹ := by + have hupper := Nat.lt_floor_add_one ((2 ^ n : ℝ) * t.1) + unfold unitDyadicFloorValue unitDyadicGrid + simp only [unitDyadicFloorIndex_val] + push_cast + have hpow : 0 < (2 : ℝ) ^ n := by positivity + apply le_of_lt + rw [sub_lt_iff_lt_add, inv_eq_one_div] + calc + t.1 = ((2 : ℝ) ^ n * t.1) / (2 : ℝ) ^ n := by field_simp + _ < (⌊(2 ^ n : ℝ) * t.1⌋₊ + 1) / (2 : ℝ) ^ n := + (div_lt_div_iff_of_pos_right hpow).2 hupper + _ = 1 / (2 : ℝ) ^ n + (⌊(2 ^ n : ℝ) * t.1⌋₊ : ℝ) / (2 : ℝ) ^ n := by + rw [add_div] + ring + +/-- Passing from level `n + 1` to its canonical parent recovers the level-`n` left index. -/ +theorem unitDyadicParentIndex_floorIndex (n : ℕ) (t : Set.Icc (0 : ℝ) 1) : + unitDyadicParentIndex n (unitDyadicFloorIndex (n + 1) t) = + unitDyadicFloorIndex n t := by + apply Fin.ext + simp only [unitDyadicParentIndex_val, unitDyadicFloorIndex_val] + have harg : (2 ^ (n + 1) : ℝ) * t.1 = ((2 ^ n : ℝ) * t.1) * 2 := by + rw [pow_succ] + ring + rw [harg] + exact Nat.mul_cast_floor_div_cancel (R := ℝ) (by norm_num : 2 ≠ 0) + ((2 ^ n : ℝ) * t.1) + +/-- At consecutive levels, the fine left index is either the refinement of the coarse index or +the immediately following fine-grid index. -/ +theorem unitDyadicFloorIndex_sub_refineIndex_le_one (n : ℕ) (t : Set.Icc (0 : ℝ) 1) : + (unitDyadicFloorIndex (n + 1) t).val - + (unitDyadicRefineIndex n (unitDyadicFloorIndex n t)).val ≤ 1 := by + rw [← unitDyadicParentIndex_floorIndex n t] + exact unitDyadic_child_sub_refineIndex_parent_le_one n (unitDyadicFloorIndex (n + 1) t) + +end + +end DyadicFloorApproximation + +section DyadicFloorPair + +open Filter MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + + +noncomputable section + +/-- Dyadic floor indices preserve the order of their represented times. -/ +theorem unitDyadicFloorIndex_mono (n : ℕ) {s t : Set.Icc (0 : ℝ) 1} + (hst : s.1 ≤ t.1) : + (unitDyadicFloorIndex n s).val ≤ (unitDyadicFloorIndex n t).val := by + simp only [unitDyadicFloorIndex_val] + exact Nat.floor_mono (mul_le_mul_of_nonneg_left hst (by positivity)) + +/-- Two ordered times separated by at most one level-`n` cell have floor indices separated by +at most one. -/ +theorem unitDyadicFloorIndex_sub_le_one_of_sub_le_inv_pow + (n : ℕ) {s t : Set.Icc (0 : ℝ) 1} (hst : s.1 ≤ t.1) + (hgap : t.1 - s.1 ≤ ((2 : ℝ) ^ n)⁻¹) : + (unitDyadicFloorIndex n t).val - (unitDyadicFloorIndex n s).val ≤ 1 := by + let c : ℝ := (2 : ℝ) ^ n + have hc : 0 < c := by + dsimp only [c] + positivity + have hscaled : c * (t.1 - s.1) ≤ 1 := by + calc + c * (t.1 - s.1) ≤ c * c⁻¹ := + mul_le_mul_of_nonneg_left hgap hc.le + _ = 1 := mul_inv_cancel₀ hc.ne' + have hmul : c * t.1 ≤ c * s.1 + 1 := by + calc + c * t.1 = c * s.1 + c * (t.1 - s.1) := by ring + _ ≤ c * s.1 + 1 := add_le_add_right hscaled _ + have hfloor : ⌊c * t.1⌋₊ ≤ ⌊c * s.1⌋₊ + 1 := by + calc + ⌊c * t.1⌋₊ ≤ ⌊c * s.1 + 1⌋₊ := Nat.floor_mono hmul + _ = ⌊c * s.1⌋₊ + 1 := Nat.floor_add_one (mul_nonneg hc.le s.2.1) + have hmono : ⌊c * s.1⌋₊ ≤ ⌊c * t.1⌋₊ := + Nat.floor_mono (mul_le_mul_of_nonneg_left hst hc.le) + simp only [unitDyadicFloorIndex_val] + change ⌊c * t.1⌋₊ - ⌊c * s.1⌋₊ ≤ 1 + omega + +/-- Adjacent-increment control on level `n` controls the process increment between two ordered +times lying at most one level-`n` cell apart. -/ +theorem edist_unitDyadicFloorValue_le_of_sub_le_inv_pow_of_adjacent_le + {Ω E : Type*} [PseudoEMetricSpace E] {X : NNRat → Ω → E} + {n : ℕ} {ε : ℝ≥0∞} {ω : Ω} + (hadj : ∀ k : Fin (2 ^ n), + edist (X (unitDyadicGrid n k.castSucc) ω) + (X (unitDyadicGrid n k.succ) ω) ≤ ε) + {s t : Set.Icc (0 : ℝ) 1} (hst : s.1 ≤ t.1) + (hgap : t.1 - s.1 ≤ ((2 : ℝ) ^ n)⁻¹) : + edist (X (unitDyadicFloorValue n s) ω) + (X (unitDyadicFloorValue n t) ω) ≤ ε := by + have hmono := unitDyadicFloorIndex_mono n hst + have hdiff := unitDyadicFloorIndex_sub_le_one_of_sub_le_inv_pow n hst hgap + calc + edist (X (unitDyadicFloorValue n s) ω) + (X (unitDyadicFloorValue n t) ω) ≤ + ((unitDyadicFloorIndex n t).val - (unitDyadicFloorIndex n s).val : ℕ) * ε := by + simpa only [unitDyadicFloorValue] using + edist_unitDyadicGrid_le_natCast_mul_of_adjacent_le hadj + (unitDyadicFloorIndex n s) (unitDyadicFloorIndex n t) hmono + _ ≤ (1 : ℝ≥0∞) * ε := by + have hcast : + (((unitDyadicFloorIndex n t).val - (unitDyadicFloorIndex n s).val : ℕ) : + ℝ≥0∞) ≤ 1 := by + exact_mod_cast hdiff + exact mul_le_mul_of_nonneg_right hcast bot_le + _ = ε := one_mul ε + +/-- Almost surely, on all sufficiently fine dyadic levels, any two ordered unit-interval times +within one cell have process increment bounded by that level's Kolmogorov--Chentsov threshold. -/ +theorem IsKolmogorovProcess.ae_eventually_edist_unitDyadicFloorValue_le_threshold + {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ᶠ n in atTop, ∀ s t : Set.Icc (0 : ℝ) 1, + s.1 ≤ t.1 → t.1 - s.1 ≤ ((2 : ℝ) ^ n)⁻¹ → + edist (X (unitDyadicFloorValue n s) ω) + (X (unitDyadicFloorValue n t) ω) ≤ dyadicIncrementThreshold γ n := by + filter_upwards + [IsKolmogorovProcess.ae_eventually_edist_unitDyadicGrid_adjacent_lt_threshold + hX hγ hγq] with ω hω + filter_upwards [hω] with n hn + intro s t hst hgap + exact edist_unitDyadicFloorValue_le_of_sub_le_inv_pow_of_adjacent_le + (fun k ↦ (hn k).le) hst hgap + +end + +end DyadicFloorPair + +section DyadicFloorSampleCauchy + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] + +/-- Iterating canonical parents of the level-`n + r` floor index recovers the level-`n` +floor index. -/ +theorem unitDyadicAncestorIndex_floorIndex + (n r : ℕ) (t : Set.Icc (0 : ℝ) 1) : + unitDyadicAncestorIndex n r (unitDyadicFloorIndex (n + r) t) = + unitDyadicFloorIndex n t := by + induction r with + | zero => rfl + | succ r ihr => + have hparent : + unitDyadicParentIndex (n + r) (unitDyadicFloorIndex (n + (r + 1)) t) = + unitDyadicFloorIndex (n + r) t := by + simpa only [Nat.add_assoc] using! unitDyadicParentIndex_floorIndex (n + r) t + rw [unitDyadicAncestorIndex_succ, hparent] + exact ihr + +/-- Almost surely, above every sufficiently fine base level, the floor samples at levels +`n + r` and `n` are bounded uniformly in the depth `r` and time `t` by the vanishing +ancestor tail. -/ +theorem IsKolmogorovProcess.ae_eventually_edist_unitDyadicFloorValue_add_le_tail + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ᶠ n in atTop, ∀ r (t : Set.Icc (0 : ℝ) 1), + edist (X (unitDyadicFloorValue (n + r) t) ω) + (X (unitDyadicFloorValue n t) ω) ≤ + dyadicIncrementThreshold γ (n + 1) * + (1 - dyadicIncrementThresholdRatio γ)⁻¹ := by + filter_upwards + [IsKolmogorovProcess.ae_eventually_edist_unitDyadicGrid_ancestor_le_tail + hX hγ hγq] with ω hω + filter_upwards [hω] with n hn + intro r t + simpa only [unitDyadicFloorValue, unitDyadicAncestorIndex_floorIndex] using + hn r (unitDyadicFloorIndex (n + r) t) + +/-- Almost surely, for every time in the unit interval, the sequence of process samples at +its left dyadic approximations is Cauchy. -/ +theorem IsKolmogorovProcess.ae_cauchySeq_unitDyadicFloorValue + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ t : Set.Icc (0 : ℝ) 1, + CauchySeq (fun n : ℕ ↦ X (unitDyadicFloorValue n t) ω) := by + filter_upwards + [IsKolmogorovProcess.ae_eventually_edist_unitDyadicFloorValue_add_le_tail + hX hγ hγq] with ω hω + rw [eventually_atTop] at hω + obtain ⟨N₀, hN₀⟩ := hω + intro t + apply EMetric.cauchySeq_iff'.2 + intro ε hε + have htail : ∀ᶠ n : ℕ in atTop, + dyadicIncrementThreshold γ (n + 1) * + (1 - dyadicIncrementThresholdRatio γ)⁻¹ < ε := + (tendsto_dyadicIncrementThreshold_ancestor_tail_zero hγ).eventually + (gt_mem_nhds hε) + rw [eventually_atTop] at htail + obtain ⟨N₁, hN₁⟩ := htail + let N := max N₀ N₁ + refine ⟨N, fun m hm ↦ ?_⟩ + let r := m - N + have hNm : N + r = m := Nat.add_sub_of_le hm + have hbound := hN₀ N (le_max_left N₀ N₁) r t + have htailN := hN₁ N (le_max_right N₀ N₁) + rw [hNm] at hbound + exact hbound.trans_lt htailN + +end DyadicFloorSampleCauchy + +section DyadicFloorDenseTime + + +noncomputable section + +/-- A point of the level-`n` unit dyadic grid, regarded as a real time in `[0, 1]`. -/ +def unitDyadicGridTime (n : ℕ) (i : Fin (2 ^ n + 1)) : Set.Icc (0 : ℝ) 1 := + ⟨(unitDyadicGrid n i : ℝ), by + constructor + · positivity + · unfold unitDyadicGrid + push_cast + apply (div_le_one (by positivity)).2 + exact_mod_cast Nat.le_of_lt_succ i.isLt⟩ + +@[simp] +theorem unitDyadicGridTime_val (n : ℕ) (i : Fin (2 ^ n + 1)) : + (unitDyadicGridTime n i).1 = (unitDyadicGrid n i : ℝ) := + rfl + +/-- At every refinement of a dyadic grid, the left floor index of an old grid point is +the correspondingly refined integer index. -/ +theorem unitDyadicFloorIndex_gridTime_add (n r : ℕ) (i : Fin (2 ^ n + 1)) : + (unitDyadicFloorIndex (n + r) (unitDyadicGridTime n i)).val = i.val * 2 ^ r := by + simp only [unitDyadicFloorIndex_val, unitDyadicGridTime_val, unitDyadicGrid] + push_cast + have harg : + (2 ^ (n + r) : ℝ) * ((i.val : ℝ) / (2 ^ n : ℝ)) = + (i.val * 2 ^ r : ℕ) := by + rw [pow_add] + push_cast + field_simp + rw [harg, Nat.floor_natCast] + +/-- Every refinement-level left dyadic approximation of a dyadic grid point is exactly +that grid point. -/ +theorem unitDyadicFloorValue_gridTime_add (n r : ℕ) (i : Fin (2 ^ n + 1)) : + unitDyadicFloorValue (n + r) (unitDyadicGridTime n i) = unitDyadicGrid n i := by + unfold unitDyadicFloorValue unitDyadicGrid + simp only [unitDyadicFloorIndex_gridTime_add] + push_cast + rw [pow_add] + field_simp + +/-- From the level where a dyadic time first appears onward, all its dyadic floor +approximations equal that time. -/ +theorem unitDyadicFloorValue_gridTime_of_le + {n m : ℕ} (hnm : n ≤ m) (i : Fin (2 ^ n + 1)) : + unitDyadicFloorValue m (unitDyadicGridTime n i) = unitDyadicGrid n i := by + obtain ⟨r, rfl⟩ := Nat.exists_eq_add_of_le hnm + exact unitDyadicFloorValue_gridTime_add n r i + +/-- Sampling any dense-time family along dyadic floor approximations at a dyadic time is +eventually exactly the original dense-time sample. -/ +theorem eventually_sample_unitDyadicFloorValue_gridTime + {E Ω : Type*} (X : NNRat → Ω → E) (n : ℕ) (i : Fin (2 ^ n + 1)) (ω : Ω) : + ∀ᶠ m in Filter.atTop, + X (unitDyadicFloorValue m (unitDyadicGridTime n i)) ω = X (unitDyadicGrid n i) ω := by + rw [Filter.eventually_atTop] + exact ⟨n, fun m hnm ↦ congrArg (fun q ↦ X q ω) + (unitDyadicFloorValue_gridTime_of_le hnm i)⟩ + +/-- Any topological limit of the dyadic floor samples at a dyadic time is the original +dense-time sample at that time. -/ +theorem eq_sample_of_tendsto_unitDyadicFloorValue_gridTime + {E Ω : Type*} [TopologicalSpace E] [T2Space E] + (X : NNRat → Ω → E) (n : ℕ) (i : Fin (2 ^ n + 1)) (ω : Ω) (y : E) + (hlim : Filter.Tendsto + (fun m ↦ X (unitDyadicFloorValue m (unitDyadicGridTime n i)) ω) + Filter.atTop (nhds y)) : + y = X (unitDyadicGrid n i) ω := by + have horiginal : Filter.Tendsto + (fun m ↦ X (unitDyadicFloorValue m (unitDyadicGridTime n i)) ω) + Filter.atTop (nhds (X (unitDyadicGrid n i) ω)) := + tendsto_const_nhds.congr' + ((eventually_sample_unitDyadicFloorValue_gridTime X n i ω).mono + fun _ hm ↦ hm.symm) + exact tendsto_nhds_unique hlim horiginal + +end + +end DyadicFloorDenseTime + +section DyadicFloorSampleLimit + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} + [PseudoEMetricSpace E] [T2Space E] [CompleteSpace E] + +/-- Almost surely, at every time in the unit interval, the process samples along the left +dyadic approximations converge to a unique point. -/ +theorem IsKolmogorovProcess.ae_existsUnique_tendsto_unitDyadicFloorValue + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ t : Set.Icc (0 : ℝ) 1, + ∃! y : E, Tendsto (fun n : ℕ ↦ X (unitDyadicFloorValue n t) ω) atTop (𝓝 y) := by + filter_upwards + [IsKolmogorovProcess.ae_cauchySeq_unitDyadicFloorValue hX hγ hγq] with ω hω + intro t + obtain ⟨y, hy⟩ := cauchySeq_tendsto_of_complete (hω t) + refine ⟨y, hy, fun z hz ↦ ?_⟩ + exact tendsto_nhds_unique hz hy + +end DyadicFloorSampleLimit + +section DyadicFloorLimitControl + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + + +noncomputable section + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] + +/-- The deterministic modulus obtained from two ancestor tails and one same-level increment. -/ +def dyadicFloorLimitModulus (γ : ℝ) (n : ℕ) : ℝ≥0∞ := + dyadicIncrementThreshold γ (n + 1) * + (1 - dyadicIncrementThresholdRatio γ)⁻¹ + + dyadicIncrementThreshold γ n + + dyadicIncrementThreshold γ (n + 1) * + (1 - dyadicIncrementThresholdRatio γ)⁻¹ + +/-- For a positive exponent, the dyadic floor-limit modulus vanishes at fine scales. -/ +theorem tendsto_dyadicFloorLimitModulus_zero {γ : ℝ} (hγ : 0 < γ) : + Tendsto (dyadicFloorLimitModulus γ) atTop (nhds 0) := by + have hratio : dyadicIncrementThresholdRatio γ < 1 := + dyadicIncrementThresholdRatio_lt_one hγ + have hthreshold : + Tendsto (dyadicIncrementThreshold γ) atTop (nhds 0) := by + rw [show dyadicIncrementThreshold γ = + fun n : ℕ ↦ dyadicIncrementThresholdRatio γ ^ n by + funext n + exact dyadicIncrementThreshold_eq_ratio_pow γ n] + exact ENNReal.tendsto_pow_atTop_nhds_zero_of_lt_one hratio + have htail := tendsto_dyadicIncrementThreshold_ancestor_tail_zero hγ + simpa only [dyadicFloorLimitModulus, zero_add] using! + (htail.add hthreshold).add htail + +/-- A uniform ancestor-tail bound and a same-level comparison bound pass to arbitrary limits of +the two floor-sample sequences. -/ +theorem edist_limit_le_dyadicFloorLimitModulus + {X : NNRat → Ω → E} {γ : ℝ} {n : ℕ} {ω : Ω} + {s t : Set.Icc (0 : ℝ) 1} {y z : E} + (htail : ∀ r (u : Set.Icc (0 : ℝ) 1), + edist (X (unitDyadicFloorValue (n + r) u) ω) + (X (unitDyadicFloorValue n u) ω) ≤ + dyadicIncrementThreshold γ (n + 1) * + (1 - dyadicIncrementThresholdRatio γ)⁻¹) + (hpair : edist (X (unitDyadicFloorValue n s) ω) + (X (unitDyadicFloorValue n t) ω) ≤ dyadicIncrementThreshold γ n) + (hy : Tendsto (fun m : ℕ ↦ X (unitDyadicFloorValue m s) ω) atTop (nhds y)) + (hz : Tendsto (fun m : ℕ ↦ X (unitDyadicFloorValue m t) ω) atTop (nhds z)) : + edist y z ≤ dyadicFloorLimitModulus γ n := by + have hy_shift : Tendsto + (fun r : ℕ ↦ X (unitDyadicFloorValue (n + r) s) ω) atTop (nhds y) := + by simpa only [Nat.add_comm] using (tendsto_add_atTop_iff_nat n).mpr hy + have hz_shift : Tendsto + (fun r : ℕ ↦ X (unitDyadicFloorValue (n + r) t) ω) atTop (nhds z) := + by simpa only [Nat.add_comm] using (tendsto_add_atTop_iff_nat n).mpr hz + have hy_base : edist y (X (unitDyadicFloorValue n s) ω) ≤ + dyadicIncrementThreshold γ (n + 1) * + (1 - dyadicIncrementThresholdRatio γ)⁻¹ := by + rw [edist_comm] + refine le_of_tendsto (tendsto_const_nhds.edist hy_shift) ?_ + exact Eventually.of_forall fun r ↦ by + simpa only [edist_comm] using htail r s + have hz_base : edist (X (unitDyadicFloorValue n t) ω) z ≤ + dyadicIncrementThreshold γ (n + 1) * + (1 - dyadicIncrementThresholdRatio γ)⁻¹ := by + refine le_of_tendsto (tendsto_const_nhds.edist hz_shift) ?_ + exact Eventually.of_forall fun r ↦ by + simpa only [edist_comm] using htail r t + unfold dyadicFloorLimitModulus + calc + edist y z ≤ edist y (X (unitDyadicFloorValue n s) ω) + + edist (X (unitDyadicFloorValue n s) ω) z := + edist_triangle _ _ _ + _ ≤ edist y (X (unitDyadicFloorValue n s) ω) + + (edist (X (unitDyadicFloorValue n s) ω) + (X (unitDyadicFloorValue n t) ω) + + edist (X (unitDyadicFloorValue n t) ω) z) := + add_le_add le_rfl (edist_triangle _ _ _) + _ = (edist y (X (unitDyadicFloorValue n s) ω) + + edist (X (unitDyadicFloorValue n s) ω) + (X (unitDyadicFloorValue n t) ω)) + + edist (X (unitDyadicFloorValue n t) ω) z := by + rw [add_assoc] + _ ≤ (dyadicIncrementThreshold γ (n + 1) * + (1 - dyadicIncrementThresholdRatio γ)⁻¹) + + dyadicIncrementThreshold γ n + + (dyadicIncrementThreshold γ (n + 1) * + (1 - dyadicIncrementThresholdRatio γ)⁻¹) := by + exact add_le_add (add_le_add hy_base hpair) hz_base + +/-- Almost surely, at every sufficiently fine dyadic scale, any limits of the floor-sample +sequences at two ordered times in one cell obey the vanishing floor-limit modulus. -/ +theorem IsKolmogorovProcess.ae_eventually_edist_floorSample_limits_le_modulus + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ᶠ n in atTop, ∀ s t : Set.Icc (0 : ℝ) 1, + s.1 ≤ t.1 → t.1 - s.1 ≤ ((2 : ℝ) ^ n)⁻¹ → + ∀ y z : E, + Tendsto (fun m : ℕ ↦ X (unitDyadicFloorValue m s) ω) atTop (nhds y) → + Tendsto (fun m : ℕ ↦ X (unitDyadicFloorValue m t) ω) atTop (nhds z) → + edist y z ≤ dyadicFloorLimitModulus γ n := by + filter_upwards + [IsKolmogorovProcess.ae_eventually_edist_unitDyadicFloorValue_add_le_tail hX hγ hγq, + IsKolmogorovProcess.ae_eventually_edist_unitDyadicFloorValue_le_threshold hX hγ hγq] + with ω htail hpair + filter_upwards [htail, hpair] with n hn_tail hn_pair + intro s t hst hgap y z hy hz + exact edist_limit_le_dyadicFloorLimitModulus hn_tail (hn_pair s t hst hgap) hy hz + +end + +end DyadicFloorLimitControl + +section DyadicFloorLimitPath + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + + +noncomputable section + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} + [PseudoMetricSpace E] [CompleteSpace E] + +/-- The canonical Mathlib limit of the left dyadic samples on the unit interval. -/ +def unitDyadicFloorLimit (X : NNRat → Ω → E) (ω : Ω) + (t : Set.Icc (0 : ℝ) 1) : E := + letI : Nonempty E := ⟨X 0 ω⟩ + limUnder atTop (fun n : ℕ ↦ X (unitDyadicFloorValue n t) ω) + +/-- A Cauchy sequence of left dyadic samples converges to its canonical dyadic-floor limit. -/ +theorem tendsto_unitDyadicFloorLimit_of_cauchySeq + {X : NNRat → Ω → E} {ω : Ω} {t : Set.Icc (0 : ℝ) 1} + (h : CauchySeq (fun n : ℕ ↦ X (unitDyadicFloorValue n t) ω)) : + Tendsto (fun n : ℕ ↦ X (unitDyadicFloorValue n t) ω) atTop + (nhds (unitDyadicFloorLimit X ω t)) := by + simpa only [unitDyadicFloorLimit] using h.tendsto_limUnder + +/-- Almost surely, the left dyadic samples converge to the canonical limit simultaneously +at every time in the unit interval. -/ +theorem IsKolmogorovProcess.ae_tendsto_unitDyadicFloorLimit + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ t : Set.Icc (0 : ℝ) 1, + Tendsto (fun n : ℕ ↦ X (unitDyadicFloorValue n t) ω) atTop + (nhds (unitDyadicFloorLimit X ω t)) := by + filter_upwards + [IsKolmogorovProcess.ae_cauchySeq_unitDyadicFloorValue hX hγ hγq] with ω hω + exact fun t ↦ tendsto_unitDyadicFloorLimit_of_cauchySeq (hω t) + +/-- Almost surely, on every sufficiently fine scale, the canonical limit path obeys the +dyadic floor-limit modulus for all ordered pairs of nearby unit-interval times. -/ +theorem IsKolmogorovProcess.ae_eventually_edist_unitDyadicFloorLimit_le_modulus + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ᶠ n in atTop, ∀ s t : Set.Icc (0 : ℝ) 1, + s.1 ≤ t.1 → t.1 - s.1 ≤ ((2 : ℝ) ^ n)⁻¹ → + edist (unitDyadicFloorLimit X ω s) (unitDyadicFloorLimit X ω t) ≤ + dyadicFloorLimitModulus γ n := by + filter_upwards + [IsKolmogorovProcess.ae_eventually_edist_floorSample_limits_le_modulus hX hγ hγq, + IsKolmogorovProcess.ae_tendsto_unitDyadicFloorLimit hX hγ hγq] + with ω hmod hlim + filter_upwards [hmod] with n hn + intro s t hst hgap + exact hn s t hst hgap _ _ (hlim s) (hlim t) + +/-- Almost surely, the canonical dyadic-floor limit is continuous on the unit interval. -/ +theorem IsKolmogorovProcess.ae_continuous_unitDyadicFloorLimit + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, Continuous (unitDyadicFloorLimit X ω) := by + filter_upwards + [IsKolmogorovProcess.ae_eventually_edist_unitDyadicFloorLimit_le_modulus + hX hγ hγq] with ω hω + apply UniformContinuous.continuous + rw [Metric.uniformContinuous_iff] + intro ε hε + have hεE : 0 < ENNReal.ofReal ε := ENNReal.ofReal_pos.2 hε + have hsmall : ∀ᶠ n : ℕ in atTop, + dyadicFloorLimitModulus γ n < ENNReal.ofReal ε := + (tendsto_dyadicFloorLimitModulus_zero hγ).eventually (gt_mem_nhds hεE) + obtain ⟨n, hn, hmodε⟩ := (hω.and hsmall).exists + refine ⟨((2 : ℝ) ^ n)⁻¹, by positivity, ?_⟩ + intro s t hst + have hgap_abs : |t.1 - s.1| < ((2 : ℝ) ^ n)⁻¹ := by + change dist s.1 t.1 < ((2 : ℝ) ^ n)⁻¹ at hst + simpa only [Real.dist_eq, abs_sub_comm] using hst + have hedist : + edist (unitDyadicFloorLimit X ω s) (unitDyadicFloorLimit X ω t) < + ENNReal.ofReal ε := by + rcases le_total s.1 t.1 with hle | hle + · exact (hn s t hle (le_abs_self _ |>.trans hgap_abs.le)).trans_lt hmodε + · rw [edist_comm] + exact (hn t s hle (le_abs_self _ |>.trans (by + simpa only [abs_sub_comm] using hgap_abs.le))).trans_lt hmodε + rw [edist_dist, ENNReal.ofReal_lt_ofReal_iff hε] at hedist + exact hedist + +end + +end DyadicFloorLimitPath + +section DyadicFloorConvergenceInMeasure + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] + +/-- A nonnegative rational bounded by one, embedded in the real unit interval. -/ +def unitIccOfNNRat (t : NNRat) (ht : t ≤ 1) : Set.Icc (0 : ℝ) 1 := + ⟨(t : ℝ), by positivity, by exact_mod_cast ht⟩ + +@[simp] +theorem unitIccOfNNRat_val (t : NNRat) (ht : t ≤ 1) : + (unitIccOfNNRat t ht).1 = (t : ℝ) := + rfl + +/-- The dyadic-floor time is within one level-`n` cell of the original nonnegative rational +time. -/ +theorem edist_unitDyadicFloorValue_unitIccOfNNRat_le + (n : ℕ) (t : NNRat) (ht : t ≤ 1) : + edist (unitDyadicFloorValue n (unitIccOfNNRat t ht)) t ≤ + ENNReal.ofReal (((2 : ℝ) ^ n)⁻¹) := by + rw [edist_dist, NNRat.dist_eq, Rat.dist_eq] + push_cast + rw [abs_of_nonpos] + · apply ENNReal.ofReal_le_ofReal + simpa only [unitIccOfNNRat_val, neg_sub] using + sub_unitDyadicFloorValue_le n (unitIccOfNNRat t ht) + · exact sub_nonpos.mpr (by + simpa only [unitIccOfNNRat_val] using + unitDyadicFloorValue_le n (unitIccOfNNRat t ht)) + +/-- Markov's inequality applied to one increment of a Kolmogorov process. -/ +theorem measure_edist_ge_le_of_isKolmogorovProcess + {T : Type*} [PseudoEMetricSpace T] {P : Measure Ω} + {X : T → Ω → E} {p q : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (s t : T) (ε : ℝ≥0∞) + (hε0 : ε ≠ 0) (hεtop : ε ≠ ∞) : + P {ω | ε ≤ edist (X s ω) (X t ω)} ≤ M * edist s t ^ q / ε ^ p := by + calc + P {ω | ε ≤ edist (X s ω) (X t ω)} = + P {ω | ε ^ p ≤ edist (X s ω) (X t ω) ^ p} := by + congr 1 + ext ω + change (ε ≤ edist (X s ω) (X t ω)) ↔ + (ε ^ p ≤ edist (X s ω) (X t ω) ^ p) + exact (ENNReal.rpow_le_rpow_iff hX.p_pos).symm + _ ≤ (∫⁻ ω, edist (X s ω) (X t ω) ^ p ∂P) / ε ^ p := by + apply meas_ge_le_lintegral_div + · exact (hX.measurable_edist.pow_const p).aemeasurable + · exact (ENNReal.rpow_eq_zero_iff_of_pos hX.p_pos).not.mpr hε0 + · exact (ENNReal.rpow_eq_top_iff_of_pos hX.p_pos).not.mpr hεtop + _ ≤ M * edist s t ^ q / ε ^ p := by + gcongr + exact hX.kolmogorovCondition s t + +/-- The dyadic-floor times converge to the represented nonnegative rational time. -/ +theorem tendsto_edist_unitDyadicFloorValue_unitIccOfNNRat + (t : NNRat) (ht : t ≤ 1) : + Tendsto (fun n ↦ edist (unitDyadicFloorValue n (unitIccOfNNRat t ht)) t) + atTop (nhds 0) := by + have hbound : Tendsto (fun n : ℕ ↦ ENNReal.ofReal (((2 : ℝ) ^ n)⁻¹)) + atTop (nhds 0) := by + have hpow : Tendsto (fun n : ℕ ↦ ((2 : ℝ)⁻¹) ^ n) atTop (nhds 0) := + tendsto_pow_atTop_nhds_zero_of_lt_one (by positivity) (by norm_num) + convert ENNReal.tendsto_ofReal hpow using 1 + · funext n + rw [inv_pow] + · simp only [ENNReal.ofReal_zero] + exact tendsto_of_tendsto_of_tendsto_of_le_of_le tendsto_const_nhds hbound + (fun _ ↦ zero_le) + (fun n ↦ edist_unitDyadicFloorValue_unitIccOfNNRat_le n t ht) + +/-- At a fixed nonnegative rational time in `[0, 1]`, samples of a Kolmogorov process at the left +dyadic approximations converge in measure to the original process sample. -/ +theorem IsKolmogorovProcess.tendstoInMeasure_unitDyadicFloorValue + {P : Measure Ω} {X : NNRat → Ω → E} {p q : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (t : NNRat) (ht : t ≤ 1) : + TendstoInMeasure P + (fun n ↦ X (unitDyadicFloorValue n (unitIccOfNNRat t ht))) atTop (X t) := by + refine tendstoInMeasure_of_ne_top fun ε hε hεtop ↦ ?_ + have hed := tendsto_edist_unitDyadicFloorValue_unitIccOfNNRat t ht + have hrpow : Tendsto + (fun n ↦ edist (unitDyadicFloorValue n (unitIccOfNNRat t ht)) t ^ q) + atTop (nhds 0) := by + simpa only [ENNReal.zero_rpow_of_pos hX.q_pos] using hed.ennrpow_const q + have hrhs : Tendsto + (fun n ↦ M * edist (unitDyadicFloorValue n (unitIccOfNNRat t ht)) t ^ q / ε ^ p) + atTop (nhds 0) := by + have hmul : Tendsto + (fun n ↦ (M : ℝ≥0∞) * + edist (unitDyadicFloorValue n (unitIccOfNNRat t ht)) t ^ q) + atTop (nhds 0) := by + simpa only [mul_zero] using + ENNReal.Tendsto.const_mul (a := (M : ℝ≥0∞)) hrpow + (Or.inr ENNReal.coe_ne_top) + have hdenom0 : ε ^ p ≠ 0 := + (ENNReal.rpow_eq_zero_iff_of_pos hX.p_pos).not.mpr hε.ne' + have hscaled := ENNReal.Tendsto.const_mul (a := (ε ^ p)⁻¹) hmul + (Or.inr (ENNReal.inv_ne_top.mpr hdenom0)) + simpa only [mul_zero, div_eq_mul_inv, mul_comm] using hscaled + exact tendsto_of_tendsto_of_tendsto_of_le_of_le tendsto_const_nhds hrhs + (fun _ ↦ zero_le) (fun n ↦ + measure_edist_ge_le_of_isKolmogorovProcess hX _ _ ε hε.ne' hεtop) + +end DyadicFloorConvergenceInMeasure + +section DyadicFloorUnitModification + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + + +noncomputable section + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [MetricSpace E] [CompleteSpace E] + [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] + +/-- At every fixed nonnegative rational time in `[0, 1]`, the canonical floor-sample limit is a +modification of the original process sample. -/ +theorem IsKolmogorovProcess.ae_eq_unitDyadicFloorLimit + {P : Measure Ω} [IsFiniteMeasure P] + {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) (t : NNRat) (ht : t ≤ 1) : + X t =ᵐ[P] fun ω ↦ unitDyadicFloorLimit X ω (unitIccOfNNRat t ht) := by + let samples : ℕ → Ω → E := + fun n ↦ X (unitDyadicFloorValue n (unitIccOfNNRat t ht)) + let limit : Ω → E := fun ω ↦ unitDyadicFloorLimit X ω (unitIccOfNNRat t ht) + have hlim : ∀ᵐ ω ∂P, Tendsto (fun n ↦ samples n ω) atTop (nhds (limit ω)) := by + filter_upwards [IsKolmogorovProcess.ae_tendsto_unitDyadicFloorLimit hX hγ hγq] + with ω hω + exact hω (unitIccOfNNRat t ht) + have hsamples : ∀ n, AEStronglyMeasurable (samples n) P := by + intro n + exact (hX.measurable (unitDyadicFloorValue n (unitIccOfNNRat t ht))).aestronglyMeasurable + have htendsto_limit : TendstoInMeasure P samples atTop limit := + tendstoInMeasure_of_tendsto_ae hsamples hlim + have htendsto_original : TendstoInMeasure P samples atTop (X t) := + IsKolmogorovProcess.tendstoInMeasure_unitDyadicFloorValue hX t ht + exact tendstoInMeasure_ae_unique htendsto_original htendsto_limit + +/-- A total version of the canonical unit-interval path: retain it when it is continuous and use +the constant initial-sample path on the exceptional set. -/ +def continuousUnitDyadicFloorLimit (X : NNRat → Ω → E) (ω : Ω) : + Set.Icc (0 : ℝ) 1 → E := by + classical + exact if Continuous (unitDyadicFloorLimit X ω) then + unitDyadicFloorLimit X ω + else + fun _ ↦ X 0 ω + +omit [CompleteSpace E] [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- The totalized unit-interval path is continuous for every sample. -/ +theorem continuous_continuousUnitDyadicFloorLimit + (X : NNRat → Ω → E) (ω : Ω) : + Continuous (continuousUnitDyadicFloorLimit X ω) := by + by_cases h : Continuous (unitDyadicFloorLimit X ω) + · simpa only [continuousUnitDyadicFloorLimit, if_pos h] using h + · simp only [continuousUnitDyadicFloorLimit, if_neg h] + exact continuous_const + +/-- At each fixed unit-interval rational time, the totalized continuous path remains a +modification of the original process sample. -/ +theorem IsKolmogorovProcess.ae_eq_continuousUnitDyadicFloorLimit + {P : Measure Ω} [IsFiniteMeasure P] + {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) (t : NNRat) (ht : t ≤ 1) : + X t =ᵐ[P] fun ω ↦ continuousUnitDyadicFloorLimit X ω (unitIccOfNNRat t ht) := by + filter_upwards + [IsKolmogorovProcess.ae_eq_unitDyadicFloorLimit hX hγ hγq t ht, + IsKolmogorovProcess.ae_continuous_unitDyadicFloorLimit hX hγ hγq] + with ω hident hcont + simpa only [continuousUnitDyadicFloorLimit, if_pos hcont] using hident + +end + +end DyadicFloorUnitModification + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicIncrements.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicIncrements.lean new file mode 100644 index 0000000000..9c224e99bd --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicIncrements.lean @@ -0,0 +1,246 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement +import Mathlib.Analysis.SpecificLimits.Basic +import Mathlib.MeasureTheory.OuterMeasure.BorelCantelli + +/-! +# Dyadic increment bounds for the Kolmogorov--Chentsov argument + +This file merges the following former modules, one section each: + +* `DyadicIncrementSummability`: Geometric summability for dyadic increment bounds +* `DyadicBorelCantelli`: Borel--Cantelli for dyadic increment events +* `DyadicIncrementControl`: Almost-sure control of adjacent dyadic increments +* `DyadicThresholdTail`: Geometric tails of dyadic increment thresholds +-/ + +namespace MarkovProcess + +section DyadicIncrementSummability + +open scoped ENNReal NNReal + + +/-- The geometric ratio in the dyadic Kolmogorov--Chentsov estimate. -/ +noncomputable def dyadicIncrementDecayRatio (p q γ : ℝ) : ℝ≥0 := + (2 : ℝ≥0) ^ (1 - q + p * γ) + +/-- The admissible Hölder-exponent inequality makes the dyadic ratio strictly less than one. -/ +theorem dyadicIncrementDecayRatio_lt_one {p q γ : ℝ} (hp : 0 < p) + (hγ : γ < (q - 1) / p) : dyadicIncrementDecayRatio p q γ < 1 := by + have hmul : p * γ < q - 1 := by + simpa only [mul_comm] using (lt_div_iff₀ hp).mp hγ + have hexp : 1 - q + p * γ < 0 := by + linarith only [hmul] + exact NNReal.rpow_lt_one_of_one_lt_of_neg (by norm_num) hexp + +/-- The geometric majorant for the dyadic bad-event probabilities is summable. -/ +theorem summable_dyadicIncrementDecayRatio {p q γ : ℝ} (M : ℝ≥0) (hp : 0 < p) + (hγ : γ < (q - 1) / p) : + Summable (fun n : ℕ ↦ M * dyadicIncrementDecayRatio p q γ ^ n) := + (NNReal.summable_geometric (dyadicIncrementDecayRatio_lt_one hp hγ)).mul_left M + +/-- The same geometric majorant has finite `ENNReal` total mass, as needed by the first +Borel--Cantelli lemma. -/ +theorem tsum_coe_dyadicIncrementDecayRatio_ne_top {p q γ : ℝ} (M : ℝ≥0) + (hp : 0 < p) (hγ : γ < (q - 1) / p) : + (∑' n : ℕ, ((M * dyadicIncrementDecayRatio p q γ ^ n : ℝ≥0) : ℝ≥0∞)) ≠ ∞ := by + rw [ENNReal.tsum_coe_ne_top_iff_summable] + exact summable_dyadicIncrementDecayRatio M hp hγ + +end DyadicIncrementSummability + +section DyadicBorelCantelli + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] + +/-- The level-`n` increment threshold used in the dyadic Kolmogorov--Chentsov argument. -/ +noncomputable def dyadicIncrementThreshold (γ : ℝ) (n : ℕ) : ℝ≥0∞ := + (((2 : ℝ≥0∞) ^ n)⁻¹) ^ γ + +theorem dyadicIncrementThreshold_ne_zero {γ : ℝ} (hγ : 0 < γ) (n : ℕ) : + dyadicIncrementThreshold γ n ≠ 0 := by + unfold dyadicIncrementThreshold + exact (ENNReal.rpow_eq_zero_iff_of_pos hγ).not.mpr (by simp) + +theorem dyadicIncrementThreshold_ne_top {γ : ℝ} (hγ : 0 < γ) (n : ℕ) : + dyadicIncrementThreshold γ n ≠ ∞ := by + unfold dyadicIncrementThreshold + exact (ENNReal.rpow_eq_top_iff_of_pos hγ).not.mpr (by simp) + +/-- Normalization of the level-`n` dyadic union bound: the product of the number of cells with +the Kolmogorov quotient at the level's threshold is exactly `M` times the `n`-th power of the +geometric decay ratio. -/ +theorem dyadic_bound_normalization (p q γ : ℝ) (M : ℝ≥0) (n : ℕ) : + (2 : ℝ≥0∞) ^ n * + ((M : ℝ≥0∞) * (((2 : ℝ≥0∞) ^ n)⁻¹) ^ q / + dyadicIncrementThreshold γ n ^ p) = + ((M * dyadicIncrementDecayRatio p q γ ^ n : ℝ≥0) : ℝ≥0∞) := by + have hl : (2 : ℝ≥0∞) ^ n * + ((M : ℝ≥0∞) * (((2 : ℝ≥0∞) ^ n)⁻¹) ^ q / + dyadicIncrementThreshold γ n ^ p) ≠ ∞ := by + apply ENNReal.mul_ne_top + · simp + apply ENNReal.div_ne_top + · apply ENNReal.mul_ne_top + · simp + exact ENNReal.rpow_ne_top_of_ne_zero (by simp) (by simp) + exact ENNReal.rpow_eq_zero_iff.not.mpr (by + unfold dyadicIncrementThreshold + simp) + have hr : ((M * dyadicIncrementDecayRatio p q γ ^ n : ℝ≥0) : ℝ≥0∞) ≠ ∞ := by + finiteness + apply (ENNReal.toReal_eq_toReal_iff' hl hr).mp + simp only [ENNReal.toReal_mul, ENNReal.toReal_pow, ENNReal.toReal_ofNat, + ENNReal.toReal_div, ENNReal.coe_toReal, NNReal.coe_mul, NNReal.coe_pow, NNReal.coe_rpow, + dyadicIncrementThreshold, dyadicIncrementDecayRatio] + rw [← ENNReal.toReal_rpow, ← ENNReal.toReal_rpow, ← ENNReal.toReal_rpow, + ENNReal.toReal_inv, ENNReal.toReal_pow, ENNReal.toReal_ofNat] + simp [← Real.rpow_natCast, ← Real.rpow_mul] + rw [← Real.rpow_neg (by positivity), ← Real.rpow_mul (by positivity), + ← Real.rpow_mul (by positivity), div_eq_mul_inv, + ← Real.rpow_neg (by positivity), ← Real.rpow_mul (by positivity)] + calc + 2 ^ (n : ℝ) * ((M : ℝ) * 2 ^ (-(n : ℝ) * q) * 2 ^ (-(n : ℝ) * -(γ * p))) = + (M : ℝ) * (2 ^ (n : ℝ) * 2 ^ (-(n : ℝ) * q) * + 2 ^ (-(n : ℝ) * -(γ * p))) := by ring_nf + _ = (M : ℝ) * 2 ^ ((n : ℝ) + (-(n : ℝ) * q) + (-(n : ℝ) * -(γ * p))) := by + rw [Real.rpow_add (by positivity), Real.rpow_add (by positivity)] + _ = (M : ℝ) * 2 ^ ((1 - q + p * γ) * (n : ℝ)) := by + congr 1 + ring_nf + +/-- The dyadic bad-increment event has a summable geometric majorant. -/ +theorem IsKolmogorovProcess.measure_unitDyadicGridBadIncrement_threshold_le + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) (n : ℕ) : + P (finiteGridBadIncrement X (unitDyadicGrid n) p (dyadicIncrementThreshold γ n)) ≤ + ((M * dyadicIncrementDecayRatio p q γ ^ n : ℝ≥0) : ℝ≥0∞) := by + rw [← dyadic_bound_normalization] + exact IsKolmogorovProcess.measure_unitDyadicGridBadIncrement_le hX n _ + (dyadicIncrementThreshold_ne_zero hγ n) (dyadicIncrementThreshold_ne_top hγ n) + +/-- The measures of the dyadic bad-increment events have finite total mass. -/ +theorem IsKolmogorovProcess.tsum_measure_unitDyadicGridBadIncrement_threshold_ne_top + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + (∑' n : ℕ, + P (finiteGridBadIncrement X (unitDyadicGrid n) p (dyadicIncrementThreshold γ n))) ≠ ∞ := by + exact ne_top_of_le_ne_top + (tsum_coe_dyadicIncrementDecayRatio_ne_top M hX.p_pos hγq) + (ENNReal.tsum_le_tsum fun n ↦ + IsKolmogorovProcess.measure_unitDyadicGridBadIncrement_threshold_le hX hγ n) + +/-- Almost surely, all sufficiently fine unit dyadic grids avoid the bad-increment event. -/ +theorem IsKolmogorovProcess.ae_eventually_notMem_unitDyadicGridBadIncrement_threshold + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ᶠ n in Filter.atTop, + ω ∉ finiteGridBadIncrement X (unitDyadicGrid n) p (dyadicIncrementThreshold γ n) := + MeasureTheory.ae_eventually_notMem + (IsKolmogorovProcess.tsum_measure_unitDyadicGridBadIncrement_threshold_ne_top + hX hγ hγq) + +end DyadicBorelCantelli + +section DyadicIncrementControl + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] + +/-- Outside the finite-grid bad event, every adjacent increment is strictly below the +specified threshold. -/ +theorem edist_adjacent_lt_of_notMem_finiteGridBadIncrement + {N : ℕ} {T : Type*} {X : T → Ω → E} {grid : Fin (N + 1) → T} + {p : ℝ} (hp : 0 < p) {ε : ℝ≥0∞} {ω : Ω} + (hω : ω ∉ finiteGridBadIncrement X grid p ε) (i : Fin N) : + edist (X (grid i.castSucc) ω) (X (grid i.succ) ω) < ε := by + rw [← ENNReal.rpow_lt_rpow_iff hp] + exact lt_of_not_ge fun hi ↦ hω (Set.mem_iUnion.mpr ⟨i, hi⟩) + +/-- Almost surely, every adjacent increment on every sufficiently fine unit dyadic grid is +strictly below the level's Kolmogorov--Chentsov threshold. -/ +theorem IsKolmogorovProcess.ae_eventually_edist_unitDyadicGrid_adjacent_lt_threshold + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ᶠ n in Filter.atTop, ∀ i : Fin (2 ^ n), + edist (X (unitDyadicGrid n i.castSucc) ω) + (X (unitDyadicGrid n i.succ) ω) < dyadicIncrementThreshold γ n := by + filter_upwards + [IsKolmogorovProcess.ae_eventually_notMem_unitDyadicGridBadIncrement_threshold + hX hγ hγq] with ω hω + filter_upwards [hω] with n hn + intro i + exact edist_adjacent_lt_of_notMem_finiteGridBadIncrement hX.p_pos hn i + +end DyadicIncrementControl + +section DyadicThresholdTail + +open scoped ENNReal NNReal + + +/-- The ratio between consecutive dyadic increment thresholds. -/ +noncomputable def dyadicIncrementThresholdRatio (γ : ℝ) : ℝ≥0∞ := + (2 : ℝ≥0∞) ^ (-γ) + +/-- The level-`n` threshold is the `n`th power of the one-level decay ratio. -/ +theorem dyadicIncrementThreshold_eq_ratio_pow (γ : ℝ) (n : ℕ) : + dyadicIncrementThreshold γ n = dyadicIncrementThresholdRatio γ ^ n := by + unfold dyadicIncrementThreshold dyadicIncrementThresholdRatio + rw [ENNReal.inv_rpow, ← ENNReal.rpow_natCast_mul, ← ENNReal.rpow_neg, + ← ENNReal.rpow_mul_natCast] + congr 2 + ring + +/-- Positive exponents make the one-level threshold ratio strictly smaller than one. -/ +theorem dyadicIncrementThresholdRatio_lt_one {γ : ℝ} (hγ : 0 < γ) : + dyadicIncrementThresholdRatio γ < 1 := by + unfold dyadicIncrementThresholdRatio + exact ENNReal.rpow_lt_one_of_one_lt_of_neg (by norm_num) (neg_neg_of_pos hγ) + +/-- The infinite tail beginning at level `n` has the exact geometric-series value. -/ +theorem tsum_dyadicIncrementThreshold_add (γ : ℝ) (n : ℕ) : + (∑' k : ℕ, dyadicIncrementThreshold γ (n + k)) = + dyadicIncrementThreshold γ n * (1 - dyadicIncrementThresholdRatio γ)⁻¹ := by + simp_rw [dyadicIncrementThreshold_eq_ratio_pow, pow_add] + rw [ENNReal.tsum_mul_left, ENNReal.tsum_geometric] + +/-- For a positive exponent, every infinite threshold tail has finite `ENNReal` mass. -/ +theorem tsum_dyadicIncrementThreshold_add_ne_top {γ : ℝ} (hγ : 0 < γ) (n : ℕ) : + (∑' k : ℕ, dyadicIncrementThreshold γ (n + k)) ≠ ∞ := by + rw [tsum_dyadicIncrementThreshold_add] + apply ENNReal.mul_ne_top + · exact dyadicIncrementThreshold_ne_top hγ n + · exact ENNReal.inv_ne_top.mpr + (tsub_pos_iff_lt.mpr (dyadicIncrementThresholdRatio_lt_one hγ)).ne' + +/-- Every finite tail segment is bounded by the corresponding infinite geometric tail. -/ +theorem sum_dyadicIncrementThreshold_add_le (γ : ℝ) (n N : ℕ) : + ∑ k ∈ Finset.range N, dyadicIncrementThreshold γ (n + k) ≤ + dyadicIncrementThreshold γ n * (1 - dyadicIncrementThresholdRatio γ)⁻¹ := by + calc + ∑ k ∈ Finset.range N, dyadicIncrementThreshold γ (n + k) ≤ + ∑' k : ℕ, dyadicIncrementThreshold γ (n + k) := + ENNReal.sum_le_tsum (Finset.range N) + _ = dyadicIncrementThreshold γ n * + (1 - dyadicIncrementThresholdRatio γ)⁻¹ := + tsum_dyadicIncrementThreshold_add γ n + +end DyadicThresholdTail + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicPathChaining.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicPathChaining.lean new file mode 100644 index 0000000000..7f28b12d2e --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicPathChaining.lean @@ -0,0 +1,314 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Analysis.SpecificLimits.Basic +import Mathlib.Topology.EMetricSpace.Basic + +/-! +# Dyadic chaining on a bounded interval of nonnegative time + +This file is deterministic infrastructure for a quantitative modulus of continuity. It +subdivides the interval `[0, T]` of nonnegative real time into `2 ^ m` equal parts and records +what uniform control of the adjacent increments of a function `f : ℝ≥0 → E` on all subdivisions +from a base level downwards implies for pairs of subdivision points. + +Main results: + +* `MarkovProcess.dyadicTime`, the `i`-th point of the level-`m` subdivision of `[0, T]`, with its + monotonicity, refinement and increment estimates; +* `MarkovProcess.HasDyadicAdjacentBound`, the hypothesis that all adjacent increments of `f` on + the level-`m` subdivision are at most `e`; +* `MarkovProcess.edist_dyadicTime_le_of_hasDyadicAdjacentBound`, the same-level chaining bound; +* `MarkovProcess.edist_dyadicTime_ancestor_le`, the bound from a fine subdivision point to its + canonical coarse ancestor by the sum of the intervening bounds; +* `MarkovProcess.edist_dyadicTime_le_of_sub_le`, the two-point chaining bound: subdivision points + of level `n + r` whose indices differ by at most `2 ^ r` are within `2 * (chain sum) + e n`; +* `MarkovProcess.dyadicIndex` and its approximation lemmas, which locate an arbitrary time of + `[0, T]` between consecutive subdivision points and compare the indices of two nearby times. + +Everything here is a statement about a fixed function of time. No measure, no probability law, +and no continuity of `f` is used or asserted. +-/ + +open Filter Topology +open scoped ENNReal NNReal + +namespace MarkovProcess + +section Subdivision + +/-- The `i`-th point of the subdivision of `[0, T]` into `2 ^ m` equal parts. -/ +noncomputable def dyadicTime (T : ℝ≥0) (m i : ℕ) : ℝ≥0 := T * i / 2 ^ m + +theorem dyadicTime_coe (T : ℝ≥0) (m i : ℕ) : + ((dyadicTime T m i : ℝ≥0) : ℝ) = (T : ℝ) * i / 2 ^ m := by + simp [dyadicTime] + +@[simp] +theorem dyadicTime_zero (T : ℝ≥0) (m : ℕ) : dyadicTime T m 0 = 0 := by + simp [dyadicTime] + +theorem dyadicTime_mono (T : ℝ≥0) (m : ℕ) {i j : ℕ} (hij : i ≤ j) : + dyadicTime T m i ≤ dyadicTime T m j := by + have hij' : (i : ℝ≥0) ≤ (j : ℝ≥0) := Nat.cast_le.mpr hij + unfold dyadicTime + gcongr + +theorem dyadicTime_le (T : ℝ≥0) {m i : ℕ} (hi : i ≤ 2 ^ m) : dyadicTime T m i ≤ T := by + rw [← NNReal.coe_le_coe, dyadicTime_coe, div_le_iff₀ (by positivity)] + have hle : ((i : ℝ)) ≤ (2 : ℝ) ^ m := by exact_mod_cast hi + exact mul_le_mul_of_nonneg_left hle T.coe_nonneg + +/-- A subdivision point of level `m` is a subdivision point of level `m + 1`. -/ +theorem dyadicTime_succ_level (T : ℝ≥0) (m i : ℕ) : + dyadicTime T (m + 1) (2 * i) = dyadicTime T m i := by + rw [← NNReal.coe_inj, dyadicTime_coe, dyadicTime_coe] + push_cast + rw [pow_succ] + field_simp + +theorem dist_dyadicTime (T : ℝ≥0) (m i j : ℕ) : + dist (dyadicTime T m i) (dyadicTime T m j) = (T : ℝ) * |(i : ℝ) - j| / 2 ^ m := by + rw [NNReal.dist_eq, dyadicTime_coe, dyadicTime_coe, div_sub_div_same, ← mul_sub, abs_div, + abs_mul, abs_of_nonneg T.coe_nonneg, abs_of_pos (by positivity : (0 : ℝ) < 2 ^ m)] + +theorem edist_dyadicTime_succ_le (T : ℝ≥0) (m i : ℕ) : + edist (dyadicTime T m i) (dyadicTime T m (i + 1)) ≤ ((T / 2 ^ m : ℝ≥0) : ℝ≥0∞) := by + rw [edist_dist] + refine ENNReal.ofReal_le_of_le_toReal ?_ + rw [ENNReal.coe_toReal, dist_dyadicTime] + push_cast + rw [show (i : ℝ) - ((i : ℝ) + 1) = -1 by ring, abs_neg, abs_one, mul_one] + +end Subdivision + +section Chaining + +variable {E : Type*} [PseudoEMetricSpace E] + +/-- Every adjacent increment of `f` on the level-`m` subdivision of `[0, T]` is at most `e`. -/ +def HasDyadicAdjacentBound (f : ℝ≥0 → E) (T : ℝ≥0) (m : ℕ) (e : ℝ≥0∞) : Prop := + ∀ i < 2 ^ m, edist (f (dyadicTime T m i)) (f (dyadicTime T m (i + 1))) ≤ e + +/-- Same-level chaining: the increment between two subdivision points of the same level is at +most the number of intervening cells times the adjacent bound. -/ +theorem edist_dyadicTime_le_of_hasDyadicAdjacentBound {f : ℝ≥0 → E} {T : ℝ≥0} {m : ℕ} + {e : ℝ≥0∞} (hf : HasDyadicAdjacentBound f T m e) {i j : ℕ} (hij : i ≤ j) (hj : j ≤ 2 ^ m) : + edist (f (dyadicTime T m i)) (f (dyadicTime T m j)) ≤ (j - i : ℕ) * e := by + have hchain := edist_le_Ico_sum_of_edist_le (f := fun k ↦ f (dyadicTime T m k)) hij + (d := fun _ ↦ e) (fun {k} _ hkj ↦ hf k (lt_of_lt_of_le hkj hj)) + simpa only [Finset.sum_const, Nat.card_Ico, nsmul_eq_mul] using hchain + +/-- Child-to-parent chaining: a level-`m + 1` subdivision point is within one adjacent bound of +the level-`m` point obtained by halving its index. -/ +theorem edist_dyadicTime_parent_le {f : ℝ≥0 → E} {T : ℝ≥0} {m : ℕ} {e : ℝ≥0∞} + (hf : HasDyadicAdjacentBound f T (m + 1) e) {i : ℕ} (hi : i ≤ 2 ^ (m + 1)) : + edist (f (dyadicTime T (m + 1) i)) (f (dyadicTime T m (i / 2))) ≤ e := by + rcases Nat.mod_two_eq_zero_or_one i with hmod | hmod + · have hval : 2 * (i / 2) = i := by omega + rw [← dyadicTime_succ_level T m (i / 2), hval, edist_self] + exact zero_le + · have hval : 2 * (i / 2) + 1 = i := by omega + have hlt : 2 * (i / 2) < 2 ^ (m + 1) := by omega + have hbound := hf (2 * (i / 2)) hlt + rw [hval] at hbound + rw [← dyadicTime_succ_level T m (i / 2), edist_comm] + exact hbound + +/-- Ancestor chaining: from a level-`n + r` subdivision point to the level-`n` point obtained by +dividing its index by `2 ^ r`, the increment is at most the sum of the intervening bounds. -/ +theorem edist_dyadicTime_ancestor_le {f : ℝ≥0 → E} {T : ℝ≥0} {e : ℕ → ℝ≥0∞} {n : ℕ} : + ∀ r : ℕ, (∀ k, n < k → k ≤ n + r → HasDyadicAdjacentBound f T k (e k)) → + ∀ i ≤ 2 ^ (n + r), + edist (f (dyadicTime T (n + r) i)) (f (dyadicTime T n (i / 2 ^ r))) ≤ + ∑ s ∈ Finset.range r, e (n + s + 1) := by + intro r + induction r with + | zero => intro _ i _; simp + | succ r ihr => + intro hadj i hi + have hlevel : n + (r + 1) = n + r + 1 := by omega + have hi' : i ≤ 2 ^ (n + r + 1) := by rwa [← hlevel] + have hparent : edist (f (dyadicTime T (n + r + 1) i)) + (f (dyadicTime T (n + r) (i / 2))) ≤ e (n + r + 1) := + edist_dyadicTime_parent_le (hadj (n + r + 1) (by omega) (by omega)) hi' + have hpow : 2 ^ (n + r + 1) = 2 ^ (n + r) * 2 := by ring + have hhalf : i / 2 ≤ 2 ^ (n + r) := by omega + have hrest := ihr (fun k hk hk' ↦ hadj k hk (by omega)) (i / 2) hhalf + have hdiv : i / 2 / 2 ^ r = i / 2 ^ (r + 1) := by + rw [Nat.div_div_eq_div_mul] + congr 1 + ring + rw [hdiv] at hrest + have htri : edist (f (dyadicTime T (n + (r + 1)) i)) + (f (dyadicTime T n (i / 2 ^ (r + 1)))) ≤ + edist (f (dyadicTime T (n + r + 1) i)) (f (dyadicTime T (n + r) (i / 2))) + + edist (f (dyadicTime T (n + r) (i / 2))) (f (dyadicTime T n (i / 2 ^ (r + 1)))) := by + rw [hlevel] + exact edist_triangle _ _ _ + refine htri.trans ((add_le_add hparent hrest).trans_eq ?_) + rw [Finset.sum_range_succ] + exact add_comm _ _ + +/-- Two-point chaining: subdivision points of level `n + r` whose indices differ by at most +`2 ^ r` have a common level-`n` ancestor cell, so their increment is bounded by twice the chain +sum plus one coarse adjacent bound. -/ +theorem edist_dyadicTime_le_of_sub_le {f : ℝ≥0 → E} {T : ℝ≥0} {e : ℕ → ℝ≥0∞} {n r : ℕ} + (hadj : ∀ k, n ≤ k → k ≤ n + r → HasDyadicAdjacentBound f T k (e k)) + {i j : ℕ} (hij : i ≤ j) (hj : j ≤ 2 ^ (n + r)) (hsub : j - i ≤ 2 ^ r) : + edist (f (dyadicTime T (n + r) i)) (f (dyadicTime T (n + r) j)) ≤ + 2 * (∑ s ∈ Finset.range r, e (n + s + 1)) + e n := by + have hi : i ≤ 2 ^ (n + r) := hij.trans hj + have hanc := fun (k : ℕ) (hk : n < k) (hk' : k ≤ n + r) ↦ hadj k hk.le hk' + have hleft := edist_dyadicTime_ancestor_le (f := f) (T := T) (e := e) (n := n) r hanc i hi + have hright := edist_dyadicTime_ancestor_le (f := f) (T := T) (e := e) (n := n) r hanc j hj + have hdivmono : i / 2 ^ r ≤ j / 2 ^ r := Nat.div_le_div_right hij + have hdivclose : j / 2 ^ r ≤ i / 2 ^ r + 1 := by + have hpos : 0 < 2 ^ r := pow_pos (by norm_num) r + have hle : j ≤ i + 2 ^ r := by omega + calc j / 2 ^ r ≤ (i + 2 ^ r) / 2 ^ r := Nat.div_le_div_right hle + _ = i / 2 ^ r + 1 := by rw [Nat.add_div_right _ hpos] + have hdivtop : j / 2 ^ r ≤ 2 ^ n := by + calc j / 2 ^ r ≤ 2 ^ (n + r) / 2 ^ r := Nat.div_le_div_right hj + _ = 2 ^ n := by rw [Nat.pow_div (by omega) (by norm_num), Nat.add_sub_cancel] + have hmid : edist (f (dyadicTime T n (i / 2 ^ r))) (f (dyadicTime T n (j / 2 ^ r))) ≤ e n := by + have hbase := edist_dyadicTime_le_of_hasDyadicAdjacentBound + (hadj n le_rfl (Nat.le_add_right n r)) hdivmono hdivtop + refine hbase.trans ?_ + have hcount : (j / 2 ^ r - i / 2 ^ r : ℕ) ≤ 1 := by omega + calc ((j / 2 ^ r - i / 2 ^ r : ℕ) : ℝ≥0∞) * e n ≤ (1 : ℝ≥0∞) * e n := by + gcongr + exact_mod_cast hcount + _ = e n := one_mul _ + have htri : edist (f (dyadicTime T (n + r) i)) (f (dyadicTime T (n + r) j)) ≤ + edist (f (dyadicTime T (n + r) i)) (f (dyadicTime T n (i / 2 ^ r))) + + (edist (f (dyadicTime T n (i / 2 ^ r))) (f (dyadicTime T n (j / 2 ^ r))) + + edist (f (dyadicTime T n (j / 2 ^ r))) (f (dyadicTime T (n + r) j))) := + (edist_triangle (f (dyadicTime T (n + r) i)) (f (dyadicTime T n (i / 2 ^ r))) + (f (dyadicTime T (n + r) j))).trans + (add_le_add le_rfl (edist_triangle (f (dyadicTime T n (i / 2 ^ r))) + (f (dyadicTime T n (j / 2 ^ r))) (f (dyadicTime T (n + r) j)))) + refine htri.trans ?_ + rw [edist_comm (f (dyadicTime T n (j / 2 ^ r)))] + have hsum := add_le_add hleft (add_le_add hmid hright) + refine hsum.trans_eq ?_ + ring + +end Chaining + +section Approximation + +/-- The index of the last level-`m` subdivision point of `[0, T]` at or below `s`. -/ +noncomputable def dyadicIndex (T : ℝ≥0) (m : ℕ) (s : ℝ≥0) : ℕ := ⌊(s : ℝ) * 2 ^ m / T⌋₊ + +theorem dyadicIndex_le {T : ℝ≥0} (hT : 0 < T) {s : ℝ≥0} (hs : s ≤ T) (m : ℕ) : + dyadicIndex T m s ≤ 2 ^ m := by + have hT' : (0 : ℝ) < (T : ℝ) := hT + have hs' : (s : ℝ) ≤ (T : ℝ) := hs + have hbound : (s : ℝ) * 2 ^ m / T ≤ ((2 ^ m : ℕ) : ℝ) := by + rw [div_le_iff₀ hT'] + push_cast + nlinarith [pow_pos (by norm_num : (0 : ℝ) < 2) m] + calc dyadicIndex T m s ≤ ⌊((2 ^ m : ℕ) : ℝ)⌋₊ := Nat.floor_mono hbound + _ = 2 ^ m := Nat.floor_natCast _ + +theorem dyadicIndex_mono {T : ℝ≥0} (hT : 0 < T) (m : ℕ) {s t : ℝ≥0} (hst : s ≤ t) : + dyadicIndex T m s ≤ dyadicIndex T m t := by + have hT' : (0 : ℝ) < (T : ℝ) := hT + have hst' : (s : ℝ) ≤ (t : ℝ) := hst + exact Nat.floor_mono (by gcongr) + +theorem dyadicTime_dyadicIndex_le {T : ℝ≥0} (hT : 0 < T) (m : ℕ) (s : ℝ≥0) : + dyadicTime T m (dyadicIndex T m s) ≤ s := by + have hT' : (0 : ℝ) < (T : ℝ) := hT + have hpow : (0 : ℝ) < 2 ^ m := by positivity + have hx0 : (0 : ℝ) ≤ (s : ℝ) * 2 ^ m / T := by positivity + have hfloor : ((dyadicIndex T m s : ℕ) : ℝ) ≤ (s : ℝ) * 2 ^ m / T := Nat.floor_le hx0 + rw [← NNReal.coe_le_coe, dyadicTime_coe, div_le_iff₀ hpow] + calc (T : ℝ) * ((dyadicIndex T m s : ℕ) : ℝ) ≤ (T : ℝ) * ((s : ℝ) * 2 ^ m / T) := + mul_le_mul_of_nonneg_left hfloor T.coe_nonneg + _ = (s : ℝ) * 2 ^ m := by field_simp + +theorem le_dyadicTime_dyadicIndex_add {T : ℝ≥0} (hT : 0 < T) (m : ℕ) (s : ℝ≥0) : + s ≤ dyadicTime T m (dyadicIndex T m s) + T / 2 ^ m := by + have hT' : (0 : ℝ) < (T : ℝ) := hT + have hpow : (0 : ℝ) < 2 ^ m := by positivity + have hfloor : (s : ℝ) * 2 ^ m / T < ((dyadicIndex T m s : ℕ) : ℝ) + 1 := + Nat.lt_floor_add_one _ + have hlt : (s : ℝ) * 2 ^ m < (((dyadicIndex T m s : ℕ) : ℝ) + 1) * T := + (div_lt_iff₀ hT').mp hfloor + rw [← NNReal.coe_le_coe] + push_cast [dyadicTime_coe] + rw [← add_div, le_div_iff₀ hpow] + nlinarith [hlt] + +theorem tendsto_dyadicTime_dyadicIndex {T : ℝ≥0} (hT : 0 < T) (s : ℝ≥0) : + Tendsto (fun m ↦ dyadicTime T m (dyadicIndex T m s)) atTop (𝓝 s) := by + rw [tendsto_iff_dist_tendsto_zero] + have hzero : Tendsto (fun m : ℕ ↦ (T : ℝ) / 2 ^ m) atTop (𝓝 0) := by + have hhalf : Tendsto (fun m : ℕ ↦ ((1 : ℝ) / 2) ^ m) atTop (𝓝 0) := + tendsto_pow_atTop_nhds_zero_of_lt_one (by norm_num) (by norm_num) + have hmul := hhalf.const_mul (T : ℝ) + rw [mul_zero] at hmul + refine hmul.congr fun m ↦ ?_ + rw [div_pow, one_pow] + ring + refine squeeze_zero (fun _ ↦ dist_nonneg) (fun m ↦ ?_) hzero + have h1 : ((dyadicTime T m (dyadicIndex T m s) : ℝ≥0) : ℝ) ≤ (s : ℝ) := + dyadicTime_dyadicIndex_le hT m s + have h2 : (s : ℝ) ≤ ((dyadicTime T m (dyadicIndex T m s) : ℝ≥0) : ℝ) + (T : ℝ) / 2 ^ m := by + have h := NNReal.coe_le_coe.mpr (le_dyadicTime_dyadicIndex_add hT m s) + push_cast at h + exact h + rw [NNReal.dist_eq, abs_sub_comm, abs_of_nonneg (by linarith)] + linarith + +/-- Two nearby times of `[0, T]` have level-`n + r` subdivision indices that differ by at most +`2 ^ r`, once their separation is at most `T / 2 ^ (n + 1)` and `r` is at least one. -/ +theorem dyadicIndex_sub_le {T : ℝ≥0} (hT : 0 < T) {s t : ℝ≥0} {n r : ℕ} + (hr : 1 ≤ r) (hd : t ≤ s + T / 2 ^ (n + 1)) : + dyadicIndex T (n + r) t - dyadicIndex T (n + r) s ≤ 2 ^ r := by + have hT' : (0 : ℝ) < (T : ℝ) := hT + have hpow : (0 : ℝ) < 2 ^ (n + r) := by positivity + set i : ℕ := dyadicIndex T (n + r) s with hi + set j : ℕ := dyadicIndex T (n + r) t with hj + have hjle : (j : ℝ) ≤ (t : ℝ) * 2 ^ (n + r) / T := Nat.floor_le (by positivity) + have hilt : (s : ℝ) * 2 ^ (n + r) / T < (i : ℝ) + 1 := Nat.lt_floor_add_one _ + have hdreal : (t : ℝ) ≤ (s : ℝ) + (T : ℝ) / 2 ^ (n + 1) := by + have := NNReal.coe_le_coe.mpr hd + push_cast at this + exact this + have hsplit : (2 : ℝ) ^ (n + r) = 2 ^ (n + 1) * 2 ^ (r - 1) := by + rw [← pow_add] + congr 1 + omega + have hstep : (t : ℝ) * 2 ^ (n + r) ≤ + (s : ℝ) * 2 ^ (n + r) + (2 : ℝ) ^ (r - 1) * T := by + have hmul : (t : ℝ) * 2 ^ (n + r) ≤ + ((s : ℝ) + (T : ℝ) / 2 ^ (n + 1)) * 2 ^ (n + r) := by + gcongr + refine hmul.trans (le_of_eq ?_) + rw [hsplit] + field_simp + have h1 : (j : ℝ) * T ≤ (t : ℝ) * 2 ^ (n + r) := by + rwa [le_div_iff₀ hT'] at hjle + have h2 : (s : ℝ) * 2 ^ (n + r) < ((i : ℝ) + 1) * T := (div_lt_iff₀ hT').mp hilt + have h3 : (j : ℝ) * T < ((i : ℝ) + 1 + (2 : ℝ) ^ (r - 1)) * T := by + have hexpand : ((i : ℝ) + 1 + (2 : ℝ) ^ (r - 1)) * T + = ((i : ℝ) + 1) * T + (2 : ℝ) ^ (r - 1) * T := by ring + rw [hexpand] + linarith + have hkey : (j : ℝ) < (i : ℝ) + 1 + (2 : ℝ) ^ (r - 1) := + lt_of_mul_lt_mul_right h3 hT'.le + have hnat : j ≤ i + 2 ^ (r - 1) := by + have hcast : (j : ℝ) < ((i + 2 ^ (r - 1) + 1 : ℕ) : ℝ) := by push_cast; linarith + exact Nat.lt_succ_iff.mp (by exact_mod_cast hcast) + have hmono : 2 ^ (r - 1) ≤ 2 ^ r := Nat.pow_le_pow_right (by norm_num) (by omega) + have hfinal : j - i ≤ 2 ^ (r - 1) := tsub_le_iff_right.mpr (by rw [add_comm]; exact hnat) + exact hfinal.trans hmono + +end Approximation + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/GlobalDyadicFloorModification.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/GlobalDyadicFloorModification.lean new file mode 100644 index 0000000000..7fd540dad0 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/GlobalDyadicFloorModification.lean @@ -0,0 +1,259 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification +import Mathlib.Topology.LocallyFinite + +/-! +# A global continuous modification assembled from canonical unit paths + +The nonnegative real half-line is covered by the closed unit intervals `[n, n + 1]`. On each +piece we use the canonical dyadic-floor limit of the process shifted by `n`. Exact endpoint +identities make these pieces compatible, so `Set.liftCover` gives an honest raw global path. +On the simultaneous probability-one event where every canonical unit piece is continuous, local +finiteness of the closed cover makes the raw path continuous. A single constant global fallback +then gives a total path which is continuous for every sample. + +No measurability of the path-valued map, path-space law, Markov property, or Hunt-process claim is +asserted here. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + +namespace MarkovProcess + +noncomputable section + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [MetricSpace E] [CompleteSpace E] + [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] + +/-- The `n`th closed unit interval in `ℝ≥0`. -/ +def nnrealUnitInterval (n : ℕ) : Set ℝ≥0 := Set.Icc n (n + 1) + +/-- Local coordinate in `[0,1]` on the `n`th closed unit interval. -/ +def nnrealUnitCoordinate (n : ℕ) (x : nnrealUnitInterval n) : Set.Icc (0 : ℝ) 1 := + ⟨(x.1 : ℝ) - n, by + constructor + · exact sub_nonneg.mpr (by exact_mod_cast x.2.1) + · rw [sub_le_iff_le_add] + simpa only [Nat.cast_add, Nat.cast_one, add_comm] using! x.2.2⟩ + +/-- The canonical shifted unit path, expressed on the corresponding closed interval of `ℝ≥0`. -/ +def globalDyadicFloorPiece (X : NNRat → Ω → E) (ω : Ω) (n : ℕ) : + nnrealUnitInterval n → E := + fun x ↦ shiftedUnitDyadicFloorLimit n X ω (nnrealUnitCoordinate n x) + +omit [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +theorem continuous_nnrealUnitCoordinate (n : ℕ) : Continuous (nnrealUnitCoordinate n) := by + apply continuous_induced_rng.2 + exact (NNReal.continuous_coe.comp continuous_subtype_val).sub continuous_const + +omit [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- Canonical pieces agree wherever two closed unit intervals overlap. -/ +theorem globalDyadicFloorPiece_eq_of_mem + (X : NNRat → Ω → E) (ω : Ω) (n m : ℕ) (x : ℝ≥0) + (hn : x ∈ nnrealUnitInterval n) (hm : x ∈ nnrealUnitInterval m) : + globalDyadicFloorPiece X ω n ⟨x, hn⟩ = globalDyadicFloorPiece X ω m ⟨x, hm⟩ := by + have hnm : n ≤ m + 1 := by exact_mod_cast hn.1.trans hm.2 + have hmn : m ≤ n + 1 := by exact_mod_cast hm.1.trans hn.2 + by_cases heq : n = m + · subst m + rfl + by_cases hlt : n < m + · have hmn' : m = n + 1 := by omega + subst m + have hmleft : (n : ℝ≥0) + 1 ≤ x := by + simpa only [Nat.cast_add, Nat.cast_one] using hm.1 + have hx : x = (n : ℝ≥0) + 1 := le_antisymm hn.2 hmleft + subst x + have hleft : nnrealUnitCoordinate n ⟨(n + 1 : ℝ≥0), hn⟩ = + (1 : Set.Icc (0 : ℝ) 1) := by + apply Subtype.ext + norm_num [nnrealUnitCoordinate] + have hright : nnrealUnitCoordinate (n + 1) ⟨(n + 1 : ℝ≥0), hm⟩ = + (0 : Set.Icc (0 : ℝ) 1) := by + apply Subtype.ext + norm_num [nnrealUnitCoordinate] + rw [globalDyadicFloorPiece, globalDyadicFloorPiece, hleft, hright, + shiftedUnitDyadicFloorLimit_one, shiftedUnitDyadicFloorLimit_zero] + simp only [Nat.cast_add, Nat.cast_one] + · have hnm' : n = m + 1 := by omega + subst n + exact (globalDyadicFloorPiece_eq_of_mem X ω m (m + 1) x hm hn).symm + +omit [CompleteSpace E] [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- The closed unit intervals cover `ℝ≥0`. -/ +theorem iUnion_nnrealUnitInterval : ⋃ n : ℕ, nnrealUnitInterval n = Set.univ := by + apply Set.iUnion_eq_univ_iff.2 + intro x + let n := ⌊(x : ℝ)⌋₊ + refine ⟨n, ?_⟩ + constructor + · exact_mod_cast Nat.floor_le x.2 + · exact_mod_cast (Nat.lt_floor_add_one (x : ℝ)).le + +omit [CompleteSpace E] [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- The cover of `ℝ≥0` by closed unit intervals is locally finite. -/ +theorem locallyFinite_nnrealUnitInterval : LocallyFinite nnrealUnitInterval := by + intro x + let N := ⌊(x : ℝ)⌋₊ + 2 + refine ⟨Set.Iio (N : ℝ≥0), ?_, ?_⟩ + · apply Iio_mem_nhds + have hxlt : (x : ℝ) < (N : ℕ) := by + calc + (x : ℝ) < ⌊(x : ℝ)⌋₊ + 1 := Nat.lt_floor_add_one (x : ℝ) + _ < (N : ℕ) := by simp only [N]; norm_num + exact_mod_cast hxlt + · apply Set.Finite.subset (Set.finite_Iio N) + intro n hn + obtain ⟨y, hy, hyN⟩ := hn + have hny : (n : ℝ≥0) ≤ y := hy.1 + have hnN : n < N := by exact_mod_cast hny.trans_lt hyN + exact hnN + +omit [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- The raw global path obtained by gluing the compatible canonical unit pieces. -/ +def globalDyadicFloorLimit (X : NNRat → Ω → E) (ω : Ω) : ℝ≥0 → E := + Set.liftCover nnrealUnitInterval (globalDyadicFloorPiece X ω) + (globalDyadicFloorPiece_eq_of_mem X ω) iUnion_nnrealUnitInterval + +omit [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +@[simp] +theorem globalDyadicFloorLimit_coe + (X : NNRat → Ω → E) (ω : Ω) (n : ℕ) (x : nnrealUnitInterval n) : + globalDyadicFloorLimit X ω x = globalDyadicFloorPiece X ω n x := + Set.liftCover_coe x + +omit [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- If every canonical unit piece is continuous, then the raw global path is continuous. -/ +theorem continuous_globalDyadicFloorLimit_of_forall + {X : NNRat → Ω → E} {ω : Ω} + (h : ∀ n : ℕ, Continuous (shiftedUnitDyadicFloorLimit n X ω)) : + Continuous (globalDyadicFloorLimit X ω) := by + apply locallyFinite_nnrealUnitInterval.continuous iUnion_nnrealUnitInterval + · exact fun n ↦ isClosed_Icc + · intro n + rw [continuousOn_iff_continuous_domRestrict] + have hpiece : Continuous (globalDyadicFloorPiece X ω n) := + (h n).comp (continuous_nnrealUnitCoordinate n) + apply hpiece.congr + intro x + simpa only [Set.domRestrict_apply] using (globalDyadicFloorLimit_coe X ω n x).symm + +omit [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- Almost surely, all natural-shift canonical pieces are simultaneously continuous. -/ +theorem IsKolmogorovProcess.ae_forall_continuous_shiftedUnitDyadicFloorLimit + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, ∀ n : ℕ, Continuous (shiftedUnitDyadicFloorLimit n X ω) := by + rw [ae_all_iff] + intro n + simpa only [shiftedUnitDyadicFloorLimit] using + IsKolmogorovProcess.ae_continuous_unitDyadicFloorLimit + (IsKolmogorovProcess.timeShift hX n) hγ hγq + +omit [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- Almost surely, the raw global dyadic-floor path is continuous. -/ +theorem IsKolmogorovProcess.ae_continuous_globalDyadicFloorLimit + {P : Measure Ω} {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) : + ∀ᵐ ω ∂P, Continuous (globalDyadicFloorLimit X ω) := by + filter_upwards + [IsKolmogorovProcess.ae_forall_continuous_shiftedUnitDyadicFloorLimit hX hγ hγq] + with ω hω + exact continuous_globalDyadicFloorLimit_of_forall hω + +/-- A single global totalization: keep the raw path when it is continuous and otherwise use the +constant initial sample on the whole half-line. -/ +def continuousGlobalDyadicFloorLimit (X : NNRat → Ω → E) (ω : Ω) : ℝ≥0 → E := by + classical + exact if Continuous (globalDyadicFloorLimit X ω) then globalDyadicFloorLimit X ω + else fun _ ↦ X 0 ω + +omit [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- The globally totalized path is continuous for every sample. -/ +theorem continuous_continuousGlobalDyadicFloorLimit + (X : NNRat → Ω → E) (ω : Ω) : + Continuous (continuousGlobalDyadicFloorLimit X ω) := by + by_cases h : Continuous (globalDyadicFloorLimit X ω) + · simpa only [continuousGlobalDyadicFloorLimit, if_pos h] using h + · simp only [continuousGlobalDyadicFloorLimit, if_neg h] + exact continuous_const + +/-- At a fixed rational time written as a natural shift plus a local time in `[0,1]`, the +globally totalized continuous path is a modification of the original process. -/ +theorem IsKolmogorovProcess.ae_eq_continuousGlobalDyadicFloorLimit_nat_add + {P : Measure Ω} [IsFiniteMeasure P] + {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) (n : ℕ) (t : NNRat) (ht : t ≤ 1) : + X (n + t) =ᵐ[P] fun ω ↦ + continuousGlobalDyadicFloorLimit X ω (↑((n : NNRat) + t) : ℝ≥0) := by + let x : ℝ≥0 := ↑((n : NNRat) + t) + have hx : x ∈ nnrealUnitInterval n := by + have hl : (n : NNRat) ≤ (n : NNRat) + t := le_add_of_nonneg_right t.2 + have hu : (n : NNRat) + t ≤ (n : NNRat) + 1 := by + simpa only [add_comm] using add_le_add_left ht (n : NNRat) + constructor + · dsimp only [x] + exact_mod_cast hl + · dsimp only [x] + exact_mod_cast hu + have hcoord : nnrealUnitCoordinate n ⟨x, hx⟩ = unitIccOfNNRat t ht := by + apply Subtype.ext + simp only [nnrealUnitCoordinate, unitIccOfNNRat_val, x] + push_cast + ring_nf + change (((t : NNRat) : ℝ≥0) : ℝ) = (t : ℝ) + exact_mod_cast rfl + filter_upwards + [IsKolmogorovProcess.ae_eq_unitDyadicFloorLimit + (IsKolmogorovProcess.timeShift hX n) hγ hγq t ht, + IsKolmogorovProcess.ae_continuous_globalDyadicFloorLimit hX hγ hγq] + with ω hident hcont + rw [continuousGlobalDyadicFloorLimit, if_pos hcont] + rw [show (↑((n : NNRat) + t) : ℝ≥0) = x by rfl, + globalDyadicFloorLimit_coe X ω n ⟨x, hx⟩, globalDyadicFloorPiece, hcoord] + simpa only [timeShift_apply] using! hident + +/-- The natural part of a nonnegative rational time. -/ +def nnratNatFloor (t : NNRat) : ℕ := ⌊(t : ℝ)⌋₊ + +/-- The unit-interval remainder of a nonnegative rational time. -/ +def nnratUnitRemainder (t : NNRat) : NNRat := t - nnratNatFloor t + +theorem nnratNatFloor_le (t : NNRat) : (nnratNatFloor t : NNRat) ≤ t := by + unfold nnratNatFloor + exact_mod_cast Nat.floor_le (show 0 ≤ (t : ℝ) by positivity) + +theorem nnratNatFloor_add_unitRemainder (t : NNRat) : + (nnratNatFloor t : NNRat) + nnratUnitRemainder t = t := by + exact add_tsub_cancel_of_le (nnratNatFloor_le t) + +theorem nnratUnitRemainder_le_one (t : NNRat) : nnratUnitRemainder t ≤ 1 := by + apply le_of_lt + rw [nnratUnitRemainder, tsub_lt_iff_left (nnratNatFloor_le t)] + unfold nnratNatFloor + exact_mod_cast Nat.lt_floor_add_one (t : ℝ) + +/-- At every fixed nonnegative rational time, the globally totalized continuous path is a +modification of the original process. -/ +theorem IsKolmogorovProcess.ae_eq_continuousGlobalDyadicFloorLimit + {P : Measure Ω} [IsFiniteMeasure P] + {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) (t : NNRat) : + X t =ᵐ[P] fun ω ↦ continuousGlobalDyadicFloorLimit X ω (t : ℝ≥0) := by + have hdecomp := nnratNatFloor_add_unitRemainder t + simpa only [hdecomp] using + IsKolmogorovProcess.ae_eq_continuousGlobalDyadicFloorLimit_nat_add + hX hγ hγq (nnratNatFloor t) (nnratUnitRemainder t) (nnratUnitRemainder_le_one t) + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovDenseTimeContinuousSupport.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovDenseTimeContinuousSupport.lean new file mode 100644 index 0000000000..8bd22b931e --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovDenseTimeContinuousSupport.lean @@ -0,0 +1,74 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.Polish +import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport + +/-! +# Kolmogorov support for dense-time trajectory kernels + +This file applies the global dyadic-floor modification to the coordinate process of a +dense-time trajectory kernel. A parameterwise Kolmogorov moment condition implies that the +dense-time law is supported on restrictions of continuous paths. + +No measurability of the totalized modification as a path-valued map, PDE increment estimate, +Markov property of the resulting paths, or Hunt-process assertion is made here. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess + +noncomputable section + +namespace Kernel + +variable {beta alpha : Type*} [MeasurableSpace beta] [MetricSpace alpha] + [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] + +/-- A parameterwise Kolmogorov moment estimate for the canonical coordinate process implies +almost-sure support of every dense-time trajectory law on restrictions of continuous paths. +The constants and exponents may depend on the kernel parameter. -/ +theorem IsSupportedOnContinuousPaths.of_isKolmogorovCoordinate + (kappa : Kernel beta (DenseTime → alpha)) [IsMarkovKernel kappa] + (hK : ∀ b, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) (kappa b) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) : + IsSupportedOnContinuousPaths kappa := by + apply IsSupportedOnContinuousPaths.of_continuousModification kappa + intro b + obtain ⟨p, q, gamma, M, hcoord, hgamma, hgammaq⟩ := hK b + let X : DenseTime → (DenseTime → alpha) → alpha := fun r omega ↦ omega r + refine ⟨fun t omega ↦ continuousGlobalDyadicFloorLimit X omega t, ?_, ?_⟩ + · intro omega + exact continuous_continuousGlobalDyadicFloorLimit X omega + · intro r + simpa only [X, DenseTime.castOrderEmbedding, NNRat.castOrderEmbedding_apply] using + IsKolmogorovProcess.ae_eq_continuousGlobalDyadicFloorLimit + hcoord hgamma hgammaq r + +section ContinuousPathKernel + +/-- Under the coordinate Kolmogorov estimate, transporting to continuous paths and restricting +back to dense time recovers the original trajectory kernel. The path-space transport uses only +the already established measurable extension map. -/ +theorem map_denseRestriction_toContinuousPathKernel_of_isKolmogorovCoordinate + (kappa : Kernel beta (DenseTime → alpha)) [IsMarkovKernel kappa] + (default : ContinuousPath alpha) + (hK : ∀ b, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) (kappa b) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) : + (toContinuousPathKernel kappa default).map ContinuousPath.denseRestriction = kappa := by + exact IsSupportedOnContinuousPaths.map_denseRestriction kappa + (IsSupportedOnContinuousPaths.of_isKolmogorovCoordinate kappa hK) default + +end ContinuousPathKernel + +end Kernel +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean new file mode 100644 index 0000000000..f5cc12d708 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean @@ -0,0 +1,100 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor + +/-! +# Nonnegative-rational time shifts + +This file translates a dense-time process by a nonnegative rational time. Translation is an +isometry of `NNRat`, so the Kolmogorov increment condition is preserved with exactly the same +exponents and constant. The final definitions and identities identify the unit-interval +dyadic samples and canonical limit for the shifted process with samples of the original process +on the interval starting at the shift. + +No global path is glued here, and no measurability of the canonical limit or modification-law +assertion is made. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + +namespace MarkovProcess + +variable {Ω E : Type*} + +/-- Translate a dense-time process by a nonnegative rational time. -/ +def timeShift (k : NNRat) (X : NNRat → Ω → E) : NNRat → Ω → E := + fun q ω ↦ X (k + q) ω + +@[simp] +theorem timeShift_apply (k q : NNRat) (X : NNRat → Ω → E) (ω : Ω) : + timeShift k X q ω = X (k + q) ω := + rfl + +/-- Nonnegative-rational translation preserves the Kolmogorov condition without changing its +exponents or constant. -/ +theorem IsKolmogorovProcess.timeShift + {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] + {P : Measure Ω} {X : NNRat → Ω → E} {p q : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (k : NNRat) : + IsKolmogorovProcess (timeShift k X) P p q M where + measurablePair s t := hX.measurablePair (k + s) (k + t) + kolmogorovCondition s t := by + have hdist : dist (k + s) (k + t) = dist s t := by + rw [NNRat.dist_eq, NNRat.dist_eq, Rat.dist_eq, Rat.dist_eq] + push_cast + rw [add_sub_add_left_eq_sub] + simpa only [timeShift, edist_dist, hdist] using! + hX.kolmogorovCondition (k + s) (k + t) + p_pos := hX.p_pos + q_pos := hX.q_pos + +/-- The level-`n` dyadic time in the unit interval, translated to the interval beginning at +`k`. -/ +noncomputable def shiftedUnitDyadicFloorValue (k : NNRat) (n : ℕ) + (t : Set.Icc (0 : ℝ) 1) : NNRat := + k + unitDyadicFloorValue n t + +@[simp] +theorem timeShift_unitDyadicFloorValue_apply + (k : NNRat) (X : NNRat → Ω → E) (ω : Ω) (n : ℕ) + (t : Set.Icc (0 : ℝ) 1) : + timeShift k X (unitDyadicFloorValue n t) ω = + X (shiftedUnitDyadicFloorValue k n t) ω := + rfl + +noncomputable section + +variable [PseudoMetricSpace E] + +/-- The canonical unit-interval dyadic-floor limit of the process translated by `k`. Its time +parameter represents the original interval `[k, k + 1]`. -/ +def shiftedUnitDyadicFloorLimit (k : NNRat) (X : NNRat → Ω → E) (ω : Ω) : + Set.Icc (0 : ℝ) 1 → E := + unitDyadicFloorLimit (timeShift k X) ω + +@[simp] +theorem shiftedUnitDyadicFloorLimit_apply + (k : NNRat) (X : NNRat → Ω → E) (ω : Ω) (t : Set.Icc (0 : ℝ) 1) : + shiftedUnitDyadicFloorLimit k X ω t = unitDyadicFloorLimit (timeShift k X) ω t := + rfl + +variable [CompleteSpace E] + +/-- Cauchy control of samples of the original process at translated dyadic times gives +convergence to the translated canonical unit-interval limit. -/ +theorem tendsto_shiftedUnitDyadicFloorLimit_of_cauchySeq + {k : NNRat} {X : NNRat → Ω → E} {ω : Ω} {t : Set.Icc (0 : ℝ) 1} + (h : CauchySeq (fun n : ℕ ↦ X (shiftedUnitDyadicFloorValue k n t) ω)) : + Tendsto (fun n : ℕ ↦ X (shiftedUnitDyadicFloorValue k n t) ω) atTop + (nhds (shiftedUnitDyadicFloorLimit k X ω t)) := by + simpa only [shiftedUnitDyadicFloorLimit, timeShift_unitDyadicFloorValue_apply] using + tendsto_unitDyadicFloorLimit_of_cauchySeq + (X := timeShift k X) (ω := ω) (t := t) h + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathModulus.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathModulus.lean new file mode 100644 index 0000000000..1047a2d61d --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathModulus.lean @@ -0,0 +1,276 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining +import LeanPool.MarkovProcess.MarkovProcess.Path.Basic + +/-! +# A quantitative modulus of continuity from a Kolmogorov moment bound + +The Kolmogorov--Chentsov argument is usually stated as an almost-sure Hölder property of a +continuous modification. This file records the *quantitative* form that a tightness argument +needs: for a probability law on continuous paths whose coordinate process satisfies the +Kolmogorov moment condition with exponents `p`, `q` and constant `M`, the mass of the paths that +oscillate by more than `r` at scale `delta` on `[0, T]` is at most `eps`, once `delta` is small +enough --- and the threshold `delta` depends only on `p`, `q`, `M`, the Hölder exponent, `T`, +`r` and `eps`, not on the law. This uniformity is the whole point: it is what makes the estimate +usable simultaneously at every starting point of a Markov process. + +Main results: + +* `MarkovProcess.ContinuousPath.modulusSet`, the closed set of paths whose oscillation over + `[0, T]` at scale `delta` is at most `r`, with `isClosed_modulusSet` and + `measurableSet_modulusSet`; +* `MarkovProcess.ContinuousPath.exists_measure_compl_modulusSet_le`, the quantitative estimate, + uniform over all laws obeying one and the same moment bound. + +Nothing here constructs a law, asserts a Hölder exponent for individual paths, or claims +tightness; tightness is assembled from this estimate elsewhere. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace ContinuousPath + +variable {alpha : Type*} [PseudoEMetricSpace alpha] + +/-- The paths whose oscillation over `[0, T]` at scale `delta` is at most `r`: any two times of +`[0, T]` within `delta` of each other carry values within `r` of each other. -/ +def modulusSet (T : ℝ≥0) (delta r : ℝ≥0∞) : Set (ContinuousPath alpha) := + {omega | ∀ s t : ℝ≥0, s ≤ T → t ≤ T → edist s t ≤ delta → edist (omega s) (omega t) ≤ r} + +theorem modulusSet_mono {T : ℝ≥0} {delta r r' : ℝ≥0∞} (hrr : r ≤ r') : + modulusSet (alpha := alpha) T delta r ⊆ modulusSet T delta r' := + fun _ homega s t hs ht hd ↦ (homega s t hs ht hd).trans hrr + +theorem isClosed_modulusSet (T : ℝ≥0) (delta r : ℝ≥0∞) : + IsClosed (modulusSet (alpha := alpha) T delta r) := by + have hrewrite : modulusSet (alpha := alpha) T delta r = + ⋂ s : ℝ≥0, ⋂ t : ℝ≥0, ⋂ _ : s ≤ T, ⋂ _ : t ≤ T, ⋂ _ : edist s t ≤ delta, + {omega : ContinuousPath alpha | edist (omega s) (omega t) ≤ r} := by + ext omega + simp only [modulusSet, Set.mem_ofPred_eq, Set.mem_iInter] + rw [hrewrite] + refine isClosed_iInter fun s ↦ isClosed_iInter fun t ↦ isClosed_iInter fun _ ↦ + isClosed_iInter fun _ ↦ isClosed_iInter fun _ ↦ ?_ + exact isClosed_le ((continuous_eval (alpha := alpha) s).edist (continuous_eval t)) + continuous_const + +theorem measurableSet_modulusSet (T : ℝ≥0) (delta r : ℝ≥0∞) : + MeasurableSet (modulusSet (alpha := alpha) T delta r) := + (isClosed_modulusSet T delta r).measurableSet + +end ContinuousPath + +section Estimate + +variable {alpha : Type*} [PseudoEMetricSpace alpha] + +/-- The chaining bound produced at base level `N`: twice the exact geometric tail above `N` plus +one coarse threshold. -/ +private noncomputable def dyadicChainBound (gamma : ℝ) (N : ℕ) : ℝ≥0∞ := + 2 * (dyadicIncrementThreshold gamma (N + 1) * + (1 - dyadicIncrementThresholdRatio gamma)⁻¹) + dyadicIncrementThreshold gamma N + +private theorem tendsto_dyadicChainBound {gamma : ℝ} (hgamma : 0 < gamma) : + Tendsto (dyadicChainBound gamma) atTop (nhds 0) := by + have htail := tendsto_dyadicIncrementThreshold_ancestor_tail_zero hgamma + have hthr : Tendsto (fun N : ℕ ↦ dyadicIncrementThreshold gamma N) atTop (nhds 0) := by + simp_rw [dyadicIncrementThreshold_eq_ratio_pow] + exact ENNReal.tendsto_pow_atTop_nhds_zero_of_lt_one + (dyadicIncrementThresholdRatio_lt_one hgamma) + have hdouble : Tendsto (fun N : ℕ ↦ 2 * (dyadicIncrementThreshold gamma (N + 1) * + (1 - dyadicIncrementThresholdRatio gamma)⁻¹)) atTop (nhds 0) := by + simpa using ENNReal.Tendsto.const_mul htail (Or.inr (by simp)) + simpa only [dyadicChainBound, add_zero] using! hdouble.add hthr + +/-- The event that some adjacent increment of the level-`n` subdivision of `[0, T]` reaches the +level's Kolmogorov--Chentsov threshold. -/ +private def badLevel (T : ℝ≥0) (p gamma : ℝ) (n : ℕ) : Set (ContinuousPath alpha) := + finiteGridBadIncrement (fun (t : ℝ≥0) (omega : ContinuousPath alpha) ↦ omega t) + (fun i : Fin (2 ^ n + 1) ↦ dyadicTime T n (i : ℕ)) p (dyadicIncrementThreshold gamma n) + +private theorem coe_div_two_pow (T : ℝ≥0) (n : ℕ) : + ((T / 2 ^ n : ℝ≥0) : ℝ≥0∞) = (T : ℝ≥0∞) * ((2 : ℝ≥0∞) ^ n)⁻¹ := by + rw [ENNReal.coe_div (by positivity), div_eq_mul_inv, ENNReal.coe_pow, ENNReal.coe_ofNat] + +private theorem measure_badLevel_le {p q : ℝ} {M : ℝ≥0} {mu : Measure (ContinuousPath alpha)} + (hX : IsKolmogorovProcess (fun (t : ℝ≥0) (omega : ContinuousPath alpha) ↦ omega t) mu p q M) + {gamma : ℝ} (hgamma : 0 < gamma) (T : ℝ≥0) (n : ℕ) : + mu (badLevel T p gamma n) ≤ + (T : ℝ≥0∞) ^ q * ((M * dyadicIncrementDecayRatio p q gamma ^ n : ℝ≥0) : ℝ≥0∞) := by + have hgrid : ∀ i : Fin (2 ^ n), + edist ((fun i : Fin (2 ^ n + 1) ↦ dyadicTime T n (i : ℕ)) i.castSucc) + ((fun i : Fin (2 ^ n + 1) ↦ dyadicTime T n (i : ℕ)) i.succ) ≤ + ((T / 2 ^ n : ℝ≥0) : ℝ≥0∞) := by + intro i + simpa only [Fin.val_castSucc, Fin.val_succ] using edist_dyadicTime_succ_le T n (i : ℕ) + have hbound := IsKolmogorovProcess.measure_finiteGridBadIncrement_le hX + (fun i : Fin (2 ^ n + 1) ↦ dyadicTime T n (i : ℕ)) _ _ hgrid + (dyadicIncrementThreshold_ne_zero hgamma n) (dyadicIncrementThreshold_ne_top hgamma n) + refine hbound.trans (le_of_eq ?_) + simp only [Nat.cast_pow, Nat.cast_ofNat] + rw [coe_div_two_pow, ENNReal.mul_rpow_of_ne_top ENNReal.coe_ne_top (by simp), + ← dyadic_bound_normalization p q gamma M n] + simp only [div_eq_mul_inv] + ring + +private theorem le_add_of_edist_le {s t c : ℝ≥0} (h : edist s t ≤ (c : ℝ≥0∞)) : t ≤ s + c := by + have hd : dist s t ≤ (c : ℝ) := by + rw [edist_dist, ← ENNReal.ofReal_coe_nnreal] at h + exact (ENNReal.ofReal_le_ofReal_iff c.coe_nonneg).mp h + rw [NNReal.dist_eq] at hd + have hlow := (abs_le.mp hd).1 + rw [← NNReal.coe_le_coe] + push_cast + linarith + +private theorem mem_modulusSet_of_notMem_badLevel {p gamma : ℝ} (hp : 0 < p) + {T : ℝ≥0} (hT : 0 < T) (N : ℕ) {omega : ContinuousPath alpha} + (homega : ∀ n, N ≤ n → omega ∉ badLevel T p gamma n) : + omega ∈ ContinuousPath.modulusSet T ((T / 2 ^ (N + 1) : ℝ≥0) : ℝ≥0∞) + (dyadicChainBound gamma N) := by + have hadj : ∀ n, N ≤ n → + HasDyadicAdjacentBound (fun t ↦ omega t) T n (dyadicIncrementThreshold gamma n) := by + intro n hn i hi + have hlt := edist_adjacent_lt_of_notMem_finiteGridBadIncrement + (X := fun (t : ℝ≥0) (eta : ContinuousPath alpha) ↦ eta t) + (grid := fun i : Fin (2 ^ n + 1) ↦ dyadicTime T n (i : ℕ)) hp (homega n hn) + (⟨i, hi⟩ : Fin (2 ^ n)) + simpa only [Fin.val_castSucc, Fin.val_succ] using hlt.le + have key : ∀ s t : ℝ≥0, s ≤ T → t ≤ T → s ≤ t → + edist s t ≤ ((T / 2 ^ (N + 1) : ℝ≥0) : ℝ≥0∞) → + edist (omega s) (omega t) ≤ dyadicChainBound gamma N := by + intro s t hs ht hst hd + have hd' : t ≤ s + T / 2 ^ (N + 1) := le_add_of_edist_le hd + have hstep : ∀ u : ℕ, + edist (omega (dyadicTime T (N + (u + 1)) (dyadicIndex T (N + (u + 1)) s))) + (omega (dyadicTime T (N + (u + 1)) (dyadicIndex T (N + (u + 1)) t))) ≤ + dyadicChainBound gamma N := by + intro u + have hj := dyadicIndex_le hT ht (N + (u + 1)) + have hij := dyadicIndex_mono hT (N + (u + 1)) hst + have hsub := dyadicIndex_sub_le (T := T) hT (n := N) (r := u + 1) (Nat.le_add_left 1 u) hd' + have hchain := edist_dyadicTime_le_of_sub_le (f := fun v ↦ omega v) (T := T) + (e := dyadicIncrementThreshold gamma) (n := N) (r := u + 1) + (fun k hk _ ↦ hadj k hk) hij hj hsub + refine hchain.trans ?_ + unfold dyadicChainBound + gcongr + exact sum_dyadicIncrementThreshold_ancestor_le_tail gamma N (u + 1) + have hlevel : Tendsto (fun u : ℕ ↦ N + (u + 1)) atTop atTop := + tendsto_atTop_mono (fun u ↦ by simp only [id_eq]; omega) tendsto_id + have htends : Tendsto + (fun u : ℕ ↦ edist (omega (dyadicTime T (N + (u + 1)) (dyadicIndex T (N + (u + 1)) s))) + (omega (dyadicTime T (N + (u + 1)) (dyadicIndex T (N + (u + 1)) t)))) + atTop (nhds (edist (omega s) (omega t))) := by + refine Tendsto.edist ?_ ?_ + · exact (omega.continuous.tendsto s).comp + ((tendsto_dyadicTime_dyadicIndex hT s).comp hlevel) + · exact (omega.continuous.tendsto t).comp + ((tendsto_dyadicTime_dyadicIndex hT t).comp hlevel) + exact le_of_tendsto htends (Eventually.of_forall hstep) + intro s t hs ht hd + rcases le_total s t with hst | hst + · exact key s t hs ht hst hd + · rw [edist_comm] + exact key t s ht hs hst (by rwa [edist_comm]) + +private theorem tendsto_badTail {p q gamma : ℝ} (hp : 0 < p) (hgamma : 0 < gamma) + (hgammaq : gamma < (q - 1) / p) (M T : ℝ≥0) : + Tendsto (fun N : ℕ ↦ (T : ℝ≥0∞) ^ q * + ∑' k : ℕ, ((M * dyadicIncrementDecayRatio p q gamma ^ (N + k) : ℝ≥0) : ℝ≥0∞)) + atTop (nhds 0) := by + set rho : ℝ≥0 := dyadicIncrementDecayRatio p q gamma with hrhodef + have hrho : (rho : ℝ≥0∞) < 1 := by + exact_mod_cast dyadicIncrementDecayRatio_lt_one hp hgammaq + have hsum : ∀ N : ℕ, (∑' k : ℕ, ((M * rho ^ (N + k) : ℝ≥0) : ℝ≥0∞)) = + (M : ℝ≥0∞) * ((rho : ℝ≥0∞) ^ N * (1 - (rho : ℝ≥0∞))⁻¹) := by + intro N + have hrw : ∀ k : ℕ, ((M * rho ^ (N + k) : ℝ≥0) : ℝ≥0∞) = + (M : ℝ≥0∞) * ((rho : ℝ≥0∞) ^ N * (rho : ℝ≥0∞) ^ k) := by + intro k + push_cast + rw [pow_add] + simp_rw [hrw] + rw [ENNReal.tsum_mul_left, ENNReal.tsum_mul_left, ENNReal.tsum_geometric] + have hpow : Tendsto (fun N : ℕ ↦ ((rho : ℝ≥0∞)) ^ N) atTop (nhds 0) := + ENNReal.tendsto_pow_atTop_nhds_zero_of_lt_one hrho + have hq : 0 < q := by + have hpos : 0 < (q - 1) / p := lt_trans hgamma hgammaq + have := (div_pos_iff_of_pos_right hp).mp hpos + linarith + have hfinite : (T : ℝ≥0∞) ^ q * (M : ℝ≥0∞) * (1 - (rho : ℝ≥0∞))⁻¹ ≠ ⊤ := by + refine ENNReal.mul_ne_top (ENNReal.mul_ne_top ?_ ENNReal.coe_ne_top) ?_ + · exact ENNReal.rpow_ne_top_of_nonneg hq.le ENNReal.coe_ne_top + · exact ENNReal.inv_ne_top.mpr (tsub_pos_iff_lt.mpr hrho).ne' + have hconst : Tendsto (fun N : ℕ ↦ ((T : ℝ≥0∞) ^ q * (M : ℝ≥0∞) * (1 - (rho : ℝ≥0∞))⁻¹) * + ((rho : ℝ≥0∞)) ^ N) atTop (nhds 0) := by + simpa using ENNReal.Tendsto.const_mul hpow (Or.inr hfinite) + refine hconst.congr fun N ↦ ?_ + rw [hsum N] + ring + +/-- **Quantitative modulus of continuity, uniform over the law.** Fix Kolmogorov exponents +`0 < p`, an admissible Hölder exponent `0 < gamma < (q - 1) / p`, a constant `M`, a horizon `T`, +an oscillation tolerance `r` and a mass tolerance `eps`. Then there is a single scale +`delta > 0` such that *every* probability law on continuous paths whose coordinate process is a +Kolmogorov process with these exponents and this constant gives mass at most `eps` to the paths +that oscillate by more than `r` at scale `delta` on `[0, T]`. + +The scale `delta` is produced by the dyadic chaining of `Continuity/DyadicPathChaining.lean` +together with the geometric union bound of `Continuity/DyadicIncrements.lean`; both bounds depend +only on the displayed data, which is why the conclusion is uniform in the law. -/ +theorem ContinuousPath.exists_measure_compl_modulusSet_le {p q : ℝ} {M : ℝ≥0} {gamma : ℝ} + (hp : 0 < p) (hgamma : 0 < gamma) (hgammaq : gamma < (q - 1) / p) (T : ℝ≥0) {r : ℝ≥0∞} + (hr : 0 < r) {eps : ℝ≥0∞} (heps : 0 < eps) : + ∃ delta : ℝ≥0∞, 0 < delta ∧ + ∀ mu : Measure (ContinuousPath alpha), + IsKolmogorovProcess (fun (t : ℝ≥0) (omega : ContinuousPath alpha) ↦ omega t) mu p q M → + mu (ContinuousPath.modulusSet T delta r)ᶜ ≤ eps := by + rcases eq_or_lt_of_le (zero_le : (0 : ℝ≥0) ≤ T) with hT | hT + · refine ⟨1, one_pos, fun mu _ ↦ ?_⟩ + have hempty : (ContinuousPath.modulusSet (alpha := alpha) T 1 r)ᶜ = ∅ := by + rw [Set.eq_empty_iff_forall_notMem] + intro omega homega + refine homega fun s t hs ht _ ↦ ?_ + have hs0 : s = 0 := le_antisymm (hT ▸ hs) (zero_le : (0 : ℝ≥0) ≤ s) + have ht0 : t = 0 := le_antisymm (hT ▸ ht) (zero_le : (0 : ℝ≥0) ≤ t) + subst hs0 + subst ht0 + simp + rw [hempty] + simp + · have hchain := (tendsto_dyadicChainBound hgamma).eventually_le_const hr + have htail := (tendsto_badTail hp hgamma hgammaq M T).eventually_le_const heps + obtain ⟨N, hN1, hN2⟩ := (hchain.and htail).exists + refine ⟨((T / 2 ^ (N + 1) : ℝ≥0) : ℝ≥0∞), ?_, fun mu hX ↦ ?_⟩ + · exact_mod_cast div_pos hT (by positivity) + · have hsubset : (ContinuousPath.modulusSet (alpha := alpha) T + ((T / 2 ^ (N + 1) : ℝ≥0) : ℝ≥0∞) r)ᶜ ⊆ + ⋃ k : ℕ, badLevel T p gamma (N + k) := by + intro omega homega + by_contra hcon + refine homega (ContinuousPath.modulusSet_mono hN1 ?_) + refine mem_modulusSet_of_notMem_badLevel hp hT N fun n hn hmem ↦ ?_ + exact hcon (Set.mem_iUnion.mpr ⟨n - N, by rwa [Nat.add_sub_cancel' hn]⟩) + calc mu (ContinuousPath.modulusSet T ((T / 2 ^ (N + 1) : ℝ≥0) : ℝ≥0∞) r)ᶜ + ≤ mu (⋃ k : ℕ, badLevel T p gamma (N + k)) := measure_mono hsubset + _ ≤ ∑' k : ℕ, mu (badLevel T p gamma (N + k)) := measure_iUnion_le _ + _ ≤ ∑' k : ℕ, (T : ℝ≥0∞) ^ q * + ((M * dyadicIncrementDecayRatio p q gamma ^ (N + k) : ℝ≥0) : ℝ≥0∞) := + ENNReal.tsum_le_tsum fun k ↦ measure_badLevel_le hX hgamma T (N + k) + _ = (T : ℝ≥0∞) ^ q * + ∑' k : ℕ, ((M * dyadicIncrementDecayRatio p q gamma ^ (N + k) : ℝ≥0) : ℝ≥0∞) := + ENNReal.tsum_mul_left + _ ≤ eps := hN2 + +end Estimate + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathTightness.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathTightness.lean new file mode 100644 index 0000000000..ac95d19d1a --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathTightness.lean @@ -0,0 +1,336 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus +import Mathlib.MeasureTheory.Measure.Tight +import Mathlib.Topology.UniformSpace.Ascoli + +/-! +# Compact sets of paths, and tightness on continuous-path space + +A family of laws on `C([0, ∞), alpha)` is tight as soon as two things hold uniformly over the +family: the time-zero position lies in a fixed compact set, and the oscillation over each bounded +time interval is controlled at a scale that does not depend on the law. This file supplies the +compact sets that make that statement work and then assembles the tightness estimate. + +The compact sets are `ContinuousPath.moduliSet K0 delta r`: the paths starting in `K0` whose +oscillation over `[0, n]` at scale `delta n` is at most `r n`, for every natural `n`. When +`r n → 0` these conditions are exactly equicontinuity, so Arzelà--Ascoli applies as soon as the +values of the family at each fixed time stay in a compact set. That last requirement --- the +compact containment condition of the weak-convergence literature --- is isolated as a hypothesis +in `isCompact_moduliSet_of_forall_isCompact`; over a *proper* metric state space (closed balls +compact) it is automatic, because the modulus already confines a path to a bounded neighbourhood +of its starting point, and `isCompact_moduliSet` discharges it. + +Main results: + +* `MarkovProcess.ContinuousPath.edist_le_of_modulus`, the chaining bound from the starting point; +* `MarkovProcess.ContinuousPath.moduliSet` and `moduliFunSet`, with closedness and + equicontinuity; +* `MarkovProcess.ContinuousPath.isCompact_moduliSet_of_forall_isCompact` and + `isCompact_moduliSet`, the Arzelà--Ascoli compactness statements; +* `MarkovProcess.ContinuousPath.isTightMeasureSet_of_measure_compl_modulusSet_le`, tightness of a + family of laws from a uniform modulus estimate and a compact time-zero law. + +Nothing here constructs a law, and no compactness theorem for measures (Prokhorov's theorem) is +proved or used. +-/ + +open Filter MeasureTheory Metric Topology +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace ContinuousPath + +variable {alpha : Type*} [MetricSpace alpha] + +section Chaining + +/-- Chaining along an equally spaced subdivision of `[0, t]`: a modulus of continuity at scale +`d` on `[0, T]` bounds the displacement from the initial value by the number of steps times the +oscillation. -/ +theorem edist_le_of_modulus {T d : ℝ≥0} (hd : 0 < d) {rho : ℝ≥0∞} {f : ℝ≥0 → alpha} + (hf : ∀ s t : ℝ≥0, s ≤ T → t ≤ T → edist s t ≤ (d : ℝ≥0∞) → edist (f s) (f t) ≤ rho) + {t : ℝ≥0} (ht : t ≤ T) : + edist (f 0) (f t) ≤ ((⌈(T : ℝ) / d⌉₊ + 1 : ℕ) : ℝ≥0∞) * rho := by + set K : ℕ := ⌈(T : ℝ) / d⌉₊ + 1 with hK + have hKpos : (0 : ℝ) < (K : ℝ) := by + rw [hK] + push_cast + positivity + have hKne : (K : ℝ≥0) ≠ 0 := by + simpa only [ne_eq, Nat.cast_eq_zero] using Nat.succ_ne_zero _ + set u : ℕ → ℝ≥0 := fun k ↦ t * k / K with hu + have hu0 : u 0 = 0 := by simp [hu] + have huK : u K = t := by + show t * (K : ℝ≥0) / (K : ℝ≥0) = t + rw [mul_div_assoc, div_self hKne, mul_one] + have hule : ∀ k, k ≤ K → u k ≤ T := by + intro k hk + refine le_trans ?_ ht + rw [← NNReal.coe_le_coe] + push_cast [hu] + rw [div_le_iff₀ hKpos] + have hkK : (k : ℝ) ≤ (K : ℝ) := by exact_mod_cast hk + nlinarith [t.coe_nonneg, hkK] + have hTK : (T : ℝ) / K < (d : ℝ) := by + have hdpos : (0 : ℝ) < (d : ℝ) := hd + have hceil : (T : ℝ) / d ≤ (⌈(T : ℝ) / d⌉₊ : ℝ) := Nat.le_ceil _ + have hlt : (T : ℝ) / d < (K : ℝ) := by + rw [hK] + push_cast + linarith + rw [div_lt_iff₀ hKpos] + rw [div_lt_iff₀ hdpos] at hlt + linarith + have hstep : ∀ k : ℕ, edist (u k) (u (k + 1)) ≤ (d : ℝ≥0∞) := by + intro k + have hexp : ((u k : ℝ≥0) : ℝ) - ((u (k + 1) : ℝ≥0) : ℝ) = -((t : ℝ) / K) := by + simp only [hu] + push_cast + rw [div_sub_div_same, ← mul_sub, show (k : ℝ) - ((k : ℝ) + 1) = -1 by ring] + ring + have hval : dist (u k) (u (k + 1)) = (t : ℝ) / K := by + rw [NNReal.dist_eq, hexp, abs_neg, abs_of_nonneg (by positivity)] + have htK : (t : ℝ) / K ≤ (d : ℝ) := by + have hmono : (t : ℝ) / K ≤ (T : ℝ) / K := by gcongr + linarith [hTK] + rw [edist_dist, hval, ← ENNReal.ofReal_coe_nnreal] + exact ENNReal.ofReal_le_ofReal htK + have hchain : edist (f (u 0)) (f (u K)) ≤ ∑ _i ∈ Finset.Ico 0 K, rho := + edist_le_Ico_sum_of_edist_le (f := fun k ↦ f (u k)) (Nat.zero_le K) + (d := fun _ ↦ rho) fun {k} _ hkK ↦ + hf (u k) (u (k + 1)) (hule k hkK.le) (hule (k + 1) hkK) (hstep k) + rw [hu0, huK] at hchain + simpa only [Finset.sum_const, Nat.card_Ico, Nat.sub_zero, nsmul_eq_mul] using hchain + +end Chaining + +section Moduli + +/-- The paths that start in `K0` and, for every natural `n`, oscillate by at most `r n` at +scale `delta n` over `[0, n]`. -/ +def moduliSet (K0 : Set alpha) (delta rho : ℕ → ℝ≥0∞) : Set (ContinuousPath alpha) := + {omega | omega 0 ∈ K0} ∩ ⋂ n : ℕ, modulusSet (n : ℝ≥0) (delta n) (rho n) + +/-- The same conditions read on arbitrary, not necessarily continuous, functions of time. -/ +def moduliFunSet (K0 : Set alpha) (delta rho : ℕ → ℝ≥0∞) : Set (ℝ≥0 → alpha) := + {f | f 0 ∈ K0} ∩ ⋂ n : ℕ, {f : ℝ≥0 → alpha | + ∀ s t : ℝ≥0, s ≤ (n : ℝ≥0) → t ≤ (n : ℝ≥0) → edist s t ≤ delta n → edist (f s) (f t) ≤ rho n} + +theorem isClosed_moduliFunSet {K0 : Set alpha} (hK0 : IsClosed K0) (delta rho : ℕ → ℝ≥0∞) : + IsClosed (moduliFunSet K0 delta rho) := by + refine IsClosed.inter (hK0.preimage (continuous_apply (0 : ℝ≥0))) (isClosed_iInter fun n ↦ ?_) + have hrewrite : {f : ℝ≥0 → alpha | ∀ s t : ℝ≥0, s ≤ (n : ℝ≥0) → t ≤ (n : ℝ≥0) → + edist s t ≤ delta n → edist (f s) (f t) ≤ rho n} = + ⋂ s : ℝ≥0, ⋂ t : ℝ≥0, ⋂ _ : s ≤ (n : ℝ≥0), ⋂ _ : t ≤ (n : ℝ≥0), + ⋂ _ : edist s t ≤ delta n, {f : ℝ≥0 → alpha | edist (f s) (f t) ≤ rho n} := by + ext f + simp only [Set.mem_ofPred_eq, Set.mem_iInter] + rw [hrewrite] + refine isClosed_iInter fun s ↦ isClosed_iInter fun t ↦ isClosed_iInter fun _ ↦ + isClosed_iInter fun _ ↦ isClosed_iInter fun _ ↦ ?_ + exact isClosed_le ((continuous_apply s).edist (continuous_apply t)) continuous_const + +/-- A vanishing oscillation sequence makes the family of functions obeying the moduli +equicontinuous. -/ +theorem equicontinuous_moduliFunSet {K0 : Set alpha} {delta rho : ℕ → ℝ≥0∞} + (hdelta : ∀ n, 0 < delta n) (hrho : Tendsto rho atTop (nhds 0)) : + Equicontinuous fun f : moduliFunSet K0 delta rho ↦ (f : ℝ≥0 → alpha) := by + intro t0 + rw [equicontinuousAt_iff] + intro eps heps + obtain ⟨n0, hn0⟩ := exists_nat_ge ((t0 : ℝ) + 1) + obtain ⟨n, hnr, hnn⟩ := + ((hrho.eventually_lt_const (ENNReal.ofReal_pos.mpr heps)).and + (eventually_ge_atTop n0)).exists + set d : ℝ≥0∞ := min (delta n) 1 with hd + have hdpos : 0 < d := lt_min (hdelta n) one_pos + have hdtop : d ≠ ⊤ := ne_top_of_le_ne_top ENNReal.one_ne_top (min_le_right _ _) + have hdreal : 0 < d.toReal := ENNReal.toReal_pos hdpos.ne' hdtop + have hdle1 : d.toReal ≤ 1 := by + simpa using ENNReal.toReal_mono ENNReal.one_ne_top (min_le_right (delta n) 1) + have hnreal : (t0 : ℝ) + 1 ≤ (n : ℝ) := by + refine hn0.trans ?_ + exact_mod_cast hnn + have ht0n : t0 ≤ (n : ℝ≥0) := by + rw [← NNReal.coe_le_coe] + push_cast + linarith + refine ⟨d.toReal, hdreal, fun s hs f ↦ ?_⟩ + have hsdist : |(s : ℝ) - (t0 : ℝ)| < d.toReal := by + rw [← NNReal.dist_eq] + exact hs + have hsn : s ≤ (n : ℝ≥0) := by + rw [← NNReal.coe_le_coe] + push_cast + have := (abs_lt.mp hsdist).2 + linarith + have hedist : edist t0 s ≤ delta n := by + have hlt : edist t0 s < d := by + rw [edist_comm, edist_dist, ← ENNReal.ofReal_toReal hdtop] + exact (ENNReal.ofReal_lt_ofReal_iff hdreal).mpr hs + exact hlt.le.trans (min_le_left _ _) + have hmod := Set.mem_iInter.mp f.2.2 n (t0 : ℝ≥0) s ht0n hsn hedist + have hkey : ENNReal.ofReal (dist ((f : ℝ≥0 → alpha) t0) ((f : ℝ≥0 → alpha) s)) < + ENNReal.ofReal eps := by + rw [← edist_dist] + exact lt_of_le_of_lt hmod hnr + exact (ENNReal.ofReal_lt_ofReal_iff heps).mp hkey + +/-- Over a proper metric state space the moduli already confine every value of the path to one +compact set, because a chain of steps of length at most `delta n` reaches every time of `[0, n]` +from the starting point. -/ +theorem exists_isCompact_eval_mem [ProperSpace alpha] {K0 : Set alpha} (hK0 : IsCompact K0) + {delta rho : ℕ → ℝ≥0∞} (hdelta : ∀ n, 0 < delta n) (hrho : Tendsto rho atTop (nhds 0)) + (t : ℝ≥0) : + ∃ Q : Set alpha, IsCompact Q ∧ ∀ f ∈ moduliFunSet K0 delta rho, f t ∈ Q := by + rcases K0.eq_empty_or_nonempty with hempty | ⟨c, hc⟩ + · refine ⟨∅, isCompact_empty, fun f hf ↦ ?_⟩ + rw [hempty] at hf + exact absurd hf.1 (Set.notMem_empty _) + obtain ⟨R, hR⟩ := (isBounded_iff_subset_closedBall c).mp hK0.isBounded + obtain ⟨n0, hn0⟩ := exists_nat_ge (t : ℝ) + obtain ⟨n, hnr, hnn⟩ := + ((hrho.eventually_lt_const (zero_lt_one (α := ℝ≥0∞))).and (eventually_ge_atTop n0)).exists + set d : ℝ≥0 := (min (delta n) 1).toNNReal with hd + have hdtop : min (delta n) 1 ≠ ⊤ := ne_top_of_le_ne_top ENNReal.one_ne_top (min_le_right _ _) + have hdcoe : (d : ℝ≥0∞) = min (delta n) 1 := by + rw [hd, ENNReal.coe_toNNReal hdtop] + have hdpos : 0 < d := by + rw [← ENNReal.coe_pos, hdcoe] + exact lt_min (hdelta n) one_pos + have hdle : (d : ℝ≥0∞) ≤ delta n := by + rw [hdcoe] + exact min_le_left _ _ + have htn : t ≤ (n : ℝ≥0) := by + rw [← NNReal.coe_le_coe] + push_cast + exact hn0.trans (by exact_mod_cast hnn) + set C : ℝ≥0∞ := ((⌈((n : ℝ≥0) : ℝ) / d⌉₊ + 1 : ℕ) : ℝ≥0∞) * rho n with hC + have hCtop : C ≠ ⊤ := + ENNReal.mul_ne_top (by simp) (ne_top_of_lt (lt_of_lt_of_le hnr le_top)) + refine ⟨closedBall c (R + C.toReal), isCompact_closedBall _ _, fun f hf ↦ ?_⟩ + have hmod : ∀ s u : ℝ≥0, s ≤ (n : ℝ≥0) → u ≤ (n : ℝ≥0) → edist s u ≤ (d : ℝ≥0∞) → + edist (f s) (f u) ≤ rho n := fun s u hs hu hsu ↦ + Set.mem_iInter.mp hf.2 n s u hs hu (hsu.trans hdle) + have hchain := edist_le_of_modulus hdpos hmod htn + have hdist : dist (f 0) (f t) ≤ C.toReal := by + rw [← ENNReal.ofReal_le_iff_le_toReal hCtop, ← edist_dist] + exact hchain + have h0 : dist (f 0) c ≤ R := mem_closedBall.mp (hR hf.1) + rw [mem_closedBall] + calc dist (f t) c ≤ dist (f t) (f 0) + dist (f 0) c := dist_triangle _ _ _ + _ ≤ C.toReal + R := add_le_add (by rw [dist_comm]; exact hdist) h0 + _ = R + C.toReal := add_comm _ _ + +/-- **Compactness of a modulus class, with compact containment as a hypothesis.** If the values +at each fixed time of the functions obeying the moduli stay in a compact set, then the continuous +paths obeying them form a compact subset of path space. This is Arzelà--Ascoli: the moduli give +equicontinuity, and the pointwise hypothesis gives the pointwise relative compactness that no +modulus can supply on a general complete separable metric space. -/ +theorem isCompact_moduliSet_of_forall_isCompact {K0 : Set alpha} (hK0 : IsClosed K0) + {delta rho : ℕ → ℝ≥0∞} (hdelta : ∀ n, 0 < delta n) (hrho : Tendsto rho atTop (nhds 0)) + (hpoint : ∀ t : ℝ≥0, ∃ Q : Set alpha, IsCompact Q ∧ + ∀ f ∈ moduliFunSet K0 delta rho, f t ∈ Q) : + IsCompact (moduliSet K0 delta rho) := by + have hequi := equicontinuous_moduliFunSet (K0 := K0) hdelta hrho + choose Q hQcompact hQmem using hpoint + have hfun : IsCompact (moduliFunSet K0 delta rho) := + IsCompact.of_isClosed_subset (isCompact_univ_pi hQcompact) + (isClosed_moduliFunSet hK0 delta rho) + fun f hf ↦ Set.mem_univ_pi.mpr fun t ↦ hQmem t f hf + have himage : ContinuousMap.toFun '' moduliSet K0 delta rho = moduliFunSet K0 delta rho := by + ext f + constructor + · rintro ⟨omega, homega, rfl⟩ + exact ⟨homega.1, Set.mem_iInter.mpr fun n ↦ Set.mem_iInter.mp homega.2 n⟩ + · intro hf + exact ⟨⟨f, hequi.continuous ⟨f, hf⟩⟩, + ⟨hf.1, Set.mem_iInter.mpr fun n ↦ Set.mem_iInter.mp hf.2 n⟩, rfl⟩ + refine ArzelaAscoli.isCompact_of_equicontinuous _ ?_ ?_ + · rw [himage] + exact hfun + · exact hequi.comp fun w : moduliSet K0 delta rho ↦ + (⟨((w : ContinuousPath alpha) : ℝ≥0 → alpha), + ⟨w.2.1, Set.mem_iInter.mpr fun n ↦ Set.mem_iInter.mp w.2.2 n⟩⟩ : + moduliFunSet K0 delta rho) + +/-- **Compactness of a modulus class over a proper state space.** Over a metric state space whose +closed balls are compact, the continuous paths starting in a compact set and obeying a vanishing +sequence of moduli form a compact subset of path space. -/ +theorem isCompact_moduliSet [ProperSpace alpha] {K0 : Set alpha} (hK0 : IsCompact K0) + {delta rho : ℕ → ℝ≥0∞} (hdelta : ∀ n, 0 < delta n) (hrho : Tendsto rho atTop (nhds 0)) : + IsCompact (moduliSet K0 delta rho) := + isCompact_moduliSet_of_forall_isCompact hK0.isClosed hdelta hrho + (exists_isCompact_eval_mem hK0 hdelta hrho) + +end Moduli + +section Tight + +private theorem tsum_geometric_half (eps : ℝ≥0∞) : + (∑' n : ℕ, eps * ((2 : ℝ≥0∞) ^ (n + 1))⁻¹) = eps := by + have hsplit : ∀ n : ℕ, ((2 : ℝ≥0∞) ^ (n + 1))⁻¹ = 2⁻¹ * ((2 : ℝ≥0∞)⁻¹) ^ n := by + intro n + rw [pow_succ, ENNReal.mul_inv (by simp) (by simp), ← ENNReal.inv_pow] + ring + have hone : (1 : ℝ≥0∞) - 2⁻¹ = 2⁻¹ := by + rw [← ENNReal.inv_two_add_inv_two, ENNReal.add_sub_cancel_left (by simp)] + rw [ENNReal.tsum_mul_left] + simp_rw [hsplit] + rw [ENNReal.tsum_mul_left, ENNReal.tsum_geometric, hone, inv_inv, + ENNReal.inv_mul_cancel (by simp) (by simp), mul_one] + +/-- **Tightness from a uniform modulus estimate.** Let `S` be a family of measures on continuous +paths over a proper metric state space. Suppose every member gives full mass to the paths +starting in one fixed compact set `K0`, and suppose that for every horizon `T`, every oscillation +tolerance `r > 0` and every mass tolerance `eps > 0` there is a *single* scale `delta > 0` at +which every member of the family gives mass at most `eps` to the paths oscillating by more than +`r` at scale `delta` on `[0, T]`. Then `S` is tight. + +Properness of the state space enters only through `exists_isCompact_eval_mem`; on a general +complete separable metric space it is replaced by the compact containment condition, in the form +of the hypothesis of `isCompact_moduliSet_of_forall_isCompact`. -/ +theorem isTightMeasureSet_of_measure_compl_modulusSet_le [ProperSpace alpha] + {S : Set (Measure (ContinuousPath alpha))} {K0 : Set alpha} (hK0 : IsCompact K0) + (hstart : ∀ mu ∈ S, mu {omega : ContinuousPath alpha | omega 0 ∉ K0} = 0) + (hmod : ∀ (T : ℝ≥0) (r : ℝ≥0∞), 0 < r → ∀ eps : ℝ≥0∞, 0 < eps → + ∃ delta : ℝ≥0∞, 0 < delta ∧ ∀ mu ∈ S, mu (modulusSet T delta r)ᶜ ≤ eps) : + IsTightMeasureSet S := by + rw [isTightMeasureSet_iff_exists_isCompact_measure_compl_le] + intro eps heps + set rho : ℕ → ℝ≥0∞ := fun n ↦ ((n : ℝ≥0∞))⁻¹ with hrho + have hrhopos : ∀ n : ℕ, 0 < rho n := fun n ↦ ENNReal.inv_pos.mpr (ENNReal.natCast_ne_top n) + have hrhotendsto : Tendsto rho atTop (nhds 0) := ENNReal.tendsto_inv_nat_nhds_zero + have hepsn : ∀ n : ℕ, 0 < eps * ((2 : ℝ≥0∞) ^ (n + 1))⁻¹ := + fun n ↦ ENNReal.mul_pos heps.ne' (by simp) + choose delta hdelta hdeltaS using fun n : ℕ ↦ + hmod (n : ℝ≥0) (rho n) (hrhopos n) _ (hepsn n) + refine ⟨moduliSet K0 delta rho, isCompact_moduliSet hK0 hdelta hrhotendsto, fun mu hmu ↦ ?_⟩ + have hcompl : (moduliSet K0 delta rho)ᶜ = + {omega : ContinuousPath alpha | omega 0 ∉ K0} ∪ + ⋃ n : ℕ, (modulusSet ((n : ℝ≥0)) (delta n) (rho n))ᶜ := by + ext omega + simp only [moduliSet, Set.mem_compl_iff, Set.mem_inter_iff, Set.mem_iInter, Set.mem_ofPred_eq, + Set.mem_union, Set.mem_iUnion, not_and_or, not_forall] + rw [hcompl] + calc mu ({omega : ContinuousPath alpha | omega 0 ∉ K0} ∪ + ⋃ n : ℕ, (modulusSet ((n : ℝ≥0)) (delta n) (rho n))ᶜ) + ≤ mu {omega : ContinuousPath alpha | omega 0 ∉ K0} + + mu (⋃ n : ℕ, (modulusSet ((n : ℝ≥0)) (delta n) (rho n))ᶜ) := measure_union_le _ _ + _ ≤ 0 + ∑' n : ℕ, mu (modulusSet ((n : ℝ≥0)) (delta n) (rho n))ᶜ := + add_le_add (hstart mu hmu).le (measure_iUnion_le _) + _ ≤ ∑' n : ℕ, eps * ((2 : ℝ≥0∞) ^ (n + 1))⁻¹ := by + rw [zero_add] + exact ENNReal.tsum_le_tsum fun n ↦ hdeltaS n mu hmu + _ = eps := tsum_geometric_half eps + +end Tight + +end ContinuousPath + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/ShiftedUnitModification.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/ShiftedUnitModification.lean new file mode 100644 index 0000000000..b336f00e1c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/ShiftedUnitModification.lean @@ -0,0 +1,104 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor + +/-! +# Continuous modifications on shifted unit intervals + +This file applies the unit-interval totalization to a nonnegative-rational time shift. It also +identifies the endpoints of the underlying canonical limit exactly, for every sample, using the +eventual constancy of dyadic approximations at dyadic grid times. + +No global path is glued here, and no path-space measurability, law, or Hunt-process property is +asserted. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + +namespace MarkovProcess + +noncomputable section + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [MetricSpace E] [CompleteSpace E] + [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] + +/-- The total continuous unit path obtained from the process translated by `k`. Its local time +parameter represents the original interval `[k, k + 1]`. -/ +def continuousShiftedUnitDyadicFloorLimit + (k : NNRat) (X : NNRat → Ω → E) (ω : Ω) : Set.Icc (0 : ℝ) 1 → E := + continuousUnitDyadicFloorLimit (timeShift k X) ω + +omit [CompleteSpace E] [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- Every shifted totalized unit path is continuous. -/ +theorem continuous_continuousShiftedUnitDyadicFloorLimit + (k : NNRat) (X : NNRat → Ω → E) (ω : Ω) : + Continuous (continuousShiftedUnitDyadicFloorLimit k X ω) := by + exact continuous_continuousUnitDyadicFloorLimit (timeShift k X) ω + +/-- At each fixed rational local time, the shifted total path is a modification of the original +process at the translated time `k + t`. -/ +theorem IsKolmogorovProcess.ae_eq_continuousShiftedUnitDyadicFloorLimit + {P : Measure Ω} [IsFiniteMeasure P] + {X : NNRat → Ω → E} {p q γ : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (hγ : 0 < γ) + (hγq : γ < (q - 1) / p) (k t : NNRat) (ht : t ≤ 1) : + X (k + t) =ᵐ[P] fun ω ↦ + continuousShiftedUnitDyadicFloorLimit k X ω (unitIccOfNNRat t ht) := by + simpa only [continuousShiftedUnitDyadicFloorLimit, timeShift_apply] using! + IsKolmogorovProcess.ae_eq_continuousUnitDyadicFloorLimit + (IsKolmogorovProcess.timeShift hX k) hγ hγq t ht + +omit [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- At every dyadic grid time, the shifted canonical limit is exactly the corresponding sample +of the original process. This is a pointwise identity for every `ω`, not an almost-sure one. -/ +theorem shiftedUnitDyadicFloorLimit_gridTime_eq_sample + (k : NNRat) (X : NNRat → Ω → E) (ω : Ω) + (n : ℕ) (i : Fin (2 ^ n + 1)) : + shiftedUnitDyadicFloorLimit k X ω (unitDyadicGridTime n i) = + X (k + unitDyadicGrid n i) ω := by + have hevent := + eventually_sample_unitDyadicFloorValue_gridTime (timeShift k X) n i ω + have htendsto : Tendsto + (fun m ↦ timeShift k X + (unitDyadicFloorValue m (unitDyadicGridTime n i)) ω) + atTop (nhds (timeShift k X (unitDyadicGrid n i) ω)) := + tendsto_const_nhds.congr' (hevent.mono fun _ hm ↦ hm.symm) + have hcanonical := tendsto_unitDyadicFloorLimit_of_cauchySeq htendsto.cauchySeq + exact eq_sample_of_tendsto_unitDyadicFloorValue_gridTime + (timeShift k X) n i ω (shiftedUnitDyadicFloorLimit k X ω (unitDyadicGridTime n i)) + (by simpa only [shiftedUnitDyadicFloorLimit] using hcanonical) + +omit [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- The local zero endpoint of a shifted canonical unit path is exactly the sample at `k`. -/ +theorem shiftedUnitDyadicFloorLimit_zero + (k : NNRat) (X : NNRat → Ω → E) (ω : Ω) : + shiftedUnitDyadicFloorLimit k X ω (0 : Set.Icc (0 : ℝ) 1) = X k ω := by + let i : Fin (2 ^ 0 + 1) := ⟨0, by norm_num⟩ + have htime : unitDyadicGridTime 0 i = (0 : Set.Icc (0 : ℝ) 1) := by + apply Subtype.ext + norm_num [unitDyadicGridTime, unitDyadicGrid, i] + rw [← htime] + simpa only [unitDyadicGrid, i, Nat.cast_zero, zero_div, add_zero] using + shiftedUnitDyadicFloorLimit_gridTime_eq_sample k X ω 0 i + +omit [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] in +/-- The local one endpoint of a shifted canonical unit path is exactly the sample at `k + 1`. -/ +theorem shiftedUnitDyadicFloorLimit_one + (k : NNRat) (X : NNRat → Ω → E) (ω : Ω) : + shiftedUnitDyadicFloorLimit k X ω (1 : Set.Icc (0 : ℝ) 1) = X (k + 1) ω := by + let i : Fin (2 ^ 0 + 1) := ⟨1, by norm_num⟩ + have htime : unitDyadicGridTime 0 i = (1 : Set.Icc (0 : ℝ) 1) := by + apply Subtype.ext + norm_num [unitDyadicGridTime, unitDyadicGrid, i] + rw [← htime] + simpa only [unitDyadicGrid, i, Nat.cast_one, Nat.cast_pow, Nat.cast_ofNat, pow_zero, + div_one] using shiftedUnitDyadicFloorLimit_gridTime_eq_sample k X ω 0 i + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime.lean new file mode 100644 index 0000000000..9908dbf50d --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime.lean @@ -0,0 +1,26 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscreteLaw +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryDenseTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals + +/-! +# DenseTime + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscreteLaw.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscreteLaw.lean new file mode 100644 index 0000000000..00aa5152b5 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscreteLaw.lean @@ -0,0 +1,78 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath +import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid + +/-! +# Canonical discrete trajectory laws + +This file equips the canonical discrete path space with the trajectory law of +a conservative transition-kernel semigroup along one fixed ordered grid. It +records exact finite-prefix and coordinate marginal identities. No +conditional-expectation Markov property is asserted here. +-/ + +open MeasureTheory +open ProbabilityTheory + +namespace MarkovProcess + +variable {α : Type*} [MeasurableSpace α] + +namespace SubMarkovKernelSemigroup + +variable (P : SubMarkovKernelSemigroup α) + +/-- The canonical discrete path law started from `x` along `grid`. -/ +noncomputable def canonicalDiscreteLaw + (hP : P.IsConservative) (grid : OrderedGrid) (x : α) : + Measure (DiscretePath α) := + orderedGridTrajectoryLaw P hP grid x + +/-- The canonical discrete path law is a probability measure. -/ +theorem IsConservative.isProbabilityMeasure_canonicalDiscreteLaw + (hP : P.IsConservative) (grid : OrderedGrid) (x : α) : + IsProbabilityMeasure (canonicalDiscreteLaw P hP grid x) := by + exact IsConservative.isProbabilityMeasure_orderedGridTrajectoryLaw P hP grid x + +/-- Restricting the canonical law to coordinates through `n` gives the +corresponding finite Ionescu--Tulcea trajectory law. -/ +theorem IsConservative.canonicalDiscreteLaw_map_prefix + (hP : P.IsConservative) (grid : OrderedGrid) (x : α) (n : ℕ) : + (canonicalDiscreteLaw P hP grid x).map + (fun path : DiscretePath α => fun i : Finset.Iic n => path i) = + Kernel.partialTraj (X := fun _ => α) (orderedGridStepKernel P grid) 0 n + (initialHistory x) := by + exact IsConservative.orderedGridTrajectoryLaw_map_frestrictLe P hP grid x n + +/-- The law of coordinate `n` is the last-coordinate pushforward of the +finite trajectory law through `n`. -/ +theorem IsConservative.canonicalDiscreteLaw_map_coordinate + (hP : P.IsConservative) (grid : OrderedGrid) (x : α) (n : ℕ) : + (canonicalDiscreteLaw P hP grid x).map (DiscretePath.coordinate n) = + (Kernel.partialTraj (X := fun _ => α) (orderedGridStepKernel P grid) 0 n + (initialHistory x)).map (fun history => history ⟨n, Finset.mem_Iic.mpr le_rfl⟩) := by + rw [← IsConservative.canonicalDiscreteLaw_map_prefix P hP grid x n, + Measure.map_map] + · rfl + · exact measurable_pi_apply (X := fun _ : Finset.Iic n => α) + ⟨n, Finset.mem_Iic.mpr le_rfl⟩ + · exact measurable_pi_iff.mpr fun _ => DiscretePath.measurable_coordinate (α := α) _ + +/-- The zeroth coordinate of the canonical law is deterministically the +starting state. -/ +theorem IsConservative.canonicalDiscreteLaw_map_coordinate_zero + (hP : P.IsConservative) (grid : OrderedGrid) (x : α) : + (canonicalDiscreteLaw P hP grid x).map (DiscretePath.coordinate 0) = Measure.dirac x := by + rw [IsConservative.canonicalDiscreteLaw_map_coordinate P hP grid x 0, + Kernel.partialTraj_self, Kernel.id_apply] + exact Measure.map_dirac' + (measurable_pi_apply (X := fun _ : Finset.Iic 0 => α) + ⟨0, Finset.mem_Iic.mpr le_rfl⟩) (initialHistory x) + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscretePath.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscretePath.lean new file mode 100644 index 0000000000..dc28d2b030 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscretePath.lean @@ -0,0 +1,111 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Probability.Process.Adapted + +/-! +# Canonical discrete path space + +This file records the elementary measurable and filtered structure on the +discrete path space `ℕ → α`. It does not equip paths with a probability law or +assert any Markov property. + +## Main definitions + +* `DiscretePath`: the canonical space of `α`-valued discrete paths. +* `DiscretePath.coordinate`: evaluation of a path at one time. +* `DiscretePath.coordinateProcess`: the canonical coordinate process. +* `DiscretePath.canonicalFiltration`: the natural filtration of the coordinate process. +-/ + +open MeasureTheory +open TopologicalSpace + +namespace MarkovProcess + +/-- The canonical space of `α`-valued paths indexed by `ℕ`. -/ +abbrev DiscretePath (α : Type*) := ℕ → α + +namespace DiscretePath + +variable {α : Type*} + +/-- Evaluation of a discrete path at time `n`. -/ +def coordinate (n : ℕ) (ω : DiscretePath α) : α := + ω n + +/-- The canonical coordinate process on discrete path space. -/ +def coordinateProcess : ℕ → DiscretePath α → α := + fun n => coordinate n + +@[simp] +theorem coordinate_apply (n : ℕ) (ω : DiscretePath α) : coordinate n ω = ω n := + rfl + +@[simp] +theorem coordinateProcess_apply (n : ℕ) (ω : DiscretePath α) : + coordinateProcess n ω = ω n := + rfl + +section Measurable + +variable [MeasurableSpace α] + +/-- Every coordinate evaluation is measurable for the product measurable +space on discrete paths. -/ +@[fun_prop] +theorem measurable_coordinate (n : ℕ) : Measurable (coordinate (α := α) n) := + measurable_pi_apply n + +/-- Every member of the coordinate process is measurable. -/ +@[fun_prop] +theorem measurable_coordinateProcess (n : ℕ) : + Measurable (coordinateProcess (α := α) n) := + measurable_coordinate n + +end Measurable + +section NaturalFiltration + +variable [TopologicalSpace α] +variable [MetrizableSpace α] +variable [MeasurableSpace α] +variable [BorelSpace α] +variable [SecondCountableTopology α] + +/-- Every coordinate evaluation is strongly measurable when the state space +is second-countable, metrizable, and carries its Borel measurable space. -/ +theorem stronglyMeasurable_coordinate (n : ℕ) : + StronglyMeasurable (coordinate (α := α) n) := + (measurable_coordinate n).stronglyMeasurable + +/-- Every member of the coordinate process is strongly measurable. -/ +theorem stronglyMeasurable_coordinateProcess (n : ℕ) : + StronglyMeasurable (coordinateProcess (α := α) n) := + stronglyMeasurable_coordinate n + +/-- The canonical filtration on discrete path space, defined as the natural +filtration generated by the coordinate process. -/ +def canonicalFiltration : Filtration ℕ (inferInstance : MeasurableSpace (DiscretePath α)) := + Filtration.natural coordinateProcess stronglyMeasurable_coordinateProcess + +/-- At time `n`, the canonical filtration is generated by coordinate maps at +times at most `n`. -/ +theorem canonicalFiltration_apply (n : ℕ) : + canonicalFiltration (α := α) n = + ⨆ k ≤ n, MeasurableSpace.comap (coordinateProcess (α := α) k) inferInstance := + rfl + +/-- The coordinate process is adapted to its canonical filtration. -/ +theorem adapted_coordinateProcess : + Adapted (canonicalFiltration (α := α)) (coordinateProcess (α := α)) := by + exact (Filtration.stronglyAdapted_natural + (u := coordinateProcess (α := α)) stronglyMeasurable_coordinateProcess).adapted + +end NaturalFiltration + +end DiscretePath + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryDenseTimeMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryDenseTimeMarginals.lean new file mode 100644 index 0000000000..e9e954d249 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryDenseTimeMarginals.lean @@ -0,0 +1,42 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals + +/-! +# Cemetery marginals of dense-time trajectories + +For a conservative live semigroup, the trajectory of its cemetery extension has no cemetery mass +at any dense-time coordinate when started from a live state. This is a finite-coordinate statement; +it does not assert that a dense-time path has a continuous lifetime-path extension. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup +namespace IsConservative + +noncomputable section + +variable {D alpha : Type*} [MeasurableSpace alpha] [StandardBorelSpace (Cemetery alpha)] + +/-- Every dense-time coordinate of the cemetery trajectory started from a live state has zero +cemetery mass when the original semigroup is conservative. -/ +theorem cemeteryDenseTimeTrajectory_map_eval_alive_delta + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (d : D) (x : alpha) : + ((denseTimeTrajectory P.cemeterySemigroup P.isConservative_cemeterySemigroup e iota).map + (fun path ↦ path d)) (Cemetery.alive x) {Cemetery.delta} = 0 := by + rw [denseTimeTrajectory_map_eval] + rw [cemeterySemigroup_apply, Kernel.cemeteryExtension_alive_singleton_delta] + rw [hP (iota d) x, tsub_self] + +end +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryExtension.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryExtension.lean new file mode 100644 index 0000000000..81d4a34638 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryExtension.lean @@ -0,0 +1,150 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +import Mathlib.Probability.Kernel.Composition.MapComap +import Mathlib.Topology.Constructions.SumProd + +/-! +# Conservative cemetery extension of a sub-Markov kernel + +This file adjoins an isolated cemetery state to a measurable state space and +extends one sub-Markov kernel to a Markov kernel. It deliberately makes no +claim about preservation of kernel composition or semigroup laws. +-/ + +open MeasureTheory +open ProbabilityTheory +open scoped ENNReal + +namespace MarkovProcess + +variable {α : Type*} + +/-- A state space with one additional isolated cemetery state. -/ +abbrev Cemetery (α : Type*) := α ⊕ Unit + +/-- Embed a live state into the cemetery extension. -/ +abbrev Cemetery.alive (x : α) : Cemetery α := Sum.inl x + +/-- The cemetery state. -/ +abbrev Cemetery.delta : Cemetery α := Sum.inr () + +/-- The added cemetery state is isolated in the inherited sum topology. -/ +theorem Cemetery.isOpen_singleton_delta [TopologicalSpace α] : + IsOpen ({Cemetery.delta} : Set (Cemetery α)) := by + simpa only [Cemetery.delta, Set.range_unique] using + (isOpen_range_inr : IsOpen (Set.range (Sum.inr : Unit → α ⊕ Unit))) + +namespace Kernel + +variable [MeasurableSpace α] + +/-- The conservative extension of a sub-Markov kernel obtained by sending its +missing mass to the cemetery state and making that state absorbing. -/ +noncomputable def cemeteryExtension (κ : ProbabilityTheory.Kernel α α) : + ProbabilityTheory.Kernel (Cemetery α) (Cemetery α) where + toFun := Sum.elim + (fun x ↦ Measure.map Cemetery.alive (κ x) + + (1 - κ x Set.univ) • Measure.dirac Cemetery.delta) + (fun _ ↦ Measure.dirac Cemetery.delta) + measurable' := measurable_fun_sum + (by + have h := + (ProbabilityTheory.Kernel.map κ Cemetery.alive).measurable.add + (((measurable_const : Measurable (fun _ : α => (1 : ℝ≥0∞))).sub + (κ.measurable_coe MeasurableSet.univ)).smul_measure + (Measure.dirac Cemetery.delta)) + simpa only [Function.comp_def, Sum.elim_inl, Pi.add_def, Pi.sub_apply, + ProbabilityTheory.Kernel.map_apply κ measurable_inl] using! + h) + measurable_const + +theorem cemeteryExtension_alive_apply (κ : ProbabilityTheory.Kernel α α) (x : α) : + cemeteryExtension κ (Cemetery.alive x) = + Measure.map Cemetery.alive (κ x) + + (1 - κ x Set.univ) • Measure.dirac Cemetery.delta := + by + rw [cemeteryExtension, ProbabilityTheory.Kernel.coe_mk] + rfl + +@[simp] +theorem cemeteryExtension_delta_apply (κ : ProbabilityTheory.Kernel α α) : + cemeteryExtension κ Cemetery.delta = Measure.dirac Cemetery.delta := + by + rw [cemeteryExtension, ProbabilityTheory.Kernel.coe_mk] + rfl + +theorem cemeteryExtension_alive_apply' (κ : ProbabilityTheory.Kernel α α) (x : α) + {s : Set (Cemetery α)} (hs : MeasurableSet s) : + cemeteryExtension κ (Cemetery.alive x) s = + κ x (Cemetery.alive ⁻¹' s) + + (1 - κ x Set.univ) * s.indicator 1 Cemetery.delta := by + rw [cemeteryExtension_alive_apply, Measure.add_apply, Measure.map_apply measurable_inl hs, + Measure.smul_apply, Measure.dirac_apply' _ hs] + rfl + +/-- On measurable sets of live states, the extension agrees exactly with the +original kernel. -/ +theorem cemeteryExtension_alive_image (κ : ProbabilityTheory.Kernel α α) (x : α) + {s : Set α} (hs : MeasurableSet s) : + cemeteryExtension κ (Cemetery.alive x) (Cemetery.alive '' s) = κ x s := by + change cemeteryExtension κ (Cemetery.alive x) (Sum.inl '' s) = κ x s + rw [cemeteryExtension_alive_apply' κ x hs.inl_image] + rw [Sum.inl_injective.preimage_image] + have hnot : Cemetery.delta ∉ Sum.inl '' s := by + rintro ⟨y, -, hy⟩ + exact Sum.inl_ne_inr hy + rw [Set.indicator_of_notMem hnot, mul_zero, add_zero] + +/-- The mass assigned to the cemetery singleton is exactly the missing mass. -/ +theorem cemeteryExtension_alive_singleton_delta (κ : ProbabilityTheory.Kernel α α) (x : α) : + cemeteryExtension κ (Cemetery.alive x) {Cemetery.delta} = 1 - κ x Set.univ := by + have hdelta : MeasurableSet ({Cemetery.delta} : Set (Cemetery α)) := by + simpa only [Set.range_unique] using + (measurableSet_range_inr : MeasurableSet (Set.range (Sum.inr : Unit → α ⊕ Unit))) + rw [cemeteryExtension_alive_apply' κ x hdelta] + have hpre : Cemetery.alive ⁻¹' ({Cemetery.delta} : Set (Cemetery α)) = ∅ := by + ext y + simp only [Set.mem_preimage, Set.mem_singleton_iff, Sum.inl_ne_inr, Set.notMem_empty] + rw [hpre, measure_empty] + simp only [Set.indicator_of_mem, Set.mem_singleton_iff, Pi.one_apply, mul_one, zero_add] + +@[simp] +theorem cemeteryExtension_delta_apply' (κ : ProbabilityTheory.Kernel α α) + {s : Set (Cemetery α)} (hs : MeasurableSet s) : + cemeteryExtension κ Cemetery.delta s = s.indicator 1 Cemetery.delta := by + rw [cemeteryExtension_delta_apply, Measure.dirac_apply' _ hs] + +theorem cemeteryExtension_alive_univ (κ : ProbabilityTheory.Kernel α α) + (hκ : IsSubMarkovKernel κ) (x : α) : + cemeteryExtension κ (Cemetery.alive x) Set.univ = 1 := by + rw [cemeteryExtension_alive_apply' κ x MeasurableSet.univ] + simp only [Set.preimage_univ, Set.indicator_of_mem, Set.mem_univ, Pi.one_apply, mul_one] + rw [add_comm] + exact tsub_add_cancel_of_le (hκ x) + +@[simp] +theorem cemeteryExtension_delta_univ (κ : ProbabilityTheory.Kernel α α) : + cemeteryExtension κ Cemetery.delta Set.univ = 1 := by + rw [cemeteryExtension_delta_apply' κ MeasurableSet.univ] + simp only [Set.indicator_of_mem, Set.mem_univ, Pi.one_apply] + +/-- The conservative cemetery extension is a Markov kernel. -/ +theorem isMarkovKernel_cemeteryExtension (κ : ProbabilityTheory.Kernel α α) + (hκ : IsSubMarkovKernel κ) : IsMarkovKernel (cemeteryExtension κ) := by + refine ⟨fun z ↦ ⟨?_⟩⟩ + cases z with + | inl x => exact cemeteryExtension_alive_univ κ hκ x + | inr u => cases u; exact cemeteryExtension_delta_univ κ + +/-- The cemetery state is absorbing under the conservative extension. -/ +theorem cemeteryExtension_absorbing (κ : ProbabilityTheory.Kernel α α) : + cemeteryExtension κ Cemetery.delta = Measure.dirac Cemetery.delta := + cemeteryExtension_delta_apply κ + +end Kernel + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeterySemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeterySemigroup.lean new file mode 100644 index 0000000000..c1a5181487 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeterySemigroup.lean @@ -0,0 +1,206 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup + +/-! +# Cemetery extensions of sub-Markov kernel semigroups + +This file shows that conservative cemetery extension preserves the identity +kernel and composition of sub-Markov kernels. Consequently, applying the +extension at every time turns any sub-Markov kernel semigroup into a +conservative semigroup on the cemetery state space. +-/ + +open MeasureTheory +open ProbabilityTheory +open scoped ENNReal + +noncomputable section + +namespace MarkovProcess + +variable {α : Type*} [MeasurableSpace α] + +namespace Kernel + +/-- Conservative cemetery extension preserves the identity kernel. -/ +theorem cemeteryExtension_id : + cemeteryExtension (Kernel.id : Kernel α α) = Kernel.id := by + ext z s hs + cases z with + | inl x => + rw [cemeteryExtension_alive_apply' _ x hs, Kernel.id_apply, + Measure.dirac_apply' _ (measurable_inl hs)] + simp only [Measure.dirac_apply' _ MeasurableSet.univ, Set.mem_univ, + Set.indicator_of_mem, Pi.one_apply, tsub_self, zero_mul, add_zero, + ] + rw [Kernel.id_apply, Measure.dirac_apply' _ hs] + rfl + | inr u => + cases u + rw [cemeteryExtension_delta_apply' _ hs, Kernel.id_apply, + Measure.dirac_apply' _ hs] + +/-- On live measurable sets, cemetery extension preserves kernel composition. -/ +theorem cemeteryExtension_comp_alive_image (η κ : Kernel α α) + (x : α) {s : Set α} (hs : MeasurableSet s) : + cemeteryExtension (η.comp κ) (Cemetery.alive x) (Cemetery.alive '' s) = + ((cemeteryExtension η).comp (cemeteryExtension κ)) + (Cemetery.alive x) (Cemetery.alive '' s) := by + rw [cemeteryExtension_alive_image _ x hs, Kernel.comp_apply' _ _ _ hs.inl_image, + cemeteryExtension_alive_apply, lintegral_add_measure, + lintegral_map ((cemeteryExtension η).measurable_coe hs.inl_image) measurable_inl] + have hnot : Cemetery.delta ∉ Cemetery.alive '' s := by + rintro ⟨a, -, h⟩ + exact Sum.inl_ne_inr h + simp only [cemeteryExtension_alive_image _ _ hs, lintegral_smul_measure] + rw [MeasureTheory.lintegral_dirac' Cemetery.delta + ((cemeteryExtension η).measurable_coe hs.inl_image)] + rw [cemeteryExtension_delta_apply' _ hs.inl_image, Set.indicator_of_notMem hnot, + smul_zero, add_zero] + rw [Kernel.comp_apply' _ _ _ hs] + +/-- Conservative cemetery extension preserves composition of sub-Markov kernels. -/ +theorem cemeteryExtension_comp (η κ : Kernel α α) + (hη : IsSubMarkovKernel η) (hκ : IsSubMarkovKernel κ) : + cemeteryExtension (η.comp κ) = + (cemeteryExtension η).comp (cemeteryExtension κ) := by + have hηκ : IsSubMarkovKernel (η.comp κ) := hη.comp hκ + have hleft : IsMarkovKernel (cemeteryExtension (η.comp κ)) := + isMarkovKernel_cemeteryExtension _ hηκ + have hright : IsMarkovKernel ((cemeteryExtension η).comp (cemeteryExtension κ)) := by + let : IsMarkovKernel (cemeteryExtension η) := isMarkovKernel_cemeteryExtension _ hη + let : IsMarkovKernel (cemeteryExtension κ) := isMarkovKernel_cemeteryExtension _ hκ + infer_instance + ext z u hu + cases z with + | inr v => + cases v + rw [cemeteryExtension_delta_apply' _ hu, Kernel.comp_apply' _ _ _ hu, + cemeteryExtension_delta_apply, MeasureTheory.lintegral_dirac', + cemeteryExtension_delta_apply' _ hu] + exact (cemeteryExtension η).measurable_coe hu + | inl x => + let live : Set (Cemetery α) := Cemetery.alive '' (Cemetery.alive ⁻¹' u) + have hlive : MeasurableSet live := (measurable_inl hu).inl_image + have hlive_eq : live = u \ {Cemetery.delta} := by + ext y + cases y with + | inl a => + constructor + · rintro ⟨b, hb, hba⟩ + injection hba with hba + subst b + exact ⟨hb, Sum.inl_ne_inr⟩ + · rintro ⟨ha, -⟩ + exact ⟨a, ha, rfl⟩ + | inr v => + cases v + simp only [live, Cemetery.alive, Cemetery.delta, Set.mem_image, + Set.mem_preimage, Set.mem_sdiff, Set.mem_singleton_iff, + not_true_eq_false, and_false, Sum.inl_ne_inr, exists_false] + have hlive_agree : + cemeteryExtension (η.comp κ) (Cemetery.alive x) live = + ((cemeteryExtension η).comp (cemeteryExtension κ)) + (Cemetery.alive x) live := by + exact cemeteryExtension_comp_alive_image η κ x (measurable_inl hu) + by_cases hδ : Cemetery.delta ∈ u + · have hu_union : u = live ∪ {Cemetery.delta} := by + rw [hlive_eq] + exact (Set.sdiff_union_of_subset (Set.singleton_subset_iff.mpr hδ)).symm + have hdisj : Disjoint live ({Cemetery.delta} : Set (Cemetery α)) := by + rw [hlive_eq] + exact Set.disjoint_sdiff_left + have hdelta : MeasurableSet ({Cemetery.delta} : Set (Cemetery α)) := by + simpa only [Set.range_unique] using + (measurableSet_range_inr : MeasurableSet (Set.range (Sum.inr : Unit → α ⊕ Unit))) + rw [hu_union, measure_union hdisj hdelta, + measure_union hdisj hdelta, hlive_agree] + congr 1 + let allLive : Set (Cemetery α) := Cemetery.alive '' (Set.univ : Set α) + have hall : + cemeteryExtension (η.comp κ) (Cemetery.alive x) allLive = + ((cemeteryExtension η).comp (cemeteryExtension κ)) + (Cemetery.alive x) allLive := + cemeteryExtension_comp_alive_image η κ x MeasurableSet.univ + have hcomp : allLiveᶜ = ({Cemetery.delta} : Set (Cemetery α)) := by + ext y + cases y with + | inl a => + simp only [allLive, Cemetery.alive, Cemetery.delta, Set.mem_compl_iff, + Set.mem_image, Set.mem_univ, true_and, Sum.inl.injEq, + Set.mem_singleton_iff, Sum.inl_ne_inr, iff_false] + exact fun h ↦ h ⟨a, rfl⟩ + | inr v => + cases v + simp only [allLive, Cemetery.alive, Cemetery.delta, Set.mem_compl_iff, + Set.mem_image, Set.mem_univ, true_and, Sum.inl_ne_inr, + Set.mem_singleton_iff, not_exists] + exact iff_true_intro fun _ ↦ id + have hall_meas : MeasurableSet allLive := MeasurableSet.univ.inl_image + rw [← hcomp, measure_compl hall_meas (measure_ne_top _ _), + measure_compl hall_meas (measure_ne_top _ _), + hleft.isProbabilityMeasure (Cemetery.alive x) |>.measure_univ, + hright.isProbabilityMeasure (Cemetery.alive x) |>.measure_univ, hall] + · have hu_eq : u = live := by + rw [hlive_eq] + ext y + constructor + · intro hy + exact ⟨hy, fun hyδ ↦ hδ (hyδ ▸ hy)⟩ + · exact fun hy ↦ hy.1 + rw [hu_eq, hlive_agree] + +end Kernel + +namespace SubMarkovKernelSemigroup + +/-- The conservative cemetery extension of a sub-Markov kernel semigroup. -/ +noncomputable def cemeterySemigroup (P : SubMarkovKernelSemigroup α) : + SubMarkovKernelSemigroup (Cemetery α) where + kernel t := Kernel.cemeteryExtension (P t) + measurable_kernel := by + let e : NNReal × Cemetery α ≃ᵐ (NNReal × α) ⊕ (NNReal × Unit) := + MeasurableEquiv.prodSumDistrib _ _ _ + apply e.symm.measurable_comp_iff.1 + apply measurable_fun_sum + · exact + (((Measure.measurable_map Cemetery.alive measurable_inl).comp P.measurable_toMeasure).add + ((measurable_const.sub (P.measurable_measure MeasurableSet.univ)).smul_measure + (Measure.dirac Cemetery.delta))) + · exact measurable_const + kernel_zero := by rw [P.zero, Kernel.cemeteryExtension_id] + kernel_add s t := by + rw [P.add] + exact Kernel.cemeteryExtension_comp (P t) (P s) (P.isSubMarkovKernel t) + (P.isSubMarkovKernel s) + isSubMarkovKernel t := by + let : IsMarkovKernel (Kernel.cemeteryExtension (P t)) := + Kernel.isMarkovKernel_cemeteryExtension (P t) (P.isSubMarkovKernel t) + exact IsSubMarkovKernel.of_isMarkovKernel _ + +variable (P : SubMarkovKernelSemigroup α) + +@[simp] +theorem cemeterySemigroup_apply (t : NNReal) : + cemeterySemigroup P t = Kernel.cemeteryExtension (P t) := + by rw [cemeterySemigroup] + +/-- The cemetery extension semigroup is conservative. -/ +theorem isConservative_cemeterySemigroup : (cemeterySemigroup P).IsConservative := by + intro t z + rw [cemeterySemigroup_apply] + exact (Kernel.isMarkovKernel_cemeteryExtension (P t) (P.isSubMarkovKernel t)).isProbabilityMeasure z |>.measure_univ + +/-- The cemetery state is absorbing at every time in the extension semigroup. -/ +theorem cemeterySemigroup_absorbing (t : NNReal) : + cemeterySemigroup P t Cemetery.delta = Measure.dirac Cemetery.delta := + by rw [cemeterySemigroup_apply]; exact Kernel.cemeteryExtension_absorbing (P t) + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/ConditionalKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/ConditionalKernel.lean new file mode 100644 index 0000000000..39247b75f1 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/ConditionalKernel.lean @@ -0,0 +1,139 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel +import Mathlib.Probability.Kernel.Disintegration.StandardBorel + +/-! +# Conditional kernels for finite dense-time histories + +This file augments finite prefix laws by their starting point and disintegrates the joint law of +a prefix and its next observation. It makes no infinite-process or path-regularity claim. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +noncomputable section + +variable {D α : Type*} [MeasurableSpace α] + +/-- The law of a finite history, including the deterministic starting point. -/ +def augmentedPrefixKernel (P : SubMarkovKernelSemigroup α) (e : ℕ ≃ D) + (ι : D ↪ NNReal) (n : ℕ) : Kernel α (DenseTimeHistory α n) := + Kernel.mapOfMeasurable + (Kernel.id ×ₖ denseTimePrefixKernel P e ι n) + (DenseTimeHistory.historyEquiv n).symm + (DenseTimeHistory.historyEquiv n).symm.measurable + +/-- Mapping an augmented history back to its two components recovers its defining product law. -/ +theorem augmentedPrefixKernel_map_historyEquiv (P : SubMarkovKernelSemigroup α) + (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + (augmentedPrefixKernel P e ι n).map (DenseTimeHistory.historyEquiv n) = + Kernel.id ×ₖ denseTimePrefixKernel P e ι n := by + rw [augmentedPrefixKernel, Kernel.mapOfMeasurable_eq_map, ← Kernel.map_comp_right] + · have hcomp : + (DenseTimeHistory.historyEquiv n : DenseTimeHistory α n → + α × (Fin n → α)) ∘ + (DenseTimeHistory.historyEquiv n).symm = id := by + funext z + exact MeasurableEquiv.apply_symm_apply _ z + rw [hcomp, Kernel.map_id] + · exact (DenseTimeHistory.historyEquiv n).symm.measurable + · exact (DenseTimeHistory.historyEquiv n).measurable + +/-- The joint law of an `n`-prefix and the next enumerated observation. -/ +def nextObservationJoint (P : SubMarkovKernelSemigroup α) (e : ℕ ≃ D) + (ι : D ↪ NNReal) (n : ℕ) : Kernel α ((Fin n → α) × α) := + Kernel.mapOfMeasurable (denseTimePrefixKernel P e ι (n + 1)) + (DenseTimeHistory.splitLast n) (DenseTimeHistory.splitLast n).measurable + +namespace IsConservative + +variable [StandardBorelSpace α] [Nonempty α] + +omit [StandardBorelSpace α] [Nonempty α] in +/-- Augmented finite-history laws are Markov kernels under conservativity. -/ +theorem isMarkovKernel_augmentedPrefixKernel (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + IsMarkovKernel (augmentedPrefixKernel P e ι n) := by + rw [augmentedPrefixKernel, Kernel.mapOfMeasurable_eq_map] + let : IsMarkovKernel (denseTimePrefixKernel P e ι n) := + hP.isMarkovKernel_denseTimePrefixKernel P e ι n + exact Kernel.IsMarkovKernel.map _ (DenseTimeHistory.historyEquiv n).symm.measurable + +omit [StandardBorelSpace α] [Nonempty α] in +/-- The first marginal of the next-observation joint law is the preceding prefix law. -/ +theorem nextObservationJoint_fst (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + (nextObservationJoint P e ι n).fst = denseTimePrefixKernel P e ι n := by + rw [nextObservationJoint, Kernel.mapOfMeasurable_eq_map, Kernel.fst_eq, + ← Kernel.map_comp_right] + · change + (denseTimePrefixKernel P e ι n.succ).map + (Prod.fst ∘ DenseTimeHistory.splitLast n) = + denseTimePrefixKernel P e ι n + calc + (denseTimePrefixKernel P e ι n.succ).map + (Prod.fst ∘ DenseTimeHistory.splitLast n) = + (denseTimePrefixKernel P e ι n.succ).map + (FiniteOrderedTimes.restrictPath + (Fin.castLEOrderEmb (Nat.le_succ n))) := by + congr 1 + funext path i + exact DenseTimeHistory.splitLast_fst_apply n path i + _ = denseTimePrefixKernel P e ι n := + (hP.denseTimePrefixKernel_map_restrictPath P e ι (Nat.le_succ n)).symm + · exact (DenseTimeHistory.splitLast n).measurable + · exact measurable_fst + +/-- A regular conditional law of the next observation given the start and preceding prefix. -/ +def observationCondKernel (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : Kernel (α × (Fin n → α)) α := by + letI : IsMarkovKernel (nextObservationJoint P e ι n) := by + rw [nextObservationJoint, Kernel.mapOfMeasurable_eq_map] + let : IsMarkovKernel (denseTimePrefixKernel P e ι (n + 1)) := + hP.isMarkovKernel_denseTimePrefixKernel P e ι (n + 1) + exact Kernel.IsMarkovKernel.map _ (DenseTimeHistory.splitLast n).measurable + exact (nextObservationJoint P e ι n).condKernel + +/-- The conditional next-observation law is Markov. -/ +theorem isMarkovKernel_observationCondKernel (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + IsMarkovKernel (observationCondKernel P hP e ι n) := by + rw [observationCondKernel] + infer_instance + +/-- Disintegration exactly reconstructs the next-observation joint law. -/ +theorem compProd_observationCondKernel (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + denseTimePrefixKernel P e ι n ⊗ₖ observationCondKernel P hP e ι n = + nextObservationJoint P e ι n := by + rw [← nextObservationJoint_fst P hP e ι n] + rw [observationCondKernel] + exact Kernel.disintegrate _ _ + +/-- The conditional next-observation law, viewed as a kernel on finite histories. -/ +def denseStep (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : Kernel (DenseTimeHistory α n) α := + Kernel.comap (observationCondKernel P hP e ι n) + (DenseTimeHistory.historyEquiv n) (DenseTimeHistory.historyEquiv n).measurable + +/-- The finite-history next-observation kernel is Markov. -/ +theorem isMarkovKernel_denseStep (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + IsMarkovKernel (denseStep P hP e ι n) := by + rw [denseStep] + let : IsMarkovKernel (observationCondKernel P hP e ι n) := + isMarkovKernel_observationCondKernel P hP e ι n + infer_instance + +end IsConservative +end +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean new file mode 100644 index 0000000000..14d24457ff --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean @@ -0,0 +1,145 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +import Mathlib.MeasureTheory.Integral.CompactlySupported + +/-! +# Compact-test transport from physical to dense-time coordinates + +This file identifies finite paths labelled by physical rational times with paths labelled by the +corresponding dense times. It pulls compactly supported tests back across this homeomorphism and +rewrites integrals against mapped finite-set kernels. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal CompactlySupported + +namespace MarkovProcess.DenseTimePath + +open SubMarkovKernelSemigroup + +private theorem stronglyMeasurable_coordinatePolynomial + {I alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + (terms : List (PiContinuousMap.CoordinateProductTerm I alpha)) : + StronglyMeasurable (PiContinuousMap.coordinatePolynomial terms) := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil] + exact stronglyMeasurable_const + | cons term terms ih => + rw [PiContinuousMap.coordinatePolynomial_cons] + apply StronglyMeasurable.add _ ih + have hprod : StronglyMeasurable (fun path : I → alpha ↦ + (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by + induction term.factors with + | nil => exact stronglyMeasurable_const + | cons p factors ihFactors => + simp only [List.map_cons, List.prod_cons] + exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul + ihFactors + rw [show (term.toContinuousMap : (I → alpha) → ℝ) = fun path ↦ + term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by + funext path + exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] + exact hprod.const_mul term.coefficient + +private theorem stronglyMeasurable_compactlySupported_pi + {I alpha : Type*} [Fintype I] [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [T3Space alpha] [LocallyCompactSpace alpha] + (f : C_c(I → alpha, ℝ)) : StronglyMeasurable f := by + have hexists (m : ℕ) : + ∃ terms : List (PiContinuousMap.CoordinateProductTerm I alpha), + ∀ x, ‖PiContinuousMap.coordinatePolynomial terms x - f x‖ < + 1 / ((m : ℝ) + 1) := by + have hpositive : 0 < 1 / ((m : ℝ) + 1) := by positivity + obtain ⟨terms, hterms⟩ := + PiContinuousMap.exists_coordinateProductTerms_near_compactlySupported f hpositive + exact ⟨terms, fun x ↦ by + rw [PiContinuousMap.coordinatePolynomial_apply] + exact hterms x⟩ + choose terms hterms using hexists + apply stronglyMeasurable_of_tendsto Filter.atTop + (fun m ↦ stronglyMeasurable_coordinatePolynomial (terms m)) + rw [tendsto_pi_nhds] + intro x + rw [Metric.tendsto_nhds] + intro epsilon hepsilon + have hscalar : Filter.Tendsto (fun m : ℕ ↦ (1 : ℝ) / ((m : ℝ) + 1)) Filter.atTop + (nhds 0) := tendsto_one_div_add_atTop_nhds_zero_nat + rw [Metric.tendsto_nhds] at hscalar + filter_upwards [hscalar epsilon hepsilon] with m hm + rw [Real.dist_eq, sub_zero, abs_of_pos (by positivity)] at hm + exact (hterms m x).trans_le hm.le + +/-- Reindexing finite paths from physical rational times to dense-time labels is a +homeomorphism. -/ +noncomputable def pullbackPhysicalSetHomeomorph + {alpha : Type*} [TopologicalSpace alpha] (J : Finset DenseTime) : + (denseTimePhysicalSet J → alpha) ≃ₜ (J → alpha) := + Homeomorph.piCongrLeft (Y := fun _ : J ↦ alpha) (DenseTime.physicalSetEquiv J).symm + +/-- The physical-coordinate homeomorphism has underlying function `pullbackPhysicalSet`. -/ +@[simp] +theorem pullbackPhysicalSetHomeomorph_apply + {alpha : Type*} [TopologicalSpace alpha] (J : Finset DenseTime) + (path : denseTimePhysicalSet J → alpha) : + pullbackPhysicalSetHomeomorph J path = pullbackPhysicalSet J path := by + ext t + change (Equiv.piCongrLeft (fun _ : J ↦ alpha) + (DenseTime.physicalSetEquiv J).symm path) t = _ + rw [Equiv.piCongrLeft_apply] + simp only [pullbackPhysicalSet] + rw [eqRec_eq_cast, cast_eq] + rfl + +/-- Pull a compactly supported test on dense-time labels back to physical-time labels. -/ +noncomputable def pullbackPhysicalSetCompactTest + {alpha : Type*} [TopologicalSpace alpha] [T2Space alpha] + (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) : + C_c(denseTimePhysicalSet J → alpha, ℝ) := + f.comp (pullbackPhysicalSetHomeomorph J).toCocompactMap + +/-- Evaluation of a compact test pulled back to physical-time labels. -/ +@[simp] +theorem pullbackPhysicalSetCompactTest_apply + {alpha : Type*} [TopologicalSpace alpha] [T2Space alpha] + (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) + (path : denseTimePhysicalSet J → alpha) : + pullbackPhysicalSetCompactTest J f path = f (pullbackPhysicalSet J path) := by + rw [pullbackPhysicalSetCompactTest] + exact congr_arg f (pullbackPhysicalSetHomeomorph_apply J path) + +/-- Integration after physical-to-dense reindexing equals integration of the pulled-back compact +test. -/ +theorem integral_map_pullbackPhysicalSet + {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) + (mu : Measure (denseTimePhysicalSet J → alpha)) : + ∫ y, f y ∂mu.map (pullbackPhysicalSet J) = + ∫ path, pullbackPhysicalSetCompactTest J f path ∂mu := by + rw [integral_map (measurable_pullbackPhysicalSet J).aemeasurable + (stronglyMeasurable_compactlySupported_pi f).aestronglyMeasurable] + apply integral_congr_ae + exact ae_of_all _ fun path ↦ (pullbackPhysicalSetCompactTest_apply J f path).symm + +/-- A compact-test integral against a physically indexed finite-set kernel mapped back to dense +labels is the pulled-back integral against the original finite-set kernel. -/ +theorem integral_map_finiteSetKernel_pullbackPhysicalSet + {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + (P : SubMarkovKernelSemigroup alpha) (J : Finset DenseTime) + (f : C_c(J → alpha, ℝ)) (x : alpha) : + ∫ y, f y ∂(finiteSetKernel P (denseTimePhysicalSet J)).map + (pullbackPhysicalSet J) x = + ∫ path, pullbackPhysicalSetCompactTest J f path + ∂finiteSetKernel P (denseTimePhysicalSet J) x := by + rw [Kernel.map_apply _ (measurable_pullbackPhysicalSet J)] + exact integral_map_pullbackPhysicalSet J f + (finiteSetKernel P (denseTimePhysicalSet J) x) + +end MarkovProcess.DenseTimePath diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalReindex.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalReindex.lean new file mode 100644 index 0000000000..f205893676 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalReindex.lean @@ -0,0 +1,86 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals + +/-! +# Reindexing finite rational coordinates by physical time + +A finite set of dense rational times is canonically equivalent to its image in `NNReal`. This +file records the induced measurable path reindexing and its compatibility with continuous-path +evaluation. No probability-law or Markov claim is made. +-/ + +namespace MarkovProcess + +noncomputable section + +namespace DenseTime + +open SubMarkovKernelSemigroup + +/-- Casting identifies a finite dense-time set with its image in physical nonnegative-real time. -/ +def physicalSetEquiv (I : Finset DenseTime) : I ≃ denseTimePhysicalSet I := + Equiv.ofBijective + (fun t ↦ ⟨castOrderEmbedding t, by + rw [denseTimePhysicalSet, Finset.mem_map] + exact ⟨t, t.property, rfl⟩⟩) + ⟨by + intro t u h + apply Subtype.ext + exact castOrderEmbedding.injective (congrArg Subtype.val h), + by + intro t + have ht := t.property + change t.val ∈ I.map castOrderEmbedding.toEmbedding at ht + rw [Finset.mem_map] at ht + obtain ⟨r, hrI, hrt⟩ := ht + exact ⟨⟨r, hrI⟩, Subtype.ext hrt⟩⟩ + +@[simp] +theorem physicalSetEquiv_apply (I : Finset DenseTime) (t : I) : + (physicalSetEquiv I t : NNReal) = castOrderEmbedding t := rfl + +end DenseTime + +namespace DenseTimePath + +open SubMarkovKernelSemigroup + +variable {alpha : Type*} + +/-- Reindex a finite path labelled by physical rational times back to dense-time labels. -/ +def pullbackPhysicalSet (I : Finset DenseTime) + (path : denseTimePhysicalSet I → alpha) : I → alpha := + fun t ↦ path (DenseTime.physicalSetEquiv I t) + +@[simp] +theorem pullbackPhysicalSet_apply (I : Finset DenseTime) + (path : denseTimePhysicalSet I → alpha) (t : I) : + pullbackPhysicalSet I path t = path (DenseTime.physicalSetEquiv I t) := rfl + +variable [MeasurableSpace alpha] + +/-- Reindexing a finite physical-time path by its dense labels is measurable. -/ +theorem measurable_pullbackPhysicalSet (I : Finset DenseTime) : + Measurable (pullbackPhysicalSet (alpha := alpha) I) := by + rw [measurable_pi_iff] + intro t + exact measurable_pi_apply (DenseTime.physicalSetEquiv I t) + +omit [MeasurableSpace alpha] in +/-- Evaluating a continuous path on physical rational times and reindexing gives restriction of +its dense-time path. -/ +theorem pullbackPhysicalSet_evaluation (I : Finset DenseTime) + [TopologicalSpace alpha] (omega : ContinuousPath alpha) : + pullbackPhysicalSet I + (fun t : denseTimePhysicalSet I ↦ omega t) = + I.restrict (ContinuousPath.denseRestriction omega) := by + funext t + rfl + +end DenseTimePath +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean new file mode 100644 index 0000000000..2cf8eb84ca --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean @@ -0,0 +1,119 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily + +/-! +# Kernels on finite prefixes of a countable time enumeration + +This file constructs the finite-dimensional kernel on the first `n` points of an arbitrary +enumeration, with coordinates retained in enumeration order. The enumeration need not respect +the order of physical time. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +noncomputable section + +variable {D α : Type*} [MeasurableSpace α] + +/-- The physical times occurring in the first `n` positions of an enumeration. -/ +def denseTimePhysicalPrefix (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : Finset NNReal := + (CountableEnumeration.prefix e n).map ι + +private theorem denseTimePhysicalPrefix_mono (e : ℕ ≃ D) (ι : D ↪ NNReal) : + Monotone (denseTimePhysicalPrefix e ι) := by + intro m n hmn t ht + rw [denseTimePhysicalPrefix, Finset.mem_map] at ht ⊢ + obtain ⟨d, hd, rfl⟩ := ht + exact ⟨d, CountableEnumeration.prefix_mono e hmn hd, rfl⟩ + +private theorem denseTime_mem_physicalPrefix (e : ℕ ≃ D) (ι : D ↪ NNReal) + (n : ℕ) (i : Fin n) : ι (e i) ∈ denseTimePhysicalPrefix e ι n := by + rw [denseTimePhysicalPrefix, Finset.mem_map] + exact ⟨e i, by + rw [CountableEnumeration.mem_prefix_iff, e.symm_apply_apply] + exact i.isLt, rfl⟩ + +/-- Reindex a path on the physical prefix by its enumeration positions. -/ +def denseTimePrefixReindex (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) + (path : denseTimePhysicalPrefix e ι n → α) : Fin n → α := + fun i ↦ path ⟨ι (e i), denseTime_mem_physicalPrefix e ι n i⟩ + +/-- Reindexing a physical-prefix path by enumeration positions is measurable. -/ +theorem measurable_denseTimePrefixReindex (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + Measurable (denseTimePrefixReindex (α := α) e ι n) := + measurable_pi_iff.mpr fun i ↦ measurable_pi_apply + (⟨ι (e i), denseTime_mem_physicalPrefix e ι n i⟩ : denseTimePhysicalPrefix e ι n) + +/-- The finite-dimensional kernel on the first `n` enumerated physical times, with coordinates +in enumeration order. -/ +def denseTimePrefixKernel (P : SubMarkovKernelSemigroup α) (e : ℕ ≃ D) + (ι : D ↪ NNReal) (n : ℕ) : Kernel α (Fin n → α) := + Kernel.mapOfMeasurable (finiteSetKernel P (denseTimePhysicalPrefix e ι n)) + (denseTimePrefixReindex e ι n) (measurable_denseTimePrefixReindex e ι n) + +/-- The enumeration-prefix kernel agrees with the ordinary kernel map. -/ +theorem denseTimePrefixKernel_eq_map (P : SubMarkovKernelSemigroup α) (e : ℕ ≃ D) + (ι : D ↪ NNReal) (n : ℕ) : + denseTimePrefixKernel P e ι n = + (finiteSetKernel P (denseTimePhysicalPrefix e ι n)).map + (denseTimePrefixReindex e ι n) := + Kernel.mapOfMeasurable_eq_map _ (measurable_denseTimePrefixReindex e ι n) + +omit [MeasurableSpace α] in +private theorem denseTimePrefixReindex_restrict {m n : ℕ} (e : ℕ ≃ D) + (ι : D ↪ NNReal) (h : m ≤ n) : + denseTimePrefixReindex (α := α) e ι m ∘ + Finset.restrict₂ (π := fun _ ↦ α) (denseTimePhysicalPrefix_mono e ι h) = + FiniteOrderedTimes.restrictPath (Fin.castLEOrderEmb h) ∘ + denseTimePrefixReindex e ι n := by + funext path i + rfl + +namespace IsConservative + +/-- Under conservativity, each enumeration-prefix kernel is a Markov kernel. -/ +theorem isMarkovKernel_denseTimePrefixKernel (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + IsMarkovKernel (denseTimePrefixKernel P e ι n) := by + rw [denseTimePrefixKernel_eq_map] + let : IsMarkovKernel (finiteSetKernel P (denseTimePhysicalPrefix e ι n)) := + hP.isMarkovKernel_finiteSetKernel P _ + exact Kernel.IsMarkovKernel.map _ (measurable_denseTimePrefixReindex e ι n) + +/-- Under conservativity, an enumeration-prefix kernel gives a probability measure at every +starting state. -/ +theorem isProbabilityMeasure_denseTimePrefixKernel (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) (x : α) : + IsProbabilityMeasure (denseTimePrefixKernel P e ι n x) := by + let : IsMarkovKernel (denseTimePrefixKernel P e ι n) := + hP.isMarkovKernel_denseTimePrefixKernel P e ι n + exact IsMarkovKernel.isProbabilityMeasure x + +/-- Prefix kernels are exactly consistent under restriction to an earlier prefix. -/ +theorem denseTimePrefixKernel_map_restrictPath (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) {m n : ℕ} (h : m ≤ n) : + denseTimePrefixKernel P e ι m = + (denseTimePrefixKernel P e ι n).map + (FiniteOrderedTimes.restrictPath (Fin.castLEOrderEmb h)) := by + rw [denseTimePrefixKernel_eq_map, denseTimePrefixKernel_eq_map, + hP.finiteSetKernel_map_restrict₂ P (denseTimePhysicalPrefix_mono e ι h), + ← Kernel.map_comp_right, ← Kernel.map_comp_right] + · rw [denseTimePrefixReindex_restrict e ι h] + · exact measurable_denseTimePrefixReindex e ι n + · exact FiniteOrderedTimes.measurable_restrictPath (Fin.castLEOrderEmb h) + · exact Finset.measurable_restrict₂ (X := fun _ ↦ α) + (denseTimePhysicalPrefix_mono e ι h) + · exact measurable_denseTimePrefixReindex e ι m + +end IsConservative +end +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean new file mode 100644 index 0000000000..bedf7cb1d8 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean @@ -0,0 +1,187 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel +import Mathlib.Probability.Kernel.Composition.Lemmas + +/-! +# One-step recursion for finite dense-time histories + +This file identifies the result of adjoining one conditionally sampled observation to an +augmented finite history. It makes no infinite-process or path-regularity claim. +-/ + +open MeasureTheory ProbabilityTheory + +namespace ProbabilityTheory.Kernel + +private theorem step_transport {X H Z Y T : Type*} + [MeasurableSpace X] [MeasurableSpace H] [MeasurableSpace Z] + [MeasurableSpace Y] [MeasurableSpace T] + (κ : Kernel X Z) [IsSFiniteKernel κ] + (η : Kernel Z Y) [IsSFiniteKernel η] (E : H ≃ᵐ Z) + (g : H × Y → T) (hg : Measurable g) (q : Z × Y → T) + (hcompat : g ∘ Prod.map E.symm id = q) : + (((Kernel.id ×ₖ η.comap E E.measurable) ∘ₖ κ.map E.symm).map g) = + ((Kernel.id ×ₖ η) ∘ₖ κ).map q := by + rw [Kernel.comp_map κ (Kernel.id ×ₖ η.comap E E.measurable) E.symm.measurable] + rw [Kernel.comap_prod] + rw [Kernel.id_comap] + rw [← Kernel.id_map] + rw [← Kernel.comap_comp_right] + have hcomap : η.comap ((E : H → Z) ∘ E.symm) + (E.measurable.comp E.symm.measurable) = η := by + ext z + rw [Kernel.comap_apply] + change η (E (E.symm z)) _ = η z _ + rw [E.apply_symm_apply] + rw [hcomap] + rw [← Kernel.map_id' η] + rw [Kernel.map_prod_map] + rw [← Kernel.map_comp] + rw [← Kernel.map_comp_right] + rw [Kernel.map_id'] + change (Kernel.id ×ₖ η ∘ₖ κ).map (g ∘ Prod.map E.symm id) = _ + rw [hcompat] + all_goals first | exact hg | fun_prop + +private theorem prod_comp_prod_map_prodAssoc {X A B : Type*} + [MeasurableSpace X] [MeasurableSpace A] [MeasurableSpace B] + (κ : Kernel X A) [IsSFiniteKernel κ] + (η : Kernel (X × A) B) [IsSFiniteKernel η] : + (((Kernel.id ×ₖ η) ∘ₖ (Kernel.id ×ₖ κ)).map MeasurableEquiv.prodAssoc) = + Kernel.id ×ₖ (κ ⊗ₖ η) := by + ext x s hs + rw [Kernel.map_apply' _ MeasurableEquiv.prodAssoc.measurable _ hs, Kernel.comp_apply] + rw [← Measure.compProd_eq_comp_prod] + have hfirst : (Kernel.id ×ₖ κ) x = Measure.dirac x ⊗ₘ κ := by + rw [Measure.compProd_eq_comp_prod] + exact (Measure.dirac_bind (Kernel.measurable (Kernel.id ×ₖ κ)) x).symm + rw [hfirst] + rw [← Measure.map_apply MeasurableEquiv.prodAssoc.measurable hs] + rw [Measure.compProd_assoc'] + have hlast : (Kernel.id ×ₖ (κ ⊗ₖ η)) x = Measure.dirac x ⊗ₘ (κ ⊗ₖ η) := by + rw [Measure.compProd_eq_comp_prod] + exact (Measure.dirac_bind (Kernel.measurable (Kernel.id ×ₖ (κ ⊗ₖ η))) x).symm + rw [hlast] + +end ProbabilityTheory.Kernel + +namespace MarkovProcess +namespace DenseTimeHistory + +variable {α : Type*} [MeasurableSpace α] + +/-- Adjoin one observation at the end of a finite dense-time history. -/ +def append (n : ℕ) : DenseTimeHistory α n × α → DenseTimeHistory α (n + 1) := + fun hx ↦ (historyEquiv (n + 1)).symm + ((historyEquiv n hx.1).1, (splitLast n).symm ((historyEquiv n hx.1).2, hx.2)) + +/-- Adjoining one observation to a finite dense-time history is measurable. -/ +theorem measurable_append (n : ℕ) : Measurable (append (α := α) n) := by + unfold append + fun_prop + +@[simp] +theorem historyEquiv_append (n : ℕ) (history : DenseTimeHistory α n) (x : α) : + historyEquiv (n + 1) (append n (history, x)) = + ((historyEquiv n history).1, (splitLast n).symm ((historyEquiv n history).2, x)) := by + exact MeasurableEquiv.apply_symm_apply _ _ + +@[simp] +theorem append_apply_castSucc (n : ℕ) (history : DenseTimeHistory α n) (x : α) + (i : Set.Iic n) : + append n (history, x) ⟨i, i.property.trans n.le_succ⟩ = history i := by + rcases i with ⟨_ | i, hi⟩ + · change (historyEquiv (n + 1) (append n (history, x))).1 = + (historyEquiv n history).1 + rw [historyEquiv_append] + · let j : Fin n := ⟨i, Nat.succ_le_iff.mp hi⟩ + change (historyEquiv (n + 1) (append n (history, x))).2 j.castSucc = + (historyEquiv n history).2 j + rw [historyEquiv_append] + change (splitLast n).symm ((historyEquiv n history).2, x) j.castSucc = _ + rw [splitLast_symm_apply_castSucc] + +@[simp] +theorem append_apply_last (n : ℕ) (history : DenseTimeHistory α n) (x : α) : + append n (history, x) ⟨n + 1, Nat.le_refl (n + 1)⟩ = x := by + change (historyEquiv (n + 1) (append n (history, x))).2 (Fin.last n) = x + rw [historyEquiv_append] + change (splitLast n).symm ((historyEquiv n history).2, x) (Fin.last n) = x + rw [splitLast_symm_apply_last] + +end DenseTimeHistory + +namespace SubMarkovKernelSemigroup + +noncomputable section + +variable {D α : Type*} [MeasurableSpace α] + +namespace IsConservative + +variable [StandardBorelSpace α] [Nonempty α] + +/-- Sampling the next observation conditionally and adjoining it gives the next prefix law. -/ +theorem augmentedPrefixKernel_step (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + (((Kernel.id ×ₖ denseStep P hP e ι n) ∘ₖ augmentedPrefixKernel P e ι n).map + (DenseTimeHistory.append n)) = + augmentedPrefixKernel P e ι (n + 1) := by + let q : ((α × (Fin n → α)) × α) → DenseTimeHistory α (n + 1) := + fun z ↦ (DenseTimeHistory.historyEquiv (n + 1)).symm + (z.1.1, (DenseTimeHistory.splitLast n).symm (z.1.2, z.2)) + let r : (α × ((Fin n → α) × α)) → DenseTimeHistory α (n + 1) := + fun z ↦ (DenseTimeHistory.historyEquiv (n + 1)).symm + (z.1, (DenseTimeHistory.splitLast n).symm z.2) + let : IsMarkovKernel (denseTimePrefixKernel P e ι n) := + hP.isMarkovKernel_denseTimePrefixKernel P e ι n + let : IsMarkovKernel (denseTimePrefixKernel P e ι (n + 1)) := + hP.isMarkovKernel_denseTimePrefixKernel P e ι (n + 1) + let : IsMarkovKernel (observationCondKernel P hP e ι n) := + isMarkovKernel_observationCondKernel P hP e ι n + have hcompat : DenseTimeHistory.append n ∘ + Prod.map (DenseTimeHistory.historyEquiv n).symm id = q := by + funext z + change DenseTimeHistory.append n + ((DenseTimeHistory.historyEquiv n).symm z.1, z.2) = q z + rw [DenseTimeHistory.append] + change _ = (DenseTimeHistory.historyEquiv (n + 1)).symm + (z.1.1, (DenseTimeHistory.splitLast n).symm (z.1.2, z.2)) + simp only [MeasurableEquiv.apply_symm_apply] + have htransport := Kernel.step_transport + (Kernel.id ×ₖ denseTimePrefixKernel P e ι n) + (observationCondKernel P hP e ι n) (DenseTimeHistory.historyEquiv n) + (DenseTimeHistory.append n) (DenseTimeHistory.measurable_append n) q hcompat + rw [augmentedPrefixKernel, denseStep, Kernel.mapOfMeasurable_eq_map] + rw [htransport] + have hq : q = r ∘ MeasurableEquiv.prodAssoc := by + rfl + rw [hq, Kernel.map_comp_right] + rw [Kernel.prod_comp_prod_map_prodAssoc] + rw [compProd_observationCondKernel P hP e ι n] + rw [nextObservationJoint] + rw [Kernel.mapOfMeasurable_eq_map] + rw [← Kernel.map_id' Kernel.id] + rw [Kernel.map_prod_map] + rw [← Kernel.map_comp_right] + change (Kernel.id ×ₖ denseTimePrefixKernel P e ι (n + 1)).map + (r ∘ Prod.map id (DenseTimeHistory.splitLast n)) = _ + have hr : r ∘ Prod.map id (DenseTimeHistory.splitLast n) = + (DenseTimeHistory.historyEquiv (n + 1)).symm := by + funext z + dsimp only [r, Function.comp_apply, Prod.map_apply, id_eq] + change (DenseTimeHistory.historyEquiv (n + 1)).symm + (z.1, (DenseTimeHistory.splitLast n).symm (DenseTimeHistory.splitLast n z.2)) = _ + rw [MeasurableEquiv.symm_apply_apply] + rw [hr, augmentedPrefixKernel, Kernel.mapOfMeasurable_eq_map] + all_goals fun_prop + +end IsConservative +end +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Shift.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Shift.lean new file mode 100644 index 0000000000..87435231a5 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Shift.lean @@ -0,0 +1,89 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension + +/-! +# Shifts of dense-time paths + +This file defines addition by a nonnegative rational time on the fixed dense carrier and the +induced shift of dense-time paths. Restriction of a continuous path commutes with this shift. +No probability law or Markov property is asserted. +-/ + +namespace MarkovProcess + +noncomputable section + +namespace DenseTime + +/-- Addition by a fixed dense time as an order embedding of the dense time carrier. -/ +def addOrderEmbedding (s : DenseTime) : DenseTime ↪o DenseTime := + OrderEmbedding.ofStrictMono (fun t ↦ s + t) fun _ _ h ↦ by + simpa only [add_comm] using add_lt_add_left h s + +@[simp] +theorem addOrderEmbedding_apply (s t : DenseTime) : addOrderEmbedding s t = s + t := rfl + +/-- Embedding a rational-time sum into physical time gives the sum of the embedded times. -/ +@[simp] +theorem castOrderEmbedding_add (s t : DenseTime) : + castOrderEmbedding (s + t) = castOrderEmbedding s + castOrderEmbedding t := by + change ((s + t : DenseTime) : NNReal) = (s : NNReal) + (t : NNReal) + norm_cast + +end DenseTime + +namespace DenseTimePath + +variable {alpha : Type*} + +/-- Shift a dense-time path by a fixed nonnegative rational time. -/ +def shift (s : DenseTime) (path : DenseTime → alpha) : DenseTime → alpha := + path ∘ DenseTime.addOrderEmbedding s + +@[simp] +theorem shift_apply (s t : DenseTime) (path : DenseTime → alpha) : + shift s path t = path (s + t) := rfl + +@[simp] +theorem shift_zero (path : DenseTime → alpha) : shift 0 path = path := by + funext t + simp only [shift_apply, zero_add] + +theorem shift_add (s t : DenseTime) (path : DenseTime → alpha) : + shift t (shift s path) = shift (s + t) path := by + funext r + simp only [shift_apply, add_assoc] + +variable [MeasurableSpace alpha] + +/-- Shifting dense-time paths by a fixed time is measurable for the product measurable space. -/ +theorem measurable_shift (s : DenseTime) : + Measurable (shift s : (DenseTime → alpha) → DenseTime → alpha) := by + rw [measurable_pi_iff] + intro t + exact measurable_pi_apply (s + t) + +end DenseTimePath + +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- Restricting a path after a rational physical-time shift is the same as shifting its +dense-time restriction. -/ +theorem denseRestriction_shift (s : DenseTime) (omega : ContinuousPath alpha) : + denseRestriction + (shift (DenseTime.castOrderEmbedding s) omega) = + DenseTimePath.shift s (denseRestriction omega) := by + funext t + simp only [denseRestriction_apply, shift_apply, DenseTimePath.shift_apply, + DenseTime.castOrderEmbedding_add] + +end ContinuousPath +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean new file mode 100644 index 0000000000..538474db76 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean @@ -0,0 +1,353 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion +import Mathlib.Probability.Kernel.IonescuTulcea.Traj + +/-! +# Trajectories on countable dense time + +This file transports the finite-history transition kernels to the history carrier used by +Mathlib's Ionescu--Tulcea construction, starts the resulting trajectory at a deterministic state, +and reindexes its positive coordinates by a countable dense-time enumeration. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup +namespace IsConservative + +noncomputable section + +variable {D α : Type*} [MeasurableSpace α] [StandardBorelSpace α] [Nonempty α] + +/-- Mathlib's locally finite interval and the set interval used by `DenseTimeHistory` give +measurably equivalent history spaces. -/ +def denseTimeHistoryMeasurableEquiv (n : ℕ) : + ((↑(Finset.Iic n) → α) ≃ᵐ DenseTimeHistory α n) := + MeasurableEquiv.piCongrLeft (fun _ : Set.Iic n ↦ α) (Equiv.IicFinsetSet n) + +/-- The dense-time transition kernel on Mathlib's finite-history carrier. -/ +def trajDenseStep (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : Kernel (↑(Finset.Iic n) → α) α := + (denseStep P hP e ι n).comap (denseTimeHistoryMeasurableEquiv n) + (denseTimeHistoryMeasurableEquiv n).measurable + +/-- The transported dense-time transition kernel is Markov. -/ +instance isMarkovKernel_trajDenseStep (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + IsMarkovKernel (trajDenseStep P hP e ι n) := by + rw [trajDenseStep] + let : IsMarkovKernel (denseStep P hP e ι n) := + isMarkovKernel_denseStep P hP e ι n + infer_instance + +/-- The time-zero history determined by an initial state. -/ +def initialTrajHistory (x : α) : ↑(Finset.Iic 0) → α := + fun _ ↦ x + +omit [StandardBorelSpace α] [Nonempty α] in +/-- The deterministic time-zero history is a measurable function of its initial state. -/ +theorem measurable_initialTrajHistory : Measurable (initialTrajHistory (α := α)) := by + rw [measurable_pi_iff] + intro i + exact measurable_id + +/-- The deterministic kernel from an initial state to its time-zero history. -/ +def initialTrajHistoryKernel : Kernel α (↑(Finset.Iic 0) → α) := + Kernel.deterministic initialTrajHistory measurable_initialTrajHistory + +/-- Remove the augmented initial-state coordinate from a natural-number trajectory. -/ +def dropInitialTrajCoordinate (path : ℕ → α) : ℕ → α := + fun n ↦ path (n + 1) + +omit [StandardBorelSpace α] [Nonempty α] in +/-- Dropping the initial trajectory coordinate is measurable. -/ +theorem measurable_dropInitialTrajCoordinate : + Measurable (dropInitialTrajCoordinate (α := α)) := by + rw [measurable_pi_iff] + intro n + exact measurable_pi_apply (n + 1) + +/-- The countable trajectory in enumeration order, with coordinate zero corresponding to the +first observation rather than the augmented initial state. -/ +def enumeratedDenseTimeTrajectory (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) : Kernel α (ℕ → α) := + ((Kernel.traj (X := fun _ ↦ α) (trajDenseStep P hP e ι) 0).comap + initialTrajHistory measurable_initialTrajHistory).map dropInitialTrajCoordinate + +/-- The trajectory in enumeration order is a Markov kernel. -/ +instance isMarkovKernel_enumeratedDenseTimeTrajectory (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) : + IsMarkovKernel (enumeratedDenseTimeTrajectory P hP e ι) := by + rw [enumeratedDenseTimeTrajectory] + exact Kernel.IsMarkovKernel.map _ measurable_dropInitialTrajCoordinate + +/-- Reindex the enumerated trajectory by its dense-time labels. -/ +def denseTimeTrajectory (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + (e : ℕ ≃ D) (ι : D ↪ NNReal) : Kernel α (D → α) := + (enumeratedDenseTimeTrajectory P hP e ι).map + (CountableEnumeration.measurableEquivPath e α) + +/-- The dense-time trajectory is a Markov kernel. -/ +instance isMarkovKernel_denseTimeTrajectory (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) : + IsMarkovKernel (denseTimeTrajectory P hP e ι) := by + rw [denseTimeTrajectory] + exact Kernel.IsMarkovKernel.map _ + (CountableEnumeration.measurableEquivPath e α).measurable + +/-- Before dropping the initial coordinate, every finite marginal of the trajectory is the +corresponding `partialTraj`, started from the deterministic time-zero history. -/ +theorem trajDenseStep_map_frestrictLe (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + ((Kernel.traj (X := fun _ ↦ α) (trajDenseStep P hP e ι) 0).comap + initialTrajHistory measurable_initialTrajHistory).map (Preorder.frestrictLe n) = + Kernel.partialTraj (X := fun _ ↦ α) (trajDenseStep P hP e ι) 0 n ∘ₖ + initialTrajHistoryKernel := by + rw [← Kernel.comap_map_comm _ measurable_initialTrajHistory + (Preorder.measurable_frestrictLe n), Kernel.traj_map_frestrictLe, + ← Kernel.comp_deterministic_eq_comap] + rfl + +private def rawTrajAppend (n : ℕ) : + ((↑(Finset.Iic n) → α) × α) → (↑(Finset.Iic (n + 1)) → α) := + IicProdIoc (X := fun _ ↦ α) n (n + 1) ∘ + Prod.map id (MeasurableEquiv.piSingleton (X := fun _ ↦ α) n) + +omit [StandardBorelSpace α] [Nonempty α] in +private theorem denseTimeHistoryMeasurableEquiv_rawTrajAppend (n : ℕ) : + denseTimeHistoryMeasurableEquiv (α := α) (n + 1) ∘ rawTrajAppend n = + DenseTimeHistory.append n ∘ + Prod.map (denseTimeHistoryMeasurableEquiv (α := α) n) id := by + funext z + funext i + rcases i with ⟨i, hi⟩ + dsimp only [Function.comp_apply, Prod.map_apply, id_eq] + change rawTrajAppend n z ⟨i, Finset.mem_Iic.mpr hi⟩ = + DenseTimeHistory.append n (denseTimeHistoryMeasurableEquiv n z.1, z.2) ⟨i, hi⟩ + by_cases hiz : i = 0 + · subst i + rfl + · by_cases hin : i = n + 1 + · subst i + change (if h : n + 1 ≤ n then + z.1 ⟨n + 1, Finset.mem_Iic.mpr h⟩ else z.2) = _ + rw [DenseTimeHistory.append_apply_last] + simp only [Nat.not_succ_le_self, dite_false] + · have hi' : i ≤ n + 1 := hi + have hil : i ≤ n := by omega + let j : Set.Iic n := ⟨i, hil⟩ + simp only [rawTrajAppend, Function.comp_apply, IicProdIoc_def, + MeasurableEquiv.piSingleton] + rw [dif_pos hil] + rw [DenseTimeHistory.append_apply_castSucc n + (denseTimeHistoryMeasurableEquiv n z.1) z.2 j] + rfl + +private theorem transport_traj_step {X H Z Y T : Type*} + [MeasurableSpace X] [MeasurableSpace H] [MeasurableSpace Z] + [MeasurableSpace Y] [MeasurableSpace T] + (κ : Kernel X Z) [IsSFiniteKernel κ] + (η : Kernel Z Y) [IsSFiniteKernel η] (E : H ≃ᵐ Z) + (g : H × Y → T) (hg : Measurable g) (q : Z × Y → T) + (hcompat : g ∘ Prod.map E.symm id = q) : + (((Kernel.id ×ₖ η.comap E E.measurable) ∘ₖ κ.map E.symm).map g) = + ((Kernel.id ×ₖ η) ∘ₖ κ).map q := by + rw [Kernel.comp_map κ (Kernel.id ×ₖ η.comap E E.measurable) E.symm.measurable] + rw [Kernel.comap_prod, Kernel.id_comap, ← Kernel.id_map, + ← Kernel.comap_comp_right] + have hcomap : η.comap ((E : H → Z) ∘ E.symm) + (E.measurable.comp E.symm.measurable) = η := by + ext z + rw [Kernel.comap_apply] + change η (E (E.symm z)) _ = η z _ + rw [E.apply_symm_apply] + rw [hcomap, ← Kernel.map_id' η, Kernel.map_prod_map, + ← Kernel.map_comp, ← Kernel.map_comp_right, Kernel.map_id'] + change (Kernel.id ×ₖ η ∘ₖ κ).map (g ∘ Prod.map E.symm id) = _ + rw [hcompat] + all_goals first | exact hg | fun_prop + +omit [StandardBorelSpace α] [Nonempty α] in +private theorem markovKernel_finZero (κ : Kernel α (Fin 0 → α)) [IsMarkovKernel κ] : + κ = Kernel.const α (Measure.dirac (FiniteOrderedTimes.emptyPath α)) := by + ext x s hs + rcases s.eq_empty_or_nonempty with rfl | ⟨z, hz⟩ + · simp + · have hsu : s = Set.univ := by + apply Set.eq_univ_of_forall + intro y + simpa only [Subsingleton.elim y z] using hz + rw [hsu] + simp only [Kernel.const_apply, IsProbabilityMeasure.measure_univ] + +/-- Every finite augmented marginal of the iterated dense-time trajectory is the prescribed +augmented prefix law. -/ +theorem partialTraj_map_denseTimeHistoryMeasurableEquiv + (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + ((Kernel.partialTraj (X := fun _ ↦ α) (trajDenseStep P hP e ι) 0 n ∘ₖ + initialTrajHistoryKernel).map (denseTimeHistoryMeasurableEquiv n)) = + augmentedPrefixKernel P e ι n := by + induction n with + | zero => + rw [Kernel.partialTraj_self, Kernel.id_comp] + let : IsMarkovKernel (denseTimePrefixKernel P e ι 0) := + hP.isMarkovKernel_denseTimePrefixKernel P e ι 0 + rw [augmentedPrefixKernel, + markovKernel_finZero (denseTimePrefixKernel P e ι 0)] + have hconst : Kernel.const α (Measure.dirac (FiniteOrderedTimes.emptyPath α)) = + Kernel.deterministic (fun _ : α ↦ FiniteOrderedTimes.emptyPath α) + measurable_const := by + ext x s hs + simp only [Kernel.const_apply, Kernel.deterministic_apply, + Measure.dirac_apply' _ hs] + rw [initialTrajHistoryKernel, Kernel.deterministic_map, hconst, Kernel.id, + Kernel.deterministic_prod_deterministic, Kernel.mapOfMeasurable_eq_map, + Kernel.deterministic_map] + apply Kernel.deterministic_congr + funext x i + rcases i with ⟨i, hi⟩ + have hi0 : i = 0 := Nat.eq_zero_of_le_zero hi + subst i + rfl + all_goals fun_prop + | succ n ih => + let : IsMarkovKernel (denseStep P hP e ι n) := + isMarkovKernel_denseStep P hP e ι n + let : IsMarkovKernel (augmentedPrefixKernel P e ι n) := + isMarkovKernel_augmentedPrefixKernel P hP e ι n + rw [Kernel.partialTraj_succ_of_le (Nat.zero_le n)] + rw [← Kernel.map_comp] + rw [Kernel.comp_assoc] + rw [← Kernel.map_comp_right] + · rw [← Kernel.map_id' Kernel.id, Kernel.map_prod_map] <;> try fun_prop + rw [← Kernel.map_comp] + rw [← Kernel.map_comp_right] + · have hfun : + ((denseTimeHistoryMeasurableEquiv (α := α) (n + 1) : + (↑(Finset.Iic (n + 1)) → α) → DenseTimeHistory α (n + 1)) ∘ + IicProdIoc (X := fun _ ↦ α) n (n + 1)) ∘ + Prod.map (fun a ↦ a) + (MeasurableEquiv.piSingleton (X := fun _ ↦ α) n) = + denseTimeHistoryMeasurableEquiv (n + 1) ∘ rawTrajAppend n := by + rfl + rw [hfun, denseTimeHistoryMeasurableEquiv_rawTrajAppend] + have hkraw := + (Kernel.map_apply_eq_iff_map_symm_apply_eq + (Kernel.partialTraj (X := fun _ ↦ α) (trajDenseStep P hP e ι) 0 n ∘ₖ + initialTrajHistoryKernel) + (augmentedPrefixKernel P e ι n)).mp ih + rw [hkraw, trajDenseStep, transport_traj_step, augmentedPrefixKernel_step] + · exact (DenseTimeHistory.measurable_append n).comp + ((denseTimeHistoryMeasurableEquiv n).measurable.prodMap measurable_id) + · funext z + change DenseTimeHistory.append n + ((denseTimeHistoryMeasurableEquiv n) + ((denseTimeHistoryMeasurableEquiv n).symm z.1), z.2) = + DenseTimeHistory.append n z + rw [MeasurableEquiv.apply_symm_apply] + · exact measurable_id.prodMap + (MeasurableEquiv.piSingleton (X := fun _ ↦ α) n).measurable + · exact (denseTimeHistoryMeasurableEquiv (α := α) (n + 1)).measurable.comp + measurable_IicProdIoc + · exact measurable_IicProdIoc + · exact (denseTimeHistoryMeasurableEquiv (α := α) (n + 1)).measurable + +/-- Restrict an enumeration-ordered trajectory to its first `n` observations. -/ +def enumeratedDenseTimePrefix (n : ℕ) (path : ℕ → α) : Fin n → α := + fun i ↦ path i + +omit [StandardBorelSpace α] [Nonempty α] in +/-- Restriction to the first `n` enumeration coordinates is measurable. -/ +theorem measurable_enumeratedDenseTimePrefix (n : ℕ) : + Measurable (enumeratedDenseTimePrefix (α := α) n) := by + rw [measurable_pi_iff] + intro i + exact measurable_pi_apply (X := fun _ : ℕ ↦ α) i + +omit [StandardBorelSpace α] [Nonempty α] in +private theorem enumeratedDenseTimePrefix_dropInitialTrajCoordinate (n : ℕ) : + enumeratedDenseTimePrefix (α := α) n ∘ dropInitialTrajCoordinate = + Prod.snd ∘ DenseTimeHistory.historyEquiv n ∘ + denseTimeHistoryMeasurableEquiv n ∘ Preorder.frestrictLe n := by + funext path i + rfl + +/-- The first `n` coordinates of the enumeration-ordered trajectory have exactly the prescribed +enumeration-prefix law. -/ +theorem enumeratedDenseTimeTrajectory_map_prefix + (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + (enumeratedDenseTimeTrajectory P hP e ι).map + (enumeratedDenseTimePrefix (α := α) n) = + denseTimePrefixKernel P e ι n := by + let : IsMarkovKernel (denseTimePrefixKernel P e ι n) := + hP.isMarkovKernel_denseTimePrefixKernel P e ι n + rw [enumeratedDenseTimeTrajectory, ← Kernel.map_comp_right] + · rw [enumeratedDenseTimePrefix_dropInitialTrajCoordinate] + rw [Kernel.map_comp_right] + · rw [← Function.comp_assoc] + rw [Kernel.map_comp_right _ (Preorder.measurable_frestrictLe n) + ((DenseTimeHistory.historyEquiv n).measurable.comp + (denseTimeHistoryMeasurableEquiv (α := α) n).measurable)] + rw [trajDenseStep_map_frestrictLe] + rw [Kernel.map_comp_right _ + (denseTimeHistoryMeasurableEquiv (α := α) n).measurable + (DenseTimeHistory.historyEquiv n).measurable] + rw [partialTraj_map_denseTimeHistoryMeasurableEquiv] + rw [augmentedPrefixKernel_map_historyEquiv] + rw [← Kernel.snd_eq, Kernel.snd_prod] + · exact ((DenseTimeHistory.historyEquiv n).measurable.comp + (denseTimeHistoryMeasurableEquiv (α := α) n).measurable).comp + (Preorder.measurable_frestrictLe n) + · exact measurable_snd + · exact measurable_dropInitialTrajCoordinate + · exact measurable_enumeratedDenseTimePrefix n + +/-- Restrict a dense-time-labelled trajectory to the first `n` labels of an enumeration. -/ +def denseTimeTrajectoryPrefix (e : ℕ ≃ D) (n : ℕ) (path : D → α) : Fin n → α := + fun i ↦ path (e i) + +omit [StandardBorelSpace α] [Nonempty α] in +/-- Restriction to the first `n` dense-time labels is measurable. -/ +theorem measurable_denseTimeTrajectoryPrefix (e : ℕ ≃ D) (n : ℕ) : + Measurable (denseTimeTrajectoryPrefix (α := α) e n) := by + rw [measurable_pi_iff] + intro i + exact measurable_pi_apply (X := fun _ : D ↦ α) (e i) + +omit [StandardBorelSpace α] [Nonempty α] in +private theorem denseTimeTrajectoryPrefix_measurableEquivPath + (e : ℕ ≃ D) (n : ℕ) : + denseTimeTrajectoryPrefix (α := α) e n ∘ + CountableEnumeration.measurableEquivPath e α = + enumeratedDenseTimePrefix n := by + funext path i + dsimp only [Function.comp_apply, denseTimeTrajectoryPrefix, + enumeratedDenseTimePrefix] + exact MeasurableEquiv.piCongrLeft_apply_apply + (β := fun _ : D ↦ α) e path i + +/-- Restricting the dense-time-labelled trajectory to the first `n` enumerated labels gives +exactly the prescribed enumeration-prefix law. -/ +theorem denseTimeTrajectory_map_prefix + (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + (denseTimeTrajectory P hP e ι).map + (denseTimeTrajectoryPrefix e n) = + denseTimePrefixKernel P e ι n := by + rw [denseTimeTrajectory, ← Kernel.map_comp_right] + · rw [denseTimeTrajectoryPrefix_measurableEquivPath] + exact enumeratedDenseTimeTrajectory_map_prefix P hP e ι n + · exact (CountableEnumeration.measurableEquivPath e α).measurable + · exact measurable_denseTimeTrajectoryPrefix e n + +end +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TrajectoryMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TrajectoryMarginals.lean new file mode 100644 index 0000000000..d2c032455a --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TrajectoryMarginals.lean @@ -0,0 +1,110 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory + +/-! +# One-time marginals of the dense-time trajectory + +This file identifies every coordinate marginal of the dense-time trajectory kernel with the +corresponding transition kernel. The result is derived from the exact finite-prefix identity. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup +namespace IsConservative + +noncomputable section + +variable {D α : Type*} [MeasurableSpace α] [StandardBorelSpace α] [Nonempty α] + +omit [StandardBorelSpace α] [Nonempty α] in +private theorem finiteTimeKernel_map_eval + (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + {n : ℕ} (times : FiniteOrderedTimes n) (i : Fin n) : + (finiteTimeKernel P times).map (fun path ↦ path i) = P (times i) := by + let select : Fin 1 ↪o Fin n := + { toFun := fun _ ↦ i + inj' := fun a b _ ↦ Subsingleton.elim a b + map_rel_iff' := by + intro a b + constructor + · intro _ + rw [Subsingleton.elim a b] + · intro _ + exact le_rfl } + have hfun : + (fun path : Fin 1 → α ↦ path 0) ∘ FiniteOrderedTimes.restrictPath select = + fun path : Fin n → α ↦ path i := by + funext path + rfl + rw [← hfun, Kernel.map_comp_right] + · rw [hP.finiteTimeKernel_map_restrictPath P times select] + simpa only using! finiteTimeKernel_one_map_eval P (times.restrict select) + · exact FiniteOrderedTimes.measurable_restrictPath select + · exact measurable_pi_apply 0 + +/-- Every coordinate marginal of the dense-time trajectory is the transition kernel at its +embedded physical time. -/ +theorem denseTimeTrajectory_map_eval + (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + (e : ℕ ≃ D) (ι : D ↪ NNReal) (d : D) : + (denseTimeTrajectory P hP e ι).map (fun path ↦ path d) = P (ι d) := by + let k : ℕ := e.symm d + let i : Fin (k + 1) := ⟨k, Nat.lt_succ_self k⟩ + have hcoord : e i = d := by + change e (e.symm d) = d + exact e.apply_symm_apply d + have hfun : + (fun path : Fin (k + 1) → α ↦ path i) ∘ + denseTimeTrajectoryPrefix e (k + 1) = + fun path : D → α ↦ path d := by + funext path + change path (e i) = path d + rw [hcoord] + rw [← hfun, Kernel.map_comp_right] + · rw [denseTimeTrajectory_map_prefix P hP e ι (k + 1)] + rw [denseTimePrefixKernel_eq_map, ← Kernel.map_comp_right] + · have ht : ι (e i) ∈ denseTimePhysicalPrefix e ι (k + 1) := by + rw [denseTimePhysicalPrefix, Finset.mem_map] + refine ⟨e i, ?_, rfl⟩ + rw [CountableEnumeration.mem_prefix_iff, e.symm_apply_apply] + exact i.isLt + let t : denseTimePhysicalPrefix e ι (k + 1) := ⟨ι (e i), ht⟩ + have hprefix : + (fun path : Fin (k + 1) → α ↦ path i) ∘ + denseTimePrefixReindex e ι (k + 1) = + fun path : denseTimePhysicalPrefix e ι (k + 1) → α ↦ path t := by + rfl + rw [hprefix, finiteSetKernel_eq_map, ← Kernel.map_comp_right] + · let j : Fin (denseTimePhysicalPrefix e ι (k + 1)).card := + ((denseTimePhysicalPrefix e ι (k + 1)).orderIsoOfFin rfl).symm t + have hordered : + (fun path : denseTimePhysicalPrefix e ι (k + 1) → α ↦ path t) ∘ + orderedPathToFiniteSet (denseTimePhysicalPrefix e ι (k + 1)) = + fun path : Fin (denseTimePhysicalPrefix e ι (k + 1)).card → α ↦ path j := by + rfl + rw [hordered, finiteTimeKernel_map_eval P hP _ j] + have hjtime : + finiteSetTimes (denseTimePhysicalPrefix e ι (k + 1)) j = ι (e i) := by + change ((((denseTimePhysicalPrefix e ι (k + 1)).orderIsoOfFin rfl) j : + denseTimePhysicalPrefix e ι (k + 1)) : NNReal) = ι (e i) + dsimp only [j] + rw [OrderIso.apply_symm_apply] + rw [hjtime, hcoord] + · exact measurable_orderedPathToFiniteSet + (denseTimePhysicalPrefix e ι (k + 1)) + · exact measurable_pi_apply t + · exact measurable_denseTimePrefixReindex e ι (k + 1) + · fun_prop + · exact measurable_denseTimeTrajectoryPrefix e (k + 1) + · fun_prop + +end +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TwoPointMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TwoPointMarginals.lean new file mode 100644 index 0000000000..f50164fe6f --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TwoPointMarginals.lean @@ -0,0 +1,336 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments +import Mathlib.Probability.Kernel.Composition.Lemmas +import Mathlib.Probability.Process.Kolmogorov + +/-! +# Two-point marginals of the dense-time trajectory, and the intrinsic Kolmogorov bridge + +The dense-time trajectory of a conservative sub-Markov kernel semigroup already has identified +one-time marginals. This file identifies its two-time marginals: at dense times whose physical +images satisfy `iota d < iota d'`, the pair `(path d, path d')` has the law obtained by running +`P` for time `iota d` and then, from the state reached, for the increment `iota d' - iota d`. + +The identification is then used to discharge the coordinate Kolmogorov hypothesis that every +trajectory theorem of the library assumes. Under the intrinsic semigroup bound +`SubMarkovKernelSemigroup.HasKolmogorovMoments`, the canonical dense-time coordinate process is a +Kolmogorov process with a positive Hölder exponent below `(q - 1) / p`. + +No continuity, modification, Markov-property, or path-regularity statement is proved here; only +the two-point law and the moment estimate it transports. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + +namespace MarkovProcess + +noncomputable section + +namespace DenseTime + +/-- On dense time the extended distance between ordered times is the physical time increment. -/ +theorem edist_eq_castOrderEmbedding_sub {s t : DenseTime} (hst : s ≤ t) : + edist s t = ((castOrderEmbedding t - castOrderEmbedding s : ℝ≥0) : ℝ≥0∞) := by + have hcast : castOrderEmbedding s ≤ castOrderEmbedding t := + castOrderEmbedding.monotone hst + have hcoe : ∀ r : DenseTime, ((castOrderEmbedding r : ℝ≥0) : ℝ) = ((r : ℚ) : ℝ) := by + intro r + simp only [castOrderEmbedding, NNRat.castOrderEmbedding_apply] + push_cast + rfl + have hreal : ((s : ℚ) : ℝ) ≤ ((t : ℚ) : ℝ) := by + rw [← hcoe s, ← hcoe t] + exact_mod_cast hcast + rw [edist_dist, ← ENNReal.ofReal_coe_nnreal] + congr 1 + rw [NNReal.coe_sub hcast, NNRat.dist_eq, ← Rat.dist_cast, Real.dist_eq, hcoe, hcoe, + abs_sub_comm, abs_of_nonneg (by linarith only [hreal])] + +/-- The physical embedding of dense time is an isometry for the extended distance. -/ +theorem dist_castOrderEmbedding (r r' : DenseTime) : + dist (castOrderEmbedding r) (castOrderEmbedding r') = dist r r' := by + have hcoe : ∀ u : DenseTime, ((castOrderEmbedding u : ℝ≥0) : ℝ) = ((u : ℚ) : ℝ) := by + intro u + simp only [castOrderEmbedding, NNRat.castOrderEmbedding_apply] + push_cast + rfl + rw [NNReal.dist_eq, hcoe, hcoe, NNRat.dist_eq, ← Rat.dist_cast, Real.dist_eq] + +/-- The physical embedding of dense time preserves the extended distance. -/ +theorem edist_castOrderEmbedding (r r' : DenseTime) : + edist (castOrderEmbedding r) (castOrderEmbedding r') = edist r r' := by + rw [edist_dist, edist_dist, dist_castOrderEmbedding] + +end DenseTime + +namespace SubMarkovKernelSemigroup + +section CompProd + +variable {A B C E : Type*} [MeasurableSpace A] [MeasurableSpace B] [MeasurableSpace C] + [MeasurableSpace E] + +/-- A composition-product whose second factor ignores the starting point is the measure-level +composition-product of the first factor's law with that second factor. -/ +private theorem compProd_prodMkLeft_apply (kappa : Kernel A B) [IsSFiniteKernel kappa] + (eta : Kernel B C) [IsSFiniteKernel eta] (x : A) : + (kappa ⊗ₖ Kernel.prodMkLeft A eta) x = (kappa x) ⊗ₘ eta := by + ext s hs + rw [Kernel.compProd_apply hs, Measure.compProd_apply hs] + simp only [Kernel.prodMkLeft_apply] + +/-- Pushing the second coordinate of such a composition-product forward along a measurable map +is the composition-product with the pushed-forward second factor. -/ +private theorem compProd_prodMkLeft_map (kappa : Kernel A B) [IsSFiniteKernel kappa] + (eta : Kernel B C) [IsSFiniteKernel eta] {g : C → E} (hg : Measurable g) : + (kappa ⊗ₖ Kernel.prodMkLeft A eta).map (Prod.map id g) = + kappa ⊗ₖ Kernel.prodMkLeft A (eta.map g) := by + ext x + rw [Kernel.map_apply _ (measurable_id.prodMap hg), compProd_prodMkLeft_apply, + compProd_prodMkLeft_apply, Measure.compProd_map hg] + +end CompProd + +section TwoPoint + +variable {D alpha : Type*} [MeasurableSpace alpha] + +private theorem measurable_finConsOne : + Measurable + (fun z : alpha × (Fin 1 → alpha) ↦ @Fin.cons 1 (fun _ : Fin 2 ↦ alpha) z.1 z.2) := by + rw [measurable_pi_iff] + intro i + refine Fin.cases ?_ (fun j ↦ ?_) i + · simpa only [Fin.cons_zero] using + (measurable_fst : Measurable (Prod.fst : alpha × (Fin 1 → alpha) → alpha)) + · simpa only [Fin.cons_succ] using! + (measurable_pi_apply j).comp + (measurable_snd : Measurable (Prod.snd : alpha × (Fin 1 → alpha) → _)) + +namespace IsConservative + +/-- The two-coordinate finite-time kernel is the transition kernel at the first time followed by +the transition kernel over the increment to the second time. -/ +theorem finiteTimeKernel_two_map_pair (P : SubMarkovKernelSemigroup alpha) + (hP : P.IsConservative) (u : FiniteOrderedTimes 2) : + (finiteTimeKernel P u).map (fun path ↦ (path 0, path 1)) = + P (u 0) ⊗ₖ Kernel.prodMkLeft alpha (P (u 1 - u 0)) := by + let : IsFiniteKernel (P (u 0)) := (P.isSubMarkovKernel (u 0)).isFiniteKernel + let : IsFiniteKernel (P (u.relativeTail 0)) := + (P.isSubMarkovKernel (u.relativeTail 0)).isFiniteKernel + let : IsMarkovKernel (finiteTimeKernel P u.relativeTail) := + hP.isMarkovKernel_finiteTimeKernel P u.relativeTail + have hmeasPair : Measurable (fun path : Fin 2 → alpha ↦ (path 0, path 1)) := by fun_prop + have hcomp : + (fun path : Fin 2 → alpha ↦ (path 0, path 1)) ∘ + (fun z : alpha × (Fin 1 → alpha) ↦ @Fin.cons 1 (fun _ : Fin 2 ↦ alpha) z.1 z.2) = + Prod.map id (fun path : Fin 1 → alpha ↦ path 0) := by + funext z + rfl + have htail : u.relativeTail 0 = u 1 - u 0 := rfl + rw [finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map, + ← Kernel.map_comp_right _ measurable_finConsOne hmeasPair, hcomp, + compProd_prodMkLeft_map _ _ (measurable_pi_apply (0 : Fin 1)), + finiteTimeKernel_one_map_eval, htail] + +variable [StandardBorelSpace alpha] [Nonempty alpha] + +private theorem denseTimeTrajectory_map_pair_aux + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) {n : ℕ} (k l : ℕ) (hk : k < n) (hl : l < n) + (hlt : iota (e k) < iota (e l)) : + (denseTimeTrajectory P hP e iota).map (fun path ↦ (path (e k), path (e l))) = + P (iota (e k)) ⊗ₖ Kernel.prodMkLeft alpha (P (iota (e l) - iota (e k))) := by + classical + set i : Fin n := ⟨k, hk⟩ with hi + set j : Fin n := ⟨l, hl⟩ with hj + have hpair : Measurable (fun path : Fin n → alpha ↦ (path i, path j)) := by fun_prop + have hstep1 : + (fun path : Fin n → alpha ↦ (path i, path j)) ∘ denseTimeTrajectoryPrefix e n = + fun path : D → alpha ↦ (path (e k), path (e l)) := rfl + rw [← hstep1, Kernel.map_comp_right _ (measurable_denseTimeTrajectoryPrefix e n) hpair, + denseTimeTrajectory_map_prefix P hP e iota n, denseTimePrefixKernel_eq_map, + ← Kernel.map_comp_right _ (measurable_denseTimePrefixReindex e iota n) hpair] + set J : Finset NNReal := denseTimePhysicalPrefix e iota n with hJ + have hmem : ∀ m : Fin n, iota (e (m : ℕ)) ∈ J := by + intro m + rw [hJ, denseTimePhysicalPrefix, Finset.mem_map] + refine ⟨e (m : ℕ), ?_, rfl⟩ + rw [CountableEnumeration.mem_prefix_iff, e.symm_apply_apply] + exact m.isLt + have hstep2 : + (fun path : Fin n → alpha ↦ (path i, path j)) ∘ denseTimePrefixReindex e iota n = + fun path : J → alpha ↦ + (path ⟨iota (e (i : ℕ)), hmem i⟩, path ⟨iota (e (j : ℕ)), hmem j⟩) := rfl + have hpairJ : Measurable (fun path : J → alpha ↦ + (path ⟨iota (e (i : ℕ)), hmem i⟩, path ⟨iota (e (j : ℕ)), hmem j⟩)) := by fun_prop + rw [hstep2, finiteSetKernel_eq_map, + ← Kernel.map_comp_right _ (measurable_orderedPathToFiniteSet J) hpairJ] + set a : Fin J.card := (J.orderIsoOfFin rfl).symm ⟨iota (e (i : ℕ)), hmem i⟩ with ha + set b : Fin J.card := (J.orderIsoOfFin rfl).symm ⟨iota (e (j : ℕ)), hmem j⟩ with hb + have hstep3 : + (fun path : J → alpha ↦ + (path ⟨iota (e (i : ℕ)), hmem i⟩, path ⟨iota (e (j : ℕ)), hmem j⟩)) ∘ + orderedPathToFiniteSet J = + fun path : Fin J.card → alpha ↦ (path a, path b) := rfl + rw [hstep3] + have hab : a < b := by + rw [ha, hb, OrderIso.lt_iff_lt, Subtype.mk_lt_mk] + exact hlt + set select : Fin 2 ↪o Fin J.card := + OrderEmbedding.ofStrictMono (fun m ↦ if m = 0 then a else b) (by + rw [Fin.strictMono_iff_lt_succ] + intro m + have hm : m = 0 := Subsingleton.elim m 0 + subst hm + simpa only [Fin.castSucc_zero, if_pos rfl, Fin.succ_zero_eq_one] using! hab) with hselect + have hpair2 : Measurable (fun path : Fin 2 → alpha ↦ (path 0, path 1)) := by fun_prop + have hstep4 : + (fun path : Fin 2 → alpha ↦ (path 0, path 1)) ∘ + FiniteOrderedTimes.restrictPath select = + fun path : Fin J.card → alpha ↦ (path a, path b) := rfl + rw [← hstep4, + Kernel.map_comp_right _ (FiniteOrderedTimes.measurable_restrictPath select) hpair2, + hP.finiteTimeKernel_map_restrictPath P (finiteSetTimes J) select, + finiteTimeKernel_two_map_pair P hP] + have hta : ((finiteSetTimes J).restrict select) 0 = iota (e k) := by + change ((((J.orderIsoOfFin rfl) a) : J) : NNReal) = iota (e k) + rw [ha, OrderIso.apply_symm_apply] + have htb : ((finiteSetTimes J).restrict select) 1 = iota (e l) := by + change ((((J.orderIsoOfFin rfl) b) : J) : NNReal) = iota (e l) + rw [hb, OrderIso.apply_symm_apply] + rw [hta, htb] + +/-- The two-time marginal of the dense-time trajectory: at dense labels whose physical times are +strictly ordered, the pair of coordinates has the law of `P` run for the first physical time and +then, from the state reached, for the increment to the second physical time. -/ +theorem denseTimeTrajectory_map_pair + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) {d d' : D} (hlt : iota d < iota d') : + (denseTimeTrajectory P hP e iota).map (fun path ↦ (path d, path d')) = + P (iota d) ⊗ₖ Kernel.prodMkLeft alpha (P (iota d' - iota d)) := by + have hd : e (e.symm d) = d := e.apply_symm_apply d + have hd' : e (e.symm d') = d' := e.apply_symm_apply d' + have hpair := denseTimeTrajectory_map_pair_aux P hP e iota + (n := max (e.symm d) (e.symm d') + 1) (e.symm d) (e.symm d') + (Nat.lt_succ_of_le (le_max_left _ _)) (Nat.lt_succ_of_le (le_max_right _ _)) + (by rw [hd, hd']; exact hlt) + rwa [hd, hd'] at hpair + +end IsConservative + +end TwoPoint + +section Bridge + +variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [StandardBorelSpace alpha] [Nonempty alpha] + +namespace IsConservative + +private theorem lintegral_edist_le_of_lt + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + {p q : ℝ} {M : ℝ≥0} (hmom : P.HasKolmogorovMoments p q M) (x : alpha) + {s t : DenseTime} (hst : s < t) : + ∫⁻ omega, edist (omega s) (omega t) ^ p + ∂(denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) ≤ M * edist s t ^ q := by + set iota : DenseTime ↪ NNReal := DenseTime.castOrderEmbedding.toEmbedding with hiota + have hlt : iota s < iota t := DenseTime.castOrderEmbedding.strictMono hst + set Delta : NNReal := iota t - iota s with hDelta + let : IsFiniteKernel (P (iota s)) := (P.isSubMarkovKernel (iota s)).isFiniteKernel + let : IsFiniteKernel (P Delta) := (P.isSubMarkovKernel Delta).isFiniteKernel + have hF : Measurable (fun z : alpha × alpha ↦ edist z.1 z.2 ^ p) := + measurable_edist.pow_const p + have hev : Measurable (fun omega : DenseTime → alpha ↦ (omega s, omega t)) := by fun_prop + have hmapint : + ∫⁻ z, edist z.1 z.2 ^ p + ∂((denseTimeTrajectory P hP DenseTime.enumeration iota x).map + (fun omega ↦ (omega s, omega t))) = + ∫⁻ omega, edist (omega s) (omega t) ^ p + ∂(denseTimeTrajectory P hP DenseTime.enumeration iota x) := + lintegral_map hF hev + have hlaw : + (denseTimeTrajectory P hP DenseTime.enumeration iota x).map + (fun omega ↦ (omega s, omega t)) = (P (iota s) x) ⊗ₘ P Delta := by + rw [← Kernel.map_apply _ hev, + denseTimeTrajectory_map_pair P hP DenseTime.enumeration iota hlt, + compProd_prodMkLeft_apply] + have hinner : ∀ y : alpha, + ∫⁻ z, edist y z ^ p ∂(P Delta y) ≤ (M : ℝ≥0∞) * (Delta : ℝ≥0∞) ^ q := by + intro y + have hcongr : ∫⁻ z, edist y z ^ p ∂(P Delta y) = ∫⁻ z, edist z y ^ p ∂(P Delta y) := + lintegral_congr fun z ↦ by rw [edist_comm] + rw [hcongr] + exact hmom.lintegral_edist_le Delta y + rw [← hmapint, hlaw, Measure.lintegral_compProd hF] + calc ∫⁻ y, ∫⁻ z, edist y z ^ p ∂(P Delta y) ∂(P (iota s) x) + ≤ ∫⁻ _, (M : ℝ≥0∞) * (Delta : ℝ≥0∞) ^ q ∂(P (iota s) x) := lintegral_mono hinner + _ = (M : ℝ≥0∞) * (Delta : ℝ≥0∞) ^ q := by + rw [lintegral_const, hP (iota s) x, mul_one] + _ = (M : ℝ≥0∞) * edist s t ^ q := by + rw [DenseTime.edist_eq_castOrderEmbedding_sub hst.le] + rfl + +/-- **The dense-time coordinate process is a Kolmogorov process, with the semigroup's own +constants.** Under the intrinsic moment bound `HasKolmogorovMoments p q M`, the canonical +dense-time coordinate process of `P` started from any state satisfies the Kolmogorov increment +condition with exactly the exponents `p`, `q` and the constant `M` of that bound. In particular +the estimate is uniform in the starting state. -/ +theorem isKolmogorovProcess_denseTimeTrajectory + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + {p q : ℝ} {M : ℝ≥0} (hmom : P.HasKolmogorovMoments p q M) (x : alpha) : + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M := by + refine IsKolmogorovProcess.mk_of_secondCountableTopology + (fun r ↦ measurable_pi_apply r) ?_ hmom.p_pos hmom.q_pos + intro s t + rcases lt_trichotomy s t with hst | hst | hst + · exact lintegral_edist_le_of_lt P hP hmom x hst + · subst hst + simp only [edist_self, ENNReal.zero_rpow_of_pos hmom.p_pos, lintegral_zero] + exact zero_le + · have hsym := lintegral_edist_le_of_lt P hP hmom x hst + have hcongr : + ∫⁻ omega, edist (omega s) (omega t) ^ p + ∂(denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) = + ∫⁻ omega, edist (omega t) (omega s) ^ p + ∂(denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) := + lintegral_congr fun omega ↦ by rw [edist_comm] + rw [hcongr, edist_comm s t] + exact hsym + +/-- An intrinsic Kolmogorov moment bound on the semigroup implies the coordinate Kolmogorov +hypothesis assumed by every trajectory theorem of the library: for each starting state the +canonical dense-time coordinate process is a Kolmogorov process admitting a positive Hölder +exponent strictly below the Kolmogorov--Chentsov threshold. -/ +theorem kolmogorovRegular_of_hasKolmogorovMoments + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + {p q : ℝ} {M : ℝ≥0} (hmom : P.HasKolmogorovMoments p q M) : + ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p := by + intro x + obtain ⟨gamma, hgamma0, hgammalt⟩ := hmom.exists_holderExponent + exact ⟨p, q, gamma, M, isKolmogorovProcess_denseTimeTrajectory P hP hmom x, hgamma0, hgammalt⟩ + +end IsConservative + +end Bridge + +end SubMarkovKernelSemigroup + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples.lean new file mode 100644 index 0000000000..07e3c48c64 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples.lean @@ -0,0 +1,18 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Examples.BrownianMotion +import LeanPool.MarkovProcess.MarkovProcess.Examples.Drift +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatGenerator +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatOnePoint +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Examples.Identity + +/-! +# Examples + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean new file mode 100644 index 0000000000..ae4347070d --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean @@ -0,0 +1,429 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +import Mathlib.Probability.HasLaw + +/-! +# The process of the heat semigroup is a Brownian motion + +The continuous-path process `brownianMotion` of `MarkovProcess.Examples.HeatSemigroup` is +identified as a Brownian motion on the line: recentred at its starting point it has centred +Gaussian marginals of variance the elapsed time, independent increments over the consecutive +intervals of every finite monotone family of times, and continuous trajectories. + +The engine is the simple Markov property in joint-law form +(`brownianMotion_map_prodMk_shift`): the law of the pair consisting of the position at a time and +the path shifted by that time is the composition-product of the position law with the process. +Iterating it identifies the law of the vector of increments of a monotone family of times as a +product of centred Gaussians, and independence follows from the product form. + +Main results: + +* `brownianMotion_map_prodMk_shift`: the simple Markov property in joint-law form. +* `brownianMotion_map_incrementsMap`, `brownianMotion_map_increments`: the joint law of the + increments is a product of centred Gaussians. +* `HasIndepIncrements`, `hasIndepIncrements_brownianMotion`: independence of the increments. +* `IsBrownianReal`, `isBrownianReal_brownianMotion`: the identification. + +`HasIndepIncrements` copies the definition of Mathlib's +`Mathlib/Probability/Independence/Process/HasIndepIncrements/Basic.lean`; `IsBrownianReal` is +the form that Mathlib's `Mathlib/Probability/BrownianMotion/Basic.lean` proves equivalent to its +own definition of `IsBrownianReal` (`HasIndepIncrements.isPreBrownianReal_of_hasLaw` and the +converse lemmas `IsPreBrownianReal.hasLaw_eval`, `IsPreBrownianReal.hasIndepIncrements`). +Neither is available at the pinned revision, and `IsBrownianReal` here is stated through Gaussian +marginals and independent increments, not through a projective family. Only one space dimension is treated, and no +Levy characterization, quadratic variation, or stochastic integral is asserted. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + +namespace MarkovProcess + +noncomputable section + +section MarkovProperty + +/-- A joint law factorizes through a kernel as soon as the law of the second variable, after +restriction to every event determined by the first, is the kernel composed with that restriction. +This is the converse of `restrict_map_eq_comap_comp_of_map_prodMk_eq_compProd`; both directions +are the same computation on rectangles. -/ +private theorem map_prodMk_eq_compProd_of_restrict_map + {Omega beta gamma : Type*} {mOmega : MeasurableSpace Omega} + {mBeta : MeasurableSpace beta} {mGamma : MeasurableSpace gamma} + (mu : Measure Omega) [IsProbabilityMeasure mu] + (X : Omega → beta) (hX : Measurable X) + (Y : Omega → gamma) (hY : Measurable Y) + (kappa : Kernel beta gamma) [IsMarkovKernel kappa] + (hrestrict : ∀ C : Set beta, MeasurableSet C → + (mu.restrict (X ⁻¹' C)).map Y = kappa.comap X hX ∘ₘ (mu.restrict (X ⁻¹' C))) : + mu.map (fun omega ↦ (X omega, Y omega)) = (mu.map X) ⊗ₘ kappa := by + have : IsProbabilityMeasure (mu.map (fun omega ↦ (X omega, Y omega))) := + Measure.isProbabilityMeasure_map (hX.prodMk hY).aemeasurable + have : IsProbabilityMeasure (mu.map X) := Measure.isProbabilityMeasure_map hX.aemeasurable + refine MeasureTheory.ext_of_generate_finite _ generateFrom_prod.symm + isPiSystem_prod ?_ ?_ + · rintro _ ⟨C, hC, B, hB, rfl⟩ + have hleft : mu.map (fun omega ↦ (X omega, Y omega)) (C ×ˢ B) + = ∫⁻ omega in X ⁻¹' C, kappa (X omega) B ∂mu := by + rw [Measure.map_apply (hX.prodMk hY) (hC.prod hB), Set.mk_preimage_prod, + Set.inter_comm, ← Measure.restrict_apply (hY hB), ← Measure.map_apply hY hB, + hrestrict C hC, Measure.bind_apply hB (Kernel.aemeasurable _)] + simp_rw [Kernel.comap_apply] + rw [hleft, Measure.compProd_apply_prod hC hB, setLIntegral_map hC (kappa.measurable_coe hB) hX] + · rw [measure_univ, measure_univ] + +/-- **The simple Markov property of Brownian motion, in joint-law form.** -/ +theorem brownianMotion_map_prodMk_shift (x : ℝ) (s : NNReal) : + (brownianMotion x).map (fun omega ↦ (omega s, ContinuousPath.shift s omega)) = + (gaussianReal x s) ⊗ₘ brownianMotion := by + have hX : Measurable (fun omega : ContinuousPath ℝ ↦ omega s) := + ContinuousPath.measurable_coordinateProcess s + have hY : Measurable (ContinuousPath.shift (alpha := ℝ) s) := + ContinuousPath.measurable_shift_fixed s + rw [← brownianMotion_map_eval s x] + refine map_prodMk_eq_compProd_of_restrict_map (brownianMotion x) _ hX _ hY brownianMotion ?_ + intro C hC + have hA : MeasurableSet[ContinuousPath.canonicalFiltration (alpha := ℝ) s] + ((fun omega : ContinuousPath ℝ ↦ omega s) ⁻¹' C) := + ContinuousPath.measurable_coordinateProcess_canonicalFiltration s hC + exact SubMarkovKernelSemigroup.IsFellerKernelSemigroup.continuousProcess_restrict_map_shift + heatSemigroup isConservative_heatSemigroup isFellerKernelSemigroup_heatSemigroup + kolmogorovRegular_heatSemigroup x s _ hA + +end MarkovProperty + +section Increments + +/-- The increments of a finite coordinate path, the first one measured from a base point. -/ +def incrementsMap : {n : ℕ} → ℝ → (Fin n → ℝ) → (Fin n → ℝ) + | 0, _, _ => fun i ↦ i.elim0 + | _ + 1, x, path => Fin.cons (path 0 - x) (incrementsMap (path 0) (Fin.tail path)) + +/-- The recursion defining the increments: the first one is measured from the base point, the +remaining ones are the increments of the tail measured from the first coordinate. -/ +theorem incrementsMap_succ {n : ℕ} (x : ℝ) (path : Fin (n + 1) → ℝ) : + incrementsMap x path = Fin.cons (path 0 - x) (incrementsMap (path 0) (Fin.tail path)) := + rfl + +/-- The first increment is the displacement from the base point. -/ +@[simp] +theorem incrementsMap_zero_apply {n : ℕ} (x : ℝ) (path : Fin (n + 1) → ℝ) : + incrementsMap x path 0 = path 0 - x := rfl + +/-- Every increment after the first is the difference of two consecutive coordinates. -/ +theorem incrementsMap_succ_apply : ∀ {n : ℕ} (x : ℝ) (path : Fin (n + 1) → ℝ) (i : Fin n), + incrementsMap x path i.succ = path i.succ - path i.castSucc := by + intro n + induction n with + | zero => exact fun _ _ i ↦ i.elim0 + | succ n ih => + intro x path i + rw [incrementsMap_succ, Fin.cons_succ] + refine Fin.cases ?_ (fun j ↦ ?_) i + · rw [incrementsMap_zero_apply] + rfl + · rw [ih (path 0) (Fin.tail path) j, Fin.tail, Fin.tail, ← Fin.succ_castSucc] + +/-- The increments of a finite coordinate path, in closed form. -/ +theorem incrementsMap_eq_cons {n : ℕ} (x : ℝ) (path : Fin (n + 1) → ℝ) : + incrementsMap x path = + Fin.cons (path 0 - x) (fun i : Fin n ↦ path i.succ - path i.castSucc) := by + funext i + refine Fin.cases ?_ (fun j ↦ ?_) i + · rw [incrementsMap_zero_apply, Fin.cons_zero] + · rw [incrementsMap_succ_apply, Fin.cons_succ] + +/-- Taking increments is measurable, jointly in the base point and the path. -/ +theorem measurable_incrementsMap {n : ℕ} : + Measurable (fun p : ℝ × (Fin n → ℝ) ↦ incrementsMap p.1 p.2) := by + cases n with + | zero => exact measurable_pi_lambda _ fun i ↦ i.elim0 + | succ n => + simp_rw [incrementsMap_eq_cons] + refine measurable_pi_iff.mpr fun i ↦ ?_ + refine Fin.cases ?_ (fun j ↦ ?_) i + · simp only [Fin.cons_zero] + fun_prop + · simp only [Fin.cons_succ] + fun_prop + +/-- The successive time increments of a finite family of times, the first one measured from +time zero. -/ +def timeIncrements : {n : ℕ} → (Fin n → NNReal) → (Fin n → NNReal) + | 0, _ => fun i ↦ i.elim0 + | _ + 1, s => Fin.cons (s 0) (timeIncrements (fun i ↦ s i.succ - s 0)) + +/-- The recursion defining the time increments. -/ +theorem timeIncrements_succ {n : ℕ} (s : Fin (n + 1) → NNReal) : + timeIncrements s = Fin.cons (s 0) (timeIncrements (fun i ↦ s i.succ - s 0)) := rfl + +/-- The first time increment is the first time itself. -/ +@[simp] +theorem timeIncrements_zero_apply {n : ℕ} (s : Fin (n + 1) → NNReal) : + timeIncrements s 0 = s 0 := rfl + +/-- For a monotone family of times, every time increment after the first is the length of the +corresponding interval. -/ +theorem timeIncrements_succ_apply : ∀ {n : ℕ} {s : Fin (n + 1) → NNReal}, Monotone s → + ∀ i : Fin n, timeIncrements s i.succ = s i.succ - s i.castSucc := by + intro n + induction n with + | zero => exact fun _ i ↦ i.elim0 + | succ n ih => + intro s hs i + have hs' : Monotone (fun i : Fin (n + 1) ↦ s i.succ - s 0) := fun a b hab ↦ + tsub_le_tsub_right (hs (Fin.succ_le_succ_iff.mpr hab)) _ + rw [timeIncrements_succ, Fin.cons_succ] + refine Fin.cases ?_ (fun j ↦ ?_) i + · rw [timeIncrements_zero_apply] + rfl + · rw [ih hs' j] + rw [← Fin.succ_castSucc, + tsub_tsub_tsub_cancel_right (hs (Fin.zero_le _))] + +/-- Reading a path at a finite family of times and taking increments is measurable. -/ +theorem measurable_incrementsMap_eval {n : ℕ} (s : Fin n → NNReal) (x : ℝ) : + Measurable (fun omega : ContinuousPath ℝ ↦ incrementsMap x (fun i ↦ omega (s i))) := + measurable_incrementsMap.comp (measurable_const.prodMk + (measurable_pi_lambda _ fun i ↦ ContinuousPath.measurable_coordinateProcess (s i))) + +/-- **The joint law of the increments of Brownian motion is a product of centred Gaussians.** +Reading the path of `brownianMotion x` at a monotone family of times and taking the increments, +the first one measured from the starting point `x`, gives independent centred Gaussians of +variances the successive time increments. -/ +theorem brownianMotion_map_incrementsMap : ∀ {n : ℕ} {s : Fin n → NNReal}, Monotone s → ∀ x : ℝ, + (brownianMotion x).map (fun omega ↦ incrementsMap x (fun i ↦ omega (s i))) = + Measure.pi (fun i ↦ gaussianReal 0 (timeIncrements s i)) := by + intro n + induction n with + | zero => + intro s _ x + have : IsProbabilityMeasure ((brownianMotion x).map + (fun omega ↦ incrementsMap x (fun i ↦ omega (s i)))) := + Measure.isProbabilityMeasure_map (measurable_incrementsMap_eval s x).aemeasurable + exact (Measure.pi_eq fun A _ ↦ by simp).symm + | succ n ih => + intro s hs x + have hs' : Monotone (fun i : Fin n ↦ s i.succ - s 0) := fun a b hab ↦ + tsub_le_tsub_right (hs (Fin.succ_le_succ_iff.mpr hab)) _ + have hPhi : Measurable (fun p : ℝ × ContinuousPath ℝ ↦ + @Fin.cons n (fun _ : Fin (n + 1) ↦ ℝ) (p.1 - x) + (incrementsMap p.1 (fun i : Fin n ↦ p.2 (s i.succ - s 0)))) := by + refine measurable_finCons.comp ((measurable_fst.sub measurable_const).prodMk ?_) + exact measurable_incrementsMap.comp (measurable_fst.prodMk + (measurable_pi_lambda _ fun i ↦ + (ContinuousPath.measurable_coordinateProcess (s i.succ - s 0)).comp measurable_snd)) + have hpair : Measurable (fun omega : ContinuousPath ℝ ↦ + (omega (s 0), ContinuousPath.shift (s 0) omega)) := + (ContinuousPath.measurable_coordinateProcess (s 0)).prodMk + (ContinuousPath.measurable_shift_fixed (s 0)) + have hfactor : (fun omega : ContinuousPath ℝ ↦ incrementsMap x (fun i ↦ omega (s i))) = + (fun p : ℝ × ContinuousPath ℝ ↦ + @Fin.cons n (fun _ : Fin (n + 1) ↦ ℝ) (p.1 - x) + (incrementsMap p.1 (fun i : Fin n ↦ p.2 (s i.succ - s 0)))) ∘ + (fun omega ↦ (omega (s 0), ContinuousPath.shift (s 0) omega)) := by + funext omega + have harg : (fun i : Fin n ↦ (ContinuousPath.shift (s 0) omega) (s i.succ - s 0)) = + Fin.tail (fun i ↦ omega (s i)) := by + funext i + show omega (s 0 + (s i.succ - s 0)) = omega (s i.succ) + rw [add_tsub_cancel_of_le (hs (Fin.zero_le _))] + show incrementsMap x (fun i ↦ omega (s i)) = + Fin.cons (omega (s 0) - x) + (incrementsMap (omega (s 0)) + (fun i : Fin n ↦ (ContinuousPath.shift (s 0) omega) (s i.succ - s 0))) + rw [incrementsMap_succ, harg] + rw [hfactor, ← Measure.map_map hPhi hpair, brownianMotion_map_prodMk_shift] + refine (Measure.pi_eq fun A hA ↦ ?_).symm + have hpiA : MeasurableSet (Set.univ.pi A) := MeasurableSet.univ_pi hA + rw [Measure.map_apply hPhi hpiA, Measure.compProd_apply (hPhi hpiA)] + have hsplit : ∀ y : ℝ, brownianMotion y (Prod.mk y ⁻¹' + ((fun p : ℝ × ContinuousPath ℝ ↦ + @Fin.cons n (fun _ : Fin (n + 1) ↦ ℝ) (p.1 - x) + (incrementsMap p.1 (fun i : Fin n ↦ p.2 (s i.succ - s 0)))) ⁻¹' Set.univ.pi A)) = + Set.indicator ((fun u : ℝ ↦ u - x) ⁻¹' (A 0)) + (fun _ ↦ ∏ i : Fin n, + gaussianReal 0 (timeIncrements (fun i : Fin n ↦ s i.succ - s 0) i) (A i.succ)) y := by + intro y + have hmem : ∀ eta : ContinuousPath ℝ, + (Prod.mk y eta ∈ ((fun p : ℝ × ContinuousPath ℝ ↦ + @Fin.cons n (fun _ : Fin (n + 1) ↦ ℝ) (p.1 - x) + (incrementsMap p.1 (fun i : Fin n ↦ p.2 (s i.succ - s 0)))) ⁻¹' Set.univ.pi A)) ↔ + (y - x ∈ A 0 ∧ + incrementsMap y (fun i : Fin n ↦ eta (s i.succ - s 0)) ∈ + Set.univ.pi (fun i : Fin n ↦ A i.succ)) := by + intro eta + simp only [Set.mem_preimage, Set.mem_univ_pi] + rw [Fin.forall_fin_succ] + simp only [Fin.cons_zero, Fin.cons_succ] + by_cases hy : y - x ∈ A 0 + · have hy' : y ∈ (fun u : ℝ ↦ u - x) ⁻¹' (A 0) := hy + rw [Set.indicator_of_mem hy'] + have hset : (Prod.mk y ⁻¹' + ((fun p : ℝ × ContinuousPath ℝ ↦ + @Fin.cons n (fun _ : Fin (n + 1) ↦ ℝ) (p.1 - x) + (incrementsMap p.1 (fun i : Fin n ↦ p.2 (s i.succ - s 0)))) ⁻¹' Set.univ.pi A)) = + (fun eta : ContinuousPath ℝ ↦ + incrementsMap y (fun i : Fin n ↦ eta (s i.succ - s 0))) ⁻¹' + (Set.univ.pi (fun i : Fin n ↦ A i.succ)) := by + ext eta + rw [Set.mem_preimage, hmem eta] + simp only [Set.mem_preimage, hy, true_and] + rw [hset, ← Measure.map_apply + (measurable_incrementsMap_eval (fun i : Fin n ↦ s i.succ - s 0) y) + (MeasurableSet.univ_pi fun i ↦ hA i.succ), ih hs' y, Measure.pi_pi] + · have hy' : y ∉ (fun u : ℝ ↦ u - x) ⁻¹' (A 0) := hy + rw [Set.indicator_of_notMem hy'] + have hset : (Prod.mk y ⁻¹' + ((fun p : ℝ × ContinuousPath ℝ ↦ + @Fin.cons n (fun _ : Fin (n + 1) ↦ ℝ) (p.1 - x) + (incrementsMap p.1 (fun i : Fin n ↦ p.2 (s i.succ - s 0)))) ⁻¹' Set.univ.pi A)) = + (∅ : Set (ContinuousPath ℝ)) := by + ext eta + rw [Set.mem_preimage, hmem eta] + simp only [Set.mem_empty_iff_false, iff_false, not_and, hy, IsEmpty.forall_iff] + rw [hset, measure_empty] + have hsub : Measurable (fun u : ℝ ↦ u - x) := by fun_prop + simp_rw [hsplit] + rw [lintegral_indicator (hsub (hA 0)), setLIntegral_const, + ← Measure.map_apply hsub (hA 0), + gaussianReal_map_sub_const x, sub_self, Fin.prod_univ_succ, timeIncrements_zero_apply] + exact mul_comm _ _ + +end Increments + +section IndependentIncrements + +/-- Dropping the first coordinate of a finite coordinate path is measurable. -/ +theorem measurable_finTail {n : ℕ} : + Measurable (Fin.tail : (Fin (n + 1) → ℝ) → (Fin n → ℝ)) := + measurable_pi_lambda _ fun i ↦ measurable_pi_apply i.succ + +/-- Dropping the first coordinate of a product of probability measures gives the product of the +remaining ones. -/ +theorem map_finTail_pi {n : ℕ} (nu : Fin (n + 1) → Measure ℝ) + [∀ i, IsProbabilityMeasure (nu i)] : + (Measure.pi nu).map Fin.tail = Measure.pi (fun i : Fin n ↦ nu i.succ) := by + refine (Measure.pi_eq fun A hA ↦ ?_).symm + have hpre : (Fin.tail : (Fin (n + 1) → ℝ) → (Fin n → ℝ)) ⁻¹' (Set.univ.pi A) + = Set.univ.pi (@Fin.cons n (fun _ ↦ Set ℝ) Set.univ A) := by + ext u + simp only [Set.mem_preimage, Set.mem_univ_pi] + rw [Fin.forall_fin_succ] + simp [Fin.tail] + rw [Measure.map_apply measurable_finTail (MeasurableSet.univ_pi hA), hpre, Measure.pi_pi, + Fin.prod_univ_succ] + simp + +/-- **The increments of Brownian motion over a monotone family of times are independent +centred Gaussians.** -/ +theorem brownianMotion_map_increments {n : ℕ} {t : Fin (n + 1) → NNReal} (ht : Monotone t) + (x : ℝ) : + (brownianMotion x).map + (fun (omega : ContinuousPath ℝ) (i : Fin n) ↦ omega (t i.succ) - omega (t i.castSucc)) = + Measure.pi (fun i : Fin n ↦ gaussianReal 0 (t i.succ - t i.castSucc)) := by + have hfac : (fun (omega : ContinuousPath ℝ) (i : Fin n) ↦ + omega (t i.succ) - omega (t i.castSucc)) = + Fin.tail ∘ (fun omega ↦ incrementsMap x (fun i ↦ omega (t i))) := by + funext omega i + exact (incrementsMap_succ_apply x (fun j ↦ omega (t j)) i).symm + rw [hfac, ← Measure.map_map measurable_finTail (measurable_incrementsMap_eval t x), + brownianMotion_map_incrementsMap ht x, map_finTail_pi] + congr 1 + funext i + rw [timeIncrements_succ_apply ht i] + +/-- Every increment of Brownian motion is a centred Gaussian of variance the elapsed time. -/ +theorem brownianMotion_map_increment (x : ℝ) (a b : NNReal) (hab : a ≤ b) : + (brownianMotion x).map (fun omega ↦ omega b - omega a) = gaussianReal 0 (b - a) := by + have ht : Monotone (![a, b]) := by + intro i j hij + fin_cases i <;> fin_cases j <;> simp_all + have h := brownianMotion_map_increments (n := 1) (t := ![a, b]) ht x + have hmeas : Measurable (fun (omega : ContinuousPath ℝ) (i : Fin 1) ↦ + omega ((![a, b] : Fin 2 → NNReal) i.succ) - omega ((![a, b] : Fin 2 → NNReal) i.castSucc)) := + measurable_pi_lambda _ fun i ↦ + (ContinuousPath.measurable_coordinateProcess _).sub + (ContinuousPath.measurable_coordinateProcess _) + have hproj := congrArg (fun mu : Measure (Fin 1 → ℝ) ↦ mu.map (Function.eval (0 : Fin 1))) h + have hpres := measurePreserving_eval (fun i : Fin 1 ↦ gaussianReal 0 + ((![a, b] : Fin 2 → NNReal) i.succ - (![a, b] : Fin 2 → NNReal) i.castSucc)) 0 + rw [Measure.map_map (measurable_pi_apply _) hmeas, hpres.map_eq] at hproj + exact hproj + +/-- A process has independent increments when, for every finite monotone family of times, the +increments over the consecutive intervals of that family are independent. -/ +def HasIndepIncrements {T Omega E : Type*} [Preorder T] [MeasurableSpace Omega] + [MeasurableSpace E] [Sub E] (X : T → Omega → E) (P : Measure Omega) : Prop := + ∀ (n : ℕ) (t : Fin (n + 1) → T), Monotone t → + iIndepFun (fun (i : Fin n) (omega : Omega) ↦ X (t i.succ) omega - X (t i.castSucc) omega) P + +/-- **Brownian motion has independent increments.** -/ +theorem hasIndepIncrements_brownianMotion (x : ℝ) : + HasIndepIncrements (fun (t : NNReal) (omega : ContinuousPath ℝ) ↦ omega t - x) + (brownianMotion x) := by + intro n t ht + have hsimp : (fun (i : Fin n) (omega : ContinuousPath ℝ) ↦ + (omega (t i.succ) - x) - (omega (t i.castSucc) - x)) = + fun (i : Fin n) (omega : ContinuousPath ℝ) ↦ omega (t i.succ) - omega (t i.castSucc) := by + funext i omega + ring + show iIndepFun (fun (i : Fin n) (omega : ContinuousPath ℝ) ↦ + (omega (t i.succ) - x) - (omega (t i.castSucc) - x)) (brownianMotion x) + rw [hsimp] + have hmeasi : ∀ i : Fin n, Measurable (fun omega : ContinuousPath ℝ ↦ + omega (t i.succ) - omega (t i.castSucc)) := fun i ↦ + (ContinuousPath.measurable_coordinateProcess _).sub + (ContinuousPath.measurable_coordinateProcess _) + rw [iIndepFun_iff_map_fun_eq_pi_map (fun i ↦ (hmeasi i).aemeasurable), + brownianMotion_map_increments ht x] + congr 1 + funext i + exact (brownianMotion_map_increment x _ _ (ht (Fin.castSucc_lt_succ (i := i)).le)).symm + +end IndependentIncrements + +section Identification + +/-- A real process is a Brownian motion when its one-time marginals are the centred Gaussians of +variance the elapsed time, it has independent increments, and almost every path is continuous. + +This is the characterization of a Brownian motion by Gaussian marginals and independent +increments, which Mathlib proves equivalent to its projective-family definition of +`IsBrownianReal` (`HasIndepIncrements.isPreBrownianReal_of_hasLaw` and its converse lemmas); +that definition is not available at the pinned revision. -/ +structure IsBrownianReal {Omega : Type*} [MeasurableSpace Omega] + (X : NNReal → Omega → ℝ) (P : Measure Omega) : Prop where + /-- At every time the value has the centred Gaussian law of variance that time. -/ + hasLaw_eval : ∀ t : NNReal, HasLaw (X t) (gaussianReal 0 t) P + /-- The increments over disjoint consecutive intervals are independent. -/ + hasIndepIncrements : HasIndepIncrements X P + /-- Almost every trajectory is continuous. -/ + cont : ∀ᵐ omega ∂P, Continuous fun t ↦ X t omega + +/-- **The canonical process under `brownianMotion x`, recentred at its starting point, is a +Brownian motion.** -/ +theorem isBrownianReal_brownianMotion (x : ℝ) : + IsBrownianReal (fun (t : NNReal) (omega : ContinuousPath ℝ) ↦ omega t - x) + (brownianMotion x) where + hasLaw_eval t := by + refine ⟨((ContinuousPath.measurable_coordinateProcess t).sub measurable_const).aemeasurable, ?_⟩ + have hmeas : Measurable (fun omega : ContinuousPath ℝ ↦ omega t) := + ContinuousPath.measurable_coordinateProcess t + have hsub : Measurable (fun u : ℝ ↦ u - x) := by fun_prop + rw [show (fun omega : ContinuousPath ℝ ↦ omega t - x) + = (fun u : ℝ ↦ u - x) ∘ (fun omega : ContinuousPath ℝ ↦ omega t) from rfl, + ← Measure.map_map hsub hmeas, brownianMotion_map_eval, gaussianReal_map_sub_const x, + sub_self] + hasIndepIncrements := hasIndepIncrements_brownianMotion x + cont := Filter.Eventually.of_forall fun omega ↦ omega.continuous.sub continuous_const + +end Identification + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/Drift.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/Drift.lean new file mode 100644 index 0000000000..f02f75f419 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/Drift.lean @@ -0,0 +1,244 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Main + +/-! +# The deterministic drift semigroup and its continuous-path process + +On a finite-dimensional real normed space the transition semigroup that translates by `t • v` in +time `t` is a conservative Feller semigroup satisfying the Kolmogorov moment criterion with +exponents `p = q = 2` and constant `‖v‖²`. The existence-and-uniqueness theorem of +`MarkovProcess.Main` therefore applies, and the process it produces is identified: from every +starting point `x` its law is the Dirac mass at the straight line `t ↦ x + t • v`. + +Together with `MarkovProcess.Examples.Identity` this shows that the hypotheses of the main +theorem are satisfiable by a semigroup that genuinely moves. Nothing here is claimed about a +semigroup with a nonzero diffusion part; for that see `MarkovProcess.Examples.HeatSemigroup`. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal ZeroAtInfty + +namespace MarkovProcess + +noncomputable section + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [FiniteDimensional ℝ E] + [MeasurableSpace E] [BorelSpace E] + +section Definition + +omit [FiniteDimensional ℝ E] in +/-- Translation by `t • v` is measurable. -/ +theorem measurable_driftTranslate (v : E) (t : NNReal) : + Measurable (fun x : E ↦ x + (t : ℝ) • v) := by + fun_prop + +/-- The deterministic drift semigroup with velocity `v`: at time `t` it moves every point by +`t • v`. -/ +def driftSemigroup (v : E) : SubMarkovKernelSemigroup E where + kernel := fun t ↦ Kernel.deterministic (fun x ↦ x + (t : ℝ) • v) (measurable_driftTranslate v t) + measurable_kernel := by + have hg : Measurable (fun p : NNReal × E ↦ p.2 + (p.1 : ℝ) • v) := by fun_prop + exact (Kernel.deterministic (fun p : NNReal × E ↦ p.2 + (p.1 : ℝ) • v) hg).measurable + kernel_zero := by + refine Kernel.ext fun x ↦ ?_ + rw [Kernel.deterministic_apply, Kernel.id_apply, NNReal.coe_zero, zero_smul, add_zero] + kernel_add := fun s t ↦ by + rw [Kernel.deterministic_comp_deterministic] + refine Kernel.ext fun x ↦ ?_ + rw [Kernel.deterministic_apply, Kernel.deterministic_apply, Function.comp_apply, + NNReal.coe_add, add_smul, add_assoc] + isSubMarkovKernel := fun _ ↦ IsSubMarkovKernel.of_isMarkovKernel _ + +/-- The transition measure of the drift semigroup is the Dirac mass at the translated point. -/ +theorem driftSemigroup_apply (v : E) (t : NNReal) (x : E) : + (driftSemigroup v) t x = Measure.dirac (x + (t : ℝ) • v) := rfl + +/-- The drift semigroup is conservative: every transition measure has total mass one. -/ +theorem isConservative_driftSemigroup (v : E) : (driftSemigroup v).IsConservative := by + intro t x + rw [driftSemigroup_apply] + exact measure_univ + +end Definition + +section Feller + +/-- Integrating a `C₀` function against the drift semigroup evaluates it at the translated +point. -/ +theorem kernelIntegral_driftSemigroup_apply (v : E) (t : NNReal) (f : C₀(E, ℝ)) (x : E) : + kernelIntegral ((driftSemigroup v) t) f x = f (x + (t : ℝ) • v) := by + rw [kernelIntegral, driftSemigroup_apply] + exact integral_dirac' (f : E → ℝ) _ f.continuous.stronglyMeasurable + +/-- The `C₀` kernel integral of the drift semigroup is the translate of the function. -/ +theorem kernelIntegral_driftSemigroup (v : E) (t : NNReal) (f : C₀(E, ℝ)) : + kernelIntegral ((driftSemigroup v) t) f = fun x ↦ f (x + (t : ℝ) • v) := + funext (kernelIntegral_driftSemigroup_apply v t f) + +/-- The drift semigroup maps `C₀` into itself: translating a continuous function vanishing at +infinity gives another one, because translation is a cocompact map. -/ +theorem mapsC0_driftSemigroup (v : E) : (driftSemigroup v).MapsC0 := by + intro t f + rw [kernelIntegral_driftSemigroup] + refine ⟨f.continuous.comp (continuous_id.add continuous_const), ?_⟩ + have htranslate : Filter.Tendsto (fun x : E ↦ x + (t : ℝ) • v) + (Filter.cocompact E) (Filter.cocompact E) := + CocompactMapClass.cocompact_tendsto + ((Homeomorph.addRight ((t : ℝ) • v)).toCocompactMap) + exact (f.zero_at_infty').comp htranslate + +/-- The `C₀` orbits of the drift semigroup are continuous in time: a `C₀` function is uniformly +continuous, and the two translates at times `a` and `b` differ pointwise by a displacement of +size `|a - b| ‖v‖`. -/ +theorem hasContinuousC0Orbits_driftSemigroup (v : E) : + (driftSemigroup v).HasContinuousC0Orbits (mapsC0_driftSemigroup v) := by + intro f + rw [Metric.continuous_iff] + intro b eps heps + obtain ⟨delta, hdelta, hf⟩ := Metric.uniformContinuous_iff.mp + (ZeroAtInftyContinuousMap.uniformContinuous f) (eps / 2) (half_pos heps) + have hv : (0 : ℝ) < ‖v‖ + 1 := by positivity + refine ⟨delta / (‖v‖ + 1), div_pos hdelta hv, fun a hab ↦ ?_⟩ + have hab' : |(a : ℝ) - (b : ℝ)| < delta / (‖v‖ + 1) := by + rw [← NNReal.dist_eq] + exact hab + have hkey : ∀ x : E, dist (f (x + (a : ℝ) • v)) (f (x + (b : ℝ) • v)) ≤ eps / 2 := by + intro x + refine le_of_lt (hf ?_) + have hsub : (x + (a : ℝ) • v) - (x + (b : ℝ) • v) = ((a : ℝ) - (b : ℝ)) • v := by + rw [sub_smul] + abel + rw [dist_eq_norm, hsub, norm_smul, Real.norm_eq_abs] + calc |(a : ℝ) - (b : ℝ)| * ‖v‖ ≤ |(a : ℝ) - (b : ℝ)| * (‖v‖ + 1) := + mul_le_mul_of_nonneg_left (by linarith only []) (abs_nonneg _) + _ < delta / (‖v‖ + 1) * (‖v‖ + 1) := mul_lt_mul_of_pos_right hab' hv + _ = delta := div_mul_cancel₀ delta (ne_of_gt hv) + have hle : dist ((driftSemigroup v).c0Operator (mapsC0_driftSemigroup v) a f) + ((driftSemigroup v).c0Operator (mapsC0_driftSemigroup v) b f) ≤ eps / 2 := by + rw [← ZeroAtInftyContinuousMap.dist_toBCF_eq_dist] + refine (BoundedContinuousFunction.dist_le (le_of_lt (half_pos heps))).2 fun x ↦ ?_ + show dist ((driftSemigroup v).c0Operator (mapsC0_driftSemigroup v) a f x) + ((driftSemigroup v).c0Operator (mapsC0_driftSemigroup v) b f x) ≤ eps / 2 + rw [SubMarkovKernelSemigroup.c0Operator_apply, SubMarkovKernelSemigroup.c0Operator_apply, + kernelIntegral_driftSemigroup_apply, kernelIntegral_driftSemigroup_apply] + exact hkey x + linarith only [hle, heps] + +/-- The drift semigroup is a Feller semigroup. -/ +theorem isFellerKernelSemigroup_driftSemigroup (v : E) : + (driftSemigroup v).IsFellerKernelSemigroup := + ⟨mapsC0_driftSemigroup v, hasContinuousC0Orbits_driftSemigroup v⟩ + +end Feller + +section Moments + +/-- The drift semigroup satisfies the Kolmogorov moment criterion with `p = q = 2` and constant +`‖v‖²`: the displacement over time `h` is exactly `h ‖v‖`. -/ +theorem hasKolmogorovMoments_driftSemigroup (v : E) : + (driftSemigroup v).HasKolmogorovMoments 2 2 (‖v‖₊ ^ 2) := by + refine ⟨two_pos, one_lt_two, fun h y ↦ ?_⟩ + have hmeas : Measurable (fun z : E ↦ edist z y ^ (2 : ℝ)) := + (measurable_edist_left (x := y)).pow_const 2 + have hnn : nndist (y + (h : ℝ) • v) y = h * ‖v‖₊ := by + rw [nndist_eq_nnnorm, add_sub_cancel_left, nnnorm_smul] + congr 1 + apply NNReal.coe_injective + rw [coe_nnnorm, Real.norm_of_nonneg h.coe_nonneg] + rw [driftSemigroup_apply, lintegral_dirac' _ hmeas, edist_nndist, hnn, + ENNReal.rpow_two, ENNReal.rpow_two, ENNReal.coe_mul, mul_pow, ENNReal.coe_pow] + exact le_of_eq (mul_comm _ _) + +end Moments + +section Process + +/-- The drift semigroup is Kolmogorov regular, by its moment bound. -/ +theorem kolmogorovRegular_driftSemigroup (v : E) : + (driftSemigroup v).KolmogorovRegular (isConservative_driftSemigroup v) := + SubMarkovKernelSemigroup.KolmogorovRegular.of_hasKolmogorovMoments _ + (isConservative_driftSemigroup v) (hasKolmogorovMoments_driftSemigroup v) + +/-- **The main theorem, applied to the drift semigroup.** There is exactly one Markov kernel +from the state space to continuous paths whose finite-dimensional distributions are those of the +deterministic drift with velocity `v`. -/ +theorem existsUnique_continuousProcess_driftSemigroup (v : E) : + ∃! Q : Kernel E (ContinuousPath E), IsMarkovKernel Q ∧ + ∀ I : Finset NNReal, + Q.map (ContinuousPath.finsetEvaluation I) = + SubMarkovKernelSemigroup.finiteSetKernel (driftSemigroup v) I := + (isFellerKernelSemigroup_driftSemigroup v).existsUnique_continuousProcess_of_hasKolmogorovMoments + (driftSemigroup v) (isConservative_driftSemigroup v) (hasKolmogorovMoments_driftSemigroup v) + +/-- The straight line started at `x` with velocity `v`, as a continuous path. -/ +def driftPath (v : E) (x : E) : ContinuousPath E where + toFun := fun t ↦ x + (t : ℝ) • v + continuous_toFun := by fun_prop + +omit [FiniteDimensional ℝ E] [MeasurableSpace E] [BorelSpace E] in +/-- The straight line, evaluated at a time. -/ +@[simp] +theorem driftPath_apply (v : E) (x : E) (t : NNReal) : + driftPath v x t = x + (t : ℝ) • v := rfl + +private theorem ae_eq_driftPath (v : E) (x : E) : + (fun omega : ContinuousPath E ↦ omega) =ᵐ[ + SubMarkovKernelSemigroup.IsConservative.continuousProcess (driftSemigroup v) + (isConservative_driftSemigroup v) x] + fun _ ↦ driftPath v x := by + set mu := SubMarkovKernelSemigroup.IsConservative.continuousProcess (driftSemigroup v) + (isConservative_driftSemigroup v) x with hmu + have hcoord : ∀ q : DenseTime, ∀ᵐ omega ∂mu, + omega (DenseTime.castOrderEmbedding q) = driftPath v x (DenseTime.castOrderEmbedding q) := by + intro q + have hmeas : Measurable + (fun omega : ContinuousPath E ↦ omega (DenseTime.castOrderEmbedding q)) := + ContinuousPath.measurable_coordinateProcess (alpha := E) _ + have hmap := SubMarkovKernelSemigroup.IsConservative.continuousProcess_map_eval + (driftSemigroup v) (isConservative_driftSemigroup v) (kolmogorovRegular_driftSemigroup v) q + have hmapx : Measure.map (fun omega : ContinuousPath E ↦ + omega (DenseTime.castOrderEmbedding q)) mu = + Measure.dirac (driftPath v x (DenseTime.castOrderEmbedding q)) := by + rw [hmu, ← Kernel.map_apply _ hmeas, hmap, driftSemigroup_apply, driftPath_apply] + set y := driftPath v x (DenseTime.castOrderEmbedding q) with hy + have hsingleton : MeasurableSet ({y}ᶜ : Set E) := + (isClosed_singleton (x := y)).measurableSet.compl + show mu ((fun omega : ContinuousPath E ↦ + omega (DenseTime.castOrderEmbedding q)) ⁻¹' ({y}ᶜ : Set E)) = 0 + rw [← Measure.map_apply hmeas hsingleton, hmapx, Measure.dirac_apply' y hsingleton, + Set.indicator_of_notMem (by simp only [Set.mem_compl_iff, Set.mem_singleton_iff, + not_true_eq_false, not_false_eq_true])] + have hall : ∀ᵐ omega ∂mu, ∀ q : DenseTime, + omega (DenseTime.castOrderEmbedding q) = + driftPath v x (DenseTime.castOrderEmbedding q) := ae_all_iff.mpr hcoord + filter_upwards [hall] with omega homega + apply ContinuousPath.denseRestriction_injective + funext q + rw [ContinuousPath.denseRestriction_apply, ContinuousPath.denseRestriction_apply, homega q] + +/-- **The continuous-path process of the drift semigroup is the straight-line path.** From every +starting point `x`, the law of the process is the Dirac mass at the path `t ↦ x + t • v`. -/ +theorem continuousProcess_driftSemigroup_eq (v : E) (x : E) : + SubMarkovKernelSemigroup.IsConservative.continuousProcess (driftSemigroup v) + (isConservative_driftSemigroup v) x = + Measure.dirac (driftPath v x) := by + set mu := SubMarkovKernelSemigroup.IsConservative.continuousProcess (driftSemigroup v) + (isConservative_driftSemigroup v) x with hmu + have hprob : IsProbabilityMeasure mu := by + rw [hmu] + infer_instance + calc mu = mu.map id := (Measure.map_id).symm + _ = mu.map (fun _ ↦ driftPath v x) := Measure.map_congr (ae_eq_driftPath v x) + _ = mu Set.univ • Measure.dirac (driftPath v x) := Measure.map_const _ _ + _ = Measure.dirac (driftPath v x) := by rw [measure_univ, one_smul] + +end Process + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatGenerator.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatGenerator.lean new file mode 100644 index 0000000000..eb365135df --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatGenerator.lean @@ -0,0 +1,426 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +import Mathlib.Analysis.Calculus.MeanValue +import Mathlib.Analysis.Calculus.IteratedDeriv.Lemmas + +/-! +# Gaussian averages and half the Laplacian on the line + +Half the second derivative — half the Laplacian in one dimension — is the infinitesimal +generator of the Gaussian averages of a twice continuously differentiable function whose value +and second derivative vanish at infinity. Writing `gaussianReal x t` for the normal law on the +line with mean `x` and variance `t`, and `x ↦ ∫ f d gaussianReal x t` for the Gaussian average +of `f` at scale `t` (at `t = 0` it is `f` itself), the difference quotient +`t⁻¹ (∫ f d gaussianReal x t - f x)` converges to `f'' x / 2` as `t → 0⁺`, uniformly in the +centre `x`. The argument is the classical one: rescaling by `√t` reduces every average to the +standard normal law, and a second-order Taylor expansion at `x` splits the increment into a term +of first order whose Gaussian mean vanishes, a term of second order whose Gaussian mean is +`t f'' x / 2`, and a remainder bounded by the modulus of continuity of `f''` on the bulk of the +law and by its fourth moment on the tail. Neither bound depends on `x`, whence the uniformity. + +Main results: + +* `abs_sub_taylor_two_le`, the second-order Taylor estimate with a modulus: the second-order + Taylor polynomial of `f` at `x` approximates `f (x + h)` to within `C h²` as soon as the + increment of `f''` over the segment from `x` to `x + h` is at most `C`; +* `tendstoUniformly_gaussianAverage_sub_div`, the limit above, as a `TendstoUniformly` + statement; +* `gaussianAverage`, the Gaussian average of a continuous function vanishing at infinity: the + `C₀` action of the heat semigroup of `Examples/HeatSemigroup.lean`, and + `tendsto_gaussianAverage_sub_div`, the same limit read as convergence in the `C₀` norm; +* `c0Semigroup_heatSemigroup_apply`, `tendsto_differenceQuotient_heatSemigroup`, + `mem_generatorDomain_heatSemigroup` and `generator_heatSemigroup`: twice continuously + differentiable `C₀` functions with `C₀` second derivative lie in the generator domain of the + `C₀` semigroup of the heat semigroup, and the generator is half the second derivative there, + in the sense of `Semigroup/Generator.lean`. + +No partial differential equation is solved, the generator domain is not characterized (only +contained), and nothing is claimed in dimension greater than one or for a function outside the +stated smoothness class. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped NNReal ZeroAtInfty + +namespace MarkovProcess + +noncomputable section + +section Taylor + +variable {f : ℝ → ℝ} + +/-- **Second-order Taylor estimate with a modulus.** If the increment of the second derivative +of `f` is at most `C` on the segment from `x` to `x + h`, then the second-order Taylor +polynomial of `f` at `x` approximates `f (x + h)` to within `C h²`. -/ +theorem abs_sub_taylor_two_le (hf : ContDiff ℝ 2 f) (x h C : ℝ) + (hC : ∀ s ∈ Set.Icc (0 : ℝ) 1, |iteratedDeriv 2 f (x + s * h) - iteratedDeriv 2 f x| ≤ C) : + |f (x + h) - f x - h * deriv f x - h ^ 2 / 2 * iteratedDeriv 2 f x| ≤ C * h ^ 2 := by + have hd2 : ContDiff ℝ 1 (deriv f) := hf.deriv' + have hdf : Differentiable ℝ f := hf.differentiable (by norm_num) + have hddf : Differentiable ℝ (deriv f) := hd2.differentiable (by norm_num) + have hiter : ∀ y : ℝ, deriv (deriv f) y = iteratedDeriv 2 f y := by + intro y; rw [iteratedDeriv_succ, iteratedDeriv_one] + set c := iteratedDeriv 2 f x with hcdef + have hinner : ∀ s : ℝ, HasDerivAt (fun s : ℝ ↦ x + s * h) h s := by + intro s + simpa using (((hasDerivAt_id s).mul_const h).const_add x) + set F : ℝ → ℝ := + fun s ↦ f (x + s * h) - f x - s * (h * deriv f x) - s ^ 2 * (h ^ 2 * c / 2) with hFdef + set G : ℝ → ℝ := fun s ↦ h * deriv f (x + s * h) - h * deriv f x - s * (h ^ 2 * c) with hGdef + have hFderiv : ∀ s : ℝ, HasDerivAt F (G s) s := by + intro s + have h1 : HasDerivAt (fun s : ℝ ↦ f (x + s * h)) (deriv f (x + s * h) * h) s := + (hdf (x + s * h)).hasDerivAt.comp s (hinner s) + have h2 : HasDerivAt (fun s : ℝ ↦ s * (h * deriv f x)) (h * deriv f x) s := by + simpa using (hasDerivAt_id s).mul_const (h * deriv f x) + have h3 : HasDerivAt (fun s : ℝ ↦ s ^ 2 * (h ^ 2 * c / 2)) (2 * s * (h ^ 2 * c / 2)) s := by + have hp : HasDerivAt (fun s : ℝ ↦ s ^ 2) (2 * s) s := by simpa using hasDerivAt_pow 2 s + exact hp.mul_const _ + have hsum := ((h1.sub_const (f x)).sub h2).sub h3 + convert hsum using 1 + all_goals first | rfl | ring + have hGderiv : ∀ s : ℝ, HasDerivAt G (h ^ 2 * (iteratedDeriv 2 f (x + s * h) - c)) s := by + intro s + have h1 := (hddf (x + s * h)).hasDerivAt.comp s (hinner s) + simp only [Function.comp_def, hiter] at h1 + have h2 : HasDerivAt (fun s : ℝ ↦ s * (h ^ 2 * c)) (h ^ 2 * c) s := by + simpa using (hasDerivAt_id s).mul_const (h ^ 2 * c) + have hsum := ((h1.const_mul h).sub_const (h * deriv f x)).sub h2 + convert hsum using 1 + all_goals first | rfl | ring + have hCnn : 0 ≤ C := by + have h0 := hC 0 (by norm_num) + rw [zero_mul, add_zero, ← hcdef, sub_self, abs_zero] at h0 + exact h0 + have hconv : Convex ℝ (Set.Icc (0 : ℝ) 1) := convex_Icc 0 1 + have hG0 : G 0 = 0 := by simp [hGdef] + have hF0 : F 0 = 0 := by simp [hFdef] + have hGbound : ∀ s ∈ Set.Icc (0 : ℝ) 1, ‖G s‖ ≤ C * h ^ 2 := by + intro s hs + have hkey : ‖G s - G 0‖ ≤ C * h ^ 2 * ‖s - 0‖ := by + refine hconv.norm_image_sub_le_of_norm_hasDerivWithin_le + (fun u _ ↦ (hGderiv u).hasDerivWithinAt) (fun u hu ↦ ?_) (by norm_num) hs + rw [Real.norm_eq_abs, abs_mul, abs_of_nonneg (sq_nonneg h)] + calc h ^ 2 * |iteratedDeriv 2 f (x + u * h) - c| ≤ h ^ 2 * C := + mul_le_mul_of_nonneg_left (hC u hu) (sq_nonneg h) + _ = C * h ^ 2 := by ring + rw [hG0, sub_zero] at hkey + refine hkey.trans ?_ + rw [Real.norm_eq_abs, sub_zero, abs_of_nonneg hs.1] + nlinarith [mul_nonneg hCnn (sq_nonneg h), hs.1, hs.2] + have hFbound : ‖F 1 - F 0‖ ≤ C * h ^ 2 * ‖(1 : ℝ) - 0‖ := + hconv.norm_image_sub_le_of_norm_hasDerivWithin_le + (fun u _ ↦ (hFderiv u).hasDerivWithinAt) hGbound (by norm_num) (by norm_num) + rw [hF0, sub_zero, Real.norm_eq_abs] at hFbound + simp only [hFdef, one_mul, one_pow] at hFbound + calc |f (x + h) - f x - h * deriv f x - h ^ 2 / 2 * c| + = |f (x + h) - f x - 1 * (h * deriv f x) - 1 * (h ^ 2 * c / 2)| := by ring_nf + _ ≤ C * h ^ 2 * ‖(1 : ℝ) - 0‖ := by simpa using hFbound + _ = C * h ^ 2 := by norm_num + +end Taylor + +section Gaussian + +/-- All polynomial moments of the standard normal law are finite. -/ +private theorem integrable_pow_gaussian (n : ℕ) : + Integrable (fun z : ℝ ↦ z ^ n) (gaussianReal 0 1) := + integrable_pow_of_mem_interior_integrableExpSet (by simp) n + +/-- The first moment of the standard normal law vanishes. -/ +private theorem integral_id_gaussian : ∫ z : ℝ, z ∂(gaussianReal 0 1) = 0 := + integral_id_gaussianReal + +/-- The second moment of the standard normal law is one. -/ +private theorem integral_sq_gaussian : ∫ z : ℝ, z ^ 2 ∂(gaussianReal 0 1) = 1 := by + have hvar : Var[fun z : ℝ ↦ z; gaussianReal 0 1] = ((1 : ℝ≥0) : ℝ) := + variance_fun_id_gaussianReal + rw [variance_eq_integral (by fun_prop), integral_id_gaussianReal] at hvar + simpa using hvar + +/-- The fourth moment of the standard normal law. -/ +private def gaussianMoment4 : ℝ := ∫ z : ℝ, z ^ 4 ∂(gaussianReal 0 1) + +private theorem gaussianMoment4_nonneg : 0 ≤ gaussianMoment4 := + integral_nonneg fun z ↦ by positivity + +/-- The Gaussian average, read on the standard normal law. -/ +private theorem integral_gaussian_eq (g : ℝ → ℝ) (hg : Continuous g) (x : ℝ) (t : ℝ≥0) : + ∫ y, g y ∂gaussianReal x t = ∫ z, g (x + Real.sqrt t * z) ∂(gaussianReal 0 1) := by + rw [gaussianReal_eq_map_add_sqrt_mul x t, integral_map (by fun_prop) hg.aestronglyMeasurable] + +end Gaussian + +section Estimate + +variable {f : ℝ → ℝ} + +/-- A pure-algebra step: away from the origin a constant is dominated by a quadratic. -/ +private theorem le_mul_sq_div {M a b : ℝ} (hM : 0 ≤ M) (hb : 0 < b) (hab : b ≤ |a|) : + M ≤ M * a ^ 2 / b ^ 2 := by + have hsq : b ^ 2 ≤ a ^ 2 := by nlinarith [sq_abs a, abs_nonneg a] + rw [le_div_iff₀ (by positivity)] + nlinarith + +/-- **The quantitative estimate.** If the second derivative of `f` is bounded by `M` and varies +by at most `ε` over distances smaller than `δ`, then the Gaussian difference quotient at scale +`t` differs from half the second derivative by at most `ε` plus a term of order `t`, uniformly +in the centre `x`. -/ +private theorem abs_gaussianQuotient_sub_le (hf : ContDiff ℝ 2 f) {B M ε δ : ℝ} + (hB : ∀ y, |f y| ≤ B) (hM : ∀ y, |iteratedDeriv 2 f y| ≤ M) (hε : 0 ≤ ε) (hδ : 0 < δ) + (hunif : ∀ u v : ℝ, |u - v| < δ → |iteratedDeriv 2 f u - iteratedDeriv 2 f v| ≤ ε) + {t : ℝ≥0} (ht : 0 < (t : ℝ)) (x : ℝ) : + |(t : ℝ)⁻¹ * (∫ y, f y ∂gaussianReal x t - f x) - iteratedDeriv 2 f x / 2| ≤ + ε + 2 * M * (t : ℝ) * gaussianMoment4 / δ ^ 2 := by + have hMnn : 0 ≤ M := le_trans (abs_nonneg _) (hM x) + set σ := Real.sqrt (t : ℝ) with hσdef + have hσ2 : σ ^ 2 = (t : ℝ) := Real.sq_sqrt t.coe_nonneg + set c := iteratedDeriv 2 f x with hcdef + have hcont : Continuous f := hf.continuous + have hz1 : Integrable (fun z : ℝ ↦ z) (gaussianReal 0 1) := by + simpa using integrable_pow_gaussian 1 + have hz2 : Integrable (fun z : ℝ ↦ z ^ 2) (gaussianReal 0 1) := integrable_pow_gaussian 2 + have hz4 : Integrable (fun z : ℝ ↦ z ^ 4) (gaussianReal 0 1) := integrable_pow_gaussian 4 + have hshift : Integrable (fun z : ℝ ↦ f (x + σ * z)) (gaussianReal 0 1) := by + refine Integrable.mono' (integrable_const B) + ((hcont.comp (by fun_prop)).aestronglyMeasurable) ?_ + filter_upwards with z + simpa using hB (x + σ * z) + have hchange : ∫ y, f y ∂gaussianReal x t = ∫ z, f (x + σ * z) ∂(gaussianReal 0 1) := + integral_gaussian_eq f hcont x t + set E : ℝ → ℝ := + fun z ↦ f (x + σ * z) - f x - σ * z * deriv f x - (σ * z) ^ 2 / 2 * c with hEdef + have h1 : Integrable (fun z : ℝ ↦ σ * z * deriv f x) (gaussianReal 0 1) := by + have h := hz1.const_mul (σ * deriv f x) + have heq : (fun z : ℝ ↦ σ * deriv f x * z) = fun z : ℝ ↦ σ * z * deriv f x := by + funext z; ring + rwa [heq] at h + have h2 : Integrable (fun z : ℝ ↦ (σ * z) ^ 2 / 2 * c) (gaussianReal 0 1) := by + have h := hz2.const_mul (σ ^ 2 * c / 2) + have heq : (fun z : ℝ ↦ σ ^ 2 * c / 2 * z ^ 2) = fun z : ℝ ↦ (σ * z) ^ 2 / 2 * c := by + funext z; ring + rwa [heq] at h + have hEint : Integrable E (gaussianReal 0 1) := + ((hshift.sub (integrable_const (f x))).sub h1).sub h2 + have hI1 : ∫ z : ℝ, σ * z * deriv f x ∂(gaussianReal 0 1) = 0 := by + have heq : (fun z : ℝ ↦ σ * z * deriv f x) = fun z : ℝ ↦ σ * deriv f x * z := by + funext z; ring + rw [heq, integral_const_mul, integral_id_gaussian, mul_zero] + have hI2 : ∫ z : ℝ, (σ * z) ^ 2 / 2 * c ∂(gaussianReal 0 1) = (t : ℝ) * c / 2 := by + have heq : (fun z : ℝ ↦ (σ * z) ^ 2 / 2 * c) = fun z : ℝ ↦ σ ^ 2 * c / 2 * z ^ 2 := by + funext z; ring + rw [heq, integral_const_mul, integral_sq_gaussian, mul_one, hσ2] + have hE : ∫ z, E z ∂(gaussianReal 0 1) + = (∫ z, f (x + σ * z) ∂(gaussianReal 0 1)) - f x - (t : ℝ) * c / 2 := by + have e1 : ∫ z, E z ∂(gaussianReal 0 1) + = (∫ z, (f (x + σ * z) - f x - σ * z * deriv f x) ∂(gaussianReal 0 1)) + - ∫ z, ((σ * z) ^ 2 / 2 * c) ∂(gaussianReal 0 1) := + integral_sub ((hshift.sub (integrable_const (f x))).sub h1) h2 + have e2 : ∫ z, (f (x + σ * z) - f x - σ * z * deriv f x) ∂(gaussianReal 0 1) + = (∫ z, (f (x + σ * z) - f x) ∂(gaussianReal 0 1)) + - ∫ z, (σ * z * deriv f x) ∂(gaussianReal 0 1) := + integral_sub (hshift.sub (integrable_const (f x))) h1 + have e3 : ∫ z, (f (x + σ * z) - f x) ∂(gaussianReal 0 1) + = (∫ z, f (x + σ * z) ∂(gaussianReal 0 1)) - ∫ _z : ℝ, f x ∂(gaussianReal 0 1) := + integral_sub hshift (integrable_const (f x)) + have e4 : ∫ _z : ℝ, f x ∂(gaussianReal 0 1) = f x := by simp + rw [e1, e2, e3, e4, hI1, hI2] + ring + have hEbound : ∀ z : ℝ, + |E z| ≤ ε * (t : ℝ) * z ^ 2 + 2 * M * (t : ℝ) ^ 2 / δ ^ 2 * z ^ 4 := by + intro z + have hCbound : ∀ s ∈ Set.Icc (0 : ℝ) 1, + |iteratedDeriv 2 f (x + s * (σ * z)) - iteratedDeriv 2 f x| ≤ + ε + 2 * M * (σ * z) ^ 2 / δ ^ 2 := by + intro s hs + rcases lt_or_ge |σ * z| δ with hlt | hge + · have hclose : |x + s * (σ * z) - x| < δ := by + rw [add_sub_cancel_left, abs_mul, abs_of_nonneg hs.1] + calc s * |σ * z| ≤ 1 * |σ * z| := + mul_le_mul_of_nonneg_right hs.2 (abs_nonneg _) + _ = |σ * z| := one_mul _ + _ < δ := hlt + have hpos : 0 ≤ 2 * M * (σ * z) ^ 2 / δ ^ 2 := by positivity + linarith [hunif _ _ hclose] + · have habs : |iteratedDeriv 2 f (x + s * (σ * z)) - iteratedDeriv 2 f x| ≤ 2 * M := by + calc |iteratedDeriv 2 f (x + s * (σ * z)) - iteratedDeriv 2 f x| + ≤ |iteratedDeriv 2 f (x + s * (σ * z))| + |iteratedDeriv 2 f x| := abs_sub _ _ + _ ≤ M + M := add_le_add (hM _) (hM _) + _ = 2 * M := by ring + have hstep : 2 * M ≤ 2 * M * (σ * z) ^ 2 / δ ^ 2 := + le_mul_sq_div (by linarith) hδ hge + linarith + have htaylor := abs_sub_taylor_two_le hf x (σ * z) _ hCbound + refine le_trans htaylor (le_of_eq ?_) + have hsq : (σ * z) ^ 2 = (t : ℝ) * z ^ 2 := by rw [mul_pow, hσ2] + rw [hsq] + field_simp + have hboundInt : Integrable + (fun z : ℝ ↦ ε * (t : ℝ) * z ^ 2 + 2 * M * (t : ℝ) ^ 2 / δ ^ 2 * z ^ 4) + (gaussianReal 0 1) := (hz2.const_mul _).add (hz4.const_mul _) + have hIabs : |∫ z, E z ∂(gaussianReal 0 1)| ≤ + ε * (t : ℝ) + 2 * M * (t : ℝ) ^ 2 / δ ^ 2 * gaussianMoment4 := by + calc |∫ z, E z ∂(gaussianReal 0 1)| ≤ ∫ z, |E z| ∂(gaussianReal 0 1) := + abs_integral_le_integral_abs + _ ≤ ∫ z, (ε * (t : ℝ) * z ^ 2 + 2 * M * (t : ℝ) ^ 2 / δ ^ 2 * z ^ 4) ∂(gaussianReal 0 1) := + integral_mono hEint.abs hboundInt hEbound + _ = ε * (t : ℝ) + 2 * M * (t : ℝ) ^ 2 / δ ^ 2 * gaussianMoment4 := by + rw [integral_add (hz2.const_mul _) (hz4.const_mul _), integral_const_mul, + integral_const_mul, integral_sq_gaussian, mul_one, gaussianMoment4] + have hkey : (t : ℝ)⁻¹ * (∫ y, f y ∂gaussianReal x t - f x) - c / 2 + = (t : ℝ)⁻¹ * ∫ z, E z ∂(gaussianReal 0 1) := by + rw [hchange, hE] + field_simp + rw [hkey, abs_mul, abs_of_nonneg (inv_nonneg.mpr ht.le)] + calc (t : ℝ)⁻¹ * |∫ z, E z ∂(gaussianReal 0 1)| + ≤ (t : ℝ)⁻¹ * (ε * (t : ℝ) + 2 * M * (t : ℝ) ^ 2 / δ ^ 2 * gaussianMoment4) := + mul_le_mul_of_nonneg_left hIabs (inv_nonneg.mpr ht.le) + _ = ε + 2 * M * (t : ℝ) * gaussianMoment4 / δ ^ 2 := by + field_simp + +end Estimate + +section Uniform + +variable {f : ℝ → ℝ} + +/-- A continuous function vanishing at infinity is bounded and uniformly continuous. -/ +private theorem exists_bound_modulus {g : ℝ → ℝ} (hg : Continuous g) + (hg0 : Tendsto g (cocompact ℝ) (𝓝 0)) : + ∃ M : ℝ, 0 ≤ M ∧ (∀ y, |g y| ≤ M) ∧ + ∀ ε : ℝ, 0 < ε → ∃ δ : ℝ, 0 < δ ∧ ∀ u v : ℝ, |u - v| < δ → |g u - g v| ≤ ε := by + set G : C₀(ℝ, ℝ) := ⟨⟨g, hg⟩, hg0⟩ with hG + refine ⟨‖G‖, norm_nonneg _, fun y ↦ ?_, fun ε hε ↦ ?_⟩ + · exact norm_apply_le_norm_c0 G y + · obtain ⟨δ, hδ, h⟩ := Metric.uniformContinuous_iff.mp + (ZeroAtInftyContinuousMap.uniformContinuous G) ε hε + refine ⟨δ, hδ, fun u v huv ↦ le_of_lt ?_⟩ + have hd := h (a := u) (b := v) (by rwa [Real.dist_eq]) + rwa [Real.dist_eq] at hd + +/-- **Half the Laplacian generates the Gaussian averages.** For a twice continuously +differentiable `f` whose value and second derivative vanish at infinity, the difference quotient +of the Gaussian average of `f` at scale `t`, taken at the centre `x`, converges as `t → 0⁺` to +half the second derivative of `f` at `x`, uniformly in `x`. -/ +theorem tendstoUniformly_gaussianAverage_sub_div (hf : ContDiff ℝ 2 f) + (hf0 : Tendsto f (cocompact ℝ) (𝓝 0)) + (hf2 : Tendsto (iteratedDeriv 2 f) (cocompact ℝ) (𝓝 0)) : + TendstoUniformly (fun (t : ℝ≥0) (x : ℝ) ↦ (t : ℝ)⁻¹ * (∫ y, f y ∂gaussianReal x t - f x)) + (fun x ↦ iteratedDeriv 2 f x / 2) (𝓝[>] 0) := by + obtain ⟨B, -, hB, -⟩ := exists_bound_modulus hf.continuous hf0 + obtain ⟨M, hMnn, hM, hmod⟩ := + exists_bound_modulus (hf.continuous_iteratedDeriv 2 (by norm_num)) hf2 + rw [Metric.tendstoUniformly_iff] + intro ε hε + obtain ⟨δ, hδ, hδ'⟩ := hmod (ε / 2) (by linarith) + have hKnn : 0 ≤ 2 * M * gaussianMoment4 := + mul_nonneg (by linarith) gaussianMoment4_nonneg + have hK : 0 < 2 * M * gaussianMoment4 + 1 := by linarith + set T : ℝ := ε * δ ^ 2 / (2 * (2 * M * gaussianMoment4 + 1)) with hT + have hTpos : 0 < T := div_pos (mul_pos hε (pow_pos hδ 2)) (by linarith) + have hev : ∀ᶠ t : ℝ≥0 in 𝓝[>] 0, (t : ℝ) < T := by + have hopen : IsOpen {t : ℝ≥0 | (t : ℝ) < T} := + isOpen_lt NNReal.continuous_coe continuous_const + have hmem : (0 : ℝ≥0) ∈ {t : ℝ≥0 | (t : ℝ) < T} := by simpa using hTpos + exact mem_nhdsWithin_of_mem_nhds (hopen.mem_nhds hmem) + filter_upwards [hev, self_mem_nhdsWithin] with t htT htpos + intro x + have htpos' : (0 : ℝ) < (t : ℝ) := NNReal.coe_pos.mpr htpos + have hmain := abs_gaussianQuotient_sub_le hf hB hM (by linarith : (0 : ℝ) ≤ ε / 2) hδ hδ' + htpos' x + rw [Real.dist_eq, abs_sub_comm] + refine lt_of_le_of_lt hmain ?_ + have hKt : (2 * M * gaussianMoment4 + 1) * (t : ℝ) + < (2 * M * gaussianMoment4 + 1) * T := mul_lt_mul_of_pos_left htT hK + have hTval : (2 * M * gaussianMoment4 + 1) * T = ε * δ ^ 2 / 2 := by + rw [hT]; field_simp + have hprod : 2 * M * gaussianMoment4 * (t : ℝ) < ε * δ ^ 2 / 2 := by + nlinarith [hKt, hTval, htpos'.le] + have hbound : 2 * M * (t : ℝ) * gaussianMoment4 / δ ^ 2 < ε / 2 := by + rw [div_lt_iff₀ (pow_pos hδ 2)] + nlinarith [hprod] + linarith + +end Uniform + +section C0 + +/-- **The Gaussian average of a `C₀` function.** At scale `t` it is the integral of `f` against +the normal law centred at `x` with variance `t`; at `t = 0` it is `f` itself. -/ +def gaussianAverage (f : C₀(ℝ, ℝ)) (t : ℝ≥0) : C₀(ℝ, ℝ) := + heatSemigroup.c0KernelIntegral mapsC0_heatSemigroup t f + +@[simp] +theorem gaussianAverage_apply (f : C₀(ℝ, ℝ)) (t : ℝ≥0) (x : ℝ) : + gaussianAverage f t x = ∫ y, f y ∂gaussianReal x t := by + rw [gaussianAverage, SubMarkovKernelSemigroup.c0KernelIntegral_apply, kernelIntegral, + heatSemigroup_apply] + +/-- **Half the Laplacian generates the Gaussian averages, in the `C₀` norm.** If `f` is a `C₀` +function which is twice continuously differentiable and whose second derivative is the `C₀` +function `g`, then the difference quotients of the Gaussian averages of `f` converge in the +`C₀` norm to `g / 2` as the scale tends to zero. -/ +theorem tendsto_gaussianAverage_sub_div (f g : C₀(ℝ, ℝ)) (hf : ContDiff ℝ 2 (f : ℝ → ℝ)) + (hg : ∀ x, g x = iteratedDeriv 2 (f : ℝ → ℝ) x) : + Tendsto (fun t : ℝ≥0 ↦ (t : ℝ)⁻¹ • (gaussianAverage f t - f)) (𝓝[>] 0) + (𝓝 ((2 : ℝ)⁻¹ • g)) := by + have hgf : iteratedDeriv 2 (f : ℝ → ℝ) = (g : ℝ → ℝ) := funext fun x ↦ (hg x).symm + have hf2 : Tendsto (iteratedDeriv 2 (f : ℝ → ℝ)) (cocompact ℝ) (𝓝 0) := by + rw [hgf]; exact g.zero_at_infty' + have huniform := tendstoUniformly_gaussianAverage_sub_div hf f.zero_at_infty' hf2 + rw [ZeroAtInftyContinuousMap.tendsto_iff_tendstoUniformly] + have hlim : (fun x : ℝ ↦ iteratedDeriv 2 (f : ℝ → ℝ) x / 2) = ⇑((2 : ℝ)⁻¹ • g) := by + funext x + rw [hgf] + simp [div_eq_inv_mul] + have hfun : (fun t : ℝ≥0 ↦ ⇑((t : ℝ)⁻¹ • (gaussianAverage f t - f))) + = fun (t : ℝ≥0) (x : ℝ) ↦ (t : ℝ)⁻¹ * (∫ y, f y ∂gaussianReal x t - f x) := by + funext t x + simp + rw [← hlim, hfun] + exact huniform + +/-- The `C₀` semigroup of the heat semigroup acts by Gaussian averages. -/ +theorem c0Semigroup_heatSemigroup_apply (f : C₀(ℝ, ℝ)) (t : ℝ≥0) : + isFellerKernelSemigroup_heatSemigroup.c0Semigroup t f = gaussianAverage f t := + ZeroAtInftyContinuousMap.ext fun x ↦ by + rw [SubMarkovKernelSemigroup.IsFellerKernelSemigroup.c0Semigroup_apply_apply, + gaussianAverage_apply, kernelIntegral, heatSemigroup_apply] + +/-- The difference quotients of the heat semigroup converge, in the `C₀` norm, to half the +second derivative. -/ +theorem tendsto_differenceQuotient_heatSemigroup (f g : C₀(ℝ, ℝ)) + (hf : ContDiff ℝ 2 (f : ℝ → ℝ)) (hg : ∀ x, g x = iteratedDeriv 2 (f : ℝ → ℝ) x) : + Tendsto (fun t : ℝ≥0 ↦ + (t : ℝ)⁻¹ • (isFellerKernelSemigroup_heatSemigroup.c0Semigroup t f - f)) + (𝓝[>] 0) (𝓝 ((2 : ℝ)⁻¹ • g)) := by + simpa only [c0Semigroup_heatSemigroup_apply] using tendsto_gaussianAverage_sub_div f g hf hg + +/-- **Twice continuously differentiable `C₀` functions with `C₀` second derivative lie in the +generator domain of the heat semigroup.** -/ +theorem mem_generatorDomain_heatSemigroup (f g : C₀(ℝ, ℝ)) (hf : ContDiff ℝ 2 (f : ℝ → ℝ)) + (hg : ∀ x, g x = iteratedDeriv 2 (f : ℝ → ℝ) x) : + f ∈ isFellerKernelSemigroup_heatSemigroup.c0Semigroup.generatorDomain := + isFellerKernelSemigroup_heatSemigroup.c0Semigroup.mem_generatorDomain_of_tendsto + (tendsto_differenceQuotient_heatSemigroup f g hf hg) + +/-- **The generator of the heat semigroup is half the Laplacian**: on a twice continuously +differentiable `C₀` function `f` with `C₀` second derivative `g`, the generator of the `C₀` +semigroup of Brownian motion is `g / 2`. -/ +theorem generator_heatSemigroup (f g : C₀(ℝ, ℝ)) (hf : ContDiff ℝ 2 (f : ℝ → ℝ)) + (hg : ∀ x, g x = iteratedDeriv 2 (f : ℝ → ℝ) x) : + isFellerKernelSemigroup_heatSemigroup.c0Semigroup.generator + ⟨f, mem_generatorDomain_heatSemigroup f g hf hg⟩ = (2 : ℝ)⁻¹ • g := + isFellerKernelSemigroup_heatSemigroup.c0Semigroup.generator_mk_eq + (tendsto_differenceQuotient_heatSemigroup f g hf hg) + +end C0 + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean new file mode 100644 index 0000000000..346fef9f1c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean @@ -0,0 +1,169 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal + +/-! +# The compactified heat process + +The heat resolvent represents the heat semigroup again +(`kernelSemigroup_heatResolvent`), so its one-point extension moves a live starting point by the +Gaussian law and never reaches the added point. In the metric determined by the exhaustion +`x ↦ 1 / (1 + |x|)` the distance of two points is at most `2` and the distance of two live points +is at most their distance on the line, so the fourth-moment estimate of the Gaussian law gives +the local Kolmogorov criterion on the compactification +(`hasLocalKolmogorovMoments_onePointKernelSemigroup_heatResolvent`). + +This assembles the regularity data from which the continuous-path process of the compactified +heat semigroup is formed (`onePointRegular_heatResolvent`), the witness that those data are +available for a genuine example. Because the heat semigroup is conservative, the compactified +process started at a live point almost surely never reaches the added point +(`ae_exitTime_eq_top_heatResolvent`). +-/ + +open MeasureTheory ProbabilityTheory Set Topology +open scoped ENNReal NNReal ZeroAtInfty + +noncomputable section + +namespace MarkovProcess + +/-- **The heat resolvent represents the heat semigroup.** -/ +theorem kernelSemigroup_heatResolvent : heatResolvent.kernelSemigroup = heatSemigroup := + isFellerKernelSemigroup_heatSemigroup.kernelSemigroup_positiveC0ContractiveResolvent + +section Metric + +/-- In the exhaustion metric of the line the compactification has diameter at most `2`. -/ +theorem dist_le_two_heatExhaustion (z w : OnePoint ℝ) : + letI := OnePoint.exhaustionMetricSpace heatExhaustion continuous_heatExhaustion + heatExhaustion_pos lipschitzWith_one_heatExhaustion isCompact_heatExhaustion_superlevel + dist z w ≤ 2 := by + let := OnePoint.exhaustionMetricSpace heatExhaustion continuous_heatExhaustion + heatExhaustion_pos lipschitzWith_one_heatExhaustion isCompact_heatExhaustion_superlevel + induction z using OnePoint.rec with + | infty => + induction w using OnePoint.rec with + | infty => + rw [dist_self] + norm_num + | coe y => + have hdist : dist (OnePoint.infty : OnePoint ℝ) (y : OnePoint ℝ) = heatExhaustion y := by + rw [dist_comm] + rfl + rw [hdist] + exact le_trans (heatExhaustion_le_one y) (by norm_num) + | coe x => + induction w using OnePoint.rec with + | infty => + have hdist : dist (x : OnePoint ℝ) (OnePoint.infty : OnePoint ℝ) = heatExhaustion x := + rfl + rw [hdist] + exact le_trans (heatExhaustion_le_one x) (by norm_num) + | coe y => + have hdist : dist (x : OnePoint ℝ) (y : OnePoint ℝ) = + min (dist x y) (heatExhaustion x + heatExhaustion y) := rfl + rw [hdist] + refine le_trans (min_le_right _ _) ?_ + have hsum : heatExhaustion x + heatExhaustion y ≤ 1 + 1 := + add_le_add (heatExhaustion_le_one x) (heatExhaustion_le_one y) + linarith only [hsum] + +/-- In the exhaustion metric of the line the distance of two live points is at most their +distance on the line. -/ +theorem edist_coe_coe_le_heatExhaustion (x y : ℝ) : + letI := OnePoint.exhaustionMetricSpace heatExhaustion continuous_heatExhaustion + heatExhaustion_pos lipschitzWith_one_heatExhaustion isCompact_heatExhaustion_superlevel + edist (x : OnePoint ℝ) (y : OnePoint ℝ) ≤ edist x y := by + let := OnePoint.exhaustionMetricSpace heatExhaustion continuous_heatExhaustion + heatExhaustion_pos lipschitzWith_one_heatExhaustion isCompact_heatExhaustion_superlevel + rw [edist_dist, edist_dist] + exact ENNReal.ofReal_le_ofReal + (OnePoint.exhaustionMetricSpace_dist_coe_coe_le heatExhaustion continuous_heatExhaustion + heatExhaustion_pos lipschitzWith_one_heatExhaustion isCompact_heatExhaustion_superlevel x y) + +end Metric + +section Moments + +/-- **The compactified heat semigroup satisfies the local Kolmogorov criterion** in the +exhaustion metric, with the Gaussian fourth moment and the diameter bound as constants. -/ +theorem hasLocalKolmogorovMoments_onePointKernelSemigroup_heatResolvent : + letI := OnePoint.exhaustionMetricSpace heatExhaustion continuous_heatExhaustion + heatExhaustion_pos lipschitzWith_one_heatExhaustion isCompact_heatExhaustion_superlevel + heatResolvent.onePointKernelSemigroup.HasLocalKolmogorovMoments 4 2 + gaussianFourthMoment 16 := by + let := OnePoint.exhaustionMetricSpace heatExhaustion continuous_heatExhaustion + heatExhaustion_pos lipschitzWith_one_heatExhaustion isCompact_heatExhaustion_superlevel + refine ⟨by norm_num, by norm_num, ?_, ?_⟩ + · intro h _hh z + induction z using OnePoint.rec with + | infty => + rw [heatResolvent.onePointKernelSemigroup_absorbing h, lintegral_dirac] + simp only [edist_self, ENNReal.rpow_ofNat, ne_eq, OfNat.ofNat_ne_zero, + not_false_eq_true, zero_pow, coe_gaussianFourthMoment, zero_le] + | coe x => + have hmass : heatSemigroup h x Set.univ = 1 := isConservative_heatSemigroup h x + have hlaw : heatResolvent.onePointKernelSemigroup h (x : OnePoint ℝ) = + (heatSemigroup h x).map ((↑) : ℝ → OnePoint ℝ) := by + rw [heatResolvent.onePointKernelSemigroup_apply_coe h x, kernelSemigroup_heatResolvent, + hmass, tsub_self, zero_smul, add_zero] + have hmeas : Measurable fun z : OnePoint ℝ ↦ edist z (x : OnePoint ℝ) ^ (4 : ℝ) := + (measurable_edist_left (x := (x : OnePoint ℝ))).pow_const 4 + rw [hlaw, lintegral_map hmeas OnePoint.continuous_coe.measurable] + refine le_trans (lintegral_mono fun y ↦ ?_) (hasKolmogorovMoments_heatSemigroup.2.2 h x) + exact ENNReal.rpow_le_rpow (edist_coe_coe_le_heatExhaustion y x) (by norm_num) + · intro y z + have hdist : edist z y ≤ 2 := by + rw [edist_dist] + calc ENNReal.ofReal (dist z y) ≤ ENNReal.ofReal 2 := + ENNReal.ofReal_le_ofReal (dist_le_two_heatExhaustion z y) + _ = 2 := by + rw [show (2 : ℝ) = ((2 : ℝ≥0) : ℝ) by norm_num, ENNReal.ofReal_coe_nnreal] + rfl + calc edist z y ^ (4 : ℝ) ≤ (2 : ℝ≥0∞) ^ (4 : ℝ) := + ENNReal.rpow_le_rpow hdist (by norm_num) + _ = 16 := by + rw [show (4 : ℝ) = ((4 : ℕ) : ℝ) by norm_num, ENNReal.rpow_natCast] + norm_num + _ = ((16 : ℝ≥0) : ℝ≥0∞) := by norm_num + +end Moments + +/-- **The regularity data of the compactified heat process**: the exhaustion `1 / (1 + |x|)` and +the Kolmogorov regularity which its metric gives the compactified heat semigroup. -/ +def onePointRegular_heatResolvent : heatResolvent.OnePointRegular where + rho := heatExhaustion + continuous_rho := continuous_heatExhaustion + rho_pos := heatExhaustion_pos + lipschitz_rho := lipschitzWith_one_heatExhaustion + isCompact_superlevel := isCompact_heatExhaustion_superlevel + kolmogorovRegular := by + let := OnePoint.exhaustionMetricSpace heatExhaustion continuous_heatExhaustion + heatExhaustion_pos lipschitzWith_one_heatExhaustion isCompact_heatExhaustion_superlevel + let : CompleteSpace (OnePoint ℝ) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + exact SubMarkovKernelSemigroup.KolmogorovRegular.of_hasKolmogorovMoments _ + heatResolvent.isConservative_onePointKernelSemigroup + (hasLocalKolmogorovMoments_onePointKernelSemigroup_heatResolvent.toHasKolmogorovMoments + heatResolvent.isConservative_onePointKernelSemigroup) + +/-- **The compactified heat process almost surely never reaches the added point.** The heat +semigroup is conservative, so the shift times its kernel resolvent of the constant observable one +is one, which is the criterion for no escape. -/ +theorem ae_exitTime_eq_top_heatResolvent (x : ℝ) : + letI := onePointRegular_heatResolvent.metricSpace + letI := onePointRegular_heatResolvent.completeSpace + ∀ᵐ omega ∂SubMarkovKernelSemigroup.IsConservative.continuousProcess + heatResolvent.onePointKernelSemigroup + heatResolvent.isConservative_onePointKernelSemigroup (x : OnePoint ℝ), + ContinuousPath.exitTime (Set.range ((↑) : ℝ → OnePoint ℝ)) omega = ⊤ := + onePointRegular_heatResolvent.ae_exitTime_eq_top one_pos x (by + rw [kernelSemigroup_heatResolvent] + exact isConservative_heatSemigroup.ofReal_mul_kernelResolvent_one one_pos x) + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatSemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatSemigroup.lean new file mode 100644 index 0000000000..fc22941077 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatSemigroup.lean @@ -0,0 +1,539 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin +import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +import Mathlib.Probability.Distributions.Gaussian.Real + +/-! +# The one-dimensional heat semigroup and its continuous-path process + +The transition semigroup on the real line whose kernel at time `t` is the Gaussian law with mean +the starting point and variance `t`. It is conservative, Feller, and satisfies the Kolmogorov +moment criterion with exponents `p = 4`, `q = 2` and the fourth moment of the standard Gaussian as +constant, so the existence-and-uniqueness theorem of `MarkovProcess.Main` applies to it. The +process it produces is named `brownianMotion`. + +Main results: + +* `heatSemigroup`, `heatSemigroup_apply`: the semigroup and its Gaussian transition measures. +* `isConservative_heatSemigroup`: no mass is lost. +* `kernelIntegral_heatSemigroup`: the scaling representation of the transition operator. +* `isFellerKernelSemigroup_heatSemigroup`: the Feller property. +* `heatResolvent`: its positive contractive `C₀` resolvent. +* `heatExhaustion`: the explicit exhaustion `x ↦ 1 / (1 + |x|)`. +* `hasKolmogorovMoments_heatSemigroup`: the intrinsic Kolmogorov moment bound. +* `existsUnique_continuousProcess_heatSemigroup`: the main theorem, applied. +* `brownianMotion`, `brownianMotion_map_eval`, `brownianMotion_map_finsetEvaluation`: the + continuous-path process and its finite-dimensional distributions. + +Only one space dimension is treated: the multidimensional heat semigroup is not constructed here. +Nothing in this file asserts independence of increments; that is proved in +`MarkovProcess.Examples.BrownianMotion`. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal ZeroAtInfty + +namespace MarkovProcess + +noncomputable section + +section Gaussian + +/-- Every real Gaussian is the image of the standard Gaussian under an affine map: the law with +mean `x` and variance `t` is the law of `x + √t * z` for a standard normal `z`. -/ +theorem gaussianReal_eq_map_add_sqrt_mul (x : ℝ) (t : ℝ≥0) : + gaussianReal x t = (gaussianReal 0 1).map (fun z ↦ x + Real.sqrt t * z) := by + have hmul : (gaussianReal 0 1).map (fun z : ℝ ↦ Real.sqrt t * z) = gaussianReal 0 t := by + rw [gaussianReal_map_const_mul (Real.sqrt t)] + congr 1 + · ring + · rw [mul_one] + ext + simp [Real.sq_sqrt t.coe_nonneg] + have hadd := gaussianReal_map_const_add (μ := 0) (v := t) x + rw [zero_add] at hadd + rw [← hadd, ← hmul, Measure.map_map (by fun_prop) (by fun_prop)] + rfl + +/-- Translating a real Gaussian by a constant translates its mean. -/ +theorem gaussianReal_eq_map_const_add (x : ℝ) (t : ℝ≥0) : + gaussianReal x t = (gaussianReal 0 t).map (fun u ↦ x + u) := by + rw [gaussianReal_map_const_add x, zero_add] + +end Gaussian + +section Definition + +/-- The Gaussian transition kernel of the heat semigroup, jointly in the time and the starting +point. It is built from the standard Gaussian by the affine map `(t, x, z) ↦ x + √t * z`, which +makes joint measurability automatic. -/ +def heatKernelJoint : Kernel (NNReal × ℝ) ℝ := + (Kernel.id ×ₖ Kernel.const (NNReal × ℝ) (gaussianReal 0 1)).map + (fun q : (NNReal × ℝ) × ℝ ↦ q.1.2 + Real.sqrt q.1.1 * q.2) + +theorem heatKernelJoint_apply (p : NNReal × ℝ) : heatKernelJoint p = gaussianReal p.2 p.1 := by + have hmeas : Measurable (fun q : (NNReal × ℝ) × ℝ ↦ q.1.2 + Real.sqrt q.1.1 * q.2) := by + fun_prop + rw [heatKernelJoint, Kernel.map_apply _ hmeas, Kernel.prod_apply, Kernel.id_apply, + Kernel.const_apply, Measure.dirac_prod, Measure.map_map hmeas (by fun_prop)] + conv_rhs => rw [gaussianReal_eq_map_add_sqrt_mul p.2 p.1] + rfl + +/-- The transition kernel of the heat semigroup at time `t`. -/ +def heatKernel (t : NNReal) : Kernel ℝ ℝ := + Kernel.comap heatKernelJoint (fun x : ℝ ↦ (t, x)) (by fun_prop) + +@[simp] +theorem heatKernel_apply (t : NNReal) (x : ℝ) : heatKernel t x = gaussianReal x t := by + rw [heatKernel, Kernel.comap_apply, heatKernelJoint_apply] + +instance isMarkovKernel_heatKernel (t : NNReal) : IsMarkovKernel (heatKernel t) := + ⟨fun x ↦ by rw [heatKernel_apply]; infer_instance⟩ + +/-- The mean of a real Gaussian of fixed variance is a measurable parameter. -/ +theorem measurable_gaussianReal_left (t : NNReal) : Measurable (fun x : ℝ ↦ gaussianReal x t) := by + have hfun : (fun x : ℝ ↦ gaussianReal x t) = fun x ↦ heatKernel t x := + funext fun x ↦ (heatKernel_apply t x).symm + rw [hfun] + exact (heatKernel t).measurable + +/-- The real Gaussians of a fixed mean form a convolution semigroup in the variance: sampling a +Gaussian of variance `s` and then, from the value obtained, a Gaussian of variance `t` gives a +Gaussian of variance `s + t`. -/ +theorem bind_gaussianReal (x : ℝ) (s t : NNReal) : + (gaussianReal x s).bind (fun y ↦ gaussianReal y t) = gaussianReal x (s + t) := by + refine Measure.ext_of_lintegral _ fun f hf ↦ ?_ + rw [Measure.lintegral_bind (measurable_gaussianReal_left t).aemeasurable hf.aemeasurable] + have hinner : ∀ y : ℝ, ∫⁻ z, f z ∂(gaussianReal y t) + = ∫⁻ u, f (y + u) ∂(gaussianReal 0 t) := by + intro y + rw [gaussianReal_eq_map_const_add y t, lintegral_map hf (by fun_prop)] + simp_rw [hinner] + rw [← Measure.lintegral_conv hf, gaussianReal_conv_gaussianReal, add_zero] + +/-- **The one-dimensional heat semigroup.** Its transition measure at time `t` from `x` is the +Gaussian law with mean `x` and variance `t`. -/ +def heatSemigroup : SubMarkovKernelSemigroup ℝ where + kernel := heatKernel + measurable_kernel := by + have hfun : (fun p : NNReal × ℝ ↦ heatKernel p.1 p.2) = fun p ↦ heatKernelJoint p := by + funext p + rw [heatKernel, Kernel.comap_apply] + rw [hfun] + exact heatKernelJoint.measurable + kernel_zero := Kernel.ext fun x ↦ by + rw [heatKernel_apply, gaussianReal_zero_var, Kernel.id_apply] + kernel_add := fun s t ↦ Kernel.ext fun x ↦ by + have hfun : ⇑(heatKernel t) = fun y ↦ gaussianReal y t := funext (heatKernel_apply t) + rw [Kernel.comp_apply, heatKernel_apply, heatKernel_apply, hfun, bind_gaussianReal] + isSubMarkovKernel := fun _ ↦ IsSubMarkovKernel.of_isMarkovKernel _ + +@[simp] +theorem heatSemigroup_apply (t : NNReal) (x : ℝ) : heatSemigroup t x = gaussianReal x t := + heatKernel_apply t x + +/-- The heat semigroup is conservative: every transition measure has total mass one. -/ +theorem isConservative_heatSemigroup : heatSemigroup.IsConservative := by + intro t x + rw [heatSemigroup_apply] + exact measure_univ + +end Definition + +section Feller + +/-- **The scaling representation of the heat semigroup.** Integrating a `C₀` function against the +transition measure at time `t` from `x` is integrating its translate `z ↦ f (x + √t * z)` against +the standard Gaussian. -/ +theorem kernelIntegral_heatSemigroup (t : NNReal) (f : C₀(ℝ, ℝ)) (x : ℝ) : + kernelIntegral (heatSemigroup t) f x = + ∫ z, f (x + Real.sqrt t * z) ∂(gaussianReal 0 1) := by + rw [kernelIntegral, heatSemigroup_apply, gaussianReal_eq_map_add_sqrt_mul] + exact integral_map (φ := fun z : ℝ ↦ x + Real.sqrt t * z) (f := fun y : ℝ ↦ f y) + (by fun_prop) f.continuous.aestronglyMeasurable + +/-- A `C₀` function is bounded by its norm. -/ +theorem norm_apply_le_norm_c0 (f : C₀(ℝ, ℝ)) (x : ℝ) : ‖f x‖ ≤ ‖f‖ := by + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + exact f.toBCF.norm_coe_le_norm x + +private theorem integrable_c0_comp (f : C₀(ℝ, ℝ)) (t : NNReal) (x : ℝ) : + Integrable (fun z ↦ f (x + Real.sqrt t * z)) (gaussianReal 0 1) := by + refine Integrable.mono' (integrable_const ‖f‖) ?_ (Filter.Eventually.of_forall fun z ↦ ?_) + · exact (f.continuous.comp (by fun_prop)).aestronglyMeasurable + · exact norm_apply_le_norm_c0 f _ + +/-- The heat semigroup maps `C₀` into itself. -/ +theorem mapsC0_heatSemigroup : heatSemigroup.MapsC0 := by + intro t f + have hrep : kernelIntegral (heatSemigroup t) f = + fun x ↦ ∫ z, f (x + Real.sqrt t * z) ∂(gaussianReal 0 1) := + funext (kernelIntegral_heatSemigroup t f) + rw [hrep] + constructor + · refine continuous_of_dominated (F := fun (x z : ℝ) ↦ f (x + Real.sqrt t * z)) + (bound := fun _ ↦ ‖f‖) ?_ ?_ (integrable_const (μ := gaussianReal 0 1) ‖f‖) ?_ + · exact fun x ↦ (f.continuous.comp (by fun_prop)).aestronglyMeasurable + · exact fun x ↦ Filter.Eventually.of_forall fun z ↦ norm_apply_le_norm_c0 f _ + · exact Filter.Eventually.of_forall fun z ↦ f.continuous.comp (by fun_prop) + · have hcg : (Filter.cocompact ℝ).IsCountablyGenerated := by + rw [cocompact_eq_atBot_atTop] + infer_instance + refine Filter.tendsto_iff_seq_tendsto.mpr fun u hu ↦ ?_ + have hlim : Filter.Tendsto + (fun n ↦ ∫ z, f (u n + Real.sqrt t * z) ∂(gaussianReal 0 1)) atTop + (nhds (∫ _z : ℝ, (0 : ℝ) ∂(gaussianReal 0 1))) := by + refine tendsto_integral_of_dominated_convergence + (F := fun (n : ℕ) (z : ℝ) ↦ f (u n + Real.sqrt t * z)) (fun _ ↦ ‖f‖) + (fun _ ↦ (f.continuous.comp (by fun_prop)).aestronglyMeasurable) + (integrable_const (μ := gaussianReal 0 1) ‖f‖) + (fun _ ↦ Filter.Eventually.of_forall fun _ ↦ norm_apply_le_norm_c0 f _) + (Filter.Eventually.of_forall fun z ↦ ?_) + have htranslate : Filter.Tendsto (fun y : ℝ ↦ y + Real.sqrt t * z) + (Filter.cocompact ℝ) (Filter.cocompact ℝ) := + CocompactMapClass.cocompact_tendsto + ((Homeomorph.addRight (Real.sqrt t * z)).toCocompactMap) + exact f.zero_at_infty'.comp (htranslate.comp hu) + rw [integral_zero] at hlim + exact hlim + +/-- A finite measure on the real line puts arbitrarily little mass far from the origin. -/ +theorem exists_measure_abs_ge_lt (nu : Measure ℝ) [IsFiniteMeasure nu] {eps : ℝ} + (heps : 0 < eps) : ∃ R : ℝ, 0 < R ∧ (nu {z : ℝ | R ≤ |z|}).toReal < eps := by + have hmeasA : ∀ n : ℕ, NullMeasurableSet {z : ℝ | (n : ℝ) ≤ |z|} nu := fun n ↦ + ((isClosed_le continuous_const continuous_abs).measurableSet).nullMeasurableSet + have hanti : Antitone (fun n : ℕ ↦ {z : ℝ | (n : ℝ) ≤ |z|}) := by + intro n m hnm z hz + simp only [Set.mem_ofPred_eq] at hz ⊢ + exact le_trans (Nat.cast_le.mpr hnm) hz + have hempty : (⋂ n : ℕ, {z : ℝ | (n : ℝ) ≤ |z|}) = (∅ : Set ℝ) := by + refine Set.eq_empty_of_forall_notMem fun z hz ↦ ?_ + obtain ⟨n, hn⟩ := exists_nat_gt |z| + exact absurd (Set.mem_iInter.mp hz n) (not_le.mpr hn) + have htend := tendsto_measure_iInter_atTop hmeasA hanti ⟨0, measure_ne_top nu _⟩ + rw [hempty, measure_empty] at htend + have hev : ∀ᶠ n : ℕ in atTop, nu {z : ℝ | (n : ℝ) ≤ |z|} < ENNReal.ofReal eps := + htend.eventually_lt_const (by simpa using heps) + obtain ⟨n, hn⟩ := (hev.and (Filter.eventually_gt_atTop 0)).exists + exact ⟨(n : ℝ), by exact_mod_cast hn.2, ENNReal.toReal_lt_of_lt_ofReal hn.1⟩ + +/-- The `C₀` orbit displacement of the heat semigroup is uniformly small over short times: for +every `ε > 0` there is a `δ > 0` such that the transition operator moves a `C₀` function by at +most `ε` in the uniform norm over every time shorter than `δ`. -/ +theorem exists_norm_c0Operator_sub_le_heatSemigroup (f : C₀(ℝ, ℝ)) {eps : ℝ} (heps : 0 < eps) : + ∃ delta : ℝ, 0 < delta ∧ ∀ h : NNReal, (h : ℝ) < delta → + ‖heatSemigroup.c0Operator mapsC0_heatSemigroup h f - f‖ ≤ eps := by + obtain ⟨delta0, hdelta0, huc⟩ := Metric.uniformContinuous_iff.mp + (ZeroAtInftyContinuousMap.uniformContinuous f) (eps / 2) (half_pos heps) + have hfpos : (0 : ℝ) < 4 * (‖f‖ + 1) := by positivity + obtain ⟨R, hR, hRmeas⟩ := exists_measure_abs_ge_lt (gaussianReal 0 1) + (eps := eps / (4 * (‖f‖ + 1))) (by positivity) + set S : Set ℝ := {z : ℝ | R ≤ |z|} with hS + have hSmeas : MeasurableSet S := (isClosed_le continuous_const continuous_abs).measurableSet + set bound : ℝ → ℝ := fun z ↦ eps / 2 + 2 * ‖f‖ * S.indicator (fun _ ↦ (1 : ℝ)) z with hbound + have hindInt : Integrable (S.indicator (fun _ ↦ (1 : ℝ))) (gaussianReal 0 1) := + (integrable_indicator_iff hSmeas).mpr (integrableOn_const (measure_ne_top _ _)) + have hboundInt : Integrable bound (gaussianReal 0 1) := + (integrable_const (μ := gaussianReal 0 1) (eps / 2)).add (hindInt.const_mul _) + have hboundIntegral : ∫ z, bound z ∂(gaussianReal 0 1) ≤ eps := by + rw [hbound, integral_add (integrable_const (μ := gaussianReal 0 1) (eps / 2)) + (hindInt.const_mul _), integral_const, MeasureTheory.integral_const_mul, + integral_indicator_const (1 : ℝ) hSmeas] + have hnorm : 0 ≤ ‖f‖ := norm_nonneg f + have hkey : 2 * ‖f‖ * ((gaussianReal 0 1).real S) ≤ eps / 2 := by + have hpos : (0 : ℝ) ≤ (gaussianReal 0 1).real S := measureReal_nonneg + calc 2 * ‖f‖ * ((gaussianReal 0 1).real S) + ≤ 2 * (‖f‖ + 1) * (eps / (4 * (‖f‖ + 1))) := by + apply mul_le_mul _ (le_of_lt hRmeas) hpos (by positivity) + exact mul_le_mul_of_nonneg_left (by linarith only []) (by norm_num) + _ = eps / 2 := by field_simp; ring + rw [probReal_univ] + simp only [smul_eq_mul, mul_one] + linarith only [hkey] + refine ⟨(delta0 / R) ^ 2, by positivity, fun h hh ↦ ?_⟩ + have hsqrt : Real.sqrt h * R < delta0 := by + have h1 : Real.sqrt h < delta0 / R := by + have := Real.sqrt_lt_sqrt h.coe_nonneg hh + rwa [Real.sqrt_sq (by positivity)] at this + calc Real.sqrt h * R < (delta0 / R) * R := by + exact mul_lt_mul_of_pos_right h1 hR + _ = delta0 := div_mul_cancel₀ delta0 (ne_of_gt hR) + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + refine (BoundedContinuousFunction.norm_le (le_of_lt heps)).2 fun x ↦ ?_ + show ‖heatSemigroup.c0Operator mapsC0_heatSemigroup h f x - f x‖ ≤ eps + rw [SubMarkovKernelSemigroup.c0Operator_apply, kernelIntegral_heatSemigroup] + have hsub : (∫ z, f (x + Real.sqrt h * z) ∂(gaussianReal 0 1)) - f x = + ∫ z, (f (x + Real.sqrt h * z) - f x) ∂(gaussianReal 0 1) := by + rw [integral_sub (integrable_c0_comp f h x) (integrable_const (f x)), integral_const, + probReal_univ, one_smul] + rw [hsub] + refine le_trans (norm_integral_le_of_norm_le hboundInt + (Filter.Eventually.of_forall fun z ↦ ?_)) hboundIntegral + by_cases hz : z ∈ S + · have h1 : ‖f (x + Real.sqrt h * z) - f x‖ ≤ 2 * ‖f‖ := by + calc ‖f (x + Real.sqrt h * z) - f x‖ ≤ ‖f (x + Real.sqrt h * z)‖ + ‖f x‖ := + norm_sub_le _ _ + _ ≤ ‖f‖ + ‖f‖ := add_le_add (norm_apply_le_norm_c0 f _) (norm_apply_le_norm_c0 f _) + _ = 2 * ‖f‖ := by ring + rw [hbound] + simp only [Set.indicator_of_mem hz, mul_one] + linarith only [h1, heps] + · have hdist : dist (x + Real.sqrt h * z) x < delta0 := by + rw [dist_eq_norm, add_sub_cancel_left, Real.norm_eq_abs, abs_mul, + abs_of_nonneg (Real.sqrt_nonneg _)] + have hzR : |z| < R := lt_of_not_ge (by simpa only [hS, Set.mem_ofPred_eq] using hz) + calc Real.sqrt h * |z| ≤ Real.sqrt h * R := + mul_le_mul_of_nonneg_left (le_of_lt hzR) (Real.sqrt_nonneg _) + _ < delta0 := hsqrt + have h2 : ‖f (x + Real.sqrt h * z) - f x‖ ≤ eps / 2 := by + rw [← dist_eq_norm] + exact le_of_lt (huc hdist) + rw [hbound] + simp only [Set.indicator_of_notMem hz, mul_zero, add_zero] + exact h2 + +/-- The `C₀` orbits of the heat semigroup are continuous in time. -/ +theorem hasContinuousC0Orbits_heatSemigroup : + heatSemigroup.HasContinuousC0Orbits mapsC0_heatSemigroup := by + intro f + rw [Metric.continuous_iff] + intro b eps heps + obtain ⟨delta, hdelta, hkey⟩ := + exists_norm_c0Operator_sub_le_heatSemigroup f (half_pos heps) + refine ⟨delta, hdelta, fun a hab ↦ ?_⟩ + have hcontraction : ∀ c d : NNReal, c ≤ d → (d : ℝ) - (c : ℝ) < delta → + dist (heatSemigroup.c0Operator mapsC0_heatSemigroup d f) + (heatSemigroup.c0Operator mapsC0_heatSemigroup c f) ≤ eps / 2 := by + intro c d hcd hlt + have hdc : c + (d - c) = d := add_tsub_cancel_of_le hcd + have hcoe : ((d - c : NNReal) : ℝ) < delta := by + rw [NNReal.coe_sub hcd] + exact hlt + have hop : heatSemigroup.c0Operator mapsC0_heatSemigroup d f = + heatSemigroup.c0Operator mapsC0_heatSemigroup c + (heatSemigroup.c0Operator mapsC0_heatSemigroup (d - c) f) := by + conv_lhs => rw [← hdc] + rw [SubMarkovKernelSemigroup.c0Operator_add] + rfl + rw [dist_eq_norm, hop, ← map_sub] + calc ‖heatSemigroup.c0Operator mapsC0_heatSemigroup c + (heatSemigroup.c0Operator mapsC0_heatSemigroup (d - c) f - f)‖ + ≤ ‖heatSemigroup.c0Operator mapsC0_heatSemigroup c‖ * + ‖heatSemigroup.c0Operator mapsC0_heatSemigroup (d - c) f - f‖ := + ContinuousLinearMap.le_opNorm _ _ + _ ≤ 1 * (eps / 2) := by + refine mul_le_mul (SubMarkovKernelSemigroup.norm_c0Operator_le _ _ c) + (hkey _ hcoe) (norm_nonneg _) zero_le_one + _ = eps / 2 := one_mul _ + have habs : |(a : ℝ) - (b : ℝ)| < delta := by + rw [← NNReal.dist_eq] + exact hab + rcases le_total b a with hba | hab' + · have := hcontraction b a hba (by + rw [abs_of_nonneg (by + have : (b : ℝ) ≤ (a : ℝ) := by exact_mod_cast hba + linarith only [this])] at habs + exact habs) + linarith only [this, heps] + · have := hcontraction a b hab' (by + rw [abs_sub_comm, abs_of_nonneg (by + have : (a : ℝ) ≤ (b : ℝ) := by exact_mod_cast hab' + linarith only [this])] at habs + exact habs) + rw [dist_comm] + linarith only [this, heps] + +/-- **The heat semigroup is a Feller semigroup.** -/ +theorem isFellerKernelSemigroup_heatSemigroup : + heatSemigroup.IsFellerKernelSemigroup := + ⟨mapsC0_heatSemigroup, hasContinuousC0Orbits_heatSemigroup⟩ + +/-- The positive contractive `C₀` resolvent obtained from the heat semigroup. -/ +noncomputable def heatResolvent : PositiveC0ContractiveResolvent ℝ := + isFellerKernelSemigroup_heatSemigroup.positiveC0ContractiveResolvent + +/-- The semigroup generated by the heat resolvent is the original heat `C₀` semigroup. -/ +theorem generatedSemigroup_heatResolvent : + heatResolvent.toContractiveResolvent.generatedSemigroup = + isFellerKernelSemigroup_heatSemigroup.c0Semigroup := + isFellerKernelSemigroup_heatSemigroup.generatedSemigroup_positiveC0ContractiveResolvent + +end Feller + +section OnePointExhaustion + +/-- The explicit positive exhaustion used to metrize the one-point compactification of the real +line. -/ +def heatExhaustion (x : ℝ) : ℝ := + 1 / (1 + |x|) + +/-- The heat exhaustion is `1`-Lipschitz. -/ +theorem lipschitzWith_one_heatExhaustion : LipschitzWith 1 heatExhaustion := by + apply LipschitzWith.of_dist_le_mul + intro x y + simp only [NNReal.coe_one, one_mul, Real.dist_eq] + rw [heatExhaustion, heatExhaustion, one_div, one_div, + inv_sub_inv (by positivity) (by positivity), abs_div] + calc + |(1 + |y|) - (1 + |x|)| / |(1 + |x|) * (1 + |y|)| + = |(|y| - |x|)| / |(1 + |x|) * (1 + |y|)| := by ring_nf + _ ≤ |(|y| - |x|)| := by + apply div_le_self (abs_nonneg _) + rw [abs_of_nonneg (mul_nonneg (by positivity) (by positivity))] + calc + (1 : ℝ) = 1 * 1 := (mul_one 1).symm + _ ≤ (1 + |x|) * (1 + |y|) := + mul_le_mul (le_add_of_nonneg_right (abs_nonneg x)) + (le_add_of_nonneg_right (abs_nonneg y)) zero_le_one (by positivity) + _ ≤ |y - x| := abs_abs_sub_abs_le_abs_sub _ _ + _ = |x - y| := abs_sub_comm y x + +/-- The heat exhaustion is continuous. -/ +theorem continuous_heatExhaustion : Continuous heatExhaustion := + lipschitzWith_one_heatExhaustion.continuous + +/-- The heat exhaustion is strictly positive. -/ +theorem heatExhaustion_pos (x : ℝ) : 0 < heatExhaustion x := by + unfold heatExhaustion + positivity + +/-- The heat exhaustion is bounded above by one. -/ +theorem heatExhaustion_le_one (x : ℝ) : heatExhaustion x ≤ 1 := by + unfold heatExhaustion + exact (div_le_one₀ (by positivity)).2 (le_add_of_nonneg_right (abs_nonneg x)) + +/-- Every positive superlevel set of the heat exhaustion is compact. -/ +theorem isCompact_heatExhaustion_superlevel (epsilon : ℝ) (hepsilon : 0 < epsilon) : + IsCompact {x : ℝ | epsilon ≤ heatExhaustion x} := by + apply IsCompact.of_isClosed_subset (isCompact_Icc : IsCompact (Set.Icc (-epsilon⁻¹) epsilon⁻¹)) + (isClosed_le continuous_const continuous_heatExhaustion) + intro x hx + have hmul : epsilon * (1 + |x|) ≤ 1 := by + change epsilon ≤ 1 / (1 + |x|) at hx + exact (le_div_iff₀ (by positivity : 0 < 1 + |x|)).mp hx + have habs : |x| ≤ epsilon⁻¹ := by + rw [inv_eq_one_div, le_div_iff₀ hepsilon] + calc + |x| * epsilon ≤ (1 + |x|) * epsilon := + mul_le_mul_of_nonneg_right (le_add_of_nonneg_left zero_le_one) hepsilon.le + _ = epsilon * (1 + |x|) := mul_comm _ _ + _ ≤ 1 := hmul + exact (abs_le.mp habs) + +end OnePointExhaustion + +section Moments + +/-- The fourth moment of the standard Gaussian is finite. -/ +theorem lintegral_enorm_pow_gaussianReal_lt_top : + ∫⁻ z, ‖z‖ₑ ^ (4 : ℕ) ∂(gaussianReal 0 1) < ⊤ := by + have hmem : MemLp id ((4 : ℝ≥0) : ℝ≥0∞) (gaussianReal 0 1) := memLp_id_gaussianReal 4 + have hfin := lintegral_rpow_enorm_lt_top_of_eLpNorm_lt_top + (p := ((4 : ℝ≥0) : ℝ≥0∞)) (f := (id : ℝ → ℝ)) (by simp) (by simp) hmem.eLpNorm_lt_top + have hp : (((4 : ℝ≥0) : ℝ≥0∞)).toReal = (4 : ℝ) := by simp + rw [hp] at hfin + simpa only [id_eq, ENNReal.rpow_ofNat] using hfin + +/-- The fourth moment of the standard Gaussian, as a nonnegative real number. -/ +def gaussianFourthMoment : NNReal := + (∫⁻ z, ‖z‖ₑ ^ (4 : ℕ) ∂(gaussianReal 0 1)).toNNReal + +@[simp] +theorem coe_gaussianFourthMoment : + (gaussianFourthMoment : ℝ≥0∞) = ∫⁻ z, ‖z‖ₑ ^ (4 : ℕ) ∂(gaussianReal 0 1) := + ENNReal.coe_toNNReal (ne_of_lt lintegral_enorm_pow_gaussianReal_lt_top) + +private theorem enorm_sqrt_sq (h : NNReal) : + ‖Real.sqrt (h : ℝ)‖ₑ ^ (2 : ℕ) = (h : ℝ≥0∞) := by + rw [← enorm_pow, Real.sq_sqrt h.coe_nonneg, Real.enorm_of_nonneg h.coe_nonneg, + ENNReal.ofReal_coe_nnreal] + +/-- **The heat semigroup satisfies the Kolmogorov moment criterion** with exponents `p = 4` and +`q = 2` and the fourth moment of the standard Gaussian as constant: the fourth moment of the +displacement over a time step `h` is exactly `h ^ 2` times that constant. -/ +theorem hasKolmogorovMoments_heatSemigroup : + heatSemigroup.HasKolmogorovMoments 4 2 gaussianFourthMoment := by + refine ⟨by norm_num, by norm_num, fun h y ↦ ?_⟩ + have hmeasf : Measurable (fun w : ℝ ↦ edist w y ^ (4 : ℝ)) := + (measurable_edist_left (x := y)).pow_const 4 + have hmeasg : Measurable (fun z : ℝ ↦ y + Real.sqrt (h : ℝ) * z) := by fun_prop + rw [heatSemigroup_apply, gaussianReal_eq_map_add_sqrt_mul, lintegral_map hmeasf hmeasg] + have hint : ∀ z : ℝ, edist (y + Real.sqrt (h : ℝ) * z) y ^ (4 : ℝ) = + ‖Real.sqrt (h : ℝ)‖ₑ ^ (4 : ℕ) * ‖z‖ₑ ^ (4 : ℕ) := by + intro z + rw [ENNReal.rpow_ofNat, edist_eq_enorm_sub, add_sub_cancel_left, enorm_mul, mul_pow] + simp_rw [hint] + rw [lintegral_const_mul _ (by fun_prop), coe_gaussianFourthMoment, ENNReal.rpow_ofNat, + show (4 : ℕ) = 2 * 2 from rfl, pow_mul, enorm_sqrt_sq] + exact le_of_eq (mul_comm _ _) + +end Moments + +section Process + +/-- The heat semigroup is Kolmogorov regular, by its moment bound. -/ +theorem kolmogorovRegular_heatSemigroup : + heatSemigroup.KolmogorovRegular isConservative_heatSemigroup := + SubMarkovKernelSemigroup.KolmogorovRegular.of_hasKolmogorovMoments _ + isConservative_heatSemigroup hasKolmogorovMoments_heatSemigroup + +/-- **The main theorem, applied to the heat semigroup.** There is exactly one Markov kernel from +the line to continuous paths whose finite-dimensional distributions are the Gaussian transition +laws of the heat semigroup. -/ +theorem existsUnique_continuousProcess_heatSemigroup : + ∃! Q : Kernel ℝ (ContinuousPath ℝ), IsMarkovKernel Q ∧ + ∀ I : Finset NNReal, + Q.map (ContinuousPath.finsetEvaluation I) = + SubMarkovKernelSemigroup.finiteSetKernel heatSemigroup I := + isFellerKernelSemigroup_heatSemigroup.existsUnique_continuousProcess_of_hasKolmogorovMoments + heatSemigroup isConservative_heatSemigroup hasKolmogorovMoments_heatSemigroup + +/-- **Brownian motion on the line**, as a Markov kernel from the starting point to continuous +paths: the continuous-path process of the heat semigroup. -/ +def brownianMotion : Kernel ℝ (ContinuousPath ℝ) := + SubMarkovKernelSemigroup.IsConservative.continuousProcess heatSemigroup + isConservative_heatSemigroup + +instance isMarkovKernel_brownianMotion : IsMarkovKernel brownianMotion := by + unfold brownianMotion + infer_instance + +/-- Every one-time marginal of Brownian motion started at `x` is the Gaussian law with mean `x` +and variance the elapsed time. -/ +theorem brownianMotion_map_eval (t : NNReal) (x : ℝ) : + (brownianMotion x).map (fun omega ↦ omega t) = gaussianReal x t := by + have hmeas : Measurable (fun omega : ContinuousPath ℝ ↦ omega t) := + ContinuousPath.measurable_coordinateProcess (alpha := ℝ) t + rw [brownianMotion, ← Kernel.map_apply _ hmeas, + SubMarkovKernelSemigroup.IsFellerKernelSemigroup.continuousProcess_map_eval_nnreal + heatSemigroup isConservative_heatSemigroup isFellerKernelSemigroup_heatSemigroup + kolmogorovRegular_heatSemigroup t, heatSemigroup_apply] + +/-- Every finite-dimensional distribution of Brownian motion is the corresponding finite-set +kernel of the heat semigroup. -/ +theorem brownianMotion_map_finsetEvaluation (I : Finset NNReal) : + brownianMotion.map (ContinuousPath.finsetEvaluation I) = + SubMarkovKernelSemigroup.finiteSetKernel heatSemigroup I := + isFellerKernelSemigroup_heatSemigroup.continuousProcess_map_finiteEvaluation heatSemigroup + isConservative_heatSemigroup kolmogorovRegular_heatSemigroup I + +/-- Brownian motion is the only Markov kernel into continuous paths with the finite-dimensional +distributions of the heat semigroup. -/ +theorem eq_brownianMotion_of_map_finsetEvaluation (Q : Kernel ℝ (ContinuousPath ℝ)) + [IsFiniteKernel Q] + (hQ : ∀ I : Finset NNReal, + Q.map (ContinuousPath.finsetEvaluation I) = + SubMarkovKernelSemigroup.finiteSetKernel heatSemigroup I) : + Q = brownianMotion := + SubMarkovKernelSemigroup.IsConservative.eq_continuousProcess_of_map_finiteEvaluation + heatSemigroup isConservative_heatSemigroup kolmogorovRegular_heatSemigroup Q hQ + +end Process + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/Identity.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/Identity.lean new file mode 100644 index 0000000000..e1210891ce --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/Identity.lean @@ -0,0 +1,194 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Main + +/-! +# The identity semigroup and its continuous-path process + +The transition semigroup that never moves: `idSemigroup t = Kernel.id` at every time. It is +conservative, Feller, and satisfies the Kolmogorov moment criterion with exponents `p = 1`, +`q = 2` and constant `M = 0`, so the existence-and-uniqueness theorem of `MarkovProcess.Main` +applies to it verbatim. The resulting process is identified: from every starting point `x` its +law is the Dirac mass at the constant path at `x`. + +This file witnesses that the hypotheses of the main theorem are jointly satisfiable; it proves +nothing about any other semigroup, and it makes no claim about a semigroup that actually moves +(see `MarkovProcess.Examples.Drift` for that). +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal ZeroAtInfty + +namespace MarkovProcess + +noncomputable section + +section Definition + +variable {alpha : Type*} [MeasurableSpace alpha] + +/-- The identity kernel semigroup: the transition kernel at every time is the identity kernel, +so the associated process never moves. -/ +def idSemigroup : SubMarkovKernelSemigroup alpha where + kernel := fun _ ↦ Kernel.id + measurable_kernel := (Kernel.id : Kernel alpha alpha).measurable.comp measurable_snd + kernel_zero := rfl + kernel_add := fun _ _ ↦ (Kernel.id_comp Kernel.id).symm + isSubMarkovKernel := fun _ ↦ IsSubMarkovKernel.id + +/-- Every transition measure of the identity semigroup is the Dirac mass at the starting +point. -/ +theorem idSemigroup_apply (t : NNReal) (x : alpha) : + (idSemigroup (alpha := alpha)) t x = Measure.dirac x := rfl + +/-- The identity semigroup is conservative: every transition measure has total mass one. -/ +theorem isConservative_idSemigroup : + (idSemigroup (alpha := alpha)).IsConservative := by + intro t x + rw [idSemigroup_apply t x] + exact measure_univ + +end Definition + +section Feller + +variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + +/-- Integrating a `C₀` function against the identity semigroup returns the function itself. -/ +theorem kernelIntegral_idSemigroup (t : NNReal) (f : C₀(alpha, ℝ)) : + kernelIntegral ((idSemigroup (alpha := alpha)) t) f = f := by + funext x + rw [kernelIntegral, idSemigroup_apply t x] + exact integral_dirac' (f : alpha → ℝ) x f.continuous.stronglyMeasurable + +/-- The identity semigroup maps `C₀` into itself. -/ +theorem mapsC0_idSemigroup : (idSemigroup (alpha := alpha)).MapsC0 := by + intro t f + rw [kernelIntegral_idSemigroup t f] + exact ⟨f.continuous, f.zero_at_infty'⟩ + +variable [LocallyCompactSpace alpha] + +/-- The identity semigroup is a Feller semigroup: its `C₀` operators are all the identity, so +they map `C₀` into itself and have constant, hence continuous, time orbits. -/ +theorem isFellerKernelSemigroup_idSemigroup : + (idSemigroup (alpha := alpha)).IsFellerKernelSemigroup := by + refine ⟨mapsC0_idSemigroup, fun f ↦ ?_⟩ + have hconst : (fun _ : NNReal ↦ (idSemigroup (alpha := alpha)).c0Operator + mapsC0_idSemigroup 0 f) = + fun t : NNReal ↦ (idSemigroup (alpha := alpha)).c0Operator mapsC0_idSemigroup t f := by + funext t + apply ZeroAtInftyContinuousMap.ext + intro x + rw [SubMarkovKernelSemigroup.c0Operator_apply, + SubMarkovKernelSemigroup.c0Operator_apply, + kernelIntegral_idSemigroup t f, kernelIntegral_idSemigroup 0 f] + rw [← hconst] + exact continuous_const + +end Feller + +section Moments + +variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + +/-- The identity semigroup satisfies the Kolmogorov moment criterion with `p = 1`, `q = 2` and +vanishing constant: the displacement over any time is identically zero. -/ +theorem hasKolmogorovMoments_idSemigroup : + (idSemigroup (alpha := alpha)).HasKolmogorovMoments 1 2 0 := by + refine ⟨one_pos, one_lt_two, fun h y ↦ ?_⟩ + have hmeas : Measurable (fun z : alpha ↦ edist z y ^ (1 : ℝ)) := + (measurable_edist_left (x := y)).pow_const 1 + rw [idSemigroup_apply h y, lintegral_dirac' y hmeas, edist_self, + ENNReal.zero_rpow_of_pos one_pos, ENNReal.coe_zero, zero_mul] + +end Moments + +section Process + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [LocallyCompactSpace alpha] [Nonempty alpha] + +omit [LocallyCompactSpace alpha] in +/-- The identity semigroup is Kolmogorov regular, by its moment bound. -/ +theorem kolmogorovRegular_idSemigroup : + (idSemigroup (alpha := alpha)).KolmogorovRegular isConservative_idSemigroup := + SubMarkovKernelSemigroup.KolmogorovRegular.of_hasKolmogorovMoments _ + isConservative_idSemigroup hasKolmogorovMoments_idSemigroup + +/-- **The main theorem, applied to the identity semigroup.** There is exactly one Markov kernel +from the state space to continuous paths whose finite-dimensional distributions are those of the +identity semigroup. In particular the hypotheses of +`SubMarkovKernelSemigroup.IsFellerKernelSemigroup.existsUnique_continuousProcess_of_hasKolmogorovMoments` +are jointly satisfiable. -/ +theorem existsUnique_continuousProcess_idSemigroup : + ∃! Q : Kernel alpha (ContinuousPath alpha), IsMarkovKernel Q ∧ + ∀ I : Finset NNReal, + Q.map (ContinuousPath.finsetEvaluation I) = + SubMarkovKernelSemigroup.finiteSetKernel (idSemigroup (alpha := alpha)) I := + isFellerKernelSemigroup_idSemigroup.existsUnique_continuousProcess_of_hasKolmogorovMoments + (idSemigroup (alpha := alpha)) isConservative_idSemigroup hasKolmogorovMoments_idSemigroup + +omit [LocallyCompactSpace alpha] in +private theorem ae_eq_const_of_continuousProcess_idSemigroup (x : alpha) : + (fun omega : ContinuousPath alpha ↦ omega) =ᵐ[ + SubMarkovKernelSemigroup.IsConservative.continuousProcess (idSemigroup (alpha := alpha)) + isConservative_idSemigroup x] + fun _ ↦ ContinuousMap.const NNReal x := by + set mu := SubMarkovKernelSemigroup.IsConservative.continuousProcess + (idSemigroup (alpha := alpha)) isConservative_idSemigroup x with hmu + have hcoord : ∀ q : DenseTime, ∀ᵐ omega ∂mu, + omega (DenseTime.castOrderEmbedding q) = x := by + intro q + have hmeas : Measurable + (fun omega : ContinuousPath alpha ↦ omega (DenseTime.castOrderEmbedding q)) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) _ + have hmap := SubMarkovKernelSemigroup.IsConservative.continuousProcess_map_eval + (idSemigroup (alpha := alpha)) isConservative_idSemigroup kolmogorovRegular_idSemigroup q + have hmapx : Measure.map (fun omega : ContinuousPath alpha ↦ + omega (DenseTime.castOrderEmbedding q)) mu = Measure.dirac x := by + rw [hmu, ← Kernel.map_apply _ hmeas, hmap, idSemigroup_apply] + have hsingleton : MeasurableSet ({x}ᶜ : Set alpha) := + (isClosed_singleton (x := x)).measurableSet.compl + have hzero : mu ((fun omega : ContinuousPath alpha ↦ + omega (DenseTime.castOrderEmbedding q)) ⁻¹' ({x}ᶜ : Set alpha)) = 0 := by + rw [← Measure.map_apply hmeas hsingleton, hmapx, Measure.dirac_apply' x hsingleton, + Set.indicator_of_notMem (by simp only [Set.mem_compl_iff, Set.mem_singleton_iff, + not_true_eq_false, not_false_eq_true])] + exact hzero + have hall : ∀ᵐ omega ∂mu, ∀ q : DenseTime, + omega (DenseTime.castOrderEmbedding q) = x := ae_all_iff.mpr hcoord + filter_upwards [hall] with omega homega + apply ContinuousPath.denseRestriction_injective + funext q + rw [ContinuousPath.denseRestriction_apply, ContinuousPath.denseRestriction_apply, homega q] + rfl + +omit [LocallyCompactSpace alpha] in +/-- **The continuous-path process of the identity semigroup is the constant path.** From every +starting point, the law of the process is the Dirac mass at the constant path at that point. -/ +theorem continuousProcess_idSemigroup_eq (x : alpha) : + SubMarkovKernelSemigroup.IsConservative.continuousProcess (idSemigroup (alpha := alpha)) + isConservative_idSemigroup x = + Measure.dirac (ContinuousMap.const NNReal x) := by + set mu := SubMarkovKernelSemigroup.IsConservative.continuousProcess + (idSemigroup (alpha := alpha)) isConservative_idSemigroup x with hmu + have hprob : IsProbabilityMeasure mu := by + rw [hmu] + infer_instance + calc mu = mu.map id := (Measure.map_id).symm + _ = mu.map (fun _ ↦ ContinuousMap.const NNReal x) := + Measure.map_congr (ae_eq_const_of_continuousProcess_idSemigroup x) + _ = mu Set.univ • Measure.dirac (ContinuousMap.const NNReal x) := Measure.map_const _ _ + _ = Measure.dirac (ContinuousMap.const NNReal x) := by + rw [measure_univ, one_smul] + +end Process + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller.lean new file mode 100644 index 0000000000..2560d4fff7 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller.lean @@ -0,0 +1,28 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion +import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeContinuityBase +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup + +/-! +# Feller + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Convergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Convergence.lean new file mode 100644 index 0000000000..41907f3346 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Convergence.lean @@ -0,0 +1,93 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit + +/-! +# Convergence of the backward `C₀` recursion along a family of semigroups + +The backward recursion of `Feller/BackwardC0Recursion.lean` evolves a nonempty ordered family of +one-coordinate `C₀` factors through the transitions of one Feller kernel semigroup. Here the +family of times and the factors are held fixed and the *semigroup* varies along a filter: if the +`C₀` semigroups converge strongly, so does the backward recursion, in the `C₀` norm. The +induction is one line per step: contractivity makes the outer transition insensitive to the +error accumulated by the inner one. + +Since the `C₀` norm is the supremum norm, this is exactly convergence of the coordinate-product +integrals against the finite-time kernels, uniformly in the starting point. + +Main results: `tendsto_backwardC0_of_tendsto_c0Semigroup`, +`tendstoUniformly_integral_coordinateProduct_finiteTimeKernel`. + +The factors and the observation times are fixed; nothing is asserted when they vary along the +filter as well, and no rate of convergence is claimed. +-/ + +open Filter MeasureTheory Topology +open scoped NNReal ZeroAtInfty BigOperators + +namespace MarkovProcess + +section Uniform + +variable {alpha : Type*} [TopologicalSpace alpha] {iota : Type*} {l : Filter iota} + +/-- Convergence in the `C₀` norm is uniform convergence of the evaluated functions. -/ +theorem tendstoUniformly_apply_of_tendsto {F : iota → C₀(alpha, ℝ)} {f : C₀(alpha, ℝ)} + (h : Tendsto F l (nhds f)) : TendstoUniformly (fun i x ↦ F i x) (fun x ↦ f x) l := + ZeroAtInftyContinuousMap.tendsto_iff_tendstoUniformly.mp h + +end Uniform + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] +variable {iota : Type*} {l : Filter iota} + +/-- **Strong convergence of the `C₀` semigroups propagates through the backward recursion.** +For a fixed nonempty ordered family of times and fixed one-coordinate factors, the backward +recursions of a family of Feller kernel semigroups converge in the `C₀` norm to the backward +recursion of the limit semigroup. -/ +theorem tendsto_backwardC0_of_tendsto_c0Semigroup + {P : iota → SubMarkovKernelSemigroup alpha} {Q : SubMarkovKernelSemigroup alpha} + (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hQ : Q.IsFellerKernelSemigroup) + (hconv : ∀ (t : NNReal) (f : C₀(alpha, ℝ)), + Tendsto (fun i ↦ (hP i).c0Semigroup t f) l (nhds (hQ.c0Semigroup t f))) + {n : ℕ} (times : FiniteOrderedTimes (n + 1)) (factors : Fin (n + 1) → C₀(alpha, ℝ)) : + Tendsto (fun i ↦ (hP i).backwardC0 times factors) l + (nhds (hQ.backwardC0 times factors)) := by + induction n with + | zero => + simpa only [IsFellerKernelSemigroup.backwardC0_zero] using hconv (times 0) (factors 0) + | succ n ih => + simp only [IsFellerKernelSemigroup.backwardC0_succ] + exact Semigroup.tendsto_apply_of_opNorm_le_one + (fun i ↦ (hP i).c0Semigroup (times 0)) (hQ.c0Semigroup (times 0)) + (fun i ↦ factors 0 * (hP i).backwardC0 times.relativeTail (Fin.tail factors)) + (factors 0 * hQ.backwardC0 times.relativeTail (Fin.tail factors)) + (fun i ↦ ((hP i).c0Semigroup).norm_operator_le_one _) (hconv (times 0) _) + (tendsto_const_nhds.mul (ih times.relativeTail (Fin.tail factors))) + +/-- **Uniform convergence of the coordinate-product integrals.** Strong convergence of the `C₀` +semigroups makes the finite-time integral of a product of one-coordinate `C₀` functions converge +uniformly in the starting point. -/ +theorem tendstoUniformly_integral_coordinateProduct_finiteTimeKernel + {P : iota → SubMarkovKernelSemigroup alpha} {Q : SubMarkovKernelSemigroup alpha} + (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hQ : Q.IsFellerKernelSemigroup) + (hconv : ∀ (t : NNReal) (f : C₀(alpha, ℝ)), + Tendsto (fun i ↦ (hP i).c0Semigroup t f) l (nhds (hQ.c0Semigroup t f))) + {n : ℕ} (times : FiniteOrderedTimes (n + 1)) (factors : Fin (n + 1) → C₀(alpha, ℝ)) : + TendstoUniformly + (fun i x ↦ ∫ path, ∏ j, factors j (path j) ∂finiteTimeKernel (P i) times x) + (fun x ↦ ∫ path, ∏ j, factors j (path j) ∂finiteTimeKernel Q times x) l := by + have h := tendstoUniformly_apply_of_tendsto + (tendsto_backwardC0_of_tendsto_c0Semigroup hP hQ hconv times factors) + simpa only [IsFellerKernelSemigroup.backwardC0_apply_eq_integral_finiteTimeKernel] using h + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean new file mode 100644 index 0000000000..bc6b4b0357 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean @@ -0,0 +1,127 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion +import Mathlib.Probability.Kernel.Composition.IntegralCompProd + +/-! +# Finite-time integral represented by the backward `C₀` recursion + +The backward Feller-semigroup recursion for a nonempty ordered family of `C₀` factors evaluates +to the integral of their coordinate product against the corresponding finite-time kernel. The +proof follows the recursive kernel construction and uses composition-product integration. + +No conservativity assumption is needed: sub-Markov finite-time kernels already give finite +measures, which suffice for bounded integrability. This is an analytic identification only; no +statement about path space is proved here, and the process itself is built in `Trajectory/`. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal ProbabilityTheory ZeroAtInfty + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + +omit [LocallyCompactSpace alpha] [T2Space alpha] in +private theorem integrable_coordinateProduct + {Omega : Type*} [MeasurableSpace Omega] {n : ℕ} + (factors : Fin n → C₀(alpha, ℝ)) (eval : Omega → Fin n → alpha) + (heval : Measurable eval) (mu : Measure Omega) [IsFiniteMeasure mu] : + Integrable (fun omega ↦ ∏ i, factors i (eval omega i)) mu := by + refine Integrable.of_bound ?_ (∏ i, ‖factors i‖) ?_ + · exact + (Finset.stronglyMeasurable_fun_prod Finset.univ fun i _ ↦ + ((factors i).measurable.comp + ((measurable_pi_apply i).comp heval)).stronglyMeasurable).aestronglyMeasurable + · filter_upwards [] with omega + rw [norm_prod] + apply Finset.prod_le_prod (fun _ _ ↦ norm_nonneg _) + intro i _ + simpa only [ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] using! + (factors i).toBCF.norm_coe_le_norm (eval omega i) + +omit [TopologicalSpace alpha] [BorelSpace alpha] [LocallyCompactSpace alpha] + [T2Space alpha] in +private theorem isFiniteKernel_finiteTimeKernel + (P : SubMarkovKernelSemigroup alpha) {n : ℕ} + (times : FiniteOrderedTimes n) : IsFiniteKernel (finiteTimeKernel P times) := by + induction n with + | zero => + rw [finiteTimeKernel_zero] + infer_instance + | succ n ih => + let : IsFiniteKernel (P (times 0)) := + (P.isSubMarkovKernel (times 0)).isFiniteKernel + let : IsFiniteKernel (finiteTimeKernel P times.relativeTail) := + ih times.relativeTail + rw [finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map] + infer_instance + +/-- Evaluation of the backward `C₀` recursion is the coordinate-product integral against the +finite-time kernel. -/ +theorem IsFellerKernelSemigroup.backwardC0_apply_eq_integral_finiteTimeKernel + {P : SubMarkovKernelSemigroup alpha} (hP : P.IsFellerKernelSemigroup) + {n : ℕ} (times : FiniteOrderedTimes (n + 1)) + (factors : Fin (n + 1) → C₀(alpha, ℝ)) (x : alpha) : + hP.backwardC0 times factors x = + ∫ path, ∏ i, factors i (path i) ∂finiteTimeKernel P times x := by + induction n generalizing x with + | zero => + rw [hP.backwardC0_zero, hP.c0Semigroup_apply_apply] + rw [← finiteTimeKernel_one_map_eval P times] + unfold kernelIntegral + rw [Kernel.map_apply _ (measurable_pi_apply 0)] + rw [integral_map (measurable_pi_apply 0).aemeasurable + (factors 0).measurable.stronglyMeasurable.aestronglyMeasurable] + congr 1 + funext path + rw [Fin.prod_univ_one] + | succ n ih => + let : IsFiniteKernel (P (times 0)) := + (P.isSubMarkovKernel (times 0)).isFiniteKernel + let : IsFiniteKernel (finiteTimeKernel P times.relativeTail) := + isFiniteKernel_finiteTimeKernel P times.relativeTail + let productTest : (Fin (n + 2) → alpha) → ℝ := + fun path ↦ ∏ i, factors i (path i) + have hProductTest : StronglyMeasurable productTest := by + exact Finset.stronglyMeasurable_fun_prod Finset.univ fun i _ ↦ + ((factors i).measurable.comp (measurable_pi_apply i)).stronglyMeasurable + rw [hP.backwardC0_succ, hP.c0Semigroup_apply_apply] + rw [finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map] + unfold kernelIntegral + change (∫ y, _ ∂P (times 0) x) = + ∫ path, productTest path ∂(Kernel.map + (P (times 0) ⊗ₖ Kernel.prodMkLeft alpha + (finiteTimeKernel P times.relativeTail)) + (fun z ↦ Fin.cons z.1 z.2)) x + rw [Kernel.map_apply _ measurable_finCons] + rw [integral_map measurable_finCons.aemeasurable + hProductTest.aestronglyMeasurable] + dsimp only [productTest] + rw [integral_compProd (integrable_coordinateProduct factors + (fun z ↦ Fin.cons z.1 z.2) measurable_finCons _)] + have heta : ∀ a, Kernel.prodMkLeft alpha + (finiteTimeKernel P times.relativeTail) (x, a) = + finiteTimeKernel P times.relativeTail a := by + intro a + ext s hs + rw [Kernel.prodMkLeft_apply'] + simp_rw [heta] + apply integral_congr_ae + filter_upwards [] with a + change factors 0 a * hP.backwardC0 times.relativeTail (Fin.tail factors) a = _ + have hprod : (fun b : Fin (n + 1) → alpha ↦ + ∏ i, factors i + (@Fin.cons (n + 1) (fun _ : Fin (n + 2) ↦ alpha) a b i)) = + fun b ↦ factors 0 a * ∏ i, (Fin.tail factors) i (b i) := by + funext b + rw [Fin.prod_univ_succ] + rfl + rw [hprod, integral_const_mul, + ih times.relativeTail (Fin.tail factors) a] + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Recursion.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Recursion.lean new file mode 100644 index 0000000000..bb6ac8b745 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Recursion.lean @@ -0,0 +1,87 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel + +/-! +# Backward `C₀` recursion for finite Feller transitions + +An ordered nonempty family of one-coordinate `C₀` factors determines a backward semigroup +recursion: evolve the last factors relative to the first time, multiply by the first factor, and +then evolve from the starting state to the first time. The recursion varies continuously in the +`C₀` norm when every ordered observation time converges. + +This file contains only the analytic recursion and its continuity. Its identification with an +integral against a finite-time kernel is in `Feller/BackwardC0Integral.lean`; no statement about +path space is proved here. +-/ + +open Filter Topology +open scoped NNReal ZeroAtInfty + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + +/-- Backward semigroup recursion for a nonempty ordered family of coordinatewise `C₀` factors. -/ +noncomputable def IsFellerKernelSemigroup.backwardC0 + {P : SubMarkovKernelSemigroup alpha} (hP : P.IsFellerKernelSemigroup) : + {n : ℕ} → FiniteOrderedTimes (n + 1) → + (Fin (n + 1) → C₀(alpha, ℝ)) → C₀(alpha, ℝ) + | 0, times, factors => hP.c0Semigroup (times 0) (factors 0) + | _n + 1, times, factors => + hP.c0Semigroup (times 0) + (factors 0 * hP.backwardC0 times.relativeTail (Fin.tail factors)) + +/-- The backward recursion for a singleton family is one Feller-semigroup application. -/ +@[simp] +theorem IsFellerKernelSemigroup.backwardC0_zero + {P : SubMarkovKernelSemigroup alpha} (hP : P.IsFellerKernelSemigroup) + (times : FiniteOrderedTimes 1) (factors : Fin 1 → C₀(alpha, ℝ)) : + hP.backwardC0 times factors = hP.c0Semigroup (times 0) (factors 0) := + rfl + +/-- At a successor length, the backward recursion multiplies the first factor by the recursively +evolved relative tail before applying the first transition. -/ +@[simp] +theorem IsFellerKernelSemigroup.backwardC0_succ + {P : SubMarkovKernelSemigroup alpha} (hP : P.IsFellerKernelSemigroup) + {n : ℕ} (times : FiniteOrderedTimes (n + 2)) + (factors : Fin (n + 2) → C₀(alpha, ℝ)) : + hP.backwardC0 times factors = hP.c0Semigroup (times 0) + (factors 0 * hP.backwardC0 times.relativeTail (Fin.tail factors)) := + rfl + +/-- The backward recursion is continuous in the `C₀` norm under coordinatewise convergence of a +nonempty ordered time family. -/ +theorem IsFellerKernelSemigroup.tendsto_backwardC0 + {P : SubMarkovKernelSemigroup alpha} (hP : P.IsFellerKernelSemigroup) + {X : Type*} {l : Filter X} {n : ℕ} + {times : X → FiniteOrderedTimes (n + 1)} + {times0 : FiniteOrderedTimes (n + 1)} + (ht : ∀ i, Tendsto (fun a ↦ times a i) l (nhds (times0 i))) + (factors : Fin (n + 1) → C₀(alpha, ℝ)) : + Tendsto (fun a ↦ hP.backwardC0 (times a) factors) l + (nhds (hP.backwardC0 times0 factors)) := by + induction n with + | zero => + simp only [backwardC0_zero] + exact hP.c0Semigroup.tendsto_apply_of_tendsto (ht 0) tendsto_const_nhds + | succ n ih => + have htail : ∀ i, Tendsto (fun a ↦ (times a).relativeTail i) l + (nhds (times0.relativeTail i)) := by + intro i + simpa only [FiniteOrderedTimes.relativeTail_apply] using + (ht i.succ).sub (ht 0) + have hinner := ih htail (Fin.tail factors) + simp only [backwardC0_succ] + exact hP.c0Semigroup.tendsto_apply_of_tendsto (ht 0) + (tendsto_const_nhds.mul hinner) + +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean new file mode 100644 index 0000000000..e7efc79571 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean @@ -0,0 +1,119 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity + +/-! +# Continuity of finite coordinate polynomials + +Continuity of finite-time integrals for one coordinate-product term extends to every finite sum +of such terms. The proof supplies explicit bounded integrability for the individual terms and +their coordinate polynomials before applying linearity of the integral. + +This file handles only explicit finite coordinate polynomials. The passage to arbitrary +compactly supported continuous tests is in `Feller/FiniteTimeCompactTestContinuity.lean`. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped NNReal ZeroAtInfty BigOperators + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + +omit [LocallyCompactSpace alpha] [T2Space alpha] in +private theorem integrable_coordinateProductTerm + {n : ℕ} (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) + (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : + Integrable term.toContinuousMap mu := by + have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ + (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by + induction term.factors with + | nil => exact stronglyMeasurable_const + | cons p factors ih => + simp only [List.map_cons, List.prod_cons] + exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul ih + have hfun : (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ + term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod := by + funext path + exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path + rw [hfun] + refine Integrable.of_bound (hprod.const_mul term.coefficient).aestronglyMeasurable + (‖term.coefficient‖ * (term.factors.map fun p ↦ ‖p.2‖).prod) ?_ + filter_upwards [] with path + rw [norm_mul, List.norm_prod] + apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) + induction term.factors with + | nil => + simp only [List.map_nil, List.prod_nil] + exact le_rfl + | cons p factors ih => + simp only [List.map_cons, List.prod_cons] + have all_nonneg : ∀ fs : List (Fin n × C₀(alpha, ℝ)), + 0 ≤ (fs.map fun q ↦ ‖q.2 (path q.1)‖).prod := by + intro fs + induction fs with + | nil => simp only [List.map_nil, List.prod_nil, zero_le_one] + | cons q fs ih_nonneg => + simp only [List.map_cons, List.prod_cons] + exact mul_nonneg (norm_nonneg _) ih_nonneg + have hnonneg : 0 ≤ + ((factors.map fun p ↦ p.2 (path p.1)).map norm).prod := by + simpa only [List.map_map, Function.comp_apply] using! all_nonneg factors + exact mul_le_mul (p.2.toBCF.norm_coe_le_norm (path p.1)) ih + hnonneg (norm_nonneg _) + +omit [LocallyCompactSpace alpha] [T2Space alpha] in +private theorem integrable_coordinatePolynomial + {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) + (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : + Integrable (PiContinuousMap.coordinatePolynomial terms) mu := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil] + change Integrable (fun _ : Fin n → alpha ↦ (0 : ℝ)) mu + refine Integrable.of_bound stronglyMeasurable_const.aestronglyMeasurable 0 ?_ + exact ae_of_all _ fun _ ↦ by + simpa only [norm_zero] using (le_refl (0 : ℝ)) + | cons term terms ih => + rw [PiContinuousMap.coordinatePolynomial_cons] + exact (integrable_coordinateProductTerm term mu).add ih + +/-- Finite-time integrals of an explicit coordinate polynomial vary continuously under +coordinatewise convergence of the ordered observation times. -/ +theorem IsFellerKernelSemigroup.tendsto_integral_coordinatePolynomial_finiteTimeKernel + {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) {X : Type*} {l : Filter X} {n : ℕ} + {times : X → FiniteOrderedTimes n} {times0 : FiniteOrderedTimes n} + (ht : ∀ i, Tendsto (fun a ↦ times a i) l (nhds (times0 i))) + (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) (x : alpha) : + Tendsto (fun a ↦ ∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel P (times a) x) l + (nhds (∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel P times0 x)) := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil, ContinuousMap.zero_apply, + integral_zero] + exact tendsto_const_nhds + | cons term terms ih => + have hIntegral (u : FiniteOrderedTimes n) : + ∫ path, PiContinuousMap.coordinatePolynomial (term :: terms) path + ∂finiteTimeKernel P u x = + (∫ path, term.toContinuousMap path ∂finiteTimeKernel P u x) + + ∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel P u x := by + let : IsProbabilityMeasure (finiteTimeKernel P u x) := + hP.isProbabilityMeasure_finiteTimeLaw P u x + rw [PiContinuousMap.coordinatePolynomial_cons] + apply integral_add + · exact integrable_coordinateProductTerm term _ + · exact integrable_coordinatePolynomial terms _ + simp_rw [hIntegral] + exact (hFeller.tendsto_integral_coordinateProductTerm_finiteTimeKernel + hP ht term x).add ih + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinateProductContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinateProductContinuity.lean new file mode 100644 index 0000000000..b4086989c2 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinateProductContinuity.lean @@ -0,0 +1,117 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction + +/-! +# Continuity of finite-time integrals of coordinate-product terms + +This file proves continuity, under coordinatewise convergence of ordered times, of the +finite-time-kernel integral of one `PiContinuousMap.CoordinateProductTerm`. The proof reduces +to the coordinates on which the term has factors and applies the backward `C₀` recursion. + +When there are no active coordinates, the integrand is its scalar coefficient. That branch +uses conservativity to identify the finite-time law as a probability measure; in particular, +it never attempts to construct a constant-one element of `C₀`. This is finite-dimensional +analytic infrastructure; no statement about path space is proved here. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped NNReal ZeroAtInfty BigOperators + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + +/-- The finite-time integral of a coordinate-product term varies continuously when every +ordered time coordinate varies continuously. -/ +theorem IsFellerKernelSemigroup.tendsto_integral_coordinateProductTerm_finiteTimeKernel + {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) {X : Type*} {l : Filter X} {n : ℕ} + {times : X → FiniteOrderedTimes n} {times0 : FiniteOrderedTimes n} + (ht : ∀ i, Tendsto (fun a ↦ times a i) l (nhds (times0 i))) + (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) (x : alpha) : + Tendsto (fun a ↦ ∫ path, term.toContinuousMap path ∂finiteTimeKernel P (times a) x) l + (nhds (∫ path, term.toContinuousMap path ∂finiteTimeKernel P times0 x)) := by + let A := PiContinuousMap.activeCoordinates term.factors + by_cases hA : A.card = 0 + · have hActive : PiContinuousMap.activeCoordinates term.factors = ∅ := by + exact Finset.card_eq_zero.mp hA + have hTerm (path : Fin n → alpha) : + term.toContinuousMap path = term.coefficient := by + rw [PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply_active] + simp only [PiContinuousMap.CoordinateProductTerm.activeEvaluation, hActive, + Finset.card_empty, Finset.prod_fin_eq_prod_range, Finset.prod_range_zero, mul_one] + have hIntegral (u : FiniteOrderedTimes n) : + ∫ path, term.toContinuousMap path ∂finiteTimeKernel P u x = term.coefficient := by + let : IsProbabilityMeasure (finiteTimeKernel P u x) := + hP.isProbabilityMeasure_finiteTimeLaw P u x + rw [integral_congr_ae (ae_of_all _ hTerm)] + simp only [integral_const, probReal_univ, one_smul] + simp_rw [hIntegral] + exact tendsto_const_nhds + · obtain ⟨k, hk⟩ := Nat.exists_eq_succ_of_ne_zero hA + let e := PiContinuousMap.activeOrderEmbedding term.factors + let ec : Fin (k + 1) ↪o Fin n := + (Fin.castOrderIso hk.symm).toOrderEmbedding.trans e + let factors : Fin (k + 1) → C₀(alpha, ℝ) := fun j ↦ + PiContinuousMap.activeNormalizedFactor term.factors (Fin.cast hk.symm j) + have htimes : ∀ i, Tendsto (fun a ↦ (times a).restrict ec i) l + (nhds (times0.restrict ec i)) := by + intro i + exact ht (ec i) + have hIntegral (u : FiniteOrderedTimes n) : + ∫ path, term.toContinuousMap path ∂finiteTimeKernel P u x = + term.coefficient * hFeller.backwardC0 + (u.restrict ec) factors x := by + let g : (Fin (k + 1) → alpha) → ℝ := + fun path ↦ ∏ i, factors i (path i) + have hg : StronglyMeasurable g := by + exact Finset.stronglyMeasurable_fun_prod Finset.univ fun i _ ↦ + ((factors i).measurable.comp (measurable_pi_apply i)).stronglyMeasurable + have hpoint : ∀ path : Fin n → alpha, + term.toContinuousMap path = + term.coefficient * g (FiniteOrderedTimes.restrictPath ec path) := by + intro path + rw [PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply_active] + simp only [PiContinuousMap.CoordinateProductTerm.activeEvaluation, g, + factors, FiniteOrderedTimes.restrictPath, ec, e, + RelEmbedding.coe_trans, Function.comp_apply, + OrderIso.coe_toOrderEmbedding] + congr 1 + exact ((Fin.castOrderIso hk.symm).toEquiv.prod_comp + (fun j ↦ PiContinuousMap.activeNormalizedFactor term.factors j + (path (PiContinuousMap.activeOrderEmbedding term.factors j)))).symm + calc + ∫ path, term.toContinuousMap path ∂finiteTimeKernel P u x = + ∫ path, term.coefficient * + g (FiniteOrderedTimes.restrictPath ec path) ∂finiteTimeKernel P u x := by + apply integral_congr_ae + exact ae_of_all _ hpoint + _ = term.coefficient * ∫ path, + g (FiniteOrderedTimes.restrictPath ec path) ∂finiteTimeKernel P u x := by + rw [integral_const_mul] + _ = term.coefficient * ∫ path, g path ∂ + (finiteTimeKernel P u).map (FiniteOrderedTimes.restrictPath ec) x := by + rw [Kernel.map_apply _ (FiniteOrderedTimes.measurable_restrictPath ec)] + rw [integral_map + (FiniteOrderedTimes.measurable_restrictPath ec).aemeasurable + hg.aestronglyMeasurable] + _ = term.coefficient * ∫ path, g path ∂ + finiteTimeKernel P (u.restrict ec) x := by + rw [hP.finiteTimeKernel_map_restrictPath P u ec] + _ = term.coefficient * hFeller.backwardC0 (u.restrict ec) factors x := by + rw [hFeller.backwardC0_apply_eq_integral_finiteTimeKernel] + simp_rw [hIntegral] + apply tendsto_const_nhds.mul + have hb := hFeller.tendsto_backwardC0 htimes factors + have heval : Continuous fun f : C₀(alpha, ℝ) ↦ f x := + (ZeroAtInftyContinuousMap.isometry_toBCF (α := alpha) (β := ℝ)).continuous.eval + continuous_const + exact heval.continuousAt.tendsto.comp hb +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/DensePhysicalFiniteSetContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/DensePhysicalFiniteSetContinuity.lean new file mode 100644 index 0000000000..7ab5339307 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/DensePhysicalFiniteSetContinuity.lean @@ -0,0 +1,79 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure + +/-! +# Compact-test bounds for finite dense-time laws + +Compact-test integrals against a physically indexed finite-set kernel, reindexed by dense-time +labels, are continuous in the starting point. Conservativity also gives a uniform norm bound by +the `C₀` norm of the test. Both statements include the empty coordinate set. + +This is finite-dimensional analytic infrastructure; no statement about path space is proved +here. The continuous-path process is built in `Trajectory/`. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal CompactlySupported ZeroAtInfty + +namespace MarkovProcess.SubMarkovKernelSemigroup + +section Continuity + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + +/-- A compact-test integral against a finite dense-time law is continuous in the starting +point. -/ +theorem IsFellerKernelSemigroup.continuous_integral_map_finiteSetKernel_pullbackPhysicalSet + {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) : + Continuous fun y ↦ ∫ z, f z ∂ + (finiteSetKernel P (denseTimePhysicalSet J)).map + (DenseTimePath.pullbackPhysicalSet J) y := by + have h := hFeller.continuous_integral_compactlySupported_finiteSetKernel hP + (denseTimePhysicalSet J) (DenseTimePath.pullbackPhysicalSetCompactTest J f) + simpa only [DenseTimePath.integral_map_finiteSetKernel_pullbackPhysicalSet P J f] using h + +end Continuity + +section Bound + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + +/-- A compact-test integral against a conservative finite dense-time law is bounded by the +test's canonical `C₀` norm. -/ +theorem IsConservative.norm_integral_map_finiteSetKernel_pullbackPhysicalSet_le + {P : SubMarkovKernelSemigroup alpha} (hP : P.IsConservative) + (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) (y : alpha) : + ‖∫ z, f z ∂(finiteSetKernel P (denseTimePhysicalSet J)).map + (DenseTimePath.pullbackPhysicalSet J) y‖ ≤ + ‖PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f‖ := by + let K := (finiteSetKernel P (denseTimePhysicalSet J)).map + (DenseTimePath.pullbackPhysicalSet J) + let : IsMarkovKernel K := by + let : IsMarkovKernel (finiteSetKernel P (denseTimePhysicalSet J)) := + hP.isMarkovKernel_finiteSetKernel P (denseTimePhysicalSet J) + exact Kernel.IsMarkovKernel.map _ (DenseTimePath.measurable_pullbackPhysicalSet J) + let : IsProbabilityMeasure (K y) := IsMarkovKernel.isProbabilityMeasure y + let f₀ : C₀(J → alpha, ℝ) := + PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f + change ‖∫ z, f z ∂K y‖ ≤ ‖f₀‖ + calc + ‖∫ z, f z ∂K y‖ ≤ ‖f₀‖ * (K y).real Set.univ := + MeasureTheory.norm_integral_le_of_norm_le_const + (ae_of_all _ fun z ↦ by + simpa only [f₀, + PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap_apply] using! + f₀.toBCF.norm_coe_le_norm z) + _ = ‖f₀‖ := by + simp only [measureReal_def, measure_univ, ENNReal.toReal_one, mul_one] + +end Bound + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteDenseApproximationContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteDenseApproximationContinuity.lean new file mode 100644 index 0000000000..123ee789f4 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteDenseApproximationContinuity.lean @@ -0,0 +1,61 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport + +/-! +# Feller continuity of finite dense approximations + +This file proves compact-test convergence of the finite laws obtained by simultaneously +approximating a finite set of nonnegative-real times by dense times. Both the approximating and +limiting kernels are transported through the same ordered-coordinate homeomorphism, after which +the finite-time Feller continuity theorem applies directly. + +This is finite-dimensional infrastructure. No path-space Markov property is asserted here; the +Markov and strong Markov statements are in `MarkovProcess/Main.lean`. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped NNReal CompactlySupported + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + +/-- Compact-test integrals against finite dense approximations converge to the corresponding +finite-set-kernel integral under simultaneous coordinatewise convergence of the times. -/ +theorem IsFellerKernelSemigroup.tendsto_integral_compactlySupported_finiteDenseApproximationKernel + {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) {I : Finset NNReal} (q : ℕ → I ↪o DenseTime) + (hq : ∀ t, Tendsto + (fun k ↦ DenseTime.castOrderEmbedding (q k t)) atTop (nhds (t : NNReal))) + (f : C_c(I → alpha, ℝ)) (x : alpha) : + Tendsto + (fun k ↦ ∫ y, f y ∂finiteDenseApproximationKernel P (q k) x) + atTop (nhds (∫ y, f y ∂finiteSetKernel P I x)) := by + have htime : ∀ i, Tendsto + (fun k ↦ finiteDenseApproximationOrderedTimes (q k) i) atTop + (nhds (finiteSetTimes I i)) := + tendsto_finiteDenseApproximationOrderedTimes q hq + have h := hFeller.tendsto_integral_compactlySupported_finiteTimeKernel + hP htime (pullbackFiniteSetCompactTest I f) x + have happrox (k : ℕ) : + (∫ y, f y ∂finiteDenseApproximationKernel P (q k) x) = + ∫ path, pullbackFiniteSetCompactTest I f path + ∂finiteTimeKernel P (finiteDenseApproximationOrderedTimes (q k)) x := by + rw [finiteDenseApproximationKernel_eq_map_finiteTimeKernel P hP (q k), + Kernel.map_apply _ (measurable_orderedPathToFiniteSet I)] + exact integral_map_orderedPathToFiniteSet I f _ + rw [show (fun k ↦ ∫ y, f y ∂finiteDenseApproximationKernel P (q k) x) = + (fun k ↦ ∫ path, pullbackFiniteSetCompactTest I f path + ∂finiteTimeKernel P (finiteDenseApproximationOrderedTimes (q k)) x) from + funext happrox, + integral_finiteSetKernel_eq_integral_pullbackFiniteSetCompactTest P I f x] + exact h + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetCompactTestContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetCompactTestContinuity.lean new file mode 100644 index 0000000000..744eca1e37 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetCompactTestContinuity.lean @@ -0,0 +1,39 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport + +/-! +# Continuity of finite-set compact-test integrals + +Compact-test integrals against a conservative Feller semigroup's finite-set kernel vary +continuously with the starting point. The proof transports the test to increasing coordinates +and applies fixed-time finite-kernel continuity. The empty finite set is included without a +separate nonemptiness assumption. + +This is finite-dimensional analytic infrastructure; no statement about path space is proved +here. The continuous-path process is built in `Trajectory/`. +-/ + +open MeasureTheory +open scoped NNReal CompactlySupported + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + +/-- A compact-test integral against a finite-set kernel is continuous in the starting point. -/ +theorem IsFellerKernelSemigroup.continuous_integral_compactlySupported_finiteSetKernel + {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) (I : Finset NNReal) (f : C_c(I → alpha, ℝ)) : + Continuous fun x ↦ ∫ path, f path ∂finiteSetKernel P I x := by + have h := hFeller.continuous_integral_compactlySupported_finiteTimeKernel hP + (finiteSetTimes I) (pullbackFiniteSetCompactTest I f) + simpa only [integral_finiteSetKernel_eq_integral_pullbackFiniteSetCompactTest P I f] + using h + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetConvergence.lean new file mode 100644 index 0000000000..67d378e6b2 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetConvergence.lean @@ -0,0 +1,87 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport +import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence + +/-! +# Convergence of the finite-dimensional laws of Feller semigroups + +The finite-time results of `Feller/FiniteTimeConvergence.lean`, reindexed by a finite set of +times. For conservative Feller kernel semigroups whose `C₀` semigroups converge strongly, the +finite-set laws converge against every compactly supported continuous test, uniformly in the +starting point; and, at a fixed starting point, against every bounded continuous test, which is +weak convergence of the finite-dimensional distributions. + +The second statement cannot be uniform in the starting point: it uses the tightness of the +limiting law at that point (`Kernel/WeakConvergence.lean`), and on a noncompact state space the +finite-dimensional laws of a family of starting points escaping to infinity are not tight. + +Main results: `tendstoUniformly_integral_compactlySupported_finiteSetKernel`, +`tendsto_integral_boundedContinuous_finiteSetKernel`. + +The set of observation times is fixed; nothing is asserted about joint convergence in the times +and the semigroups. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped BoundedContinuousFunction CompactlySupported NNReal ZeroAtInfty + +namespace MarkovProcess.SubMarkovKernelSemigroup + +section CompactTest + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] [SecondCountableTopology alpha] +variable {iota : Type*} {l : Filter iota} +variable {P : iota → SubMarkovKernelSemigroup alpha} {Q : SubMarkovKernelSemigroup alpha} + +/-- **Uniform convergence of the finite-set laws against compactly supported tests.** -/ +theorem tendstoUniformly_integral_compactlySupported_finiteSetKernel + (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hPc : ∀ i, (P i).IsConservative) + (hQ : Q.IsFellerKernelSemigroup) (hQc : Q.IsConservative) + (hconv : ∀ (t : NNReal) (f : C₀(alpha, ℝ)), + Tendsto (fun i ↦ (hP i).c0Semigroup t f) l (nhds (hQ.c0Semigroup t f))) + (I : Finset NNReal) (f : C_c(I → alpha, ℝ)) : + TendstoUniformly (fun i x ↦ ∫ path, f path ∂finiteSetKernel (P i) I x) + (fun x ↦ ∫ path, f path ∂finiteSetKernel Q I x) l := by + have h := tendstoUniformly_integral_compactlySupported_finiteTimeKernel hP hPc hQ hQc hconv + (finiteSetTimes I) (pullbackFiniteSetCompactTest I f) + simpa only [integral_finiteSetKernel_eq_integral_pullbackFiniteSetCompactTest] using h + +end CompactTest + +section BoundedContinuousTest + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [SecondCountableTopology alpha] [LocallyCompactSpace alpha] +variable {iota : Type*} {l : Filter iota} +variable {P : iota → SubMarkovKernelSemigroup alpha} {Q : SubMarkovKernelSemigroup alpha} + +/-- **Weak convergence of the finite-dimensional laws.** At every starting point, the finite-set +law of `P i` converges to that of `Q` against every bounded continuous test function. -/ +theorem tendsto_integral_boundedContinuous_finiteSetKernel + (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hPc : ∀ i, (P i).IsConservative) + (hQ : Q.IsFellerKernelSemigroup) (hQc : Q.IsConservative) + (hconv : ∀ (t : NNReal) (f : C₀(alpha, ℝ)), + Tendsto (fun i ↦ (hP i).c0Semigroup t f) l (nhds (hQ.c0Semigroup t f))) + (I : Finset NNReal) (f : (I → alpha) →ᵇ ℝ) (x : alpha) : + Tendsto (fun i ↦ ∫ path, f path ∂finiteSetKernel (P i) I x) l + (nhds (∫ path, f path ∂finiteSetKernel Q I x)) := by + let : ∀ i, IsMarkovKernel (finiteSetKernel (P i) I) := fun i ↦ + (hPc i).isMarkovKernel_finiteSetKernel (P i) I + let : IsMarkovKernel (finiteSetKernel Q I) := hQc.isMarkovKernel_finiteSetKernel Q I + let : ∀ i, IsProbabilityMeasure (finiteSetKernel (P i) I x) := fun i ↦ + IsMarkovKernel.isProbabilityMeasure x + let : IsProbabilityMeasure (finiteSetKernel Q I x) := IsMarkovKernel.isProbabilityMeasure x + refine tendsto_integral_boundedContinuous_of_tendsto_compactlySupported + (fun i ↦ finiteSetKernel (P i) I x) (finiteSetKernel Q I x) (fun g ↦ ?_) f + exact (tendstoUniformly_integral_compactlySupported_finiteSetKernel hP hPc hQ hQc hconv + I g).tendsto_at x + +end BoundedContinuousTest + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeCompactTestContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeCompactTestContinuity.lean new file mode 100644 index 0000000000..3df21eb34f --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeCompactTestContinuity.lean @@ -0,0 +1,209 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity +import Mathlib.MeasureTheory.Integral.CompactlySupported + +/-! +# Continuity of finite-time integrals of compactly supported tests + +This file extends finite coordinate-polynomial continuity to arbitrary compactly supported +continuous tests by uniform approximation. Conservativity makes every finite-time law a +probability measure, so the approximation error is uniform in the ordered time family. + +The measurable structure on a finite product need not expose an `OpensMeasurableSpace` instance +under the standing assumptions. We therefore derive strong measurability of the test from its +coordinate-polynomial approximants instead of adding that extra assumption. This is +finite-dimensional analytic infrastructure; no statement about path space is proved here. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped NNReal ZeroAtInfty BigOperators CompactlySupported + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + +omit [LocallyCompactSpace alpha] [T2Space alpha] in +private theorem integrable_coordinateProductTerm + {n : ℕ} (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) + (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : + Integrable term.toContinuousMap mu := by + have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ + (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by + induction term.factors with + | nil => exact stronglyMeasurable_const + | cons p factors ih => + simp only [List.map_cons, List.prod_cons] + exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul ih + rw [show (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ + term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by + funext path + exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] + refine Integrable.of_bound (hprod.const_mul term.coefficient).aestronglyMeasurable + (‖term.coefficient‖ * (term.factors.map fun p ↦ ‖p.2‖).prod) ?_ + filter_upwards [] with path + rw [norm_mul, List.norm_prod] + apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) + induction term.factors with + | nil => + simp only [List.map_nil, List.prod_nil] + exact le_rfl + | cons p factors ih => + simp only [List.map_cons, List.prod_cons] + have all_nonneg : ∀ fs : List (Fin n × C₀(alpha, ℝ)), + 0 ≤ (fs.map fun q ↦ ‖q.2 (path q.1)‖).prod := by + intro fs + induction fs with + | nil => simp only [List.map_nil, List.prod_nil, zero_le_one] + | cons q fs ih_nonneg => + simp only [List.map_cons, List.prod_cons] + exact mul_nonneg (norm_nonneg _) ih_nonneg + have hnonneg : 0 ≤ + ((factors.map fun p ↦ p.2 (path p.1)).map norm).prod := by + simpa only [List.map_map, Function.comp_apply] using! all_nonneg factors + exact mul_le_mul (p.2.toBCF.norm_coe_le_norm (path p.1)) ih + hnonneg (norm_nonneg _) + +omit [LocallyCompactSpace alpha] [T2Space alpha] in +private theorem integrable_coordinatePolynomial + {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) + (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : + Integrable (PiContinuousMap.coordinatePolynomial terms) mu := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil] + change Integrable (fun _ : Fin n → alpha ↦ (0 : ℝ)) mu + refine Integrable.of_bound stronglyMeasurable_const.aestronglyMeasurable 0 ?_ + exact ae_of_all _ fun _ ↦ by + simpa only [norm_zero] using (le_refl (0 : ℝ)) + | cons term terms ih => + rw [PiContinuousMap.coordinatePolynomial_cons] + exact (integrable_coordinateProductTerm term mu).add ih + +omit [LocallyCompactSpace alpha] [T2Space alpha] in +private theorem stronglyMeasurable_coordinatePolynomial + {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) : + StronglyMeasurable (PiContinuousMap.coordinatePolynomial terms) := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil] + exact stronglyMeasurable_const + | cons term terms ih => + rw [PiContinuousMap.coordinatePolynomial_cons] + apply StronglyMeasurable.add _ ih + have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ + (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by + induction term.factors with + | nil => exact stronglyMeasurable_const + | cons p factors ihFactors => + simp only [List.map_cons, List.prod_cons] + exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul + ihFactors + rw [show (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ + term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by + funext path + exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] + exact hprod.const_mul term.coefficient + +-- This approximation argument avoids assuming `OpensMeasurableSpace (Fin n → alpha)`. +private theorem stronglyMeasurable_compactlySupported_fin + {n : ℕ} (f : C_c(Fin n → alpha, ℝ)) : StronglyMeasurable f := by + have hexists (m : ℕ) : + ∃ terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha), + ∀ x, ‖PiContinuousMap.coordinatePolynomial terms x - f x‖ < + 1 / ((m : ℝ) + 1) := by + have hpositive : 0 < 1 / ((m : ℝ) + 1) := by positivity + obtain ⟨terms, hterms⟩ := + PiContinuousMap.exists_coordinateProductTerms_near_compactlySupported f hpositive + exact ⟨terms, fun x ↦ by + rw [PiContinuousMap.coordinatePolynomial_apply] + exact hterms x⟩ + choose terms hterms using hexists + apply stronglyMeasurable_of_tendsto atTop + (fun m ↦ stronglyMeasurable_coordinatePolynomial (terms m)) + rw [tendsto_pi_nhds] + intro x + rw [Metric.tendsto_nhds] + intro epsilon hepsilon + have hscalar : Tendsto (fun m : ℕ ↦ (1 : ℝ) / ((m : ℝ) + 1)) atTop (nhds 0) := + tendsto_one_div_add_atTop_nhds_zero_nat + rw [Metric.tendsto_nhds] at hscalar + filter_upwards [hscalar epsilon hepsilon] with m hm + rw [Real.dist_eq, sub_zero, abs_of_pos (by positivity)] at hm + exact (hterms m x).trans_le hm.le + +/-- Finite-time integrals of compactly supported continuous tests vary continuously under +coordinatewise convergence of the ordered observation times. -/ +theorem IsFellerKernelSemigroup.tendsto_integral_compactlySupported_finiteTimeKernel + {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) {X : Type*} {l : Filter X} {n : ℕ} + {times : X → FiniteOrderedTimes n} {times0 : FiniteOrderedTimes n} + (ht : ∀ i, Tendsto (fun a ↦ times a i) l (nhds (times0 i))) + (f : C_c(Fin n → alpha, ℝ)) (x : alpha) : + Tendsto (fun a ↦ ∫ path, f path ∂finiteTimeKernel P (times a) x) l + (nhds (∫ path, f path ∂finiteTimeKernel P times0 x)) := by + rw [Metric.tendsto_nhds] + intro epsilon hepsilon + obtain ⟨terms, hterms⟩ := + PiContinuousMap.exists_coordinateProductTerms_near_compactlySupported f + (div_pos hepsilon (by norm_num : (0 : ℝ) < 3)) + let polynomial := PiContinuousMap.coordinatePolynomial terms + have hnear (path : Fin n → alpha) : ‖polynomial path - f path‖ < epsilon / 3 := by + rw [PiContinuousMap.coordinatePolynomial_apply] + exact hterms path + have hApprox (u : FiniteOrderedTimes n) : + dist (∫ path, polynomial path ∂finiteTimeKernel P u x) + (∫ path, f path ∂finiteTimeKernel P u x) ≤ epsilon / 3 := by + let : IsProbabilityMeasure (finiteTimeKernel P u x) := + hP.isProbabilityMeasure_finiteTimeLaw P u x + have hdiff : Integrable (fun path ↦ polynomial path - f path) + (finiteTimeKernel P u x) := by + apply Integrable.of_bound (C := epsilon / 3) + · exact (stronglyMeasurable_coordinatePolynomial terms).sub + (stronglyMeasurable_compactlySupported_fin f) |>.aestronglyMeasurable + · exact ae_of_all _ fun path ↦ (hnear path).le + have hp : Integrable polynomial (finiteTimeKernel P u x) := + integrable_coordinatePolynomial terms _ + have hf : Integrable f (finiteTimeKernel P u x) := by + have hsub := hp.sub hdiff + apply hsub.congr + exact ae_of_all _ fun path ↦ by simp only [Pi.sub_apply, sub_sub_cancel] + rw [Real.dist_eq, ← MeasureTheory.integral_sub hp hf] + calc + ‖∫ path, polynomial path - f path ∂finiteTimeKernel P u x‖ ≤ + (epsilon / 3) * (finiteTimeKernel P u x).real Set.univ := + MeasureTheory.norm_integral_le_of_norm_le_const + (ae_of_all _ fun path ↦ (hnear path).le) + _ = epsilon / 3 := by + simp only [measureReal_def, measure_univ, ENNReal.toReal_one, mul_one] + have hPolynomial := + hFeller.tendsto_integral_coordinatePolynomial_finiteTimeKernel hP ht terms x + rw [Metric.tendsto_nhds] at hPolynomial + filter_upwards [hPolynomial (epsilon / 3) + (div_pos hepsilon (by norm_num : (0 : ℝ) < 3))] with a ha + calc + dist (∫ path, f path ∂finiteTimeKernel P (times a) x) + (∫ path, f path ∂finiteTimeKernel P times0 x) ≤ + dist (∫ path, f path ∂finiteTimeKernel P (times a) x) + (∫ path, polynomial path ∂finiteTimeKernel P (times a) x) + + dist (∫ path, polynomial path ∂finiteTimeKernel P (times a) x) + (∫ path, f path ∂finiteTimeKernel P times0 x) := dist_triangle _ _ _ + _ ≤ dist (∫ path, f path ∂finiteTimeKernel P (times a) x) + (∫ path, polynomial path ∂finiteTimeKernel P (times a) x) + + (dist (∫ path, polynomial path ∂finiteTimeKernel P (times a) x) + (∫ path, polynomial path ∂finiteTimeKernel P times0 x) + + dist (∫ path, polynomial path ∂finiteTimeKernel P times0 x) + (∫ path, f path ∂finiteTimeKernel P times0 x)) := by + apply add_le_add_right + exact dist_triangle _ _ _ + _ < epsilon := by + have hleft := hApprox (times a) + rw [dist_comm] at hleft + have hright := hApprox times0 + linarith only [hleft, ha, hright] + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeContinuityBase.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeContinuityBase.lean new file mode 100644 index 0000000000..e77ad56f26 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeContinuityBase.lean @@ -0,0 +1,43 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel + +/-! +# Singleton finite-time Feller continuity + +For a one-coordinate finite-time kernel, evaluation at the unique coordinate recovers the +transition kernel at that time. Feller continuity therefore gives convergence of its `C₀` test +integrals as the observation time varies. This is the base case for a recursive finite-time +continuity argument; no higher-dimensional continuity is asserted here. +-/ + +open Filter MeasureTheory Topology +open scoped NNReal ZeroAtInfty + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +variable {alpha X : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + +/-- Kernel integrals of `C₀` tests against singleton finite-time laws vary continuously with the +unique observation time. -/ +theorem IsFellerKernelSemigroup.tendsto_kernelIntegral_finiteTimeKernel_one_map_eval + {P : SubMarkovKernelSemigroup alpha} (hP : P.IsFellerKernelSemigroup) + {l : Filter X} {times : X → FiniteOrderedTimes 1} + {times0 : FiniteOrderedTimes 1} + (ht : Tendsto (fun a ↦ times a 0) l (nhds (times0 0))) + (f : C₀(alpha, ℝ)) (x : alpha) : + Tendsto (fun a ↦ kernelIntegral + ((finiteTimeKernel P (times a)).map (fun path ↦ path 0)) f x) + l (nhds (kernelIntegral + ((finiteTimeKernel P times0).map (fun path ↦ path 0)) f x)) := by + simp_rw [finiteTimeKernel_one_map_eval] + exact hP.tendsto_kernelIntegral_c0 ht tendsto_const_nhds x + +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean new file mode 100644 index 0000000000..47021f3160 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean @@ -0,0 +1,375 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +import Mathlib.MeasureTheory.Integral.CompactlySupported + +/-! +# Convergence of finite-time laws along a family of Feller semigroups + +Let `P i` be conservative Feller kernel semigroups whose `C₀` semigroups converge strongly to +that of a conservative Feller kernel semigroup `Q`. Then, at every fixed finite ordered family +of observation times, the finite-time laws converge, uniformly in the starting point: + +* for a coordinate-product term, by reduction to the coordinates carrying a factor and the + backward `C₀` recursion (`Feller/BackwardC0Convergence.lean`); a term with no active + coordinate integrates to its coefficient because the finite-time law is a probability measure; +* for a finite coordinate polynomial, by linearity; +* for an arbitrary compactly supported continuous test, by uniform approximation with coordinate + polynomials (`FiniteTime/FiniteProductCoordinateNormalForm.lean`), the approximation error + being uniform because the laws are probability measures. + +Main results: `tendstoUniformly_integral_coordinateProductTerm_finiteTimeKernel`, +`tendstoUniformly_integral_coordinatePolynomial_finiteTimeKernel`, +`tendstoUniformly_integral_compactlySupported_finiteTimeKernel`. + +The observation times are fixed throughout; nothing is asserted for test functions that are only +bounded and continuous, which needs the tightness of the limiting law and is therefore not +uniform in the starting point. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped NNReal ZeroAtInfty BigOperators CompactlySupported + +namespace MarkovProcess + +section UniformAlgebra + +variable {beta : Type*} {iota : Type*} {l : Filter iota} + +/-- A family of constants converges uniformly to that constant. -/ +theorem tendstoUniformly_const (c : ℝ) : + TendstoUniformly (fun (_ : iota) (_ : beta) ↦ c) (fun _ ↦ c) l := + tendstoUniformlyOn_univ.mp (tendsto_const_nhds.tendstoUniformlyOn_const Set.univ) + +/-- Uniform convergence is preserved by multiplication with a fixed scalar. -/ +theorem tendstoUniformly_const_mul {F : iota → beta → ℝ} {f : beta → ℝ} + (h : TendstoUniformly F f l) (c : ℝ) : + TendstoUniformly (fun i x ↦ c * F i x) (fun x ↦ c * f x) l := + (uniformContinuous_const_smul c).comp_tendstoUniformly h + +/-- Uniform convergence is preserved by addition. -/ +theorem tendstoUniformly_add {F G : iota → beta → ℝ} {f g : beta → ℝ} + (hf : TendstoUniformly F f l) (hg : TendstoUniformly G g l) : + TendstoUniformly (fun i x ↦ F i x + G i x) (fun x ↦ f x + g x) l := + hf.add hg + +end UniformAlgebra + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] +variable {iota : Type*} {l : Filter iota} + +section Integrability + +omit [LocallyCompactSpace alpha] [T2Space alpha] in +private theorem integrable_coordinateProductTerm + {n : ℕ} (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) + (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : + Integrable term.toContinuousMap mu := by + have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ + (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by + induction term.factors with + | nil => exact stronglyMeasurable_const + | cons p factors ih => + simp only [List.map_cons, List.prod_cons] + exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul ih + have hfun : (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ + term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod := by + funext path + exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path + rw [hfun] + refine Integrable.of_bound (hprod.const_mul term.coefficient).aestronglyMeasurable + (‖term.coefficient‖ * (term.factors.map fun p ↦ ‖p.2‖).prod) ?_ + filter_upwards [] with path + rw [norm_mul, List.norm_prod] + apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) + induction term.factors with + | nil => + simp only [List.map_nil, List.prod_nil] + exact le_rfl + | cons p factors ih => + simp only [List.map_cons, List.prod_cons] + have all_nonneg : ∀ fs : List (Fin n × C₀(alpha, ℝ)), + 0 ≤ (fs.map fun q ↦ ‖q.2 (path q.1)‖).prod := by + intro fs + induction fs with + | nil => simp only [List.map_nil, List.prod_nil, zero_le_one] + | cons q fs ih_nonneg => + simp only [List.map_cons, List.prod_cons] + exact mul_nonneg (norm_nonneg _) ih_nonneg + have hnonneg : 0 ≤ ((factors.map fun p ↦ p.2 (path p.1)).map norm).prod := by + simpa only [List.map_map, Function.comp_apply] using! all_nonneg factors + exact mul_le_mul (p.2.toBCF.norm_coe_le_norm (path p.1)) ih hnonneg (norm_nonneg _) + +omit [LocallyCompactSpace alpha] [T2Space alpha] in +private theorem integrable_coordinatePolynomial + {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) + (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : + Integrable (PiContinuousMap.coordinatePolynomial terms) mu := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil] + change Integrable (fun _ : Fin n → alpha ↦ (0 : ℝ)) mu + exact integrable_zero _ _ _ + | cons term terms ih => + rw [PiContinuousMap.coordinatePolynomial_cons] + exact (integrable_coordinateProductTerm term mu).add ih + +end Integrability + +section ActiveReduction + +/-- The increasing enumeration of the active coordinates of a coordinate-product term, read at a +positive cardinality of the active set. -/ +private def activeEmbedding {n k : ℕ} (factors : List (Fin n × C₀(alpha, ℝ))) + (hk : (PiContinuousMap.activeCoordinates factors).card = k + 1) : Fin (k + 1) ↪o Fin n := + (Fin.castOrderIso hk.symm).toOrderEmbedding.trans + (PiContinuousMap.activeOrderEmbedding factors) + +/-- The normalized `C₀` factors at the active coordinates, indexed in increasing order. -/ +private def activeFactor {n k : ℕ} (factors : List (Fin n × C₀(alpha, ℝ))) + (hk : (PiContinuousMap.activeCoordinates factors).card = k + 1) : + Fin (k + 1) → C₀(alpha, ℝ) := + fun j ↦ PiContinuousMap.activeNormalizedFactor factors (Fin.cast hk.symm j) + +omit [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] in +/-- A coordinate-product term with no active coordinate integrates to its coefficient. -/ +private theorem integral_coordinateProductTerm_eq_coefficient + {Q : SubMarkovKernelSemigroup alpha} (hQc : Q.IsConservative) {n : ℕ} + (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) + (hA : PiContinuousMap.activeCoordinates term.factors = ∅) + (u : FiniteOrderedTimes n) (x : alpha) : + ∫ path, term.toContinuousMap path ∂finiteTimeKernel Q u x = term.coefficient := by + let : IsProbabilityMeasure (finiteTimeKernel Q u x) := + hQc.isProbabilityMeasure_finiteTimeLaw Q u x + have hTerm : ∀ path : Fin n → alpha, term.toContinuousMap path = term.coefficient := by + intro path + rw [PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply_active] + simp only [PiContinuousMap.CoordinateProductTerm.activeEvaluation, hA, + Finset.card_empty, Finset.prod_fin_eq_prod_range, Finset.prod_range_zero, mul_one] + rw [integral_congr_ae (ae_of_all _ hTerm)] + simp only [integral_const, probReal_univ, one_smul] + +/-- A coordinate-product term with active coordinates integrates to its coefficient times the +backward `C₀` recursion at the active times. -/ +private theorem integral_coordinateProductTerm_eq_backwardC0 + {Q : SubMarkovKernelSemigroup alpha} (hQ : Q.IsFellerKernelSemigroup) + (hQc : Q.IsConservative) {n k : ℕ} + (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) + (hk : (PiContinuousMap.activeCoordinates term.factors).card = k + 1) + (u : FiniteOrderedTimes n) (x : alpha) : + ∫ path, term.toContinuousMap path ∂finiteTimeKernel Q u x = + term.coefficient * hQ.backwardC0 (u.restrict (activeEmbedding term.factors hk)) + (activeFactor term.factors hk) x := by + have hg : StronglyMeasurable + (fun path : Fin (k + 1) → alpha ↦ ∏ i, activeFactor term.factors hk i (path i)) := + Finset.stronglyMeasurable_fun_prod Finset.univ fun i _ ↦ + (((activeFactor term.factors hk i).measurable.comp + (measurable_pi_apply i)).stronglyMeasurable) + have hpoint : ∀ path : Fin n → alpha, term.toContinuousMap path = + term.coefficient * ∏ i, activeFactor term.factors hk i + (FiniteOrderedTimes.restrictPath (activeEmbedding term.factors hk) path i) := by + intro path + rw [PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply_active] + simp only [PiContinuousMap.CoordinateProductTerm.activeEvaluation, activeFactor, + activeEmbedding, FiniteOrderedTimes.restrictPath, RelEmbedding.coe_trans, + Function.comp_apply, OrderIso.coe_toOrderEmbedding] + congr 1 + exact ((Fin.castOrderIso hk.symm).toEquiv.prod_comp + (fun j ↦ PiContinuousMap.activeNormalizedFactor term.factors j + (path (PiContinuousMap.activeOrderEmbedding term.factors j)))).symm + calc + ∫ path, term.toContinuousMap path ∂finiteTimeKernel Q u x = + ∫ path, term.coefficient * ∏ i, activeFactor term.factors hk i + (FiniteOrderedTimes.restrictPath (activeEmbedding term.factors hk) path i) + ∂finiteTimeKernel Q u x := + integral_congr_ae (ae_of_all _ hpoint) + _ = term.coefficient * ∫ path, (fun p : Fin (k + 1) → alpha ↦ + ∏ i, activeFactor term.factors hk i (p i)) + (FiniteOrderedTimes.restrictPath (activeEmbedding term.factors hk) path) + ∂finiteTimeKernel Q u x := by + rw [integral_const_mul] + _ = term.coefficient * ∫ path, ∏ i, activeFactor term.factors hk i (path i) + ∂(finiteTimeKernel Q u).map + (FiniteOrderedTimes.restrictPath (activeEmbedding term.factors hk)) x := by + rw [Kernel.map_apply _ + (FiniteOrderedTimes.measurable_restrictPath (activeEmbedding term.factors hk))] + rw [integral_map (FiniteOrderedTimes.measurable_restrictPath + (activeEmbedding term.factors hk)).aemeasurable hg.aestronglyMeasurable] + _ = term.coefficient * ∫ path, ∏ i, activeFactor term.factors hk i (path i) + ∂finiteTimeKernel Q (u.restrict (activeEmbedding term.factors hk)) x := by + rw [hQc.finiteTimeKernel_map_restrictPath Q u (activeEmbedding term.factors hk)] + _ = term.coefficient * hQ.backwardC0 (u.restrict (activeEmbedding term.factors hk)) + (activeFactor term.factors hk) x := by + rw [hQ.backwardC0_apply_eq_integral_finiteTimeKernel] + +end ActiveReduction + +variable {P : iota → SubMarkovKernelSemigroup alpha} {Q : SubMarkovKernelSemigroup alpha} + +/-- **Uniform convergence of the finite-time integral of a coordinate-product term.** -/ +theorem tendstoUniformly_integral_coordinateProductTerm_finiteTimeKernel + (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hPc : ∀ i, (P i).IsConservative) + (hQ : Q.IsFellerKernelSemigroup) (hQc : Q.IsConservative) + (hconv : ∀ (t : NNReal) (f : C₀(alpha, ℝ)), + Tendsto (fun i ↦ (hP i).c0Semigroup t f) l (nhds (hQ.c0Semigroup t f))) + {n : ℕ} (times : FiniteOrderedTimes n) + (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) : + TendstoUniformly + (fun i x ↦ ∫ path, term.toContinuousMap path ∂finiteTimeKernel (P i) times x) + (fun x ↦ ∫ path, term.toContinuousMap path ∂finiteTimeKernel Q times x) l := by + by_cases hA : (PiContinuousMap.activeCoordinates term.factors).card = 0 + · have hAe : PiContinuousMap.activeCoordinates term.factors = ∅ := Finset.card_eq_zero.mp hA + have hcoefP : ∀ (i : iota) (y : alpha), + ∫ path, term.toContinuousMap path ∂finiteTimeKernel (P i) times y = term.coefficient := + fun i y ↦ integral_coordinateProductTerm_eq_coefficient (hPc i) term hAe times y + have hcoefQ : ∀ y : alpha, + ∫ path, term.toContinuousMap path ∂finiteTimeKernel Q times y = term.coefficient := + fun y ↦ integral_coordinateProductTerm_eq_coefficient hQc term hAe times y + simp only [hcoefP, hcoefQ] + exact tendstoUniformly_const term.coefficient + · obtain ⟨k, hk⟩ := Nat.exists_eq_succ_of_ne_zero hA + have hbackP : ∀ (i : iota) (y : alpha), + ∫ path, term.toContinuousMap path ∂finiteTimeKernel (P i) times y = + term.coefficient * (hP i).backwardC0 + (times.restrict (activeEmbedding term.factors hk)) + (activeFactor term.factors hk) y := + fun i y ↦ integral_coordinateProductTerm_eq_backwardC0 (hP i) (hPc i) term hk times y + have hbackQ : ∀ y : alpha, + ∫ path, term.toContinuousMap path ∂finiteTimeKernel Q times y = + term.coefficient * hQ.backwardC0 + (times.restrict (activeEmbedding term.factors hk)) + (activeFactor term.factors hk) y := + fun y ↦ integral_coordinateProductTerm_eq_backwardC0 hQ hQc term hk times y + simp only [hbackP, hbackQ] + exact tendstoUniformly_const_mul (tendstoUniformly_apply_of_tendsto + (tendsto_backwardC0_of_tendsto_c0Semigroup hP hQ hconv + (times.restrict (activeEmbedding term.factors hk)) + (activeFactor term.factors hk))) term.coefficient + +/-- **Uniform convergence of the finite-time integral of a coordinate polynomial.** -/ +theorem tendstoUniformly_integral_coordinatePolynomial_finiteTimeKernel + (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hPc : ∀ i, (P i).IsConservative) + (hQ : Q.IsFellerKernelSemigroup) (hQc : Q.IsConservative) + (hconv : ∀ (t : NNReal) (f : C₀(alpha, ℝ)), + Tendsto (fun i ↦ (hP i).c0Semigroup t f) l (nhds (hQ.c0Semigroup t f))) + {n : ℕ} (times : FiniteOrderedTimes n) + (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) : + TendstoUniformly + (fun i x ↦ ∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel (P i) times x) + (fun x ↦ ∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel Q times x) l := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil, ContinuousMap.zero_apply, + integral_zero] + exact tendstoUniformly_const 0 + | cons term terms ih => + have hsplit : ∀ (R : SubMarkovKernelSemigroup alpha), R.IsConservative → ∀ y : alpha, + ∫ path, PiContinuousMap.coordinatePolynomial (term :: terms) path + ∂finiteTimeKernel R times y = + (∫ path, term.toContinuousMap path ∂finiteTimeKernel R times y) + + ∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel R times y := by + intro R hRc y + let : IsProbabilityMeasure (finiteTimeKernel R times y) := + hRc.isProbabilityMeasure_finiteTimeLaw R times y + rw [PiContinuousMap.coordinatePolynomial_cons] + exact integral_add (integrable_coordinateProductTerm term _) + (integrable_coordinatePolynomial terms _) + have hsplitP : ∀ (i : iota) (y : alpha), + ∫ path, PiContinuousMap.coordinatePolynomial (term :: terms) path + ∂finiteTimeKernel (P i) times y = + (∫ path, term.toContinuousMap path ∂finiteTimeKernel (P i) times y) + + ∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel (P i) times y := + fun i y ↦ hsplit (P i) (hPc i) y + have hsplitQ : ∀ y : alpha, + ∫ path, PiContinuousMap.coordinatePolynomial (term :: terms) path + ∂finiteTimeKernel Q times y = + (∫ path, term.toContinuousMap path ∂finiteTimeKernel Q times y) + + ∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel Q times y := + fun y ↦ hsplit Q hQc y + simp only [hsplitP, hsplitQ] + exact tendstoUniformly_add + (tendstoUniformly_integral_coordinateProductTerm_finiteTimeKernel hP hPc hQ hQc + hconv times term) ih + +section CompactTest + +variable [SecondCountableTopology alpha] + +/-- **Uniform convergence of the finite-time integral of a compactly supported test.** -/ +theorem tendstoUniformly_integral_compactlySupported_finiteTimeKernel + (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hPc : ∀ i, (P i).IsConservative) + (hQ : Q.IsFellerKernelSemigroup) (hQc : Q.IsConservative) + (hconv : ∀ (t : NNReal) (f : C₀(alpha, ℝ)), + Tendsto (fun i ↦ (hP i).c0Semigroup t f) l (nhds (hQ.c0Semigroup t f))) + {n : ℕ} (times : FiniteOrderedTimes n) (f : C_c(Fin n → alpha, ℝ)) : + TendstoUniformly (fun i x ↦ ∫ path, f path ∂finiteTimeKernel (P i) times x) + (fun x ↦ ∫ path, f path ∂finiteTimeKernel Q times x) l := by + rw [Metric.tendstoUniformly_iff] + intro eps heps + have heps3 : (0 : ℝ) < eps / 3 := by positivity + obtain ⟨terms, hterms⟩ := + PiContinuousMap.exists_coordinateProductTerms_near_compactlySupported f heps3 + have hnear : ∀ path : Fin n → alpha, + ‖PiContinuousMap.coordinatePolynomial terms path - f path‖ < eps / 3 := by + intro path + rw [PiContinuousMap.coordinatePolynomial_apply] + exact hterms path + have hApprox : ∀ (R : SubMarkovKernelSemigroup alpha), R.IsConservative → ∀ y : alpha, + dist (∫ path, PiContinuousMap.coordinatePolynomial terms path ∂finiteTimeKernel R times y) + (∫ path, f path ∂finiteTimeKernel R times y) ≤ eps / 3 := by + intro R hRc y + let : IsProbabilityMeasure (finiteTimeKernel R times y) := + hRc.isProbabilityMeasure_finiteTimeLaw R times y + have hp : Integrable (PiContinuousMap.coordinatePolynomial terms) + (finiteTimeKernel R times y) := integrable_coordinatePolynomial terms _ + have hf : Integrable (f : (Fin n → alpha) → ℝ) (finiteTimeKernel R times y) := + (map_continuous f).integrable_of_hasCompactSupport f.hasCompactSupport + rw [Real.dist_eq, ← MeasureTheory.integral_sub hp hf] + calc + |∫ path, (PiContinuousMap.coordinatePolynomial terms path - f path) + ∂finiteTimeKernel R times y| ≤ (eps / 3) * (finiteTimeKernel R times y).real Set.univ := + MeasureTheory.norm_integral_le_of_norm_le_const + (ae_of_all _ fun path ↦ (hnear path).le) + _ = eps / 3 := by + simp only [measureReal_def, measure_univ, ENNReal.toReal_one, mul_one] + have hpoly := tendstoUniformly_integral_coordinatePolynomial_finiteTimeKernel hP hPc hQ hQc + hconv times terms + rw [Metric.tendstoUniformly_iff] at hpoly + filter_upwards [hpoly (eps / 3) heps3] with i hi x + have hleft := hApprox Q hQc x + have hright := hApprox (P i) (hPc i) x + have hix := hi x + have htri : dist (∫ path, f path ∂finiteTimeKernel Q times x) + (∫ path, f path ∂finiteTimeKernel (P i) times x) ≤ + dist (∫ path, f path ∂finiteTimeKernel Q times x) + (∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel Q times x) + + dist (∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel Q times x) + (∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel (P i) times x) + + dist (∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel (P i) times x) + (∫ path, f path ∂finiteTimeKernel (P i) times x) := dist_triangle4 _ _ _ _ + rw [dist_comm] at hleft + linarith + +end CompactTest + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean new file mode 100644 index 0000000000..60cf4cdcc2 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean @@ -0,0 +1,359 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity + +/-! +# Joint continuity of finite-time compact-test integrals + +Finite-time integrals of compactly supported continuous tests vary continuously when both the +ordered observation times and the starting point vary. The empty coordinate family is included; +in that case the integral is constant, and no constant-one `C₀` function is introduced. + +This is finite-dimensional analytic infrastructure; no statement about path space is proved +here. The continuous-path process is built in `Trajectory/`. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped NNReal ZeroAtInfty BigOperators CompactlySupported + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + +omit [MeasurableSpace alpha] [BorelSpace alpha] [LocallyCompactSpace alpha] + [T2Space alpha] in +private theorem tendsto_c0_apply_of_tendsto + {X : Type*} {l : Filter X} {f : X → C₀(alpha, ℝ)} {f₀ : C₀(alpha, ℝ)} + {x : X → alpha} {x₀ : alpha} (hf : Tendsto f l (nhds f₀)) + (hx : Tendsto x l (nhds x₀)) : + Tendsto (fun a ↦ f a (x a)) l (nhds (f₀ x₀)) := by + rw [Metric.tendsto_nhds] at hf ⊢ + intro epsilon hepsilon + have hhalf : 0 < epsilon / 2 := half_pos hepsilon + have hpoint : Tendsto (fun a ↦ f₀ (x a)) l (nhds (f₀ x₀)) := + f₀.continuous.continuousAt.tendsto.comp hx + rw [Metric.tendsto_nhds] at hpoint + filter_upwards [hf (epsilon / 2) hhalf, hpoint (epsilon / 2) hhalf] with a ha hxa + calc + dist (f a (x a)) (f₀ x₀) ≤ + dist (f a (x a)) (f₀ (x a)) + dist (f₀ (x a)) (f₀ x₀) := + dist_triangle _ _ _ + _ ≤ dist (f a) f₀ + dist (f₀ (x a)) (f₀ x₀) := by + have hdist : dist (f a (x a)) (f₀ (x a)) ≤ + dist (f a).toBCF f₀.toBCF := + BoundedContinuousFunction.dist_coe_le_dist + (f := (f a).toBCF) (g := f₀.toBCF) (x a) + rw [ZeroAtInftyContinuousMap.dist_toBCF_eq_dist] at hdist + exact add_le_add_left hdist _ + _ < epsilon / 2 + epsilon / 2 := add_lt_add ha hxa + _ = epsilon := add_halves epsilon + +omit [LocallyCompactSpace alpha] [T2Space alpha] in +private theorem integrable_coordinateProductTerm_joint + {n : ℕ} (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) + (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : + Integrable term.toContinuousMap mu := by + have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ + (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by + induction term.factors with + | nil => exact stronglyMeasurable_const + | cons p factors ih => + simp only [List.map_cons, List.prod_cons] + exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul ih + rw [show (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ + term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by + funext path + exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] + refine Integrable.of_bound (hprod.const_mul term.coefficient).aestronglyMeasurable + (‖term.coefficient‖ * (term.factors.map fun p ↦ ‖p.2‖).prod) ?_ + filter_upwards [] with path + rw [norm_mul, List.norm_prod] + apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) + induction term.factors with + | nil => + simp only [List.map_nil, List.prod_nil] + exact le_rfl + | cons p factors ih => + simp only [List.map_cons, List.prod_cons] + have all_nonneg : ∀ fs : List (Fin n × C₀(alpha, ℝ)), + 0 ≤ (fs.map fun q ↦ ‖q.2 (path q.1)‖).prod := by + intro fs + induction fs with + | nil => simp only [List.map_nil, List.prod_nil, zero_le_one] + | cons q fs ihFactors => + simp only [List.map_cons, List.prod_cons] + exact mul_nonneg (norm_nonneg _) ihFactors + have hnonneg : 0 ≤ + ((factors.map fun p ↦ p.2 (path p.1)).map norm).prod := by + simpa only [List.map_map, Function.comp_apply] using! all_nonneg factors + apply mul_le_mul (p.2.toBCF.norm_coe_le_norm (path p.1)) ih + · exact hnonneg + · exact norm_nonneg _ + +omit [LocallyCompactSpace alpha] [T2Space alpha] in +private theorem integrable_coordinatePolynomial_joint + {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) + (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : + Integrable (PiContinuousMap.coordinatePolynomial terms) mu := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil] + change Integrable (fun _ : Fin n → alpha ↦ (0 : ℝ)) mu + refine Integrable.of_bound stronglyMeasurable_const.aestronglyMeasurable 0 ?_ + exact ae_of_all _ fun _ ↦ by + simpa only [norm_zero] using (le_refl (0 : ℝ)) + | cons term terms ih => + rw [PiContinuousMap.coordinatePolynomial_cons] + exact (integrable_coordinateProductTerm_joint term mu).add ih + +omit [LocallyCompactSpace alpha] [T2Space alpha] in +private theorem stronglyMeasurable_coordinatePolynomial_joint + {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) : + StronglyMeasurable (PiContinuousMap.coordinatePolynomial terms) := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil] + exact stronglyMeasurable_const + | cons term terms ih => + rw [PiContinuousMap.coordinatePolynomial_cons] + apply StronglyMeasurable.add _ ih + have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ + (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by + induction term.factors with + | nil => exact stronglyMeasurable_const + | cons p factors ihFactors => + simp only [List.map_cons, List.prod_cons] + exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul + ihFactors + rw [show (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ + term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by + funext path + exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] + exact hprod.const_mul term.coefficient + +private theorem stronglyMeasurable_compactlySupported_fin_joint + {n : ℕ} (f : C_c(Fin n → alpha, ℝ)) : StronglyMeasurable f := by + have hexists (m : ℕ) : + ∃ terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha), + ∀ x, ‖PiContinuousMap.coordinatePolynomial terms x - f x‖ < + 1 / ((m : ℝ) + 1) := by + have hpositive : 0 < 1 / ((m : ℝ) + 1) := by positivity + obtain ⟨terms, hterms⟩ := + PiContinuousMap.exists_coordinateProductTerms_near_compactlySupported f hpositive + exact ⟨terms, fun x ↦ by + rw [PiContinuousMap.coordinatePolynomial_apply] + exact hterms x⟩ + choose terms hterms using hexists + apply stronglyMeasurable_of_tendsto atTop + (fun m ↦ stronglyMeasurable_coordinatePolynomial_joint (terms m)) + rw [tendsto_pi_nhds] + intro x + rw [Metric.tendsto_nhds] + intro epsilon hepsilon + have hscalar : Tendsto (fun m : ℕ ↦ (1 : ℝ) / ((m : ℝ) + 1)) atTop (nhds 0) := + tendsto_one_div_add_atTop_nhds_zero_nat + rw [Metric.tendsto_nhds] at hscalar + filter_upwards [hscalar epsilon hepsilon] with m hm + rw [Real.dist_eq, sub_zero, abs_of_pos (by positivity)] at hm + exact (hterms m x).trans_le hm.le + +private theorem tendsto_integral_coordinateProductTerm_joint + {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) {X : Type*} {l : Filter X} {n : ℕ} + {times : X → FiniteOrderedTimes n} {times₀ : FiniteOrderedTimes n} + {x : X → alpha} {x₀ : alpha} + (ht : ∀ i, Tendsto (fun a ↦ times a i) l (nhds (times₀ i))) + (hx : Tendsto x l (nhds x₀)) + (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) : + Tendsto (fun a ↦ ∫ path, term.toContinuousMap path + ∂finiteTimeKernel P (times a) (x a)) l + (nhds (∫ path, term.toContinuousMap path ∂finiteTimeKernel P times₀ x₀)) := by + let A := PiContinuousMap.activeCoordinates term.factors + by_cases hA : A.card = 0 + · have hActive : PiContinuousMap.activeCoordinates term.factors = ∅ := + Finset.card_eq_zero.mp hA + have hTerm (path : Fin n → alpha) : term.toContinuousMap path = term.coefficient := by + rw [PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply_active] + simp only [PiContinuousMap.CoordinateProductTerm.activeEvaluation, hActive, + Finset.card_empty, Finset.prod_fin_eq_prod_range, Finset.prod_range_zero, mul_one] + have hIntegral (u : FiniteOrderedTimes n) (y : alpha) : + ∫ path, term.toContinuousMap path ∂finiteTimeKernel P u y = term.coefficient := by + let : IsProbabilityMeasure (finiteTimeKernel P u y) := + hP.isProbabilityMeasure_finiteTimeLaw P u y + rw [integral_congr_ae (ae_of_all _ hTerm)] + simp only [integral_const, probReal_univ, one_smul] + simp_rw [hIntegral] + exact tendsto_const_nhds + · obtain ⟨k, hk⟩ := Nat.exists_eq_succ_of_ne_zero hA + let e := PiContinuousMap.activeOrderEmbedding term.factors + let ec : Fin (k + 1) ↪o Fin n := + (Fin.castOrderIso hk.symm).toOrderEmbedding.trans e + let factors : Fin (k + 1) → C₀(alpha, ℝ) := fun j ↦ + PiContinuousMap.activeNormalizedFactor term.factors (Fin.cast hk.symm j) + have htimes : ∀ i, Tendsto (fun a ↦ (times a).restrict ec i) l + (nhds (times₀.restrict ec i)) := fun i ↦ ht (ec i) + have hIntegral (u : FiniteOrderedTimes n) (y : alpha) : + ∫ path, term.toContinuousMap path ∂finiteTimeKernel P u y = + term.coefficient * hFeller.backwardC0 (u.restrict ec) factors y := by + let g : (Fin (k + 1) → alpha) → ℝ := + fun path ↦ ∏ i, factors i (path i) + have hg : StronglyMeasurable g := + Finset.stronglyMeasurable_fun_prod Finset.univ fun i _ ↦ + ((factors i).measurable.comp (measurable_pi_apply i)).stronglyMeasurable + have hpoint : ∀ path : Fin n → alpha, + term.toContinuousMap path = + term.coefficient * g (FiniteOrderedTimes.restrictPath ec path) := by + intro path + rw [PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply_active] + simp only [PiContinuousMap.CoordinateProductTerm.activeEvaluation, g, + factors, FiniteOrderedTimes.restrictPath, ec, e, + RelEmbedding.coe_trans, Function.comp_apply, OrderIso.coe_toOrderEmbedding] + congr 1 + exact ((Fin.castOrderIso hk.symm).toEquiv.prod_comp + (fun j ↦ PiContinuousMap.activeNormalizedFactor term.factors j + (path (PiContinuousMap.activeOrderEmbedding term.factors j)))).symm + calc + ∫ path, term.toContinuousMap path ∂finiteTimeKernel P u y = + ∫ path, term.coefficient * + g (FiniteOrderedTimes.restrictPath ec path) ∂finiteTimeKernel P u y := by + exact integral_congr_ae (ae_of_all _ hpoint) + _ = term.coefficient * ∫ path, + g (FiniteOrderedTimes.restrictPath ec path) ∂finiteTimeKernel P u y := by + rw [integral_const_mul] + _ = term.coefficient * ∫ path, g path ∂ + (finiteTimeKernel P u).map (FiniteOrderedTimes.restrictPath ec) y := by + rw [Kernel.map_apply _ (FiniteOrderedTimes.measurable_restrictPath ec), + integral_map (FiniteOrderedTimes.measurable_restrictPath ec).aemeasurable + hg.aestronglyMeasurable] + _ = term.coefficient * ∫ path, g path ∂ + finiteTimeKernel P (u.restrict ec) y := by + rw [hP.finiteTimeKernel_map_restrictPath P u ec] + _ = term.coefficient * hFeller.backwardC0 (u.restrict ec) factors y := by + rw [hFeller.backwardC0_apply_eq_integral_finiteTimeKernel] + simp_rw [hIntegral] + apply tendsto_const_nhds.mul + exact tendsto_c0_apply_of_tendsto + (hFeller.tendsto_backwardC0 htimes factors) hx + +private theorem tendsto_integral_coordinatePolynomial_joint + {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) {X : Type*} {l : Filter X} {n : ℕ} + {times : X → FiniteOrderedTimes n} {times₀ : FiniteOrderedTimes n} + {x : X → alpha} {x₀ : alpha} + (ht : ∀ i, Tendsto (fun a ↦ times a i) l (nhds (times₀ i))) + (hx : Tendsto x l (nhds x₀)) + (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) : + Tendsto (fun a ↦ ∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel P (times a) (x a)) l + (nhds (∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel P times₀ x₀)) := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil, ContinuousMap.zero_apply, + integral_zero] + exact tendsto_const_nhds + | cons term terms ih => + have hIntegral (u : FiniteOrderedTimes n) (y : alpha) : + ∫ path, PiContinuousMap.coordinatePolynomial (term :: terms) path + ∂finiteTimeKernel P u y = + (∫ path, term.toContinuousMap path ∂finiteTimeKernel P u y) + + ∫ path, PiContinuousMap.coordinatePolynomial terms path + ∂finiteTimeKernel P u y := by + let : IsProbabilityMeasure (finiteTimeKernel P u y) := + hP.isProbabilityMeasure_finiteTimeLaw P u y + rw [PiContinuousMap.coordinatePolynomial_cons] + exact integral_add (integrable_coordinateProductTerm_joint term _) + (integrable_coordinatePolynomial_joint terms _) + simp_rw [hIntegral] + exact (tendsto_integral_coordinateProductTerm_joint hFeller hP ht hx term).add ih + +/-- Finite-time compact-test integrals vary continuously when both the ordered observation +times and the starting point vary. This includes the empty coordinate family. -/ +theorem IsFellerKernelSemigroup.tendsto_integral_compactlySupported_finiteTimeKernel_of_tendsto + {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) {X : Type*} {l : Filter X} {n : ℕ} + {times : X → FiniteOrderedTimes n} {times₀ : FiniteOrderedTimes n} + {x : X → alpha} {x₀ : alpha} + (ht : ∀ i, Tendsto (fun a ↦ times a i) l (nhds (times₀ i))) + (hx : Tendsto x l (nhds x₀)) (f : C_c(Fin n → alpha, ℝ)) : + Tendsto (fun a ↦ ∫ path, f path ∂finiteTimeKernel P (times a) (x a)) l + (nhds (∫ path, f path ∂finiteTimeKernel P times₀ x₀)) := by + rw [Metric.tendsto_nhds] + intro epsilon hepsilon + obtain ⟨terms, hterms⟩ := + PiContinuousMap.exists_coordinateProductTerms_near_compactlySupported f + (div_pos hepsilon (by norm_num : (0 : ℝ) < 3)) + let polynomial := PiContinuousMap.coordinatePolynomial terms + have hnear (path : Fin n → alpha) : ‖polynomial path - f path‖ < epsilon / 3 := by + rw [PiContinuousMap.coordinatePolynomial_apply] + exact hterms path + have hApprox (u : FiniteOrderedTimes n) (y : alpha) : + dist (∫ path, polynomial path ∂finiteTimeKernel P u y) + (∫ path, f path ∂finiteTimeKernel P u y) ≤ epsilon / 3 := by + let : IsProbabilityMeasure (finiteTimeKernel P u y) := + hP.isProbabilityMeasure_finiteTimeLaw P u y + have hdiff : Integrable (fun path ↦ polynomial path - f path) + (finiteTimeKernel P u y) := by + apply Integrable.of_bound (C := epsilon / 3) + · exact (stronglyMeasurable_coordinatePolynomial_joint terms).sub + (stronglyMeasurable_compactlySupported_fin_joint f) |>.aestronglyMeasurable + · exact ae_of_all _ fun path ↦ (hnear path).le + have hp : Integrable polynomial (finiteTimeKernel P u y) := + integrable_coordinatePolynomial_joint terms _ + have hf : Integrable f (finiteTimeKernel P u y) := by + have hsub := hp.sub hdiff + apply hsub.congr + exact ae_of_all _ fun path ↦ by simp only [Pi.sub_apply, sub_sub_cancel] + rw [Real.dist_eq, ← MeasureTheory.integral_sub hp hf] + calc + ‖∫ path, polynomial path - f path ∂finiteTimeKernel P u y‖ ≤ + (epsilon / 3) * (finiteTimeKernel P u y).real Set.univ := + MeasureTheory.norm_integral_le_of_norm_le_const + (ae_of_all _ fun path ↦ (hnear path).le) + _ = epsilon / 3 := by + simp only [measureReal_def, measure_univ, ENNReal.toReal_one, mul_one] + have hPolynomial := tendsto_integral_coordinatePolynomial_joint + hFeller hP ht hx terms + rw [Metric.tendsto_nhds] at hPolynomial + filter_upwards [hPolynomial (epsilon / 3) + (div_pos hepsilon (by norm_num : (0 : ℝ) < 3))] with a ha + calc + dist (∫ path, f path ∂finiteTimeKernel P (times a) (x a)) + (∫ path, f path ∂finiteTimeKernel P times₀ x₀) ≤ + dist (∫ path, f path ∂finiteTimeKernel P (times a) (x a)) + (∫ path, polynomial path ∂finiteTimeKernel P (times a) (x a)) + + dist (∫ path, polynomial path ∂finiteTimeKernel P (times a) (x a)) + (∫ path, f path ∂finiteTimeKernel P times₀ x₀) := + dist_triangle _ _ _ + _ ≤ dist (∫ path, f path ∂finiteTimeKernel P (times a) (x a)) + (∫ path, polynomial path ∂finiteTimeKernel P (times a) (x a)) + + (dist (∫ path, polynomial path ∂finiteTimeKernel P (times a) (x a)) + (∫ path, polynomial path ∂finiteTimeKernel P times₀ x₀) + + dist (∫ path, polynomial path ∂finiteTimeKernel P times₀ x₀) + (∫ path, f path ∂finiteTimeKernel P times₀ x₀)) := by + apply add_le_add_right + exact dist_triangle _ _ _ + _ < epsilon := by + have hleft := hApprox (times a) (x a) + rw [dist_comm] at hleft + have hright := hApprox times₀ x₀ + linarith only [hleft, ha, hright] + +/-- At fixed ordered observation times, a finite-time compact-test integral is continuous in the +starting point. The statement also covers the empty observation family. -/ +theorem IsFellerKernelSemigroup.continuous_integral_compactlySupported_finiteTimeKernel + {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) {n : ℕ} (times : FiniteOrderedTimes n) + (f : C_c(Fin n → alpha, ℝ)) : + Continuous fun x ↦ ∫ path, f path ∂finiteTimeKernel P times x := by + rw [continuous_iff_continuousAt] + intro x + exact hFeller.tendsto_integral_compactlySupported_finiteTimeKernel_of_tendsto hP + (times := fun _ : alpha ↦ times) (times₀ := times) (x := fun y ↦ y) (x₀ := x) + (fun _ ↦ tendsto_const_nhds) tendsto_id f + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeKernelContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeKernelContinuity.lean new file mode 100644 index 0000000000..f7a830c4a3 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeKernelContinuity.lean @@ -0,0 +1,110 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint + +/-! +# Continuity tools for finite-time Feller kernels + +This file records the analytic continuity mechanism needed in a recursive proof of continuity of +finite-time laws. In particular, strong continuity and contractivity imply joint continuity in +the time and in a varying `C₀` test function. After evaluation, this gives convergence of kernel +integrals when both the transition time and the test function vary. + +The extension from product tests to arbitrary compactly supported tests on a finite product is +not asserted here. +-/ + +open Filter MeasureTheory Topology +open scoped NNReal ZeroAtInfty + +namespace MarkovProcess + +namespace Semigroup.StronglyContinuousContractionSemigroup + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + +/-- A strongly continuous contraction semigroup acts continuously when both time and the vector +vary. Strong continuity alone only states this for a fixed vector; contractivity makes the +dependence on the vector uniform in time. -/ +theorem tendsto_apply_of_tendsto + (S : StronglyContinuousContractionSemigroup E) {X : Type*} {l : Filter X} + {t : X → NNReal} {t₀ : NNReal} {f : X → E} {f₀ : E} + (ht : Tendsto t l (nhds t₀)) (hf : Tendsto f l (nhds f₀)) : + Tendsto (fun x ↦ S (t x) (f x)) l (nhds (S t₀ f₀)) := by + rw [Metric.tendsto_nhds] at hf ⊢ + intro ε hε + have hhalf : 0 < ε / 2 := half_pos hε + have htime : ∀ᶠ x in l, dist (S (t x) f₀) (S t₀ f₀) < ε / 2 := + ((S.continuous f₀).tendsto t₀ |>.comp ht) (Metric.ball_mem_nhds _ hhalf) + filter_upwards [hf (ε / 2) hhalf, htime] with x hx htx + calc + dist (S (t x) (f x)) (S t₀ f₀) + ≤ dist (S (t x) (f x)) (S (t x) f₀) + + dist (S (t x) f₀) (S t₀ f₀) := dist_triangle _ _ _ + _ ≤ dist (f x) f₀ + dist (S (t x) f₀) (S t₀ f₀) := + by + simpa only [add_comm] using + add_le_add_right (S.dist_apply_le (t x) (f x) f₀) + (dist (S (t x) f₀) (S t₀ f₀)) + _ < ε / 2 + ε / 2 := add_lt_add hx htx + _ = ε := add_halves ε + +/-- Joint continuity of the semigroup action in time and the evolving vector. -/ +theorem continuous_apply + (S : StronglyContinuousContractionSemigroup E) : + Continuous fun tf : NNReal × E ↦ S tf.1 tf.2 := by + rw [continuous_iff_continuousAt] + intro tf + exact S.tendsto_apply_of_tendsto continuousAt_fst continuousAt_snd + +end Semigroup.StronglyContinuousContractionSemigroup + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + +/-- Feller continuity permits both the time and the `C₀` integrand to vary. -/ +theorem IsFellerKernelSemigroup.tendsto_kernelIntegral_c0 + {P : SubMarkovKernelSemigroup alpha} (hP : P.IsFellerKernelSemigroup) + {X : Type*} {l : Filter X} {t : X → NNReal} {t₀ : NNReal} + {f : X → C₀(alpha, ℝ)} {f₀ : C₀(alpha, ℝ)} + (ht : Tendsto t l (nhds t₀)) (hf : Tendsto f l (nhds f₀)) (x : alpha) : + Tendsto (fun a ↦ kernelIntegral (P (t a)) (f a) x) l + (nhds (kernelIntegral (P t₀) f₀ x)) := by + have haction := hP.c0Semigroup.tendsto_apply_of_tendsto ht hf + have heval : Continuous fun g : C₀(alpha, ℝ) ↦ g x := + (ZeroAtInftyContinuousMap.isometry_toBCF (α := alpha) (β := ℝ)).continuous.eval + continuous_const + simpa only [IsFellerKernelSemigroup.c0Semigroup_apply_apply] using! + heval.continuousAt.tendsto.comp haction + +/-- The two-transition backward recursion is continuous for product `C₀` tests. The inner +transition acts on `g`; multiplication by the first-coordinate test `f` gives the varying `C₀` +test seen by the outer transition. This is the successor-step analytic mechanism in the +finite-time argument. -/ +theorem IsFellerKernelSemigroup.tendsto_twoStepProduct_c0 + {P : SubMarkovKernelSemigroup alpha} (hP : P.IsFellerKernelSemigroup) + {X : Type*} {l : Filter X} + {t s : X → NNReal} {t₀ s₀ : NNReal} + {f g : X → C₀(alpha, ℝ)} {f₀ g₀ : C₀(alpha, ℝ)} + (ht : Tendsto t l (nhds t₀)) (hs : Tendsto s l (nhds s₀)) + (hf : Tendsto f l (nhds f₀)) (hg : Tendsto g l (nhds g₀)) (x : alpha) : + Tendsto + (fun a ↦ kernelIntegral (P (t a)) + (f a * hP.c0Semigroup (s a) (g a)) x) + l + (nhds (kernelIntegral (P t₀) + (f₀ * hP.c0Semigroup s₀ g₀) x)) := by + have hinner : Tendsto (fun a ↦ hP.c0Semigroup (s a) (g a)) l + (nhds (hP.c0Semigroup s₀ g₀)) := + hP.c0Semigroup.tendsto_apply_of_tendsto hs hg + exact hP.tendsto_kernelIntegral_c0 ht (hf.mul hinner) x + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/Resolvent.lean new file mode 100644 index 0000000000..de32463224 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/Resolvent.lean @@ -0,0 +1,173 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration + +/-! +# The resolvent of a Feller kernel semigroup + +The resolvent of the `C₀` semigroup of a Feller kernel semigroup `P`, evaluated at a point, is +the Laplace transform of the transition integrals, + + `R_μ f (x) = ∫₀^∞ e^{-μ t} (∫ f d(P t x)) dt` (`IsFellerKernelSemigroup.resolvent_apply_apply`), + +and the generator domain of the `C₀` semigroup is the range of this resolvent +(`IsFellerKernelSemigroup.mem_generatorDomain_iff_exists_resolvent`), the kernel-side reading of +`Semigroup/Resolvent.lean`. The shared bounded evaluation functional `c0EvalCLM` commutes with +Bochner integrals in `C₀(α, ℝ)`. For the Feller kernel +semigroup represented by a positive contractive resolvent `R` (`Kernel/PositiveC0Resolvent.lean`), +the resolvent of its `C₀` semigroup is `R` itself +(`PositiveC0ContractiveResolvent.resolvent_c0Semigroup_kernelSemigroup`). + +Conversely, the kernel semigroup represented by that resolvent is the original one +(`IsFellerKernelSemigroup.kernelSemigroup_positiveC0ContractiveResolvent`). + +Main results: `IsFellerKernelSemigroup.resolvent_apply_apply`, +`IsFellerKernelSemigroup.positiveC0ContractiveResolvent`, +`IsFellerKernelSemigroup.kernelResolvent_ofReal_eq_resolvent`, +`IsFellerKernelSemigroup.mem_generatorDomain_iff_exists_resolvent`, +`PositiveC0ContractiveResolvent.resolvent_c0Semigroup_kernelSemigroup`. + +The bridge to `SubMarkovKernelSemigroup.kernelResolvent` is pointwise on nonnegative observables; +no kernel-valued resolvent is constructed. +-/ + +open Filter MeasureTheory ProbabilityTheory Set +open scoped NNReal ZeroAtInfty + +namespace MarkovProcess + +namespace SubMarkovKernelSemigroup + +variable {α : Type*} [TopologicalSpace α] [MeasurableSpace α] [BorelSpace α] + [LocallyCompactSpace α] [T2Space α] +variable {P : SubMarkovKernelSemigroup α} (hP : P.IsFellerKernelSemigroup) + +/-- **The resolvent of the `C₀` semigroup, evaluated at a point**: the Laplace transform of the +transition integrals. -/ +theorem IsFellerKernelSemigroup.resolvent_apply_apply (μ : Semigroup.PositiveShift) + (f : C₀(α, ℝ)) (x : α) : + hP.c0Semigroup.resolvent μ f x = + ∫ t in Ioi (0 : ℝ), Real.exp (-(μ : ℝ) * t) * kernelIntegral (P (Real.toNNReal t)) f x := by + rw [← c0EvalCLM_apply x (hP.c0Semigroup.resolvent μ f), + Semigroup.StronglyContinuousContractionSemigroup.resolvent_apply, + ← ContinuousLinearMap.integral_comp_comm _ + (hP.c0Semigroup.integrableOn_laplaceIntegrand μ.2 f)] + refine setIntegral_congr_fun measurableSet_Ioi fun t _ ↦ ?_ + simp only [Semigroup.StronglyContinuousContractionSemigroup.laplaceIntegrand_apply, map_smul, + c0EvalCLM_apply, smul_eq_mul, IsFellerKernelSemigroup.c0Semigroup_apply_apply] + +/-- The resolvent of a Feller kernel semigroup, packaged as a positive contractive resolvent on +`C₀`. Positivity follows directly from the nonnegative Laplace-transform integrand. -/ +noncomputable def IsFellerKernelSemigroup.positiveC0ContractiveResolvent : + PositiveC0ContractiveResolvent α where + toContractiveResolvent := hP.c0Semigroup.toContractiveResolvent + isPositive := fun μ f hf x ↦ by + rw [Semigroup.StronglyContinuousContractionSemigroup.toContractiveResolvent_operator, + hP.resolvent_apply_apply] + exact integral_nonneg fun t ↦ mul_nonneg (Real.exp_pos _).le (integral_nonneg hf) + +/-- Generating a semigroup from the positive resolvent of a Feller semigroup recovers its +original `C₀` semigroup. -/ +theorem IsFellerKernelSemigroup.generatedSemigroup_positiveC0ContractiveResolvent : + hP.positiveC0ContractiveResolvent.toContractiveResolvent.generatedSemigroup = + hP.c0Semigroup := + hP.c0Semigroup.generatedSemigroup_toContractiveResolvent + +/-- The real kernel resolvent of a `C₀` observable is the pointwise resolvent of the associated +`C₀` semigroup. -/ +theorem IsFellerKernelSemigroup.kernelResolventReal_eq_resolvent + (hP : P.IsFellerKernelSemigroup) (μ : Semigroup.PositiveShift) + (f : C₀(α, ℝ)) (x : α) : + P.kernelResolventReal (μ : ℝ) (fun y ↦ f y) x = + hP.c0Semigroup.resolvent μ f x := by + exact (hP.resolvent_apply_apply μ f x).symm + +/-- The extended-real kernel resolvent of a nonnegative `C₀` observable agrees with the +pointwise `C₀`-semigroup resolvent after applying `ENNReal.ofReal`. -/ +theorem IsFellerKernelSemigroup.kernelResolvent_ofReal_eq_resolvent + (hP : P.IsFellerKernelSemigroup) (μ : Semigroup.PositiveShift) + (f : C₀(α, ℝ)) (hf0 : ∀ y, 0 ≤ f y) (x : α) : + P.kernelResolvent (μ : ℝ) (fun y ↦ ENNReal.ofReal (f y)) x = + ENNReal.ofReal (hP.c0Semigroup.resolvent μ f x) := by + have houter : IntegrableOn (fun t : ℝ ↦ + Real.exp (-(μ : ℝ) * t) * kernelIntegral (P (Real.toNNReal t)) f x) (Ioi 0) := by + have hint := (c0EvalCLM x).integrable_comp + (hP.c0Semigroup.integrableOn_laplaceIntegrand μ.2 f) + simpa only [Function.comp_apply, + Semigroup.StronglyContinuousContractionSemigroup.laplaceIntegrand_apply, + map_smul, c0EvalCLM_apply, smul_eq_mul, + IsFellerKernelSemigroup.c0Semigroup_apply_apply] using! hint + rw [hP.resolvent_apply_apply μ f x, + ofReal_integral_eq_lintegral_ofReal houter + (Eventually.of_forall fun t ↦ mul_nonneg (Real.exp_pos _).le + (integral_nonneg fun y ↦ hf0 y))] + unfold SubMarkovKernelSemigroup.kernelResolvent + apply lintegral_congr + intro t + rw [ENNReal.ofReal_mul (Real.exp_pos _).le] + congr 1 + let : IsFiniteKernel (P (Real.toNNReal t)) := + (P.isSubMarkovKernel (Real.toNNReal t)).isFiniteKernel + have hfint : Integrable (fun y ↦ f y) (P (Real.toNNReal t) x) := + f.toBCF.integrable (P (Real.toNNReal t) x) + exact (ofReal_integral_eq_lintegral_ofReal hfint (Eventually.of_forall hf0)).symm + +/-- **The kernel semigroup represented by the resolvent of a Feller kernel semigroup is that +semigroup.** Both transition laws are finite Borel measures with the same integral on every +compactly supported continuous observable. -/ +theorem IsFellerKernelSemigroup.kernelSemigroup_positiveC0ContractiveResolvent + [SecondCountableTopology α] (hP : P.IsFellerKernelSemigroup) : + hP.positiveC0ContractiveResolvent.kernelSemigroup = P := by + refine SubMarkovKernelSemigroup.ext fun t ↦ ?_ + refine Kernel.ext fun x ↦ ?_ + have : IsFiniteMeasure (P t x) := + ⟨lt_of_le_of_lt (P.measure_univ_le_one t x) ENNReal.one_lt_top⟩ + have : IsFiniteMeasure (hP.positiveC0ContractiveResolvent.kernelSemigroup t x) := + ⟨lt_of_le_of_lt + (hP.positiveC0ContractiveResolvent.kernelSemigroup.measure_univ_le_one t x) + ENNReal.one_lt_top⟩ + refine Measure.ext_of_integral_eq_on_compactlySupported fun f ↦ ?_ + set g : C₀(α, ℝ) := PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f with hg + have hgf : ∀ y, g y = f y := fun y ↦ + PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap_apply f y + have hleft : ∫ y, f y ∂hP.positiveC0ContractiveResolvent.kernelSemigroup t x = + ∫ y, g y ∂hP.positiveC0ContractiveResolvent.kernelSemigroup t x := by + simp only [hgf] + have hright : ∫ y, f y ∂P t x = ∫ y, g y ∂P t x := by + simp only [hgf] + rw [hleft, hright, hP.positiveC0ContractiveResolvent.integral_kernelSemigroup t g x, + hP.generatedSemigroup_positiveC0ContractiveResolvent, hP.c0Semigroup_apply_apply t g x] + rfl + +/-- **The generator domain of the `C₀` semigroup is the range of its resolvent**, at every +positive shift. -/ +theorem IsFellerKernelSemigroup.mem_generatorDomain_iff_exists_resolvent + (μ : Semigroup.PositiveShift) (f : C₀(α, ℝ)) : + f ∈ hP.c0Semigroup.generatorDomain ↔ ∃ g, hP.c0Semigroup.resolvent μ g = f := by + rw [← SetLike.mem_coe, hP.c0Semigroup.generatorDomain_eq_range_resolvent μ] + exact Set.mem_range + +end SubMarkovKernelSemigroup + +namespace PositiveC0ContractiveResolvent + +variable {X : Type*} [TopologicalSpace X] [T2Space X] [LocallyCompactSpace X] + [SecondCountableTopology X] [MeasurableSpace X] [BorelSpace X] + (R : PositiveC0ContractiveResolvent X) + +/-- **The resolvent of the represented process is the given resolvent.** -/ +theorem resolvent_c0Semigroup_kernelSemigroup (μ : Semigroup.PositiveShift) : + R.isFellerKernelSemigroup_kernelSemigroup.c0Semigroup.resolvent μ = + R.toContractiveResolvent.operator μ := by + rw [R.c0Semigroup_kernelSemigroup, Semigroup.ContractiveResolvent.resolvent_generatedSemigroup] + +end PositiveC0ContractiveResolvent + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean new file mode 100644 index 0000000000..517609ee93 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean @@ -0,0 +1,99 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic + +/-! +# Strongly continuous `C₀` semigroups from kernels + +This file isolates continuity in time as an explicit hypothesis on the `C₀` kernel operators and +packages those operators as a strongly continuous contraction semigroup. Spatial preservation of +`C₀`, continuity of its time orbits, and conservativity of the kernels remain separate properties. +No stochastic process or Hunt process is constructed here. +-/ + +open Topology +open scoped ZeroAtInfty + +namespace MarkovProcess + +namespace SubMarkovKernelSemigroup + +variable {α : Type*} [TopologicalSpace α] [MeasurableSpace α] [BorelSpace α] + +/-- The `C₀` kernel operators have continuous time orbits in the `C₀` norm. This is an +additional hypothesis beyond the spatial `MapsC0` property. -/ +def HasContinuousC0Orbits (P : SubMarkovKernelSemigroup α) (hC0 : P.MapsC0) : Prop := + ∀ f : C₀(α, ℝ), Continuous fun t : NNReal ↦ P.c0Operator hC0 t f + +/-- A sub-Markov kernel semigroup on a locally compact Hausdorff space has the `C₀` +Feller-semigroup properties when it maps `C₀` into itself and its resulting `C₀` operator orbits +are continuous in time. Conservativity is not part of this predicate. -/ +def IsFellerKernelSemigroup (P : SubMarkovKernelSemigroup α) + [LocallyCompactSpace α] [T2Space α] : Prop := + ∃ hC0 : P.MapsC0, P.HasContinuousC0Orbits hC0 + +variable (P : SubMarkovKernelSemigroup α) (hC0 : P.MapsC0) + +/-- Package the kernel action on `C₀` as a strongly continuous contraction semigroup. -/ +noncomputable def c0Semigroup (hTime : P.HasContinuousC0Orbits hC0) : + Semigroup.StronglyContinuousContractionSemigroup C₀(α, ℝ) where + operator := P.c0Operator hC0 + operator_zero := P.c0Operator_zero hC0 + operator_add := P.c0Operator_add hC0 + opNorm_le_one := P.norm_c0Operator_le hC0 + continuous_orbit := hTime + +@[simp] +theorem c0Semigroup_operator (hTime : P.HasContinuousC0Orbits hC0) (t : NNReal) : + (P.c0Semigroup hC0 hTime) t = P.c0Operator hC0 t := + rfl + +@[simp] +theorem c0Semigroup_apply (hTime : P.HasContinuousC0Orbits hC0) + (t : NNReal) (f : C₀(α, ℝ)) : + (P.c0Semigroup hC0 hTime) t f = P.c0KernelIntegral hC0 t f := + rfl + +/-- Evaluation of the packaged semigroup is exactly the raw kernel integral. -/ +@[simp] +theorem c0Semigroup_apply_apply (hTime : P.HasContinuousC0Orbits hC0) + (t : NNReal) (f : C₀(α, ℝ)) (x : α) : + (P.c0Semigroup hC0 hTime) t f x = kernelIntegral (P t) f x := + rfl + +section Feller + +variable [LocallyCompactSpace α] [T2Space α] + +/-- A combined Feller predicate supplies its spatial `C₀` property. -/ +theorem IsFellerKernelSemigroup.mapsC0 {P : SubMarkovKernelSemigroup α} + (hP : P.IsFellerKernelSemigroup) : P.MapsC0 := + hP.choose + +/-- A combined Feller predicate supplies continuity of the corresponding `C₀` orbits. -/ +theorem IsFellerKernelSemigroup.hasContinuousC0Orbits {P : SubMarkovKernelSemigroup α} + (hP : P.IsFellerKernelSemigroup) : P.HasContinuousC0Orbits hP.mapsC0 := + hP.choose_spec + +/-- The strongly continuous contraction semigroup selected by the combined Feller predicate. -/ +noncomputable def IsFellerKernelSemigroup.c0Semigroup {P : SubMarkovKernelSemigroup α} + (hP : P.IsFellerKernelSemigroup) : + Semigroup.StronglyContinuousContractionSemigroup C₀(α, ℝ) := + P.c0Semigroup hP.mapsC0 hP.hasContinuousC0Orbits + +@[simp] +theorem IsFellerKernelSemigroup.c0Semigroup_apply_apply + {P : SubMarkovKernelSemigroup α} (hP : P.IsFellerKernelSemigroup) + (t : NNReal) (f : C₀(α, ℝ)) (x : α) : + hP.c0Semigroup t f x = kernelIntegral (P t) f x := + rfl + +end Feller + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime.lean new file mode 100644 index 0000000000..cd4a5ad531 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime.lean @@ -0,0 +1,30 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily + +/-! +# FiniteTime + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductActiveReduction.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductActiveReduction.lean new file mode 100644 index 0000000000..4b60b4e65e --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductActiveReduction.lean @@ -0,0 +1,106 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization + +/-! +# Restricting normalized coordinate products to active coordinates + +This file enumerates the active coordinates of a normalized `CoordinateProductTerm`, extracts +their genuine `C₀` factors, and proves that evaluation factors through the corresponding +coordinate restriction. The restricting function is definitionally the same path operation as +`FiniteOrderedTimes.restrictPath (activeOrderEmbedding factors)` when that finite-time API is in +scope. + +If there are no active coordinates, the reduced index type is `Fin 0` and the empty scalar +product is one. No constant-one element of `C₀` is constructed. This is purely algebraic +finite-product infrastructure: it involves no measure and no kernel. +-/ + +open scoped CompactlySupported ZeroAtInfty BigOperators + +namespace MarkovProcess.PiContinuousMap + +variable {n : ℕ} {alpha : Type*} [TopologicalSpace alpha] + +/-- The increasing enumeration of the coordinates carrying normalized factors. -/ +def activeOrderEmbedding (factors : List (Fin n × C₀(alpha, ℝ))) : + Fin (activeCoordinates factors).card ↪o Fin n := + (activeCoordinates factors).orderEmbOfFin rfl + +/-- The genuine `C₀` factor at an active coordinate, indexed in increasing order. -/ +def activeNormalizedFactor (factors : List (Fin n × C₀(alpha, ℝ))) + (j : Fin (activeCoordinates factors).card) : C₀(alpha, ℝ) := + (normalizedCoordinateFactors factors (activeOrderEmbedding factors j)).get (by + apply (mem_activeCoordinates_iff factors _).mp + exact Finset.orderEmbOfFin_mem (activeCoordinates factors) rfl j) + +private theorem eval_activeNormalizedFactor + (factors : List (Fin n × C₀(alpha, ℝ))) + (j : Fin (activeCoordinates factors).card) (x : alpha) : + evalOptionalFactor x + (normalizedCoordinateFactors factors (activeOrderEmbedding factors j)) = + activeNormalizedFactor factors j x := by + have hj : (normalizedCoordinateFactors factors + (activeOrderEmbedding factors j)).isSome := by + apply (mem_activeCoordinates_iff factors _).mp + exact Finset.orderEmbOfFin_mem (activeCoordinates factors) rfl j + generalize hq : normalizedCoordinateFactors factors + (activeOrderEmbedding factors j) = q at hj ⊢ + cases q with + | none => exact Bool.noConfusion hj + | some f => + simp only [evalOptionalFactor, activeNormalizedFactor, hq, Option.get_some] + +/-- The product of all optional normalized factors equals the product over active coordinates. +In particular, this holds uniformly when the active set, or the ambient `Fin n`, is empty. -/ +theorem normalizedCoordinateFactors_evaluation_active + (factors : List (Fin n × C₀(alpha, ℝ))) (x : Fin n → alpha) : + ∏ i, evalOptionalFactor (x i) (normalizedCoordinateFactors factors i) = + ∏ j, activeNormalizedFactor factors j (x (activeOrderEmbedding factors j)) := by + let A := activeCoordinates factors + let v : Fin n → ℝ := fun i ↦ + evalOptionalFactor (x i) (normalizedCoordinateFactors factors i) + calc + ∏ i, evalOptionalFactor (x i) (normalizedCoordinateFactors factors i) = + ∏ i ∈ A, v i := by + symm + apply Finset.prod_subset (fun i _ ↦ Finset.mem_univ i) + intro i _ hi + have hnone := normalizedCoordinateFactors_eq_none_of_notMem_activeCoordinates + factors (show i ∉ activeCoordinates factors from hi) + simp only [v, hnone, evalOptionalFactor] + _ = ∏ i : A, v i := (Finset.prod_finset_coe v A).symm + _ = ∏ j, v ((A.orderIsoOfFin rfl) j) := by + symm + exact (A.orderIsoOfFin rfl).toEquiv.prod_comp (fun i : A ↦ v i) + _ = ∏ j, activeNormalizedFactor factors j + (x (activeOrderEmbedding factors j)) := by + apply Finset.prod_congr rfl + intro j _ + simpa only [v, A, activeOrderEmbedding, + Finset.coe_orderIsoOfFin_apply] using + (eval_activeNormalizedFactor factors j + (x (activeOrderEmbedding factors j))) + +/-- Scalar evaluation of a normalized term on only its active coordinates. For an empty active +set this is the coefficient times the empty scalar product, hence just the coefficient. -/ +def CoordinateProductTerm.activeEvaluation + (t : CoordinateProductTerm (Fin n) alpha) + (y : Fin (activeCoordinates t.factors).card → alpha) : ℝ := + t.coefficient * ∏ j, activeNormalizedFactor t.factors j (y j) + +/-- Evaluation of a coordinate-product term factors through its increasing active-coordinate +restriction. The restricting lambda is definitionally +`FiniteOrderedTimes.restrictPath (activeOrderEmbedding t.factors)`. -/ +theorem CoordinateProductTerm.toContinuousMap_apply_active + (t : CoordinateProductTerm (Fin n) alpha) (x : Fin n → alpha) : + t.toContinuousMap x = + t.activeEvaluation (fun k ↦ x (activeOrderEmbedding t.factors k)) := by + rw [CoordinateProductTerm.toContinuousMap_apply_normalized, + normalizedCoordinateFactors_evaluation_active] + rfl + +end MarkovProcess.PiContinuousMap diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductNormalization.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductNormalization.lean new file mode 100644 index 0000000000..34f53bae92 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductNormalization.lean @@ -0,0 +1,122 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm + +/-! +# Normalizing finite coordinate products + +This file groups every factor of a `CoordinateProductTerm (Fin n) alpha` by its coordinate. +The normalized representation is a function into `Option C₀(alpha, ℝ)`: an active coordinate +contains the single product of all its original factors, while an inactive coordinate is `none`. + +Using `none` is essential because `C₀(alpha, ℝ)` generally has no constant-one element. Scalar +evaluation interprets inactivity as `1 : ℝ`, but the normalization itself never constructs a +spurious `1 : C₀(alpha, ℝ)`. The resulting evaluation identity is suitable for backward kernel +recursions that branch only over active coordinates. + +This is purely algebraic finite-product infrastructure: it involves no measure and no kernel. +-/ + +open scoped CompactlySupported ZeroAtInfty BigOperators + +namespace MarkovProcess.PiContinuousMap + +variable {n : ℕ} {alpha : Type*} [TopologicalSpace alpha] + +/-- Merge a new factor into an optional factor without requiring a unit in `C₀`. -/ +def mergeOptionalFactor (f : C₀(alpha, ℝ)) : Option C₀(alpha, ℝ) → Option C₀(alpha, ℝ) + | none => some f + | some g => some (f * g) + +/-- Coordinate-indexed normalization of a factor list. `none` marks an inactive coordinate. -/ +def normalizedCoordinateFactors (factors : List (Fin n × C₀(alpha, ℝ))) : + Fin n → Option C₀(alpha, ℝ) := + factors.foldr (fun p accumulated ↦ + Function.update accumulated p.1 (mergeOptionalFactor p.2 (accumulated p.1))) + (fun _ ↦ none) + +/-- Scalar evaluation of an optional normalized factor; inactivity contributes scalar one. -/ +def evalOptionalFactor (x : alpha) : Option C₀(alpha, ℝ) → ℝ + | none => 1 + | some f => f x + +private theorem prod_update_mul (i : Fin n) (a : ℝ) (v : Fin n → ℝ) : + ∏ j, Function.update v i (a * v i) j = a * ∏ j, v j := by + have hfun : Function.update v i (a * v i) = + fun j ↦ (if i = j then a else 1) * v j := by + funext j + by_cases h : i = j + · subst j + simp only [Function.update_self, if_pos] + · simp only [Function.update, h, Ne.symm h, dite_false, if_false, one_mul] + rw [hfun, Finset.prod_mul_distrib, Fintype.prod_ite_eq] + +private theorem evalOptionalFactor_merge (f : C₀(alpha, ℝ)) + (g : Option C₀(alpha, ℝ)) (x : alpha) : + evalOptionalFactor x (mergeOptionalFactor f g) = f x * evalOptionalFactor x g := by + cases g with + | none => simp only [mergeOptionalFactor, evalOptionalFactor, mul_one] + | some g => rfl + +/-- Normalization merges every factor at the same coordinate into a single optional `C₀` +factor and preserves pointwise evaluation. -/ +theorem normalizedCoordinateFactors_evaluation + (factors : List (Fin n × C₀(alpha, ℝ))) (x : Fin n → alpha) : + (factors.map fun p ↦ p.2 (x p.1)).prod = + ∏ i, evalOptionalFactor (x i) (normalizedCoordinateFactors factors i) := by + induction factors with + | nil => simp only [List.map_nil, List.prod_nil, normalizedCoordinateFactors, + List.foldr_nil, evalOptionalFactor, Finset.prod_const_one] + | cons p factors ih => + simp only [List.map_cons, List.prod_cons, normalizedCoordinateFactors, + List.foldr_cons] + rw [ih] + let accumulated := normalizedCoordinateFactors factors + have hEvalUpdate : + (fun i ↦ evalOptionalFactor (x i) + (Function.update accumulated p.1 + (mergeOptionalFactor p.2 (accumulated p.1)) i)) = + Function.update (fun i ↦ evalOptionalFactor (x i) (accumulated i)) p.1 + (p.2 (x p.1) * evalOptionalFactor (x p.1) (accumulated p.1)) := by + funext i + by_cases h : p.1 = i + · subst i + rw [Function.update_self, Function.update_self, evalOptionalFactor_merge] + · simp only [Function.update, Ne.symm h, dite_false] + change p.2 (x p.1) * ∏ i, evalOptionalFactor (x i) (accumulated i) = + ∏ i, evalOptionalFactor (x i) + (Function.update accumulated p.1 + (mergeOptionalFactor p.2 (accumulated p.1)) i) + rw [hEvalUpdate, prod_update_mul] + +/-- Active coordinates of a normalized coordinate product. -/ +def activeCoordinates (factors : List (Fin n × C₀(alpha, ℝ))) : Finset (Fin n) := + Finset.univ.filter fun i ↦ (normalizedCoordinateFactors factors i).isSome + +@[simp] +theorem mem_activeCoordinates_iff (factors : List (Fin n × C₀(alpha, ℝ))) + (i : Fin n) : + i ∈ activeCoordinates factors ↔ (normalizedCoordinateFactors factors i).isSome := by + simp only [activeCoordinates, Finset.mem_filter, Finset.mem_univ, true_and] + +/-- Inactive coordinates have no manufactured `C₀` unit factor. -/ +theorem normalizedCoordinateFactors_eq_none_of_notMem_activeCoordinates + (factors : List (Fin n × C₀(alpha, ℝ))) {i : Fin n} + (hi : i ∉ activeCoordinates factors) : + normalizedCoordinateFactors factors i = none := by + rw [mem_activeCoordinates_iff, Option.isSome_iff_ne_none] at hi + exact not_ne_iff.mp hi + +/-- Evaluation of a coordinate-product term through its normalized optional factors. -/ +theorem CoordinateProductTerm.toContinuousMap_apply_normalized + (t : CoordinateProductTerm (Fin n) alpha) (x : Fin n → alpha) : + t.toContinuousMap x = t.coefficient * + ∏ i, evalOptionalFactor (x i) (normalizedCoordinateFactors t.factors i) := by + rw [CoordinateProductTerm.toContinuousMap_apply, + normalizedCoordinateFactors_evaluation] + + +end MarkovProcess.PiContinuousMap diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteSetKernelShift.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteSetKernelShift.lean new file mode 100644 index 0000000000..cae3a260cb --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteSetKernelShift.lean @@ -0,0 +1,72 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift + +/-! +# Translation of finite dense-time kernels + +This file transports the finite-set kernel translation law from physical nonnegative-real times +to finite sets of dense times, using the canonical coordinate reindexings. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +noncomputable section + +namespace IsConservative + +variable {alpha : Type*} [MeasurableSpace alpha] + +/-- Translating a finite dense-time observation set is the same as first evolving for the +corresponding physical duration, after both physical and dense coordinates are reindexed. -/ +theorem finiteSetKernel_map_pullback_addFinset + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (s : DenseTime) (I : Finset DenseTime) : + (finiteSetKernel P (denseTimePhysicalSet (DenseTime.addFinset s I))).map + (DenseTimePath.pullbackAddFinset s I ∘ + DenseTimePath.pullbackPhysicalSet (DenseTime.addFinset s I)) = + ((finiteSetKernel P (denseTimePhysicalSet I)).map + (DenseTimePath.pullbackPhysicalSet I)).comp + (P (DenseTime.castOrderEmbedding s)) := by + have hsets : + denseTimePhysicalSet (DenseTime.addFinset s I) = + finiteSetTranslate (DenseTime.castOrderEmbedding s) (denseTimePhysicalSet I) := + DenseTime.map_castOrderEmbedding_addFinset s I + have hsubset : + finiteSetTranslate (DenseTime.castOrderEmbedding s) (denseTimePhysicalSet I) ⊆ + denseTimePhysicalSet (DenseTime.addFinset s I) := + hsets.symm.le + have hcoordinates : + DenseTimePath.pullbackAddFinset (alpha := alpha) s I ∘ + DenseTimePath.pullbackPhysicalSet (DenseTime.addFinset s I) = + (DenseTimePath.pullbackPhysicalSet I ∘ + pullbackFiniteSetTranslate (DenseTime.castOrderEmbedding s) + (denseTimePhysicalSet I)) ∘ + Finset.restrict₂ (π := fun _ ↦ alpha) hsubset := by + funext path t + apply congrArg path + apply Subtype.ext + exact DenseTime.castOrderEmbedding_add s t + rw [hcoordinates, Kernel.map_comp_right] + · rw [← hP.finiteSetKernel_map_restrict₂ P hsubset, Kernel.map_comp_right] + · rw [hP.finiteSetKernel_map_pullback_translate P, Kernel.map_comp] + · exact measurable_pullbackFiniteSetTranslate + (DenseTime.castOrderEmbedding s) (denseTimePhysicalSet I) + · exact DenseTimePath.measurable_pullbackPhysicalSet I + · exact Finset.measurable_restrict₂ (X := fun _ ↦ alpha) hsubset + · exact (DenseTimePath.measurable_pullbackPhysicalSet I).comp + (measurable_pullbackFiniteSetTranslate + (DenseTime.castOrderEmbedding s) (denseTimePhysicalSet I)) + +end IsConservative + +end +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteShift.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteShift.lean new file mode 100644 index 0000000000..8dddd418fe --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteShift.lean @@ -0,0 +1,91 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift + +/-! +# Finite-coordinate shifts on dense-time paths + +Addition by a dense time transports finite sets of dense-time coordinates injectively. This file +provides the resulting coordinate equivalence and relates restriction after shifting a dense-time +path to restriction on the translated finite set. It makes no probability-law or Markov claim. +-/ + +namespace MarkovProcess + +noncomputable section + +namespace DenseTime + +/-- The image of a finite dense-time set under addition by `s`. -/ +def addFinset (s : DenseTime) (I : Finset DenseTime) : Finset DenseTime := + I.map (addOrderEmbedding s).toEmbedding + +@[simp] +theorem mem_addFinset (s : DenseTime) (I : Finset DenseTime) (t : DenseTime) : + t ∈ addFinset s I ↔ ∃ r ∈ I, s + r = t := by + rw [addFinset, Finset.mem_map] + constructor + · rintro ⟨r, hr, hrt⟩ + exact ⟨r, hr, hrt⟩ + · rintro ⟨r, hr, hrt⟩ + exact ⟨r, hr, hrt⟩ + +/-- Addition by `s` identifies a finite dense-time set with its translated image. -/ +def addFinsetEquiv (s : DenseTime) (I : Finset DenseTime) : I ≃ addFinset s I := + Equiv.ofBijective + (fun t ↦ ⟨s + t, (mem_addFinset s I (s + t)).mpr ⟨t, t.property, rfl⟩⟩) + ⟨by + intro t u h + apply Subtype.ext + apply (addOrderEmbedding s).injective + exact congrArg Subtype.val h, + by + intro t + obtain ⟨r, hrI, hrt⟩ := (mem_addFinset s I t).mp t.property + refine ⟨⟨r, hrI⟩, Subtype.ext ?_⟩ + exact hrt⟩ + +@[simp] +theorem addFinsetEquiv_apply (s : DenseTime) (I : Finset DenseTime) (t : I) : + (addFinsetEquiv s I t : DenseTime) = s + t := rfl + +end DenseTime + +namespace DenseTimePath + +variable {alpha : Type*} + +/-- Reindex a path on a translated finite dense-time set back to the original coordinates. -/ +def pullbackAddFinset (s : DenseTime) (I : Finset DenseTime) + (path : DenseTime.addFinset s I → alpha) : I → alpha := + fun t ↦ path (DenseTime.addFinsetEquiv s I t) + +@[simp] +theorem pullbackAddFinset_apply (s : DenseTime) (I : Finset DenseTime) + (path : DenseTime.addFinset s I → alpha) (t : I) : + pullbackAddFinset s I path t = path (DenseTime.addFinsetEquiv s I t) := rfl + +variable [MeasurableSpace alpha] + +/-- Reindexing from a translated finite dense-time set is measurable. -/ +theorem measurable_pullbackAddFinset (s : DenseTime) (I : Finset DenseTime) : + Measurable (pullbackAddFinset (alpha := alpha) s I) := by + rw [measurable_pi_iff] + intro t + exact measurable_pi_apply (DenseTime.addFinsetEquiv s I t) + +omit [MeasurableSpace alpha] in +/-- Restriction after shifting equals translated restriction followed by the canonical +reindexing. -/ +theorem restrict_shift (s : DenseTime) (I : Finset DenseTime) (path : DenseTime → alpha) : + I.restrict (shift s path) = + pullbackAddFinset s I ((DenseTime.addFinset s I).restrict path) := by + funext t + rfl + +end DenseTimePath +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean new file mode 100644 index 0000000000..6d6ee7b88c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean @@ -0,0 +1,126 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass + +/-! +# Compactly supported approximation on a finite product + +This file upgrades compact-set Stone--Weierstrass approximation to a uniform approximation on the +whole product. The key device is a product of one-coordinate compactly supported cutoffs. Each +coordinate cutoff is one on the corresponding projection of the target's compact support. +-/ + +open Topology +open scoped CompactlySupported ZeroAtInfty + +namespace MarkovProcess.PiContinuousMap + +variable {I α : Type*} [Fintype I] [TopologicalSpace α] + +/-- Coordinatewise compactly supported cutoffs for a compactly supported function. The product +cutoff is one on the target's topological support, and its natural product box is compact. -/ +theorem exists_coordinate_cutoffs_of_hasCompactSupport + [T3Space α] [LocallyCompactSpace α] (f : C_c(I → α, ℝ)) : + ∃ (φ : I → C₀(α, ℝ)) (B : Set (I → α)), + IsCompact B ∧ + (∀ i x, 0 ≤ φ i x ∧ φ i x ≤ 1) ∧ + Set.EqOn (∏ i, coordinate i ((φ i : C₀(α, ℝ)) : C(α, ℝ))) 1 (tsupport f) ∧ + tsupport f ⊆ B ∧ + Set.EqOn (∏ i, coordinate i ((φ i : C₀(α, ℝ)) : C(α, ℝ))) 0 Bᶜ := by + classical + have hprojection (i : I) : IsCompact ((fun x : I → α ↦ x i) '' tsupport f) := + f.hasCompactSupport.image (continuous_apply i) + have hcutoff (i : I) : + ∃ φ : C₀(α, ℝ), + Set.EqOn φ 1 ((fun x : I → α ↦ x i) '' tsupport f) ∧ + HasCompactSupport φ ∧ + ∀ x, 0 ≤ φ x ∧ φ x ≤ 1 := by + obtain ⟨u, huone, -, hucompact, hurange⟩ := + exists_continuous_one_zero_of_isCompact (hprojection i) isClosed_empty + (Set.disjoint_empty _) + exact ⟨⟨u, HasCompactSupport.is_zero_at_infty hucompact⟩, huone, hucompact, hurange⟩ + choose φ hφone hφcompact hφrange using hcutoff + let B : Set (I → α) := Set.pi Set.univ (fun i ↦ tsupport (φ i)) + refine ⟨φ, B, isCompact_univ_pi hφcompact, hφrange, ?_, ?_, ?_⟩ + · intro x hx + simp only [Finset.prod_apply, coordinate_apply, Pi.one_apply] + apply Finset.prod_eq_one + intro i hi + exact hφone i ⟨x, hx, rfl⟩ + · intro x hx i hi + apply subset_tsupport + show φ i (x i) ≠ 0 + rw [hφone i ⟨x, hx, rfl⟩] + exact one_ne_zero + · intro x hx + simp only [Finset.prod_apply, coordinate_apply, Pi.zero_apply] + simp only [B, Set.mem_compl_iff, Set.mem_pi, Set.mem_univ, true_implies, not_forall] at hx + obtain ⟨i, hi⟩ := hx + exact Finset.prod_eq_zero (Finset.mem_univ i) (image_eq_zero_of_notMem_tsupport hi) + +/-- A compactly supported continuous function on a finite product can be approximated uniformly on +the whole product by the coordinate `C₀` algebra. -/ +theorem exists_coordinateC0Subalgebra_near_compactlySupported + [T3Space α] [LocallyCompactSpace α] + (f : C_c(I → α, ℝ)) {epsilon : ℝ} (hepsilon : 0 < epsilon) : + ∃ h ∈ coordinateC0Subalgebra (I := I) (α := α), + ∀ x, ‖h x - f x‖ < epsilon := by + classical + obtain ⟨φ, B, hBcompact, hφrange, hcutoff_one, hsupport_subset, hcutoff_zero⟩ := + exists_coordinate_cutoffs_of_hasCompactSupport f + let q : C(I → α, ℝ) := ∏ i, coordinate i (((φ i : C₀(α, ℝ)) : C(α, ℝ))) + obtain ⟨g, hgmem, hgnear⟩ := + exists_coordinateC0Subalgebra_near_on_isCompact (f := f.toContinuousMap) hBcompact hepsilon + refine ⟨q * g, ?_, fun x ↦ ?_⟩ + · have hqmem : q ∈ coordinateC0Subalgebra (I := I) (α := α) := by + dsimp only [q] + have hprod (s : Finset I) : + (∏ i ∈ s, coordinate i (((φ i : C₀(α, ℝ)) : C(α, ℝ)))) ∈ + coordinateC0Subalgebra (I := I) (α := α) := by + induction s using Finset.induction_on with + | empty => exact (coordinateC0Subalgebra (I := I) (α := α)).one_mem + | @insert i s hi ih => + rw [Finset.prod_insert hi] + exact (coordinateC0Subalgebra (I := I) (α := α)).mul_mem + (coordinate_c0_mem_coordinateC0Subalgebra (I := I) i (φ i)) ih + exact hprod Finset.univ + exact (coordinateC0Subalgebra (I := I) (α := α)).mul_mem hqmem hgmem + · by_cases hxB : x ∈ B + · have hq_nonneg : 0 ≤ q x := by + dsimp only [q] + simp only [ContinuousMap.prod_apply, coordinate_apply] + exact Finset.prod_nonneg fun i _ ↦ (hφrange i (x i)).1 + have hq_le_one : q x ≤ 1 := by + dsimp only [q] + simp only [ContinuousMap.prod_apply, coordinate_apply] + exact Finset.prod_le_one (fun i _ ↦ (hφrange i (x i)).1) + (fun i _ ↦ (hφrange i (x i)).2) + have hqf : q x * f x = f x := by + by_cases hxsupport : x ∈ tsupport f + · have hqone : q x = 1 := by + dsimp only [q] + simpa only [ContinuousMap.prod_apply, Finset.prod_apply, coordinate_apply, + Pi.one_apply] using hcutoff_one hxsupport + rw [hqone, one_mul] + · rw [image_eq_zero_of_notMem_tsupport hxsupport, mul_zero] + rw [ContinuousMap.mul_apply, ← hqf, ← mul_sub] + calc + ‖q x * (g x - f x)‖ = ‖q x‖ * ‖g x - f x‖ := norm_mul _ _ + _ ≤ 1 * ‖g x - f x‖ := mul_le_mul_of_nonneg_right + (by simpa only [Real.norm_eq_abs, abs_of_nonneg hq_nonneg] using hq_le_one) + (norm_nonneg _) + _ < 1 * epsilon := mul_lt_mul_of_pos_left (hgnear x hxB) zero_lt_one + _ = epsilon := one_mul _ + · have hqzero : q x = 0 := by + dsimp only [q] + simp only [ContinuousMap.prod_apply, coordinate_apply] + simpa only [Finset.prod_apply, coordinate_apply, Pi.zero_apply] using hcutoff_zero hxB + have hxfzero : f x = 0 := + image_eq_zero_of_notMem_tsupport (fun hx ↦ hxB (hsupport_subset hx)) + rw [ContinuousMap.mul_apply, hqzero, zero_mul, hxfzero, sub_zero, norm_zero] + exact hepsilon + +end MarkovProcess.PiContinuousMap diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean new file mode 100644 index 0000000000..7abe6bda00 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean @@ -0,0 +1,163 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation + +/-! +# Explicit coordinate-product normal forms + +This file replaces abstract membership in the coordinate `C₀` algebra by a concrete finite +sum of finite products. Factors are stored in lists, so the normal form can subsequently be +consumed by recursion (for example, by iterated kernel integration). The empty factor list is +the constant function `1`; in particular the representation treats constants and an empty +coordinate type without exceptional cases. +-/ + +open scoped CompactlySupported ZeroAtInfty + +namespace MarkovProcess.PiContinuousMap + +variable {I α : Type*} [TopologicalSpace α] + +/-- A scalar coefficient together with a finite ordered list of one-coordinate `C₀` factors. -/ +structure CoordinateProductTerm (I α : Type*) [TopologicalSpace α] where + coefficient : ℝ + factors : List (I × C₀(α, ℝ)) + +/-- The continuous function represented by one coordinate-product term. -/ +def CoordinateProductTerm.toContinuousMap (t : CoordinateProductTerm I α) : C(I → α, ℝ) := + t.coefficient • (t.factors.map (fun p ↦ coordinate p.1 (p.2 : C(α, ℝ)))).prod + +@[simp] +theorem CoordinateProductTerm.toContinuousMap_apply + (t : CoordinateProductTerm I α) (x : I → α) : + t.toContinuousMap x = t.coefficient * (t.factors.map (fun p ↦ p.2 (x p.1))).prod := by + rw [CoordinateProductTerm.toContinuousMap, ContinuousMap.smul_apply, smul_eq_mul] + congr 1 + induction t.factors with + | nil => rfl + | cons p factors ih => + simp only [List.map_cons, List.prod_cons, ContinuousMap.mul_apply, coordinate_apply] + change p.2 (x p.1) * _ = p.2 (x p.1) * _ + exact congrArg (fun z ↦ p.2 (x p.1) * z) ih + +/-- Evaluate a finite list of coordinate-product terms by summing its terms. -/ +def coordinatePolynomial (terms : List (CoordinateProductTerm I α)) : C(I → α, ℝ) := + (terms.map CoordinateProductTerm.toContinuousMap).sum + +@[simp] +theorem coordinatePolynomial_apply (terms : List (CoordinateProductTerm I α)) (x : I → α) : + coordinatePolynomial terms x = + (terms.map fun t ↦ t.coefficient * (t.factors.map fun p ↦ p.2 (x p.1)).prod).sum := by + induction terms with + | nil => rfl + | cons t terms ih => + rw [coordinatePolynomial] + simp only [List.map_cons, List.sum_cons, ContinuousMap.add_apply, + CoordinateProductTerm.toContinuousMap_apply] + change _ + coordinatePolynomial terms x = _ + rw [ih] + +@[simp] +theorem coordinatePolynomial_nil : + coordinatePolynomial ([] : List (CoordinateProductTerm I α)) = 0 := + rfl + +@[simp] +theorem coordinatePolynomial_cons (t : CoordinateProductTerm I α) + (terms : List (CoordinateProductTerm I α)) : + coordinatePolynomial (t :: terms) = t.toContinuousMap + coordinatePolynomial terms := + rfl + +@[simp] +theorem coordinatePolynomial_append (left right : List (CoordinateProductTerm I α)) : + coordinatePolynomial (left ++ right) = coordinatePolynomial left + coordinatePolynomial right := by + simp only [coordinatePolynomial, List.map_append, List.sum_append] + +/-- Multiply two terms by multiplying coefficients and concatenating their factor lists. -/ +def CoordinateProductTerm.mul (s t : CoordinateProductTerm I α) : + CoordinateProductTerm I α := + ⟨s.coefficient * t.coefficient, s.factors ++ t.factors⟩ + +@[simp] +theorem CoordinateProductTerm.toContinuousMap_mul + (s t : CoordinateProductTerm I α) : + (s.mul t).toContinuousMap = s.toContinuousMap * t.toContinuousMap := by + ext x + simp only [CoordinateProductTerm.toContinuousMap_apply, CoordinateProductTerm.mul, + List.map_append, List.prod_append, ContinuousMap.mul_apply] + ac_rfl + +@[simp] +theorem coordinatePolynomial_map_mul (s : CoordinateProductTerm I α) + (terms : List (CoordinateProductTerm I α)) : + coordinatePolynomial (terms.map s.mul) = + s.toContinuousMap * coordinatePolynomial terms := by + induction terms with + | nil => simp only [List.map_nil, coordinatePolynomial_nil, mul_zero] + | cons t terms ih => + simp only [List.map_cons, coordinatePolynomial_cons, + CoordinateProductTerm.toContinuousMap_mul, ih, mul_add] + +/-- Distributive product of two finite coordinate polynomials. -/ +def coordinatePolynomialMul (left right : List (CoordinateProductTerm I α)) : + List (CoordinateProductTerm I α) := + left.flatMap fun s ↦ right.map s.mul + +@[simp] +theorem coordinatePolynomial_coordinatePolynomialMul + (left right : List (CoordinateProductTerm I α)) : + coordinatePolynomial (coordinatePolynomialMul left right) = + coordinatePolynomial left * coordinatePolynomial right := by + induction left with + | nil => simp only [coordinatePolynomialMul, List.flatMap_nil, coordinatePolynomial_nil, zero_mul] + | cons s left ih => + simp only [coordinatePolynomialMul, List.flatMap_cons, coordinatePolynomial_append, + coordinatePolynomial_map_mul, coordinatePolynomial_cons, add_mul] + change s.toContinuousMap * coordinatePolynomial right + + coordinatePolynomial (coordinatePolynomialMul left right) = _ + rw [ih] + +/-- Every member of the coordinate `C₀` algebra is an explicit finite sum of scalar multiples +of finite products of one-coordinate `C₀` functions. -/ +theorem exists_coordinateProductTerms_of_mem_coordinateC0Subalgebra + {h : C(I → α, ℝ)} (hh : h ∈ coordinateC0Subalgebra (I := I) (α := α)) : + ∃ terms : List (CoordinateProductTerm I α), h = coordinatePolynomial terms := by + change h ∈ Algebra.adjoin ℝ + {g | ∃ (i : I) (f : C₀(α, ℝ)), g = coordinate i (f : C(α, ℝ))} at hh + induction hh using Algebra.adjoin_induction with + | mem g hg => + obtain ⟨i, f, rfl⟩ := hg + exact ⟨[⟨1, [(i, f)]⟩], by ext x; simp [coordinatePolynomial, + CoordinateProductTerm.toContinuousMap]⟩ + | algebraMap r => + exact ⟨[⟨r, []⟩], by ext x; simp [coordinatePolynomial, + CoordinateProductTerm.toContinuousMap]⟩ + | add x y hx hy ihx ihy => + obtain ⟨left, hleft⟩ := ihx + obtain ⟨right, hright⟩ := ihy + exact ⟨left ++ right, by rw [coordinatePolynomial_append, ← hleft, ← hright]⟩ + | mul x y hx hy ihx ihy => + obtain ⟨left, hleft⟩ := ihx + obtain ⟨right, hright⟩ := ihy + exact ⟨coordinatePolynomialMul left right, by + rw [coordinatePolynomial_coordinatePolynomialMul, ← hleft, ← hright]⟩ + +/-- Every compactly supported continuous finite-product test is uniformly approximable on the +whole product by an explicit finite sum of scalar multiples of coordinate products. -/ +theorem exists_coordinateProductTerms_near_compactlySupported + [Fintype I] [T3Space α] [LocallyCompactSpace α] + (f : C_c(I → α, ℝ)) {epsilon : ℝ} (hepsilon : 0 < epsilon) : + ∃ terms : List (CoordinateProductTerm I α), + ∀ x, ‖(terms.map fun t ↦ + t.coefficient * (t.factors.map fun p ↦ p.2 (x p.1)).prod).sum - f x‖ < epsilon := by + obtain ⟨h, hh, hnear⟩ := + exists_coordinateC0Subalgebra_near_compactlySupported f hepsilon + obtain ⟨terms, rfl⟩ := exists_coordinateProductTerms_of_mem_coordinateC0Subalgebra hh + refine ⟨terms, fun x ↦ ?_⟩ + rw [← coordinatePolynomial_apply] + exact hnear x + +end MarkovProcess.PiContinuousMap diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductStoneWeierstrass.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductStoneWeierstrass.lean new file mode 100644 index 0000000000..4696aa589a --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductStoneWeierstrass.lean @@ -0,0 +1,132 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Topology.ContinuousMap.StoneWeierstrass +import Mathlib.Topology.ContinuousMap.CompactlySupported +import Mathlib.Topology.Separation.CompletelyRegular +import Mathlib.Topology.UrysohnsLemma + +/-! +# Stone--Weierstrass on products + +This file packages the subalgebra of real continuous functions on a finite product generated by +one-coordinate functions. It proves that this subalgebra separates points, and hence is uniformly +dense when the factor is compact. + +Membership in `PiContinuousMap.coordinateSubalgebra` expresses precisely that a +function is obtained from one-coordinate functions using finitely many constants, sums, and +products. Thus the approximation theorem is a reusable bundled form of finite-product test +function density. + +The coordinate pullback of a function in `C₀(α, ℝ)` need not itself vanish at infinity on the +whole product. Accordingly, `coordinateC0Subalgebra` is a subalgebra of continuous maps; the +`C₀` designation records its one-coordinate generators, not its ambient carrier. +-/ + +open Topology +open scoped ZeroAtInfty + +namespace MarkovProcess.PiContinuousMap + +variable {I α : Type*} [TopologicalSpace α] + +/-- Pull a continuous function on one factor back along a coordinate projection. -/ +def coordinate (i : I) (f : C(α, ℝ)) : C(I → α, ℝ) := + f.comp ⟨fun x ↦ x i, continuous_apply i⟩ + +@[simp] +theorem coordinate_apply (i : I) (f : C(α, ℝ)) (x : I → α) : + coordinate i f x = f (x i) := + rfl + +/-- The algebra generated by pullbacks of continuous functions from individual factors. -/ +def coordinateSubalgebra : Subalgebra ℝ C(I → α, ℝ) := + Algebra.adjoin ℝ {g | ∃ (i : I) (f : C(α, ℝ)), g = coordinate i f} + +theorem coordinate_mem_coordinateSubalgebra (i : I) (f : C(α, ℝ)) : + coordinate i f ∈ coordinateSubalgebra (I := I) (α := α) := + Algebra.subset_adjoin ⟨i, f, rfl⟩ + +/-- The algebra generated by coordinate pullbacks of functions vanishing at infinity. -/ +def coordinateC0Subalgebra : Subalgebra ℝ C(I → α, ℝ) := + Algebra.adjoin ℝ + {g | ∃ (i : I) (f : C₀(α, ℝ)), g = coordinate i (f : C(α, ℝ))} + +theorem coordinate_c0_mem_coordinateC0Subalgebra (i : I) (f : C₀(α, ℝ)) : + coordinate i (f : C(α, ℝ)) ∈ coordinateC0Subalgebra (I := I) (α := α) := + Algebra.subset_adjoin ⟨i, f, rfl⟩ + +/-- If continuous real functions separate points of the factor, the algebra generated by +one-coordinate functions separates points of every product. -/ +theorem coordinateSubalgebra_separatesPoints [T35Space α] : + (coordinateSubalgebra (I := I) (α := α)).SeparatesPoints := by + intro x y hxy + have hcoord : ∃ i : I, x i ≠ y i := by + by_contra h + apply hxy + funext i + exact not_ne_iff.mp (not_exists.mp h i) + obtain ⟨i, hi⟩ := hcoord + obtain ⟨f, hfcont, hfne⟩ := separatesPoints_continuous_of_t35Space hi + let cf : C(α, ℝ) := ⟨f, hfcont⟩ + refine ⟨coordinate i cf, ?_, ?_⟩ + · exact ⟨coordinate i cf, + ⟨coordinate_mem_coordinateSubalgebra (I := I) i cf, rfl⟩⟩ + · exact hfne + +/-- On a locally compact regular factor, one-coordinate `C₀` functions already separate points +of every product. -/ +theorem coordinateC0Subalgebra_separatesPoints + [T3Space α] [LocallyCompactSpace α] : + (coordinateC0Subalgebra (I := I) (α := α)).SeparatesPoints := by + intro x y hxy + have hcoord : ∃ i : I, x i ≠ y i := by + by_contra h + apply hxy + funext i + exact not_ne_iff.mp (not_exists.mp h i) + obtain ⟨i, hi⟩ := hcoord + obtain ⟨f, hfone, hfzero, hfcompact, -⟩ := + exists_continuous_one_zero_of_isCompact (isCompact_singleton : IsCompact ({x i} : Set α)) + (isClosed_singleton : IsClosed ({y i} : Set α)) (Set.disjoint_singleton.mpr hi) + let f0 : C₀(α, ℝ) := + ⟨f, HasCompactSupport.is_zero_at_infty hfcompact⟩ + refine ⟨coordinate i (f0 : C(α, ℝ)), ?_, ?_⟩ + · exact ⟨coordinate i (f0 : C(α, ℝ)), + ⟨coordinate_c0_mem_coordinateC0Subalgebra (I := I) i f0, rfl⟩⟩ + · change f (x i) ≠ f (y i) + rw [hfone (Set.mem_singleton _), + hfzero (Set.mem_singleton _)] + exact one_ne_zero + +/-- On every compact subset of a product, restrictions of globally continuous functions can be +approximated uniformly by algebraic combinations of one-coordinate `C₀` functions. -/ +theorem exists_coordinateC0Subalgebra_near_on_isCompact + [T3Space α] [LocallyCompactSpace α] + (f : C(I → α, ℝ)) {K : Set (I → α)} (hK : IsCompact K) + {epsilon : ℝ} (hepsilon : 0 < epsilon) : + ∃ g ∈ coordinateC0Subalgebra (I := I) (α := α), + ∀ x ∈ K, ‖g x - f x‖ < epsilon := + ContinuousMap.exists_mem_subalgebra_near_continuous_of_isCompact_of_separatesPoints + coordinateC0Subalgebra_separatesPoints f hK hepsilon + +/-- Finite algebraic combinations of one-coordinate continuous functions are uniformly dense in +the continuous real functions on a compact finite product. -/ +theorem coordinateSubalgebra_topologicalClosure_eq_top + [Fintype I] [T35Space α] [CompactSpace α] : + (coordinateSubalgebra (I := I) (α := α)).topologicalClosure = ⊤ := + ContinuousMap.subalgebra_topologicalClosure_eq_top_of_separatesPoints _ + coordinateSubalgebra_separatesPoints + +/-- Epsilon form of finite-product test-function density. -/ +theorem exists_coordinateSubalgebra_near + [Fintype I] [T35Space α] [CompactSpace α] + (f : C(I → α, ℝ)) {epsilon : ℝ} (hepsilon : 0 < epsilon) : + ∃ g : coordinateSubalgebra (I := I) (α := α), + ‖(g : C(I → α, ℝ)) - f‖ < epsilon := + ContinuousMap.exists_mem_subalgebra_near_continuousMap_of_separatesPoints _ + coordinateSubalgebra_separatesPoints f epsilon hepsilon + +end MarkovProcess.PiContinuousMap diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean new file mode 100644 index 0000000000..098d462d36 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean @@ -0,0 +1,142 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +import Mathlib.MeasureTheory.Integral.CompactlySupported + +/-! +# Compact-test transport for finite-set kernels + +This file identifies the increasing-coordinate representation of a finite set with its ordinary +function space by a homeomorphism. It transports compactly supported tests across that +homeomorphism and rewrites their finite-set-kernel integrals as finite-time-kernel integrals. + +Strong measurability of a compactly supported test is obtained privately from uniform coordinate- +polynomial approximations. This avoids adding an `OpensMeasurableSpace` assumption on the finite +product. These declarations are finite-dimensional infrastructure; no statement about path space +is proved here. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal CompactlySupported + +namespace MarkovProcess.SubMarkovKernelSemigroup + +private theorem stronglyMeasurable_coordinatePolynomial + {I alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + (terms : List (PiContinuousMap.CoordinateProductTerm I alpha)) : + StronglyMeasurable (PiContinuousMap.coordinatePolynomial terms) := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil] + exact stronglyMeasurable_const + | cons term terms ih => + rw [PiContinuousMap.coordinatePolynomial_cons] + apply StronglyMeasurable.add _ ih + have hprod : StronglyMeasurable (fun path : I → alpha ↦ + (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by + induction term.factors with + | nil => exact stronglyMeasurable_const + | cons p factors ihFactors => + simp only [List.map_cons, List.prod_cons] + exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul + ihFactors + rw [show (term.toContinuousMap : (I → alpha) → ℝ) = fun path ↦ + term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by + funext path + exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] + exact hprod.const_mul term.coefficient + +private theorem stronglyMeasurable_compactlySupported_pi + {I alpha : Type*} [Fintype I] [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [T3Space alpha] [LocallyCompactSpace alpha] + (f : C_c(I → alpha, ℝ)) : StronglyMeasurable f := by + have hexists (m : ℕ) : + ∃ terms : List (PiContinuousMap.CoordinateProductTerm I alpha), + ∀ x, ‖PiContinuousMap.coordinatePolynomial terms x - f x‖ < + 1 / ((m : ℝ) + 1) := by + have hpositive : 0 < 1 / ((m : ℝ) + 1) := by positivity + obtain ⟨terms, hterms⟩ := + PiContinuousMap.exists_coordinateProductTerms_near_compactlySupported f hpositive + exact ⟨terms, fun x ↦ by + rw [PiContinuousMap.coordinatePolynomial_apply] + exact hterms x⟩ + choose terms hterms using hexists + apply stronglyMeasurable_of_tendsto Filter.atTop + (fun m ↦ stronglyMeasurable_coordinatePolynomial (terms m)) + rw [tendsto_pi_nhds] + intro x + rw [Metric.tendsto_nhds] + intro epsilon hepsilon + have hscalar : Filter.Tendsto (fun m : ℕ ↦ (1 : ℝ) / ((m : ℝ) + 1)) Filter.atTop + (nhds 0) := tendsto_one_div_add_atTop_nhds_zero_nat + rw [Metric.tendsto_nhds] at hscalar + filter_upwards [hscalar epsilon hepsilon] with m hm + rw [Real.dist_eq, sub_zero, abs_of_pos (by positivity)] at hm + exact (hterms m x).trans_le hm.le + +/-- The increasing-coordinate representation of paths on a finite time set, as a homeomorphism. -/ +noncomputable def orderedPathToFiniteSetHomeomorph + {alpha : Type*} [TopologicalSpace alpha] (I : Finset NNReal) : + (Fin I.card → alpha) ≃ₜ (I → alpha) := + Homeomorph.piCongrLeft (Y := fun _ : I ↦ alpha) (I.orderIsoOfFin rfl).toEquiv + +/-- The ordered-coordinate homeomorphism has underlying function `orderedPathToFiniteSet`. -/ +@[simp] +theorem orderedPathToFiniteSetHomeomorph_apply + {alpha : Type*} [TopologicalSpace alpha] (I : Finset NNReal) + (path : Fin I.card → alpha) : + orderedPathToFiniteSetHomeomorph I path = orderedPathToFiniteSet I path := by + ext t + change (Equiv.piCongrLeft (fun _ : I ↦ alpha) (I.orderIsoOfFin rfl).toEquiv path) t = _ + rw [Equiv.piCongrLeft_apply] + simp only [orderedPathToFiniteSet] + rw [eqRec_eq_cast, cast_eq] + rfl + +/-- Pull a compactly supported test on finite-set coordinates back to increasing coordinates. -/ +noncomputable def pullbackFiniteSetCompactTest + {alpha : Type*} [TopologicalSpace alpha] [T2Space alpha] + (I : Finset NNReal) (f : C_c(I → alpha, ℝ)) : C_c(Fin I.card → alpha, ℝ) := + f.comp (orderedPathToFiniteSetHomeomorph I).toCocompactMap + +/-- Evaluation of a compact test pulled back to increasing coordinates. -/ +@[simp] +theorem pullbackFiniteSetCompactTest_apply + {alpha : Type*} [TopologicalSpace alpha] [T2Space alpha] + (I : Finset NNReal) (f : C_c(I → alpha, ℝ)) (path : Fin I.card → alpha) : + pullbackFiniteSetCompactTest I f path = f (orderedPathToFiniteSet I path) := by + rw [pullbackFiniteSetCompactTest] + exact congr_arg f (orderedPathToFiniteSetHomeomorph_apply I path) + +/-- Integration against the mapped ordered-coordinate law equals integration of the pulled-back +compact test. -/ +theorem integral_map_orderedPathToFiniteSet + {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + (I : Finset NNReal) (f : C_c(I → alpha, ℝ)) + (mu : Measure (Fin I.card → alpha)) : + ∫ y, f y ∂mu.map (orderedPathToFiniteSet I) = + ∫ path, pullbackFiniteSetCompactTest I f path ∂mu := by + rw [integral_map (measurable_orderedPathToFiniteSet I).aemeasurable + (stronglyMeasurable_compactlySupported_pi f).aestronglyMeasurable] + apply integral_congr_ae + exact ae_of_all _ fun path ↦ (pullbackFiniteSetCompactTest_apply I f path).symm + +/-- A compact-test integral against `finiteSetKernel` is the corresponding pulled-back integral +against `finiteTimeKernel`. -/ +theorem integral_finiteSetKernel_eq_integral_pullbackFiniteSetCompactTest + {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] + (P : SubMarkovKernelSemigroup alpha) (I : Finset NNReal) + (f : C_c(I → alpha, ℝ)) (x : alpha) : + ∫ y, f y ∂finiteSetKernel P I x = + ∫ path, pullbackFiniteSetCompactTest I f path + ∂finiteTimeKernel P (finiteSetTimes I) x := by + rw [finiteSetKernel_eq_map, Kernel.map_apply _ (measurable_orderedPathToFiniteSet I)] + exact integral_map_orderedPathToFiniteSet I f (finiteTimeKernel P (finiteSetTimes I) x) + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelShift.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelShift.lean new file mode 100644 index 0000000000..49852690d8 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelShift.lean @@ -0,0 +1,183 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily + +/-! +# Translation of finite-set kernels + +This file translates finite sets of nonnegative observation times, reindexes paths on the +translated set back to the original coordinates, and proves the corresponding translation law +for conservative transition-kernel semigroups. It is finite-dimensional kernel infrastructure; +it does not assert a path-space Markov property. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +noncomputable section + +/-- The image of a finite set of nonnegative times under translation by `s`. -/ +def finiteSetTranslate (s : NNReal) (I : Finset NNReal) : Finset NNReal := + I.map (addLeftEmbedding s) + +@[simp] +theorem mem_finiteSetTranslate (s : NNReal) (I : Finset NNReal) (t : NNReal) : + t ∈ finiteSetTranslate s I ↔ ∃ r ∈ I, s + r = t := by + rw [finiteSetTranslate, Finset.mem_map] + rfl + +/-- Translation identifies the original finite time set with its translated image. -/ +def finiteSetTranslateEquiv (s : NNReal) (I : Finset NNReal) : I ≃ finiteSetTranslate s I := + Equiv.ofBijective + (fun t ↦ ⟨s + t, (mem_finiteSetTranslate s I (s + t)).mpr ⟨t, t.property, rfl⟩⟩) + ⟨by + intro t u h + apply Subtype.ext + exact add_left_cancel (congrArg Subtype.val h), + by + intro t + obtain ⟨r, hrI, hrt⟩ := (mem_finiteSetTranslate s I t).mp t.property + exact ⟨⟨r, hrI⟩, Subtype.ext hrt⟩⟩ + +@[simp] +theorem finiteSetTranslateEquiv_apply (s : NNReal) (I : Finset NNReal) (t : I) : + (finiteSetTranslateEquiv s I t : NNReal) = s + t := + rfl + +/-- Reindex a path on translated times back to the original finite set. -/ +def pullbackFiniteSetTranslate {alpha : Type*} (s : NNReal) (I : Finset NNReal) + (path : finiteSetTranslate s I → alpha) : I → alpha := + fun t ↦ path (finiteSetTranslateEquiv s I t) + +@[simp] +theorem pullbackFiniteSetTranslate_apply {alpha : Type*} (s : NNReal) (I : Finset NNReal) + (path : finiteSetTranslate s I → alpha) (t : I) : + pullbackFiniteSetTranslate s I path t = path (finiteSetTranslateEquiv s I t) := + rfl + +theorem measurable_pullbackFiniteSetTranslate {alpha : Type*} [MeasurableSpace alpha] + (s : NNReal) (I : Finset NNReal) : + Measurable (pullbackFiniteSetTranslate (alpha := alpha) s I) := + measurable_pi_iff.mpr fun t ↦ measurable_pi_apply (finiteSetTranslateEquiv s I t) + +private def finiteSetTranslateFinOrderIso (s : NNReal) (I : Finset NNReal) : + Fin I.card ≃o Fin (finiteSetTranslate s I).card := + Fin.castOrderIso (by simp only [finiteSetTranslate, Finset.card_map]) + +private theorem finiteSetTimes_translate (s : NNReal) (I : Finset NNReal) : + (finiteSetTimes (finiteSetTranslate s I)).restrict + (finiteSetTranslateFinOrderIso s I).toOrderEmbedding = + (finiteSetTimes I).translate s := by + let e := (finiteSetTranslateFinOrderIso s I).toOrderEmbedding + have hcard : (finiteSetTranslate s I).card = I.card := by + simp only [finiteSetTranslate, Finset.card_map] + have hleft : + (fun i : Fin I.card ↦ finiteSetTimes (finiteSetTranslate s I) (e i)) = + (finiteSetTranslate s I).orderEmbOfFin hcard := by + apply Finset.orderEmbOfFin_unique hcard + · intro i + exact Finset.orderEmbOfFin_mem _ rfl (e i) + · exact (finiteSetTimes (finiteSetTranslate s I)).strictMono.comp e.strictMono + have hright : + (fun i : Fin I.card ↦ s + finiteSetTimes I i) = + (finiteSetTranslate s I).orderEmbOfFin hcard := by + apply Finset.orderEmbOfFin_unique hcard + · intro i + exact Finset.mem_map_of_mem (addLeftEmbedding s) + (Finset.orderEmbOfFin_mem I rfl i) + · intro i j hij + simpa only [add_comm] using add_lt_add_left ((finiteSetTimes I).strictMono hij) s + apply DFunLike.ext _ _ + intro i + exact congrFun (hleft.trans hright.symm) i + +private theorem pullback_orderedPathToFiniteSet {alpha : Type*} + (s : NNReal) (I : Finset NNReal) : + pullbackFiniteSetTranslate (alpha := alpha) s I ∘ + orderedPathToFiniteSet (α := alpha) (finiteSetTranslate s I) = + orderedPathToFiniteSet I ∘ FiniteOrderedTimes.restrictPath + (finiteSetTranslateFinOrderIso s I).toOrderEmbedding := by + funext path t + apply congrArg path + apply (finiteSetTimes (finiteSetTranslate s I)).injective + have hshifted : + finiteSetTimes (finiteSetTranslate s I) + (((finiteSetTranslate s I).orderIsoOfFin rfl).symm + (finiteSetTranslateEquiv s I t)) = + s + t := by + change (((finiteSetTranslate s I).orderIsoOfFin rfl + (((finiteSetTranslate s I).orderIsoOfFin rfl).symm + (finiteSetTranslateEquiv s I t)) : finiteSetTranslate s I) : NNReal) = s + t + rw [OrderIso.apply_symm_apply] + exact finiteSetTranslateEquiv_apply s I t + have htimes := congrArg + (fun times : FiniteOrderedTimes I.card ↦ + times ((I.orderIsoOfFin rfl).symm t)) + (finiteSetTimes_translate s I) + have horiginal : finiteSetTimes I ((I.orderIsoOfFin rfl).symm t) = t := by + change (((I.orderIsoOfFin rfl) ((I.orderIsoOfFin rfl).symm t) : I) : NNReal) = t + exact congrArg Subtype.val ((I.orderIsoOfFin rfl).apply_symm_apply t) + change finiteSetTimes (finiteSetTranslate s I) + ((finiteSetTranslateFinOrderIso s I).toOrderEmbedding + ((I.orderIsoOfFin rfl).symm t)) = + s + finiteSetTimes I ((I.orderIsoOfFin rfl).symm t) at htimes + rw [horiginal] at htimes + rw [hshifted] + exact htimes.symm + +namespace IsConservative + +variable {alpha : Type*} [MeasurableSpace alpha] + +/-- Translating a finite observation set is the same as evolving first for the translation +amount, after the translated coordinates are reindexed by their original times. -/ +theorem finiteSetKernel_map_pullback_translate + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (s : NNReal) (I : Finset NNReal) : + (finiteSetKernel P (finiteSetTranslate s I)).map + (pullbackFiniteSetTranslate (alpha := alpha) s I) = + (finiteSetKernel P I).comp (P s) := by + rw [finiteSetKernel_eq_map, finiteSetKernel_eq_map, ← Kernel.map_comp_right] + · rw [pullback_orderedPathToFiniteSet, Kernel.map_comp_right] + · rw [hP.finiteTimeKernel_map_restrictPath P + (finiteSetTimes (finiteSetTranslate s I)) + (finiteSetTranslateFinOrderIso s I).toOrderEmbedding, + finiteSetTimes_translate, hP.finiteTimeKernel_translate P s, + Kernel.map_comp] + · exact FiniteOrderedTimes.measurable_restrictPath + (finiteSetTranslateFinOrderIso s I).toOrderEmbedding + · exact measurable_orderedPathToFiniteSet I + · exact measurable_orderedPathToFiniteSet (finiteSetTranslate s I) + · exact measurable_pullbackFiniteSetTranslate s I + +end IsConservative + +end +end SubMarkovKernelSemigroup + +namespace DenseTime + +/-- Casting a translated finite dense-time set to physical time agrees with translating its +finite set of physical times. -/ +theorem map_castOrderEmbedding_addFinset (s : DenseTime) (I : Finset DenseTime) : + (addFinset s I).map castOrderEmbedding.toEmbedding = + SubMarkovKernelSemigroup.finiteSetTranslate (castOrderEmbedding s) + (I.map castOrderEmbedding.toEmbedding) := by + ext t + simp only [addFinset, SubMarkovKernelSemigroup.finiteSetTranslate, Finset.mem_map] + constructor + · rintro ⟨u, ⟨r, hrI, rfl⟩, rfl⟩ + exact ⟨castOrderEmbedding r, ⟨r, hrI, rfl⟩, (castOrderEmbedding_add s r).symm⟩ + · rintro ⟨u, ⟨r, hrI, hru⟩, hut⟩ + subst u + exact ⟨s + r, ⟨r, hrI, rfl⟩, (castOrderEmbedding_add s r).trans hut⟩ + +end DenseTime +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/Kernel.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/Kernel.lean new file mode 100644 index 0000000000..469a235ead --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/Kernel.lean @@ -0,0 +1,124 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +import Mathlib.Data.Fin.Tuple.Basic +import Mathlib.Probability.Kernel.Composition.CompProd + +/-! +# Finite-time kernels on strictly ordered time families + +A conservative sub-Markov kernel semigroup determines probability kernels on finite coordinate +spaces. The construction itself does not use a conservativity witness: it recursively samples the +first observation and then the relative tail. Conservativity is used only to prove that the +resulting kernels are Markov kernels. + +This file constructs finite-dimensional kernels only. It makes no path-space, projectivity, +conservativity, or stochastic-process existence claim beyond the explicitly stated results. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ProbabilityTheory + +namespace MarkovProcess + +/-- Prepending one coordinate to a finite coordinate path is measurable. -/ +theorem measurable_finCons {α : Type*} [MeasurableSpace α] {n : ℕ} : + Measurable (fun z : α × (Fin n → α) ↦ + @Fin.cons n (fun _ : Fin (n + 1) ↦ α) z.1 z.2) := by + rw [measurable_pi_iff] + intro i + refine Fin.cases ?_ (fun j ↦ ?_) i + · simpa only [Fin.cons_zero] using (measurable_fst : Measurable (Prod.fst : α × (Fin n → α) → α)) + · simpa only [Fin.cons_succ] using! + (measurable_pi_apply j).comp (measurable_snd : Measurable (Prod.snd : α × (Fin n → α) → _)) + +namespace SubMarkovKernelSemigroup + +variable {α : Type*} [MeasurableSpace α] + +/-- The finite-time kernel obtained by recursively sampling a strictly ordered family of times. -/ +noncomputable def finiteTimeKernel (P : SubMarkovKernelSemigroup α) : + {n : ℕ} → FiniteOrderedTimes n → Kernel α (Fin n → α) + | 0, _ => Kernel.const α (Measure.dirac (FiniteOrderedTimes.emptyPath α)) + | n + 1, times => + Kernel.mapOfMeasurable + (P (times 0) ⊗ₖ Kernel.prodMkLeft α (finiteTimeKernel P times.relativeTail)) + (fun z ↦ @Fin.cons n (fun _ : Fin (n + 1) ↦ α) z.1 z.2) measurable_finCons + +/-- At the empty time family, the finite-time kernel is the constant Dirac mass at the empty +path. -/ +@[simp] +theorem finiteTimeKernel_zero (P : SubMarkovKernelSemigroup α) + (times : FiniteOrderedTimes 0) : + finiteTimeKernel P times = + Kernel.const α (Measure.dirac (FiniteOrderedTimes.emptyPath α)) := + rfl + +/-- The successor finite-time kernel first samples at the first time, then samples the relative +tail from that state. -/ +@[simp] +theorem finiteTimeKernel_succ (P : SubMarkovKernelSemigroup α) {n : ℕ} + (times : FiniteOrderedTimes (n + 1)) : + finiteTimeKernel P times = + Kernel.mapOfMeasurable + (P (times 0) ⊗ₖ Kernel.prodMkLeft α (finiteTimeKernel P times.relativeTail)) + (fun z ↦ @Fin.cons n (fun _ : Fin (n + 1) ↦ α) z.1 z.2) + measurable_finCons := + rfl + +/-- Under conservativity, every finite-time kernel is a Markov kernel. -/ +theorem IsConservative.isMarkovKernel_finiteTimeKernel + (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) {n : ℕ} + (times : FiniteOrderedTimes n) : IsMarkovKernel (finiteTimeKernel P times) := by + induction n with + | zero => + rw [finiteTimeKernel_zero] + infer_instance + | succ n ih => + let : IsMarkovKernel (P (times 0)) := hP.isMarkovKernel (times 0) + let : IsMarkovKernel (finiteTimeKernel P times.relativeTail) := ih times.relativeTail + rw [finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map] + exact Kernel.IsMarkovKernel.map _ measurable_finCons + +/-- The finite-time law at a starting state. -/ +noncomputable def finiteTimeLaw (P : SubMarkovKernelSemigroup α) {n : ℕ} + (times : FiniteOrderedTimes n) (x : α) : Measure (Fin n → α) := + finiteTimeKernel P times x + +/-- Under conservativity, every finite-time law is a probability measure. -/ +theorem IsConservative.isProbabilityMeasure_finiteTimeLaw + (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) {n : ℕ} + (times : FiniteOrderedTimes n) (x : α) : IsProbabilityMeasure (finiteTimeLaw P times x) := by + let : IsMarkovKernel (finiteTimeKernel P times) := + hP.isMarkovKernel_finiteTimeKernel P times + exact IsMarkovKernel.isProbabilityMeasure x + +/-- The unique coordinate of a singleton finite-time kernel has transition kernel `P` at that +time. -/ +@[simp] +theorem finiteTimeKernel_one_map_eval (P : SubMarkovKernelSemigroup α) + (times : FiniteOrderedTimes 1) : + (finiteTimeKernel P times).map (fun path ↦ path 0) = P (times 0) := by + let : IsFiniteKernel (P (times 0)) := (P.isSubMarkovKernel (times 0)).isFiniteKernel + let : IsMarkovKernel (finiteTimeKernel P times.relativeTail) := + by rw [finiteTimeKernel_zero]; infer_instance + rw [finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map] + rw [← Kernel.map_comp_right] + · have hcomp : + ((fun path : Fin 1 → α ↦ path 0) ∘ + fun z : α × (Fin 0 → α) ↦ + @Fin.cons 0 (fun _ : Fin 1 ↦ α) z.1 z.2) = Prod.fst := by + funext z + rfl + rw [hcomp, ← Kernel.fst_eq] + exact Kernel.fst_compProd _ _ + · exact measurable_finCons + · exact measurable_pi_apply 0 + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean new file mode 100644 index 0000000000..af168de7b0 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean @@ -0,0 +1,429 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +import Mathlib.Probability.Kernel.Composition.Lemmas + +/-! +# Concatenating finite-time kernels at an ordered cut + +This file factors an ordered finite-dimensional transition law at a designated observation +time. The future factor is the finite-time kernel at the corresponding relative times, started +from the terminal coordinate of the past. This is finite-dimensional kernel infrastructure and +does not assert a path-space or conditional Markov theorem. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ProbabilityTheory + +namespace MarkovProcess + +/-- Reassociate the cardinality of a split finite path so recursion removes its first point +definitionally while the coordinate order remains past-then-future. -/ +def cutIndexOrderIso (m n : ℕ) : Fin ((m + 1) + n) ≃o Fin (n + (m + 1)) := + Fin.castOrderIso (Nat.add_comm (m + 1) n) + +namespace FiniteOrderedTimes + +/-- Restrict an ordered family to the coordinates at or before a designated cut. -/ +def initialSegment {m n : ℕ} + (times : FiniteOrderedTimes (n + (m + 1))) : FiniteOrderedTimes (m + 1) := + times.restrict ((Fin.castAddOrderEmb n).trans (cutIndexOrderIso m n).toOrderEmbedding) + +/-- Times after the cut, measured relative to the time at the cut. -/ +def relativeFinalSegment {m n : ℕ} + (times : FiniteOrderedTimes (n + (m + 1))) : FiniteOrderedTimes n := + OrderEmbedding.ofStrictMono + (fun i ↦ + times (cutIndexOrderIso m n (Fin.natAdd (m + 1) i)) - + times (cutIndexOrderIso m n (Fin.castAdd n (Fin.last m)))) + fun i j hij ↦ by + have hcut : + cutIndexOrderIso m n (Fin.castAdd n (Fin.last m)) ≤ + cutIndexOrderIso m n (Fin.natAdd (m + 1) i) := by + apply (cutIndexOrderIso m n).le_iff_le.mpr + apply Fin.mk_le_mk.mpr + change m ≤ m + 1 + i + omega + exact tsub_lt_tsub_right_of_le (times.monotone hcut) + (times.strictMono ((cutIndexOrderIso m n).strictMono + (Fin.natAddOrderEmb (m + 1) |>.strictMono hij))) + +@[simp] +theorem relativeFinalSegment_apply {m n : ℕ} + (times : FiniteOrderedTimes (n + (m + 1))) (i : Fin n) : + relativeFinalSegment times i = + times (cutIndexOrderIso m n (Fin.natAdd (m + 1) i)) - + times (cutIndexOrderIso m n (Fin.castAdd n (Fin.last m))) := + rfl + +end FiniteOrderedTimes + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [MeasurableSpace alpha] + +private theorem initialSegment_relativeTail {m n : ℕ} + (times : FiniteOrderedTimes (n + (m + 2))) : + FiniteOrderedTimes.initialSegment times.relativeTail = + (FiniteOrderedTimes.initialSegment times).relativeTail := by + apply DFunLike.ext _ _ + intro i + rfl + +private theorem relativeFinalSegment_relativeTail {m n : ℕ} + (times : FiniteOrderedTimes (n + (m + 2))) : + FiniteOrderedTimes.relativeFinalSegment times.relativeTail = + FiniteOrderedTimes.relativeFinalSegment times := by + apply DFunLike.ext _ _ + intro i + change + (times _ - times 0) - (times _ - times 0) = times _ - times _ + rw [tsub_tsub_tsub_cancel_right (times.monotone (Fin.zero_le _))] + apply congrArg₂ (· - ·) + · apply congrArg times + apply Fin.ext + simp [cutIndexOrderIso] + omega + · apply congrArg times + apply Fin.ext + simp [cutIndexOrderIso] + +/-- Separate a finite path into its coordinates at or before the cut and those after the cut. -/ +def splitFinitePath {m n : ℕ} (path : Fin (n + (m + 1)) → alpha) : + (Fin (m + 1) → alpha) × (Fin n → alpha) := + (fun i ↦ path (cutIndexOrderIso m n (Fin.castAdd n i)), + fun i ↦ path (cutIndexOrderIso m n (Fin.natAdd (m + 1) i))) + +/-- Splitting a finite path at a cut is measurable. -/ +theorem measurable_splitFinitePath {m n : ℕ} : + Measurable (splitFinitePath (alpha := alpha) (m := m) (n := n)) := by + apply Measurable.prodMk + · exact measurable_pi_iff.mpr fun i ↦ measurable_pi_apply + (cutIndexOrderIso m n (Fin.castAdd n i)) + · exact measurable_pi_iff.mpr fun i ↦ measurable_pi_apply + (cutIndexOrderIso m n (Fin.natAdd (m + 1) i)) + +omit [MeasurableSpace alpha] in +private theorem splitFinitePath_cons {m n : ℕ} + (z : alpha × (Fin (n + (m + 1)) → alpha)) : + splitFinitePath (m := m + 1) (n := n) (Fin.cons z.1 z.2) = + (Fin.cons z.1 (splitFinitePath (m := m) (n := n) z.2).1, + (splitFinitePath (m := m) (n := n) z.2).2) := by + apply Prod.ext + · funext i + refine Fin.cases ?_ (fun j ↦ ?_) i + · rfl + · simp only [splitFinitePath] + have hidx : + cutIndexOrderIso (m + 1) n (Fin.castAdd n j.succ) = + (cutIndexOrderIso m n (Fin.castAdd n j)).succ := by + apply Fin.ext + simp [cutIndexOrderIso] + rw [hidx, Fin.cons_succ, Fin.cons_succ] + · funext i + simp only [splitFinitePath] + have hidx : + cutIndexOrderIso (m + 1) n (Fin.natAdd (m + 1 + 1) i) = + (cutIndexOrderIso m n (Fin.natAdd (m + 1) i)).succ := by + apply Fin.ext + simp [cutIndexOrderIso] + omega + rw [hidx, Fin.cons_succ] + +/-- The terminal state of the first component of a split finite path. -/ +def splitPastTerminal {m : ℕ} + (z : alpha × (Fin (m + 1) → alpha)) : alpha := + z.2 (Fin.last m) + +/-- Reading the terminal past coordinate is measurable. -/ +theorem measurable_splitPastTerminal {m : ℕ} : + Measurable (splitPastTerminal (alpha := alpha) (m := m)) := + (measurable_pi_apply (Fin.last m)).comp measurable_snd + +/-- Measurable equivalence between a head/tail pair and a finite successor path. -/ +def finConsMeasurableEquiv (n : ℕ) : + alpha × (Fin n → alpha) ≃ᵐ (Fin (n + 1) → alpha) := + (MeasurableEquiv.piFinSuccAbove (fun _ : Fin (n + 1) ↦ alpha) 0).symm + +@[simp] +theorem finConsMeasurableEquiv_apply (n : ℕ) (z : alpha × (Fin n → alpha)) : + finConsMeasurableEquiv n z = Fin.cons z.1 z.2 := by + ext i + refine Fin.cases ?_ (fun j ↦ ?_) i + · rfl + · rfl + +@[simp] +theorem finConsMeasurableEquiv_symm_apply (n : ℕ) (path : Fin (n + 1) → alpha) : + (finConsMeasurableEquiv n).symm path = (path 0, Fin.tail path) := by + rfl + +private theorem measurable_headTail {n : ℕ} : + Measurable (fun path : Fin (n + 1) → alpha ↦ (path 0, Fin.tail path)) := by + apply Measurable.prodMk (measurable_pi_apply 0) + exact measurable_pi_iff.mpr fun i ↦ measurable_pi_apply i.succ + +omit [MeasurableSpace alpha] in +private theorem headTail_finCons {n : ℕ} (z : alpha × (Fin n → alpha)) : + ((fun path : Fin (n + 1) → alpha ↦ (path 0, Fin.tail path)) + (@Fin.cons n (fun _ ↦ alpha) z.1 z.2)) = z := by + apply Prod.ext + · rfl + · funext i + rfl + +private theorem compProd_map_left_equiv + {X A B C : Type*} [MeasurableSpace X] [MeasurableSpace A] + [MeasurableSpace B] [MeasurableSpace C] + (kappa : Kernel X A) [IsSFiniteKernel kappa] + (eta : Kernel (X × A) B) [IsSFiniteKernel eta] + (E : A ≃ᵐ C) : + (kappa ⊗ₖ eta).map (Prod.map E id) = + kappa.map E ⊗ₖ eta.comap + (fun z : X × C ↦ (z.1, E.symm z.2)) + (measurable_fst.prodMk (E.symm.measurable.comp measurable_snd)) := by + ext x s hs + rw [Kernel.map_apply' _ (E.measurable.prodMap measurable_id) x hs, + Kernel.compProd_apply (hs.preimage (E.measurable.prodMap measurable_id)), + Kernel.compProd_apply hs] + rw [Kernel.map_apply kappa E.measurable x] + rw [MeasureTheory.lintegral_map] + · congr with a + rw [Kernel.comap_apply] + change eta (x, a) (Prod.mk (E a) ⁻¹' s) = _ + rw [E.symm_apply_apply] + · exact ProbabilityTheory.Kernel.measurable_kernel_prodMk_left' hs x + · exact E.measurable + +private theorem map_compProd_prodMkLeft_right + {X A B C : Type*} [MeasurableSpace X] [MeasurableSpace A] + [MeasurableSpace B] [MeasurableSpace C] + (kappa : Kernel X A) [IsSFiniteKernel kappa] + (eta : Kernel A B) [IsSFiniteKernel eta] + (f : B → C) (hf : Measurable f) : + (kappa ⊗ₖ Kernel.prodMkLeft X eta).map + (fun z ↦ (z.1, f z.2)) = + kappa ⊗ₖ Kernel.prodMkLeft X (eta.map f) := by + have hpair : Measurable (fun z : A × B ↦ (z.1, f z.2)) := + measurable_fst.prodMk (hf.comp measurable_snd) + ext x s hs + rw [Kernel.map_apply' _ hpair x hs, + Kernel.compProd_apply (hs.preimage hpair), Kernel.compProd_apply hs] + congr with a + rw [Kernel.prodMkLeft_apply', Kernel.prodMkLeft_apply', + Kernel.map_apply' _ hf _ (measurable_prodMk_left hs)] + rfl + +private theorem compProd_prodMkLeft_assoc + {X A B C : Type*} [MeasurableSpace X] [MeasurableSpace A] + [MeasurableSpace B] [MeasurableSpace C] + (kappa : Kernel X A) [IsSFiniteKernel kappa] + (eta : Kernel A B) [IsSFiniteKernel eta] + (xi : Kernel (A × B) C) [IsSFiniteKernel xi] : + (kappa ⊗ₖ Kernel.prodMkLeft X (eta ⊗ₖ xi)).map + MeasurableEquiv.prodAssoc.symm = + (kappa ⊗ₖ Kernel.prodMkLeft X eta) ⊗ₖ + xi.comap (fun z : X × (A × B) ↦ z.2) + measurable_snd := by + let xiLift : Kernel (X × (A × B)) C := + xi.comap (fun z : X × (A × B) ↦ z.2) measurable_snd + have hinner : + Kernel.prodMkLeft X (eta ⊗ₖ xi) = + Kernel.prodMkLeft X eta ⊗ₖ + xiLift.comap MeasurableEquiv.prodAssoc + MeasurableEquiv.prodAssoc.measurable := by + ext z s hs + rw [Kernel.prodMkLeft_apply', Kernel.compProd_apply hs] + rw [Kernel.compProd_apply hs] + congr with b + rw [hinner] + simpa only [xiLift] using + (Kernel.compProd_assoc (κ := kappa) (η := Kernel.prodMkLeft X eta) + (ξ := xiLift)) + +/-- Splitting the finite-time kernel after its first observation recovers exactly the recursive +transition-kernel product used in its construction. -/ +theorem finiteTimeKernel_map_headTail (P : SubMarkovKernelSemigroup alpha) {n : ℕ} + (times : FiniteOrderedTimes (n + 1)) : + (finiteTimeKernel P times).map + (fun path ↦ (path 0, Fin.tail path)) = + P (times 0) ⊗ₖ Kernel.prodMkLeft alpha + (finiteTimeKernel P times.relativeTail) := by + rw [finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map, ← Kernel.map_comp_right] + · have hcomp : + (fun path : Fin (n + 1) → alpha ↦ (path 0, Fin.tail path)) ∘ + (fun z : alpha × (Fin n → alpha) ↦ + @Fin.cons n (fun _ ↦ alpha) z.1 z.2) = id := by + funext z + exact headTail_finCons z + rw [hcomp, Kernel.map_id] + · exact measurable_pi_iff.mpr fun i ↦ Fin.cases measurable_fst + (fun j ↦ (measurable_pi_apply j).comp measurable_snd) i + · exact measurable_headTail + +private theorem finiteTimeKernel_one_eq_map (P : SubMarkovKernelSemigroup alpha) + (times : FiniteOrderedTimes 1) : + finiteTimeKernel P times = + (P (times 0)).map (fun x ↦ fun _ : Fin 1 ↦ x) := by + calc + finiteTimeKernel P times = + ((finiteTimeKernel P times).map (fun path ↦ path 0)).map + (fun x ↦ fun _ : Fin 1 ↦ x) := by + rw [← Kernel.map_comp_right] + · have hcomp : + (fun x : alpha ↦ fun _ : Fin 1 ↦ x) ∘ + (fun path : Fin 1 → alpha ↦ path 0) = id := by + funext path + funext i + exact Fin.eq_zero i ▸ rfl + rw [hcomp, Kernel.map_id] + · exact measurable_pi_apply 0 + · exact measurable_pi_iff.mpr fun _ ↦ measurable_id + _ = (P (times 0)).map (fun x ↦ fun _ : Fin 1 ↦ x) := by + rw [finiteTimeKernel_one_map_eval] + +namespace IsConservative + +private theorem finiteTimeKernel_map_splitFinitePath_zero + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (n : ℕ) (times : FiniteOrderedTimes (n + 1)) : + (finiteTimeKernel P times).map + (splitFinitePath (alpha := alpha) (m := 0) (n := n)) = + finiteTimeKernel P (FiniteOrderedTimes.initialSegment times) ⊗ₖ + (finiteTimeKernel P (FiniteOrderedTimes.relativeFinalSegment times)).comap + (splitPastTerminal (alpha := alpha) (m := 0)) + measurable_splitPastTerminal := by + let E : alpha ≃ᵐ (Fin 1 → alpha) := + (MeasurableEquiv.piUnique (fun _ : Fin 1 ↦ alpha)).symm + have hE (x : alpha) : E x = fun _ : Fin 1 ↦ x := by + funext i + exact Fin.eq_zero i ▸ rfl + have hfuture : + FiniteOrderedTimes.relativeFinalSegment times = times.relativeTail := by + apply DFunLike.ext _ _ + intro i + change times _ - times _ = times _ - times _ + apply congrArg₂ (· - ·) <;> apply congrArg times <;> apply Fin.ext <;> + simp [cutIndexOrderIso] + have hsplit : + splitFinitePath (alpha := alpha) (m := 0) (n := n) = + Prod.map E id ∘ + (fun path : Fin (n + 1) → alpha ↦ (path 0, Fin.tail path)) := by + funext path + apply Prod.ext + · funext i + change path _ = E (path 0) i + rw [hE] + have hi : i = 0 := Fin.eq_zero i + subst i + congr 1 + · funext i + change path _ = path i.succ + congr 1 + apply Fin.ext + simp [cutIndexOrderIso] + let : IsMarkovKernel (finiteTimeKernel P times.relativeTail) := + hP.isMarkovKernel_finiteTimeKernel P times.relativeTail + let : IsMarkovKernel (P (times 0)) := hP.isMarkovKernel (times 0) + rw [hsplit, Kernel.map_comp_right _ measurable_headTail + (E.measurable.prodMap measurable_id), finiteTimeKernel_map_headTail] + rw [compProd_map_left_equiv] + rw [finiteTimeKernel_one_eq_map, hfuture] + congr 1 + +/-- Splitting an ordered finite-dimensional law at a cut factors it into its past law and the +relative future law started from the terminal state of that past. -/ +theorem finiteTimeKernel_map_splitFinitePath + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (m n : ℕ) (times : FiniteOrderedTimes (n + (m + 1))) : + (finiteTimeKernel P times).map + (splitFinitePath (alpha := alpha) (m := m) (n := n)) = + finiteTimeKernel P (FiniteOrderedTimes.initialSegment times) ⊗ₖ + (finiteTimeKernel P (FiniteOrderedTimes.relativeFinalSegment times)).comap + (splitPastTerminal (alpha := alpha) (m := m)) + measurable_splitPastTerminal := by + induction m with + | zero => exact finiteTimeKernel_map_splitFinitePath_zero P hP n times + | succ m ih => + let E := finConsMeasurableEquiv (alpha := alpha) (m + 1) + let g : alpha × ((Fin (m + 1) → alpha) × (Fin n → alpha)) → + (Fin (m + 2) → alpha) × (Fin n → alpha) := + fun z ↦ (Fin.cons z.1 z.2.1, z.2.2) + have hg : Measurable g := by + apply Measurable.prodMk + · rw [measurable_pi_iff] + intro i + refine Fin.cases measurable_fst (fun j ↦ ?_) i + exact (measurable_pi_apply j).comp (measurable_fst.comp measurable_snd) + · exact measurable_snd.comp measurable_snd + let f : alpha × (Fin (n + (m + 1)) → alpha) → + alpha × ((Fin (m + 1) → alpha) × (Fin n → alpha)) := + fun z ↦ (z.1, splitFinitePath (m := m) (n := n) z.2) + have hf : Measurable f := + measurable_fst.prodMk (measurable_splitFinitePath.comp measurable_snd) + have hcomp : + splitFinitePath (alpha := alpha) (m := m + 1) (n := n) ∘ + (fun z : alpha × (Fin (n + (m + 1)) → alpha) ↦ + Fin.cons z.1 z.2) = + g ∘ f := by + funext z + exact splitFinitePath_cons z + let : IsMarkovKernel (P (times 0)) := hP.isMarkovKernel (times 0) + let : IsMarkovKernel (finiteTimeKernel P times.relativeTail) := + hP.isMarkovKernel_finiteTimeKernel P times.relativeTail + let : IsMarkovKernel + (finiteTimeKernel P (FiniteOrderedTimes.initialSegment times.relativeTail)) := + hP.isMarkovKernel_finiteTimeKernel P _ + let : IsMarkovKernel + (finiteTimeKernel P (FiniteOrderedTimes.relativeFinalSegment times.relativeTail)) := + hP.isMarkovKernel_finiteTimeKernel P _ + rw [finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map, + ← Kernel.map_comp_right] + · refine (congrArg (fun f ↦ + (P (times 0) ⊗ₖ Kernel.prodMkLeft alpha + (finiteTimeKernel P times.relativeTail)).map f) hcomp).trans ?_ + rw [Kernel.map_comp_right _ hf hg] + have hsplitMap : + (P (times 0) ⊗ₖ Kernel.prodMkLeft alpha + (finiteTimeKernel P times.relativeTail)).map f = + P (times 0) ⊗ₖ Kernel.prodMkLeft alpha + ((finiteTimeKernel P times.relativeTail).map + (splitFinitePath (alpha := alpha) (m := m) (n := n))) := by + simpa only [f] using! map_compProd_prodMkLeft_right + (P (times 0)) (finiteTimeKernel P times.relativeTail) + (splitFinitePath (alpha := alpha) (m := m) (n := n)) + measurable_splitFinitePath + refine (congrArg (fun K ↦ K.map g) hsplitMap).trans ?_ + rw [ih times.relativeTail] + have hg_assoc : g = Prod.map E id ∘ MeasurableEquiv.prodAssoc.symm := by + funext z + apply Prod.ext + · funext i + refine Fin.cases ?_ (fun j ↦ ?_) i <;> rfl + · rfl + rw [hg_assoc, Kernel.map_comp_right _ + MeasurableEquiv.prodAssoc.symm.measurable + (E.measurable.prodMap measurable_id)] + rw [compProd_prodMkLeft_assoc] + rw [compProd_map_left_equiv] + rw [initialSegment_relativeTail, relativeFinalSegment_relativeTail] + congr 1 + have hEfun : (E : alpha × (Fin (m + 1) → alpha) → + Fin (m + 2) → alpha) = fun z ↦ Fin.cons z.1 z.2 := by + funext z i + refine Fin.cases ?_ (fun j ↦ ?_) i <;> rfl + rw [hEfun, ← Kernel.mapOfMeasurable_eq_map] + exact (finiteTimeKernel_succ P + (FiniteOrderedTimes.initialSegment times)).symm + · exact measurable_pi_iff.mpr fun i ↦ Fin.cases measurable_fst + (fun j ↦ (measurable_pi_apply j).comp measurable_snd) i + · exact measurable_splitFinitePath + + +end IsConservative + +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelDeletion.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelDeletion.lean new file mode 100644 index 0000000000..d2ef4c0a9a --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelDeletion.lean @@ -0,0 +1,169 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift +import Mathlib.Probability.Kernel.Composition.KernelLemmas + +/-! +# Deleting one coordinate from a finite-time kernel + +For a conservative sub-Markov kernel semigroup, removing one observation from a finite-time law +gives the law on the remaining ordered times. This is finite-dimensional kernel infrastructure; +it does not construct a path-space law or a stochastic process. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ProbabilityTheory + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +variable {α : Type*} [MeasurableSpace α] + +private theorem measurable_removeNth {n : ℕ} (p : Fin (n + 1)) : + Measurable (Fin.removeNth p : (Fin (n + 1) → α) → Fin n → α) := + FiniteOrderedTimes.measurable_restrictPath (Fin.succAboveOrderEmb p) + +private theorem map_compProd_prodMkLeft_right + {X Y Z W : Type*} [MeasurableSpace X] [MeasurableSpace Y] + [MeasurableSpace Z] [MeasurableSpace W] + (κ : Kernel X Y) (η : Kernel Y Z) [IsSFiniteKernel κ] [IsSFiniteKernel η] + (f : Z → W) (hf : Measurable f) : + (κ ⊗ₖ Kernel.prodMkLeft X η).map (fun z ↦ (z.1, f z.2)) = + κ ⊗ₖ Kernel.prodMkLeft X (η.map f) := by + have hpair : Measurable (fun z : Y × Z ↦ (z.1, f z.2)) := + measurable_fst.prodMk (hf.comp measurable_snd) + ext x s hs + rw [Kernel.map_apply' _ hpair x hs, + Kernel.compProd_apply (hs.preimage hpair), Kernel.compProd_apply hs] + congr with y + have hsection : MeasurableSet (Prod.mk y ⁻¹' s) := measurable_prodMk_left hs + rw [Kernel.prodMkLeft_apply', Kernel.prodMkLeft_apply', + Kernel.map_apply' _ hf _ hsection] + rfl + +omit [MeasurableSpace α] in +private theorem removeNth_zero_cons {n : ℕ} (z : α × (Fin n → α)) : + Fin.removeNth 0 (@Fin.cons n (fun _ ↦ α) z.1 z.2) = z.2 := by + ext i + rfl + +omit [MeasurableSpace α] in +private theorem removeNth_succ_cons {n : ℕ} (p : Fin (n + 1)) + (z : α × (Fin (n + 1) → α)) : + Fin.removeNth p.succ (@Fin.cons (n + 1) (fun _ ↦ α) z.1 z.2) = + @Fin.cons n (fun _ ↦ α) z.1 (Fin.removeNth p z.2) := by + ext i + refine Fin.cases ?_ (fun j ↦ ?_) i + · rfl + · simp only [Fin.removeNth_apply, Fin.cons_succ] + rw [Fin.succ_succAbove_succ] + rfl + +private theorem translate_relativeTail_eq_restrict_zero {n : ℕ} + (times : FiniteOrderedTimes (n + 1)) : + times.relativeTail.translate (times 0) = + times.restrict (Fin.succAboveOrderEmb 0) := by + apply DFunLike.ext _ _ + intro i + rw [FiniteOrderedTimes.translate_apply, FiniteOrderedTimes.restrict_apply, + Fin.succAboveOrderEmb_apply, Fin.succAbove_zero_apply] + exact FiniteOrderedTimes.add_relativeTail times i + +private theorem relativeTail_restrict_succ {n : ℕ} (times : FiniteOrderedTimes (n + 2)) + (p : Fin (n + 1)) : + (times.restrict (Fin.succAboveOrderEmb p.succ)).relativeTail = + times.relativeTail.restrict (Fin.succAboveOrderEmb p) := by + apply DFunLike.ext _ _ + intro i + simp only [FiniteOrderedTimes.relativeTail_apply, FiniteOrderedTimes.restrict_apply, + Fin.succAboveOrderEmb_apply] + rw [Fin.succ_succAbove_succ, Fin.succ_succAbove_zero] + +namespace IsConservative + +/-- Removing one coordinate from a conservative finite-time kernel gives the kernel on the +remaining ordered times. -/ +theorem finiteTimeKernel_map_removeNth (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) {n : ℕ} (times : FiniteOrderedTimes (n + 1)) + (p : Fin (n + 1)) : + (finiteTimeKernel P times).map (Fin.removeNth p) = + finiteTimeKernel P (times.restrict (Fin.succAboveOrderEmb p)) := by + induction n with + | zero => + have hp : p = 0 := Fin.eq_zero p + subst p + let : IsFiniteKernel (P (times 0)) := + (P.isSubMarkovKernel (times 0)).isFiniteKernel + let : IsMarkovKernel (finiteTimeKernel P times.relativeTail) := + hP.isMarkovKernel_finiteTimeKernel P times.relativeTail + rw [finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map, ← Kernel.map_comp_right] + · rw [show (Fin.removeNth 0 ∘ fun z : α × (Fin 0 → α) ↦ + @Fin.cons 0 (fun _ ↦ α) z.1 z.2) = Prod.snd by + funext z + exact removeNth_zero_cons z] + rw [← Kernel.snd_eq, Kernel.snd_compProd_prodMkLeft, + ← hP.finiteTimeKernel_translate, translate_relativeTail_eq_restrict_zero] + · exact measurable_finCons + · exact measurable_removeNth 0 + | succ n ih => + refine Fin.cases ?_ (fun p ↦ ?_) p + · let : IsFiniteKernel (P (times 0)) := + (P.isSubMarkovKernel (times 0)).isFiniteKernel + let : IsMarkovKernel (finiteTimeKernel P times.relativeTail) := + hP.isMarkovKernel_finiteTimeKernel P times.relativeTail + rw [finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map, ← Kernel.map_comp_right] + · rw [show (Fin.removeNth 0 ∘ fun z : α × (Fin (n + 1) → α) ↦ + @Fin.cons (n + 1) (fun _ ↦ α) z.1 z.2) = Prod.snd by + funext z + exact removeNth_zero_cons z] + rw [← Kernel.snd_eq, Kernel.snd_compProd_prodMkLeft, + ← hP.finiteTimeKernel_translate, translate_relativeTail_eq_restrict_zero] + · exact measurable_finCons + · exact measurable_removeNth 0 + · let : IsFiniteKernel (P (times 0)) := + (P.isSubMarkovKernel (times 0)).isFiniteKernel + let : IsMarkovKernel (finiteTimeKernel P times.relativeTail) := + hP.isMarkovKernel_finiteTimeKernel P times.relativeTail + rw [finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map, ← Kernel.map_comp_right] + · rw [show (Fin.removeNth p.succ ∘ fun z : α × (Fin (n + 1) → α) ↦ + @Fin.cons (n + 1) (fun _ ↦ α) z.1 z.2) = + (fun z : α × (Fin (n + 1) → α) ↦ + @Fin.cons n (fun _ ↦ α) z.1 (Fin.removeNth p z.2)) by + funext z + exact removeNth_succ_cons p z] + rw [show (fun z : α × (Fin (n + 1) → α) ↦ + @Fin.cons n (fun _ ↦ α) z.1 (Fin.removeNth p z.2)) = + (fun z : α × (Fin n → α) ↦ + @Fin.cons n (fun _ ↦ α) z.1 z.2) ∘ + (fun z : α × (Fin (n + 1) → α) ↦ + (z.1, Fin.removeNth p z.2)) by rfl] + have hremovePair : Measurable (fun z : α × (Fin (n + 1) → α) ↦ + (z.1, Fin.removeNth p z.2)) := + measurable_fst.prodMk ((measurable_removeNth p).comp measurable_snd) + have hcons : Measurable (fun z : α × (Fin n → α) ↦ + @Fin.cons n (fun _ ↦ α) z.1 z.2) := measurable_finCons + have hhead : (times.restrict (Fin.succAboveOrderEmb p.succ)) 0 = times 0 := by + rw [FiniteOrderedTimes.restrict_apply, Fin.succAboveOrderEmb_apply, + Fin.succ_succAbove_zero] + rw [Kernel.map_comp_right _ hremovePair hcons, + map_compProd_prodMkLeft_right _ _ _ (measurable_removeNth p), + ih times.relativeTail p, finiteTimeKernel_succ, + Kernel.mapOfMeasurable_eq_map, relativeTail_restrict_succ, hhead] + · exact measurable_finCons + · exact measurable_removeNth p.succ + +/-- The deletion theorem in the common path-restriction notation. -/ +theorem finiteTimeKernel_map_restrictPath_succAbove (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) {n : ℕ} (times : FiniteOrderedTimes (n + 1)) + (p : Fin (n + 1)) : + (finiteTimeKernel P times).map + (FiniteOrderedTimes.restrictPath (Fin.succAboveOrderEmb p)) = + finiteTimeKernel P (times.restrict (Fin.succAboveOrderEmb p)) := + hP.finiteTimeKernel_map_removeNth P times p + +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelEquivariance.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelEquivariance.lean new file mode 100644 index 0000000000..7e9fc27020 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelEquivariance.lean @@ -0,0 +1,306 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments +import Mathlib.MeasureTheory.Constructions.BorelSpace.Basic +import Mathlib.MeasureTheory.Function.SpecialFunctions.Basic + +/-! +# Rescaled conjugation of finite-time kernels + +A sub-Markov kernel semigroup `P'` on a state space `beta` is the *rescaled conjugate* of `P` on +`alpha` when it is obtained from `P` by conjugating the state with a homeomorphism `e : alpha ≃ₜ beta` +and speeding time up by a positive factor `c`, that is `P' t x = ((P (c * t)) (e.symm x)).map e`. + +This file transfers the finite-dimensional laws across such a relation. The main result is +`SubMarkovKernelSemigroup.IsRescaledConjugate.finiteTimeKernel_eq`, which computes every +finite-time kernel of `P'` from the finite-time kernel of `P` at the rescaled times. Supporting +API: the time-scaling operation `FiniteOrderedTimes.rescale`, the coordinatewise state map +`FiniteOrderedTimes.mapPath`, and two composition-product lemmas, `comap_compProd_prodMkLeft` and +`map_compProd_prodMkLeft_conjugate`, which have no direct Mathlib counterpart. + +Nothing here mentions path space; the path-space equivariance statement is in +`MarkovProcess/Trajectory/Equivariance.lean`. When the state map is an isometry, the intrinsic +Kolmogorov moment criterion also transfers, with the constant multiplied by `c ^ q` +(`IsRescaledConjugate.hasKolmogorovMoments`). +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal ProbabilityTheory + +namespace MarkovProcess + +namespace FiniteOrderedTimes + +/-- Multiply every time of a finite ordered family by a fixed positive factor. Positivity of the +factor is what keeps the family strictly increasing. -/ +def rescale {n : ℕ} (c : NNReal) (hc : 0 < c) (times : FiniteOrderedTimes n) : + FiniteOrderedTimes n := + OrderEmbedding.ofStrictMono (fun i ↦ c * times i) fun _ _ hij ↦ + mul_lt_mul_of_pos_left (times.strictMono hij) hc + +/-- Rescaled times, evaluated. -/ +@[simp] +theorem rescale_apply {n : ℕ} (c : NNReal) (hc : 0 < c) (times : FiniteOrderedTimes n) + (i : Fin n) : times.rescale c hc i = c * times i := + rfl + +/-- Rescaling by the factor one does not change a finite ordered time family. -/ +@[simp] +theorem rescale_one {n : ℕ} (times : FiniteOrderedTimes n) : + times.rescale 1 one_pos = times := by + apply DFunLike.ext _ _ + intro i + exact one_mul (times i) + +/-- Successive rescalings combine by multiplication. -/ +theorem rescale_rescale {n : ℕ} (c d : NNReal) (hc : 0 < c) (hd : 0 < d) + (times : FiniteOrderedTimes n) : + (times.rescale d hd).rescale c hc = times.rescale (c * d) (mul_pos hc hd) := by + apply DFunLike.ext _ _ + intro i + exact (mul_assoc c d (times i)).symm + +/-- Rescaling commutes with passing to the relative tail: subtracting the first time and then +scaling is the same as scaling and then subtracting the scaled first time. -/ +@[simp] +theorem relativeTail_rescale {n : ℕ} (c : NNReal) (hc : 0 < c) + (times : FiniteOrderedTimes (n + 1)) : + (times.rescale c hc).relativeTail = times.relativeTail.rescale c hc := by + apply DFunLike.ext _ _ + intro i + simp only [relativeTail_apply, rescale_apply] + exact (mul_tsub c (times i.succ) (times 0)).symm + +/-- Apply a map of the state space to every coordinate of a coordinate path. -/ +def mapPath {ι alpha beta : Type*} (e : alpha → beta) (path : ι → alpha) : ι → beta := + fun i ↦ e (path i) + +/-- A path mapped coordinatewise, evaluated. -/ +@[simp] +theorem mapPath_apply {ι alpha beta : Type*} (e : alpha → beta) (path : ι → alpha) (i : ι) : + mapPath e path i = e (path i) := + rfl + +/-- The coordinatewise state map is measurable when the state map is. -/ +theorem measurable_mapPath {ι alpha beta : Type*} [MeasurableSpace alpha] [MeasurableSpace beta] + {e : alpha → beta} (he : Measurable e) : + Measurable (mapPath e : (ι → alpha) → ι → beta) := + measurable_pi_iff.mpr fun i ↦ he.comp (measurable_pi_apply i) + +/-- The coordinatewise state map commutes with restriction along an embedding of index sets. -/ +theorem mapPath_comp_restrictPath {m n : ℕ} (d : Fin m ↪o Fin n) {alpha beta : Type*} + (e : alpha → beta) : + mapPath e ∘ (restrictPath d : (Fin n → alpha) → Fin m → alpha) = + restrictPath d ∘ mapPath e := + rfl + +/-- Prepending a state to a finite path commutes with the coordinatewise state map. -/ +theorem mapPath_finCons {n : ℕ} {alpha beta : Type*} (e : alpha → beta) + (z : alpha × (Fin n → alpha)) : + mapPath e (@Fin.cons n (fun _ : Fin (n + 1) ↦ alpha) z.1 z.2) = + @Fin.cons n (fun _ : Fin (n + 1) ↦ beta) (e z.1) (mapPath e z.2) := by + funext i + refine Fin.cases ?_ (fun j ↦ ?_) i + · rfl + · rfl + +end FiniteOrderedTimes + +namespace SubMarkovKernelSemigroup + +/-- The increasing enumeration of a finite set of times, read at the position of one of its +elements, returns that element. -/ +theorem finiteSetTimes_orderIsoOfFin_symm_apply (I : Finset NNReal) (t : I) : + finiteSetTimes I ((I.orderIsoOfFin rfl).symm t) = (t : NNReal) := by + show I.orderEmbOfFin rfl ((I.orderIsoOfFin rfl).symm t) = (t : NNReal) + rw [← Finset.coe_orderIsoOfFin_apply, OrderIso.apply_symm_apply] + +section CompProd + +variable {X X' Y Y' Z Z' : Type*} [MeasurableSpace X] [MeasurableSpace X'] [MeasurableSpace Y] + [MeasurableSpace Y'] [MeasurableSpace Z] [MeasurableSpace Z'] + +/-- Pulling the source of a composition-product back along a measurable map only affects the first +factor, because a `prodMkLeft` second factor does not read the source. -/ +theorem comap_compProd_prodMkLeft (kappa : Kernel X Y) [IsSFiniteKernel kappa] + (eta : Kernel Y Z) [IsSFiniteKernel eta] {g : X' → X} (hg : Measurable g) : + Kernel.comap (kappa ⊗ₖ Kernel.prodMkLeft X eta) g hg = + (Kernel.comap kappa g hg) ⊗ₖ Kernel.prodMkLeft X' eta := by + ext x s hs + rw [Kernel.comap_apply', Kernel.compProd_apply hs, Kernel.compProd_apply hs] + simp only [Kernel.prodMkLeft_apply, Kernel.comap_apply] + +/-- Relabelling a composition-product coordinatewise. Relabelling the first coordinate by an +invertible measurable map `f` and the second by a measurable map `g` gives the composition-product +of the relabelled factors, the second factor being read at the `f`-preimage of its new index. -/ +theorem map_compProd_prodMkLeft_conjugate (kappa : Kernel X Y) [IsSFiniteKernel kappa] + (eta : Kernel Y Z) [IsSFiniteKernel eta] {f : Y → Y'} {f' : Y' → Y} + (hf : Measurable f) (hf' : Measurable f') (hleft : Function.LeftInverse f' f) + (hright : Function.RightInverse f' f) {g : Z → Z'} (hg : Measurable g) : + (kappa ⊗ₖ Kernel.prodMkLeft X eta).map (fun z ↦ (f z.1, g z.2)) = + (kappa.map f) ⊗ₖ Kernel.prodMkLeft X ((Kernel.comap eta f' hf').map g) := by + set F : Y ≃ᵐ Y' := + { toEquiv := ⟨f, f', hleft, hright⟩ + measurable_toFun := hf + measurable_invFun := hf' } with hF + have hpair : Measurable (fun z : Y × Z ↦ (f z.1, g z.2)) := + (hf.comp measurable_fst).prodMk (hg.comp measurable_snd) + ext x s hs + rw [Kernel.map_apply' _ hpair x hs, Kernel.compProd_apply (hs.preimage hpair), + Kernel.compProd_apply hs, Kernel.map_apply _ hf, + show (kappa x).map f = (kappa x).map (F : Y → Y') from rfl, + MeasureTheory.lintegral_map_equiv _ F] + refine lintegral_congr fun y ↦ ?_ + have hsection : MeasurableSet (Prod.mk (f y) ⁻¹' s) := measurable_prodMk_left hs + show eta y (Prod.mk y ⁻¹' ((fun z : Y × Z ↦ (f z.1, g z.2)) ⁻¹' s)) = + ((Kernel.comap eta f' hf').map g) (f y) (Prod.mk (f y) ⁻¹' s) + rw [Kernel.map_apply' _ hg _ hsection, Kernel.comap_apply, hleft y] + rfl + +end CompProd + +section RescaledConjugate + +variable {alpha beta : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [TopologicalSpace beta] [MeasurableSpace beta] [BorelSpace beta] + +/-- `P'` is the *rescaled conjugate* of `P` by the homeomorphism `e` and the time factor `c`: +started at `x`, the state of `P'` at time `t` is the image under `e` of the state of `P` at the +sped-up time `c * t` started at `e.symm x`. -/ +def IsRescaledConjugate (P : SubMarkovKernelSemigroup alpha) (P' : SubMarkovKernelSemigroup beta) + (e : alpha ≃ₜ beta) + (c : NNReal) : Prop := + ∀ t x, P' t x = ((P (c * t)) (e.symm x)).map e + +namespace IsRescaledConjugate + +variable {P : SubMarkovKernelSemigroup alpha} {P' : SubMarkovKernelSemigroup beta} {e : alpha ≃ₜ beta} + {c : NNReal} + +/-- The rescaled-conjugacy relation in kernel form: at every time the transition kernel of `P'` is +the transition kernel of `P` at the sped-up time, conjugated by `e`. -/ +theorem kernel_eq (h : IsRescaledConjugate P P' e c) (t : NNReal) : + P' t = (Kernel.comap (P (c * t)) e.symm e.symm.measurable).map e := by + refine Kernel.ext fun x ↦ ?_ + rw [Kernel.map_apply _ e.measurable, Kernel.comap_apply] + exact h t x + +/-- Conservativity transfers across rescaled conjugacy: no mass is lost by conjugating with a +homeomorphism and speeding up time. -/ +theorem isConservative (h : IsRescaledConjugate P P' e c) (hP : P.IsConservative) : + P'.IsConservative := by + intro t x + rw [h t x, Measure.map_apply e.measurable MeasurableSet.univ, Set.preimage_univ] + exact hP (c * t) (e.symm x) + +/-- **Finite-dimensional transfer.** Every finite-time kernel of the rescaled conjugate `P'` is +the finite-time kernel of `P` at the rescaled times, started from the `e`-preimage of the initial +state and read through `e` in every coordinate. -/ +theorem finiteTimeKernel_eq (h : IsRescaledConjugate P P' e c) (hc : 0 < c) + (hP : P.IsConservative) : + ∀ {n : ℕ} (times : FiniteOrderedTimes n), + finiteTimeKernel P' times = + (Kernel.comap (finiteTimeKernel P (times.rescale c hc)) e.symm + e.symm.measurable).map (FiniteOrderedTimes.mapPath e) := by + intro n + induction n with + | zero => + intro times + refine Kernel.ext fun x ↦ ?_ + simp only [finiteTimeKernel_zero] + rw [Kernel.map_apply _ (FiniteOrderedTimes.measurable_mapPath (ι := Fin 0) e.measurable), + Kernel.comap_apply, Kernel.const_apply, Kernel.const_apply, + Measure.map_dirac (FiniteOrderedTimes.emptyPath alpha)] + congr 1 + exact Subsingleton.elim _ _ + | succ n ih => + intro times + let : IsFiniteKernel (P (c * times 0)) := + (P.isSubMarkovKernel (c * times 0)).isFiniteKernel + let : IsMarkovKernel (finiteTimeKernel P (times.relativeTail.rescale c hc)) := + hP.isMarkovKernel_finiteTimeKernel P (times.relativeTail.rescale c hc) + have hmapn : Measurable + (FiniteOrderedTimes.mapPath e : (Fin n → alpha) → Fin n → beta) := + FiniteOrderedTimes.measurable_mapPath e.measurable + have hconj : Measurable (fun z : alpha × (Fin n → alpha) ↦ + (e z.1, FiniteOrderedTimes.mapPath e z.2)) := + (e.measurable.comp measurable_fst).prodMk (hmapn.comp measurable_snd) + rw [finiteTimeKernel_succ, finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map, + Kernel.mapOfMeasurable_eq_map, FiniteOrderedTimes.relativeTail_rescale, + FiniteOrderedTimes.rescale_apply, + Kernel.comap_map_comm _ e.symm.measurable measurable_finCons, + ← Kernel.map_comp_right _ measurable_finCons + (FiniteOrderedTimes.measurable_mapPath (ι := Fin (n + 1)) e.measurable), + show (FiniteOrderedTimes.mapPath e ∘ fun z : alpha × (Fin n → alpha) ↦ + @Fin.cons n (fun _ : Fin (n + 1) ↦ alpha) z.1 z.2) = + (fun z : beta × (Fin n → beta) ↦ + @Fin.cons n (fun _ : Fin (n + 1) ↦ beta) z.1 z.2) ∘ + (fun z : alpha × (Fin n → alpha) ↦ (e z.1, FiniteOrderedTimes.mapPath e z.2)) from + funext fun z ↦ FiniteOrderedTimes.mapPath_finCons e z, + Kernel.map_comp_right _ hconj (measurable_finCons (α := beta)), + comap_compProd_prodMkLeft _ _ e.symm.measurable, + map_compProd_prodMkLeft_conjugate _ _ e.measurable e.symm.measurable + e.symm_apply_apply e.apply_symm_apply hmapn, + ← h.kernel_eq (times 0), ← ih times.relativeTail] + +/-- **Finite-set transfer.** The finite-dimensional law of the rescaled conjugate `P'` on a +finite set `I` of times is the law of `P` at the times `c * t`, `t ∈ I`, started from the +`e`-preimage of the initial state and read through `e` in every coordinate. -/ +theorem finiteSetKernel_eq (h : IsRescaledConjugate P P' e c) (hc : 0 < c) + (hP : P.IsConservative) (I : Finset NNReal) : + finiteSetKernel P' I = + (Kernel.comap (finiteTimeKernel P ((finiteSetTimes I).rescale c hc)) e.symm + e.symm.measurable).map + (FiniteOrderedTimes.mapPath e ∘ orderedPathToFiniteSet I) := by + have hmap : Measurable + (FiniteOrderedTimes.mapPath e : (Fin I.card → alpha) → Fin I.card → beta) := + FiniteOrderedTimes.measurable_mapPath e.measurable + rw [finiteSetKernel_eq_map, h.finiteTimeKernel_eq hc hP (finiteSetTimes I), + ← Kernel.map_comp_right _ hmap (measurable_orderedPathToFiniteSet I), + show (orderedPathToFiniteSet (α := beta) I ∘ FiniteOrderedTimes.mapPath e) = + FiniteOrderedTimes.mapPath e ∘ orderedPathToFiniteSet I from rfl] + +end IsRescaledConjugate + +section Moments + +variable {alpha beta : Type*} [PseudoEMetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [PseudoEMetricSpace beta] [MeasurableSpace beta] [BorelSpace beta] +variable {P : SubMarkovKernelSemigroup alpha} {P' : SubMarkovKernelSemigroup beta} {e : alpha ≃ₜ beta} + {c : NNReal} + +/-- **Transfer of the Kolmogorov moment criterion.** If the state map `e` is an isometry, then +the intrinsic displacement bound of `P` passes to its rescaled conjugate `P'` with the constant +multiplied by `c ^ q`: the conjugation leaves the displacement untouched and speeding time up by +`c` multiplies the time budget `h ^ q` by `c ^ q`. -/ +theorem IsRescaledConjugate.hasKolmogorovMoments + (h : IsRescaledConjugate P P' e c) (he : Isometry (e : alpha → beta)) {p q : ℝ} {M : ℝ≥0} + (hmom : P.HasKolmogorovMoments p q M) : P'.HasKolmogorovMoments p q (M * c ^ q) := by + obtain ⟨hp, hq, hbound⟩ := hmom + have hq0 : (0 : ℝ) ≤ q := le_of_lt (lt_trans zero_lt_one hq) + refine ⟨hp, hq, fun t y ↦ ?_⟩ + have hstep : ∫⁻ z, edist z y ^ p ∂(P' t y) = + ∫⁻ w, edist w (e.symm y) ^ p ∂(P (c * t) (e.symm y)) := by + have hmeas : Measurable (fun z : beta ↦ edist z y ^ p) := + (measurable_edist_left (x := y)).pow_const p + rw [h t y, MeasureTheory.lintegral_map hmeas e.measurable] + refine lintegral_congr fun w ↦ ?_ + congr 1 + conv_lhs => rw [← e.apply_symm_apply y] + exact he.edist_eq w (e.symm y) + rw [hstep] + refine le_trans (hbound (c * t) (e.symm y)) (le_of_eq ?_) + rw [ENNReal.coe_mul, ENNReal.mul_rpow_of_nonneg _ _ hq0, ← mul_assoc, ENNReal.coe_mul, + ENNReal.coe_rpow_of_nonneg c hq0] + +end Moments + +end RescaledConjugate + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelMixedPullback.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelMixedPullback.lean new file mode 100644 index 0000000000..d9d9df3f20 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelMixedPullback.lean @@ -0,0 +1,81 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation + +/-! +# Pulling a finite-time concatenation back to mixed labels + +This file records the reindexing step after an ordered finite-dimensional law has been split at +a designated cut. A mixed label may select a past coordinate, a strict-future coordinate, or +the terminal past coordinate. The last alternative permits a future-zero label to duplicate a +terminal past label without requiring either label to be present. + +The result is pure finite-dimensional Chapman--Kolmogorov algebra. In particular it has no +continuity, density, path-space, or Feller hypothesis. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +variable {alpha pastLabel futureLabel : Type*} [MeasurableSpace alpha] + +/-- Pull a split finite path back to arbitrary past and future label types. `none` selects the +terminal past coordinate; this is the coordinate used by a future label representing elapsed +time zero. -/ +def pullbackSplitFinitePath {m n : ℕ} + (pastIndex : pastLabel → Fin (m + 1)) + (futureIndex : futureLabel → Option (Fin n)) + (z : (Fin (m + 1) → alpha) × (Fin n → alpha)) : + pastLabel ⊕ futureLabel → alpha + | Sum.inl i => z.1 (pastIndex i) + | Sum.inr j => (futureIndex j).elim (z.1 (Fin.last m)) z.2 + +/-- Pullback to mixed labels is measurable, including when either label type is empty and when +several labels select the terminal coordinate. -/ +theorem measurable_pullbackSplitFinitePath {m n : ℕ} + (pastIndex : pastLabel → Fin (m + 1)) + (futureIndex : futureLabel → Option (Fin n)) : + Measurable + (pullbackSplitFinitePath (alpha := alpha) pastIndex futureIndex) := by + rw [measurable_pi_iff] + rintro (i | j) + · exact (measurable_pi_apply (pastIndex i)).comp measurable_fst + · cases h : futureIndex j with + | none => + simpa only [pullbackSplitFinitePath, h] using! + ((measurable_pi_apply (Fin.last m)).comp measurable_fst) + | some k => + simpa only [pullbackSplitFinitePath, h] using! + ((measurable_pi_apply k).comp measurable_snd) + +namespace IsConservative + +/-- Concatenation at an ordered cut remains valid after pulling the two pieces back to arbitrary +mixed labels. Mapping a future label to `none` reads the cut coordinate from the past, so the +theorem directly permits simultaneous terminal-past/future-zero observations. -/ +theorem finiteTimeKernel_map_pullbackSplitFinitePath + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (m n : ℕ) (times : FiniteOrderedTimes (n + (m + 1))) + (pastIndex : pastLabel → Fin (m + 1)) + (futureIndex : futureLabel → Option (Fin n)) : + (finiteTimeKernel P times).map + (pullbackSplitFinitePath (alpha := alpha) pastIndex futureIndex ∘ + splitFinitePath (alpha := alpha) (m := m) (n := n)) = + (finiteTimeKernel P (FiniteOrderedTimes.initialSegment times) ⊗ₖ + (finiteTimeKernel P (FiniteOrderedTimes.relativeFinalSegment times)).comap + (splitPastTerminal (alpha := alpha) (m := m)) + measurable_splitPastTerminal).map + (pullbackSplitFinitePath (alpha := alpha) pastIndex futureIndex) := by + rw [Kernel.map_comp_right] + · rw [hP.finiteTimeKernel_map_splitFinitePath P m n times] + · exact measurable_splitFinitePath + · exact measurable_pullbackSplitFinitePath pastIndex futureIndex + +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelRestriction.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelRestriction.lean new file mode 100644 index 0000000000..fe91b4d115 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelRestriction.lean @@ -0,0 +1,87 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion + +/-! +# Restricting finite-time kernels + +For a conservative sub-Markov kernel semigroup, restriction along any finite order embedding +gives the finite-time kernel at the selected times. This is finite-dimensional kernel +infrastructure and does not construct a path-space law or a stochastic process. +-/ + +open ProbabilityTheory + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +variable {α : Type*} [MeasurableSpace α] + +private theorem fin_orderEmbedding_self_eq_id {n : ℕ} (e : Fin n ↪o Fin n) : + e = (OrderIso.refl (Fin n)).toOrderEmbedding := by + let eo : Fin n ≃o Fin n := + { Equiv.ofBijective e ⟨e.injective, Finite.surjective_of_injective e.injective⟩ with + map_rel_iff' := e.le_iff_le } + apply DFunLike.ext _ _ + intro i + apply Fin.ext + exact Fin.coe_orderIso_apply eo i + +namespace IsConservative + +/-- Restricting a conservative finite-time kernel along any finite order embedding gives the +kernel at the restricted times. -/ +theorem finiteTimeKernel_map_restrictPath + (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + {m n : ℕ} (times : FiniteOrderedTimes n) (e : Fin m ↪o Fin n) : + (finiteTimeKernel P times).map (FiniteOrderedTimes.restrictPath e) = + finiteTimeKernel P (times.restrict e) := by + induction n generalizing m with + | zero => + have hm : m = 0 := by + have hcard := Fintype.card_le_of_injective e e.injective + simpa only [Fintype.card_fin, Nat.le_zero] using hcard + subst m + rw [fin_orderEmbedding_self_eq_id e] + rw [show (FiniteOrderedTimes.restrictPath (OrderIso.refl (Fin 0)).toOrderEmbedding : + (Fin 0 → α) → Fin 0 → α) = id by + funext path + exact FiniteOrderedTimes.restrictPath_id path] + rw [Kernel.map_id, FiniteOrderedTimes.restrict_id] + | succ n ih => + have hcard : m ≤ n + 1 := by + simpa only [Fintype.card_fin] using Fintype.card_le_of_injective e e.injective + by_cases hm : m = n + 1 + · subst m + rw [fin_orderEmbedding_self_eq_id e] + rw [show (FiniteOrderedTimes.restrictPath + (OrderIso.refl (Fin (n + 1))).toOrderEmbedding : + (Fin (n + 1) → α) → Fin (n + 1) → α) = id by + funext path + exact FiniteOrderedTimes.restrictPath_id path] + rw [Kernel.map_id, FiniteOrderedTimes.restrict_id] + · have hmn : m ≤ n := Nat.le_of_lt_succ (lt_of_le_of_ne hcard hm) + obtain ⟨p, d, hd⟩ := exists_factor_succAboveOrderEmb e hmn + rw [← hd] + have hdelete := hP.finiteTimeKernel_map_restrictPath_succAbove P times p + have hdel : Measurable (FiniteOrderedTimes.restrictPath + (Fin.succAboveOrderEmb p) : (Fin (n + 1) → α) → Fin n → α) := + FiniteOrderedTimes.measurable_restrictPath (Fin.succAboveOrderEmb p) + have hdmeas : Measurable + (FiniteOrderedTimes.restrictPath d : (Fin n → α) → Fin m → α) := + FiniteOrderedTimes.measurable_restrictPath d + rw [show (FiniteOrderedTimes.restrictPath (d.trans (Fin.succAboveOrderEmb p)) : + (Fin (n + 1) → α) → Fin m → α) = + FiniteOrderedTimes.restrictPath d ∘ + FiniteOrderedTimes.restrictPath (Fin.succAboveOrderEmb p) by rfl] + rw [Kernel.map_comp_right _ hdel hdmeas, hdelete, + ih (times.restrict (Fin.succAboveOrderEmb p)) d, + FiniteOrderedTimes.restrict_trans] + +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelShift.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelShift.lean new file mode 100644 index 0000000000..59bb6d6c20 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelShift.lean @@ -0,0 +1,56 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +import Mathlib.Probability.Kernel.Composition.KernelLemmas + +/-! +# Translation of finite-time kernels + +This file proves the finite-dimensional translation identity for a conservative transition-kernel +semigroup. It is ordinary kernel infrastructure and makes no path-space or process-existence claim. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ProbabilityTheory + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +variable {W X Y Z : Type*} +variable [MeasurableSpace W] [MeasurableSpace X] [MeasurableSpace Y] [MeasurableSpace Z] + +private theorem compProd_prodMkLeft_comp (κ : Kernel X Y) (η : Kernel Y Z) + (ξ : Kernel W X) [IsSFiniteKernel κ] [IsSFiniteKernel η] [IsSFiniteKernel ξ] : + (κ.comp ξ) ⊗ₖ Kernel.prodMkLeft W η = (κ ⊗ₖ Kernel.prodMkLeft X η).comp ξ := by + rw [Kernel.compProd_prodMkLeft_eq_comp, Kernel.compProd_prodMkLeft_eq_comp, + Kernel.comp_assoc] + +namespace IsConservative + +variable {α : Type*} [MeasurableSpace α] + +/-- Translating all observation times is the same as first evolving for the translation amount. -/ +theorem finiteTimeKernel_translate (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + (s : NNReal) {n : ℕ} (times : FiniteOrderedTimes n) : + finiteTimeKernel P (times.translate s) = (finiteTimeKernel P times).comp (P s) := by + induction n with + | zero => + let : IsMarkovKernel (P s) := hP.isMarkovKernel s + rw [finiteTimeKernel_zero, finiteTimeKernel_zero, Kernel.const_comp'] + | succ n ih => + let : IsFiniteKernel (P s) := (P.isSubMarkovKernel s).isFiniteKernel + let : IsFiniteKernel (P (times 0)) := + (P.isSubMarkovKernel (times 0)).isFiniteKernel + let : IsMarkovKernel (finiteTimeKernel P times.relativeTail) := + hP.isMarkovKernel_finiteTimeKernel P times.relativeTail + rw [finiteTimeKernel_succ, finiteTimeKernel_succ] + simp only [FiniteOrderedTimes.translate_apply, FiniteOrderedTimes.relativeTail_translate] + rw [P.add s (times 0), Kernel.mapOfMeasurable_eq_map, + Kernel.mapOfMeasurable_eq_map, compProd_prodMkLeft_comp, Kernel.map_comp] + +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/MeasureFiniteRestrictionIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/MeasureFiniteRestrictionIdentification.lean new file mode 100644 index 0000000000..0f8187fc47 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/MeasureFiniteRestrictionIdentification.lean @@ -0,0 +1,47 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.MeasureTheory.Constructions.Projective + +/-! +# Identifying measures from finite-coordinate restrictions + +A finite measure on a product space is determined by all of its finite-coordinate pushforwards. +The empty coordinate set is part of the family and therefore records the total mass; measures of +unequal mass cannot satisfy the hypothesis. + +This is generic measure-theoretic infrastructure and requires no topology. +-/ + +open MeasureTheory + +namespace MarkovProcess +namespace Measure + +noncomputable section + +variable {index alpha : Type*} [MeasurableSpace alpha] + +/-- Two measures on a product space agree if all their finite-coordinate pushforwards agree. -/ +theorem eq_of_map_finiteRestriction_eq + (mu nu : Measure (index → alpha)) [IsFiniteMeasure mu] + (h : ∀ I : Finset index, mu.map I.restrict = nu.map I.restrict) : + mu = nu := by + let family : (I : Finset index) → Measure (I → alpha) := + fun I ↦ mu.map I.restrict + have hmu : IsProjectiveLimit mu family := by + intro I + rfl + have hnu : IsProjectiveLimit nu family := by + intro I + exact (h I).symm + let (I : Finset index) : IsFiniteMeasure (family I) := by + dsimp only [family] + infer_instance + exact hmu.unique hnu + +end +end Measure +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/ProjectiveFamily.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/ProjectiveFamily.lean new file mode 100644 index 0000000000..44b7ddf543 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/ProjectiveFamily.lean @@ -0,0 +1,128 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +import Mathlib.Data.Finset.Sort +import Mathlib.MeasureTheory.Constructions.Projective + +/-! +# Finite-set finite-time laws + +This file reindexes the ordered finite-time kernels by finite sets of times and proves their +Mathlib-native projectivity. It does not assert or construct a projective-limit measure. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +variable {α : Type*} [MeasurableSpace α] + +/-- The increasing enumeration of a finite set of nonnegative times. -/ +noncomputable def finiteSetTimes (I : Finset NNReal) : FiniteOrderedTimes I.card := + I.orderEmbOfFin rfl + +/-- Reindex an ordered coordinate path by its finite set of times. -/ +noncomputable def orderedPathToFiniteSet (I : Finset NNReal) (path : Fin I.card → α) : I → α := + fun t ↦ path ((I.orderIsoOfFin rfl).symm t) + +/-- Reindexing an ordered coordinate path by its finite set of times is measurable. -/ +theorem measurable_orderedPathToFiniteSet (I : Finset NNReal) : + Measurable (orderedPathToFiniteSet (α := α) I) := + measurable_pi_iff.mpr fun t ↦ measurable_pi_apply ((I.orderIsoOfFin rfl).symm t) + +/-- The finite-time kernel indexed by a finite set of times. -/ +noncomputable def finiteSetKernel (P : SubMarkovKernelSemigroup α) (I : Finset NNReal) : + Kernel α (I → α) := + Kernel.mapOfMeasurable (finiteTimeKernel P (finiteSetTimes I)) + (orderedPathToFiniteSet I) (measurable_orderedPathToFiniteSet I) + +/-- The finite-set kernel agrees with the ordinary kernel map. -/ +theorem finiteSetKernel_eq_map (P : SubMarkovKernelSemigroup α) (I : Finset NNReal) : + finiteSetKernel P I = + (finiteTimeKernel P (finiteSetTimes I)).map (orderedPathToFiniteSet I) := + Kernel.mapOfMeasurable_eq_map _ (measurable_orderedPathToFiniteSet I) + +/-- The finite-set law at a starting state. -/ +noncomputable def finiteSetLaw (P : SubMarkovKernelSemigroup α) (I : Finset NNReal) + (x : α) : Measure (I → α) := + finiteSetKernel P I x + +private noncomputable def inclusionOrderEmb {I J : Finset NNReal} (hJI : J ⊆ I) : + Fin J.card ↪o Fin I.card := + (J.orderIsoOfFin rfl).toOrderEmbedding |>.trans + (OrderEmbedding.ofStrictMono + (fun t : J ↦ (⟨t, hJI t.property⟩ : I)) (fun _ _ h ↦ h)) |>.trans + (I.orderIsoOfFin rfl).symm.toOrderEmbedding + +private theorem finiteSetTimes_restrict {I J : Finset NNReal} (hJI : J ⊆ I) : + (finiteSetTimes I).restrict (inclusionOrderEmb hJI) = finiteSetTimes J := by + apply DFunLike.ext _ _ + intro i + change (((I.orderIsoOfFin rfl) + ((I.orderIsoOfFin rfl).symm + ⟨↑(J.orderIsoOfFin rfl i), hJI (J.orderIsoOfFin rfl i).property⟩) : I) : + NNReal) = ((J.orderIsoOfFin rfl i : J) : NNReal) + rw [OrderIso.apply_symm_apply] + +omit [MeasurableSpace α] in +private theorem orderedPathToFiniteSet_restrict {I J : Finset NNReal} (hJI : J ⊆ I) : + Finset.restrict₂ (π := fun _ ↦ α) hJI ∘ orderedPathToFiniteSet (α := α) I = + orderedPathToFiniteSet J ∘ + FiniteOrderedTimes.restrictPath (inclusionOrderEmb hJI) := by + funext path t + change path ((I.orderIsoOfFin rfl).symm ⟨t, hJI t.property⟩) = + path (inclusionOrderEmb hJI ((J.orderIsoOfFin rfl).symm t)) + simp only [inclusionOrderEmb, RelEmbedding.coe_trans, Function.comp_apply, + OrderIso.coe_toOrderEmbedding, OrderIso.apply_symm_apply] + rfl + +namespace IsConservative + +/-- Under conservativity, every finite-set kernel is a Markov kernel. -/ +theorem isMarkovKernel_finiteSetKernel (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (I : Finset NNReal) : IsMarkovKernel (finiteSetKernel P I) := by + rw [finiteSetKernel_eq_map] + let : IsMarkovKernel (finiteTimeKernel P (finiteSetTimes I)) := + hP.isMarkovKernel_finiteTimeKernel P (finiteSetTimes I) + exact Kernel.IsMarkovKernel.map _ (measurable_orderedPathToFiniteSet I) + +/-- Under conservativity, every finite-set law is a probability measure. -/ +theorem isProbabilityMeasure_finiteSetLaw (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (I : Finset NNReal) (x : α) : + IsProbabilityMeasure (finiteSetLaw P I x) := by + let : IsMarkovKernel (finiteSetKernel P I) := hP.isMarkovKernel_finiteSetKernel P I + exact IsMarkovKernel.isProbabilityMeasure x + +/-- A finite-set kernel restricted along an inclusion is the kernel on the smaller set. -/ +theorem finiteSetKernel_map_restrict₂ (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) {I J : Finset NNReal} (hJI : J ⊆ I) : + finiteSetKernel P J = + (finiteSetKernel P I).map (Finset.restrict₂ (π := fun _ ↦ α) hJI) := by + rw [finiteSetKernel_eq_map, finiteSetKernel_eq_map, ← Kernel.map_comp_right] + · rw [orderedPathToFiniteSet_restrict hJI, Kernel.map_comp_right] + · rw [hP.finiteTimeKernel_map_restrictPath P (finiteSetTimes I) + (inclusionOrderEmb hJI), finiteSetTimes_restrict hJI] + · exact FiniteOrderedTimes.measurable_restrictPath (inclusionOrderEmb hJI) + · exact measurable_orderedPathToFiniteSet J + · exact measurable_orderedPathToFiniteSet I + · exact Finset.measurable_restrict₂ (X := fun _ ↦ α) hJI + +/-- The finite-set laws of a conservative semigroup form a projective measure family. -/ +theorem isProjectiveMeasureFamily_finiteSetLaw (P : SubMarkovKernelSemigroup α) + (hP : P.IsConservative) (x : α) : + IsProjectiveMeasureFamily (α := fun _ : NNReal ↦ α) + (fun I : Finset NNReal ↦ finiteSetLaw P I x) := by + intro I J hJI + change finiteSetKernel P J x = + Measure.map (Finset.restrict₂ (π := fun _ ↦ α) hJI) (finiteSetKernel P I x) + rw [← Kernel.map_apply _ (Finset.measurable_restrict₂ (X := fun _ ↦ α) hJI)] + exact congrArg (fun K : Kernel α (J → α) ↦ K x) + (hP.finiteSetKernel_map_restrict₂ P hJI) + +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel.lean new file mode 100644 index 0000000000..fd4de87b6b --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel.lean @@ -0,0 +1,42 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 +import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint +import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativityAE +import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpConsistency +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop +import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OperatorSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness +import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence + +/-! +# Kernel + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Basic.lean new file mode 100644 index 0000000000..36e9a6312f --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Basic.lean @@ -0,0 +1,75 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Probability.Kernel.Composition.Comp + +/-! +# Sub-Markov kernels + +This file records the elementary mass algebra of sub-Markov kernels. It does +not define transition families or connect kernels to operator semigroups or +stochastic processes. +-/ + +open MeasureTheory +open scoped ENNReal ProbabilityTheory + +namespace MarkovProcess + +variable {α β γ : Type*} [MeasurableSpace α] [MeasurableSpace β] [MeasurableSpace γ] + +/-- A kernel is sub-Markov if each of its measures has total mass at most one. -/ +def IsSubMarkovKernel (κ : ProbabilityTheory.Kernel α β) : Prop := + ∀ x, κ x Set.univ ≤ 1 + +namespace IsSubMarkovKernel + +open ProbabilityTheory + +variable {κ : Kernel α β} {η : Kernel β γ} + +/-- A sub-Markov kernel assigns mass at most one to every set. -/ +theorem measure_le_one (hκ : IsSubMarkovKernel κ) (x : α) (s : Set β) : κ x s ≤ 1 := + (measure_mono (Set.subset_univ s)).trans (hκ x) + +/-- The uniform Mathlib kernel bound of a sub-Markov kernel is at most one. -/ +theorem bound_le_one (hκ : IsSubMarkovKernel κ) : κ.bound ≤ 1 := by + apply iSup_le + exact hκ + +/-- A sub-Markov kernel is a finite kernel. -/ +theorem isFiniteKernel (hκ : IsSubMarkovKernel κ) : IsFiniteKernel κ := + ⟨⟨1, ENNReal.one_lt_top, hκ⟩⟩ + +/-- The zero kernel is sub-Markov. -/ +theorem zero : IsSubMarkovKernel (0 : Kernel α β) := by + intro x + rw [zero_apply] + exact zero_le + +/-- The identity kernel is sub-Markov. -/ +theorem id : IsSubMarkovKernel (Kernel.id : Kernel α α) := by + intro x + rw [Kernel.id_apply] + exact le_of_eq measure_univ + +/-- Every Markov kernel is sub-Markov. -/ +theorem of_isMarkovKernel (κ : Kernel α β) [IsMarkovKernel κ] : IsSubMarkovKernel κ := by + intro x + exact le_of_eq measure_univ + +/-- The composition of two sub-Markov kernels is sub-Markov. -/ +theorem comp (hη : IsSubMarkovKernel η) (hκ : IsSubMarkovKernel κ) : + IsSubMarkovKernel (η ∘ₖ κ) := by + intro x + calc + (η ∘ₖ κ) x Set.univ ≤ κ x Set.univ * η.bound := + Kernel.comp_apply_univ_le κ η x + _ ≤ 1 * 1 := mul_le_mul' (hκ x) hη.bound_le_one + _ = 1 := one_mul 1 + +end IsSubMarkovKernel + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0.lean new file mode 100644 index 0000000000..08310c5dfc --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0.lean @@ -0,0 +1,139 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction +import Mathlib.Probability.Kernel.Composition.IntegralCompProd +import Mathlib.Topology.ContinuousMap.ZeroAtInfty +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup + +/-! +# Kernel operators on continuous functions vanishing at infinity + +This file records the spatial `C₀` property of a sub-Markov kernel semigroup and packages its +raw integral as a contractive continuous linear map on `C₀(α, ℝ)`. It makes no assertion about +continuity in time or the existence of an associated stochastic process. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal ZeroAtInfty + +namespace MarkovProcess + +namespace SubMarkovKernelSemigroup + +variable {α : Type*} [TopologicalSpace α] [MeasurableSpace α] + +/-- A kernel semigroup maps `C₀(α, ℝ)` into itself when its raw kernel integral is continuous +and vanishes at infinity at every time. -/ +def MapsC0 (P : SubMarkovKernelSemigroup α) : Prop := + ∀ t (f : C₀(α, ℝ)), + Continuous (kernelIntegral (P t) f) ∧ + Tendsto (kernelIntegral (P t) f) (cocompact α) (nhds 0) + +variable (P : SubMarkovKernelSemigroup α) (hC0 : P.MapsC0) + +/-- The exact `C₀` representative obtained by integrating against `P t`. -/ +noncomputable def c0KernelIntegral (t : NNReal) (f : C₀(α, ℝ)) : C₀(α, ℝ) where + toFun := kernelIntegral (P t) f + continuous_toFun := (hC0 t f).1 + zero_at_infty' := (hC0 t f).2 + +@[simp] +theorem c0KernelIntegral_apply (t : NNReal) (f : C₀(α, ℝ)) (x : α) : + P.c0KernelIntegral hC0 t f x = kernelIntegral (P t) f x := + rfl + +variable [BorelSpace α] + +private theorem integrable_fiber (t : NNReal) (f : C₀(α, ℝ)) (x : α) : + Integrable f (P t x) := by + let : IsFiniteKernel (P t) := (P.isSubMarkovKernel t).isFiniteKernel + exact f.toBCF.integrable (P t x) + +private theorem norm_c0KernelIntegral_le (t : NNReal) (f : C₀(α, ℝ)) : + ‖P.c0KernelIntegral hC0 t f‖ ≤ ‖f‖ := by + let : IsFiniteKernel (P t) := (P.isSubMarkovKernel t).isFiniteKernel + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + apply (BoundedContinuousFunction.norm_le (norm_nonneg f)).2 + intro x + calc + ‖P.c0KernelIntegral hC0 t f x‖ + ≤ (P t x).real Set.univ * ‖f.toBCF‖ := + f.toBCF.norm_integral_le_mul_norm (P t x) + _ ≤ 1 * ‖f.toBCF‖ := by + apply mul_le_mul_of_nonneg_right _ (norm_nonneg _) + rw [Measure.real_def] + exact ENNReal.toReal_mono ENNReal.one_ne_top + ((P.isSubMarkovKernel t) x) + _ = ‖f‖ := by + rw [one_mul, ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + +/-- The kernel integral as a contraction on real continuous functions vanishing at infinity. -/ +noncomputable def c0Operator (t : NNReal) : C₀(α, ℝ) →L[ℝ] C₀(α, ℝ) := + LinearMap.mkContinuous + { toFun := P.c0KernelIntegral hC0 t + map_add' := fun f g ↦ by + apply ZeroAtInftyContinuousMap.ext + intro x + change ∫ y, (f y + g y) ∂P t x = (∫ y, f y ∂P t x) + ∫ y, g y ∂P t x + exact integral_add (P.integrable_fiber t f x) (P.integrable_fiber t g x) + map_smul' := fun c f ↦ by + apply ZeroAtInftyContinuousMap.ext + intro x + change ∫ y, c * f y ∂P t x = c * ∫ y, f y ∂P t x + simpa only [smul_eq_mul] using + (integral_smul c (fun y ↦ f y) : + (∫ y, c • f y ∂P t x) = c • ∫ y, f y ∂P t x) } + 1 fun f ↦ by + rw [one_mul] + exact P.norm_c0KernelIntegral_le hC0 t f + +@[simp] +theorem c0Operator_apply (t : NNReal) (f : C₀(α, ℝ)) (x : α) : + P.c0Operator hC0 t f x = kernelIntegral (P t) f x := + rfl + +/-- At time zero the `C₀` kernel operator is the identity. -/ +@[simp] +theorem c0Operator_zero : + P.c0Operator hC0 0 = ContinuousLinearMap.id ℝ C₀(α, ℝ) := by + apply ContinuousLinearMap.ext + intro f + apply ZeroAtInftyContinuousMap.ext + intro x + rw [c0Operator_apply, P.zero] + exact integral_dirac' f x f.continuous.stronglyMeasurable + +/-- Kernel composition gives the algebraic semigroup law on `C₀`. -/ +@[simp] +theorem c0Operator_add (s t : NNReal) : + P.c0Operator hC0 (s + t) = + (P.c0Operator hC0 s).comp (P.c0Operator hC0 t) := by + apply ContinuousLinearMap.ext + intro f + apply ZeroAtInftyContinuousMap.ext + intro x + change kernelIntegral (P (s + t)) f x = + kernelIntegral (P s) (kernelIntegral (P t) f) x + have hf := P.integrable_fiber (s + t) f x + rw [P.add] at hf ⊢ + exact Kernel.integral_comp hf + +/-- Every time slice of the `C₀` kernel operator has operator norm at most one. -/ +theorem norm_c0Operator_le (t : NNReal) : ‖P.c0Operator hC0 t‖ ≤ 1 := by + apply ContinuousLinearMap.opNorm_le_bound _ zero_le_one + intro f + simpa only [one_mul] using! P.norm_c0KernelIntegral_le hC0 t f + +/-- The `C₀` kernel operator preserves pointwise nonnegativity. -/ +theorem c0Operator_apply_nonneg (t : NNReal) {f : C₀(α, ℝ)} + (hf : ∀ x, 0 ≤ f x) (x : α) : 0 ≤ P.c0Operator hC0 t f x := by + rw [c0Operator_apply] + exact integral_nonneg hf + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0SemigroupJoint.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0SemigroupJoint.lean new file mode 100644 index 0000000000..daa29dc32f --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0SemigroupJoint.lean @@ -0,0 +1,44 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +import Mathlib.MeasureTheory.Constructions.BorelSpace.Basic +import Mathlib.Topology.ContinuousMap.ZeroAtInfty + +/-! +# Joint regularity of strongly continuous semigroups on `C₀` + +Strong continuity of a semigroup orbit in the `C₀` norm and continuity of +evaluation give continuity, jointly in time and state, of the evaluated orbit. +The corresponding Borel measurability statement follows without any additional +regularity premise on the semigroup. + +This is a generic functional-analytic API. It makes no representation claim +about the semigroup. +-/ + +open scoped ZeroAtInfty + +namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +variable {α : Type*} [TopologicalSpace α] + +/-- A strongly continuous `C₀`-semigroup orbit is jointly continuous in time +and state after evaluation. -/ +theorem continuous_apply_apply + (S : StronglyContinuousContractionSemigroup C₀(α, ℝ)) (f : C₀(α, ℝ)) : + Continuous fun tx : NNReal × α ↦ S tx.1 f tx.2 := + ((ZeroAtInftyContinuousMap.isometry_toBCF (α := α) (β := ℝ)).continuous.comp + ((S.continuous f).comp continuous_fst)).eval continuous_snd + +/-- Joint evaluation of a strongly continuous `C₀`-semigroup orbit is Borel +measurable for the product measurable space. -/ +theorem measurable_apply_apply + [MeasurableSpace α] [BorelSpace α] + (S : StronglyContinuousContractionSemigroup C₀(α, ℝ)) (f : C₀(α, ℝ)) : + Measurable fun tx : NNReal × α ↦ S tx.1 f tx.2 := + (S.continuous_apply_apply f).measurable + +end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/CompProdReindex.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/CompProdReindex.lean new file mode 100644 index 0000000000..15d4d82cc4 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/CompProdReindex.lean @@ -0,0 +1,96 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Probability.Kernel.Composition.CompProd + +/-! +# Mapping product kernels by coordinate maps + +This file provides generic identities for mapping the coordinates of a kernel composition +product. They are measure-kernel infrastructure and make no assertion about a stochastic +process. +-/ + +open MeasureTheory +open scoped ProbabilityTheory + +namespace ProbabilityTheory.Kernel + +/-- Mapping the left output of a composition product by a measurable equivalence transports +the second kernel along the inverse equivalence. -/ +theorem map_compProd_left_equiv + {X A B C : Type*} [MeasurableSpace X] [MeasurableSpace A] + [MeasurableSpace B] [MeasurableSpace C] + (κ : Kernel X A) [IsSFiniteKernel κ] + (η : Kernel (X × A) B) [IsSFiniteKernel η] + (e : A ≃ᵐ C) : + (κ ⊗ₖ η).map (Prod.map e id) = + κ.map e ⊗ₖ η.comap + (fun z : X × C ↦ (z.1, e.symm z.2)) + (measurable_fst.prodMk (e.symm.measurable.comp measurable_snd)) := by + ext x s hs + rw [Kernel.map_apply' _ (e.measurable.prodMap measurable_id) x hs, + Kernel.compProd_apply (hs.preimage (e.measurable.prodMap measurable_id)), + Kernel.compProd_apply hs] + rw [Kernel.map_apply κ e.measurable x] + rw [MeasureTheory.lintegral_map] + · congr with a + rw [Kernel.comap_apply] + change η (x, a) (Prod.mk (e a) ⁻¹' s) = _ + rw [e.symm_apply_apply] + · exact Kernel.measurable_kernel_prodMk_left' hs x + · exact e.measurable + +/-- Mapping the right output of a composition product whose second kernel is `prodMkLeft` +is the same as mapping that second kernel before forming the composition product. -/ +theorem map_compProd_prodMkLeft_right + {X A B C : Type*} [MeasurableSpace X] [MeasurableSpace A] + [MeasurableSpace B] [MeasurableSpace C] + (κ : Kernel X A) [IsSFiniteKernel κ] + (η : Kernel A B) [IsSFiniteKernel η] + (f : B → C) (hf : Measurable f) : + (κ ⊗ₖ Kernel.prodMkLeft X η).map (fun z ↦ (z.1, f z.2)) = + κ ⊗ₖ Kernel.prodMkLeft X (η.map f) := by + have hpair : Measurable (fun z : A × B ↦ (z.1, f z.2)) := + measurable_fst.prodMk (hf.comp measurable_snd) + ext x s hs + rw [Kernel.map_apply' _ hpair x hs, + Kernel.compProd_apply (hs.preimage hpair), Kernel.compProd_apply hs] + congr with a + rw [Kernel.prodMkLeft_apply', Kernel.prodMkLeft_apply', + Kernel.map_apply' _ hf _ (measurable_prodMk_left hs)] + rfl + +/-- A measurable reindexing of the first output commutes with mapping the second output when +the latter kernel depends on the first output only through compatible measurable statistics. -/ +theorem map_compProd_prodMkLeft_comap + {X A B C D T : Type*} [MeasurableSpace X] [MeasurableSpace A] + [MeasurableSpace B] [MeasurableSpace C] [MeasurableSpace D] [MeasurableSpace T] + (κ : Kernel X A) [IsSFiniteKernel κ] + (η : Kernel T B) [IsSFiniteKernel η] + (terminal : A → T) + (terminal' : C → T) (hterminal' : Measurable terminal') + (f : A → C) (hf : Measurable f) (g : B → D) (hg : Measurable g) + (hcompat : terminal' ∘ f = terminal) : + (κ ⊗ₖ Kernel.prodMkLeft X + (η.comap terminal (hcompat ▸ hterminal'.comp hf))).map (Prod.map f g) = + κ.map f ⊗ₖ + Kernel.prodMkLeft X ((η.map g).comap terminal' hterminal') := by + have hpair : Measurable (Prod.map f g) := hf.prodMap hg + ext x s hs + rw [Kernel.map_apply' _ hpair x hs, + Kernel.compProd_apply (hs.preimage hpair), Kernel.compProd_apply hs] + rw [Kernel.map_apply κ hf x] + rw [MeasureTheory.lintegral_map] + · congr with a + rw [Kernel.prodMkLeft_apply', Kernel.prodMkLeft_apply', + Kernel.comap_apply, Kernel.comap_apply, + Kernel.map_apply' _ hg _ (measurable_prodMk_left hs)] + rw [← congrFun hcompat a] + rfl + · exact Kernel.measurable_kernel_prodMk_left' hs x + · exact hf + +end ProbabilityTheory.Kernel diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativeResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativeResolvent.lean new file mode 100644 index 0000000000..ab416e4982 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativeResolvent.lean @@ -0,0 +1,155 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential + +/-! +# Conservativity from the resolvent of the constant observable + +A sub-Markov kernel semigroup loses no mass as soon as its resolvent at one positive shift has +the full mass of the exponential weight, + + `lam * R_lam 1 = 1` (`SubMarkovKernelSemigroup.isConservative_of_kernelResolvent_one`). + +The transition mass is nonincreasing in time (`SubMarkovKernelSemigroup.measure_univ_le_of_le`), +because the Chapman--Kolmogorov law integrates a mass at most one against an earlier transition +law. The hypothesis says that the Laplace transform of the transition mass equals the Laplace +transform of the constant observable one; both integrands are integrable and ordered, so they +agree at almost every time, and monotonicity in time upgrades this to every time. + +The converse is immediate from the mass of the exponential weight +(`SubMarkovKernelSemigroup.IsConservative.kernelResolvent_one`, +`SubMarkovKernelSemigroup.IsConservative.ofReal_mul_kernelResolvent_one`), so the criterion is an +equivalence and not merely a sufficient condition. + +No topology on the state space is used. +-/ + +open Filter MeasureTheory ProbabilityTheory Set +open scoped ENNReal NNReal + +noncomputable section + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [MeasurableSpace alpha] (P : SubMarkovKernelSemigroup alpha) + +/-- **The transition mass is nonincreasing in time.** A later transition law is an average of +transition masses at most one against an earlier one. -/ +theorem measure_univ_le_of_le {u v : NNReal} (huv : u ≤ v) (x : alpha) : + P v x univ ≤ P u x univ := by + obtain ⟨w, rfl⟩ := exists_add_of_le huv + rw [P.add_apply' u w x MeasurableSet.univ] + calc ∫⁻ y, P w y univ ∂P u x ≤ ∫⁻ _y, 1 ∂P u x := + lintegral_mono fun y ↦ P.measure_univ_le_one w y + _ = P u x univ := lintegral_one + +/-- The Laplace transform of the constant observable one at a positive shift. -/ +theorem lintegral_expWeight_one {lam : ℝ} (hlam : 0 < lam) : + ∫⁻ t in Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) = ENNReal.ofReal lam⁻¹ := by + have hmass : ∫⁻ _t : ℝ, (1 : ℝ≥0∞) ∂laplaceWeight lam = laplaceWeight lam univ := + lintegral_one + have hweight : ∫⁻ _t : ℝ, (1 : ℝ≥0∞) ∂laplaceWeight lam = + ∫⁻ t in Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * 1 := + lintegral_laplaceWeight lam measurable_const + simp only [mul_one] at hweight + rw [← hweight, hmass, laplaceWeight_univ hlam] + +/-- **Conservativity from the resolvent of the constant observable.** If at one positive shift +the shift times the kernel resolvent of the constant observable one is one, then no transition +law loses mass. -/ +theorem isConservative_of_kernelResolvent_one {lam : ℝ} (hlam : 0 < lam) + (hone : ∀ x, ENNReal.ofReal lam * P.kernelResolvent lam (fun _ ↦ 1) x = 1) : + P.IsConservative := by + have hlam0 : ENNReal.ofReal lam ≠ 0 := by + simpa using hlam + have hlamtop : ENNReal.ofReal lam ≠ ⊤ := ENNReal.ofReal_ne_top + intro t x + -- the resolvent of the constant observable one carries the full weight + have hmass : P.kernelResolvent lam (fun _ ↦ 1) x = ENNReal.ofReal lam⁻¹ := by + have hcancel : (ENNReal.ofReal lam)⁻¹ * + (ENNReal.ofReal lam * P.kernelResolvent lam (fun _ ↦ 1) x) = + P.kernelResolvent lam (fun _ ↦ 1) x := by + rw [← mul_assoc, ENNReal.inv_mul_cancel hlam0 hlamtop, one_mul] + rw [← hcancel, hone x, mul_one, ← ENNReal.ofReal_inv_of_pos hlam] + -- the two integrands: the weighted transition mass and the weight itself + have hprofile : P.kernelResolvent lam (fun _ ↦ 1) x = + ∫⁻ s in Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * s)) * P (Real.toNNReal s) x univ := by + unfold kernelResolvent + exact setLIntegral_congr_fun measurableSet_Ioi fun s _hs ↦ by rw [lintegral_one] + have hle : ∀ s : ℝ, ENNReal.ofReal (Real.exp (-lam * s)) * P (Real.toNNReal s) x univ ≤ + ENNReal.ofReal (Real.exp (-lam * s)) := by + intro s + calc ENNReal.ofReal (Real.exp (-lam * s)) * P (Real.toNNReal s) x univ + ≤ ENNReal.ofReal (Real.exp (-lam * s)) * 1 := + mul_le_mul' le_rfl (P.measure_univ_le_one _ x) + _ = ENNReal.ofReal (Real.exp (-lam * s)) := mul_one _ + have hFtop : (∫⁻ s in Ioi (0 : ℝ), + ENNReal.ofReal (Real.exp (-lam * s)) * P (Real.toNNReal s) x univ) ≠ ⊤ := by + rw [← hprofile, hmass] + exact ENNReal.ofReal_ne_top + have hGF : (∫⁻ s in Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * s))) ≤ + ∫⁻ s in Ioi (0 : ℝ), + ENNReal.ofReal (Real.exp (-lam * s)) * P (Real.toNNReal s) x univ := by + rw [← hprofile, hmass, lintegral_expWeight_one hlam] + have hFG := ae_eq_of_ae_le_of_lintegral_le (μ := volume.restrict (Ioi (0 : ℝ))) + (Eventually.of_forall hle) hFtop (measurable_laplaceDensity lam).aemeasurable hGF + -- almost every positive time carries the full mass + have hae : ∀ᵐ s ∂(volume.restrict (Ioi (0 : ℝ))), P (Real.toNNReal s) x univ = 1 := by + filter_upwards [hFG] with s hs + have hpos : ENNReal.ofReal (Real.exp (-lam * s)) ≠ 0 := by + simp only [ne_eq, ENNReal.ofReal_eq_zero, not_le] + exact Real.exp_pos _ + refine (ENNReal.mul_right_inj hpos ENNReal.ofReal_ne_top).mp ?_ + rw [hs, mul_one] + -- a later time with the full mass forces the full mass at the given time + have hinterval : MeasurableSet (Ioo ((t : ℝ) + 1) ((t : ℝ) + 2)) := measurableSet_Ioo + have hsub : Ioo ((t : ℝ) + 1) ((t : ℝ) + 2) ⊆ Ioi (0 : ℝ) := fun s hs ↦ + lt_trans (by positivity) hs.1 + have haeI : ∀ᵐ s ∂(volume.restrict (Ioo ((t : ℝ) + 1) ((t : ℝ) + 2))), + P (Real.toNNReal s) x univ = 1 := + ae_mono (Measure.restrict_mono hsub le_rfl) hae + have hne : volume.restrict (Ioo ((t : ℝ) + 1) ((t : ℝ) + 2)) ≠ 0 := by + intro hzero + have hmeasure : volume.restrict (Ioo ((t : ℝ) + 1) ((t : ℝ) + 2)) + (Ioo ((t : ℝ) + 1) ((t : ℝ) + 2)) = 0 := by + rw [hzero] + rfl + rw [Measure.restrict_apply_self, Real.volume_Ioo] at hmeasure + exact absurd hmeasure (by + simp only [add_sub_add_left_eq_sub, ENNReal.ofReal_eq_zero, tsub_le_iff_right, zero_add, + Nat.not_ofNat_le_one, not_false_eq_true]) + have : (ae (volume.restrict (Ioo ((t : ℝ) + 1) ((t : ℝ) + 2)))).NeBot := + ae_neBot.mpr hne + obtain ⟨s, hsone, hsmem⟩ := (haeI.and (self_mem_ae_restrict hinterval)).exists + have hts : t ≤ Real.toNNReal s := by + have hcoe : Real.toNNReal (t : ℝ) = t := Real.toNNReal_coe + rw [← hcoe] + exact Real.toNNReal_le_toNNReal (le_of_lt (lt_trans (by linarith) hsmem.1)) + refine le_antisymm (P.measure_univ_le_one t x) ?_ + calc (1 : ℝ≥0∞) = P (Real.toNNReal s) x univ := hsone.symm + _ ≤ P t x univ := P.measure_univ_le_of_le hts x + +/-- **The resolvent of the constant observable one under conservativity.** A conservative +semigroup carries the full mass of the exponential weight, so its kernel resolvent of the +constant observable one is the reciprocal of the shift. -/ +theorem IsConservative.kernelResolvent_one {P : SubMarkovKernelSemigroup alpha} + (hP : P.IsConservative) {lam : ℝ} (hlam : 0 < lam) (x : alpha) : + P.kernelResolvent lam (fun _ ↦ 1) x = ENNReal.ofReal lam⁻¹ := by + rw [← lintegral_expWeight_one hlam] + unfold kernelResolvent + refine setLIntegral_congr_fun measurableSet_Ioi fun t _ht ↦ ?_ + rw [lintegral_one, hP _ x, mul_one] + +/-- **The conservativity criterion is an equivalence.** For a conservative semigroup the shift +times the kernel resolvent of the constant observable one is one at every positive shift, which +is the converse of `isConservative_of_kernelResolvent_one`. -/ +theorem IsConservative.ofReal_mul_kernelResolvent_one {P : SubMarkovKernelSemigroup alpha} + (hP : P.IsConservative) {lam : ℝ} (hlam : 0 < lam) (x : alpha) : + ENNReal.ofReal lam * P.kernelResolvent lam (fun _ ↦ 1) x = 1 := by + rw [hP.kernelResolvent_one hlam x, ← ENNReal.ofReal_mul hlam.le, + mul_inv_cancel₀ hlam.ne', ENNReal.ofReal_one] + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativityAE.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativityAE.lean new file mode 100644 index 0000000000..5fd34f4c3e --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativityAE.lean @@ -0,0 +1,96 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.MeasureTheory.Measure.OpenPos +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator + +/-! +# Conservativity from preservation of constants + +This file extracts the measure-theoretic conservativity consequence of an +associated `L∞` operator that preserves the constant-one class. The conclusion +is initially almost everywhere in the starting point. Continuity of the +transition mass and positivity of the reference measure on nonempty open sets +upgrade it to pointwise conservativity. +-/ + +open MeasureTheory +open ProbabilityTheory +open scoped ENNReal + +namespace MarkovProcess + +variable {α : Type*} [MeasurableSpace α] + +/-- The constant-one class in `L∞`, available without a finiteness assumption +on the reference measure. -/ +noncomputable def oneLpTop (μ : Measure α) : Lp ℝ ∞ μ := + (memLp_top_const (μ := μ) (1 : ℝ)).toLp (fun _ : α => (1 : ℝ)) + +/-- The `L∞` constant-one class is represented by the constant-one function. -/ +theorem coeFn_oneLpTop (μ : Measure α) : + oneLpTop μ =ᵐ[μ] fun _ : α => (1 : ℝ) := + (memLp_top_const (μ := μ) (1 : ℝ)).coeFn_toLp + +namespace SubMarkovKernelSemigroup + +variable (P : SubMarkovKernelSemigroup α) + +/-- Conservativity almost everywhere in the starting point, relative to `μ`. -/ +def IsConservativeAE (μ : Measure α) : Prop := + ∀ t, ∀ᵐ x ∂μ, P t x Set.univ = 1 + +/-- An `L∞` operator family preserves the constant-one equivalence class. -/ +def PreservesOneTop (μ : Measure α) + (T : NNReal → Lp ℝ ∞ μ →L[ℝ] Lp ℝ ∞ μ) : Prop := + ∀ t, T t (oneLpTop μ) = oneLpTop μ + +/-- Association with a subinvariant kernel family and preservation of one imply +conservativity almost everywhere in the starting point. -/ +theorem IsAssociatedTop.isConservativeAE_of_preservesOne + {μ : Measure α} {T : NNReal → Lp ℝ ∞ μ →L[ℝ] Lp ℝ ∞ μ} + (hμ : P.IsSubInvariant μ) (hAssoc : P.IsAssociatedTop μ T) + (hOne : PreservesOneTop μ T) : P.IsConservativeAE μ := by + intro t + have hPres : T t (oneLpTop μ) =ᵐ[μ] oneLpTop μ := + Filter.Eventually.of_forall fun x => congrArg (fun f : Lp ℝ ∞ μ => f x) (hOne t) + have hKernel := kernelIntegral_congr_ae (hμ t) (coeFn_oneLpTop μ) + filter_upwards [hAssoc t (oneLpTop μ), hPres, coeFn_oneLpTop μ, hKernel] with + x hAssocX hPresX hOneX hKernelX + have hIntegral : kernelIntegral (P t) (fun _ : α => (1 : ℝ)) x = 1 := by + calc + kernelIntegral (P t) (fun _ : α => (1 : ℝ)) x = + kernelIntegral (P t) (oneLpTop μ) x := hKernelX.symm + _ = T t (oneLpTop μ) x := hAssocX.symm + _ = oneLpTop μ x := hPresX + _ = 1 := hOneX + have hReal : (P t x Set.univ).toReal = 1 := by + simpa only [kernelIntegral, integral_const, Measure.real_def, smul_eq_mul, mul_one] + using hIntegral + exact (ENNReal.toReal_eq_one_iff _).mp hReal + +/-- If the canonical `L∞` operator family preserves one, then the transition +kernel is conservative almost everywhere in the starting point. -/ +theorem isConservativeAE_of_operatorTop_preservesOne + {μ : Measure α} (hμ : P.IsSubInvariant μ) + (hOne : PreservesOneTop μ (P.operatorTop μ hμ)) : + P.IsConservativeAE μ := + IsAssociatedTop.isConservativeAE_of_preservesOne + (P := P) hμ (P.isAssociatedTop_operatorTop μ hμ) hOne + +/-- Almost-everywhere conservativity becomes pointwise conservativity when +transition mass is continuous and the reference measure is positive on every +nonempty open set. -/ +theorem IsConservativeAE.isConservative_of_continuous_mass + {μ : Measure α} [TopologicalSpace α] [Measure.IsOpenPosMeasure μ] + (hAE : P.IsConservativeAE μ) + (hcont : ∀ t, Continuous fun x => P t x Set.univ) : + P.IsConservative := by + intro t x + exact congrFun (Measure.eq_of_ae_eq (hAE t) (hcont t) continuous_const) x + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/FiniteRestrictionIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/FiniteRestrictionIdentification.lean new file mode 100644 index 0000000000..518be44f14 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/FiniteRestrictionIdentification.lean @@ -0,0 +1,50 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.MeasureTheory.Constructions.Projective +import Mathlib.Probability.Kernel.Composition.MapComap + +/-! +# Identifying path kernels from finite-coordinate restrictions + +A finite kernel on a product path space is determined by all of its finite-coordinate +pushforwards. The proof applies uniqueness of finite projective limits pointwise in the source +parameter. No topology, time order, path regularity, or Markov property is used. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace Kernel + +noncomputable section + +variable {index alpha beta : Type*} [MeasurableSpace alpha] [MeasurableSpace beta] + +/-- Two finite kernels on a product path space agree if all their finite-coordinate pushforwards +agree. -/ +theorem eq_of_map_finiteRestriction_eq + (kappa eta : Kernel beta (index → alpha)) [IsFiniteKernel kappa] + (h : ∀ I : Finset index, + kappa.map I.restrict = eta.map I.restrict) : + kappa = eta := by + ext x : 1 + let family : (I : Finset index) → Measure (I → alpha) := + fun I ↦ (kappa x).map I.restrict + have hkappa : IsProjectiveLimit (kappa x) family := by + intro I + rfl + have heta : IsProjectiveLimit (eta x) family := by + intro I + have hx := congrArg (fun z : Kernel beta (I → alpha) ↦ z x) (h I) + simpa only [Kernel.map_apply _ (Finset.measurable_restrict I) x] using hx.symm + let (I : Finset index) : IsFiniteMeasure (family I) := by + dsimp only [family] + infer_instance + exact hkappa.unique heta + +end +end Kernel +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Integral.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Integral.lean new file mode 100644 index 0000000000..6ae3cf3f63 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Integral.lean @@ -0,0 +1,59 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +import Mathlib.Probability.Kernel.Composition.MeasureComp +import Mathlib.Probability.Kernel.MeasurableIntegral + +/-! +# Integration against a kernel + +This file defines the raw real-valued integral operator associated with a +kernel. Subinvariance of a measure makes this operator independent, almost +everywhere, of the chosen representative of its input. +-/ + +open MeasureTheory +open ProbabilityTheory + +namespace MarkovProcess + +variable {α : Type*} [MeasurableSpace α] + +/-- The raw real-valued integral of `f` against the measure `κ x`. -/ +noncomputable def kernelIntegral (κ : Kernel α α) (f : α → ℝ) (x : α) : ℝ := + ∫ y, f y ∂κ x + +/-- Subinvariance transports an almost-everywhere statement for `μ` to the +kernel measures `κ x`, for almost every `x` with respect to `μ`. -/ +theorem ae_ae_kernel_of_comp_le {μ : Measure α} {κ : Kernel α α} {p : α → Prop} + (hκμ : κ ∘ₘ μ ≤ μ) (hp : ∀ᵐ y ∂μ, p y) : + ∀ᵐ x ∂μ, ∀ᵐ y ∂κ x, p y := by + apply Measure.ae_ae_of_ae_comp + exact Measure.ae_le_iff_absolutelyContinuous.mpr + (Measure.absolutelyContinuous_of_le hκμ) hp + +/-- Under subinvariance, the raw kernel integral depends only on the +`μ`-almost-everywhere equivalence class of its input. -/ +theorem kernelIntegral_congr_ae {μ : Measure α} {κ : Kernel α α} {f g : α → ℝ} + (hκμ : κ ∘ₘ μ ≤ μ) (hfg : f =ᵐ[μ] g) : + kernelIntegral κ f =ᵐ[μ] kernelIntegral κ g := by + filter_upwards [ae_ae_kernel_of_comp_le hκμ hfg] with x hx + exact integral_congr_ae hx + +/-- Under subinvariance, integrating an almost-everywhere strongly measurable +function against `κ x` gives an almost-everywhere strongly measurable function +of `x`. -/ +theorem AEStronglyMeasurable.kernelIntegral {μ : Measure α} {κ : Kernel α α} + {f : α → ℝ} (hf : AEStronglyMeasurable f μ) (hκμ : κ ∘ₘ μ ≤ μ) : + AEStronglyMeasurable (kernelIntegral κ f) μ := by + let hfComp : AEStronglyMeasurable f (κ ∘ₘ μ) := + hf.mono_ac (Measure.absolutelyContinuous_of_le hκμ) + refine ⟨fun x ↦ MarkovProcess.kernelIntegral κ (hfComp.mk f) x, ?_, ?_⟩ + · exact hfComp.stronglyMeasurable_mk.integral_kernel + · filter_upwards [Measure.ae_ae_of_ae_comp hfComp.ae_eq_mk] with x hx + exact integral_congr_ae hx + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/KernelSemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/KernelSemigroup.lean new file mode 100644 index 0000000000..9732b4d84c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/KernelSemigroup.lean @@ -0,0 +1,127 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic + +/-! +# Sub-Markov transition-kernel semigroups + +This file packages jointly measurable, nonnegative-time transition kernels with +the Chapman--Kolmogorov law. Mathlib writes `η.comp κ` for first applying `κ` +and then `η`; consequently the law below is `K (s + t) = (K t).comp (K s)`. + +Conservativity is deliberately a separate predicate. A killed transition +family has mass at most one, while a conservative family has mass exactly one. +-/ + +open Set +open scoped ENNReal ProbabilityTheory + +noncomputable section + +namespace MarkovProcess + +open MeasureTheory ProbabilityTheory + +/-- A jointly measurable sub-Markov transition-kernel semigroup. + +The measurability field is joint in time and starting point. The composition +orientation agrees with the convention that the operator associated with a +kernel `K` sends `f` to `x ↦ ∫ y, f y ∂K x`. +-/ +structure SubMarkovKernelSemigroup (α : Type*) [MeasurableSpace α] where + /-- The transition kernel at a nonnegative time. -/ + kernel : NNReal → Kernel α α + /-- Joint measurability in time and starting point. -/ + measurable_kernel : Measurable fun p : NNReal × α ↦ kernel p.1 p.2 + /-- At time zero the transition kernel is the identity kernel. -/ + kernel_zero : kernel 0 = Kernel.id + /-- The Chapman--Kolmogorov law, in Mathlib's kernel-composition orientation. -/ + kernel_add : ∀ s t, kernel (s + t) = (kernel t).comp (kernel s) + /-- Every transition measure has mass at most one. -/ + isSubMarkovKernel : ∀ t, IsSubMarkovKernel (kernel t) + +namespace SubMarkovKernelSemigroup + +variable {α : Type*} [MeasurableSpace α] + +instance : CoeFun (SubMarkovKernelSemigroup α) + (fun _ ↦ NNReal → Kernel α α) where + coe P := P.kernel + +@[ext] +theorem ext {P Q : SubMarkovKernelSemigroup α} + (h : ∀ t, P t = Q t) : P = Q := by + cases P with + | mk P _ _ _ _ => + cases Q with + | mk Q _ _ _ _ => + have hPQ : P = Q := funext h + cases hPQ + rfl + +variable (P : SubMarkovKernelSemigroup α) + +/-- The transition measures are jointly measurable in time and starting point. -/ +theorem measurable_toMeasure : Measurable fun p : NNReal × α ↦ P p.1 p.2 := + P.measurable_kernel + +/-- Evaluation on a measurable set is jointly measurable in time and start. -/ +theorem measurable_measure {s : Set α} (hs : MeasurableSet s) : + Measurable fun p : NNReal × α ↦ P p.1 p.2 s := + (Measure.measurable_coe hs).comp P.measurable_toMeasure + +@[simp] +theorem zero : P 0 = Kernel.id := + P.kernel_zero + +@[simp] +theorem add (s t : NNReal) : P (s + t) = (P t).comp (P s) := + P.kernel_add s t + +/-- Transition kernels commute under composition because nonnegative times commute. -/ +theorem comp_comm (s t : NNReal) : (P t).comp (P s) = (P s).comp (P t) := by + rw [← P.add, ← P.add, add_comm] + +/-- Chapman--Kolmogorov as equality of the transition measures. -/ +theorem add_apply (s t : NNReal) (x : α) : + P (s + t) x = (P s x).bind (P t) := by + rw [P.add, Kernel.comp_apply] + +/-- Chapman--Kolmogorov evaluated on a measurable set. -/ +theorem add_apply' (s t : NNReal) (x : α) {u : Set α} (hu : MeasurableSet u) : + P (s + t) x u = ∫⁻ y, P t y u ∂P s x := by + rw [P.add, Kernel.comp_apply' _ _ _ hu] + +/-- The tower form of Chapman--Kolmogorov for nonnegative measurable functions. -/ +theorem lintegral_add (s t : NNReal) (x : α) {f : α → ℝ≥0∞} + (hf : Measurable f) : + ∫⁻ y, f y ∂P (s + t) x = ∫⁻ y, ∫⁻ z, f z ∂P t y ∂P s x := by + rw [P.add, Kernel.lintegral_comp _ _ _ hf] + +/-- Every transition measure has mass at most one. -/ +theorem measure_univ_le_one (t : NNReal) (x : α) : P t x univ ≤ 1 := + P.isSubMarkovKernel t x + +/-- Every transition measure assigns mass at most one to every set. -/ +theorem measure_le_one (t : NNReal) (x : α) (s : Set α) : P t x s ≤ 1 := + (P.isSubMarkovKernel t).measure_le_one x s + +/-- A transition-kernel semigroup is conservative when no mass is lost. -/ +def IsConservative : Prop := + ∀ t x, P t x univ = 1 + +namespace IsConservative + +/-- At each time, a conservative transition family is a Mathlib Markov kernel. -/ +theorem isMarkovKernel {P : SubMarkovKernelSemigroup α} (hP : P.IsConservative) + (t : NNReal) : IsMarkovKernel (P t) where + isProbabilityMeasure x := ⟨hP t x⟩ + +end IsConservative + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/KolmogorovMoments.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/KolmogorovMoments.lean new file mode 100644 index 0000000000..cec3c0563c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/KolmogorovMoments.lean @@ -0,0 +1,75 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +import Mathlib.Analysis.SpecialFunctions.Pow.NNReal + +/-! +# Intrinsic Kolmogorov moment bounds for a transition semigroup + +Kolmogorov's continuity criterion is usually imposed on an already constructed coordinate +process. This file states the same criterion directly on the transition semigroup: the +`p`-th moment of the displacement accumulated over a time step `h` is at most `M * h ^ q`, +uniformly in the starting point. + +The predicate is purely a moment bound on the transition kernels. It makes no path-space, +continuity, or stochastic-process claim; the transport of this bound to the canonical +dense-time coordinate process is proved elsewhere. +-/ + +open MeasureTheory +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [PseudoEMetricSpace alpha] [MeasurableSpace alpha] + +/-- A uniform `p`-th moment bound on the displacement of `P` over time `h`, of order `h ^ q`. + +The exponents are constrained by `0 < p` and `1 < q`, exactly the range in which the +Kolmogorov--Chentsov threshold `(q - 1) / p` is a positive Hölder exponent. The bound is demanded for every time `h ≥ 0`, not only +for small `h`; this is stronger than the local criterion the Kolmogorov--Chentsov theorem +needs, and it is what the bridge to `KolmogorovRegular` consumes. -/ +def HasKolmogorovMoments (P : SubMarkovKernelSemigroup alpha) (p q : ℝ) (M : ℝ≥0) : Prop := + 0 < p ∧ 1 < q ∧ + ∀ (h : ℝ≥0) (y : alpha), ∫⁻ z, edist z y ^ p ∂(P h y) ≤ M * (h : ℝ≥0∞) ^ q + +namespace HasKolmogorovMoments + +variable {P : SubMarkovKernelSemigroup alpha} {p q : ℝ} {M : ℝ≥0} + +/-- The moment exponent of a Kolmogorov moment bound is positive. -/ +theorem p_pos (hmom : P.HasKolmogorovMoments p q M) : 0 < p := + hmom.1 + +/-- The time exponent of a Kolmogorov moment bound is strictly larger than one. -/ +theorem one_lt_q (hmom : P.HasKolmogorovMoments p q M) : 1 < q := + hmom.2.1 + +/-- The time exponent of a Kolmogorov moment bound is positive. -/ +theorem q_pos (hmom : P.HasKolmogorovMoments p q M) : 0 < q := + lt_trans zero_lt_one hmom.one_lt_q + +/-- The displacement moment estimate carried by a Kolmogorov moment bound. -/ +theorem lintegral_edist_le (hmom : P.HasKolmogorovMoments p q M) (h : ℝ≥0) (y : alpha) : + ∫⁻ z, edist z y ^ p ∂(P h y) ≤ M * (h : ℝ≥0∞) ^ q := + hmom.2.2 h y + +/-- A Kolmogorov moment bound admits a strictly positive Hölder exponent below the +Kolmogorov--Chentsov threshold `(q - 1) / p`; the witness `(q - 1) / (2 * p)` is used. -/ +theorem exists_holderExponent (hmom : P.HasKolmogorovMoments p q M) : + ∃ gamma : ℝ, 0 < gamma ∧ gamma < (q - 1) / p := by + have hp : 0 < p := hmom.p_pos + have hq : 0 < q - 1 := by linarith only [hmom.one_lt_q] + refine ⟨(q - 1) / (2 * p), div_pos hq (by linarith only [hp]), ?_⟩ + exact div_lt_div_of_pos_left hq hp (by linarith only [hp]) + +end HasKolmogorovMoments + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean new file mode 100644 index 0000000000..ba7bebd656 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean @@ -0,0 +1,216 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop +import Mathlib.MeasureTheory.Function.LpSpace.Basic + +/-! +# Kernel integral operators on real `Lᵖ` + +This file packages the raw kernel integral as continuous linear contractions on +finite-exponent and infinite-exponent real `Lᵖ` spaces. +-/ + +open MeasureTheory +open ProbabilityTheory +open scoped ENNReal + +namespace MarkovProcess + +variable {α : Type*} [MeasurableSpace α] + +private instance fact_one_le_coe_nnreal (p : NNReal) [Fact (1 ≤ p)] : + Fact (1 ≤ (p : ℝ≥0∞)) := ⟨by exact_mod_cast Fact.out⟩ + +/- Head-class caches for the `Lᵖ` carrier. Without them every normed-group +class search on `↥(Lp ℝ p μ)` first tries `AddSubgroup.seminormedAddCommGroup` +and burns a failing search for `SeminormedAddCommGroup (α →ₘ[μ] ℝ)`. -/ +private noncomputable instance cacheSeminormedLp (p : ℝ≥0∞) [Fact (1 ≤ p)] + (μ : Measure α) : SeminormedAddCommGroup (Lp ℝ p μ) := inferInstance + +private noncomputable instance cacheAddCommMonoidLp (p : ℝ≥0∞) [Fact (1 ≤ p)] + (μ : Measure α) : AddCommMonoid (Lp ℝ p μ) := inferInstance + +private noncomputable instance cacheModuleLp (p : ℝ≥0∞) [Fact (1 ≤ p)] + (μ : Measure α) : Module ℝ (Lp ℝ p μ) := inferInstance + +private noncomputable instance cacheTopologicalSpaceLp (p : ℝ≥0∞) [Fact (1 ≤ p)] + (μ : Measure α) : TopologicalSpace (Lp ℝ p μ) := inferInstance + +private theorem ae_integrable_kernel_finite {μ : Measure α} {κ : Kernel α α} + (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) {p : NNReal} + (hp : 1 ≤ p) (f : Lp ℝ (p : ℝ≥0∞) μ) : ∀ᵐ x ∂μ, Integrable f (κ x) := by + let : IsFiniteKernel κ := hκ.isFiniteKernel + have hfComp : MemLp f p (κ ∘ₘ μ) := (Lp.memLp f).mono_measure hκμ + have hFiberEq := Measure.ae_ae_of_ae_comp hfComp.1.ae_eq_mk + have hp0 : (p : ℝ≥0∞) ≠ 0 := by + exact_mod_cast ne_of_gt (zero_lt_one.trans_le hp) + have hpowInt := hfComp.integrable_norm_rpow hp0 ENNReal.coe_ne_top + have hFiberInt := Measure.ae_integrable_of_integrable_comp hpowInt + filter_upwards [hFiberEq, hFiberInt] with x hxEq hxInt + have hxEq' : f =ᵐ[κ x] hfComp.1.mk f := hxEq + have hxMeas : AEStronglyMeasurable f (κ x) := + hfComp.1.stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq'.symm + have hxMemLp : MemLp f p (κ x) := + (integrable_norm_rpow_iff hxMeas hp0 ENNReal.coe_ne_top).mp hxInt + exact hxMemLp.integrable (by exact_mod_cast hp) + +private theorem ae_integrable_kernel_top {μ : Measure α} {κ : Kernel α α} + (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) + (f : Lp ℝ ∞ μ) : ∀ᵐ x ∂μ, Integrable f (κ x) := by + have hCtop : eLpNormEssSup f μ ≠ ∞ := by + rw [← eLpNorm_exponent_top] + exact (Lp.memLp f).2.ne + have hCcoe : ((eLpNormEssSup f μ).toNNReal : ℝ≥0∞) = eLpNormEssSup f μ := + ENNReal.coe_toNNReal hCtop + have hFiberEq : ∀ᵐ x ∂μ, f =ᵐ[κ x] (Lp.aestronglyMeasurable f).mk f := + ae_ae_kernel_of_comp_le hκμ (Lp.aestronglyMeasurable f).ae_eq_mk + have hBound := ae_ae_kernel_of_comp_le hκμ (enorm_ae_le_eLpNormEssSup f μ) + let : IsFiniteKernel κ := hκ.isFiniteKernel + filter_upwards [hFiberEq, hBound] with x hxEq hxBound + have hxAS : AEStronglyMeasurable f (κ x) := + (Lp.aestronglyMeasurable f).stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq.symm + apply MemLp.integrable (q := ∞) le_top + apply memLp_top_of_bound_enorm hxAS (eLpNormEssSup f μ).toNNReal + simpa only [hCcoe] using hxBound + +private theorem kernelIntegral_add_ae {μ : Measure α} {κ : Kernel α α} + {f g : α → ℝ} (hf : ∀ᵐ x ∂μ, Integrable f (κ x)) + (hg : ∀ᵐ x ∂μ, Integrable g (κ x)) : + kernelIntegral κ (f + g) =ᵐ[μ] kernelIntegral κ f + kernelIntegral κ g := by + filter_upwards [hf, hg] with x hfx hgx + exact integral_add hfx hgx + +/-- The kernel integral as a contraction on finite-exponent real `Lᵖ`. -/ +noncomputable def kernelLpFinite (μ : Measure α) (κ : Kernel α α) + (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) (p : NNReal) + [Fact (1 ≤ p)] : Lp ℝ (p : ℝ≥0∞) μ →L[ℝ] Lp ℝ (p : ℝ≥0∞) μ := + LinearMap.mkContinuous + { toFun := fun f ↦ (MemLp.kernelIntegral hκ hκμ Fact.out (Lp.memLp f)).toLp + (kernelIntegral κ f) + map_add' := fun f g ↦ by + apply Lp.ext + refine (MemLp.coeFn_toLp _).trans ?_ + refine (kernelIntegral_congr_ae hκμ (Lp.coeFn_add f g)).trans ?_ + exact (kernelIntegral_add_ae + (ae_integrable_kernel_finite hκ hκμ Fact.out f) + (ae_integrable_kernel_finite hκ hκμ Fact.out g)).trans + (((MemLp.coeFn_toLp _).add (MemLp.coeFn_toLp _)).symm.trans + (Lp.coeFn_add _ _).symm) + map_smul' := fun c f ↦ by + apply Lp.ext + refine (MemLp.coeFn_toLp _).trans ?_ + refine (kernelIntegral_congr_ae hκμ (Lp.coeFn_smul c f)).trans ?_ + have hsmul : kernelIntegral κ (c • f) =ᵐ[μ] + c • kernelIntegral κ f := by + filter_upwards with x + unfold kernelIntegral + simpa only [Pi.smul_apply, smul_eq_mul] using + (integral_smul c (fun y ↦ f y) : + (∫ y, c • f y ∂κ x) = c • ∫ y, f y ∂κ x) + refine hsmul.trans ?_ + exact ((MemLp.coeFn_toLp + (MemLp.kernelIntegral hκ hκμ Fact.out (Lp.memLp f))).symm.const_smul c).trans + (Lp.coeFn_smul c _).symm } + 1 fun f ↦ by + change ‖(MemLp.kernelIntegral hκ hκμ Fact.out (Lp.memLp f)).toLp + (kernelIntegral κ f)‖ ≤ 1 * ‖f‖ + rw [Lp.norm_toLp, Lp.norm_def, one_mul] + exact ENNReal.toReal_mono (Lp.eLpNorm_ne_top f) + (eLpNorm_kernelIntegral_le hκ hκμ Fact.out (Lp.memLp f)) + +/-- The finite-exponent operator is represented by the raw kernel integral. -/ +theorem coeFn_kernelLpFinite (μ : Measure α) (κ : Kernel α α) + (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) (p : NNReal) + [Fact (1 ≤ p)] (f : Lp ℝ (p : ℝ≥0∞) μ) : + kernelLpFinite μ κ hκ hκμ p f =ᵐ[μ] kernelIntegral κ f := by + rw [kernelLpFinite, LinearMap.mkContinuous_apply] + exact MemLp.coeFn_toLp + (MemLp.kernelIntegral hκ hκμ Fact.out (Lp.memLp f)) + +/-- The finite-exponent operator contracts the norm of every input. -/ +theorem norm_kernelLpFinite_apply_le (μ : Measure α) (κ : Kernel α α) + (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) (p : NNReal) + [Fact (1 ≤ p)] (f : Lp ℝ (p : ℝ≥0∞) μ) : + ‖kernelLpFinite μ κ hκ hκμ p f‖ ≤ ‖f‖ := by + change ‖(MemLp.kernelIntegral hκ hκμ Fact.out (Lp.memLp f)).toLp + (kernelIntegral κ f)‖ ≤ ‖f‖ + rw [Lp.norm_toLp, Lp.norm_def] + exact ENNReal.toReal_mono (Lp.eLpNorm_ne_top f) + (eLpNorm_kernelIntegral_le hκ hκμ Fact.out (Lp.memLp f)) + +/-- The finite-exponent kernel operator has operator norm at most one. -/ +theorem norm_kernelLpFinite_le (μ : Measure α) (κ : Kernel α α) + (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) (p : NNReal) + [Fact (1 ≤ p)] : ‖kernelLpFinite μ κ hκ hκμ p‖ ≤ 1 := by + apply ContinuousLinearMap.opNorm_le_bound _ zero_le_one + intro f + simpa only [one_mul] using norm_kernelLpFinite_apply_le μ κ hκ hκμ p f + +/-- The kernel integral as a contraction on real `L^∞`. -/ +noncomputable def kernelLpTop (μ : Measure α) (κ : Kernel α α) + (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) : + Lp ℝ ∞ μ →L[ℝ] Lp ℝ ∞ μ := + LinearMap.mkContinuous + { toFun := fun f ↦ (MemLp.kernelIntegral_top hκ hκμ (Lp.memLp f)).toLp + (kernelIntegral κ f) + map_add' := fun f g ↦ by + apply Lp.ext + refine (MemLp.coeFn_toLp _).trans ?_ + refine (kernelIntegral_congr_ae hκμ (Lp.coeFn_add f g)).trans ?_ + exact (kernelIntegral_add_ae + (ae_integrable_kernel_top hκ hκμ f) + (ae_integrable_kernel_top hκ hκμ g)).trans + (((MemLp.coeFn_toLp _).add (MemLp.coeFn_toLp _)).symm.trans + (Lp.coeFn_add _ _).symm) + map_smul' := fun c f ↦ by + apply Lp.ext + refine (MemLp.coeFn_toLp _).trans ?_ + refine (kernelIntegral_congr_ae hκμ (Lp.coeFn_smul c f)).trans ?_ + have hsmul : kernelIntegral κ (c • f) =ᵐ[μ] + c • kernelIntegral κ f := by + filter_upwards with x + unfold kernelIntegral + simpa only [Pi.smul_apply, smul_eq_mul] using + (integral_smul c (fun y ↦ f y) : + (∫ y, c • f y ∂κ x) = c • ∫ y, f y ∂κ x) + refine hsmul.trans ?_ + exact ((MemLp.coeFn_toLp + (MemLp.kernelIntegral_top hκ hκμ (Lp.memLp f))).symm.const_smul c).trans + (Lp.coeFn_smul c _).symm } + 1 fun f ↦ by + change ‖(MemLp.kernelIntegral_top hκ hκμ (Lp.memLp f)).toLp + (kernelIntegral κ f)‖ ≤ 1 * ‖f‖ + rw [Lp.norm_toLp, Lp.norm_def, one_mul] + exact ENNReal.toReal_mono (Lp.eLpNorm_ne_top f) + (eLpNorm_kernelIntegral_top_le hκ hκμ f) + +/-- The infinite-exponent operator is represented by the raw kernel integral. -/ +theorem coeFn_kernelLpTop (μ : Measure α) (κ : Kernel α α) + (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) (f : Lp ℝ ∞ μ) : + kernelLpTop μ κ hκ hκμ f =ᵐ[μ] kernelIntegral κ f := by + rw [kernelLpTop, LinearMap.mkContinuous_apply] + exact MemLp.coeFn_toLp (MemLp.kernelIntegral_top hκ hκμ (Lp.memLp f)) + +/-- The infinite-exponent operator contracts the norm of every input. -/ +theorem norm_kernelLpTop_apply_le (μ : Measure α) (κ : Kernel α α) + (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) (f : Lp ℝ ∞ μ) : + ‖kernelLpTop μ κ hκ hκμ f‖ ≤ ‖f‖ := by + change ‖(MemLp.kernelIntegral_top hκ hκμ (Lp.memLp f)).toLp + (kernelIntegral κ f)‖ ≤ ‖f‖ + rw [Lp.norm_toLp, Lp.norm_def] + exact ENNReal.toReal_mono (Lp.eLpNorm_ne_top f) + (eLpNorm_kernelIntegral_top_le hκ hκμ f) + +/-- The infinite-exponent kernel operator has operator norm at most one. -/ +theorem norm_kernelLpTop_le (μ : Measure α) (κ : Kernel α α) + (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) : + ‖kernelLpTop μ κ hκ hκμ‖ ≤ 1 := by + apply ContinuousLinearMap.opNorm_le_bound _ zero_le_one + intro f + simpa only [one_mul] using norm_kernelLpTop_apply_le μ κ hκ hκμ f + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpConsistency.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpConsistency.lean new file mode 100644 index 0000000000..0bd80e010f --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpConsistency.lean @@ -0,0 +1,63 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp + +/-! +# Cross-exponent consistency of kernel integral operators + +The finite- and infinite-exponent operators are packages of the same raw +kernel integral. Consequently their representatives agree almost everywhere +whenever their inputs do, even when the inputs and outputs inhabit different +`Lp` types. +-/ + +open MeasureTheory +open ProbabilityTheory +open scoped ENNReal ProbabilityTheory + +namespace MarkovProcess + +variable {α : Type*} [MeasurableSpace α] + +/-- Finite-exponent kernel operators at possibly different exponents have +almost-everywhere equal representatives on almost-everywhere equal inputs. -/ +theorem kernelLpFinite_consistent + (μ : Measure α) (κ : Kernel α α) (hκ : IsSubMarkovKernel κ) + (hκμ : κ ∘ₘ μ ≤ μ) (p q : NNReal) [Fact (1 ≤ p)] [Fact (1 ≤ q)] + (f : Lp ℝ (p : ℝ≥0∞) μ) (g : Lp ℝ (q : ℝ≥0∞) μ) + (hfg : f =ᵐ[μ] g) : + kernelLpFinite μ κ hκ hκμ p f =ᵐ[μ] + kernelLpFinite μ κ hκ hκμ q g := by + exact (coeFn_kernelLpFinite μ κ hκ hκμ p f).trans + ((kernelIntegral_congr_ae hκμ hfg).trans + (coeFn_kernelLpFinite μ κ hκ hκμ q g).symm) + +/-- The finite-exponent and infinite-exponent packages have almost-everywhere +equal representatives on almost-everywhere equal inputs. -/ +theorem kernelLpFinite_consistent_top + (μ : Measure α) (κ : Kernel α α) (hκ : IsSubMarkovKernel κ) + (hκμ : κ ∘ₘ μ ≤ μ) (p : NNReal) [Fact (1 ≤ p)] + (f : Lp ℝ (p : ℝ≥0∞) μ) (g : Lp ℝ ∞ μ) + (hfg : f =ᵐ[μ] g) : + kernelLpFinite μ κ hκ hκμ p f =ᵐ[μ] + kernelLpTop μ κ hκ hκμ g := by + exact (coeFn_kernelLpFinite μ κ hκ hκμ p f).trans + ((kernelIntegral_congr_ae hκμ hfg).trans + (coeFn_kernelLpTop μ κ hκ hκμ g).symm) + +/-- Symmetric orientation of `kernelLpFinite_consistent_top`. -/ +theorem kernelLpTop_consistent_finite + (μ : Measure α) (κ : Kernel α α) (hκ : IsSubMarkovKernel κ) + (hκμ : κ ∘ₘ μ ≤ μ) (p : NNReal) [Fact (1 ≤ p)] + (f : Lp ℝ ∞ μ) (g : Lp ℝ (p : ℝ≥0∞) μ) + (hfg : f =ᵐ[μ] g) : + kernelLpTop μ κ hκ hκμ f =ᵐ[μ] + kernelLpFinite μ κ hκ hκμ p g := by + exact (coeFn_kernelLpTop μ κ hκ hκμ f).trans + ((kernelIntegral_congr_ae hκμ hfg).trans + (coeFn_kernelLpFinite μ κ hκ hκμ p g).symm) + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean new file mode 100644 index 0000000000..e027cc772c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean @@ -0,0 +1,123 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +import Mathlib.MeasureTheory.Function.L1Space.Integrable +import Mathlib.MeasureTheory.Function.LpSeminorm.CompareExp +import Mathlib.Probability.Kernel.Composition.IntegralCompProd + +/-! +# Finite-exponent contraction for sub-Markov kernels + +This file proves the scalar subprobability estimate behind contraction of a +sub-Markov kernel on finite `Lᵖ` spaces, and its fibrewise integrated form. +-/ + +open MeasureTheory +open ProbabilityTheory +open scoped ENNReal ProbabilityTheory + +namespace MarkovProcess + +variable {α : Type*} [MeasurableSpace α] + +/-- On a finite measure of mass at most one, the `L¹` seminorm is bounded by +every finite `Lᵖ` seminorm with `p ≥ 1`. -/ +theorem eLpNorm_one_le_of_measure_univ_le_one {ν : Measure α} {f : α → ℝ} + [IsFiniteMeasure ν] {p : NNReal} (hp : 1 ≤ p) (hν : ν Set.univ ≤ 1) + (hf : AEStronglyMeasurable f ν) : + eLpNorm f 1 ν ≤ eLpNorm f p ν := by + have hcompare := eLpNorm_le_eLpNorm_mul_rpow_measure_univ + (μ := ν) (f := f) (p := (1 : ℝ≥0∞)) (q := (p : ℝ≥0∞)) + (by exact_mod_cast hp) hf + calc + eLpNorm f 1 ν + ≤ eLpNorm f p ν * ν Set.univ ^ (1 - 1 / (p : ℝ)) := by + simpa using hcompare + _ ≤ eLpNorm f p ν * 1 := by + gcongr + calc + ν Set.univ ^ (1 - 1 / (p : ℝ)) + ≤ (1 : ℝ≥0∞) ^ (1 - 1 / (p : ℝ)) := by + exact ENNReal.rpow_le_rpow hν (by + rw [sub_nonneg, div_le_one (by exact_mod_cast zero_lt_one.trans_le hp)] + exact_mod_cast hp) + _ = 1 := ENNReal.one_rpow _ + _ = eLpNorm f p ν := mul_one _ + +/-- Jensen's power estimate for a finite subprobability measure. This form is +well suited to fibrewise use because both sides take values in `ℝ≥0∞`. -/ +theorem enorm_integral_rpow_le_lintegral_enorm_rpow + {ν : Measure α} [IsFiniteMeasure ν] {f : α → ℝ} {p : NNReal} + (hp : 1 ≤ p) (hν : ν Set.univ ≤ 1) (hf : MemLp f p ν) : + ‖∫ y, f y ∂ν‖ₑ ^ (p : ℝ) ≤ ∫⁻ y, ‖f y‖ₑ ^ (p : ℝ) ∂ν := by + have hp0 : p ≠ 0 := ne_of_gt (zero_lt_one.trans_le hp) + have hnorm : ‖∫ y, f y ∂ν‖ₑ ≤ eLpNorm f p ν := by + calc + ‖∫ y, f y ∂ν‖ₑ ≤ ∫⁻ y, ‖f y‖ₑ ∂ν := enorm_integral_le_lintegral_enorm f + _ = eLpNorm f 1 ν := eLpNorm_one_eq_lintegral_enorm.symm + _ ≤ eLpNorm f p ν := eLpNorm_one_le_of_measure_univ_le_one hp hν hf.1 + calc + ‖∫ y, f y ∂ν‖ₑ ^ (p : ℝ) ≤ eLpNorm f p ν ^ (p : ℝ) := by + exact ENNReal.rpow_le_rpow hnorm (by positivity) + _ = ∫⁻ y, ‖f y‖ₑ ^ (p : ℝ) ∂ν := eLpNorm_nnreal_pow_eq_lintegral hp0 + +/-- The integrated fibrewise power estimate for a sub-Markov kernel. -/ +theorem lintegral_enorm_kernelIntegral_rpow_le + {μ : Measure α} {κ : Kernel α α} (hκ : IsSubMarkovKernel κ) + (hκμ : κ ∘ₘ μ ≤ μ) {f : α → ℝ} {p : NNReal} + (hp : 1 ≤ p) (hf : MemLp f p μ) : + ∫⁻ x, ‖kernelIntegral κ f x‖ₑ ^ (p : ℝ) ∂μ + ≤ ∫⁻ y, ‖f y‖ₑ ^ (p : ℝ) ∂μ := by + let : IsFiniteKernel κ := hκ.isFiniteKernel + have hfComp : MemLp f p (κ ∘ₘ μ) := hf.mono_measure hκμ + have hfFiber : ∀ᵐ x ∂μ, MemLp f p (κ x) := by + have hFiberEq := Measure.ae_ae_of_ae_comp hfComp.1.ae_eq_mk + have hp0 : (p : ℝ≥0∞) ≠ 0 := by + exact_mod_cast ne_of_gt (zero_lt_one.trans_le hp) + have hpowInt := hfComp.integrable_norm_rpow hp0 ENNReal.coe_ne_top + have hFiberInt := Measure.ae_integrable_of_integrable_comp hpowInt + filter_upwards [hFiberEq, hFiberInt] with x hxEq hxInt + have hxEq' : f =ᵐ[κ x] hfComp.1.mk f := hxEq + have hxMeas : AEStronglyMeasurable f (κ x) := + hfComp.1.stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq'.symm + exact (integrable_norm_rpow_iff hxMeas hp0 ENNReal.coe_ne_top).mp hxInt + calc + ∫⁻ x, ‖kernelIntegral κ f x‖ₑ ^ (p : ℝ) ∂μ + ≤ ∫⁻ x, ∫⁻ y, ‖f y‖ₑ ^ (p : ℝ) ∂κ x ∂μ := by + refine lintegral_mono_ae ?_ + filter_upwards [hfFiber] with x hx + exact enorm_integral_rpow_le_lintegral_enorm_rpow hp (hκ x) hx + _ = ∫⁻ y, ‖f y‖ₑ ^ (p : ℝ) ∂(κ ∘ₘ μ) := by + symm + exact Measure.lintegral_bind (Kernel.aemeasurable κ) + (hfComp.1.enorm.pow_const (p : ℝ)) + _ ≤ ∫⁻ y, ‖f y‖ₑ ^ (p : ℝ) ∂μ := + lintegral_mono' hκμ le_rfl + +/-- A sub-Markov kernel which is subinvariant for `μ` is contractive on every +finite `Lᵖ` seminorm, `1 ≤ p < ∞`. -/ +theorem eLpNorm_kernelIntegral_le + {μ : Measure α} {κ : Kernel α α} (hκ : IsSubMarkovKernel κ) + (hκμ : κ ∘ₘ μ ≤ μ) {f : α → ℝ} {p : NNReal} + (hp : 1 ≤ p) (hf : MemLp f p μ) : + eLpNorm (kernelIntegral κ f) p μ ≤ eLpNorm f p μ := by + have hp0 : p ≠ 0 := ne_of_gt (zero_lt_one.trans_le hp) + rw [eLpNorm_nnreal_eq_lintegral hp0, eLpNorm_nnreal_eq_lintegral hp0] + apply ENNReal.rpow_le_rpow + · exact lintegral_enorm_kernelIntegral_rpow_le hκ hκμ hp hf + · positivity + +/-- The kernel integral of an `Lᵖ` function is again in `Lᵖ` for every finite +exponent `p ≥ 1`. -/ +theorem MemLp.kernelIntegral + {μ : Measure α} {κ : Kernel α α} (hκ : IsSubMarkovKernel κ) + (hκμ : κ ∘ₘ μ ≤ μ) {f : α → ℝ} {p : NNReal} + (hp : 1 ≤ p) (hf : MemLp f p μ) : + MemLp (kernelIntegral κ f) p μ := by + refine ⟨AEStronglyMeasurable.kernelIntegral hf.1 hκμ, ?_⟩ + exact (eLpNorm_kernelIntegral_le hκ hκμ hp hf).trans_lt hf.2 + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpTop.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpTop.lean new file mode 100644 index 0000000000..17765fbd34 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpTop.lean @@ -0,0 +1,69 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +import Mathlib.MeasureTheory.Function.LpSeminorm.Basic + +/-! +# The kernel integral on `L^∞` + +This file proves the real-valued `L^∞` contraction estimate for integration +against a sub-Markov kernel preserving a subinvariant measure. The operator +itself is packaged as a continuous linear map by `kernelLpTop` in +`Kernel/Lp.lean`. +-/ + +open MeasureTheory +open ProbabilityTheory +open scoped ENNReal + +namespace MarkovProcess + +variable {α : Type*} [MeasurableSpace α] + +/-- Integrating a function bounded almost everywhere by `C` against a +sub-Markov kernel measure preserves that bound. -/ +theorem enorm_kernelIntegral_le_of_ae {κ : ProbabilityTheory.Kernel α α} + (hκ : IsSubMarkovKernel κ) {f : α → ℝ} {C : ℝ≥0∞} {x : α} + (hf : ∀ᵐ y ∂κ x, ‖f y‖ₑ ≤ C) : + ‖kernelIntegral κ f x‖ₑ ≤ C := by + calc + ‖kernelIntegral κ f x‖ₑ ≤ ∫⁻ y, ‖f y‖ₑ ∂κ x := + enorm_integral_le_lintegral_enorm f + _ ≤ ∫⁻ _y, C ∂κ x := lintegral_mono_ae hf + _ = C * κ x Set.univ := lintegral_const C + _ ≤ C * 1 := mul_le_mul_right (hκ.measure_le_one x Set.univ) C + _ = C := mul_one C + +/-- The essential-supremum bound for `f` bounds its kernel integral almost +everywhere under subinvariance. -/ +theorem enorm_kernelIntegral_ae_le_eLpNormEssSup {μ : Measure α} + {κ : ProbabilityTheory.Kernel α α} (hκ : IsSubMarkovKernel κ) + (hκμ : κ ∘ₘ μ ≤ μ) (f : α → ℝ) : + ∀ᵐ x ∂μ, ‖kernelIntegral κ f x‖ₑ ≤ eLpNormEssSup f μ := by + filter_upwards + [ae_ae_kernel_of_comp_le hκμ (enorm_ae_le_eLpNormEssSup f μ)] with x hx + exact enorm_kernelIntegral_le_of_ae hκ hx + +/-- Integration against a sub-Markov kernel is a contraction for the raw +`L^∞` seminorm under subinvariance. -/ +theorem eLpNorm_kernelIntegral_top_le {μ : Measure α} + {κ : ProbabilityTheory.Kernel α α} (hκ : IsSubMarkovKernel κ) + (hκμ : κ ∘ₘ μ ≤ μ) (f : α → ℝ) : + eLpNorm (kernelIntegral κ f) ∞ μ ≤ eLpNorm f ∞ μ := by + rw [eLpNorm_exponent_top, eLpNorm_exponent_top] + exact eLpNormEssSup_le_of_ae_enorm_bound + (enorm_kernelIntegral_ae_le_eLpNormEssSup hκ hκμ f) + +/-- Integration against a sub-Markov kernel sends `L^∞` functions to +`L^∞` functions under subinvariance. -/ +theorem MemLp.kernelIntegral_top {μ : Measure α} + {κ : ProbabilityTheory.Kernel α α} (hκ : IsSubMarkovKernel κ) + (hκμ : κ ∘ₘ μ ≤ μ) {f : α → ℝ} (hf : MemLp f ∞ μ) : + MemLp (kernelIntegral κ f) ∞ μ := by + refine ⟨AEStronglyMeasurable.kernelIntegral hf.aestronglyMeasurable hκμ, ?_⟩ + exact (eLpNorm_kernelIntegral_top_le hκ hκμ f).trans_lt hf.2 + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/MeasurableRadonFamily.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/MeasurableRadonFamily.lean new file mode 100644 index 0000000000..2e9cd5c765 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/MeasurableRadonFamily.lean @@ -0,0 +1,165 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.MeasureTheory.Integral.RieszMarkovKakutani.Real +import Mathlib.MeasureTheory.Measure.GiryMonad + +/-! +# Measurability of finite Radon measure families + +On a second-countable locally compact Hausdorff space, a family of finite +regular measures is measurable when integration against every compactly +supported real continuous function is measurable. The proof uses compact +exhaustions and Urysohn cutoffs to make every open-set evaluation a countable +supremum of measurable test integrals, then applies Mathlib's Giry +π-system criterion. + +The compact exhaustion and cutoff choices are private implementation details. +-/ + +open scoped CompactlySupported ENNReal NNReal Topology +open Set MeasureTheory TopologicalSpace + +namespace MeasureTheory + +namespace MeasurableRadonFamily + +variable {X : Type*} [TopologicalSpace X] [T2Space X] [LocallyCompactSpace X] + [SecondCountableTopology X] [MeasurableSpace X] [BorelSpace X] + +private noncomputable def compactSet (U : Set X) (hU : IsOpen U) (n : ℕ) : Set X := by + letI := hU.locallyCompactSpace + exact Subtype.val '' CompactExhaustion.choice U n + +omit [T2Space X] [MeasurableSpace X] [BorelSpace X] in +private lemma compactSet_isCompact (U : Set X) (hU : IsOpen U) (n : ℕ) : + IsCompact (compactSet U hU n) := by + let := hU.locallyCompactSpace + exact (CompactExhaustion.choice U).isCompact n |>.image continuous_subtype_val + +omit [T2Space X] [MeasurableSpace X] [BorelSpace X] in +private lemma compactSet_subset (U : Set X) (hU : IsOpen U) (n : ℕ) : + compactSet U hU n ⊆ U := + image_subset_iff.mpr fun x _ ↦ x.property + +omit [T2Space X] [MeasurableSpace X] [BorelSpace X] in +private lemma iUnion_compactSet (U : Set X) (hU : IsOpen U) : + ⋃ n, compactSet U hU n = U := by + let := hU.locallyCompactSpace + ext x + simp only [compactSet, mem_iUnion, mem_image] + constructor + · rintro ⟨n, y, -, rfl⟩ + exact y.property + · intro hx + let y : U := ⟨x, hx⟩ + obtain ⟨n, hn⟩ := (CompactExhaustion.choice U).exists_mem y + exact ⟨n, y, hn, rfl⟩ + +omit [T2Space X] [MeasurableSpace X] [BorelSpace X] in +private lemma compactSet_mono (U : Set X) (hU : IsOpen U) : + Monotone (compactSet U hU) := by + let := hU.locallyCompactSpace + intro m n hmn + exact image_mono ((CompactExhaustion.choice U).subset hmn) + +private noncomputable def openCutoff (U : Set X) (hU : IsOpen U) (n : ℕ) : C_c(X, ℝ) := by + choose f hf using exists_continuousMap_one_of_isCompact_subset_isOpen + (compactSet_isCompact U hU n) hU (compactSet_subset U hU n) + exact ⟨f, hasCompactSupport_def.mpr hf.2.1⟩ + +omit [MeasurableSpace X] [BorelSpace X] in +private lemma cutoff_eq_one (U : Set X) (hU : IsOpen U) (n : ℕ) : + Set.EqOn (openCutoff U hU n) 1 (compactSet U hU n) := by + unfold openCutoff + exact Classical.choose_spec + (exists_continuousMap_one_of_isCompact_subset_isOpen + (compactSet_isCompact U hU n) hU (compactSet_subset U hU n)) |>.1 + +omit [MeasurableSpace X] [BorelSpace X] in +private lemma cutoff_tsupport_subset (U : Set X) (hU : IsOpen U) (n : ℕ) : + tsupport (openCutoff U hU n) ⊆ U := by + unfold openCutoff + exact Classical.choose_spec + (exists_continuousMap_one_of_isCompact_subset_isOpen + (compactSet_isCompact U hU n) hU (compactSet_subset U hU n)) |>.2.2.1 + +omit [MeasurableSpace X] [BorelSpace X] in +private lemma cutoff_mem_Icc (U : Set X) (hU : IsOpen U) (n : ℕ) (x : X) : + openCutoff U hU n x ∈ Set.Icc (0 : ℝ) 1 := by + unfold openCutoff + exact Classical.choose_spec + (exists_continuousMap_one_of_isCompact_subset_isOpen + (compactSet_isCompact U hU n) hU (compactSet_subset U hU n)) |>.2.2.2 x + +private lemma measure_open_eq_iSup_integral_cutoff (U : Set X) (hU : IsOpen U) + (ν : Measure X) [IsFiniteMeasure ν] : + ν U = ⨆ n, ENNReal.ofReal (∫ x, openCutoff U hU n x ∂ν) := by + apply le_antisymm + · have hmeasure : ν U = ⨆ n, ν (compactSet U hU n) := by + calc + ν U = ν (⋃ n, compactSet U hU n) := congrArg ν (iUnion_compactSet U hU).symm + _ = ⨆ n, ν (compactSet U hU n) := (compactSet_mono U hU).measure_iUnion + rw [hmeasure] + refine iSup_le fun n ↦ ?_ + refine le_trans ?_ (le_iSup (fun n ↦ ENNReal.ofReal (∫ x, openCutoff U hU n x ∂ν)) n) + rw [ENNReal.le_ofReal_iff_toReal_le (measure_ne_top _ _) (integral_nonneg + fun x ↦ (cutoff_mem_Icc U hU n x).1)] + rw [← measureReal_def, ← integral_indicator_one (compactSet_isCompact U hU n).measurableSet] + refine integral_mono ?_ (openCutoff U hU n).integrable fun x ↦ ?_ + · exact + (continuousOn_const.integrableOn_compact + (compactSet_isCompact U hU n)).integrable_indicator + (compactSet_isCompact U hU n).measurableSet + · by_cases hx : x ∈ compactSet U hU n + · rw [indicator_of_mem hx, Pi.one_apply, cutoff_eq_one U hU n hx, Pi.one_apply] + · exact (indicator_of_notMem hx _).trans_le (cutoff_mem_Icc U hU n x).1 + · refine iSup_le fun n ↦ ?_ + rw [ENNReal.ofReal_le_iff_le_toReal (measure_ne_top _ _)] + rw [← measureReal_def, ← integral_indicator_one hU.measurableSet] + refine integral_mono (openCutoff U hU n).integrable ?_ fun x ↦ ?_ + · exact IntegrableOn.integrable_indicator integrableOn_const hU.measurableSet + · by_cases hx : x ∈ tsupport (openCutoff U hU n) + · simp only [indicator_of_mem (cutoff_tsupport_subset U hU n hx), Pi.one_apply] + exact (cutoff_mem_Icc U hU n x).2 + · rw [image_eq_zero_of_notMem_tsupport hx] + exact (indicator_nonneg fun _ _ ↦ zero_le_one) x + +end MeasurableRadonFamily + +/-- A finite regular measure family is Giry-measurable when all of its +compactly supported continuous test integrals are measurable. -/ +theorem measurable_measure_of_measurable_integral_compactlySupported + {Q X : Type*} [MeasurableSpace Q] + [TopologicalSpace X] [T2Space X] [LocallyCompactSpace X] + [SecondCountableTopology X] [MeasurableSpace X] [BorelSpace X] + (μ : Q → Measure X) [∀ q, (μ q).Regular] [∀ q, IsFiniteMeasure (μ q)] + (hμ : ∀ f : C_c(X, ℝ), Measurable fun q ↦ ∫ x, f x ∂μ q) : + Measurable μ := by + refine Measurable.measure_of_isPiSystem (S := generatePiSystem (countableBasis X)) + (by rw [BorelSpace.measurable_eq (α := X), (isBasis_countableBasis X).borel_eq_generateFrom, + generateFrom_generatePiSystem_eq]) + (isPiSystem_generatePiSystem _) ?_ ?_ + · intro U hU + have hU_open : IsOpen U := by + induction hU with + | base h => exact isOpen_of_mem_countableBasis h + | inter _ _ _ hs ht => exact hs.inter ht + have heval : (fun q ↦ μ q U) = fun q ↦ + ⨆ n, ENNReal.ofReal (∫ x, MeasurableRadonFamily.openCutoff U hU_open n x ∂μ q) := by + funext q + exact MeasurableRadonFamily.measure_open_eq_iSup_integral_cutoff U hU_open (μ q) + rw [heval] + exact Measurable.iSup fun n ↦ (hμ (MeasurableRadonFamily.openCutoff U hU_open n)).ennreal_ofReal + · have heval : (fun q ↦ μ q Set.univ) = fun q ↦ + ⨆ n, ENNReal.ofReal + (∫ x, MeasurableRadonFamily.openCutoff Set.univ isOpen_univ n x ∂μ q) := by + funext q + exact MeasurableRadonFamily.measure_open_eq_iSup_integral_cutoff Set.univ isOpen_univ (μ q) + rw [heval] + exact Measurable.iSup fun n ↦ + (hμ (MeasurableRadonFamily.openCutoff Set.univ isOpen_univ n)).ennreal_ofReal + +end MeasureTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointConservative.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointConservative.lean new file mode 100644 index 0000000000..d326632bd9 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointConservative.lean @@ -0,0 +1,82 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal + +/-! +# A conservative resolvent keeps the compactified process in the live space + +The Laplace transform of the finite exit time from the live part of the compactification is one +minus the shift times the kernel resolvent of the constant observable one +(`Kernel/OnePointKilled.lean`). When that product is one, the transform vanishes, so the exit +time is almost surely infinite: the compactified process started at a live point almost surely +never reaches the added point +(`PositiveC0ContractiveResolvent.OnePointRegular.ae_exitTime_eq_top`). No kernel into the +continuous paths of the live space is produced here; the statement is about the law of the +compactified process. + +The regularity data of the compactification are an explicit hypothesis, as everywhere the +continuous-path process is formed. +-/ + +open Filter MeasureTheory ProbabilityTheory Set Topology +open scoped ENNReal NNReal ZeroAtInfty + +noncomputable section + +namespace MarkovProcess.PositiveC0ContractiveResolvent + +open MarkovProcess.SubMarkovKernelSemigroup + +variable {X : Type*} [MetricSpace X] [LocallyCompactSpace X] [SecondCountableTopology X] + [MeasurableSpace X] [BorelSpace X] {R : PositiveC0ContractiveResolvent X} + +/-- **A conservative resolvent leaves no escape.** If at one positive shift the shift times the +kernel resolvent of the constant observable one is one at a live starting point, then the +compactified process started there almost surely never leaves the live space. -/ +theorem OnePointRegular.ae_exitTime_eq_top (h : R.OnePointRegular) {lam : ℝ} (hlam : 0 < lam) + (x : X) (hone : ENNReal.ofReal lam * + R.kernelSemigroup.kernelResolvent lam (fun _ : X ↦ 1) x = 1) : + letI := h.metricSpace + letI := h.completeSpace + ∀ᵐ omega ∂IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X), + ContinuousPath.exitTime (Set.range ((↑) : X → OnePoint X)) omega = ⊤ := by + let := h.metricSpace + let := h.completeSpace + have hlaplace := R.lintegral_exp_neg_onePoint_exitTime h.rho h.continuous_rho h.rho_pos + h.lipschitz_rho h.isCompact_superlevel h.kolmogorovRegular lam hlam x + rw [hone, tsub_self] at hlaplace + have hmeasTime : Measurable + (ContinuousPath.exitTime (Set.range ((↑) : X → OnePoint X)) : + ContinuousPath (OnePoint X) → ℝ≥0∞) := + ContinuousPath.measurable_exitTime _ OnePoint.isOpen_range_coe + have hmeasSet : MeasurableSet + {omega : ContinuousPath (OnePoint X) | + ContinuousPath.exitTime (Set.range ((↑) : X → OnePoint X)) omega < ⊤} := + measurableSet_lt hmeasTime measurable_const + have hmeas : Measurable + (({omega : ContinuousPath (OnePoint X) | + ContinuousPath.exitTime (Set.range ((↑) : X → OnePoint X)) omega < ⊤}).indicator + (fun omega ↦ ENNReal.ofReal (Real.exp (-lam * + (ContinuousPath.exitTime (Set.range ((↑) : X → OnePoint X)) omega).toReal)))) := + Measurable.indicator + (ENNReal.measurable_ofReal.comp (Real.continuous_exp.measurable.comp + ((measurable_const.mul hmeasTime.ennreal_toReal)))) + hmeasSet + have hzero := (lintegral_eq_zero_iff hmeas).mp hlaplace + filter_upwards [hzero] with omega homega + by_contra hlt + have hfinite : omega ∈ {omega : ContinuousPath (OnePoint X) | + ContinuousPath.exitTime (Set.range ((↑) : X → OnePoint X)) omega < ⊤} := + lt_top_iff_ne_top.mpr hlt + rw [Set.indicator_of_mem hfinite] at homega + exact absurd homega (by + simp only [Pi.zero_apply, ENNReal.ofReal_eq_zero, not_le] + exact Real.exp_pos _) + +end MarkovProcess.PositiveC0ContractiveResolvent diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean new file mode 100644 index 0000000000..7544dcd484 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean @@ -0,0 +1,593 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Topology.Compactification.OnePoint.Basic +import Mathlib.Topology.Compactness.SigmaCompact +import Mathlib.Topology.Metrizable.Urysohn +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration + +/-! +# One-point extension of a positive `C₀` resolvent + +A positive contractive resolvent on a locally compact Polish space generates a sub-Markov +semigroup. This file adjoins the genuine Alexandroff point at infinity, extends continuous +functions by splitting off their value there, and lets the generated semigroup evolve only the +part which vanishes at infinity. The resulting positive contractive resolvent has a conservative +Feller kernel semigroup, and the added point is absorbing. + +Main results: `PositiveC0ContractiveResolvent.onePointResolvent`, +`PositiveC0ContractiveResolvent.onePointResolvent_operator`, +`PositiveC0ContractiveResolvent.isConservative_onePointKernelSemigroup`, and +`PositiveC0ContractiveResolvent.onePointKernelSemigroup_absorbing`. + +This construction does not assert a Kolmogorov moment bound or construct a continuous-path +process. +-/ + +open Filter Set Topology TopologicalSpace + +noncomputable section + +namespace OnePoint + +variable {X : Type*} [TopologicalSpace X] [T2Space X] [LocallyCompactSpace X] + [SecondCountableTopology X] + +private def basis : Set (Set (OnePoint X)) := + ((fun s : Set X => ((↑) '' s : Set (OnePoint X))) '' TopologicalSpace.countableBasis X) ∪ + Set.range (fun n : ℕ => OnePoint.opensOfCompl + (CompactExhaustion.choice X n) + ((CompactExhaustion.choice X).isCompact n).isClosed + ((CompactExhaustion.choice X).isCompact n)) + +private theorem basis_countable : (basis (X := X)).Countable := by + apply Set.Countable.union + · exact (TopologicalSpace.countable_countableBasis X).image _ + · exact Set.countable_range _ + +private theorem basis_isOpen (s : Set (OnePoint X)) (hs : s ∈ basis (X := X)) : IsOpen s := by + rcases hs with hs | hs + · rcases hs with ⟨u, hu, rfl⟩ + exact OnePoint.isOpen_image_coe.mpr + ((TopologicalSpace.isBasis_countableBasis X).isOpen hu) + · rcases hs with ⟨n, rfl⟩ + exact (OnePoint.opensOfCompl (CompactExhaustion.choice X n) + ((CompactExhaustion.choice X).isCompact n).isClosed + ((CompactExhaustion.choice X).isCompact n)).is_open' + +private theorem basis_isTopologicalBasis : IsTopologicalBasis (basis (X := X)) := by + apply isTopologicalBasis_of_isOpen_of_nhds basis_isOpen + intro z u hzu hu + induction z using OnePoint.rec with + | infty => + have hu_inf : OnePoint.infty ∈ u := hzu + rw [OnePoint.isOpen_iff_of_mem hu_inf] at hu + obtain ⟨n, hn⟩ := (CompactExhaustion.choice X).exists_superset_of_isCompact hu.2 + refine ⟨OnePoint.opensOfCompl (CompactExhaustion.choice X n) + ((CompactExhaustion.choice X).isCompact n).isClosed + ((CompactExhaustion.choice X).isCompact n), ?_, ?_, ?_⟩ + · exact Or.inr ⟨n, rfl⟩ + · exact OnePoint.infty_mem_opensOfCompl _ _ + · intro z hz + induction z using OnePoint.rec with + | infty => exact hu_inf + | coe x => + change (x : OnePoint X) ∈ + (((↑) '' (CompactExhaustion.choice X n)) : Set (OnePoint X))ᶜ at hz + have hx : x ∈ ((CompactExhaustion.choice X n) : Set X)ᶜ := by + simpa only [Set.mem_compl_iff, Set.mem_image, OnePoint.coe_eq_coe, + exists_eq_right] using hz + have hxpre : x ∈ ((↑) ⁻¹' u : Set X) := by + by_contra hxnot + exact hx (hn hxnot) + exact hxpre + | coe x => + have hx : x ∈ ((↑) ⁻¹' u : Set X) := hzu + have hopen : IsOpen (((↑) ⁻¹' u : Set X)) := + OnePoint.continuous_coe.isOpen_preimage _ hu + obtain ⟨v, hvbasis, hxv, hvu⟩ := + (TopologicalSpace.isBasis_countableBasis X).exists_subset_of_mem_open hx hopen + refine ⟨((↑) '' v : Set (OnePoint X)), ?_, ⟨x, hxv, rfl⟩, ?_⟩ + · exact Or.inl ⟨v, hvbasis, rfl⟩ + · rintro _ ⟨y, hyv, rfl⟩ + exact hvu hyv + +/-- The one-point compactification of a second-countable locally compact Hausdorff space is +second countable. -/ +noncomputable instance instSecondCountableTopology : SecondCountableTopology (OnePoint X) := + (basis_isTopologicalBasis (X := X)).secondCountableTopology (basis_countable (X := X)) + +/-- The canonical measurable structure on a one-point compactification is its Borel structure. -/ +instance instMeasurableSpace : MeasurableSpace (OnePoint X) := + borel (OnePoint X) + +/-- The canonical measurable structure on a one-point compactification is Borel. -/ +instance instBorelSpace : BorelSpace (OnePoint X) := + ⟨rfl⟩ + +end OnePoint + +namespace MarkovProcess.PositiveC0ContractiveResolvent + +open MeasureTheory ProbabilityTheory +open scoped BoundedContinuousFunction NNReal ZeroAtInfty + +variable {X : Type*} [TopologicalSpace X] [T2Space X] [LocallyCompactSpace X] + [SecondCountableTopology X] + +/-- The part of a function on the one-point compactification which vanishes at infinity. -/ +noncomputable def onePointRemainder (g : C₀(OnePoint X, ℝ)) : C₀(X, ℝ) where + toFun x := g (x : OnePoint X) - g OnePoint.infty + continuous_toFun := + (g.continuous.comp OnePoint.continuous_coe).sub continuous_const + zero_at_infty' := by + have hg := (OnePoint.continuous_iff (g : OnePoint X → ℝ)).mp g.continuous + rw [← Filter.coclosedCompact_eq_cocompact] + simpa only [Function.comp_apply, sub_self] using hg.1.sub_const (g OnePoint.infty) + +/-- Reassemble a vanishing function and its value at infinity. -/ +noncomputable def onePointAssemble (f : C₀(X, ℝ)) (c : ℝ) : C₀(OnePoint X, ℝ) := + ZeroAtInftyContinuousMap.ContinuousMap.liftZeroAtInfty + (OnePoint.continuousMapMk (f.toContinuousMap + ContinuousMap.const X c) c (by + rw [Filter.coclosedCompact_eq_cocompact] + simpa only [ContinuousMap.coe_add, ContinuousMap.coe_const, Pi.add_apply, zero_add] + using! (zero_at_infty f).add_const c)) + +omit [LocallyCompactSpace X] [SecondCountableTopology X] in +/-- The remainder of a compactified observable, unfolded. -/ +@[simp] theorem onePointRemainder_apply (g : C₀(OnePoint X, ℝ)) (x : X) : + onePointRemainder g x = g (x : OnePoint X) - g OnePoint.infty := rfl + +omit [LocallyCompactSpace X] [SecondCountableTopology X] in +/-- The assembled observable at a live point. -/ +@[simp] theorem onePointAssemble_coe (f : C₀(X, ℝ)) (c : ℝ) (x : X) : + onePointAssemble f c (x : OnePoint X) = f x + c := by + rfl + +omit [LocallyCompactSpace X] [SecondCountableTopology X] in +/-- The assembled observable at the added point. -/ +@[simp] theorem onePointAssemble_infty (f : C₀(X, ℝ)) (c : ℝ) : + onePointAssemble f c OnePoint.infty = c := by + rfl + +omit [LocallyCompactSpace X] [SecondCountableTopology X] in +/-- Assembling an observable and taking the remainder returns it. -/ +@[simp] theorem onePointRemainder_assemble (f : C₀(X, ℝ)) (c : ℝ) : + onePointRemainder (onePointAssemble f c) = f := by + apply ZeroAtInftyContinuousMap.ext + intro x + simp only [onePointRemainder_apply, onePointAssemble_coe, onePointAssemble_infty, + add_sub_cancel_right] + +omit [LocallyCompactSpace X] [SecondCountableTopology X] in +/-- Taking the remainder and reassembling at the value at infinity returns the observable. -/ +@[simp] theorem onePointAssemble_remainder (g : C₀(OnePoint X, ℝ)) : + onePointAssemble (onePointRemainder g) (g OnePoint.infty) = g := by + apply ZeroAtInftyContinuousMap.ext + intro z + induction z using OnePoint.rec with + | infty => rfl + | coe x => simp only [onePointAssemble_coe, onePointRemainder_apply, sub_add_cancel] + +omit [LocallyCompactSpace X] [SecondCountableTopology X] in +/-- The remainder is additive. -/ +@[simp] theorem onePointRemainder_add (g h : C₀(OnePoint X, ℝ)) : + onePointRemainder (g + h) = onePointRemainder g + onePointRemainder h := by + apply ZeroAtInftyContinuousMap.ext + intro x + simp only [onePointRemainder_apply, ZeroAtInftyContinuousMap.add_apply] + ring + +omit [LocallyCompactSpace X] [SecondCountableTopology X] in +/-- The remainder commutes with scalar multiplication. -/ +@[simp] theorem onePointRemainder_smul (c : ℝ) (g : C₀(OnePoint X, ℝ)) : + onePointRemainder (c • g) = c • onePointRemainder g := by + apply ZeroAtInftyContinuousMap.ext + intro x + simp only [onePointRemainder_apply, ZeroAtInftyContinuousMap.smul_apply, smul_eq_mul] + ring + +private noncomputable def onePointRemainderLinearMap : + C₀(OnePoint X, ℝ) →ₗ[ℝ] C₀(X, ℝ) where + toFun := onePointRemainder + map_add' := onePointRemainder_add + map_smul' := onePointRemainder_smul + +omit [LocallyCompactSpace X] [SecondCountableTopology X] in +private theorem norm_onePointRemainder_le (g : C₀(OnePoint X, ℝ)) : + ‖onePointRemainder g‖ ≤ 2 * ‖g‖ := by + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + refine (BoundedContinuousFunction.norm_le (mul_nonneg (by norm_num) (norm_nonneg g))).2 fun x ↦ ?_ + change ‖g (x : OnePoint X) - g OnePoint.infty‖ ≤ 2 * ‖g‖ + calc + ‖g (x : OnePoint X) - g OnePoint.infty‖ ≤ + ‖g (x : OnePoint X)‖ + ‖g OnePoint.infty‖ := norm_sub_le _ _ + _ ≤ ‖g‖ + ‖g‖ := add_le_add + (g.toBCF.norm_coe_le_norm (x : OnePoint X)) + (g.toBCF.norm_coe_le_norm OnePoint.infty) + _ = 2 * ‖g‖ := by ring + +private noncomputable def onePointRemainderCLM : + C₀(OnePoint X, ℝ) →L[ℝ] C₀(X, ℝ) := + onePointRemainderLinearMap.mkContinuous 2 norm_onePointRemainder_le + +omit [LocallyCompactSpace X] [SecondCountableTopology X] in +@[simp] private theorem onePointRemainderCLM_apply (g : C₀(OnePoint X, ℝ)) : + onePointRemainderCLM g = onePointRemainder g := rfl + +variable [MeasurableSpace X] [BorelSpace X] + +variable (R : PositiveC0ContractiveResolvent X) + +/-- Extend the generated semigroup action by fixing the value at infinity. -/ +noncomputable def onePointSemigroupAction (t : NNReal) (g : C₀(OnePoint X, ℝ)) : + C₀(OnePoint X, ℝ) := + onePointAssemble + (R.toContractiveResolvent.generatedSemigroup t (onePointRemainder g)) + (g OnePoint.infty) + +omit [MeasurableSpace X] [BorelSpace X] [LocallyCompactSpace X] [SecondCountableTopology X] in +/-- The extended action fixes the value of an observable at the added point. -/ +@[simp] theorem onePointSemigroupAction_infty (t : NNReal) (g : C₀(OnePoint X, ℝ)) : + R.onePointSemigroupAction t g OnePoint.infty = g OnePoint.infty := by + rw [onePointSemigroupAction, onePointAssemble_infty] + +/-- At a live point, the extended semigroup integrates over the original transition law and +assigns its missing mass to the value of the observable at infinity. -/ +theorem onePointSemigroupAction_coe (t : NNReal) (g : C₀(OnePoint X, ℝ)) (x : X) : + R.onePointSemigroupAction t g (x : OnePoint X) = + ∫ y, g (y : OnePoint X) ∂R.kernelSemigroup t x + + (1 - (R.kernelSemigroup t x).real Set.univ) * g OnePoint.infty := by + rw [onePointSemigroupAction, onePointAssemble_coe, + ← R.integral_kernelSemigroup t (onePointRemainder g) x] + let μ := R.kernelSemigroup t x + have hmassE := R.kernelSemigroup.measure_univ_le_one t x + have hfin : μ Set.univ < ⊤ := + lt_of_le_of_lt hmassE ENNReal.one_lt_top + let : IsFiniteMeasure μ := ⟨hfin⟩ + let gc : X →ᵇ ℝ := g.toBCF.compContinuous + ⟨fun x : X ↦ (x : OnePoint X), OnePoint.continuous_coe⟩ + have hg : Integrable (fun y : X ↦ g (y : OnePoint X)) μ := gc.integrable μ + rw [show (∫ y, onePointRemainder g y ∂μ) = + ∫ y, (g (y : OnePoint X) - g OnePoint.infty) ∂μ by rfl, + integral_sub hg (integrable_const _), integral_const] + change (∫ y, g (y : OnePoint X) ∂μ) - μ.real Set.univ * g OnePoint.infty + + g OnePoint.infty = _ + ring + +private theorem norm_onePointSemigroupAction_le (t : NNReal) (g : C₀(OnePoint X, ℝ)) : + ‖R.onePointSemigroupAction t g‖ ≤ ‖g‖ := by + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + refine (BoundedContinuousFunction.norm_le (norm_nonneg g)).2 fun z ↦ ?_ + induction z using OnePoint.rec with + | infty => + change ‖R.onePointSemigroupAction t g OnePoint.infty‖ ≤ ‖g‖ + rw [onePointSemigroupAction_infty] + exact g.toBCF.norm_coe_le_norm OnePoint.infty + | coe x => + change ‖R.onePointSemigroupAction t g (x : OnePoint X)‖ ≤ ‖g‖ + rw [Real.norm_eq_abs, onePointSemigroupAction_coe] + let μ := R.kernelSemigroup t x + have hmassE : μ Set.univ ≤ 1 := R.kernelSemigroup.measure_univ_le_one t x + have hfin : μ Set.univ < ⊤ := lt_of_le_of_lt hmassE ENNReal.one_lt_top + let : IsFiniteMeasure μ := ⟨hfin⟩ + have hmass0 : 0 ≤ μ.real Set.univ := measureReal_nonneg + have hmass1 : μ.real Set.univ ≤ 1 := by + rw [measureReal_def] + simpa only [ENNReal.toReal_one] using + (ENNReal.toReal_le_toReal hfin.ne ENNReal.one_ne_top).mpr hmassE + have hint : |∫ y, g (y : OnePoint X) ∂μ| ≤ ‖g‖ * μ.real Set.univ := by + rw [← Real.norm_eq_abs] + exact norm_integral_le_of_norm_le_const + (ae_of_all μ fun y ↦ g.toBCF.norm_coe_le_norm (y : OnePoint X)) + calc + |∫ y, g (y : OnePoint X) ∂μ + + (1 - μ.real Set.univ) * g OnePoint.infty| ≤ + |∫ y, g (y : OnePoint X) ∂μ| + + |(1 - μ.real Set.univ) * g OnePoint.infty| := abs_add_le _ _ + _ ≤ ‖g‖ * μ.real Set.univ + + (1 - μ.real Set.univ) * ‖g‖ := by + refine add_le_add hint ?_ + rw [abs_mul, abs_of_nonneg (sub_nonneg.mpr hmass1)] + exact mul_le_mul_of_nonneg_left + (g.toBCF.norm_coe_le_norm OnePoint.infty) (sub_nonneg.mpr hmass1) + _ = ‖g‖ := by ring + +private noncomputable def onePointSemigroupLinearMap (t : NNReal) : + C₀(OnePoint X, ℝ) →ₗ[ℝ] C₀(OnePoint X, ℝ) where + toFun := R.onePointSemigroupAction t + map_add' g h := by + apply ZeroAtInftyContinuousMap.ext + intro z + induction z using OnePoint.rec with + | infty => simp only [onePointSemigroupAction_infty, ZeroAtInftyContinuousMap.add_apply] + | coe x => + simp only [onePointSemigroupAction, onePointAssemble_coe, onePointRemainder_add, + ZeroAtInftyContinuousMap.add_apply, map_add] + abel + map_smul' c g := by + apply ZeroAtInftyContinuousMap.ext + intro z + induction z using OnePoint.rec with + | infty => simp only [onePointSemigroupAction_infty, ZeroAtInftyContinuousMap.smul_apply, + RingHom.id_apply] + | coe x => + simp only [onePointSemigroupAction, onePointAssemble_coe, onePointRemainder_smul, + ZeroAtInftyContinuousMap.smul_apply, map_smul, RingHom.id_apply, smul_eq_mul] + ring + +/-- The contraction on the compactified function space induced at time `t`. -/ +noncomputable def onePointSemigroupOperator (t : NNReal) : + C₀(OnePoint X, ℝ) →L[ℝ] C₀(OnePoint X, ℝ) := + (R.onePointSemigroupLinearMap t).mkContinuous 1 fun g ↦ by + simpa only [one_mul] using! R.norm_onePointSemigroupAction_le t g + +/-- The bundled extended operator acts by the extended semigroup action. -/ +@[simp] theorem onePointSemigroupOperator_apply (t : NNReal) (g : C₀(OnePoint X, ℝ)) : + R.onePointSemigroupOperator t g = R.onePointSemigroupAction t g := rfl + +private noncomputable def onePointEmbedLinearMap : C₀(X, ℝ) →ₗ[ℝ] C₀(OnePoint X, ℝ) where + toFun := fun f ↦ onePointAssemble f 0 + map_add' f g := by + apply ZeroAtInftyContinuousMap.ext + intro z + induction z using OnePoint.rec with + | infty => simp only [onePointAssemble_infty, ZeroAtInftyContinuousMap.add_apply, add_zero] + | coe x => simp only [onePointAssemble_coe, ZeroAtInftyContinuousMap.add_apply, add_zero] + map_smul' c f := by + apply ZeroAtInftyContinuousMap.ext + intro z + induction z using OnePoint.rec with + | infty => simp only [onePointAssemble_infty, ZeroAtInftyContinuousMap.smul_apply, + smul_zero, RingHom.id_apply] + | coe x => simp only [onePointAssemble_coe, ZeroAtInftyContinuousMap.smul_apply, + add_zero, smul_eq_mul, RingHom.id_apply] + +omit [MeasurableSpace X] [BorelSpace X] [LocallyCompactSpace X] [SecondCountableTopology X] in +private theorem norm_onePointEmbed_le (f : C₀(X, ℝ)) : + ‖onePointAssemble f 0‖ ≤ ‖f‖ := by + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + refine (BoundedContinuousFunction.norm_le (norm_nonneg f)).2 fun z ↦ ?_ + induction z using OnePoint.rec with + | infty => + change ‖onePointAssemble f 0 OnePoint.infty‖ ≤ ‖f‖ + rw [onePointAssemble_infty, norm_zero] + exact norm_nonneg f + | coe x => + change ‖onePointAssemble f 0 (x : OnePoint X)‖ ≤ ‖f‖ + rw [onePointAssemble_coe, add_zero] + exact f.toBCF.norm_coe_le_norm x + +private noncomputable def onePointEmbed : C₀(X, ℝ) →L[ℝ] C₀(OnePoint X, ℝ) := + onePointEmbedLinearMap.mkContinuous 1 fun f ↦ by + simpa only [one_mul] using! norm_onePointEmbed_le f + +omit [MeasurableSpace X] [BorelSpace X] [LocallyCompactSpace X] [SecondCountableTopology X] in +@[simp] private theorem onePointEmbed_apply (f : C₀(X, ℝ)) : + onePointEmbed f = onePointAssemble f 0 := rfl + +omit [MeasurableSpace X] [BorelSpace X] [LocallyCompactSpace X] [SecondCountableTopology X] in +private theorem onePointSemigroupAction_eq (t : NNReal) (g : C₀(OnePoint X, ℝ)) : + R.onePointSemigroupAction t g = + onePointEmbed (R.toContractiveResolvent.generatedSemigroup t (onePointRemainder g)) + + onePointAssemble 0 (g OnePoint.infty) := by + apply ZeroAtInftyContinuousMap.ext + intro z + induction z using OnePoint.rec with + | infty => + simp only [onePointSemigroupAction_infty, onePointEmbed_apply, + ZeroAtInftyContinuousMap.add_apply, onePointAssemble_infty, zero_add] + | coe x => + simp only [onePointSemigroupAction, onePointAssemble_coe, + onePointEmbed_apply, ZeroAtInftyContinuousMap.add_apply, + ZeroAtInftyContinuousMap.zero_apply] + ring + +/-- The generated semigroup on the one-point compactification. -/ +noncomputable def onePointSemigroup : + Semigroup.StronglyContinuousContractionSemigroup C₀(OnePoint X, ℝ) where + operator := R.onePointSemigroupOperator + operator_zero := by + apply ContinuousLinearMap.ext + intro g + rw [onePointSemigroupOperator_apply, onePointSemigroupAction, + R.toContractiveResolvent.generatedSemigroup.zero_apply, + onePointAssemble_remainder] + rfl + operator_add s t := by + apply ContinuousLinearMap.ext + intro g + change R.onePointSemigroupAction (s + t) g = + R.onePointSemigroupAction s (R.onePointSemigroupAction t g) + rw [onePointSemigroupAction, onePointSemigroupAction, + onePointSemigroupAction, onePointRemainder_assemble, + R.toContractiveResolvent.generatedSemigroup.add_apply] + rfl + opNorm_le_one t := by + apply ContinuousLinearMap.opNorm_le_bound _ zero_le_one + intro g + rw [onePointSemigroupOperator_apply, one_mul] + exact R.norm_onePointSemigroupAction_le t g + continuous_orbit g := by + rw [show (fun t ↦ R.onePointSemigroupOperator t g) = fun t ↦ + onePointEmbed (R.toContractiveResolvent.generatedSemigroup t (onePointRemainder g)) + + onePointAssemble 0 (g OnePoint.infty) by + funext t + rw [onePointSemigroupOperator_apply, onePointSemigroupAction_eq]] + exact (onePointEmbed.continuous.comp + (R.toContractiveResolvent.generatedSemigroup.continuous (onePointRemainder g))).add + continuous_const + +/-- The compactified semigroup acts by the extended semigroup action. -/ +@[simp] theorem onePointSemigroup_apply (t : NNReal) (g : C₀(OnePoint X, ℝ)) : + R.onePointSemigroup t g = R.onePointSemigroupAction t g := rfl + +/-- The compactified semigroup preserves pointwise nonnegative functions. -/ +theorem isPositive_onePointSemigroup (t : NNReal) : + PositiveC0OperatorMeasure.IsPositive (R.onePointSemigroup t) := by + intro g hg z + induction z using OnePoint.rec with + | infty => + rw [onePointSemigroup_apply, onePointSemigroupAction_infty] + exact hg OnePoint.infty + | coe x => + rw [onePointSemigroup_apply, onePointSemigroupAction_coe] + apply add_nonneg + · exact integral_nonneg fun y ↦ hg (y : OnePoint X) + · apply mul_nonneg + · have hmassE := R.kernelSemigroup.measure_univ_le_one t x + have hfin : (R.kernelSemigroup t x) Set.univ ≠ ⊤ := + (lt_of_le_of_lt hmassE ENNReal.one_lt_top).ne + rw [sub_nonneg, measureReal_def] + simpa only [ENNReal.toReal_one] using + (ENNReal.toReal_le_toReal hfin ENNReal.one_ne_top).mpr hmassE + · exact hg OnePoint.infty + +private noncomputable def onePointEvaluation (z : OnePoint X) : + C₀(OnePoint X, ℝ) →L[ℝ] ℝ := + LinearMap.mkContinuous + { toFun := fun g ↦ g z + map_add' := fun _ _ ↦ rfl + map_smul' := fun _ _ ↦ rfl } + 1 fun g ↦ by + rw [one_mul] + exact g.toBCF.norm_coe_le_norm z + +private theorem isPositive_onePointResolventOperator (mu : Semigroup.PositiveShift) : + PositiveC0OperatorMeasure.IsPositive (R.onePointSemigroup.resolvent mu) := by + intro g hg z + change 0 ≤ (R.onePointSemigroup.resolvent mu g) z + rw [Semigroup.StronglyContinuousContractionSemigroup.resolvent] + change 0 ≤ onePointEvaluation z + (∫ t in Set.Ioi (0 : ℝ), R.onePointSemigroup.laplaceIntegrand mu g t) + rw [← (onePointEvaluation z).integral_comp_comm + (R.onePointSemigroup.integrableOn_laplaceIntegrand mu.property g)] + apply integral_nonneg_of_ae + filter_upwards with t + change 0 ≤ Real.exp (-(mu : ℝ) * t) * + R.onePointSemigroup (Real.toNNReal t) g z + exact mul_nonneg (Real.exp_pos _).le (R.isPositive_onePointSemigroup _ g hg z) + +/-- The positive contractive resolvent on the genuine one-point compactification. -/ +noncomputable def onePointResolvent : PositiveC0ContractiveResolvent (OnePoint X) where + toContractiveResolvent := R.onePointSemigroup.toContractiveResolvent + isPositive := R.isPositive_onePointResolventOperator + +/-- The semigroup generated by the compactified resolvent is the compactified semigroup. -/ +theorem generatedSemigroup_onePointResolvent : + R.onePointResolvent.toContractiveResolvent.generatedSemigroup = R.onePointSemigroup := + R.onePointSemigroup.generatedSemigroup_toContractiveResolvent + +private theorem onePointResolvent_remainder (mu : Semigroup.PositiveShift) + (g : C₀(OnePoint X, ℝ)) : + onePointRemainder (R.onePointResolvent.toContractiveResolvent.operator mu g) = + R.toContractiveResolvent.operator mu (onePointRemainder g) := by + change onePointRemainder (R.onePointSemigroup.resolvent mu g) = _ + rw [Semigroup.StronglyContinuousContractionSemigroup.resolvent] + change onePointRemainderCLM + (∫ t in Set.Ioi (0 : ℝ), R.onePointSemigroup.laplaceIntegrand mu g t) = _ + rw [← onePointRemainderCLM.integral_comp_comm + (R.onePointSemigroup.integrableOn_laplaceIntegrand mu.property g)] + rw [← R.toContractiveResolvent.resolvent_generatedSemigroup mu] + change (∫ t in Set.Ioi (0 : ℝ), onePointRemainderCLM + (R.onePointSemigroup.laplaceIntegrand mu g t)) = + ∫ t in Set.Ioi (0 : ℝ), + R.toContractiveResolvent.generatedSemigroup.laplaceIntegrand mu + (onePointRemainder g) t + apply MeasureTheory.integral_congr_ae + filter_upwards with t + simp only [Semigroup.StronglyContinuousContractionSemigroup.laplaceIntegrand_apply, + map_smul, onePointRemainderCLM_apply, onePointSemigroup_apply, + onePointSemigroupAction, onePointRemainder_assemble] + +private theorem onePointResolvent_infty (mu : Semigroup.PositiveShift) + (g : C₀(OnePoint X, ℝ)) : + R.onePointResolvent.toContractiveResolvent.operator mu g OnePoint.infty = + (mu : ℝ)⁻¹ * g OnePoint.infty := by + change R.onePointSemigroup.resolvent mu g OnePoint.infty = _ + rw [Semigroup.StronglyContinuousContractionSemigroup.resolvent] + change onePointEvaluation OnePoint.infty + (∫ t in Set.Ioi (0 : ℝ), R.onePointSemigroup.laplaceIntegrand mu g t) = _ + rw [← (onePointEvaluation OnePoint.infty).integral_comp_comm + (R.onePointSemigroup.integrableOn_laplaceIntegrand mu.property g)] + change (∫ t in Set.Ioi (0 : ℝ), + Real.exp (-(mu : ℝ) * t) * g OnePoint.infty) = _ + rw [integral_mul_const, + Semigroup.StronglyContinuousContractionSemigroup.integral_exp_neg_mul_Ioi_zero mu.property] + +/-- The compactified resolvent evolves the vanishing remainder and divides the value at infinity +by the shift. -/ +theorem onePointResolvent_operator (mu : Semigroup.PositiveShift) + (g : C₀(OnePoint X, ℝ)) : + R.onePointResolvent.toContractiveResolvent.operator mu g = + onePointAssemble + (R.toContractiveResolvent.operator mu (onePointRemainder g)) + ((mu : ℝ)⁻¹ * g OnePoint.infty) := by + rw [← R.onePointResolvent_remainder mu g, ← R.onePointResolvent_infty mu g] + exact (onePointAssemble_remainder _).symm + +/-- The Feller kernel semigroup represented by the compactified resolvent. -/ +noncomputable def onePointKernelSemigroup : SubMarkovKernelSemigroup (OnePoint X) := + R.onePointResolvent.kernelSemigroup + +/-- The represented compactified kernel semigroup is Feller. -/ +theorem isFellerKernelSemigroup_onePointKernelSemigroup : + R.onePointKernelSemigroup.IsFellerKernelSemigroup := + R.onePointResolvent.isFellerKernelSemigroup_kernelSemigroup + +/-- The compactified kernel semigroup acts on continuous functions by the compactified +semigroup. -/ +theorem integral_onePointKernelSemigroup (t : NNReal) (g : C₀(OnePoint X, ℝ)) + (z : OnePoint X) : + ∫ w, g w ∂R.onePointKernelSemigroup t z = R.onePointSemigroup t g z := by + rw [onePointKernelSemigroup, R.onePointResolvent.integral_kernelSemigroup, + R.generatedSemigroup_onePointResolvent] + +private noncomputable def onePointConstant (c : ℝ) : C₀(OnePoint X, ℝ) := + onePointAssemble 0 c + +omit [MeasurableSpace X] [BorelSpace X] [LocallyCompactSpace X] [SecondCountableTopology X] in +@[simp] private theorem onePointConstant_apply (c : ℝ) (z : OnePoint X) : + onePointConstant c z = c := by + induction z using OnePoint.rec with + | infty => exact onePointAssemble_infty 0 c + | coe x => simp only [onePointConstant, onePointAssemble_coe, + ZeroAtInftyContinuousMap.zero_apply, zero_add] + +/-- The compactified semigroup fixes the constants. -/ +@[simp] theorem onePointSemigroup_constant (t : NNReal) (c : ℝ) : + R.onePointSemigroup t (onePointConstant c) = onePointConstant c := by + rw [onePointSemigroup_apply, onePointSemigroupAction, onePointConstant, + onePointRemainder_assemble] + simp only [map_zero, onePointAssemble_infty] + +/-- The represented compactified semigroup is conservative. -/ +theorem isConservative_onePointKernelSemigroup : + R.onePointKernelSemigroup.IsConservative := by + intro t z + have h := R.integral_onePointKernelSemigroup t (onePointConstant 1) z + rw [R.onePointSemigroup_constant] at h + simp only [onePointConstant_apply, integral_const, smul_eq_mul, mul_one] at h + rw [measureReal_def, ENNReal.toReal_eq_one_iff] at h + exact h + +/-- The added point is absorbing for every transition kernel of the compactified semigroup. -/ +theorem onePointKernelSemigroup_absorbing (t : NNReal) : + R.onePointKernelSemigroup t OnePoint.infty = Measure.dirac OnePoint.infty := by + rw [onePointKernelSemigroup, PositiveC0ContractiveResolvent.kernelSemigroup, + PositiveC0SemigroupKernel.kernelSemigroup_apply, + PositiveC0OperatorKernel.kernel_apply] + apply Measure.ext_of_integral_eq_on_compactlySupported + intro f + let f₀ : C₀(OnePoint X, ℝ) := + PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f + have h := R.integral_onePointKernelSemigroup t f₀ OnePoint.infty + rw [onePointSemigroup_apply, onePointSemigroupAction_infty] at h + change (∫ x, f x ∂R.onePointKernelSemigroup t OnePoint.infty) = f OnePoint.infty at h + simpa only [integral_dirac] using! h + + +end MarkovProcess.PositiveC0ContractiveResolvent diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKilled.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKilled.lean new file mode 100644 index 0000000000..cfe1061f5c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKilled.lean @@ -0,0 +1,784 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov +import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace +import Mathlib.Topology.Homeomorph.Lemmas +import Mathlib.MeasureTheory.Measure.RegularityCompacts + +/-! +# Killing the one-point process at infinity + +This file identifies the continuous process of the one-point extension of a positive +`C₀`-contractive resolvent with the process killed on leaving its live part. +-/ + +open Filter MeasureTheory ProbabilityTheory Set Topology +open scoped ENNReal NNReal ZeroAtInfty + +noncomputable section + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [Nonempty alpha] + +/-- If a state is absorbing for every transition kernel, then the continuous-path process +started there is almost surely the constant path. -/ +theorem IsConservative.ae_eq_const_of_absorbing + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (hK : P.KolmogorovRegular hP) (a : alpha) + (hAbsorb : ∀ t, P t a = Measure.dirac a) : + (fun omega : ContinuousPath alpha ↦ omega) =ᵐ[IsConservative.continuousProcess P hP a] + fun _ ↦ ContinuousMap.const NNReal a := by + let mu := IsConservative.continuousProcess P hP a + have hcoord : ∀ q : DenseTime, ∀ᵐ omega ∂mu, + omega (DenseTime.castOrderEmbedding q) = a := by + intro q + have hmeas : Measurable + (fun omega : ContinuousPath alpha ↦ omega (DenseTime.castOrderEmbedding q)) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) _ + have hmap := IsConservative.continuousProcess_map_eval P hP hK q + have hmapa : Measure.map (fun omega : ContinuousPath alpha ↦ + omega (DenseTime.castOrderEmbedding q)) mu = Measure.dirac a := by + rw [show mu = IsConservative.continuousProcess P hP a by rfl, + ← Kernel.map_apply _ hmeas, hmap, hAbsorb] + have hsingleton : MeasurableSet ({a}ᶜ : Set alpha) := + (isClosed_singleton (x := a)).measurableSet.compl + have hzero : mu ((fun omega : ContinuousPath alpha ↦ + omega (DenseTime.castOrderEmbedding q)) ⁻¹' ({a}ᶜ : Set alpha)) = 0 := by + rw [← Measure.map_apply hmeas hsingleton, hmapa, Measure.dirac_apply' a hsingleton, + Set.indicator_of_notMem (by simp)] + exact hzero + have hall : ∀ᵐ omega ∂mu, ∀ q : DenseTime, + omega (DenseTime.castOrderEmbedding q) = a := ae_all_iff.mpr hcoord + filter_upwards [hall] with omega homega + apply ContinuousPath.denseRestriction_injective + funext q + rw [ContinuousPath.denseRestriction_apply, ContinuousPath.denseRestriction_apply, homega q] + rfl + +/-- At an absorbing state the entire continuous-path law is the Dirac mass at the constant +path. -/ +theorem IsConservative.continuousProcess_eq_dirac_of_absorbing + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (hK : P.KolmogorovRegular hP) (a : alpha) + (hAbsorb : ∀ t, P t a = Measure.dirac a) : + IsConservative.continuousProcess P hP a = + Measure.dirac (ContinuousMap.const NNReal a) := by + let mu := IsConservative.continuousProcess P hP a + have hprob : IsProbabilityMeasure mu := by + dsimp only [mu] + infer_instance + calc + mu = mu.map id := (Measure.map_id).symm + _ = mu.map (fun _ ↦ ContinuousMap.const NNReal a) := + Measure.map_congr (hP.ae_eq_const_of_absorbing P hK a hAbsorb) + _ = mu Set.univ • Measure.dirac (ContinuousMap.const NNReal a) := Measure.map_const _ _ + _ = Measure.dirac (ContinuousMap.const NNReal a) := by rw [measure_univ, one_smul] + +variable [LocallyCompactSpace alpha] + +/-- If the complement of an open set is a single absorbing state, then, on every path which +leaves the open set in finite time, the path shifted to its exit time is almost surely the +constant path at that state. -/ +theorem IsFellerKernelSemigroup.ae_shift_exitTime_eq_const_of_compl_eq_singleton + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (U : Set alpha) (hU : IsOpen U) (a : alpha) (hcompl : Uᶜ = {a}) + (hAbsorb : ∀ t, P t a = Measure.dirac a) {x : alpha} (hx : x ∈ U) : + ∀ᵐ omega ∂IsConservative.continuousProcess P hP x, + ContinuousPath.exitTime U omega < ⊤ → + ContinuousPath.shift (ContinuousPath.exitTime U omega).toNNReal omega = + ContinuousMap.const NNReal a := by + let Q := IsConservative.continuousProcess P hP + let tau := ContinuousPath.exitTimeTop U + let S : Set (ContinuousPath alpha) := {omega | tau omega < ⊤} + let Y : ContinuousPath alpha → ContinuousPath alpha := fun omega ↦ + ContinuousPath.shift ((tau omega).untopD 0) omega + have htau := ContinuousPath.isStoppingTime_exitTime U hU + have hS : MeasurableSet S := by + simpa only [S, tau, ContinuousPath.exitTimeTop_apply] using! + ContinuousPath.measurableSet_exitTime_lt_top U hU + have hY : Measurable Y := ContinuousPath.measurable_shift_untopD_stoppingTime tau htau + have heval0 : ∀ᵐ omega ∂Q x, omega 0 = x := IsConservative.ae_eval_zero_eq hP hK x + have hevalExit : ∀ᵐ omega ∂(Q x).restrict S, + omega ((tau omega).untopD 0) = a := by + rw [ae_restrict_iff' hS] + filter_upwards [heval0] with omega hzero homega + have hfin : ContinuousPath.exitTime U omega ≠ ⊤ := by + exact ne_of_lt (by simpa only [S, tau, ContinuousPath.exitTimeTop_apply] using! homega) + rw [ContinuousPath.untopD_exitTimeTop_eq_toNNReal U omega hfin] + have hfront := ContinuousPath.coordinate_exitTime_mem_frontier U hU omega + (hzero.symm ▸ hx) hfin + have hout : omega (ContinuousPath.exitTime U omega).toNNReal ∈ Uᶜ := by + exact (hU.frontier_eq ▸ hfront).2 + rw [hcompl] at hout + exact Set.mem_singleton_iff.mp hout + have hRestart : ((Q x).restrict S).map Y = + Kernel.comap Q (fun omega ↦ omega ((tau omega).untopD 0)) + (ContinuousPath.measurable_eval_untopD_stoppingTime tau htau) ∘ₘ + ((Q x).restrict S) := by + simpa only [Q, S, Y, Set.univ_inter] using + hFeller.continuousProcess_restrict_map_shift_stoppingTime_lt_top + P hP hK x tau htau Set.univ MeasurableSet.univ + have hrhs : ∀ᵐ eta ∂Kernel.comap Q + (fun omega ↦ omega ((tau omega).untopD 0)) + (ContinuousPath.measurable_eval_untopD_stoppingTime tau htau) ∘ₘ + ((Q x).restrict S), + eta = ContinuousMap.const NNReal a := by + apply Measure.ae_comp_of_ae_ae + (show MeasurableSet ({eta : ContinuousPath alpha | + eta = ContinuousMap.const NNReal a}) by + simpa only [Set.ofPred_eq_eq_singleton] using + (isClosed_singleton (x := ContinuousMap.const NNReal a)).measurableSet) + filter_upwards [hevalExit] with omega homega + rw [Kernel.comap_apply, homega, + hP.continuousProcess_eq_dirac_of_absorbing P hK a hAbsorb] + exact (ae_dirac_iff (show MeasurableSet ({eta : ContinuousPath alpha | + eta = ContinuousMap.const NNReal a}) by + simpa only [Set.ofPred_eq_eq_singleton] using + (isClosed_singleton (x := ContinuousMap.const NNReal a)).measurableSet)).mpr rfl + rw [← hRestart] at hrhs + have hshift : ∀ᵐ omega ∂(Q x).restrict S, + Y omega = ContinuousMap.const NNReal a := + (ae_map_iff hY.aemeasurable + (show MeasurableSet ({eta : ContinuousPath alpha | + eta = ContinuousMap.const NNReal a}) by + simpa only [Set.ofPred_eq_eq_singleton] using + (isClosed_singleton (x := ContinuousMap.const NNReal a)).measurableSet)).mp hrhs + rw [ae_restrict_iff' hS] at hshift + filter_upwards [hshift] with omega homega hfin + have hs : omega ∈ S := by + change tau omega < ⊤ + rw [show tau omega = ContinuousPath.exitTime U omega by + exact ContinuousPath.exitTimeTop_apply U omega] + exact hfin + have h := homega hs + dsimp only [Y] at h + rw [show (tau omega).untopD 0 = (ContinuousPath.exitTime U omega).toNNReal by + exact ContinuousPath.untopD_exitTimeTop_eq_toNNReal U omega (ne_of_lt hfin)] at h + exact h + +/-- Pathwise absorption after the finite exit time from an open set whose complement is a +single absorbing state. -/ +theorem IsFellerKernelSemigroup.ae_absorbed_after_exitTime_of_compl_eq_singleton + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (U : Set alpha) (hU : IsOpen U) (a : alpha) (hcompl : Uᶜ = {a}) + (hAbsorb : ∀ t, P t a = Measure.dirac a) {x : alpha} (hx : x ∈ U) : + ∀ᵐ omega ∂IsConservative.continuousProcess P hP x, + ContinuousPath.exitTime U omega < ⊤ → + ∀ t : NNReal, (ContinuousPath.exitTime U omega).toNNReal ≤ t → omega t = a := by + filter_upwards [hFeller.ae_shift_exitTime_eq_const_of_compl_eq_singleton + P hP hK U hU a hcompl hAbsorb hx] with omega homega hfin t ht + let s := t - (ContinuousPath.exitTime U omega).toNNReal + have hadd : (ContinuousPath.exitTime U omega).toNNReal + s = t := by + exact add_tsub_cancel_of_le ht + have h := congrArg (fun eta : ContinuousPath alpha ↦ eta s) (homega hfin) + simpa only [ContinuousPath.shift_apply, ContinuousMap.const_apply, hadd] using h + +/-- Under pathwise absorption, survival to a deterministic time is equivalent almost surely to +being in the open live set at that time. -/ +theorem IsFellerKernelSemigroup.ae_lt_exitTime_iff_mem_of_compl_eq_singleton + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (U : Set alpha) (hU : IsOpen U) (a : alpha) (hcompl : Uᶜ = {a}) + (hAbsorb : ∀ t, P t a = Measure.dirac a) {x : alpha} (hx : x ∈ U) (t : NNReal) : + ∀ᵐ omega ∂IsConservative.continuousProcess P hP x, + ((t : ℝ≥0∞) < ContinuousPath.exitTime U omega ↔ omega t ∈ U) := by + filter_upwards [hFeller.ae_absorbed_after_exitTime_of_compl_eq_singleton + P hP hK U hU a hcompl hAbsorb hx] with omega habs + constructor + · exact fun ht ↦ ContinuousPath.mem_of_lt_exitTime U omega t ht + · intro htU + by_contra hsurv + have hle : ContinuousPath.exitTime U omega ≤ (t : ℝ≥0∞) := le_of_not_gt hsurv + have hfin : ContinuousPath.exitTime U omega < ⊤ := + hle.trans_lt ENNReal.coe_lt_top + have htime : (ContinuousPath.exitTime U omega).toNNReal ≤ t := by + rw [← ENNReal.coe_le_coe, ENNReal.coe_toNNReal (ne_of_lt hfin)] + exact hle + have heq : omega t = a := habs hfin t htime + have haU : a ∉ U := by + intro ha + have : a ∈ Uᶜ := by rw [hcompl]; exact Set.mem_singleton a + exact this ha + exact haU (heq ▸ htU) + +end MarkovProcess.SubMarkovKernelSemigroup + +namespace MarkovProcess.PositiveC0ContractiveResolvent + +open MarkovProcess.SubMarkovKernelSemigroup + +variable {X : Type*} [MetricSpace X] [LocallyCompactSpace X] + [SecondCountableTopology X] [MeasurableSpace X] [BorelSpace X] + +omit [LocallyCompactSpace X] [SecondCountableTopology X] [MeasurableSpace X] [BorelSpace X] in +/-- The one-point compactification is compact under the exhaustion metric's topology, since that +topology coincides with the canonical one-point topology (which is always compact). This is a +typeclass-search cache in the same spirit as `OnePoint.instCompleteSpaceOnePointExhaustion`: it +lets the `isCompact_univ` calls that build `CompleteSpace (OnePoint X)` (via +`completeSpace_of_isComplete_univ`) inside this file's `letI` chains resolve automatically. -/ +private instance instCompactSpaceOnePointExhaustion + (rho : X → ℝ) (hrho_cont : Continuous rho) (hrho_pos : ∀ x, 0 < rho x) + (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) : + @CompactSpace (OnePoint X) + (OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz + hrho_compact).toPseudoMetricSpace.toUniformSpace.toTopologicalSpace := by + rw [OnePoint.exhaustionMetricSpace_toTopologicalSpace] + infer_instance + +/-- The original space is homeomorphic to the live part of its one-point compactification. -/ +noncomputable def onePointLiveHomeomorph : + X ≃ₜ Set.range ((↑) : X → OnePoint X) := + OnePoint.isOpenEmbedding_coe.isEmbedding.toHomeomorph + +omit [LocallyCompactSpace X] [SecondCountableTopology X] [MeasurableSpace X] + [BorelSpace X] in +/-- The homeomorphism onto the live part is the coercion into the compactification. -/ +@[simp] theorem onePointLiveHomeomorph_apply (x : X) : + (onePointLiveHomeomorph x : OnePoint X) = (x : OnePoint X) := rfl + +/-- At a live starting point, the compactified transition law is the original transition law, +pushed into the live part, plus the missing mass at infinity. -/ +theorem onePointKernelSemigroup_apply_coe + (R : PositiveC0ContractiveResolvent X) (t : NNReal) (x : X) : + R.onePointKernelSemigroup t (x : OnePoint X) = + (R.kernelSemigroup t x).map ((↑) : X → OnePoint X) + + (1 - R.kernelSemigroup t x Set.univ) • Measure.dirac OnePoint.infty := by + let : (R.kernelSemigroup t x).Regular := by + rw [PositiveC0ContractiveResolvent.kernelSemigroup, + PositiveC0SemigroupKernel.kernelSemigroup_apply, + PositiveC0OperatorKernel.kernel_apply] + infer_instance + let : IsFiniteMeasure (R.kernelSemigroup t x) := + ⟨lt_of_le_of_lt (R.kernelSemigroup.measure_univ_le_one t x) ENNReal.one_lt_top⟩ + let : Measure.InnerRegularCompactLTTop + ((R.kernelSemigroup t x).map ((↑) : X → OnePoint X)) := + Measure.InnerRegularCompactLTTop.map_of_continuous OnePoint.continuous_coe + let : IsFiniteMeasure + ((R.kernelSemigroup t x).map ((↑) : X → OnePoint X)) := inferInstance + have hmissing_ne_top : 1 - R.kernelSemigroup t x Set.univ ≠ ⊤ := + ne_top_of_le_ne_top ENNReal.one_ne_top tsub_le_self + let : IsFiniteMeasure + ((1 - R.kernelSemigroup t x Set.univ) • + Measure.dirac (OnePoint.infty : OnePoint X)) := + Measure.smul_finite _ hmissing_ne_top + let : IsFiniteMeasure + ((R.kernelSemigroup t x).map ((↑) : X → OnePoint X) + + (1 - R.kernelSemigroup t x Set.univ) • Measure.dirac OnePoint.infty) := + ⟨(ENNReal.add_lt_top).2 ⟨measure_lt_top _ _, measure_lt_top _ _⟩⟩ + let : (R.onePointKernelSemigroup t (x : OnePoint X)).Regular := by + rw [onePointKernelSemigroup, PositiveC0ContractiveResolvent.kernelSemigroup, + PositiveC0SemigroupKernel.kernelSemigroup_apply, + PositiveC0OperatorKernel.kernel_apply] + infer_instance + apply Measure.ext_of_integral_eq_on_compactlySupported + intro f + let g : C₀(OnePoint X, ℝ) := + PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f + have hmain := R.integral_onePointKernelSemigroup t g (x : OnePoint X) + rw [onePointSemigroup_apply, R.onePointSemigroupAction_coe] at hmain + have hmap : + ∫ z, f z ∂(R.kernelSemigroup t x).map ((↑) : X → OnePoint X) = + ∫ y, f (y : OnePoint X) ∂R.kernelSemigroup t x := by + simpa only using! integral_map OnePoint.continuous_coe.aemeasurable + f.continuous.aestronglyMeasurable + have hmass : R.kernelSemigroup t x Set.univ ≠ ⊤ := + (lt_of_le_of_lt (R.kernelSemigroup.measure_univ_le_one t x) ENNReal.one_lt_top).ne + have hmissing : + (1 - R.kernelSemigroup t x Set.univ).toReal = + 1 - (R.kernelSemigroup t x).real Set.univ := by + rw [ENNReal.toReal_sub_of_le (R.kernelSemigroup.measure_univ_le_one t x) + ENNReal.one_ne_top, + ENNReal.toReal_one, measureReal_def] + have hleft : ∫ z, f z ∂R.onePointKernelSemigroup t (x : OnePoint X) = + ∫ z, g z ∂R.onePointKernelSemigroup t (x : OnePoint X) := by + apply integral_congr_ae + filter_upwards with z + exact (PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap_apply f z).symm + rw [integral_add_measure] + · rw [hleft, hmain, hmap, integral_smul_measure, integral_dirac, hmissing, smul_eq_mul] + congr 2 + · exact f.integrable + · exact f.integrable + +/-- A tail estimate in the original metric and the explicit cemetery-mass identity give a +whole-space tail estimate for the one-point extension. -/ +theorem onePointKernelSemigroup_tail_le_of_tail_le + (R : PositiveC0ContractiveResolvent X) (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) + (h : NNReal) (x : X) (r : ℝ) (a : ℝ≥0∞) + (hlive : R.kernelSemigroup h x {y | r < dist y x} ≤ a) + (hcemetery : R.onePointKernelSemigroup h (x : OnePoint X) {OnePoint.infty} = + 1 - R.kernelSemigroup h x Set.univ) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + R.onePointKernelSemigroup h (x : OnePoint X) + {z | r < dist z (x : OnePoint X)} ≤ + a + (1 - R.kernelSemigroup h x Set.univ) := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + let tail : Set (OnePoint X) := {z | r < dist z (x : OnePoint X)} + let live : Set (OnePoint X) := Set.range ((↑) : X → OnePoint X) + have htail : MeasurableSet tail := + measurableSet_lt measurable_const + (measurable_dist.comp (measurable_id.prodMk measurable_const)) + have hliveSet : MeasurableSet live := OnePoint.isOpen_range_coe.measurableSet + have hliveBound : + R.onePointKernelSemigroup h (x : OnePoint X) (tail ∩ live) ≤ a := by + rw [R.onePointKernelSemigroup_apply_coe h x, Measure.add_apply, + Measure.map_apply OnePoint.continuous_coe.measurable (htail.inter hliveSet), + Measure.smul_apply, Measure.dirac_apply' OnePoint.infty (htail.inter hliveSet)] + have hinfty : OnePoint.infty ∉ tail ∩ live := + fun hz ↦ OnePoint.infty_notMem_range_coe hz.2 + rw [Set.indicator_of_notMem hinfty, smul_zero, add_zero] + apply (measure_mono ?_).trans hlive + intro y hy + exact OnePoint.exhaustionMetricSpace_live_tail_subset rho hrho_cont hrho_pos + hrho_lipschitz hrho_compact x r hy.1 + have hcover : tail ⊆ (tail ∩ live) ∪ {OnePoint.infty} := by + intro z hz + induction z using OnePoint.rec with + | infty => exact Set.mem_union_right _ (Set.mem_singleton _) + | coe y => exact Set.mem_union_left _ ⟨hz, ⟨y, rfl⟩⟩ + calc + R.onePointKernelSemigroup h (x : OnePoint X) tail ≤ + R.onePointKernelSemigroup h (x : OnePoint X) + ((tail ∩ live) ∪ {OnePoint.infty}) := measure_mono hcover + _ ≤ R.onePointKernelSemigroup h (x : OnePoint X) (tail ∩ live) + + R.onePointKernelSemigroup h (x : OnePoint X) {OnePoint.infty} := measure_union_le _ _ + _ ≤ a + (1 - R.kernelSemigroup h x Set.univ) := + add_le_add hliveBound hcemetery.le + +/-- The process furnished by the one-point resolvent is absorbed at infinity after its finite +exit time from the live part. -/ +theorem ae_absorbed_after_onePoint_exitTime + (R : PositiveC0ContractiveResolvent X) (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) + (hK : letI := + OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + R.onePointKernelSemigroup.KolmogorovRegular + R.isConservative_onePointKernelSemigroup) (x : X) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + ∀ᵐ omega ∂IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X), + ContinuousPath.exitTime (Set.range ((↑) : X → OnePoint X)) omega < ⊤ → + ∀ t : NNReal, + (ContinuousPath.exitTime (Set.range ((↑) : X → OnePoint X)) omega).toNNReal ≤ t → + omega t = OnePoint.infty := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + let : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + exact R.isFellerKernelSemigroup_onePointKernelSemigroup + |>.ae_absorbed_after_exitTime_of_compl_eq_singleton R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup + hK + (Set.range ((↑) : X → OnePoint X)) OnePoint.isOpen_range_coe OnePoint.infty + OnePoint.compl_range_coe R.onePointKernelSemigroup_absorbing + ⟨x, rfl⟩ + +/-- For the one-point process, survival to a deterministic time is almost surely equivalent to +the time-`t` coordinate still being a live point. -/ +theorem ae_lt_onePoint_exitTime_iff_mem + (R : PositiveC0ContractiveResolvent X) (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) + (hK : letI := + OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + R.onePointKernelSemigroup.KolmogorovRegular + R.isConservative_onePointKernelSemigroup) + (x : X) (t : NNReal) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + ∀ᵐ omega ∂IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X), + ((t : ℝ≥0∞) < ContinuousPath.exitTime + (Set.range ((↑) : X → OnePoint X)) omega ↔ + omega t ∈ Set.range ((↑) : X → OnePoint X)) := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + let : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + exact R.isFellerKernelSemigroup_onePointKernelSemigroup + |>.ae_lt_exitTime_iff_mem_of_compl_eq_singleton R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup + hK + (Set.range ((↑) : X → OnePoint X)) OnePoint.isOpen_range_coe OnePoint.infty + OnePoint.compl_range_coe R.onePointKernelSemigroup_absorbing + ⟨x, rfl⟩ t + +/-- In the canonical live coordinates, every transition kernel of the killed one-point process +is exactly the kernel generated by the original resolvent. -/ +theorem killedSemigroup_onePointLive_image + (R : PositiveC0ContractiveResolvent X) (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) + (hK : letI := + OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + R.onePointKernelSemigroup.KolmogorovRegular + R.isConservative_onePointKernelSemigroup) + (t : NNReal) (x : X) {B : Set X} (hB : MeasurableSet B) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + IsConservative.killedSemigroup R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup + (Set.range ((↑) : X → OnePoint X)) OnePoint.isOpen_range_coe + R.isFellerKernelSemigroup_onePointKernelSemigroup + hK t + (onePointLiveHomeomorph x) (onePointLiveHomeomorph '' B) = + R.kernelSemigroup t x B := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + let : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + let live : Set (OnePoint X) := Set.range ((↑) : X → OnePoint X) + let e := onePointLiveHomeomorph (X := X) + have heB : MeasurableSet (e '' B) := + e.toMeasurableEquiv.measurableEmbedding.measurableSet_image.mpr hB + have hcoeB : MeasurableSet (((↑) : X → OnePoint X) '' B) := + OnePoint.isOpenEmbedding_coe.measurableEmbedding.measurableSet_image.mpr hB + have himage : Subtype.val '' (e '' B) = ((↑) : X → OnePoint X) '' B := by + ext z + constructor + · rintro ⟨w, ⟨y, hy, rfl⟩, rfl⟩ + exact ⟨y, hy, rfl⟩ + · rintro ⟨y, hy, rfl⟩ + exact ⟨e y, ⟨y, hy, rfl⟩, rfl⟩ + rw [IsConservative.killedSemigroup_apply_apply + R.onePointKernelSemigroup R.isConservative_onePointKernelSemigroup + (Set.range ((↑) : X → OnePoint X)) OnePoint.isOpen_range_coe + R.isFellerKernelSemigroup_onePointKernelSemigroup + hK t + (onePointLiveHomeomorph x) heB] + change IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X) + (ContinuousPath.killedEvent live t (Subtype.val '' (e '' B))) = _ + rw [himage] + have hae := R.ae_lt_onePoint_exitTime_iff_mem rho hrho_cont hrho_pos hrho_lipschitz + hrho_compact hK x t + have hevent : ∀ᵐ omega ∂IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X), + (omega ∈ ContinuousPath.killedEvent live t + (((↑) : X → OnePoint X) '' B) ↔ + omega t ∈ ((↑) : X → OnePoint X) '' B) := by + filter_upwards [hae] with omega homega + have homega' : ((t : ℝ≥0∞) < ContinuousPath.exitTime + (Set.range ((↑) : X → OnePoint X)) omega ↔ + omega t ∈ Set.range ((↑) : X → OnePoint X)) := homega + rw [ContinuousPath.mem_killedEvent_iff, homega'] + exact and_iff_right_of_imp fun h ↦ Set.mem_of_mem_of_subset h (Set.image_subset_range _ _) + have hmeasure : + IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X) + (ContinuousPath.killedEvent live t (((↑) : X → OnePoint X) '' B)) = + IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X) + ((fun omega : ContinuousPath (OnePoint X) ↦ omega t) ⁻¹' + (((↑) : X → OnePoint X) '' B)) := by + apply measure_congr + filter_upwards [hevent] with omega homega + exact propext homega + rw [hmeasure] + show (IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X)) + (ContinuousPath.coordinateProcess t ⁻¹' (((↑) : X → OnePoint X) '' B)) = + R.kernelSemigroup t x B + rw [← Kernel.map_apply' + (IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup) (hf := ContinuousPath.measurable_coordinateProcess t) + (x : OnePoint X) hcoeB] + show ((IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup).map (fun omega => omega t) (x : OnePoint X)) + (((↑) : X → OnePoint X) '' B) = + R.kernelSemigroup t x B + rw [R.isFellerKernelSemigroup_onePointKernelSemigroup.continuousProcess_map_eval_nnreal + R.onePointKernelSemigroup R.isConservative_onePointKernelSemigroup + hK t, + R.onePointKernelSemigroup_apply_coe, Measure.add_apply, + Measure.map_apply OnePoint.continuous_coe.measurable hcoeB, + Measure.smul_apply, Measure.dirac_apply' OnePoint.infty hcoeB] + simp only [Set.preimage_image_eq B OnePoint.coe_injective, + Set.indicator_of_notMem (OnePoint.infty_notMem_image_coe (s := B)), smul_zero, add_zero] + +/-- The ambient killed kernel of the one-point process is the pushforward of the original +sub-Markov transition law. -/ +theorem killedKernel_onePointLive_eq_map + (R : PositiveC0ContractiveResolvent X) (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) + (hK : letI := + OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + R.onePointKernelSemigroup.KolmogorovRegular + R.isConservative_onePointKernelSemigroup) + (t : NNReal) (x : X) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + IsConservative.killedKernel R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup + (Set.range ((↑) : X → OnePoint X)) OnePoint.isOpen_range_coe t + (x : OnePoint X) = + (R.kernelSemigroup t x).map ((↑) : X → OnePoint X) := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + let : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + let live : Set (OnePoint X) := Set.range ((↑) : X → OnePoint X) + apply Measure.ext + intro A hA + have hAlive : MeasurableSet (A ∩ live) := hA.inter OnePoint.isOpen_range_coe.measurableSet + have hae := R.ae_lt_onePoint_exitTime_iff_mem rho hrho_cont hrho_pos hrho_lipschitz + hrho_compact hK x t + rw [IsConservative.killedKernel_apply R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup live OnePoint.isOpen_range_coe t + (x : OnePoint X) hA] + have hevent : ∀ᵐ omega ∂IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X), + (omega ∈ ContinuousPath.killedEvent live t A ↔ omega t ∈ A ∩ live) := by + filter_upwards [hae] with omega homega + have homega' : ((t : ℝ≥0∞) < ContinuousPath.exitTime + (Set.range ((↑) : X → OnePoint X)) omega ↔ + omega t ∈ Set.range ((↑) : X → OnePoint X)) := homega + rw [ContinuousPath.mem_killedEvent_iff, homega'] + exact and_comm + have hmeasure : + IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X) + (ContinuousPath.killedEvent live t A) = + IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X) + ((fun omega : ContinuousPath (OnePoint X) ↦ omega t) ⁻¹' (A ∩ live)) := by + apply measure_congr + filter_upwards [hevent] with omega homega + exact propext homega + rw [hmeasure] + show (IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X)) + (ContinuousPath.coordinateProcess t ⁻¹' (A ∩ live)) = + (R.kernelSemigroup t x).map ((↑) : X → OnePoint X) A + rw [← Kernel.map_apply' + (IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup) (hf := ContinuousPath.measurable_coordinateProcess t) + (x : OnePoint X) hAlive] + show ((IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup).map (fun omega => omega t) (x : OnePoint X)) + (A ∩ live) = + (R.kernelSemigroup t x).map ((↑) : X → OnePoint X) A + rw [R.isFellerKernelSemigroup_onePointKernelSemigroup.continuousProcess_map_eval_nnreal + R.onePointKernelSemigroup R.isConservative_onePointKernelSemigroup + hK t, + R.onePointKernelSemigroup_apply_coe, Measure.add_apply, + Measure.map_apply OnePoint.continuous_coe.measurable hAlive, + Measure.smul_apply, Measure.dirac_apply' OnePoint.infty hAlive, + Measure.map_apply OnePoint.continuous_coe.measurable hA] + have hinf : OnePoint.infty ∉ A ∩ live := fun h ↦ OnePoint.infty_notMem_range_coe h.2 + rw [Set.indicator_of_notMem hinf, smul_zero, add_zero] + congr 1 + ext y + simp only [Set.mem_preimage, Set.mem_inter_iff] + exact and_iff_left ⟨y, rfl⟩ + +/-- Extend a nonnegative observable on the live space by zero at infinity. -/ +def onePointLiveExtension (f : X → ℝ≥0∞) : OnePoint X → ℝ≥0∞ := + OnePoint.rec 0 f + +omit [MetricSpace X] [LocallyCompactSpace X] + [SecondCountableTopology X] [MeasurableSpace X] [BorelSpace X] in +/-- The zero extension of a function on the live space agrees with it at live points. -/ +@[simp] theorem onePointLiveExtension_coe (f : X → ℝ≥0∞) (x : X) : + onePointLiveExtension f (x : OnePoint X) = f x := rfl + +omit [MetricSpace X] [LocallyCompactSpace X] + [SecondCountableTopology X] [MeasurableSpace X] [BorelSpace X] in +/-- The zero extension vanishes at the added point. -/ +@[simp] theorem onePointLiveExtension_infty (f : X → ℝ≥0∞) : + onePointLiveExtension f OnePoint.infty = 0 := rfl + +omit [LocallyCompactSpace X] [SecondCountableTopology X] in +/-- Zero extension from the live space is measurable. -/ +theorem measurable_onePointLiveExtension {f : X → ℝ≥0∞} (hf : Measurable f) : + Measurable (onePointLiveExtension f) := by + intro A hA + by_cases hzero : (0 : ℝ≥0∞) ∈ A + · have hpre : onePointLiveExtension f ⁻¹' A = + ((↑) : X → OnePoint X) '' (f ⁻¹' A) ∪ {OnePoint.infty} := by + ext z + induction z using OnePoint.rec with + | infty => simp only [Set.mem_preimage, onePointLiveExtension_infty, hzero, + Set.mem_union, OnePoint.infty_notMem_image_coe, Set.mem_singleton_iff, or_true] + | coe x => simp only [Set.mem_preimage, onePointLiveExtension_coe, Set.mem_union, + Set.mem_image, OnePoint.coe_eq_coe, exists_eq_right, OnePoint.coe_ne_infty, + Set.mem_singleton_iff, or_false] + rw [hpre] + exact (OnePoint.isOpenEmbedding_coe.measurableEmbedding.measurableSet_image.mpr + (hf hA)).union OnePoint.isClosed_infty.measurableSet + · have hpre : onePointLiveExtension f ⁻¹' A = + ((↑) : X → OnePoint X) '' (f ⁻¹' A) := by + ext z + induction z using OnePoint.rec with + | infty => simp only [Set.mem_preimage, onePointLiveExtension_infty, hzero, + OnePoint.infty_notMem_image_coe] + | coe x => simp only [Set.mem_preimage, onePointLiveExtension_coe, Set.mem_image, + OnePoint.coe_eq_coe, exists_eq_right] + rw [hpre] + exact OnePoint.isOpenEmbedding_coe.measurableEmbedding.measurableSet_image.mpr (hf hA) + +/-- The killed resolvent of the one-point process, on an observable extended by zero at +infinity, is the kernel resolvent of the original sub-Markov semigroup. -/ +theorem killedResolvent_onePointLive_eq_kernelResolvent + (R : PositiveC0ContractiveResolvent X) (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) + (hK : letI := + OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + R.onePointKernelSemigroup.KolmogorovRegular + R.isConservative_onePointKernelSemigroup) + (lam : ℝ) {f : X → ℝ≥0∞} (hf : Measurable f) (x : X) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + IsConservative.killedResolvent R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup + (Set.range ((↑) : X → OnePoint X)) OnePoint.isOpen_range_coe lam + (onePointLiveExtension f) (x : OnePoint X) = + R.kernelSemigroup.kernelResolvent lam f x := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + let : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + unfold IsConservative.killedResolvent SubMarkovKernelSemigroup.kernelResolvent + apply setLIntegral_congr_fun measurableSet_Ioi + intro t _ht + change ENNReal.ofReal (Real.exp (-lam * t)) * + (∫⁻ y, onePointLiveExtension f y ∂IsConservative.killedKernel + R.onePointKernelSemigroup R.isConservative_onePointKernelSemigroup + (Set.range ((↑) : X → OnePoint X)) OnePoint.isOpen_range_coe + (Real.toNNReal t) (x : OnePoint X)) = + ENNReal.ofReal (Real.exp (-lam * t)) * + ∫⁻ y, f y ∂R.kernelSemigroup (Real.toNNReal t) x + congr 1 + rw [R.killedKernel_onePointLive_eq_map rho hrho_cont hrho_pos hrho_lipschitz hrho_compact hK, + lintegral_map + (measurable_onePointLiveExtension hf) OnePoint.continuous_coe.measurable] + rfl + +/-- For a nonnegative `C₀` observable, the killed resolvent is the originally supplied analytic +resolvent, evaluated at the starting point. -/ +theorem killedResolvent_onePointLive_ofReal_eq_operator + (R : PositiveC0ContractiveResolvent X) (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) + (hK : letI := + OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + R.onePointKernelSemigroup.KolmogorovRegular + R.isConservative_onePointKernelSemigroup) + (mu : Semigroup.PositiveShift) (f : C₀(X, ℝ)) (hf0 : ∀ y, 0 ≤ f y) (x : X) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + IsConservative.killedResolvent R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup + (Set.range ((↑) : X → OnePoint X)) OnePoint.isOpen_range_coe (mu : ℝ) + (onePointLiveExtension fun y ↦ ENNReal.ofReal (f y)) (x : OnePoint X) = + ENNReal.ofReal (R.toContractiveResolvent.operator mu f x) := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + let : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + calc + IsConservative.killedResolvent R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup + (Set.range ((↑) : X → OnePoint X)) OnePoint.isOpen_range_coe (mu : ℝ) + (onePointLiveExtension fun y ↦ ENNReal.ofReal (f y)) (x : OnePoint X) = + R.kernelSemigroup.kernelResolvent (mu : ℝ) (fun y ↦ ENNReal.ofReal (f y)) x := + R.killedResolvent_onePointLive_eq_kernelResolvent rho hrho_cont hrho_pos + hrho_lipschitz hrho_compact hK mu + (ENNReal.measurable_ofReal.comp f.continuous.measurable) x + _ = ENNReal.ofReal + (R.isFellerKernelSemigroup_kernelSemigroup.c0Semigroup.resolvent mu f x) := + R.isFellerKernelSemigroup_kernelSemigroup.kernelResolvent_ofReal_eq_resolvent + mu f hf0 x + _ = ENNReal.ofReal (R.toContractiveResolvent.operator mu f x) := by + rw [R.resolvent_c0Semigroup_kernelSemigroup] + +/-- The Laplace transform of the finite exit time from the live part is one minus the shift +times the original kernel resolvent of one. -/ +theorem lintegral_exp_neg_onePoint_exitTime + (R : PositiveC0ContractiveResolvent X) (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) + (hK : letI := + OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + R.onePointKernelSemigroup.KolmogorovRegular + R.isConservative_onePointKernelSemigroup) + (lam : ℝ) (hlam : 0 < lam) (x : X) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + ∫⁻ omega, ({omega | ContinuousPath.exitTime + (Set.range ((↑) : X → OnePoint X)) omega < ⊤} : Set _).indicator + (fun omega ↦ ENNReal.ofReal (Real.exp (-lam * + (ContinuousPath.exitTime + (Set.range ((↑) : X → OnePoint X)) omega).toReal))) omega + ∂IsConservative.continuousProcess R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup (x : OnePoint X) = + 1 - ENNReal.ofReal lam * + R.kernelSemigroup.kernelResolvent lam (fun _ : X ↦ 1) x := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + let : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + have hUexh : @IsOpen (OnePoint X) + (OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz + hrho_compact).toPseudoMetricSpace.toUniformSpace.toTopologicalSpace + (Set.range ((↑) : X → OnePoint X)) := + OnePoint.isOpen_range_coe + have hlem := @IsConservative.lintegral_exp_neg_exitTime (OnePoint X) + (OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact) + inferInstance OnePoint.instMeasurableSpace inferInstance inferInstance inferInstance + R.onePointKernelSemigroup R.isConservative_onePointKernelSemigroup + (Set.range ((↑) : X → OnePoint X)) hUexh lam hlam + (x : OnePoint X) + trans (1 - ENNReal.ofReal lam * + IsConservative.killedResolvent R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup + (Set.range ((↑) : X → OnePoint X)) hUexh lam (fun _ : OnePoint X ↦ 1) x) + · exact hlem + congr 2 + unfold IsConservative.killedResolvent SubMarkovKernelSemigroup.kernelResolvent + apply setLIntegral_congr_fun measurableSet_Ioi + intro t _ht + change ENNReal.ofReal (Real.exp (-lam * t)) * + (∫⁻ _y, 1 ∂IsConservative.killedKernel + R.onePointKernelSemigroup R.isConservative_onePointKernelSemigroup + (Set.range ((↑) : X → OnePoint X)) OnePoint.isOpen_range_coe + (Real.toNNReal t) (x : OnePoint X)) = + ENNReal.ofReal (Real.exp (-lam * t)) * + ∫⁻ _y, 1 ∂R.kernelSemigroup (Real.toNNReal t) x + congr 1 + rw [R.killedKernel_onePointLive_eq_map rho hrho_cont hrho_pos hrho_lipschitz hrho_compact hK, + lintegral_map measurable_const OnePoint.continuous_coe.measurable] + +end MarkovProcess.PositiveC0ContractiveResolvent diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean new file mode 100644 index 0000000000..aa3a177902 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean @@ -0,0 +1,537 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Analysis.SpecialFunctions.Pow.Integral +import Mathlib.MeasureTheory.Integral.Lebesgue.Markov +import Mathlib.Topology.MetricSpace.Lipschitz +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension +import LeanPool.MarkovProcess.MarkovProcess.Main + +/-! +# Kolmogorov bounds on a one-point compactification + +This file provides a compatible metric on the one-point compactification and a local-time form of +the intrinsic Kolmogorov moment criterion. It transports whole-space distance tails, including +the cemetery point, to that local criterion by the weighted layer-cake formula. + +Main results: `OnePoint.exhaustionMetricSpace`, +`SubMarkovKernelSemigroup.HasLocalKolmogorovMoments.toHasKolmogorovMoments`, and +`SubMarkovKernelSemigroup.HasOnePointTailBounds.kolmogorovRegular`. + +The tail bounds and their scalar integral budget remain hypotheses for the consumer; no analytic +estimate for a particular semigroup is asserted here. +-/ + +open Filter MeasureTheory ProbabilityTheory Set Topology +open scoped ENNReal NNReal ZeroAtInfty + +noncomputable section + +namespace OnePoint + +variable {X : Type*} [MetricSpace X] + +/-- The explicit distance on the one-point compactification associated with a positive +exhaustion function. -/ +def exhaustionDist (rho : X → ℝ) : OnePoint X → OnePoint X → ℝ + | ∞, ∞ => 0 + | ∞, (y : X) => rho y + | (x : X), ∞ => rho x + | (x : X), (y : X) => min (dist x y) (rho x + rho y) + +/-- The exhaustion distance from the added point to itself vanishes. -/ +@[simp] theorem exhaustionDist_infty_infty (rho : X → ℝ) : + exhaustionDist rho (∞ : OnePoint X) ∞ = 0 := rfl + +/-- The exhaustion distance from the added point to a live point is the exhaustion level there. -/ +@[simp] theorem exhaustionDist_infty_coe (rho : X → ℝ) (y : X) : + exhaustionDist rho ∞ (y : OnePoint X) = rho y := rfl + +/-- The exhaustion distance from a live point to the added point is its exhaustion level. -/ +@[simp] theorem exhaustionDist_coe_infty (rho : X → ℝ) (x : X) : + exhaustionDist rho (x : OnePoint X) ∞ = rho x := rfl + +/-- Between live points the exhaustion distance is the live distance capped by the sum of the +two exhaustion levels. -/ +@[simp] theorem exhaustionDist_coe_coe (rho : X → ℝ) (x y : X) : + exhaustionDist rho (x : OnePoint X) (y : OnePoint X) = + min (dist x y) (rho x + rho y) := rfl + +private theorem exhaustionDist_self (rho : X → ℝ) (hrho_pos : ∀ x, 0 < rho x) + (z : OnePoint X) : + exhaustionDist rho z z = 0 := by + induction z using OnePoint.rec with + | infty => rfl + | coe x => + rw [exhaustionDist_coe_coe, dist_self, min_eq_left] + exact add_nonneg (hrho_pos x).le (hrho_pos x).le + +private theorem exhaustionDist_comm (rho : X → ℝ) (z w : OnePoint X) : + exhaustionDist rho z w = exhaustionDist rho w z := by + induction z using OnePoint.rec with + | infty => induction w using OnePoint.rec <;> rfl + | coe x => + induction w using OnePoint.rec with + | infty => rfl + | coe y => simp only [exhaustionDist_coe_coe, dist_comm, add_comm] + +private theorem exhaustionDist_triangle (rho : X → ℝ) (hrho_pos : ∀ x, 0 < rho x) + (hrho_lipschitz : LipschitzWith 1 rho) (z w u : OnePoint X) : + exhaustionDist rho z u ≤ exhaustionDist rho z w + exhaustionDist rho w u := by + induction z using OnePoint.rec with + | infty => + induction w using OnePoint.rec with + | infty => simp only [exhaustionDist_infty_infty, zero_add, le_rfl] + | coe y => + induction u using OnePoint.rec with + | infty => + simp only [exhaustionDist_infty_infty, exhaustionDist_infty_coe, + exhaustionDist_coe_infty] + exact add_nonneg (hrho_pos y).le (hrho_pos y).le + | coe x => + simp only [exhaustionDist_infty_coe, exhaustionDist_coe_coe] + rcases min_choice (dist y x) (rho y + rho x) with hmin | hmin + · rw [hmin] + simpa only [NNReal.coe_one, one_mul, dist_comm] using + LipschitzWith.le_add_mul hrho_lipschitz x y + · rw [hmin] + linarith only [(hrho_pos y).le] + | coe x => + induction w using OnePoint.rec with + | infty => + induction u using OnePoint.rec with + | infty => + simp only [exhaustionDist_coe_infty, exhaustionDist_infty_infty, add_zero, + le_rfl] + | coe y => + simp only [exhaustionDist_coe_coe, exhaustionDist_coe_infty, + exhaustionDist_infty_coe] + exact min_le_right _ _ + | coe y => + induction u using OnePoint.rec with + | infty => + simp only [exhaustionDist_coe_infty, exhaustionDist_coe_coe] + rcases min_choice (dist x y) (rho x + rho y) with hmin | hmin + · rw [hmin] + simpa only [NNReal.coe_one, one_mul, add_comm] using + LipschitzWith.le_add_mul hrho_lipschitz x y + · rw [hmin] + linarith only [(hrho_pos y).le] + | coe u => + simp only [exhaustionDist_coe_coe] + rcases min_choice (dist x y) (rho x + rho y) with hxy | hxy <;> + rcases min_choice (dist y u) (rho y + rho u) with hyu | hyu + · rw [hxy, hyu] + exact (min_le_left _ _).trans (dist_triangle x y u) + · rw [hxy, hyu] + calc + min (dist x u) (rho x + rho u) ≤ rho x + rho u := min_le_right _ _ + _ ≤ (rho y + dist x y) + rho u := add_le_add (by + simpa only [NNReal.coe_one, one_mul] using + LipschitzWith.le_add_mul hrho_lipschitz x y) le_rfl + _ = dist x y + (rho y + rho u) := by ring + · rw [hxy, hyu] + calc + min (dist x u) (rho x + rho u) ≤ rho x + rho u := min_le_right _ _ + _ ≤ rho x + (rho y + dist u y) := add_le_add le_rfl (by + simpa only [NNReal.coe_one, one_mul] using + LipschitzWith.le_add_mul hrho_lipschitz u y) + _ = (rho x + rho y) + dist y u := by rw [dist_comm u y]; ring + · rw [hxy, hyu] + calc + min (dist x u) (rho x + rho u) ≤ rho x + rho u := min_le_right _ _ + _ ≤ (rho x + rho y) + (rho y + rho u) := by + linarith only [(hrho_pos y).le] + +private theorem exhaustionDist_eq_zero (rho : X → ℝ) (hrho_pos : ∀ x, 0 < rho x) + (z w : OnePoint X) (hzw : exhaustionDist rho z w = 0) : z = w := by + induction z using OnePoint.rec with + | infty => + induction w using OnePoint.rec with + | infty => rfl + | coe y => + change rho y = 0 at hzw + exact (ne_of_gt (hrho_pos y) hzw).elim + | coe x => + induction w using OnePoint.rec with + | infty => + change rho x = 0 at hzw + exact (ne_of_gt (hrho_pos x) hzw).elim + | coe y => + rcases le_total (dist x y) (rho x + rho y) with hle | hle + · rw [exhaustionDist_coe_coe, min_eq_left hle] at hzw + exact congrArg ((↑) : X → OnePoint X) (dist_eq_zero.mp hzw) + · rw [exhaustionDist_coe_coe, min_eq_right hle] at hzw + exact (ne_of_gt (add_pos (hrho_pos x) (hrho_pos y)) hzw).elim + +private theorem isOpen_iff_exhaustionDist {rho : X → ℝ} (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) + (s : Set (OnePoint X)) : + IsOpen s ↔ ∀ z ∈ s, ∃ epsilon > 0, ∀ w, exhaustionDist rho z w < epsilon → w ∈ s := by + constructor + · intro hs z hzs + induction z using OnePoint.rec with + | infty => + let K : Set X := ((↑) ⁻¹' s : Set X)ᶜ + have hK : IsCompact K := (OnePoint.isOpen_def.mp hs).1 hzs + obtain ⟨epsilon, hepsilon, hepsilonK⟩ := + hK.exists_forall_le' hrho_cont.continuousOn fun x _hx ↦ hrho_pos x + refine ⟨epsilon, hepsilon, fun w hw ↦ ?_⟩ + induction w using OnePoint.rec with + | infty => exact hzs + | coe y => + have hyK : y ∉ K := fun hyK ↦ (not_lt_of_ge (hepsilonK y hyK)) hw + exact not_not.mp hyK + | coe x => + have hsX : IsOpen ((↑) ⁻¹' s : Set X) := (OnePoint.isOpen_def.mp hs).2 + obtain ⟨epsilon, hepsilon, hepsilon_ball⟩ := + Metric.isOpen_iff.mp hsX x hzs + refine ⟨min epsilon (rho x), lt_min hepsilon (hrho_pos x), fun w hw ↦ ?_⟩ + induction w using OnePoint.rec with + | infty => + exact (not_lt_of_ge (min_le_right epsilon (rho x))) hw |>.elim + | coe y => + apply hepsilon_ball + rcases min_lt_iff.mp hw with hdist | hrho + · rw [Metric.mem_ball, dist_comm] + exact lt_of_lt_of_le hdist (min_le_left epsilon (rho x)) + · exact (not_lt_of_ge + ((min_le_right epsilon (rho x)).trans (le_add_of_nonneg_right + (hrho_pos y).le)) hrho).elim + · intro hmetric + have hsX : IsOpen ((↑) ⁻¹' s : Set X) := Metric.isOpen_iff.mpr fun x hx ↦ by + obtain ⟨epsilon, hepsilon, hepsilon_ball⟩ := hmetric (x : OnePoint X) hx + refine ⟨epsilon, hepsilon, fun y hy ↦ ?_⟩ + apply hepsilon_ball (y : OnePoint X) + rw [Metric.mem_ball, dist_comm] at hy + exact (min_le_left (dist x y) (rho x + rho y)).trans_lt hy + refine OnePoint.isOpen_def.mpr ⟨?_, hsX⟩ + intro hinfty + obtain ⟨epsilon, hepsilon, hepsilon_ball⟩ := hmetric OnePoint.infty hinfty + apply IsCompact.of_isClosed_subset (hrho_compact epsilon hepsilon) hsX.isClosed_compl + intro x hx + change epsilon ≤ rho x + by_contra hnot + have hrho : rho x < epsilon := lt_of_not_ge hnot + exact hx (hepsilon_ball (x : OnePoint X) hrho) + +/-- The explicit metric on the one-point compactification determined by a positive Lipschitz +exhaustion function with compact positive superlevel sets. -/ +noncomputable def exhaustionMetricSpace (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) : + MetricSpace (OnePoint X) := + MetricSpace.ofDistTopology (exhaustionDist rho) (exhaustionDist_self rho hrho_pos) + (exhaustionDist_comm rho) (exhaustionDist_triangle rho hrho_pos hrho_lipschitz) + (isOpen_iff_exhaustionDist hrho_cont hrho_pos hrho_compact) + (exhaustionDist_eq_zero rho hrho_pos) + +/-- The exhaustion metric has definitionally the canonical one-point topology. -/ +theorem exhaustionMetricSpace_toTopologicalSpace (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) : + (exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz + hrho_compact).toPseudoMetricSpace.toUniformSpace.toTopologicalSpace = + OnePoint.instTopologicalSpace := rfl + +/-- The exhaustion distance between live points is at most their original distance. -/ +theorem exhaustionDist_coe_coe_le (rho : X → ℝ) (x y : X) : + exhaustionDist rho (x : OnePoint X) (y : OnePoint X) ≤ dist x y := + min_le_left _ _ + +/-- Under the explicit metric, the distance between live points is the displayed exhaustion +formula. -/ +theorem exhaustionMetricSpace_dist_coe_coe (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) (x y : X) : + letI := exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + dist (x : OnePoint X) (y : OnePoint X) = min (dist x y) (rho x + rho y) := rfl + +/-- Under the explicit metric, live-point distance is bounded by the original distance. -/ +theorem exhaustionMetricSpace_dist_coe_coe_le (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) (x y : X) : + letI := exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + dist (x : OnePoint X) (y : OnePoint X) ≤ dist x y := by + let := exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + exact min_le_left _ _ + +/-- Under the explicit metric, a live point's distance to infinity is its exhaustion value. -/ +theorem exhaustionMetricSpace_dist_coe_infty (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) (x : X) : + letI := exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + dist (x : OnePoint X) OnePoint.infty = rho x := rfl + +/-- A live exhaustion-metric tail is contained in the corresponding tail for the original +metric. -/ +theorem exhaustionMetricSpace_live_tail_subset (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) (x : X) (r : ℝ) : + letI := exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + {y : X | r < dist (y : OnePoint X) (x : OnePoint X)} ⊆ {y | r < dist y x} := by + let := exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + intro y hy + exact hy.trans_le (exhaustionMetricSpace_dist_coe_coe_le rho hrho_cont hrho_pos + hrho_lipschitz hrho_compact y x) + +end OnePoint + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [PseudoEMetricSpace alpha] [MeasurableSpace alpha] + +/-- A Kolmogorov moment estimate required only for time increments at most one, together with a +uniform bound for all displacements. On a compact metric space the latter bound is automatic. -/ +def HasLocalKolmogorovMoments (P : SubMarkovKernelSemigroup alpha) + (p q : ℝ) (M B : ℝ≥0) : Prop := + 0 < p ∧ 1 < q ∧ + (∀ (h : ℝ≥0), h ≤ 1 → ∀ y : alpha, + ∫⁻ z, edist z y ^ p ∂(P h y) ≤ M * (h : ℝ≥0∞) ^ q) ∧ + ∀ y z : alpha, edist z y ^ p ≤ B + +namespace HasLocalKolmogorovMoments + +variable {P : SubMarkovKernelSemigroup alpha} {p q : ℝ} {M B : ℝ≥0} + +/-- A local-time moment estimate plus a global displacement bound gives the library's global +moment criterion, with constant `M + B`. -/ +theorem toHasKolmogorovMoments (hP : P.IsConservative) + (hmom : P.HasLocalKolmogorovMoments p q M B) : + P.HasKolmogorovMoments p q (M + B) := by + refine ⟨hmom.1, hmom.2.1, fun h y ↦ ?_⟩ + by_cases hh : h ≤ 1 + · calc + ∫⁻ z, edist z y ^ p ∂(P h y) ≤ M * (h : ℝ≥0∞) ^ q := hmom.2.2.1 h hh y + _ ≤ (M + B) * (h : ℝ≥0∞) ^ q := by gcongr; exact le_add_right le_rfl + · have hh1 : (1 : ℝ≥0∞) ≤ h := by + exact_mod_cast (le_of_not_ge hh) + have hq : 0 < q := lt_trans zero_lt_one hmom.2.1 + calc + ∫⁻ z, edist z y ^ p ∂(P h y) ≤ ∫⁻ _z, (B : ℝ≥0∞) ∂(P h y) := + lintegral_mono fun z ↦ hmom.2.2.2 y z + _ = B := by rw [lintegral_const, hP h y, mul_one] + _ ≤ (M + B) * 1 := by + rw [mul_one] + exact le_add_left le_rfl + _ ≤ (M + B) * (h : ℝ≥0∞) ^ q := by + gcongr + exact ENNReal.one_le_rpow hh1 hq + +end HasLocalKolmogorovMoments + +section OnePointTails + +variable {X : Type*} [MetricSpace X] [LocallyCompactSpace X] + [SecondCountableTopology X] (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) + +omit [LocallyCompactSpace X] [SecondCountableTopology X] in +/-- The one-point compactification is complete under the exhaustion metric, since it is +compact under that metric's (canonical) topology. This is a typeclass-search cache: it lets +`letI := OnePoint.exhaustionMetricSpace …` discharge the ambient `[CompleteSpace (OnePoint X)]` +hypothesis of `KolmogorovRegular` without re-deriving compactness at each call site. -/ +private instance instCompleteSpaceOnePointExhaustion : + @CompleteSpace (OnePoint X) + (OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz + hrho_compact).toPseudoMetricSpace.toUniformSpace := by + have hCompact : @CompactSpace (OnePoint X) + (OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz + hrho_compact).toPseudoMetricSpace.toUniformSpace.toTopologicalSpace := by + rw [OnePoint.exhaustionMetricSpace_toTopologicalSpace] + infer_instance + exact @complete_of_compact (OnePoint X) + (OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz + hrho_compact).toPseudoMetricSpace.toUniformSpace + hCompact + +/-- The one-point compactification is a Borel space under the exhaustion metric: its +`MeasurableSpace` (the canonical Borel structure fixed at `OnePoint.instMeasurableSpace`) agrees +with the exhaustion metric's Borel sets, since the two topologies coincide. This is a +typeclass-search cache in the same spirit as `instCompleteSpaceOnePointExhaustion`. -/ +private instance instBorelSpaceOnePointExhaustion : + @BorelSpace (OnePoint X) + (OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz + hrho_compact).toPseudoMetricSpace.toUniformSpace.toTopologicalSpace + OnePoint.instMeasurableSpace := by + rw [OnePoint.exhaustionMetricSpace_toTopologicalSpace] + exact OnePoint.instBorelSpace + +/-- The one-point compactification is second countable under the exhaustion metric's topology, +since that topology coincides with the canonical one. Typeclass-search cache, as above. -/ +private instance instSecondCountableTopologyOnePointExhaustion : + @SecondCountableTopology (OnePoint X) + (OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz + hrho_compact).toPseudoMetricSpace.toUniformSpace.toTopologicalSpace := by + rw [OnePoint.exhaustionMetricSpace_toTopologicalSpace] + exact OnePoint.instSecondCountableTopology + +omit [LocallyCompactSpace X] [SecondCountableTopology X] in +/-- Kernel-level Markov inequality for a nonnegative `C₀` majorant of an exhaustion-metric tail +set. A semigroup comparison bound on the integral becomes the advertised exponential tail +bound. -/ +theorem measure_gt_le_of_le_c0 (P : SubMarkovKernelSemigroup (OnePoint X)) + (rho : X → ℝ) (hrho_cont : Continuous rho) (hrho_pos : ∀ x, 0 < rho x) + (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) + (h : ℝ≥0) (x : X) (r A theta : ℝ) (v : C₀(OnePoint X, ℝ)) + (hA : 0 < A) (hv_nonneg : ∀ z, 0 ≤ v z) + (hmajorant : ∀ z, r < OnePoint.exhaustionDist rho z (x : OnePoint X) → A ≤ v z) + (hintegral : ∫ z, v z ∂P h (x : OnePoint X) ≤ + Real.exp (theta * (h : ℝ)) * v (x : OnePoint X)) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + P h (x : OnePoint X) {z | r < dist z (x : OnePoint X)} ≤ + ENNReal.ofReal (Real.exp (theta * (h : ℝ)) * v (x : OnePoint X) / A) := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + let mu := P h (x : OnePoint X) + let : IsFiniteMeasure mu := + ⟨lt_of_le_of_lt (P.measure_univ_le_one h (x : OnePoint X)) ENNReal.one_lt_top⟩ + have hv_integrable : Integrable v mu := v.toBCF.integrable mu + have hmajorant' : + {z : OnePoint X | r < dist z (x : OnePoint X)} ⊆ + {z | ENNReal.ofReal A ≤ ENNReal.ofReal (v z)} := by + intro z hz + exact ENNReal.ofReal_le_ofReal (hmajorant z hz) + calc + mu {z | r < dist z (x : OnePoint X)} ≤ + mu {z | ENNReal.ofReal A ≤ ENNReal.ofReal (v z)} := measure_mono hmajorant' + _ ≤ (∫⁻ z, ENNReal.ofReal (v z) ∂mu) / ENNReal.ofReal A := by + apply meas_ge_le_lintegral_div + · exact (ENNReal.measurable_ofReal.comp v.continuous.measurable).aemeasurable + · exact (ENNReal.ofReal_pos.mpr hA).ne' + · exact ENNReal.ofReal_ne_top + _ = ENNReal.ofReal (∫ z, v z ∂mu) / ENNReal.ofReal A := by + rw [ofReal_integral_eq_lintegral_ofReal hv_integrable + (Eventually.of_forall hv_nonneg)] + _ ≤ ENNReal.ofReal (Real.exp (theta * (h : ℝ)) * v (x : OnePoint X)) / + ENNReal.ofReal A := by + gcongr + _ = ENNReal.ofReal (Real.exp (theta * (h : ℝ)) * v (x : OnePoint X) / A) := by + rw [ENNReal.ofReal_div_of_pos hA] + +/-- Whole-space distance-tail estimates and their weighted scalar layer-cake budget, which imply +a local Kolmogorov moment estimate on the one-point compactification. The tail set includes the +point at infinity whenever its distance from the live starting point exceeds the radius. -/ +def HasOnePointTailBounds (P : SubMarkovKernelSemigroup (OnePoint X)) + (p q : ℝ) (M B : ℝ≥0) + (phi : ℝ≥0 → X → ℝ → ℝ≥0∞) : Prop := + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + (∀ x, rho x ≤ 1) ∧ 0 < p ∧ 1 < q ∧ + (∀ (h : ℝ≥0), h ≤ 1 → ∀ (x : X) (r : ℝ), + 0 < r → P h (x : OnePoint X) {z | r < dist z (x : OnePoint X)} ≤ phi h x r) ∧ + (∀ (h : ℝ≥0), h ≤ 1 → ∀ x : X, + ENNReal.ofReal p * + ∫⁻ r in Set.Ioi (0 : ℝ), + phi h x r * ENNReal.ofReal (r ^ (p - 1)) ≤ + M * (h : ℝ≥0∞) ^ q) ∧ + ∀ z w : OnePoint X, edist w z ^ p ≤ B + +namespace HasOnePointTailBounds + +variable {rho : X → ℝ} {hrho_cont : Continuous rho} {hrho_pos : ∀ x, 0 < rho x} + {hrho_lipschitz : LipschitzWith 1 rho} + {hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}} +variable {P : SubMarkovKernelSemigroup (OnePoint X)} {p q : ℝ} {M B : ℝ≥0} + {phi : ℝ≥0 → X → ℝ → ℝ≥0∞} + +/-- Whole-space distance tails and their weighted budget imply the local moment criterion. -/ +theorem hasLocalKolmogorovMoments + (htail : P.HasOnePointTailBounds rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + p q M B phi) + (hAbsorb : ∀ h, P h OnePoint.infty = Measure.dirac OnePoint.infty) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + P.HasLocalKolmogorovMoments p q M B := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + refine ⟨htail.2.1, htail.2.2.1, ?_, htail.2.2.2.2.2⟩ + intro h hh z + induction z using OnePoint.rec with + | infty => + rw [hAbsorb h, lintegral_dirac] + simp only [edist_self, ENNReal.zero_rpow_of_pos htail.2.1] + exact zero_le + | coe x => + let mu := P h (x : OnePoint X) + have hBorel : BorelSpace (OnePoint X) := OnePoint.instBorelSpace + have hSecondCountable : SecondCountableTopology (OnePoint X) := + OnePoint.instSecondCountableTopology + have hdist_meas : Measurable (fun z : OnePoint X ↦ dist z (x : OnePoint X)) := + measurable_dist.comp (measurable_id.prodMk measurable_const) + rw [show (∫⁻ z, edist z (x : OnePoint X) ^ p ∂mu) = + ∫⁻ z, ENNReal.ofReal (dist z (x : OnePoint X) ^ p) ∂mu by + apply lintegral_congr + intro z + rw [edist_dist, ENNReal.ofReal_rpow_of_nonneg dist_nonneg htail.2.1.le]] + rw [lintegral_rpow_eq_lintegral_meas_lt_mul mu + (Eventually.of_forall fun _z ↦ dist_nonneg) + hdist_meas.aemeasurable htail.2.1] + calc + ENNReal.ofReal p * + ∫⁻ r in Set.Ioi (0 : ℝ), + mu {z | r < dist z (x : OnePoint X)} * ENNReal.ofReal (r ^ (p - 1)) ≤ + ENNReal.ofReal p * + ∫⁻ r in Set.Ioi (0 : ℝ), + phi h x r * ENNReal.ofReal (r ^ (p - 1)) := by + apply mul_le_mul_right + apply setLIntegral_mono' measurableSet_Ioi + intro r hr + gcongr + exact htail.2.2.2.1 h hh x r hr + _ ≤ M * (h : ℝ≥0∞) ^ q := htail.2.2.2.2.1 h hh x + +/-- Whole-space tail bounds yield the global intrinsic moment criterion. -/ +theorem hasKolmogorovMoments (hP : P.IsConservative) + (htail : P.HasOnePointTailBounds rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + p q M B phi) + (hAbsorb : ∀ h, P h OnePoint.infty = Measure.dirac OnePoint.infty) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + P.HasKolmogorovMoments p q (M + B) := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + exact + (htail.hasLocalKolmogorovMoments hAbsorb).toHasKolmogorovMoments hP + +/-- Whole-space tail bounds yield the regularity needed for the continuous-path process. -/ +theorem kolmogorovRegular (hP : P.IsConservative) + (htail : P.HasOnePointTailBounds rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + p q M B phi) + (hAbsorb : ∀ h, P h OnePoint.infty = Measure.dirac OnePoint.infty) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + P.KolmogorovRegular hP := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + exact + KolmogorovRegular.of_hasKolmogorovMoments P hP (htail.hasKolmogorovMoments hP hAbsorb) + +end HasOnePointTailBounds + +end OnePointTails + +end MarkovProcess.SubMarkovKernelSemigroup + +namespace MarkovProcess.PositiveC0ContractiveResolvent + +open MarkovProcess.SubMarkovKernelSemigroup + +variable {X : Type*} [MetricSpace X] [LocallyCompactSpace X] + [SecondCountableTopology X] [MeasurableSpace X] [BorelSpace X] + +/-- Whole-space tail bounds for the compactified semigroup produced by a positive `C₀`-resolvent +give the regularity required to construct its continuous-path process. -/ +theorem kolmogorovRegular_onePointKernelSemigroup + (R : PositiveC0ContractiveResolvent X) (rho : X → ℝ) (hrho_cont : Continuous rho) + (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) + (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) + {p q : ℝ} {M B : ℝ≥0} + {phi : ℝ≥0 → X → ℝ → ℝ≥0∞} + (htail : R.onePointKernelSemigroup.HasOnePointTailBounds rho hrho_cont hrho_pos + hrho_lipschitz hrho_compact p q M B phi) : + letI := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + R.onePointKernelSemigroup.KolmogorovRegular + R.isConservative_onePointKernelSemigroup := by + let := OnePoint.exhaustionMetricSpace rho hrho_cont hrho_pos hrho_lipschitz hrho_compact + exact htail.kolmogorovRegular R.isConservative_onePointKernelSemigroup + R.onePointKernelSemigroup_absorbing + +end MarkovProcess.PositiveC0ContractiveResolvent diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Operator.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Operator.lean new file mode 100644 index 0000000000..7688536948 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Operator.lean @@ -0,0 +1,109 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp + +/-! +# Operators associated with a sub-Markov kernel semigroup + +This file constructs the jointly measurable time-space kernel and the +canonical contractive operator families on real `Lᵖ`. It deliberately makes +no claim here about the operator semigroup laws or strong continuity. +-/ + +open MeasureTheory +open ProbabilityTheory +open scoped ENNReal + +namespace MarkovProcess + +variable {α : Type*} [MeasurableSpace α] + +namespace SubMarkovKernelSemigroup + +variable (P : SubMarkovKernelSemigroup α) + +/-- The time-space kernel obtained from the jointly measurable transition +measures of `P`. -/ +def jointKernel : Kernel (NNReal × α) α where + toFun p := P p.1 p.2 + measurable' := P.measurable_kernel + +@[simp] +theorem jointKernel_apply (p : NNReal × α) : P.jointKernel p = P p.1 p.2 := + rfl + +/-- Joint strong measurability of the raw kernel integral. -/ +theorem stronglyMeasurable_kernelIntegral {f : α → ℝ} + (hf : StronglyMeasurable f) : + StronglyMeasurable fun p : NNReal × α ↦ kernelIntegral (P p.1) f p.2 := by + exact hf.integral_kernel (κ := P.jointKernel) + +/-- Joint measurability of the raw kernel integral. -/ +theorem measurable_kernelIntegral {f : α → ℝ} (hf : Measurable f) : + Measurable fun p : NNReal × α ↦ kernelIntegral (P p.1) f p.2 := + (P.stronglyMeasurable_kernelIntegral hf.stronglyMeasurable).measurable + +/-- A measure is subinvariant for `P` when it dominates its image under every +transition kernel. -/ +def IsSubInvariant (μ : Measure α) : Prop := + ∀ t, P t ∘ₘ μ ≤ μ + +private instance fact_one_le_coe_nnreal (p : NNReal) [Fact (1 ≤ p)] : + Fact (1 ≤ (p : ℝ≥0∞)) := ⟨by exact_mod_cast Fact.out⟩ + +/-- The canonical finite-exponent operator family associated with `P`. -/ +noncomputable def operatorFinite (μ : Measure α) (hμ : P.IsSubInvariant μ) + (p : NNReal) [Fact (1 ≤ p)] : + NNReal → Lp ℝ (p : ℝ≥0∞) μ →L[ℝ] Lp ℝ (p : ℝ≥0∞) μ := + fun t ↦ kernelLpFinite μ (P t) (P.isSubMarkovKernel t) (hμ t) p + +/-- The canonical infinite-exponent operator family associated with `P`. -/ +noncomputable def operatorTop (μ : Measure α) (hμ : P.IsSubInvariant μ) : + NNReal → Lp ℝ ∞ μ →L[ℝ] Lp ℝ ∞ μ := + fun t ↦ kernelLpTop μ (P t) (P.isSubMarkovKernel t) (hμ t) + +/-- A finite-exponent operator family is associated with `P` when each output +is represented by the corresponding raw kernel integral. -/ +def IsAssociatedFinite (μ : Measure α) (p : NNReal) [Fact (1 ≤ p)] + (T : NNReal → Lp ℝ (p : ℝ≥0∞) μ →L[ℝ] Lp ℝ (p : ℝ≥0∞) μ) : Prop := + ∀ t f, T t f =ᵐ[μ] kernelIntegral (P t) f + +/-- An infinite-exponent operator family is associated with `P` when each +output is represented by the corresponding raw kernel integral. -/ +def IsAssociatedTop (μ : Measure α) + (T : NNReal → Lp ℝ ∞ μ →L[ℝ] Lp ℝ ∞ μ) : Prop := + ∀ t f, T t f =ᵐ[μ] kernelIntegral (P t) f + +/-- The canonical finite-exponent family is associated with `P`. -/ +theorem isAssociatedFinite_operatorFinite (μ : Measure α) (hμ : P.IsSubInvariant μ) + (p : NNReal) [Fact (1 ≤ p)] : + P.IsAssociatedFinite μ p (P.operatorFinite μ hμ p) := by + intro t f + exact coeFn_kernelLpFinite μ (P t) (P.isSubMarkovKernel t) (hμ t) p f + +/-- The canonical infinite-exponent family is associated with `P`. -/ +theorem isAssociatedTop_operatorTop (μ : Measure α) (hμ : P.IsSubInvariant μ) : + P.IsAssociatedTop μ (P.operatorTop μ hμ) := by + intro t f + exact coeFn_kernelLpTop μ (P t) (P.isSubMarkovKernel t) (hμ t) f + +/-- Every time slice of the canonical finite-exponent family has norm at most +one. -/ +theorem norm_operatorFinite_le (μ : Measure α) (hμ : P.IsSubInvariant μ) + (p : NNReal) [Fact (1 ≤ p)] (t : NNReal) : + ‖P.operatorFinite μ hμ p t‖ ≤ 1 := + norm_kernelLpFinite_le μ (P t) (P.isSubMarkovKernel t) (hμ t) p + +/-- Every time slice of the canonical infinite-exponent family has norm at +most one. -/ +theorem norm_operatorTop_le (μ : Measure α) (hμ : P.IsSubInvariant μ) + (t : NNReal) : ‖P.operatorTop μ hμ t‖ ≤ 1 := + norm_kernelLpTop_le μ (P t) (P.isSubMarkovKernel t) (hμ t) + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean new file mode 100644 index 0000000000..6373ec9c2e --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean @@ -0,0 +1,149 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator + +/-! +# Semigroup laws for the canonical kernel operators + +This file proves only the algebraic zero- and add-time laws for the canonical +real `Lᵖ` operator families. It makes no strong-continuity claim. +-/ + +open MeasureTheory +open ProbabilityTheory +open scoped ENNReal + +namespace MarkovProcess + +variable {α : Type*} [MeasurableSpace α] + +namespace SubMarkovKernelSemigroup + +variable (P : SubMarkovKernelSemigroup α) + +private instance fact_one_le_coe_nnreal (p : NNReal) [Fact (1 ≤ p)] : + Fact (1 ≤ (p : ℝ≥0∞)) := ⟨by exact_mod_cast Fact.out⟩ + +private theorem kernelIntegral_id_ae {μ : Measure α} {f : α → ℝ} + (hf : AEStronglyMeasurable f μ) : + kernelIntegral Kernel.id f =ᵐ[μ] f := by + let g := hf.mk f + have hfg : kernelIntegral Kernel.id f =ᵐ[μ] kernelIntegral Kernel.id g := + kernelIntegral_congr_ae (by rw [Measure.id_comp]) hf.ae_eq_mk + refine hfg.trans ?_ + filter_upwards [hf.ae_eq_mk] with x hx + rw [kernelIntegral, Kernel.id_apply, integral_dirac' g x hf.stronglyMeasurable_mk] + exact hx.symm + +private theorem ae_integrable_kernel_finite {μ : Measure α} {κ : Kernel α α} + (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) {p : NNReal} + (hp : 1 ≤ p) (f : Lp ℝ (p : ℝ≥0∞) μ) : ∀ᵐ x ∂μ, Integrable f (κ x) := by + let : IsFiniteKernel κ := hκ.isFiniteKernel + have hfComp : MemLp f p (κ ∘ₘ μ) := (Lp.memLp f).mono_measure hκμ + have hFiberEq := Measure.ae_ae_of_ae_comp hfComp.1.ae_eq_mk + have hp0 : (p : ℝ≥0∞) ≠ 0 := by + exact_mod_cast ne_of_gt (zero_lt_one.trans_le hp) + have hpowInt := hfComp.integrable_norm_rpow hp0 ENNReal.coe_ne_top + have hFiberInt := Measure.ae_integrable_of_integrable_comp hpowInt + filter_upwards [hFiberEq, hFiberInt] with x hxEq hxInt + have hxEq' : f =ᵐ[κ x] hfComp.1.mk f := hxEq + have hxMeas : AEStronglyMeasurable f (κ x) := + hfComp.1.stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq'.symm + have hxMemLp : MemLp f p (κ x) := + (integrable_norm_rpow_iff hxMeas hp0 ENNReal.coe_ne_top).mp hxInt + exact hxMemLp.integrable (by exact_mod_cast hp) + +private theorem ae_integrable_kernel_top {μ : Measure α} {κ : Kernel α α} + (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) + (f : Lp ℝ ∞ μ) : ∀ᵐ x ∂μ, Integrable f (κ x) := by + have hCtop : eLpNormEssSup f μ ≠ ∞ := by + rw [← eLpNorm_exponent_top] + exact (Lp.memLp f).2.ne + have hCcoe : ((eLpNormEssSup f μ).toNNReal : ℝ≥0∞) = eLpNormEssSup f μ := + ENNReal.coe_toNNReal hCtop + have hFiberEq : ∀ᵐ x ∂μ, f =ᵐ[κ x] (Lp.aestronglyMeasurable f).mk f := + ae_ae_kernel_of_comp_le hκμ (Lp.aestronglyMeasurable f).ae_eq_mk + have hBound := ae_ae_kernel_of_comp_le hκμ (enorm_ae_le_eLpNormEssSup f μ) + let : IsFiniteKernel κ := hκ.isFiniteKernel + filter_upwards [hFiberEq, hBound] with x hxEq hxBound + have hxAS : AEStronglyMeasurable f (κ x) := + (Lp.aestronglyMeasurable f).stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq.symm + apply MemLp.integrable (q := ∞) le_top + apply memLp_top_of_bound_enorm hxAS (eLpNormEssSup f μ).toNNReal + simpa only [hCcoe] using hxBound + +private theorem kernelIntegral_add_ae_finite {μ : Measure α} + (hμ : P.IsSubInvariant μ) (p : NNReal) [Fact (1 ≤ p)] + (s t : NNReal) (f : Lp ℝ (p : ℝ≥0∞) μ) : + kernelIntegral (P (s + t)) f =ᵐ[μ] + kernelIntegral (P s) (kernelIntegral (P t) f) := by + filter_upwards + [ae_integrable_kernel_finite (P.isSubMarkovKernel (s + t)) (hμ (s + t)) Fact.out f] + with x hx + have hx' : Integrable f ((P t ∘ₖ P s) x) := by + rw [← P.add] + exact hx + rw [kernelIntegral, P.add] + exact Kernel.integral_comp hx' + +private theorem kernelIntegral_add_ae_top {μ : Measure α} + (hμ : P.IsSubInvariant μ) (s t : NNReal) (f : Lp ℝ ∞ μ) : + kernelIntegral (P (s + t)) f =ᵐ[μ] + kernelIntegral (P s) (kernelIntegral (P t) f) := by + filter_upwards + [ae_integrable_kernel_top (P.isSubMarkovKernel (s + t)) (hμ (s + t)) f] with x hx + have hx' : Integrable f ((P t ∘ₖ P s) x) := by + rw [← P.add] + exact hx + rw [kernelIntegral, P.add] + exact Kernel.integral_comp hx' + +/-- The finite-exponent canonical operator at time zero is the identity. -/ +theorem operatorFinite_zero (μ : Measure α) (hμ : P.IsSubInvariant μ) + (p : NNReal) [Fact (1 ≤ p)] : + P.operatorFinite μ hμ p 0 = ContinuousLinearMap.id ℝ (Lp ℝ (p : ℝ≥0∞) μ) := by + ext f + refine (P.isAssociatedFinite_operatorFinite μ hμ p 0 f).trans ?_ + rw [P.zero] + exact (kernelIntegral_id_ae (Lp.aestronglyMeasurable f)).trans + Filter.EventuallyEq.rfl + +/-- The finite-exponent canonical operators obey the add-time law. -/ +theorem operatorFinite_add (μ : Measure α) (hμ : P.IsSubInvariant μ) + (p : NNReal) [Fact (1 ≤ p)] (s t : NNReal) : + P.operatorFinite μ hμ p (s + t) = + (P.operatorFinite μ hμ p s).comp (P.operatorFinite μ hμ p t) := by + ext f + refine (P.isAssociatedFinite_operatorFinite μ hμ p (s + t) f).trans ?_ + refine (kernelIntegral_add_ae_finite P hμ p s t f).trans ?_ + refine (kernelIntegral_congr_ae (hμ s) + (P.isAssociatedFinite_operatorFinite μ hμ p t f).symm).trans ?_ + exact (P.isAssociatedFinite_operatorFinite μ hμ p s (P.operatorFinite μ hμ p t f)).symm + +/-- The infinite-exponent canonical operator at time zero is the identity. -/ +theorem operatorTop_zero (μ : Measure α) (hμ : P.IsSubInvariant μ) : + P.operatorTop μ hμ 0 = ContinuousLinearMap.id ℝ (Lp ℝ ∞ μ) := by + ext f + refine (P.isAssociatedTop_operatorTop μ hμ 0 f).trans ?_ + rw [P.zero] + exact (kernelIntegral_id_ae (Lp.aestronglyMeasurable f)).trans + Filter.EventuallyEq.rfl + +/-- The infinite-exponent canonical operators obey the add-time law. -/ +theorem operatorTop_add (μ : Measure α) (hμ : P.IsSubInvariant μ) + (s t : NNReal) : + P.operatorTop μ hμ (s + t) = + (P.operatorTop μ hμ s).comp (P.operatorTop μ hμ t) := by + ext f + refine (P.isAssociatedTop_operatorTop μ hμ (s + t) f).trans ?_ + refine (kernelIntegral_add_ae_top P hμ s t f).trans ?_ + refine (kernelIntegral_congr_ae (hμ s) + (P.isAssociatedTop_operatorTop μ hμ t f).symm).trans ?_ + exact (P.isAssociatedTop_operatorTop μ hμ s (P.operatorTop μ hμ t f)).symm + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorKernel.lean new file mode 100644 index 0000000000..8ecb04e1cb --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorKernel.lean @@ -0,0 +1,158 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass +import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction + +/-! +# Kernels represented by positive operators on `C₀` + +A positive contraction on real continuous functions vanishing at infinity determines a +sub-Markov kernel. Its values are the pointwise Riesz measures of the evaluation functionals. +-/ + +open CompactlySupported Filter MeasureTheory ProbabilityTheory Set +open scoped ZeroAtInfty + +namespace MarkovProcess.PositiveC0OperatorKernel + +variable {α : Type*} [TopologicalSpace α] [T2Space α] [LocallyCompactSpace α] + [SecondCountableTopology α] [MeasurableSpace α] [BorelSpace α] + +variable (T : C₀(α, ℝ) →L[ℝ] C₀(α, ℝ)) + (hT : PositiveC0OperatorMeasure.IsPositive T) + +omit [SecondCountableTopology α] [MeasurableSpace α] [BorelSpace α] in +private lemma exists_compactlySupported_norm_sub_le (f : C₀(α, ℝ)) {ε : ℝ} + (hε : 0 < ε) : + ∃ g : C_c(α, ℝ), + ‖PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap g - f‖ ≤ ε := by + have heventually : ∀ᶠ x in cocompact α, dist (f x) 0 < ε := + (Metric.tendsto_nhds.mp (zero_at_infty f) ε hε) + obtain ⟨K, hK, houtside⟩ := mem_cocompact.mp heventually + obtain ⟨cutoff, hcutoff_one, hcutoff_compact, _hcutoff_support, hcutoff⟩ := + exists_continuousMap_one_of_isCompact_subset_isOpen hK isOpen_univ (subset_univ K) + let g : C_c(α, ℝ) := + ⟨cutoff * f.toContinuousMap, hasCompactSupport_def.mpr hcutoff_compact |>.mul_right⟩ + refine ⟨g, ?_⟩ + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + refine (BoundedContinuousFunction.norm_le hε.le).2 fun x ↦ ?_ + rw [Real.norm_eq_abs] + by_cases hx : x ∈ K + · change |cutoff x * f x - f x| ≤ ε + rw [hcutoff_one hx, Pi.one_apply, one_mul, sub_self, abs_zero] + exact hε.le + · change |cutoff x * f x - f x| ≤ ε + have hcutoff_abs : |cutoff x - 1| ≤ 1 := by + rw [abs_le] + exact ⟨by linarith only [(hcutoff x).1], by linarith only [(hcutoff x).2]⟩ + calc + |cutoff x * f x - f x| = |cutoff x - 1| * |f x| := by + rw [← abs_mul, sub_mul, one_mul] + |cutoff x - 1| * |f x| ≤ 1 * |f x| := + mul_le_mul_of_nonneg_right hcutoff_abs (abs_nonneg _) + _ ≤ ε := by + rw [one_mul, ← Real.norm_eq_abs, ← dist_zero_right] + exact (houtside (mem_compl hx)).le + +/-- The kernel whose value at `x` is the Riesz measure representing evaluation of `T` at `x`. -/ +noncomputable def kernel (hT_norm : ‖T‖ ≤ 1) : Kernel α α := by + letI : ∀ x, IsFiniteMeasure (PositiveC0OperatorMeasure.measure T hT x) := + fun x ↦ PositiveC0OperatorMeasure.isFiniteMeasure_measure T hT hT_norm x + exact + { toFun := PositiveC0OperatorMeasure.measure T hT + measurable' := + measurable_measure_of_measurable_integral_compactlySupported + (PositiveC0OperatorMeasure.measure T hT) fun f ↦ by + rw [show (fun x ↦ ∫ y, f y ∂PositiveC0OperatorMeasure.measure T hT x) = + fun x ↦ T (PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f) x by + funext x + exact PositiveC0OperatorMeasure.integral_measure T hT x f] + exact + (T (PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f)).continuous + |>.measurable } + +/-- The constructed kernel has the pointwise Riesz measure as its value. -/ +@[simp] +theorem kernel_apply (hT_norm : ‖T‖ ≤ 1) (x : α) : + kernel T hT hT_norm x = PositiveC0OperatorMeasure.measure T hT x := + rfl + +/-- The kernel represented by a positive contraction is sub-Markov. -/ +theorem isSubMarkovKernel_kernel (hT_norm : ‖T‖ ≤ 1) : + IsSubMarkovKernel (kernel T hT hT_norm) := by + intro x + rw [kernel_apply] + exact PositiveC0OperatorMeasure.measure_univ_le_one T hT hT_norm x + +/-- The kernel represents `T` on compactly supported continuous functions. -/ +@[simp] +theorem integral_kernel_compactlySupported (hT_norm : ‖T‖ ≤ 1) (x : α) + (f : C_c(α, ℝ)) : + ∫ y, f y ∂kernel T hT hT_norm x = + T (PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f) x := by + rw [kernel_apply] + exact PositiveC0OperatorMeasure.integral_measure T hT x f + +/-- Every real continuous function vanishing at infinity is integrable against a kernel value. -/ +theorem integrable_kernel (hT_norm : ‖T‖ ≤ 1) (x : α) (f : C₀(α, ℝ)) : + Integrable f (kernel T hT hT_norm x) := by + let : IsFiniteMeasure (kernel T hT hT_norm x) := + PositiveC0OperatorMeasure.isFiniteMeasure_measure T hT hT_norm x + exact f.toBCF.integrable _ + +/-- The kernel represents `T` on every real continuous function vanishing at infinity. -/ +theorem integral_kernel (hT_norm : ‖T‖ ≤ 1) (x : α) (f : C₀(α, ℝ)) : + ∫ y, f y ∂kernel T hT hT_norm x = T f x := by + let : IsFiniteMeasure (kernel T hT hT_norm x) := + PositiveC0OperatorMeasure.isFiniteMeasure_measure T hT hT_norm x + apply eq_of_forall_dist_le + intro ε hε + obtain ⟨g, hg⟩ := exists_compactlySupported_norm_sub_le f (half_pos hε) + let g₀ : C₀(α, ℝ) := PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap g + have hmass : (kernel T hT hT_norm x).real Set.univ ≤ 1 := by + rw [measureReal_def] + exact (ENNReal.toReal_le_toReal (measure_ne_top _ _) ENNReal.one_ne_top).mpr + (isSubMarkovKernel_kernel T hT hT_norm x) + have hf_integrable : Integrable f (kernel T hT hT_norm x) := f.toBCF.integrable _ + have hg_integrable : Integrable g₀ (kernel T hT hT_norm x) := g₀.toBCF.integrable _ + have hintegral : + dist (∫ y, f y ∂kernel T hT hT_norm x) + (∫ y, g₀ y ∂kernel T hT hT_norm x) ≤ ε / 2 := by + rw [Real.dist_eq, ← integral_sub hf_integrable hg_integrable] + calc + ‖∫ y, (f - g₀) y ∂kernel T hT hT_norm x‖ ≤ + (kernel T hT hT_norm x).real Set.univ * ‖(f - g₀).toBCF‖ := + (f - g₀).toBCF.norm_integral_le_mul_norm _ + _ ≤ 1 * (ε / 2) := mul_le_mul hmass (by simpa only [norm_sub_rev] using! hg) + (norm_nonneg _) zero_le_one + _ = ε / 2 := one_mul _ + have hoperator : dist (T g₀ x) (T f x) ≤ ε / 2 := by + rw [Real.dist_eq] + change |(T g₀ - T f) x| ≤ ε / 2 + rw [← map_sub] + calc + |(T (g₀ - f)) x| ≤ ‖T (g₀ - f)‖ := + (T (g₀ - f)).toBCF.norm_coe_le_norm x + _ ≤ ‖T‖ * ‖g₀ - f‖ := T.le_opNorm _ + _ ≤ 1 * (ε / 2) := mul_le_mul hT_norm hg (norm_nonneg _) zero_le_one + _ = ε / 2 := one_mul _ + calc + dist (∫ y, f y ∂kernel T hT hT_norm x) (T f x) ≤ + dist (∫ y, f y ∂kernel T hT hT_norm x) + (∫ y, g₀ y ∂kernel T hT hT_norm x) + + dist (∫ y, g₀ y ∂kernel T hT hT_norm x) (T f x) := + dist_triangle _ _ _ + _ = dist (∫ y, f y ∂kernel T hT hT_norm x) + (∫ y, g₀ y ∂kernel T hT hT_norm x) + dist (T g₀ x) (T f x) := by + have hg_rep := integral_kernel_compactlySupported T hT hT_norm x g + change (∫ y, g₀ y ∂kernel T hT hT_norm x) = T g₀ x at hg_rep + rw [hg_rep] + _ ≤ ε / 2 + ε / 2 := add_le_add hintegral hoperator + _ = ε := add_halves ε + +end MarkovProcess.PositiveC0OperatorKernel diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMass.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMass.lean new file mode 100644 index 0000000000..167a55b843 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMass.lean @@ -0,0 +1,71 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure + +/-! +# Total mass of pointwise Riesz measures + +A positive contraction on real continuous functions vanishing at infinity induces pointwise +Riesz measures of total mass at most one. The proof first bounds compact sets using compactly +supported Urysohn cutoff functions, then passes to the whole space by inner regularity. + +This file proves only a pointwise total-mass bound and finiteness. It does not construct a kernel +or prove any regularity in the evaluation point. +-/ + +open CompactlySupported MeasureTheory +open scoped ZeroAtInfty + +namespace MarkovProcess.PositiveC0OperatorMeasure + +variable {α : Type*} [TopologicalSpace α] [T2Space α] [LocallyCompactSpace α] + [MeasurableSpace α] [BorelSpace α] + +variable (T : C₀(α, ℝ) →L[ℝ] C₀(α, ℝ)) (hT : IsPositive T) + +/-- The Riesz measure of a positive contraction assigns mass at most one to every compact set. -/ +theorem measure_compact_le_one (hT_norm : ‖T‖ ≤ 1) (x : α) {K : Set α} (hK : IsCompact K) : + measure T hT x K ≤ 1 := by + obtain ⟨f, hfK, hfcompact, _hf_support, hf⟩ := + exists_continuousMap_one_of_isCompact_subset_isOpen hK isOpen_univ (Set.subset_univ K) + let g : C_c(α, ℝ) := ⟨f, hasCompactSupport_def.mpr hfcompact⟩ + have hg_nonneg (y : α) : 0 ≤ g y := (hf y).1 + have hg_le_one (y : α) : g y ≤ 1 := (hf y).2 + have hg_norm : ‖compactlySupportedToC0LinearMap g‖ ≤ 1 := by + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + refine (BoundedContinuousFunction.norm_le zero_le_one).2 fun y ↦ ?_ + rw [Real.norm_eq_abs] + exact abs_le.mpr ⟨(neg_nonpos.mpr zero_le_one).trans (hg_nonneg y), hg_le_one y⟩ + have hfunctional_le_one : functional T hT x g ≤ 1 := by + calc + functional T hT x g = T (compactlySupportedToC0LinearMap g) x := rfl + _ ≤ |T (compactlySupportedToC0LinearMap g) x| := le_abs_self _ + _ ≤ ‖T (compactlySupportedToC0LinearMap g)‖ := by + exact (T (compactlySupportedToC0LinearMap g)).toBCF.norm_coe_le_norm x + _ ≤ 1 := by + simpa only [one_mul] using + T.le_of_opNorm_le_of_le hT_norm hg_norm + calc + measure T hT x K ≤ ENNReal.ofReal (functional T hT x g) := by + apply RealRMK.rieszMeasure_le_of_eq_one (functional T hT x) hg_nonneg hK + intro y hy + exact hfK hy + _ ≤ 1 := ENNReal.ofReal_le_one.mpr hfunctional_le_one + +/-- The Riesz measure of a positive contraction has total mass at most one. -/ +theorem measure_univ_le_one (hT_norm : ‖T‖ ≤ 1) (x : α) : + measure T hT x Set.univ ≤ 1 := by + let := regular_measure T hT x + rw [isOpen_univ.measure_eq_iSup_isCompact] + refine iSup_le fun K ↦ iSup_le fun _hK_univ ↦ iSup_le fun hK ↦ ?_ + exact measure_compact_le_one T hT hT_norm x hK + +/-- The pointwise Riesz measure of a positive contraction is finite. -/ +theorem isFiniteMeasure_measure (hT_norm : ‖T‖ ≤ 1) (x : α) : + IsFiniteMeasure (measure T hT x) := + ⟨(measure_univ_le_one T hT hT_norm x).trans_lt ENNReal.one_lt_top⟩ + +end MarkovProcess.PositiveC0OperatorMeasure diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMeasure.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMeasure.lean new file mode 100644 index 0000000000..d7b1ebc107 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMeasure.lean @@ -0,0 +1,119 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.MeasureTheory.Integral.RieszMarkovKakutani.Real +import Mathlib.Topology.ContinuousMap.ZeroAtInfty + +/-! +# Pointwise Riesz measures of positive operators on `C₀` + +A positive continuous linear operator on real continuous functions vanishing at infinity gives, +after evaluation at a point, a positive linear functional on compactly supported continuous +functions. The real Riesz--Markov--Kakutani theorem represents this functional by a regular, +locally finite measure. + +This file makes only this pointwise construction. It does not prove that the measures depend +measurably on the evaluation point, have bounded total mass, form a kernel, or satisfy any +semigroup or stochastic-process law. +-/ + +open CompactlySupported MeasureTheory +open scoped ZeroAtInfty + +namespace MarkovProcess + +variable {α : Type*} [TopologicalSpace α] + +/-- Evaluation at a point, as a bounded linear functional on `C₀(α, ℝ)`. -/ +noncomputable def c0EvalCLM (x : α) : C₀(α, ℝ) →L[ℝ] ℝ := + LinearMap.mkContinuous + { toFun := fun f ↦ f x + map_add' := fun _ _ ↦ rfl + map_smul' := fun _ _ ↦ rfl } 1 fun f ↦ by + rw [one_mul, ← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + exact BoundedContinuousFunction.norm_coe_le_norm f.toBCF x + +/-- Evaluation, unfolded. -/ +@[simp] +theorem c0EvalCLM_apply (x : α) (f : C₀(α, ℝ)) : c0EvalCLM x f = f x := + rfl + +namespace PositiveC0OperatorMeasure + +/-- Pointwise preservation of nonnegative functions by an operator on `C₀(α, ℝ)`. -/ +def IsPositive (T : C₀(α, ℝ) →L[ℝ] C₀(α, ℝ)) : Prop := + ∀ f : C₀(α, ℝ), (∀ x, 0 ≤ f x) → ∀ x, 0 ≤ T f x + +/-- A positive operator on `C₀` is monotone for the pointwise order. -/ +theorem apply_le_apply_of_isPositive + (T : C₀(α, ℝ) →L[ℝ] C₀(α, ℝ)) (hT : IsPositive T) + {f g : C₀(α, ℝ)} (hfg : ∀ x, f x ≤ g x) (x : α) : + T f x ≤ T g x := by + have hnonneg : ∀ y, 0 ≤ (g - f) y := fun y ↦ sub_nonneg.mpr (hfg y) + have h := hT (g - f) hnonneg x + rw [map_sub] at h + exact sub_nonneg.mp h + +/-- The canonical real-linear inclusion of compactly supported continuous functions into `C₀`. -/ +noncomputable def compactlySupportedToC0LinearMap : C_c(α, ℝ) →ₗ[ℝ] C₀(α, ℝ) where + toFun f := f + map_add' f g := by + ext x + rfl + map_smul' c f := by + ext x + rfl + +@[simp] +theorem compactlySupportedToC0LinearMap_apply (f : C_c(α, ℝ)) (x : α) : + compactlySupportedToC0LinearMap f x = f x := + rfl + +variable (T : C₀(α, ℝ) →L[ℝ] C₀(α, ℝ)) (hT : IsPositive T) + +/-- Evaluation at `x` after applying `T`, restricted from `C₀(α, ℝ)` to compactly supported +continuous functions, as a positive linear functional. -/ +noncomputable def functional (x : α) : C_c(α, ℝ) →ₚ[ℝ] ℝ := + PositiveLinearMap.mk₀ + { toFun := fun f ↦ T (compactlySupportedToC0LinearMap f) x + map_add' := by + intro f g + rw [map_add, map_add] + rfl + map_smul' := by + intro c f + rw [map_smul, map_smul] + rfl } + fun f hf ↦ hT (compactlySupportedToC0LinearMap f) (fun y ↦ hf y) x + +@[simp] +theorem functional_apply (x : α) (f : C_c(α, ℝ)) : + functional T hT x f = T (compactlySupportedToC0LinearMap f) x := + rfl + +variable [T2Space α] [LocallyCompactSpace α] [MeasurableSpace α] [BorelSpace α] + +/-- The regular Riesz measure representing point evaluation after applying `T`. -/ +noncomputable def measure (x : α) : Measure α := + RealRMK.rieszMeasure (functional T hT x) + +instance regular_measure (x : α) : (measure T hT x).Regular := + RealRMK.regular_rieszMeasure (functional T hT x) + +instance isFiniteMeasureOnCompacts_measure (x : α) : + IsFiniteMeasureOnCompacts (measure T hT x) := + inferInstance + +/-- The pointwise Riesz measure represents `T` exactly on every compactly supported continuous +function. -/ +@[simp] +theorem integral_measure (x : α) (f : C_c(α, ℝ)) : + ∫ y, f y ∂(measure T hT x) = T (compactlySupportedToC0LinearMap f) x := by + rw [measure, RealRMK.integral_rieszMeasure] + rfl + +end PositiveC0OperatorMeasure + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0Resolvent.lean new file mode 100644 index 0000000000..5d408ba190 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0Resolvent.lean @@ -0,0 +1,124 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller + +/-! +# Positive `C₀` resolvents and their Feller kernels + +A positive contractive resolvent on `C₀` canonically generates a strongly continuous semigroup +of positive contractions. The existing pointwise Riesz construction then represents that +semigroup by a sub-Markov kernel semigroup and identifies its `C₀` operators exactly. + +The package in this file starts from the resolvent identity, the Hille--Yosida bound, dense range, +and positivity of the actual shifted resolvents. It assumes neither a semigroup nor a kernel. +-/ + +open MeasureTheory ProbabilityTheory Set +open scoped ZeroAtInfty + +noncomputable section + +namespace MarkovProcess + +open MarkovProcess.Semigroup + +variable (X : Type*) [TopologicalSpace X] + +/-- A contractive resolvent on `C₀(X, ℝ)` whose shifted operators preserve nonnegative +functions. -/ +structure PositiveC0ContractiveResolvent extends ContractiveResolvent C₀(X, ℝ) where + /-- Every shifted resolvent is positivity preserving. -/ + isPositive : ∀ alpha, + PositiveC0OperatorMeasure.IsPositive (toContractiveResolvent.operator alpha) + +namespace PositiveC0ContractiveResolvent + +variable {X : Type*} [TopologicalSpace X] + +/-- The closed cone of pointwise nonnegative functions in `C₀(X, ℝ)`. -/ +def nonnegativeSet : Set C₀(X, ℝ) := + {f | ∀ x, 0 ≤ f x} + +theorem isClosed_nonnegativeSet : IsClosed (nonnegativeSet (X := X)) := by + unfold nonnegativeSet + rw [show {f : C₀(X, ℝ) | ∀ x, 0 ≤ f x} = + ⋂ x : X, {f : C₀(X, ℝ) | f x ∈ Set.Ici 0} by + ext f + simp only [mem_ofPred_eq, mem_iInter, mem_Ici]] + apply isClosed_iInter + intro x + exact isClosed_Ici.preimage + (((ZeroAtInftyContinuousMap.isometry_toBCF (α := X) (β := ℝ)).continuous).eval + continuous_const) + +theorem convex_nonnegativeSet : Convex ℝ (nonnegativeSet (X := X)) := by + intro f hf g hg a b ha hb _hab x + change 0 ≤ a * f x + b * g x + exact add_nonneg (mul_nonneg ha (hf x)) (mul_nonneg hb (hg x)) + +theorem zero_mem_nonnegativeSet : + (0 : C₀(X, ℝ)) ∈ nonnegativeSet (X := X) := by + intro x + exact le_rfl + +variable (R : PositiveC0ContractiveResolvent X) + +/-- Every normalized shifted resolvent preserves the pointwise nonnegative cone. -/ +theorem preservesSet_scaledOperator_nonnegative (alpha : PositiveShift) : + PreservesSet (R.toContractiveResolvent.scaledOperator alpha) + (nonnegativeSet (X := X)) (nonnegativeSet (X := X)) := by + intro f hf x + change 0 ≤ (alpha : ℝ) * R.toContractiveResolvent.operator alpha f x + exact mul_nonneg alpha.property.le (R.isPositive alpha f hf x) + +/-- The canonical semigroup generated by a positive `C₀` contractive resolvent is positivity +preserving at every time. -/ +theorem isPositive_generatedSemigroup : + ∀ t, PositiveC0OperatorMeasure.IsPositive + (R.toContractiveResolvent.generatedSemigroup t) := by + intro t f hf + exact R.toContractiveResolvent.preservesSet_generatedSemigroup_of_scaledOperator + (nonnegativeSet (X := X)) isClosed_nonnegativeSet convex_nonnegativeSet + zero_mem_nonnegativeSet R.preservesSet_scaledOperator_nonnegative t hf + +section Kernel + +variable [T2Space X] [LocallyCompactSpace X] [SecondCountableTopology X] + [MeasurableSpace X] [BorelSpace X] + +/-- The sub-Markov kernel semigroup represented by the canonical positive `C₀` semigroup. -/ +noncomputable def kernelSemigroup : SubMarkovKernelSemigroup X := + PositiveC0SemigroupKernel.kernelSemigroup + R.toContractiveResolvent.generatedSemigroup R.isPositive_generatedSemigroup + +/-- The represented kernels act on `C₀` exactly by the generated semigroup operators. -/ +theorem integral_kernelSemigroup (t : NNReal) (f : C₀(X, ℝ)) (x : X) : + ∫ y, f y ∂R.kernelSemigroup t x = + R.toContractiveResolvent.generatedSemigroup t f x := by + rw [kernelSemigroup, PositiveC0SemigroupKernel.kernelSemigroup_apply] + exact PositiveC0OperatorKernel.integral_kernel + (R.toContractiveResolvent.generatedSemigroup t) + (R.isPositive_generatedSemigroup t) + (R.toContractiveResolvent.generatedSemigroup.norm_operator_le_one t) x f + +/-- The represented kernel semigroup satisfies the Feller interface. -/ +theorem isFellerKernelSemigroup_kernelSemigroup : R.kernelSemigroup.IsFellerKernelSemigroup := + PositiveC0SemigroupFeller.isFellerKernelSemigroup_kernelSemigroup + R.toContractiveResolvent.generatedSemigroup R.isPositive_generatedSemigroup + +/-- Repackaging the represented Feller kernels recovers the generated `C₀` semigroup. -/ +theorem c0Semigroup_kernelSemigroup : + R.isFellerKernelSemigroup_kernelSemigroup.c0Semigroup = + R.toContractiveResolvent.generatedSemigroup := + PositiveC0SemigroupFeller.c0Semigroup_kernelSemigroup + R.toContractiveResolvent.generatedSemigroup R.isPositive_generatedSemigroup + +end Kernel + +end PositiveC0ContractiveResolvent + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupFeller.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupFeller.lean new file mode 100644 index 0000000000..ba2b80747c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupFeller.lean @@ -0,0 +1,92 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel + +/-! +# Feller property of kernels represented by positive `C₀` semigroups + +The kernel semigroup represented by a strongly continuous semigroup of positive contractions +recovers the original operators on `C₀` and therefore satisfies the existing Feller interface. +This file makes no conservativity, stochastic-process, or Hunt-process claim. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ZeroAtInfty + +namespace MarkovProcess.PositiveC0SemigroupFeller + +open MarkovProcess.Semigroup + +variable {α : Type*} [TopologicalSpace α] [T2Space α] [LocallyCompactSpace α] + [SecondCountableTopology α] [MeasurableSpace α] [BorelSpace α] + +variable (S : StronglyContinuousContractionSemigroup C₀(α, ℝ)) + (hS : ∀ t, PositiveC0OperatorMeasure.IsPositive (S t)) + +/-- The represented kernel semigroup maps `C₀(α, ℝ)` into itself. -/ +theorem mapsC0_kernelSemigroup : + (PositiveC0SemigroupKernel.kernelSemigroup S hS).MapsC0 := by + intro t f + have heq : kernelIntegral (PositiveC0SemigroupKernel.kernelSemigroup S hS t) f = S t f := by + funext x + change ∫ y, f y ∂PositiveC0SemigroupKernel.kernelSemigroup S hS t x = S t f x + rw [PositiveC0SemigroupKernel.kernelSemigroup_apply] + exact PositiveC0OperatorKernel.integral_kernel + (S t) (hS t) (S.norm_operator_le_one t) x f + rw [heq] + exact ⟨(S t f).continuous, zero_at_infty (S t f)⟩ + +/-- The represented `C₀`-valued kernel integral is exactly the original semigroup action. -/ +@[simp] +theorem kernelSemigroup_c0KernelIntegral + (hC0 : (PositiveC0SemigroupKernel.kernelSemigroup S hS).MapsC0) + (t : NNReal) (f : C₀(α, ℝ)) : + (PositiveC0SemigroupKernel.kernelSemigroup S hS).c0KernelIntegral hC0 t f = S t f := by + apply ZeroAtInftyContinuousMap.ext + intro x + change ∫ y, f y ∂PositiveC0SemigroupKernel.kernelSemigroup S hS t x = S t f x + rw [PositiveC0SemigroupKernel.kernelSemigroup_apply] + exact PositiveC0OperatorKernel.integral_kernel + (S t) (hS t) (S.norm_operator_le_one t) x f + +/-- The represented continuous linear `C₀` operator is the original semigroup operator. -/ +@[simp] +theorem kernelSemigroup_c0Operator + (hC0 : (PositiveC0SemigroupKernel.kernelSemigroup S hS).MapsC0) + (t : NNReal) : + (PositiveC0SemigroupKernel.kernelSemigroup S hS).c0Operator hC0 t = S t := by + apply ContinuousLinearMap.ext + intro f + exact kernelSemigroup_c0KernelIntegral S hS hC0 t f + +/-- The represented `C₀` kernel operators have continuous time orbits. -/ +theorem hasContinuousC0Orbits_kernelSemigroup : + (PositiveC0SemigroupKernel.kernelSemigroup S hS).HasContinuousC0Orbits + (mapsC0_kernelSemigroup S hS) := by + intro f + have heq : (fun t : NNReal ↦ + (PositiveC0SemigroupKernel.kernelSemigroup S hS).c0Operator + (mapsC0_kernelSemigroup S hS) t f) = fun t ↦ S t f := by + funext t + rw [kernelSemigroup_c0Operator] + rw [heq] + exact S.continuous f + +/-- The represented sub-Markov kernel semigroup satisfies the Feller interface. -/ +theorem isFellerKernelSemigroup_kernelSemigroup : + (PositiveC0SemigroupKernel.kernelSemigroup S hS).IsFellerKernelSemigroup := + ⟨mapsC0_kernelSemigroup S hS, hasContinuousC0Orbits_kernelSemigroup S hS⟩ + +/-- Packaging the represented Feller kernel semigroup recovers the original `C₀` semigroup. -/ +theorem c0Semigroup_kernelSemigroup : + (isFellerKernelSemigroup_kernelSemigroup S hS).c0Semigroup = S := by + apply StronglyContinuousContractionSemigroup.ext + intro t + rw [SubMarkovKernelSemigroup.IsFellerKernelSemigroup.c0Semigroup] + exact kernelSemigroup_c0Operator S hS _ t + +end MarkovProcess.PositiveC0SemigroupFeller diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupKernel.lean new file mode 100644 index 0000000000..5cb23cf97a --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupKernel.lean @@ -0,0 +1,119 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +import Mathlib.Probability.Kernel.Composition.IntegralCompProd +import Mathlib.Topology.Metrizable.Urysohn + +/-! +# Kernel semigroups represented by positive contraction semigroups on `C₀` + +A strongly continuous semigroup of positive contractions on real continuous functions vanishing +at infinity determines a jointly measurable sub-Markov kernel semigroup. +-/ + +open CompactlySupported MeasureTheory ProbabilityTheory +open scoped ENNReal ZeroAtInfty + +namespace MarkovProcess.PositiveC0SemigroupKernel + +open MarkovProcess.Semigroup + +variable {α : Type*} [TopologicalSpace α] [T2Space α] [LocallyCompactSpace α] + [SecondCountableTopology α] [MeasurableSpace α] [BorelSpace α] + +variable (S : StronglyContinuousContractionSemigroup C₀(α, ℝ)) + (hS : ∀ t, PositiveC0OperatorMeasure.IsPositive (S t)) + +/-- The pointwise Riesz kernels are jointly measurable in time and starting state. -/ +theorem measurable_kernel : Measurable fun p : NNReal × α ↦ + PositiveC0OperatorKernel.kernel (S p.1) (hS p.1) (S.norm_operator_le_one p.1) p.2 := by + let : ∀ p : NNReal × α, + IsFiniteMeasure (PositiveC0OperatorMeasure.measure (S p.1) (hS p.1) p.2) := + fun p ↦ PositiveC0OperatorMeasure.isFiniteMeasure_measure + (S p.1) (hS p.1) (S.norm_operator_le_one p.1) p.2 + have hmeasure : Measurable fun p : NNReal × α ↦ + PositiveC0OperatorMeasure.measure (S p.1) (hS p.1) p.2 := + measurable_measure_of_measurable_integral_compactlySupported _ fun f ↦ by + rw [show (fun p : NNReal × α ↦ + ∫ y, f y ∂PositiveC0OperatorMeasure.measure (S p.1) (hS p.1) p.2) = + fun p ↦ S p.1 (PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f) p.2 by + funext p + exact PositiveC0OperatorMeasure.integral_measure (S p.1) (hS p.1) p.2 f] + exact S.measurable_apply_apply _ + simpa only [PositiveC0OperatorKernel.kernel_apply] using hmeasure + +/-- At time zero the represented kernel is the identity kernel. -/ +theorem kernel_zero : + PositiveC0OperatorKernel.kernel (S 0) (hS 0) (S.norm_operator_le_one 0) = Kernel.id := by + apply Kernel.ext + intro x + rw [PositiveC0OperatorKernel.kernel_apply, Kernel.id_apply] + let : IsFiniteMeasure (Measure.dirac x) := inferInstance + let : (Measure.dirac x).Regular := inferInstance + apply Measure.ext_of_integral_eq_on_compactlySupported + intro f + rw [PositiveC0OperatorMeasure.integral_measure] + simp only [StronglyContinuousContractionSemigroup.zero_apply] + simpa only [PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap_apply] using + (integral_dirac' f x f.continuous.stronglyMeasurable).symm + +/-- The represented kernels satisfy the Chapman--Kolmogorov law. -/ +theorem kernel_add (s t : NNReal) : + PositiveC0OperatorKernel.kernel (S (s + t)) (hS (s + t)) + (S.norm_operator_le_one (s + t)) = + (PositiveC0OperatorKernel.kernel (S t) (hS t) (S.norm_operator_le_one t)).comp + (PositiveC0OperatorKernel.kernel (S s) (hS s) (S.norm_operator_le_one s)) := by + apply Kernel.ext + intro x + rw [PositiveC0OperatorKernel.kernel_apply] + let Ks := PositiveC0OperatorKernel.kernel (S s) (hS s) (S.norm_operator_le_one s) + let Kt := PositiveC0OperatorKernel.kernel (S t) (hS t) (S.norm_operator_le_one t) + change PositiveC0OperatorMeasure.measure (S (s + t)) (hS (s + t)) x = (Kt.comp Ks) x + have hKs : IsSubMarkovKernel Ks := + PositiveC0OperatorKernel.isSubMarkovKernel_kernel _ _ _ + have hKt : IsSubMarkovKernel Kt := + PositiveC0OperatorKernel.isSubMarkovKernel_kernel _ _ _ + let : IsFiniteKernel (Kt.comp Ks) := (hKt.comp hKs).isFiniteKernel + let : IsFiniteMeasure ((Kt.comp Ks) x) := inferInstance + let : ((Kt.comp Ks) x).Regular := inferInstance + apply Measure.ext_of_integral_eq_on_compactlySupported + intro f + let f₀ : C₀(α, ℝ) := PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f + have hf_comp : Integrable f₀ ((Kt.comp Ks) x) := f₀.toBCF.integrable _ + rw [PositiveC0OperatorMeasure.integral_measure] + rw [StronglyContinuousContractionSemigroup.add_apply] + change S s (S t f₀) x = ∫ z, f₀ z ∂(Kt.comp Ks) x + calc + S s (S t f₀) x = ∫ y, S t f₀ y ∂Ks x := by + exact (PositiveC0OperatorKernel.integral_kernel + (S s) (hS s) (S.norm_operator_le_one s) x (S t f₀)).symm + _ = ∫ y, ∫ z, f₀ z ∂Kt y ∂Ks x := by + congr 1 + funext y + exact (PositiveC0OperatorKernel.integral_kernel_compactlySupported + (S t) (hS t) (S.norm_operator_le_one t) y f).symm + _ = ∫ z, f₀ z ∂(Kt.comp Ks) x := (Kernel.integral_comp hf_comp).symm + +/-- The sub-Markov kernel semigroup represented by a positive contraction semigroup on `C₀`. -/ +noncomputable def kernelSemigroup : SubMarkovKernelSemigroup α where + kernel t := PositiveC0OperatorKernel.kernel (S t) (hS t) (S.norm_operator_le_one t) + measurable_kernel := measurable_kernel S hS + kernel_zero := kernel_zero S hS + kernel_add := kernel_add S hS + isSubMarkovKernel t := + PositiveC0OperatorKernel.isSubMarkovKernel_kernel + (S t) (hS t) (S.norm_operator_le_one t) + +/-- Evaluation of the represented kernel semigroup is the fixed-operator Riesz kernel. -/ +@[simp] +theorem kernelSemigroup_apply (t : NNReal) : + kernelSemigroup S hS t = + PositiveC0OperatorKernel.kernel (S t) (hS t) (S.norm_operator_le_one t) := + rfl + +end MarkovProcess.PositiveC0SemigroupKernel diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Resolvent.lean new file mode 100644 index 0000000000..2e548324ba --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Resolvent.lean @@ -0,0 +1,156 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Analysis.SpecialFunctions.ImproperIntegrals +import Mathlib.MeasureTheory.Integral.ExpDecay +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator + +/-! +# Resolvents of kernel semigroups + +This file defines the resolvent of a sub-Markov kernel semigroup on nonnegative extended-real +observables by Laplace transformation of its transition kernels. + +Main definitions: `SubMarkovKernelSemigroup.kernelResolvent` and +`SubMarkovKernelSemigroup.kernelResolventReal`. + +No conservativity, topology, or finiteness of the resolvent is asserted. +-/ + +open Filter MeasureTheory ProbabilityTheory Set +open scoped ENNReal NNReal + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [MeasurableSpace alpha] + +/-- The kernel resolvent on nonnegative extended-real observables. -/ +noncomputable def kernelResolvent (P : SubMarkovKernelSemigroup alpha) (lam : ℝ) + (f : alpha → ℝ≥0∞) (x : alpha) : ℝ≥0∞ := + ∫⁻ t in Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + ∫⁻ y, f y ∂(P (Real.toNNReal t) x) + +/-- The kernel resolvent on real-valued observables. Finiteness is established separately for +bounded observables at positive shifts. -/ +noncomputable def kernelResolventReal (P : SubMarkovKernelSemigroup alpha) (lam : ℝ) + (f : alpha → ℝ) (x : alpha) : ℝ := + ∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + kernelIntegral (P (Real.toNNReal t)) f x + +private theorem norm_kernelIntegral_le_of_bound (P : SubMarkovKernelSemigroup alpha) + {f : alpha → ℝ} {D : ℝ} (hfD : ∀ y, |f y| ≤ D) (t : NNReal) (x : alpha) : + |kernelIntegral (P t) f x| ≤ D := by + have hD0 : 0 ≤ D := (abs_nonneg (f x)).trans (hfD x) + rw [← Real.norm_eq_abs] + let : IsFiniteKernel (P t) := (P.isSubMarkovKernel t).isFiniteKernel + calc + ‖kernelIntegral (P t) f x‖ ≤ ∫ _y, D ∂(P t x) := by + apply norm_integral_le_of_norm_le (integrable_const D) + exact Eventually.of_forall hfD + _ ≤ D := by + rw [integral_const, smul_eq_mul] + apply mul_le_of_le_one_left hD0 + rw [measureReal_def, ← ENNReal.toReal_one] + apply (ENNReal.toReal_le_toReal (measure_ne_top _ _) ENNReal.one_ne_top).2 + exact (P.isSubMarkovKernel t).measure_le_one x Set.univ + +private theorem integrableOn_kernelResolventReal_integrand + (P : SubMarkovKernelSemigroup alpha) {lam : ℝ} (hlam : 0 < lam) + {f : alpha → ℝ} (hf : Measurable f) {D : ℝ} (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + IntegrableOn (fun t : ℝ ↦ Real.exp (-lam * t) * + kernelIntegral (P (Real.toNNReal t)) f x) (Ioi 0) := by + apply Integrable.mono' ((exp_neg_integrableOn_Ioi 0 hlam).mul_const D) + · exact (((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.mul + ((P.measurable_kernelIntegral hf).comp + (measurable_real_toNNReal.prodMk measurable_const))).stronglyMeasurable + ).aestronglyMeasurable.restrict + · exact Eventually.of_forall fun t ↦ by + rw [Real.norm_eq_abs, abs_mul, abs_of_pos (Real.exp_pos _)] + exact mul_le_mul_of_nonneg_left + (norm_kernelIntegral_le_of_bound P hfD (Real.toNNReal t) x) (Real.exp_pos _).le + +/-- The real kernel resolvent is additive on bounded measurable observables. -/ +theorem kernelResolventReal_add (P : SubMarkovKernelSemigroup alpha) + {lam : ℝ} (hlam : 0 < lam) {f g : alpha → ℝ} + (hf : Measurable f) (hg : Measurable g) {D E : ℝ} + (hfD : ∀ y, |f y| ≤ D) (hgE : ∀ y, |g y| ≤ E) : + P.kernelResolventReal lam (f + g) = + P.kernelResolventReal lam f + P.kernelResolventReal lam g := by + funext x + unfold kernelResolventReal + change (∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + kernelIntegral (P (Real.toNNReal t)) (f + g) x) = + (∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + kernelIntegral (P (Real.toNNReal t)) f x) + + ∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + kernelIntegral (P (Real.toNNReal t)) g x + rw [← integral_add + (integrableOn_kernelResolventReal_integrand P hlam hf hfD x) + (integrableOn_kernelResolventReal_integrand P hlam hg hgE x)] + apply setIntegral_congr_fun measurableSet_Ioi + intro t _ht + let : IsFiniteKernel (P (Real.toNNReal t)) := + (P.isSubMarkovKernel (Real.toNNReal t)).isFiniteKernel + have hfint : Integrable f (P (Real.toNNReal t) x) := + Integrable.of_bound hf.stronglyMeasurable.aestronglyMeasurable D + (Eventually.of_forall hfD) + have hgint : Integrable g (P (Real.toNNReal t) x) := + Integrable.of_bound hg.stronglyMeasurable.aestronglyMeasurable E + (Eventually.of_forall hgE) + have hinner : kernelIntegral (P (Real.toNNReal t)) (f + g) x = + kernelIntegral (P (Real.toNNReal t)) f x + + kernelIntegral (P (Real.toNNReal t)) g x := by + unfold kernelIntegral + simpa only [Pi.add_apply] using integral_add hfint hgint + dsimp only + rw [hinner] + ring + +/-- The real kernel resolvent is real homogeneous. -/ +theorem kernelResolventReal_smul (P : SubMarkovKernelSemigroup alpha) + (lam a : ℝ) (f : alpha → ℝ) : + P.kernelResolventReal lam (a • f) = a • P.kernelResolventReal lam f := by + funext x + unfold kernelResolventReal + change (∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + kernelIntegral (P (Real.toNNReal t)) (a • f) x) = + a * ∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + kernelIntegral (P (Real.toNNReal t)) f x + rw [← MeasureTheory.integral_const_mul] + apply setIntegral_congr_fun measurableSet_Ioi + intro t _ht + have hinner : kernelIntegral (P (Real.toNNReal t)) (a • f) x = + a * kernelIntegral (P (Real.toNNReal t)) f x := by + unfold kernelIntegral + simp only [Pi.smul_apply, smul_eq_mul] + rw [MeasureTheory.integral_const_mul] + dsimp only + rw [hinner] + ring + +/-- The uniform bound for the real kernel resolvent of a bounded observable at a positive +shift. -/ +theorem norm_kernelResolventReal_le (P : SubMarkovKernelSemigroup alpha) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ} {D : ℝ} + (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + |P.kernelResolventReal lam f x| ≤ D / lam := by + rw [← Real.norm_eq_abs] + unfold kernelResolventReal + calc + ‖∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + kernelIntegral (P (Real.toNNReal t)) f x‖ ≤ + ∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * D := by + apply norm_integral_le_of_norm_le + ((exp_neg_integrableOn_Ioi 0 hlam).mul_const D) + filter_upwards [ae_restrict_mem measurableSet_Ioi] with t _ht + rw [Real.norm_eq_abs, abs_mul, abs_of_pos (Real.exp_pos _)] + exact mul_le_mul_of_nonneg_left + (norm_kernelIntegral_le_of_bound P hfD (Real.toNNReal t) x) (Real.exp_pos _).le + _ = D / lam := by + rw [integral_mul_const, integral_exp_mul_Ioi (neg_neg_of_pos hlam) 0] + simp only [mul_zero, Real.exp_zero] + field_simp + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ResolventUniqueness.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ResolventUniqueness.lean new file mode 100644 index 0000000000..f2abb2a699 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ResolventUniqueness.lean @@ -0,0 +1,351 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator + +/-! +# Uniqueness for resolvents on bounded measurable functions + +This file proves three elementary contraction principles for maps acting on bounded measurable +real functions. The first gives uniqueness for a bounded multiplicative perturbation equation. +The second propagates equality of two resolvent families from all sufficiently large shifts to +every positive shift by the resolvent identity. The third combines the first two principles. + +Main results: `perturbed_unique`, `resolventFamily_eq_of_eventually`, and +`perturbed_eq_of_resolventFamilies`. + +The operators are plain maps on functions; no Banach-space carrier or continuity is asserted. +-/ + +open Filter + +namespace MarkovProcess + +noncomputable section + +private theorem function_eq_zero_of_geometric_bound {alpha : Type*} {d : alpha → ℝ} + {r D : ℝ} (hr0 : 0 ≤ r) (hr1 : r < 1) (hD0 : 0 ≤ D) + (himprove : ∀ {B : ℝ}, 0 ≤ B → (∀ x, |d x| ≤ B) → ∀ x, |d x| ≤ r * B) + (hdD : ∀ x, |d x| ≤ D) : d = 0 := by + have hpow : ∀ n : ℕ, ∀ x, |d x| ≤ r ^ n * D := by + intro n + induction n with + | zero => + simpa only [pow_zero, one_mul] using hdD + | succ n ih => + have hnext := himprove (mul_nonneg (pow_nonneg hr0 n) hD0) ih + intro x + simpa only [pow_succ, mul_assoc, mul_comm r (r ^ n), mul_left_comm] using hnext x + funext x + have hlim : Tendsto (fun n : ℕ ↦ r ^ n * D) atTop (nhds 0) := by + simpa only [zero_mul] using + (tendsto_pow_atTop_nhds_zero_of_lt_one hr0 hr1).mul_const D + have hx0 : |d x| ≤ 0 := ge_of_tendsto hlim (Eventually.of_forall fun n ↦ hpow n x) + exact abs_eq_zero.mp (le_antisymm hx0 (abs_nonneg _)) + +variable {alpha : Type*} [MeasurableSpace alpha] [Nonempty alpha] + +/-- **Uniqueness for a bounded perturbation equation.** Suppose `R` is additive on bounded +measurable functions and has the uniform bound `|R f x| ≤ D / λ` whenever `|f| ≤ D`. If +`0 ≤ q ≤ C` and `C < λ`, then two maps preserving bounded measurable functions and solving +`Z f = R f - R (q * Z f)` agree on every bounded measurable function. + +At a fixed sufficiently large shift, this gives the bounded-measurable equality needed by +`resolventFamily_eq_of_eventually`. The `Nonempty alpha` assumption is used to extract +`0 ≤ C` and nonnegativity of bounds from their pointwise hypotheses. -/ +theorem perturbed_unique + (R X Y : (alpha → ℝ) → alpha → ℝ) {q : alpha → ℝ} {C lam : ℝ} + (hR_add : ∀ {f g : alpha → ℝ}, Measurable f → Measurable g → + (∃ D, ∀ x, |f x| ≤ D) → (∃ D, ∀ x, |g x| ≤ D) → R (f + g) = R f + R g) + (hR_bound : ∀ {f : alpha → ℝ}, Measurable f → ∀ {D : ℝ}, + (∀ x, |f x| ≤ D) → ∀ x, |R f x| ≤ D / lam) + (hq : Measurable q) (hq0 : ∀ x, 0 ≤ q x) (hqC : ∀ x, q x ≤ C) (hlam : C < lam) + (hX_meas : ∀ {f : alpha → ℝ}, Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + Measurable (X f)) + (hY_meas : ∀ {f : alpha → ℝ}, Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + Measurable (Y f)) + (hX_bound : ∀ {f : alpha → ℝ}, Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + ∃ D, ∀ x, |X f x| ≤ D) + (hY_bound : ∀ {f : alpha → ℝ}, Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + ∃ D, ∀ x, |Y f x| ≤ D) + (hX_fixed : ∀ {f : alpha → ℝ}, Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + X f = R f - R (fun x ↦ q x * X f x)) + (hY_fixed : ∀ {f : alpha → ℝ}, Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + Y f = R f - R (fun x ↦ q x * Y f x)) + {f : alpha → ℝ} (hf : Measurable f) {D : ℝ} (hfD : ∀ x, |f x| ≤ D) : + X f = Y f := by + have hfBound : ∃ E : ℝ, ∀ x, |f x| ≤ E := ⟨D, hfD⟩ + have hXeq := hX_fixed hf hfBound + have hYeq := hY_fixed hf hfBound + have hXm : Measurable (X f) := hX_meas hf hfBound + have hYm : Measurable (Y f) := hY_meas hf hfBound + obtain ⟨DX, hDX⟩ := hX_bound hf hfBound + obtain ⟨DY, hDY⟩ := hY_bound hf hfBound + let d : alpha → ℝ := X f - Y f + have hdMeas : Measurable d := hXm.sub hYm + have hdBound : ∀ x, |d x| ≤ |DX| + |DY| := by + intro x + calc + |d x| ≤ |X f x| + |Y f x| := abs_sub _ _ + _ ≤ DX + DY := add_le_add (hDX x) (hDY x) + _ ≤ |DX| + |DY| := add_le_add (le_abs_self _) (le_abs_self _) + let alpha0 : alpha := Classical.choice inferInstance + have hC0 : 0 ≤ C := (hq0 alpha0).trans (hqC alpha0) + have hlam0 : 0 < lam := hC0.trans_lt hlam + have hratio0 : 0 ≤ C / lam := div_nonneg hC0 hlam0.le + have hratio1 : C / lam < 1 := (div_lt_one hlam0).mpr hlam + have hdEq : d = fun x ↦ -R (fun y ↦ q y * d y) x := by + have hqXm : Measurable (fun x ↦ q x * X f x) := hq.mul hXm + have hqYm : Measurable (fun x ↦ q x * Y f x) := hq.mul hYm + have hqXBound : ∃ E, ∀ x, |q x * X f x| ≤ E := by + refine ⟨C * |DX|, fun x ↦ ?_⟩ + rw [abs_mul] + exact mul_le_mul (by simpa only [abs_of_nonneg (hq0 x)] using hqC x) + ((hDX x).trans (le_abs_self _)) (abs_nonneg _) hC0 + have hqYBound : ∃ E, ∀ x, |q x * Y f x| ≤ E := by + refine ⟨C * |DY|, fun x ↦ ?_⟩ + rw [abs_mul] + exact mul_le_mul (by simpa only [abs_of_nonneg (hq0 x)] using hqC x) + ((hDY x).trans (le_abs_self _)) (abs_nonneg _) hC0 + have hnegMeas : Measurable (fun x ↦ -(q x * Y f x)) := hqYm.neg + have hnegBound : ∃ E, ∀ x, |-(q x * Y f x)| ≤ E := by + simpa only [abs_neg] using hqYBound + have hRsum := hR_add hqXm hnegMeas hqXBound hnegBound + have hzeroMeas : Measurable (fun _ : alpha ↦ (0 : ℝ)) := measurable_const + have hzeroBound : ∃ E : ℝ, ∀ x : alpha, |(0 : ℝ)| ≤ E := + ⟨0, fun _ ↦ by simp only [abs_zero, le_refl]⟩ + have hRzero : R (fun _ : alpha ↦ (0 : ℝ)) = 0 := by + have h := hR_add hzeroMeas hzeroMeas hzeroBound hzeroBound + rw [show (fun _ : alpha ↦ (0 : ℝ)) + (fun _ ↦ 0) = fun _ ↦ 0 by + funext x + simp only [Pi.add_apply, zero_add]] at h + funext x + have hx := congrFun h x + simp only [Pi.add_apply] at hx + change R (fun _ ↦ 0) x = (0 : ℝ) + linarith only [hx] + have hRneg : R (fun x ↦ -(q x * Y f x)) = -R (fun x ↦ q x * Y f x) := by + have hcancel := hR_add hqYm hnegMeas hqYBound hnegBound + rw [show (fun x ↦ q x * Y f x) + (fun x ↦ -(q x * Y f x)) = fun _ ↦ 0 by + funext x + simp only [Pi.add_apply, add_neg_cancel], hRzero] at hcancel + funext x + have hx := congrFun hcancel x + simp only [Pi.add_apply, Pi.zero_apply, Pi.neg_apply] at hx ⊢ + linarith only [hx] + funext x + have hpoint := congrFun hRsum x + have hnegPoint := congrFun hRneg x + simp only [Pi.add_apply, Pi.neg_apply] at hpoint hnegPoint + have hinput : (fun y ↦ q y * (X f y - Y f y)) = + (fun y ↦ q y * X f y) + fun y ↦ -(q y * Y f y) := by + funext y + simp only [Pi.add_apply] + ring + have hRdiff : R (fun y ↦ q y * (X f y - Y f y)) x = + R (fun y ↦ q y * X f y) x - R (fun y ↦ q y * Y f y) x := by + rw [hinput, hpoint] + have hn : R (fun y ↦ -(q y * Y f y)) x = + -R (fun y ↦ q y * Y f y) x := by + exact hnegPoint + rw [hn] + ring + dsimp only [d] + change X f x - Y f x = -R (fun y ↦ q y * (X f y - Y f y)) x + calc + X f x - Y f x = + (R f x - R (fun y ↦ q y * X f y) x) - + (R f x - R (fun y ↦ q y * Y f y) x) := by + rw [congrFun hXeq x, congrFun hYeq x] + simp only [Pi.sub_apply] + _ = -R (fun y ↦ q y * (X f y - Y f y)) x := by + rw [hRdiff] + ring + have himprove : ∀ {B : ℝ}, 0 ≤ B → (∀ x, |d x| ≤ B) → + ∀ x, |d x| ≤ (C / lam) * B := by + intro B hB hdB x + have hprodMeas : Measurable (fun y ↦ q y * d y) := hq.mul hdMeas + have hprodBound : ∀ y, |q y * d y| ≤ C * B := by + intro y + rw [abs_mul, abs_of_nonneg (hq0 y)] + exact mul_le_mul (hqC y) (hdB y) (abs_nonneg _) hC0 + rw [congrFun hdEq x, abs_neg] + calc + |R (fun y ↦ q y * d y) x| ≤ C * B / lam := + hR_bound hprodMeas hprodBound x + _ = (C / lam) * B := by field_simp + have hd0 := function_eq_zero_of_geometric_bound hratio0 hratio1 + (add_nonneg (abs_nonneg _) (abs_nonneg _)) himprove hdBound + exact sub_eq_zero.mp hd0 + +/-- **Equality of resolvent families from equality at large shifts.** Let `X` and `Y` be +families of maps on bounded measurable real functions. Suppose `X` is additive and satisfies the +bound `|X_λ f| ≤ D / λ`, while both families preserve measurability and boundedness. If both +satisfy the resolvent identity and agree on bounded measurable functions above a fixed threshold, +then they agree on bounded measurable functions at every positive shift. + +The large-shift equality need only hold at the bounded measurable arguments used by the proof. -/ +theorem resolventFamily_eq_of_eventually + (X Y : ℝ → (alpha → ℝ) → alpha → ℝ) (C : ℝ) + (hX_add : ∀ {lam : ℝ}, 0 < lam → ∀ {f g : alpha → ℝ}, + Measurable f → Measurable g → (∃ D, ∀ x, |f x| ≤ D) → + (∃ D, ∀ x, |g x| ≤ D) → X lam (f + g) = X lam f + X lam g) + (hX_meas : ∀ {lam : ℝ}, 0 < lam → ∀ {f : alpha → ℝ}, Measurable f → + (∃ D, ∀ x, |f x| ≤ D) → Measurable (X lam f)) + (hY_meas : ∀ {lam : ℝ}, 0 < lam → ∀ {f : alpha → ℝ}, Measurable f → + (∃ D, ∀ x, |f x| ≤ D) → Measurable (Y lam f)) + (hX_bound : ∀ {lam : ℝ}, 0 < lam → ∀ {f : alpha → ℝ}, Measurable f → + ∀ {D : ℝ}, (∀ x, |f x| ≤ D) → ∀ x, |X lam f x| ≤ D / lam) + (hY_bound : ∀ {lam : ℝ}, 0 < lam → ∀ {f : alpha → ℝ}, Measurable f → + (∃ D, ∀ x, |f x| ≤ D) → ∃ D, ∀ x, |Y lam f x| ≤ D) + (hX_resolvent : ∀ {mu lam : ℝ}, 0 < mu → 0 < lam → ∀ {f : alpha → ℝ}, + Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + X mu f = X lam f + (lam - mu) • X lam (X mu f)) + (hY_resolvent : ∀ {mu lam : ℝ}, 0 < mu → 0 < lam → ∀ {f : alpha → ℝ}, + Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + Y mu f = Y lam f + (lam - mu) • Y lam (Y mu f)) + (hlarge : ∀ {lam : ℝ}, C < lam → 0 < lam → ∀ {g : alpha → ℝ}, Measurable g → + (∃ D, ∀ x, |g x| ≤ D) → X lam g = Y lam g) {mu : ℝ} (hmu : 0 < mu) + {f : alpha → ℝ} (hfMeas : Measurable f) {D : ℝ} (hfD : ∀ x, |f x| ≤ D) : + X mu f = Y mu f := by + let lam : ℝ := max C mu + 1 + have hClam : C < lam := (le_max_left C mu).trans_lt (lt_add_of_pos_right _ zero_lt_one) + have hmulam : mu < lam := (le_max_right C mu).trans_lt (lt_add_of_pos_right _ zero_lt_one) + have hlam : 0 < lam := hmu.trans hmulam + have hfBound : ∃ E, ∀ x, |f x| ≤ E := ⟨D, hfD⟩ + have hXm : Measurable (X mu f) := hX_meas hmu hfMeas hfBound + have hYm : Measurable (Y mu f) := hY_meas hmu hfMeas hfBound + have hDX := hX_bound hmu hfMeas hfD + obtain ⟨EY, hEY⟩ := hY_bound hmu hfMeas hfBound + let d : alpha → ℝ := X mu f - Y mu f + have hdMeas : Measurable d := hXm.sub hYm + have hdBound : ∀ x, |d x| ≤ D / mu + EY := by + intro x + exact (abs_sub _ _).trans (add_le_add (hDX x) (hEY x)) + let alpha0 : alpha := Classical.choice inferInstance + have hDmu0 : 0 ≤ D / mu := by + have hD0 : 0 ≤ D := (abs_nonneg (f alpha0)).trans (hfD alpha0) + exact div_nonneg hD0 hmu.le + have hEY0 : 0 ≤ EY := (abs_nonneg (Y mu f alpha0)).trans (hEY alpha0) + have hdEq : d = (lam - mu) • X lam d := by + have hXid := hX_resolvent hmu hlam hfMeas hfBound + have hYid := hY_resolvent hmu hlam hfMeas hfBound + have hXYf := hlarge hClam hlam hfMeas hfBound + have hXYY := hlarge hClam hlam hYm ⟨EY, hEY⟩ + rw [← hXYf, ← hXYY] at hYid + have hzeroMeas : Measurable (fun _ : alpha ↦ (0 : ℝ)) := measurable_const + have hzeroBound : ∃ E : ℝ, ∀ x : alpha, |(0 : ℝ)| ≤ E := + ⟨0, fun _ ↦ by simp only [abs_zero, le_refl]⟩ + have hXzero : X lam (fun _ ↦ 0) = 0 := by + have h := hX_add hlam hzeroMeas hzeroMeas hzeroBound hzeroBound + have hzadd : (fun _ : alpha ↦ (0 : ℝ)) + (fun _ ↦ 0) = fun _ ↦ 0 := by + funext x + simp only [Pi.add_apply, zero_add] + rw [hzadd] at h + funext x + have hx := congrFun h x + simp only [Pi.add_apply] at hx + change X lam (fun _ ↦ 0) x = (0 : ℝ) + linarith only [hx] + have hnegBound : ∃ E, ∀ x, |-(Y mu f x)| ≤ E := + ⟨EY, fun x ↦ by simpa only [abs_neg] using hEY x⟩ + have hnegMeas : Measurable (fun x ↦ -(Y mu f x)) := hYm.neg + have hsum := hX_add hlam hXm hnegMeas ⟨D / mu, hDX⟩ hnegBound + have hneg : X lam (fun x ↦ -(Y mu f x)) = -X lam (Y mu f) := by + have hcancel := hX_add hlam hYm hnegMeas ⟨EY, hEY⟩ hnegBound + rw [show (Y mu f + fun x ↦ -(Y mu f x)) = fun _ ↦ 0 by + funext x + simp only [Pi.add_apply, add_neg_cancel]] at hcancel + rw [hXzero] at hcancel + funext x + have hx := congrFun hcancel x + simp only [Pi.add_apply, Pi.zero_apply, Pi.neg_apply] at hx ⊢ + linarith only [hx] + funext x + have hsumx := congrFun hsum x + have hnegx := congrFun hneg x + have hXx := congrFun hXid x + have hYx := congrFun hYid x + dsimp only [d] + simp only [Pi.sub_apply, Pi.add_apply, Pi.smul_apply, smul_eq_mul] at hsumx hXx hYx ⊢ + change X lam (fun z ↦ -(Y mu f z)) x = -X lam (Y mu f) x at hnegx + rw [show X mu f - Y mu f = X mu f + fun z ↦ -(Y mu f z) by + funext z + simp only [Pi.sub_apply, Pi.add_apply] + ring] + rw [hsumx, hnegx] + rw [hXx, hYx] + ring + have hratio0 : 0 ≤ (lam - mu) / lam := + div_nonneg (sub_nonneg.mpr hmulam.le) hlam.le + have hratio1 : (lam - mu) / lam < 1 := (div_lt_one hlam).mpr (sub_lt_self lam hmu) + have himprove : ∀ {B : ℝ}, 0 ≤ B → (∀ x, |d x| ≤ B) → + ∀ x, |d x| ≤ ((lam - mu) / lam) * B := by + intro B hB hdB x + rw [congrFun hdEq x, Pi.smul_apply, smul_eq_mul, abs_mul, + abs_of_nonneg (sub_nonneg.mpr hmulam.le)] + calc + (lam - mu) * |X lam d x| ≤ (lam - mu) * (B / lam) := + mul_le_mul_of_nonneg_left (hX_bound hlam hdMeas hdB x) + (sub_nonneg.mpr hmulam.le) + _ = ((lam - mu) / lam) * B := by field_simp + have hd0 := function_eq_zero_of_geometric_bound hratio0 hratio1 + (add_nonneg hDmu0 hEY0) himprove hdBound + exact sub_eq_zero.mp hd0 + +/-- **Equality of perturbed resolvent families.** Two resolvent families that satisfy the same +bounded perturbation equation above the potential bound agree on every bounded measurable +function at every positive shift. The first family must be additive and contractive; the second +need only preserve boundedness. Both preserve measurability and satisfy the resolvent identity. -/ +theorem perturbed_eq_of_resolventFamilies + (R X Y : ℝ → (alpha → ℝ) → alpha → ℝ) {q : alpha → ℝ} {C : ℝ} + (hR_add : ∀ {lam : ℝ}, C < lam → 0 < lam → ∀ {f g : alpha → ℝ}, + Measurable f → Measurable g → (∃ D, ∀ x, |f x| ≤ D) → + (∃ D, ∀ x, |g x| ≤ D) → R lam (f + g) = R lam f + R lam g) + (hR_bound : ∀ {lam : ℝ}, C < lam → 0 < lam → ∀ {f : alpha → ℝ}, + Measurable f → ∀ {D : ℝ}, (∀ x, |f x| ≤ D) → + ∀ x, |R lam f x| ≤ D / lam) + (hq : Measurable q) (hq0 : ∀ x, 0 ≤ q x) (hqC : ∀ x, q x ≤ C) + (hX_add : ∀ {lam : ℝ}, 0 < lam → ∀ {f g : alpha → ℝ}, + Measurable f → Measurable g → (∃ D, ∀ x, |f x| ≤ D) → + (∃ D, ∀ x, |g x| ≤ D) → X lam (f + g) = X lam f + X lam g) + (hX_meas : ∀ {lam : ℝ}, 0 < lam → ∀ {f : alpha → ℝ}, Measurable f → + (∃ D, ∀ x, |f x| ≤ D) → Measurable (X lam f)) + (hY_meas : ∀ {lam : ℝ}, 0 < lam → ∀ {f : alpha → ℝ}, Measurable f → + (∃ D, ∀ x, |f x| ≤ D) → Measurable (Y lam f)) + (hX_bound : ∀ {lam : ℝ}, 0 < lam → ∀ {f : alpha → ℝ}, Measurable f → + ∀ {D : ℝ}, (∀ x, |f x| ≤ D) → ∀ x, |X lam f x| ≤ D / lam) + (hY_bound : ∀ {lam : ℝ}, 0 < lam → ∀ {f : alpha → ℝ}, Measurable f → + (∃ D, ∀ x, |f x| ≤ D) → ∃ D, ∀ x, |Y lam f x| ≤ D) + (hX_resolvent : ∀ {mu lam : ℝ}, 0 < mu → 0 < lam → ∀ {f : alpha → ℝ}, + Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + X mu f = X lam f + (lam - mu) • X lam (X mu f)) + (hY_resolvent : ∀ {mu lam : ℝ}, 0 < mu → 0 < lam → ∀ {f : alpha → ℝ}, + Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + Y mu f = Y lam f + (lam - mu) • Y lam (Y mu f)) + (hX_fixed : ∀ {lam : ℝ}, C < lam → 0 < lam → ∀ {f : alpha → ℝ}, + Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + X lam f = R lam f - R lam (fun x ↦ q x * X lam f x)) + (hY_fixed : ∀ {lam : ℝ}, C < lam → 0 < lam → ∀ {f : alpha → ℝ}, + Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + Y lam f = R lam f - R lam (fun x ↦ q x * Y lam f x)) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ} (hf : Measurable f) + {D : ℝ} (hfD : ∀ x, |f x| ≤ D) : + X lam f = Y lam f := by + apply resolventFamily_eq_of_eventually X Y C hX_add hX_meas hY_meas + hX_bound hY_bound hX_resolvent hY_resolvent _ hlam hf hfD + intro mu hCmu hmu g hg hgb + obtain ⟨E, hgE⟩ := hgb + exact perturbed_unique (R mu) (X mu) (Y mu) (hR_add hCmu hmu) + (hR_bound hCmu hmu) hq hq0 hqC hCmu (hX_meas hmu) (hY_meas hmu) + (fun hf' hf'b ↦ by + obtain ⟨E', hfE'⟩ := hf'b + exact ⟨E' / mu, hX_bound hmu hf' hfE'⟩) + (hY_bound hmu) + (hX_fixed hCmu hmu) (hY_fixed hCmu hmu) hg hgE + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/WeakConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/WeakConvergence.lean new file mode 100644 index 0000000000..920ad72a41 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/WeakConvergence.lean @@ -0,0 +1,135 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.MeasureTheory.Integral.Bochner.Set +import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction +import Mathlib.MeasureTheory.Integral.CompactlySupported +import Mathlib.MeasureTheory.Measure.Tight +import Mathlib.Topology.UrysohnsLemma + +/-! +# Vague convergence to a probability measure is weak convergence + +On a locally compact Polish space, a family of probability measures whose integrals of every +compactly supported continuous test converge to those of a probability measure also converges +against every bounded continuous test. The reason is that no mass escapes: the limit is a +probability measure, so it is tight, and a compactly supported cutoff with values in `[0, 1]` +captures all but `epsilon` of its mass; convergence of the cutoff integral then forces the +approximating measures to keep all but `epsilon` of their mass on the same compact set, and the +truncation error of a bounded continuous test is at most its norm times the discarded mass. + +Main results: `tendsto_integral_boundedContinuous_of_tendsto_compactlySupported`. + +Nothing is asserted for families that are not probability measures: for sub-probability measures +the conclusion is false, since mass may escape to infinity. +-/ + +open Filter MeasureTheory Topology +open scoped BoundedContinuousFunction CompactlySupported + +namespace MarkovProcess + +variable {X : Type*} [MeasurableSpace X] + +/-- Tightness in integral form: on a locally compact Polish space, a probability measure has all +but `eps` of its mass captured by the integral of a compactly supported continuous cutoff with +values in `[0, 1]`. -/ +theorem exists_compactlySupported_one_sub_lt_integral [PseudoEMetricSpace X] + [CompleteSpace X] [SecondCountableTopology X] [BorelSpace X] [LocallyCompactSpace X] + [T2Space X] (mu : Measure X) [IsProbabilityMeasure mu] {eps : ℝ} (heps : 0 < eps) : + ∃ g : C_c(X, ℝ), (∀ y, g y ∈ Set.Icc (0 : ℝ) 1) ∧ 1 - eps < ∫ y, g y ∂mu := by + have htight : IsTightMeasureSet ({mu} : Set (Measure X)) := isTightMeasureSet_singleton + rw [isTightMeasureSet_iff_exists_isCompact_measure_compl_le] at htight + obtain ⟨K, hK, hKmu⟩ := htight (ENNReal.ofReal (eps / 2)) (by positivity) + simp only [Set.mem_singleton_iff, forall_eq] at hKmu + obtain ⟨g, hgK, -, hgsupp, hg01⟩ := + exists_continuous_one_zero_of_isCompact hK isClosed_empty (Set.disjoint_empty K) + refine ⟨⟨g, hgsupp⟩, hg01, ?_⟩ + show (1 : ℝ) - eps < ∫ y, g y ∂mu + have hKmeas : MeasurableSet K := hK.isClosed.measurableSet + have hKcompl : mu.real Kᶜ ≤ eps / 2 := by + have h := ENNReal.toReal_mono (by simp) hKmu + rwa [ENNReal.toReal_ofReal (by positivity)] at h + have hint : Integrable (fun y ↦ g y) mu := + g.continuous.integrable_of_hasCompactSupport hgsupp + have hlow : mu.real K ≤ ∫ y, g y ∂mu := by + rw [← integral_indicator_one hKmeas] + refine integral_mono ((integrable_const (1 : ℝ)).indicator hKmeas) hint fun y ↦ ?_ + by_cases hy : y ∈ K + · simp only [Set.indicator_of_mem hy, Pi.one_apply] + exact le_of_eq (hgK hy).symm + · simp only [Set.indicator_of_notMem hy] + exact (hg01 y).1 + have huniv : mu.real K + mu.real Kᶜ = 1 := by + rw [measureReal_add_measureReal_compl hKmeas, probReal_univ] + linarith + +/-- Truncation error: cutting a bounded continuous `f` down to `f * g` by a cutoff `g` with +values in `[0, 1]` costs at most `‖f‖` times the mass `1 - ∫ g` that the cutoff discards. -/ +theorem abs_integral_sub_integral_smul_le [TopologicalSpace X] [OpensMeasurableSpace X] + (mu : Measure X) [IsProbabilityMeasure mu] (f : X →ᵇ ℝ) (g : C_c(X, ℝ)) + (hg01 : ∀ y, g y ∈ Set.Icc (0 : ℝ) 1) : + |(∫ y, f y ∂mu) - ∫ y, (f • g) y ∂mu| ≤ ‖f‖ * (1 - ∫ y, g y ∂mu) := by + have hf : Integrable (fun y ↦ f y) mu := f.integrable mu + have hg : Integrable (fun y ↦ g y) mu := + (map_continuous g).integrable_of_hasCompactSupport g.hasCompactSupport + have hfg : Integrable (fun y ↦ (f • g) y) mu := + (map_continuous (f • g)).integrable_of_hasCompactSupport + (f • g : C_c(X, ℝ)).hasCompactSupport + have hbound : ∀ y, ‖f y - (f • g) y‖ ≤ ‖f‖ * (1 - g y) := by + intro y + have hy1 : g y ≤ 1 := (hg01 y).2 + have hsub : f y - (f • g) y = f y * (1 - g y) := by + simp only [CompactlySupportedContinuousMap.smulc_apply, smul_eq_mul] + ring + rw [hsub, norm_mul, Real.norm_eq_abs (1 - g y), abs_of_nonneg (by linarith)] + exact mul_le_mul_of_nonneg_right (f.norm_coe_le_norm y) (by linarith) + have hmaj : Integrable (fun y ↦ ‖f‖ * (1 - g y)) mu := + ((integrable_const (1 : ℝ)).sub hg).const_mul ‖f‖ + rw [← integral_sub hf hfg, ← Real.norm_eq_abs] + refine (norm_integral_le_of_norm_le hmaj (Eventually.of_forall hbound)).trans_eq ?_ + rw [integral_const_mul, integral_sub (integrable_const (1 : ℝ)) hg, integral_const, + probReal_univ, smul_eq_mul, mul_one] + +/-- **Vague convergence to a probability measure is weak convergence.** If the integrals of every +compactly supported continuous test against a family of probability measures converge to those +against a probability measure, then the same holds for every bounded continuous test. -/ +theorem tendsto_integral_boundedContinuous_of_tendsto_compactlySupported + [PseudoEMetricSpace X] [CompleteSpace X] [SecondCountableTopology X] [BorelSpace X] + [LocallyCompactSpace X] [T2Space X] {iota : Type*} {l : Filter iota} + (mu : iota → Measure X) (nu : Measure X) + [∀ i, IsProbabilityMeasure (mu i)] [IsProbabilityMeasure nu] + (h : ∀ g : C_c(X, ℝ), Tendsto (fun i ↦ ∫ y, g y ∂mu i) l (nhds (∫ y, g y ∂nu))) + (f : X →ᵇ ℝ) : Tendsto (fun i ↦ ∫ y, f y ∂mu i) l (nhds (∫ y, f y ∂nu)) := by + rw [Metric.tendsto_nhds] + intro eps heps + have hnorm : (0 : ℝ) ≤ ‖f‖ := norm_nonneg f + have hdpos : 0 < eps / (3 * (‖f‖ + 1)) := by positivity + obtain ⟨g, hg01, hgint⟩ := exists_compactlySupported_one_sub_lt_integral nu hdpos + have hsmall : ‖f‖ * (eps / (3 * (‖f‖ + 1))) ≤ eps / 3 := by + rw [mul_div_assoc', div_le_div_iff₀ (by positivity) (by norm_num : (0 : ℝ) < 3)] + have hexpand : eps * (3 * (‖f‖ + 1)) - ‖f‖ * eps * 3 = 3 * eps := by ring + linarith only [hexpand, heps] + have htrunc : ∀ᶠ i in l, + |(∫ y, (f • g) y ∂mu i) - ∫ y, (f • g) y ∂nu| < eps / 3 := by + have hstep := Metric.tendsto_nhds.mp (h (f • g)) (eps / 3) (by positivity) + simpa only [Real.dist_eq] using hstep + have hmass : ∀ᶠ i in l, 1 - (∫ y, g y ∂mu i) < eps / (3 * (‖f‖ + 1)) := + Tendsto.eventually_lt_const (by linarith only [hgint]) + (tendsto_const_nhds.sub (h g)) + filter_upwards [htrunc, hmass] with i hitrunc himass + rw [Real.dist_eq] + have hkey := abs_integral_sub_integral_smul_le (mu i) f g hg01 + have hkey0 := abs_integral_sub_integral_smul_le nu f g hg01 + have hbound : ‖f‖ * (1 - ∫ y, g y ∂mu i) ≤ ‖f‖ * (eps / (3 * (‖f‖ + 1))) := + mul_le_mul_of_nonneg_left himass.le hnorm + have hbound0 : ‖f‖ * (1 - ∫ y, g y ∂nu) ≤ ‖f‖ * (eps / (3 * (‖f‖ + 1))) := + mul_le_mul_of_nonneg_left (by linarith only [hgint]) hnorm + have htri := abs_sub_le (∫ y, f y ∂mu i) (∫ y, (f • g) y ∂mu i) (∫ y, f y ∂nu) + have htri0 := abs_sub_le (∫ y, (f • g) y ∂mu i) (∫ y, (f • g) y ∂nu) (∫ y, f y ∂nu) + have hcomm := abs_sub_comm (∫ y, (f • g) y ∂nu) (∫ y, f y ∂nu) + linarith only [hkey, hkey0, hitrunc, hbound, hbound0, hsmall, htri, htri0, hcomm] + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed.lean new file mode 100644 index 0000000000..e9e08375ff --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed.lean @@ -0,0 +1,30 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Killed.ExitTimeIdentification +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingC0 +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer +import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel +import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit +import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals +import LeanPool.MarkovProcess.MarkovProcess.Killed.Minimal +import LeanPool.MarkovProcess.MarkovProcess.Killed.Nested +import LeanPool.MarkovProcess.MarkovProcess.Killed.Process +import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup + +/-! +# Killed + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/ExitTimeIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/ExitTimeIdentification.lean new file mode 100644 index 0000000000..00af7ac810 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/ExitTimeIdentification.lean @@ -0,0 +1,210 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent + +/-! +# Identifying the expected exit time with a Dirichlet resolvent + +The killed resolvent of the constant function one at the shift zero is the expected exit time, + + `E_x τ_U = R^U_0 1 (x)` (`IsConservative.lintegral_exitTime_eq_killedResolvent_zero`), + +and the shift zero is the increasing limit of the positive shifts `1 / (n + 1)` +(`IsConservative.killedResolvent_zero_eq_iSup`). Both statements are unconditional. + +Consumers who identify the killed resolvent at positive shifts with an analytically defined +Dirichlet resolvent `RU` then read the expected exit time off the limit of `RU` +(`IsConservative.lintegral_exitTime_eq_of_killedResolvent_eq`): the identification enters only as a +hypothesis, so nothing here depends on how it is established. Two one-sided corollaries are +recorded, an upper bound from a uniform upper bound on the limit +(`IsConservative.lintegral_exitTime_le_of_killedResolvent_eq`) and a lower bound on a subset from a +uniform lower bound there (`IsConservative.le_lintegral_exitTime_of_killedResolvent_eq`). + +The limit of `RU` enters those statements as a supremum along the shifts `1 / (n + 1)`. A +consumer who instead has a limit as the shift decreases to zero converts it with +`IsConservative.iSup_eq_of_tendsto_nhdsGT_zero`: the killed resolvent is antitone in the shift, so +the identification makes `RU` antitone on `U` too and the sequence increases to its limit. + +The consumer-supplied resolvent and its limit are `ℝ≥0∞`-valued, so no integrability or finiteness +hypothesis appears; a consumer working with real-valued solutions bridges with `ENNReal.ofReal`. +-/ + +open Filter MeasureTheory ProbabilityTheory Set +open scoped ENNReal NNReal Topology + +namespace MarkovProcess.SubMarkovKernelSemigroup + +noncomputable section + +/-- The exponential discounts at the shifts `1 / (n + 1)` increase to one on the nonnegative +half-line. -/ +private theorem iSup_ofReal_exp_neg_inv_mul (t : ℝ) (ht : 0 ≤ t) : + ⨆ n : ℕ, ENNReal.ofReal (Real.exp (-((n : ℝ) + 1)⁻¹ * t)) = 1 := by + have hmono : Monotone fun n : ℕ ↦ ENNReal.ofReal (Real.exp (-((n : ℝ) + 1)⁻¹ * t)) := by + intro m n hmn + refine ENNReal.ofReal_le_ofReal (Real.exp_le_exp.mpr ?_) + refine mul_le_mul_of_nonneg_right ?_ ht + refine neg_le_neg ?_ + exact inv_anti₀ (by positivity) (add_le_add (Nat.cast_le.mpr hmn) le_rfl) + have hzero : Tendsto (fun n : ℕ ↦ ((n : ℝ) + 1)⁻¹) atTop (𝓝 0) := by + have h : Tendsto (fun n : ℕ ↦ 1 / ((n : ℝ) + 1)) atTop (𝓝 0) := + tendsto_one_div_add_atTop_nhds_zero_nat + simp_rw [one_div] at h + exact h + have hlim : Tendsto (fun n : ℕ ↦ ENNReal.ofReal (Real.exp (-((n : ℝ) + 1)⁻¹ * t))) atTop + (𝓝 1) := by + have hreal : Tendsto (fun n : ℕ ↦ Real.exp (-((n : ℝ) + 1)⁻¹ * t)) atTop + (𝓝 (Real.exp (-(0 : ℝ) * t))) := + (Real.continuous_exp.tendsto _).comp (((hzero.neg).mul_const t)) + have h := ENNReal.tendsto_ofReal hreal + simpa only [neg_zero, zero_mul, Real.exp_zero, ENNReal.ofReal_one] using h + exact tendsto_nhds_unique (tendsto_atTop_iSup hmono) hlim + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- **The expected exit time is the killed resolvent of one at the shift zero.** -/ +theorem IsConservative.lintegral_exitTime_eq_killedResolvent_zero (U : Set alpha) (hU : IsOpen U) + (x : alpha) : + ∫⁻ omega, ContinuousPath.exitTime U omega ∂(IsConservative.continuousProcess P hP x) = + IsConservative.killedResolvent P hP U hU 0 (fun _ ↦ 1) x := by + rw [IsConservative.killedResolvent_eq_lintegral P hP U hU 0 (f := fun _ ↦ (1 : ℝ≥0∞)) + measurable_const x] + refine lintegral_congr fun omega ↦ ?_ + set tau : ℝ≥0∞ := ContinuousPath.exitTime U omega with htau + have hS : MeasurableSet {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau} := + measurableSet_lt (measurable_coe_nnreal_ennreal.comp measurable_real_toNNReal) + measurable_const + have hinner : (∫⁻ t in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-0 * t)) * + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau}.indicator + (fun _ ↦ (1 : ℝ≥0∞)) t) = + volume ({t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau} ∩ Set.Ioi 0) := by + have hpoint : ∀ t : ℝ, ENNReal.ofReal (Real.exp (-0 * t)) * + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau}.indicator + (fun _ ↦ (1 : ℝ≥0∞)) t = + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau}.indicator + (fun _ ↦ (1 : ℝ≥0∞)) t := by + intro t + simp only [neg_zero, zero_mul, Real.exp_zero, ENNReal.ofReal_one, one_mul] + rw [lintegral_congr hpoint, lintegral_indicator hS, setLIntegral_one, + Measure.restrict_apply hS] + rw [hinner, ContinuousPath.survivalSet tau] + by_cases htop : tau = ⊤ + · rw [if_pos htop, htop, Real.volume_Ioi] + · rw [if_neg htop, Real.volume_Ioo, sub_zero, ENNReal.ofReal_toReal htop] + +/-- The killed resolvent at the shift zero is the increasing limit of the killed resolvents at the +positive shifts `1 / (n + 1)`. -/ +theorem IsConservative.killedResolvent_zero_eq_iSup (U : Set alpha) (hU : IsOpen U) + {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + IsConservative.killedResolvent P hP U hU 0 f x = + ⨆ n : ℕ, IsConservative.killedResolvent P hP U hU ((n : ℝ) + 1)⁻¹ f x := by + set G : ℝ → ℝ≥0∞ := fun t ↦ + ∫⁻ y, f y ∂(IsConservative.killedKernel P hP U hU (Real.toNNReal t) x) with hG + have hGmeas : Measurable G := by + refine (Measure.measurable_lintegral hf).comp ?_ + exact (IsConservative.measurable_killedKernel P hP U hU).comp + (measurable_real_toNNReal.prodMk measurable_const) + have hFmeas : ∀ n : ℕ, + Measurable fun t : ℝ ↦ ENNReal.ofReal (Real.exp (-((n : ℝ) + 1)⁻¹ * t)) * G t := by + intro n + exact (ENNReal.measurable_ofReal.comp (Real.continuous_exp.measurable.comp + (measurable_const.mul measurable_id))).mul hGmeas + have hFmono : ∀ t ∈ Set.Ioi (0 : ℝ), + Monotone fun n : ℕ ↦ ENNReal.ofReal (Real.exp (-((n : ℝ) + 1)⁻¹ * t)) * G t := by + intro t ht m n hmn + refine mul_le_mul_left ?_ (G t) + refine ENNReal.ofReal_le_ofReal (Real.exp_le_exp.mpr ?_) + refine mul_le_mul_of_nonneg_right (neg_le_neg ?_) (le_of_lt ht) + exact inv_anti₀ (by positivity) (add_le_add (Nat.cast_le.mpr hmn) le_rfl) + have hkey : ∀ t ∈ Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-0 * t)) * G t = + ⨆ n : ℕ, ENNReal.ofReal (Real.exp (-((n : ℝ) + 1)⁻¹ * t)) * G t := by + intro t ht + rw [← ENNReal.iSup_mul, iSup_ofReal_exp_neg_inv_mul t (le_of_lt ht)] + simp only [neg_zero, zero_mul, Real.exp_zero, ENNReal.ofReal_one] + calc + IsConservative.killedResolvent P hP U hU 0 f x = + ∫⁻ t in Set.Ioi (0 : ℝ), ⨆ n : ℕ, + ENNReal.ofReal (Real.exp (-((n : ℝ) + 1)⁻¹ * t)) * G t := + setLIntegral_congr_fun measurableSet_Ioi hkey + _ = ⨆ n : ℕ, ∫⁻ t in Set.Ioi (0 : ℝ), + ENNReal.ofReal (Real.exp (-((n : ℝ) + 1)⁻¹ * t)) * G t := + lintegral_iSup' (fun n ↦ (hFmeas n).aemeasurable) + (ae_restrict_of_forall_mem measurableSet_Ioi hFmono) + _ = ⨆ n : ℕ, IsConservative.killedResolvent P hP U hU ((n : ℝ) + 1)⁻¹ f x := rfl + +variable (RU : ℝ → alpha → ℝ≥0∞) (w : alpha → ℝ≥0∞) + +/-- **A limit as the shift decreases to zero is the supremum along `1 / (n + 1)`.** The killed +resolvent is antitone in the shift, so a family `RU` agreeing with it on `U` at every positive +shift is antitone there as well, and a limit of `RU` as the shift decreases to zero is therefore +the supremum of the sequence. This produces the hypothesis `hlim` of +`IsConservative.lintegral_exitTime_eq_of_killedResolvent_eq` from the limit a consumer usually +has. -/ +theorem IsConservative.iSup_eq_of_tendsto_nhdsGT_zero (U : Set alpha) (hU : IsOpen U) + (hident : ∀ lam : ℝ, 0 < lam → ∀ y ∈ U, + IsConservative.killedResolvent P hP U hU lam (fun _ ↦ 1) y = RU lam y) + (hw : ∀ y ∈ U, Tendsto (fun lam : ℝ ↦ RU lam y) (𝓝[>] (0 : ℝ)) (𝓝 (w y))) : + ∀ y ∈ U, ⨆ n : ℕ, RU ((n : ℝ) + 1)⁻¹ y = w y := by + intro y hy + have hpos : ∀ n : ℕ, (0 : ℝ) < ((n : ℝ) + 1)⁻¹ := fun n ↦ by positivity + have hmono : Monotone fun n : ℕ ↦ RU ((n : ℝ) + 1)⁻¹ y := by + intro m n hmn + dsimp only + rw [← hident _ (hpos m) y hy, ← hident _ (hpos n) y hy] + refine IsConservative.killedResolvent_antitone P hP U hU (fun _ ↦ 1) y ?_ + exact inv_anti₀ (by positivity) (add_le_add (Nat.cast_le.mpr hmn) le_rfl) + have hseq : Tendsto (fun n : ℕ ↦ ((n : ℝ) + 1)⁻¹) atTop (𝓝[>] (0 : ℝ)) := by + refine tendsto_nhdsWithin_of_tendsto_nhds_of_eventually_within _ ?_ + (Filter.Eventually.of_forall fun n ↦ hpos n) + have h : Tendsto (fun n : ℕ ↦ 1 / ((n : ℝ) + 1)) atTop (𝓝 0) := + tendsto_one_div_add_atTop_nhds_zero_nat + simpa only [one_div] using h + exact tendsto_nhds_unique (tendsto_atTop_iSup hmono) ((hw y hy).comp hseq) + +/-- **The expected exit time from an identified Dirichlet resolvent.** If the killed resolvent of +one agrees on `U` with a consumer-supplied family `RU` at every positive shift, and `RU` has the +pointwise limit `w` along the shifts `1 / (n + 1)`, then the expected exit time is `w`. -/ +theorem IsConservative.lintegral_exitTime_eq_of_killedResolvent_eq (U : Set alpha) (hU : IsOpen U) + (hident : ∀ lam : ℝ, 0 < lam → ∀ y ∈ U, + IsConservative.killedResolvent P hP U hU lam (fun _ ↦ 1) y = RU lam y) + (hlim : ∀ y ∈ U, ⨆ n : ℕ, RU ((n : ℝ) + 1)⁻¹ y = w y) + {x : alpha} (hx : x ∈ U) : + ∫⁻ omega, ContinuousPath.exitTime U omega ∂(IsConservative.continuousProcess P hP x) = w x := by + rw [IsConservative.lintegral_exitTime_eq_killedResolvent_zero P hP U hU x, + IsConservative.killedResolvent_zero_eq_iSup P hP U hU measurable_const x, ← hlim x hx] + refine iSup_congr fun n ↦ ?_ + exact hident _ (by positivity) x hx + +/-- The upper half of the identification: a uniform upper bound on the limit bounds the expected +exit time. -/ +theorem IsConservative.lintegral_exitTime_le_of_killedResolvent_eq (U : Set alpha) (hU : IsOpen U) + (hident : ∀ lam : ℝ, 0 < lam → ∀ y ∈ U, + IsConservative.killedResolvent P hP U hU lam (fun _ ↦ 1) y = RU lam y) + (hlim : ∀ y ∈ U, ⨆ n : ℕ, RU ((n : ℝ) + 1)⁻¹ y = w y) + (M : ℝ≥0∞) (hupper : ∀ y ∈ U, w y ≤ M) {x : alpha} (hx : x ∈ U) : + ∫⁻ omega, ContinuousPath.exitTime U omega ∂(IsConservative.continuousProcess P hP x) ≤ M := by + rw [IsConservative.lintegral_exitTime_eq_of_killedResolvent_eq P hP RU w U hU hident hlim hx] + exact hupper x hx + +/-- The lower half of the identification: a uniform lower bound on the limit over a subset bounds +the expected exit time from below there. -/ +theorem IsConservative.le_lintegral_exitTime_of_killedResolvent_eq (U : Set alpha) (hU : IsOpen U) + (hident : ∀ lam : ℝ, 0 < lam → ∀ y ∈ U, + IsConservative.killedResolvent P hP U hU lam (fun _ ↦ 1) y = RU lam y) + (hlim : ∀ y ∈ U, ⨆ n : ℕ, RU ((n : ℝ) + 1)⁻¹ y = w y) + (W : Set alpha) (hWU : W ⊆ U) (c : ℝ≥0∞) (hlower : ∀ y ∈ W, c ≤ w y) + {x : alpha} (hx : x ∈ W) : + c ≤ ∫⁻ omega, ContinuousPath.exitTime U omega ∂(IsConservative.continuousProcess P hP x) := by + rw [IsConservative.lintegral_exitTime_eq_of_killedResolvent_eq P hP RU w U hU hident hlim + (hWU hx)] + exact hlower x hx + +end + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingC0.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingC0.lean new file mode 100644 index 0000000000..a9560a42a2 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingC0.lean @@ -0,0 +1,266 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer + +/-! +# The supremum resolvent as a positive `C₀`-contractive resolvent + +The supremum resolvent of a family of local resolvents acts on bounded measurable observables. +Two properties of its action on `C₀` are analytic and are hypotheses here: that the value on an +observable vanishing at infinity is again continuous and vanishing at infinity, supplied as a map +`T` together with the identification `hT` of its values, and that the range of `T` is dense. +Additivity, real homogeneity, the operator bound `1 / lam`, positivity and the resolvent identity +are then proved from the extended-real theory, and assemble the supremum resolvent into a +`PositiveC0ContractiveResolvent` (`minimalC0Resolvent`). + +The semigroup which that resolvent generates is represented by a sub-Markov kernel semigroup, and +its kernel resolvent is the supremum resolvent again, on every nonnegative measurable observable +(`kernelResolvent_minimalC0Resolvent`): the two potential measures agree on continuous +observables vanishing at infinity, hence everywhere. + +If in addition the shift times the supremum resolvent of the constant observable one is one, the +represented semigroup loses no mass (`isConservative_kernelSemigroup_minimalC0Resolvent`), and +the compactified process started at any point almost surely never reaches the added point +(`ae_exitTime_eq_top_minimalC0Resolvent`). No kernel into the continuous paths of the state +space is produced from that statement. +-/ + +open Filter MeasureTheory ProbabilityTheory Set Topology +open scoped ENNReal NNReal ZeroAtInfty + +noncomputable section + +namespace MarkovProcess + +variable {alpha : Type*} [MetricSpace alpha] [LocallyCompactSpace alpha] + [SecondCountableTopology alpha] [MeasurableSpace alpha] [BorelSpace alpha] + {X : ℕ → Type*} [∀ m, MetricSpace (X m)] [∀ m, LocallyCompactSpace (X m)] + [∀ m, SecondCountableTopology (X m)] [∀ m, MeasurableSpace (X m)] [∀ m, BorelSpace (X m)] + +variable (R : ∀ m, PositiveC0ContractiveResolvent (X m)) (emb : ∀ m, X m → alpha) + +omit [LocallyCompactSpace alpha] [SecondCountableTopology alpha] [MeasurableSpace alpha] + [BorelSpace alpha] in +/-- A continuous observable vanishing at infinity is bounded by its norm. -/ +private theorem abs_le_norm_c0 (f : C₀(alpha, ℝ)) (y : alpha) : |f y| ≤ ‖f‖ := by + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm, ← Real.norm_eq_abs] + exact BoundedContinuousFunction.norm_coe_le_norm f.toBCF y + +section Operator + +variable (T : Semigroup.PositiveShift → C₀(alpha, ℝ) → C₀(alpha, ℝ)) + +/-- **The `C₀` operator of the supremum resolvent** at a positive shift: the value supplied by +the analytic hypothesis `hT`, packaged as a continuous linear map by additivity, real +homogeneity, and the uniform bound `1 / lam`. -/ +def minimalC0Operator (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + (hT : ∀ (nu : Semigroup.PositiveShift) (f : C₀(alpha, ℝ)) (x : alpha), + T nu f x = minimalResolventReal R emb (nu : ℝ) (fun y ↦ f y) x) + (nu : Semigroup.PositiveShift) : C₀(alpha, ℝ) →L[ℝ] C₀(alpha, ℝ) := + LinearMap.mkContinuous + { toFun := T nu + map_add' := fun f g ↦ by + refine DFunLike.ext _ _ fun x ↦ ?_ + rw [hT nu (f + g) x] + have hsum : minimalResolventReal R emb (nu : ℝ) (fun y ↦ (f + g) y) x = + minimalResolventReal R emb (nu : ℝ) (fun y ↦ f y) x + + minimalResolventReal R emb (nu : ℝ) (fun y ↦ g y) x := + minimalResolventReal_add R emb hemb hmono nu.property f.continuous.measurable + g.continuous.measurable (abs_le_norm_c0 f) (abs_le_norm_c0 g) x + rw [hsum, ← hT nu f x, ← hT nu g x] + rfl + map_smul' := fun c f ↦ by + refine DFunLike.ext _ _ fun x ↦ ?_ + rw [hT nu (c • f) x] + have hsmul : minimalResolventReal R emb (nu : ℝ) (fun y ↦ (c • f) y) x = + c * minimalResolventReal R emb (nu : ℝ) (fun y ↦ f y) x := + minimalResolventReal_smul R emb hemb (nu : ℝ) c f.continuous.measurable x + rw [hsmul, ← hT nu f x] + rfl } + (nu : ℝ)⁻¹ fun f ↦ by + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + refine (BoundedContinuousFunction.norm_le + (mul_nonneg (inv_nonneg.mpr nu.property.le) (norm_nonneg f))).2 fun x ↦ ?_ + have hbound : |minimalResolventReal R emb (nu : ℝ) (fun y ↦ f y) x| ≤ ‖f‖ / (nu : ℝ) := + abs_minimalResolventReal_le R emb hemb nu.property (abs_le_norm_c0 f) x + rw [Real.norm_eq_abs] + calc |(T nu f).toBCF x| = |T nu f x| := rfl + _ = |minimalResolventReal R emb (nu : ℝ) (fun y ↦ f y) x| := by rw [hT nu f x] + _ ≤ ‖f‖ / (nu : ℝ) := hbound + _ = (nu : ℝ)⁻¹ * ‖f‖ := by rw [div_eq_inv_mul] + +omit [LocallyCompactSpace alpha] [SecondCountableTopology alpha] in +/-- The bundled minimal `C₀` operator acts by the given family. -/ +@[simp] theorem minimalC0Operator_apply (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + (hT : ∀ (nu : Semigroup.PositiveShift) (f : C₀(alpha, ℝ)) (x : alpha), + T nu f x = minimalResolventReal R emb (nu : ℝ) (fun y ↦ f y) x) + (nu : Semigroup.PositiveShift) (f : C₀(alpha, ℝ)) : + minimalC0Operator R emb T hemb hmono hT nu f = T nu f := rfl + +/-- **The supremum resolvent as a positive `C₀`-contractive resolvent**, from the analytic +hypotheses that its values on `C₀` are again in `C₀` and have dense range. -/ +def minimalC0Resolvent (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + (hT : ∀ (nu : Semigroup.PositiveShift) (f : C₀(alpha, ℝ)) (x : alpha), + T nu f x = minimalResolventReal R emb (nu : ℝ) (fun y ↦ f y) x) + (hdense : ∀ nu, DenseRange (T nu)) : PositiveC0ContractiveResolvent alpha where + toContractiveResolvent := + { operator := minimalC0Operator R emb T hemb hmono hT + resolvent_identity := by + intro a b + refine ContinuousLinearMap.ext fun f ↦ ?_ + refine DFunLike.ext _ _ fun x ↦ ?_ + have hcomp : ∀ c d : Semigroup.PositiveShift, + T c (T d f) x = minimalResolventReal R emb (c : ℝ) + (fun z ↦ minimalResolventReal R emb (d : ℝ) (fun y ↦ f y) z) x := by + intro c d + rw [hT c (T d f) x] + congr 1 + funext z + exact hT d f z + have hgoal : T a f x - T b f x = + ((b : ℝ) - (a : ℝ)) * T a (T b f) x := by + rcases lt_trichotomy (a : ℝ) (b : ℝ) with hab | hab | hab + · have heq := minimalResolventReal_resolventEquation R emb hemb hmono a.property hab + (f := fun y ↦ f y) f.continuous.measurable (abs_le_norm_c0 f) x + rw [hcomp a b, hT a f x, hT b f x, heq] + ring + · have hab' : a = b := Subtype.ext hab + rw [hab'] + ring + · have heq := minimalResolventReal_resolventEquation R emb hemb hmono b.property hab + (f := fun y ↦ f y) f.continuous.measurable (abs_le_norm_c0 f) x + have hcommute := minimalResolventReal_comm R emb hemb hmono b.property a.property + (f := fun y ↦ f y) f.continuous.measurable (abs_le_norm_c0 f) x + rw [hcomp a b, hT a f x, hT b f x, heq, ← hcommute] + ring + simpa using hgoal + opNorm_le_inv := fun nu ↦ + LinearMap.mkContinuous_norm_le _ (inv_nonneg.mpr nu.property.le) _ + denseRange := fun nu ↦ hdense nu } + isPositive := fun nu f hf x ↦ by + change 0 ≤ T nu f x + rw [hT nu f x] + exact minimalResolventReal_nonneg R emb hemb nu.property hf x + +omit [LocallyCompactSpace alpha] [SecondCountableTopology alpha] in +/-- The operator of the minimal `C₀` resolvent is the given family, pointwise. -/ +@[simp] theorem minimalC0Resolvent_operator_apply (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + (hT : ∀ (nu : Semigroup.PositiveShift) (f : C₀(alpha, ℝ)) (x : alpha), + T nu f x = minimalResolventReal R emb (nu : ℝ) (fun y ↦ f y) x) + (hdense : ∀ nu, DenseRange (T nu)) (nu : Semigroup.PositiveShift) (f : C₀(alpha, ℝ)) + (x : alpha) : + (minimalC0Resolvent R emb T hemb hmono hT hdense).toContractiveResolvent.operator nu f x = + minimalResolventReal R emb (nu : ℝ) (fun y ↦ f y) x := + hT nu f x + +end Operator + +section Identification + +variable (T : Semigroup.PositiveShift → C₀(alpha, ℝ) → C₀(alpha, ℝ)) + (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + (hT : ∀ (nu : Semigroup.PositiveShift) (f : C₀(alpha, ℝ)) (x : alpha), + T nu f x = minimalResolventReal R emb (nu : ℝ) (fun y ↦ f y) x) + (hdense : ∀ nu, DenseRange (T nu)) + +omit [MetricSpace alpha] [LocallyCompactSpace alpha] [SecondCountableTopology alpha] + [MeasurableSpace alpha] [BorelSpace alpha] in +private theorem extend_id (g : alpha → ℝ≥0∞) : + Function.extend (id : alpha → alpha) g 0 = g := by + funext y + exact Function.Injective.extend_apply Function.injective_id g 0 y + +/-- **The kernel resolvent of the generated semigroup is the supremum resolvent**, on every +nonnegative measurable observable. The two potential measures agree on continuous observables +vanishing at infinity, and finite Borel measures on a locally compact second-countable metric +space are determined by those. -/ +theorem kernelResolvent_minimalC0Resolvent {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ≥0∞} + (hf : Measurable f) (x : alpha) : + (minimalC0Resolvent R emb T hemb hmono hT hdense).kernelSemigroup.kernelResolvent lam f x = + minimalResolvent R emb lam f x := by + have := (minimalC0Resolvent R emb T hemb hmono hT + hdense).kernelSemigroup.isFiniteMeasure_resolventPotential hlam x + have := isFiniteMeasure_minimalPotential R emb hemb hmono hlam x + have hc0 : ∀ g : C₀(alpha, ℝ), (∀ y, 0 ≤ g y) → + ∫⁻ z, Function.extend (id : alpha → alpha) (fun y ↦ ENNReal.ofReal (g y)) 0 z + ∂(minimalC0Resolvent R emb T hemb hmono hT hdense).kernelSemigroup.resolventPotential + lam x = + ∫⁻ y, ENNReal.ofReal (g y) ∂minimalPotential R emb hemb hmono hlam x := by + intro g hg0 + have hgmeas : Measurable fun y ↦ ENNReal.ofReal (g y) := + ENNReal.measurable_ofReal.comp g.continuous.measurable + rw [extend_id, (minimalC0Resolvent R emb T hemb hmono hT + hdense).kernelSemigroup.lintegral_resolventPotential lam hgmeas x, + lintegral_minimalPotential R emb hemb hmono hlam x hgmeas, + (minimalC0Resolvent R emb T hemb hmono hT hdense).kernelResolvent_ofReal_eq_operator + ⟨lam, hlam⟩ g hg0 x, + minimalC0Resolvent_operator_apply R emb T hemb hmono hT hdense ⟨lam, hlam⟩ g x] + exact ofReal_minimalResolventReal R emb hemb hlam (abs_le_norm_c0 g) hg0 x + have hmain := lintegral_extend_eq_of_forall_zeroAtInfty (i := (id : alpha → alpha)) + MeasurableEmbedding.id + ((minimalC0Resolvent R emb T hemb hmono hT hdense).kernelSemigroup.resolventPotential lam x) + (minimalPotential R emb hemb hmono hlam x) hc0 hf + rwa [extend_id, (minimalC0Resolvent R emb T hemb hmono hT + hdense).kernelSemigroup.lintegral_resolventPotential lam hf x, + lintegral_minimalPotential R emb hemb hmono hlam x hf] at hmain + +end Identification + +section Conservativity + +variable (T : Semigroup.PositiveShift → C₀(alpha, ℝ) → C₀(alpha, ℝ)) + (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + (hT : ∀ (nu : Semigroup.PositiveShift) (f : C₀(alpha, ℝ)) (x : alpha), + T nu f x = minimalResolventReal R emb (nu : ℝ) (fun y ↦ f y) x) + (hdense : ∀ nu, DenseRange (T nu)) + +/-- **Conservativity of the represented semigroup.** If at one positive shift the shift times +the supremum resolvent of the constant observable one is one, the semigroup represented by the +supremum resolvent loses no mass. -/ +theorem isConservative_kernelSemigroup_minimalC0Resolvent {lam : ℝ} (hlam : 0 < lam) + (hone : ∀ x, ENNReal.ofReal lam * minimalResolvent R emb lam (fun _ ↦ 1) x = 1) : + (minimalC0Resolvent R emb T hemb hmono hT hdense).kernelSemigroup.IsConservative := + SubMarkovKernelSemigroup.isConservative_of_kernelResolvent_one _ hlam fun x ↦ by + rw [kernelResolvent_minimalC0Resolvent R emb T hemb hmono hT hdense hlam measurable_const x] + exact hone x + +/-- **The process almost surely never reaches the added point.** Under the same hypothesis, the +compactified process of the supremum resolvent, started at any point, almost surely never leaves +the state space. -/ +theorem ae_exitTime_eq_top_minimalC0Resolvent + (hreg : (minimalC0Resolvent R emb T hemb hmono hT hdense).OnePointRegular) {lam : ℝ} + (hlam : 0 < lam) + (hone : ∀ x, ENNReal.ofReal lam * minimalResolvent R emb lam (fun _ ↦ 1) x = 1) + (x : alpha) : + letI := hreg.metricSpace + letI := hreg.completeSpace + ∀ᵐ omega ∂SubMarkovKernelSemigroup.IsConservative.continuousProcess + (minimalC0Resolvent R emb T hemb hmono hT hdense).onePointKernelSemigroup + (minimalC0Resolvent R emb T hemb hmono hT + hdense).isConservative_onePointKernelSemigroup (x : OnePoint alpha), + ContinuousPath.exitTime (Set.range ((↑) : alpha → OnePoint alpha)) omega = ⊤ := by + refine hreg.ae_exitTime_eq_top hlam x ?_ + rw [kernelResolvent_minimalC0Resolvent R emb T hemb hmono hT hdense hlam measurable_const x] + exact hone x + +end Conservativity + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLinearity.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLinearity.lean new file mode 100644 index 0000000000..9dc9a3b1df --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLinearity.lean @@ -0,0 +1,152 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal + +/-! +# Linearity of the transported local resolvents and of their supremum + +The transported local resolvents of `Killed/GluingMinimal.lean` inherit additivity and +homogeneity from the kernel resolvents they extend (`localResolvent_add`, +`localResolvent_const_mul`). Homogeneity passes to the supremum without further hypotheses +(`minimalResolvent_const_mul`), while additivity passes to it exactly when the transported +resolvents are monotone in the index, so that the two suprema can be added term by term +(`minimalResolvent_add`). + +A uniformly bounded observable has a uniformly bounded supremum resolvent: at the shift `lam` +the bound is the bound of the observable divided by `lam` +(`minimalResolvent_le_of_le_const`), so the value is finite (`minimalResolvent_ne_top`). This +is the estimate which makes the real-valued form of the supremum resolvent well defined. + +The transported resolvents at two shifts commute (`localResolvent_comm`), and so do their +suprema once the family is monotone in the index (`minimalResolvent_comm`). + +Nothing here uses the part-process identity; monotonicity in the index is a bare hypothesis. +-/ + +open Filter MeasureTheory ProbabilityTheory Set Topology +open scoped ENNReal NNReal ZeroAtInfty + +noncomputable section + +namespace MarkovProcess + +variable {alpha : Type*} [MeasurableSpace alpha] {X : ℕ → Type*} + [∀ m, MetricSpace (X m)] [∀ m, LocallyCompactSpace (X m)] + [∀ m, SecondCountableTopology (X m)] [∀ m, MeasurableSpace (X m)] [∀ m, BorelSpace (X m)] + +variable (R : ∀ m, PositiveC0ContractiveResolvent (X m)) (emb : ∀ m, X m → alpha) + +/-- The transported resolvent is additive on measurable observables. -/ +theorem localResolvent_add {m : ℕ} (hemb : MeasurableEmbedding (emb m)) (lam : ℝ) + {f g : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + localResolvent R emb m lam (fun y ↦ f y + g y) x = + localResolvent R emb m lam f x + localResolvent R emb m lam g x := by + by_cases hx : x ∈ Set.range (emb m) + · obtain ⟨y, rfl⟩ := hx + rw [localResolvent_apply R emb hemb.injective lam _ y, + localResolvent_apply R emb hemb.injective lam f y, + localResolvent_apply R emb hemb.injective lam g y] + exact (R m).kernelSemigroup.kernelResolvent_add lam (hf.comp hemb.measurable) y + · rw [localResolvent_of_notMem R emb m lam _ hx, localResolvent_of_notMem R emb m lam f hx, + localResolvent_of_notMem R emb m lam g hx, add_zero] + +/-- The transported resolvent is homogeneous under multiplication by an extended-real +constant. -/ +theorem localResolvent_const_mul {m : ℕ} (hemb : MeasurableEmbedding (emb m)) (lam : ℝ) + (c : ℝ≥0∞) {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + localResolvent R emb m lam (fun y ↦ c * f y) x = c * localResolvent R emb m lam f x := by + by_cases hx : x ∈ Set.range (emb m) + · obtain ⟨y, rfl⟩ := hx + rw [localResolvent_apply R emb hemb.injective lam _ y, + localResolvent_apply R emb hemb.injective lam f y] + exact (R m).kernelSemigroup.kernelResolvent_const_mul lam c (hf.comp hemb.measurable) y + · rw [localResolvent_of_notMem R emb m lam _ hx, localResolvent_of_notMem R emb m lam f hx, + mul_zero] + +/-- **The supremum resolvent is additive** on measurable observables, as soon as the transported +resolvents are monotone in the index: the suprema of two monotone families add term by term. -/ +theorem minimalResolvent_add (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam : ℝ} (hlam : 0 < lam) {f g : alpha → ℝ≥0∞} (hf : Measurable f) (hg : Measurable g) + (x : alpha) : + minimalResolvent R emb lam (fun y ↦ f y + g y) x = + minimalResolvent R emb lam f x + minimalResolvent R emb lam g x := by + unfold minimalResolvent + rw [ENNReal.iSup_add_iSup_of_monotone (hmono lam hlam hf x) (hmono lam hlam hg x)] + exact iSup_congr fun m ↦ localResolvent_add R emb (hemb m) lam hf x + +/-- The supremum resolvent is homogeneous under multiplication by an extended-real constant. -/ +theorem minimalResolvent_const_mul (hemb : ∀ m, MeasurableEmbedding (emb m)) (lam : ℝ) + (c : ℝ≥0∞) {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + minimalResolvent R emb lam (fun y ↦ c * f y) x = c * minimalResolvent R emb lam f x := by + unfold minimalResolvent + rw [ENNReal.mul_iSup] + exact iSup_congr fun m ↦ localResolvent_const_mul R emb (hemb m) lam c hf x + +/-- **The uniform bound.** At a positive shift, a uniform bound for the observable divided by +the shift is a uniform bound for the supremum resolvent. -/ +theorem minimalResolvent_le_of_le_const (hemb : ∀ m, MeasurableEmbedding (emb m)) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ≥0∞} {c : ℝ≥0∞} (hfc : ∀ y, f y ≤ c) + (x : alpha) : + minimalResolvent R emb lam f x ≤ c * ENNReal.ofReal lam⁻¹ := by + calc minimalResolvent R emb lam f x + ≤ minimalResolvent R emb lam (fun _ ↦ c * 1) x := + minimalResolvent_mono_of_le R emb (fun m ↦ (hemb m).injective) lam + (fun y ↦ by simpa using hfc y) x + _ = c * minimalResolvent R emb lam (fun _ ↦ 1) x := + minimalResolvent_const_mul R emb hemb lam c measurable_const x + _ ≤ c * ENNReal.ofReal lam⁻¹ := + mul_le_mul' le_rfl (minimalResolvent_one_le R emb (fun m ↦ (hemb m).injective) hlam x) + +/-- At a positive shift the supremum resolvent of a uniformly bounded observable is finite. -/ +theorem minimalResolvent_ne_top (hemb : ∀ m, MeasurableEmbedding (emb m)) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ≥0∞} {c : ℝ≥0∞} (hc : c ≠ ⊤) + (hfc : ∀ y, f y ≤ c) (x : alpha) : + minimalResolvent R emb lam f x ≠ ⊤ := + ne_top_of_le_ne_top (ENNReal.mul_ne_top hc ENNReal.ofReal_ne_top) + (minimalResolvent_le_of_le_const R emb hemb hlam hfc x) + +/-- The transported resolvents at two shifts commute. -/ +theorem localResolvent_comm {m : ℕ} (hemb : MeasurableEmbedding (emb m)) (lam mu : ℝ) + {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + localResolvent R emb m lam (localResolvent R emb m mu f) x = + localResolvent R emb m mu (localResolvent R emb m lam f) x := by + by_cases hx : x ∈ Set.range (emb m) + · obtain ⟨y, rfl⟩ := hx + have hinner : ∀ nu : ℝ, (fun z ↦ localResolvent R emb m nu f (emb m z)) = + (R m).kernelSemigroup.kernelResolvent nu fun z ↦ f (emb m z) := by + intro nu + funext z + exact localResolvent_apply R emb hemb.injective nu f z + rw [localResolvent_apply R emb hemb.injective lam _ y, + localResolvent_apply R emb hemb.injective mu _ y, hinner, hinner] + exact (R m).kernelSemigroup.kernelResolvent_comm lam mu (hf.comp hemb.measurable) y + · rw [localResolvent_of_notMem R emb m lam _ hx, localResolvent_of_notMem R emb m mu _ hx] + +/-- **The supremum resolvents at two shifts commute**, as soon as the transported resolvents are +monotone in the index: each composition is the supremum of the commuting compositions along the +diagonal. -/ +theorem minimalResolvent_comm (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam mu : ℝ} (hlam : 0 < lam) (hmu : 0 < mu) {f : alpha → ℝ≥0∞} (hf : Measurable f) + (x : alpha) : + minimalResolvent R emb lam (minimalResolvent R emb mu f) x = + minimalResolvent R emb mu (minimalResolvent R emb lam f) x := by + rw [minimalResolvent_comp_eq_iSup R emb hemb hmono hlam hmu hf x, + minimalResolvent_comp_eq_iSup R emb hemb hmono hmu hlam hf x] + exact iSup_congr fun n ↦ localResolvent_comm R emb (hemb n) lam mu hf x + +/-- At a positive shift the supremum resolvent of the zero observable vanishes. -/ +theorem minimalResolvent_zero (hemb : ∀ m, MeasurableEmbedding (emb m)) {lam : ℝ} + (hlam : 0 < lam) (x : alpha) : + minimalResolvent R emb lam (fun _ ↦ 0) x = 0 := by + refine le_antisymm ?_ zero_le + simpa using minimalResolvent_le_of_le_const R emb hemb hlam + (f := fun _ : alpha ↦ (0 : ℝ≥0∞)) (c := 0) (fun _ ↦ le_rfl) x + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLocal.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLocal.lean new file mode 100644 index 0000000000..48fe337fe4 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLocal.lean @@ -0,0 +1,287 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer + +/-! +# Comparing two local resolvents through the part-process identity + +Two positive `C₀`-contractive resolvents on nested locally compact state spaces are compared here +through the process of the larger one. The data are an open embedding `iota : X₀ → X₁`, the +regularity data (`PositiveC0ContractiveResolvent.OnePointRegular`) which the continuous-path +process of the compactification of `X₁` is formed from, and the part-process identity: the +resolvent of the process of `X₁` killed at the exit from the image of `X₀` is the resolvent +supplied on `X₀`. + +The conclusion (`PositiveC0ContractiveResolvent.kernelResolvent_le_of_partProcess`) is that the +kernel resolvent of the smaller space is dominated by the kernel resolvent of the larger one: a +path leaves the smaller domain no later, so it accumulates less. The identity is supplied for +nonnegative continuous observables vanishing at infinity, which is the form an analytic +construction produces, and is upgraded to all nonnegative measurable observables through the +potential measures. + +The regularity data are an explicit hypothesis: positivity, contractivity and the resolvent +identity do not by themselves give the compactified semigroup a continuous-path process. +-/ + +open Filter MeasureTheory ProbabilityTheory Set Topology +open scoped ENNReal NNReal ZeroAtInfty + +noncomputable section + +namespace MarkovProcess.PositiveC0ContractiveResolvent + +open MarkovProcess.SubMarkovKernelSemigroup + +variable {X : Type*} [MetricSpace X] [LocallyCompactSpace X] [SecondCountableTopology X] + [MeasurableSpace X] [BorelSpace X] + +/-- Regularity data for the compactified process of a positive `C₀`-contractive resolvent: a +positive `1`-Lipschitz exhaustion function with compact positive superlevel sets, together with +the Kolmogorov regularity of the compactified kernel semigroup in the metric which that function +determines. The continuous-path process of the compactified semigroup is formed from exactly +these data. -/ +structure OnePointRegular (R : PositiveC0ContractiveResolvent X) where + /-- The exhaustion function on the live space. -/ + rho : X → ℝ + /-- The exhaustion function is continuous. -/ + continuous_rho : Continuous rho + /-- The exhaustion function is positive. -/ + rho_pos : ∀ x, 0 < rho x + /-- The exhaustion function is `1`-Lipschitz. -/ + lipschitz_rho : LipschitzWith 1 rho + /-- The positive superlevel sets of the exhaustion function are compact. -/ + isCompact_superlevel : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x} + /-- The compactified kernel semigroup is Kolmogorov regular in the exhaustion metric. -/ + kolmogorovRegular : + letI := OnePoint.exhaustionMetricSpace rho continuous_rho rho_pos lipschitz_rho + isCompact_superlevel + letI : CompleteSpace (OnePoint X) := + completeSpace_of_isComplete_univ isCompact_univ.isComplete + R.onePointKernelSemigroup.KolmogorovRegular R.isConservative_onePointKernelSemigroup + +namespace OnePointRegular + +variable {R : PositiveC0ContractiveResolvent X} + +/-- The metric on the compactification determined by the exhaustion function. -/ +noncomputable def metricSpace (h : R.OnePointRegular) : MetricSpace (OnePoint X) := + OnePoint.exhaustionMetricSpace h.rho h.continuous_rho h.rho_pos h.lipschitz_rho + h.isCompact_superlevel + +/-- Typeclass-search cache: lets `letI := h.metricSpace` discharge an ambient +`CompactSpace (OnePoint X)` obligation without re-deriving compactness at each call site (the +exhaustion metric's topology coincides with the canonical one-point topology, which is always +compact). -/ +private instance instCompactSpaceMetricSpace (h : R.OnePointRegular) : + @CompactSpace (OnePoint X) h.metricSpace.toPseudoMetricSpace.toUniformSpace.toTopologicalSpace := by + unfold OnePointRegular.metricSpace + rw [OnePoint.exhaustionMetricSpace_toTopologicalSpace] + infer_instance + +/-- Typeclass-search cache, in the same spirit as `instCompactSpaceMetricSpace`: lets +`letI := h.metricSpace` discharge an ambient `BorelSpace (OnePoint X)` obligation. -/ +private instance instBorelSpaceMetricSpace (h : R.OnePointRegular) : + @BorelSpace (OnePoint X) h.metricSpace.toPseudoMetricSpace.toUniformSpace.toTopologicalSpace + OnePoint.instMeasurableSpace := by + unfold OnePointRegular.metricSpace + rw [OnePoint.exhaustionMetricSpace_toTopologicalSpace] + exact OnePoint.instBorelSpace + +/-- Typeclass-search cache, in the same spirit as `instCompactSpaceMetricSpace`: lets +`letI := h.metricSpace` discharge an ambient `SecondCountableTopology (OnePoint X)` +obligation. -/ +private instance instSecondCountableTopologyMetricSpace (h : R.OnePointRegular) : + @SecondCountableTopology (OnePoint X) + h.metricSpace.toPseudoMetricSpace.toUniformSpace.toTopologicalSpace := by + unfold OnePointRegular.metricSpace + rw [OnePoint.exhaustionMetricSpace_toTopologicalSpace] + exact OnePoint.instSecondCountableTopology + +/-- The compactification is complete in the exhaustion metric. -/ +theorem completeSpace (h : R.OnePointRegular) : + letI := h.metricSpace + CompleteSpace (OnePoint X) := + letI := h.metricSpace + completeSpace_of_isComplete_univ isCompact_univ.isComplete + +/-- **The killed resolvent of the compactified process is the kernel resolvent.** Killing the +process of the compactification at the exit from the live space returns the sub-Markov semigroup +originally represented by the resolvent. -/ +theorem killedResolvent_live_eq_kernelResolvent (h : R.OnePointRegular) (lam : ℝ) + {f : X → ℝ≥0∞} (hf : Measurable f) (x : X) : + letI := h.metricSpace + letI := h.completeSpace + IsConservative.killedResolvent R.onePointKernelSemigroup + R.isConservative_onePointKernelSemigroup + (Set.range ((↑) : X → OnePoint X)) OnePoint.isOpen_range_coe lam + (onePointLiveExtension f) (x : OnePoint X) = + R.kernelSemigroup.kernelResolvent lam f x := + R.killedResolvent_onePointLive_eq_kernelResolvent h.rho h.continuous_rho h.rho_pos + h.lipschitz_rho h.isCompact_superlevel h.kolmogorovRegular lam hf x + +end OnePointRegular + +/-- For a nonnegative observable vanishing at infinity, the kernel resolvent of the represented +semigroup is the analytic resolvent originally supplied. -/ +theorem kernelResolvent_ofReal_eq_operator (R : PositiveC0ContractiveResolvent X) + (mu : Semigroup.PositiveShift) (f : C₀(X, ℝ)) (hf0 : ∀ y, 0 ≤ f y) (x : X) : + R.kernelSemigroup.kernelResolvent (mu : ℝ) (fun y ↦ ENNReal.ofReal (f y)) x = + ENNReal.ofReal (R.toContractiveResolvent.operator mu f x) := by + rw [R.isFellerKernelSemigroup_kernelSemigroup.kernelResolvent_ofReal_eq_resolvent mu f hf0 x, + R.resolvent_c0Semigroup_kernelSemigroup] + +section Embedding + +variable {X₀ X₁ : Type*} + +/-- The embedding of a smaller live space into the compactification of a larger one. -/ +def compactifiedEmbedding (iota : X₀ → X₁) (y : X₀) : OnePoint X₁ := ((iota y : X₁) : OnePoint X₁) + +/-- The embedding of a smaller live space into the compactification, unfolded. -/ +@[simp] theorem compactifiedEmbedding_apply (iota : X₀ → X₁) (y : X₀) : + compactifiedEmbedding iota y = ((iota y : X₁) : OnePoint X₁) := rfl + +/-- The embedding of a smaller live space into the compactification of a larger one is +injective. -/ +theorem injective_compactifiedEmbedding {iota : X₀ → X₁} (hiota : Function.Injective iota) : + Function.Injective (compactifiedEmbedding iota) := + OnePoint.coe_injective.comp hiota + +/-- The image of the smaller live space is contained in the live part of the compactification. -/ +theorem range_compactifiedEmbedding_subset (iota : X₀ → X₁) : + Set.range (compactifiedEmbedding iota) ⊆ Set.range ((↑) : X₁ → OnePoint X₁) := by + rintro _ ⟨y, rfl⟩ + exact ⟨iota y, rfl⟩ + +/-- An observable of the smaller space, extended by zero off its image in the compactification, +is dominated by the observable of the larger space extended by zero at infinity. -/ +theorem extend_compactifiedEmbedding_le (iota : X₀ → X₁) (hiota : Function.Injective iota) + (g : X₁ → ℝ≥0∞) : + Function.extend (compactifiedEmbedding iota) (fun z ↦ g (iota z)) 0 ≤ + onePointLiveExtension g := by + intro w + by_cases hw : w ∈ Set.range (compactifiedEmbedding iota) + · obtain ⟨z, rfl⟩ := hw + rw [(injective_compactifiedEmbedding hiota).extend_apply] + exact le_of_eq rfl + · rw [Function.extend_apply' _ _ _ fun hmem ↦ hw hmem] + exact zero_le + +end Embedding + +section EmbeddingTopology + +variable {X₀ X₁ : Type*} [TopologicalSpace X₀] [TopologicalSpace X₁] + +/-- The embedding of a smaller live space into the compactification of a larger one is an open +embedding. -/ +theorem isOpenEmbedding_compactifiedEmbedding {iota : X₀ → X₁} (hiota : IsOpenEmbedding iota) : + IsOpenEmbedding (compactifiedEmbedding iota) := + OnePoint.isOpenEmbedding_coe.comp hiota + +/-- The image of a smaller live space in the compactification of a larger one is open. -/ +theorem isOpen_range_compactifiedEmbedding {iota : X₀ → X₁} (hiota : IsOpenEmbedding iota) : + IsOpen (Set.range (compactifiedEmbedding iota)) := + (isOpenEmbedding_compactifiedEmbedding hiota).isOpen_range + +end EmbeddingTopology + +section Comparison + +variable {X₀ X₁ : Type*} + [MetricSpace X₀] [LocallyCompactSpace X₀] [SecondCountableTopology X₀] + [MeasurableSpace X₀] [BorelSpace X₀] + [MetricSpace X₁] [LocallyCompactSpace X₁] [SecondCountableTopology X₁] + [MeasurableSpace X₁] [BorelSpace X₁] + +/-- **The part-process identity.** The resolvent of the compactified process of `R₁`, killed at +the exit from the image of the smaller live space, is the analytic resolvent supplied on that +space, tested on nonnegative observables vanishing at infinity and extended by zero off the +image. -/ +def IsPartProcess (R₀ : PositiveC0ContractiveResolvent X₀) + (R₁ : PositiveC0ContractiveResolvent X₁) (h₁ : R₁.OnePointRegular) + {iota : X₀ → X₁} (hiota : IsOpenEmbedding iota) : Prop := + ∀ (mu : Semigroup.PositiveShift) (f : C₀(X₀, ℝ)), (∀ z, 0 ≤ f z) → ∀ y : X₀, + letI := h₁.metricSpace + letI := h₁.completeSpace + IsConservative.killedResolvent R₁.onePointKernelSemigroup + R₁.isConservative_onePointKernelSemigroup + (Set.range (compactifiedEmbedding iota)) + (isOpen_range_compactifiedEmbedding hiota) (mu : ℝ) + (Function.extend (compactifiedEmbedding iota) (fun z ↦ ENNReal.ofReal (f z)) 0) + (compactifiedEmbedding iota y) = + ENNReal.ofReal (R₀.toContractiveResolvent.operator mu f y) + +/-- **Domination of the local kernel resolvents.** If the resolvent of the compactified process +of `R₁` killed at the exit from the image of `X₀` is the resolvent `R₀`, then the kernel resolvent +of `R₀` is dominated by the kernel resolvent of `R₁`: leaving the smaller domain kills the path +earlier, so it accumulates less. -/ +theorem kernelResolvent_le_of_partProcess (R₀ : PositiveC0ContractiveResolvent X₀) + (R₁ : PositiveC0ContractiveResolvent X₁) (h₁ : R₁.OnePointRegular) + {iota : X₀ → X₁} (hiota : IsOpenEmbedding iota) + (hcompat : IsPartProcess R₀ R₁ h₁ hiota) + {lam : ℝ} (hlam : 0 < lam) {g : X₁ → ℝ≥0∞} (hg : Measurable g) (y : X₀) : + R₀.kernelSemigroup.kernelResolvent lam (fun z ↦ g (iota z)) y ≤ + R₁.kernelSemigroup.kernelResolvent lam g (iota y) := by + let := h₁.metricSpace + let := h₁.completeSpace + have hj : IsOpenEmbedding (compactifiedEmbedding iota) := + isOpenEmbedding_compactifiedEmbedding hiota + have hjm : MeasurableEmbedding (compactifiedEmbedding iota) := hj.measurableEmbedding + have hjopen : IsOpen (Set.range (compactifiedEmbedding iota)) := + isOpen_range_compactifiedEmbedding hiota + have hgi : Measurable fun z : X₀ ↦ g (iota z) := hg.comp hiota.continuous.measurable + have := IsConservative.isFiniteMeasure_killedPotential R₁.onePointKernelSemigroup + R₁.isConservative_onePointKernelSemigroup (Set.range (compactifiedEmbedding iota)) + hjopen hlam (compactifiedEmbedding iota y) + have := R₀.kernelSemigroup.isFiniteMeasure_resolventPotential hlam y + have hc0 : ∀ f : C₀(X₀, ℝ), (∀ z, 0 ≤ f z) → + ∫⁻ w, Function.extend (compactifiedEmbedding iota) + (fun z ↦ ENNReal.ofReal (f z)) 0 w + ∂IsConservative.killedPotential R₁.onePointKernelSemigroup + R₁.isConservative_onePointKernelSemigroup (Set.range (compactifiedEmbedding iota)) + hjopen lam (compactifiedEmbedding iota y) = + ∫⁻ z, ENNReal.ofReal (f z) ∂R₀.kernelSemigroup.resolventPotential lam y := by + intro f hf0 + have hfmeas : Measurable fun z : X₀ ↦ ENNReal.ofReal (f z) := + ENNReal.measurable_ofReal.comp f.continuous.measurable + have hextmeas : Measurable (Function.extend (compactifiedEmbedding iota) + (fun z ↦ ENNReal.ofReal (f z)) (0 : OnePoint X₁ → ℝ≥0∞)) := + hjm.measurable_extend hfmeas measurable_const + rw [IsConservative.lintegral_killedPotential R₁.onePointKernelSemigroup + R₁.isConservative_onePointKernelSemigroup (Set.range (compactifiedEmbedding iota)) + hjopen lam hextmeas (compactifiedEmbedding iota y), + R₀.kernelSemigroup.lintegral_resolventPotential lam hfmeas y, + hcompat ⟨lam, hlam⟩ f hf0 y, + ← R₀.kernelResolvent_ofReal_eq_operator ⟨lam, hlam⟩ f hf0 y] + have hgextmeas : Measurable (Function.extend (compactifiedEmbedding iota) + (fun z ↦ g (iota z)) (0 : OnePoint X₁ → ℝ≥0∞)) := + hjm.measurable_extend hgi measurable_const + have hstep : IsConservative.killedResolvent R₁.onePointKernelSemigroup + R₁.isConservative_onePointKernelSemigroup (Set.range (compactifiedEmbedding iota)) + hjopen lam + (Function.extend (compactifiedEmbedding iota) (fun z ↦ g (iota z)) 0) + (compactifiedEmbedding iota y) = + R₀.kernelSemigroup.kernelResolvent lam (fun z ↦ g (iota z)) y := by + have h := lintegral_extend_eq_of_forall_zeroAtInfty hjm + (IsConservative.killedPotential R₁.onePointKernelSemigroup + R₁.isConservative_onePointKernelSemigroup (Set.range (compactifiedEmbedding iota)) + hjopen lam (compactifiedEmbedding iota y)) + (R₀.kernelSemigroup.resolventPotential lam y) hc0 hgi + rwa [IsConservative.lintegral_killedPotential R₁.onePointKernelSemigroup + R₁.isConservative_onePointKernelSemigroup (Set.range (compactifiedEmbedding iota)) + hjopen lam hgextmeas (compactifiedEmbedding iota y), + R₀.kernelSemigroup.lintegral_resolventPotential lam hgi y] at h + rw [← hstep, ← h₁.killedResolvent_live_eq_kernelResolvent lam hg (iota y)] + exact IsConservative.killedResolvent_mono R₁.onePointKernelSemigroup + R₁.isConservative_onePointKernelSemigroup (Set.range (compactifiedEmbedding iota)) + hjopen OnePoint.isOpen_range_coe (range_compactifiedEmbedding_subset iota) lam + (extend_compactifiedEmbedding_le iota hiota.injective g) (compactifiedEmbedding iota y) + +end Comparison + +end MarkovProcess.PositiveC0ContractiveResolvent diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMeasure.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMeasure.lean new file mode 100644 index 0000000000..783148d627 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMeasure.lean @@ -0,0 +1,157 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity + +/-! +# The potential measure of the supremum resolvent + +Additivity and continuity along monotone limits make the supremum resolvent countably additive +on measurable observables (`minimalResolvent_tsum`), so at a positive shift it is the integral +against a finite measure on the state space, the potential measure `minimalPotential` +(`lintegral_minimalPotential`, `isFiniteMeasure_minimalPotential`). + +This is the form in which the supremum resolvent is compared with the kernel resolvent of a +transition semigroup: an identity tested on continuous observables vanishing at infinity extends +to all nonnegative measurable observables through the two potential measures. + +Monotonicity of the transported resolvents in the index is a bare hypothesis throughout. +-/ + +open Filter MeasureTheory ProbabilityTheory Set +open scoped ENNReal NNReal + +noncomputable section + +namespace MarkovProcess + +variable {alpha : Type*} [MeasurableSpace alpha] {X : ℕ → Type*} + [∀ m, MetricSpace (X m)] [∀ m, LocallyCompactSpace (X m)] + [∀ m, SecondCountableTopology (X m)] [∀ m, MeasurableSpace (X m)] [∀ m, BorelSpace (X m)] + +variable (R : ∀ m, PositiveC0ContractiveResolvent (X m)) (emb : ∀ m, X m → alpha) + +/-- **The supremum resolvent is countably additive** on measurable observables: finite additivity +and continuity along monotone limits give the sum of a series. -/ +theorem minimalResolvent_tsum (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam : ℝ} (hlam : 0 < lam) {u : ℕ → alpha → ℝ≥0∞} (hu : ∀ i, Measurable (u i)) + (x : alpha) : + minimalResolvent R emb lam (fun y ↦ ∑' i, u i y) x = + ∑' i, minimalResolvent R emb lam (u i) x := by + have hpartial : ∀ N, Measurable fun y ↦ ∑ i ∈ Finset.range N, u i y := fun N ↦ + Finset.measurable_sum _ fun i _ ↦ hu i + have hpartialMono : Monotone fun N ↦ fun y ↦ ∑ i ∈ Finset.range N, u i y := by + intro a b hab y + have hsub : Finset.range a ⊆ Finset.range b := Finset.range_subset_range.2 hab + exact Finset.sum_le_sum_of_subset hsub + have hfinite : ∀ N, minimalResolvent R emb lam (fun y ↦ ∑ i ∈ Finset.range N, u i y) x = + ∑ i ∈ Finset.range N, minimalResolvent R emb lam (u i) x := by + intro N + induction N with + | zero => simpa using minimalResolvent_zero R emb hemb hlam x + | succ N ih => + have hsplit : (fun y ↦ ∑ i ∈ Finset.range (N + 1), u i y) = + fun y ↦ (∑ i ∈ Finset.range N, u i y) + u N y := by + funext y + rw [Finset.sum_range_succ] + rw [hsplit, minimalResolvent_add R emb hemb hmono hlam (hpartial N) (hu N) x, ih, + Finset.sum_range_succ] + have hseries : (fun y ↦ ∑' i, u i y) = fun y ↦ ⨆ N, ∑ i ∈ Finset.range N, u i y := by + funext y + exact ENNReal.tsum_eq_iSup_nat + rw [hseries, minimalResolvent_iSup R emb hemb lam hpartial hpartialMono x, + ENNReal.tsum_eq_iSup_nat] + exact iSup_congr hfinite + +omit [MeasurableSpace alpha] in +/-- The indicator of a countable disjoint union is the sum of the indicators. -/ +private theorem tsum_indicator_one {S : ℕ → Set alpha} + (hdisj : Pairwise (Function.onFun Disjoint S)) (y : alpha) : + (⋃ i, S i).indicator (fun _ ↦ (1 : ℝ≥0∞)) y = + ∑' i, (S i).indicator (fun _ ↦ (1 : ℝ≥0∞)) y := by + by_cases hy : y ∈ ⋃ i, S i + · obtain ⟨j, hj⟩ := Set.mem_iUnion.mp hy + have hzero : ∀ i, i ≠ j → (S i).indicator (fun _ ↦ (1 : ℝ≥0∞)) y = 0 := by + intro i hij + exact Set.indicator_of_notMem + (fun hmem ↦ Set.disjoint_left.mp (hdisj hij) hmem hj) _ + rw [Set.indicator_of_mem hy, tsum_eq_single j hzero, Set.indicator_of_mem hj] + · have hzero : ∀ i, (S i).indicator (fun _ ↦ (1 : ℝ≥0∞)) y = 0 := fun i ↦ + Set.indicator_of_notMem (fun hmem ↦ hy (Set.mem_iUnion.mpr ⟨i, hmem⟩)) _ + rw [Set.indicator_of_notMem hy] + simp only [hzero, tsum_zero] + +/-- **The potential measure of the supremum resolvent** at a positive shift: the measure whose +value on a measurable set is the supremum resolvent of its indicator. -/ +def minimalPotential (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam : ℝ} (hlam : 0 < lam) (x : alpha) : Measure alpha := + Measure.ofMeasurable + (fun S _ ↦ minimalResolvent R emb lam (S.indicator fun _ ↦ 1) x) + (by simpa using minimalResolvent_zero R emb hemb hlam x) + (fun {S} hS hdisj ↦ by + have hindicator : (⋃ i, S i).indicator (fun _ ↦ (1 : ℝ≥0∞)) = + fun y ↦ ∑' i, (S i).indicator (fun _ ↦ (1 : ℝ≥0∞)) y := by + funext y + exact tsum_indicator_one hdisj y + rw [hindicator, + minimalResolvent_tsum R emb hemb hmono hlam + (fun i ↦ measurable_const.indicator (hS i)) x]) + +/-- The potential measure of a measurable set is the supremum resolvent of its indicator. -/ +theorem minimalPotential_apply (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam : ℝ} (hlam : 0 < lam) (x : alpha) {S : Set alpha} (hS : MeasurableSet S) : + minimalPotential R emb hemb hmono hlam x S = + minimalResolvent R emb lam (S.indicator fun _ ↦ 1) x := + Measure.ofMeasurable_apply S hS + +/-- **The supremum resolvent is integration against its potential measure**, on every +nonnegative measurable observable. -/ +theorem lintegral_minimalPotential (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam : ℝ} (hlam : 0 < lam) (x : alpha) {f : alpha → ℝ≥0∞} (hf : Measurable f) : + ∫⁻ y, f y ∂minimalPotential R emb hemb hmono hlam x = minimalResolvent R emb lam f x := by + refine Measurable.ennreal_induction + (motive := fun g ↦ ∫⁻ y, g y ∂minimalPotential R emb hemb hmono hlam x = + minimalResolvent R emb lam g x) ?_ ?_ ?_ hf + · intro c S hS + have hconst : (S.indicator fun _ ↦ c) = fun y ↦ c * (S.indicator fun _ ↦ (1 : ℝ≥0∞)) y := by + funext y + by_cases hy : y ∈ S + · rw [Set.indicator_of_mem hy, Set.indicator_of_mem hy, mul_one] + · rw [Set.indicator_of_notMem hy, Set.indicator_of_notMem hy, mul_zero] + rw [lintegral_indicator_const hS, minimalPotential_apply R emb hemb hmono hlam x hS, + hconst, minimalResolvent_const_mul R emb hemb lam c + (measurable_const.indicator hS) x] + · intro g h _hdisj hg hh ihg ihh + have hlhs : ∫⁻ y, (g + h) y ∂minimalPotential R emb hemb hmono hlam x = + ∫⁻ y, g y ∂minimalPotential R emb hemb hmono hlam x + + ∫⁻ y, h y ∂minimalPotential R emb hemb hmono hlam x := by + simp only [Pi.add_apply] + exact lintegral_add_left hg _ + rw [hlhs, ihg, ihh] + exact (minimalResolvent_add R emb hemb hmono hlam hg hh x).symm + · intro g hg hgmono ih + rw [lintegral_iSup hg hgmono, minimalResolvent_iSup R emb hemb lam hg hgmono x] + exact iSup_congr ih + +/-- The potential measure is finite at a positive shift, with mass at most `1 / lam`. -/ +theorem isFiniteMeasure_minimalPotential (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam : ℝ} (hlam : 0 < lam) (x : alpha) : + IsFiniteMeasure (minimalPotential R emb hemb hmono hlam x) := by + refine ⟨?_⟩ + rw [minimalPotential_apply R emb hemb hmono hlam x MeasurableSet.univ, Set.indicator_univ] + exact lt_of_le_of_lt + (minimalResolvent_one_le R emb (fun m ↦ (hemb m).injective) hlam x) ENNReal.ofReal_lt_top + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMinimal.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMinimal.lean new file mode 100644 index 0000000000..35975978d4 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMinimal.lean @@ -0,0 +1,343 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation + +/-! +# The supremum resolvent (the minimal process of Blumenthal--Getoor, in name only) + +A family of positive `C₀`-contractive resolvents `R m` on local state spaces `X m`, embedded as +an increasing family of open subsets of an ambient measurable space, is glued here at the level +of resolvents. Each `R m` is transported to the ambient space by extending its kernel resolvent +by zero off the `m`-th domain (`localResolvent`). Under the part-process identity of +`Killed/GluingLocal.lean` -- the resolvent of the compactified process of `R (m+1)`, killed at +the exit from the image of `X m`, is `R m` -- the transported resolvents increase with `m` +(`localResolvent_le_succ`), because a path leaves the smaller domain no later and therefore +accumulates less. Their supremum is `minimalResolvent`. + +The supremum is monotone in the observable, measurable in the starting point, and sub-Markov at +every positive shift: `lam` times its value on the constant observable one is at most one +(`ofReal_mul_minimalResolvent_one_le`). It satisfies the resolvent equation as soon as the +transported resolvents are monotone in `m` +(`minimalResolvent_resolventEquation_of_monotone`, by monotone convergence from the resolvent +equation of each member); the part-process identity enters only through that monotonicity +(`minimalResolvent_resolventEquation`). + +No minimality property among resolvent families is asserted here. The declaration names +keep the word `minimal` because the object is the resolvent of Blumenthal--Getoor's minimal +process, but that is a name and not a claim. + +The regularity data of each compactification are an explicit hypothesis throughout: positivity, +contractivity and the resolvent identity do not by themselves give a compactified semigroup a +continuous-path process. + +No transition semigroup, no process on the ambient space, and no conservativity are constructed +here. +-/ + +open Filter MeasureTheory ProbabilityTheory Set Topology +open scoped ENNReal NNReal ZeroAtInfty + +noncomputable section + +namespace MarkovProcess + +variable {alpha : Type*} [MeasurableSpace alpha] {X : ℕ → Type*} + [∀ m, MetricSpace (X m)] [∀ m, LocallyCompactSpace (X m)] + [∀ m, SecondCountableTopology (X m)] [∀ m, MeasurableSpace (X m)] [∀ m, BorelSpace (X m)] + +variable (R : ∀ m, PositiveC0ContractiveResolvent (X m)) (emb : ∀ m, X m → alpha) + +/-- The kernel resolvent of the `m`-th local resolvent, transported to the ambient space and +extended by zero off the `m`-th local domain. -/ +noncomputable def localResolvent (m : ℕ) (lam : ℝ) (f : alpha → ℝ≥0∞) : alpha → ℝ≥0∞ := + Function.extend (emb m) + (fun y ↦ (R m).kernelSemigroup.kernelResolvent lam (fun z ↦ f (emb m z)) y) 0 + +omit [MeasurableSpace alpha] in +/-- Inside the `m`-th local domain the transported resolvent is the `m`-th kernel resolvent. -/ +theorem localResolvent_apply {m : ℕ} (hemb : Function.Injective (emb m)) (lam : ℝ) + (f : alpha → ℝ≥0∞) (y : X m) : + localResolvent R emb m lam f (emb m y) = + (R m).kernelSemigroup.kernelResolvent lam (fun z ↦ f (emb m z)) y := + hemb.extend_apply _ _ y + +omit [MeasurableSpace alpha] in +/-- Off the `m`-th local domain the transported resolvent vanishes. -/ +theorem localResolvent_of_notMem (m : ℕ) (lam : ℝ) (f : alpha → ℝ≥0∞) {x : alpha} + (hx : x ∉ Set.range (emb m)) : localResolvent R emb m lam f x = 0 := + Function.extend_apply' _ _ _ fun hmem ↦ hx hmem + +omit [MeasurableSpace alpha] in +/-- The transported resolvent is monotone in the observable. -/ +theorem localResolvent_mono_of_le {m : ℕ} (hemb : Function.Injective (emb m)) (lam : ℝ) + {f g : alpha → ℝ≥0∞} (hfg : f ≤ g) (x : alpha) : + localResolvent R emb m lam f x ≤ localResolvent R emb m lam g x := by + by_cases hx : x ∈ Set.range (emb m) + · obtain ⟨y, rfl⟩ := hx + rw [localResolvent_apply R emb hemb lam f y, localResolvent_apply R emb hemb lam g y] + exact (R m).kernelSemigroup.kernelResolvent_mono lam (fun z ↦ hfg (emb m z)) y + · rw [localResolvent_of_notMem R emb m lam f hx] + exact zero_le + +/-- The transported resolvent is measurable in the starting point. -/ +theorem measurable_localResolvent {m : ℕ} (hemb : MeasurableEmbedding (emb m)) (lam : ℝ) + {f : alpha → ℝ≥0∞} (hf : Measurable f) : + Measurable (localResolvent R emb m lam f) := + hemb.measurable_extend + ((R m).kernelSemigroup.measurable_kernelResolvent lam (hf.comp hemb.measurable)) + measurable_const + +/-- The transported resolvent is continuous along monotone limits of observables. -/ +theorem localResolvent_iSup {m : ℕ} (hemb : MeasurableEmbedding (emb m)) (lam : ℝ) + {f : ℕ → alpha → ℝ≥0∞} (hf : ∀ n, Measurable (f n)) (hmono : Monotone f) (x : alpha) : + localResolvent R emb m lam (fun y ↦ ⨆ n, f n y) x = + ⨆ n, localResolvent R emb m lam (f n) x := by + by_cases hx : x ∈ Set.range (emb m) + · obtain ⟨y, rfl⟩ := hx + rw [localResolvent_apply R emb hemb.injective lam _ y] + have hcomp : ∀ n, Measurable fun z : X m ↦ f n (emb m z) := fun n ↦ + (hf n).comp hemb.measurable + have hmonoComp : Monotone fun n ↦ fun z : X m ↦ f n (emb m z) := + fun a b hab z ↦ hmono hab (emb m z) + rw [(R m).kernelSemigroup.kernelResolvent_iSup lam hcomp hmonoComp y] + exact iSup_congr fun n ↦ (localResolvent_apply R emb hemb.injective lam (f n) y).symm + · have hzero : ∀ n, localResolvent R emb m lam (f n) x = 0 := + fun n ↦ localResolvent_of_notMem R emb m lam (f n) hx + rw [localResolvent_of_notMem R emb m lam _ hx] + simp only [hzero, ciSup_const] + +section Compatible + +variable (iota : ∀ m, X m → X (m + 1)) + +/-- **The transported resolvents increase along the family.** Under the part-process identity, a +path of the larger domain is killed no earlier than a path of the smaller one, so the transported +kernel resolvents increase. -/ +theorem localResolvent_le_succ (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hiota : ∀ m, IsOpenEmbedding (iota m)) + (hcomm : ∀ m (y : X m), emb (m + 1) (iota m y) = emb m y) + (hreg : ∀ m, (R m).OnePointRegular) + (hcompat : ∀ m, PositiveC0ContractiveResolvent.IsPartProcess (R m) (R (m + 1)) + (hreg (m + 1)) (hiota m)) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ≥0∞} (hf : Measurable f) (m : ℕ) (x : alpha) : + localResolvent R emb m lam f x ≤ localResolvent R emb (m + 1) lam f x := by + by_cases hx : x ∈ Set.range (emb m) + · obtain ⟨y, rfl⟩ := hx + rw [localResolvent_apply R emb (hemb m).injective lam f y, ← hcomm m y, + localResolvent_apply R emb (hemb (m + 1)).injective lam f (iota m y)] + have hg : Measurable fun z : X (m + 1) ↦ f (emb (m + 1) z) := + hf.comp (hemb (m + 1)).measurable + have hdom := PositiveC0ContractiveResolvent.kernelResolvent_le_of_partProcess + (R m) (R (m + 1)) (hreg (m + 1)) (hiota m) (hcompat m) hlam hg y + have hgf : (fun z : X m ↦ f (emb (m + 1) (iota m z))) = fun z : X m ↦ f (emb m z) := by + funext z + rw [hcomm m z] + rwa [hgf] at hdom + · rw [localResolvent_of_notMem R emb m lam f hx] + exact zero_le + +/-- The transported resolvents form a monotone family. -/ +theorem monotone_localResolvent (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hiota : ∀ m, IsOpenEmbedding (iota m)) + (hcomm : ∀ m (y : X m), emb (m + 1) (iota m y) = emb m y) + (hreg : ∀ m, (R m).OnePointRegular) + (hcompat : ∀ m, PositiveC0ContractiveResolvent.IsPartProcess (R m) (R (m + 1)) + (hreg (m + 1)) (hiota m)) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + Monotone fun m ↦ localResolvent R emb m lam f x := + monotone_nat_of_le_succ fun m ↦ + localResolvent_le_succ R emb iota hemb hiota hcomm hreg hcompat hlam hf m x + +end Compatible + +/-- **The minimal resolvent** of a family of local resolvents: the pointwise supremum of the +transported local kernel resolvents. Monotonicity in `m`, under which the supremum is an +increasing limit, is the content of `localResolvent_le_succ`. -/ +noncomputable def minimalResolvent (lam : ℝ) (f : alpha → ℝ≥0∞) (x : alpha) : ℝ≥0∞ := + ⨆ m, localResolvent R emb m lam f x + +omit [MeasurableSpace alpha] in +/-- Each transported resolvent is dominated by the minimal resolvent. -/ +theorem localResolvent_le_minimalResolvent (m : ℕ) (lam : ℝ) (f : alpha → ℝ≥0∞) (x : alpha) : + localResolvent R emb m lam f x ≤ minimalResolvent R emb lam f x := + le_iSup (fun n ↦ localResolvent R emb n lam f x) m + +omit [MeasurableSpace alpha] in +/-- The minimal resolvent is monotone in the observable. -/ +theorem minimalResolvent_mono_of_le (hemb : ∀ m, Function.Injective (emb m)) (lam : ℝ) + {f g : alpha → ℝ≥0∞} (hfg : f ≤ g) (x : alpha) : + minimalResolvent R emb lam f x ≤ minimalResolvent R emb lam g x := + iSup_mono fun m ↦ localResolvent_mono_of_le R emb (hemb m) lam hfg x + +/-- The minimal resolvent is continuous along monotone limits of observables. -/ +theorem minimalResolvent_iSup (hemb : ∀ m, MeasurableEmbedding (emb m)) (lam : ℝ) + {f : ℕ → alpha → ℝ≥0∞} (hf : ∀ n, Measurable (f n)) (hmono : Monotone f) (x : alpha) : + minimalResolvent R emb lam (fun y ↦ ⨆ n, f n y) x = + ⨆ n, minimalResolvent R emb lam (f n) x := by + unfold minimalResolvent + rw [iSup_comm] + exact iSup_congr fun m ↦ localResolvent_iSup R emb (hemb m) lam hf hmono x + +/-- The minimal resolvent is measurable in the starting point. -/ +theorem measurable_minimalResolvent (hemb : ∀ m, MeasurableEmbedding (emb m)) (lam : ℝ) + {f : alpha → ℝ≥0∞} (hf : Measurable f) : + Measurable (minimalResolvent R emb lam f) := + Measurable.iSup fun m ↦ measurable_localResolvent R emb (hemb m) lam hf + +omit [MeasurableSpace alpha] in +/-- At a positive shift the minimal resolvent of the constant observable one is at most +`1 / lam`. -/ +theorem minimalResolvent_one_le (hemb : ∀ m, Function.Injective (emb m)) + {lam : ℝ} (hlam : 0 < lam) (x : alpha) : + minimalResolvent R emb lam (fun _ ↦ 1) x ≤ ENNReal.ofReal lam⁻¹ := by + refine iSup_le fun m ↦ ?_ + by_cases hx : x ∈ Set.range (emb m) + · obtain ⟨y, rfl⟩ := hx + rw [localResolvent_apply R emb (hemb m) lam _ y] + exact (R m).kernelSemigroup.kernelResolvent_one_le hlam y + · rw [localResolvent_of_notMem R emb m lam _ hx] + exact zero_le + +omit [MeasurableSpace alpha] in +/-- **The minimal resolvent is sub-Markov.** At a positive shift, `lam` times the minimal +resolvent of the constant observable one is at most one. -/ +theorem ofReal_mul_minimalResolvent_one_le (hemb : ∀ m, Function.Injective (emb m)) + {lam : ℝ} (hlam : 0 < lam) (x : alpha) : + ENNReal.ofReal lam * minimalResolvent R emb lam (fun _ ↦ 1) x ≤ 1 := by + calc ENNReal.ofReal lam * minimalResolvent R emb lam (fun _ ↦ 1) x + ≤ ENNReal.ofReal lam * ENNReal.ofReal lam⁻¹ := + mul_le_mul' le_rfl (minimalResolvent_one_le R emb hemb hlam x) + _ = 1 := by + rw [← ENNReal.ofReal_mul hlam.le, mul_inv_cancel₀ hlam.ne', ENNReal.ofReal_one] + +section ResolventEquation + +variable (iota : ∀ m, X m → X (m + 1)) + +/-- Each transported resolvent satisfies the resolvent equation. -/ +theorem localResolvent_resolventEquation {m : ℕ} (hemb : MeasurableEmbedding (emb m)) + {lam mu : ℝ} (hlt : lam < mu) {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + localResolvent R emb m lam f x = + localResolvent R emb m mu f x + + ENNReal.ofReal (mu - lam) * + localResolvent R emb m lam (localResolvent R emb m mu f) x := by + by_cases hx : x ∈ Set.range (emb m) + · obtain ⟨y, rfl⟩ := hx + have hinner : (fun z ↦ localResolvent R emb m mu f (emb m z)) = + (R m).kernelSemigroup.kernelResolvent mu fun z ↦ f (emb m z) := by + funext z + exact localResolvent_apply R emb hemb.injective mu f z + rw [localResolvent_apply R emb hemb.injective lam f y, + localResolvent_apply R emb hemb.injective mu f y, + localResolvent_apply R emb hemb.injective lam _ y, hinner] + exact (R m).kernelSemigroup.kernelResolvent_resolventEquation hlt + (hf.comp hemb.measurable) y + · rw [localResolvent_of_notMem R emb m lam f hx, + localResolvent_of_notMem R emb m mu f hx, + localResolvent_of_notMem R emb m lam _ hx] + simp only [mul_zero, add_zero] + +/-- **The composition of two supremum resolvents is the supremum along the diagonal**, as soon +as the transported resolvents are monotone in the index. -/ +theorem minimalResolvent_comp_eq_iSup (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {g : alpha → ℝ≥0∞}, Measurable g → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu g y) + {lam mu : ℝ} (hlam : 0 < lam) (hmu : 0 < mu) {f : alpha → ℝ≥0∞} (hf : Measurable f) + (x : alpha) : + minimalResolvent R emb lam (minimalResolvent R emb mu f) x = + ⨆ n, localResolvent R emb n lam (localResolvent R emb n mu f) x := by + have hgmeas : ∀ k, Measurable (localResolvent R emb k mu f) := fun k ↦ + measurable_localResolvent R emb (hemb k) mu hf + have hgmono : Monotone fun k ↦ localResolvent R emb k mu f := + fun a b hab y ↦ hmono mu hmu hf y hab + have hrepr : minimalResolvent R emb mu f = + fun y ↦ ⨆ k, localResolvent R emb k mu f y := rfl + have hstep : ∀ m, localResolvent R emb m lam + (fun y ↦ ⨆ k, localResolvent R emb k mu f y) x = + ⨆ k, localResolvent R emb m lam (localResolvent R emb k mu f) x := + fun m ↦ localResolvent_iSup R emb (hemb m) lam hgmeas hgmono x + rw [minimalResolvent, hrepr] + simp_rw [hstep] + refine le_antisymm (iSup_le fun m ↦ iSup_le fun k ↦ ?_) (iSup_le fun n ↦ ?_) + · refine le_iSup_of_le (max m k) ?_ + calc localResolvent R emb m lam (localResolvent R emb k mu f) x + ≤ localResolvent R emb (max m k) lam (localResolvent R emb k mu f) x := + hmono lam hlam (hgmeas k) x (le_max_left m k) + _ ≤ localResolvent R emb (max m k) lam + (localResolvent R emb (max m k) mu f) x := + localResolvent_mono_of_le R emb (hemb (max m k)).injective lam + (hgmono (le_max_right m k)) x + · exact le_iSup_of_le n (le_iSup_of_le n le_rfl) + +/-- **The resolvent equation for the supremum of the transported resolvents.** Each member +satisfies the resolvent equation, and both sides pass to the supremum by monotone convergence. +The only property of the family used is that the transported resolvents are monotone in `m` at +every positive shift. -/ +theorem minimalResolvent_resolventEquation_of_monotone + (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {g : alpha → ℝ≥0∞}, Measurable g → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu g y) + {lam mu : ℝ} (hlam : 0 < lam) (hlt : lam < mu) {f : alpha → ℝ≥0∞} (hf : Measurable f) + (x : alpha) : + minimalResolvent R emb lam f x = + minimalResolvent R emb mu f x + + ENNReal.ofReal (mu - lam) * + minimalResolvent R emb lam (minimalResolvent R emb mu f) x := by + have hmu : 0 < mu := hlam.trans hlt + have hgmeas : ∀ k, Measurable (localResolvent R emb k mu f) := fun k ↦ + measurable_localResolvent R emb (hemb k) mu hf + have hgmono : Monotone fun k ↦ localResolvent R emb k mu f := + fun a b hab y ↦ hmono mu hmu hf y hab + have hamono : Monotone fun n ↦ localResolvent R emb n mu f x := hmono mu hmu hf x + have hbmono : Monotone fun n ↦ + localResolvent R emb n lam (localResolvent R emb n mu f) x := by + refine monotone_nat_of_le_succ fun n ↦ ?_ + refine le_trans (hmono lam hlam (hgmeas n) x (Nat.le_succ n)) ?_ + exact localResolvent_mono_of_le R emb (hemb (n + 1)).injective lam + (hgmono (Nat.le_succ n)) x + have hcmono : Monotone fun n ↦ + ENNReal.ofReal (mu - lam) * + localResolvent R emb n lam (localResolvent R emb n mu f) x := + fun i j hij ↦ mul_le_mul' le_rfl (hbmono hij) + calc minimalResolvent R emb lam f x = ⨆ n, localResolvent R emb n lam f x := rfl + _ = ⨆ n, (localResolvent R emb n mu f x + + ENNReal.ofReal (mu - lam) * + localResolvent R emb n lam (localResolvent R emb n mu f) x) := + iSup_congr fun n ↦ + localResolvent_resolventEquation R emb (hemb n) hlt hf x + _ = (⨆ n, localResolvent R emb n mu f x) + + ⨆ n, ENNReal.ofReal (mu - lam) * + localResolvent R emb n lam (localResolvent R emb n mu f) x := + (ENNReal.iSup_add_iSup_of_monotone hamono hcmono).symm + _ = minimalResolvent R emb mu f x + + ENNReal.ofReal (mu - lam) * + minimalResolvent R emb lam (minimalResolvent R emb mu f) x := by + rw [minimalResolvent_comp_eq_iSup R emb hemb hmono hlam hmu hf x, + ENNReal.mul_iSup, minimalResolvent] + +/-- **The minimal resolvent satisfies the resolvent equation.** The part-process identity is +consumed only through the monotonicity of the transported resolvents. -/ +theorem minimalResolvent_resolventEquation (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hiota : ∀ m, IsOpenEmbedding (iota m)) + (hcomm : ∀ m (y : X m), emb (m + 1) (iota m y) = emb m y) + (hreg : ∀ m, (R m).OnePointRegular) + (hcompat : ∀ m, PositiveC0ContractiveResolvent.IsPartProcess (R m) (R (m + 1)) + (hreg (m + 1)) (hiota m)) + {lam mu : ℝ} (hlam : 0 < lam) (hlt : lam < mu) {f : alpha → ℝ≥0∞} (hf : Measurable f) + (x : alpha) : + minimalResolvent R emb lam f x = + minimalResolvent R emb mu f x + + ENNReal.ofReal (mu - lam) * + minimalResolvent R emb lam (minimalResolvent R emb mu f) x := + minimalResolvent_resolventEquation_of_monotone R emb hemb + (fun _nu hnu {_g} hg y ↦ + monotone_localResolvent R emb iota hemb hiota hcomm hreg hcompat hnu hg y) + hlam hlt hf x + +end ResolventEquation + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingPotential.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingPotential.lean new file mode 100644 index 0000000000..efcd78e464 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingPotential.lean @@ -0,0 +1,281 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion + +/-! +# Potential measures + +The resolvent of a transition family at a shift `lam` integrates an observable against the +exponentially weighted time average of its transition kernels. This file realises that average +as a genuine measure, the `lam`-potential measure + + `laplacePotential lam mu = ∫_0^∞ e^{-lam t} (mu t) dt`, + +so that both the kernel resolvent of a sub-Markov kernel semigroup and the killed resolvent of an +open set are integrals against a measure on the state space: +`SubMarkovKernelSemigroup.lintegral_resolventPotential` and +`IsConservative.lintegral_killedPotential`. Potential measures of sub-Markov families are finite +at every positive shift, with total mass at most `1 / lam`. + +Two consequences of the measure form are proved here: the killed resolvent is monotone in the +open set and in the observable (`IsConservative.killedResolvent_mono`), and the kernel resolvent +is measurable in the starting point and continuous along monotone limits of observables +(`SubMarkovKernelSemigroup.measurable_kernelResolvent`, +`SubMarkovKernelSemigroup.kernelResolvent_iSup`). The kernel resolvent is also additive and +homogeneous on measurable observables (`SubMarkovKernelSemigroup.kernelResolvent_add`, +`SubMarkovKernelSemigroup.kernelResolvent_const_mul`). + +No resolvent identity and no topology on the state space are used here. +-/ + +open Filter MeasureTheory ProbabilityTheory Set +open scoped ENNReal NNReal + +noncomputable section + +namespace MarkovProcess + +/-- The exponentially weighted measure on positive times at the shift `lam`. -/ +noncomputable def laplaceWeight (lam : ℝ) : Measure ℝ := + (volume.restrict (Ioi (0 : ℝ))).withDensity fun t ↦ ENNReal.ofReal (Real.exp (-lam * t)) + +/-- The exponential weight is measurable in time. -/ +theorem measurable_laplaceDensity (lam : ℝ) : + Measurable fun t : ℝ ↦ ENNReal.ofReal (Real.exp (-lam * t)) := + ENNReal.measurable_ofReal.comp + (Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable + +/-- Integration against the exponentially weighted time measure. -/ +theorem lintegral_laplaceWeight (lam : ℝ) {g : ℝ → ℝ≥0∞} (hg : Measurable g) : + ∫⁻ t, g t ∂laplaceWeight lam = + ∫⁻ t in Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * g t := by + rw [laplaceWeight, + lintegral_withDensity_eq_lintegral_mul _ (measurable_laplaceDensity lam) hg] + rfl + +/-- At a positive shift the exponentially weighted time measure has total mass `1 / lam`. -/ +theorem laplaceWeight_univ {lam : ℝ} (hlam : 0 < lam) : + laplaceWeight lam univ = ENNReal.ofReal lam⁻¹ := by + have hmass : ∫⁻ _t : ℝ, (1 : ℝ≥0∞) ∂laplaceWeight lam = laplaceWeight lam univ := + lintegral_one + rw [← hmass, lintegral_laplaceWeight lam measurable_const] + simp only [mul_one] + rw [← ofReal_integral_eq_lintegral_ofReal (exp_neg_integrableOn_Ioi 0 hlam) + (Eventually.of_forall fun t ↦ (Real.exp_pos _).le)] + congr 1 + rw [integral_exp_mul_Ioi (neg_neg_of_pos hlam) 0] + simp only [mul_zero, Real.exp_zero] + field_simp + +/-- At a positive shift the exponentially weighted time measure is finite. -/ +theorem isFiniteMeasure_laplaceWeight {lam : ℝ} (hlam : 0 < lam) : + IsFiniteMeasure (laplaceWeight lam) := + ⟨by rw [laplaceWeight_univ hlam]; exact ENNReal.ofReal_lt_top⟩ + +variable {alpha : Type*} [MeasurableSpace alpha] + +/-- The `lam`-potential measure of a measurable family of transition measures: the exponentially +weighted time average of the family. -/ +noncomputable def laplacePotential (lam : ℝ) (mu : ℝ → Measure alpha) : Measure alpha := + (laplaceWeight lam).bind mu + +/-- Integration against a potential measure is the Laplace transform in time of the integrals +against the family. -/ +theorem lintegral_laplacePotential (lam : ℝ) {mu : ℝ → Measure alpha} (hmu : Measurable mu) + {f : alpha → ℝ≥0∞} (hf : Measurable f) : + ∫⁻ y, f y ∂laplacePotential lam mu = + ∫⁻ t in Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * ∫⁻ y, f y ∂mu t := by + have hinner : Measurable fun t : ℝ ↦ ∫⁻ y, f y ∂mu t := + (Measure.measurable_lintegral hf).comp hmu + rw [laplacePotential, Measure.lintegral_bind hmu.aemeasurable hf.aemeasurable, + lintegral_laplaceWeight lam hinner] + +/-- A potential measure of a family of sub-probability measures has mass at most `1 / lam`. -/ +theorem laplacePotential_univ_le {lam : ℝ} (hlam : 0 < lam) {mu : ℝ → Measure alpha} + (hmu : Measurable mu) (hmass : ∀ t, mu t univ ≤ 1) : + laplacePotential lam mu univ ≤ ENNReal.ofReal lam⁻¹ := by + have hone : ∫⁻ _y : alpha, (1 : ℝ≥0∞) ∂laplacePotential lam mu = + laplacePotential lam mu univ := lintegral_one + have hweight : ∫⁻ _t : ℝ, (1 : ℝ≥0∞) ∂laplaceWeight lam = laplaceWeight lam univ := + lintegral_one + rw [← hone, lintegral_laplacePotential lam hmu measurable_const, ← laplaceWeight_univ hlam, + ← hweight, lintegral_laplaceWeight lam measurable_const] + refine setLIntegral_mono' measurableSet_Ioi fun t _ht ↦ ?_ + rw [lintegral_one] + gcongr + exact hmass t + +/-- A potential measure of a family of sub-probability measures is finite at a positive shift. -/ +theorem isFiniteMeasure_laplacePotential {lam : ℝ} (hlam : 0 < lam) {mu : ℝ → Measure alpha} + (hmu : Measurable mu) (hmass : ∀ t, mu t univ ≤ 1) : + IsFiniteMeasure (laplacePotential lam mu) := + ⟨lt_of_le_of_lt (laplacePotential_univ_le hlam hmu hmass) ENNReal.ofReal_lt_top⟩ + +namespace SubMarkovKernelSemigroup + +variable (P : SubMarkovKernelSemigroup alpha) + +/-- The transition measures of a sub-Markov kernel semigroup are measurable in time. -/ +theorem measurable_toMeasure_toNNReal (x : alpha) : + Measurable fun t : ℝ ↦ P (Real.toNNReal t) x := + P.measurable_toMeasure.comp (measurable_real_toNNReal.prodMk measurable_const) + +/-- The `lam`-potential measure of a sub-Markov kernel semigroup started at `x`. -/ +noncomputable def resolventPotential (lam : ℝ) (x : alpha) : Measure alpha := + laplacePotential lam fun t ↦ P (Real.toNNReal t) x + +/-- The kernel resolvent is integration against the potential measure. -/ +theorem lintegral_resolventPotential (lam : ℝ) {f : alpha → ℝ≥0∞} (hf : Measurable f) + (x : alpha) : + ∫⁻ y, f y ∂P.resolventPotential lam x = P.kernelResolvent lam f x := + lintegral_laplacePotential lam (P.measurable_toMeasure_toNNReal x) hf + +/-- The potential measure of a sub-Markov kernel semigroup is finite at a positive shift. -/ +theorem isFiniteMeasure_resolventPotential {lam : ℝ} (hlam : 0 < lam) (x : alpha) : + IsFiniteMeasure (P.resolventPotential lam x) := + isFiniteMeasure_laplacePotential hlam (P.measurable_toMeasure_toNNReal x) + fun _t ↦ P.measure_univ_le_one _ x + +/-- At a positive shift the kernel resolvent of the constant observable one is at most +`1 / lam`. -/ +theorem kernelResolvent_one_le {lam : ℝ} (hlam : 0 < lam) (x : alpha) : + P.kernelResolvent lam (fun _ ↦ 1) x ≤ ENNReal.ofReal lam⁻¹ := by + rw [← P.lintegral_resolventPotential lam measurable_const x, lintegral_one] + exact laplacePotential_univ_le hlam (P.measurable_toMeasure_toNNReal x) + fun _t ↦ P.measure_univ_le_one _ x + +/-- **The normalized potential mass of any set is at most one.** At a positive shift the +`lam`-potential measure of a sub-Markov kernel semigroup has total mass at most `1 / lam`, so +the normalization by `lam` used in the resolvent tail estimates is a sub-probability. -/ +theorem ofReal_mul_resolventPotential_le_one {lam : ℝ} (hlam : 0 < lam) (x : alpha) + (s : Set alpha) : + ENNReal.ofReal lam * P.resolventPotential lam x s ≤ 1 := by + have hmass : P.resolventPotential lam x s ≤ ENNReal.ofReal lam⁻¹ := + le_trans (measure_mono (Set.subset_univ s)) + (laplacePotential_univ_le hlam (P.measurable_toMeasure_toNNReal x) + fun _t ↦ P.measure_univ_le_one _ x) + calc ENNReal.ofReal lam * P.resolventPotential lam x s + ≤ ENNReal.ofReal lam * ENNReal.ofReal lam⁻¹ := by gcongr + _ = 1 := by + rw [← ENNReal.ofReal_mul hlam.le, mul_inv_cancel₀ hlam.ne', ENNReal.ofReal_one] + +/-- The kernel resolvent is monotone in the observable. -/ +theorem kernelResolvent_mono (lam : ℝ) {f g : alpha → ℝ≥0∞} (hfg : f ≤ g) (x : alpha) : + P.kernelResolvent lam f x ≤ P.kernelResolvent lam g x := by + refine setLIntegral_mono' measurableSet_Ioi fun _t _ht ↦ ?_ + exact mul_le_mul' le_rfl (lintegral_mono hfg) + +/-- The kernel resolvent is additive on measurable observables. -/ +theorem kernelResolvent_add (lam : ℝ) {f g : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + P.kernelResolvent lam (fun y ↦ f y + g y) x = + P.kernelResolvent lam f x + P.kernelResolvent lam g x := by + unfold kernelResolvent + have hinner : ∀ t : ℝ, ENNReal.ofReal (Real.exp (-lam * t)) * + ∫⁻ y, (f y + g y) ∂P (Real.toNNReal t) x = + ENNReal.ofReal (Real.exp (-lam * t)) * ∫⁻ y, f y ∂P (Real.toNNReal t) x + + ENNReal.ofReal (Real.exp (-lam * t)) * ∫⁻ y, g y ∂P (Real.toNNReal t) x := by + intro t + rw [lintegral_add_left hf, mul_add] + simp_rw [hinner] + exact lintegral_add_left ((measurable_laplaceDensity lam).mul + ((Measure.measurable_lintegral hf).comp (P.measurable_toMeasure_toNNReal x))) _ + +/-- The kernel resolvent is homogeneous under multiplication by an extended-real constant. -/ +theorem kernelResolvent_const_mul (lam : ℝ) (c : ℝ≥0∞) {f : alpha → ℝ≥0∞} (hf : Measurable f) + (x : alpha) : + P.kernelResolvent lam (fun y ↦ c * f y) x = c * P.kernelResolvent lam f x := by + unfold kernelResolvent + have hinner : ∀ t : ℝ, ENNReal.ofReal (Real.exp (-lam * t)) * + ∫⁻ y, c * f y ∂P (Real.toNNReal t) x = + c * (ENNReal.ofReal (Real.exp (-lam * t)) * ∫⁻ y, f y ∂P (Real.toNNReal t) x) := by + intro t + rw [lintegral_const_mul c hf] + ring + simp_rw [hinner] + exact lintegral_const_mul c ((measurable_laplaceDensity lam).mul + ((Measure.measurable_lintegral hf).comp (P.measurable_toMeasure_toNNReal x))) + +/-- The kernel resolvent is measurable in the starting point. -/ +theorem measurable_kernelResolvent (lam : ℝ) {f : alpha → ℝ≥0∞} (hf : Measurable f) : + Measurable fun x ↦ P.kernelResolvent lam f x := by + have hjoint : Measurable fun q : alpha × ℝ ↦ + ENNReal.ofReal (Real.exp (-lam * q.2)) * ∫⁻ y, f y ∂P (Real.toNNReal q.2) q.1 := by + refine Measurable.mul ((measurable_laplaceDensity lam).comp measurable_snd) ?_ + exact (Measure.measurable_lintegral hf).comp + (P.measurable_toMeasure.comp ((measurable_real_toNNReal.comp measurable_snd).prodMk + measurable_fst)) + exact hjoint.lintegral_prod_right' + +/-- The kernel resolvent is continuous along monotone limits of observables. -/ +theorem kernelResolvent_iSup (lam : ℝ) {f : ℕ → alpha → ℝ≥0∞} (hf : ∀ n, Measurable (f n)) + (hmono : Monotone f) (x : alpha) : + P.kernelResolvent lam (fun y ↦ ⨆ n, f n y) x = ⨆ n, P.kernelResolvent lam (f n) x := by + unfold kernelResolvent + have hinner : ∀ t : ℝ, ENNReal.ofReal (Real.exp (-lam * t)) * + ∫⁻ y, (⨆ n, f n y) ∂P (Real.toNNReal t) x = + ⨆ n, ENNReal.ofReal (Real.exp (-lam * t)) * ∫⁻ y, f n y ∂P (Real.toNNReal t) x := by + intro t + rw [lintegral_iSup hf fun m n hmn ↦ hmono hmn, ENNReal.mul_iSup] + simp_rw [hinner] + refine lintegral_iSup (fun n ↦ ?_) fun m n hmn ↦ ?_ + · exact (measurable_laplaceDensity lam).mul + ((Measure.measurable_lintegral (hf n)).comp (P.measurable_toMeasure_toNNReal x)) + · intro _t + exact mul_le_mul' le_rfl (lintegral_mono (hmono hmn)) + +section Killed + +variable [MetricSpace alpha] [CompleteSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) +variable (U : Set alpha) (hU : IsOpen U) + +/-- The killed transition kernels are measurable in time. -/ +theorem IsConservative.measurable_killedKernel_toNNReal (x : alpha) : + Measurable fun t : ℝ ↦ IsConservative.killedKernel P hP U hU (Real.toNNReal t) x := + (IsConservative.measurable_killedKernel P hP U hU).comp + (measurable_real_toNNReal.prodMk measurable_const) + +/-- The `lam`-potential measure of the process killed at the exit of `U`, started at `x`. -/ +noncomputable def IsConservative.killedPotential (lam : ℝ) (x : alpha) : Measure alpha := + laplacePotential lam fun t ↦ IsConservative.killedKernel P hP U hU (Real.toNNReal t) x + +/-- The killed resolvent is integration against the killed potential measure. -/ +theorem IsConservative.lintegral_killedPotential (lam : ℝ) {f : alpha → ℝ≥0∞} + (hf : Measurable f) (x : alpha) : + ∫⁻ y, f y ∂IsConservative.killedPotential P hP U hU lam x = + IsConservative.killedResolvent P hP U hU lam f x := + lintegral_laplacePotential lam (IsConservative.measurable_killedKernel_toNNReal P hP U hU x) hf + +/-- The killed potential measure is finite at a positive shift. -/ +theorem IsConservative.isFiniteMeasure_killedPotential {lam : ℝ} (hlam : 0 < lam) (x : alpha) : + IsFiniteMeasure (IsConservative.killedPotential P hP U hU lam x) := + isFiniteMeasure_laplacePotential hlam + (IsConservative.measurable_killedKernel_toNNReal P hP U hU x) + fun _t ↦ (IsConservative.isSubMarkovKernel_killedKernel P hP U hU _) x + +/-- **The killed resolvent is monotone in the open set and in the observable.** A path leaves a +larger set no earlier, so the killed transition kernels increase with the set. -/ +theorem IsConservative.killedResolvent_mono {V : Set alpha} (hV : IsOpen V) (hUV : U ⊆ V) + (lam : ℝ) {f g : alpha → ℝ≥0∞} (hfg : f ≤ g) (x : alpha) : + IsConservative.killedResolvent P hP U hU lam f x ≤ + IsConservative.killedResolvent P hP V hV lam g x := by + refine setLIntegral_mono' measurableSet_Ioi fun t _ht ↦ ?_ + refine mul_le_mul' le_rfl (lintegral_mono' ?_ hfg) + refine Measure.le_iff.mpr fun B hB ↦ ?_ + rw [IsConservative.killedKernel_apply P hP U hU _ x hB, + IsConservative.killedKernel_apply P hP V hV _ x hB] + refine measure_mono fun omega homega ↦ ?_ + exact ⟨lt_of_lt_of_le homega.1 (ContinuousPath.exitTime_mono hUV omega), homega.2⟩ + +end Killed + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingRealResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingRealResolvent.lean new file mode 100644 index 0000000000..41b9e3c67b --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingRealResolvent.lean @@ -0,0 +1,406 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity + +/-! +# The supremum resolvent on bounded real observables + +The supremum resolvent of `Killed/GluingMinimal.lean` acts on nonnegative extended-real +observables. On a bounded real observable it acts through the positive and negative parts, + + `R_lam f := (R_lam f⁺).toReal - (R_lam f⁻).toReal` (`minimalResolventReal`), + +which is well defined because a uniform bound `D` for the observable bounds both values by +`D / lam` (`Killed/GluingLinearity.lean`). The real form is measurable in the starting point +(`measurable_minimalResolventReal`), obeys the same uniform bound +(`abs_minimalResolventReal_le`), is additive and real homogeneous on bounded measurable +observables (`minimalResolventReal_add`, `minimalResolventReal_smul`), satisfies the +resolvent equation (`minimalResolventReal_resolventEquation`), and commutes at two shifts +(`minimalResolventReal_comm`). + +Additivity, and with it the resolvent equation, is available exactly when the transported +resolvents are monotone in the index; that monotonicity is a bare hypothesis here. +-/ + +open Filter MeasureTheory ProbabilityTheory Set Topology +open scoped ENNReal NNReal ZeroAtInfty + +noncomputable section + +namespace MarkovProcess + +variable {alpha : Type*} [MeasurableSpace alpha] {X : ℕ → Type*} + [∀ m, MetricSpace (X m)] [∀ m, LocallyCompactSpace (X m)] + [∀ m, SecondCountableTopology (X m)] [∀ m, MeasurableSpace (X m)] [∀ m, BorelSpace (X m)] + +variable (R : ∀ m, PositiveC0ContractiveResolvent (X m)) (emb : ∀ m, X m → alpha) + +/-- **The supremum resolvent on real observables**: the difference of its values on the positive +and the negative part of the observable. -/ +def minimalResolventReal (lam : ℝ) (f : alpha → ℝ) (x : alpha) : ℝ := + (minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (f y)) x).toReal - + (minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (-f y)) x).toReal + +section Bounds + + +/-- A real observable bounded by `D` has both parts bounded by `D` after `ENNReal.ofReal`. -/ +private theorem ofReal_le_ofReal_of_abs_le {a D : ℝ} (h : |a| ≤ D) : + ENNReal.ofReal a ≤ ENNReal.ofReal D := + ENNReal.ofReal_le_ofReal ((le_abs_self a).trans h) + +/-- The supremum resolvent of a bounded real observable is finite. -/ +theorem minimalResolvent_ofReal_ne_top (hemb : ∀ m, MeasurableEmbedding (emb m)) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ} {D : ℝ} (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (f y)) x ≠ ⊤ := + minimalResolvent_ne_top R emb hemb hlam ENNReal.ofReal_ne_top + (fun y ↦ ofReal_le_ofReal_of_abs_le (hfD y)) x + +/-- The supremum resolvent of a bounded real observable is at most `D / lam`. -/ +theorem minimalResolvent_ofReal_toReal_le (hemb : ∀ m, MeasurableEmbedding (emb m)) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ} {D : ℝ} (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + (minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (f y)) x).toReal ≤ D / lam := by + have hD0 : 0 ≤ D := (abs_nonneg (f x)).trans (hfD x) + refine ENNReal.toReal_le_of_le_ofReal (div_nonneg hD0 hlam.le) ?_ + refine le_trans (minimalResolvent_le_of_le_const R emb hemb hlam + (fun y ↦ ofReal_le_ofReal_of_abs_le (hfD y)) x) ?_ + rw [← ENNReal.ofReal_mul hD0] + exact le_of_eq (by rw [div_eq_mul_inv]) + +end Bounds + +section Elementary + + +/-- On a nonnegative observable the real form is the extended-real value. -/ +theorem minimalResolventReal_of_nonneg (hemb : ∀ m, MeasurableEmbedding (emb m)) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ} (hf0 : ∀ y, 0 ≤ f y) (x : alpha) : + minimalResolventReal R emb lam f x = + (minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (f y)) x).toReal := by + have hzero : (fun y ↦ ENNReal.ofReal (-f y)) = fun _ : alpha ↦ (0 : ℝ≥0∞) := by + funext y + exact ENNReal.ofReal_eq_zero.mpr (neg_nonpos.mpr (hf0 y)) + rw [minimalResolventReal, hzero, minimalResolvent_zero R emb hemb hlam x, + ENNReal.toReal_zero, sub_zero] + +/-- On a bounded nonnegative observable the extended-real value is recovered from the real +form. -/ +theorem ofReal_minimalResolventReal (hemb : ∀ m, MeasurableEmbedding (emb m)) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ} {D : ℝ} (hfD : ∀ y, |f y| ≤ D) + (hf0 : ∀ y, 0 ≤ f y) (x : alpha) : + ENNReal.ofReal (minimalResolventReal R emb lam f x) = + minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (f y)) x := by + rw [minimalResolventReal_of_nonneg R emb hemb hlam hf0 x, + ENNReal.ofReal_toReal (minimalResolvent_ofReal_ne_top R emb hemb hlam hfD x)] + +/-- The real form is nonnegative on a nonnegative observable. -/ +theorem minimalResolventReal_nonneg (hemb : ∀ m, MeasurableEmbedding (emb m)) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ} (hf0 : ∀ y, 0 ≤ f y) (x : alpha) : + 0 ≤ minimalResolventReal R emb lam f x := by + rw [minimalResolventReal_of_nonneg R emb hemb hlam hf0 x] + exact ENNReal.toReal_nonneg + +/-- **The uniform bound in the real form**: the bound of the observable divided by the shift. -/ +theorem abs_minimalResolventReal_le (hemb : ∀ m, MeasurableEmbedding (emb m)) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ} {D : ℝ} (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + |minimalResolventReal R emb lam f x| ≤ D / lam := by + have hpos := minimalResolvent_ofReal_toReal_le R emb hemb hlam hfD x + have hneg := minimalResolvent_ofReal_toReal_le R emb (f := fun y ↦ -f y) hemb hlam + (fun y ↦ by rw [abs_neg]; exact hfD y) x + have hpos0 : 0 ≤ (minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (f y)) x).toReal := + ENNReal.toReal_nonneg + have hneg0 : 0 ≤ (minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (-f y)) x).toReal := + ENNReal.toReal_nonneg + rw [minimalResolventReal, abs_le] + constructor + · linarith only [hneg, hpos0] + · linarith only [hpos, hneg0] + +/-- The real form is measurable in the starting point. -/ +theorem measurable_minimalResolventReal (hemb : ∀ m, MeasurableEmbedding (emb m)) (lam : ℝ) + {f : alpha → ℝ} (hf : Measurable f) : + Measurable (minimalResolventReal R emb lam f) := + ((measurable_minimalResolvent R emb hemb lam + (ENNReal.measurable_ofReal.comp hf)).ennreal_toReal).sub + ((measurable_minimalResolvent R emb hemb lam + (ENNReal.measurable_ofReal.comp hf.neg)).ennreal_toReal) + +omit [MeasurableSpace alpha] in +/-- The real form changes sign with the observable. -/ +theorem minimalResolventReal_neg (lam : ℝ) (f : alpha → ℝ) (x : alpha) : + minimalResolventReal R emb lam (fun y ↦ -f y) x = + -minimalResolventReal R emb lam f x := by + have hdouble : (fun y ↦ ENNReal.ofReal (-(-f y))) = fun y ↦ ENNReal.ofReal (f y) := by + funext y + rw [neg_neg] + rw [minimalResolventReal, minimalResolventReal, hdouble, neg_sub] + +/-- The real form is homogeneous under a nonnegative real factor. -/ +theorem minimalResolventReal_const_mul_of_nonneg (hemb : ∀ m, MeasurableEmbedding (emb m)) + (lam : ℝ) {c : ℝ} (hc : 0 ≤ c) {f : alpha → ℝ} (hf : Measurable f) (x : alpha) : + minimalResolventReal R emb lam (fun y ↦ c * f y) x = + c * minimalResolventReal R emb lam f x := by + have hpos : (fun y ↦ ENNReal.ofReal (c * f y)) = + fun y ↦ ENNReal.ofReal c * ENNReal.ofReal (f y) := by + funext y + rw [ENNReal.ofReal_mul hc] + have hneg : (fun y ↦ ENNReal.ofReal (-(c * f y))) = + fun y ↦ ENNReal.ofReal c * ENNReal.ofReal (-f y) := by + funext y + rw [← ENNReal.ofReal_mul hc, mul_neg] + rw [minimalResolventReal, minimalResolventReal, hpos, hneg, + minimalResolvent_const_mul R emb hemb lam (ENNReal.ofReal c) + (f := fun y ↦ ENNReal.ofReal (f y)) (ENNReal.measurable_ofReal.comp hf) x, + minimalResolvent_const_mul R emb hemb lam (ENNReal.ofReal c) + (f := fun y ↦ ENNReal.ofReal (-f y)) (ENNReal.measurable_ofReal.comp hf.neg) x, + ENNReal.toReal_mul, ENNReal.toReal_mul, ENNReal.toReal_ofReal hc] + ring + +/-- **The real form is real homogeneous.** -/ +theorem minimalResolventReal_smul (hemb : ∀ m, MeasurableEmbedding (emb m)) (lam : ℝ) (c : ℝ) + {f : alpha → ℝ} (hf : Measurable f) (x : alpha) : + minimalResolventReal R emb lam (fun y ↦ c * f y) x = + c * minimalResolventReal R emb lam f x := by + rcases le_or_gt 0 c with hc | hc + · exact minimalResolventReal_const_mul_of_nonneg R emb hemb lam hc hf x + · have hrewrite : (fun y ↦ c * f y) = fun y ↦ -((-c) * f y) := by + funext y + ring + rw [hrewrite, minimalResolventReal_neg R emb, + minimalResolventReal_const_mul_of_nonneg R emb hemb lam (neg_nonneg.mpr hc.le) hf x] + ring + +end Elementary + +section Additive + + +private theorem ofReal_eq_ofReal_max (t : ℝ) : + ENNReal.ofReal t = ENNReal.ofReal (max t 0) := by + rcases le_total 0 t with h | h + · rw [max_eq_left h] + · rw [max_eq_right h, ENNReal.ofReal_eq_zero.mpr h, ENNReal.ofReal_zero] + +private theorem max_eq_add_max_neg (t : ℝ) : max t 0 = t + max (-t) 0 := by + rcases le_total 0 t with h | h + · rw [max_eq_left h, max_eq_right (neg_nonpos.mpr h), add_zero] + · rw [max_eq_right h, max_eq_left (neg_nonneg.mpr h)] + ring + +/-- The positive and negative parts of a sum of two reals rearrange into the parts of the +summands. -/ +private theorem ofReal_parts_add (a b : ℝ) : + ENNReal.ofReal (a + b) + ENNReal.ofReal (-a) + ENNReal.ofReal (-b) = + ENNReal.ofReal a + ENNReal.ofReal b + ENNReal.ofReal (-(a + b)) := by + rw [ofReal_eq_ofReal_max (a + b), ofReal_eq_ofReal_max (-a), ofReal_eq_ofReal_max (-b), + ofReal_eq_ofReal_max a, ofReal_eq_ofReal_max b, ofReal_eq_ofReal_max (-(a + b)), + ← ENNReal.ofReal_add (le_max_right _ _) (le_max_right _ _), + ← ENNReal.ofReal_add (add_nonneg (le_max_right _ _) (le_max_right _ _)) + (le_max_right _ _), + ← ENNReal.ofReal_add (le_max_right _ _) (le_max_right _ _), + ← ENNReal.ofReal_add (add_nonneg (le_max_right _ _) (le_max_right _ _)) + (le_max_right _ _)] + congr 1 + rw [max_eq_add_max_neg a, max_eq_add_max_neg b, max_eq_add_max_neg (a + b)] + ring + +/-- The supremum resolvent of a sum of three measurable observables. -/ +private theorem minimalResolvent_add_three (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam : ℝ} (hlam : 0 < lam) {u v w : alpha → ℝ≥0∞} (hu : Measurable u) (hv : Measurable v) + (hw : Measurable w) (x : alpha) : + minimalResolvent R emb lam (fun y ↦ u y + v y + w y) x = + minimalResolvent R emb lam u x + minimalResolvent R emb lam v x + + minimalResolvent R emb lam w x := by + have hfun : (fun y ↦ u y + v y + w y) = fun y ↦ (u + v) y + w y := rfl + have hfun' : (u + v) = fun y ↦ u y + v y := rfl + rw [hfun, minimalResolvent_add R emb hemb hmono hlam (hu.add hv) hw x, hfun', + minimalResolvent_add R emb hemb hmono hlam hu hv x] + +/-- **The real form is additive** on bounded measurable observables. -/ +theorem minimalResolventReal_add (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam : ℝ} (hlam : 0 < lam) {f g : alpha → ℝ} {D E : ℝ} + (hf : Measurable f) (hg : Measurable g) (hfD : ∀ y, |f y| ≤ D) (hgE : ∀ y, |g y| ≤ E) + (x : alpha) : + minimalResolventReal R emb lam (fun y ↦ f y + g y) x = + minimalResolventReal R emb lam f x + minimalResolventReal R emb lam g x := by + have hsum : ∀ y, |f y + g y| ≤ D + E := fun y ↦ + (abs_add_le (f y) (g y)).trans (add_le_add (hfD y) (hgE y)) + have hmeasP1 : Measurable fun y ↦ ENNReal.ofReal (f y + g y) := + ENNReal.measurable_ofReal.comp (hf.add hg) + have hmeasN1 : Measurable fun y ↦ ENNReal.ofReal (-f y) := + ENNReal.measurable_ofReal.comp hf.neg + have hmeasN2 : Measurable fun y ↦ ENNReal.ofReal (-g y) := + ENNReal.measurable_ofReal.comp hg.neg + have hmeasP2 : Measurable fun y ↦ ENNReal.ofReal (f y) := + ENNReal.measurable_ofReal.comp hf + have hmeasP3 : Measurable fun y ↦ ENNReal.ofReal (g y) := + ENNReal.measurable_ofReal.comp hg + have hmeasN3 : Measurable fun y ↦ ENNReal.ofReal (-(f y + g y)) := + ENNReal.measurable_ofReal.comp (hf.add hg).neg + have hkey : minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (f y + g y)) x + + minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (-f y)) x + + minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (-g y)) x = + minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (f y)) x + + minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (g y)) x + + minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (-(f y + g y))) x := by + rw [← minimalResolvent_add_three R emb hemb hmono hlam hmeasP1 hmeasN1 hmeasN2 x, + ← minimalResolvent_add_three R emb hemb hmono hlam hmeasP2 hmeasP3 hmeasN3 x] + congr 1 + funext y + exact ofReal_parts_add (f y) (g y) + have hP1 := minimalResolvent_ofReal_ne_top R emb (f := fun y ↦ f y + g y) hemb hlam hsum x + have hN1 := minimalResolvent_ofReal_ne_top R emb (f := fun y ↦ -f y) hemb hlam + (fun y ↦ by rw [abs_neg]; exact hfD y) x + have hN2 := minimalResolvent_ofReal_ne_top R emb (f := fun y ↦ -g y) hemb hlam + (fun y ↦ by rw [abs_neg]; exact hgE y) x + have hP2 := minimalResolvent_ofReal_ne_top R emb (f := f) hemb hlam hfD x + have hP3 := minimalResolvent_ofReal_ne_top R emb (f := g) hemb hlam hgE x + have hN3 := minimalResolvent_ofReal_ne_top R emb (f := fun y ↦ -(f y + g y)) hemb hlam + (fun y ↦ by rw [abs_neg]; exact hsum y) x + have hreal := congrArg ENNReal.toReal hkey + rw [ENNReal.toReal_add (ENNReal.add_ne_top.mpr ⟨hP1, hN1⟩) hN2, + ENNReal.toReal_add hP1 hN1, + ENNReal.toReal_add (ENNReal.add_ne_top.mpr ⟨hP2, hP3⟩) hN3, + ENNReal.toReal_add hP2 hP3] at hreal + rw [minimalResolventReal, minimalResolventReal, minimalResolventReal] + linarith only [hreal] + +/-- The real form is subtractive on bounded measurable observables. -/ +theorem minimalResolventReal_sub (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam : ℝ} (hlam : 0 < lam) {f g : alpha → ℝ} {D E : ℝ} + (hf : Measurable f) (hg : Measurable g) (hfD : ∀ y, |f y| ≤ D) (hgE : ∀ y, |g y| ≤ E) + (x : alpha) : + minimalResolventReal R emb lam (fun y ↦ f y - g y) x = + minimalResolventReal R emb lam f x - minimalResolventReal R emb lam g x := by + have hrewrite : (fun y ↦ f y - g y) = fun y ↦ f y + (-g) y := by + funext y + show f y - g y = f y + -g y + ring + have hneg : minimalResolventReal R emb lam (-g) x = + - minimalResolventReal R emb lam g x := by + have h : (-g) = fun y ↦ -g y := rfl + rw [h, minimalResolventReal_neg R emb] + rw [hrewrite, minimalResolventReal_add R emb hemb hmono hlam hf hg.neg hfD + (fun y ↦ by simpa using hgE y) x, hneg] + ring + +end Additive + +section ResolventEquation + + +/-- The real form of the supremum resolvent, composed with itself, in extended-real terms. -/ +theorem minimalResolventReal_comp (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam mu : ℝ} (hlam : 0 < lam) (hmu : 0 < mu) {f : alpha → ℝ} {D : ℝ} + (hf : Measurable f) (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + minimalResolventReal R emb lam (fun z ↦ minimalResolventReal R emb mu f z) x = + (minimalResolvent R emb lam + (fun z ↦ minimalResolvent R emb mu (fun y ↦ ENNReal.ofReal (f y)) z) x).toReal - + (minimalResolvent R emb lam + (fun z ↦ minimalResolvent R emb mu (fun y ↦ ENNReal.ofReal (-f y)) z) x).toReal := by + set u : alpha → ℝ := fun z ↦ + (minimalResolvent R emb mu (fun y ↦ ENNReal.ofReal (f y)) z).toReal with hu + set v : alpha → ℝ := fun z ↦ + (minimalResolvent R emb mu (fun y ↦ ENNReal.ofReal (-f y)) z).toReal with hv + have hfneg : ∀ y, |(-f y)| ≤ D := fun y ↦ by rw [abs_neg]; exact hfD y + have humeas : Measurable u := + (measurable_minimalResolvent R emb hemb mu + (ENNReal.measurable_ofReal.comp hf)).ennreal_toReal + have hvmeas : Measurable v := + (measurable_minimalResolvent R emb hemb mu + (ENNReal.measurable_ofReal.comp hf.neg)).ennreal_toReal + have hu0 : ∀ z, 0 ≤ u z := fun z ↦ ENNReal.toReal_nonneg + have hv0 : ∀ z, 0 ≤ v z := fun z ↦ ENNReal.toReal_nonneg + have huD : ∀ z, |u z| ≤ D / mu := fun z ↦ by + rw [abs_of_nonneg (hu0 z)] + exact minimalResolvent_ofReal_toReal_le R emb hemb hmu hfD z + have hvD : ∀ z, |v z| ≤ D / mu := fun z ↦ by + rw [abs_of_nonneg (hv0 z)] + exact minimalResolvent_ofReal_toReal_le R emb hemb hmu hfneg z + have hsplit : (fun z ↦ minimalResolventReal R emb mu f z) = fun z ↦ u z - v z := rfl + have hofu : (fun z ↦ ENNReal.ofReal (u z)) = + fun z ↦ minimalResolvent R emb mu (fun y ↦ ENNReal.ofReal (f y)) z := by + funext z + exact ENNReal.ofReal_toReal (minimalResolvent_ofReal_ne_top R emb hemb hmu hfD z) + have hofv : (fun z ↦ ENNReal.ofReal (v z)) = + fun z ↦ minimalResolvent R emb mu (fun y ↦ ENNReal.ofReal (-f y)) z := by + funext z + exact ENNReal.ofReal_toReal (minimalResolvent_ofReal_ne_top R emb hemb hmu hfneg z) + rw [hsplit, minimalResolventReal_sub R emb hemb hmono hlam humeas hvmeas huD hvD x, + minimalResolventReal_of_nonneg R emb hemb hlam hu0 x, + minimalResolventReal_of_nonneg R emb hemb hlam hv0 x, hofu, hofv] + +/-- **The real form at two shifts commutes** on bounded measurable observables. -/ +theorem minimalResolventReal_comm (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam mu : ℝ} (hlam : 0 < lam) (hmu : 0 < mu) {f : alpha → ℝ} {D : ℝ} + (hf : Measurable f) (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + minimalResolventReal R emb lam (fun z ↦ minimalResolventReal R emb mu f z) x = + minimalResolventReal R emb mu (fun z ↦ minimalResolventReal R emb lam f z) x := by + rw [minimalResolventReal_comp R emb hemb hmono hlam hmu hf hfD x, + minimalResolventReal_comp R emb hemb hmono hmu hlam hf hfD x, + minimalResolvent_comm R emb hemb hmono hlam hmu + (f := fun y ↦ ENNReal.ofReal (f y)) (ENNReal.measurable_ofReal.comp hf) x, + minimalResolvent_comm R emb hemb hmono hlam hmu + (f := fun y ↦ ENNReal.ofReal (-f y)) (ENNReal.measurable_ofReal.comp hf.neg) x] + +/-- **The resolvent equation in real form** on bounded measurable observables. -/ +theorem minimalResolventReal_resolventEquation (hemb : ∀ m, MeasurableEmbedding (emb m)) + (hmono : ∀ nu > 0, ∀ {h : alpha → ℝ≥0∞}, Measurable h → ∀ y, + Monotone fun m ↦ localResolvent R emb m nu h y) + {lam mu : ℝ} (hlam : 0 < lam) (hlt : lam < mu) {f : alpha → ℝ} {D : ℝ} + (hf : Measurable f) (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + minimalResolventReal R emb lam f x = + minimalResolventReal R emb mu f x + + (mu - lam) * minimalResolventReal R emb lam + (fun z ↦ minimalResolventReal R emb mu f z) x := by + have hmu : 0 < mu := hlam.trans hlt + have hfneg : ∀ y, |(-f y)| ≤ D := fun y ↦ by rw [abs_neg]; exact hfD y + -- the extended-real resolvent equation, on the positive and on the negative part + have hstep : ∀ (h : alpha → ℝ), Measurable h → (∀ y, |h y| ≤ D) → + (minimalResolvent R emb lam (fun y ↦ ENNReal.ofReal (h y)) x).toReal = + (minimalResolvent R emb mu (fun y ↦ ENNReal.ofReal (h y)) x).toReal + + (mu - lam) * (minimalResolvent R emb lam + (fun z ↦ minimalResolvent R emb mu (fun y ↦ ENNReal.ofReal (h y)) z) x).toReal := by + intro h hmeas hbound + have hmeasE : Measurable fun y ↦ ENNReal.ofReal (h y) := + ENNReal.measurable_ofReal.comp hmeas + have hinnermeas : Measurable fun z ↦ + minimalResolvent R emb mu (fun y ↦ ENNReal.ofReal (h y)) z := + measurable_minimalResolvent R emb hemb mu hmeasE + have hinnerbound : ∀ z, minimalResolvent R emb mu (fun y ↦ ENNReal.ofReal (h y)) z ≤ + ENNReal.ofReal D * ENNReal.ofReal mu⁻¹ := + fun z ↦ minimalResolvent_le_of_le_const R emb hemb hmu + (fun y ↦ ENNReal.ofReal_le_ofReal ((le_abs_self (h y)).trans (hbound y))) z + have houter : minimalResolvent R emb lam + (fun z ↦ minimalResolvent R emb mu (fun y ↦ ENNReal.ofReal (h y)) z) x ≠ ⊤ := + minimalResolvent_ne_top R emb hemb hlam + (ENNReal.mul_ne_top ENNReal.ofReal_ne_top ENNReal.ofReal_ne_top) hinnerbound x + have hmid : minimalResolvent R emb mu (fun y ↦ ENNReal.ofReal (h y)) x ≠ ⊤ := + minimalResolvent_ofReal_ne_top R emb hemb hmu hbound x + have heq := minimalResolvent_resolventEquation_of_monotone R emb hemb hmono hlam hlt + hmeasE x + rw [heq, ENNReal.toReal_add hmid + (ENNReal.mul_ne_top ENNReal.ofReal_ne_top houter), + ENNReal.toReal_mul, ENNReal.toReal_ofReal (by linarith only [hlt])] + have hpos := hstep f hf hfD + have hneg := hstep (fun y ↦ -f y) hf.neg hfneg + rw [minimalResolventReal, minimalResolventReal, + minimalResolventReal_comp R emb hemb hmono hlam hmu hf hfD x] + linarith only [hpos, hneg] + +end ResolventEquation + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingResolventEquation.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingResolventEquation.lean new file mode 100644 index 0000000000..dd755ff8bd --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingResolventEquation.lean @@ -0,0 +1,280 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential + +/-! +# The resolvent equation for a kernel resolvent + +The kernel resolvent of a sub-Markov kernel semigroup satisfies the resolvent equation + + `R_lam f = R_mu f + (mu - lam) R_lam (R_mu f)` for `0 < lam < mu` + +(`SubMarkovKernelSemigroup.kernelResolvent_resolventEquation`), as an identity of +extended-nonnegative-real valued observables, so no integrability hypothesis is needed. The proof +is the convolution identity for exponential weights + + `e^{-mu u} + (mu - lam) ∫_0^u e^{-lam s} e^{-mu (u - s)} ds = e^{-lam u}` + +(`expWeight_convolution`) together with the Chapman--Kolmogorov law, which turns the composition +of the two resolvents into a convolution in time. + +Main definitions: `expWeight`. + +The same double-integral form is symmetric in the two shifts, so the two resolvents commute +(`SubMarkovKernelSemigroup.kernelResolvent_comm`). + +Main results: `expWeight_convolution`, +`SubMarkovKernelSemigroup.kernelResolvent_eq_lintegral_expWeight`, +`SubMarkovKernelSemigroup.kernelResolvent_comp_eq_lintegral`, +`SubMarkovKernelSemigroup.kernelResolvent_comm`, +`SubMarkovKernelSemigroup.kernelResolvent_resolventEquation`. +-/ + +open Filter MeasureTheory ProbabilityTheory Set +open scoped ENNReal NNReal + +noncomputable section + +namespace MarkovProcess + +/-- The exponential weight at the shift `c`, extended by zero to nonpositive times. -/ +noncomputable def expWeight (c : ℝ) (t : ℝ) : ℝ≥0∞ := + (Set.Ioi (0 : ℝ)).indicator (fun t ↦ ENNReal.ofReal (Real.exp (-c * t))) t + +/-- The exponential weight is measurable. -/ +theorem measurable_expWeight (c : ℝ) : Measurable (expWeight c) := + (measurable_laplaceDensity c).indicator measurableSet_Ioi + +/-- At a positive time the exponential weight is the exponential density. -/ +@[simp] theorem expWeight_of_pos {c t : ℝ} (ht : 0 < t) : + expWeight c t = ENNReal.ofReal (Real.exp (-c * t)) := + Set.indicator_of_mem (Set.mem_Ioi.mpr ht) _ + +/-- At a nonpositive time the exponential weight vanishes. -/ +@[simp] theorem expWeight_of_nonpos {c t : ℝ} (ht : t ≤ 0) : expWeight c t = 0 := + Set.indicator_of_notMem (by simpa using ht) _ + +/-- Integration against the exponential weight is integration over positive times. -/ +theorem lintegral_expWeight_mul (c : ℝ) (F : ℝ → ℝ≥0∞) : + ∫⁻ t, expWeight c t * F t = ∫⁻ t in Set.Ioi (0 : ℝ), + ENNReal.ofReal (Real.exp (-c * t)) * F t := by + rw [← lintegral_indicator measurableSet_Ioi] + refine lintegral_congr fun t ↦ ?_ + by_cases ht : (0 : ℝ) < t + · rw [expWeight_of_pos ht, Set.indicator_of_mem (Set.mem_Ioi.mpr ht)] + · rw [expWeight_of_nonpos (le_of_not_gt ht), + Set.indicator_of_notMem (by simpa using ht), zero_mul] + +/-- **The convolution identity for exponential weights.** At two different shifts the difference +of the weights is the convolution of the weights, scaled by the difference of the shifts. -/ +theorem expWeight_convolution {lam mu : ℝ} (hlt : lam < mu) (u : ℝ) : + expWeight mu u + ENNReal.ofReal (mu - lam) * + ∫⁻ s, expWeight lam s * expWeight mu (u - s) = expWeight lam u := by + have hc : (0 : ℝ) < mu - lam := sub_pos.mpr hlt + have hind : (fun s ↦ expWeight lam s * expWeight mu (u - s)) = + (Set.Ioo (0 : ℝ) u).indicator + (fun s ↦ ENNReal.ofReal (Real.exp (-mu * u + (mu - lam) * s))) := by + funext s + by_cases hs : s ∈ Set.Ioo (0 : ℝ) u + · rw [Set.indicator_of_mem hs, expWeight_of_pos hs.1, + expWeight_of_pos (sub_pos.mpr hs.2), ← ENNReal.ofReal_mul (Real.exp_pos _).le, + ← Real.exp_add] + congr 2 + ring + · rw [Set.indicator_of_notMem hs] + rcases le_or_gt s 0 with h | h + · rw [expWeight_of_nonpos h, zero_mul] + · have h2 : u ≤ s := by + by_contra hcon + exact hs ⟨h, lt_of_not_ge hcon⟩ + rw [expWeight_of_nonpos (sub_nonpos.mpr h2), mul_zero] + rw [hind, lintegral_indicator measurableSet_Ioo] + rcases le_or_gt u 0 with hu | hu + · rw [expWeight_of_nonpos hu, expWeight_of_nonpos hu, + Set.Ioo_eq_empty (not_lt.mpr hu)] + simp only [Measure.restrict_empty, neg_mul, lintegral_zero_measure, mul_zero, add_zero] + · have hcont : Continuous fun s : ℝ ↦ Real.exp (-mu * u + (mu - lam) * s) := by fun_prop + have hint : IntegrableOn (fun s : ℝ ↦ Real.exp (-mu * u + (mu - lam) * s)) + (Set.Ioo (0 : ℝ) u) := + ((hcont.intervalIntegrable 0 u).1).mono_set Set.Ioo_subset_Ioc_self + have hval : ∫ s in Set.Ioo (0 : ℝ) u, Real.exp (-mu * u + (mu - lam) * s) = + (Real.exp (-lam * u) - Real.exp (-mu * u)) / (mu - lam) := by + rw [← integral_Ioc_eq_integral_Ioo, ← intervalIntegral.integral_of_le hu.le] + have hderiv : ∀ s ∈ Set.uIcc (0 : ℝ) u, HasDerivAt + (fun s : ℝ ↦ Real.exp (-mu * u + (mu - lam) * s) / (mu - lam)) + (Real.exp (-mu * u + (mu - lam) * s)) s := by + intro s _ + have h1 : HasDerivAt (fun s : ℝ ↦ -mu * u + (mu - lam) * s) (mu - lam) s := by + simpa using ((hasDerivAt_id s).const_mul (mu - lam)).const_add (-mu * u) + have h2 := (h1.exp).div_const (mu - lam) + simpa only [neg_mul, mul_div_cancel_right₀ _ hc.ne'] using h2 + rw [intervalIntegral.integral_eq_sub_of_hasDerivAt hderiv (hcont.intervalIntegrable 0 u)] + have hexp : Real.exp (-mu * u + (mu - lam) * u) = Real.exp (-lam * u) := by + congr 1 + ring + rw [hexp] + simp only [mul_zero, add_zero] + ring + have hmul : (mu - lam) * ((Real.exp (-lam * u) - Real.exp (-mu * u)) / (mu - lam)) = + Real.exp (-lam * u) - Real.exp (-mu * u) := by + field_simp + have hnn : 0 ≤ Real.exp (-lam * u) - Real.exp (-mu * u) := by + have hle : -mu * u ≤ -lam * u := by nlinarith only [hlt, hu] + exact sub_nonneg.mpr (Real.exp_le_exp.mpr hle) + rw [expWeight_of_pos hu, expWeight_of_pos hu, + ← ofReal_integral_eq_lintegral_ofReal hint + (Eventually.of_forall fun s ↦ (Real.exp_pos _).le), + hval, ← ENNReal.ofReal_mul hc.le, hmul, + ← ENNReal.ofReal_add (Real.exp_pos _).le hnn] + congr 1 + ring + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [MeasurableSpace alpha] (P : SubMarkovKernelSemigroup alpha) + +/-- Every transition measure of a sub-Markov kernel semigroup is finite. -/ +theorem isFiniteMeasure_apply (t : NNReal) (x : alpha) : IsFiniteMeasure (P t x) := + ⟨lt_of_le_of_lt (P.measure_univ_le_one t x) ENNReal.one_lt_top⟩ + +/-- The time profile of an observable from a starting point: its transition integral at each +time, read on the whole time line through the nonnegative part. -/ +noncomputable def transitionProfile (f : alpha → ℝ≥0∞) (x : alpha) (u : ℝ) : ℝ≥0∞ := + ∫⁻ y, f y ∂P (Real.toNNReal u) x + +/-- The time profile is measurable in time. -/ +theorem measurable_transitionProfile {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + Measurable (P.transitionProfile f x) := + (Measure.measurable_lintegral hf).comp (P.measurable_toMeasure_toNNReal x) + +/-- The kernel resolvent, written as an integral over the whole time line against the exponential +weight. -/ +theorem kernelResolvent_eq_lintegral_expWeight (lam : ℝ) (f : alpha → ℝ≥0∞) (x : alpha) : + P.kernelResolvent lam f x = ∫⁻ t, expWeight lam t * P.transitionProfile f x t := + (lintegral_expWeight_mul lam _).symm + +/-- The composition of two kernel resolvents is a convolution in time. -/ +theorem lintegral_kernelResolvent_eq (mu : ℝ) {f : alpha → ℝ≥0∞} (hf : Measurable f) + (x : alpha) {s : ℝ} (hs : 0 < s) : + ∫⁻ y, P.kernelResolvent mu f y ∂P (Real.toNNReal s) x = + ∫⁻ t, expWeight mu t * P.transitionProfile f x (s + t) := by + have := P.isFiniteMeasure_apply (Real.toNNReal s) x + have hjoint : Measurable fun q : alpha × ℝ ↦ + expWeight mu q.2 * ∫⁻ z, f z ∂P (Real.toNNReal q.2) q.1 := + ((measurable_expWeight mu).comp measurable_snd).mul + ((Measure.measurable_lintegral hf).comp + (P.measurable_toMeasure.comp ((measurable_real_toNNReal.comp measurable_snd).prodMk + measurable_fst))) + calc ∫⁻ y, P.kernelResolvent mu f y ∂P (Real.toNNReal s) x + = ∫⁻ y, (∫⁻ t, expWeight mu t * ∫⁻ z, f z ∂P (Real.toNNReal t) y) + ∂P (Real.toNNReal s) x := + lintegral_congr fun y ↦ P.kernelResolvent_eq_lintegral_expWeight mu f y + _ = ∫⁻ t, ∫⁻ y, expWeight mu t * (∫⁻ z, f z ∂P (Real.toNNReal t) y) + ∂P (Real.toNNReal s) x := lintegral_lintegral_swap hjoint.aemeasurable + _ = ∫⁻ t, expWeight mu t * ∫⁻ y, (∫⁻ z, f z ∂P (Real.toNNReal t) y) + ∂P (Real.toNNReal s) x := + lintegral_congr fun t ↦ lintegral_const_mul _ + ((Measure.measurable_lintegral hf).comp + (P.measurable_toMeasure.comp (measurable_const.prodMk measurable_id))) + _ = ∫⁻ t, expWeight mu t * P.transitionProfile f x (s + t) := by + refine lintegral_congr fun t ↦ ?_ + rcases le_or_gt t 0 with ht | ht + · rw [expWeight_of_nonpos ht, zero_mul, zero_mul] + · rw [transitionProfile, Real.toNNReal_add hs.le ht.le, P.lintegral_add _ _ x hf] + +/-- **The composition of two kernel resolvents is a double integral in time**, against the +product of the two exponential weights. -/ +theorem kernelResolvent_comp_eq_lintegral (lam mu : ℝ) {f : alpha → ℝ≥0∞} (hf : Measurable f) + (x : alpha) : + P.kernelResolvent lam (P.kernelResolvent mu f) x = + ∫⁻ s, ∫⁻ t, (expWeight lam s * expWeight mu t) * P.transitionProfile f x (s + t) := by + have hFmeas : Measurable (P.transitionProfile f x) := P.measurable_transitionProfile hf x + rw [P.kernelResolvent_eq_lintegral_expWeight lam _ x] + refine lintegral_congr fun s ↦ ?_ + rcases le_or_gt s 0 with hs | hs + · rw [expWeight_of_nonpos hs, zero_mul] + symm + simp only [zero_mul, lintegral_const, measure_univ_of_isAddLeftInvariant] + · have hgmeas : Measurable fun t : ℝ ↦ + expWeight mu t * P.transitionProfile f x (s + t) := + (measurable_expWeight mu).mul (hFmeas.comp (measurable_const_add s)) + rw [transitionProfile, P.lintegral_kernelResolvent_eq mu hf x hs, + ← lintegral_const_mul _ hgmeas] + exact lintegral_congr fun t ↦ (mul_assoc _ _ _).symm + +/-- **The kernel resolvents at two shifts commute**: their composition is a double integral +which is symmetric in the two shifts. -/ +theorem kernelResolvent_comm (lam mu : ℝ) {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + P.kernelResolvent lam (P.kernelResolvent mu f) x = + P.kernelResolvent mu (P.kernelResolvent lam f) x := by + have hFmeas : Measurable (P.transitionProfile f x) := P.measurable_transitionProfile hf x + have hjoint : Measurable fun q : ℝ × ℝ ↦ + (expWeight lam q.1 * expWeight mu q.2) * P.transitionProfile f x (q.1 + q.2) := + (((measurable_expWeight lam).comp measurable_fst).mul + ((measurable_expWeight mu).comp measurable_snd)).mul + (hFmeas.comp (measurable_fst.add measurable_snd)) + rw [P.kernelResolvent_comp_eq_lintegral lam mu hf x, + P.kernelResolvent_comp_eq_lintegral mu lam hf x, + lintegral_lintegral_swap hjoint.aemeasurable] + refine lintegral_congr fun t ↦ lintegral_congr fun s ↦ ?_ + rw [mul_comm (expWeight lam s) (expWeight mu t), add_comm s t] + +/-- **The resolvent equation.** At two different positive shifts the kernel resolvents differ by +their composition, scaled by the difference of the shifts. -/ +theorem kernelResolvent_resolventEquation {lam mu : ℝ} (hlt : lam < mu) + {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + P.kernelResolvent lam f x = + P.kernelResolvent mu f x + + ENNReal.ofReal (mu - lam) * P.kernelResolvent lam (P.kernelResolvent mu f) x := by + have hFmeas : Measurable (P.transitionProfile f x) := P.measurable_transitionProfile hf x + have hprodmeas : Measurable fun q : ℝ × ℝ ↦ + (expWeight lam q.1 * expWeight mu (q.2 - q.1)) * P.transitionProfile f x q.2 := + (((measurable_expWeight lam).comp measurable_fst).mul + ((measurable_expWeight mu).comp (measurable_snd.sub measurable_fst))).mul + (hFmeas.comp measurable_snd) + have hconvmeas : Measurable fun u : ℝ ↦ ∫⁻ s, expWeight lam s * expWeight mu (u - s) := by + have hj : Measurable fun q : ℝ × ℝ ↦ expWeight lam q.2 * expWeight mu (q.1 - q.2) := + ((measurable_expWeight lam).comp measurable_snd).mul + ((measurable_expWeight mu).comp (measurable_fst.sub measurable_snd)) + exact hj.lintegral_prod_right' + have hdouble := P.kernelResolvent_comp_eq_lintegral lam mu hf x + have hshift : ∀ s : ℝ, + (∫⁻ t, (expWeight lam s * expWeight mu t) * P.transitionProfile f x (s + t)) = + ∫⁻ v, (expWeight lam s * expWeight mu (v - s)) * P.transitionProfile f x v := by + intro s + rw [← lintegral_add_right_eq_self + (fun v ↦ (expWeight lam s * expWeight mu (v - s)) * P.transitionProfile f x v) s] + refine lintegral_congr fun t ↦ ?_ + rw [add_sub_cancel_right, add_comm t s] + have hswap : + (∫⁻ s, ∫⁻ t, (expWeight lam s * expWeight mu t) * P.transitionProfile f x (s + t)) = + ∫⁻ u, (∫⁻ s, expWeight lam s * expWeight mu (u - s)) * + P.transitionProfile f x u := by + simp_rw [hshift] + rw [lintegral_lintegral_swap hprodmeas.aemeasurable] + refine lintegral_congr fun v ↦ ?_ + exact lintegral_mul_const _ ((measurable_expWeight lam).mul + ((measurable_expWeight mu).comp (measurable_const.sub measurable_id))) + have hconst : ENNReal.ofReal (mu - lam) * + ∫⁻ u, (∫⁻ s, expWeight lam s * expWeight mu (u - s)) * P.transitionProfile f x u = + ∫⁻ u, ENNReal.ofReal (mu - lam) * + ((∫⁻ s, expWeight lam s * expWeight mu (u - s)) * P.transitionProfile f x u) := + (lintegral_const_mul _ (hconvmeas.mul hFmeas)).symm + have hadd : (∫⁻ u, expWeight mu u * P.transitionProfile f x u) + + ∫⁻ u, ENNReal.ofReal (mu - lam) * + ((∫⁻ s, expWeight lam s * expWeight mu (u - s)) * P.transitionProfile f x u) = + ∫⁻ u, expWeight mu u * P.transitionProfile f x u + + ENNReal.ofReal (mu - lam) * + ((∫⁻ s, expWeight lam s * expWeight mu (u - s)) * P.transitionProfile f x u) := + (lintegral_add_left ((measurable_expWeight mu).mul hFmeas) _).symm + rw [hdouble, hswap, P.kernelResolvent_eq_lintegral_expWeight lam f x, + P.kernelResolvent_eq_lintegral_expWeight mu f x, hconst, hadd] + refine lintegral_congr fun u ↦ ?_ + rw [← mul_assoc, ← add_mul, expWeight_convolution hlt u] + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingTransfer.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingTransfer.lean new file mode 100644 index 0000000000..b7e49ef63f --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingTransfer.lean @@ -0,0 +1,133 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.MeasureTheory.Integral.RieszMarkovKakutani.NNReal +import Mathlib.Topology.ContinuousMap.CompactlySupported +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential + +/-! +# From vanishing observables to measurable ones + +An identity between a measure `nu` on a target space and a measure `mu` on a source space, +tested on observables which are supported in the range of a measurable embedding `i` and +extended by zero off it, propagates from continuous observables vanishing at infinity to all +nonnegative measurable observables +(`lintegral_extend_eq_of_forall_zeroAtInfty`). The reason is that both sides are integrals +against finite Borel measures on the source space, and continuous observables with compact +support already separate finite Borel measures on a locally compact second-countable metric +space. + +This is the bridge which upgrades an analytically supplied identity of resolvents, stated for +continuous observables vanishing at infinity, to the identity of the corresponding potential +measures. + +No topology on the target space is used, and no relation between the two measures other than the +tested identity is assumed. +-/ + +open Filter MeasureTheory ProbabilityTheory Set Topology +open scoped ENNReal NNReal ZeroAtInfty CompactlySupported + +noncomputable section + +namespace MarkovProcess + +section Topological + +variable {X : Type*} [TopologicalSpace X] + +/-- A continuous observable with compact support, read as an observable vanishing at infinity. -/ +noncomputable def compactlySupportedToZeroAtInfty (f : C_c(X, ℝ)) : C₀(X, ℝ) where + toContinuousMap := f.toContinuousMap + zero_at_infty' := HasCompactSupport.is_zero_at_infty f.hasCompactSupport' + +/-- A compactly supported function, read as an observable vanishing at infinity, keeps its +values. -/ +@[simp] theorem compactlySupportedToZeroAtInfty_apply (f : C_c(X, ℝ)) (x : X) : + compactlySupportedToZeroAtInfty f x = f x := rfl + +end Topological + +section Measurable + +variable {X Y : Type*} [MeasurableSpace X] [MeasurableSpace Y] + +/-- Integration of an observable extended by zero off the range of a measurable embedding is +integration of the observable against the pullback measure. -/ +theorem lintegral_extend_eq_lintegral_comap {i : X → Y} (hi : MeasurableEmbedding i) + (nu : Measure Y) {h : X → ℝ≥0∞} (hh : Measurable h) : + ∫⁻ z, Function.extend i h 0 z ∂nu = ∫⁻ y, h y ∂nu.comap i := by + have hext : Measurable (Function.extend i h 0) := hi.measurable_extend hh measurable_const + have hzero : Function.extend i h 0 = (Set.range i).indicator (Function.extend i h 0) := by + funext z + by_cases hz : z ∈ Set.range i + · rw [Set.indicator_of_mem hz] + · rw [Set.indicator_of_notMem hz, Function.extend_apply' _ _ _ fun hmem ↦ hz hmem] + rfl + calc ∫⁻ z, Function.extend i h 0 z ∂nu + = ∫⁻ z, (Set.range i).indicator (Function.extend i h 0) z ∂nu := by rw [← hzero] + _ = ∫⁻ z in Set.range i, Function.extend i h 0 z ∂nu := + lintegral_indicator hi.measurableSet_range _ + _ = ∫⁻ z, Function.extend i h 0 z ∂(nu.comap i).map i := by rw [hi.map_comap] + _ = ∫⁻ y, Function.extend i h 0 (i y) ∂nu.comap i := lintegral_map hext hi.measurable + _ = ∫⁻ y, h y ∂nu.comap i := by simp only [hi.injective.extend_apply] + +/-- The pullback of a finite measure along a measurable embedding is finite. -/ +theorem isFiniteMeasure_comap {i : X → Y} (hi : MeasurableEmbedding i) (nu : Measure Y) + [IsFiniteMeasure nu] : IsFiniteMeasure (nu.comap i) := by + refine ⟨?_⟩ + have hmass : (nu.comap i).map i Set.univ = nu.comap i Set.univ := by + rw [Measure.map_apply hi.measurable MeasurableSet.univ, Set.preimage_univ] + rw [← hmass, hi.map_comap] + exact lt_of_le_of_lt (Measure.restrict_le_self Set.univ) (measure_lt_top nu Set.univ) + +end Measurable + +section Transfer + +variable {X Y : Type*} [MetricSpace X] [LocallyCompactSpace X] [SecondCountableTopology X] + [MeasurableSpace X] [BorelSpace X] [MeasurableSpace Y] + +/-- **Testing an identity of measures on vanishing observables is enough.** If a measure on the +target and a measure on the source assign the same integral to every nonnegative continuous +observable vanishing at infinity, extended by zero off the range of a measurable embedding, then +they assign the same integral to every nonnegative measurable observable. -/ +theorem lintegral_extend_eq_of_forall_zeroAtInfty {i : X → Y} (hi : MeasurableEmbedding i) + (nu : Measure Y) (mu : Measure X) [IsFiniteMeasure nu] [IsFiniteMeasure mu] + (hc0 : ∀ f : C₀(X, ℝ), (∀ y, 0 ≤ f y) → + ∫⁻ z, Function.extend i (fun y ↦ ENNReal.ofReal (f y)) 0 z ∂nu = + ∫⁻ y, ENNReal.ofReal (f y) ∂mu) + {g : X → ℝ≥0∞} (hg : Measurable g) : + ∫⁻ z, Function.extend i g 0 z ∂nu = ∫⁻ y, g y ∂mu := by + have : IsFiniteMeasure (nu.comap i) := isFiniteMeasure_comap hi nu + have hpull : nu.comap i = mu := by + refine Measure.ext_of_integral_eq_on_compactlySupported_nnreal fun f ↦ ?_ + set F : C₀(X, ℝ) := compactlySupportedToZeroAtInfty f.toReal with hF + have hFapp : ∀ y, F y = (f y : ℝ) := by + intro y + rw [hF, compactlySupportedToZeroAtInfty_apply, + CompactlySupportedContinuousMap.toReal_apply] + have hF0 : ∀ y, 0 ≤ F y := fun y ↦ by rw [hFapp y]; exact (f y).coe_nonneg + have hFmeas : Measurable fun y ↦ ENNReal.ofReal (F y) := + ENNReal.measurable_ofReal.comp F.continuous.measurable + have hkey : ∫⁻ y, ENNReal.ofReal (F y) ∂nu.comap i = ∫⁻ y, ENNReal.ofReal (F y) ∂mu := by + rw [← lintegral_extend_eq_lintegral_comap hi nu hFmeas] + exact hc0 F hF0 + have h1 : ENNReal.ofReal (∫ y, F y ∂nu.comap i) = + ∫⁻ y, ENNReal.ofReal (F y) ∂nu.comap i := + ofReal_integral_eq_lintegral_ofReal (F.toBCF.integrable (nu.comap i)) + (Eventually.of_forall hF0) + have h2 : ENNReal.ofReal (∫ y, F y ∂mu) = ∫⁻ y, ENNReal.ofReal (F y) ∂mu := + ofReal_integral_eq_lintegral_ofReal (F.toBCF.integrable mu) (Eventually.of_forall hF0) + have hreal : ENNReal.ofReal (∫ y, F y ∂nu.comap i) = ENNReal.ofReal (∫ y, F y ∂mu) := by + rw [h1, hkey, ← h2] + have hbochner : ∫ y, F y ∂nu.comap i = ∫ y, F y ∂mu := + (ENNReal.ofReal_eq_ofReal_iff (integral_nonneg hF0) (integral_nonneg hF0)).mp hreal + simpa only [hFapp] using hbochner + rw [lintegral_extend_eq_lintegral_comap hi nu hg, hpull] + +end Transfer + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Kernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Kernel.lean new file mode 100644 index 0000000000..33e449bd49 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Kernel.lean @@ -0,0 +1,242 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Main +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift + +/-! +# The process killed at the exit time of an open set: transition kernels + +For the continuous-path process `Q = continuousProcess P hP` of a conservative Feller semigroup +and an open set `U`, the transition kernel at time `t` of the process **killed when it leaves +`U`** is + + `killedKernel P hP U hU t x B = Q x {ω | t < exitTime U ω ∧ ω t ∈ B}`, + +the law of the position at time `t` restricted to the survival event `{t < τ_U}`. This file +proves that these kernels are sub-Markov (`isSubMarkovKernel_killedKernel`), jointly measurable +in time and starting point (`measurable_killedKernel`), vanish off `U` +(`killedKernel_apply_of_notMem`), reduce at time zero to the identity restricted to `U` +(`killedKernel_zero`), and satisfy the Chapman--Kolmogorov law `killedKernel_add`, + + `killedKernel (s + t) = killedKernel t ∘ₖ killedKernel s`, + +which follows from the Markov property of `Q` at the deterministic time `s` on the +`𝓕_s`-event `{s < τ_U}` together with the path identity `{s + t < τ} = {s < τ} ∩ {t < τ ∘ θ_s}`. + +On the carrier `alpha` the family is not a `SubMarkovKernelSemigroup`, because at time zero it is +the identity only on `U` (it is `0` off `U`); the semigroup structure on the carrier `U` is a +separate packaging. No Feller property of the killed family is claimed. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace ContinuousPath + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +/-- The event that a path is still inside `U` at time `t` and sits in `B` at time `t`. -/ +def killedEvent (U : Set alpha) (t : NNReal) (B : Set alpha) : Set (ContinuousPath alpha) := + {omega | (t : ℝ≥0∞) < exitTime U omega ∧ omega t ∈ B} + +/-- Membership in the killed event, unfolded. -/ +theorem mem_killedEvent_iff (U : Set alpha) (t : NNReal) (B : Set alpha) + (omega : ContinuousPath alpha) : + omega ∈ killedEvent U t B ↔ (t : ℝ≥0∞) < exitTime U omega ∧ omega t ∈ B := + Iff.rfl + +/-- The killed event of the whole space is the survival event. -/ +theorem killedEvent_univ (U : Set alpha) (t : NNReal) : + killedEvent U t Set.univ = {omega | (t : ℝ≥0∞) < exitTime U omega} := by + ext omega + simp only [mem_killedEvent_iff, Set.mem_univ, and_true, Set.mem_ofPred_eq] + +/-- The killed event at time `s + t` is the survival event at time `s` intersected with the +killed event at time `t` of the path shifted by `s`. -/ +theorem killedEvent_add (U : Set alpha) (s t : NNReal) (B : Set alpha) : + killedEvent U (s + t) B = + shift s ⁻¹' killedEvent U t B ∩ {omega | (s : ℝ≥0∞) < exitTime U omega} := by + ext omega + simp only [mem_killedEvent_iff, Set.mem_inter_iff, Set.mem_preimage, Set.mem_ofPred_eq, + shift_apply] + constructor + · rintro ⟨hlt, hmem⟩ + obtain ⟨hs, ht⟩ := (coe_add_lt_exitTime_iff U omega s t).mp hlt + exact ⟨⟨ht, hmem⟩, hs⟩ + · rintro ⟨⟨ht, hmem⟩, hs⟩ + exact ⟨(coe_add_lt_exitTime_iff U omega s t).mpr ⟨hs, ht⟩, hmem⟩ + +variable [MeasurableSpace alpha] [BorelSpace alpha] + +/-- The killed event of a measurable set is measurable. -/ +theorem measurableSet_killedEvent (U : Set alpha) (hU : IsOpen U) (t : NNReal) {B : Set alpha} + (hB : MeasurableSet B) : MeasurableSet (killedEvent U t B) := + (measurableSet_lt_exitTime U hU t).inter + ((measurable_coordinateProcess (alpha := alpha) t) hB) + +omit [MeasurableSpace alpha] [BorelSpace alpha] in +/-- A path is inside an open set `U` at time zero exactly when its exit time from `U` is +positive. -/ +theorem exitTime_pos_iff (U : Set alpha) (hU : IsOpen U) (omega : ContinuousPath alpha) : + 0 < exitTime U omega ↔ omega 0 ∈ U := by + constructor + · intro h + exact mem_of_lt_exitTime U omega 0 (by rwa [ENNReal.coe_zero]) + · intro h + by_contra hle + rw [not_lt, ← ENNReal.coe_zero, exitTime_le_iff_mem_hitsSetBy U hU 0 omega] at hle + obtain ⟨s, hs⟩ := hle + have hs0 : (s : NNReal) = 0 := le_antisymm (Set.mem_Iic.mp s.2) zero_le + rw [hs0] at hs + exact hs h + +end ContinuousPath + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) +variable (U : Set alpha) (hU : IsOpen U) + +/-- The transition kernel at time `t` of the continuous-path process of `P` killed when it leaves +the open set `U`: the law of the position at time `t`, restricted to the event that the path has +not yet left `U`. -/ +noncomputable def IsConservative.killedKernel (t : NNReal) : Kernel alpha alpha := + Kernel.map ((IsConservative.continuousProcess P hP).restrict + (ContinuousPath.measurableSet_lt_exitTime U hU t)) (fun omega ↦ omega t) + +/-- The killed kernel at time `t` started at `x` is the image of the law of the process, restricted +to the survival event `{t < τ_U}`, under evaluation at time `t`. -/ +theorem IsConservative.killedKernel_eq_map (t : NNReal) (x : alpha) : + IsConservative.killedKernel P hP U hU t x = + ((IsConservative.continuousProcess P hP x).restrict + {omega | (t : ℝ≥0∞) < ContinuousPath.exitTime U omega}).map (fun omega ↦ omega t) := by + have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ omega t) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) t + rw [IsConservative.killedKernel, Kernel.map_apply _ hmeas, Kernel.restrict_apply] + +/-- The killed kernel evaluated on a measurable set: the probability that the process is still in +`U` at time `t` and sits in `B` at time `t`. -/ +theorem IsConservative.killedKernel_apply (t : NNReal) (x : alpha) {B : Set alpha} + (hB : MeasurableSet B) : + IsConservative.killedKernel P hP U hU t x B = + IsConservative.continuousProcess P hP x (ContinuousPath.killedEvent U t B) := by + have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ omega t) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) t + rw [IsConservative.killedKernel_eq_map, Measure.map_apply hmeas hB, + Measure.restrict_apply (hmeas hB)] + congr 1 + ext omega + simp only [Set.mem_inter_iff, Set.mem_preimage, Set.mem_ofPred_eq, + ContinuousPath.mem_killedEvent_iff] + exact and_comm + +/-- The total mass of the killed kernel is the survival probability `Q x {t < τ_U}`. -/ +theorem IsConservative.killedKernel_apply_univ (t : NNReal) (x : alpha) : + IsConservative.killedKernel P hP U hU t x Set.univ = + IsConservative.continuousProcess P hP x + {omega | (t : ℝ≥0∞) < ContinuousPath.exitTime U omega} := by + rw [IsConservative.killedKernel_apply P hP U hU t x MeasurableSet.univ, + ContinuousPath.killedEvent_univ] + +/-- The killed kernels are sub-Markov. -/ +theorem IsConservative.isSubMarkovKernel_killedKernel (t : NNReal) : + IsSubMarkovKernel (IsConservative.killedKernel P hP U hU t) := by + intro x + rw [IsConservative.killedKernel_apply_univ] + exact prob_le_one + +/-- The killed kernels are jointly measurable in the time and the starting point. -/ +theorem IsConservative.measurable_killedKernel : + Measurable fun q : NNReal × alpha ↦ IsConservative.killedKernel P hP U hU q.1 q.2 := by + refine Measure.measurable_of_measurable_coe _ fun B hB ↦ ?_ + have hfun : (fun q : NNReal × alpha ↦ IsConservative.killedKernel P hP U hU q.1 q.2 B) = + fun q ↦ IsConservative.continuousProcess P hP q.2 (ContinuousPath.killedEvent U q.1 B) := + funext fun q ↦ IsConservative.killedKernel_apply P hP U hU q.1 q.2 hB + rw [hfun] + have heval : Measurable fun p : NNReal × ContinuousPath alpha ↦ p.2 p.1 := + (ContinuousEval.continuous_eval.comp continuous_swap).measurable + have hS : MeasurableSet {p : (NNReal × alpha) × ContinuousPath alpha | + (p.1.1 : ℝ≥0∞) < ContinuousPath.exitTime U p.2 ∧ p.2 p.1.1 ∈ B} := by + refine MeasurableSet.inter ?_ ?_ + · exact measurableSet_lt (measurable_coe_nnreal_ennreal.comp measurable_fst.fst) + ((ContinuousPath.measurable_exitTime U hU).comp measurable_snd) + · exact (heval.comp (measurable_fst.fst.prodMk measurable_snd)) hB + exact Kernel.measurable_kernel_prodMk_left + (κ := Kernel.prodMkLeft NNReal (IsConservative.continuousProcess P hP)) hS + +/-- Off `U` the killed kernels vanish: a path started outside `U` has exit time zero. -/ +theorem IsConservative.killedKernel_apply_of_notMem (hK : P.KolmogorovRegular hP) (t : NNReal) + {x : alpha} (hx : x ∉ U) : IsConservative.killedKernel P hP U hU t x = 0 := by + have hmeas0 : Measurable (fun omega : ContinuousPath alpha ↦ omega 0) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) 0 + have hzero : IsConservative.continuousProcess P hP x {omega | omega 0 ∈ U} = 0 := by + have h := congrArg (fun mu : Measure alpha ↦ mu U) + (IsConservative.continuousProcess_map_eval_zero P hP hK ▸ rfl : + (IsConservative.continuousProcess P hP).map (fun omega ↦ omega 0) x = Kernel.id x) + rw [Kernel.map_apply _ hmeas0, Measure.map_apply hmeas0 hU.measurableSet, Kernel.id_apply, + Measure.dirac_apply' x hU.measurableSet, Set.indicator_of_notMem hx] at h + exact h + refine Measure.ext fun B hB ↦ ?_ + rw [IsConservative.killedKernel_apply P hP U hU t x hB, Measure.coe_zero, Pi.zero_apply] + refine measure_mono_null (fun omega homega ↦ ?_) hzero + obtain ⟨hlt, -⟩ := (ContinuousPath.mem_killedEvent_iff U t B omega).mp homega + exact (ContinuousPath.exitTime_pos_iff U hU omega).mp (lt_of_le_of_lt zero_le hlt) + +/-- At time zero the killed kernel is the identity kernel restricted to `U`: the Dirac mass at the +starting point if it lies in `U`, and zero otherwise. -/ +theorem IsConservative.killedKernel_zero (hK : P.KolmogorovRegular hP) : + IsConservative.killedKernel P hP U hU 0 = Kernel.id.restrict hU.measurableSet := by + have hmeas0 : Measurable (fun omega : ContinuousPath alpha ↦ omega 0) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) 0 + refine Kernel.ext fun x ↦ Measure.ext fun B hB ↦ ?_ + have hevent : ContinuousPath.killedEvent U 0 B = (fun omega : ContinuousPath alpha ↦ omega 0) ⁻¹' + (B ∩ U) := by + ext omega + simp only [ContinuousPath.mem_killedEvent_iff, ENNReal.coe_zero, Set.mem_preimage, + Set.mem_inter_iff, ContinuousPath.exitTime_pos_iff U hU] + exact and_comm + rw [IsConservative.killedKernel_apply P hP U hU 0 x hB, hevent, + ← Measure.map_apply hmeas0 (hB.inter hU.measurableSet), ← Kernel.map_apply _ hmeas0, + IsConservative.continuousProcess_map_eval_zero P hP hK, Kernel.restrict_apply' _ _ _ hB] + +variable [LocallyCompactSpace alpha] + +/-- **Chapman--Kolmogorov law for the killed kernels**: `killedKernel (s + t) = killedKernel t ∘ₖ +killedKernel s`. It follows from the Markov property of the process at the deterministic time `s` +on the `𝓕_s`-event `{s < τ_U}`, and the path identity `{s + t < τ_U} = {s < τ_U} ∩ {t < τ_U ∘ θ_s}`. -/ +theorem IsConservative.killedKernel_add (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) (s t : NNReal) : + IsConservative.killedKernel P hP U hU (s + t) = + (IsConservative.killedKernel P hP U hU t).comp (IsConservative.killedKernel P hP U hU s) := by + refine Kernel.ext fun x ↦ Measure.ext fun B hB ↦ ?_ + have hmeas_s : Measurable (fun omega : ContinuousPath alpha ↦ omega s) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) s + have hE : MeasurableSet (ContinuousPath.killedEvent U t B) := + ContinuousPath.measurableSet_killedEvent U hU t hB + have hA := ContinuousPath.measurableSet_lt_exitTime_canonicalFiltration U hU s + have hrestart := congrArg (fun mu : Measure (ContinuousPath alpha) ↦ + mu (ContinuousPath.killedEvent U t B)) + (hFeller.continuousProcess_restrict_map_shift P hP hK x s _ hA) + rw [Measure.map_apply (ContinuousPath.measurable_shift_fixed s) hE, + Measure.restrict_apply ((ContinuousPath.measurable_shift_fixed s) hE), + Measure.bind_apply hE (Kernel.aemeasurable _)] at hrestart + have hfun : (fun y ↦ IsConservative.killedKernel P hP U hU t y B) = + fun y ↦ IsConservative.continuousProcess P hP y (ContinuousPath.killedEvent U t B) := + funext fun y ↦ IsConservative.killedKernel_apply P hP U hU t y hB + rw [Kernel.comp_apply' _ _ _ hB, hfun, IsConservative.killedKernel_apply P hP U hU (s + t) x hB, + IsConservative.killedKernel_eq_map P hP U hU s x, + lintegral_map ((IsConservative.continuousProcess P hP).measurable_coe hE) hmeas_s, + ContinuousPath.killedEvent_add] + exact hrestart + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/KillAtExit.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/KillAtExit.lean new file mode 100644 index 0000000000..bb782f5a38 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/KillAtExit.lean @@ -0,0 +1,210 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift + +/-! +# Killing a continuous path at the exit time of a set + +A continuous path `omega` and a set `U` determine a path with a lifetime: keep the path as long +as it stays in `U`, and send it to the cemetery from the exit time `ContinuousPath.exitTime U` +onwards. This file defines that operation, + + `ContinuousPath.killAtExit U omega : LifetimePath U`, + +whose lifetime is the exit time and whose live path is the original path read in the carrier `U`. + +The main facts are the two coordinate formulas `coordinate_killAtExit_of_lt` and +`coordinate_killAtExit_of_le`, the shift identity `coordinate_killAtExit_shift` (before the exit +time, the coordinates of the killed shifted path are the later coordinates of the killed path), +and, for an open set `U`, the measurability `measurable_killAtExit` of the killing map for the +lifetime-path measurable structure generated by the lifetime and the coordinates. + +This file constructs no probability law. +-/ + +open MeasureTheory +open scoped ENNReal NNReal + +namespace MarkovProcess + +section SubtypeImage + +variable {alpha : Type*} (U : Set alpha) + +/-- A point of `U` lies in the image of a set of the carrier `U` exactly when the corresponding +element of the carrier lies in that set. -/ +theorem mem_image_val_iff {C : Set U} {y : alpha} (hy : y ∈ U) : + y ∈ Subtype.val '' C ↔ (⟨y, hy⟩ : U) ∈ C := by + rw [Subtype.coe_image, Set.mem_ofPred_eq] + exact ⟨fun h ↦ h.choose_spec, fun h ↦ ⟨hy, h⟩⟩ + +end SubtypeImage + +namespace ContinuousPath + +noncomputable section + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +/-- The continuous path `omega` killed when it leaves `U`: the lifetime path whose lifetime is the +exit time of `U` and whose live path is `omega`, read as a path in the carrier `U`. -/ +def killAtExit (U : Set alpha) (omega : ContinuousPath alpha) : LifetimePath U where + lifetime := exitTime U omega + livePath := fun t ↦ ⟨omega (t : NNReal), mem_of_lt_exitTime U omega (t : NNReal) t.property⟩ + continuous_livePath := by + apply Continuous.subtype_mk + exact omega.continuous.comp continuous_subtype_val + +@[simp] +theorem lifetime_killAtExit (U : Set alpha) (omega : ContinuousPath alpha) : + (killAtExit U omega).lifetime = exitTime U omega := + rfl + +/-- Strictly before the exit time, the killed path is alive at the position of the original +path. -/ +theorem coordinate_killAtExit_of_lt (U : Set alpha) (omega : ContinuousPath alpha) (t : NNReal) + (ht : (t : ℝ≥0∞) < exitTime U omega) : + LifetimePath.coordinate t (killAtExit U omega) = + Cemetery.alive ⟨omega t, mem_of_lt_exitTime U omega t ht⟩ := + LifetimePath.coordinate_of_lt (killAtExit U omega) t ht + +/-- From the exit time onwards, the killed path sits at the cemetery. -/ +theorem coordinate_killAtExit_of_le (U : Set alpha) (omega : ContinuousPath alpha) (t : NNReal) + (ht : exitTime U omega ≤ (t : ℝ≥0∞)) : + LifetimePath.coordinate t (killAtExit U omega) = Cemetery.delta := + LifetimePath.coordinate_of_le (killAtExit U omega) t ht + +/-- Once the path has left `U` by time `t`, every later coordinate of the killed path is the +cemetery state. -/ +theorem coordinate_killAtExit_of_exitTime_le (U : Set alpha) (omega : ContinuousPath alpha) + {t s : NNReal} (ht : exitTime U omega ≤ (t : ℝ≥0∞)) (hts : t ≤ s) : + LifetimePath.coordinate s (killAtExit U omega) = Cemetery.delta := + coordinate_killAtExit_of_le U omega s (ht.trans (ENNReal.coe_le_coe.mpr hts)) + +/-- The coordinates of the killed path, in closed form. -/ +theorem coordinate_killAtExit (U : Set alpha) (omega : ContinuousPath alpha) (t : NNReal) : + LifetimePath.coordinate t (killAtExit U omega) = + if ht : (t : ℝ≥0∞) < exitTime U omega then + Cemetery.alive ⟨omega t, mem_of_lt_exitTime U omega t ht⟩ + else Cemetery.delta := by + by_cases ht : (t : ℝ≥0∞) < exitTime U omega + · rw [dif_pos ht, coordinate_killAtExit_of_lt U omega t ht] + · rw [dif_neg ht, coordinate_killAtExit_of_le U omega t (not_lt.mp ht)] + +/-- **Shift identity for the killed path.** Strictly before the exit time of `U`, killing the +path shifted by `t` and reading it at time `s` is the same as killing the path and reading it at +time `t + s`. -/ +theorem coordinate_killAtExit_shift (U : Set alpha) (omega : ContinuousPath alpha) (t s : NNReal) + (ht : (t : ℝ≥0∞) < exitTime U omega) : + LifetimePath.coordinate s (killAtExit U (shift t omega)) = + LifetimePath.coordinate (t + s) (killAtExit U omega) := by + by_cases hs : (s : ℝ≥0∞) < exitTime U (shift t omega) + · have hts : ((t + s : NNReal) : ℝ≥0∞) < exitTime U omega := + (coe_add_lt_exitTime_iff U omega t s).mpr ⟨ht, hs⟩ + rw [coordinate_killAtExit_of_lt U (shift t omega) s hs, + coordinate_killAtExit_of_lt U omega (t + s) hts] + exact congrArg Cemetery.alive (Subtype.ext (shift_apply t s omega)) + · have hts : ¬ ((t + s : NNReal) : ℝ≥0∞) < exitTime U omega := fun h ↦ + hs ((coe_add_lt_exitTime_iff U omega t s).mp h).2 + rw [coordinate_killAtExit_of_le U (shift t omega) s (not_lt.mp hs), + coordinate_killAtExit_of_le U omega (t + s) (not_lt.mp hts)] + +section Preimage + +variable (U : Set alpha) (t : NNReal) + +/-- The event that the killed path is alive at time `t` and its live coordinate lies in `S`. -/ +theorem preimage_coordinate_killAtExit_of_notMem {S : Set (Cemetery U)} + (hS : (Cemetery.delta : Cemetery U) ∉ S) : + (fun omega ↦ LifetimePath.coordinate t (killAtExit U omega)) ⁻¹' S = + {omega : ContinuousPath alpha | (t : ℝ≥0∞) < exitTime U omega ∧ + omega t ∈ Subtype.val '' (Cemetery.alive ⁻¹' S)} := by + ext omega + rw [Set.mem_preimage, coordinate_killAtExit, Set.mem_ofPred_eq] + by_cases ht : (t : ℝ≥0∞) < exitTime U omega + · rw [dif_pos ht] + have hmem := mem_image_val_iff U (C := Cemetery.alive ⁻¹' S) + (mem_of_lt_exitTime U omega t ht) + rw [hmem] + exact ⟨fun h ↦ ⟨ht, h⟩, fun h ↦ h.2⟩ + · rw [dif_neg ht] + exact ⟨fun h ↦ absurd h hS, fun h ↦ absurd h.1 ht⟩ + +/-- The event that the killed path is at the cemetery at time `t`, or is alive with live +coordinate in `S`. -/ +theorem preimage_coordinate_killAtExit_of_mem {S : Set (Cemetery U)} + (hS : (Cemetery.delta : Cemetery U) ∈ S) : + (fun omega ↦ LifetimePath.coordinate t (killAtExit U omega)) ⁻¹' S = + {omega : ContinuousPath alpha | (t : ℝ≥0∞) < exitTime U omega ∧ + omega t ∈ Subtype.val '' (Cemetery.alive ⁻¹' S)} ∪ + {omega : ContinuousPath alpha | ¬ (t : ℝ≥0∞) < exitTime U omega} := by + ext omega + rw [Set.mem_preimage, coordinate_killAtExit, Set.mem_union, Set.mem_ofPred_eq, Set.mem_ofPred_eq] + by_cases ht : (t : ℝ≥0∞) < exitTime U omega + · rw [dif_pos ht] + have hmem := mem_image_val_iff U (C := Cemetery.alive ⁻¹' S) + (mem_of_lt_exitTime U omega t ht) + rw [hmem] + constructor + · exact fun h ↦ Or.inl ⟨ht, h⟩ + · rintro (h | h) + · exact h.2 + · exact absurd ht h + · rw [dif_neg ht] + exact ⟨fun _ ↦ Or.inr ht, fun _ ↦ hS⟩ + +end Preimage + +section Measurable + +variable [MeasurableSpace alpha] [BorelSpace alpha] + +/-- Every fixed-time coordinate of the path killed at the exit of an open set is measurable. -/ +theorem measurable_coordinate_killAtExit (U : Set alpha) (hU : IsOpen U) (t : NNReal) : + Measurable fun omega : ContinuousPath alpha ↦ + LifetimePath.coordinate t (killAtExit U omega) := by + intro S hS + have hC : MeasurableSet (Subtype.val '' (Cemetery.alive ⁻¹' S)) := + (MeasurableEmbedding.subtype_coe hU.measurableSet).measurableSet_image.mpr + (measurable_inl hS) + have hlive : MeasurableSet {omega : ContinuousPath alpha | + (t : ℝ≥0∞) < exitTime U omega ∧ omega t ∈ Subtype.val '' (Cemetery.alive ⁻¹' S)} := + (measurableSet_lt_exitTime U hU t).inter + ((measurable_coordinateProcess (alpha := alpha) t) hC) + by_cases hdelta : (Cemetery.delta : Cemetery U) ∈ S + · rw [preimage_coordinate_killAtExit_of_mem U t hdelta] + refine hlive.union ?_ + have hcompl : {omega : ContinuousPath alpha | ¬ (t : ℝ≥0∞) < exitTime U omega} = + {omega : ContinuousPath alpha | (t : ℝ≥0∞) < exitTime U omega}ᶜ := rfl + rw [hcompl] + exact (measurableSet_lt_exitTime U hU t).compl + · rw [preimage_coordinate_killAtExit_of_notMem U t hdelta] + exact hlive + +/-- **Killing at the exit time of an open set is measurable** for the measurable structure on +lifetime paths generated by the lifetime and the fixed-time coordinates. -/ +theorem measurable_killAtExit (U : Set alpha) (hU : IsOpen U) : + Measurable (killAtExit U : ContinuousPath alpha → LifetimePath U) := by + apply Measurable.of_comap_le + rw [LifetimePath.instMeasurableSpace, MeasurableSpace.comap_sup, MeasurableSpace.comap_iSup] + apply sup_le + · rw [MeasurableSpace.comap_comp] + have hfun : LifetimePath.lifetime ∘ (killAtExit U : ContinuousPath alpha → LifetimePath U) = + exitTime U := rfl + rw [hfun] + exact (measurable_exitTime U hU).comap_le + · rw [iSup_le_iff] + intro t + rw [MeasurableSpace.comap_comp] + exact (measurable_coordinate_killAtExit U hU t).comap_le + +end Measurable + +end + +end ContinuousPath + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean new file mode 100644 index 0000000000..b043ccc5fb --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean @@ -0,0 +1,403 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance +import LeanPool.MarkovProcess.MarkovProcess.Killed.Process + +/-! +# Finite-dimensional distributions of the killed process + +For the continuous-path process of a conservative Feller semigroup and an open set `U`, this file +identifies every finite-dimensional distribution of the process killed at the exit of `U` +(`killedProcess P hP U hU` of `Killed/Process.lean`, a law on lifetime paths in the carrier `U`) +with the corresponding finite-dimensional distribution of the **cemetery extension of the killed +semigroup** on `U`: + + `(killedProcess x).map (fun ω ↦ fun i : I ↦ coordinate i ω) = + finiteSetKernel (cemeterySemigroup (killedSemigroup P hP U hU hFeller hK)) I (alive x)` + +(`killedProcess_map_finiteEvaluation`), and, at a strictly increasing family of times, the +corresponding statement for `finiteTimeKernel` (`killedProcess_map_coordinates_ordered`). + +The proof is by induction on the number of times, along the recursion of `finiteTimeKernel`. The +induction step splits the survival event at the first time `t₁`: on `{t₁ < τ_U}` the later +coordinates of the killed path are the coordinates of the killed shifted path +(`coordinate_killAtExit_shift`), and the law of the shifted path is supplied by the restart +statement `continuousProcess_killedEvent_inter_shift` proved here, a form of the Markov property +at `t₁` restricted to the `𝓕_{t₁}`-event `{t₁ < τ_U} ∩ {ω t₁ ∈ B}`; on the complement every +coordinate is the cemetery state, matching the absorbing behaviour of the cemetery +(`finiteTimeKernel_cemeterySemigroup_delta`). Measures on a finite product are compared on boxes. + +No Feller property, strong continuity, or regularity of the killed semigroup is claimed, and no +statement here covers a random time. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace SubMarkovKernelSemigroup + +section Dead + +variable {beta : Type*} [MeasurableSpace beta] (S : SubMarkovKernelSemigroup beta) + +/-- Started at the cemetery, every finite-time law of a cemetery extension is the Dirac mass at +the path that is dead at all times: the cemetery is absorbing. -/ +theorem finiteTimeKernel_cemeterySemigroup_delta {n : ℕ} (times : FiniteOrderedTimes n) : + finiteTimeKernel (cemeterySemigroup S) times Cemetery.delta = + Measure.dirac (fun _ ↦ Cemetery.delta) := by + induction n with + | zero => + rw [finiteTimeKernel_zero, Kernel.const_apply] + exact congrArg Measure.dirac (Subsingleton.elim _ _) + | succ n ih => + let : IsMarkovKernel (cemeterySemigroup S (times 0)) := + (isConservative_cemeterySemigroup S).isMarkovKernel (times 0) + let : IsMarkovKernel (finiteTimeKernel (cemeterySemigroup S) times.relativeTail) := + (isConservative_cemeterySemigroup S).isMarkovKernel_finiteTimeKernel _ _ + have hprod : (cemeterySemigroup S (times 0) ⊗ₖ + Kernel.prodMkLeft (Cemetery beta) + (finiteTimeKernel (cemeterySemigroup S) times.relativeTail)) + Cemetery.delta = + Measure.dirac (Cemetery.delta, fun _ ↦ Cemetery.delta) := by + refine Measure.ext fun s hs ↦ ?_ + rw [Kernel.compProd_apply hs, cemeterySemigroup_absorbing, + lintegral_dirac' _ (Kernel.measurable_kernel_prodMk_left' hs _), + Kernel.prodMkLeft_apply, ih, + Measure.dirac_apply' _ (measurable_prodMk_left hs), Measure.dirac_apply' _ hs] + by_cases hmem : ((Cemetery.delta : Cemetery beta), + (fun _ ↦ Cemetery.delta : Fin n → Cemetery beta)) ∈ s + · rw [Set.indicator_of_mem hmem, + Set.indicator_of_mem (Set.mem_preimage.mpr hmem), Pi.one_apply, Pi.one_apply] + · rw [Set.indicator_of_notMem hmem] + exact Set.indicator_of_notMem + (show (fun _ ↦ Cemetery.delta : Fin n → Cemetery beta) ∉ + Prod.mk (Cemetery.delta : Cemetery beta) ⁻¹' s from fun h ↦ hmem h) + (1 : (Fin n → Cemetery beta) → ℝ≥0∞) + rw [finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map, + Kernel.map_apply _ measurable_finCons, hprod, Measure.map_dirac' measurable_finCons _] + refine congrArg Measure.dirac ?_ + funext i + refine Fin.cases ?_ (fun j ↦ ?_) i + · rw [Fin.cons_zero] + · rw [Fin.cons_succ] + +end Dead + + +section Restart + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + [LocallyCompactSpace alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) +variable (U : Set alpha) (hU : IsOpen U) + +/-- **Restart on a killed event.** On the event that the process is still in `U` at time `t` and +sits there in `C`, the law of the path shifted by `t` is the law of the process started at the +time-`t` state, averaged over the killed transition kernel on `U`. -/ +theorem IsConservative.continuousProcess_killedEvent_inter_shift + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (t : NNReal) (x : U) {C : Set U} (hC : MeasurableSet C) + {D : Set (ContinuousPath alpha)} (hD : MeasurableSet D) : + IsConservative.continuousProcess P hP (x : alpha) + (ContinuousPath.killedEvent U t (Subtype.val '' C) ∩ ContinuousPath.shift t ⁻¹' D) = + ∫⁻ y in C, IsConservative.continuousProcess P hP (y : alpha) D + ∂(IsConservative.killedKernelOn P hP U hU t x) := by + have hE : MeasurableSet (Subtype.val '' C) := + (MeasurableEmbedding.subtype_coe hU.measurableSet).measurableSet_image.mpr hC + have hEpre : MeasurableSet ((fun omega : ContinuousPath alpha ↦ omega t) ⁻¹' + (Subtype.val '' C)) := (ContinuousPath.measurable_coordinateProcess (alpha := alpha) t) hE + have hg : Measurable fun y : alpha ↦ IsConservative.continuousProcess P hP y D := + (IsConservative.continuousProcess P hP).measurable_coe hD + have hAfilt : MeasurableSet[ContinuousPath.canonicalFiltration (alpha := alpha) t] + (ContinuousPath.killedEvent U t (Subtype.val '' C)) := + (ContinuousPath.measurableSet_lt_exitTime_canonicalFiltration U hU t).inter + ((ContinuousPath.measurable_coordinateProcess_canonicalFiltration (alpha := alpha) t) hE) + have hrestart := congrArg (fun mu : Measure (ContinuousPath alpha) ↦ mu D) + (hFeller.continuousProcess_restrict_map_shift P hP hK (x : alpha) t + (ContinuousPath.killedEvent U t (Subtype.val '' C)) hAfilt) + rw [Measure.map_apply (ContinuousPath.measurable_shift_fixed t) hD, + Measure.restrict_apply ((ContinuousPath.measurable_shift_fixed t) hD), + Measure.bind_apply hD (Kernel.aemeasurable _)] at hrestart + have hset : ContinuousPath.killedEvent U t (Subtype.val '' C) = + ((fun omega : ContinuousPath alpha ↦ omega t) ⁻¹' (Subtype.val '' C)) ∩ + {omega : ContinuousPath alpha | (t : ℝ≥0∞) < ContinuousPath.exitTime U omega} := by + ext omega + simp only [ContinuousPath.mem_killedEvent_iff, Set.mem_inter_iff, Set.mem_preimage, + Set.mem_ofPred_eq] + exact and_comm + have hcoord : Measurable fun omega : ContinuousPath alpha ↦ omega t := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) t + rw [Set.inter_comm, hrestart] + simp only [Kernel.comap_apply, ContinuousPath.coordinateProcess_apply] + rw [hset, ← Measure.restrict_restrict hEpre, ← setLIntegral_map hE hg hcoord, + ← IsConservative.killedKernel_eq_map P hP U hU t (x : alpha), + ← IsConservative.map_val_killedKernelOn P hP U hU t x, + setLIntegral_map hE hg measurable_subtype_coe, + Set.preimage_image_eq C Subtype.val_injective] + +end Restart + + +section OrderedMarginals + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) +variable (U : Set alpha) (hU : IsOpen U) + +/-- Reading the killed process at a family of fixed times is reading the killed continuous path at +those times. -/ +theorem IsConservative.killedProcess_map_coordinates {iota : Type*} (tau : iota → NNReal) + (x : U) : + (IsConservative.killedProcess P hP U hU x).map + (fun omega ↦ fun i ↦ LifetimePath.coordinate (tau i) omega) = + (IsConservative.continuousProcess P hP (x : alpha)).map + (fun omega ↦ fun i ↦ + LifetimePath.coordinate (tau i) (ContinuousPath.killAtExit U omega)) := by + rw [IsConservative.killedProcess_apply P hP U hU x, + Measure.map_map (LifetimePath.measurable_coordinateFamily tau) + (ContinuousPath.measurable_killAtExit U hU)] + rfl + +variable [LocallyCompactSpace alpha] +variable (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + +/-- **Finite-dimensional distributions of the killed process, at ordered times.** Read at a +strictly increasing family of times, the process killed at the exit of `U` and started at `x ∈ U` +has the finite-time law of the cemetery extension of the killed semigroup on `U`, started at the +live state `x`. -/ +theorem IsConservative.killedProcess_map_coordinates_ordered {n : ℕ} + (times : FiniteOrderedTimes n) (x : U) : + (IsConservative.killedProcess P hP U hU x).map + (fun omega ↦ fun i : Fin n ↦ LifetimePath.coordinate (times i) omega) = + finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) + times (Cemetery.alive x) := by + induction n generalizing x with + | zero => + rw [finiteTimeKernel_zero, Kernel.const_apply] + have hconst : (fun omega : LifetimePath U ↦ + fun i : Fin 0 ↦ LifetimePath.coordinate (times i) omega) = + fun _ ↦ FiniteOrderedTimes.emptyPath (Cemetery U) := by + funext omega + exact Subsingleton.elim _ _ + rw [hconst, Measure.map_const, measure_univ, one_smul] + | succ n ih => + have hmeasTimes : Measurable (fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) := + measurable_pi_lambda _ fun i ↦ + ContinuousPath.measurable_coordinate_killAtExit U hU (times i) + have hmeasTail : Measurable (fun omega : ContinuousPath alpha ↦ fun i : Fin n ↦ + LifetimePath.coordinate (times.relativeTail i) + (ContinuousPath.killAtExit U omega)) := + measurable_pi_lambda _ fun i ↦ + ContinuousPath.measurable_coordinate_killAtExit U hU (times.relativeTail i) + have hRcons : (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)).IsConservative := isConservative_cemeterySemigroup _ + let : IsMarkovKernel (finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times) := + hRcons.isMarkovKernel_finiteTimeKernel _ times + let : IsMarkovKernel (finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail) := + hRcons.isMarkovKernel_finiteTimeKernel _ _ + let : IsMarkovKernel ((cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) (times 0)) := hRcons.isMarkovKernel (times 0) + rw [IsConservative.killedProcess_map_coordinates P hP U hU _ x] + have : IsProbabilityMeasure + ((IsConservative.continuousProcess P hP (x : alpha)).map (fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega))) := + Measure.isProbabilityMeasure_map hmeasTimes.aemeasurable + refine MeasureTheory.ext_of_generate_finite _ generateFrom_pi.symm isPiSystem_pi ?_ ?_ + · rintro _ ⟨B, hB, rfl⟩ + have hBmeas : ∀ i : Fin (n + 1), MeasurableSet (B i) := fun i ↦ hB i (Set.mem_univ i) + have hbox : MeasurableSet (Set.univ.pi B) := MeasurableSet.univ_pi hBmeas + have hbox' : MeasurableSet (Set.univ.pi fun i : Fin n ↦ B i.succ) := + MeasurableSet.univ_pi fun i ↦ hBmeas i.succ + have hC0 : MeasurableSet (Cemetery.alive ⁻¹' (B 0) : Set U) := measurable_inl (hBmeas 0) + have hA : MeasurableSet {omega : ContinuousPath alpha | + ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} := + ContinuousPath.measurableSet_lt_exitTime U hU (times 0) + have hg : Measurable fun z : Cemetery U ↦ + finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail z (Set.univ.pi fun i : Fin n ↦ B i.succ) := + (finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail).measurable_coe hbox' + have hinl : Measurable (Cemetery.alive : U → Cemetery U) := measurable_inl + have hcoorddead : ∀ omega : ContinuousPath alpha, + omega ∉ {omega : ContinuousPath alpha | + ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} → + ∀ i : Fin (n + 1), LifetimePath.coordinate (times i) + (ContinuousPath.killAtExit U omega) = Cemetery.delta := fun omega homega i ↦ + ContinuousPath.coordinate_killAtExit_of_exitTime_le U omega + (not_lt.mp homega) (times.monotone (Fin.zero_le i)) + have hliveset : (fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' Set.univ.pi B ∩ {omega : ContinuousPath alpha | + ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} = + ContinuousPath.killedEvent U (times 0) (Subtype.val '' (Cemetery.alive ⁻¹' (B 0) : Set U)) ∩ + ContinuousPath.shift (times 0) ⁻¹' ((fun omega : ContinuousPath alpha ↦ fun i : Fin n ↦ + LifetimePath.coordinate (times.relativeTail i) + (ContinuousPath.killAtExit U omega)) ⁻¹' (Set.univ.pi fun i : Fin n ↦ B i.succ)) := by + ext omega + simp only [Set.mem_inter_iff, Set.mem_preimage, Set.mem_univ_pi, Set.mem_ofPred_eq, + ContinuousPath.mem_killedEvent_iff] + constructor + · rintro ⟨hmem, hsurv⟩ + refine ⟨⟨hsurv, ?_⟩, fun i ↦ ?_⟩ + · have h0 := hmem 0 + rw [ContinuousPath.coordinate_killAtExit_of_lt U omega (times 0) hsurv] at h0 + exact (mem_image_val_iff U + (ContinuousPath.mem_of_lt_exitTime U omega (times 0) hsurv)).mpr h0 + · have hi := hmem i.succ + rw [← FiniteOrderedTimes.add_relativeTail times i, + ← ContinuousPath.coordinate_killAtExit_shift U omega (times 0) + (times.relativeTail i) hsurv] at hi + exact hi + · rintro ⟨⟨hsurv, h0⟩, htail⟩ + refine ⟨fun i ↦ ?_, hsurv⟩ + refine Fin.cases ?_ (fun j ↦ ?_) i + · rw [ContinuousPath.coordinate_killAtExit_of_lt U omega (times 0) hsurv] + exact (mem_image_val_iff U + (ContinuousPath.mem_of_lt_exitTime U omega (times 0) hsurv)).mp h0 + · rw [← FiniteOrderedTimes.add_relativeTail times j, + ← ContinuousPath.coordinate_killAtExit_shift U omega (times 0) + (times.relativeTail j) hsurv] + exact htail j + have hliveval : IsConservative.continuousProcess P hP (x : alpha) + ((fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' Set.univ.pi B ∩ {omega : ContinuousPath alpha | + ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega}) = + ∫⁻ y in (Cemetery.alive ⁻¹' (B 0) : Set U), finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail + (Cemetery.alive y) (Set.univ.pi fun i : Fin n ↦ B i.succ) ∂(IsConservative.killedKernelOn P hP U hU (times 0) x) := by + rw [hliveset, IsConservative.continuousProcess_killedEvent_inter_shift P hP U hU + hFeller hK (times 0) x hC0 (hmeasTail hbox')] + refine lintegral_congr fun y ↦ ?_ + rw [← Measure.map_apply hmeasTail hbox', + ← IsConservative.killedProcess_map_coordinates P hP U hU _ y, + ih times.relativeTail y] + have hdeadval : IsConservative.continuousProcess P hP (x : alpha) + ((fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' Set.univ.pi B \ {omega : ContinuousPath alpha | + ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega}) = + (1 - IsConservative.killedKernelOn P hP U hU (times 0) x Set.univ) * + (B 0).indicator (fun z ↦ finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail z + (Set.univ.pi fun i : Fin n ↦ B i.succ)) Cemetery.delta := by + have hQA : IsConservative.continuousProcess P hP (x : alpha) ({omega : ContinuousPath alpha | + ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega})ᶜ = + 1 - IsConservative.killedKernelOn P hP U hU (times 0) x Set.univ := by + rw [IsConservative.killedKernelOn_univ_eq_continuousProcess P hP U hU (times 0) x] + exact prob_compl_eq_one_sub hA + by_cases hdelta : ∀ i : Fin (n + 1), (Cemetery.delta : Cemetery U) ∈ B i + · have hset : (fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' Set.univ.pi B \ {omega : ContinuousPath alpha | + ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} = ({omega : ContinuousPath alpha | + ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega})ᶜ := by + refine Set.eq_of_subset_of_subset (fun omega homega ↦ homega.2) fun omega homega ↦ ?_ + refine ⟨fun i _ ↦ ?_, homega⟩ + have hci : LifetimePath.coordinate (times i) + (ContinuousPath.killAtExit U omega) ∈ B i := by + rw [hcoorddead omega homega i] + exact hdelta i + exact hci + rw [hset, hQA, Set.indicator_of_mem (hdelta 0), + finiteTimeKernel_cemeterySemigroup_delta, Measure.dirac_apply' _ hbox', + Set.indicator_of_mem + (show (fun _ ↦ Cemetery.delta : Fin n → Cemetery U) ∈ + (Set.univ.pi fun i : Fin n ↦ B i.succ) from fun i _ ↦ hdelta i.succ), + Pi.one_apply, mul_one] + · obtain ⟨i, hi⟩ := not_forall.mp hdelta + have hset : (fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' Set.univ.pi B \ {omega : ContinuousPath alpha | + ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} = ∅ := by + refine Set.eq_empty_iff_forall_notMem.mpr fun omega homega ↦ ?_ + have h1 : LifetimePath.coordinate (times i) + (ContinuousPath.killAtExit U omega) ∈ B i := homega.1 i (Set.mem_univ i) + rw [hcoorddead omega homega.2 i] at h1 + exact hi h1 + rw [hset, measure_empty] + by_cases h0 : (Cemetery.delta : Cemetery U) ∈ B 0 + · have hnotbox : (fun _ ↦ Cemetery.delta : Fin n → Cemetery U) ∉ (Set.univ.pi fun i : Fin n ↦ B i.succ) := by + intro hmem + exact hdelta fun k ↦ Fin.cases h0 (fun j ↦ hmem j (Set.mem_univ j)) k + rw [Set.indicator_of_mem h0, finiteTimeKernel_cemeterySemigroup_delta, + Measure.dirac_apply' _ hbox', Set.indicator_of_notMem hnotbox, mul_zero] + · rw [Set.indicator_of_notMem h0, mul_zero] + have hintegrand : ∀ z : Cemetery U, + finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail z + (Prod.mk z ⁻¹' ((fun w : Cemetery U × (Fin n → Cemetery U) ↦ + @Fin.cons n (fun _ : Fin (n + 1) ↦ Cemetery U) w.1 w.2) ⁻¹' Set.univ.pi B)) = + (B 0).indicator (fun z ↦ finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail z + (Set.univ.pi fun i : Fin n ↦ B i.succ)) z := by + intro z + by_cases hz : z ∈ B 0 + · rw [Set.indicator_of_mem hz] + congr 1 + ext q + simp only [Set.mem_preimage, Set.mem_univ_pi] + constructor + · intro h j + have hj := h j.succ + rwa [Fin.cons_succ] at hj + · intro h j + refine Fin.cases ?_ (fun k ↦ ?_) j + · rw [Fin.cons_zero] + exact hz + · rw [Fin.cons_succ] + exact h k + · rw [Set.indicator_of_notMem hz] + have hempty : (Prod.mk z ⁻¹' ((fun w : Cemetery U × (Fin n → Cemetery U) ↦ + @Fin.cons n (fun _ : Fin (n + 1) ↦ Cemetery U) w.1 w.2) ⁻¹' + Set.univ.pi B)) = ∅ := by + refine Set.eq_empty_iff_forall_notMem.mpr fun q hq ↦ ?_ + have h0 : @Fin.cons n (fun _ : Fin (n + 1) ↦ Cemetery U) z q 0 ∈ B 0 := + hq 0 (Set.mem_univ 0) + rw [Fin.cons_zero] at h0 + exact hz h0 + rw [hempty, measure_empty] + rw [Measure.map_apply hmeasTimes hbox, + ← measure_inter_add_sdiff (μ := IsConservative.continuousProcess P hP (x : alpha)) + ((fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' Set.univ.pi B) hA, + hliveval, hdeadval, finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map, + Kernel.map_apply _ measurable_finCons, Measure.map_apply measurable_finCons hbox, + Kernel.compProd_apply (measurable_finCons hbox)] + simp only [Kernel.prodMkLeft_apply] + rw [lintegral_congr hintegrand, lintegral_indicator (hBmeas 0), cemeterySemigroup_apply, + IsConservative.killedSemigroup_apply, Kernel.cemeteryExtension_alive_apply, + Measure.restrict_add, lintegral_add_measure, + setLIntegral_map (hBmeas 0) hg hinl, Measure.restrict_smul, lintegral_smul_measure, + ← lintegral_indicator (hBmeas 0), lintegral_dirac' _ (hg.indicator (hBmeas 0)), + smul_eq_mul] + · rw [measure_univ, measure_univ] + +/-- **The finite-dimensional distributions of the killed process.** For every finite set `I` of +nonnegative times and every starting point `x` of the open set `U`, the coordinates at `I` of the +process killed at the exit of `U` have the law of the finite-set kernel at `I` of the cemetery +extension of the killed semigroup on `U`, started at the live state `x`. + +This identifies the process killed at the exit of `U` with the process of the killed semigroup, +the cemetery recording the time at which the path leaves `U`. -/ +theorem IsConservative.killedProcess_map_finiteEvaluation (I : Finset NNReal) (x : U) : + (IsConservative.killedProcess P hP U hU x).map + (fun omega ↦ fun i : I ↦ LifetimePath.coordinate (i : NNReal) omega) = + finiteSetKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) I (Cemetery.alive x) := by + have hfun : orderedPathToFiniteSet (α := Cemetery U) I ∘ + (fun omega : LifetimePath U ↦ fun j : Fin I.card ↦ + LifetimePath.coordinate (finiteSetTimes I j) omega) = + fun omega : LifetimePath U ↦ fun t : I ↦ LifetimePath.coordinate (t : NNReal) omega := by + funext omega t + show LifetimePath.coordinate (finiteSetTimes I ((I.orderIsoOfFin rfl).symm t)) omega = + LifetimePath.coordinate (t : NNReal) omega + rw [finiteSetTimes_orderIsoOfFin_symm_apply] + rw [finiteSetKernel_eq_map, Kernel.map_apply _ (measurable_orderedPathToFiniteSet I), + ← IsConservative.killedProcess_map_coordinates_ordered P hP U hU hFeller hK + (finiteSetTimes I) x, + Measure.map_map (measurable_orderedPathToFiniteSet I) + (LifetimePath.measurable_coordinateFamily _), hfun] + +end OrderedMarginals + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Minimal.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Minimal.lean new file mode 100644 index 0000000000..62440afb71 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Minimal.lean @@ -0,0 +1,115 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel +import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin + +/-! +# The semigroup as the limit of its killed parts + +Along an open exhaustion `U n ↑ α` of the state space, the killed kernels increase to the +transition kernels of the semigroup: for every time `t`, starting point `x` and measurable set +`B`, + + `⨆ n, killedKernel P hP (U n) _ t x B = P t x B` (`iSup_killedKernel_apply`), + +and the survival probabilities `Q x {t < τ_{U n}}` increase to one. This is the statement that the +whole-space semigroup is the minimal semigroup of its killed parts; it rests on the path-space +fact that exit times along an exhaustion tend to infinity (`Path/Exhaustion.lean`), so the +killed events increase to the whole event `{ω t ∈ B}`. + +The killed kernels are monotone in the open set (`killedKernel_mono`); no other structure is +used. +-/ + +open MeasureTheory ProbabilityTheory Filter +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace ContinuousPath + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +/-- Killed events are monotone in the set. -/ +theorem killedEvent_mono {U V : Set alpha} (hUV : U ⊆ V) (t : NNReal) (B : Set alpha) : + killedEvent U t B ⊆ killedEvent V t B := by + rintro omega ⟨hlt, hmem⟩ + exact ⟨lt_of_lt_of_le hlt (exitTime_mono hUV omega), hmem⟩ + +/-- Along an open exhaustion, the killed events increase to the event that the path is in `B` at +time `t`. -/ +theorem IsOpenExhaustion.iUnion_killedEvent {U : ℕ → Set alpha} (hU : IsOpenExhaustion U) + (t : NNReal) (B : Set alpha) : + ⋃ n, killedEvent (U n) t B = {omega : ContinuousPath alpha | omega t ∈ B} := by + ext omega + simp only [Set.mem_iUnion, mem_killedEvent_iff, Set.mem_ofPred_eq] + constructor + · rintro ⟨n, -, hmem⟩ + exact hmem + · intro hmem + obtain ⟨N, hN⟩ := hU.exists_lt_exitTime omega t + exact ⟨N, hN N le_rfl, hmem⟩ + +/-- Along an open exhaustion, the survival events increase to the whole space. -/ +theorem IsOpenExhaustion.iUnion_lt_exitTime {U : ℕ → Set alpha} (hU : IsOpenExhaustion U) + (t : NNReal) : + ⋃ n, {omega : ContinuousPath alpha | (t : ℝ≥0∞) < exitTime (U n) omega} = Set.univ := by + ext omega + simp only [Set.mem_iUnion, Set.mem_ofPred_eq, Set.mem_univ, iff_true] + obtain ⟨N, hN⟩ := hU.exists_lt_exitTime omega t + exact ⟨N, hN N le_rfl⟩ + +end ContinuousPath + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- The killed kernels are monotone in the open set. -/ +theorem IsConservative.killedKernel_mono {U V : Set alpha} (hU : IsOpen U) (hV : IsOpen V) + (hUV : U ⊆ V) (t : NNReal) (x : alpha) {B : Set alpha} (hB : MeasurableSet B) : + IsConservative.killedKernel P hP U hU t x B ≤ IsConservative.killedKernel P hP V hV t x B := by + rw [IsConservative.killedKernel_apply P hP U hU t x hB, + IsConservative.killedKernel_apply P hP V hV t x hB] + exact measure_mono (ContinuousPath.killedEvent_mono hUV t B) + +/-- Along an open exhaustion, the survival probabilities increase to one. -/ +theorem IsConservative.iSup_measure_lt_exitTime {U : ℕ → Set alpha} + (hU : ContinuousPath.IsOpenExhaustion U) (t : NNReal) (x : alpha) : + ⨆ n, IsConservative.continuousProcess P hP x + {omega | (t : ℝ≥0∞) < ContinuousPath.exitTime (U n) omega} = 1 := by + have hmono : Monotone fun n ↦ + {omega : ContinuousPath alpha | (t : ℝ≥0∞) < ContinuousPath.exitTime (U n) omega} := + fun m n hmn omega h ↦ + lt_of_lt_of_le h (ContinuousPath.exitTime_mono (hU.monotone hmn) omega) + rw [← Monotone.measure_iUnion hmono, hU.iUnion_lt_exitTime t, measure_univ] + +variable [LocallyCompactSpace alpha] + +/-- **The semigroup is the limit of its killed parts.** Along an open exhaustion, the killed +kernels increase to the transition kernels of the semigroup. -/ +theorem IsFellerKernelSemigroup.iSup_killedKernel_apply (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) {U : ℕ → Set alpha} (hU : ContinuousPath.IsOpenExhaustion U) + (t : NNReal) (x : alpha) {B : Set alpha} (hB : MeasurableSet B) : + ⨆ n, IsConservative.killedKernel P hP (U n) (hU.isOpen n) t x B = P t x B := by + have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ omega t) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) t + have hmono : Monotone fun n ↦ ContinuousPath.killedEvent (U n) t B := + fun m n hmn ↦ ContinuousPath.killedEvent_mono (hU.monotone hmn) t B + simp_rw [IsConservative.killedKernel_apply P hP _ _ t x hB] + rw [← Monotone.measure_iUnion hmono, hU.iUnion_killedEvent t B] + change IsConservative.continuousProcess P hP x + ((fun omega : ContinuousPath alpha ↦ omega t) ⁻¹' B) = _ + rw [← Measure.map_apply hmeas hB, ← Kernel.map_apply _ hmeas, + hFeller.continuousProcess_map_eval_nnreal P hP hK t] + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean new file mode 100644 index 0000000000..f624aa2e8e --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean @@ -0,0 +1,267 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping +import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion + +/-! +# Nested domains: killing at the exit of a smaller set + +For two sets `U ⊆ V` the path killed at the exit of `U` is the path killed at the exit of `V`, +killed once more at the exit of `U`. This file proves that relation on path space and transports +it to the killed processes. + +* `ContinuousPath.exitTime_mono`: a path leaves a smaller set no later; +* `LifetimePath.killedCoordinate W t`: the coordinate at time `t` of a lifetime path killed once + more at the exit of `W`, together with its two coordinate formulas and its measurability for an + open `W` (`LifetimePath.measurable_killedCoordinate`), which rests on the measurability of the + lifetime-path exit time `LifetimePath.measurable_exitTime` proved here; +* `ContinuousPath.lifetimePath_exitTime_killAtExit`: the first time the `V`-killed path is not a + live point of `U` is the exit time of `U`, that is, the lifetime of the `U`-killed path; +* `ContinuousPath.killedCoordinate_killAtExit`: killing the `V`-killed path once more at the exit + of `U` reads, at every time, the coordinate of the `U`-killed path through the inclusion of `U` + in `V`; +* `killedProcess_map_exitTime` and `killedProcess_map_killedCoordinates`: the same two statements + for the laws, and finally `killedProcess_map_killedFinsetCoordinates`, the part-process property + at the level of the finite-dimensional distributions: the process of `V` killed again at the + exit of `U` has the finite-dimensional distributions of the cemetery extension of the killed + semigroup on `U`. + +The carriers of the two killed processes are the subtypes `U` and `V`, which are different types; +the statements here compare them through the inclusion of `U` in `V` rather than identifying the +two killed processes as laws on a common carrier. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace LifetimePath + +section Killing + +variable {beta : Type*} [PseudoMetricSpace beta] + +/-- The coordinate at time `t` of a lifetime path killed once more at the exit of `W`: the +coordinate of the path strictly before the first time it is not a live point of `W`, and the +cemetery state from that time on. -/ +noncomputable def killedCoordinate (W : Set beta) (t : NNReal) (eta : LifetimePath beta) : Cemetery beta := + if (t : ℝ≥0∞) < exitTime W eta then coordinate t eta else Cemetery.delta + +/-- Before the exit time of `W`, killing again at the exit of `W` changes no coordinate. -/ +theorem killedCoordinate_of_lt (W : Set beta) (t : NNReal) (eta : LifetimePath beta) + (ht : (t : ℝ≥0∞) < exitTime W eta) : + killedCoordinate W t eta = coordinate t eta := + if_pos ht + +/-- From the exit time of `W` on, the path killed again at the exit of `W` is at the cemetery. -/ +theorem killedCoordinate_of_le (W : Set beta) (t : NNReal) (eta : LifetimePath beta) + (ht : exitTime W eta ≤ (t : ℝ≥0∞)) : + killedCoordinate W t eta = Cemetery.delta := + if_neg (not_lt.mpr ht) + +end Killing + +section MeasurableExitTime + +variable {beta : Type*} [PseudoMetricSpace beta] [MeasurableSpace beta] [BorelSpace beta] + +/-- The exit time from an open set is a Borel function on lifetime-path space: it is a stopping +time for the canonical filtration, and the filtration is contained in the measurable structure. -/ +theorem measurable_exitTime (W : Set beta) (hW : IsOpen W) : + Measurable (exitTime W : LifetimePath beta → ℝ≥0∞) := by + refine measurable_of_Iic fun a ↦ ?_ + induction a with + | top => + have h : (exitTime W : LifetimePath beta → ℝ≥0∞) ⁻¹' Set.Iic ⊤ = Set.univ := by + ext eta + simp only [Set.mem_preimage, Set.mem_Iic, le_top, Set.mem_univ] + rw [h] + exact MeasurableSet.univ + | coe t => + exact (canonicalFiltration (alpha := beta)).le t _ (isStoppingTime_exitTime W hW t) + +/-- Every coordinate of a lifetime path killed again at the exit of an open set is measurable. -/ +theorem measurable_killedCoordinate (W : Set beta) (hW : IsOpen W) (t : NNReal) : + Measurable (killedCoordinate W t) := by + intro S hS + have hA : MeasurableSet {eta : LifetimePath beta | (t : ℝ≥0∞) < exitTime W eta} := + measurable_exitTime W hW measurableSet_Ioi + by_cases hdelta : (Cemetery.delta : Cemetery beta) ∈ S + · have hpre : killedCoordinate W t ⁻¹' S = + ({eta : LifetimePath beta | (t : ℝ≥0∞) < exitTime W eta} ∩ coordinate t ⁻¹' S) ∪ + {eta : LifetimePath beta | (t : ℝ≥0∞) < exitTime W eta}ᶜ := by + ext eta + simp only [Set.mem_preimage, Set.mem_union, Set.mem_inter_iff, Set.mem_ofPred_eq, + Set.mem_compl_iff, killedCoordinate] + by_cases hlt : (t : ℝ≥0∞) < exitTime W eta + · rw [if_pos hlt] + exact ⟨fun h ↦ Or.inl ⟨hlt, h⟩, fun h ↦ h.elim (fun h ↦ h.2) fun h ↦ absurd hlt h⟩ + · rw [if_neg hlt] + exact ⟨fun _ ↦ Or.inr hlt, fun _ ↦ hdelta⟩ + rw [hpre] + exact (hA.inter (measurable_coordinate t hS)).union hA.compl + · have hpre : killedCoordinate W t ⁻¹' S = + {eta : LifetimePath beta | (t : ℝ≥0∞) < exitTime W eta} ∩ coordinate t ⁻¹' S := by + ext eta + simp only [Set.mem_preimage, Set.mem_inter_iff, Set.mem_ofPred_eq, killedCoordinate] + by_cases hlt : (t : ℝ≥0∞) < exitTime W eta + · rw [if_pos hlt] + exact ⟨fun h ↦ ⟨hlt, h⟩, fun h ↦ h.2⟩ + · rw [if_neg hlt] + exact ⟨fun h ↦ absurd h hdelta, fun h ↦ absurd h.1 hlt⟩ + rw [hpre] + exact hA.inter (measurable_coordinate t hS) + +end MeasurableExitTime + +end LifetimePath + +namespace ContinuousPath + +section Nested + +variable {alpha : Type*} [PseudoMetricSpace alpha] {U V : Set alpha} + +/-- **The `V`-killed path, killed once more at the exit of `U`, dies at the exit time of `U`.** +The first time at which the `V`-killed lifetime path is not a live point of `U` is the exit time +of `U`, that is, the lifetime of the `U`-killed path. -/ +theorem lifetimePath_exitTime_killAtExit (hUV : U ⊆ V) (omega : ContinuousPath alpha) : + LifetimePath.exitTime (Subtype.val ⁻¹' U : Set V) (killAtExit V omega) = + exitTime U omega := by + refine le_antisymm ?_ ?_ + · refine sInf_le_sInf ?_ + rintro s ⟨t, hst, ht⟩ + refine ⟨t, hst, ?_⟩ + rintro ⟨v, hv, hveq⟩ + by_cases hlt : (t : ℝ≥0∞) < exitTime V omega + · rw [coordinate_killAtExit_of_lt V omega t hlt] at hveq + have hvalue : (v : alpha) = omega t := congrArg Subtype.val (Sum.inl.inj hveq) + exact ht (hvalue ▸ hv) + · rw [coordinate_killAtExit_of_le V omega t (not_lt.mp hlt)] at hveq + exact Sum.inl_ne_inr hveq + · refine le_sInf ?_ + rintro s ⟨t, hst, ht⟩ + rw [hst] + by_cases hlt : (t : ℝ≥0∞) < exitTime V omega + · refine exitTime_le_of_notMem U omega t fun hmem ↦ ht ?_ + exact ⟨⟨omega t, mem_of_lt_exitTime V omega t hlt⟩, hmem, + (coordinate_killAtExit_of_lt V omega t hlt).symm⟩ + · exact (exitTime_mono hUV omega).trans (not_lt.mp hlt) + +/-- Strictly before the exit time of `U`, the `V`-killed path is alive at the point where the +`U`-killed path is alive, matched by the inclusion of `U` in `V`. -/ +theorem coordinate_killAtExit_inclusion (hUV : U ⊆ V) (omega : ContinuousPath alpha) (t : NNReal) + (ht : (t : ℝ≥0∞) < exitTime U omega) : + LifetimePath.coordinate t (killAtExit V omega) = + Cemetery.alive (Set.inclusion hUV ⟨omega t, mem_of_lt_exitTime U omega t ht⟩) := + coordinate_killAtExit_of_lt V omega t (ht.trans_le (exitTime_mono hUV omega)) + +/-- Killing the `V`-killed path once more at the exit of `U` reads, at every time, the coordinate +of the `U`-killed path through the inclusion of `U` in `V`. -/ +theorem killedCoordinate_killAtExit (hUV : U ⊆ V) (omega : ContinuousPath alpha) (t : NNReal) : + LifetimePath.killedCoordinate (Subtype.val ⁻¹' U : Set V) t (killAtExit V omega) = + Sum.map (Set.inclusion hUV) id (LifetimePath.coordinate t (killAtExit U omega)) := by + rw [LifetimePath.killedCoordinate, lifetimePath_exitTime_killAtExit hUV omega] + by_cases hlt : (t : ℝ≥0∞) < exitTime U omega + · rw [if_pos hlt, coordinate_killAtExit_inclusion hUV omega t hlt, + coordinate_killAtExit_of_lt U omega t hlt] + rfl + · rw [if_neg hlt, coordinate_killAtExit_of_le U omega t (not_lt.mp hlt)] + rfl + +end Nested + +end ContinuousPath + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) +variable (U V : Set alpha) + +/-- **Nested domains, at the level of lifetimes.** For open sets `U ⊆ V`, the first time at which +the process killed at the exit of `V` is not a live point of `U` has the law of the lifetime of +the process killed at the exit of `U`, started at the same point of `U`. -/ +theorem IsConservative.killedProcess_map_exitTime (hUV : U ⊆ V) (hU : IsOpen U) (hV : IsOpen V) + (x : U) : + (IsConservative.killedProcess P hP V hV (Set.inclusion hUV x)).map + (LifetimePath.exitTime (Subtype.val ⁻¹' U : Set V)) = + (IsConservative.killedProcess P hP U hU x).map LifetimePath.lifetime := by + have hW : IsOpen (Subtype.val ⁻¹' U : Set V) := hU.preimage continuous_subtype_val + have hfun : LifetimePath.exitTime (Subtype.val ⁻¹' U : Set V) ∘ + ContinuousPath.killAtExit V = ContinuousPath.exitTime U := + funext fun omega ↦ ContinuousPath.lifetimePath_exitTime_killAtExit hUV omega + rw [IsConservative.killedProcess_map_lifetime P hP U hU x, + IsConservative.killedProcess_apply P hP V hV (Set.inclusion hUV x), + Measure.map_map (LifetimePath.measurable_exitTime _ hW) + (ContinuousPath.measurable_killAtExit V hV), hfun] + +/-- **Nested domains, at the level of the coordinate laws.** For open sets `U ⊆ V`, killing the +process of `V` once more at the exit of `U` gives, at every family of fixed times, the coordinate +law of the process killed at the exit of `U`, read through the inclusion of `U` in `V`. -/ +theorem IsConservative.killedProcess_map_killedCoordinates (hUV : U ⊆ V) (hU : IsOpen U) + (hV : IsOpen V) (x : U) {iota : Type*} (tau : iota → NNReal) : + (IsConservative.killedProcess P hP V hV (Set.inclusion hUV x)).map + (fun eta ↦ fun i ↦ + LifetimePath.killedCoordinate (Subtype.val ⁻¹' U : Set V) (tau i) eta) = + (IsConservative.killedProcess P hP U hU x).map + (fun omega ↦ fun i ↦ + Sum.map (Set.inclusion hUV) id (LifetimePath.coordinate (tau i) omega)) := by + have hW : IsOpen (Subtype.val ⁻¹' U : Set V) := hU.preimage continuous_subtype_val + have hm1 : Measurable fun eta : LifetimePath V ↦ fun i ↦ + LifetimePath.killedCoordinate (Subtype.val ⁻¹' U : Set V) (tau i) eta := + measurable_pi_lambda _ fun i ↦ + LifetimePath.measurable_killedCoordinate _ hW (tau i) + have hm2 : Measurable fun omega : LifetimePath U ↦ fun i ↦ + Sum.map (Set.inclusion hUV) id (LifetimePath.coordinate (tau i) omega) := + measurable_pi_lambda _ fun i ↦ + ((measurable_inclusion hUV).sumMap measurable_id).comp + (LifetimePath.measurable_coordinate (tau i)) + have hfun : (fun eta : LifetimePath V ↦ fun i ↦ + LifetimePath.killedCoordinate (Subtype.val ⁻¹' U : Set V) (tau i) eta) ∘ + ContinuousPath.killAtExit V = + (fun omega : LifetimePath U ↦ fun i ↦ + Sum.map (Set.inclusion hUV) id (LifetimePath.coordinate (tau i) omega)) ∘ + ContinuousPath.killAtExit U := by + funext omega i + exact ContinuousPath.killedCoordinate_killAtExit hUV omega (tau i) + rw [IsConservative.killedProcess_apply P hP V hV (Set.inclusion hUV x), + IsConservative.killedProcess_apply P hP U hU x, + Measure.map_map hm1 (ContinuousPath.measurable_killAtExit V hV), + Measure.map_map hm2 (ContinuousPath.measurable_killAtExit U hU), hfun] + +variable [LocallyCompactSpace alpha] + +/-- **The part-process property, at the level of the finite-dimensional distributions.** For open +sets `U ⊆ V`, the process killed at the exit of `V` and then killed once more at the exit of `U` +has, at every finite set of times, the finite-dimensional distribution of the cemetery extension +of the killed semigroup on `U`, read through the inclusion of `U` in `V`. -/ +theorem IsConservative.killedProcess_map_killedFinsetCoordinates + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (hUV : U ⊆ V) (hU : IsOpen U) (hV : IsOpen V) (x : U) (I : Finset NNReal) : + (IsConservative.killedProcess P hP V hV (Set.inclusion hUV x)).map + (fun eta ↦ fun i : I ↦ + LifetimePath.killedCoordinate (Subtype.val ⁻¹' U : Set V) (i : NNReal) eta) = + (finiteSetKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) + I (Cemetery.alive x)).map + (fun p ↦ fun i : I ↦ Sum.map (Set.inclusion hUV) id (p i)) := by + have hmap : Measurable fun p : I → Cemetery U ↦ + fun i : I ↦ Sum.map (Set.inclusion hUV) id (p i) := + measurable_pi_lambda _ fun i ↦ + ((measurable_inclusion hUV).sumMap measurable_id).comp (measurable_pi_apply i) + rw [IsConservative.killedProcess_map_killedCoordinates P hP U V hUV hU hV x + (fun i : I ↦ (i : NNReal)), + ← IsConservative.killedProcess_map_finiteEvaluation P hP U hU hFeller hK I x, + Measure.map_map hmap (LifetimePath.measurable_coordinateFamily _)] + rfl + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean new file mode 100644 index 0000000000..ea3a079cb6 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean @@ -0,0 +1,152 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit +import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup + +/-! +# The process killed at the exit of an open set, as a law on lifetime paths + +For the continuous-path process `Q = continuousProcess P hP` of a conservative semigroup and an +open set `U`, killing each path at its exit time from `U` produces a Markov kernel + + `killedProcess P hP U hU : Kernel U (LifetimePath U)`, + +the law of the process started inside `U` and sent to the cemetery when it leaves `U`. It is the +image of `Q` under `ContinuousPath.killAtExit U`, pulled back to the carrier `U`. + +Two marginals are identified here. The lifetime of the killed process is the exit time +(`killedProcess_map_lifetime`), and its coordinate at a fixed time is the cemetery extension of +the killed transition kernel on `U` (`killedProcess_map_coordinate`): the live part is +`killedKernelOn P hP U hU t x` and the cemetery carries exactly the mass lost by time `t`. + +No finite-dimensional distribution of the killed process is identified here, and no Feller or +regularity property of the killed family is claimed. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace LifetimePath + +/-- Reading a lifetime path at a family of fixed times is measurable. -/ +theorem measurable_coordinateFamily {beta : Type*} [TopologicalSpace beta] + [MeasurableSpace beta] {iota : Type*} (tau : iota → NNReal) : + Measurable fun omega : LifetimePath beta ↦ fun i ↦ coordinate (tau i) omega := + measurable_pi_lambda _ fun i ↦ measurable_coordinate (tau i) + +end LifetimePath + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) +variable (U : Set alpha) (hU : IsOpen U) + +/-- **The process killed at the exit of `U`.** The continuous-path process of `P`, started at a +point of the open set `U` and killed when it leaves `U`, as a law on lifetime paths in the +carrier `U`. -/ +noncomputable def IsConservative.killedProcess : Kernel U (LifetimePath U) := + Kernel.mapOfMeasurable + ((IsConservative.continuousProcess P hP).comap Subtype.val measurable_subtype_coe) + (ContinuousPath.killAtExit U) (ContinuousPath.measurable_killAtExit U hU) + +/-- The killed process is the image of the continuous-path process under killing at the exit +time, pulled back to the carrier `U`. -/ +theorem IsConservative.killedProcess_eq_map : + IsConservative.killedProcess P hP U hU = + ((IsConservative.continuousProcess P hP).comap Subtype.val measurable_subtype_coe).map + (ContinuousPath.killAtExit U) := + Kernel.mapOfMeasurable_eq_map _ (ContinuousPath.measurable_killAtExit U hU) + +/-- The killed process is a Markov kernel: killing loses no mass, it only moves it to the +cemetery. -/ +instance IsConservative.isMarkovKernel_killedProcess : + IsMarkovKernel (IsConservative.killedProcess P hP U hU) := by + rw [IsConservative.killedProcess_eq_map] + exact Kernel.IsMarkovKernel.map _ (ContinuousPath.measurable_killAtExit U hU) + +/-- The killed process started at `x ∈ U` is the law of the process started at `x`, pushed forward +by killing at the exit time of `U`. -/ +theorem IsConservative.killedProcess_apply (x : U) : + IsConservative.killedProcess P hP U hU x = + (IsConservative.continuousProcess P hP (x : alpha)).map (ContinuousPath.killAtExit U) := by + rw [IsConservative.killedProcess_eq_map, + Kernel.map_apply _ (ContinuousPath.measurable_killAtExit U hU), Kernel.comap_apply] + +/-- **The lifetime law of the killed process is the law of the exit time.** -/ +theorem IsConservative.killedProcess_map_lifetime (x : U) : + (IsConservative.killedProcess P hP U hU x).map LifetimePath.lifetime = + (IsConservative.continuousProcess P hP (x : alpha)).map (ContinuousPath.exitTime U) := by + rw [IsConservative.killedProcess_apply P hP U hU x, + Measure.map_map LifetimePath.measurable_lifetime + (ContinuousPath.measurable_killAtExit U hU)] + rfl + +/-- The law of the killed process, read through the coordinate at a fixed time. -/ +theorem IsConservative.killedProcess_map_coordinate_eq (t : NNReal) (x : U) : + (IsConservative.killedProcess P hP U hU x).map (LifetimePath.coordinate t) = + (IsConservative.continuousProcess P hP (x : alpha)).map + (fun omega ↦ LifetimePath.coordinate t (ContinuousPath.killAtExit U omega)) := by + rw [IsConservative.killedProcess_apply P hP U hU x, + Measure.map_map (LifetimePath.measurable_coordinate t) + (ContinuousPath.measurable_killAtExit U hU)] + rfl + +/-- The total mass of the killed transition kernel on `U` is the survival probability. -/ +theorem IsConservative.killedKernelOn_univ_eq_continuousProcess (t : NNReal) (x : U) : + IsConservative.killedKernelOn P hP U hU t x Set.univ = + IsConservative.continuousProcess P hP (x : alpha) + {omega : ContinuousPath alpha | (t : ℝ≥0∞) < ContinuousPath.exitTime U omega} := by + have hsum : IsConservative.killedKernel P hP U hU t (x : alpha) U + + IsConservative.killedKernel P hP U hU t (x : alpha) Uᶜ = + IsConservative.killedKernel P hP U hU t (x : alpha) Set.univ := + measure_add_measure_compl hU.measurableSet + rw [IsConservative.killedKernel_apply_compl P hP U hU t (x : alpha), add_zero, + IsConservative.killedKernel_apply_univ P hP U hU t (x : alpha)] at hsum + rw [IsConservative.killedKernelOn_apply_univ P hP U hU t x, hsum] + +/-- **The one-time marginal of the killed process.** At every fixed time the coordinate of the +killed process has the law of the cemetery extension of the killed transition kernel on `U`: the +live part is the killed kernel `killedKernelOn P hP U hU t x`, and the cemetery carries the mass +`1 - Q x {t < τ_U}` lost by time `t`. -/ +theorem IsConservative.killedProcess_map_coordinate (t : NNReal) (x : U) : + (IsConservative.killedProcess P hP U hU x).map (LifetimePath.coordinate t) = + Kernel.cemeteryExtension (IsConservative.killedKernelOn P hP U hU t) + (Cemetery.alive x) := by + rw [IsConservative.killedProcess_map_coordinate_eq P hP U hU t x] + refine Measure.ext fun S hS ↦ ?_ + have hC : MeasurableSet (Cemetery.alive ⁻¹' S : Set U) := measurable_inl hS + have hlive : IsConservative.continuousProcess P hP (x : alpha) {omega : ContinuousPath alpha | (t : ℝ≥0∞) < ContinuousPath.exitTime U omega ∧ + omega t ∈ Subtype.val '' (Cemetery.alive ⁻¹' S)} = + IsConservative.killedKernelOn P hP U hU t x (Cemetery.alive ⁻¹' S) := + (IsConservative.killedKernelOn_apply_eq_continuousProcess P hP U hU t x hC).symm + have hdead : IsConservative.continuousProcess P hP (x : alpha) {omega : ContinuousPath alpha | + ¬ (t : ℝ≥0∞) < ContinuousPath.exitTime U omega} = + 1 - IsConservative.killedKernelOn P hP U hU t x Set.univ := by + rw [IsConservative.killedKernelOn_univ_eq_continuousProcess P hP U hU t x] + exact prob_compl_eq_one_sub (ContinuousPath.measurableSet_lt_exitTime U hU t) + rw [Measure.map_apply (ContinuousPath.measurable_coordinate_killAtExit U hU t) hS, + Kernel.cemeteryExtension_alive_apply' _ x hS] + by_cases hdelta : (Cemetery.delta : Cemetery U) ∈ S + · rw [ContinuousPath.preimage_coordinate_killAtExit_of_mem U t hdelta, + Set.indicator_of_mem hdelta, Pi.one_apply, mul_one] + have hdisj : Disjoint + {omega : ContinuousPath alpha | (t : ℝ≥0∞) < ContinuousPath.exitTime U omega ∧ + omega t ∈ Subtype.val '' (Cemetery.alive ⁻¹' S)} + {omega : ContinuousPath alpha | ¬ (t : ℝ≥0∞) < ContinuousPath.exitTime U omega} := + Set.disjoint_left.mpr fun omega homega hbad ↦ hbad homega.1 + rw [measure_union hdisj + ((ContinuousPath.measurableSet_lt_exitTime U hU t).compl), hlive, hdead] + · rw [ContinuousPath.preimage_coordinate_killAtExit_of_notMem U t hdelta, + Set.indicator_of_notMem hdelta, mul_zero, add_zero, hlive] + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Resolvent.lean new file mode 100644 index 0000000000..0bfc99e936 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Resolvent.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel + +/-! +# The killed resolvent + +The resolvent of the process killed at the exit of an open set `U`, at the shift `λ > 0`, is the +Laplace transform of the killed kernels, + + `killedResolvent λ f x = ∫ t in (0, ∞), e^{-λ t} (∫ f d(killedKernel t x)) dt`, + +and this file proves the path-space formula + + `killedResolvent λ f x = E_x ∫_0^{τ_U} e^{-λ t} f(ω_t) dt` + +(`killedResolvent_eq_lintegral`), for nonnegative extended measurable `f`; the integral over time +runs up to the exit time, where the survival indicator vanishes. The statement is an identity of +`ℝ≥0∞`-valued integrals, proved by Tonelli's theorem, so it carries no integrability hypothesis; +a consumer working with real-valued bounded `f` splits it into its positive and negative parts. + +This is the probabilistic side of the Dirichlet resolvent `(λ − L)⁻¹` on `U` with zero boundary +values: the identification with the analytic resolvent of a given operator is the consumer's +statement about that operator. One order fact is recorded alongside: the killed resolvent is +antitone in the shift (`IsConservative.killedResolvent_antitone`), because a larger shift +discounts the future more. +-/ + +open MeasureTheory ProbabilityTheory Filter +open scoped ENNReal NNReal + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) +variable (U : Set alpha) (hU : IsOpen U) + +/-- The killed resolvent at the shift `lam`, applied to a nonnegative extended function: the +Laplace transform in time of the killed kernels. -/ +noncomputable def IsConservative.killedResolvent (lam : ℝ) (f : alpha → ℝ≥0∞) (x : alpha) : + ℝ≥0∞ := + ∫⁻ t in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + ∫⁻ y, f y ∂(IsConservative.killedKernel P hP U hU (Real.toNNReal t) x) + +/-- An integral against a killed kernel is an integral over the survival event. -/ +theorem IsConservative.lintegral_killedKernel (t : NNReal) (x : alpha) {f : alpha → ℝ≥0∞} + (hf : Measurable f) : + ∫⁻ y, f y ∂(IsConservative.killedKernel P hP U hU t x) = + ∫⁻ omega, {omega : ContinuousPath alpha | (t : ℝ≥0∞) < ContinuousPath.exitTime U omega}.indicator + (fun omega ↦ f (omega t)) omega ∂(IsConservative.continuousProcess P hP x) := by + have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ omega t) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) t + rw [IsConservative.killedKernel_eq_map, lintegral_map hf hmeas, + ← lintegral_indicator (ContinuousPath.measurableSet_lt_exitTime U hU t)] + +/-- **The killed resolvent on path space.** For nonnegative extended measurable `f` and `lam > 0` +(only the measurability is used), +`killedResolvent lam f x = E_x ∫_0^{τ_U} e^{-lam t} f(ω_t) dt`, the time integral being cut off at +the exit time by the survival indicator. -/ +theorem IsConservative.killedResolvent_eq_lintegral (lam : ℝ) {f : alpha → ℝ≥0∞} + (hf : Measurable f) (x : alpha) : + IsConservative.killedResolvent P hP U hU lam f x = + ∫⁻ omega, (∫⁻ t in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega}.indicator + (fun t ↦ f (omega (Real.toNNReal t))) t) + ∂(IsConservative.continuousProcess P hP x) := by + have heval : Measurable fun p : ℝ × ContinuousPath alpha ↦ p.2 (Real.toNNReal p.1) := + (ContinuousEval.continuous_eval.comp continuous_swap).measurable.comp + ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_snd) + have hS : MeasurableSet {p : ℝ × ContinuousPath alpha | + ((Real.toNNReal p.1 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U p.2} := + measurableSet_lt (measurable_coe_nnreal_ennreal.comp (measurable_real_toNNReal.comp measurable_fst)) + ((ContinuousPath.measurable_exitTime U hU).comp measurable_snd) + have hjoint : Measurable (Function.uncurry fun (t : ℝ) (omega : ContinuousPath alpha) ↦ + ENNReal.ofReal (Real.exp (-lam * t)) * + {omega : ContinuousPath alpha | + ((Real.toNNReal t : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega}.indicator + (fun omega ↦ f (omega (Real.toNNReal t))) omega) := by + have hrw : (Function.uncurry fun (t : ℝ) (omega : ContinuousPath alpha) ↦ + ENNReal.ofReal (Real.exp (-lam * t)) * + {omega : ContinuousPath alpha | + ((Real.toNNReal t : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega}.indicator + (fun omega ↦ f (omega (Real.toNNReal t))) omega) = + fun p : ℝ × ContinuousPath alpha ↦ ENNReal.ofReal (Real.exp (-lam * p.1)) * + {p : ℝ × ContinuousPath alpha | + ((Real.toNNReal p.1 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U p.2}.indicator + (fun p ↦ f (p.2 (Real.toNNReal p.1))) p := by + funext p + simp only [Function.uncurry, Set.indicator_apply, Set.mem_ofPred_eq] + rw [hrw] + refine Measurable.mul ?_ ((hf.comp heval).indicator hS) + exact ENNReal.measurable_ofReal.comp + ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.comp + measurable_fst) + have hinner : ∀ t : ℝ, ENNReal.ofReal (Real.exp (-lam * t)) * + ∫⁻ y, f y ∂(IsConservative.killedKernel P hP U hU (Real.toNNReal t) x) = + ∫⁻ omega, ENNReal.ofReal (Real.exp (-lam * t)) * + {omega : ContinuousPath alpha | + ((Real.toNNReal t : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega}.indicator + (fun omega ↦ f (omega (Real.toNNReal t))) omega ∂(IsConservative.continuousProcess P hP x) := by + intro t + have hg : Measurable (fun omega : ContinuousPath alpha ↦ f (omega (Real.toNNReal t))) := + hf.comp (ContinuousPath.measurable_coordinateProcess (alpha := alpha) _) + rw [IsConservative.lintegral_killedKernel P hP U hU _ x hf] + exact (lintegral_const_mul _ (hg.indicator (ContinuousPath.measurableSet_lt_exitTime U hU _))).symm + unfold IsConservative.killedResolvent + simp_rw [hinner] + rw [lintegral_lintegral_swap hjoint.aemeasurable] + refine lintegral_congr fun omega ↦ ?_ + refine setLIntegral_congr_fun measurableSet_Ioi ?_ + intro t _ + simp only [Set.indicator_apply, Set.mem_ofPred_eq] + +/-- **The killed resolvent is antitone in the shift.** A larger shift discounts the future more, +so it produces a smaller resolvent. -/ +theorem IsConservative.killedResolvent_antitone (f : alpha → ℝ≥0∞) (x : alpha) {lam mu : ℝ} + (hle : lam ≤ mu) : + IsConservative.killedResolvent P hP U hU mu f x ≤ + IsConservative.killedResolvent P hP U hU lam f x := by + unfold IsConservative.killedResolvent + refine lintegral_mono_ae (ae_restrict_of_forall_mem measurableSet_Ioi fun t ht ↦ ?_) + refine mul_le_mul_left (ENNReal.ofReal_le_ofReal (Real.exp_le_exp.mpr ?_)) _ + exact mul_le_mul_of_nonneg_right (neg_le_neg hle) (le_of_lt ht) + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Semigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Semigroup.lean new file mode 100644 index 0000000000..871acd5b13 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Semigroup.lean @@ -0,0 +1,178 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel + +/-! +# The killed semigroup on the domain + +The killed kernels `killedKernel P hP U hU t` of `Killed/Kernel.lean` live on the whole state +space and are the identity only on `U` at time zero. Restricting them to the carrier `U` (the +subtype, with its Borel sigma-algebra) gives kernels `killedKernelOn P hP U hU t : Kernel U U` +which do form a sub-Markov kernel semigroup, the **killed semigroup** +`killedSemigroup P hP U hU hFeller hK : SubMarkovKernelSemigroup U`: + + `killedSemigroup t x B = Q x {ω | t < τ_U(ω) ∧ ω t ∈ B}` for `x ∈ U`, `B ⊆ U`. + +The passage to the subtype uses that the killed kernels put no mass outside `U` +(`killedKernel_apply_compl`), so nothing is lost: `(killedKernelOn t x).map Subtype.val = +killedKernel t x` (`map_val_killedKernelOn`). The Chapman--Kolmogorov law, joint measurability +and the sub-Markov bound transfer from the carrier `alpha`. + +No Feller property, strong continuity, or regularity of the killed semigroup is claimed, and its +process is not identified with the cemetery-extended process on lifetime paths. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + +namespace MarkovProcess.SubMarkovKernelSemigroup + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) +variable (U : Set alpha) (hU : IsOpen U) + +/-- The killed kernels put no mass outside `U`: a path still inside `U` at time `t` is at a point +of `U` at time `t`. -/ +theorem IsConservative.killedKernel_apply_compl (t : NNReal) (x : alpha) : + IsConservative.killedKernel P hP U hU t x Uᶜ = 0 := by + rw [IsConservative.killedKernel_apply P hP U hU t x hU.measurableSet.compl] + have hempty : ContinuousPath.killedEvent U t Uᶜ = ∅ := by + ext omega + simp only [ContinuousPath.mem_killedEvent_iff, Set.mem_compl_iff, Set.mem_empty_iff_false, + iff_false, not_and, not_not] + exact fun h ↦ ContinuousPath.mem_of_lt_exitTime U omega t h + rw [hempty, measure_empty] + +/-- Almost every point under a killed kernel lies in `U`. -/ +theorem IsConservative.ae_mem_killedKernel (t : NNReal) (x : alpha) : + ∀ᵐ y ∂(IsConservative.killedKernel P hP U hU t x), y ∈ U := + (ae_iff).mpr (IsConservative.killedKernel_apply_compl P hP U hU t x) + +/-- The killed transition kernel at time `t`, on the carrier `U`. -/ +noncomputable def IsConservative.killedKernelOn (t : NNReal) : Kernel U U := + Kernel.comapRight + (Kernel.comap (IsConservative.killedKernel P hP U hU t) Subtype.val measurable_subtype_coe) + (MeasurableEmbedding.subtype_coe hU.measurableSet) + +/-- The killed kernel on `U` is the pullback of the killed kernel on `alpha` along the inclusion. -/ +theorem IsConservative.killedKernelOn_apply_eq (t : NNReal) (x : U) : + IsConservative.killedKernelOn P hP U hU t x = + (IsConservative.killedKernel P hP U hU t x).comap Subtype.val := by + rw [IsConservative.killedKernelOn, Kernel.comapRight_apply, Kernel.comap_apply] + +/-- The killed kernel on `U` evaluated on a measurable set of `U`. -/ +theorem IsConservative.killedKernelOn_apply (t : NNReal) (x : U) {B : Set U} + (hB : MeasurableSet B) : + IsConservative.killedKernelOn P hP U hU t x B = + IsConservative.killedKernel P hP U hU t x (Subtype.val '' B) := by + rw [IsConservative.killedKernelOn, Kernel.comapRight_apply' _ _ _ hB, Kernel.comap_apply] + +/-- The killed kernel on `U`, evaluated on a set, as a probability of the path event. -/ +theorem IsConservative.killedKernelOn_apply_eq_continuousProcess (t : NNReal) (x : U) + {B : Set U} (hB : MeasurableSet B) : + IsConservative.killedKernelOn P hP U hU t x B = + IsConservative.continuousProcess P hP x + (ContinuousPath.killedEvent U t (Subtype.val '' B)) := by + rw [IsConservative.killedKernelOn_apply P hP U hU t x hB, + IsConservative.killedKernel_apply P hP U hU t x + ((MeasurableEmbedding.subtype_coe hU.measurableSet).measurableSet_image.mpr hB)] + +/-- Pushing the killed kernel on `U` forward along the inclusion recovers the killed kernel on +`alpha`. -/ +theorem IsConservative.map_val_killedKernelOn (t : NNReal) (x : U) : + (IsConservative.killedKernelOn P hP U hU t x).map Subtype.val = + IsConservative.killedKernel P hP U hU t x := by + rw [IsConservative.killedKernelOn_apply_eq, + (MeasurableEmbedding.subtype_coe hU.measurableSet).map_comap, Subtype.range_val] + exact Measure.restrict_eq_self_of_ae_mem (IsConservative.ae_mem_killedKernel P hP U hU t x) + +/-- The total mass of the killed kernel on `U` is the survival probability. -/ +theorem IsConservative.killedKernelOn_apply_univ (t : NNReal) (x : U) : + IsConservative.killedKernelOn P hP U hU t x Set.univ = + IsConservative.killedKernel P hP U hU t x U := by + rw [IsConservative.killedKernelOn_apply P hP U hU t x MeasurableSet.univ, Set.image_univ, + Subtype.range_val] + +/-- The killed kernels on `U` are sub-Markov. -/ +theorem IsConservative.isSubMarkovKernel_killedKernelOn (t : NNReal) : + IsSubMarkovKernel (IsConservative.killedKernelOn P hP U hU t) := by + intro x + rw [IsConservative.killedKernelOn_apply_univ] + exact (IsConservative.isSubMarkovKernel_killedKernel P hP U hU t).measure_le_one x U + +/-- The killed kernels on `U` are jointly measurable in time and starting point. -/ +theorem IsConservative.measurable_killedKernelOn : + Measurable fun q : NNReal × U ↦ IsConservative.killedKernelOn P hP U hU q.1 q.2 := by + refine Measure.measurable_of_measurable_coe _ fun B hB ↦ ?_ + have hfun : (fun q : NNReal × U ↦ IsConservative.killedKernelOn P hP U hU q.1 q.2 B) = + fun q ↦ IsConservative.killedKernel P hP U hU q.1 q.2 (Subtype.val '' B) := + funext fun q ↦ IsConservative.killedKernelOn_apply P hP U hU q.1 q.2 hB + rw [hfun] + have hB' : MeasurableSet (Subtype.val '' B) := + (MeasurableEmbedding.subtype_coe hU.measurableSet).measurableSet_image.mpr hB + exact (Measure.measurable_coe hB').comp ((IsConservative.measurable_killedKernel P hP U hU).comp + (measurable_fst.prodMk (measurable_subtype_coe.comp measurable_snd))) + +/-- At time zero the killed kernel on `U` is the identity kernel of `U`. -/ +theorem IsConservative.killedKernelOn_zero (hK : P.KolmogorovRegular hP) : + IsConservative.killedKernelOn P hP U hU 0 = Kernel.id := by + refine Kernel.ext fun x ↦ Measure.ext fun B hB ↦ ?_ + have hB' : MeasurableSet (Subtype.val '' B) := + (MeasurableEmbedding.subtype_coe hU.measurableSet).measurableSet_image.mpr hB + rw [IsConservative.killedKernelOn_apply P hP U hU 0 x hB, IsConservative.killedKernel_zero P hP U hU hK, + Kernel.restrict_apply' _ _ _ hB', Kernel.id_apply, Kernel.id_apply, + Measure.dirac_apply' _ (hB'.inter hU.measurableSet), Measure.dirac_apply' _ hB] + rw [Set.inter_eq_left.mpr (Subtype.coe_image_subset U B), + Set.indicator_image Subtype.val_injective] + rfl + +variable [LocallyCompactSpace alpha] + +/-- **Chapman--Kolmogorov law for the killed kernels on `U`.** -/ +theorem IsConservative.killedKernelOn_add (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) (s t : NNReal) : + IsConservative.killedKernelOn P hP U hU (s + t) = + (IsConservative.killedKernelOn P hP U hU t).comp + (IsConservative.killedKernelOn P hP U hU s) := by + refine Kernel.ext fun x ↦ Measure.ext fun B hB ↦ ?_ + have hB' : MeasurableSet (Subtype.val '' B) := + (MeasurableEmbedding.subtype_coe hU.measurableSet).measurableSet_image.mpr hB + have hfun : (fun y : U ↦ IsConservative.killedKernelOn P hP U hU t y B) = + fun y : U ↦ IsConservative.killedKernel P hP U hU t (y : alpha) (Subtype.val '' B) := + funext fun y ↦ IsConservative.killedKernelOn_apply P hP U hU t y hB + rw [IsConservative.killedKernelOn_apply P hP U hU (s + t) x hB, + IsConservative.killedKernel_add P hP U hU hFeller hK s t, Kernel.comp_apply' _ _ _ hB', + Kernel.comp_apply' _ _ _ hB, hfun, ← IsConservative.map_val_killedKernelOn P hP U hU s x, + (MeasurableEmbedding.subtype_coe hU.measurableSet).lintegral_map] + +/-- **The killed semigroup on the domain `U`**: the process of `P` killed when it leaves `U`, as a +sub-Markov kernel semigroup on the carrier `U`. -/ +noncomputable def IsConservative.killedSemigroup (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) : SubMarkovKernelSemigroup U where + kernel := IsConservative.killedKernelOn P hP U hU + measurable_kernel := IsConservative.measurable_killedKernelOn P hP U hU + kernel_zero := IsConservative.killedKernelOn_zero P hP U hU hK + kernel_add := IsConservative.killedKernelOn_add P hP U hU hFeller hK + isSubMarkovKernel := IsConservative.isSubMarkovKernel_killedKernelOn P hP U hU + +/-- The transition kernels of the killed semigroup are the killed kernels on `U`. -/ +theorem IsConservative.killedSemigroup_apply (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) (t : NNReal) : + IsConservative.killedSemigroup P hP U hU hFeller hK t = + IsConservative.killedKernelOn P hP U hU t := rfl + +/-- The killed semigroup evaluated on a set: the probability that the process started at `x ∈ U` +is still in `U` at time `t` and sits in `B` at time `t`. -/ +theorem IsConservative.killedSemigroup_apply_apply (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) (t : NNReal) (x : U) {B : Set U} (hB : MeasurableSet B) : + IsConservative.killedSemigroup P hP U hU hFeller hK t x B = + IsConservative.continuousProcess P hP x + (ContinuousPath.killedEvent U t (Subtype.val '' B)) := + IsConservative.killedKernelOn_apply_eq_continuousProcess P hP U hU t x hB + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime.lean new file mode 100644 index 0000000000..67a2bb5091 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime.lean @@ -0,0 +1,22 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.CountablySeparated +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Killing +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Nonexplosion +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.NonexplosiveTransport +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift + +/-! +# Lifetime + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Basic.lean new file mode 100644 index 0000000000..f55f85fab6 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Basic.lean @@ -0,0 +1,235 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension +import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +import Mathlib.MeasureTheory.Constructions.Polish.Basic + +/-! +# Paths with a lifetime + +This file defines paths that are continuous in the live state space strictly before a possibly +infinite lifetime and are at the cemetery state from the lifetime onward. + +The canonical measurable structure is generated by the lifetime and all fixed-time coordinates. +No countable-generation or standard-Borel claim for the lifetime-path carrier is made here. +-/ + +open MeasureTheory +open scoped ENNReal + +namespace MarkovProcess + +noncomputable section + +/-- A path with a possibly infinite lifetime, continuous on its open live-time interval. -/ +structure LifetimePath (α : Type*) [TopologicalSpace α] where + /-- The lifetime, with `∞` denoting a nonexplosive path. -/ + lifetime : ENNReal + /-- The live-state path, defined precisely at times strictly before the lifetime. -/ + livePath : {t : NNReal // (t : ENNReal) < lifetime} → α + /-- The live-state path is continuous on its natural subtype domain. -/ + continuous_livePath : Continuous livePath + +namespace LifetimePath + +variable {α : Type*} [TopologicalSpace α] + +/-- The coordinate of a lifetime path, equal to the live path before its lifetime and to the +cemetery state from its lifetime onward. -/ +def coordinate (t : NNReal) (ω : LifetimePath α) : Cemetery α := + if h : (t : ENNReal) < ω.lifetime then Cemetery.alive (ω.livePath ⟨t, h⟩) + else Cemetery.delta + +@[simp] +theorem coordinate_of_lt (ω : LifetimePath α) (t : NNReal) + (ht : (t : ENNReal) < ω.lifetime) : + coordinate t ω = Cemetery.alive (ω.livePath ⟨t, ht⟩) := by + rw [coordinate, dif_pos ht] + +@[simp] +theorem coordinate_of_le (ω : LifetimePath α) (t : NNReal) + (ht : ω.lifetime ≤ (t : ENNReal)) : coordinate t ω = Cemetery.delta := by + rw [coordinate, dif_neg (not_lt_of_ge ht)] + +/-- Coordinates strictly before the lifetime are live. -/ +theorem coordinate_ne_delta_of_lt (ω : LifetimePath α) (t : NNReal) + (ht : (t : ENNReal) < ω.lifetime) : coordinate t ω ≠ Cemetery.delta := by + rw [coordinate_of_lt ω t ht] + exact Sum.inl_ne_inr + +/-- A coordinate is live exactly when its time is strictly before the lifetime. -/ +theorem coordinate_ne_delta_iff (ω : LifetimePath α) (t : NNReal) : + coordinate t ω ≠ Cemetery.delta ↔ (t : ENNReal) < ω.lifetime := by + constructor + · intro h + by_contra hlt + exact h (coordinate_of_le ω t (not_lt.mp hlt)) + · exact coordinate_ne_delta_of_lt ω t + +/-- Two lifetime paths with the same lifetime and coordinates are equal. -/ +theorem ext_coordinate {ω η : LifetimePath α} (hlifetime : ω.lifetime = η.lifetime) + (hcoordinate : ∀ t, coordinate t ω = coordinate t η) : ω = η := by + cases ω with + | mk ωlifetime ωpath hωpath => + cases η with + | mk ηlifetime ηpath hηpath => + dsimp only at hlifetime + subst ηlifetime + congr + funext t + have h := hcoordinate t.1 + rw [coordinate_of_lt _ _ t.property, coordinate_of_lt _ _ t.property] at h + exact Sum.inl.inj h + +/-- The cemetery-valued coordinate path is continuous on its live-time subtype. -/ +theorem continuous_coordinate_before (ω : LifetimePath α) : + Continuous (fun t : {t : NNReal // (t : ENNReal) < ω.lifetime} ↦ + coordinate t ω) := by + have hcoordinate : + (fun t : {t : NNReal // (t : ENNReal) < ω.lifetime} ↦ coordinate t ω) = + Cemetery.alive ∘ ω.livePath := by + funext t + exact coordinate_of_lt ω t t.property + rw [hcoordinate] + exact continuous_inl.comp ω.continuous_livePath + +/-- Restrict a lifetime path to a compact time interval lying strictly before its lifetime. -/ +def restrictBefore (ω : LifetimePath α) (T : NNReal) + (hT : (T : ENNReal) < ω.lifetime) : C(Set.Iic T, α) where + toFun t := ω.livePath ⟨t, (ENNReal.coe_le_coe.mpr t.property).trans_lt hT⟩ + continuous_toFun := by + have hinclusion : + Continuous (fun t : Set.Iic T ↦ + (⟨t, (ENNReal.coe_le_coe.mpr t.property).trans_lt hT⟩ : + {t : NNReal // (t : ENNReal) < ω.lifetime})) := + continuous_subtype_val.subtype_mk _ + exact ω.continuous_livePath.comp hinclusion + +@[simp] +theorem restrictBefore_apply (ω : LifetimePath α) (T : NNReal) + (hT : (T : ENNReal) < ω.lifetime) (t : Set.Iic T) : + restrictBefore ω T hT t = + ω.livePath ⟨t, (ENNReal.coe_le_coe.mpr t.property).trans_lt hT⟩ := by + apply congrArg ω.livePath + apply Subtype.ext + rfl + +/-- The measurable structure generated by the lifetime and all fixed-time coordinates. -/ +instance instMeasurableSpace [MeasurableSpace α] : MeasurableSpace (LifetimePath α) := + MeasurableSpace.comap lifetime inferInstance ⊔ + ⨆ t : NNReal, MeasurableSpace.comap (coordinate t) inferInstance + +/-- The lifetime is measurable for the canonical measurable structure. -/ +theorem measurable_lifetime [MeasurableSpace α] : + Measurable (lifetime : LifetimePath α → ENNReal) := by + apply Measurable.of_comap_le + exact le_sup_left + +/-- Every fixed-time coordinate is measurable for the canonical measurable structure. -/ +theorem measurable_coordinate [MeasurableSpace α] (t : NNReal) : + Measurable (coordinate (α := α) t) := by + apply Measurable.of_comap_le + exact le_sup_of_le_right (le_iSup (fun s : NNReal ↦ + MeasurableSpace.comap (coordinate s) inferInstance) t) + +/-- An ordinary continuous path regarded as a lifetime path with infinite lifetime. -/ +def ofContinuousPath (ω : C(NNReal, α)) : LifetimePath α where + lifetime := ∞ + livePath := fun t ↦ ω t + continuous_livePath := ω.continuous.comp continuous_subtype_val + +@[simp] +theorem lifetime_ofContinuousPath (ω : C(NNReal, α)) : + (ofContinuousPath ω).lifetime = ∞ := rfl + +@[simp] +theorem coordinate_ofContinuousPath (ω : C(NNReal, α)) (t : NNReal) : + coordinate t (ofContinuousPath ω) = Cemetery.alive (ω t) := by + rw [coordinate_of_lt] + simp only [ofContinuousPath] + exact ENNReal.coe_lt_top + +/-- The infinite-lifetime embedding of ordinary continuous paths is injective. -/ +theorem ofContinuousPath_injective : + Function.Injective (ofContinuousPath (α := α)) := by + intro ω η h + apply ContinuousMap.ext + intro t + have hcoordinate := congrArg (coordinate (α := α) t) h + rw [coordinate_ofContinuousPath, coordinate_ofContinuousPath] at hcoordinate + exact Sum.inl.inj hcoordinate + +/-- An infinite-lifetime path regarded as an ordinary continuous path. -/ +def toContinuousPath (ω : LifetimePath α) (hω : ω.lifetime = ∞) : ContinuousPath α where + toFun t := ω.livePath ⟨t, by rw [hω]; exact ENNReal.coe_lt_top⟩ + continuous_toFun := by + have hinclusion : + Continuous (fun t : NNReal ↦ + (⟨t, by rw [hω]; exact ENNReal.coe_lt_top⟩ : + {t : NNReal // (t : ENNReal) < ω.lifetime})) := + continuous_id.subtype_mk _ + exact ω.continuous_livePath.comp hinclusion + +@[simp] +theorem toContinuousPath_ofContinuousPath (ω : ContinuousPath α) : + toContinuousPath (ofContinuousPath ω) (lifetime_ofContinuousPath ω) = ω := by + apply ContinuousMap.ext + intro t + rfl + +@[simp] +theorem ofContinuousPath_toContinuousPath (ω : LifetimePath α) (hω : ω.lifetime = ∞) : + ofContinuousPath (toContinuousPath ω hω) = ω := by + apply ext_coordinate + · rw [lifetime_ofContinuousPath, hω] + · intro t + have ht : (t : ENNReal) < ω.lifetime := by + rw [hω] + exact ENNReal.coe_lt_top + rw [coordinate_ofContinuousPath, coordinate_of_lt _ _ ht] + congr 2 + +section MeasurableContinuousPath + +variable [MeasurableSpace α] [BorelSpace α] + +/-- The infinite-lifetime embedding is measurable for the coordinate-generated structure. -/ +theorem measurable_ofContinuousPath : Measurable (ofContinuousPath (α := α)) := by + apply Measurable.of_comap_le + rw [instMeasurableSpace, MeasurableSpace.comap_sup, MeasurableSpace.comap_iSup] + apply sup_le + · rw [MeasurableSpace.comap_comp] + change MeasurableSpace.comap (fun _ : ContinuousPath α ↦ (∞ : ENNReal)) + inferInstance ≤ borel (ContinuousPath α) + exact measurable_const.comap_le + · rw [iSup_le_iff] + intro t + have hcoordinate : + coordinate (α := α) t ∘ ofContinuousPath = + Cemetery.alive ∘ fun ω : ContinuousPath α ↦ ω t := by + funext ω + exact coordinate_ofContinuousPath ω t + rw [MeasurableSpace.comap_comp, hcoordinate] + have heval : Measurable (fun ω : ContinuousPath α ↦ ω t) := + (continuous_eval_const t).borel_measurable.mono le_rfl + (le_of_eq BorelSpace.measurable_eq) + exact (measurable_inl.comp heval).comap_le + +variable [StandardBorelSpace (ContinuousPath α)] + [MeasurableSpace.CountablySeparated (LifetimePath α)] + +/-- The infinite-lifetime embedding is a measurable embedding whenever the lifetime-path +measurable space is countably separated. -/ +theorem measurableEmbedding_ofContinuousPath : + MeasurableEmbedding (ofContinuousPath (α := α)) := + measurable_ofContinuousPath.measurableEmbedding ofContinuousPath_injective + +end MeasurableContinuousPath + +end LifetimePath + +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/CountablySeparated.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/CountablySeparated.lean new file mode 100644 index 0000000000..b1aead5f4b --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/CountablySeparated.lean @@ -0,0 +1,126 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic + +/-! +# Countable separation of lifetime paths + +Lifetime and the coordinates at the fixed countable dense time set separate continuous lifetime +paths. Their measurable coding therefore gives a countable separating family. +-/ + +open MeasureTheory Set +open scoped ENNReal + +namespace MarkovProcess +namespace LifetimePath + +noncomputable section + +variable {alpha : Type*} [TopologicalSpace alpha] [T2Space alpha] + [MeasurableSpace alpha] + +/-- The lifetime together with all coordinates at the fixed countable dense times. -/ +def countableCode (omega : LifetimePath alpha) : + ENNReal × (DenseTime → Cemetery alpha) := + (omega.lifetime, fun q ↦ omega.coordinate (DenseTime.castOrderEmbedding q)) + +omit [T2Space alpha] in +/-- The lifetime-path code is measurable for the canonical coordinate-generated structure. -/ +theorem measurable_countableCode : Measurable (countableCode (alpha := alpha)) := by + apply measurable_lifetime.prodMk + rw [measurable_pi_iff] + intro q + exact measurable_coordinate (DenseTime.castOrderEmbedding q) + +private def denseBefore (L : ENNReal) : + {q : DenseTime // (DenseTime.castOrderEmbedding q : ENNReal) < L} → + {t : NNReal // (t : ENNReal) < L} := + fun q ↦ ⟨DenseTime.castOrderEmbedding q, q.property⟩ + +private theorem denseRange_denseBefore (L : ENNReal) : + DenseRange (denseBefore L) := by + rw [DenseRange] + rw [dense_iff_closure_eq] + apply Set.eq_univ_of_forall + intro t + rw [closure_subtype] + let U : Set NNReal := {s | (s : ENNReal) < L} + have hU : IsOpen U := isOpen_lt ENNReal.continuous_coe continuous_const + have himage : + ((↑) : {s : NNReal // (s : ENNReal) < L} → NNReal) '' + Set.range (denseBefore L) = + Set.range DenseTime.castOrderEmbedding ∩ U := by + ext s + constructor + · rintro ⟨r, ⟨q, hqr⟩, hrs⟩ + have hr := r.property + have hqrval := congrArg Subtype.val hqr + change r.1 = s at hrs + refine ⟨⟨q, hqrval.trans hrs⟩, ?_⟩ + change (s : ENNReal) < L + rw [← hrs] + exact hr + · rintro ⟨⟨q, hq⟩, hs⟩ + subst s + exact ⟨denseBefore L ⟨q, hs⟩, ⟨⟨q, hs⟩, rfl⟩, rfl⟩ + rw [himage] + simpa only [inter_comm] using + ContinuousPath.denseRange_castOrderEmbedding.open_subset_closure_inter hU t.property + +omit [MeasurableSpace alpha] in +/-- Lifetime and dense-time coordinates determine a lifetime path. -/ +theorem countableCode_injective : Function.Injective (countableCode (alpha := alpha)) := by + intro omega eta hcode + have hlifetime : omega.lifetime = eta.lifetime := congrArg Prod.fst hcode + cases omega with + | mk omegaLifetime omegaPath homega => + cases eta with + | mk etaLifetime etaPath heta => + dsimp only [countableCode] at hcode hlifetime + subst etaLifetime + congr + funext t + have hdense : + (fun q ↦ omegaPath (denseBefore omegaLifetime q)) = + fun q ↦ etaPath (denseBefore omegaLifetime q) := by + funext q + have hq := congrFun (congrArg Prod.snd hcode) q.1 + change coordinate (DenseTime.castOrderEmbedding q.1) + { lifetime := omegaLifetime, livePath := omegaPath, + continuous_livePath := homega } = + coordinate (DenseTime.castOrderEmbedding q.1) + { lifetime := omegaLifetime, livePath := etaPath, + continuous_livePath := heta } at hq + rw [coordinate_of_lt _ _ q.property, coordinate_of_lt _ _ q.property] at hq + exact Sum.inl.inj hq + have hall : omegaPath = etaPath := + (denseRange_denseBefore omegaLifetime).equalizer homega heta hdense + exact congrFun hall t + +/-- Continuous lifetime paths are countably separated by lifetime and fixed dense-time +coordinates. -/ +instance instCountablySeparated + [StandardBorelSpace (Cemetery alpha)] : + MeasurableSpace.CountablySeparated (LifetimePath alpha) := by + rcases (inferInstance : + MeasurableSpace.CountablySeparated + (ENNReal × (DenseTime → Cemetery alpha))) with ⟨S, hScount, hSmeas, hSsep⟩ + let T : Set (Set (LifetimePath alpha)) := + (fun s ↦ countableCode (alpha := alpha) ⁻¹' s) '' S + refine ⟨T, hScount.image _, ?_, ?_⟩ + · rintro t ⟨s, hs, rfl⟩ + exact hSmeas s hs |>.preimage measurable_countableCode + · intro omega _ eta _ h + apply countableCode_injective + apply hSsep _ trivial _ trivial + intro s hs + exact h _ ⟨s, hs, rfl⟩ + +end +end LifetimePath +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTime.lean new file mode 100644 index 0000000000..33e35bc235 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTime.lean @@ -0,0 +1,110 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic + +/-! +# Exit times of lifetime paths + +This file defines the first time at which a lifetime path is not a live point of a prescribed +set. Reaching the cemetery state counts as exit. The infimum of the empty set is infinity, so a +path which never exits has infinite exit time. + +Only deterministic order properties are proved here. No measurability or stopping-time claim is +made. +-/ + +open Set +open scoped ENNReal + +namespace MarkovProcess + +noncomputable section + +namespace LifetimePath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- The first time at which a lifetime path is not a live point of `U`. -/ +def exitTime (U : Set alpha) (omega : LifetimePath alpha) : ENNReal := + sInf {s : ENNReal | ∃ t : NNReal, s = (t : ENNReal) ∧ + coordinate t omega ∉ Cemetery.alive '' U} + +/-- A failed live-`U` coordinate bounds the first exit time from above. -/ +theorem exitTime_le_of_coordinate_notMem (U : Set alpha) (omega : LifetimePath alpha) + (t : NNReal) (ht : coordinate t omega ∉ Cemetery.alive '' U) : + exitTime U omega ≤ (t : ENNReal) := by + apply sInf_le + exact ⟨t, rfl, ht⟩ + +/-- Strictly before the exit time, the coordinate is a live point of `U`. -/ +theorem exists_coordinate_eq_alive_of_lt_exitTime (U : Set alpha) + (omega : LifetimePath alpha) (t : NNReal) (ht : (t : ENNReal) < exitTime U omega) : + ∃ x ∈ U, coordinate t omega = Cemetery.alive x := by + by_contra hcoordinate + have hnotmem : coordinate t omega ∉ Cemetery.alive '' U := by + rintro ⟨x, hx, hxeq⟩ + exact hcoordinate ⟨x, hx, hxeq.symm⟩ + exact (not_le_of_gt ht) (exitTime_le_of_coordinate_notMem U omega t hnotmem) + +/-- The exit time is no later than the lifetime, since killing counts as exit. -/ +theorem exitTime_le_lifetime (U : Set alpha) (omega : LifetimePath alpha) : + exitTime U omega ≤ omega.lifetime := by + by_cases hlifetime : omega.lifetime = ∞ + · rw [hlifetime] + exact le_top + · let t : NNReal := omega.lifetime.toNNReal + have ht : (t : ENNReal) = omega.lifetime := ENNReal.coe_toNNReal hlifetime + rw [← ht] + apply exitTime_le_of_coordinate_notMem + rw [coordinate_of_le omega t ht.ge] + rintro ⟨x, _, hdelta⟩ + exact Sum.inl_ne_inr hdelta + +end LifetimePath + +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- The first time at which an ordinary continuous path leaves `U`. -/ +def exitTime (U : Set alpha) (omega : ContinuousPath alpha) : ENNReal := + sInf {s : ENNReal | ∃ t : NNReal, s = (t : ENNReal) ∧ omega t ∉ U} + +end ContinuousPath + +namespace LifetimePath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- The lifetime-path exit time of an ordinary continuous path is its ordinary exit time. -/ +@[simp] +theorem exitTime_ofContinuousPath (U : Set alpha) (omega : ContinuousPath alpha) : + exitTime U (ofContinuousPath omega) = ContinuousPath.exitTime U omega := by + apply congrArg sInf + ext s + constructor + · rintro ⟨t, hst, ht⟩ + refine ⟨t, hst, ?_⟩ + intro homega + apply ht + exact ⟨omega t, homega, coordinate_ofContinuousPath omega t |>.symm⟩ + · rintro ⟨t, hst, ht⟩ + refine ⟨t, hst, ?_⟩ + rintro ⟨x, hx, hcoordinate⟩ + rw [coordinate_ofContinuousPath] at hcoordinate + have heq : omega t = x := Sum.inl.inj hcoordinate.symm + exact ht (heq.symm ▸ hx) + +/-- An infinite-lifetime path has the exit time of its associated ordinary continuous path. -/ +theorem exitTime_eq_exitTime_toContinuousPath (U : Set alpha) (omega : LifetimePath alpha) + (homega : omega.lifetime = ∞) : + exitTime U omega = ContinuousPath.exitTime U (toContinuousPath omega homega) := by + rw [← exitTime_ofContinuousPath, ofContinuousPath_toContinuousPath omega homega] + +end LifetimePath + +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTimeStopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTimeStopping.lean new file mode 100644 index 0000000000..49941beae2 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTimeStopping.lean @@ -0,0 +1,307 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration + +/-! # Exit times as stopping times -/ + +open MeasureTheory Set +open scoped ENNReal + +namespace MarkovProcess.LifetimePath + +noncomputable section + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +private theorem exists_time_between_lifetime (omega : LifetimePath alpha) (t : NNReal) + (ht : (t : ENNReal) < omega.lifetime) : + ∃ r : NNReal, t < r ∧ (r : ENNReal) < omega.lifetime := by + cases hlifetime : omega.lifetime with + | top => + refine ⟨t + 1, lt_add_one t, ?_⟩ + exact ENNReal.coe_lt_top + | coe u => + have htu : t < u := by + rw [hlifetime, ENNReal.coe_lt_coe] at ht + exact ht + obtain ⟨r, htr, hru⟩ := exists_between htu + exact ⟨r, htr, ENNReal.coe_lt_coe.mpr hru⟩ + +private theorem exists_right_interval_in_open (omega : LifetimePath alpha) (U : Set alpha) + (hU : IsOpen U) (t : NNReal) (ht : (t : ENNReal) < omega.lifetime) + (htU : omega.livePath ⟨t, ht⟩ ∈ U) : + ∃ r : NNReal, t < r ∧ (r : ENNReal) < omega.lifetime ∧ + ∀ s : NNReal, t < s → s < r → coordinate s omega ∈ Cemetery.alive '' U := by + let O : Set {s : NNReal // (s : ENNReal) < omega.lifetime} := omega.livePath ⁻¹' U + have hOopen : IsOpen O := hU.preimage omega.continuous_livePath + have htO : (⟨t, ht⟩ : {s : NNReal // (s : ENNReal) < omega.lifetime}) ∈ O := htU + obtain ⟨V, hVopen, hV⟩ := isOpen_induced_iff.mp hOopen + have htV : t ∈ V := by + have : (⟨t, ht⟩ : {s : NNReal // (s : ENNReal) < omega.lifetime}) ∈ + Subtype.val ⁻¹' V := by + rw [hV] + exact htO + exact this + obtain ⟨b, htb, hblife⟩ := exists_time_between_lifetime omega t ht + let W : Set NNReal := V ∩ Set.Iio b + have hWopen : IsOpen W := hVopen.inter isOpen_Iio + have htW : t ∈ W := ⟨htV, htb⟩ + have hWnhds : W ∈ nhdsWithin t (Set.Ioi t) := + mem_nhdsWithin_of_mem_nhds (hWopen.mem_nhds htW) + obtain ⟨r, htr, hrW⟩ := (mem_nhdsGT_iff_exists_Ioo_subset.mp hWnhds) + have hrb : r ≤ b := by + by_contra hbr + obtain ⟨s, hbs, hsr⟩ := exists_between (lt_of_not_ge hbr) + have hsW := hrW ⟨htb.trans hbs, hsr⟩ + exact (not_lt_of_ge hbs.le) hsW.2 + have hrlife : (r : ENNReal) < omega.lifetime := + (ENNReal.coe_le_coe.mpr hrb).trans_lt hblife + refine ⟨r, htr, hrlife, ?_⟩ + intro s hts hsr + have hsW := hrW ⟨hts, hsr⟩ + have hslife : (s : ENNReal) < omega.lifetime := + (ENNReal.coe_lt_coe.mpr hsr).trans hrlife + rw [coordinate_of_lt omega s hslife] + refine ⟨omega.livePath ⟨s, hslife⟩, ?_, rfl⟩ + have hsO : (⟨s, hslife⟩ : {u : NNReal // (u : ENNReal) < omega.lifetime}) ∈ O := by + rw [← hV] + exact hsW.1 + exact hsO + +private theorem exitTime_le_iff (U : Set alpha) (hU : IsOpen U) + (omega : LifetimePath alpha) (t : NNReal) : + exitTime U omega ≤ (t : ENNReal) ↔ + omega.lifetime ≤ (t : ENNReal) ∨ + ∃ s : Set.Iic t, coordinate s omega ∈ Cemetery.alive '' Uᶜ := by + constructor + · intro hexit + by_cases hlifetime : omega.lifetime ≤ (t : ENNReal) + · exact Or.inl hlifetime + · right + have ht : (t : ENNReal) < omega.lifetime := lt_of_not_ge hlifetime + by_contra hhit + have hgood : ∀ s : Set.Iic t, coordinate s omega ∈ Cemetery.alive '' U := by + intro s + have hslife : (s : ENNReal) < omega.lifetime := + (ENNReal.coe_le_coe.mpr s.property).trans_lt ht + rw [coordinate_of_lt omega s hslife] + let x := omega.livePath ⟨s, hslife⟩ + have hxU : x ∈ U := by + by_contra hxU + exact hhit ⟨s, x, hxU, (coordinate_of_lt omega s hslife).symm⟩ + refine ⟨x, hxU, ?_⟩ + dsimp only [x] + obtain ⟨x, hxU, htx⟩ := hgood ⟨t, Set.mem_Iic.mpr le_rfl⟩ + rw [coordinate_of_lt omega t ht] at htx + have hx : omega.livePath ⟨t, ht⟩ = x := (Sum.inl.inj htx).symm + have htU : omega.livePath ⟨t, ht⟩ ∈ U := hx ▸ hxU + obtain ⟨r, htr, -, hright⟩ := exists_right_interval_in_open omega U hU t ht htU + have hrle : (r : ENNReal) ≤ exitTime U omega := by + apply le_sInf + rintro z ⟨s, rfl, hsbad⟩ + apply ENNReal.coe_le_coe.mpr + by_contra hsr + have hsr' : s < r := lt_of_not_ge hsr + by_cases hst : s ≤ t + · exact hsbad (hgood ⟨s, Set.mem_Iic.mpr hst⟩) + · exact hsbad (hright s (lt_of_not_ge hst) hsr') + exact (not_lt_of_ge hexit) ((ENNReal.coe_lt_coe.mpr htr).trans_le hrle) + · rintro (hlifetime | ⟨s, x, hxnotU, hsx⟩) + · exact (exitTime_le_lifetime U omega).trans hlifetime + · refine (exitTime_le_of_coordinate_notMem U omega s ?_).trans + (ENNReal.coe_le_coe.mpr s.property) + rintro ⟨y, hyU, hy⟩ + have hxy : x = y := Sum.inl.inj (hsx.trans hy.symm) + exact hxnotU (hxy ▸ hyU) + +private def detectionThreshold (n : ℕ) : ℝ := 1 / (n + 1 : ℝ) + +private def liveInfDist (F : Set alpha) : Cemetery alpha → ℝ := + Sum.elim (fun x ↦ Metric.infDist x F) (fun _ ↦ 1) + +private def DetectsLiveClosedSetBy (t : NNReal) (F : Set alpha) + (omega : LifetimePath alpha) : Prop := + F.Nonempty ∧ ∀ n : ℕ, + liveInfDist F (coordinate t omega) < detectionThreshold n ∨ + ∃ k : ℕ, DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t ∧ + liveInfDist F + (coordinate (DenseTime.castOrderEmbedding (DenseTime.enumeration k)) omega) < + detectionThreshold n + +private theorem detectsLiveClosedSetBy_iff (t : NNReal) (F : Set alpha) + (hF : IsClosed F) (omega : LifetimePath alpha) + (ht : (t : ENNReal) < omega.lifetime) : + DetectsLiveClosedSetBy t F omega ↔ + ∃ s : Set.Iic t, coordinate s omega ∈ Cemetery.alive '' F := by + have hhit : (∃ s : Set.Iic t, coordinate s omega ∈ Cemetery.alive '' F) ↔ + ∃ s : Set.Iic t, (restrictBefore omega t ht) s ∈ F := by + constructor + · rintro ⟨s, x, hxF, hsx⟩ + have hslife : (s : ENNReal) < omega.lifetime := + (ENNReal.coe_le_coe.mpr s.property).trans_lt ht + rw [coordinate_of_lt omega s hslife] at hsx + have hx : omega.livePath ⟨s, hslife⟩ = x := (Sum.inl.inj hsx).symm + refine ⟨s, ?_⟩ + rw [restrictBefore_apply] + exact hx ▸ hxF + · rintro ⟨s, hsF⟩ + have hslife : (s : ENNReal) < omega.lifetime := + (ENNReal.coe_le_coe.mpr s.property).trans_lt ht + refine ⟨s, omega.livePath ⟨s, hslife⟩, ?_, ?_⟩ + · rw [restrictBefore_apply] at hsF + exact hsF + · exact (coordinate_of_lt omega s hslife).symm + have hrestrict := ContinuousPath.detectsClosedSetOnIic_iff + t F hF (restrictBefore omega t ht) + rw [hhit, ← hrestrict] + constructor + · rintro ⟨hFnonempty, hdetect⟩ + refine ⟨hFnonempty, fun n ↦ ?_⟩ + rcases hdetect n with hendpoint | ⟨k, hkt, hk⟩ + · left + simpa only [ContinuousPath.restrictIic, restrictBefore_apply, + liveInfDist, detectionThreshold, + coordinate_of_lt omega t ht] using! hendpoint + · right + refine ⟨k, hkt, ?_⟩ + have hklife : + (DenseTime.castOrderEmbedding (DenseTime.enumeration k) : ENNReal) < + omega.lifetime := + (ENNReal.coe_lt_coe.mpr hkt).trans ht + simpa only [ContinuousPath.restrictIic, restrictBefore_apply, + liveInfDist, detectionThreshold, + coordinate_of_lt omega _ hklife] using! hk + · rintro ⟨hFnonempty, hdetect⟩ + refine ⟨hFnonempty, fun n ↦ ?_⟩ + rcases hdetect n with hendpoint | ⟨k, hkt, hk⟩ + · left + simpa only [ContinuousPath.restrictIic, restrictBefore_apply, + liveInfDist, detectionThreshold, + coordinate_of_lt omega t ht] using! hendpoint + · right + refine ⟨k, hkt, ?_⟩ + have hklife : + (DenseTime.castOrderEmbedding (DenseTime.enumeration k) : ENNReal) < + omega.lifetime := + (ENNReal.coe_lt_coe.mpr hkt).trans ht + simpa only [ContinuousPath.restrictIic, restrictBefore_apply, + liveInfDist, detectionThreshold, + coordinate_of_lt omega _ hklife] using! hk + +section Measurable + +variable [MeasurableSpace alpha] [BorelSpace alpha] + +private theorem measurable_liveInfDist (F : Set alpha) : Measurable (liveInfDist F) := by + apply measurable_fun_sum + · exact (Metric.continuous_infDist_pt (s := F)).borel_measurable.mono + (le_of_eq BorelSpace.measurable_eq.symm) le_rfl + · exact measurable_const + +private theorem measurable_liveInfDist_coordinate (t : NNReal) (F : Set alpha) + {s : NNReal} (hs : s ≤ t) : + Measurable[canonicalFiltration (alpha := alpha) t] + (fun omega : LifetimePath alpha ↦ liveInfDist F (coordinate s omega)) := by + have hcoordinate : Measurable[canonicalFiltration (alpha := alpha) t] + (coordinate (α := alpha) s) := by + apply Measurable.of_comap_le + exact le_iSup_of_le (⟨s, Set.mem_Iic.mpr hs⟩ : Set.Iic t) le_rfl + exact (measurable_liveInfDist F).comp hcoordinate + +private theorem measurableSet_detectsLiveClosedSetBy (t : NNReal) (F : Set alpha) : + MeasurableSet[canonicalFiltration (alpha := alpha) t] + {omega | DetectsLiveClosedSetBy t F omega} := by + by_cases hFnonempty : F.Nonempty + swap + have hevent : {omega | DetectsLiveClosedSetBy t F omega} = ∅ := by + ext omega + change DetectsLiveClosedSetBy t F omega ↔ False + simp only [DetectsLiveClosedSetBy, hFnonempty, false_and] + rw [hevent] + exact @MeasurableSet.empty _ (canonicalFiltration (alpha := alpha) t) + have hmeas (n : ℕ) : MeasurableSet[canonicalFiltration (alpha := alpha) t] + ({omega | liveInfDist F (coordinate t omega) < detectionThreshold n} ∪ + ⋃ k : ℕ, if h : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t then + {omega | liveInfDist F + (coordinate (DenseTime.castOrderEmbedding (DenseTime.enumeration k)) omega) < + detectionThreshold n} + else ∅) := by + apply MeasurableSet.union + · exact (measurable_liveInfDist_coordinate t F le_rfl) measurableSet_Iio + · apply MeasurableSet.iUnion + intro k + split_ifs with hkt + · exact (measurable_liveInfDist_coordinate t F hkt.le) measurableSet_Iio + · exact @MeasurableSet.empty _ (canonicalFiltration (alpha := alpha) t) + have hevent : {omega | DetectsLiveClosedSetBy t F omega} = + ⋂ n : ℕ, + ({omega | liveInfDist F (coordinate t omega) < detectionThreshold n} ∪ + ⋃ k : ℕ, if h : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t then + {omega | liveInfDist F + (coordinate (DenseTime.castOrderEmbedding (DenseTime.enumeration k)) omega) < + detectionThreshold n} + else ∅) := by + ext omega + simp only [DetectsLiveClosedSetBy, hFnonempty, true_and, Set.mem_ofPred_eq, + Set.mem_iInter, Set.mem_union, Set.mem_iUnion] + constructor + · intro h n + rcases h n with hendpoint | ⟨k, hkt, hk⟩ + · exact Or.inl hendpoint + · exact Or.inr ⟨k, by rw [dif_pos hkt]; exact hk⟩ + · intro h n + rcases h n with hendpoint | ⟨k, hk⟩ + · exact Or.inl hendpoint + · by_cases hkt : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t + · exact Or.inr ⟨k, hkt, by simpa only [dif_pos hkt] using! hk⟩ + · simp only [dif_neg hkt, Set.notMem_empty] at hk + rw [hevent] + exact MeasurableSet.iInter hmeas + +/-- The exit time from an open set is a stopping time for the raw canonical filtration. -/ +theorem isStoppingTime_exitTime (U : Set alpha) (hU : IsOpen U) : + IsStoppingTime (canonicalFiltration (alpha := alpha)) (exitTime U) := by + intro t + let death : Set (LifetimePath alpha) := + {omega | omega.lifetime ≤ (t : ENNReal)} + let spatial : Set (LifetimePath alpha) := + {omega | (t : ENNReal) < omega.lifetime ∧ DetectsLiveClosedSetBy t Uᶜ omega} + have hdeath : MeasurableSet[canonicalFiltration (alpha := alpha) t] death := + isStoppingTime_lifetime t + have hpast : MeasurableSet[canonicalFiltration (alpha := alpha) t] + {omega : LifetimePath alpha | (t : ENNReal) < omega.lifetime} := by + have hcompl : {omega : LifetimePath alpha | (t : ENNReal) < omega.lifetime} = deathᶜ := by + ext omega + simp only [death, Set.mem_ofPred_eq, Set.mem_compl_iff] + exact lt_iff_not_ge + rw [hcompl] + exact hdeath.compl + have hspatial : MeasurableSet[canonicalFiltration (alpha := alpha) t] spatial := by + exact hpast.inter (measurableSet_detectsLiveClosedSetBy t Uᶜ) + have hevent : {omega : LifetimePath alpha | exitTime U omega ≤ (t : ENNReal)} = + death ∪ spatial := by + ext omega + change (exitTime U omega ≤ (t : ENNReal)) ↔ _ + rw [Set.mem_union] + rw [exitTime_le_iff U hU] + by_cases hlifetime : omega.lifetime ≤ (t : ENNReal) + · simp only [death, spatial, Set.mem_ofPred_eq, hlifetime, true_or, + not_lt_of_ge hlifetime, false_and, or_false] + · have ht : (t : ENNReal) < omega.lifetime := lt_of_not_ge hlifetime + have hdetect := detectsLiveClosedSetBy_iff t Uᶜ hU.isClosed_compl omega ht + simp only [death, spatial, Set.mem_ofPred_eq, hlifetime, false_or, ht, true_and] + exact hdetect.symm + change MeasurableSet[canonicalFiltration (alpha := alpha) t] + {omega : LifetimePath alpha | exitTime U omega ≤ (t : ENNReal)} + rw [hevent] + exact hdeath.union hspatial + +end Measurable + +end +end MarkovProcess.LifetimePath diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean new file mode 100644 index 0000000000..4c90e491c0 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean @@ -0,0 +1,89 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift +import Mathlib.Probability.Process.Stopping + +/-! +# Canonical filtration of lifetime paths + +The raw canonical filtration is generated by the cemetery-valued coordinates up to each time. +The lifetime is a stopping time because death by time `t` is exactly the event that the time-`t` +coordinate is the cemetery state. +-/ + +open MeasureTheory +open scoped ENNReal + +namespace MarkovProcess.LifetimePath + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + +omit [MeasurableSpace alpha] in +/-- A coordinate is the cemetery state exactly at and after the lifetime. -/ +theorem coordinate_eq_delta_iff (omega : LifetimePath alpha) (t : NNReal) : + coordinate t omega = Cemetery.delta ↔ omega.lifetime ≤ (t : ENNReal) := by + constructor + · intro hcoordinate + by_contra hlifetime + exact coordinate_ne_delta_of_lt omega t (lt_of_not_ge hlifetime) hcoordinate + · exact coordinate_of_le omega t + +/-- The raw canonical filtration generated by lifetime-path coordinates up to time `t`. -/ +noncomputable def canonicalFiltration : + Filtration NNReal (instMeasurableSpace (α := alpha)) where + seq t := ⨆ s : Set.Iic t, + MeasurableSpace.comap (coordinate (α := alpha) s) inferInstance + mono' t u htu := by + refine iSup_le fun s ↦ ?_ + exact le_iSup_of_le (⟨s.1, s.2.trans htu⟩ : Set.Iic u) le_rfl + le' t := iSup_le fun s ↦ (measurable_coordinate s).comap_le + +/-- The time-`t` coordinate is measurable for the canonical filtration at time `t`. -/ +theorem measurable_coordinate_canonicalFiltration (t : NNReal) : + Measurable[canonicalFiltration (alpha := alpha) t] + (coordinate (α := alpha) t) := by + apply Measurable.of_comap_le + exact le_iSup_of_le (⟨t, Set.mem_Iic.mpr le_rfl⟩ : Set.Iic t) le_rfl + +/-- Shifting by `S` sends events observable by shifted time `t` to events observable by original +time `S + t`. -/ +theorem measurable_shift_canonicalFiltration (S t : NNReal) : + Measurable[canonicalFiltration (alpha := alpha) (S + t), + canonicalFiltration (alpha := alpha) t] + (shift S : LifetimePath alpha → LifetimePath alpha) := by + apply Measurable.of_comap_le + rw [canonicalFiltration, MeasurableSpace.comap_iSup] + rw [iSup_le_iff] + intro u + rw [MeasurableSpace.comap_comp] + have hfun : coordinate (α := alpha) u ∘ shift S = coordinate (S + u) := by + funext omega + exact coordinate_shift S u omega + rw [hfun] + exact le_iSup_of_le + (⟨S + u, by simpa only [add_comm] using! add_le_add_left u.property S⟩ : + Set.Iic (S + t)) le_rfl + +/-- The lifetime is a stopping time for the raw canonical filtration. -/ +theorem isStoppingTime_lifetime : + IsStoppingTime (canonicalFiltration (alpha := alpha)) + (lifetime : LifetimePath alpha → ENNReal) := by + intro t + have hdelta : MeasurableSet ({Cemetery.delta} : Set (Cemetery alpha)) := by + simpa only [Set.range_unique] using + (measurableSet_range_inr : + MeasurableSet (Set.range (Sum.inr : Unit → alpha ⊕ Unit))) + have hevent : {omega : LifetimePath alpha | omega.lifetime ≤ (t : ENNReal)} = + coordinate (α := alpha) t ⁻¹' {Cemetery.delta} := by + ext omega + simpa only [Set.mem_ofPred_eq, Set.mem_preimage, Set.mem_singleton_iff] using + (coordinate_eq_delta_iff omega t).symm + show MeasurableSet[canonicalFiltration (alpha := alpha) t] + {omega : LifetimePath alpha | omega.lifetime ≤ (t : ENNReal)} + rw [hevent] + exact (measurable_coordinate_canonicalFiltration t) hdelta + +end MarkovProcess.LifetimePath diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Killing.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Killing.lean new file mode 100644 index 0000000000..789700e360 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Killing.lean @@ -0,0 +1,110 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic + +/-! +# Deterministic killing of lifetime paths + +This file truncates a lifetime path at a deterministic finite time. The coordinate at the +killing time itself is the cemetery state, so this operation is distinct from endpoint-retaining +stopping. +-/ + +open MeasureTheory +open scoped ENNReal + +namespace MarkovProcess.LifetimePath + +noncomputable section + +variable {α : Type*} [TopologicalSpace α] + +/-- Kill a lifetime path at the deterministic time `T`. -/ +def killAt (T : NNReal) (ω : LifetimePath α) : LifetimePath α where + lifetime := min ω.lifetime (T : ENNReal) + livePath := fun t ↦ ω.livePath ⟨t, lt_of_lt_of_le t.property (min_le_left _ _)⟩ + continuous_livePath := by + apply ω.continuous_livePath.comp + exact continuous_subtype_val.subtype_mk _ + +@[simp] +theorem lifetime_killAt (T : NNReal) (ω : LifetimePath α) : + (killAt T ω).lifetime = min ω.lifetime (T : ENNReal) := + rfl + +/-- Killing does not change a coordinate strictly before the killing time. -/ +theorem coordinate_killAt_of_lt (T t : NNReal) (ω : LifetimePath α) + (ht : (t : ENNReal) < (T : ENNReal)) : + coordinate t (killAt T ω) = coordinate t ω := by + by_cases hω : (t : ENNReal) < ω.lifetime + · have hk : (t : ENNReal) < min ω.lifetime (T : ENNReal) := lt_min hω ht + rw [coordinate_of_lt _ _ hk, coordinate_of_lt _ _ hω] + rfl + · have hωle : ω.lifetime ≤ (t : ENNReal) := not_lt.mp hω + rw [coordinate_of_le _ _ hωle] + apply coordinate_of_le + exact (min_le_left _ _).trans hωle + +/-- At and after the deterministic killing time, the killed coordinate is the cemetery state. -/ +@[simp] +theorem coordinate_killAt_of_le (T t : NNReal) (ω : LifetimePath α) (ht : T ≤ t) : + coordinate t (killAt T ω) = Cemetery.delta := by + apply coordinate_of_le + exact (min_le_right _ _).trans (ENNReal.coe_le_coe.mpr ht) + +/-- Killing twice is killing once at the earlier of the two deterministic times. -/ +theorem killAt_killAt (S T : NNReal) (ω : LifetimePath α) : + killAt T (killAt S ω) = killAt (min T S) ω := by + apply ext_coordinate + · simp only [lifetime_killAt, ENNReal.coe_min] + rw [min_assoc] + exact congrArg (min ω.lifetime) (min_comm (S : ENNReal) (T : ENNReal)) + · intro t + by_cases htT : t < T + · rw [coordinate_killAt_of_lt T t (killAt S ω) (ENNReal.coe_lt_coe.mpr htT)] + by_cases htS : t < S + · rw [coordinate_killAt_of_lt S t ω (ENNReal.coe_lt_coe.mpr htS)] + rw [coordinate_killAt_of_lt (min T S) t ω] + exact ENNReal.coe_lt_coe.mpr (lt_min htT htS) + · rw [coordinate_killAt_of_le S t ω (not_lt.mp htS)] + rw [coordinate_killAt_of_le (min T S) t ω] + exact (min_le_right T S).trans (not_lt.mp htS) + · rw [coordinate_killAt_of_le T t (killAt S ω) (not_lt.mp htT)] + rw [coordinate_killAt_of_le (min T S) t ω] + exact (min_le_left T S).trans (not_lt.mp htT) + +section Measurable + +variable [MeasurableSpace α] + +/-- Killing at a fixed deterministic time is measurable for the coordinate-generated +measurable structure on lifetime paths. -/ +theorem measurable_killAt (T : NNReal) : + Measurable (killAt T : LifetimePath α → LifetimePath α) := by + apply Measurable.of_comap_le + rw [instMeasurableSpace, MeasurableSpace.comap_sup, MeasurableSpace.comap_iSup] + apply sup_le + · rw [MeasurableSpace.comap_comp] + exact (measurable_lifetime.min measurable_const).comap_le + · rw [iSup_le_iff] + intro t + rw [MeasurableSpace.comap_comp] + by_cases ht : (t : ENNReal) < (T : ENNReal) + · have hfun : coordinate (α := α) t ∘ killAt T = coordinate t := by + funext ω + exact coordinate_killAt_of_lt T t ω ht + rw [hfun] + exact (measurable_coordinate t).comap_le + · have hfun : coordinate (α := α) t ∘ killAt T = fun _ ↦ Cemetery.delta := by + funext ω + exact coordinate_killAt_of_le T t ω (ENNReal.coe_le_coe.mp (not_lt.mp ht)) + rw [hfun] + exact measurable_const.comap_le + +end Measurable + +end +end MarkovProcess.LifetimePath diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Law.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Law.lean new file mode 100644 index 0000000000..4251f74e4e --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Law.lean @@ -0,0 +1,80 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +import Mathlib.Probability.Kernel.Composition.MapComap + +/-! +# Continuous laws as nonexplosive lifetime-path laws + +This file transports kernels on ordinary continuous paths through the infinite-lifetime +embedding. It records the resulting nonexplosion and coordinate identities without asserting +that any particular dense-time or PDE law has continuous paths. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal + +namespace MarkovProcess + +noncomputable section + +namespace Kernel + +variable {beta alpha : Type*} [MeasurableSpace beta] [TopologicalSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] + +/-- A kernel on lifetime paths is nonexplosive when its lifetime is almost surely infinite +from every starting point. -/ +def IsNonexplosive (kappa : Kernel beta (LifetimePath alpha)) : Prop := + ∀ x, ∀ᵐ omega ∂kappa x, omega.lifetime = ∞ + +/-- Regard a kernel on ordinary continuous paths as a kernel on infinite-lifetime paths. -/ +def toLifetimePathKernel (kappa : Kernel beta (ContinuousPath alpha)) : + Kernel beta (LifetimePath alpha) := + Kernel.mapOfMeasurable kappa LifetimePath.ofContinuousPath + LifetimePath.measurable_ofContinuousPath + +/-- The lifetime-path transport agrees with ordinary kernel mapping. -/ +theorem toLifetimePathKernel_eq_map (kappa : Kernel beta (ContinuousPath alpha)) : + toLifetimePathKernel kappa = kappa.map LifetimePath.ofContinuousPath := + Kernel.mapOfMeasurable_eq_map _ LifetimePath.measurable_ofContinuousPath + +/-- A Markov continuous-path kernel remains Markov after the infinite-lifetime embedding. -/ +theorem isMarkovKernel_toLifetimePathKernel + (kappa : Kernel beta (ContinuousPath alpha)) [IsMarkovKernel kappa] : + IsMarkovKernel (toLifetimePathKernel kappa) := by + rw [toLifetimePathKernel_eq_map] + exact Kernel.IsMarkovKernel.map _ LifetimePath.measurable_ofContinuousPath + +/-- Transporting an ordinary continuous-path law through the infinite-lifetime embedding is +nonexplosive. -/ +theorem isNonexplosive_toLifetimePathKernel + (kappa : Kernel beta (ContinuousPath alpha)) : + IsNonexplosive (toLifetimePathKernel kappa) := by + intro x + rw [toLifetimePathKernel_eq_map, + Kernel.map_apply _ LifetimePath.measurable_ofContinuousPath] + refine (ae_map_iff (μ := kappa x) + LifetimePath.measurable_ofContinuousPath.aemeasurable ?_).2 ?_ + · exact measurableSet_eq_fun LifetimePath.measurable_lifetime measurable_const + · exact Filter.Eventually.of_forall LifetimePath.lifetime_ofContinuousPath + +/-- At every time, the coordinate law of the lifetime-path transport is the original +continuous-path coordinate law, embedded as a live cemetery state. -/ +theorem toLifetimePathKernel_map_coordinate + (kappa : Kernel beta (ContinuousPath alpha)) (t : NNReal) : + (toLifetimePathKernel kappa).map (LifetimePath.coordinate t) = + kappa.map (fun omega => Cemetery.alive (omega t)) := by + rw [toLifetimePathKernel_eq_map, ← Kernel.map_comp_right] + · apply congrArg (Kernel.map kappa) + funext omega + exact LifetimePath.coordinate_ofContinuousPath omega t + · exact LifetimePath.measurable_ofContinuousPath + · exact LifetimePath.measurable_coordinate t + +end Kernel +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Nonexplosion.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Nonexplosion.lean new file mode 100644 index 0000000000..7359a855ac --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Nonexplosion.lean @@ -0,0 +1,94 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law + +/-! +# Detecting nonexplosion from countably many coordinates + +For a lifetime path, infinite lifetime is equivalent to being alive at every natural-number +time. Consequently, nonexplosion of a lifetime-path kernel can be proved from countably many +almost-sure coordinate statements. This is the measure-theoretic reduction later used to turn +conservativity of transition laws into nonexplosion. +-/ + +open MeasureTheory +open scoped ENNReal NNReal + +namespace MarkovProcess + +noncomputable section + +namespace LifetimePath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- A lifetime path has infinite lifetime exactly when it is alive at every natural-number +time. -/ +theorem lifetime_eq_top_iff_coordinate_nat_ne_delta (omega : LifetimePath alpha) : + omega.lifetime = ∞ ↔ + ∀ n : ℕ, coordinate (n : NNReal) omega ≠ Cemetery.delta := by + constructor + · intro hlifetime n + rw [coordinate_ne_delta_iff, hlifetime] + exact ENNReal.coe_lt_top + · intro hcoordinate + by_contra hlifetime + obtain ⟨n, hn⟩ := ENNReal.exists_nat_gt hlifetime + exact hcoordinate n (coordinate_of_le omega (n : NNReal) hn.le) + +end LifetimePath + +namespace Kernel + +variable {beta alpha : Type*} [MeasurableSpace beta] [TopologicalSpace alpha] + [MeasurableSpace alpha] + +/-- Nonexplosion is equivalent to almost-sure liveness at every natural-number time, separately +for every starting point. -/ +theorem isNonexplosive_iff_coordinate_nat_ne_delta + (kappa : ProbabilityTheory.Kernel beta (LifetimePath alpha)) : + IsNonexplosive kappa ↔ + ∀ n : ℕ, ∀ x, ∀ᵐ omega ∂kappa x, + LifetimePath.coordinate (n : NNReal) omega ≠ Cemetery.delta := by + constructor + · intro hnonexplosive n x + exact (hnonexplosive x).mono fun omega hlifetime ↦ + (LifetimePath.lifetime_eq_top_iff_coordinate_nat_ne_delta omega).mp hlifetime n + · intro hcoordinate x + filter_upwards [ae_all_iff.2 fun n ↦ hcoordinate n x] with omega homega + exact (LifetimePath.lifetime_eq_top_iff_coordinate_nat_ne_delta omega).mpr homega + +/-- Equivalently, nonexplosion is the vanishing of the cemetery mass in every +natural-number-time coordinate marginal. -/ +theorem isNonexplosive_iff_map_coordinate_nat_delta + (kappa : ProbabilityTheory.Kernel beta (LifetimePath alpha)) : + IsNonexplosive kappa ↔ + ∀ n : ℕ, ∀ x, + kappa.map (LifetimePath.coordinate (n : NNReal)) x {Cemetery.delta} = 0 := by + have hdelta : MeasurableSet ({Cemetery.delta} : Set (Cemetery alpha)) := by + simpa only [Set.range_unique] using + (measurableSet_range_inr : + MeasurableSet (Set.range (Sum.inr : Unit → alpha ⊕ Unit))) + constructor + · intro hnonexplosive n x + rw [ProbabilityTheory.Kernel.map_apply' _ + (LifetimePath.measurable_coordinate (n : NNReal)) x hdelta] + apply measure_eq_zero_iff_ae_notMem.mpr + exact (hnonexplosive x).mono fun omega hlifetime homega ↦ + ((LifetimePath.lifetime_eq_top_iff_coordinate_nat_ne_delta omega).mp hlifetime n) + (by simpa only [Set.mem_preimage, Set.mem_singleton_iff] using homega) + · rw [isNonexplosive_iff_coordinate_nat_ne_delta] + intro hdeltaMass n x + apply measure_eq_zero_iff_ae_notMem.mp + change kappa x + (LifetimePath.coordinate (n : NNReal) ⁻¹' {Cemetery.delta}) = 0 + rw [← ProbabilityTheory.Kernel.map_apply' _ + (LifetimePath.measurable_coordinate (n : NNReal)) x hdelta] + exact hdeltaMass n x + +end Kernel +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/NonexplosiveTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/NonexplosiveTransport.lean new file mode 100644 index 0000000000..e575c00a5a --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/NonexplosiveTransport.lean @@ -0,0 +1,159 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law + +/-! +# Transporting nonexplosive lifetime laws to continuous paths + +This file constructs the measurable inverse of the infinite-lifetime embedding. A kernel on +lifetime paths whose lifetime is almost surely infinite therefore gives a canonical kernel on +ordinary continuous paths, independent of the off-support default. +-/ + +open MeasureTheory ProbabilityTheory Set +open scoped ENNReal + +namespace MarkovProcess + +noncomputable section + +namespace LifetimePath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- Infinite-lifetime paths are exactly the paths coming from ordinary continuous paths. -/ +theorem mem_range_ofContinuousPath_iff (omega : LifetimePath alpha) : + omega ∈ Set.range (ofContinuousPath (α := alpha)) ↔ omega.lifetime = ∞ := by + constructor + · rintro ⟨eta, rfl⟩ + exact lifetime_ofContinuousPath eta + · intro homega + exact ⟨toContinuousPath omega homega, + ofContinuousPath_toContinuousPath omega homega⟩ + +/-- A total inverse to `ofContinuousPath`, with a fixed value away from infinite-lifetime paths. -/ +def continuousPathExtension (default : ContinuousPath alpha) : + LifetimePath alpha → ContinuousPath alpha := + Function.extend ofContinuousPath id (fun _ ↦ default) + +@[simp] +theorem continuousPathExtension_ofContinuousPath (default eta : ContinuousPath alpha) : + continuousPathExtension default (ofContinuousPath eta) = eta := by + exact Function.Injective.extend_apply ofContinuousPath_injective _ _ _ + +theorem continuousPathExtension_of_lifetime_eq_top (default : ContinuousPath alpha) + (omega : LifetimePath alpha) (homega : omega.lifetime = ∞) : + continuousPathExtension default omega = toContinuousPath omega homega := by + calc + continuousPathExtension default omega = + continuousPathExtension default + (ofContinuousPath (toContinuousPath omega homega)) := + congrArg (continuousPathExtension default) + (ofContinuousPath_toContinuousPath omega homega).symm + _ = toContinuousPath omega homega := + continuousPathExtension_ofContinuousPath default _ + +section Measurable + +variable [MeasurableSpace alpha] [BorelSpace alpha] + +variable [StandardBorelSpace (ContinuousPath alpha)] + [MeasurableSpace.CountablySeparated (LifetimePath alpha)] + +/-- The total inverse is measurable for the coordinate-generated lifetime-path structure. -/ +theorem measurable_continuousPathExtension (default : ContinuousPath alpha) : + Measurable (continuousPathExtension default) := + measurableEmbedding_ofContinuousPath.measurable_extend measurable_id measurable_const + +end Measurable +end LifetimePath + +namespace Kernel + +variable {beta alpha : Type*} [MeasurableSpace beta] [TopologicalSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] + +variable [StandardBorelSpace (ContinuousPath alpha)] + [MeasurableSpace.CountablySeparated (LifetimePath alpha)] + +/-- Transport a lifetime-path kernel to ordinary continuous paths. Under nonexplosion, the +result is independent of `default`. -/ +def fromLifetimePathKernel (kappa : Kernel beta (LifetimePath alpha)) + (default : ContinuousPath alpha) : Kernel beta (ContinuousPath alpha) := + Kernel.mapOfMeasurable kappa (LifetimePath.continuousPathExtension default) + (LifetimePath.measurable_continuousPathExtension default) + +/-- The lifetime-path transport agrees with ordinary kernel mapping. -/ +theorem fromLifetimePathKernel_eq_map (kappa : Kernel beta (LifetimePath alpha)) + (default : ContinuousPath alpha) : + fromLifetimePathKernel kappa default = + kappa.map (LifetimePath.continuousPathExtension default) := + Kernel.mapOfMeasurable_eq_map _ + (LifetimePath.measurable_continuousPathExtension default) + +/-- A Markov lifetime-path kernel remains Markov after transport to continuous paths. -/ +theorem isMarkovKernel_fromLifetimePathKernel + (kappa : Kernel beta (LifetimePath alpha)) [IsMarkovKernel kappa] + (default : ContinuousPath alpha) : + IsMarkovKernel (fromLifetimePathKernel kappa default) := by + rw [fromLifetimePathKernel_eq_map] + exact Kernel.IsMarkovKernel.map _ + (LifetimePath.measurable_continuousPathExtension default) + +/-- Under nonexplosion, the transported continuous-path kernel does not depend on the default. -/ +theorem IsNonexplosive.fromLifetimePathKernel_eq + (kappa : Kernel beta (LifetimePath alpha)) (hkappa : IsNonexplosive kappa) + (default₁ default₂ : ContinuousPath alpha) : + fromLifetimePathKernel kappa default₁ = fromLifetimePathKernel kappa default₂ := by + rw [fromLifetimePathKernel_eq_map, fromLifetimePathKernel_eq_map] + ext x s hs + rw [Kernel.map_apply' _ (LifetimePath.measurable_continuousPathExtension default₁) x hs, + Kernel.map_apply' _ (LifetimePath.measurable_continuousPathExtension default₂) x hs] + have hfun : LifetimePath.continuousPathExtension default₁ =ᵐ[kappa x] + LifetimePath.continuousPathExtension default₂ := + (hkappa x).mono fun omega homega ↦ by + rw [LifetimePath.continuousPathExtension_of_lifetime_eq_top default₁ omega homega, + LifetimePath.continuousPathExtension_of_lifetime_eq_top default₂ omega homega] + exact measure_congr (hfun.preimage s) + +/-- Under nonexplosion, transport to continuous paths and back recovers the lifetime-path law. -/ +theorem IsNonexplosive.toLifetimePathKernel_fromLifetimePathKernel + (kappa : Kernel beta (LifetimePath alpha)) (hkappa : IsNonexplosive kappa) + (default : ContinuousPath alpha) : + toLifetimePathKernel (fromLifetimePathKernel kappa default) = kappa := by + rw [toLifetimePathKernel_eq_map, fromLifetimePathKernel_eq_map, ← Kernel.map_comp_right] + · ext x s hs + rw [Kernel.map_apply' _ + (LifetimePath.measurable_ofContinuousPath.comp + (LifetimePath.measurable_continuousPathExtension default)) x hs] + have hfun : LifetimePath.ofContinuousPath ∘ + LifetimePath.continuousPathExtension default =ᵐ[kappa x] id := + (hkappa x).mono fun omega homega ↦ by + change LifetimePath.ofContinuousPath + (LifetimePath.continuousPathExtension default omega) = omega + rw [LifetimePath.continuousPathExtension_of_lifetime_eq_top default omega homega, + LifetimePath.ofContinuousPath_toContinuousPath omega homega] + simpa only [Set.preimage_id] using measure_congr (hfun.preimage s) + · exact LifetimePath.measurable_continuousPathExtension default + · exact LifetimePath.measurable_ofContinuousPath + +/-- Transporting an ordinary continuous-path kernel to lifetime paths and back recovers it. -/ +@[simp] +theorem fromLifetimePathKernel_toLifetimePathKernel + (kappa : Kernel beta (ContinuousPath alpha)) (default : ContinuousPath alpha) : + fromLifetimePathKernel (toLifetimePathKernel kappa) default = kappa := by + rw [fromLifetimePathKernel_eq_map, toLifetimePathKernel_eq_map, ← Kernel.map_comp_right] + · have hcomp : LifetimePath.continuousPathExtension default ∘ + LifetimePath.ofContinuousPath = id := by + funext eta + exact LifetimePath.continuousPathExtension_ofContinuousPath default eta + rw [hcomp, Kernel.map_id] + · exact LifetimePath.measurable_ofContinuousPath + · exact LifetimePath.measurable_continuousPathExtension default + +end Kernel +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean new file mode 100644 index 0000000000..6fefaae786 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean @@ -0,0 +1,137 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic + +/-! +# Deterministic time shifts of lifetime paths + +This file shifts a lifetime path forward by a fixed finite time. A shift beyond the original +lifetime produces a path with zero lifetime, hence with cemetery state at every coordinate. +-/ + +open MeasureTheory +open scoped ENNReal + +namespace MarkovProcess.LifetimePath + +noncomputable section + +variable {α : Type*} [TopologicalSpace α] + +/-- Shift a lifetime path forward by the deterministic time `S`. -/ +def shift (S : NNReal) (ω : LifetimePath α) : LifetimePath α where + lifetime := ω.lifetime - (S : ENNReal) + livePath := fun t ↦ ω.livePath ⟨S + t, by + rw [ENNReal.coe_add, add_comm] + exact lt_tsub_iff_right.mp t.property⟩ + continuous_livePath := by + apply ω.continuous_livePath.comp + exact (continuous_const.add continuous_subtype_val).subtype_mk _ + +@[simp] +theorem lifetime_shift (S : NNReal) (ω : LifetimePath α) : + (shift S ω).lifetime = ω.lifetime - (S : ENNReal) := + rfl + +/-- A shifted coordinate before the shifted lifetime is the corresponding original coordinate. -/ +theorem coordinate_shift_of_lt (S t : NNReal) (ω : LifetimePath α) + (ht : (t : ENNReal) < (shift S ω).lifetime) : + coordinate t (shift S ω) = coordinate (S + t) ω := by + rw [coordinate_of_lt _ _ ht] + have hst : ((S + t : NNReal) : ENNReal) < ω.lifetime := by + rw [ENNReal.coe_add, add_comm] + exact lt_tsub_iff_right.mp ht + rw [coordinate_of_lt _ _ hst] + rfl + +/-- At and after the shifted lifetime, the shifted coordinate is the cemetery state. -/ +@[simp] +theorem coordinate_shift_of_le (S t : NNReal) (ω : LifetimePath α) + (ht : (shift S ω).lifetime ≤ (t : ENNReal)) : + coordinate t (shift S ω) = Cemetery.delta := + coordinate_of_le _ _ ht + +/-- Every shifted coordinate is the corresponding original coordinate, including at and after +the lifetime, where both sides are the cemetery state. -/ +@[simp] +theorem coordinate_shift (S t : NNReal) (ω : LifetimePath α) : + coordinate t (shift S ω) = coordinate (S + t) ω := by + by_cases ht : (t : ENNReal) < (shift S ω).lifetime + · exact coordinate_shift_of_lt S t ω ht + · rw [coordinate_shift_of_le S t ω (not_lt.mp ht)] + apply Eq.symm + apply coordinate_of_le + rw [lifetime_shift] at ht + rw [ENNReal.coe_add, add_comm] + exact not_lt.mp (lt_tsub_iff_right.not.mp ht) + +/-- Shifting at or beyond the original lifetime leaves zero remaining lifetime. -/ +theorem lifetime_shift_eq_zero_of_le (S : NNReal) (ω : LifetimePath α) + (hω : ω.lifetime ≤ (S : ENNReal)) : (shift S ω).lifetime = 0 := by + rw [lifetime_shift] + exact tsub_eq_zero_iff_le.mpr hω + +/-- A shift at or beyond the original lifetime is at the cemetery state at every time, +including time zero. -/ +theorem coordinate_shift_eq_delta_of_lifetime_le (S t : NNReal) (ω : LifetimePath α) + (hω : ω.lifetime ≤ (S : ENNReal)) : + coordinate t (shift S ω) = Cemetery.delta := by + apply coordinate_shift_of_le + rw [lifetime_shift_eq_zero_of_le S ω hω] + exact bot_le + +/-- Shifting twice is shifting once by the sum of the two deterministic times. -/ +theorem shift_shift (S T : NNReal) (ω : LifetimePath α) : + shift T (shift S ω) = shift (S + T) ω := by + have hlifetime : + (shift T (shift S ω)).lifetime = (shift (S + T) ω).lifetime := by + simp only [lifetime_shift, ENNReal.coe_add] + exact tsub_tsub ω.lifetime (S : ENNReal) (T : ENNReal) + apply ext_coordinate + · exact hlifetime + · intro t + by_cases ht : (t : ENNReal) < (shift T (shift S ω)).lifetime + · rw [coordinate_shift_of_lt T t (shift S ω) ht] + have hTt : ((T + t : NNReal) : ENNReal) < (shift S ω).lifetime := by + rw [lifetime_shift] at ht + rw [ENNReal.coe_add, add_comm] + exact lt_tsub_iff_right.mp ht + rw [coordinate_shift_of_lt S (T + t) ω hTt] + have hsum : (t : ENNReal) < (shift (S + T) ω).lifetime := by + rwa [← hlifetime] + rw [coordinate_shift_of_lt (S + T) t ω hsum] + rw [add_assoc] + · have htle : (shift T (shift S ω)).lifetime ≤ (t : ENNReal) := not_lt.mp ht + rw [coordinate_shift_of_le T t (shift S ω) htle] + rw [coordinate_shift_of_le] + rwa [← hlifetime] + +section Measurable + +variable [MeasurableSpace α] + +/-- Shifting by a fixed deterministic time is measurable for the coordinate-generated +measurable structure on lifetime paths. -/ +theorem measurable_shift (S : NNReal) : + Measurable (shift S : LifetimePath α → LifetimePath α) := by + apply Measurable.of_comap_le + rw [instMeasurableSpace, MeasurableSpace.comap_sup, MeasurableSpace.comap_iSup] + apply sup_le + · rw [MeasurableSpace.comap_comp] + exact (measurable_lifetime.sub measurable_const).comap_le + · rw [iSup_le_iff] + intro t + rw [MeasurableSpace.comap_comp] + have hfun : coordinate (α := α) t ∘ shift S = coordinate (S + t) := by + funext ω + exact coordinate_shift S t ω + rw [hfun] + exact (measurable_coordinate (S + t)).comap_le + +end Measurable + +end +end MarkovProcess.LifetimePath diff --git a/LeanPool/MarkovProcess/MarkovProcess/Main.lean b/LeanPool/MarkovProcess/MarkovProcess/Main.lean new file mode 100644 index 0000000000..71450474c8 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Main.lean @@ -0,0 +1,405 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification +import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +import LeanPool.MarkovProcess.MarkovProcess.Path.Polish +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals + +/-! +# The continuous-path Markov process of a Feller semigroup + +This is the entry point of the library: for a conservative sub-Markov kernel semigroup `P` on a +nonempty, locally compact Polish state space it names the continuous-path process +`continuousProcess P hP`, restates under quotable names the properties proved for that process +elsewhere in the library, and proves that it is the unique Markov kernel into continuous paths +with the finite-dimensional distributions of `P`. + +Every statement carries the Kolmogorov regularity hypothesis `P.KolmogorovRegular hP`, which is +what gives the dense-time trajectory of `P` a continuous modification. The shift and restart +statements carry in addition the Feller hypothesis `P.IsFellerKernelSemigroup`; the uniqueness +statements carry neither Feller continuity nor local compactness. + +Nothing here asserts a Hunt-process property, and no statement covers a stopping time that can be +infinite. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess + +section FinsetEvaluation + +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- Evaluate a continuous path simultaneously at every time of a finite set of nonnegative +times, indexing the result by that set. -/ +abbrev finsetEvaluation (I : Finset NNReal) : ContinuousPath alpha → (I → alpha) := + finiteEvaluation (fun t : I ↦ (t : NNReal)) + +end ContinuousPath + +end FinsetEvaluation + +namespace Kernel + +noncomputable section DenseFiniteEvaluation + +variable {alpha beta : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [MeasurableSpace beta] + +/-- The finite rational-time marginals of a continuous-path kernel are its evaluations at the +corresponding physical times, reindexed by the rational labels. -/ +theorem map_denseRestriction_map_restrict + (kappa : Kernel beta (ContinuousPath alpha)) (I : Finset DenseTime) : + (kappa.map ContinuousPath.denseRestriction).map I.restrict = + (kappa.map (ContinuousPath.finsetEvaluation + (SubMarkovKernelSemigroup.denseTimePhysicalSet I))).map + (DenseTimePath.pullbackPhysicalSet I) := by + have hEvaluate : Measurable (ContinuousPath.finsetEvaluation (alpha := alpha) + (SubMarkovKernelSemigroup.denseTimePhysicalSet I)) := by + rw [measurable_pi_iff] + intro t + exact ContinuousPath.measurable_coordinateProcess (alpha := alpha) (t : NNReal) + have hfun : I.restrict ∘ ContinuousPath.denseRestriction (alpha := alpha) = + DenseTimePath.pullbackPhysicalSet I ∘ ContinuousPath.finsetEvaluation + (SubMarkovKernelSemigroup.denseTimePhysicalSet I) := by + funext path + exact (DenseTimePath.pullbackPhysicalSet_evaluation I path).symm + rw [← Kernel.map_comp_right kappa ContinuousPath.measurable_denseRestriction + (Finset.measurable_restrict I), hfun, + Kernel.map_comp_right kappa hEvaluate (DenseTimePath.measurable_pullbackPhysicalSet I)] + +section Identification + +variable [T2Space alpha] [StandardBorelSpace (ContinuousPath alpha)] + [MeasurableSpace.CountablySeparated (DenseTime → alpha)] + +/-- A finite kernel into continuous-path space is determined by its evaluations at the finite +sets of physical times carried by rational labels. -/ +theorem eq_of_map_denseFiniteEvaluation_eq + (kappa eta : Kernel beta (ContinuousPath alpha)) [IsFiniteKernel kappa] + (h : ∀ I : Finset DenseTime, + kappa.map (ContinuousPath.finsetEvaluation + (SubMarkovKernelSemigroup.denseTimePhysicalSet I)) = + eta.map (ContinuousPath.finsetEvaluation + (SubMarkovKernelSemigroup.denseTimePhysicalSet I))) : + kappa = eta := by + rw [← map_denseRestriction_eq_iff (alpha := alpha) (beta := beta)] + apply eq_of_map_finiteRestriction_eq + intro I + rw [map_denseRestriction_map_restrict kappa I, map_denseRestriction_map_restrict eta I, h I] + +end Identification + +end DenseFiniteEvaluation + +end Kernel + +namespace SubMarkovKernelSemigroup + +noncomputable section + +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- Kolmogorov regularity of a conservative sub-Markov kernel semigroup: at every starting point +the canonical dense-time coordinate process of `P` satisfies a Kolmogorov--Chentsov moment bound +with an admissible Hölder exponent. + +This is the hypothesis under which the dense-time trajectory of `P` admits a continuous +modification, and every statement about `continuousProcess P hP` carries it. -/ +def KolmogorovRegular : Prop := + ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p + +/-- The continuous-path process of a conservative sub-Markov kernel semigroup: the canonical +continuous trajectory kernel, with the fallback path of the underlying measurable extension fixed +once and for all. Under `P.KolmogorovRegular hP` the choice of fallback is immaterial, by +`continuousProcess_eq_continuousPathTrajectory`. -/ +def IsConservative.continuousProcess : Kernel alpha (ContinuousPath alpha) := + continuousPathTrajectory P hP (ContinuousMap.const NNReal (Classical.arbitrary alpha)) + +/-- The continuous-path process of a conservative semigroup is a Markov kernel: it assigns total +mass one to path space from every starting point. -/ +instance isMarkovKernel_continuousProcess : IsMarkovKernel (continuousProcess P hP) := by + unfold IsConservative.continuousProcess + infer_instance + +/-- The continuous-path process is the canonical continuous trajectory kernel built from any +fallback path whatsoever. -/ +theorem IsConservative.continuousProcess_eq_continuousPathTrajectory + (hK : P.KolmogorovRegular hP) (default : ContinuousPath alpha) : + continuousProcess P hP = continuousPathTrajectory P hP default := + continuousPathTrajectory_eq P hP _ default hK + +/-- Evaluating the continuous-path process at a nonnegative rational time gives the transition +kernel of `P` at that time. -/ +theorem IsConservative.continuousProcess_map_eval + (hK : P.KolmogorovRegular hP) (r : DenseTime) : + (continuousProcess P hP).map (fun omega ↦ omega (DenseTime.castOrderEmbedding r)) = + P (DenseTime.castOrderEmbedding r) := + continuousPathTrajectory_map_eval P hP _ hK r + +/-- The continuous-path process starts where it is told: its time-zero coordinate has the law of +the identity kernel, that is, the Dirac measure at the starting point. -/ +theorem IsConservative.continuousProcess_map_eval_zero (hK : P.KolmogorovRegular hP) : + (continuousProcess P hP).map (fun omega ↦ omega 0) = Kernel.id := by + have hzero : DenseTime.castOrderEmbedding (0 : DenseTime) = (0 : NNReal) := by + rw [DenseTime.castOrderEmbedding, NNRat.castOrderEmbedding_apply, NNRat.cast_zero] + have heval := IsConservative.continuousProcess_map_eval P hP hK 0 + rw [hzero] at heval + rw [heval] + exact P.zero + +/-- Every finite rational-time marginal of the continuous-path process is the finite-set kernel of +`P` at the corresponding physical times. -/ +theorem IsConservative.continuousProcess_map_finiteEvaluation_denseTime + (hK : P.KolmogorovRegular hP) (I : Finset DenseTime) : + (continuousProcess P hP).map + (ContinuousPath.finsetEvaluation (denseTimePhysicalSet I)) = + finiteSetKernel P (denseTimePhysicalSet I) := + continuousPathTrajectory_map_finiteDenseTimeSet P hP _ hK I + +/-- Every finite restriction of the dense-time projection of the continuous-path process is the +finite-set kernel of `P`, reindexed from physical times back to rational labels. -/ +theorem IsConservative.continuousProcess_map_denseRestriction_map_restrict + (hK : P.KolmogorovRegular hP) (I : Finset DenseTime) : + ((continuousProcess P hP).map ContinuousPath.denseRestriction).map I.restrict = + (finiteSetKernel P (denseTimePhysicalSet I)).map (DenseTimePath.pullbackPhysicalSet I) := + continuousPathTrajectory_map_denseRestriction_map_restrict P hP _ hK I + +omit [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] in +include hP in +/-- A kernel into continuous paths whose empty finite-dimensional distribution is that of a +conservative `P` is automatically a Markov kernel: reading no coordinate at all already forces +total mass one. This is why requiring `IsMarkovKernel Q` alongside the finite-dimensional +distributions of `P` costs nothing. -/ +theorem IsConservative.isMarkovKernel_of_map_finiteEvaluation_empty + (Q : Kernel alpha (ContinuousPath alpha)) + (hQ : Q.map (ContinuousPath.finsetEvaluation (alpha := alpha) (∅ : Finset NNReal)) = + finiteSetKernel P ∅) : + IsMarkovKernel Q := by + let : IsMarkovKernel (finiteSetKernel P (∅ : Finset NNReal)) := + hP.isMarkovKernel_finiteSetKernel P ∅ + have hmeas : Measurable + (ContinuousPath.finsetEvaluation (alpha := alpha) (∅ : Finset NNReal)) := by + rw [measurable_pi_iff] + intro t + exact ContinuousPath.measurable_coordinateProcess (alpha := alpha) (t : NNReal) + refine ⟨fun x ↦ ⟨?_⟩⟩ + have hx := congrArg (fun k : Kernel alpha ((∅ : Finset NNReal) → alpha) ↦ k x Set.univ) hQ + rw [Kernel.map_apply' Q hmeas x MeasurableSet.univ, Set.preimage_univ] at hx + rw [hx] + exact measure_univ + +variable [LocallyCompactSpace alpha] + +/-- Every finite-dimensional distribution of the continuous-path process of a conservative Feller +semigroup is the finite-set kernel of `P` at the same times. -/ +theorem IsFellerKernelSemigroup.continuousProcess_map_finiteEvaluation + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) (I : Finset NNReal) : + (continuousProcess P hP).map (ContinuousPath.finsetEvaluation I) = finiteSetKernel P I := + hFeller.continuousPathTrajectory_map_finiteTimeSet P hP _ hK I + +/-- Simple Markov property of the continuous-path process of a conservative Feller semigroup: +shifting by a deterministic nonnegative time gives the process started from the state at that +time, averaged over the transition kernel. -/ +theorem IsFellerKernelSemigroup.continuousProcess_map_shift + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) (s : NNReal) : + (continuousProcess P hP).map (ContinuousPath.shift s) = (continuousProcess P hP).comp (P s) := + hFeller.continuousPathTrajectory_map_shift P hP _ hK s + +/-- Restart at a deterministic time: after restriction to an event of the canonical filtration at +time `s`, the law of the shifted path is the process started from the time-`s` state. -/ +theorem IsFellerKernelSemigroup.continuousProcess_restrict_map_shift + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (x : alpha) (s : NNReal) (A : Set (ContinuousPath alpha)) + (hA : MeasurableSet[ContinuousPath.canonicalFiltration (alpha := alpha) s] A) : + (((continuousProcess P hP) x).restrict A).map (ContinuousPath.shift s) = + Kernel.comap (continuousProcess P hP) + (ContinuousPath.coordinateProcess (alpha := alpha) s) + (ContinuousPath.measurable_coordinateProcess s) ∘ₘ + (((continuousProcess P hP) x).restrict A) := + hFeller.continuousPathTrajectory_restrict_map_shift P hP _ hK x s A hA + +/-- Strong Markov property at a finite stopping time, in restart form: after restriction to an +event of the stopped sigma-algebra, the law of the path shifted at the stopping time is the +process started from the state at that time. -/ +theorem IsFellerKernelSemigroup.continuousProcess_restrict_map_shift_stoppingTime + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (x : alpha) (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + (A : Set (ContinuousPath alpha)) (hA : MeasurableSet[hT.measurableSpace] A) : + (((continuousProcess P hP) x).restrict A).map + (fun omega ↦ ContinuousPath.shift (T omega) omega) = + Kernel.comap (continuousProcess P hP) (fun omega ↦ omega (T omega)) + (ContinuousPath.measurable_eval_stoppingTime_borel T hT) ∘ₘ + (((continuousProcess P hP) x).restrict A) := + hFeller.continuousPathTrajectory_restrict_map_shift_stoppingTime P hP _ hK x T hT A hA + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace Real E] [CompleteSpace E] + +/-- Simple Markov property in conditional-expectation form: given the canonical filtration at a +deterministic time, the conditional expectation of a bounded functional of the shifted path is +that functional's expectation under the process started from the current state. -/ +theorem IsFellerKernelSemigroup.continuousProcess_condExp_shift + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (x : alpha) (s : NNReal) (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : ℝ) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + ((continuousProcess P hP) x)[fun omega ↦ F (ContinuousPath.shift s omega)| + ContinuousPath.canonicalFiltration (alpha := alpha) s] =ᵐ[ + (continuousProcess P hP) x] + fun omega ↦ ∫ eta, F eta ∂(continuousProcess P hP) (omega s) := + hFeller.continuousPathTrajectory_condExp_shift P hP _ hK x s F hF C hFC + +/-- Strong Markov property in conditional-expectation form at a finite stopping time: given the +stopped sigma-algebra, the conditional expectation of a bounded functional of the path shifted at +the stopping time is that functional's expectation under the process started from the state at the +stopping time. -/ +theorem IsFellerKernelSemigroup.continuousProcess_condExp_shift_stoppingTime + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (x : alpha) (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : ℝ) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + ((continuousProcess P hP) x)[fun omega ↦ + F (ContinuousPath.shift (T omega) omega)|hT.measurableSpace] =ᵐ[ + (continuousProcess P hP) x] + fun omega ↦ ∫ eta, F eta ∂(continuousProcess P hP) (omega (T omega)) := + hFeller.continuousPathTrajectory_condExp_shift_stoppingTime P hP _ hK x T hT F hF C hFC + +/-- Strong Markov property at a finite stopping time with countable range, in +conditional-expectation form. This is the countable-range case from which the general finite +stopping time is obtained by dyadic approximation from above. -/ +theorem IsFellerKernelSemigroup.continuousProcess_condExp_shift_countableStoppingTime + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (x : alpha) (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + (hTrange : (Set.range T).Countable) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : ℝ) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + ((continuousProcess P hP) x)[fun omega ↦ + F (ContinuousPath.shift (T omega) omega)|hT.measurableSpace] =ᵐ[ + (continuousProcess P hP) x] + fun omega ↦ ∫ eta, F eta ∂(continuousProcess P hP) (omega (T omega)) := + hFeller.continuousPathTrajectory_condExp_shift_countableStoppingTime P hP _ hK x T hT hTrange + F hF C hFC + +omit [LocallyCompactSpace alpha] in +/-- Uniqueness from rational times: a finite kernel into continuous paths whose evaluations at +the finite sets of physical times carried by rational labels are the finite-set kernels of `P` is +the continuous-path process of `P`. Neither Feller continuity nor local compactness is used. -/ +theorem IsConservative.eq_continuousProcess_of_map_finiteEvaluation_denseTime + (hK : P.KolmogorovRegular hP) (Q : Kernel alpha (ContinuousPath alpha)) [IsFiniteKernel Q] + (hQ : ∀ I : Finset DenseTime, + Q.map (ContinuousPath.finsetEvaluation (denseTimePhysicalSet I)) = + finiteSetKernel P (denseTimePhysicalSet I)) : + Q = continuousProcess P hP := + Kernel.eq_of_map_denseFiniteEvaluation_eq Q _ fun I ↦ + (hQ I).trans (continuousProcess_map_finiteEvaluation_denseTime P hP hK I).symm + +omit [LocallyCompactSpace alpha] in +/-- Uniqueness: a finite kernel into continuous paths with the finite-dimensional distributions of +`P` is the continuous-path process of `P`. Only rational times are read off the hypothesis, so +neither Feller continuity nor local compactness is used. -/ +theorem IsConservative.eq_continuousProcess_of_map_finiteEvaluation + (hK : P.KolmogorovRegular hP) (Q : Kernel alpha (ContinuousPath alpha)) [IsFiniteKernel Q] + (hQ : ∀ I : Finset NNReal, + Q.map (ContinuousPath.finsetEvaluation I) = finiteSetKernel P I) : + Q = continuousProcess P hP := + IsConservative.eq_continuousProcess_of_map_finiteEvaluation_denseTime P hP hK Q fun I ↦ + hQ (denseTimePhysicalSet I) + +omit [LocallyCompactSpace alpha] in +/-- Existence and uniqueness at rational times, for a conservative Kolmogorov-regular semigroup: +there is exactly one Markov kernel into continuous paths whose evaluations at the finite sets of +physical times carried by rational labels are the finite-set kernels of `P`, namely +`continuousProcess P hP`. No Feller hypothesis is used. -/ +theorem IsConservative.existsUnique_continuousProcess_denseTime (hK : P.KolmogorovRegular hP) : + ∃! Q : Kernel alpha (ContinuousPath alpha), IsMarkovKernel Q ∧ + ∀ I : Finset DenseTime, + Q.map (ContinuousPath.finsetEvaluation (denseTimePhysicalSet I)) = + finiteSetKernel P (denseTimePhysicalSet I) := by + refine ⟨continuousProcess P hP, + ⟨inferInstance, continuousProcess_map_finiteEvaluation_denseTime P hP hK⟩, ?_⟩ + rintro Q ⟨hQ, hmarg⟩ + let : IsMarkovKernel Q := hQ + exact IsConservative.eq_continuousProcess_of_map_finiteEvaluation_denseTime P hP hK Q hmarg + +/-- **Existence and uniqueness of the continuous-path Markov process.** Let `P` be a sub-Markov +kernel semigroup on a nonempty, locally compact Polish state space that is conservative (`hP`), +Feller (`hFeller`), and Kolmogorov regular (`hK`). Then there is exactly one Markov kernel `Q` +from the state space to continuous paths whose finite-dimensional distributions are those of `P`, +and it is `continuousProcess P hP`. + +Here "finite-dimensional distributions" means, for each finite set `I` of nonnegative times, the +kernel `finiteSetKernel P I` obtained by composing the transition kernels of `P` along `I` in +increasing order; `ContinuousPath.finsetEvaluation I` reads the coordinates of a path at `I`. + +The hypothesis `IsMarkovKernel Q` is not an extra requirement in disguise: it already follows from +the marginal condition at `I = ∅`, by `isMarkovKernel_of_map_finiteEvaluation_empty`. -/ +theorem IsFellerKernelSemigroup.existsUnique_continuousProcess + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) : + ∃! Q : Kernel alpha (ContinuousPath alpha), IsMarkovKernel Q ∧ + ∀ I : Finset NNReal, + Q.map (ContinuousPath.finsetEvaluation I) = finiteSetKernel P I := by + refine ⟨continuousProcess P hP, + ⟨inferInstance, hFeller.continuousProcess_map_finiteEvaluation P hP hK⟩, ?_⟩ + rintro Q ⟨hQ, hmarg⟩ + let : IsMarkovKernel Q := hQ + exact IsConservative.eq_continuousProcess_of_map_finiteEvaluation P hP hK Q hmarg + + +omit [LocallyCompactSpace alpha] in +/-- Kolmogorov regularity follows from the intrinsic moment criterion on the semigroup. -/ +theorem KolmogorovRegular.of_hasKolmogorovMoments {p q : ℝ} {M : ℝ≥0} + (hmom : P.HasKolmogorovMoments p q M) : P.KolmogorovRegular hP := + IsConservative.kolmogorovRegular_of_hasKolmogorovMoments P hP hmom + +include hP in +/-- **Existence and uniqueness of the continuous Markov process, intrinsic form.** For a +conservative Feller sub-Markov kernel semigroup on a locally compact Polish state space +satisfying the Kolmogorov moment criterion `HasKolmogorovMoments`, there is exactly one Markov +kernel into continuous paths whose finite-dimensional distributions are the increasing-order +iterated transition laws `finiteSetKernel P I`. This is the form whose hypotheses mention only +the semigroup; `existsUnique_continuousProcess` is the same statement under the +construction-level regularity hypothesis `KolmogorovRegular`. -/ +theorem IsFellerKernelSemigroup.existsUnique_continuousProcess_of_hasKolmogorovMoments + (hFeller : P.IsFellerKernelSemigroup) {p q : ℝ} {M : ℝ≥0} + (hmom : P.HasKolmogorovMoments p q M) : + ∃! Q : Kernel alpha (ContinuousPath alpha), IsMarkovKernel Q ∧ + ∀ I : Finset NNReal, + Q.map (ContinuousPath.finsetEvaluation I) = finiteSetKernel P I := + hFeller.existsUnique_continuousProcess P hP (KolmogorovRegular.of_hasKolmogorovMoments P hP hmom) + +end + + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized.lean new file mode 100644 index 0000000000..17460bad85 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized.lean @@ -0,0 +1,28 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Annealed +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeSupport +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Equivariance +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Killed +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup + +/-! +# Parameterized + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean new file mode 100644 index 0000000000..219a3ebf57 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean @@ -0,0 +1,135 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties + +/-! +# The annealed law of a parameterized continuous-path process + +For a measurably parameterized family of semigroups with quenched continuous-path process +`Q : Kernel (Theta × alpha) (ContinuousPath alpha)` and a law `mu` on the parameter space, the +**annealed process** is the kernel from the starting state to path space obtained by averaging +the parameter, + + `annealedProcess P hP mu x = ∫ Q (theta, x) mu(dtheta)` + +(`annealedProcess_apply`, as a `Measure.bind`). This file records the facts a consumer needs to +pass between quenched and annealed expectations: the annealed process is a Markov kernel when +`mu` is a probability law; annealed expectations are the `mu`-averages of quenched expectations +(`lintegral_annealedProcess`, `integral_annealedProcess`); and the annealed finite-dimensional +distributions and starting law are the averages of the quenched ones +(`annealedProcess_map_finiteEvaluation_apply`, `annealedProcess_map_eval_zero`). + +The annealed process is in general not Markov in the probabilistic sense (the averaged law does +not have the Markov property); nothing of that kind is claimed. +-/ + +open MeasureTheory ProbabilityTheory Filter +open scoped ENNReal NNReal + +namespace MarkovProcess.ParameterizedSubMarkovKernelSemigroup + +variable {Theta alpha : Type*} [MeasurableSpace Theta] [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (hP : P.IsConservative) +variable (mu : Measure Theta) [SFinite mu] + +/-- The annealed continuous-path process: the parameterized process with its parameter averaged +over the law `mu`, as a kernel from the starting state to path space. -/ +noncomputable def IsConservative.annealedProcess : Kernel alpha (ContinuousPath alpha) := + (IsConservative.continuousProcess P hP).comp (Kernel.const alpha mu ×ₖ Kernel.id) + +omit [SFinite mu] in +/-- Freezing the starting state, the quenched law is a measurable function of the parameter. -/ +theorem IsConservative.measurable_continuousProcess_prodMk (x : alpha) : + Measurable fun theta ↦ IsConservative.continuousProcess P hP (theta, x) := + (IsConservative.continuousProcess P hP).measurable.comp (measurable_id.prodMk measurable_const) + +/-- The annealed law at a starting point is the `mu`-average of the quenched laws. -/ +theorem IsConservative.annealedProcess_apply (x : alpha) : + IsConservative.annealedProcess P hP mu x = + mu.bind (fun theta ↦ IsConservative.continuousProcess P hP (theta, x)) := by + rw [IsConservative.annealedProcess, Kernel.comp_apply, Kernel.prod_apply, Kernel.const_apply, + Kernel.id_apply, Measure.prod_dirac] + have hpm : Measurable fun theta : Theta ↦ (theta, x) := measurable_prodMk_right + refine Measure.ext fun s hs ↦ ?_ + rw [Measure.bind_apply hs (Kernel.aemeasurable _), + Measure.bind_apply hs (IsConservative.measurable_continuousProcess_prodMk P hP x).aemeasurable, + lintegral_map ((IsConservative.continuousProcess P hP).measurable_coe hs) hpm] + +/-- For a probability law on the parameters, the annealed process is a Markov kernel. -/ +instance isMarkovKernel_annealedProcess [IsProbabilityMeasure mu] : + IsMarkovKernel (IsConservative.annealedProcess P hP mu) := by + unfold IsConservative.annealedProcess + infer_instance + +/-- Annealed expectations of nonnegative extended functionals are the averages of the quenched +expectations. -/ +theorem IsConservative.lintegral_annealedProcess (x : alpha) {g : ContinuousPath alpha → ℝ≥0∞} + (hg : Measurable g) : + ∫⁻ omega, g omega ∂(IsConservative.annealedProcess P hP mu x) = + ∫⁻ theta, ∫⁻ omega, g omega ∂(IsConservative.continuousProcess P hP (theta, x)) ∂mu := by + rw [IsConservative.annealedProcess_apply, + Measure.lintegral_bind (IsConservative.measurable_continuousProcess_prodMk P hP x).aemeasurable + hg.aemeasurable] + +/-- Annealed expectations of bounded strongly measurable functionals are the averages of the +quenched expectations: `∫ F d(annealed x) = ∫ (∫ F dQ(theta, x)) mu(dtheta)`. -/ +theorem IsConservative.integral_annealedProcess [IsProbabilityMeasure mu] (x : alpha) + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) (C : ℝ) + (hFC : ∀ eta, ‖F eta‖ ≤ C) : + ∫ omega, F omega ∂(IsConservative.annealedProcess P hP mu x) = + ∫ theta, ∫ omega, F omega ∂(IsConservative.continuousProcess P hP (theta, x)) ∂mu := by + have hint : Integrable F (IsConservative.annealedProcess P hP mu x) := + Integrable.of_bound hF.aestronglyMeasurable C (Eventually.of_forall hFC) + have hG : StronglyMeasurable fun p : Theta × alpha ↦ + ∫ omega, F omega ∂(IsConservative.continuousProcess P hP p) := + hF.integral_kernel (κ := IsConservative.continuousProcess P hP) + have hpm : Measurable fun theta : Theta ↦ (theta, x) := measurable_prodMk_right + rw [IsConservative.annealedProcess] at hint ⊢ + rw [Kernel.integral_comp hint, Kernel.prod_apply, Kernel.const_apply, Kernel.id_apply, + Measure.prod_dirac, integral_map hpm.aemeasurable hG.aestronglyMeasurable] + +variable [LocallyCompactSpace alpha] + +/-- The annealed finite-dimensional distributions are the `mu`-averages of the quenched ones: +on every measurable set `s` of the coordinate space, the annealed law of the coordinates at `I` +is the average over the parameter of the finite-set kernels of the semigroups. -/ +theorem IsConservative.annealedProcess_map_finiteEvaluation_apply + (hFeller : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) (x : alpha) (I : Finset NNReal) {s : Set (I → alpha)} + (hs : MeasurableSet s) : + (IsConservative.annealedProcess P hP mu x).map (ContinuousPath.finsetEvaluation I) s = + ∫⁻ theta, SubMarkovKernelSemigroup.finiteSetKernel (P.toSubMarkovKernelSemigroup theta) I x s + ∂mu := by + have hphi : Measurable (ContinuousPath.finsetEvaluation (alpha := alpha) I) := + ContinuousPath.measurable_finsetEvaluation I + rw [Measure.map_apply hphi hs, IsConservative.annealedProcess_apply, + Measure.bind_apply (hphi hs) (IsConservative.measurable_continuousProcess_prodMk P hP x).aemeasurable] + refine lintegral_congr fun theta ↦ ?_ + rw [← Measure.map_apply hphi hs, + IsConservative.continuousProcess_map_finiteEvaluation P hP hFeller hK theta x I] + +omit [LocallyCompactSpace alpha] in +/-- The annealed process starts where it is told: for a probability law on the parameters, the +time-zero coordinate has law the Dirac measure at the starting point. -/ +theorem IsConservative.annealedProcess_map_eval_zero [IsProbabilityMeasure mu] + (hK : P.KolmogorovRegular hP) (x : alpha) : + (IsConservative.annealedProcess P hP mu x).map (fun omega ↦ omega 0) = Measure.dirac x := by + have hmeas0 : Measurable (fun omega : ContinuousPath alpha ↦ omega 0) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) 0 + refine Measure.ext fun s hs ↦ ?_ + rw [Measure.map_apply hmeas0 hs, IsConservative.annealedProcess_apply, + Measure.bind_apply (hmeas0 hs) + (IsConservative.measurable_continuousProcess_prodMk P hP x).aemeasurable] + have hfib : ∀ theta, IsConservative.continuousProcess P hP (theta, x) + ((fun omega : ContinuousPath alpha ↦ omega 0) ⁻¹' s) = Measure.dirac x s := by + intro theta + rw [← Measure.map_apply hmeas0 hs, IsConservative.continuousProcess_map_eval_zero P hP hK] + rw [lintegral_congr hfib, lintegral_const, measure_univ, mul_one] + +end MarkovProcess.ParameterizedSubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeMarginals.lean new file mode 100644 index 0000000000..cc33b06b8c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeMarginals.lean @@ -0,0 +1,44 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals + +/-! +# Cemetery marginals of parameterized dense-time trajectories + +This file proves a one-time marginal identity. It makes no simultaneous path-support or +lifetime claim. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace ParameterizedSubMarkovKernelSemigroup + +noncomputable section + +variable {Theta D alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] + [StandardBorelSpace (Cemetery alpha)] + +/-- From a live starting state, every coordinate of the parameterized cemetery trajectory has +zero cemetery mass when the original parameter slices are conservative. -/ +theorem parameterizedCemeteryDenseTimeTrajectory_map_eval_singleton_delta + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (theta : Theta) (x : alpha) (d : D) : + ((P.cemeterySemigroup.parameterizedDenseTimeTrajectory + P.isConservative_cemeterySemigroup e iota).map + (fun path ↦ path d)) (theta, Cemetery.alive x) {Cemetery.delta} = 0 := by + rw [parameterizedDenseTimeTrajectory_map_eval, parameterStateKernel_apply, + cemeterySemigroup_apply, Kernel.cemeteryExtension_alive_singleton_delta] + have hmass := hP theta (iota d) x + change P theta (iota d) x Set.univ = 1 at hmass + rw [hmass] + exact tsub_self 1 + +end +end ParameterizedSubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeSupport.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeSupport.lean new file mode 100644 index 0000000000..8fbc9acab0 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeSupport.lean @@ -0,0 +1,64 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals + +/-! +# Simultaneous dense-time cemetery avoidance + +For conservative live fibers, the jointly constructed parameterized cemetery trajectory avoids +the cemetery state simultaneously at every point of its countable dense-time index. + +This is only a statement about the countable trajectory. It makes no continuous-extension, +lifetime-path, or spatial support claim. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess + +noncomputable section + +/-- A cemetery-valued path is live at every point of its index set. -/ +def IsLiveAtEveryTime {D alpha : Type*} (path : D → Cemetery alpha) : Prop := + ∀ d, path d ≠ Cemetery.delta + +namespace ParameterizedSubMarkovKernelSemigroup + +variable {Theta D alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] + [StandardBorelSpace (Cemetery alpha)] + +/-- From a live starting state, the parameterized cemetery trajectory is almost surely live at +all enumerated dense times simultaneously. -/ +theorem ae_isLiveAtEveryTime_parameterizedCemeteryDenseTimeTrajectory + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (theta : Theta) (x : alpha) : + ∀ᵐ path ∂P.cemeterySemigroup.parameterizedDenseTimeTrajectory + P.isConservative_cemeterySemigroup e iota (theta, Cemetery.alive x), + IsLiveAtEveryTime path := by + let mu := P.cemeterySemigroup.parameterizedDenseTimeTrajectory + P.isConservative_cemeterySemigroup e iota (theta, Cemetery.alive x) + have hdelta : MeasurableSet ({Cemetery.delta} : Set (Cemetery alpha)) := by + simpa only [Set.range_unique] using + (measurableSet_range_inr : + MeasurableSet (Set.range (Sum.inr : Unit → alpha ⊕ Unit))) + have hcoordinate : ∀ n : ℕ, ∀ᵐ path ∂mu, path (e n) ≠ Cemetery.delta := by + intro n + have hzero := + P.parameterizedCemeteryDenseTimeTrajectory_map_eval_singleton_delta + hP e iota theta x (e n) + rw [Kernel.map_apply _ (measurable_pi_apply (e n)), + Measure.map_apply (measurable_pi_apply (e n)) hdelta] at hzero + rw [ae_iff] + simpa only [Set.mem_preimage, Set.mem_singleton_iff, not_ne_iff] using! hzero + filter_upwards [ae_all_iff.mpr hcoordinate] with path hpath + intro d + simpa only [e.apply_symm_apply] using hpath (e.symm d) + +end ParameterizedSubMarkovKernelSemigroup + +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeterySemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeterySemigroup.lean new file mode 100644 index 0000000000..567d6cc868 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeterySemigroup.lean @@ -0,0 +1,85 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup + +/-! +# Parameterized cemetery-extension semigroups + +This file extends a jointly measurable family of sub-Markov semigroups by one absorbing +cemetery state. The construction is jointly measurable in the parameter, time, and state. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal + +noncomputable section + +namespace MarkovProcess +namespace ParameterizedSubMarkovKernelSemigroup + +variable {Theta alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] + +/-- The jointly measurable conservative cemetery extension of a parameterized sub-Markov +kernel semigroup. -/ +def cemeterySemigroup (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) : + ParameterizedSubMarkovKernelSemigroup Theta (Cemetery alpha) where + kernel theta t := Kernel.cemeteryExtension (P theta t) + measurable_kernel := by + let e : Theta × (NNReal × Cemetery alpha) ≃ᵐ + ((Theta × NNReal) × alpha) ⊕ ((Theta × NNReal) × Unit) := + (MeasurableEquiv.prodAssoc : + ((Theta × NNReal) × Cemetery alpha) ≃ᵐ Theta × (NNReal × Cemetery alpha)).symm.trans + (MeasurableEquiv.prodSumDistrib (Theta × NNReal) alpha Unit) + apply e.symm.measurable_comp_iff.1 + apply measurable_fun_sum + · have hkernel : Measurable fun q : (Theta × NNReal) × alpha ↦ + P q.1.1 q.1.2 q.2 := + P.measurable_kernel.comp + (MeasurableEquiv.prodAssoc : + ((Theta × NNReal) × alpha) ≃ᵐ Theta × (NNReal × alpha)).measurable + exact + (((Measure.measurable_map Cemetery.alive measurable_inl).comp hkernel).add + ((measurable_const.sub + ((Measure.measurable_coe MeasurableSet.univ).comp hkernel)).smul_measure + (Measure.dirac Cemetery.delta))) + · exact measurable_const + kernel_zero theta := by + rw [P.zero, Kernel.cemeteryExtension_id] + kernel_add theta s t := by + rw [P.add] + exact Kernel.cemeteryExtension_comp (P theta t) (P theta s) + (P.isSubMarkovKernel theta t) (P.isSubMarkovKernel theta s) + isSubMarkovKernel theta t := by + let : IsMarkovKernel (Kernel.cemeteryExtension (P theta t)) := + Kernel.isMarkovKernel_cemeteryExtension (P theta t) (P.isSubMarkovKernel theta t) + exact IsSubMarkovKernel.of_isMarkovKernel _ + +variable (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + +/-- Evaluation of the parameterized cemetery extension is ordinary cemetery extension of the +corresponding parameter and time slice. -/ +@[simp] +theorem cemeterySemigroup_apply (theta : Theta) (t : NNReal) : + P.cemeterySemigroup theta t = Kernel.cemeteryExtension (P theta t) := rfl + +/-- A fixed-parameter slice of the parameterized extension is exactly the ordinary cemetery +extension of that parameter slice. -/ +theorem toSubMarkovKernelSemigroup_cemeterySemigroup (theta : Theta) : + P.cemeterySemigroup.toSubMarkovKernelSemigroup theta = + (P.toSubMarkovKernelSemigroup theta).cemeterySemigroup := by + apply SubMarkovKernelSemigroup.ext + intro t + rfl + +/-- Every fixed-parameter slice of the cemetery extension is conservative. -/ +theorem isConservative_cemeterySemigroup (theta : Theta) : + (P.cemeterySemigroup.toSubMarkovKernelSemigroup theta).IsConservative := by + rw [P.toSubMarkovKernelSemigroup_cemeterySemigroup theta] + exact (P.toSubMarkovKernelSemigroup theta).isConservative_cemeterySemigroup + +end ParameterizedSubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcess.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcess.lean new file mode 100644 index 0000000000..1c95dc92d0 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcess.lean @@ -0,0 +1,273 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification +import LeanPool.MarkovProcess.MarkovProcess.Main +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory + +/-! +# The continuous-path process of a measurably parameterized semigroup + +For a jointly measurable family of sub-Markov kernel semigroups indexed by a measurable parameter +space `Theta`, this file constructs the quenched continuous-path process as a single kernel +`Kernel (Theta × alpha) (ContinuousPath alpha)`: joint measurability in the parameter and the +starting state is carried by the kernel structure, not proved parameter by parameter afterwards. + +The construction transports the jointly measurable dense-time trajectory +`parameterizedDenseTimeTrajectory` through the same measurable continuous-extension map that the +unparameterized `continuousProcess` uses, with the same fallback path. The central result is the +fibre identity: at every parameter and every starting point the parameterized process is +*literally* the unparameterized process of that parameter's semigroup, with no null set and no +regularity hypothesis. It rests on the corresponding dense-time fibre identity, which is proved +here from the finite enumeration-prefix marginals of the two trajectory kernels. + +Fibrewise conservativity, Kolmogorov regularity and Kolmogorov moment bounds are named as +predicates on the parameterized family, so that consumers state hypotheses once. + +No Markov, strong Markov, Feller, equivariance, annealed or killed statement is proved here; each +of those is a separate transport through the fibre identity. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess +namespace ParameterizedSubMarkovKernelSemigroup + +noncomputable section + +section Conservativity + +variable {Theta alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] + +/-- Fibrewise conservativity of a measurably parameterized sub-Markov kernel semigroup: every +parameter slice is a conservative sub-Markov kernel semigroup, so that no mass is lost at any +time from any state for any parameter. -/ +def IsConservative (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) : Prop := + ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative + +end Conservativity + +section Moments + +variable {Theta alpha : Type*} [MeasurableSpace Theta] [PseudoEMetricSpace alpha] + [MeasurableSpace alpha] + +/-- Fibrewise Kolmogorov moment bounds with parameter-independent constants: every parameter slice +satisfies the intrinsic displacement estimate `∫ edist z y ^ p ∂(P theta h y) ≤ M * h ^ q`, with +the same exponents `p`, `q` and the same constant `M` for every parameter. -/ +def HasKolmogorovMoments (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (p q : ℝ) (M : ℝ≥0) : Prop := + ∀ theta, (P.toSubMarkovKernelSemigroup theta).HasKolmogorovMoments p q M + +end Moments + +section DenseTimeFibre + +variable {Theta D alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] + [StandardBorelSpace alpha] [Nonempty alpha] + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +/-- Two finite measures on a countable product path space that agree on every finite +enumeration prefix agree. Every finite coordinate set is contained in a long enough prefix, +so the prefix marginals already determine all finite-coordinate marginals. -/ +private theorem measure_eq_of_map_denseTimeTrajectoryPrefix_eq (e : ℕ ≃ D) + (mu nu : Measure (D → alpha)) [IsFiniteMeasure mu] + (h : ∀ n : ℕ, + mu.map (SubMarkovKernelSemigroup.IsConservative.denseTimeTrajectoryPrefix e n) = + nu.map (SubMarkovKernelSemigroup.IsConservative.denseTimeTrajectoryPrefix e n)) : + mu = nu := by + refine MarkovProcess.Measure.eq_of_map_finiteRestriction_eq mu nu fun I ↦ ?_ + obtain ⟨n, hlt⟩ : ∃ n : ℕ, ∀ d ∈ I, e.symm d < n := + ⟨I.sup fun d ↦ e.symm d + 1, + fun d hd ↦ Nat.lt_of_succ_le (Finset.le_sup (f := fun d ↦ e.symm d + 1) hd)⟩ + have hprefix : Measurable + (SubMarkovKernelSemigroup.IsConservative.denseTimeTrajectoryPrefix (α := alpha) e n) := + SubMarkovKernelSemigroup.IsConservative.measurable_denseTimeTrajectoryPrefix e n + have hg : Measurable + (fun z : Fin n → alpha ↦ fun d : I ↦ z ⟨e.symm (d : D), hlt (d : D) d.2⟩) := by + rw [measurable_pi_iff] + intro d + exact measurable_pi_apply _ + have hfun : + (fun z : Fin n → alpha ↦ fun d : I ↦ z ⟨e.symm (d : D), hlt (d : D) d.2⟩) ∘ + SubMarkovKernelSemigroup.IsConservative.denseTimeTrajectoryPrefix (α := alpha) e n = + I.restrict := by + funext path d + change path (e (e.symm (d : D))) = path (d : D) + rw [e.apply_symm_apply] + rw [← hfun, ← Measure.map_map hg hprefix, ← Measure.map_map hg hprefix, h n] + +/-- **Dense-time fibre identity.** At every parameter and every starting state, the jointly +measurable parameterized dense-time trajectory is the dense-time trajectory of that parameter's +semigroup. Both kernels are Markov with the same finite enumeration-prefix marginals. -/ +theorem parameterizedDenseTimeTrajectory_apply + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (hP : P.IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (theta : Theta) (x : alpha) : + P.parameterizedDenseTimeTrajectory hP e iota (theta, x) = + SubMarkovKernelSemigroup.IsConservative.denseTimeTrajectory + (P.toSubMarkovKernelSemigroup theta) (hP theta) e iota x := by + let : IsMarkovKernel (P.parameterizedDenseTimeTrajectory hP e iota) := + P.isMarkovKernel_parameterizedDenseTimeTrajectory hP e iota + refine measure_eq_of_map_denseTimeTrajectoryPrefix_eq e _ _ fun n ↦ ?_ + have hprefix : Measurable + (SubMarkovKernelSemigroup.IsConservative.denseTimeTrajectoryPrefix (α := alpha) e n) := + SubMarkovKernelSemigroup.IsConservative.measurable_denseTimeTrajectoryPrefix e n + rw [← Kernel.map_apply _ hprefix, ← Kernel.map_apply _ hprefix, + P.parameterizedDenseTimeTrajectory_map_prefix hP e iota n, + SubMarkovKernelSemigroup.IsConservative.denseTimeTrajectory_map_prefix + (P.toSubMarkovKernelSemigroup theta) (hP theta) e iota n, + P.parameterizedDenseTimePrefixKernel_apply e iota n theta x] + +end DenseTimeFibre + +section ContinuousProcess + +variable {Theta alpha : Type*} [MeasurableSpace Theta] [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (hP : P.IsConservative) + +/-- Fibrewise Kolmogorov regularity: for every parameter, the dense-time coordinate process of +that parameter's semigroup satisfies a Kolmogorov--Chentsov moment bound with an admissible +Hölder exponent at every starting point. The exponents and constants may depend on the parameter +and on the starting point. -/ +def KolmogorovRegular : Prop := + ∀ theta, (P.toSubMarkovKernelSemigroup theta).KolmogorovRegular (hP theta) + +/-- Fibrewise Kolmogorov moment bounds imply fibrewise Kolmogorov regularity. -/ +theorem KolmogorovRegular.of_hasKolmogorovMoments {p q : ℝ} {M : ℝ≥0} + (hmom : P.HasKolmogorovMoments p q M) : P.KolmogorovRegular hP := + fun theta ↦ SubMarkovKernelSemigroup.IsConservative.kolmogorovRegular_of_hasKolmogorovMoments + (P.toSubMarkovKernelSemigroup theta) (hP theta) (hmom theta) + +/-- The parameterized continuous-path process: the jointly measurable dense-time trajectory of +`P`, transported to continuous paths by the canonical measurable extension, with the fallback path +of that extension fixed to the constant path at `Classical.arbitrary alpha` — exactly the fallback +used by the unparameterized `continuousProcess`. + +Joint measurability in the parameter and the starting state is carried by the kernel structure. +Under `P.KolmogorovRegular hP` the choice of fallback is immaterial, by `continuousProcess_eq`. -/ +def IsConservative.continuousProcess : Kernel (Theta × alpha) (ContinuousPath alpha) := + Kernel.toContinuousPathKernel + (P.parameterizedDenseTimeTrajectory hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding) + (ContinuousMap.const NNReal (Classical.arbitrary alpha)) + +/-- The parameterized continuous-path process is a Markov kernel: from every parameter and every +starting state it assigns total mass one to continuous-path space. -/ +instance isMarkovKernel_continuousProcess : + IsMarkovKernel (IsConservative.continuousProcess P hP) := by + let : IsMarkovKernel (P.parameterizedDenseTimeTrajectory hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding) := + P.isMarkovKernel_parameterizedDenseTimeTrajectory hP _ _ + unfold IsConservative.continuousProcess + exact Kernel.isMarkovKernel_toContinuousPathKernel _ _ + +/-- **Fibre identity.** At every parameter `theta` and every starting state `x`, the parameterized +continuous-path process is the continuous-path process of the semigroup at `theta`, started at `x`. + +The identity is exact and unconditional: it holds for every parameter and every starting point, +with no exceptional set and without any regularity hypothesis, because both sides transport the +same dense-time law through the same measurable extension. It is the theorem that lets every +property of the unparameterized process be restated on the parameterized kernel. -/ +theorem IsConservative.continuousProcess_apply (theta : Theta) (x : alpha) : + IsConservative.continuousProcess P hP (theta, x) = + SubMarkovKernelSemigroup.IsConservative.continuousProcess + (P.toSubMarkovKernelSemigroup theta) (hP theta) x := by + have hext := ContinuousPath.measurable_continuousExtension + (ContinuousMap.const NNReal (Classical.arbitrary alpha)) + unfold IsConservative.continuousProcess + SubMarkovKernelSemigroup.IsConservative.continuousProcess + SubMarkovKernelSemigroup.IsConservative.continuousPathTrajectory + rw [Kernel.toContinuousPathKernel_eq_map, Kernel.map_apply _ hext, + Kernel.toContinuousPathKernel_eq_map, Kernel.map_apply _ hext, + parameterizedDenseTimeTrajectory_apply] + +/-- The fibre identity in kernel form: freezing the parameter of the parameterized +continuous-path process gives the continuous-path process of that parameter's semigroup, as +kernels from the starting state. -/ +theorem IsConservative.continuousProcess_apply' (theta : Theta) : + (IsConservative.continuousProcess P hP).comap (fun x ↦ (theta, x)) + (measurable_const.prodMk measurable_id) = + SubMarkovKernelSemigroup.IsConservative.continuousProcess + (P.toSubMarkovKernelSemigroup theta) (hP theta) := by + refine Kernel.ext fun x ↦ ?_ + rw [Kernel.comap_apply, IsConservative.continuousProcess_apply] + +/-- Under fibrewise Kolmogorov regularity, the jointly measurable dense-time trajectory of `P` is +almost surely supported on the dense-time restrictions of continuous paths, simultaneously for +every parameter and every starting state. -/ +theorem IsConservative.isSupportedOnContinuousPaths_parameterizedDenseTimeTrajectory + (hK : P.KolmogorovRegular hP) : + Kernel.IsSupportedOnContinuousPaths + (P.parameterizedDenseTimeTrajectory hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding) := by + let : IsMarkovKernel (P.parameterizedDenseTimeTrajectory hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding) := + P.isMarkovKernel_parameterizedDenseTimeTrajectory hP _ _ + refine Kernel.IsSupportedOnContinuousPaths.of_isKolmogorovCoordinate _ ?_ + rintro ⟨theta, x⟩ + rw [parameterizedDenseTimeTrajectory_apply] + exact hK theta x + +/-- Under fibrewise Kolmogorov regularity the parameterized continuous-path process is the +transport of the dense-time trajectory through the measurable extension built from *any* fallback +path: the arbitrary choice made in the definition is immaterial. -/ +theorem IsConservative.continuousProcess_eq (hK : P.KolmogorovRegular hP) + (default : ContinuousPath alpha) : + IsConservative.continuousProcess P hP = + Kernel.toContinuousPathKernel + (P.parameterizedDenseTimeTrajectory hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding) default := + Kernel.IsSupportedOnContinuousPaths.toContinuousPathKernel_eq _ + (IsConservative.isSupportedOnContinuousPaths_parameterizedDenseTimeTrajectory P hP hK) _ default + +section QuenchedExpectations + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + +/-- **Quenched expectations are jointly measurable.** For a strongly measurable functional `F` on +continuous paths, the quenched expectation of `F` is a strongly measurable function of the +parameter and the starting state. This is what allows a quenched expectation to be integrated +against a law on the parameter space. -/ +theorem stronglyMeasurable_integral_continuousProcess (F : ContinuousPath alpha → E) + (hF : StronglyMeasurable F) : + StronglyMeasurable fun p : Theta × alpha ↦ + ∫ eta, F eta ∂IsConservative.continuousProcess P hP p := + hF.integral_kernel (κ := IsConservative.continuousProcess P hP) + +variable [MeasurableSpace E] [BorelSpace E] + +/-- **Measurable quenched expectations.** For a strongly measurable functional `F` on continuous +paths, `(theta, x) ↦ ∫ F d(law of the process for parameter `theta` started at `x`)` is +measurable. -/ +theorem measurable_integral_continuousProcess (F : ContinuousPath alpha → E) + (hF : StronglyMeasurable F) : + Measurable fun p : Theta × alpha ↦ + ∫ eta, F eta ∂IsConservative.continuousProcess P hP p := + (stronglyMeasurable_integral_continuousProcess P hP F hF).measurable + +/-- Measurable quenched expectations of a finite-dimensional cylinder functional: for a finite set +`I` of times and a strongly measurable `f` on the coordinates at `I`, the quenched expectation of +`f` composed with the evaluation at `I` is measurable in the parameter and the starting state. -/ +theorem measurable_integral_finsetEvaluation_continuousProcess (I : Finset NNReal) + (f : (I → alpha) → E) (hf : StronglyMeasurable f) : + Measurable fun p : Theta × alpha ↦ + ∫ eta, f (ContinuousPath.finsetEvaluation I eta) + ∂IsConservative.continuousProcess P hP p := by + have hI : Measurable (ContinuousPath.finsetEvaluation (alpha := alpha) I) := by + rw [measurable_pi_iff] + intro t + exact ContinuousPath.measurable_coordinateProcess (alpha := alpha) (t : NNReal) + exact measurable_integral_continuousProcess P hP _ (hf.comp_measurable hI) + +end QuenchedExpectations + +end ContinuousProcess + +end +end ParameterizedSubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcessProperties.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcessProperties.lean new file mode 100644 index 0000000000..f75e8e2870 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcessProperties.lean @@ -0,0 +1,265 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess + +/-! +# Properties of the parameterized continuous-path process + +Every property of the continuous-path process of a single semigroup, as exposed in +`MarkovProcess/Main.lean`, restated for the measurably parameterized process +`ParameterizedSubMarkovKernelSemigroup.IsConservative.continuousProcess P hP` at a point +`(theta, x)` of the parameter-and-state space. The hypotheses are the fibrewise ones: fibrewise +conservativity `hP`, fibrewise Feller property `hFeller` where the single-semigroup statement needs +it, and fibrewise Kolmogorov regularity `hK`. + +Every proof is a transport through the exact fibre identity +`IsConservative.continuousProcess_apply`; consumers never need that identity themselves. The +restarted kernels are written as the parameterized kernel composed with the map +`omega ↦ (theta, omega (T omega))`, so that the parameter is carried along the restart. + +Main statements: `continuousProcess_map_eval`, `continuousProcess_map_eval_zero` (and its kernel +form `continuousProcess_map_eval_zero'`), `continuousProcess_map_finiteEvaluation`, +`continuousProcess_map_finiteEvaluation_denseTime`, `continuousProcess_map_shift`, +`continuousProcess_restrict_map_shift`, `continuousProcess_restrict_map_shift_stoppingTime`, +`continuousProcess_condExp_shift`, `continuousProcess_condExp_shift_stoppingTime`, +`continuousProcess_condExp_shift_countableStoppingTime`. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess + +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + +/-- Evaluation of a continuous path at a finite set of times is measurable. -/ +theorem measurable_finsetEvaluation (I : Finset NNReal) : + Measurable (finsetEvaluation (alpha := alpha) I) := by + rw [measurable_pi_iff] + intro t + exact measurable_coordinateProcess (alpha := alpha) (t : NNReal) + +end ContinuousPath + +namespace ParameterizedSubMarkovKernelSemigroup + +variable {Theta alpha : Type*} [MeasurableSpace Theta] [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (hP : P.IsConservative) + +section Fibre + +/-- Freezing the parameter of the parameterized process, as a function of the starting state, is +the process of that parameter's semigroup. -/ +theorem IsConservative.continuousProcess_comp_prodMk (theta : Theta) : + (fun x ↦ IsConservative.continuousProcess P hP (theta, x)) = + SubMarkovKernelSemigroup.IsConservative.continuousProcess + (P.toSubMarkovKernelSemigroup theta) (hP theta) := by + funext x + exact IsConservative.continuousProcess_apply P hP theta x + +omit [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] in +/-- The map `omega ↦ (theta, omega s)` carrying the parameter along the state at time `s` is +measurable. -/ +theorem measurable_prodMk_coordinateProcess (theta : Theta) (s : NNReal) : + Measurable (fun omega : ContinuousPath alpha ↦ (theta, omega s)) := + measurable_const.prodMk (ContinuousPath.measurable_coordinateProcess (alpha := alpha) s) + +omit [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] in +/-- The map `omega ↦ (theta, omega (T omega))` carrying the parameter along the state at a finite +stopping time `T` is measurable. -/ +theorem measurable_prodMk_eval_stoppingTime (theta : Theta) (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) : + Measurable (fun omega : ContinuousPath alpha ↦ (theta, omega (T omega))) := + measurable_const.prodMk (ContinuousPath.measurable_eval_stoppingTime_borel T hT) + +end Fibre + +section Marginals + +/-- One-time marginal at a rational time: the law of `omega (r)` under the parameterized process +at `(theta, x)` is the transition measure of the semigroup at `theta`. -/ +theorem IsConservative.continuousProcess_map_eval (hK : P.KolmogorovRegular hP) + (theta : Theta) (x : alpha) (r : DenseTime) : + (IsConservative.continuousProcess P hP (theta, x)).map + (fun omega ↦ omega (DenseTime.castOrderEmbedding r)) = + (P.toSubMarkovKernelSemigroup theta) (DenseTime.castOrderEmbedding r) x := by + have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ + omega (DenseTime.castOrderEmbedding r)) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) _ + rw [IsConservative.continuousProcess_apply, ← Kernel.map_apply _ hmeas, + SubMarkovKernelSemigroup.IsConservative.continuousProcess_map_eval _ _ (hK theta)] + +/-- The parameterized process starts where it is told: at `(theta, x)` the time-zero coordinate +has law the Dirac measure at `x`. -/ +theorem IsConservative.continuousProcess_map_eval_zero (hK : P.KolmogorovRegular hP) + (theta : Theta) (x : alpha) : + (IsConservative.continuousProcess P hP (theta, x)).map (fun omega ↦ omega 0) = + Measure.dirac x := by + have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ omega 0) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) 0 + rw [IsConservative.continuousProcess_apply, ← Kernel.map_apply _ hmeas, + SubMarkovKernelSemigroup.IsConservative.continuousProcess_map_eval_zero _ _ (hK theta), + Kernel.id_apply] + +/-- Kernel form of the starting law: the time-zero coordinate of the parameterized process is the +deterministic kernel projecting `(theta, x)` to `x`. -/ +theorem IsConservative.continuousProcess_map_eval_zero' (hK : P.KolmogorovRegular hP) : + (IsConservative.continuousProcess P hP).map (fun omega ↦ omega 0) = + Kernel.deterministic Prod.snd measurable_snd := by + have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ omega 0) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) 0 + refine Kernel.ext fun p ↦ ?_ + rw [Kernel.map_apply _ hmeas, Kernel.deterministic_apply] + exact IsConservative.continuousProcess_map_eval_zero P hP hK p.1 p.2 + +/-- Finite-dimensional distributions at rational times, without any Feller hypothesis. -/ +theorem IsConservative.continuousProcess_map_finiteEvaluation_denseTime + (hK : P.KolmogorovRegular hP) (theta : Theta) (x : alpha) (I : Finset DenseTime) : + (IsConservative.continuousProcess P hP (theta, x)).map + (ContinuousPath.finsetEvaluation (SubMarkovKernelSemigroup.denseTimePhysicalSet I)) = + SubMarkovKernelSemigroup.finiteSetKernel (P.toSubMarkovKernelSemigroup theta) + (SubMarkovKernelSemigroup.denseTimePhysicalSet I) x := by + rw [IsConservative.continuousProcess_apply, + ← Kernel.map_apply _ (ContinuousPath.measurable_finsetEvaluation _), + SubMarkovKernelSemigroup.IsConservative.continuousProcess_map_finiteEvaluation_denseTime _ _ + (hK theta)] + +variable [LocallyCompactSpace alpha] + (hFeller : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsFellerKernelSemigroup) + +include hFeller + +/-- Finite-dimensional distributions at all real times: under the parameterized process at +`(theta, x)`, the law of the coordinates at a finite set `I` of times is the finite-set kernel of +the semigroup at `theta`, started at `x`. -/ +theorem IsConservative.continuousProcess_map_finiteEvaluation (hK : P.KolmogorovRegular hP) + (theta : Theta) (x : alpha) (I : Finset NNReal) : + (IsConservative.continuousProcess P hP (theta, x)).map (ContinuousPath.finsetEvaluation I) = + SubMarkovKernelSemigroup.finiteSetKernel (P.toSubMarkovKernelSemigroup theta) I x := by + rw [IsConservative.continuousProcess_apply, + ← Kernel.map_apply _ (ContinuousPath.measurable_finsetEvaluation _), + (hFeller theta).continuousProcess_map_finiteEvaluation _ _ (hK theta)] + +/-- Simple Markov property of the parameterized process: shifting by a deterministic time `s` +gives the process at the same parameter, started from the time-`s` state, averaged over the +transition measure of the semigroup at `theta`. -/ +theorem IsConservative.continuousProcess_map_shift (hK : P.KolmogorovRegular hP) + (theta : Theta) (x : alpha) (s : NNReal) : + (IsConservative.continuousProcess P hP (theta, x)).map (ContinuousPath.shift s) = + ((P.toSubMarkovKernelSemigroup theta) s x).bind + (fun y ↦ IsConservative.continuousProcess P hP (theta, y)) := by + rw [IsConservative.continuousProcess_apply, + ← Kernel.map_apply _ (ContinuousPath.measurable_shift_fixed s), + (hFeller theta).continuousProcess_map_shift _ _ (hK theta) s, Kernel.comp_apply, + IsConservative.continuousProcess_comp_prodMk] + +/-- Restart at a deterministic time: after restriction to an event of the canonical filtration at +time `s`, the law of the shifted path is the parameterized process at the same parameter started +from the time-`s` state. -/ +theorem IsConservative.continuousProcess_restrict_map_shift (hK : P.KolmogorovRegular hP) + (theta : Theta) (x : alpha) (s : NNReal) (A : Set (ContinuousPath alpha)) + (hA : MeasurableSet[ContinuousPath.canonicalFiltration (alpha := alpha) s] A) : + ((IsConservative.continuousProcess P hP (theta, x)).restrict A).map + (ContinuousPath.shift s) = + Kernel.comap (IsConservative.continuousProcess P hP) (fun omega ↦ (theta, omega s)) + (measurable_prodMk_coordinateProcess theta s) + ∘ₘ ((IsConservative.continuousProcess P hP (theta, x)).restrict A) := by + have h := (hFeller theta).continuousProcess_restrict_map_shift _ _ (hK theta) x s A hA + rw [IsConservative.continuousProcess_apply] + refine h.trans (congrArg (Measure.bind _) ?_) + funext omega + exact (IsConservative.continuousProcess_apply P hP theta (omega s)).symm + +/-- Strong Markov property at a finite stopping time, in restart form: after restriction to an +event of the stopped sigma-algebra, the law of the path shifted at the stopping time is the +parameterized process at the same parameter started from the state at that time. -/ +theorem IsConservative.continuousProcess_restrict_map_shift_stoppingTime + (hK : P.KolmogorovRegular hP) (theta : Theta) (x : alpha) + (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + (A : Set (ContinuousPath alpha)) (hA : MeasurableSet[hT.measurableSpace] A) : + ((IsConservative.continuousProcess P hP (theta, x)).restrict A).map + (fun omega ↦ ContinuousPath.shift (T omega) omega) = + Kernel.comap (IsConservative.continuousProcess P hP) + (fun omega ↦ (theta, omega (T omega))) + (measurable_prodMk_eval_stoppingTime theta T hT) + ∘ₘ ((IsConservative.continuousProcess P hP (theta, x)).restrict A) := by + have h := (hFeller theta).continuousProcess_restrict_map_shift_stoppingTime _ _ (hK theta) x T + hT A hA + rw [IsConservative.continuousProcess_apply] + refine h.trans (congrArg (Measure.bind _) ?_) + funext omega + exact (IsConservative.continuousProcess_apply P hP theta (omega (T omega))).symm + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace Real E] [CompleteSpace E] + +/-- Simple Markov property in conditional-expectation form: given the canonical filtration at a +deterministic time `s`, the conditional expectation of a bounded functional of the shifted path is +its expectation under the parameterized process at the same parameter, started from the current +state. -/ +theorem IsConservative.continuousProcess_condExp_shift (hK : P.KolmogorovRegular hP) + (theta : Theta) (x : alpha) (s : NNReal) (F : ContinuousPath alpha → E) + (hF : StronglyMeasurable F) (C : ℝ) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + (IsConservative.continuousProcess P hP (theta, x))[fun omega ↦ + F (ContinuousPath.shift s omega)|ContinuousPath.canonicalFiltration (alpha := alpha) s] + =ᵐ[IsConservative.continuousProcess P hP (theta, x)] + fun omega ↦ ∫ eta, F eta ∂IsConservative.continuousProcess P hP (theta, omega s) := by + have h := (hFeller theta).continuousProcess_condExp_shift _ _ (hK theta) x s F hF C hFC + rw [← IsConservative.continuousProcess_apply P hP theta x, + ← IsConservative.continuousProcess_comp_prodMk P hP theta] at h + exact h + +/-- Strong Markov property in conditional-expectation form at a finite stopping time: given the +stopped sigma-algebra, the conditional expectation of a bounded functional of the path shifted at +the stopping time is its expectation under the parameterized process at the same parameter, +started from the state at the stopping time. -/ +theorem IsConservative.continuousProcess_condExp_shift_stoppingTime (hK : P.KolmogorovRegular hP) + (theta : Theta) (x : alpha) (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : ℝ) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + (IsConservative.continuousProcess P hP (theta, x))[fun omega ↦ + F (ContinuousPath.shift (T omega) omega)|hT.measurableSpace] + =ᵐ[IsConservative.continuousProcess P hP (theta, x)] + fun omega ↦ ∫ eta, F eta ∂IsConservative.continuousProcess P hP (theta, omega (T omega)) := by + have h := (hFeller theta).continuousProcess_condExp_shift_stoppingTime _ _ (hK theta) x T hT F + hF C hFC + rw [← IsConservative.continuousProcess_apply P hP theta x, + ← IsConservative.continuousProcess_comp_prodMk P hP theta] at h + exact h + +/-- Strong Markov property at a finite stopping time with countable range, in +conditional-expectation form, for the parameterized process. -/ +theorem IsConservative.continuousProcess_condExp_shift_countableStoppingTime + (hK : P.KolmogorovRegular hP) (theta : Theta) (x : alpha) + (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + (hTrange : (Set.range T).Countable) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : ℝ) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + (IsConservative.continuousProcess P hP (theta, x))[fun omega ↦ + F (ContinuousPath.shift (T omega) omega)|hT.measurableSpace] + =ᵐ[IsConservative.continuousProcess P hP (theta, x)] + fun omega ↦ ∫ eta, F eta ∂IsConservative.continuousProcess P hP (theta, omega (T omega)) := by + have h := (hFeller theta).continuousProcess_condExp_shift_countableStoppingTime _ _ (hK theta) + x T hT hTrange F hF C hFC + rw [← IsConservative.continuousProcess_apply P hP theta x, + ← IsConservative.continuousProcess_comp_prodMk P hP theta] at h + exact h + +end Marginals + +end ParameterizedSubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeConditionalKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeConditionalKernel.lean new file mode 100644 index 0000000000..f13f12939c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeConditionalKernel.lean @@ -0,0 +1,103 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel +import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory +import Mathlib.Probability.Kernel.Disintegration.StandardBorel + +/-! +# Conditional kernels for parameterized finite dense-time prefixes + +This file disintegrates the jointly parameterized law of a finite dense-time prefix and its next +observation. The resulting conditional kernel is one jointly measurable version. No comparison +with separately chosen fixed-parameter conditional versions is asserted. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace ParameterizedSubMarkovKernelSemigroup + +noncomputable section + +variable {Theta D alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] + +/-- The jointly parameterized law of an `n`-prefix and its next enumerated observation. -/ +def parameterizedNextObservationJoint + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (e : ℕ ≃ D) + (iota : D ↪ NNReal) (n : ℕ) : + Kernel (Theta × alpha) ((Fin n → alpha) × alpha) := + Kernel.mapOfMeasurable (P.parameterizedDenseTimePrefixKernel e iota (n + 1)) + (DenseTimeHistory.splitLast n) (DenseTimeHistory.splitLast n).measurable + +variable [StandardBorelSpace alpha] [Nonempty alpha] + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +/-- The first marginal of the joint law is the preceding parameterized prefix law. -/ +theorem parameterizedNextObservationJoint_fst + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (n : ℕ) : + (P.parameterizedNextObservationJoint e iota n).fst = + P.parameterizedDenseTimePrefixKernel e iota n := by + rw [parameterizedNextObservationJoint, Kernel.mapOfMeasurable_eq_map, Kernel.fst_eq, + ← Kernel.map_comp_right] + · change + (P.parameterizedDenseTimePrefixKernel e iota n.succ).map + (Prod.fst ∘ DenseTimeHistory.splitLast n) = + P.parameterizedDenseTimePrefixKernel e iota n + calc + (P.parameterizedDenseTimePrefixKernel e iota n.succ).map + (Prod.fst ∘ DenseTimeHistory.splitLast n) = + (P.parameterizedDenseTimePrefixKernel e iota n.succ).map + (FiniteOrderedTimes.restrictPath + (Fin.castLEOrderEmb (Nat.le_succ n))) := by + congr 1 + funext path i + exact DenseTimeHistory.splitLast_fst_apply n path i + _ = P.parameterizedDenseTimePrefixKernel e iota n := + (P.parameterizedDenseTimePrefixKernel_map_restrictPath + hP e iota (Nat.le_succ n)).symm + · exact (DenseTimeHistory.splitLast n).measurable + · exact measurable_fst + +/-- One jointly measurable conditional law of the next observation given the parameter, start, +and preceding prefix. -/ +def parameterizedObservationCondKernel + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (n : ℕ) : + Kernel ((Theta × alpha) × (Fin n → alpha)) alpha := by + letI : IsMarkovKernel (P.parameterizedNextObservationJoint e iota n) := by + rw [parameterizedNextObservationJoint, Kernel.mapOfMeasurable_eq_map] + let : IsMarkovKernel (P.parameterizedDenseTimePrefixKernel e iota (n + 1)) := + P.isMarkovKernel_parameterizedDenseTimePrefixKernel hP e iota (n + 1) + exact Kernel.IsMarkovKernel.map _ (DenseTimeHistory.splitLast n).measurable + exact (P.parameterizedNextObservationJoint e iota n).condKernel + +/-- The jointly parameterized conditional next-observation law is Markov. -/ +theorem isMarkovKernel_parameterizedObservationCondKernel + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (n : ℕ) : + IsMarkovKernel (P.parameterizedObservationCondKernel hP e iota n) := by + rw [parameterizedObservationCondKernel] + infer_instance + +/-- Disintegration reconstructs the jointly parameterized next-observation law. -/ +theorem compProd_parameterizedObservationCondKernel + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (n : ℕ) : + P.parameterizedDenseTimePrefixKernel e iota n ⊗ₖ + P.parameterizedObservationCondKernel hP e iota n = + P.parameterizedNextObservationJoint e iota n := by + rw [← P.parameterizedNextObservationJoint_fst hP e iota n] + rw [parameterizedObservationCondKernel] + exact Kernel.disintegrate _ _ + +end +end ParameterizedSubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimePrefixKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimePrefixKernel.lean new file mode 100644 index 0000000000..a6133c91bf --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimePrefixKernel.lean @@ -0,0 +1,102 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily + +/-! +# Parameterized kernels on finite prefixes of a countable time enumeration + +This file constructs jointly measurable kernels on the first `n` points of an arbitrary +enumeration. Coordinates remain in enumeration order; the enumeration need not be monotone in +physical time. Fiberwise conservativity is used only for Markovness and prefix consistency. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace ParameterizedSubMarkovKernelSemigroup + +noncomputable section + +variable {Theta D alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] + +/-- The jointly measurable kernel on the first `n` enumerated physical times. -/ +def parameterizedDenseTimePrefixKernel + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (e : ℕ ≃ D) + (ι : D ↪ NNReal) (n : ℕ) : Kernel (Theta × alpha) (Fin n → alpha) := + Kernel.mapOfMeasurable + (P.parameterizedFiniteSetKernel + (SubMarkovKernelSemigroup.denseTimePhysicalPrefix e ι n)) + (SubMarkovKernelSemigroup.denseTimePrefixReindex e ι n) + (SubMarkovKernelSemigroup.measurable_denseTimePrefixReindex e ι n) + +/-- The parameterized prefix kernel agrees with the ordinary kernel map. -/ +theorem parameterizedDenseTimePrefixKernel_eq_map + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (e : ℕ ≃ D) + (ι : D ↪ NNReal) (n : ℕ) : + P.parameterizedDenseTimePrefixKernel e ι n = + (P.parameterizedFiniteSetKernel + (SubMarkovKernelSemigroup.denseTimePhysicalPrefix e ι n)).map + (SubMarkovKernelSemigroup.denseTimePrefixReindex e ι n) := + Kernel.mapOfMeasurable_eq_map _ + (SubMarkovKernelSemigroup.measurable_denseTimePrefixReindex e ι n) + +/-- At a fixed parameter and start, the prefix kernel is the ordinary prefix kernel. -/ +theorem parameterizedDenseTimePrefixKernel_apply + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (e : ℕ ≃ D) + (ι : D ↪ NNReal) (n : ℕ) (theta : Theta) (x : alpha) : + P.parameterizedDenseTimePrefixKernel e ι n (theta, x) = + (P.toSubMarkovKernelSemigroup theta).denseTimePrefixKernel e ι n x := by + rw [parameterizedDenseTimePrefixKernel_eq_map, + Kernel.map_apply _ + (SubMarkovKernelSemigroup.measurable_denseTimePrefixReindex e ι n), + parameterizedFiniteSetKernel_apply, + SubMarkovKernelSemigroup.denseTimePrefixKernel_eq_map, + Kernel.map_apply _ + (SubMarkovKernelSemigroup.measurable_denseTimePrefixReindex e ι n)] + +/-- Fiberwise conservativity makes each parameterized prefix kernel Markov. -/ +theorem isMarkovKernel_parameterizedDenseTimePrefixKernel + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : + IsMarkovKernel (P.parameterizedDenseTimePrefixKernel e ι n) := by + rw [parameterizedDenseTimePrefixKernel_eq_map] + let : IsMarkovKernel + (P.parameterizedFiniteSetKernel + (SubMarkovKernelSemigroup.denseTimePhysicalPrefix e ι n)) := + P.isMarkovKernel_parameterizedFiniteSetKernel hP _ + exact Kernel.IsMarkovKernel.map _ + (SubMarkovKernelSemigroup.measurable_denseTimePrefixReindex e ι n) + +/-- Parameterized prefix kernels restrict exactly to every earlier enumeration prefix. -/ +theorem parameterizedDenseTimePrefixKernel_map_restrictPath + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (ι : D ↪ NNReal) {m n : ℕ} (h : m ≤ n) : + P.parameterizedDenseTimePrefixKernel e ι m = + (P.parameterizedDenseTimePrefixKernel e ι n).map + (FiniteOrderedTimes.restrictPath (Fin.castLEOrderEmb h)) := by + apply Kernel.ext + intro q + obtain ⟨theta, x⟩ := q + rw [Kernel.map_apply _ + (FiniteOrderedTimes.measurable_restrictPath (Fin.castLEOrderEmb h)), + parameterizedDenseTimePrefixKernel_apply, + parameterizedDenseTimePrefixKernel_apply] + have hrestrict := congrArg (fun K : Kernel alpha (Fin m → alpha) ↦ K x) + ((hP theta).denseTimePrefixKernel_map_restrictPath + (P.toSubMarkovKernelSemigroup theta) e ι h) + change (P.toSubMarkovKernelSemigroup theta).denseTimePrefixKernel e ι m x = + ((P.toSubMarkovKernelSemigroup theta).denseTimePrefixKernel e ι n).map + (FiniteOrderedTimes.restrictPath (Fin.castLEOrderEmb h)) x at hrestrict + rw [Kernel.map_apply _ + (FiniteOrderedTimes.measurable_restrictPath (Fin.castLEOrderEmb h))] at hrestrict + exact hrestrict + +end +end ParameterizedSubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean new file mode 100644 index 0000000000..9e5d361570 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean @@ -0,0 +1,548 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory +import Mathlib.Probability.Kernel.IonescuTulcea.Traj + +/-! # Parameterized trajectories on countable dense time -/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace ParameterizedSubMarkovKernelSemigroup + +noncomputable section + +universe uTheta uAlpha + +variable {Theta : Type uTheta} {D : Type*} {alpha : Type uAlpha} + [MeasurableSpace Theta] [MeasurableSpace alpha] [StandardBorelSpace alpha] [Nonempty alpha] + +private def trajectoryCoordinate : ℕ → Type (max uTheta uAlpha) + | 0 => ULift.{max uTheta uAlpha} (Theta × alpha) + | _ + 1 => ULift.{max uTheta uAlpha} alpha + +private instance instMeasurableSpaceTrajectoryCoordinate (n : ℕ) : MeasurableSpace + (trajectoryCoordinate (Theta := Theta) (alpha := alpha) n) := + match n with + | 0 => (inferInstance : MeasurableSpace (ULift.{max uTheta uAlpha} (Theta × alpha))) + | _ + 1 => (inferInstance : MeasurableSpace (ULift.{max uTheta uAlpha} alpha)) + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +/-- Bridging lemma: `ULift.down` out of the `(n + 1)`-st trajectory coordinate is measurable +w.r.t. the project's registered `MeasurableSpace (trajectoryCoordinate (n + 1))` instance, not +just the generic `ULift.instMeasurableSpace` instance that `measurable_down` is stated for. -/ +private theorem measurable_down_trajectoryCoordinate (n : ℕ) : + Measurable (ULift.down : trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1) → alpha) := by + simpa only [trajectoryCoordinate] using! measurable_down + +private def historyInitial (n : ℕ) + (path : (i : ↑(Finset.Iic n)) → + trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) : + ULift.{max uTheta uAlpha} (Theta × alpha) := + path ⟨0, Finset.mem_Iic.mpr (Nat.zero_le n)⟩ + +private def historyObservation (n : ℕ) + (path : (i : ↑(Finset.Iic n)) → + trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) (i : Fin n) : + ULift.{max uTheta uAlpha} alpha := + path ⟨i + 1, Finset.mem_Iic.mpr i.isLt⟩ + +/-- An augmented history is exactly the immutable data and its observed prefix. -/ +private def historyEquiv (n : ℕ) : + ((i : ↑(Finset.Iic n)) → trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) ≃ᵐ + ((Theta × alpha) × (Fin n → alpha)) where + toFun path := + ((historyInitial n path).down, fun i ↦ (historyObservation n path i).down) + invFun z i := by + rcases i with ⟨_ | k, hi⟩ + · exact ULift.up z.1 + · exact ULift.up (z.2 ⟨k, by + rw [Finset.mem_Iic] at hi + exact Nat.succ_le_iff.mp hi⟩) + left_inv path := by + funext i + rcases i with ⟨_ | k, hi⟩ + · rfl + · rfl + right_inv z := by + apply Prod.ext + · rfl + · funext i + rfl + measurable_toFun := by + apply Measurable.prodMk + · have h := measurable_pi_apply + (X := fun i : ↑(Finset.Iic n) ↦ + trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) + ⟨0, Finset.mem_Iic.mpr (Nat.zero_le n)⟩ + simpa only [trajectoryCoordinate] using! measurable_down.comp h + · rw [measurable_pi_iff] + intro i + have h := measurable_pi_apply + (X := fun i : ↑(Finset.Iic n) ↦ + trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) + ⟨i + 1, Finset.mem_Iic.mpr i.isLt⟩ + simpa only [trajectoryCoordinate] using! measurable_down.comp h + measurable_invFun := by + rw [measurable_pi_iff] + rintro ⟨_ | k, hi⟩ + · simpa only [trajectoryCoordinate] using! measurable_up.comp measurable_fst + · simpa only [trajectoryCoordinate] using! measurable_up.comp + ((measurable_pi_apply + (X := fun _ : Fin n ↦ alpha) + ⟨k, Nat.succ_le_iff.mp (Finset.mem_Iic.mp hi)⟩).comp + measurable_snd) + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +private theorem historyEquiv_fst (n : ℕ) (path) : + (historyEquiv (Theta := Theta) (alpha := alpha) n path).1 = + (historyInitial n path).down := rfl + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +private theorem historyEquiv_snd_apply (n : ℕ) (path) (i : Fin n) : + (historyEquiv (Theta := Theta) (alpha := alpha) n path).2 i = + (historyObservation n path i).down := rfl + +attribute [irreducible] historyEquiv + +private def parameterizedTrajStep + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (n : ℕ) : + Kernel ((i : ↑(Finset.Iic n)) → trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) + (trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) := + ((P.parameterizedObservationCondKernel hP e iota n).map + (γ := trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) ULift.up).comap + (historyEquiv n) (historyEquiv n).measurable + +private instance isMarkovKernel_parameterizedTrajStep + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (n : ℕ) : + IsMarkovKernel (parameterizedTrajStep P hP e iota n) := by + rw [parameterizedTrajStep] + let _ := P.isMarkovKernel_parameterizedObservationCondKernel hP e iota n + let _ : IsMarkovKernel ((P.parameterizedObservationCondKernel hP e iota n).map + (γ := trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) ULift.up) := + Kernel.IsMarkovKernel.map _ + (by simpa only [trajectoryCoordinate] using! measurable_up) + exact Kernel.IsMarkovKernel.comap _ (historyEquiv n).measurable + +private def initialHistory (q : Theta × alpha) : + (i : ↑(Finset.Iic 0)) → trajectoryCoordinate (Theta := Theta) (alpha := alpha) i := + fun i ↦ by + rcases i with ⟨_ | k, hi⟩ + · exact ULift.up q + · simp only [Finset.mem_Iic] at hi + omega + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +private theorem measurable_initialHistory : + Measurable (initialHistory (Theta := Theta) (alpha := alpha)) := by + rw [measurable_pi_iff] + rintro ⟨_ | k, hi⟩ + · simpa only [trajectoryCoordinate] using! + (measurable_up : Measurable (ULift.up : Theta × alpha → + ULift.{max uTheta uAlpha} (Theta × alpha))) + · simp only [Finset.mem_Iic] at hi + omega + +private def eraseAugmentation (e : ℕ ≃ D) + (path : (n : ℕ) → trajectoryCoordinate (Theta := Theta) (alpha := alpha) n) : D → alpha := + fun d ↦ (path (e.symm d + 1)).down + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +private theorem measurable_eraseAugmentation (e : ℕ ≃ D) : + Measurable (eraseAugmentation (Theta := Theta) (alpha := alpha) e) := by + rw [measurable_pi_iff] + intro d + simpa only [trajectoryCoordinate] using! measurable_down.comp + (measurable_pi_apply + (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) (e.symm d + 1)) + +private def rawTrajAppend (n : ℕ) : + (((i : ↑(Finset.Iic n)) → trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) × + trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) → + ((i : ↑(Finset.Iic (n + 1))) → + trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) := + IicProdIoc (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) n (n + 1) ∘ + Prod.map id (MeasurableEquiv.piSingleton + (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) n) + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +private theorem rawTrajAppend_apply_cast (n : ℕ) (z) (i : ↑(Finset.Iic n)) : + rawTrajAppend (Theta := Theta) (alpha := alpha) n z + ⟨i, Finset.mem_Iic.mpr ((Finset.mem_Iic.mp i.2).trans n.le_succ)⟩ = z.1 i := by + simp only [rawTrajAppend, Function.comp_apply, IicProdIoc_def] + rw [dif_pos (Finset.mem_Iic.mp i.2)] + rfl + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +private theorem rawTrajAppend_apply_last (n : ℕ) (z) : + rawTrajAppend (Theta := Theta) (alpha := alpha) n z + ⟨n + 1, Finset.mem_Iic.mpr (Nat.le_refl (n + 1))⟩ = z.2 := by + simp only [rawTrajAppend, Function.comp_apply, IicProdIoc_def] + rw [dif_neg (Nat.not_succ_le_self n)] + change (MeasurableEquiv.piSingleton + (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) n).symm + (MeasurableEquiv.piSingleton n z.2) = z.2 + exact MeasurableEquiv.symm_apply_apply _ _ + +private def appendObservation (n : ℕ) : + (((Theta × alpha) × (Fin n → alpha)) × + ULift.{max uTheta uAlpha} alpha) → (Theta × alpha) × (Fin (n + 1) → alpha) := + fun z ↦ (z.1.1, (DenseTimeHistory.splitLast n).symm (z.1.2, z.2.down)) + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +private theorem measurable_appendObservation (n : ℕ) : + Measurable (appendObservation (Theta := Theta) (alpha := alpha) n) := by + apply Measurable.prodMk + · exact measurable_fst.comp measurable_fst + · exact (DenseTimeHistory.splitLast n).symm.measurable.comp + ((measurable_snd.comp measurable_fst).prodMk + (measurable_down.comp measurable_snd)) + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +private theorem historyEquiv_rawTrajAppend (n : ℕ) + (z : (((i : ↑(Finset.Iic n)) → + trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) × + trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1))) : + historyEquiv (Theta := Theta) (alpha := alpha) (n + 1) (rawTrajAppend n z) = + ((historyEquiv n z.1).1, + (DenseTimeHistory.splitLast n).symm + ((historyEquiv n z.1).2, + (show ULift.{max uTheta uAlpha} alpha from z.2).down)) := by + apply Prod.ext + · rw [historyEquiv_fst] + rw [historyEquiv_fst] + change (rawTrajAppend n z + ⟨0, Finset.mem_Iic.mpr (Nat.zero_le (n + 1))⟩).down = + (z.1 ⟨0, Finset.mem_Iic.mpr (Nat.zero_le n)⟩).down + have h := rawTrajAppend_apply_cast (Theta := Theta) (alpha := alpha) n z + (⟨0, Finset.mem_Iic.mpr (Nat.zero_le n)⟩ : ↑(Finset.Iic n)) + exact congrArg ULift.down h + · change _ = (DenseTimeHistory.splitLast n).symm (_, _) + apply (DenseTimeHistory.splitLast n).injective + rw [MeasurableEquiv.apply_symm_apply] + apply Prod.ext + · funext i + rw [DenseTimeHistory.splitLast_fst_apply] + rw [historyEquiv_snd_apply] + change _ = (historyEquiv n z.1).2 i + rw [historyEquiv_snd_apply] + change (rawTrajAppend n z + ⟨i + 1, Finset.mem_Iic.mpr (Nat.succ_le_succ i.isLt.le)⟩).down = + (z.1 ⟨i + 1, Finset.mem_Iic.mpr i.isLt⟩).down + have h := rawTrajAppend_apply_cast (Theta := Theta) (alpha := alpha) n z + (⟨i + 1, Finset.mem_Iic.mpr i.isLt⟩ : ↑(Finset.Iic n)) + exact congrArg ULift.down h + · rw [DenseTimeHistory.splitLast_snd] + rw [historyEquiv_snd_apply] + change _ = z.2.down + change (rawTrajAppend n z + ⟨n + 1, Finset.mem_Iic.mpr (Nat.le_refl (n + 1))⟩).down = z.2.down + exact congrArg ULift.down + (rawTrajAppend_apply_last (Theta := Theta) (alpha := alpha) n z) + +private theorem transport_traj_step {X H Z Y T : Type*} + [MeasurableSpace X] [MeasurableSpace H] [MeasurableSpace Z] + [MeasurableSpace Y] [MeasurableSpace T] + (kappa : Kernel X Z) [IsSFiniteKernel kappa] + (eta : Kernel Z Y) [IsSFiniteKernel eta] (E : H ≃ᵐ Z) + (g : H × Y → T) (hg : Measurable g) (q : Z × Y → T) + (hcompat : g ∘ Prod.map E.symm id = q) : + (((Kernel.id ×ₖ eta.comap E E.measurable) ∘ₖ kappa.map E.symm).map g) = + ((Kernel.id ×ₖ eta) ∘ₖ kappa).map q := by + rw [Kernel.comp_map kappa (Kernel.id ×ₖ eta.comap E E.measurable) E.symm.measurable] + rw [Kernel.comap_prod, Kernel.id_comap, ← Kernel.id_map, + ← Kernel.comap_comp_right] + have hcomap : eta.comap ((E : H → Z) ∘ E.symm) + (E.measurable.comp E.symm.measurable) = eta := by + ext z + rw [Kernel.comap_apply] + change eta (E (E.symm z)) _ = eta z _ + rw [E.apply_symm_apply] + rw [hcomap, ← Kernel.map_id' eta, Kernel.map_prod_map, + ← Kernel.map_comp, ← Kernel.map_comp_right, Kernel.map_id'] + change (Kernel.id ×ₖ eta ∘ₖ kappa).map (g ∘ Prod.map E.symm id) = _ + rw [hcompat] + all_goals first | exact hg | fun_prop + +private theorem prod_comp_prod_map_prodAssoc {X A B : Type*} + [MeasurableSpace X] [MeasurableSpace A] [MeasurableSpace B] + (kappa : Kernel X A) [IsSFiniteKernel kappa] + (eta : Kernel (X × A) B) [IsSFiniteKernel eta] : + (((Kernel.id ×ₖ eta) ∘ₖ (Kernel.id ×ₖ kappa)).map MeasurableEquiv.prodAssoc) = + Kernel.id ×ₖ (kappa ⊗ₖ eta) := by + ext x s hs + rw [Kernel.map_apply' _ MeasurableEquiv.prodAssoc.measurable _ hs, Kernel.comp_apply] + rw [← Measure.compProd_eq_comp_prod] + have hfirst : (Kernel.id ×ₖ kappa) x = Measure.dirac x ⊗ₘ kappa := by + rw [Measure.compProd_eq_comp_prod] + exact (Measure.dirac_bind (Kernel.measurable (Kernel.id ×ₖ kappa)) x).symm + rw [hfirst] + rw [← Measure.map_apply MeasurableEquiv.prodAssoc.measurable hs] + rw [Measure.compProd_assoc'] + have hlast : (Kernel.id ×ₖ (kappa ⊗ₖ eta)) x = + Measure.dirac x ⊗ₘ (kappa ⊗ₖ eta) := by + rw [Measure.compProd_eq_comp_prod] + exact (Measure.dirac_bind (Kernel.measurable (Kernel.id ×ₖ (kappa ⊗ₖ eta))) x).symm + rw [hlast] + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +private theorem compProd_map_ulift_down {X A : Type*} + [MeasurableSpace X] [MeasurableSpace A] + (kappa : Kernel X A) [IsSFiniteKernel kappa] + (eta : Kernel (X × A) alpha) [IsSFiniteKernel eta] : + (kappa ⊗ₖ eta.map (ULift.up : alpha → ULift.{max uTheta uAlpha} alpha)).map + (Prod.map id ULift.down) = kappa ⊗ₖ eta := by + ext x s hs + rw [Kernel.map_apply _ (measurable_id.prodMap measurable_down)] + rw [Measure.map_apply (measurable_id.prodMap measurable_down) hs] + rw [Kernel.compProd_apply (hs.preimage (measurable_id.prodMap measurable_down))] + rw [Kernel.compProd_apply hs] + congr with a + rw [Kernel.map_apply _ measurable_up] + rw [Measure.map_apply measurable_up + ((hs.preimage (measurable_id.prodMap measurable_down)).preimage measurable_prodMk_left)] + apply congrArg (eta (x, a)) + ext y + simp only [Set.mem_preimage, Prod.map_apply, id_eq] + +private def initialHistoryKernel : Kernel (Theta × alpha) + ((i : ↑(Finset.Iic 0)) → trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) := + Kernel.deterministic initialHistory measurable_initialHistory + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +private theorem markovKernel_finZero (kappa : Kernel (Theta × alpha) (Fin 0 → alpha)) + [IsMarkovKernel kappa] : + kappa = Kernel.const (Theta × alpha) + (Measure.dirac (FiniteOrderedTimes.emptyPath alpha)) := by + ext q s hs + rcases s.eq_empty_or_nonempty with rfl | ⟨z, hz⟩ + · simp + · have hsu : s = Set.univ := by + apply Set.eq_univ_of_forall + intro y + simpa only [Subsingleton.elim y z] using hz + rw [hsu] + simp only [Kernel.const_apply, IsProbabilityMeasure.measure_univ] + +private theorem partialTraj_map_historyEquiv + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (n : ℕ) : + ((Kernel.partialTraj + (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) + (parameterizedTrajStep P hP e iota) 0 n ∘ₖ initialHistoryKernel).map + (historyEquiv n)) = + Kernel.id ×ₖ P.parameterizedDenseTimePrefixKernel e iota n := by + induction n with + | zero => + rw [Kernel.partialTraj_self, Kernel.id_comp, initialHistoryKernel, + Kernel.deterministic_map] + let _ : IsMarkovKernel (P.parameterizedDenseTimePrefixKernel e iota 0) := + P.isMarkovKernel_parameterizedDenseTimePrefixKernel hP e iota 0 + rw [markovKernel_finZero (P.parameterizedDenseTimePrefixKernel e iota 0)] + have hconst : Kernel.const (Theta × alpha) + (Measure.dirac (FiniteOrderedTimes.emptyPath alpha)) = + Kernel.deterministic (fun _ : Theta × alpha ↦ FiniteOrderedTimes.emptyPath alpha) + measurable_const := by + ext q s hs + simp only [Kernel.const_apply, Kernel.deterministic_apply, + Measure.dirac_apply' _ hs] + rw [hconst, Kernel.id, Kernel.deterministic_prod_deterministic] + apply Kernel.deterministic_congr + funext q + apply Prod.ext + · change (historyEquiv 0 (initialHistory q)).1 = q + rw [historyEquiv_fst] + rfl + · exact Subsingleton.elim _ _ + all_goals fun_prop + | succ n ih => + let _ : IsMarkovKernel (P.parameterizedDenseTimePrefixKernel e iota n) := + P.isMarkovKernel_parameterizedDenseTimePrefixKernel hP e iota n + let _ : IsMarkovKernel (P.parameterizedObservationCondKernel hP e iota n) := + P.isMarkovKernel_parameterizedObservationCondKernel hP e iota n + let _ : IsMarkovKernel ((P.parameterizedObservationCondKernel hP e iota n).map + (γ := trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) ULift.up) := + Kernel.IsMarkovKernel.map _ + (by simpa only [trajectoryCoordinate] using! measurable_up) + let _ : IsMarkovKernel + (((P.parameterizedObservationCondKernel hP e iota n).map + (γ := trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) ULift.up).comap + (historyEquiv n) (historyEquiv n).measurable) := + Kernel.IsMarkovKernel.comap _ (historyEquiv n).measurable + rw [Kernel.partialTraj_succ_of_le (Nat.zero_le n)] + rw [← Kernel.map_comp] + rw [Kernel.comp_assoc] + rw [← Kernel.map_comp_right] + · rw [parameterizedTrajStep] + rw [← Kernel.map_id' Kernel.id, Kernel.map_prod_map] <;> try fun_prop + rw [← Kernel.map_comp] + rw [← Kernel.map_comp_right] + · have hkraw := + (Kernel.map_apply_eq_iff_map_symm_apply_eq + (Kernel.partialTraj + (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) + (parameterizedTrajStep P hP e iota) 0 n ∘ₖ initialHistoryKernel) + (Kernel.id ×ₖ P.parameterizedDenseTimePrefixKernel e iota n)).mp ih + rw [hkraw] + have htransport := transport_traj_step + (Kernel.id ×ₖ P.parameterizedDenseTimePrefixKernel e iota n) + ((P.parameterizedObservationCondKernel hP e iota n).map + (γ := trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) ULift.up) + (historyEquiv n) + (historyEquiv (n + 1) ∘ rawTrajAppend n) + ((historyEquiv (n + 1)).measurable.comp + (measurable_IicProdIoc.comp + (measurable_id.prodMap (MeasurableEquiv.piSingleton n).measurable))) + (appendObservation n) (by + funext z + change historyEquiv (n + 1) + (rawTrajAppend n ((historyEquiv n).symm z.1, z.2)) = _ + rw [historyEquiv_rawTrajAppend] + rw [MeasurableEquiv.apply_symm_apply] + rfl) + have hfun : + ((historyEquiv (Theta := Theta) (alpha := alpha) (n + 1) ∘ + IicProdIoc + (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) + n (n + 1)) ∘ + Prod.map (fun a ↦ a) (MeasurableEquiv.piSingleton + (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) n)) = + historyEquiv (Theta := Theta) (alpha := alpha) (n + 1) ∘ + rawTrajAppend n := by + rfl + rw [hfun, htransport] + let r : (Theta × alpha) × + ((Fin n → alpha) × trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) → + (Theta × alpha) × (Fin (n + 1) → alpha) := + fun z ↦ (z.1, (DenseTimeHistory.splitLast n).symm (z.2.1, z.2.2.down)) + have hq : appendObservation n = r ∘ MeasurableEquiv.prodAssoc := by + rfl + have hr_meas : Measurable r := + measurable_fst.prodMk ((DenseTimeHistory.splitLast n).symm.measurable.comp + ((measurable_fst.comp measurable_snd).prodMk + ((measurable_down_trajectoryCoordinate n).comp + (measurable_snd.comp measurable_snd)))) + rw [hq, Kernel.map_comp_right _ MeasurableEquiv.prodAssoc.measurable hr_meas] + rw [prod_comp_prod_map_prodAssoc] + have hr : r = Prod.map id + ((DenseTimeHistory.splitLast n).symm ∘ + Prod.map (β₁ := trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) + id ULift.down) := by + rfl + rw [hr, ← Kernel.map_id' Kernel.id] + rw [← Kernel.map_prod_map (Kernel.id.map (fun a : Theta × alpha => a)) + (P.parameterizedDenseTimePrefixKernel e iota n ⊗ₖ + (P.parameterizedObservationCondKernel hP e iota n).map + (γ := trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) ULift.up) + measurable_id + ((DenseTimeHistory.splitLast n).symm.measurable.comp + (measurable_id.prodMap (measurable_down_trajectoryCoordinate n)))] + rw [Kernel.map_comp_right + (P.parameterizedDenseTimePrefixKernel e iota n ⊗ₖ + (P.parameterizedObservationCondKernel hP e iota n).map + (γ := trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) ULift.up) + (measurable_id.prodMap (measurable_down_trajectoryCoordinate n)) + (DenseTimeHistory.splitLast n).symm.measurable] + have hcpmud : + (P.parameterizedDenseTimePrefixKernel e iota n ⊗ₖ + (P.parameterizedObservationCondKernel hP e iota n).map + (γ := trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) + ULift.up).map (Prod.map id ULift.down) = + P.parameterizedDenseTimePrefixKernel e iota n ⊗ₖ + P.parameterizedObservationCondKernel hP e iota n := + compProd_map_ulift_down _ _ + rw [hcpmud] + rw [P.compProd_parameterizedObservationCondKernel hP e iota n] + rw [parameterizedNextObservationJoint, Kernel.mapOfMeasurable_eq_map] + rw [← Kernel.map_comp_right _ + (DenseTimeHistory.splitLast n).measurable + (DenseTimeHistory.splitLast n).symm.measurable] + have hsplit : (DenseTimeHistory.splitLast n).symm ∘ + DenseTimeHistory.splitLast n = + (id : (Fin (n + 1) → alpha) → (Fin (n + 1) → alpha)) := by + funext z + exact (DenseTimeHistory.splitLast n).symm_apply_apply z + rw [hsplit, Kernel.map_id, Kernel.map_id] + · exact measurable_id.prodMap (MeasurableEquiv.piSingleton + (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) n).measurable + · exact (historyEquiv (n + 1)).measurable.comp measurable_IicProdIoc + · exact measurable_IicProdIoc + · exact (historyEquiv (n + 1)).measurable + +/-- The jointly measurable dense-time trajectory kernel. -/ +def parameterizedDenseTimeTrajectory + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) : Kernel (Theta × alpha) (D → alpha) := + ((Kernel.traj (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) + (parameterizedTrajStep P hP e iota) 0).comap initialHistory + measurable_initialHistory).map (eraseAugmentation e) + +/-- The parameterized dense-time trajectory kernel is Markov. -/ +theorem isMarkovKernel_parameterizedDenseTimeTrajectory + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) : + IsMarkovKernel (P.parameterizedDenseTimeTrajectory hP e iota) := by + rw [parameterizedDenseTimeTrajectory] + exact Kernel.IsMarkovKernel.map _ (measurable_eraseAugmentation e) + +omit [StandardBorelSpace alpha] [Nonempty alpha] in +private theorem denseTimeTrajectoryPrefix_eraseAugmentation + (e : ℕ ≃ D) (n : ℕ) : + SubMarkovKernelSemigroup.IsConservative.denseTimeTrajectoryPrefix + (α := alpha) e n ∘ + eraseAugmentation (Theta := Theta) (alpha := alpha) e = + (Prod.snd : ((Theta × alpha) × (Fin n → alpha)) → (Fin n → alpha)) ∘ + historyEquiv (Theta := Theta) (alpha := alpha) n ∘ + Preorder.frestrictLe n := by + funext path i + change (path (e.symm (e i) + 1)).down = + (historyEquiv n (Preorder.frestrictLe n path)).2 i + rw [historyEquiv_snd_apply] + rw [e.symm_apply_apply] + rfl + +/-- Restricting the trajectory to the first `n` enumeration labels gives exactly the +parameterized prefix kernel. -/ +theorem parameterizedDenseTimeTrajectory_map_prefix + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (n : ℕ) : + (P.parameterizedDenseTimeTrajectory hP e iota).map + (SubMarkovKernelSemigroup.IsConservative.denseTimeTrajectoryPrefix e n) = + P.parameterizedDenseTimePrefixKernel e iota n := by + let _ : IsMarkovKernel (P.parameterizedDenseTimePrefixKernel e iota n) := + P.isMarkovKernel_parameterizedDenseTimePrefixKernel hP e iota n + rw [parameterizedDenseTimeTrajectory, ← Kernel.map_comp_right] + · rw [denseTimeTrajectoryPrefix_eraseAugmentation] + rw [Kernel.map_comp_right] + · rw [Kernel.map_comp_right _ (Preorder.measurable_frestrictLe n) + (historyEquiv n).measurable] + rw [← Kernel.comap_map_comm _ measurable_initialHistory + (Preorder.measurable_frestrictLe n)] + rw [Kernel.traj_map_frestrictLe] + rw [← Kernel.comp_deterministic_eq_comap] + change ((Kernel.partialTraj + (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) + (parameterizedTrajStep P hP e iota) 0 n ∘ₖ initialHistoryKernel).map + (historyEquiv n)).map Prod.snd = _ + rw [partialTraj_map_historyEquiv] + rw [← Kernel.snd_eq, Kernel.snd_prod] + · exact (historyEquiv n).measurable.comp (Preorder.measurable_frestrictLe n) + · exact measurable_snd + · exact measurable_eraseAugmentation e + · exact SubMarkovKernelSemigroup.IsConservative.measurable_denseTimeTrajectoryPrefix e n + +end +end ParameterizedSubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectoryMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectoryMarginals.lean new file mode 100644 index 0000000000..04b1f2ddcb --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectoryMarginals.lean @@ -0,0 +1,72 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory + +/-! +# One-time marginals of parameterized dense-time trajectories + +This file identifies every coordinate marginal of the jointly measurable parameterized +trajectory kernel. No standard-Borel assumption is imposed on the parameter space. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace ParameterizedSubMarkovKernelSemigroup + +noncomputable section + +variable {Theta D alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] + [StandardBorelSpace alpha] [Nonempty alpha] + +/-- Every coordinate marginal of the parameterized dense-time trajectory is the jointly +measurable transition kernel at its embedded physical time. -/ +theorem parameterizedDenseTimeTrajectory_map_eval + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (e : ℕ ≃ D) (iota : D ↪ NNReal) (d : D) : + (P.parameterizedDenseTimeTrajectory hP e iota).map (fun path ↦ path d) = + P.parameterStateKernel (iota d) := by + let k : ℕ := e.symm d + let i : Fin (k + 1) := ⟨k, Nat.lt_succ_self k⟩ + have hcoord : e i = d := by + change e (e.symm d) = d + exact e.apply_symm_apply d + have hfun : + (fun path : Fin (k + 1) → alpha ↦ path i) ∘ + SubMarkovKernelSemigroup.IsConservative.denseTimeTrajectoryPrefix e (k + 1) = + fun path : D → alpha ↦ path d := by + funext path + change path (e i) = path d + rw [hcoord] + rw [← hfun, Kernel.map_comp_right] + · rw [P.parameterizedDenseTimeTrajectory_map_prefix hP e iota (k + 1)] + apply Kernel.ext + rintro ⟨theta, x⟩ + rw [Kernel.map_apply _ (measurable_pi_apply i), + parameterizedDenseTimePrefixKernel_apply, parameterStateKernel_apply] + let Q := P.toSubMarkovKernelSemigroup theta + have hmarg := + SubMarkovKernelSemigroup.IsConservative.denseTimeTrajectory_map_eval + Q (hP theta) e iota d + rw [← hfun, Kernel.map_comp_right] at hmarg + · rw [SubMarkovKernelSemigroup.IsConservative.denseTimeTrajectory_map_prefix] at hmarg + have hx := congrArg (fun K : Kernel alpha alpha ↦ K x) hmarg + change ((Q.denseTimePrefixKernel e iota (k + 1)).map + (fun path ↦ path i)) x = Q (iota d) x at hx + rw [Kernel.map_apply _ (measurable_pi_apply i)] at hx + simpa only [Q, toSubMarkovKernelSemigroup_apply] using hx + · exact + SubMarkovKernelSemigroup.IsConservative.measurable_denseTimeTrajectoryPrefix e (k + 1) + · exact measurable_pi_apply i + · exact + SubMarkovKernelSemigroup.IsConservative.measurable_denseTimeTrajectoryPrefix e (k + 1) + · exact measurable_pi_apply i + +end +end ParameterizedSubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Equivariance.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Equivariance.lean new file mode 100644 index 0000000000..c18a9aa910 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Equivariance.lean @@ -0,0 +1,195 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance + +/-! +# Equivariance of the parameterized continuous-path process + +The equivariance theorem of `MarkovProcess/Trajectory/Equivariance.lean`, restated for a measurably +parameterized family of sub-Markov kernel semigroups. Here the state map `e` and the time factor +`c` are accompanied by a measurable reparameterization `g` of the parameter space, and the +intertwining hypothesis is fibrewise: +`P' theta t x = ((P (g theta) (c * t)) (e.symm x)).map e`. + +The conclusion is a single identity of kernels on `Theta × alpha`: the quenched continuous-path +process of `P'` is the quenched process of `P` pulled back along `(theta, x) ↦ (g theta, e.symm x)` +and pushed forward by `ContinuousPath.rescale e c`. The proof is fibrewise, through the exact +fibre identity `IsConservative.continuousProcess_apply`. + +Main results: `ParameterizedSubMarkovKernelSemigroup.IsRescaledConjugate` with its fibre form and +its transfers of conservativity and of the Kolmogorov moment criterion; +`IsConservative.continuousProcess_eq_map_rescale`, its pointwise form and its intrinsic form +`continuousProcess_eq_map_rescale_of_hasKolmogorovMoments`; the covariance corollary +`IsConservative.continuousProcess_covariant` for a family that is its own rescaled conjugate, of +which stationarity and re-gauging covariance of a random environment (`g` the environment shift, +`e` the spatial translation, `c = 1`) are instances. + +No scaling limit and no ergodic statement is asserted: the environment map `g`, the factor `c` +and both families are given in advance, and nothing is claimed about the law of the environment. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess +namespace ParameterizedSubMarkovKernelSemigroup + +noncomputable section + +section Measurability + +variable {Theta alpha beta : Type*} [MeasurableSpace Theta] [TopologicalSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [TopologicalSpace beta] [MeasurableSpace beta] + [BorelSpace beta] + +/-- The reparameterization of the parameter-and-state space used by the equivariance statement: +relabel the parameter by `g` and pull the starting state back along `e`. -/ +theorem measurable_reparameterize {g : Theta → Theta} (hg : Measurable g) (e : alpha ≃ₜ beta) : + Measurable (fun p : Theta × beta ↦ (g p.1, e.symm p.2)) := + (hg.comp measurable_fst).prodMk (e.symm.measurable.comp measurable_snd) + +/-- `P'` is the *rescaled conjugate* of `P` along the reparameterization `g`, the homeomorphism `e` +and the time factor `c`: the fibre of `P'` at `theta` is the rescaled conjugate of the fibre of `P` +at `g theta`. -/ +def IsRescaledConjugate (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (P' : ParameterizedSubMarkovKernelSemigroup Theta beta) + (g : Theta → Theta) (e : alpha ≃ₜ beta) (c : NNReal) : Prop := + ∀ theta t x, P' theta t x = ((P (g theta) (c * t)) (e.symm x)).map e + +namespace IsRescaledConjugate + +variable {P : ParameterizedSubMarkovKernelSemigroup Theta alpha} + {P' : ParameterizedSubMarkovKernelSemigroup Theta beta} {g : Theta → Theta} + {e : alpha ≃ₜ beta} {c : NNReal} + +omit [BorelSpace alpha] [BorelSpace beta] in +/-- The fibre form of the relation: at every parameter the corresponding slices of `P` and `P'` +are rescaled conjugates in the sense of `SubMarkovKernelSemigroup.IsRescaledConjugate`. -/ +theorem fibre (h : IsRescaledConjugate P P' g e c) (theta : Theta) : + SubMarkovKernelSemigroup.IsRescaledConjugate (P.toSubMarkovKernelSemigroup (g theta)) + (P'.toSubMarkovKernelSemigroup theta) e c := + fun t x ↦ h theta t x + +/-- Fibrewise conservativity transfers across rescaled conjugacy. -/ +theorem isConservative (h : IsRescaledConjugate P P' g e c) (hP : P.IsConservative) : + P'.IsConservative := + fun theta ↦ (h.fibre theta).isConservative (hP (g theta)) + +end IsRescaledConjugate + +end Measurability + +section Moments + +variable {Theta alpha beta : Type*} [MeasurableSpace Theta] [PseudoEMetricSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [PseudoEMetricSpace beta] [MeasurableSpace beta] + [BorelSpace beta] +variable {P : ParameterizedSubMarkovKernelSemigroup Theta alpha} + {P' : ParameterizedSubMarkovKernelSemigroup Theta beta} {g : Theta → Theta} + {e : alpha ≃ₜ beta} {c : NNReal} + +/-- **Fibrewise transfer of the Kolmogorov moment criterion.** If the state map is an isometry, +the parameter-uniform displacement bound of `P` passes to its rescaled conjugate `P'` with the +constant multiplied by `c ^ q`, uniformly in the parameter. -/ +theorem IsRescaledConjugate.hasKolmogorovMoments + (h : IsRescaledConjugate P P' g e c) (he : Isometry (e : alpha → beta)) {p q : ℝ} {M : ℝ≥0} + (hmom : P.HasKolmogorovMoments p q M) : P'.HasKolmogorovMoments p q (M * c ^ q) := + fun theta ↦ (h.fibre theta).hasKolmogorovMoments he (hmom (g theta)) + +end Moments + +section ContinuousProcess + +variable {Theta alpha beta : Type*} [MeasurableSpace Theta] [MetricSpace alpha] + [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [Nonempty alpha] [LocallyCompactSpace alpha] [MetricSpace beta] [CompleteSpace beta] + [MeasurableSpace beta] [BorelSpace beta] [SecondCountableTopology beta] [Nonempty beta] + +variable (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (P' : ParameterizedSubMarkovKernelSemigroup Theta beta) + (hP : P.IsConservative) (hP' : P'.IsConservative) + +/-- **Equivariance of the parameterized continuous-path process.** If the fibre of `P'` at every +parameter `theta` is the fibre of `P` at `g theta` conjugated by `e` and sped up by `c`, then the +quenched continuous-path process of `P'` is the quenched process of `P`, pulled back along +`(theta, x) ↦ (g theta, e.symm x)` and pushed forward by `ContinuousPath.rescale e c`. + +Joint measurability in the parameter and the starting state is carried by the kernel structure on +both sides; the Feller hypothesis is needed only for `P`. -/ +theorem IsConservative.continuousProcess_eq_map_rescale + (hFeller : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) (hK' : P'.KolmogorovRegular hP') + {g : Theta → Theta} (hg : Measurable g) {e : alpha ≃ₜ beta} {c : NNReal} (hc : 0 < c) + (h : IsRescaledConjugate P P' g e c) : + IsConservative.continuousProcess P' hP' = + (Kernel.comap (IsConservative.continuousProcess P hP) + (fun p : Theta × beta ↦ (g p.1, e.symm p.2)) + (measurable_reparameterize hg e)).map (ContinuousPath.rescale e c) := by + refine Kernel.ext fun p ↦ ?_ + obtain ⟨theta, x⟩ := p + rw [IsConservative.continuousProcess_apply, + Kernel.map_apply _ (ContinuousPath.measurable_rescale e c), Kernel.comap_apply, + IsConservative.continuousProcess_apply] + exact SubMarkovKernelSemigroup.IsConservative.continuousProcess_apply_rescale + (P.toSubMarkovKernelSemigroup (g theta)) (hP (g theta)) + (P'.toSubMarkovKernelSemigroup theta) (hP' theta) (hFeller (g theta)) (hK (g theta)) + (hK' theta) hc (h.fibre theta) x + +/-- The parameterized equivariance identity at a fixed parameter and starting state. -/ +theorem IsConservative.continuousProcess_apply_rescale + (hFeller : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) (hK' : P'.KolmogorovRegular hP') + {g : Theta → Theta} {e : alpha ≃ₜ beta} {c : NNReal} (hc : 0 < c) + (h : IsRescaledConjugate P P' g e c) (theta : Theta) (x : beta) : + IsConservative.continuousProcess P' hP' (theta, x) = + (IsConservative.continuousProcess P hP (g theta, e.symm x)).map + (ContinuousPath.rescale e c) := by + rw [IsConservative.continuousProcess_apply, IsConservative.continuousProcess_apply] + exact SubMarkovKernelSemigroup.IsConservative.continuousProcess_apply_rescale + (P.toSubMarkovKernelSemigroup (g theta)) (hP (g theta)) + (P'.toSubMarkovKernelSemigroup theta) (hP' theta) (hFeller (g theta)) (hK (g theta)) + (hK' theta) hc (h.fibre theta) x + +/-- **Intrinsic form of the parameterized equivariance theorem.** When the state map is an +isometry, a parameter-uniform Kolmogorov moment bound on `P` alone supplies the fibrewise +regularity of both families. -/ +theorem IsConservative.continuousProcess_eq_map_rescale_of_hasKolmogorovMoments + (hFeller : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsFellerKernelSemigroup) + {p q : ℝ} {M : ℝ≥0} (hmom : P.HasKolmogorovMoments p q M) + {g : Theta → Theta} (hg : Measurable g) {e : alpha ≃ₜ beta} + (he : Isometry (e : alpha → beta)) {c : NNReal} (hc : 0 < c) + (h : IsRescaledConjugate P P' g e c) : + IsConservative.continuousProcess P' hP' = + (Kernel.comap (IsConservative.continuousProcess P hP) + (fun p : Theta × beta ↦ (g p.1, e.symm p.2)) + (measurable_reparameterize hg e)).map (ContinuousPath.rescale e c) := + IsConservative.continuousProcess_eq_map_rescale P P' hP hP' hFeller + (KolmogorovRegular.of_hasKolmogorovMoments P hP hmom) + (KolmogorovRegular.of_hasKolmogorovMoments P' hP' (h.hasKolmogorovMoments he hmom)) hg hc h + +/-- **Covariance.** A parameterized family that is its own rescaled conjugate along `(g, e, c)` +has a quenched continuous-path process invariant under the corresponding transformation of the +parameter, the starting state and the path. Stationarity and re-gauging covariance of a random +environment are the case `c = 1`, with `g` the environment shift and `e` the matching spatial +translation. -/ +theorem IsConservative.continuousProcess_covariant + (hFeller : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) + {g : Theta → Theta} (hg : Measurable g) {e : alpha ≃ₜ alpha} {c : NNReal} (hc : 0 < c) + (h : IsRescaledConjugate P P g e c) : + IsConservative.continuousProcess P hP = + (Kernel.comap (IsConservative.continuousProcess P hP) + (fun p : Theta × alpha ↦ (g p.1, e.symm p.2)) + (measurable_reparameterize hg e)).map (ContinuousPath.rescale e c) := + IsConservative.continuousProcess_eq_map_rescale P P hP hP hFeller hK hK hg hc h + +end ContinuousProcess + +end + +end ParameterizedSubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeKernel.lean new file mode 100644 index 0000000000..5923264951 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeKernel.lean @@ -0,0 +1,194 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid + +/-! +# Parameterized finite-time kernels + +This file constructs the finite-dimensional kernel at a fixed strictly ordered time family for a +measurably parameterized sub-Markov semigroup. The construction recursively carries the parameter +through the augmented state kernel. Fiberwise conservativity is used only for the Markov-kernel +property. + +The slice theorem identifies evaluation at a parameter and start with the existing +nonparameterized finite-time kernel of the fixed-parameter semigroup. No path-space or +stochastic-process existence claim is made here. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ProbabilityTheory + +namespace MarkovProcess + +namespace ParameterizedSubMarkovKernelSemigroup + +variable {Theta alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] + +private theorem measurable_finCons_snd {n : ℕ} : + Measurable (fun z : (Theta × alpha) × (Fin n → alpha) ↦ + @Fin.cons n (fun _ : Fin (n + 1) ↦ alpha) z.1.2 z.2) := by + rw [measurable_pi_iff] + intro i + refine Fin.cases ?_ (fun j ↦ ?_) i + · simpa only [Fin.cons_zero] using! + (measurable_snd.comp measurable_fst : + Measurable (fun z : (Theta × alpha) × (Fin n → alpha) ↦ z.1.2)) + · simpa only [Fin.cons_succ] using! + (measurable_pi_apply j).comp + (measurable_snd : Measurable (Prod.snd : + (Theta × alpha) × (Fin n → alpha) → Fin n → alpha)) + +/-- The jointly measurable finite-time kernel for a parameterized semigroup. -/ +noncomputable def parameterizedFiniteTimeKernel + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) : + {n : ℕ} → FiniteOrderedTimes n → Kernel (Theta × alpha) (Fin n → alpha) + | 0, _ => Kernel.const (Theta × alpha) (Measure.dirac (FiniteOrderedTimes.emptyPath alpha)) + | n + 1, times => + Kernel.mapOfMeasurable + (P.augmentedKernel (times 0) ⊗ₖ + Kernel.prodMkLeft (Theta × alpha) + (parameterizedFiniteTimeKernel P times.relativeTail)) + (fun z ↦ @Fin.cons n (fun _ : Fin (n + 1) ↦ alpha) z.1.2 z.2) + measurable_finCons_snd + +@[simp] +theorem parameterizedFiniteTimeKernel_zero + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (times : FiniteOrderedTimes 0) : + P.parameterizedFiniteTimeKernel times = + Kernel.const (Theta × alpha) (Measure.dirac (FiniteOrderedTimes.emptyPath alpha)) := + rfl + +@[simp] +theorem parameterizedFiniteTimeKernel_succ + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) {n : ℕ} + (times : FiniteOrderedTimes (n + 1)) : + P.parameterizedFiniteTimeKernel times = + Kernel.mapOfMeasurable + (P.augmentedKernel (times 0) ⊗ₖ + Kernel.prodMkLeft (Theta × alpha) + (P.parameterizedFiniteTimeKernel times.relativeTail)) + (fun z ↦ @Fin.cons n (fun _ : Fin (n + 1) ↦ alpha) z.1.2 z.2) + measurable_finCons_snd := + rfl + +theorem isMarkovKernel_parameterizedFiniteTimeKernel + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + {n : ℕ} (times : FiniteOrderedTimes n) : + IsMarkovKernel (P.parameterizedFiniteTimeKernel times) := by + induction n with + | zero => + rw [parameterizedFiniteTimeKernel_zero] + infer_instance + | succ n ih => + let : IsMarkovKernel (P.augmentedKernel (times 0)) := + P.isMarkovKernel_augmentedKernel hP (times 0) + let : IsMarkovKernel (P.parameterizedFiniteTimeKernel times.relativeTail) := + ih times.relativeTail + rw [parameterizedFiniteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map] + exact Kernel.IsMarkovKernel.map _ measurable_finCons_snd + +private theorem isFiniteKernel_parameterizedFiniteTimeKernel + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + {n : ℕ} (times : FiniteOrderedTimes n) : + IsFiniteKernel (P.parameterizedFiniteTimeKernel times) := by + induction n with + | zero => + rw [parameterizedFiniteTimeKernel_zero] + infer_instance + | succ n ih => + have hParameterState : IsSubMarkovKernel (P.parameterStateKernel (times 0)) := + fun q ↦ by + rw [parameterStateKernel_apply] + exact P.isSubMarkovKernel q.1 (times 0) q.2 + let : IsFiniteKernel (P.parameterStateKernel (times 0)) := + hParameterState.isFiniteKernel + let : IsFiniteKernel (P.augmentedKernel (times 0)) := by + rw [augmentedKernel] + infer_instance + let : IsFiniteKernel (P.parameterizedFiniteTimeKernel times.relativeTail) := + ih times.relativeTail + rw [parameterizedFiniteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map] + infer_instance + +private theorem isFiniteKernel_finiteTimeKernel + (Q : SubMarkovKernelSemigroup alpha) + {n : ℕ} (times : FiniteOrderedTimes n) : + IsFiniteKernel (Q.finiteTimeKernel times) := by + induction n with + | zero => + rw [SubMarkovKernelSemigroup.finiteTimeKernel_zero] + infer_instance + | succ n ih => + let : IsFiniteKernel (Q (times 0)) := + (Q.isSubMarkovKernel (times 0)).isFiniteKernel + let : IsFiniteKernel (Q.finiteTimeKernel times.relativeTail) := + ih times.relativeTail + rw [SubMarkovKernelSemigroup.finiteTimeKernel_succ, + Kernel.mapOfMeasurable_eq_map] + infer_instance + +private theorem augmentedKernel_apply_eq_map + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (theta : Theta) (t : NNReal) (x : alpha) : + P.augmentedKernel t (theta, x) = (P theta t x).map (Prod.mk theta) := by + have hParameterState : IsSubMarkovKernel (P.parameterStateKernel t) := fun q ↦ by + rw [parameterStateKernel_apply] + exact P.isSubMarkovKernel q.1 t q.2 + let : IsFiniteKernel (P.parameterStateKernel t) := hParameterState.isFiniteKernel + let : IsFiniteKernel (P theta t) := (P.isSubMarkovKernel theta t).isFiniteKernel + rw [augmentedKernel, Kernel.prod_apply, Kernel.deterministic_apply, + parameterStateKernel_apply, Measure.dirac_prod] + +/-- A fixed-parameter slice is the ordinary finite-time kernel of that semigroup slice. -/ +theorem parameterizedFiniteTimeKernel_apply + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + {n : ℕ} (times : FiniteOrderedTimes n) (theta : Theta) (x : alpha) : + P.parameterizedFiniteTimeKernel times (theta, x) = + SubMarkovKernelSemigroup.finiteTimeKernel + (P.toSubMarkovKernelSemigroup theta) times x := by + induction n generalizing theta x with + | zero => + rw [parameterizedFiniteTimeKernel_zero, + SubMarkovKernelSemigroup.finiteTimeKernel_zero, + Kernel.const_apply, Kernel.const_apply] + | succ n ih => + let Q := P.toSubMarkovKernelSemigroup theta + let : IsFiniteKernel (P.augmentedKernel (times 0)) := by + have hParameterState : IsSubMarkovKernel (P.parameterStateKernel (times 0)) := + fun q ↦ by + rw [parameterStateKernel_apply] + exact P.isSubMarkovKernel q.1 (times 0) q.2 + let : IsFiniteKernel (P.parameterStateKernel (times 0)) := + hParameterState.isFiniteKernel + rw [augmentedKernel] + infer_instance + let : IsFiniteKernel (P.parameterizedFiniteTimeKernel times.relativeTail) := + isFiniteKernel_parameterizedFiniteTimeKernel P times.relativeTail + let : IsFiniteKernel (Q (times 0)) := Q.isSubMarkovKernel (times 0) |>.isFiniteKernel + let : IsFiniteKernel + (SubMarkovKernelSemigroup.finiteTimeKernel Q times.relativeTail) := + isFiniteKernel_finiteTimeKernel Q times.relativeTail + ext s hs + rw [parameterizedFiniteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map, + Kernel.map_apply' _ measurable_finCons_snd _ hs, + Kernel.compProd_apply (hs.preimage measurable_finCons_snd), + augmentedKernel_apply_eq_map, MeasureTheory.lintegral_map] + · rw [SubMarkovKernelSemigroup.finiteTimeKernel_succ, + Kernel.mapOfMeasurable_eq_map] + rw [Kernel.map_apply' _ measurable_finCons _ hs, + Kernel.compProd_apply (hs.preimage measurable_finCons)] + simp_rw [Kernel.prodMkLeft_apply', ih times.relativeTail theta] + rfl + · exact Kernel.measurable_kernel_prodMk_left' + (hs.preimage measurable_finCons_snd) (theta, x) + · exact measurable_const.prodMk measurable_id + +end ParameterizedSubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeProjectiveFamily.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeProjectiveFamily.lean new file mode 100644 index 0000000000..201d0ffe59 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeProjectiveFamily.lean @@ -0,0 +1,107 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel + +/-! +# Parameterized finite-set finite-time kernels + +This file reindexes parameterized finite-time kernels by finite sets of times. It proves exact +agreement with the ordinary finite-set kernel at every fixed parameter and starting state, and +derives projectivity under fiberwise conservativity. It does not construct a projective-limit +measure or a stochastic process. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace ParameterizedSubMarkovKernelSemigroup + +variable {Theta alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] + +/-- The jointly measurable finite-time kernel indexed by a finite set of times. -/ +noncomputable def parameterizedFiniteSetKernel + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (I : Finset NNReal) : + Kernel (Theta × alpha) (I → alpha) := + Kernel.mapOfMeasurable + (P.parameterizedFiniteTimeKernel (SubMarkovKernelSemigroup.finiteSetTimes I)) + (SubMarkovKernelSemigroup.orderedPathToFiniteSet I) + (SubMarkovKernelSemigroup.measurable_orderedPathToFiniteSet I) + +/-- The parameterized finite-set kernel agrees with the ordinary kernel map. -/ +theorem parameterizedFiniteSetKernel_eq_map + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (I : Finset NNReal) : + P.parameterizedFiniteSetKernel I = + (P.parameterizedFiniteTimeKernel + (SubMarkovKernelSemigroup.finiteSetTimes I)).map + (SubMarkovKernelSemigroup.orderedPathToFiniteSet I) := + Kernel.mapOfMeasurable_eq_map _ + (SubMarkovKernelSemigroup.measurable_orderedPathToFiniteSet I) + +/-- At a fixed parameter and start, the parameterized finite-set kernel is the ordinary one. -/ +theorem parameterizedFiniteSetKernel_apply + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (I : Finset NNReal) + (theta : Theta) (x : alpha) : + P.parameterizedFiniteSetKernel I (theta, x) = + (P.toSubMarkovKernelSemigroup theta).finiteSetKernel I x := by + rw [parameterizedFiniteSetKernel_eq_map, + Kernel.map_apply _ (SubMarkovKernelSemigroup.measurable_orderedPathToFiniteSet I), + parameterizedFiniteTimeKernel_apply, + SubMarkovKernelSemigroup.finiteSetKernel_eq_map, + Kernel.map_apply _ (SubMarkovKernelSemigroup.measurable_orderedPathToFiniteSet I)] + +/-- Fiberwise conservativity makes every parameterized finite-set kernel Markov. -/ +theorem isMarkovKernel_parameterizedFiniteSetKernel + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (I : Finset NNReal) : IsMarkovKernel (P.parameterizedFiniteSetKernel I) := by + rw [parameterizedFiniteSetKernel_eq_map] + let : IsMarkovKernel + (P.parameterizedFiniteTimeKernel (SubMarkovKernelSemigroup.finiteSetTimes I)) := + P.isMarkovKernel_parameterizedFiniteTimeKernel hP + (SubMarkovKernelSemigroup.finiteSetTimes I) + exact Kernel.IsMarkovKernel.map _ + (SubMarkovKernelSemigroup.measurable_orderedPathToFiniteSet I) + +/-- Restriction along an inclusion gives the kernel on the smaller finite time set. -/ +theorem parameterizedFiniteSetKernel_map_restrict₂ + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + {I J : Finset NNReal} (hJI : J ⊆ I) : + P.parameterizedFiniteSetKernel J = + (P.parameterizedFiniteSetKernel I).map + (Finset.restrict₂ (π := fun _ ↦ alpha) hJI) := by + apply Kernel.ext + intro q + obtain ⟨theta, x⟩ := q + rw [Kernel.map_apply _ (Finset.measurable_restrict₂ (X := fun _ ↦ alpha) hJI), + parameterizedFiniteSetKernel_apply, parameterizedFiniteSetKernel_apply] + have h := congrArg (fun K : Kernel alpha (J → alpha) ↦ K x) + ((hP theta).finiteSetKernel_map_restrict₂ + (P.toSubMarkovKernelSemigroup theta) hJI) + change (P.toSubMarkovKernelSemigroup theta).finiteSetKernel J x = + ((P.toSubMarkovKernelSemigroup theta).finiteSetKernel I).map + (Finset.restrict₂ (π := fun _ ↦ alpha) hJI) x at h + rw [Kernel.map_apply _ (Finset.measurable_restrict₂ (X := fun _ ↦ alpha) hJI)] at h + exact h + +/-- At every parameter and start, the finite-set laws form a projective measure family. -/ +theorem isProjectiveMeasureFamily_parameterizedFiniteSetKernel_apply + (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (theta : Theta) (x : alpha) : + IsProjectiveMeasureFamily (α := fun _ : NNReal ↦ alpha) + (fun I : Finset NNReal ↦ P.parameterizedFiniteSetKernel I (theta, x)) := by + intro I J hJI + change P.parameterizedFiniteSetKernel J (theta, x) = + Measure.map (Finset.restrict₂ (π := fun _ ↦ alpha) hJI) + (P.parameterizedFiniteSetKernel I (theta, x)) + rw [← Kernel.map_apply _ (Finset.measurable_restrict₂ (X := fun _ ↦ alpha) hJI)] + exact congrArg (fun K : Kernel (Theta × alpha) (J → alpha) ↦ K (theta, x)) + (P.parameterizedFiniteSetKernel_map_restrict₂ hP hJI) + +end ParameterizedSubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Killed.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Killed.lean new file mode 100644 index 0000000000..134591e114 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Killed.lean @@ -0,0 +1,111 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties + +/-! +# The killed parameterized family + +For a measurably parameterized family of conservative Feller semigroups and an open set `U`, the +processes of the fibres killed when they leave `U` again form a measurably parameterized family +of sub-Markov kernel semigroups on the carrier `U`: `killedFamily P hP U hU hFeller hK : +ParameterizedSubMarkovKernelSemigroup Theta U`, whose fibre at `theta` is the killed semigroup +`killedSemigroup` of `Killed/Semigroup.lean` for the semigroup at `theta` +(`killedFamily_toSubMarkovKernelSemigroup`, definitionally). The only new content is the joint +measurability of the killed transition probabilities in the parameter, the time and the starting +point, `measurable_killedKernelOn_family`, which comes from the joint measurability of the +parameterized continuous-path process through the fibre identity. + +The killed process on lifetime paths (with a cemetery state) is not constructed here. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + +namespace MarkovProcess.ParameterizedSubMarkovKernelSemigroup + +variable {Theta alpha : Type*} [MeasurableSpace Theta] [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (hP : P.IsConservative) +variable (U : Set alpha) (hU : IsOpen U) + +/-- The killed transition probabilities of the fibres are jointly measurable in the parameter, the +time and the starting point in `U`. -/ +theorem IsConservative.measurable_killedKernelOn_family : + Measurable fun q : Theta × (NNReal × U) ↦ + SubMarkovKernelSemigroup.IsConservative.killedKernelOn (P.toSubMarkovKernelSemigroup q.1) + (hP q.1) U hU q.2.1 q.2.2 := by + refine Measure.measurable_of_measurable_coe _ fun B hB ↦ ?_ + have hB' : MeasurableSet (Subtype.val '' B) := + (MeasurableEmbedding.subtype_coe hU.measurableSet).measurableSet_image.mpr hB + have hfun : (fun q : Theta × (NNReal × U) ↦ + SubMarkovKernelSemigroup.IsConservative.killedKernelOn (P.toSubMarkovKernelSemigroup q.1) + (hP q.1) U hU q.2.1 q.2.2 B) = + fun q ↦ IsConservative.continuousProcess P hP (q.1, (q.2.2 : alpha)) + (ContinuousPath.killedEvent U q.2.1 (Subtype.val '' B)) := by + funext q + rw [SubMarkovKernelSemigroup.IsConservative.killedKernelOn_apply_eq_continuousProcess _ _ U hU + _ _ hB, IsConservative.continuousProcess_apply] + rw [hfun] + have hg : Measurable fun q : Theta × (NNReal × U) ↦ (q.1, (q.2.2 : alpha)) := + measurable_fst.prodMk (measurable_subtype_coe.comp (measurable_snd.comp measurable_snd)) + have heval : Measurable fun p : NNReal × ContinuousPath alpha ↦ p.2 p.1 := + (ContinuousEval.continuous_eval.comp continuous_swap).measurable + have hS : MeasurableSet {p : (Theta × (NNReal × U)) × ContinuousPath alpha | + (p.1.2.1 : ℝ≥0∞) < ContinuousPath.exitTime U p.2 ∧ p.2 p.1.2.1 ∈ Subtype.val '' B} := by + refine MeasurableSet.inter ?_ ?_ + · exact measurableSet_lt + (measurable_coe_nnreal_ennreal.comp (measurable_fst.comp (measurable_snd.comp measurable_fst))) + ((ContinuousPath.measurable_exitTime U hU).comp measurable_snd) + · exact (heval.comp ((measurable_fst.comp (measurable_snd.comp measurable_fst)).prodMk + measurable_snd)) hB' + exact Kernel.measurable_kernel_prodMk_left + (κ := (IsConservative.continuousProcess P hP).comap _ hg) hS + +variable [LocallyCompactSpace alpha] + +/-- **The killed parameterized family**: the processes of the fibres killed when they leave the +open set `U`, as a measurably parameterized family of sub-Markov kernel semigroups on the carrier +`U`. -/ +noncomputable def IsConservative.killedFamily + (hFeller : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) : ParameterizedSubMarkovKernelSemigroup Theta U where + kernel theta t := + SubMarkovKernelSemigroup.IsConservative.killedKernelOn (P.toSubMarkovKernelSemigroup theta) + (hP theta) U hU t + measurable_kernel := IsConservative.measurable_killedKernelOn_family P hP U hU + kernel_zero theta := + SubMarkovKernelSemigroup.IsConservative.killedKernelOn_zero _ _ U hU (hK theta) + kernel_add theta := + SubMarkovKernelSemigroup.IsConservative.killedKernelOn_add _ _ U hU (hFeller theta) (hK theta) + isSubMarkovKernel theta t := + SubMarkovKernelSemigroup.IsConservative.isSubMarkovKernel_killedKernelOn + (P.toSubMarkovKernelSemigroup theta) (hP theta) U hU t + +/-- The fibre of the killed family at `theta` is the killed semigroup of the semigroup at `theta`. -/ +theorem IsConservative.killedFamily_toSubMarkovKernelSemigroup + (hFeller : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) (theta : Theta) : + (IsConservative.killedFamily P hP U hU hFeller hK).toSubMarkovKernelSemigroup theta = + SubMarkovKernelSemigroup.IsConservative.killedSemigroup (P.toSubMarkovKernelSemigroup theta) + (hP theta) U hU (hFeller theta) (hK theta) := rfl + +/-- The transition probabilities of the killed family, as probabilities of path events of the +parameterized process. -/ +theorem IsConservative.killedFamily_apply + (hFeller : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) (theta : Theta) (t : NNReal) (x : U) {B : Set U} + (hB : MeasurableSet B) : + IsConservative.killedFamily P hP U hU hFeller hK theta t x B = + IsConservative.continuousProcess P hP (theta, x) + (ContinuousPath.killedEvent U t (Subtype.val '' B)) := by + change SubMarkovKernelSemigroup.IsConservative.killedKernelOn (P.toSubMarkovKernelSemigroup theta) + (hP theta) U hU t x B = _ + rw [SubMarkovKernelSemigroup.IsConservative.killedKernelOn_apply_eq_continuousProcess _ _ U hU + t x hB, IsConservative.continuousProcess_apply] + +end MarkovProcess.ParameterizedSubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/OrderedGrid.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/OrderedGrid.lean new file mode 100644 index 0000000000..ce7467477e --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/OrderedGrid.lean @@ -0,0 +1,111 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup + +/-! +# Parameterized trajectory laws on a fixed ordered time grid + +This file constructs a jointly measurable kernel from a parameter and starting state to the +discrete trajectory on one fixed ordered grid. The parameter is carried as a deterministic +component of an augmented state through the Ionescu--Tulcea construction, then removed from the +output path. + +The result is a path-law kernel on `Theta × alpha` with values in measures on `ℕ → alpha`. +It is not a continuous-time path law and does not assert measurability in the grid. +-/ + +open MeasureTheory +open ProbabilityTheory +open scoped ProbabilityTheory + +namespace MarkovProcess + +namespace ParameterizedSubMarkovKernelSemigroup + +variable {Theta alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] + +variable (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + +private def lastIndex (n : ℕ) : Finset.Iic n := + ⟨n, Finset.mem_Iic.mpr le_rfl⟩ + +/-- The jointly measurable transition kernel at one fixed time increment. -/ +def parameterStateKernel (t : NNReal) : Kernel (Theta × alpha) alpha := + P.jointKernel.comap (fun q : Theta × alpha ↦ (q.1, (t, q.2))) + (measurable_fst.prodMk (measurable_const.prodMk measurable_snd)) + +@[simp] +theorem parameterStateKernel_apply (t : NNReal) (theta : Theta) (x : alpha) : + P.parameterStateKernel t (theta, x) = P theta t x := + rfl + +/-- The augmented transition preserves the parameter deterministically and samples the state. -/ +noncomputable def augmentedKernel (t : NNReal) : Kernel (Theta × alpha) (Theta × alpha) := + Kernel.deterministic Prod.fst measurable_fst ×ₖ P.parameterStateKernel t + +/-- Pointwise conservativity makes each augmented transition a Markov kernel. -/ +theorem isMarkovKernel_augmentedKernel + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) (t : NNReal) : + IsMarkovKernel (P.augmentedKernel t) := by + let : IsMarkovKernel (P.parameterStateKernel t) := + ⟨fun q ↦ by + rw [parameterStateKernel_apply] + exact ⟨hP q.1 t q.2⟩⟩ + rw [augmentedKernel] + infer_instance + +/-- The history-dependent augmented step kernel on a fixed ordered grid. -/ +noncomputable def parameterizedOrderedGridStepKernel (grid : OrderedGrid) (n : ℕ) : + Kernel ((i : Finset.Iic n) → Theta × alpha) (Theta × alpha) := + (P.augmentedKernel (grid.increment n)).comap + (fun history ↦ history (lastIndex n)) + (measurable_pi_apply (lastIndex n)) + +/-- Every augmented ordered-grid step is a Markov kernel under pointwise conservativity. -/ +theorem isMarkovKernel_parameterizedOrderedGridStepKernel + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (grid : OrderedGrid) (n : ℕ) : + IsMarkovKernel (P.parameterizedOrderedGridStepKernel grid n) := by + let : IsMarkovKernel (P.augmentedKernel (grid.increment n)) := + P.isMarkovKernel_augmentedKernel hP (grid.increment n) + rw [parameterizedOrderedGridStepKernel] + infer_instance + +/-- The jointly measurable path-law kernel from parameter and starting state to trajectories on +one fixed ordered grid. -/ +noncomputable def parameterizedOrderedGridTrajectoryKernel + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (grid : OrderedGrid) : Kernel (Theta × alpha) (ℕ → alpha) := by + letI (n : ℕ) : IsMarkovKernel (P.parameterizedOrderedGridStepKernel grid n) := + P.isMarkovKernel_parameterizedOrderedGridStepKernel hP grid n + exact ((Kernel.traj (P.parameterizedOrderedGridStepKernel grid) 0).comap + (fun q ↦ initialHistory q) measurable_initialHistory).map + (fun path : ℕ → Theta × alpha ↦ fun n ↦ (path n).2) + +/-- The parameterized ordered-grid trajectory kernel is a Markov kernel. -/ +theorem isMarkovKernel_parameterizedOrderedGridTrajectoryKernel + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (grid : OrderedGrid) : + IsMarkovKernel (P.parameterizedOrderedGridTrajectoryKernel hP grid) := by + let (n : ℕ) : IsMarkovKernel (P.parameterizedOrderedGridStepKernel grid n) := + P.isMarkovKernel_parameterizedOrderedGridStepKernel hP grid n + rw [parameterizedOrderedGridTrajectoryKernel] + apply Kernel.IsMarkovKernel.map + exact measurable_pi_iff.mpr fun n ↦ measurable_snd.comp (measurable_pi_apply n) + +/-- Evaluation of the parameterized path-law kernel is a probability measure. -/ +theorem isProbabilityMeasure_parameterizedOrderedGridTrajectoryKernel_apply + (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) + (grid : OrderedGrid) (theta : Theta) (x : alpha) : + IsProbabilityMeasure (P.parameterizedOrderedGridTrajectoryKernel hP grid (theta, x)) := by + let : IsMarkovKernel (P.parameterizedOrderedGridTrajectoryKernel hP grid) := + P.isMarkovKernel_parameterizedOrderedGridTrajectoryKernel hP grid + exact IsMarkovKernel.isProbabilityMeasure (theta, x) + +end ParameterizedSubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Semigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Semigroup.lean new file mode 100644 index 0000000000..f12e26afa7 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Semigroup.lean @@ -0,0 +1,156 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup + +/-! +# Measurably parameterized sub-Markov kernel semigroups + +This file packages sub-Markov kernel semigroups depending measurably on a parameter. The +measurability field is joint in parameter, time, and starting state, with carrier ordering +`Theta × (NNReal × alpha)`. Each fixed-parameter slice is an ordinary +`SubMarkovKernelSemigroup`. + +No parameter family is selected here, and no concrete coefficient, domain, Feller, conservativity, +or stochastic-process assertion is made. +-/ + +open Set +open scoped ENNReal ProbabilityTheory + +noncomputable section + +namespace MarkovProcess + +open MeasureTheory ProbabilityTheory + +/-- A jointly measurable parameter family of sub-Markov transition-kernel semigroups. + +The kernel is jointly measurable on `Θ × (NNReal × α)`. Mathlib writes `η.comp κ` for +first applying `κ` and then `η`, so the Chapman--Kolmogorov field has the orientation +`K θ (s + t) = (K θ t).comp (K θ s)`. +-/ +structure ParameterizedSubMarkovKernelSemigroup (Theta alpha : Type*) + [MeasurableSpace Theta] [MeasurableSpace alpha] where + /-- The transition kernel at a parameter and nonnegative time. -/ + kernel : Theta → NNReal → Kernel alpha alpha + /-- Joint measurability in parameter, time, and starting state. -/ + measurable_kernel : Measurable fun q : Theta × (NNReal × alpha) ↦ + kernel q.1 q.2.1 q.2.2 + /-- At time zero every parameter slice is the identity kernel. -/ + kernel_zero : ∀ theta, kernel theta 0 = Kernel.id + /-- The Chapman--Kolmogorov law, in Mathlib's kernel-composition orientation. -/ + kernel_add : ∀ theta s t, kernel theta (s + t) = (kernel theta t).comp (kernel theta s) + /-- Every transition measure has mass at most one. -/ + isSubMarkovKernel : ∀ theta t, IsSubMarkovKernel (kernel theta t) + +namespace ParameterizedSubMarkovKernelSemigroup + +variable {Theta alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] + +instance : CoeFun (ParameterizedSubMarkovKernelSemigroup Theta alpha) + (fun _ ↦ Theta → NNReal → Kernel alpha alpha) where + coe P := P.kernel + +/-- Two parameterized semigroups are equal when all their kernel slices are equal. -/ +@[ext] +theorem ext {P Q : ParameterizedSubMarkovKernelSemigroup Theta alpha} + (h : ∀ theta t, P theta t = Q theta t) : P = Q := by + cases P with + | mk P _ _ _ _ => + cases Q with + | mk Q _ _ _ _ => + have hPQ : P = Q := funext fun theta ↦ funext fun t ↦ h theta t + cases hPQ + rfl + +variable (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) + +/-- The jointly measurable kernel with input ordered as parameter, then time and state. -/ +def jointKernel : Kernel (Theta × (NNReal × alpha)) alpha where + toFun q := P q.1 q.2.1 q.2.2 + measurable' := P.measurable_kernel + +/-- Evaluation of the joint kernel is evaluation of the original parameter family. -/ +@[simp] +theorem jointKernel_apply (q : Theta × (NNReal × alpha)) : + P.jointKernel q = P q.1 q.2.1 q.2.2 := + rfl + +/-- Evaluation of the joint kernel at an explicit parameter, time, and state. -/ +@[simp] +theorem jointKernel_apply' (theta : Theta) (t : NNReal) (x : alpha) : + P.jointKernel (theta, (t, x)) = P theta t x := + rfl + +/-- Evaluation of the parameterized kernel on a measurable set is jointly measurable. -/ +theorem measurable_measure {s : Set alpha} (hs : MeasurableSet s) : + Measurable fun q : Theta × (NNReal × alpha) ↦ P q.1 q.2.1 q.2.2 s := + (Measure.measurable_coe hs).comp P.measurable_kernel + +/-- The ordinary sub-Markov kernel semigroup at one fixed parameter. -/ +def toSubMarkovKernelSemigroup (theta : Theta) : SubMarkovKernelSemigroup alpha where + kernel := P theta + measurable_kernel := by + have hPair : Measurable fun p : NNReal × alpha ↦ (theta, p) := + (measurable_const : Measurable fun _ : NNReal × alpha ↦ theta).prod measurable_id + exact P.measurable_kernel.comp hPair + kernel_zero := P.kernel_zero theta + kernel_add := P.kernel_add theta + isSubMarkovKernel := P.isSubMarkovKernel theta + +/-- A fixed-parameter slice evaluates to the original parameterized kernel. -/ +@[simp] +theorem toSubMarkovKernelSemigroup_apply (theta : Theta) (t : NNReal) : + toSubMarkovKernelSemigroup (P := P) theta t = P theta t := + rfl + +/-- Every parameter slice is the identity kernel at time zero. -/ +@[simp] +theorem zero (theta : Theta) : P theta 0 = Kernel.id := + P.kernel_zero theta + +/-- The parameterwise Chapman--Kolmogorov law. -/ +@[simp] +theorem add (theta : Theta) (s t : NNReal) : + P theta (s + t) = (P theta t).comp (P theta s) := + P.kernel_add theta s t + +/-- Transition kernels commute under composition at each fixed parameter. -/ +theorem comp_comm (theta : Theta) (s t : NNReal) : + (P theta t).comp (P theta s) = (P theta s).comp (P theta t) := by + rw [← P.add theta s t, ← P.add theta t s, add_comm] + +/-- Chapman--Kolmogorov as equality of parameterized transition measures. -/ +theorem add_apply (theta : Theta) (s t : NNReal) (x : alpha) : + P theta (s + t) x = (P theta s x).bind (P theta t) := by + rw [P.add, Kernel.comp_apply] + +/-- Chapman--Kolmogorov evaluated on a measurable set. -/ +theorem add_apply' (theta : Theta) (s t : NNReal) (x : alpha) + {u : Set alpha} (hu : MeasurableSet u) : + P theta (s + t) x u = ∫⁻ y, P theta t y u ∂P theta s x := by + rw [P.add, Kernel.comp_apply' _ _ _ hu] + +/-- The tower form of Chapman--Kolmogorov for nonnegative measurable functions. -/ +theorem lintegral_add (theta : Theta) (s t : NNReal) (x : alpha) + {f : alpha → ℝ≥0∞} (hf : Measurable f) : + ∫⁻ y, f y ∂P theta (s + t) x = + ∫⁻ y, ∫⁻ z, f z ∂P theta t y ∂P theta s x := by + rw [P.add, Kernel.lintegral_comp _ _ _ hf] + +/-- Every parameterized transition measure has mass at most one. -/ +theorem measure_univ_le_one (theta : Theta) (t : NNReal) (x : alpha) : + P theta t x univ ≤ 1 := + P.isSubMarkovKernel theta t x + +/-- Every parameterized transition measure assigns mass at most one to every set. -/ +theorem measure_le_one (theta : Theta) (t : NNReal) (x : alpha) (s : Set alpha) : + P theta t x s ≤ 1 := + (P.isSubMarkovKernel theta t).measure_le_one x s + +end ParameterizedSubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path.lean b/LeanPool/MarkovProcess/MarkovProcess/Path.lean new file mode 100644 index 0000000000..c393ab25b4 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path.lean @@ -0,0 +1,33 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration +import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral +import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift +import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification +import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +import LeanPool.MarkovProcess.MarkovProcess.Path.Polish +import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability +import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence +import LeanPool.MarkovProcess.MarkovProcess.Path.RelativeHitting +import LeanPool.MarkovProcess.MarkovProcess.Path.Sampling +import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence +import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability +import LeanPool.MarkovProcess.MarkovProcess.Path.Stopping +import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling + +/-! +# Path + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Basic.lean new file mode 100644 index 0000000000..f42fdd19ee --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Basic.lean @@ -0,0 +1,87 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Probability.Process.Filtration +import Mathlib.Topology.CompactOpen + +/-! +# Canonical continuous-path space + +This file provides the compact-open space of continuous paths on nonnegative real time, its +coordinate process, and the filtration generated by coordinates up to each time. It constructs +no probability law and makes no stochastic-process association or path-regularity claim. +-/ + +open MeasureTheory + +namespace MarkovProcess + +/-- Continuous paths on nonnegative real time, with the compact-open topology. -/ +abbrev ContinuousPath (alpha : Type*) [TopologicalSpace alpha] := C(NNReal, alpha) + +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- The Borel sigma-algebra of the compact-open topology on continuous paths. -/ +instance instMeasurableSpace : MeasurableSpace (ContinuousPath alpha) := borel _ + +/-- Continuous-path space carries its Borel sigma-algebra. -/ +instance instBorelSpace : BorelSpace (ContinuousPath alpha) := ⟨rfl⟩ + +/-- Evaluation of a continuous path at a fixed nonnegative time. -/ +def eval (t : NNReal) : ContinuousPath alpha → alpha := fun omega => omega t + +@[simp] +theorem eval_apply (t : NNReal) (omega : ContinuousPath alpha) : eval t omega = omega t := rfl + +/-- Fixed-time evaluation is continuous for the compact-open topology. -/ +theorem continuous_eval (t : NNReal) : Continuous (eval (alpha := alpha) t) := + continuous_eval_const t + +/-- The coordinate process on canonical continuous-path space. -/ +def coordinateProcess (t : NNReal) (omega : ContinuousPath alpha) : alpha := omega t + +@[simp] +theorem coordinateProcess_apply (t : NNReal) (omega : ContinuousPath alpha) : + coordinateProcess t omega = omega t := rfl + +/-- Every fixed-time coordinate of the canonical process is continuous. -/ +theorem continuous_coordinateProcess (t : NNReal) : + Continuous (coordinateProcess (alpha := alpha) t) := + continuous_eval_const t + +/-- Every fixed-time coordinate is Borel measurable. -/ +theorem measurable_coordinateProcess [MeasurableSpace alpha] [BorelSpace alpha] (t : NNReal) : + Measurable[borel (ContinuousPath alpha)] (coordinateProcess (alpha := alpha) t) := + (continuous_coordinateProcess t).borel_measurable.mono le_rfl + (le_of_eq BorelSpace.measurable_eq) + +/-- Two continuous paths are equal when all of their time coordinates agree. -/ +@[ext] +theorem ext {omega eta : ContinuousPath alpha} (h : ∀ t, omega t = eta t) : omega = eta := + ContinuousMap.ext h + +/-- The canonical filtration generated by coordinates at times `s ≤ t`. -/ +def canonicalFiltration [MeasurableSpace alpha] [BorelSpace alpha] : + Filtration NNReal (borel (ContinuousPath alpha)) where + seq t := ⨆ s : Set.Iic t, + MeasurableSpace.comap (coordinateProcess (alpha := alpha) s) ‹MeasurableSpace alpha› + mono' t u htu := by + refine iSup_le fun s => ?_ + exact le_iSup_of_le (⟨s.1, s.2.trans htu⟩ : Set.Iic u) le_rfl + le' t := iSup_le fun s => (measurable_coordinateProcess s).comap_le + +/-- The time-`t` coordinate is measurable for the canonical filtration at time `t`. -/ +theorem measurable_coordinateProcess_canonicalFiltration + [MeasurableSpace alpha] [BorelSpace alpha] (t : NNReal) : + Measurable[canonicalFiltration (alpha := alpha) t] + (coordinateProcess (alpha := alpha) t) := by + apply Measurable.of_comap_le + exact le_iSup_of_le (⟨t, Set.mem_Iic.mpr le_rfl⟩ : Set.Iic t) le_rfl + +end ContinuousPath + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean new file mode 100644 index 0000000000..3a081456d6 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean @@ -0,0 +1,324 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +import Mathlib.Topology.MetricSpace.HausdorffDistance + +/-! # Detecting closed sets from countably many path coordinates -/ + +open MeasureTheory Set + +namespace MarkovProcess + +noncomputable section + +namespace ContinuousPath + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +/-- The positive thresholds used to detect zero distance to a closed set. -/ +private def detectionThreshold (n : ℕ) : ℝ := 1 / (n + 1 : ℝ) + +private theorem detectionThreshold_pos (n : ℕ) : 0 < detectionThreshold n := by + exact one_div_pos.mpr (Nat.cast_add_one_pos n) + +/-- A countable test for whether a path on `[0, t]` meets `F`. The endpoint `t` is included +separately, while all earlier samples use the fixed enumeration of nonnegative rational times. -/ +def DetectsClosedSetOnIic (t : NNReal) (F : Set alpha) (f : C(Set.Iic t, alpha)) : Prop := + F.Nonempty ∧ ∀ n : ℕ, + Metric.infDist (f ⟨t, Set.mem_Iic.mpr le_rfl⟩) F < detectionThreshold n ∨ + ∃ k : ℕ, ∃ hk : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t, + Metric.infDist + (f ⟨DenseTime.castOrderEmbedding (DenseTime.enumeration k), + Set.mem_Iic.mpr hk.le⟩) F < + detectionThreshold n + +private theorem exists_denseTime_sample_of_lt + (t : NNReal) (f : C(Set.Iic t, alpha)) (F : Set alpha) + {s : Set.Iic t} (hs : (s : NNReal) < t) {epsilon : ℝ} (hepsilon : 0 < epsilon) + (hzero : Metric.infDist (f s) F = 0) : + ∃ k : ℕ, ∃ hk : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t, + Metric.infDist + (f ⟨DenseTime.castOrderEmbedding (DenseTime.enumeration k), + Set.mem_Iic.mpr hk.le⟩) F < epsilon := by + let g : Set.Iic t → ℝ := fun u ↦ Metric.infDist (f u) F + have hg : Continuous g := + (Metric.continuous_infDist_pt (s := F)).comp f.continuous + let O : Set (Set.Iic t) := g ⁻¹' Set.Iio epsilon + have hOopen : IsOpen O := isOpen_Iio.preimage hg + have hsO : s ∈ O := by + change Metric.infDist (f s) F < epsilon + rw [hzero] + exact hepsilon + obtain ⟨V, hVopen, hV⟩ := isOpen_induced_iff.mp hOopen + have hsV : (s : NNReal) ∈ V := by + have : s ∈ Subtype.val ⁻¹' V := by + rw [hV] + exact hsO + exact this + have hWopen : IsOpen (V ∩ Set.Iio t) := hVopen.inter isOpen_Iio + have hWnonempty : (V ∩ Set.Iio t).Nonempty := ⟨s, hsV, hs⟩ + obtain ⟨a, b, hab, hsub⟩ := hWopen.exists_Ioo_subset hWnonempty + obtain ⟨q, haq, hqb⟩ := DenseTime.exists_cast_btwn hab + let k : ℕ := DenseTime.enumeration.symm q + have hkq : DenseTime.enumeration k = q := DenseTime.enumeration.apply_symm_apply q + have hqW : DenseTime.castOrderEmbedding q ∈ V ∩ Set.Iio t := hsub ⟨haq, hqb⟩ + have hkW : DenseTime.castOrderEmbedding (DenseTime.enumeration k) ∈ + V ∩ Set.Iio t := by + rw [hkq] + exact hqW + refine ⟨k, ?_, ?_⟩ + · exact hkW.2 + · have hqO : + (⟨DenseTime.castOrderEmbedding (DenseTime.enumeration k), + Set.mem_Iic.mpr hkW.2.le⟩ : Set.Iic t) ∈ O := by + rw [← hV] + exact hkW.1 + exact hqO + +/-- A continuous path on a compact initial interval meets a closed set exactly when the endpoint +and the fixed countable dense-time samples detect arbitrarily small distance to that set. -/ +theorem detectsClosedSetOnIic_iff + (t : NNReal) (F : Set alpha) (hF : IsClosed F) (f : C(Set.Iic t, alpha)) : + DetectsClosedSetOnIic t F f ↔ ∃ s : Set.Iic t, f s ∈ F := by + constructor + · rintro ⟨hFnonempty, hdetect⟩ + by_contra hmeet + have hnotmem : ∀ s : Set.Iic t, f s ∉ F := by + intro s hs + exact hmeet ⟨s, hs⟩ + let g : Set.Iic t → ℝ := fun s ↦ Metric.infDist (f s) F + have hg : Continuous g := + (Metric.continuous_infDist_pt (s := F)).comp f.continuous + have hIic : IsCompact (Set.Iic t : Set NNReal) := by + have heq : Set.Iic t = Set.Icc 0 t := by + ext u + simp only [Set.mem_Iic, Set.mem_Icc, zero_le, true_and] + rw [heq] + exact isCompact_Icc + let : CompactSpace (Set.Iic t) := isCompact_iff_compactSpace.mp hIic + have hcompact : IsCompact (Set.univ : Set (Set.Iic t)) := isCompact_univ + have huniv : (Set.univ : Set (Set.Iic t)).Nonempty := + ⟨⟨0, (zero_le : (0 : NNReal) ≤ t)⟩, Set.mem_univ _⟩ + obtain ⟨s, -, hsmin⟩ := hcompact.exists_isMinOn huniv hg.continuousOn + have hgs : 0 < g s := (hF.notMem_iff_infDist_pos hFnonempty).mp (hnotmem s) + obtain ⟨n, hn⟩ := exists_nat_one_div_lt hgs + have hn' : detectionThreshold n < g s := hn + rcases hdetect n with hendpoint | ⟨k, hkt, hk⟩ + · have hmin := hsmin + (Set.mem_univ (⟨t, Set.mem_Iic.mpr le_rfl⟩ : Set.Iic t)) + exact (not_lt_of_ge hmin) (hendpoint.trans hn') + · let q : Set.Iic t := + ⟨DenseTime.castOrderEmbedding (DenseTime.enumeration k), hkt.le⟩ + have hmin := hsmin (Set.mem_univ q) + exact (not_lt_of_ge hmin) (hk.trans hn') + · rintro ⟨s, hsF⟩ + have hFnonempty : F.Nonempty := ⟨f s, hsF⟩ + refine ⟨hFnonempty, fun n ↦ ?_⟩ + have hzero : Metric.infDist (f s) F = 0 := Metric.infDist_zero_of_mem hsF + by_cases hst : (s : NNReal) = t + · left + have hs : s = (⟨t, Set.mem_Iic.mpr le_rfl⟩ : Set.Iic t) := Subtype.ext hst + rw [← hs, hzero] + exact detectionThreshold_pos n + · right + exact exists_denseTime_sample_of_lt t f F + (lt_of_le_of_ne s.property hst) (detectionThreshold_pos n) hzero + +/-- The positive thresholds used to detect zero distance to a closed set. -/ +def closedSetDetectionThreshold (n : ℕ) : ℝ := 1 / (n + 1 : ℝ) + +private theorem closedSetDetectionThreshold_pos (n : ℕ) : + 0 < closedSetDetectionThreshold n := by + exact one_div_pos.mpr (Nat.cast_add_one_pos n) + +/-- A countable test for whether a continuous map on `[u, t]` meets `F`. -/ +def DetectsClosedSetOnIcc (u t : NNReal) (hut : u ≤ t) (F : Set alpha) + (f : C(Set.Icc u t, alpha)) : Prop := + F.Nonempty ∧ ∀ n : ℕ, + Metric.infDist (f ⟨u, le_rfl, hut⟩) F < closedSetDetectionThreshold n ∨ + Metric.infDist (f ⟨t, hut, le_rfl⟩) F < closedSetDetectionThreshold n ∨ + ∃ k : ℕ, + ∃ huk : u < DenseTime.castOrderEmbedding (DenseTime.enumeration k), + ∃ hkt : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t, + Metric.infDist + (f ⟨DenseTime.castOrderEmbedding (DenseTime.enumeration k), huk.le, hkt.le⟩) F < + closedSetDetectionThreshold n + +private theorem exists_denseTime_sample_between + (u t : NNReal) (f : C(Set.Icc u t, alpha)) (F : Set alpha) + {s : Set.Icc u t} (hus : u < s) (hst : (s : NNReal) < t) + {epsilon : ℝ} (hepsilon : 0 < epsilon) (hzero : Metric.infDist (f s) F = 0) : + ∃ k : ℕ, + ∃ huk : u < DenseTime.castOrderEmbedding (DenseTime.enumeration k), + ∃ hkt : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t, + Metric.infDist + (f ⟨DenseTime.castOrderEmbedding (DenseTime.enumeration k), huk.le, hkt.le⟩) F < + epsilon := by + let g : Set.Icc u t → ℝ := fun v ↦ Metric.infDist (f v) F + have hg : Continuous g := (Metric.continuous_infDist_pt (s := F)).comp f.continuous + let O : Set (Set.Icc u t) := g ⁻¹' Set.Iio epsilon + have hOopen : IsOpen O := isOpen_Iio.preimage hg + have hsO : s ∈ O := by + change Metric.infDist (f s) F < epsilon + rw [hzero] + exact hepsilon + obtain ⟨W, hWopen, hW⟩ := isOpen_induced_iff.mp hOopen + have hsW : (s : NNReal) ∈ W := by + have hsPreimage : s ∈ Subtype.val ⁻¹' W := by + rw [hW] + exact hsO + exact hsPreimage + have hOpen : IsOpen (W ∩ Set.Ioo u t) := hWopen.inter isOpen_Ioo + have hNonempty : (W ∩ Set.Ioo u t).Nonempty := ⟨s, hsW, hus, hst⟩ + obtain ⟨a, b, hab, hsub⟩ := hOpen.exists_Ioo_subset hNonempty + obtain ⟨q, haq, hqb⟩ := DenseTime.exists_cast_btwn hab + let k : ℕ := DenseTime.enumeration.symm q + have hkq : DenseTime.enumeration k = q := DenseTime.enumeration.apply_symm_apply q + have hqW : DenseTime.castOrderEmbedding q ∈ W ∩ Set.Ioo u t := hsub ⟨haq, hqb⟩ + refine ⟨k, ?_, ?_, ?_⟩ + · simpa only [hkq] using hqW.2.1 + · simpa only [hkq] using hqW.2.2 + · have hqO : + (⟨DenseTime.castOrderEmbedding (DenseTime.enumeration k), + (by simpa only [hkq] using hqW.2.1.le), + (by simpa only [hkq] using hqW.2.2.le)⟩ : Set.Icc u t) ∈ O := by + rw [← hW] + simpa only [hkq] using! hqW.1 + exact hqO + +/-- A continuous map on a nonempty compact interval meets a closed set exactly when the +endpoint and fixed dense-time samples detect arbitrarily small distance to that set. -/ +theorem detectsClosedSetOnIcc_iff + (u t : NNReal) (hut : u ≤ t) (F : Set alpha) (hF : IsClosed F) + (f : C(Set.Icc u t, alpha)) : + DetectsClosedSetOnIcc u t hut F f ↔ ∃ s : Set.Icc u t, f s ∈ F := by + constructor + · rintro ⟨hFnonempty, hdetect⟩ + by_contra hmeet + have hnotmem : ∀ s : Set.Icc u t, f s ∉ F := by + intro s hs + exact hmeet ⟨s, hs⟩ + let g : Set.Icc u t → ℝ := fun s ↦ Metric.infDist (f s) F + have hg : Continuous g := (Metric.continuous_infDist_pt (s := F)).comp f.continuous + let : CompactSpace (Set.Icc u t) := isCompact_iff_compactSpace.mp isCompact_Icc + have hcompact : IsCompact (Set.univ : Set (Set.Icc u t)) := isCompact_univ + have huniv : (Set.univ : Set (Set.Icc u t)).Nonempty := + ⟨⟨u, le_rfl, hut⟩, Set.mem_univ _⟩ + obtain ⟨s, -, hsmin⟩ := hcompact.exists_isMinOn huniv hg.continuousOn + have hgs : 0 < g s := (hF.notMem_iff_infDist_pos hFnonempty).mp (hnotmem s) + obtain ⟨n, hn⟩ := exists_nat_one_div_lt hgs + have hn' : closedSetDetectionThreshold n < g s := hn + rcases hdetect n with hu | ht | ⟨k, huk, hkt, hk⟩ + · have hmin := hsmin (Set.mem_univ (⟨u, le_rfl, hut⟩ : Set.Icc u t)) + exact (not_lt_of_ge hmin) (hu.trans hn') + · have hmin := hsmin (Set.mem_univ (⟨t, hut, le_rfl⟩ : Set.Icc u t)) + exact (not_lt_of_ge hmin) (ht.trans hn') + · let q : Set.Icc u t := + ⟨DenseTime.castOrderEmbedding (DenseTime.enumeration k), huk.le, hkt.le⟩ + have hmin := hsmin (Set.mem_univ q) + exact (not_lt_of_ge hmin) (hk.trans hn') + · rintro ⟨s, hsF⟩ + have hFnonempty : F.Nonempty := ⟨f s, hsF⟩ + refine ⟨hFnonempty, fun n ↦ ?_⟩ + have hzero : Metric.infDist (f s) F = 0 := Metric.infDist_zero_of_mem hsF + by_cases hsu : (s : NNReal) = u + · left + have hs : s = (⟨u, le_rfl, hut⟩ : Set.Icc u t) := Subtype.ext hsu + rw [← hs, hzero] + exact closedSetDetectionThreshold_pos n + by_cases hst : (s : NNReal) = t + · right + left + have hs : s = (⟨t, hut, le_rfl⟩ : Set.Icc u t) := Subtype.ext hst + rw [← hs, hzero] + exact closedSetDetectionThreshold_pos n + · right + right + exact exists_denseTime_sample_between u t f F + (lt_of_le_of_ne s.property.1 (Ne.symm hsu)) + (lt_of_le_of_ne s.property.2 hst) (closedSetDetectionThreshold_pos n) hzero + +/-- Restrict an ordinary continuous path to a compact initial time interval. -/ +def restrictIic (t : NNReal) (omega : ContinuousPath alpha) : C(Set.Iic t, alpha) where + toFun s := omega s + continuous_toFun := omega.continuous.comp continuous_subtype_val + +/-- The event that a continuous path meets `F` at or before time `t`. -/ +def hitsSetBy (t : NNReal) (F : Set alpha) : Set (ContinuousPath alpha) := + {omega | ∃ s : Set.Iic t, omega s ∈ F} + +variable [MeasurableSpace alpha] [BorelSpace alpha] + +private theorem measurable_infDist_coordinate (t : NNReal) (F : Set alpha) + {s : NNReal} (hs : s ≤ t) : + Measurable[canonicalFiltration (alpha := alpha) t] + (fun omega : ContinuousPath alpha ↦ Metric.infDist (omega s) F) := by + have hcoordinate : Measurable[canonicalFiltration (alpha := alpha) t] + (coordinateProcess (alpha := alpha) s) := by + apply Measurable.of_comap_le + exact le_iSup_of_le (⟨s, Set.mem_Iic.mpr hs⟩ : Set.Iic t) le_rfl + have hcoordinate' : Measurable[canonicalFiltration (alpha := alpha) t, borel alpha] + (coordinateProcess (alpha := alpha) s) := + hcoordinate.mono le_rfl (le_of_eq BorelSpace.measurable_eq.symm) + exact (Metric.continuous_infDist_pt (s := F)).borel_measurable.comp hcoordinate' + +/-- Hitting a closed set by a fixed time is measurable in the raw canonical filtration. -/ +theorem measurableSet_hitsSetBy (t : NNReal) (F : Set alpha) (hF : IsClosed F) : + MeasurableSet[canonicalFiltration (alpha := alpha) t] (hitsSetBy t F) := by + by_cases hFnonempty : F.Nonempty + swap + · have hFempty : F = ∅ := not_nonempty_iff_eq_empty.mp hFnonempty + have hevent : hitsSetBy t F = ∅ := by + rw [hFempty] + ext omega + simp only [hitsSetBy, Set.mem_ofPred_eq, Set.notMem_empty, exists_const] + rw [hevent] + exact @MeasurableSet.empty _ (canonicalFiltration (alpha := alpha) t) + let A : ℕ → Set (ContinuousPath alpha) := fun n ↦ + {omega | Metric.infDist (omega t) F < detectionThreshold n} + let B : ℕ → ℕ → Set (ContinuousPath alpha) := fun n k ↦ + if h : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t then + {omega | Metric.infDist + (omega (DenseTime.castOrderEmbedding (DenseTime.enumeration k))) F < + detectionThreshold n} + else ∅ + have hA : ∀ n, MeasurableSet[canonicalFiltration (alpha := alpha) t] (A n) := by + intro n + exact (measurable_infDist_coordinate t F le_rfl) + (measurableSet_Iio : MeasurableSet (Set.Iio (detectionThreshold n))) + have hB : ∀ n k, MeasurableSet[canonicalFiltration (alpha := alpha) t] (B n k) := by + intro n k + dsimp only [B] + split_ifs with hkt + · exact (measurable_infDist_coordinate t F hkt.le) + (measurableSet_Iio : MeasurableSet (Set.Iio (detectionThreshold n))) + · exact @MeasurableSet.empty _ (canonicalFiltration (alpha := alpha) t) + have hevent : hitsSetBy t F = ⋂ n : ℕ, (A n ∪ ⋃ k : ℕ, B n k) := by + ext omega + rw [Set.mem_iInter] + change (∃ s : Set.Iic t, (restrictIic t omega) s ∈ F) ↔ _ + rw [← detectsClosedSetOnIic_iff t F hF (restrictIic t omega)] + simp only [DetectsClosedSetOnIic, hFnonempty, true_and, Set.mem_union, + Set.mem_iUnion, Set.mem_ofPred_eq, A, B, restrictIic] + constructor + · intro hdetect n + rcases hdetect n with hendpoint | ⟨k, hkt, hk⟩ + · exact Or.inl hendpoint + · exact Or.inr ⟨k, by rw [dif_pos hkt]; exact hk⟩ + · intro h n + rcases h n with hendpoint | ⟨k, hk⟩ + · exact Or.inl hendpoint + · by_cases hkt : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t + · exact Or.inr ⟨k, hkt, by simpa only [dif_pos hkt] using! hk⟩ + · simp only [dif_neg hkt, Set.notMem_empty] at hk + rw [hevent] + exact MeasurableSet.iInter fun n ↦ (hA n).union (MeasurableSet.iUnion (hB n)) + +end ContinuousPath + +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/DenseFiltration.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/DenseFiltration.lean new file mode 100644 index 0000000000..5ffc838c5c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/DenseFiltration.lean @@ -0,0 +1,109 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension + +/-! +# Dense-time generation of the continuous-path filtration + +At a nonnegative rational terminal time, the canonical filtration on continuous-path space is +already generated by the rational-time coordinates up to that terminal time. This deterministic +fact is the filtration bridge needed to extend finite-cylinder restart identities to all past +events. No probability law or Markov property is asserted here. +-/ + +open Filter MeasureTheory + +namespace MarkovProcess +namespace ContinuousPath + +noncomputable section + +variable {alpha : Type*} [PseudoMetricSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] + +/-- The measurable space generated by rational-time path coordinates up to `S`. -/ +def denseCanonicalFiltration (S : DenseTime) : MeasurableSpace (ContinuousPath alpha) := + ⨆ r : Set.Iic S, + MeasurableSpace.comap + (coordinateProcess (alpha := alpha) (DenseTime.castOrderEmbedding r)) + inferInstance + +/-- Restrict a continuous path to the rational times at most `S`. -/ +def densePastRestriction (S : DenseTime) (omega : ContinuousPath alpha) : Set.Iic S → alpha := + fun r ↦ coordinateProcess (alpha := alpha) (DenseTime.castOrderEmbedding r) omega + +omit [MeasurableSpace alpha] [BorelSpace alpha] in +@[simp] +theorem densePastRestriction_apply (S : DenseTime) (omega : ContinuousPath alpha) + (r : Set.Iic S) : + densePastRestriction S omega r = omega (DenseTime.castOrderEmbedding r) := + rfl + +omit [BorelSpace alpha] in +/-- The measurable space generated by the combined rational-past restriction is exactly the +supremum of the individual rational-coordinate measurable spaces. -/ +theorem comap_densePastRestriction_eq_denseCanonicalFiltration (S : DenseTime) : + MeasurableSpace.comap (densePastRestriction (alpha := alpha) S) inferInstance = + denseCanonicalFiltration (alpha := alpha) S := by + rw [denseCanonicalFiltration] + change + MeasurableSpace.comap (densePastRestriction (alpha := alpha) S) + (⨆ r, MeasurableSpace.comap (fun path : Set.Iic S → alpha ↦ path r) inferInstance) = + _ + simp only [MeasurableSpace.comap_iSup, MeasurableSpace.comap_comp] + rfl + +/-- At a rational terminal time, dense-time coordinates generate the full canonical +continuous-path filtration. -/ +theorem denseCanonicalFiltration_eq_canonicalFiltration (S : DenseTime) : + denseCanonicalFiltration (alpha := alpha) S = + canonicalFiltration (alpha := alpha) (DenseTime.castOrderEmbedding S) := by + apply le_antisymm + · rw [denseCanonicalFiltration] + refine iSup_le fun r ↦ ?_ + exact le_iSup_of_le + (⟨DenseTime.castOrderEmbedding r, + DenseTime.castOrderEmbedding.le_iff_le.mpr r.property⟩ : + Set.Iic (DenseTime.castOrderEmbedding S)) + le_rfl + · rw [canonicalFiltration] + refine iSup_le fun s ↦ ?_ + by_cases hs : (s : NNReal) = DenseTime.castOrderEmbedding S + · rw [hs] + exact le_iSup_of_le (⟨S, show S ≤ S from le_rfl⟩ : Set.Iic S) le_rfl + · have hst : (s : NNReal) < DenseTime.castOrderEmbedding S := + lt_of_le_of_ne s.property hs + obtain ⟨q, _hqAnti, hqMem, hq⟩ := + ContinuousPath.denseRange_castOrderEmbedding + |>.exists_seq_strictAnti_tendsto_of_lt + DenseTime.castOrderEmbedding.monotone hst + let qIic : ℕ → Set.Iic S := fun n ↦ + ⟨q n, DenseTime.castOrderEmbedding.le_iff_le.mp (hqMem n).2.le⟩ + let : MeasurableSpace (ContinuousPath alpha) := + denseCanonicalFiltration (alpha := alpha) S + have hmeas : Measurable (coordinateProcess (alpha := alpha) s) := by + apply measurable_of_tendsto_metrizable + (f := fun n ↦ coordinateProcess (alpha := alpha) + (DenseTime.castOrderEmbedding (qIic n))) + · intro n + apply Measurable.of_comap_le + exact le_iSup_of_le (qIic n) le_rfl + · apply tendsto_pi_nhds.2 + intro omega + exact Filter.Tendsto.comp omega.continuous.continuousAt hq + exact hmeas.comap_le + +/-- At a rational terminal time, the complete rational-past restriction generates the canonical +continuous-path filtration. -/ +theorem comap_densePastRestriction_eq_canonicalFiltration (S : DenseTime) : + MeasurableSpace.comap (densePastRestriction (alpha := alpha) S) inferInstance = + canonicalFiltration (alpha := alpha) (DenseTime.castOrderEmbedding S) := by + rw [comap_densePastRestriction_eq_denseCanonicalFiltration, + denseCanonicalFiltration_eq_canonicalFiltration] + +end +end ContinuousPath +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/DenseRestrictionIntegral.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/DenseRestrictionIntegral.lean new file mode 100644 index 0000000000..433549f4c1 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/DenseRestrictionIntegral.lean @@ -0,0 +1,39 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +import Mathlib.Topology.ContinuousMap.CompactlySupported + +/-! +# Integrals of finite dense-time marginals of a path measure + +Integrating a compactly supported test against the finite dense-time marginal of a measure on +continuous-path space is integrating the composed test against the measure itself. This is a +change-of-variables identity with no probabilistic content. +-/ + +open MeasureTheory +open scoped CompactlySupported + +namespace MarkovProcess +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] [SecondCountableTopology alpha] + [MeasurableSpace alpha] [BorelSpace alpha] + +/-- A compactly supported test integrated against a finite dense-time marginal of a path measure +is the composed test integrated against the path measure. -/ +theorem integral_map_denseRestriction_map_restrict + (nu : Measure (ContinuousPath alpha)) (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) : + ∫ z, f z ∂((nu.map denseRestriction).map J.restrict) = + ∫ omega, f (J.restrict (denseRestriction omega)) ∂nu := by + have hdense := measurable_denseRestriction (alpha := alpha) + have hrestrict := Finset.measurable_restrict (X := fun _ ↦ alpha) J + rw [Measure.map_map hrestrict hdense] + exact integral_map (hrestrict.comp hdense).aemeasurable + f.continuous.stronglyMeasurable.aestronglyMeasurable + +end ContinuousPath +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Exhaustion.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Exhaustion.lean new file mode 100644 index 0000000000..f9aa83f0ea --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Exhaustion.lean @@ -0,0 +1,98 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift + +/-! +# Exit times along an exhaustion + +For an increasing sequence of open sets `U n` covering the state space (an open exhaustion), the +exit time of a continuous path from `U n` tends to infinity: the path restricted to a compact time +interval has compact range, which lies in some `U N`, and the path therefore stays in `U n` on that +interval for every `n ≥ N` (`tendsto_exitTime_atTop`). Exit times are monotone in the set +(`exitTime_mono`), as are the truncated exit times. + +This is the path-space fact behind nonexplosion arguments: no probability law is involved here. +-/ + +open Filter Topology +open scoped ENNReal NNReal + +namespace MarkovProcess.ContinuousPath + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +/-- Exit times are monotone in the set: a path leaves a larger set no earlier. -/ +theorem exitTime_mono {U V : Set alpha} (hUV : U ⊆ V) (omega : ContinuousPath alpha) : + exitTime U omega ≤ exitTime V omega := by + rw [le_exitTime_iff] + intro v hv + exact exitTime_le_of_notMem U omega v (fun h ↦ hv (hUV h)) + +/-- Truncated exit times are monotone in the set. -/ +theorem exitTimeTrunc_mono {U V : Set alpha} (hUV : U ⊆ V) (K : NNReal) + (omega : ContinuousPath alpha) : exitTimeTrunc U K omega ≤ exitTimeTrunc V K omega := by + rw [← WithTop.coe_le_coe, coe_exitTimeTrunc, coe_exitTimeTrunc] + exact min_le_min_right _ (exitTime_mono hUV omega) + +/-- An open exhaustion of the state space: an increasing sequence of open sets whose union is the +whole space. -/ +structure IsOpenExhaustion (U : ℕ → Set alpha) : Prop where + /-- Every member is open. -/ + isOpen : ∀ n, IsOpen (U n) + /-- The sequence is increasing. -/ + monotone : Monotone U + /-- The sequence covers the state space. -/ + iUnion_eq : ⋃ n, U n = Set.univ + +/-- On a compact time interval, a continuous path eventually lies inside the members of an open +exhaustion, and its exit times are eventually larger than the interval's endpoint. -/ +theorem IsOpenExhaustion.exists_lt_exitTime {U : ℕ → Set alpha} (hU : IsOpenExhaustion U) + (omega : ContinuousPath alpha) (T : NNReal) : + ∃ N, ∀ n ≥ N, (T : ℝ≥0∞) < exitTime (U n) omega := by + have hcompact : IsCompact ((omega : NNReal → alpha) '' Set.Icc 0 T) := + isCompact_Icc.image omega.continuous + have hcover : (omega : NNReal → alpha) '' Set.Icc 0 T ⊆ ⋃ n, U n := by + rw [hU.iUnion_eq] + exact Set.subset_univ _ + obtain ⟨s, hs⟩ := hcompact.elim_finite_subcover U hU.isOpen hcover + refine ⟨s.sup id, fun n hn ↦ ?_⟩ + have hsub : (omega : NNReal → alpha) '' Set.Icc 0 T ⊆ U n := by + refine hs.trans (Set.iUnion₂_subset fun i hi ↦ hU.monotone ?_) + exact (Finset.le_sup (f := id) hi).trans hn + by_contra hle + rw [not_lt, exitTime_le_iff_mem_hitsSetBy (U n) (hU.isOpen n) T omega] at hle + obtain ⟨t, ht⟩ := hle + exact ht (hsub ⟨t, Set.mem_Icc.mpr ⟨zero_le, t.2⟩, rfl⟩) + +/-- Along an open exhaustion the exit times of a continuous path tend to infinity. -/ +theorem IsOpenExhaustion.tendsto_exitTime_atTop {U : ℕ → Set alpha} (hU : IsOpenExhaustion U) + (omega : ContinuousPath alpha) : + Tendsto (fun n ↦ exitTime (U n) omega) atTop (𝓝 ⊤) := by + rw [ENNReal.tendsto_nhds_top_iff_nnreal] + intro T + obtain ⟨N, hN⟩ := hU.exists_lt_exitTime omega T + exact Filter.eventually_atTop.mpr ⟨N, hN⟩ + +/-- Along an open exhaustion, every time is eventually below the exit time. -/ +theorem IsOpenExhaustion.eventually_lt_exitTime {U : ℕ → Set alpha} (hU : IsOpenExhaustion U) + (omega : ContinuousPath alpha) (t : NNReal) : + ∀ᶠ n in atTop, (t : ℝ≥0∞) < exitTime (U n) omega := + Filter.eventually_atTop.mpr (hU.exists_lt_exitTime omega t) + +/-- The exit times along an open exhaustion form a monotone sequence. -/ +theorem IsOpenExhaustion.monotone_exitTime {U : ℕ → Set alpha} (hU : IsOpenExhaustion U) + (omega : ContinuousPath alpha) : Monotone fun n ↦ exitTime (U n) omega := + fun _ _ hmn ↦ exitTime_mono (hU.monotone hmn) omega + +/-- The supremum of the exit times along an open exhaustion is infinite. -/ +theorem IsOpenExhaustion.iSup_exitTime {U : ℕ → Set alpha} (hU : IsOpenExhaustion U) + (omega : ContinuousPath alpha) : ⨆ n, exitTime (U n) omega = ⊤ := by + rw [eq_top_iff, ← ENNReal.iSup_natCast] + refine iSup_le fun T ↦ ?_ + obtain ⟨N, hN⟩ := hU.exists_lt_exitTime omega T + exact le_iSup_of_le N (by exact_mod_cast (hN N le_rfl).le) + +end MarkovProcess.ContinuousPath diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTime.lean new file mode 100644 index 0000000000..84bb7e1615 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTime.lean @@ -0,0 +1,284 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime +import Mathlib.Probability.Process.Stopping + +/-! +# Exit times of open sets on continuous-path space + +For an open set `U` this file studies `ContinuousPath.exitTime U`, the first time a continuous +path leaves `U`, in the `WithTop`-valued form `ContinuousPath.exitTimeTop U` demanded by +Mathlib's stopping-time convention. The main consumer facts are: the exit time is a stopping +time for the canonical filtration; it is finite exactly when the path leaves `U` at some time; +at a finite exit time the path sits on the frontier of `U` when it started inside; and its +truncation `exitTimeTrunc U K` at a deterministic horizon is an `NNReal`-valued stopping time, +which is the form the finite-stopping-time API of this library consumes. The generic time-set +identities `survivalSet_top`, `survivalSet_ne_top`, and `survivalSet` identify the positive real +times below an extended nonnegative horizon. + +The route is the closed-set detection of `Path/ClosedSetDetection.lean`: the event +`{exitTime ≤ t}` is the event of hitting the closed set `Uᶜ` by time `t`, because a path that +stays in the open set `U` throughout `[0, t]` stays in it slightly beyond `t`. + +This file constructs no probability law and proves no probabilistic statement; in particular it +does not claim that the exit time is almost surely finite for any process. +-/ + +open MeasureTheory Set Filter +open scoped ENNReal NNReal Topology + +namespace MarkovProcess + +namespace ContinuousPath + +noncomputable section + +section SurvivalSets + +/-- The survival set below an infinite extended horizon is the positive half-line. -/ +theorem survivalSet_top : + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < ⊤} ∩ Set.Ioi 0 = Set.Ioi 0 := by + ext t + simp only [Set.mem_inter_iff, Set.mem_ofPred_eq, Set.mem_Ioi] + exact and_iff_right ENNReal.coe_lt_top + +/-- The survival set below a finite extended horizon is an ordinary open interval. -/ +theorem survivalSet_ne_top (tau : ℝ≥0∞) (htau : tau ≠ ⊤) : + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau} ∩ Set.Ioi 0 = + Set.Ioo 0 tau.toReal := by + ext t + simp only [Set.mem_inter_iff, Set.mem_ofPred_eq, Set.mem_Ioi, Set.mem_Ioo] + constructor + · rintro ⟨httau, ht⟩ + refine ⟨ht, ?_⟩ + have hcoe : ((Real.toNNReal t : NNReal) : ℝ≥0∞) = ENNReal.ofReal t := rfl + rw [hcoe] at httau + exact (ENNReal.ofReal_lt_iff_lt_toReal ht.le htau).mp httau + · rintro ⟨ht, httau⟩ + refine ⟨?_, ht⟩ + have hcoe : ((Real.toNNReal t : NNReal) : ℝ≥0∞) = ENNReal.ofReal t := rfl + rw [hcoe] + exact (ENNReal.ofReal_lt_iff_lt_toReal ht.le htau).mpr httau + +/-- The time set on which the nonnegative-time coordinate remains below an extended horizon. -/ +theorem survivalSet (tau : ℝ≥0∞) : + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau} ∩ Set.Ioi 0 = + if tau = ⊤ then Set.Ioi 0 else Set.Ioo 0 tau.toReal := by + by_cases htau : tau = ⊤ + · rw [if_pos htau, htau] + exact survivalSet_top + · rw [if_neg htau] + exact survivalSet_ne_top tau htau + +end SurvivalSets + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +section Order + +/-- A time at which the path is outside `U` bounds the exit time from above. -/ +theorem exitTime_le_of_notMem (U : Set alpha) (omega : ContinuousPath alpha) (t : NNReal) + (ht : omega t ∉ U) : exitTime U omega ≤ (t : ℝ≥0∞) := by + apply sInf_le + exact ⟨t, rfl, ht⟩ + +/-- Strictly before the exit time the path is inside `U`. -/ +theorem mem_of_lt_exitTime (U : Set alpha) (omega : ContinuousPath alpha) (t : NNReal) + (ht : (t : ℝ≥0∞) < exitTime U omega) : omega t ∈ U := by + by_contra htU + exact absurd (exitTime_le_of_notMem U omega t htU) (not_le_of_gt ht) + +/-- The exit time from `U` is infinite exactly when the path never leaves `U`. -/ +theorem exitTime_eq_top_iff (U : Set alpha) (omega : ContinuousPath alpha) : + exitTime U omega = ⊤ ↔ ∀ t : NNReal, omega t ∈ U := by + constructor + · intro htop t + by_contra ht + have hle := exitTime_le_of_notMem U omega t ht + rw [htop, top_le_iff] at hle + exact ENNReal.coe_ne_top hle + · intro hmem + have hempty : {s : ℝ≥0∞ | ∃ t : NNReal, s = (t : ℝ≥0∞) ∧ omega t ∉ U} = ∅ := by + ext s + simp only [Set.mem_ofPred_eq, Set.mem_empty_iff_false, iff_false, not_exists, not_and] + intro u _ + exact fun hu ↦ hu (hmem u) + rw [exitTime, hempty, sInf_empty] + +/-- The exit time from `U` is finite exactly when the path leaves `U` at some time. -/ +theorem exitTime_lt_top_iff (U : Set alpha) (omega : ContinuousPath alpha) : + exitTime U omega < ⊤ ↔ ∃ t : NNReal, omega t ∉ U := by + rw [lt_top_iff_ne_top, Ne, exitTime_eq_top_iff, not_forall] + +/-- For an open set `U`, the exit time is at most `t` exactly when the path meets the closed set +`Uᶜ` at or before time `t`. The forward direction uses openness of `U`: a path inside `U` +throughout `[0, t]` stays inside `U` for a further positive amount of time, so its exit time is +strictly larger than `t`. -/ +theorem exitTime_le_iff_mem_hitsSetBy (U : Set alpha) (hU : IsOpen U) (t : NNReal) + (omega : ContinuousPath alpha) : + exitTime U omega ≤ (t : ℝ≥0∞) ↔ omega ∈ hitsSetBy t Uᶜ := by + constructor + · intro hle + by_contra hnot + have hall : ∀ s : NNReal, s ≤ t → omega s ∈ U := by + intro s hs + by_contra hsU + exact hnot ⟨⟨s, Set.mem_Iic.mpr hs⟩, hsU⟩ + have hVopen : IsOpen ((omega : NNReal → alpha) ⁻¹' U) := hU.preimage omega.continuous + have htV : t ∈ (omega : NNReal → alpha) ⁻¹' U := hall t le_rfl + obtain ⟨delta, hdelta, hball⟩ := Metric.isOpen_iff.mp hVopen t htV + have hhalf : (0 : ℝ) < delta / 2 := by linarith only [hdelta] + set d : NNReal := ⟨delta / 2, le_of_lt hhalf⟩ with hd + have hdpos : 0 < d := NNReal.coe_pos.mp hhalf + have hmem : ∀ s : NNReal, s < t + d → omega s ∈ U := by + intro s hs + by_cases hst : s ≤ t + · exact hall s hst + · apply hball + rw [Metric.mem_ball, NNReal.dist_eq] + have hts : (t : ℝ) < (s : ℝ) := by exact_mod_cast lt_of_not_ge hst + have hsd : (s : ℝ) < (t : ℝ) + delta / 2 := by + have := hs + rw [← NNReal.coe_lt_coe, NNReal.coe_add] at this + exact this + rw [abs_of_pos (by linarith only [hts])] + linarith only [hsd, hdelta] + have hge : ((t + d : NNReal) : ℝ≥0∞) ≤ exitTime U omega := by + rw [exitTime] + apply le_sInf + rintro s ⟨u, rfl, hu⟩ + have hnotlt : ¬ u < t + d := fun h ↦ hu (hmem u h) + exact_mod_cast not_lt.mp hnotlt + have hlt : (t : ℝ≥0∞) < ((t + d : NNReal) : ℝ≥0∞) := by + rw [ENNReal.coe_lt_coe] + exact lt_add_of_pos_right t hdpos + exact absurd (hlt.trans_le (hge.trans hle)) (lt_irrefl _) + · rintro ⟨s, hs⟩ + refine le_trans (exitTime_le_of_notMem U omega s hs) ?_ + exact_mod_cast s.property + +end Order + +section WithTopValue + +/-- The exit time of a continuous path from `U`, read in `WithTop ℝ≥0`: this is the same value as +`ContinuousPath.exitTime U`, presented in the type Mathlib's `IsStoppingTime` expects. -/ +def exitTimeTop (U : Set alpha) (omega : ContinuousPath alpha) : WithTop NNReal := + exitTime U omega + +/-- The `WithTop`-valued exit time is the exit time. -/ +theorem exitTimeTop_apply (U : Set alpha) (omega : ContinuousPath alpha) : + exitTimeTop U omega = exitTime U omega := rfl + +/-- The exit time from `U` truncated at the deterministic horizon `K`: an `NNReal`-valued, hence +finite, time, equal to the exit time when that is at most `K` and to `K` otherwise. -/ +def exitTimeTrunc (U : Set alpha) (K : NNReal) (omega : ContinuousPath alpha) : NNReal := + (min (exitTimeTop U omega) (K : WithTop NNReal)).untopA + +/-- The truncated exit time, read in `WithTop ℝ≥0`, is the minimum of the exit time and the +horizon. -/ +theorem coe_exitTimeTrunc (U : Set alpha) (K : NNReal) (omega : ContinuousPath alpha) : + ((exitTimeTrunc U K omega : NNReal) : WithTop NNReal) = + min (exitTimeTop U omega) (K : WithTop NNReal) := by + have hne : min (exitTimeTop U omega) (K : WithTop NNReal) ≠ ⊤ := by + intro htop + have hle := min_le_right (exitTimeTop U omega) (K : WithTop NNReal) + rw [htop] at hle + exact WithTop.coe_ne_top (top_le_iff.mp hle) + rw [exitTimeTrunc, WithTop.untopA_eq_untop hne, WithTop.coe_untop] + +/-- The truncated exit time never exceeds its horizon. -/ +theorem exitTimeTrunc_le (U : Set alpha) (K : NNReal) (omega : ContinuousPath alpha) : + exitTimeTrunc U K omega ≤ K := by + rw [← WithTop.coe_le_coe, coe_exitTimeTrunc] + exact min_le_right _ _ + +end WithTopValue + +section Frontier + +/-- The exit position is read at the time `(exitTime U omega).toNNReal`. The `WithTop.untopD` +spelling of that time, which the `WithTop`-valued stopping-time API produces, is the same +value. -/ +@[simp] +theorem untopD_exitTime (U : Set alpha) (omega : ContinuousPath alpha) : + (exitTime U omega).untopD 0 = (exitTime U omega).toNNReal := rfl + +/-- At a finite exit time, a path that started inside the open set `U` sits on the frontier of +`U`: it is outside `U`, and it is a limit of points of `U` visited strictly earlier. -/ +theorem coordinate_exitTime_mem_frontier (U : Set alpha) (hU : IsOpen U) + (omega : ContinuousPath alpha) (h0 : omega 0 ∈ U) (hfin : exitTime U omega ≠ ⊤) : + omega ((exitTime U omega).toNNReal) ∈ frontier U := by + set tau : NNReal := (exitTime U omega).toNNReal with htau + have hcoe : (tau : ℝ≥0∞) = exitTime U omega := ENNReal.coe_toNNReal hfin + have hbefore : ∀ s : NNReal, s < tau → omega s ∈ U := by + intro s hs + apply mem_of_lt_exitTime + rw [← hcoe, ENNReal.coe_lt_coe] + exact hs + have hnot : omega tau ∉ U := by + obtain ⟨s, hs⟩ := + (exitTime_le_iff_mem_hitsSetBy U hU tau omega).mp (le_of_eq hcoe.symm) + have hge : tau ≤ (s : NNReal) := by + by_contra hlt + exact hs (hbefore s (lt_of_not_ge hlt)) + have hseq : (s : NNReal) = tau := le_antisymm s.property hge + rw [← hseq] + exact hs + have htau0 : tau ≠ 0 := by + intro h + rw [h] at hnot + exact hnot h0 + have hclosure : omega tau ∈ closure U := by + have hnebot : (nhdsWithin tau (Set.Iio tau)).NeBot := + nhdsLT_neBot_of_exists_lt ⟨0, lt_of_le_of_ne (zero_le : (0 : NNReal) ≤ tau) (Ne.symm htau0)⟩ + have htend : Filter.Tendsto (omega : NNReal → alpha) (nhdsWithin tau (Set.Iio tau)) + (nhds (omega tau)) := (omega.continuous.tendsto tau).mono_left nhdsWithin_le_nhds + refine mem_closure_of_tendsto htend ?_ + filter_upwards [self_mem_nhdsWithin] with s hs + exact hbefore s hs + rw [hU.frontier_eq] + exact ⟨hclosure, hnot⟩ + +end Frontier + +section Stopping + +variable [MeasurableSpace alpha] [BorelSpace alpha] + +/-- **The exit time from an open set is a stopping time** for the canonical filtration on +continuous paths: the event `{exitTime ≤ t}` is the event of hitting the closed set `Uᶜ` by time +`t`, which is measurable in the canonical filtration at time `t`. -/ +theorem isStoppingTime_exitTime (U : Set alpha) (hU : IsOpen U) : + IsStoppingTime (canonicalFiltration (alpha := alpha)) (exitTimeTop U) := by + intro t + have hevent : {omega : ContinuousPath alpha | exitTimeTop U omega ≤ (t : WithTop NNReal)} = + hitsSetBy t Uᶜ := by + ext omega + simp only [Set.mem_ofPred_eq] + exact exitTime_le_iff_mem_hitsSetBy U hU t omega + show MeasurableSet[canonicalFiltration (alpha := alpha) t] + {omega : ContinuousPath alpha | exitTimeTop U omega ≤ (t : WithTop NNReal)} + rw [hevent] + exact measurableSet_hitsSetBy t Uᶜ hU.isClosed_compl + +/-- **The truncated exit time from an open set is a finite stopping time** for the canonical +filtration, in the `NNReal`-valued form consumed by the finite-stopping-time API of this +library. -/ +theorem isStoppingTime_exitTimeTrunc (U : Set alpha) (hU : IsOpen U) (K : NNReal) : + IsStoppingTime (canonicalFiltration (alpha := alpha)) + (fun omega ↦ ((exitTimeTrunc U K omega : NNReal) : WithTop NNReal)) := by + simp only [coe_exitTimeTrunc] + exact (isStoppingTime_exitTime U hU).min_const K + +end Stopping + +end + +end ContinuousPath + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTimeShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTimeShift.lean new file mode 100644 index 0000000000..cfbebc008d --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTimeShift.lean @@ -0,0 +1,126 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +import LeanPool.MarkovProcess.MarkovProcess.Path.Shift + +/-! +# Exit times under shifts + +Path-space identities relating the exit time `ContinuousPath.exitTime U` of an open set to the +shift `ContinuousPath.shift t`, and the measurability of the survival events they generate. + +* `exitTime_shift_add`: before the exit time, shifting by `t` subtracts `t` from the exit time, + `τ(θ_t ω) + t = τ(ω)` whenever `t < τ(ω)`; +* `coe_add_lt_exitTime_iff`: the event identity `{t + s < τ} = {t < τ} ∩ {s < τ ∘ θ_t}`, which is + the Chapman--Kolmogorov identity for the process killed at `τ`; +* `measurableSet_lt_exitTime_canonicalFiltration`, `measurableSet_lt_exitTime`, + `measurable_exitTime`: the survival event `{t < τ}` is measurable for the canonical filtration + at time `t`, and the exit time is a Borel function on path space. + +Nothing here involves a probability law. +-/ + +open MeasureTheory Set +open scoped ENNReal NNReal + +namespace MarkovProcess.ContinuousPath + +section Shift + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +/-- A bound `a ≤ exitTime U omega` holds exactly when `a ≤ v` at every time `v` at which the +path is outside `U`. -/ +theorem le_exitTime_iff (U : Set alpha) (omega : ContinuousPath alpha) (a : ℝ≥0∞) : + a ≤ exitTime U omega ↔ ∀ v : NNReal, omega v ∉ U → a ≤ (v : ℝ≥0∞) := by + rw [exitTime, le_sInf_iff] + constructor + · intro h v hv + exact h _ ⟨v, rfl, hv⟩ + · rintro h _ ⟨v, rfl, hv⟩ + exact h v hv + +/-- Before the exit time, shifting by `t` subtracts `t` from the exit time: +`exitTime U (shift t omega) + t = exitTime U omega` whenever `t < exitTime U omega`. -/ +theorem exitTime_shift_add (U : Set alpha) (omega : ContinuousPath alpha) (t : NNReal) + (ht : (t : ℝ≥0∞) < exitTime U omega) : + exitTime U (shift t omega) + t = exitTime U omega := by + apply le_antisymm + · rw [le_exitTime_iff] + intro v hv + have hle : exitTime U omega ≤ v := exitTime_le_of_notMem U omega v hv + have htv : t ≤ v := ENNReal.coe_le_coe.mp (ht.trans_le hle).le + have hbad : shift t omega (v - t) ∉ U := by + rw [shift_apply, add_tsub_cancel_of_le htv] + exact hv + calc exitTime U (shift t omega) + (t : ℝ≥0∞) ≤ ((v - t : NNReal) : ℝ≥0∞) + t := + add_le_add (exitTime_le_of_notMem U (shift t omega) (v - t) hbad) le_rfl + _ = v := by rw [← ENNReal.coe_add, tsub_add_cancel_of_le htv] + · rw [← tsub_le_iff_right, le_exitTime_iff] + intro u hu + have hle : exitTime U omega ≤ ((t + u : NNReal) : ℝ≥0∞) := + exitTime_le_of_notMem U omega (t + u) hu + rw [tsub_le_iff_right, ← ENNReal.coe_add, add_comm] + exact hle + +/-- The event identity `{t + s < τ} = {t < τ} ∩ {s < τ ∘ θ_t}` for the exit time `τ` of `U`. -/ +theorem coe_add_lt_exitTime_iff (U : Set alpha) (omega : ContinuousPath alpha) (t s : NNReal) : + ((t + s : NNReal) : ℝ≥0∞) < exitTime U omega ↔ + (t : ℝ≥0∞) < exitTime U omega ∧ (s : ℝ≥0∞) < exitTime U (shift t omega) := by + constructor + · intro h + have ht : (t : ℝ≥0∞) < exitTime U omega := + lt_of_le_of_lt (ENNReal.coe_le_coe.mpr le_self_add) h + refine ⟨ht, ?_⟩ + rw [← exitTime_shift_add U omega t ht, ENNReal.coe_add, add_comm] at h + exact (ENNReal.add_lt_add_iff_right ENNReal.coe_ne_top).mp h + · rintro ⟨ht, hs⟩ + rw [← exitTime_shift_add U omega t ht, ENNReal.coe_add, add_comm] + exact (ENNReal.add_lt_add_iff_right ENNReal.coe_ne_top).mpr hs + +end Shift + +section Measurable + +variable {alpha : Type*} [PseudoMetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + +/-- The survival event `{t < exitTime U}` of an open set is measurable for the canonical +filtration at time `t`. -/ +theorem measurableSet_lt_exitTime_canonicalFiltration (U : Set alpha) (hU : IsOpen U) + (t : NNReal) : + MeasurableSet[canonicalFiltration (alpha := alpha) t] + {omega : ContinuousPath alpha | (t : ℝ≥0∞) < exitTime U omega} := by + have hcompl : {omega : ContinuousPath alpha | (t : ℝ≥0∞) < exitTime U omega} = + {omega : ContinuousPath alpha | exitTimeTop U omega ≤ (t : WithTop NNReal)}ᶜ := by + ext omega + simp only [Set.mem_ofPred_eq, Set.mem_compl_iff, not_le] + exact Iff.rfl + rw [hcompl] + exact (isStoppingTime_exitTime U hU t).compl + +/-- The survival event `{t < exitTime U}` of an open set is a Borel set of path space. -/ +theorem measurableSet_lt_exitTime (U : Set alpha) (hU : IsOpen U) (t : NNReal) : + MeasurableSet {omega : ContinuousPath alpha | (t : ℝ≥0∞) < exitTime U omega} := + (canonicalFiltration (alpha := alpha)).le t _ + (measurableSet_lt_exitTime_canonicalFiltration U hU t) + +/-- The exit time of an open set is a Borel function on path space. -/ +theorem measurable_exitTime (U : Set alpha) (hU : IsOpen U) : + Measurable (exitTime U : ContinuousPath alpha → ℝ≥0∞) := by + refine measurable_of_Ioi fun a ↦ ?_ + induction a with + | top => + have h : (exitTime U : ContinuousPath alpha → ℝ≥0∞) ⁻¹' Set.Ioi ⊤ = ∅ := by + ext omega + simp only [Set.mem_preimage, Set.mem_Ioi, not_top_lt, Set.mem_empty_iff_false] + rw [h] + exact MeasurableSet.empty + | coe t => + exact measurableSet_lt_exitTime U hU t + +end Measurable + +end MarkovProcess.ContinuousPath diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/KernelIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/KernelIdentification.lean new file mode 100644 index 0000000000..4a7c227d53 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/KernelIdentification.lean @@ -0,0 +1,79 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +import Mathlib.Probability.Kernel.Composition.MapComap + +/-! +# Identifying continuous-path kernels from dense-time restrictions + +Restriction to the fixed dense time carrier is injective on kernels whose target is continuous-path +space. A measurable left inverse is obtained from the total continuous-extension map. This is a +deterministic property of continuous paths; it makes no stochastic-process, Markov, or regularity +claim. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace Kernel + +noncomputable section + +variable {alpha beta : Type*} [TopologicalSpace alpha] [T2Space alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [MeasurableSpace beta] + +variable [StandardBorelSpace (ContinuousPath alpha)] + [MeasurableSpace.CountablySeparated (DenseTime → alpha)] + +/-- Pushing a continuous-path kernel to dense-time paths and then applying the measurable total +continuous extension recovers the original kernel. -/ +@[simp] +theorem map_denseRestriction_map_continuousExtension + (kappa : Kernel beta (ContinuousPath alpha)) (default : ContinuousPath alpha) : + (kappa.map ContinuousPath.denseRestriction).map + (ContinuousPath.continuousExtension default) = kappa := by + rw [← Kernel.map_comp_right] + · have hcomp : ContinuousPath.continuousExtension default ∘ + ContinuousPath.denseRestriction = id := by + funext omega + exact ContinuousPath.continuousExtension_denseRestriction default omega + rw [hcomp, Kernel.map_id] + · exact ContinuousPath.measurable_denseRestriction + · exact ContinuousPath.measurable_continuousExtension default + +/-- A kernel on continuous-path space is determined by its pushforward to the fixed dense time +carrier. -/ +theorem map_denseRestriction_injective : + Function.Injective + (fun kappa : Kernel beta (ContinuousPath alpha) ↦ + kappa.map ContinuousPath.denseRestriction) := by + intro kappa eta h + ext x s hs + have himage : MeasurableSet (ContinuousPath.denseRestriction '' s) := + ContinuousPath.measurableEmbedding_denseRestriction.measurableSet_image' hs + have hx := congrArg + (fun z : Kernel beta (DenseTime → alpha) ↦ + z x (ContinuousPath.denseRestriction '' s)) h + dsimp only at hx + rw [Kernel.map_apply' _ ContinuousPath.measurable_denseRestriction x himage, + Kernel.map_apply' _ ContinuousPath.measurable_denseRestriction x himage] at hx + simpa only [ContinuousPath.denseRestriction_injective.preimage_image] using hx + +/-- Equality of continuous-path kernels is equivalent to equality after restriction to the fixed +dense time carrier. -/ +theorem map_denseRestriction_eq_iff {kappa eta : Kernel beta (ContinuousPath alpha)} : + kappa.map ContinuousPath.denseRestriction = eta.map ContinuousPath.denseRestriction ↔ + kappa = eta := by + constructor + · intro h + exact map_denseRestriction_injective (alpha := alpha) (beta := beta) h + · exact fun h ↦ congrArg + (fun z : Kernel beta (ContinuousPath alpha) ↦ + z.map ContinuousPath.denseRestriction) h + +end +end Kernel +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/MeasureIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/MeasureIdentification.lean new file mode 100644 index 0000000000..df1bb8f315 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/MeasureIdentification.lean @@ -0,0 +1,63 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension + +/-! +# Identifying continuous-path measures from dense-time restrictions + +A measure on continuous-path space is determined by its pushforward to the fixed dense time +carrier. This is the measure-level counterpart of continuous-path kernel identification and is a +deterministic property of continuous paths. +-/ + +open MeasureTheory + +namespace MarkovProcess +namespace Measure + +noncomputable section + +variable {alpha : Type*} [TopologicalSpace alpha] [T2Space alpha] + [MeasurableSpace alpha] [BorelSpace alpha] + +variable [StandardBorelSpace (ContinuousPath alpha)] + [MeasurableSpace.CountablySeparated (DenseTime → alpha)] + +/-- A measure on continuous-path space is determined by its pushforward to the fixed dense time +carrier. -/ +theorem map_denseRestriction_injective : + Function.Injective + (fun mu : MeasureTheory.Measure (ContinuousPath alpha) ↦ + mu.map ContinuousPath.denseRestriction) := by + intro mu nu h + ext s hs + have himage : MeasurableSet (ContinuousPath.denseRestriction '' s) := + ContinuousPath.measurableEmbedding_denseRestriction.measurableSet_image' hs + have hmap := congrArg + (fun rho : MeasureTheory.Measure (DenseTime → alpha) ↦ + rho (ContinuousPath.denseRestriction '' s)) h + dsimp only at hmap + rw [MeasureTheory.Measure.map_apply ContinuousPath.measurable_denseRestriction himage, + MeasureTheory.Measure.map_apply ContinuousPath.measurable_denseRestriction himage] at hmap + simpa only [ContinuousPath.denseRestriction_injective.preimage_image] using hmap + +/-- Equality of continuous-path measures is equivalent to equality after restriction to the fixed +dense time carrier. -/ +theorem map_denseRestriction_eq_iff + {mu nu : MeasureTheory.Measure (ContinuousPath alpha)} : + mu.map ContinuousPath.denseRestriction = nu.map ContinuousPath.denseRestriction ↔ + mu = nu := by + constructor + · intro h + exact map_denseRestriction_injective (alpha := alpha) h + · intro h + exact congrArg + (fun rho : MeasureTheory.Measure (ContinuousPath alpha) ↦ + rho.map ContinuousPath.denseRestriction) h + +end +end Measure +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/MixedFiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/MixedFiniteMarginals.lean new file mode 100644 index 0000000000..0f9cb8f7ba --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/MixedFiniteMarginals.lean @@ -0,0 +1,75 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture + +/-! +# Finite mixed past/future marginals of continuous trajectories + +Every finite collection of rational coordinates drawn from the past through `S` and the shifted +future has the finite transition law on the corresponding union of absolute physical times, +followed by the canonical possibly noninjective coordinate pullback. In particular, a terminal +past coordinate and a future coordinate at zero are both retained even though they observe the +same absolute time. + +This is a finite-dimensional law identity. The conditional factorization of that law through +the state at `S` is in `Restart/RationalRestart.lean`. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup +namespace IsConservative + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [StandardBorelSpace alpha] [Nonempty alpha] + +/-- A finite mixed rational past/shifted-future marginal is the finite transition law on its +absolute physical times, pulled back to the original mixed labels. -/ +theorem continuousPathTrajectory_map_mixedPastShiftedCoordinates_restrict + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) : + (continuousPathTrajectory P hP default).map + (I.restrict ∘ ContinuousPath.mixedPastShiftedCoordinates S) = + (finiteSetKernel P (MixedPastFuture.absolutePhysicalFinset S I)).map + (MixedPastFuture.pullbackAbsolutePhysical S I) := by + let evaluateAbsolute : ContinuousPath alpha → + MixedPastFuture.absolutePhysicalFinset S I → alpha := + fun path t ↦ path t + have hEvaluateAbsolute : Measurable evaluateAbsolute := by + rw [measurable_pi_iff] + intro t + exact ContinuousPath.measurable_coordinateProcess (alpha := alpha) t + have hcoordinates : + I.restrict ∘ ContinuousPath.mixedPastShiftedCoordinates S = + MixedPastFuture.pullbackAbsolutePhysical S I ∘ evaluateAbsolute := by + funext omega + exact ContinuousPath.restrict_mixedPastShiftedCoordinates S I omega + rw [hcoordinates, Kernel.map_comp_right] + · change + ((continuousPathTrajectory P hP default).map + (fun path (t : denseTimePhysicalSet (MixedPastFuture.absoluteFinset S I)) ↦ + path t)).map (MixedPastFuture.pullbackAbsolutePhysical S I) = _ + rw [continuousPathTrajectory_map_finiteDenseTimeSet P hP default hK] + rfl + · exact hEvaluateAbsolute + · exact MixedPastFuture.measurable_pullbackAbsolutePhysical S I + +end +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/OptionalStopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/OptionalStopping.lean new file mode 100644 index 0000000000..f5c252a9b1 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/OptionalStopping.lean @@ -0,0 +1,311 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling +import Mathlib.MeasureTheory.Integral.DominatedConvergence +import Mathlib.Probability.Martingale.OptionalStopping + +/-! +# Optional stopping in continuous time, at a bounded finite stopping time + +Mathlib's optional stopping theorem is discrete-time. This file proves the continuous-time +statement the library consumes: if `M` is a real-valued martingale for a filtration indexed by +`ℝ≥0`, bounded on bounded time intervals and right continuous in time along every sample point, +and `T` is a finite stopping time bounded by a deterministic horizon `K`, then + + `∫ omega, M (T omega) omega ∂mu = ∫ omega, M 0 omega ∂mu` + +(`integral_stoppedValue_eq_of_locallyBounded`, with the uniformly bounded case +`integral_stoppedValue_eq_of_le`). + +For a supermartingale the corresponding expectation is at most its initial expectation +(`integral_stoppedValue_le_of_locallyBounded` and `integral_stoppedValue_le_of_le`). + +The proof samples a supermartingale on the dyadic grid and applies Mathlib's +`Submartingale.expected_stoppedValue_mono` after negation. The dyadic ceilings `T_n` of a finite +stopping time are stopping times with finite range that decrease to `T` +(`Path/StoppingTimeDyadicCeiling.lean`), so dominated convergence and right continuity give the +supermartingale inequality. Applying that inequality to a martingale and its negation gives the +martingale equality. + +Nothing here is specific to path space: the statements are for an arbitrary measurable space with +a filtration indexed by `ℝ≥0`. No optional-stopping result for unbounded stopping times is +asserted. +-/ + +open Filter MeasureTheory Topology +open scoped NNReal + +namespace MarkovProcess + +noncomputable section + +variable {Omega : Type*} {m : MeasurableSpace Omega} {mu : Measure Omega} + {ℱ : Filtration NNReal m} {M : NNReal → Omega → ℝ} + +section FiniteRange + +variable [IsFiniteMeasure mu] + +/-- A function of a time-valued map with values in a finite set is the sum of the indicators of +the level sets. -/ +private theorem apply_eq_sum_indicator {S : Omega → NNReal} {V : Finset NNReal} + (hSV : ∀ omega, S omega ∈ V) (g : NNReal → Omega → ℝ) (omega : Omega) : + g (S omega) omega = ∑ v ∈ V, Set.indicator {eta | S eta = v} (g v) omega := by + rw [Finset.sum_eq_single_of_mem (S omega) (hSV omega)] + · rw [Set.indicator_of_mem (Set.mem_ofPred_eq ▸ rfl)] + · intro v _ hv + exact Set.indicator_of_notMem (fun h ↦ hv h.symm) _ + +/-- The level sets of a stopping time with finite range are events of the filtration at the +corresponding time. -/ +theorem measurableSet_eq_of_finite_range {S : Omega → NNReal} + (hS : IsStoppingTime ℱ fun omega ↦ ((S omega : NNReal) : WithTop NNReal)) + (hfin : (Set.range S).Finite) (v : NNReal) : + MeasurableSet[ℱ v] {omega | S omega = v} := by + have hcount : (Set.range fun omega ↦ ((S omega : NNReal) : WithTop NNReal)).Countable := by + refine (hfin.countable.image (fun w : NNReal ↦ (w : WithTop NNReal))).mono ?_ + rintro _ ⟨omega, rfl⟩ + exact ⟨S omega, ⟨omega, rfl⟩, rfl⟩ + have hset : {omega | S omega = v} = + {omega | ((S omega : NNReal) : WithTop NNReal) = (v : WithTop NNReal)} := by + ext omega + simp only [Set.mem_ofPred_eq, WithTop.coe_eq_coe] + rw [hset] + exact hS.measurableSet_eq_of_countable_range hcount v + +/-- The value of an adapted process at a stopping time with finite range is measurable. -/ +theorem stronglyMeasurable_apply_of_finite_range (hadapted : StronglyAdapted ℱ M) {S : Omega → NNReal} + (hS : IsStoppingTime ℱ fun omega ↦ ((S omega : NNReal) : WithTop NNReal)) + (hfin : (Set.range S).Finite) : + StronglyMeasurable fun omega ↦ M (S omega) omega := by + have hSV : ∀ omega, S omega ∈ hfin.toFinset := fun omega ↦ + hfin.mem_toFinset.mpr ⟨omega, rfl⟩ + have hsum : (fun omega ↦ M (S omega) omega) = + fun omega ↦ ∑ v ∈ hfin.toFinset, Set.indicator {eta | S eta = v} (M v) omega := by + funext omega + exact apply_eq_sum_indicator hSV M omega + rw [hsum] + refine Finset.stronglyMeasurable_fun_sum _ fun v _ ↦ ?_ + exact ((hadapted v).mono (ℱ.le v)).indicator + (ℱ.le v _ (measurableSet_eq_of_finite_range hS hfin v)) + +/-- **Optional stopping at a stopping time with finite range.** For a martingale `M` with +integrable values and a stopping time `S` with finite range bounded by the deterministic time +`u`, the expectation of `M` at time `S` is the expectation of `M` at time `u`. This is a finite +sum over the values of `S`, each term handled by the defining property of the conditional +expectation on the event `{S = v}`, which belongs to the filtration at time `v`. -/ +theorem integral_apply_eq_of_finite_range (hM : Martingale M ℱ mu) + (hMint : ∀ t : NNReal, Integrable (M t) mu) {S : Omega → NNReal} + (hS : IsStoppingTime ℱ fun omega ↦ ((S omega : NNReal) : WithTop NNReal)) + (hfin : (Set.range S).Finite) {u : NNReal} (hu : ∀ omega, S omega ≤ u) : + ∫ omega, M (S omega) omega ∂mu = ∫ omega, M u omega ∂mu := by + have hSV : ∀ omega, S omega ∈ hfin.toFinset := fun omega ↦ + hfin.mem_toFinset.mpr ⟨omega, rfl⟩ + have hmeas : ∀ v : NNReal, MeasurableSet[ℱ v] {omega | S omega = v} := + measurableSet_eq_of_finite_range hS hfin + have hmeas' : ∀ v : NNReal, MeasurableSet {omega | S omega = v} := fun v ↦ + ℱ.le v _ (hmeas v) + have hind : ∀ (g : NNReal → Omega → ℝ), (∀ t : NNReal, Integrable (g t) mu) → + ∫ omega, g (S omega) omega ∂mu = + ∑ v ∈ hfin.toFinset, ∫ omega in {omega | S omega = v}, g v omega ∂mu := by + intro g hg + have hsum : ∫ omega, g (S omega) omega ∂mu = + ∫ omega, ∑ v ∈ hfin.toFinset, Set.indicator {eta | S eta = v} (g v) omega ∂mu := + integral_congr_ae (Eventually.of_forall fun omega ↦ apply_eq_sum_indicator hSV g omega) + rw [hsum, integral_finsetSum _ fun v _ ↦ (hg v).indicator (hmeas' v)] + exact Finset.sum_congr rfl fun v _ ↦ integral_indicator (hmeas' v) + rw [hind M hMint, hind (fun _ ↦ M u) fun _ ↦ hMint u] + refine Finset.sum_congr rfl fun v hv ↦ ?_ + have hle : v ≤ u := by + obtain ⟨omega, rfl⟩ := hfin.mem_toFinset.mp hv + exact hu omega + rw [← setIntegral_condExp (ℱ.le v) (hMint u) (hmeas v)] + exact (setIntegral_congr_ae (hmeas' v) ((hM.2 v u hle).mono fun _ hx _ ↦ hx)).symm + +end FiniteRange + +section DyadicApproximation + +/-- Sampling an `NNReal` filtration on a dyadic grid gives a discrete filtration. -/ +private def dyadicFiltration (n : ℕ) (ℱ : Filtration NNReal m) : Filtration ℕ m where + seq k := ℱ (dyadicGrid n k) + mono' _ _ hkl := ℱ.mono (monotone_dyadicGrid n hkl) + le' k := ℱ.le (dyadicGrid n k) + +/-- The dyadic ceiling index is a stopping time for the sampled filtration. -/ +private theorem isStoppingTime_dyadicCeilingIndex {T : Omega → NNReal} + (hT : IsStoppingTime ℱ fun omega ↦ ((T omega : NNReal) : WithTop NNReal)) (n : ℕ) : + IsStoppingTime (dyadicFiltration n ℱ) + (fun omega ↦ (dyadicCeilingIndex n (T omega) : ℕ∞)) := by + intro k + have hstop := isStoppingTime_dyadicCeiling hT n (dyadicGrid n k) + change MeasurableSet[ℱ (dyadicGrid n k)] + {omega | (dyadicCeilingIndex n (T omega) : ℕ∞) ≤ k} + convert hstop using 1 + ext omega + simp only [Set.mem_ofPred_eq, ENat.natCast_le_natCast] + rw [← dyadicGrid_ceilingIndex] + rw [WithTop.coe_le_coe] + exact (strictMono_dyadicGrid n).le_iff_le.symm + +/-- Sampling a supermartingale at dyadic grid points gives a discrete supermartingale. -/ +private theorem dyadicSample_supermartingale (hM : Supermartingale M ℱ mu) (n : ℕ) : + Supermartingale (fun k ↦ M (dyadicGrid n k)) (dyadicFiltration n ℱ) mu := by + refine ⟨fun k ↦ hM.1 (dyadicGrid n k), ?_, fun k ↦ hM.2.2 (dyadicGrid n k)⟩ + intro k l hkl + exact hM.2.1 _ _ (monotone_dyadicGrid n hkl) + +/-- One dyadic grid step is at most one. -/ +private theorem inv_two_pow_le_one (n : ℕ) : ((2 : NNReal) ^ n)⁻¹ ≤ 1 := by + rw [← NNReal.coe_le_coe, NNReal.coe_inv, NNReal.coe_pow, NNReal.coe_ofNat, NNReal.coe_one] + exact inv_le_one_of_one_le₀ (one_le_pow₀ (by norm_num)) + +/-- The dyadic ceiling of a time bounded by `K` is bounded by `K + 1`. -/ +private theorem dyadicCeiling_le_add_one (n : ℕ) {t K : NNReal} (ht : t ≤ K) : + dyadicCeiling n t ≤ K + 1 := + (dyadicCeiling_le_add n t).trans (add_le_add ht (inv_two_pow_le_one n)) + +/-- At each dyadic level, the ceilings of times bounded by a fixed horizon form a finite set. -/ +private theorem finite_range_dyadicCeiling (n : ℕ) {S : Omega → NNReal} {K : NNReal} + (hSK : ∀ omega, S omega ≤ K) : + (Set.range fun omega ↦ dyadicCeiling n (S omega)).Finite := by + refine Set.Finite.subset ((Set.finite_Iic (⌈(2 ^ n : ℝ) * (K : ℝ)⌉₊)).image + (dyadicGrid n)) ?_ + rintro _ ⟨omega, rfl⟩ + refine ⟨⌈(2 ^ n : ℝ) * (S omega : ℝ)⌉₊, Set.mem_Iic.mpr (Nat.ceil_le_ceil ?_), rfl⟩ + exact mul_le_mul_of_nonneg_left (NNReal.coe_le_coe.mpr (hSK omega)) + (by positivity : (0 : ℝ) ≤ 2 ^ n) + +end DyadicApproximation + +section OptionalStopping + +variable [IsFiniteMeasure mu] + +/-- **Optional stopping inequality at a bounded finite stopping time.** For a supermartingale +which is bounded on bounded time intervals and has right-continuous orbits, the expectation at a +bounded stopping time is at most its initial expectation. -/ +theorem integral_stoppedValue_le_of_locallyBounded (hM : Supermartingale M ℱ mu) + (hbound : ∀ v : NNReal, ∃ C : ℝ, ∀ t ≤ v, ∀ omega, ‖M t omega‖ ≤ C) + (hright : ∀ (omega : Omega) (v : NNReal), + ContinuousWithinAt (fun t : NNReal ↦ M t omega) (Set.Ici v) v) + {T : Omega → NNReal} + (hT : IsStoppingTime ℱ fun omega ↦ ((T omega : NNReal) : WithTop NNReal)) + {K : NNReal} (hTK : ∀ omega, T omega ≤ K) : + ∫ omega, M (T omega) omega ∂mu ≤ ∫ omega, M 0 omega ∂mu := by + have hstopfin : ∀ n : ℕ, (Set.range fun omega ↦ dyadicCeiling n (T omega)).Finite := fun n ↦ + finite_range_dyadicCeiling n hTK + have hstep : ∀ n : ℕ, + ∫ omega, M (dyadicCeiling n (T omega)) omega ∂mu ≤ ∫ omega, M 0 omega ∂mu := by + intro n + let G := dyadicFiltration n ℱ + let X : ℕ → Omega → ℝ := fun k ↦ -M (dyadicGrid n k) + let S : Omega → ℕ∞ := fun omega ↦ dyadicCeilingIndex n (T omega) + have hsub : Submartingale X G mu := by + change Submartingale (-(fun k ↦ M (dyadicGrid n k))) G mu + exact (dyadicSample_supermartingale hM n).neg + have hS : IsStoppingTime G S := isStoppingTime_dyadicCeilingIndex hT n + have hSK : ∀ omega, S omega ≤ + (dyadicCeilingIndex n K : ℕ) := by + intro omega + change (dyadicCeilingIndex n (T omega) : ℕ∞) ≤ + (dyadicCeilingIndex n K : ℕ∞) + exact WithTop.coe_le_coe.mpr (Nat.ceil_le_ceil (mul_le_mul_of_nonneg_left + (NNReal.coe_le_coe.mpr (hTK omega)) (by positivity : (0 : ℝ) ≤ 2 ^ n))) + have hoptional := hsub.expected_stoppedValue_mono + (isStoppingTime_const G 0) hS (fun _ ↦ bot_le) hSK + change (∫ omega, -M (dyadicGrid n 0) omega ∂mu) ≤ + ∫ omega, -M (dyadicGrid n (dyadicCeilingIndex n (T omega))) omega ∂mu at hoptional + rw [show dyadicGrid n 0 = 0 by + apply NNReal.eq + simp only [dyadicGrid, Nat.cast_zero, zero_div, NNReal.coe_zero] + rfl] at hoptional + have hgrid : + (∫ omega, M (dyadicGrid n (dyadicCeilingIndex n (T omega))) omega ∂mu) ≤ + ∫ omega, M 0 omega ∂mu := by + simpa only [integral_neg, neg_le_neg_iff] using hoptional + calc + ∫ omega, M (dyadicCeiling n (T omega)) omega ∂mu = + ∫ omega, M (dyadicGrid n (dyadicCeilingIndex n (T omega))) omega ∂mu := by + refine integral_congr_ae (Eventually.of_forall fun omega ↦ ?_) + change M (dyadicCeiling n (T omega)) omega = + M (dyadicGrid n (dyadicCeilingIndex n (T omega))) omega + rw [dyadicGrid_ceilingIndex] + _ ≤ ∫ omega, M 0 omega ∂mu := hgrid + obtain ⟨C, hC⟩ := hbound (K + 1) + have hptw : ∀ᵐ omega ∂mu, Tendsto (fun n ↦ M (dyadicCeiling n (T omega)) omega) atTop + (𝓝 (M (T omega) omega)) := by + refine Eventually.of_forall fun omega ↦ ?_ + have hnbhd : Tendsto (fun n ↦ dyadicCeiling n (T omega)) atTop (𝓝[≥] (T omega)) := + tendsto_nhdsWithin_of_tendsto_nhds_of_eventually_within _ + (tendsto_dyadicCeiling (T omega)) + (Eventually.of_forall fun n ↦ Set.mem_Ici.mpr (le_dyadicCeiling n (T omega))) + exact Tendsto.comp (hright omega (T omega)) hnbhd + have hlim := tendsto_integral_of_dominated_convergence (μ := mu) (fun _ ↦ C) + (F := fun n omega ↦ M (dyadicCeiling n (T omega)) omega) + (f := fun omega ↦ M (T omega) omega) + (fun n ↦ (stronglyMeasurable_apply_of_finite_range hM.1 + (isStoppingTime_dyadicCeiling hT n) (hstopfin n)).aestronglyMeasurable) + (integrable_const C) + (fun n ↦ Eventually.of_forall fun omega ↦ + hC _ (dyadicCeiling_le_add_one n (hTK omega)) omega) + hptw + exact le_of_tendsto hlim (Eventually.of_forall hstep) + +/-- Uniformly bounded specialization of +`integral_stoppedValue_le_of_locallyBounded`. -/ +theorem integral_stoppedValue_le_of_le (hM : Supermartingale M ℱ mu) {C : ℝ} + (hC : ∀ (t : NNReal) (omega : Omega), ‖M t omega‖ ≤ C) + (hright : ∀ (omega : Omega) (v : NNReal), + ContinuousWithinAt (fun t : NNReal ↦ M t omega) (Set.Ici v) v) + {T : Omega → NNReal} + (hT : IsStoppingTime ℱ fun omega ↦ ((T omega : NNReal) : WithTop NNReal)) + {K : NNReal} (hTK : ∀ omega, T omega ≤ K) : + ∫ omega, M (T omega) omega ∂mu ≤ ∫ omega, M 0 omega ∂mu := + integral_stoppedValue_le_of_locallyBounded hM + (fun _ ↦ ⟨C, fun t _ omega ↦ hC t omega⟩) hright hT hTK + +/-- **Optional stopping at a bounded finite stopping time**, for a martingale that is bounded on +bounded time intervals and right continuous in time. + +This is obtained by applying the supermartingale inequality to `M` and `-M`. -/ +theorem integral_stoppedValue_eq_of_locallyBounded (hM : Martingale M ℱ mu) + (hbound : ∀ v : NNReal, ∃ C : ℝ, ∀ t ≤ v, ∀ omega, ‖M t omega‖ ≤ C) + (hright : ∀ (omega : Omega) (v : NNReal), + ContinuousWithinAt (fun t : NNReal ↦ M t omega) (Set.Ici v) v) + {T : Omega → NNReal} + (hT : IsStoppingTime ℱ fun omega ↦ ((T omega : NNReal) : WithTop NNReal)) + {K : NNReal} (hTK : ∀ omega, T omega ≤ K) : + ∫ omega, M (T omega) omega ∂mu = ∫ omega, M 0 omega ∂mu := by + apply le_antisymm + · exact integral_stoppedValue_le_of_locallyBounded hM.supermartingale hbound hright hT hTK + · have hnegBound : ∀ v : NNReal, ∃ C : ℝ, ∀ t ≤ v, ∀ omega, ‖-M t omega‖ ≤ C := by + intro v + obtain ⟨C, hC⟩ := hbound v + exact ⟨C, fun t ht omega ↦ by simpa only [norm_neg] using hC t ht omega⟩ + have hneg := integral_stoppedValue_le_of_locallyBounded hM.neg.supermartingale + hnegBound (fun omega v ↦ (hright omega v).neg) hT hTK + simpa only [Pi.neg_apply, integral_neg, neg_le_neg_iff] using hneg + +/-- **Optional stopping at a bounded finite stopping time**, for a uniformly bounded martingale +with right continuous orbits: the expectation of `M` at a stopping time bounded by a +deterministic horizon is its expectation at time `0`. -/ +theorem integral_stoppedValue_eq_of_le (hM : Martingale M ℱ mu) {C : ℝ} + (hC : ∀ (t : NNReal) (omega : Omega), ‖M t omega‖ ≤ C) + (hright : ∀ (omega : Omega) (v : NNReal), + ContinuousWithinAt (fun t : NNReal ↦ M t omega) (Set.Ici v) v) + {T : Omega → NNReal} + (hT : IsStoppingTime ℱ fun omega ↦ ((T omega : NNReal) : WithTop NNReal)) + {K : NNReal} (hTK : ∀ omega, T omega ≤ K) : + ∫ omega, M (T omega) omega ∂mu = ∫ omega, M 0 omega ∂mu := + integral_stoppedValue_eq_of_locallyBounded hM (fun _ ↦ ⟨C, fun t _ omega ↦ hC t omega⟩) hright + hT hTK + +end OptionalStopping + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Polish.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Polish.lean new file mode 100644 index 0000000000..ba39b3bbca --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Polish.lean @@ -0,0 +1,37 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +import Mathlib.Topology.ContinuousMap.SecondCountableSpace +import Mathlib.MeasureTheory.Constructions.Polish.Basic + +/-! +# Polish structure of continuous-path space + +For a complete separable metric state space, the compact-open topology on continuous paths is +Polish: it is second countable, and it is induced by the compact-convergence uniformity, which is +complete and countably generated because nonnegative time is locally compact and sigma-compact. +With the Borel sigma-algebra the path space is therefore a standard Borel space. + +This is ordinary topological infrastructure. It proves no probabilistic statement. +-/ + +namespace MarkovProcess +namespace ContinuousPath + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [SecondCountableTopology alpha] + +/-- Continuous-path space over a complete separable metric space is Polish. -/ +instance instPolishSpace : PolishSpace (ContinuousPath alpha) := inferInstance + +/-- With the Borel sigma-algebra, continuous-path space is a standard Borel space. -/ +theorem standardBorelSpace_borel : + @StandardBorelSpace (ContinuousPath alpha) (borel (ContinuousPath alpha)) := by + let : MeasurableSpace (ContinuousPath alpha) := borel (ContinuousPath alpha) + have : BorelSpace (ContinuousPath alpha) := ⟨rfl⟩ + infer_instance + +end ContinuousPath +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/RandomShiftMeasurability.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/RandomShiftMeasurability.lean new file mode 100644 index 0000000000..28d52088c0 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/RandomShiftMeasurability.lean @@ -0,0 +1,71 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +import Mathlib.Probability.Process.Stopping + +/-! +# Measurability of random shifts of continuous paths + +Shifting a continuous path by a Borel measurable random time, and evaluating it at that time, +are Borel measurable, because the deterministic shift and the evaluation are jointly continuous +in the time and the path. A finite `NNReal`-valued stopping time for the canonical filtration is +such a random time. No countable-range premise is used. + +This is ordinary measurability infrastructure. It proves no restart identity and no conditional +expectation formula; those are in `Trajectory/FellerStoppingRestart.lean` and +`Trajectory/FellerStoppingConditional.lean`. +-/ + +open MeasureTheory + +namespace MarkovProcess +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- Shifting by a Borel measurable random time is Borel measurable. -/ +theorem measurable_shift_of_measurable (T : ContinuousPath alpha → NNReal) + (hT : Measurable T) : + Measurable (fun omega ↦ shift (T omega) omega) := by + have hpair : Measurable (fun omega : ContinuousPath alpha ↦ (T omega, omega)) := + hT.prodMk measurable_id + exact (continuous_shift (alpha := alpha)).measurable.comp hpair + +variable [MeasurableSpace alpha] [BorelSpace alpha] + +/-- Evaluating a path at a Borel measurable random time is Borel measurable. -/ +theorem measurable_eval_of_measurable (T : ContinuousPath alpha → NNReal) + (hT : Measurable T) : + Measurable (fun omega : ContinuousPath alpha ↦ omega (T omega)) := by + have hpair : Measurable (fun omega : ContinuousPath alpha ↦ (omega, T omega)) := + measurable_id.prodMk hT + exact (ContinuousEval.continuous_eval (F := ContinuousPath alpha)).measurable.comp hpair + +/-- A finite stopping time for the canonical filtration is Borel measurable. -/ +theorem measurable_of_isStoppingTime (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) : + Measurable T := by + refine measurable_of_Iic fun i ↦ ?_ + have h := (canonicalFiltration (alpha := alpha)).le i _ (hT i) + simpa only [Set.preimage, Set.mem_Iic, WithTop.coe_le_coe] using h + +/-- Shifting by a finite stopping time for the canonical filtration is Borel measurable. -/ +theorem measurable_shift_stoppingTime (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) : + Measurable (fun omega ↦ shift (T omega) omega) := + measurable_shift_of_measurable T (measurable_of_isStoppingTime T hT) + +/-- The state at a finite stopping time for the canonical filtration is Borel measurable. -/ +theorem measurable_eval_stoppingTime_borel (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) : + Measurable (fun omega : ContinuousPath alpha ↦ omega (T omega)) := + measurable_eval_of_measurable T (measurable_of_isStoppingTime T hT) + +end ContinuousPath +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/RandomTimeCompactTestConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/RandomTimeCompactTestConvergence.lean new file mode 100644 index 0000000000..06532458d2 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/RandomTimeCompactTestConvergence.lean @@ -0,0 +1,86 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability + +/-! +# Dominated convergence for tests along random times + +This file records path-side dominated-convergence tools for a sequence of measurable random +times converging pointwise to a limiting random time. The measure is any finite measure on +continuous-path space; no Markov or kernel assumption is used. The deterministic-sequence +versions are in `ContinuousPathShiftCompactTestConvergence.lean`. +-/ + +open Filter MeasureTheory Topology +open scoped NNReal ZeroAtInfty CompactlySupported + +namespace MarkovProcess + +noncomputable section + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + +/-- Integrals of a bounded continuous state observable at pointwise convergent measurable random +times converge under any finite path measure. -/ +theorem tendsto_integral_continuousPath_eval_randomTime_of_tendsto + (mu : Measure (ContinuousPath alpha)) [IsFiniteMeasure mu] + (T : ℕ → ContinuousPath alpha → NNReal) (Tlim : ContinuousPath alpha → NNReal) + (hT : ∀ n, Measurable (T n)) + (hlim : ∀ omega, Tendsto (fun n ↦ T n omega) atTop (nhds (Tlim omega))) + (g : alpha → ℝ) (hg : Continuous g) (C : ℝ) (hgC : ∀ y, ‖g y‖ ≤ C) : + Tendsto (fun n ↦ ∫ omega, g (omega (T n omega)) ∂mu) atTop + (nhds (∫ omega, g (omega (Tlim omega)) ∂mu)) := by + apply tendsto_integral_filter_of_norm_le_const + · filter_upwards [] with n + exact ((hg.measurable.comp + (ContinuousPath.measurable_eval_of_measurable (T n) (hT n))).stronglyMeasurable + ).aestronglyMeasurable + · exact ⟨C, Filter.Eventually.of_forall fun n ↦ ae_of_all _ fun omega ↦ hgC _⟩ + · filter_upwards [] with omega + exact hg.continuousAt.tendsto.comp + (omega.continuous.continuousAt.tendsto.comp (hlim omega)) + +omit [MeasurableSpace alpha] [BorelSpace alpha] in +/-- Integrals of a compactly supported test of finitely many dense-time coordinates of the path +shifted by pointwise convergent measurable random times converge under any finite path +measure. -/ +theorem tendsto_integral_continuousPath_finiteDenseEvaluation_shift_randomTime_of_tendsto + (mu : Measure (ContinuousPath alpha)) [IsFiniteMeasure mu] + (T : ℕ → ContinuousPath alpha → NNReal) (Tlim : ContinuousPath alpha → NNReal) + (hT : ∀ n, Measurable (T n)) + (hlim : ∀ omega, Tendsto (fun n ↦ T n omega) atTop (nhds (Tlim omega))) + (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) : + Tendsto (fun n ↦ ∫ omega, f (fun j : J ↦ + omega (T n omega + DenseTime.castOrderEmbedding j)) ∂mu) atTop + (nhds (∫ omega, f (fun j : J ↦ + omega (Tlim omega + DenseTime.castOrderEmbedding j)) ∂mu)) := by + let f0 : C₀(J → alpha, ℝ) := PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f + have hcont : Continuous (fun p : NNReal × ContinuousPath alpha ↦ + f (fun j : J ↦ p.2 (p.1 + DenseTime.castOrderEmbedding j))) := by + refine f.continuous.comp (continuous_pi fun j ↦ ?_) + exact ContinuousEval.continuous_eval.comp + (continuous_snd.prodMk (continuous_fst.add continuous_const)) + apply tendsto_integral_filter_of_norm_le_const + · filter_upwards [] with n + exact (hcont.measurable.comp + ((hT n).prodMk measurable_id)).stronglyMeasurable.aestronglyMeasurable + · refine ⟨‖f0‖, Filter.Eventually.of_forall fun n ↦ ?_⟩ + filter_upwards [] with omega + simpa only [f0, PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap_apply, + Real.norm_eq_abs] using! f0.toBCF.norm_coe_le_norm + (fun j : J ↦ omega (T n omega + DenseTime.castOrderEmbedding j)) + · filter_upwards [] with omega + apply f.continuous.continuousAt.tendsto.comp + rw [tendsto_pi_nhds] + intro j + exact omega.continuous.continuousAt.tendsto.comp + ((hlim omega).add tendsto_const_nhds) + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/RelativeHitting.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/RelativeHitting.lean new file mode 100644 index 0000000000..5a2573e95f --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/RelativeHitting.lean @@ -0,0 +1,200 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop + +/-! +# Closed-set detection after a stopping time + +This file relativizes closed-set detection to the random compact interval between a stopping +time and a fixed deterministic horizon. The lower endpoint is truncated at the horizon, so it +is a bounded finite stopping time. Continuity reduces detection on that interval to its two +endpoints and the fixed enumeration of nonnegative rational times strictly between them. + +Public declarations: + +* `ContinuousPath.hitsSetBetween`; +* `ContinuousPath.measurableSet_hitsSetBetween`. +-/ + +open MeasureTheory Set +open scoped ENNReal NNReal + +namespace MarkovProcess + +noncomputable section + +namespace ContinuousPath + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +/-- The event that a path meets `F` between the stopping time `T` and the fixed horizon `t`. -/ +def hitsSetBetween (T : ContinuousPath alpha → ℝ≥0∞) (t : NNReal) (F : Set alpha) : + Set (ContinuousPath alpha) := + {omega | ∃ s : NNReal, T omega ≤ s ∧ s ≤ t ∧ omega s ∈ F} + +private def restrictIcc (u t : NNReal) (omega : ContinuousPath alpha) : + C(Set.Icc u t, alpha) where + toFun s := omega s + continuous_toFun := omega.continuous.comp continuous_subtype_val + +variable [SecondCountableTopology alpha] [MeasurableSpace alpha] [BorelSpace alpha] + +/-- Meeting a closed set between a stopping time and a fixed horizon is measurable in the raw +canonical filtration at that horizon. -/ +theorem measurableSet_hitsSetBetween + (T : ContinuousPath alpha → ℝ≥0∞) + (hT : IsStoppingTime (canonicalFiltration (alpha := alpha)) T) + (t : NNReal) (F : Set alpha) (hF : IsClosed F) : + MeasurableSet[canonicalFiltration (alpha := alpha) t] (hitsSetBetween T t F) := by + by_cases hFnonempty : F.Nonempty + swap + · have hFempty : F = ∅ := not_nonempty_iff_eq_empty.mp hFnonempty + have hevent : hitsSetBetween T t F = ∅ := by + rw [hFempty] + ext omega + simp only [hitsSetBetween, Set.mem_ofPred_eq, Set.notMem_empty, and_false, + exists_const] + rw [hevent] + exact @MeasurableSet.empty _ (canonicalFiltration (alpha := alpha) t) + let u : ContinuousPath alpha → NNReal := StoppingTime.truncTime T t + have huStop : IsStoppingTime (canonicalFiltration (alpha := alpha)) + (fun omega ↦ ((u omega : NNReal) : ℝ≥0∞)) := + StoppingTime.isStoppingTime_truncTime hT t + have hut : ∀ omega, u omega ≤ t := by + intro omega + apply WithTop.coe_le_coe.mp + exact (le_of_eq (StoppingTime.coe_truncTime T t omega)).trans (min_le_right _ _) + have huSpace : huStop.measurableSpace ≤ canonicalFiltration (alpha := alpha) t := + huStop.measurableSpace_le_of_le_const fun omega ↦ WithTop.coe_le_coe.mpr (hut omega) + have huMeas : Measurable[canonicalFiltration (alpha := alpha) t] + (fun omega ↦ ((u omega : NNReal) : ℝ≥0∞)) := + huStop.measurable.mono huSpace le_rfl + have hEvalU : Measurable[canonicalFiltration (alpha := alpha) t] + (fun omega : ContinuousPath alpha ↦ omega (u omega)) := + (measurable_eval_stoppingTime u huStop).mono huSpace le_rfl + have hDistU : Measurable[canonicalFiltration (alpha := alpha) t] + (fun omega : ContinuousPath alpha ↦ Metric.infDist (omega (u omega)) F) := by + let : MeasurableSpace (ContinuousPath alpha) := canonicalFiltration (alpha := alpha) t + exact hEvalU.infDist + have hEvalT : Measurable[canonicalFiltration (alpha := alpha) t] + (fun omega : ContinuousPath alpha ↦ omega t) := + measurable_coordinateProcess_canonicalFiltration t + have hDistT : Measurable[canonicalFiltration (alpha := alpha) t] + (fun omega : ContinuousPath alpha ↦ Metric.infDist (omega t) F) := by + let : MeasurableSpace (ContinuousPath alpha) := canonicalFiltration (alpha := alpha) t + exact hEvalT.infDist + let A : ℕ → Set (ContinuousPath alpha) := fun n ↦ + {omega | Metric.infDist (omega (u omega)) F < closedSetDetectionThreshold n} + let B : ℕ → Set (ContinuousPath alpha) := fun n ↦ + {omega | Metric.infDist (omega t) F < closedSetDetectionThreshold n} + let C : ℕ → ℕ → Set (ContinuousPath alpha) := fun n k ↦ + if hkt : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t then + {omega | u omega < DenseTime.castOrderEmbedding (DenseTime.enumeration k)} ∩ + {omega | Metric.infDist + (omega (DenseTime.castOrderEmbedding (DenseTime.enumeration k))) F < + closedSetDetectionThreshold n} + else ∅ + have hA : ∀ n, MeasurableSet[canonicalFiltration (alpha := alpha) t] (A n) := by + intro n + exact hDistU + (measurableSet_Iio : MeasurableSet (Set.Iio (closedSetDetectionThreshold n))) + have hB : ∀ n, MeasurableSet[canonicalFiltration (alpha := alpha) t] (B n) := by + intro n + exact hDistT + (measurableSet_Iio : MeasurableSet (Set.Iio (closedSetDetectionThreshold n))) + have hC : ∀ n k, MeasurableSet[canonicalFiltration (alpha := alpha) t] (C n k) := by + intro n k + dsimp only [C] + split_ifs with hkt + · have hConst : Measurable[canonicalFiltration (alpha := alpha) t] + (fun _ : ContinuousPath alpha ↦ + ((DenseTime.castOrderEmbedding (DenseTime.enumeration k) : NNReal) : ℝ≥0∞)) := + measurable_const + refine (show MeasurableSet[canonicalFiltration (alpha := alpha) t] + {omega | u omega < DenseTime.castOrderEmbedding (DenseTime.enumeration k)} by + simpa only [ENNReal.coe_lt_coe] using + measurableSet_lt huMeas hConst).inter ?_ + have hEvalQ : Measurable[canonicalFiltration (alpha := alpha) t] + (fun omega : ContinuousPath alpha ↦ + omega (DenseTime.castOrderEmbedding (DenseTime.enumeration k))) := + (measurable_coordinateProcess_canonicalFiltration + (DenseTime.castOrderEmbedding (DenseTime.enumeration k))).mono + (canonicalFiltration.mono hkt.le) le_rfl + let : MeasurableSpace (ContinuousPath alpha) := canonicalFiltration (alpha := alpha) t + exact hEvalQ.infDist + (measurableSet_Iio : MeasurableSet (Set.Iio (closedSetDetectionThreshold n))) + · exact @MeasurableSet.empty _ (canonicalFiltration (alpha := alpha) t) + have hevent : hitsSetBetween T t F = + {omega | T omega ≤ (t : ℝ≥0∞)} ∩ ⋂ n : ℕ, (A n ∪ B n ∪ ⋃ k : ℕ, C n k) := by + ext omega + simp only [hitsSetBetween, Set.mem_ofPred_eq, Set.mem_inter_iff, Set.mem_iInter, + Set.mem_union, Set.mem_iUnion] + constructor + · rintro ⟨s, hTs, hst, hsF⟩ + have hTt : T omega ≤ (t : ℝ≥0∞) := hTs.trans (by exact_mod_cast hst) + refine ⟨hTt, ?_⟩ + have hTne : T omega ≠ ⊤ := ne_top_of_le_ne_top (WithTop.coe_ne_top) hTt + lift T omega to NNReal using hTne with a ha + have has : a ≤ s := WithTop.coe_le_coe.mp hTs + have huEq : u omega = a := by + change (min (T omega) (t : ℝ≥0∞)).untopD 0 = a + rw [← ha] + have hmin : min (a : ℝ≥0∞) (t : ℝ≥0∞) = (a : ℝ≥0∞) := + min_eq_left (WithTop.coe_le_coe.mpr (has.trans hst)) + rw [hmin] + rfl + have hdetect := + (detectsClosedSetOnIcc_iff a t (has.trans hst) F hF (restrictIcc a t omega)).2 + ⟨⟨s, has, hst⟩, hsF⟩ + intro n + rcases hdetect.2 n with hu | ht | ⟨k, huk, hkt, hk⟩ + · refine Or.inl (Or.inl ?_) + change Metric.infDist (omega (u omega)) F < closedSetDetectionThreshold n + rw [huEq] + exact hu + · exact Or.inl (Or.inr (by simpa only [B] using! ht)) + · refine Or.inr ⟨k, ?_⟩ + simp only [C, dif_pos hkt, Set.mem_inter_iff, Set.mem_ofPred_eq] + exact ⟨huEq.symm ▸ huk, hk⟩ + · rintro ⟨hTt, hdetect⟩ + have hTne : T omega ≠ ⊤ := ne_top_of_le_ne_top (WithTop.coe_ne_top) hTt + lift T omega to NNReal using hTne with a ha + have hat : a ≤ t := WithTop.coe_le_coe.mp hTt + have huEq : u omega = a := by + change (min (T omega) (t : ℝ≥0∞)).untopD 0 = a + rw [← ha] + have hmin : min (a : ℝ≥0∞) (t : ℝ≥0∞) = (a : ℝ≥0∞) := + min_eq_left (WithTop.coe_le_coe.mpr hat) + rw [hmin] + rfl + have hdetector : + DetectsClosedSetOnIcc a t hat F (restrictIcc a t omega) := by + refine ⟨hFnonempty, fun n ↦ ?_⟩ + rcases hdetect n with (hu | ht) | ⟨k, hk⟩ + · refine Or.inl ?_ + change Metric.infDist (omega a) F < closedSetDetectionThreshold n + rw [← huEq] + exact hu + · exact Or.inr (Or.inl (by simpa only [B] using! ht)) + · dsimp only [C] at hk + split_ifs at hk with hkt + · refine Or.inr (Or.inr ⟨k, ?_, hkt, hk.2⟩) + rw [← huEq] + exact hk.1 + · exact (Set.notMem_empty omega hk).elim + obtain ⟨s, hsF⟩ := + (detectsClosedSetOnIcc_iff a t hat F hF (restrictIcc a t omega)).1 hdetector + refine ⟨s, WithTop.coe_le_coe.mpr s.property.1, s.property.2, hsF⟩ + rw [hevent] + exact (hT t).inter <| MeasurableSet.iInter fun n ↦ + ((hA n).union (hB n)).union (MeasurableSet.iUnion (hC n)) + +end ContinuousPath + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Sampling.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Sampling.lean new file mode 100644 index 0000000000..82932ec1b2 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Sampling.lean @@ -0,0 +1,175 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime + +/-! +# Uniform sampling of a continuous path + +A continuous path is uniformly continuous on every bounded time interval, so for each accuracy +`h > 0` a uniform partition of `[0, T]` fine enough makes every consecutive pair of samples closer +than `h` (`ContinuousPath.exists_uniform_sampling`). Three variants are recorded for use with the +exit time from a set `U`: when the horizon `T` is strictly before the exit time, every sample time +is too (`ContinuousPath.exists_uniform_sampling_lt_exitTime`), so the samples witness a family of +visited sets before the exit; and when the exit time is finite and positive there are times +strictly before it at which the path is within `h` of its exit position +(`ContinuousPath.exists_lt_exitTime_dist_coordinate_exitTime_lt`). For an open `U` the exit +position lies on `frontier U`, and the third variant carries that conclusion with it +(`ContinuousPath.exists_lt_exitTime_mem_frontier_dist_lt`): a positive exit time already forces +`omega 0 ∈ U`, the hypothesis of `ContinuousPath.coordinate_exitTime_mem_frontier`, so no extra +hypothesis is needed. The exit position is spelled `(exitTime U omega).toNNReal` throughout, as +in `Path/ExitTime.lean`; `ContinuousPath.untopD_exitTime` converts the `WithTop.untopD` spelling. + +No lattice, no covering family and no discrete geometry appears here: the sampling is purely +metric. +-/ + +open Set +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace ContinuousPath + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +/-- **Uniform sampling of a continuous path.** For every horizon `T` and every accuracy `h > 0` +there is a uniform partition of `[0, T]` into `M` parts along which consecutive samples of the +path are at distance less than `h`. -/ +theorem exists_uniform_sampling (omega : ContinuousPath alpha) (T : NNReal) (h : ℝ) (hh : 0 < h) : + ∃ M : ℕ, 0 < M ∧ ∀ k < M, + dist (omega ((k : NNReal) * T / (M : NNReal))) + (omega (((k : NNReal) + 1) * T / (M : NNReal))) < h := by + obtain ⟨delta, hdelta, hd⟩ := + Metric.uniformContinuousOn_iff.mp + (isCompact_Icc.uniformContinuousOn_of_continuous + (omega.continuous.continuousOn (s := Set.Icc (0 : NNReal) T))) h hh + obtain ⟨n, hn⟩ := exists_nat_gt ((T : ℝ) / delta) + refine ⟨n + 1, Nat.succ_pos n, fun k hk ↦ ?_⟩ + have hMR : (0 : ℝ) < ((n : ℝ) + 1) := by positivity + have hMN : (0 : NNReal) < ((n + 1 : ℕ) : NNReal) := by + rw [← NNReal.coe_pos] + push_cast + positivity + have hmem : ∀ j : ℕ, j ≤ n + 1 → + (j : NNReal) * T / ((n + 1 : ℕ) : NNReal) ∈ Set.Icc (0 : NNReal) T := by + intro j hj + refine ⟨zero_le, ?_⟩ + rw [div_le_iff₀ hMN] + calc + (j : NNReal) * T ≤ ((n + 1 : ℕ) : NNReal) * T := + mul_le_mul_left (Nat.cast_le.mpr hj) T + _ = T * ((n + 1 : ℕ) : NNReal) := mul_comm _ _ + have hstep : (T : ℝ) / ((n : ℝ) + 1) < delta := by + rw [div_lt_iff₀ hMR] + have hTn : (T : ℝ) < (n : ℝ) * delta := by + rw [div_lt_iff₀ hdelta] at hn + exact hn + calc + (T : ℝ) < (n : ℝ) * delta := hTn + _ ≤ delta * ((n : ℝ) + 1) := by + rw [mul_comm] + exact mul_le_mul_of_nonneg_left (by linarith only []) hdelta.le + have hdistR : dist ((k : NNReal) * T / ((n + 1 : ℕ) : NNReal)) + (((k : NNReal) + 1) * T / ((n + 1 : ℕ) : NNReal)) = (T : ℝ) / ((n : ℝ) + 1) := by + have hnonneg : (0 : ℝ) ≤ (T : ℝ) / ((n : ℝ) + 1) := by positivity + have hexpand : (k : ℝ) * (T : ℝ) / ((n : ℝ) + 1) - + ((k : ℝ) + 1) * (T : ℝ) / ((n : ℝ) + 1) = -((T : ℝ) / ((n : ℝ) + 1)) := by + field_simp + ring + rw [NNReal.dist_eq] + push_cast + rw [hexpand, abs_neg, abs_of_nonneg hnonneg] + refine hd _ (hmem k (by omega)) _ (?_) ?_ + · have : ((k : NNReal) + 1) = ((k + 1 : ℕ) : NNReal) := by push_cast; ring + rw [this] + exact hmem (k + 1) (by omega) + · rw [hdistR] + exact hstep + +/-- Sampling admissible before an exit: when the horizon lies strictly before the exit time from +`U`, so does every sample time of a uniform partition of `[0, T]`. -/ +theorem exists_uniform_sampling_lt_exitTime (U : Set alpha) (omega : ContinuousPath alpha) + (T : NNReal) (hT : (T : ℝ≥0∞) < exitTime U omega) (h : ℝ) (hh : 0 < h) : + ∃ M : ℕ, 0 < M ∧ + (∀ k ≤ M, (((k : NNReal) * T / (M : NNReal) : NNReal) : ℝ≥0∞) < exitTime U omega) ∧ + ∀ k < M, dist (omega ((k : NNReal) * T / (M : NNReal))) + (omega (((k : NNReal) + 1) * T / (M : NNReal))) < h := by + obtain ⟨M, hM, hsample⟩ := exists_uniform_sampling omega T h hh + refine ⟨M, hM, fun k hk ↦ ?_, hsample⟩ + have hMN : (0 : NNReal) < ((M : ℕ) : NNReal) := by + rw [← NNReal.coe_pos] + have : (0 : ℕ) < M := hM + push_cast + exact_mod_cast this + have hle : (k : NNReal) * T / (M : NNReal) ≤ T := by + rw [div_le_iff₀ hMN] + calc + (k : NNReal) * T ≤ ((M : ℕ) : NNReal) * T := mul_le_mul_left (Nat.cast_le.mpr hk) T + _ = T * ((M : ℕ) : NNReal) := mul_comm _ _ + exact lt_of_le_of_lt (by exact_mod_cast hle) hT + +/-- Approaching a finite exit position from inside: if the exit time from `U` is positive and +finite, then arbitrarily close to it, and strictly before it, the path is within `h` of its +position at the exit time. -/ +theorem exists_lt_exitTime_dist_coordinate_exitTime_lt (U : Set alpha) + (omega : ContinuousPath alpha) (hpos : 0 < exitTime U omega) (hfin : exitTime U omega ≠ ⊤) + (h : ℝ) (hh : 0 < h) : + ∃ T : NNReal, (T : ℝ≥0∞) < exitTime U omega ∧ + dist (omega T) (omega ((exitTime U omega).toNNReal)) < h := by + set tau : NNReal := (exitTime U omega).toNNReal with htau + have hcoe : ((tau : NNReal) : ℝ≥0∞) = exitTime U omega := by + rw [htau] + exact ENNReal.coe_toNNReal hfin + have htaupos : 0 < tau := by + rw [← ENNReal.coe_pos, hcoe] + exact hpos + obtain ⟨delta, hdelta, hd⟩ := + Metric.continuousAt_iff.mp (omega.continuous.continuousAt (x := tau)) h hh + set c : NNReal := min (Real.toNNReal (delta / 2)) (tau / 2) + have hcpos : 0 < c := by + refine lt_min ?_ ?_ + · rw [← NNReal.coe_pos, Real.coe_toNNReal _ (by positivity)] + positivity + · exact half_pos htaupos + have hcle : c ≤ tau := by + refine le_trans (min_le_right _ _) ?_ + rw [← NNReal.coe_le_coe] + push_cast + linarith only [tau.coe_nonneg] + refine ⟨tau - c, ?_, ?_⟩ + · rw [← hcoe, ENNReal.coe_lt_coe] + exact tsub_lt_self htaupos hcpos + · refine hd ?_ + rw [NNReal.dist_eq, NNReal.coe_sub hcle] + have hval : |(tau : ℝ) - (c : ℝ) - (tau : ℝ)| = (c : ℝ) := by + rw [show (tau : ℝ) - (c : ℝ) - (tau : ℝ) = -(c : ℝ) by ring, abs_neg, + abs_of_nonneg c.coe_nonneg] + rw [hval] + calc + (c : ℝ) ≤ ((Real.toNNReal (delta / 2) : NNReal) : ℝ) := by + exact_mod_cast min_le_left (Real.toNNReal (delta / 2)) (tau / 2) + _ = delta / 2 := Real.coe_toNNReal _ (by positivity) + _ < delta := by linarith only [hdelta] + +/-- Approaching the exit position on the frontier: for an open `U`, a positive finite exit time +is approached from strictly inside, and the position at the exit time lies on `frontier U`. This +is `ContinuousPath.exists_lt_exitTime_dist_coordinate_exitTime_lt` with the conclusion of +`ContinuousPath.coordinate_exitTime_mem_frontier` folded in; the hypothesis `omega 0 ∈ U` of the +latter comes from the positivity of the exit time. -/ +theorem exists_lt_exitTime_mem_frontier_dist_lt (U : Set alpha) (hU : IsOpen U) + (omega : ContinuousPath alpha) (hpos : 0 < exitTime U omega) (hfin : exitTime U omega ≠ ⊤) + (h : ℝ) (hh : 0 < h) : + ∃ T : NNReal, (T : ℝ≥0∞) < exitTime U omega ∧ + omega ((exitTime U omega).toNNReal) ∈ frontier U ∧ + dist (omega T) (omega ((exitTime U omega).toNNReal)) < h := by + obtain ⟨T, hT, hdist⟩ := exists_lt_exitTime_dist_coordinate_exitTime_lt U omega hpos hfin h hh + have h0 : omega 0 ∈ U := + mem_of_lt_exitTime U omega 0 (by simpa only [ENNReal.coe_zero] using hpos) + exact ⟨T, hT, coordinate_exitTime_mem_frontier U hU omega h0 hfin, hdist⟩ + +end ContinuousPath + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean new file mode 100644 index 0000000000..b14ac41e00 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean @@ -0,0 +1,94 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.Basic + +/-! +# Deterministic shifts of continuous paths + +This file defines translation by a fixed nonnegative time on canonical continuous-path space. +The shift is jointly continuous in the shift time and path for the compact-open topology. It also +records the corresponding deterministic relation between the canonical filtrations. + +No random-time shift, Markov property, strong Markov property, or Hunt-process assertion is made. +-/ + +open MeasureTheory + +namespace MarkovProcess +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- Translation of nonnegative time by `S`, as a continuous self-map of `NNReal`. -/ +def timeTranslation (S : NNReal) : C(NNReal, NNReal) where + toFun t := S + t + continuous_toFun := continuous_const.add continuous_id + +@[simp] +theorem timeTranslation_apply (S t : NNReal) : timeTranslation S t = S + t := rfl + +/-- Shift a continuous path forward by the deterministic time `S`. -/ +def shift (S : NNReal) (omega : ContinuousPath alpha) : ContinuousPath alpha := + omega.comp (timeTranslation S) + +@[simp] +theorem shift_apply (S t : NNReal) (omega : ContinuousPath alpha) : + shift S omega t = omega (S + t) := rfl + +@[simp] +theorem shift_zero (omega : ContinuousPath alpha) : shift 0 omega = omega := by + ext t + simp only [shift_apply, zero_add] + +theorem shift_add (S T : NNReal) (omega : ContinuousPath alpha) : + shift T (shift S omega) = shift (S + T) omega := by + ext t + simp only [shift_apply, add_assoc] + +/-- The family of time translations is continuous for the compact-open topology. -/ +theorem continuous_timeTranslation : Continuous (timeTranslation : NNReal → C(NNReal, NNReal)) := by + apply ContinuousMap.continuous_of_continuous_uncurry + exact continuous_fst.add continuous_snd + +/-- Deterministic path shifting is jointly continuous in the shift time and the path. -/ +theorem continuous_shift : + Continuous (fun p : NNReal × ContinuousPath alpha ↦ shift p.1 p.2) := by + exact ContinuousMap.continuous_comp'.comp + ((continuous_timeTranslation.comp continuous_fst).prodMk continuous_snd) + +/-- Shifting by a fixed deterministic time is continuous. -/ +theorem continuous_shift_fixed (S : NNReal) : + Continuous (shift S : ContinuousPath alpha → ContinuousPath alpha) := + continuous_shift.comp (continuous_const.prodMk continuous_id) + +/-- Shifting by a fixed deterministic time is Borel measurable. -/ +theorem measurable_shift_fixed (S : NNReal) : + Measurable[borel (ContinuousPath alpha), borel (ContinuousPath alpha)] + (shift S : ContinuousPath alpha → ContinuousPath alpha) := + (continuous_shift_fixed S).borel_measurable + +/-- A shifted event observable by shifted time `t` is observable by original time `S + t`. -/ +theorem measurable_shift_canonicalFiltration [MeasurableSpace alpha] [BorelSpace alpha] + (S t : NNReal) : + Measurable[canonicalFiltration (alpha := alpha) (S + t), + canonicalFiltration (alpha := alpha) t] + (shift S : ContinuousPath alpha → ContinuousPath alpha) := by + apply Measurable.of_comap_le + rw [canonicalFiltration, MeasurableSpace.comap_iSup] + rw [iSup_le_iff] + intro u + rw [MeasurableSpace.comap_comp] + have hfun : coordinateProcess (alpha := alpha) u ∘ shift S = + coordinateProcess (alpha := alpha) (S + u) := by + funext omega + exact shift_apply S u omega + rw [hfun] + exact le_iSup_of_le + (⟨S + u.1, by simpa only [add_comm] using! add_le_add_left u.2 S⟩ : + Set.Iic (S + t)) le_rfl + +end ContinuousPath +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/ShiftCompactTestConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/ShiftCompactTestConvergence.lean new file mode 100644 index 0000000000..2c5a56e9cb --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/ShiftCompactTestConvergence.lean @@ -0,0 +1,86 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals + +/-! +# Dominated convergence for shifted continuous-path tests + +This file records path-side dominated-convergence tools for deterministic times approached by +dense times. The measure is any finite measure on continuous-path space; no Markov or kernel +assumption is used. +-/ + +open Filter MeasureTheory Topology +open scoped NNReal ZeroAtInfty CompactlySupported + +namespace MarkovProcess + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [LocallyCompactSpace alpha] + +omit [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [LocallyCompactSpace alpha] in +/-- Integrals of a bounded continuous state observable along convergent continuous-path +coordinates converge under any finite path measure. -/ +theorem tendsto_integral_continuousPath_eval_of_tendsto + (mu : Measure (ContinuousPath alpha)) [IsFiniteMeasure mu] + (s : NNReal) (q : ℕ → DenseTime) + (hq : Tendsto (fun n ↦ DenseTime.castOrderEmbedding (q n)) atTop (nhds s)) + (g : alpha → ℝ) (hg : Continuous g) (C : ℝ) + (hgC : ∀ y, ‖g y‖ ≤ C) : + Tendsto + (fun n ↦ ∫ omega, g (omega (DenseTime.castOrderEmbedding (q n))) ∂mu) + atTop (nhds (∫ omega, g (omega s) ∂mu)) := by + apply tendsto_integral_filter_of_norm_le_const + · filter_upwards [] with n + exact (hg.comp (ContinuousPath.continuous_eval (alpha := alpha) + (DenseTime.castOrderEmbedding (q n)))).aestronglyMeasurable + · exact ⟨C, Filter.Eventually.of_forall fun n ↦ ae_of_all _ fun omega ↦ + hgC (omega (DenseTime.castOrderEmbedding (q n)))⟩ + · filter_upwards [] with omega + exact hg.continuousAt.tendsto.comp + (omega.continuous.continuousAt.tendsto.comp hq) + +omit [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [LocallyCompactSpace alpha] in +/-- Compact-test integrals of finitely many relative dense-time coordinates converge when the +deterministic shift times converge. The finite coordinate set may be empty. -/ +theorem tendsto_integral_continuousPath_finiteDenseEvaluation_shift + (mu : Measure (ContinuousPath alpha)) [IsFiniteMeasure mu] + (s : NNReal) (q : ℕ → DenseTime) + (hq : Tendsto (fun n ↦ DenseTime.castOrderEmbedding (q n)) atTop (nhds s)) + (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) : + Tendsto + (fun n ↦ ∫ omega, f (fun j : J ↦ + omega (DenseTime.castOrderEmbedding (q n) + + DenseTime.castOrderEmbedding j)) ∂mu) + atTop + (nhds (∫ omega, f (fun j : J ↦ + omega (s + DenseTime.castOrderEmbedding j)) ∂mu)) := by + let f₀ : C₀(J → alpha, ℝ) := + PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f + apply tendsto_integral_filter_of_norm_le_const + · filter_upwards [] with n + exact (f.continuous.comp (ContinuousPath.continuous_finiteEvaluation + (fun j : J ↦ DenseTime.castOrderEmbedding (q n) + + DenseTime.castOrderEmbedding j))).aestronglyMeasurable + · refine ⟨‖f₀‖, Filter.Eventually.of_forall fun n ↦ ?_⟩ + filter_upwards [] with omega + simpa only [f₀, PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap_apply, + Real.norm_eq_abs] using! f₀.toBCF.norm_coe_le_norm + (fun j : J ↦ omega (DenseTime.castOrderEmbedding (q n) + + DenseTime.castOrderEmbedding j)) + · filter_upwards [] with omega + apply f.continuous.continuousAt.tendsto.comp + rw [tendsto_pi_nhds] + intro j + exact omega.continuous.continuousAt.tendsto.comp + (hq.add tendsto_const_nhds) + +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/StoppedValueMeasurability.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/StoppedValueMeasurability.lean new file mode 100644 index 0000000000..504f974058 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/StoppedValueMeasurability.lean @@ -0,0 +1,51 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +import Mathlib.Probability.Process.Stopping + +/-! +# Measurability of the state at a stopping time + +The coordinate process of canonical continuous-path space is adapted to the canonical filtration +and continuous in time, hence progressively measurable. Consequently the state at a finite +stopping time is measurable for the stopped sigma-algebra. No countable-range premise is used. +Plain Borel measurability of the same map, under weaker assumptions, is in +`Path/RandomShiftMeasurability.lean`. + +This is ordinary measurability infrastructure. It proves no restart identity and no conditional +expectation formula; those are in `Trajectory/FellerStoppingRestart.lean` and +`Trajectory/FellerStoppingConditional.lean`. +-/ + +open MeasureTheory + +namespace MarkovProcess +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] [TopologicalSpace.PseudoMetrizableSpace alpha] + [SecondCountableTopology alpha] [MeasurableSpace alpha] [BorelSpace alpha] + +/-- The coordinate process is adapted to the canonical filtration. -/ +theorem adapted_coordinateProcess : + StronglyAdapted (canonicalFiltration (alpha := alpha)) (coordinateProcess (alpha := alpha)) := + fun t ↦ (measurable_coordinateProcess_canonicalFiltration (alpha := alpha) t).stronglyMeasurable + +/-- The coordinate process is progressively measurable for the canonical filtration. -/ +theorem progMeasurable_coordinateProcess : + IsStronglyProgressive (canonicalFiltration (alpha := alpha)) + (coordinateProcess (alpha := alpha)) := + adapted_coordinateProcess.isStronglyProgressive_of_continuous fun omega ↦ omega.continuous + +/-- The state at a finite stopping time is measurable for the stopped sigma-algebra. -/ +theorem measurable_eval_stoppingTime (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) : + Measurable[hT.measurableSpace] (fun omega ↦ omega (T omega)) := by + have h := measurable_stoppedValue (progMeasurable_coordinateProcess (alpha := alpha)) hT + simpa only [stoppedValue, coordinateProcess_apply] using! h + +end ContinuousPath +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Stopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Stopping.lean new file mode 100644 index 0000000000..a78487eb42 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Stopping.lean @@ -0,0 +1,76 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.Basic + +/-! +# Deterministic stopping of continuous paths + +This file defines stopping a continuous path at a fixed deterministic time. It proves only +topological and Borel-measurability properties of this operation; it introduces no stopping +times or stochastic laws. +-/ + +namespace MarkovProcess + +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- Clamp nonnegative time at the fixed deterministic time `T`. -/ +def clampTime (T : NNReal) : C(NNReal, NNReal) where + toFun t := min t T + continuous_toFun := continuous_id.min continuous_const + +@[simp] +theorem clampTime_apply (T t : NNReal) : clampTime T t = min t T := rfl + +/-- A continuous path stopped at the fixed deterministic time `T`. -/ +def stoppedPath (T : NNReal) (omega : ContinuousPath alpha) : ContinuousPath alpha := + omega.comp (clampTime T) + +@[simp] +theorem stoppedPath_apply (T : NNReal) (omega : ContinuousPath alpha) (t : NNReal) : + stoppedPath T omega t = omega (min t T) := + rfl + +@[simp] +theorem stoppedPath_apply_of_le (T : NNReal) (omega : ContinuousPath alpha) (t : NNReal) + (ht : t ≤ T) : stoppedPath T omega t = omega t := by + rw [stoppedPath_apply, min_eq_left ht] + +@[simp] +theorem stoppedPath_apply_of_ge (T : NNReal) (omega : ContinuousPath alpha) (t : NNReal) + (ht : T ≤ t) : stoppedPath T omega t = omega T := by + rw [stoppedPath_apply, min_eq_right ht] + +/-- Every path stopped at a deterministic time is continuous in time. -/ +theorem continuous_stoppedPath (T : NNReal) (omega : ContinuousPath alpha) : + Continuous (stoppedPath T omega) := + (stoppedPath T omega).continuous + +/-- Stopping at a fixed deterministic time is continuous in the compact-open topology. -/ +theorem continuous_stoppedPath_operator (T : NNReal) : + Continuous (stoppedPath (alpha := alpha) T) := + ContinuousMap.continuous_precomp (clampTime T) + +/-- Stopping at a fixed deterministic time is Borel measurable. -/ +theorem measurable_stoppedPath_operator (T : NNReal) : + @Measurable (ContinuousPath alpha) (ContinuousPath alpha) + (borel (ContinuousPath alpha)) (borel (ContinuousPath alpha)) + (stoppedPath (alpha := alpha) T) := + (continuous_stoppedPath_operator T).borel_measurable + +/-- Successive deterministic stops combine by taking the earlier stopping time. -/ +@[simp] +theorem stoppedPath_stoppedPath (S T : NNReal) (omega : ContinuousPath alpha) : + stoppedPath S (stoppedPath T omega) = stoppedPath (min S T) omega := by + apply ContinuousMap.ext + intro t + simp only [stoppedPath_apply, min_assoc] + +end ContinuousPath + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/StoppingTimeDyadicCeiling.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/StoppingTimeDyadicCeiling.lean new file mode 100644 index 0000000000..f30cefce5d --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/StoppingTimeDyadicCeiling.lean @@ -0,0 +1,177 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Probability.Process.Stopping +import Mathlib.Topology.Instances.NNReal.Lemmas + +/-! +# Dyadic ceiling approximation of finite stopping times + +The level-`n` dyadic ceiling of a nonnegative time is the least point of the grid `2⁻ⁿ ℕ` that is +at least the time. Composed with a finite `NNReal`-valued stopping time it produces stopping +times with countable range that decrease to the original time. This is ordinary stopping-time +infrastructure and proves no restart identity; the restart identity obtained from this +approximation is in `Trajectory/FellerStoppingRestart.lean`. +-/ + +open MeasureTheory Filter Topology +open scoped NNReal + +namespace MarkovProcess + +noncomputable section + +/-- The level-`n` dyadic ceiling of a nonnegative real time. -/ +def dyadicCeiling (n : ℕ) (t : NNReal) : NNReal := + ⟨(⌈(2 ^ n : ℝ) * (t : ℝ)⌉₊ : ℝ) / 2 ^ n, by positivity⟩ + +/-- The level-`n` dyadic floor of a nonnegative real time. -/ +def dyadicFloor (n : ℕ) (t : NNReal) : NNReal := + ⟨(⌊(2 ^ n : ℝ) * (t : ℝ)⌋₊ : ℝ) / 2 ^ n, by positivity⟩ + +/-- The real coercion of a dyadic ceiling is its defining quotient. -/ +private theorem coe_dyadicCeiling (n : ℕ) (t : NNReal) : + ((dyadicCeiling n t : NNReal) : ℝ) = (⌈(2 ^ n : ℝ) * (t : ℝ)⌉₊ : ℝ) / 2 ^ n := rfl + +/-- The real coercion of a dyadic floor is its defining quotient. -/ +private theorem coe_dyadicFloor (n : ℕ) (t : NNReal) : + ((dyadicFloor n t : NNReal) : ℝ) = (⌊(2 ^ n : ℝ) * (t : ℝ)⌋₊ : ℝ) / 2 ^ n := rfl + +/-- The level-`n` dyadic ceiling is at least the time it approximates. -/ +theorem le_dyadicCeiling (n : ℕ) (t : NNReal) : t ≤ dyadicCeiling n t := by + rw [← NNReal.coe_le_coe, coe_dyadicCeiling, le_div_iff₀ (by positivity : (0 : ℝ) < 2 ^ n)] + calc (t : ℝ) * 2 ^ n = (2 ^ n : ℝ) * (t : ℝ) := by ring + _ ≤ (⌈(2 ^ n : ℝ) * (t : ℝ)⌉₊ : ℝ) := Nat.le_ceil _ + +/-- The level-`n` dyadic floor is at most the time it approximates. -/ +theorem dyadicFloor_le (n : ℕ) (t : NNReal) : dyadicFloor n t ≤ t := by + rw [← NNReal.coe_le_coe, coe_dyadicFloor, div_le_iff₀ (by positivity : (0 : ℝ) < 2 ^ n)] + calc (⌊(2 ^ n : ℝ) * (t : ℝ)⌋₊ : ℝ) ≤ (2 ^ n : ℝ) * (t : ℝ) := Nat.floor_le (by positivity) + _ = (t : ℝ) * 2 ^ n := by ring + +/-- The level-`n` dyadic ceiling overshoots by at most one grid step. -/ +theorem dyadicCeiling_le_add (n : ℕ) (t : NNReal) : + dyadicCeiling n t ≤ t + (2 ^ n : NNReal)⁻¹ := by + have h2 : (0 : ℝ) < 2 ^ n := by positivity + have hinv : ((2 : ℝ) ^ n)⁻¹ * 2 ^ n = 1 := inv_mul_cancel₀ (ne_of_gt h2) + rw [← NNReal.coe_le_coe, coe_dyadicCeiling, NNReal.coe_add, NNReal.coe_inv, NNReal.coe_pow, + NNReal.coe_ofNat, div_le_iff₀ h2] + calc (⌈(2 ^ n : ℝ) * (t : ℝ)⌉₊ : ℝ) ≤ (2 ^ n : ℝ) * (t : ℝ) + 1 := + (Nat.ceil_lt_add_one (by positivity)).le + _ = ((t : ℝ) + ((2 : ℝ) ^ n)⁻¹) * 2 ^ n := by rw [add_mul, hinv]; ring + +/-- The ceiling comparison rewritten as an inequality between natural indices. -/ +private theorem dyadicCeiling_le_iff_nat (n : ℕ) (t i : NNReal) : + dyadicCeiling n t ≤ i ↔ ⌈(2 ^ n : ℝ) * (t : ℝ)⌉₊ ≤ ⌊(2 ^ n : ℝ) * (i : ℝ)⌋₊ := by + have h2 : (0 : ℝ) < 2 ^ n := by positivity + have hfloor : ⌈(2 ^ n : ℝ) * (t : ℝ)⌉₊ ≤ ⌊(2 ^ n : ℝ) * (i : ℝ)⌋₊ ↔ + ((⌈(2 ^ n : ℝ) * (t : ℝ)⌉₊ : ℕ) : ℝ) ≤ (2 ^ n : ℝ) * (i : ℝ) := + Nat.le_floor_iff (by positivity) + rw [← NNReal.coe_le_coe, coe_dyadicCeiling, div_le_iff₀ h2, hfloor, + mul_comm ((2 : ℝ) ^ n) (i : ℝ)] + +/-- The floor comparison rewritten as the same inequality between natural indices. -/ +private theorem le_dyadicFloor_iff_nat (n : ℕ) (t i : NNReal) : + t ≤ dyadicFloor n i ↔ ⌈(2 ^ n : ℝ) * (t : ℝ)⌉₊ ≤ ⌊(2 ^ n : ℝ) * (i : ℝ)⌋₊ := by + have h2 : (0 : ℝ) < 2 ^ n := by positivity + rw [← NNReal.coe_le_coe, coe_dyadicFloor, le_div_iff₀ h2, Nat.ceil_le, + mul_comm ((2 : ℝ) ^ n) (t : ℝ)] + +/-- The dyadic ceiling lies below a time exactly when the time's dyadic floor lies above. -/ +theorem dyadicCeiling_le_iff (n : ℕ) (t i : NNReal) : + dyadicCeiling n t ≤ i ↔ t ≤ dyadicFloor n i := + (dyadicCeiling_le_iff_nat n t i).trans (le_dyadicFloor_iff_nat n t i).symm + +/-- Refining the dyadic level decreases the ceiling. -/ +theorem antitone_dyadicCeiling (t : NNReal) : Antitone fun n ↦ dyadicCeiling n t := by + refine antitone_nat_of_succ_le fun n ↦ ?_ + show dyadicCeiling (n + 1) t ≤ dyadicCeiling n t + have hceil : ⌈(2 : ℝ) ^ (n + 1) * (t : ℝ)⌉₊ ≤ 2 * ⌈(2 : ℝ) ^ n * (t : ℝ)⌉₊ := by + rw [Nat.ceil_le] + push_cast + calc (2 : ℝ) ^ (n + 1) * (t : ℝ) = 2 * ((2 : ℝ) ^ n * (t : ℝ)) := by ring + _ ≤ 2 * (⌈(2 : ℝ) ^ n * (t : ℝ)⌉₊ : ℝ) := by gcongr; exact Nat.le_ceil _ + have hceilR : ((⌈(2 : ℝ) ^ (n + 1) * (t : ℝ)⌉₊ : ℕ) : ℝ) ≤ + 2 * ((⌈(2 : ℝ) ^ n * (t : ℝ)⌉₊ : ℕ) : ℝ) := by exact_mod_cast hceil + rw [← NNReal.coe_le_coe, coe_dyadicCeiling, coe_dyadicCeiling, + div_le_div_iff₀ (by positivity) (by positivity)] + calc ((⌈(2 : ℝ) ^ (n + 1) * (t : ℝ)⌉₊ : ℕ) : ℝ) * 2 ^ n + ≤ (2 * ((⌈(2 : ℝ) ^ n * (t : ℝ)⌉₊ : ℕ) : ℝ)) * 2 ^ n := by gcongr + _ = ((⌈(2 : ℝ) ^ n * (t : ℝ)⌉₊ : ℕ) : ℝ) * 2 ^ (n + 1) := by ring + +/-- The dyadic ceilings of a fixed time converge to that time. -/ +theorem tendsto_dyadicCeiling (t : NNReal) : + Tendsto (fun n ↦ dyadicCeiling n t) atTop (𝓝 t) := by + have hhalf : ((2 : NNReal))⁻¹ < 1 := by + rw [← NNReal.coe_lt_coe, NNReal.coe_inv, NNReal.coe_ofNat, NNReal.coe_one] + norm_num + have hinv : Tendsto (fun n : ℕ ↦ (2 ^ n : NNReal)⁻¹) atTop (𝓝 0) := by + simpa only [inv_pow] using NNReal.tendsto_pow_atTop_nhds_zero_of_lt_one hhalf + have hupper : Tendsto (fun n : ℕ ↦ t + (2 ^ n : NNReal)⁻¹) atTop (𝓝 t) := by + simpa only [add_zero] using tendsto_const_nhds.add hinv + exact tendsto_of_tendsto_of_tendsto_of_le_of_le tendsto_const_nhds hupper + (fun n ↦ le_dyadicCeiling n t) (fun n ↦ dyadicCeiling_le_add n t) + +/-- The level-`n` dyadic grid point with index `k`. -/ +def dyadicGrid (n k : ℕ) : NNReal := ⟨(k : ℝ) / 2 ^ n, by positivity⟩ + +/-- The grid index of the level-`n` dyadic ceiling. -/ +def dyadicCeilingIndex (n : ℕ) (t : NNReal) : ℕ := + ⌈(2 ^ n : ℝ) * (t : ℝ)⌉₊ + +/-- A dyadic ceiling is the grid point at its ceiling index. -/ +theorem dyadicGrid_ceilingIndex (n : ℕ) (t : NNReal) : + dyadicGrid n (dyadicCeilingIndex n t) = dyadicCeiling n t := + rfl + +/-- The dyadic grid is monotone in its index. -/ +theorem monotone_dyadicGrid (n : ℕ) : Monotone (dyadicGrid n) := by + intro k l hkl + rw [← NNReal.coe_le_coe] + exact div_le_div_of_nonneg_right (Nat.cast_le.mpr hkl) (by positivity) + +/-- The dyadic grid is strictly monotone in its index. -/ +theorem strictMono_dyadicGrid (n : ℕ) : StrictMono (dyadicGrid n) := by + intro k l hkl + rw [← NNReal.coe_lt_coe] + exact div_lt_div_of_pos_right (Nat.cast_lt.mpr hkl) (by positivity) + +/-- Each dyadic level has only countably many ceiling values. -/ +theorem countable_range_dyadicCeiling (n : ℕ) : (Set.range (dyadicCeiling n)).Countable := by + refine (Set.countable_range (dyadicGrid n)).mono ?_ + rintro x ⟨t, rfl⟩ + exact ⟨⌈(2 ^ n : ℝ) * (t : ℝ)⌉₊, rfl⟩ + +variable {Omega : Type*} {m : MeasurableSpace Omega} + +/-- The dyadic ceiling of any time-valued map has countable range. -/ +theorem countable_range_dyadicCeiling_comp (n : ℕ) (T : Omega → NNReal) : + (Set.range fun omega ↦ dyadicCeiling n (T omega)).Countable := by + refine (countable_range_dyadicCeiling n).mono ?_ + rintro x ⟨omega, rfl⟩ + exact ⟨T omega, rfl⟩ + +/-- The dyadic ceiling of a time-valued map dominates it pointwise. -/ +theorem le_dyadicCeiling_comp (n : ℕ) (T : Omega → NNReal) : + T ≤ fun omega ↦ dyadicCeiling n (T omega) := fun omega ↦ le_dyadicCeiling n (T omega) + +/-- The dyadic ceilings of a time-valued map converge pointwise to it. -/ +theorem tendsto_dyadicCeiling_comp (T : Omega → NNReal) (omega : Omega) : + Tendsto (fun n ↦ dyadicCeiling n (T omega)) atTop (𝓝 (T omega)) := + tendsto_dyadicCeiling (T omega) + +/-- The dyadic ceiling of a finite stopping time is a stopping time for the same filtration. -/ +theorem isStoppingTime_dyadicCeiling {f : Filtration NNReal m} {T : Omega → NNReal} + (hT : IsStoppingTime f (fun omega ↦ (T omega : WithTop NNReal))) (n : ℕ) : + IsStoppingTime f (fun omega ↦ (dyadicCeiling n (T omega) : WithTop NNReal)) := by + intro i + refine (f.mono (dyadicFloor_le n i) _ (hT (dyadicFloor n i))).congr ?_ + ext omega + simp only [Set.mem_ofPred_eq, WithTop.coe_le_coe] + exact (dyadicCeiling_le_iff n (T omega) i).symm + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart.lean new file mode 100644 index 0000000000..aa6b02197c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart.lean @@ -0,0 +1,21 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation +import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov +import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure +import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture +import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint + +/-! +# Restart + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalExpectation.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalExpectation.lean new file mode 100644 index 0000000000..a3d0bfe06d --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalExpectation.lean @@ -0,0 +1,81 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.MeasureTheory.Function.ConditionalExpectation.Basic +import Mathlib.Probability.Kernel.Composition.IntegralCompProd + +/-! +# Conditional expectation from restricted restart laws + +This file records a generic measure-theoretic bridge from an event-restricted future-law identity +to a conditional-expectation identity. The restart hypothesis is required after restriction to +every event in the conditioning measurable space. Its specialization to the whole space alone is +only an unconditional distributional identity and is not enough for this conclusion. + +No stochastic process, Markov property, or path-space construction is asserted here. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess + +noncomputable section + +variable {Omega beta E : Type*} {m : MeasurableSpace Omega} + {mOmega : MeasurableSpace Omega} {mBeta : MeasurableSpace beta} + [NormedAddCommGroup E] [NormedSpace Real E] [CompleteSpace E] + +/-- If the law of `Y` after restriction to every conditioning event is obtained by mixing +`kappa`, then integrating any bounded strongly measurable observable against `kappa` gives the +corresponding conditional expectation. -/ +theorem condExp_comp_ae_eq_integral_kernel_of_restrict_map + (mu : @Measure Omega mOmega) [IsFiniteMeasure mu] + (kappa : @Kernel Omega beta mOmega mBeta) [IsMarkovKernel kappa] + (Y : Omega → beta) (hY : @Measurable Omega beta mOmega mBeta Y) + (hm : m ≤ mOmega) + (hJoint : ∀ A : Set Omega, MeasurableSet[m] A → + (mu.restrict A).map Y = kappa ∘ₘ (mu.restrict A)) + (F : beta → E) (hF : StronglyMeasurable F) + (hFm : StronglyMeasurable[m] (fun omega ↦ ∫ y, F y ∂kappa omega)) + (C : Real) (hFC : ∀ y, ‖F y‖ ≤ C) : + mu[fun omega ↦ F (Y omega)|m] =ᵐ[mu] + fun omega ↦ ∫ y, F y ∂kappa omega := by + have hfMeas : AEStronglyMeasurable (fun omega ↦ F (Y omega)) mu := + (hF.comp_measurable hY).aestronglyMeasurable + have hfInt : Integrable (fun omega ↦ F (Y omega)) mu := + Integrable.of_bound hfMeas C (ae_of_all _ fun omega ↦ hFC (Y omega)) + have hgMeas : AEStronglyMeasurable[m] + (fun omega ↦ ∫ y, F y ∂kappa omega) mu := + hFm.aestronglyMeasurable + refine (ae_eq_condExp_of_forall_setIntegral_eq + (m := m) (m₀ := mOmega) (μ := mu) hm hfInt ?_ ?_ hgMeas).symm + · intro A _hA _hmuA + exact Integrable.of_bound + (hF.integral_kernel.aestronglyMeasurable.restrict) + C (ae_of_all _ fun omega ↦ by + simpa only [measureReal_def, measure_univ, ENNReal.toReal_one, mul_one] using + norm_integral_le_of_norm_le_const + (μ := kappa omega) (ae_of_all _ hFC)) + · intro A hA _hmuA + have hFA : Integrable F ((mu.restrict A).map Y) := by + rw [integrable_map_measure hF.aestronglyMeasurable hY.aemeasurable] + exact hfInt.restrict + have hFAComp : Integrable F (kappa ∘ₘ (mu.restrict A)) := by + rw [← hJoint A hA] + exact hFA + rw [Measure.comp_eq_comp_const_apply] at hFAComp + have hIntegralComp := Kernel.integral_comp hFAComp + calc + ∫ omega in A, (∫ y, F y ∂kappa omega) ∂mu = + ∫ omega, (∫ y, F y ∂kappa omega) ∂(mu.restrict A) := rfl + _ = ∫ y, F y ∂(kappa ∘ₘ (mu.restrict A)) := + by simpa only [Kernel.const_apply] using! hIntegralComp.symm + _ = ∫ y, F y ∂((mu.restrict A).map Y) := by rw [hJoint A hA] + _ = ∫ omega, F (Y omega) ∂(mu.restrict A) := by + rw [integral_map hY.aemeasurable hF.aestronglyMeasurable] + _ = ∫ omega in A, F (Y omega) ∂mu := rfl + +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalMarkov.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalMarkov.lean new file mode 100644 index 0000000000..b4463aca01 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalMarkov.lean @@ -0,0 +1,67 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation +import LeanPool.MarkovProcess.MarkovProcess.Path.Shift + +/-! +# Deterministic-time conditional restart on continuous paths + +This file specializes the generic conditional-expectation bridge to canonical continuous-path +space. The required input is the full future restart identity after restriction to every event in +the canonical filtration at the restart time. An unconditional shifted-law identity is only the +special case of the input for the whole path space and does not imply the result below. + +The theorem is a conditional API: it does not prove its restricted restart-law hypothesis and does +not by itself associate a Markov or Hunt process with a transition semigroup. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace ContinuousPath + +noncomputable section + +variable {alpha E : Type*} [TopologicalSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] + [NormedAddCommGroup E] [NormedSpace Real E] [CompleteSpace E] + +/-- An event-restricted whole-future restart identity gives the deterministic-time conditional +Markov formula for every bounded strongly measurable functional of the shifted path. -/ +theorem condExp_shift_ae_eq_integral_pathKernel_of_restrict_map + (Q : Kernel alpha (ContinuousPath alpha)) [IsMarkovKernel Q] + (x : alpha) (S : NNReal) + (hRestart : ∀ A : Set (ContinuousPath alpha), + MeasurableSet[canonicalFiltration (alpha := alpha) S] A → + ((Q x).restrict A).map (shift S) = + Kernel.comap Q (coordinateProcess (alpha := alpha) S) + (measurable_coordinateProcess S) ∘ₘ ((Q x).restrict A)) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : Real) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + (Q x)[fun omega ↦ F (shift S omega)|canonicalFiltration (alpha := alpha) S] =ᵐ[Q x] + fun omega ↦ ∫ eta, F eta ∂Q (omega S) := by + let kappa : Kernel (ContinuousPath alpha) (ContinuousPath alpha) := + Kernel.comap Q (coordinateProcess (alpha := alpha) S) + (measurable_coordinateProcess S) + let : IsMarkovKernel kappa := by + dsimp only [kappa] + infer_instance + have hFm : StronglyMeasurable[canonicalFiltration (alpha := alpha) S] + (fun omega ↦ ∫ eta, F eta ∂kappa omega) := by + have hBase : StronglyMeasurable[canonicalFiltration (alpha := alpha) S] + (fun omega ↦ ∫ eta, F eta ∂Q (omega S)) := + hF.integral_kernel.comp_measurable + (measurable_coordinateProcess_canonicalFiltration S) + simpa only [kappa, Kernel.comap_apply, coordinateProcess_apply] using hBase + have h := condExp_comp_ae_eq_integral_kernel_of_restrict_map + (Q x) kappa (shift S) (measurable_shift_fixed S) + ((canonicalFiltration (alpha := alpha)).le S) + (by simpa only [kappa] using hRestart) F hF hFm C hFC + simpa only [kappa, Kernel.comap_apply, coordinateProcess_apply] using h + +end +end ContinuousPath +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestart.lean new file mode 100644 index 0000000000..11cb30473d --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestart.lean @@ -0,0 +1,189 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov +import Mathlib.MeasureTheory.Function.ConditionalExpectation.Indicator +import Mathlib.Probability.Process.Stopping + +/-! +# Conditional restart at countable-valued stopping times + +This file upgrades deterministic-time conditional restart identities to a finite-valued or, +more generally, countable-valued finite stopping time. It is ordinary conditional probability +infrastructure: the deterministic-time restart identity is a hypothesis here, proved for the +continuous-path process in `Trajectory/FellerRestrictedRestart.lean`. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace ContinuousPath + +noncomputable section + +variable {alpha E : Type*} [TopologicalSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] + [NormedAddCommGroup E] [NormedSpace Real E] [CompleteSpace E] + +private theorem condExp_congr_ae_restrict + {Omega : Type*} {m mOmega : MeasurableSpace Omega} {mu : Measure Omega} + {f g : Omega → E} {s : Set Omega} (hm : m ≤ mOmega) + (hs : MeasurableSet[m] s) (hf : Integrable f mu) (hg : Integrable g mu) + (hfg : f =ᵐ[mu.restrict s] g) : + mu[f|m] =ᵐ[mu.restrict s] mu[g|m] := by + have hind : s.indicator f =ᵐ[mu] s.indicator g := by + rw [Filter.EventuallyEq, ae_restrict_iff' (hm _ hs)] at hfg + filter_upwards [hfg] with omega homega + by_cases hts : omega ∈ s + · simpa only [Set.indicator_of_mem hts] using homega hts + · simp only [Set.indicator_of_notMem hts] + have hce := condExp_congr_ae (m := m) hind + have hfInd := condExp_indicator (m := m) hf hs + have hgInd := condExp_indicator (m := m) hg hs + rw [Filter.EventuallyEq, ae_restrict_iff' (hm _ hs)] + filter_upwards [hfInd, hce, hgInd] with omega hfomega hceomega hgomega homega + simpa only [Set.indicator_of_mem homega] using hfomega.symm.trans (hceomega.trans hgomega) + +private theorem measurable_shift_stoppingTime + (tau : ContinuousPath alpha → NNReal) + (htau : IsStoppingTime (canonicalFiltration (alpha := alpha)) + (fun omega ↦ (tau omega : WithTop NNReal))) + (htauRange : (Set.range tau).Countable) : + Measurable (fun omega ↦ shift (tau omega) omega) := by + intro B hB + have hpre : (fun omega ↦ shift (tau omega) omega) ⁻¹' B = + ⋃ S ∈ Set.range tau, {omega | tau omega = S} ∩ shift S ⁻¹' B := by + ext omega + simp only [Set.mem_preimage, Set.mem_iUnion, Set.mem_range, Set.mem_inter_iff, + Set.mem_ofPred_eq] + exact ⟨fun homega ↦ ⟨tau omega, ⟨omega, rfl⟩, rfl, homega⟩, + fun ⟨S, _, htauS, homega⟩ ↦ by simpa only [htauS] using homega⟩ + rw [hpre] + refine MeasurableSet.biUnion htauRange fun S _ ↦ ?_ + refine ((canonicalFiltration (alpha := alpha)).le S _ ?_).inter + ((measurable_shift_fixed S) hB) + have hcoercedRange : (Set.range fun omega ↦ (tau omega : WithTop NNReal)).Countable := by + rw [show Set.range (fun omega ↦ (tau omega : WithTop NNReal)) = + (fun t : NNReal ↦ (t : WithTop NNReal)) '' Set.range tau by + ext i + simp only [Set.mem_range, Set.mem_image] + constructor + · rintro ⟨omega, rfl⟩ + exact ⟨tau omega, ⟨omega, rfl⟩, rfl⟩ + · rintro ⟨S, ⟨omega, rfl⟩, rfl⟩ + exact ⟨omega, rfl⟩] + exact htauRange.image fun t : NNReal ↦ (t : WithTop NNReal) + simpa only [WithTop.coe_eq_coe] using + htau.measurableSet_eq_of_countable_range hcoercedRange S + +/-- Deterministic-time conditional Markov formulas on the range of a countable-valued finite +stopping time patch to a conditional restart identity. Countability and the stopping-time +property make the random shift measurable by gluing its deterministic restrictions along the +measurable level sets of `tau`. -/ +theorem condExp_shift_stoppingTime_ae_eq_integral_pathKernel_of_restart_on_range + (Q : Kernel alpha (ContinuousPath alpha)) [IsMarkovKernel Q] + (x : alpha) (tau : ContinuousPath alpha → NNReal) + (htau : IsStoppingTime (canonicalFiltration (alpha := alpha)) + (fun omega ↦ (tau omega : WithTop NNReal))) + (htauRange : (Set.range tau).Countable) + (hRestart : ∀ S ∈ Set.range tau, ∀ A : Set (ContinuousPath alpha), + MeasurableSet[canonicalFiltration (alpha := alpha) S] A → + ((Q x).restrict A).map (shift S) = + Kernel.comap Q (coordinateProcess (alpha := alpha) S) + (measurable_coordinateProcess S) ∘ₘ ((Q x).restrict A)) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : Real) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + (Q x)[fun omega ↦ F (shift (tau omega) omega)|htau.measurableSpace] =ᵐ[Q x] + fun omega ↦ ∫ eta, F eta ∂Q (omega (tau omega)) := by + let tauTop : ContinuousPath alpha → WithTop NNReal := + fun omega ↦ (tau omega : WithTop NNReal) + have htauTopRange : (Set.range tauTop).Countable := + by + rw [show Set.range tauTop = + (fun t : NNReal ↦ (t : WithTop NNReal)) '' Set.range tau by + ext i + simp only [Set.mem_range, tauTop, Set.mem_image] + constructor + · rintro ⟨omega, rfl⟩ + exact ⟨tau omega, ⟨omega, rfl⟩, rfl⟩ + · rintro ⟨S, ⟨omega, rfl⟩, rfl⟩ + exact ⟨omega, rfl⟩] + exact htauRange.image fun t : NNReal ↦ (t : WithTop NNReal) + have huniv : Set.univ = ⋃ i ∈ Set.range tauTop, {omega | tauTop omega = i} := by + ext omega + simp only [Set.mem_univ, Set.mem_range, Set.iUnion_exists, Set.iUnion_iUnion_eq', + Set.mem_iUnion, Set.mem_ofPred_eq, exists_apply_eq_apply'] + have hRandomShiftMeas : Measurable (fun omega ↦ shift (tau omega) omega) := + measurable_shift_stoppingTime tau htau htauRange + have hRandomInt : Integrable (fun omega ↦ F (shift (tau omega) omega)) (Q x) := + Integrable.of_bound + (hF.comp_measurable hRandomShiftMeas).aestronglyMeasurable C + (ae_of_all _ fun omega ↦ hFC (shift (tau omega) omega)) + nth_rw 1 [← @Measure.restrict_univ (ContinuousPath alpha) _ (Q x)] + rw [huniv, ae_eq_restrict_biUnion_iff _ htauTopRange] + intro i hi + have hiTop : i ≠ ⊤ := by + rintro rfl + obtain ⟨omega, homega⟩ := hi + simp only [tauTop, WithTop.coe_ne_top] at homega + lift i to NNReal using hiTop with S + have hLevel : MeasurableSet[canonicalFiltration (alpha := alpha) S] + {omega | tauTop omega = S} := + htau.measurableSet_eq_of_countable_range htauTopRange S + have hSRange : S ∈ Set.range tau := by + obtain ⟨omega, homega⟩ := hi + exact ⟨omega, WithTop.coe_eq_coe.mp homega⟩ + have hDet := condExp_shift_ae_eq_integral_pathKernel_of_restrict_map + Q x S (hRestart S hSRange) F hF C hFC + have hDetInt : Integrable (fun omega ↦ F (shift S omega)) (Q x) := + Integrable.of_bound + (hF.comp_measurable (measurable_shift_fixed S)).aestronglyMeasurable C + (ae_of_all _ fun omega ↦ hFC (shift S omega)) + have hLocalInput : + (fun omega ↦ F (shift (tau omega) omega)) =ᵐ[(Q x).restrict {omega | tauTop omega = S}] + fun omega ↦ F (shift S omega) := by + rw [Filter.EventuallyEq, ae_restrict_iff' + ((canonicalFiltration (alpha := alpha)).le S _ hLevel)] + exact Filter.Eventually.of_forall fun omega homega ↦ by + simp only [Set.mem_ofPred_eq, tauTop, WithTop.coe_eq_coe] at homega + rw [homega] + have hLocalOutput : + (fun omega ↦ ∫ eta, F eta ∂Q (omega S)) =ᵐ[(Q x).restrict {omega | tauTop omega = S}] + fun omega ↦ ∫ eta, F eta ∂Q (omega (tau omega)) := by + rw [Filter.EventuallyEq, ae_restrict_iff' + ((canonicalFiltration (alpha := alpha)).le S _ hLevel)] + exact Filter.Eventually.of_forall fun omega homega ↦ by + simp only [Set.mem_ofPred_eq, tauTop, WithTop.coe_eq_coe] at homega + rw [homega] + exact + (condExp_stopping_time_ae_eq_restrict_eq_of_countable_range + (μ := Q x) (f := fun omega ↦ F (shift (tau omega) omega)) htau htauTopRange S).trans + ((condExp_congr_ae_restrict (E := E) + ((canonicalFiltration (alpha := alpha)).le S) hLevel hRandomInt hDetInt hLocalInput).trans + (hDet.restrict.trans hLocalOutput)) + +/-- Deterministic-time conditional Markov formulas patch to a countable-valued finite stopping +time. This backward-compatible form asks for the deterministic formula at every finite time. -/ +theorem condExp_shift_stoppingTime_ae_eq_integral_pathKernel + (Q : Kernel alpha (ContinuousPath alpha)) [IsMarkovKernel Q] + (x : alpha) (tau : ContinuousPath alpha → NNReal) + (htau : IsStoppingTime (canonicalFiltration (alpha := alpha)) + (fun omega ↦ (tau omega : WithTop NNReal))) + (htauRange : (Set.range tau).Countable) + (hRestart : ∀ (S : NNReal) (A : Set (ContinuousPath alpha)), + MeasurableSet[canonicalFiltration (alpha := alpha) S] A → + ((Q x).restrict A).map (shift S) = + Kernel.comap Q (coordinateProcess (alpha := alpha) S) + (measurable_coordinateProcess S) ∘ₘ ((Q x).restrict A)) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : Real) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + (Q x)[fun omega ↦ F (shift (tau omega) omega)|htau.measurableSpace] =ᵐ[Q x] + fun omega ↦ ∫ eta, F eta ∂Q (omega (tau omega)) := by + exact condExp_shift_stoppingTime_ae_eq_integral_pathKernel_of_restart_on_range + Q x tau htau htauRange (fun S _ ↦ hRestart S) F hF C hFC + +end +end ContinuousPath +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestartMeasure.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestartMeasure.lean new file mode 100644 index 0000000000..1f16544ec4 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestartMeasure.lean @@ -0,0 +1,122 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability + +/-! +# Measure-level restart at countable-range stopping times + +Deterministic-time restricted restart identities at the attained times of a countable-range +finite stopping time patch to the measure-level identity at that stopping time: restricting the +path law to an event in the stopped sigma-algebra and shifting by the stopping time gives the +path kernel restarted from the state at the stopping time. The proof decomposes the event over +the countable level sets of the stopping time. + +This is ordinary conditional infrastructure. The restart hypothesis is an assumption here; it +is proved for the continuous-path process in `Trajectory/FellerRestrictedRestart.lean`. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + +/-- Restricted restart at every attained deterministic time gives restricted restart at a +countable-range finite stopping time, as an identity of measures. -/ +theorem restrict_map_shift_stoppingTime_eq_pathKernel_comp_of_restart_on_range + (Q : Kernel alpha (ContinuousPath alpha)) + (x : alpha) (tau : ContinuousPath alpha → NNReal) + (htau : IsStoppingTime (canonicalFiltration (alpha := alpha)) + (fun omega ↦ (tau omega : WithTop NNReal))) + (htauRange : (Set.range tau).Countable) + (hRestart : ∀ S ∈ Set.range tau, ∀ A : Set (ContinuousPath alpha), + MeasurableSet[canonicalFiltration (alpha := alpha) S] A → + ((Q x).restrict A).map (shift S) = + Kernel.comap Q (coordinateProcess (alpha := alpha) S) + (measurable_coordinateProcess S) ∘ₘ ((Q x).restrict A)) : + ∀ A : Set (ContinuousPath alpha), MeasurableSet[htau.measurableSpace] A → + ((Q x).restrict A).map (fun omega ↦ shift (tau omega) omega) = + Kernel.comap Q (fun omega ↦ omega (tau omega)) + (measurable_eval_stoppingTime_borel tau htau) ∘ₘ ((Q x).restrict A) := by + classical + intro A hA + have : Countable (Set.range tau) := htauRange.to_subtype + have hcoercedRange : (Set.range fun omega ↦ (tau omega : WithTop NNReal)).Countable := by + refine (htauRange.image (fun t : NNReal ↦ (t : WithTop NNReal))).mono ?_ + rintro i ⟨omega, rfl⟩ + exact ⟨tau omega, ⟨omega, rfl⟩, rfl⟩ + have hYmeas : Measurable (fun omega : ContinuousPath alpha ↦ shift (tau omega) omega) := + measurable_shift_stoppingTime tau htau + set lev : (Set.range tau) → Set (ContinuousPath alpha) := + fun S ↦ A ∩ {omega | tau omega = (S : NNReal)} with hlev + have hlevF : ∀ S : Set.range tau, + MeasurableSet[canonicalFiltration (alpha := alpha) (S : NNReal)] (lev S) := by + intro S + have h1 := hA.2 ((S : NNReal)) + have h2 : MeasurableSet[canonicalFiltration (alpha := alpha) (S : NNReal)] + {omega | (tau omega : WithTop NNReal) = ((S : NNReal) : WithTop NNReal)} := + htau.measurableSet_eq_of_countable_range hcoercedRange (S : NNReal) + have hset : lev S = + (A ∩ {omega | (tau omega : WithTop NNReal) ≤ ((S : NNReal) : WithTop NNReal)}) ∩ + {omega | (tau omega : WithTop NNReal) = ((S : NNReal) : WithTop NNReal)} := by + ext omega + simp only [hlev, Set.mem_inter_iff, Set.mem_ofPred_eq, WithTop.coe_eq_coe, + WithTop.coe_le_coe] + exact ⟨fun h ↦ ⟨⟨h.1, h.2.le⟩, h.2⟩, fun h ↦ ⟨h.1.1, h.2⟩⟩ + rw [hset] + exact h1.inter h2 + have hlevAmb : ∀ S : Set.range tau, MeasurableSet (lev S) := fun S ↦ + (canonicalFiltration (alpha := alpha)).le (S : NNReal) _ (hlevF S) + have hdisj : Pairwise (Function.onFun Disjoint lev) := by + intro S S' hSS' + refine Set.disjoint_left.mpr fun omega homega homega' ↦ hSS' ?_ + simp only [hlev, Set.mem_inter_iff, Set.mem_ofPred_eq] at homega homega' + exact Subtype.ext (by rw [← homega.2, ← homega'.2]) + have hunion : ⋃ S : Set.range tau, lev S = A := by + ext omega + simp only [hlev, Set.mem_iUnion, Set.mem_inter_iff, Set.mem_ofPred_eq] + exact ⟨fun ⟨_, h, _⟩ ↦ h, fun h ↦ ⟨⟨tau omega, ⟨omega, rfl⟩⟩, h, rfl⟩⟩ + ext B hB + rw [Measure.map_apply hYmeas hB, + Measure.bind_apply hB (Kernel.aemeasurable _), + Measure.restrict_apply (hYmeas hB)] + have hLHS : ((fun omega : ContinuousPath alpha ↦ shift (tau omega) omega) ⁻¹' B) ∩ A = + ⋃ S : Set.range tau, (((shift (S : NNReal)) ⁻¹' B) ∩ lev S) := by + rw [← hunion] + ext omega + simp only [Set.mem_inter_iff, Set.mem_iUnion, Set.mem_preimage, hlev, Set.mem_ofPred_eq] + constructor + · rintro ⟨hB', S, hA', hS⟩ + exact ⟨S, by rw [← hS]; exact hB', hA', hS⟩ + · rintro ⟨S, hB', hA', hS⟩ + exact ⟨by rw [hS]; exact hB', S, hA', hS⟩ + rw [hLHS, measure_iUnion (fun S S' hSS' ↦ ((hdisj hSS').mono + Set.inter_subset_right Set.inter_subset_right)) + (fun S ↦ (measurable_shift_fixed (S : NNReal) hB).inter (hlevAmb S))] + have hRHS : ∫⁻ omega, (Kernel.comap Q (fun omega ↦ omega (tau omega)) + (measurable_eval_stoppingTime_borel tau htau)) omega B ∂((Q x).restrict A) = + ∑' S : Set.range tau, ∫⁻ omega in lev S, Q (omega (tau omega)) B ∂(Q x) := by + simp only [Kernel.comap_apply] + show ∫⁻ omega in A, Q (omega (tau omega)) B ∂(Q x) = _ + rw [← hunion, lintegral_iUnion hlevAmb hdisj] + rw [hRHS] + refine tsum_congr fun S ↦ ?_ + have hres := congrArg (fun rho : Measure (ContinuousPath alpha) ↦ rho B) + (hRestart (S : NNReal) S.2 (lev S) (hlevF S)) + simp only [Measure.map_apply (measurable_shift_fixed (S : NNReal)) hB, + Measure.restrict_apply (measurable_shift_fixed (S : NNReal) hB), + Measure.bind_apply hB (Kernel.aemeasurable _), Kernel.comap_apply, + coordinateProcess_apply] at hres + rw [hres] + refine setLIntegral_congr_fun (hlevAmb S) fun omega homega ↦ ?_ + simp only [hlev, Set.mem_inter_iff, Set.mem_ofPred_eq] at homega + rw [homega.2] + +end ContinuousPath +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/FinitePastRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/FinitePastRestart.lean new file mode 100644 index 0000000000..fa11a385bc --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/FinitePastRestart.lean @@ -0,0 +1,112 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification + +/-! +# Identifying joint laws of a finite past and a continuous future + +A kernel whose values consist of a finite-coordinate past and a continuous future path is +determined by all finite coordinate marginals which retain coordinates from both pieces. This is +the uniqueness step needed to upgrade finite-dimensional restart identities to a whole-future +joint-law factorization. It does not assert that any particular stochastic process has those +finite-dimensional identities. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace Kernel + +noncomputable section + +variable {index alpha beta : Type*} [TopologicalSpace alpha] [T2Space alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [MeasurableSpace beta] + +variable [StandardBorelSpace (ContinuousPath alpha)] + [MeasurableSpace.CountablySeparated (DenseTime → alpha)] + +/-- Encode a finite-coordinate past and the dense restriction of a continuous future as one path +indexed by the disjoint union of the past and future coordinate types. -/ +def finitePastDenseFuture + (z : (index → alpha) × ContinuousPath alpha) : index ⊕ DenseTime → alpha + | Sum.inl i => z.1 i + | Sum.inr t => ContinuousPath.denseRestriction z.2 t + +omit [T2Space alpha] [StandardBorelSpace (ContinuousPath alpha)] + [MeasurableSpace.CountablySeparated (DenseTime → alpha)] in +theorem measurable_finitePastDenseFuture : + Measurable (finitePastDenseFuture (index := index) (alpha := alpha)) := by + rw [measurable_pi_iff] + rintro (i | t) + · exact (measurable_pi_apply i).comp measurable_fst + · exact (measurable_pi_apply t).comp + (ContinuousPath.measurable_denseRestriction.comp measurable_snd) + +private def finitePastContinuousFuture + (default : ContinuousPath alpha) (z : index ⊕ DenseTime → alpha) : + (index → alpha) × ContinuousPath alpha := + (fun i ↦ z (Sum.inl i), + ContinuousPath.continuousExtension default (fun t ↦ z (Sum.inr t))) + +private theorem measurable_finitePastContinuousFuture (default : ContinuousPath alpha) : + Measurable (finitePastContinuousFuture (index := index) (alpha := alpha) default) := by + apply Measurable.prodMk + · exact measurable_pi_iff.mpr fun i ↦ measurable_pi_apply (Sum.inl i) + · exact ContinuousPath.measurable_continuousExtension default |>.comp + (measurable_pi_iff.mpr fun t ↦ measurable_pi_apply (Sum.inr t)) + +omit [MeasurableSpace alpha] [BorelSpace alpha] + [StandardBorelSpace (ContinuousPath alpha)] + [MeasurableSpace.CountablySeparated (DenseTime → alpha)] in +private theorem finitePastContinuousFuture_comp_finitePastDenseFuture + (default : ContinuousPath alpha) : + finitePastContinuousFuture (index := index) default ∘ + finitePastDenseFuture (index := index) (alpha := alpha) = id := by + funext z + apply Prod.ext + · funext i + rfl + · exact ContinuousPath.continuousExtension_denseRestriction default z.2 + +/-- Two finite kernels on a finite-past/continuous-future space agree if every joint finite +coordinate restriction agrees. The finite set may contain coordinates from both the past and +future summands; retaining only future coordinates would not determine their dependence. -/ +theorem eq_of_map_finitePastDenseFutureRestriction_eq + (default : ContinuousPath alpha) + (kappa eta : Kernel beta ((index → alpha) × ContinuousPath alpha)) + [IsFiniteKernel kappa] + (h : ∀ I : Finset (index ⊕ DenseTime), + kappa.map (I.restrict ∘ finitePastDenseFuture) = + eta.map (I.restrict ∘ finitePastDenseFuture)) : + kappa = eta := by + have hDense : + kappa.map finitePastDenseFuture = eta.map finitePastDenseFuture := by + apply eq_of_map_finiteRestriction_eq + intro I + rw [← Kernel.map_comp_right kappa measurable_finitePastDenseFuture + (Finset.measurable_restrict I), + ← Kernel.map_comp_right eta measurable_finitePastDenseFuture + (Finset.measurable_restrict I)] + exact h I + calc + kappa = (kappa.map finitePastDenseFuture).map + (finitePastContinuousFuture (index := index) default) := by + rw [← Kernel.map_comp_right] + · rw [finitePastContinuousFuture_comp_finitePastDenseFuture, Kernel.map_id] + · exact measurable_finitePastDenseFuture + · exact measurable_finitePastContinuousFuture default + _ = (eta.map finitePastDenseFuture).map + (finitePastContinuousFuture (index := index) default) := by rw [hDense] + _ = eta := by + rw [← Kernel.map_comp_right] + · rw [finitePastContinuousFuture_comp_finitePastDenseFuture, Kernel.map_id] + · exact measurable_finitePastDenseFuture + · exact measurable_finitePastContinuousFuture default + +end +end Kernel +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/MixedPastFuture.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/MixedPastFuture.lean new file mode 100644 index 0000000000..e3cda96174 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/MixedPastFuture.lean @@ -0,0 +1,1122 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +import Mathlib.Data.Finset.Sum +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback + +/-! +# Mixed past-future coordinates and the cut factorization + +This file merges the following former modules, one section each: + +* `MixedPastFutureCoordinates`: Finite coordinates mixing a rational past and shifted future +* `MixedPastFutureCutCoordinates`: Finite mixed coordinates split at their rational terminal time +* `MixedPastFutureCutFactorization`: Factoring finite mixed past/future coordinates at a rational cut +-/ + +namespace MarkovProcess + +section MixedPastFutureCoordinates + +open MeasureTheory + + +noncomputable section + +namespace MixedPastFuture + +/-- Past labels occurring in a finite mixed-coordinate set, viewed as dense absolute times. -/ +def pastFinset (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) : Finset DenseTime := + I.toLeft.map + ⟨(fun r ↦ r.1), fun _ _ h ↦ Subtype.ext h⟩ + +/-- Future labels occurring in a finite mixed-coordinate set. -/ +def futureFinset (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) : Finset DenseTime := + I.toRight + +@[simp] +theorem mem_pastFinset (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (r : DenseTime) : + r ∈ pastFinset S I ↔ ∃ h : r ≤ S, Sum.inl ⟨r, h⟩ ∈ I := by + rw [pastFinset, Finset.mem_map] + constructor + · rintro ⟨t, ht, htr⟩ + subst r + refine ⟨t.property, ?_⟩ + exact Finset.mem_toLeft.mp ht + · rintro ⟨hrS, hrI⟩ + exact ⟨⟨r, hrS⟩, Finset.mem_toLeft.mpr hrI, rfl⟩ + +@[simp] +theorem mem_futureFinset (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) (r : DenseTime) : + r ∈ futureFinset S I ↔ Sum.inr r ∈ I := by + exact Finset.mem_toRight + +/-- The finite set of absolute dense times observed by a mixed past/future coordinate set. -/ +def absoluteFinset (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) : + Finset DenseTime := + pastFinset S I ∪ DenseTime.addFinset S (futureFinset S I) + +@[simp] +theorem mem_absoluteFinset (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (r : DenseTime) : + r ∈ absoluteFinset S I ↔ + (∃ h : r ≤ S, Sum.inl ⟨r, h⟩ ∈ I) ∨ + ∃ t ∈ futureFinset S I, S + t = r := by + rw [absoluteFinset, Finset.mem_union, mem_pastFinset, DenseTime.mem_addFinset] + +/-- Send a mixed label to the absolute dense time which it observes. This map need not be +injective: the terminal past label and future zero both map to `S`. -/ +def absoluteTime (S : DenseTime) : Set.Iic S ⊕ DenseTime → DenseTime + | Sum.inl r => r.1 + | Sum.inr t => S + t + +@[simp] +theorem absoluteTime_inl (S : DenseTime) (r : Set.Iic S) : + absoluteTime S (Sum.inl r) = r := rfl + +@[simp] +theorem absoluteTime_inr (S t : DenseTime) : + absoluteTime S (Sum.inr t) = S + t := rfl + +@[simp] +theorem absoluteTime_terminal_eq_zeroFuture (S : DenseTime) : + absoluteTime S (Sum.inl ⟨S, show S ≤ S from le_rfl⟩) = + absoluteTime S (Sum.inr 0) := by + simp only [absoluteTime_inl, absoluteTime_inr, add_zero] + +/-- Every label in `I` has its absolute time in `absoluteFinset S I`. -/ +def absoluteIndex (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) (i : I) : + absoluteFinset S I := by + refine ⟨absoluteTime S i, ?_⟩ + cases hi : i.1 with + | inl r => + have hir : Sum.inl r ∈ I := by simpa only [hi] using i.property + change r.1 ∈ pastFinset S I ∪ DenseTime.addFinset S (futureFinset S I) + apply Finset.mem_union_left + rw [pastFinset, Finset.mem_map] + exact ⟨r, Finset.mem_toLeft.mpr hir, rfl⟩ + | inr t => + have hit : Sum.inr t ∈ I := by simpa only [hi] using i.property + apply Finset.mem_union_right + rw [DenseTime.mem_addFinset] + exact ⟨t, Finset.mem_toRight.mpr hit, rfl⟩ + +@[simp] +theorem absoluteIndex_val (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) (i : I) : + (absoluteIndex S I i : DenseTime) = absoluteTime S i := rfl + +/-- The physical nonnegative-real times corresponding to a finite mixed-coordinate set. -/ +def absolutePhysicalFinset (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) : + Finset NNReal := + SubMarkovKernelSemigroup.denseTimePhysicalSet (absoluteFinset S I) + +/-- The physical-time coordinate selected by a mixed label. -/ +def absolutePhysicalIndex (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) (i : I) : + absolutePhysicalFinset S I := + DenseTime.physicalSetEquiv (absoluteFinset S I) (absoluteIndex S I i) + +@[simp] +theorem absolutePhysicalIndex_val (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) (i : I) : + (absolutePhysicalIndex S I i : NNReal) = + DenseTime.castOrderEmbedding (absoluteTime S i) := rfl + +/-- Pull physical absolute-time coordinates back to their mixed labels. This merely duplicates a +coordinate when past terminal time and future zero both occur. -/ +def pullbackAbsolutePhysical {alpha : Type*} (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) + (path : absolutePhysicalFinset S I → alpha) : I → alpha := + fun i ↦ path (absolutePhysicalIndex S I i) + +@[simp] +theorem pullbackAbsolutePhysical_apply {alpha : Type*} (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) + (path : absolutePhysicalFinset S I → alpha) (i : I) : + pullbackAbsolutePhysical S I path i = path (absolutePhysicalIndex S I i) := rfl + +variable {alpha : Type*} [MeasurableSpace alpha] + +/-- Pullback from absolute physical coordinates to mixed labels is measurable. -/ +theorem measurable_pullbackAbsolutePhysical (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + Measurable (pullbackAbsolutePhysical (alpha := alpha) S I) := by + rw [measurable_pi_iff] + intro i + exact measurable_pi_apply (absolutePhysicalIndex S I i) + +end MixedPastFuture + +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- The rational past through `S` and the rational coordinates of the future shifted at `S`, +combined into a single sum-indexed path. -/ +def mixedPastShiftedCoordinates (S : DenseTime) (omega : ContinuousPath alpha) : + Set.Iic S ⊕ DenseTime → alpha + | Sum.inl r => omega (DenseTime.castOrderEmbedding r) + | Sum.inr t => denseRestriction (shift (DenseTime.castOrderEmbedding S) omega) t + +@[simp] +theorem mixedPastShiftedCoordinates_inl (S : DenseTime) (omega : ContinuousPath alpha) + (r : Set.Iic S) : + mixedPastShiftedCoordinates S omega (Sum.inl r) = + omega (DenseTime.castOrderEmbedding r) := rfl + +@[simp] +theorem mixedPastShiftedCoordinates_inr (S t : DenseTime) (omega : ContinuousPath alpha) : + mixedPastShiftedCoordinates S omega (Sum.inr t) = + omega (DenseTime.castOrderEmbedding (S + t)) := by + simp only [mixedPastShiftedCoordinates, denseRestriction_apply, shift_apply, + DenseTime.castOrderEmbedding_add] + +/-- Mixed shifted coordinates depend only on the corresponding absolute dense time. -/ +theorem mixedPastShiftedCoordinates_eq_absoluteTime (S : DenseTime) + (omega : ContinuousPath alpha) (i : Set.Iic S ⊕ DenseTime) : + mixedPastShiftedCoordinates S omega i = + omega (DenseTime.castOrderEmbedding (MixedPastFuture.absoluteTime S i)) := by + rcases i with r | t + · rfl + · exact mixedPastShiftedCoordinates_inr S t omega + +/-- Restricting the mixed rational past and shifted future is evaluation on the one finite set of +absolute physical times followed by the canonical (possibly noninjective) coordinate pullback. -/ +theorem restrict_mixedPastShiftedCoordinates (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) (omega : ContinuousPath alpha) : + I.restrict (mixedPastShiftedCoordinates S omega) = + MixedPastFuture.pullbackAbsolutePhysical S I + (fun t : MixedPastFuture.absolutePhysicalFinset S I ↦ omega t) := by + funext i + change mixedPastShiftedCoordinates S omega i = + omega (MixedPastFuture.absolutePhysicalIndex S I i) + rw [mixedPastShiftedCoordinates_eq_absoluteTime] + exact congrArg omega (MixedPastFuture.absolutePhysicalIndex_val S I i).symm + +variable [MeasurableSpace alpha] [BorelSpace alpha] + +/-- The mixed rational-past/shifted-future coordinate map is Borel measurable. -/ +theorem measurable_mixedPastShiftedCoordinates (S : DenseTime) : + Measurable (mixedPastShiftedCoordinates (alpha := alpha) S) := by + rw [measurable_pi_iff] + rintro (r | t) + · exact measurable_coordinateProcess (DenseTime.castOrderEmbedding r) + · rw [show (fun omega ↦ mixedPastShiftedCoordinates S omega (Sum.inr t)) = + coordinateProcess (alpha := alpha) (DenseTime.castOrderEmbedding (S + t)) by + funext omega + exact mixedPastShiftedCoordinates_inr S t omega] + exact measurable_coordinateProcess (DenseTime.castOrderEmbedding (S + t)) + +end ContinuousPath + +namespace ContinuousPath + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +/-- The mixed-coordinate map is literally the existing complete rational-past restriction paired +with the dense restriction of the shifted future. This bridge contains no probability algebra. -/ +theorem mixedPastShiftedCoordinates_eq_densePast_sumElim (S : DenseTime) + (omega : ContinuousPath alpha) : + mixedPastShiftedCoordinates S omega = + Sum.elim (densePastRestriction S omega) + (denseRestriction (shift (DenseTime.castOrderEmbedding S) omega)) := by + funext i + rcases i with r | t + · rfl + · rfl + +end ContinuousPath +end + +end MixedPastFutureCoordinates + +section MixedPastFutureCutCoordinates + +open MeasureTheory ProbabilityTheory +open scoped ProbabilityTheory + +namespace MixedPastFuture + +noncomputable section + +private theorem sort_union_eq_append {beta : Type*} [LinearOrder beta] + (A B : Finset beta) (hAB : ∀ a ∈ A, ∀ b ∈ B, a < b) : + (A ∪ B).sort = A.sort ++ B.sort := by + apply (A ∪ B).sortedLT_sort.eq_of_mem_iff + · rw [List.sortedLT_iff_pairwise, List.pairwise_append] + exact ⟨A.sortedLT_sort.pairwise, B.sortedLT_sort.pairwise, fun a ha b hb ↦ + hAB a ((A.mem_sort (· ≤ ·)).mp ha) b ((B.mem_sort (· ≤ ·)).mp hb)⟩ + · intro x + simp only [Finset.mem_sort, Finset.mem_union, List.mem_append] + +/-- Past observation times with the cut inserted, whether or not the mixed labels observe it. -/ +def pastWithTerminalFinset (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : Finset DenseTime := + pastFinset S I ∪ {S} + +@[simp] +theorem mem_pastWithTerminalFinset (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) (r : DenseTime) : + r ∈ pastWithTerminalFinset S I ↔ + (∃ h : r ≤ S, Sum.inl ⟨r, h⟩ ∈ I) ∨ r = S := by + simp only [pastWithTerminalFinset, Finset.mem_union, mem_pastFinset, + Finset.mem_singleton] + +/-- Strictly positive elapsed future times. Future zero is represented by the terminal past +coordinate instead of a second coordinate in the ordered concatenation. -/ +def positiveFutureFinset (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : Finset DenseTime := + (futureFinset S I).filter (0 < ·) + +@[simp] +theorem mem_positiveFutureFinset (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) (t : DenseTime) : + t ∈ positiveFutureFinset S I ↔ Sum.inr t ∈ I ∧ 0 < t := by + simp only [positiveFutureFinset, Finset.mem_filter, mem_futureFinset] + +/-- The absolute observation set after inserting the cut. -/ +def absoluteFinsetWithTerminal (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : Finset DenseTime := + absoluteFinset S I ∪ {S} + +/-- The cut-augmented absolute set is the union of the augmented past and the translate of the +strictly positive future. Thus future zero creates no second ordered coordinate. -/ +theorem absoluteFinsetWithTerminal_eq (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + absoluteFinsetWithTerminal S I = + pastWithTerminalFinset S I ∪ DenseTime.addFinset S (positiveFutureFinset S I) := by + ext r + simp only [absoluteFinsetWithTerminal, Finset.mem_union, mem_absoluteFinset, + Finset.mem_singleton, mem_pastWithTerminalFinset, DenseTime.mem_addFinset, + mem_positiveFutureFinset] + constructor + · rintro ((hp | ⟨t, htI, htr⟩) | hrS) + · exact Or.inl (Or.inl hp) + · by_cases ht0 : t = 0 + · exact Or.inl (Or.inr (by simpa only [ht0, add_zero] using htr.symm)) + · exact Or.inr ⟨t, + ⟨(mem_futureFinset S I t).mp htI, bot_lt_iff_ne_bot.mpr ht0⟩, htr⟩ + · exact Or.inl (Or.inr hrS) + · rintro ((hp | hrS) | ⟨t, ⟨htI, _⟩, htr⟩) + · exact Or.inl (Or.inl hp) + · exact Or.inr hrS + · exact Or.inl (Or.inr ⟨t, (mem_futureFinset S I t).mpr htI, htr⟩) + +theorem le_terminal_of_mem_pastWithTerminalFinset (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) {r : DenseTime} + (hr : r ∈ pastWithTerminalFinset S I) : r ≤ S := by + rcases (mem_pastWithTerminalFinset S I r).mp hr with ⟨h, _⟩ | rfl + · exact h + · exact le_rfl + +theorem terminal_lt_of_mem_add_positiveFutureFinset (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) {r : DenseTime} + (hr : r ∈ DenseTime.addFinset S (positiveFutureFinset S I)) : S < r := by + obtain ⟨t, ht, rfl⟩ := (DenseTime.mem_addFinset S (positiveFutureFinset S I) r).mp hr + exact lt_add_of_pos_right S ((mem_positiveFutureFinset S I t).mp ht).2 + +/-- The two sides of the cut are disjoint after future zero has been represented by the cut. -/ +theorem disjoint_pastWithTerminalFinset_add_positiveFutureFinset (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + Disjoint (pastWithTerminalFinset S I) + (DenseTime.addFinset S (positiveFutureFinset S I)) := by + rw [Finset.disjoint_left] + intro r hrPast hrFuture + exact (not_lt_of_ge (le_terminal_of_mem_pastWithTerminalFinset S I hrPast)) + (terminal_lt_of_mem_add_positiveFutureFinset S I hrFuture) + +/-- Cardinality splits as strict future plus cut-augmented past. The order matches the +`n + (m + 1)` convention of finite-time concatenation. -/ +theorem card_absoluteFinsetWithTerminal (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + (absoluteFinsetWithTerminal S I).card = + (positiveFutureFinset S I).card + (pastWithTerminalFinset S I).card := by + rw [absoluteFinsetWithTerminal_eq, + Finset.card_union_of_disjoint + (disjoint_pastWithTerminalFinset_add_positiveFutureFinset S I), + DenseTime.addFinset, Finset.card_map, Nat.add_comm] + +/-- Number of past coordinates strictly before the final slot occupied by the cut. -/ +def pastPredecessorCard (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : ℕ := + (pastWithTerminalFinset S I).card - 1 + +theorem card_pastWithTerminalFinset (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + (pastWithTerminalFinset S I).card = pastPredecessorCard S I + 1 := by + symm + exact Nat.sub_add_cancel + (Finset.one_le_card.mpr ⟨S, + Finset.mem_union_right _ (Finset.mem_singleton_self S)⟩) + +/-- Physical-time version of the cut-augmented absolute set. -/ +def absolutePhysicalFinsetWithTerminal (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : Finset NNReal := + SubMarkovKernelSemigroup.denseTimePhysicalSet (absoluteFinsetWithTerminal S I) + +/-- Physical coordinates of the cut-augmented past. -/ +def pastPhysicalFinsetWithTerminal (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : Finset NNReal := + SubMarkovKernelSemigroup.denseTimePhysicalSet (pastWithTerminalFinset S I) + +/-- Absolute physical coordinates of the strictly positive future. -/ +def positiveFutureAbsolutePhysicalFinset (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : Finset NNReal := + SubMarkovKernelSemigroup.denseTimePhysicalSet + (DenseTime.addFinset S (positiveFutureFinset S I)) + +theorem absolutePhysicalFinsetWithTerminal_eq_union (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + absolutePhysicalFinsetWithTerminal S I = + pastPhysicalFinsetWithTerminal S I ∪ positiveFutureAbsolutePhysicalFinset S I := by + simp only [absolutePhysicalFinsetWithTerminal, absoluteFinsetWithTerminal_eq, + pastPhysicalFinsetWithTerminal, positiveFutureAbsolutePhysicalFinset, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.map_union] + +theorem pastPhysical_lt_positiveFutureAbsolutePhysical (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + ∀ a ∈ pastPhysicalFinsetWithTerminal S I, + ∀ b ∈ positiveFutureAbsolutePhysicalFinset S I, a < b := by + intro a ha b hb + rw [pastPhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.mem_map] at ha + rw [positiveFutureAbsolutePhysicalFinset, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.mem_map] at hb + obtain ⟨r, hr, rfl⟩ := ha + obtain ⟨t, ht, rfl⟩ := hb + exact DenseTime.castOrderEmbedding.strictMono + (lt_of_le_of_lt (le_terminal_of_mem_pastWithTerminalFinset S I hr) + (terminal_lt_of_mem_add_positiveFutureFinset S I ht)) + +theorem card_absolutePhysicalFinsetWithTerminal (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + (absolutePhysicalFinsetWithTerminal S I).card = + (positiveFutureFinset S I).card + (pastPredecessorCard S I + 1) := by + rw [absolutePhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map, + card_absoluteFinsetWithTerminal, card_pastWithTerminalFinset] + +/-- Reindex the cut cardinality by the cardinality of the augmented absolute physical set. -/ +def cutOrderEmbedding (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + Fin ((positiveFutureFinset S I).card + (pastPredecessorCard S I + 1)) ↪o + Fin (absolutePhysicalFinsetWithTerminal S I).card := + (Fin.castOrderIso (card_absolutePhysicalFinsetWithTerminal S I).symm).toOrderEmbedding + +/-- Increasing physical times of the cut-augmented mixed set, cast to the cardinal convention +expected by finite-time concatenation. -/ +def cutOrderedPhysicalTimes (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + FiniteOrderedTimes + ((positiveFutureFinset S I).card + (pastPredecessorCard S I + 1)) := + (cutOrderEmbedding S I).trans + (SubMarkovKernelSemigroup.finiteSetTimes (absolutePhysicalFinsetWithTerminal S I)) + +/-- Sorted physical coordinates of the augmented past, with its cardinality written as a +successor. -/ +def cutPastOrderedPhysicalTimes (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + FiniteOrderedTimes (pastPredecessorCard S I + 1) := + (Fin.castOrderIso (by + rw [pastPhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map, + card_pastWithTerminalFinset])).toOrderEmbedding.trans + (SubMarkovKernelSemigroup.finiteSetTimes (pastPhysicalFinsetWithTerminal S I)) + +/-- Sorted physical elapsed times of the strictly positive future. -/ +def positiveFutureOrderedPhysicalTimes (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + FiniteOrderedTimes (positiveFutureFinset S I).card := + (Fin.castOrderIso (by + rw [SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map])).toOrderEmbedding.trans + (SubMarkovKernelSemigroup.finiteSetTimes + (SubMarkovKernelSemigroup.denseTimePhysicalSet (positiveFutureFinset S I))) + +/-- The initial block of the sorted augmented absolute times is exactly the augmented past. -/ +theorem cutOrderedPhysicalTimes_initialSegment (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + FiniteOrderedTimes.initialSegment + (cutOrderedPhysicalTimes S I) = + cutPastOrderedPhysicalTimes S I := by + apply DFunLike.ext _ _ + intro i + change + (absolutePhysicalFinsetWithTerminal S I).orderEmbOfFin + (card_absolutePhysicalFinsetWithTerminal S I) + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.castAdd (positiveFutureFinset S I).card i)) = + (pastPhysicalFinsetWithTerminal S I).orderEmbOfFin + (by rw [pastPhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map, + card_pastWithTerminalFinset]) i + have hsort : (absolutePhysicalFinsetWithTerminal S I).sort = + (pastPhysicalFinsetWithTerminal S I).sort ++ + (positiveFutureAbsolutePhysicalFinset S I).sort := by + rw [absolutePhysicalFinsetWithTerminal_eq_union] + exact sort_union_eq_append _ _ + (pastPhysical_lt_positiveFutureAbsolutePhysical S I) + rw [Finset.orderEmbOfFin_apply, Finset.orderEmbOfFin_apply] + simp only [hsort] + have hcardPast : (pastPhysicalFinsetWithTerminal S I).card = pastPredecessorCard S I + 1 := by + rw [pastPhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map, + card_pastWithTerminalFinset] + have hb : i.val < (pastPhysicalFinsetWithTerminal S I).sort.length := by + rw [Finset.length_sort, hcardPast] + exact i.isLt + exact List.getElem_append_left hb + +theorem cutPastOrderedPhysicalTimes_last (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + cutPastOrderedPhysicalTimes S I (Fin.last (pastPredecessorCard S I)) = + DenseTime.castOrderEmbedding S := by + let A := pastPhysicalFinsetWithTerminal S I + have hcard : A.card = pastPredecessorCard S I + 1 := by + simp only [A, pastPhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map, + card_pastWithTerminalFinset] + change A.orderEmbOfFin hcard (Fin.last (pastPredecessorCard S I)) = _ + have hi : Fin.last (pastPredecessorCard S I) = + ⟨pastPredecessorCard S I + 1 - 1, + Nat.sub_lt (Nat.succ_pos _) Nat.zero_lt_one⟩ := by + apply Fin.ext + simp only [Fin.last, Nat.add_sub_cancel_right] + rw [hi] + rw [Finset.orderEmbOfFin_last hcard (Nat.succ_pos _)] + have hS : DenseTime.castOrderEmbedding S ∈ A := by + simp only [A, pastPhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.mem_map] + exact ⟨S, Finset.mem_union_right _ (Finset.mem_singleton_self S), rfl⟩ + have hA : A.Nonempty := ⟨DenseTime.castOrderEmbedding S, hS⟩ + apply (Finset.max'_eq_iff (s := A) (H := hA) + (DenseTime.castOrderEmbedding S)).mpr + constructor + · exact hS + · intro a ha + simp only [A, pastPhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.mem_map] at ha + obtain ⟨r, hr, rfl⟩ := ha + exact DenseTime.castOrderEmbedding.monotone + (le_terminal_of_mem_pastWithTerminalFinset S I hr) + +theorem cutOrderedPhysicalTimes_future_mem (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) + (i : Fin (positiveFutureFinset S I).card) : + cutOrderedPhysicalTimes S I + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.natAdd (pastPredecessorCard S I + 1) i)) ∈ + positiveFutureAbsolutePhysicalFinset S I := by + change + (absolutePhysicalFinsetWithTerminal S I).orderEmbOfFin + (card_absolutePhysicalFinsetWithTerminal S I) + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.natAdd (pastPredecessorCard S I + 1) i)) ∈ _ + rw [Finset.orderEmbOfFin_apply] + have hsort : (absolutePhysicalFinsetWithTerminal S I).sort = + (pastPhysicalFinsetWithTerminal S I).sort ++ + (positiveFutureAbsolutePhysicalFinset S I).sort := by + rw [absolutePhysicalFinsetWithTerminal_eq_union] + exact sort_union_eq_append _ _ + (pastPhysical_lt_positiveFutureAbsolutePhysical S I) + simp only [hsort] + let k := pastPredecessorCard S I + 1 + i.val + change + (((pastPhysicalFinsetWithTerminal S I).sort ++ + (positiveFutureAbsolutePhysicalFinset S I).sort)[k]'(by + dsimp only [k] + simp only [List.length_append, Finset.length_sort, + pastPhysicalFinsetWithTerminal, + positiveFutureAbsolutePhysicalFinset, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map, + DenseTime.addFinset, Finset.card_map, card_pastWithTerminalFinset] + exact Nat.add_lt_add_left i.isLt _)) + ∈ positiveFutureAbsolutePhysicalFinset S I + rw [List.getElem_append_right (h₁ := by + rw [Finset.length_sort, pastPhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map, + card_pastWithTerminalFinset] + dsimp only [k] + omega)] + apply (Finset.mem_sort (r := (· ≤ ·))).mp + exact List.getElem_mem _ + +/-- The final block, shifted back by the cut, is exactly the sorted strictly positive relative +future. -/ +theorem cutOrderedPhysicalTimes_relativeFinalSegment (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + FiniteOrderedTimes.relativeFinalSegment + (cutOrderedPhysicalTimes S I) = + positiveFutureOrderedPhysicalTimes S I := by + let F := SubMarkovKernelSemigroup.denseTimePhysicalSet (positiveFutureFinset S I) + have hcard : F.card = (positiveFutureFinset S I).card := by + simp only [F, SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map] + change FiniteOrderedTimes.relativeFinalSegment + (cutOrderedPhysicalTimes S I) = F.orderEmbOfFin hcard + apply Finset.orderEmbOfFin_unique' hcard + intro i + have hcut : cutOrderedPhysicalTimes S I + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.castAdd (positiveFutureFinset S I).card + (Fin.last (pastPredecessorCard S I)))) = + DenseTime.castOrderEmbedding S := by + change FiniteOrderedTimes.initialSegment + (cutOrderedPhysicalTimes S I) (Fin.last (pastPredecessorCard S I)) = _ + rw [cutOrderedPhysicalTimes_initialSegment, cutPastOrderedPhysicalTimes_last] + have hfut := cutOrderedPhysicalTimes_future_mem S I i + rw [positiveFutureAbsolutePhysicalFinset, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.mem_map] at hfut + obtain ⟨u, hu, hu_eq⟩ := hfut + obtain ⟨t, ht, hut⟩ := + (DenseTime.mem_addFinset S (positiveFutureFinset S I) u).mp hu + subst u + simp only [F, SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.mem_map] + refine ⟨t, ht, ?_⟩ + rw [FiniteOrderedTimes.relativeFinalSegment_apply, + hcut, ← hu_eq] + change DenseTime.castOrderEmbedding t = + DenseTime.castOrderEmbedding (S + t) - DenseTime.castOrderEmbedding S + rw [DenseTime.castOrderEmbedding_add, add_tsub_cancel_left] + +/-- Position of an augmented-past coordinate in the initial ordered block. -/ +def pastCutOrderIndex (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (r : pastWithTerminalFinset S I) : Fin (pastPredecessorCard S I + 1) := + Fin.cast (by + rw [pastPhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map, + card_pastWithTerminalFinset]) + (((pastPhysicalFinsetWithTerminal S I).orderIsoOfFin rfl).symm + (DenseTime.physicalSetEquiv (pastWithTerminalFinset S I) r)) + +/-- Position of a positive relative-future coordinate in the final ordered block. -/ +def positiveFutureOrderIndex (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) + (t : positiveFutureFinset S I) : Fin (positiveFutureFinset S I).card := + Fin.cast (by + rw [SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map]) + ((((SubMarkovKernelSemigroup.denseTimePhysicalSet + (positiveFutureFinset S I)).orderIsoOfFin rfl).symm + (DenseTime.physicalSetEquiv (positiveFutureFinset S I) t))) + +@[simp] +theorem cutPastOrderedPhysicalTimes_pastCutOrderIndex + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (r : pastWithTerminalFinset S I) : + cutPastOrderedPhysicalTimes S I (pastCutOrderIndex S I r) = + DenseTime.castOrderEmbedding r := by + let A := pastPhysicalFinsetWithTerminal S I + have hcard : A.card = pastPredecessorCard S I + 1 := by + simp only [A, pastPhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map, + card_pastWithTerminalFinset] + change A.orderEmbOfFin hcard + (Fin.cast hcard ((A.orderIsoOfFin rfl).symm + (DenseTime.physicalSetEquiv (pastWithTerminalFinset S I) r))) = _ + have hx := congrArg Subtype.val ((A.orderIsoOfFin rfl).apply_symm_apply + (DenseTime.physicalSetEquiv (pastWithTerminalFinset S I) r)) + simpa only [Finset.coe_orderIsoOfFin_apply, + DenseTime.physicalSetEquiv_apply] using! hx + +@[simp] +theorem positiveFutureOrderedPhysicalTimes_positiveFutureOrderIndex + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (t : positiveFutureFinset S I) : + positiveFutureOrderedPhysicalTimes S I (positiveFutureOrderIndex S I t) = + DenseTime.castOrderEmbedding t := by + let F := SubMarkovKernelSemigroup.denseTimePhysicalSet (positiveFutureFinset S I) + have hcard : F.card = (positiveFutureFinset S I).card := by + simp only [F, SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.card_map] + change F.orderEmbOfFin hcard + (Fin.cast hcard ((F.orderIsoOfFin rfl).symm + (DenseTime.physicalSetEquiv (positiveFutureFinset S I) t))) = _ + have hx := congrArg Subtype.val ((F.orderIsoOfFin rfl).apply_symm_apply + (DenseTime.physicalSetEquiv (positiveFutureFinset S I) t)) + simpa only [Finset.coe_orderIsoOfFin_apply, + DenseTime.physicalSetEquiv_apply] using! hx + +/-- Reindex a split ordered path by augmented-past and positive-future dense labels. -/ +def orderedSplitToCutCoordinates {alpha : Type*} (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) + (z : (Fin (pastPredecessorCard S I + 1) → alpha) × + (Fin (positiveFutureFinset S I).card → alpha)) : + (pastWithTerminalFinset S I → alpha) × (positiveFutureFinset S I → alpha) := + (fun r ↦ z.1 (pastCutOrderIndex S I r), + fun t ↦ z.2 (positiveFutureOrderIndex S I t)) + +theorem measurable_orderedSplitToCutCoordinates {alpha : Type*} [MeasurableSpace alpha] + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) : + Measurable (orderedSplitToCutCoordinates (alpha := alpha) S I) := by + apply Measurable.prodMk + · rw [measurable_pi_iff] + intro r + exact (measurable_pi_apply (pastCutOrderIndex S I r)).comp measurable_fst + · rw [measurable_pi_iff] + intro t + exact (measurable_pi_apply (positiveFutureOrderIndex S I t)).comp measurable_snd + +/-- A past label as a coordinate of the cut-augmented past set. -/ +def pastCutIndex (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (r : I.toLeft) : pastWithTerminalFinset S I := + ⟨r.1.1, (mem_pastWithTerminalFinset S I r).mpr + (Or.inl ⟨r.1.property, Finset.mem_toLeft.mp r.property⟩)⟩ + +@[simp] +theorem pastCutIndex_val (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (r : I.toLeft) : (pastCutIndex S I r : DenseTime) = r := rfl + +/-- A positive future label is a coordinate of the strict future set; future zero is sent to +`none`, meaning that concatenation should read the terminal past coordinate. -/ +def futureCutIndex (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (t : I.toRight) : Option (positiveFutureFinset S I) := + if ht : t.1 = 0 then none else + some ⟨t, (mem_positiveFutureFinset S I t).mpr + ⟨Finset.mem_toRight.mp t.property, bot_lt_iff_ne_bot.mpr ht⟩⟩ + +@[simp] +theorem futureCutIndex_eq_none_iff (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) (t : I.toRight) : + futureCutIndex S I t = none ↔ (t : DenseTime) = 0 := by + simp only [futureCutIndex] + split <;> simp_all + +variable {alpha : Type*} + +/-- Select the augmented-past or strict-future coordinate represented by a mixed label. -/ +def cutCoordinateIndex (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) (i : I) : + pastWithTerminalFinset S I ⊕ positiveFutureFinset S I := by + cases hi : i.1 with + | inl r => + exact Sum.inl ⟨r, (mem_pastWithTerminalFinset S I r).mpr + (Or.inl ⟨r.property, by simpa only [hi] using i.property⟩)⟩ + | inr t => + if ht : t = 0 then + exact Sum.inl ⟨S, Finset.mem_union_right _ (Finset.mem_singleton_self S)⟩ + else + exact Sum.inr ⟨t, (mem_positiveFutureFinset S I t).mpr + ⟨by simpa only [hi] using i.property, bot_lt_iff_ne_bot.mpr ht⟩⟩ + +/-- Pull coordinates indexed by the augmented past and the strictly positive relative future +back to the original mixed labels. -/ +def pullbackCutCoordinates (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (z : (pastWithTerminalFinset S I → alpha) × (positiveFutureFinset S I → alpha)) : + I → alpha := fun i ↦ Sum.elim z.1 z.2 (cutCoordinateIndex S I i) + +variable [MeasurableSpace alpha] + +theorem measurable_pullbackCutCoordinates (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + Measurable (pullbackCutCoordinates (alpha := alpha) S I) := by + rw [measurable_pi_iff] + intro i + cases h : cutCoordinateIndex S I i with + | inl r => + simpa only [pullbackCutCoordinates, h, Sum.elim_inl] using! + ((measurable_pi_apply r).comp measurable_fst) + | inr t => + simpa only [pullbackCutCoordinates, h, Sum.elim_inr] using! + ((measurable_pi_apply t).comp measurable_snd) + +/-- Include an original absolute physical coordinate into the cut-augmented set. -/ +def includeAbsolutePhysical (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (t : absolutePhysicalFinset S I) : absolutePhysicalFinsetWithTerminal S I := + ⟨t, by + exact (Finset.map_subset_map.mpr Finset.subset_union_left) t.property⟩ + +/-- Restrict a path on the augmented absolute set to the actually observed absolute set. -/ +def restrictAugmentedAbsolute {alpha : Type*} (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) + (path : absolutePhysicalFinsetWithTerminal S I → alpha) : + absolutePhysicalFinset S I → alpha := + fun t ↦ path (includeAbsolutePhysical S I t) + +/-- Read the augmented absolute path as an augmented past and a strictly positive relative +future. -/ +def splitAugmentedAbsolute {alpha : Type*} (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) + (path : absolutePhysicalFinsetWithTerminal S I → alpha) : + (pastWithTerminalFinset S I → alpha) × (positiveFutureFinset S I → alpha) := + (fun r ↦ path ⟨DenseTime.castOrderEmbedding r, by + rw [absolutePhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.mem_map] + exact ⟨r, (absoluteFinsetWithTerminal_eq S I).symm.le + (Finset.mem_union_left _ r.property), rfl⟩⟩, + fun t ↦ path ⟨DenseTime.castOrderEmbedding (S + t), by + rw [absolutePhysicalFinsetWithTerminal, + SubMarkovKernelSemigroup.denseTimePhysicalSet, Finset.mem_map] + exact ⟨S + t, (absoluteFinsetWithTerminal_eq S I).symm.le + (Finset.mem_union_right _ ((DenseTime.mem_addFinset S + (positiveFutureFinset S I) (S + t)).mpr ⟨t, t.property, rfl⟩)), rfl⟩⟩) + +theorem measurable_splitAugmentedAbsolute {alpha : Type*} [MeasurableSpace alpha] + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) : + Measurable (splitAugmentedAbsolute (alpha := alpha) S I) := by + apply Measurable.prodMk + · rw [measurable_pi_iff] + intro r + exact measurable_pi_apply _ + · rw [measurable_pi_iff] + intro t + exact measurable_pi_apply _ + +/-- Splitting the canonical ordered augmented path gives its augmented-past coordinates and its +strictly positive relative-future coordinates. -/ +theorem orderedSplitToCutCoordinates_splitFinitePath_restrictPath + {alpha : Type*} (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + orderedSplitToCutCoordinates (alpha := alpha) S I ∘ + SubMarkovKernelSemigroup.splitFinitePath ∘ + FiniteOrderedTimes.restrictPath (cutOrderEmbedding S I) = + splitAugmentedAbsolute S I ∘ + SubMarkovKernelSemigroup.orderedPathToFiniteSet + (absolutePhysicalFinsetWithTerminal S I) := by + funext path + apply Prod.ext + · funext r + change path _ = path _ + apply congrArg path + apply (SubMarkovKernelSemigroup.finiteSetTimes + (absolutePhysicalFinsetWithTerminal S I)).injective + rw [show + (SubMarkovKernelSemigroup.finiteSetTimes + (absolutePhysicalFinsetWithTerminal S I)) + (cutOrderEmbedding S I + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.castAdd (positiveFutureFinset S I).card (pastCutOrderIndex S I r)))) = + cutOrderedPhysicalTimes S I + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.castAdd (positiveFutureFinset S I).card (pastCutOrderIndex S I r))) by + rfl] + change FiniteOrderedTimes.initialSegment + (cutOrderedPhysicalTimes S I) (pastCutOrderIndex S I r) = + (SubMarkovKernelSemigroup.finiteSetTimes + (absolutePhysicalFinsetWithTerminal S I)) + (((absolutePhysicalFinsetWithTerminal S I).orderIsoOfFin rfl).symm + ⟨DenseTime.castOrderEmbedding r, _⟩) + rw [cutOrderedPhysicalTimes_initialSegment, + cutPastOrderedPhysicalTimes_pastCutOrderIndex] + change DenseTime.castOrderEmbedding r = + (((absolutePhysicalFinsetWithTerminal S I).orderIsoOfFin rfl) + (((absolutePhysicalFinsetWithTerminal S I).orderIsoOfFin rfl).symm + ⟨DenseTime.castOrderEmbedding r, _⟩) : + absolutePhysicalFinsetWithTerminal S I) + rw [OrderIso.apply_symm_apply] + · funext t + change path _ = path _ + apply congrArg path + apply (SubMarkovKernelSemigroup.finiteSetTimes + (absolutePhysicalFinsetWithTerminal S I)).injective + rw [show + (SubMarkovKernelSemigroup.finiteSetTimes + (absolutePhysicalFinsetWithTerminal S I)) + (cutOrderEmbedding S I + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.natAdd (pastPredecessorCard S I + 1) + (positiveFutureOrderIndex S I t)))) = + cutOrderedPhysicalTimes S I + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.natAdd (pastPredecessorCard S I + 1) + (positiveFutureOrderIndex S I t))) by + rfl] + change cutOrderedPhysicalTimes S I + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.natAdd (pastPredecessorCard S I + 1) (positiveFutureOrderIndex S I t))) = + (SubMarkovKernelSemigroup.finiteSetTimes + (absolutePhysicalFinsetWithTerminal S I)) + (((absolutePhysicalFinsetWithTerminal S I).orderIsoOfFin rfl).symm + ⟨DenseTime.castOrderEmbedding (S + t), _⟩) + have hcut : cutOrderedPhysicalTimes S I + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.castAdd (positiveFutureFinset S I).card + (Fin.last (pastPredecessorCard S I)))) = + DenseTime.castOrderEmbedding S := by + change FiniteOrderedTimes.initialSegment + (cutOrderedPhysicalTimes S I) (Fin.last (pastPredecessorCard S I)) = _ + rw [cutOrderedPhysicalTimes_initialSegment, cutPastOrderedPhysicalTimes_last] + have hrelative : + cutOrderedPhysicalTimes S I + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.natAdd (pastPredecessorCard S I + 1) + (positiveFutureOrderIndex S I t))) - + DenseTime.castOrderEmbedding S = DenseTime.castOrderEmbedding t := by + rw [← hcut, + ← FiniteOrderedTimes.relativeFinalSegment_apply, + cutOrderedPhysicalTimes_relativeFinalSegment, + positiveFutureOrderedPhysicalTimes_positiveFutureOrderIndex] + have hle : DenseTime.castOrderEmbedding S ≤ + cutOrderedPhysicalTimes S I + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.natAdd (pastPredecessorCard S I + 1) + (positiveFutureOrderIndex S I t))) := by + rw [← hcut] + apply (cutOrderedPhysicalTimes S I).monotone + apply (cutIndexOrderIso + (pastPredecessorCard S I) (positiveFutureFinset S I).card).monotone + apply Fin.mk_le_mk.mpr + change pastPredecessorCard S I ≤ + pastPredecessorCard S I + 1 + (positiveFutureOrderIndex S I t).val + omega + have habsolute : cutOrderedPhysicalTimes S I + (cutIndexOrderIso (pastPredecessorCard S I) + (positiveFutureFinset S I).card + (Fin.natAdd (pastPredecessorCard S I + 1) + (positiveFutureOrderIndex S I t))) = + DenseTime.castOrderEmbedding (S + t) := by + calc + _ = DenseTime.castOrderEmbedding t + DenseTime.castOrderEmbedding S := + (tsub_eq_iff_eq_add_of_le hle).mp hrelative + _ = DenseTime.castOrderEmbedding S + DenseTime.castOrderEmbedding t := + add_comm _ _ + _ = DenseTime.castOrderEmbedding (S + t) := + (DenseTime.castOrderEmbedding_add S t).symm + rw [habsolute] + change DenseTime.castOrderEmbedding (S + t) = + (((absolutePhysicalFinsetWithTerminal S I).orderIsoOfFin rfl) + (((absolutePhysicalFinsetWithTerminal S I).orderIsoOfFin rfl).symm + ⟨DenseTime.castOrderEmbedding (S + t), _⟩) : + absolutePhysicalFinsetWithTerminal S I) + rw [OrderIso.apply_symm_apply] + +/-- Splitting an augmented absolute path and pulling it back to mixed labels is exactly the +original possibly noninjective absolute-coordinate pullback. -/ +theorem pullbackCutCoordinates_splitAugmentedAbsolute {alpha : Type*} + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (path : absolutePhysicalFinsetWithTerminal S I → alpha) : + pullbackCutCoordinates S I (splitAugmentedAbsolute S I path) = + pullbackAbsolutePhysical S I (restrictAugmentedAbsolute S I path) := by + funext i + rcases i with ⟨r | t, hi⟩ + · simp only [pullbackCutCoordinates, cutCoordinateIndex, splitAugmentedAbsolute, + pullbackAbsolutePhysical_apply, restrictAugmentedAbsolute] + apply congrArg path + apply Subtype.ext + change DenseTime.castOrderEmbedding r = DenseTime.castOrderEmbedding r + rfl + · by_cases ht : t = 0 + · subst t + simp only [pullbackCutCoordinates, cutCoordinateIndex, ↓reduceDIte, + splitAugmentedAbsolute, pullbackAbsolutePhysical_apply, restrictAugmentedAbsolute] + apply congrArg path + apply Subtype.ext + change DenseTime.castOrderEmbedding S = DenseTime.castOrderEmbedding (S + 0) + rw [add_zero] + · simp only [pullbackCutCoordinates, cutCoordinateIndex, ht, ↓reduceDIte, + splitAugmentedAbsolute, pullbackAbsolutePhysical_apply, restrictAugmentedAbsolute] + apply congrArg path + apply Subtype.ext + change DenseTime.castOrderEmbedding (S + t) = DenseTime.castOrderEmbedding (S + t) + rfl + +theorem absolutePhysicalFinset_subset_withTerminal (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + absolutePhysicalFinset S I ⊆ absolutePhysicalFinsetWithTerminal S I := by + exact Finset.map_subset_map.mpr Finset.subset_union_left + +theorem restrictAugmentedAbsolute_eq_restrict₂ {alpha : Type*} (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + restrictAugmentedAbsolute (alpha := alpha) S I = + Finset.restrict₂ (π := fun _ ↦ alpha) + (absolutePhysicalFinset_subset_withTerminal S I) := by + rfl + +end +end MixedPastFuture + +namespace SubMarkovKernelSemigroup +namespace IsConservative + +/-- The mixed marginal may be computed from the cut-augmented finite-set law, split into the +augmented past and strict future. This is the projective reduction which makes omission of `S` +and duplication at future zero harmless before applying ordered concatenation. -/ +theorem finiteSetKernel_map_pullbackAbsolutePhysical_eq_cutAugmented + {alpha : Type*} [MeasurableSpace alpha] + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) : + (MarkovProcess.SubMarkovKernelSemigroup.finiteSetKernel P + (MixedPastFuture.absolutePhysicalFinset S I)).map + (MixedPastFuture.pullbackAbsolutePhysical S I) = + (MarkovProcess.SubMarkovKernelSemigroup.finiteSetKernel P + (MixedPastFuture.absolutePhysicalFinsetWithTerminal S I)).map + (MixedPastFuture.pullbackCutCoordinates S I ∘ + MixedPastFuture.splitAugmentedAbsolute S I) := by + rw [hP.finiteSetKernel_map_restrict₂ P + (MixedPastFuture.absolutePhysicalFinset_subset_withTerminal S I)] + let K := MarkovProcess.SubMarkovKernelSemigroup.finiteSetKernel P + (MixedPastFuture.absolutePhysicalFinsetWithTerminal S I) + change + (K.map (Finset.restrict₂ (π := fun _ ↦ alpha) + (MixedPastFuture.absolutePhysicalFinset_subset_withTerminal S I))).map + (MixedPastFuture.pullbackAbsolutePhysical S I) = _ + calc + (K.map (Finset.restrict₂ (π := fun _ ↦ alpha) + (MixedPastFuture.absolutePhysicalFinset_subset_withTerminal S I))).map + (MixedPastFuture.pullbackAbsolutePhysical S I) = + K.map (MixedPastFuture.pullbackAbsolutePhysical S I ∘ + Finset.restrict₂ (π := fun _ ↦ alpha) + (MixedPastFuture.absolutePhysicalFinset_subset_withTerminal S I)) := by + exact (ProbabilityTheory.Kernel.map_comp_right K + (Finset.measurable_restrict₂ (X := fun _ ↦ alpha) + (MixedPastFuture.absolutePhysicalFinset_subset_withTerminal S I)) + (MixedPastFuture.measurable_pullbackAbsolutePhysical S I)).symm + _ = K.map (MixedPastFuture.pullbackCutCoordinates S I ∘ + MixedPastFuture.splitAugmentedAbsolute S I) := by + congr 1 + funext path + exact (MixedPastFuture.pullbackCutCoordinates_splitAugmentedAbsolute S I path).symm + +/-- Canonical mixed-cut specialization of finite-time concatenation. Arbitrary label maps may +omit either side, and mapping a future label to `none` reads the terminal past coordinate. -/ +theorem finiteTimeKernel_map_pullbackSplit_cutOrderedPhysicalTimes + {alpha pastLabel futureLabel : Type*} [MeasurableSpace alpha] + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (pastIndex : pastLabel → Fin (MixedPastFuture.pastPredecessorCard S I + 1)) + (futureIndex : futureLabel → + Option (Fin (MixedPastFuture.positiveFutureFinset S I).card)) : + (MarkovProcess.SubMarkovKernelSemigroup.finiteTimeKernel P + (MixedPastFuture.cutOrderedPhysicalTimes S I)).map + (MarkovProcess.SubMarkovKernelSemigroup.pullbackSplitFinitePath + (alpha := alpha) pastIndex futureIndex ∘ + MarkovProcess.SubMarkovKernelSemigroup.splitFinitePath + (alpha := alpha) + (m := MixedPastFuture.pastPredecessorCard S I) + (n := (MixedPastFuture.positiveFutureFinset S I).card)) = + (MarkovProcess.SubMarkovKernelSemigroup.finiteTimeKernel P + (MixedPastFuture.cutPastOrderedPhysicalTimes S I) ⊗ₖ + (MarkovProcess.SubMarkovKernelSemigroup.finiteTimeKernel P + (MixedPastFuture.positiveFutureOrderedPhysicalTimes S I)).comap + (MarkovProcess.SubMarkovKernelSemigroup.splitPastTerminal + (alpha := alpha) + (m := MixedPastFuture.pastPredecessorCard S I)) + MarkovProcess.SubMarkovKernelSemigroup.measurable_splitPastTerminal).map + (MarkovProcess.SubMarkovKernelSemigroup.pullbackSplitFinitePath + (alpha := alpha) pastIndex futureIndex) := by + rw [← MixedPastFuture.cutOrderedPhysicalTimes_initialSegment S I, + ← MixedPastFuture.cutOrderedPhysicalTimes_relativeFinalSegment S I] + exact hP.finiteTimeKernel_map_pullbackSplitFinitePath P + (MixedPastFuture.pastPredecessorCard S I) + (MixedPastFuture.positiveFutureFinset S I).card + (MixedPastFuture.cutOrderedPhysicalTimes S I) pastIndex futureIndex + +end IsConservative +end SubMarkovKernelSemigroup + +end MixedPastFutureCutCoordinates + +section MixedPastFutureCutFactorization + +open MeasureTheory ProbabilityTheory +open scoped ProbabilityTheory + +namespace SubMarkovKernelSemigroup +namespace IsConservative + +/-- A mixed finite marginal factors into its cut-augmented past law and the strict relative-future +law started from the terminal past coordinate. -/ +theorem finiteSetKernel_map_pullbackAbsolutePhysical_eq_cutFactorized + {alpha : Type*} [MeasurableSpace alpha] + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) : + (finiteSetKernel P (MixedPastFuture.absolutePhysicalFinset S I)).map + (MixedPastFuture.pullbackAbsolutePhysical S I) = + ((finiteTimeKernel P (MixedPastFuture.cutPastOrderedPhysicalTimes S I)) ⊗ₖ + (finiteTimeKernel P + (MixedPastFuture.positiveFutureOrderedPhysicalTimes S I)).comap + (splitPastTerminal (alpha := alpha) + (m := MixedPastFuture.pastPredecessorCard S I)) + measurable_splitPastTerminal).map + (MixedPastFuture.pullbackCutCoordinates S I ∘ + MixedPastFuture.orderedSplitToCutCoordinates S I) := by + rw [hP.finiteSetKernel_map_pullbackAbsolutePhysical_eq_cutAugmented P S I, + finiteSetKernel_eq_map] + let G := MixedPastFuture.pullbackCutCoordinates (alpha := alpha) S I ∘ + MixedPastFuture.orderedSplitToCutCoordinates S I + have hG : Measurable G := + (MixedPastFuture.measurable_pullbackCutCoordinates S I).comp + (MixedPastFuture.measurable_orderedSplitToCutCoordinates S I) + have hsplit : Measurable + (splitFinitePath (alpha := alpha) + (m := MixedPastFuture.pastPredecessorCard S I) + (n := (MixedPastFuture.positiveFutureFinset S I).card)) := + measurable_splitFinitePath + have hreindex : Measurable + (FiniteOrderedTimes.restrictPath (MixedPastFuture.cutOrderEmbedding S I) : + (Fin (MixedPastFuture.absolutePhysicalFinsetWithTerminal S I).card → alpha) → + Fin ((MixedPastFuture.positiveFutureFinset S I).card + + (MixedPastFuture.pastPredecessorCard S I + 1)) → alpha) := + FiniteOrderedTimes.measurable_restrictPath _ + let K := finiteTimeKernel P + (finiteSetTimes (MixedPastFuture.absolutePhysicalFinsetWithTerminal S I)) + calc + (K.map (orderedPathToFiniteSet + (MixedPastFuture.absolutePhysicalFinsetWithTerminal S I))).map + (MixedPastFuture.pullbackCutCoordinates S I ∘ + MixedPastFuture.splitAugmentedAbsolute S I) = + K.map ((MixedPastFuture.pullbackCutCoordinates S I ∘ + MixedPastFuture.splitAugmentedAbsolute S I) ∘ + orderedPathToFiniteSet + (MixedPastFuture.absolutePhysicalFinsetWithTerminal S I)) := by + exact (Kernel.map_comp_right K + (measurable_orderedPathToFiniteSet + (MixedPastFuture.absolutePhysicalFinsetWithTerminal S I)) + ((MixedPastFuture.measurable_pullbackCutCoordinates S I).comp + (MixedPastFuture.measurable_splitAugmentedAbsolute S I))).symm + _ = K.map ((G ∘ splitFinitePath) ∘ + FiniteOrderedTimes.restrictPath (MixedPastFuture.cutOrderEmbedding S I)) := by + congr 1 + funext path + exact congrArg (MixedPastFuture.pullbackCutCoordinates S I) + (congrFun + (MixedPastFuture.orderedSplitToCutCoordinates_splitFinitePath_restrictPath + (alpha := alpha) S I) path).symm + _ = (K.map (FiniteOrderedTimes.restrictPath + (MixedPastFuture.cutOrderEmbedding S I))).map + (G ∘ splitFinitePath) := by + exact Kernel.map_comp_right K hreindex (hG.comp hsplit) + _ = (finiteTimeKernel P (MixedPastFuture.cutOrderedPhysicalTimes S I)).map + (G ∘ splitFinitePath) := by + rw [hP.finiteTimeKernel_map_restrictPath P + (finiteSetTimes (MixedPastFuture.absolutePhysicalFinsetWithTerminal S I)) + (MixedPastFuture.cutOrderEmbedding S I)] + rfl + _ = ((finiteTimeKernel P (MixedPastFuture.cutOrderedPhysicalTimes S I)).map + splitFinitePath).map G := by + exact Kernel.map_comp_right _ hsplit hG + _ = ((finiteTimeKernel P + (FiniteOrderedTimes.initialSegment + (MixedPastFuture.cutOrderedPhysicalTimes S I))) ⊗ₖ + (finiteTimeKernel P + (FiniteOrderedTimes.relativeFinalSegment + (MixedPastFuture.cutOrderedPhysicalTimes S I))).comap + (splitPastTerminal (alpha := alpha) + (m := MixedPastFuture.pastPredecessorCard S I)) + measurable_splitPastTerminal).map G := by + rw [hP.finiteTimeKernel_map_splitFinitePath P + (MixedPastFuture.pastPredecessorCard S I) + (MixedPastFuture.positiveFutureFinset S I).card + (MixedPastFuture.cutOrderedPhysicalTimes S I)] + _ = _ := by + rw [MixedPastFuture.cutOrderedPhysicalTimes_initialSegment, + MixedPastFuture.cutOrderedPhysicalTimes_relativeFinalSegment] + +end IsConservative +end SubMarkovKernelSemigroup + +end MixedPastFutureCutFactorization + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestart.lean new file mode 100644 index 0000000000..0b8db02202 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestart.lean @@ -0,0 +1,535 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture +import Mathlib.Probability.Kernel.Composition.KernelLemmas +import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex +import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals + +/-! +# The rational-time restart kernel and its joint law + +This file merges the following former modules, one section each: + +* `RationalJointKernel`: The rational past/future restart kernel +* `RationalRestartFiniteMarginals`: Finite marginals of the rational restart kernel +* `RationalJointLaw`: Rational-time joint restart law +-/ + +namespace MarkovProcess + +section RationalJointKernel + +open MeasureTheory ProbabilityTheory +open scoped ProbabilityTheory + +namespace ContinuousPath + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] + +/-- The complete rational-past restriction is Borel measurable. -/ +theorem measurable_densePastRestriction (S : DenseTime) : + Measurable (densePastRestriction (alpha := alpha) S) := by + apply Measurable.of_comap_le + rw [comap_densePastRestriction_eq_canonicalFiltration] + exact (canonicalFiltration (alpha := alpha)).le (DenseTime.castOrderEmbedding S) + +omit [MeasurableSpace alpha] [BorelSpace alpha] in +/-- Encoding the complete rational past and the dense coordinates of the shifted future is the +existing mixed past/future coordinate map. -/ +@[simp] +theorem finitePastDenseFuture_densePastRestriction_shift + (S : DenseTime) (omega : ContinuousPath alpha) : + Kernel.finitePastDenseFuture + (densePastRestriction S omega, + shift (DenseTime.castOrderEmbedding S) omega) = + mixedPastShiftedCoordinates S omega := by + funext i + rcases i with r | t + · rfl + · rfl + +/-- The kernel which samples the rational past and then an independent future trajectory started +from the terminal state of that past. -/ +def rationalPastFutureRestartKernel + (Q : Kernel alpha (ContinuousPath alpha)) (S : DenseTime) : + Kernel alpha ((Set.Iic S → alpha) × ContinuousPath alpha) := + Q.map (densePastRestriction S) ⊗ₖ + Kernel.prodMkLeft alpha + (Kernel.comap Q (densePastTerminal S) (measurable_densePastTerminal S)) + +/-- If `Q` is a Markov path kernel, then so is its rational past/future restart kernel. -/ +instance instIsMarkovKernelRationalPastFutureRestartKernel + (Q : Kernel alpha (ContinuousPath alpha)) [IsMarkovKernel Q] (S : DenseTime) : + IsMarkovKernel (rationalPastFutureRestartKernel Q S) := by + unfold rationalPastFutureRestartKernel + let : IsMarkovKernel (Q.map (densePastRestriction S)) := + Kernel.IsMarkovKernel.map Q (measurable_densePastRestriction S) + infer_instance + +/-- At a starting point, the rational past/future restart kernel is the measure composition +product of the rational-past marginal and the path kernel started from its terminal state. -/ +theorem rationalPastFutureRestartKernel_apply + (Q : Kernel alpha (ContinuousPath alpha)) [IsMarkovKernel Q] + (S : DenseTime) (x : alpha) : + rationalPastFutureRestartKernel Q S x = + ((Q x).map (densePastRestriction S)) ⊗ₘ + Kernel.comap Q (densePastTerminal S) (measurable_densePastTerminal S) := by + ext A hA + rw [rationalPastFutureRestartKernel, Kernel.compProd_apply hA, + Measure.compProd_apply hA, + Kernel.map_apply Q (measurable_densePastRestriction S) x] + congr with history + +end +end ContinuousPath + +end RationalJointKernel + +section RationalRestartFiniteMarginals + +open MeasureTheory ProbabilityTheory +open scoped ProbabilityTheory +open scoped NNReal + + +noncomputable section + +namespace MixedPastFuture + +private def restrictPastWithTerminal {alpha : Type*} (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) (path : Set.Iic S → alpha) : + pastWithTerminalFinset S I → alpha := + fun r ↦ path ⟨r, le_terminal_of_mem_pastWithTerminalFinset S I r.property⟩ + +private def restrictPositiveFuture {alpha : Type*} [TopologicalSpace alpha] + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (path : ContinuousPath alpha) : positiveFutureFinset S I → alpha := + fun t ↦ path (DenseTime.castOrderEmbedding t) + +private def reindexCutPast {alpha : Type*} (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) + (path : Fin (pastPredecessorCard S I + 1) → alpha) : + pastWithTerminalFinset S I → alpha := + fun r ↦ path (pastCutOrderIndex S I r) + +private def reindexPositiveFuture {alpha : Type*} (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) + (path : Fin (positiveFutureFinset S I).card → alpha) : + positiveFutureFinset S I → alpha := + fun t ↦ path (positiveFutureOrderIndex S I t) + +variable {alpha : Type*} [MetricSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] + +omit [MetricSpace alpha] [BorelSpace alpha] in +private theorem measurable_restrictPastWithTerminal (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + Measurable (restrictPastWithTerminal (alpha := alpha) S I) := by + rw [measurable_pi_iff] + intro r + exact measurable_pi_apply _ + +private theorem measurable_restrictPositiveFuture (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + Measurable (restrictPositiveFuture (alpha := alpha) S I) := by + rw [measurable_pi_iff] + intro t + exact ContinuousPath.measurable_coordinateProcess _ + +omit [MetricSpace alpha] [BorelSpace alpha] in +private theorem measurable_reindexCutPast (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + Measurable (reindexCutPast (alpha := alpha) S I) := by + rw [measurable_pi_iff] + intro r + exact measurable_pi_apply _ + +omit [MetricSpace alpha] [BorelSpace alpha] in +private theorem measurable_reindexPositiveFuture (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + Measurable (reindexPositiveFuture (alpha := alpha) S I) := by + rw [measurable_pi_iff] + intro t + exact measurable_pi_apply _ + +omit [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] in +private theorem restrictPast_terminal (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + (fun z : pastWithTerminalFinset S I → alpha ↦ + z ⟨S, Finset.mem_union_right _ (Finset.mem_singleton_self S)⟩) ∘ + restrictPastWithTerminal S I = ContinuousPath.densePastTerminal S := by + funext path + rfl + +omit [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] in +private theorem reindexCutPast_terminal (S : DenseTime) + (I : Finset (Set.Iic S ⊕ DenseTime)) : + (fun z : pastWithTerminalFinset S I → alpha ↦ + z ⟨S, Finset.mem_union_right _ (Finset.mem_singleton_self S)⟩) ∘ + reindexCutPast S I = + (fun path : Fin (pastPredecessorCard S I + 1) → alpha ↦ + path (Fin.last (pastPredecessorCard S I))) := by + funext path + apply congrArg path + apply (cutPastOrderedPhysicalTimes S I).injective + rw [cutPastOrderedPhysicalTimes_pastCutOrderIndex, + cutPastOrderedPhysicalTimes_last] + +end MixedPastFuture + +namespace SubMarkovKernelSemigroup.IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [StandardBorelSpace alpha] [Nonempty alpha] + +private theorem map_restrictPastWithTerminal + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) : + ((continuousPathTrajectory P hP default).map + (ContinuousPath.densePastRestriction S)).map + (MixedPastFuture.restrictPastWithTerminal S I) = + (finiteTimeKernel P (MixedPastFuture.cutPastOrderedPhysicalTimes S I)).map + (MixedPastFuture.reindexCutPast S I) := by + rw [← Kernel.map_comp_right] + · let J := MixedPastFuture.pastWithTerminalFinset S I + let E : ContinuousPath alpha → denseTimePhysicalSet J → alpha := + fun path t ↦ path t + have hE : Measurable E := by + rw [measurable_pi_iff] + intro t + exact ContinuousPath.measurable_coordinateProcess t + have hfun : + MixedPastFuture.restrictPastWithTerminal S I ∘ + ContinuousPath.densePastRestriction S = + DenseTimePath.pullbackPhysicalSet J ∘ E := by + funext path r + rfl + rw [hfun, Kernel.map_comp_right] + · rw [continuousPathTrajectory_map_finiteDenseTimeSet P hP default hK J] + rw [finiteSetKernel_eq_map] + let e : Fin (MixedPastFuture.pastPredecessorCard S I + 1) ↪o + Fin (MixedPastFuture.pastPhysicalFinsetWithTerminal S I).card := + (Fin.castOrderIso (by + rw [MixedPastFuture.pastPhysicalFinsetWithTerminal, + denseTimePhysicalSet, Finset.card_map, + MixedPastFuture.card_pastWithTerminalFinset])).toOrderEmbedding + rw [show MixedPastFuture.cutPastOrderedPhysicalTimes S I = + (finiteSetTimes (MixedPastFuture.pastPhysicalFinsetWithTerminal S I)).restrict e + from rfl, + ← hP.finiteTimeKernel_map_restrictPath P _ e, + ← Kernel.map_comp_right, ← Kernel.map_comp_right] + · congr 1 + · exact FiniteOrderedTimes.measurable_restrictPath e + · exact MixedPastFuture.measurable_reindexCutPast S I + · exact measurable_orderedPathToFiniteSet _ + · exact DenseTimePath.measurable_pullbackPhysicalSet J + · exact hE + · exact DenseTimePath.measurable_pullbackPhysicalSet J + · exact ContinuousPath.measurable_densePastRestriction S + · exact MixedPastFuture.measurable_restrictPastWithTerminal S I + +private theorem map_restrictPositiveFuture + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) : + (continuousPathTrajectory P hP default).map + (MixedPastFuture.restrictPositiveFuture S I) = + (finiteTimeKernel P + (MixedPastFuture.positiveFutureOrderedPhysicalTimes S I)).map + (MixedPastFuture.reindexPositiveFuture S I) := by + let J := MixedPastFuture.positiveFutureFinset S I + let E : ContinuousPath alpha → denseTimePhysicalSet J → alpha := + fun path t ↦ path t + have hE : Measurable E := by + rw [measurable_pi_iff] + intro t + exact ContinuousPath.measurable_coordinateProcess t + have hfun : MixedPastFuture.restrictPositiveFuture S I = + DenseTimePath.pullbackPhysicalSet J ∘ E := by + funext path t + rfl + rw [hfun, Kernel.map_comp_right] + · rw [continuousPathTrajectory_map_finiteDenseTimeSet P hP default hK J] + rw [finiteSetKernel_eq_map] + let e : Fin (MixedPastFuture.positiveFutureFinset S I).card ↪o + Fin (denseTimePhysicalSet J).card := + (Fin.castOrderIso (by + simp only [J, denseTimePhysicalSet, Finset.card_map])).toOrderEmbedding + rw [show MixedPastFuture.positiveFutureOrderedPhysicalTimes S I = + (finiteSetTimes (denseTimePhysicalSet J)).restrict e from rfl, + ← hP.finiteTimeKernel_map_restrictPath P _ e, + ← Kernel.map_comp_right, ← Kernel.map_comp_right] + · congr 1 + · exact FiniteOrderedTimes.measurable_restrictPath e + · exact MixedPastFuture.measurable_reindexPositiveFuture S I + · exact measurable_orderedPathToFiniteSet _ + · exact DenseTimePath.measurable_pullbackPhysicalSet J + · exact hE + · exact DenseTimePath.measurable_pullbackPhysicalSet J + +omit [CompleteSpace alpha] [SecondCountableTopology alpha] + [StandardBorelSpace alpha] [Nonempty alpha] in +private theorem rationalRestart_map_restrict_eq_cutPullback + (Q : Kernel alpha (ContinuousPath alpha)) [IsMarkovKernel Q] + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) + (hzero : ∀ x, ∀ᵐ path ∂Q x, + path (0 : NNReal) = x) : + (ContinuousPath.rationalPastFutureRestartKernel Q S).map + (I.restrict ∘ Kernel.finitePastDenseFuture) = + (ContinuousPath.rationalPastFutureRestartKernel Q S).map + (MixedPastFuture.pullbackCutCoordinates S I ∘ + Prod.map (MixedPastFuture.restrictPastWithTerminal S I) + (MixedPastFuture.restrictPositiveFuture S I)) := by + let F := I.restrict ∘ + Kernel.finitePastDenseFuture (index := Set.Iic S) (alpha := alpha) + let H := MixedPastFuture.pullbackCutCoordinates (alpha := alpha) S I ∘ + Prod.map (MixedPastFuture.restrictPastWithTerminal S I) + (MixedPastFuture.restrictPositiveFuture S I) + have hF : Measurable F := + (Finset.measurable_restrict I).comp Kernel.measurable_finitePastDenseFuture + have hH : Measurable H := + (MixedPastFuture.measurable_pullbackCutCoordinates S I).comp + ((MixedPastFuture.measurable_restrictPastWithTerminal S I).prodMap + (MixedPastFuture.measurable_restrictPositiveFuture S I)) + change (ContinuousPath.rationalPastFutureRestartKernel Q S).map F = + (ContinuousPath.rationalPastFutureRestartKernel Q S).map H + ext x A hA + rw [Kernel.map_apply' _ hF x hA, Kernel.map_apply' _ hH x hA, + ContinuousPath.rationalPastFutureRestartKernel, + Kernel.compProd_apply (hA.preimage hF), + Kernel.compProd_apply (hA.preimage hH)] + congr with history + rw [Kernel.prodMkLeft_apply', Kernel.prodMkLeft_apply'] + apply Filter.EventuallyEq.measure_eq + filter_upwards [hzero (ContinuousPath.densePastTerminal S history)] with path hpath + apply congrArg (fun z ↦ z ∈ A) + funext i + rcases i with ⟨i, hi⟩ + rcases i with r | t + · + simp [F, H, Function.comp_apply, Kernel.finitePastDenseFuture, + MixedPastFuture.pullbackCutCoordinates, MixedPastFuture.cutCoordinateIndex, + MixedPastFuture.restrictPastWithTerminal, Prod.map_apply] + · + by_cases ht : t = 0 + · subst t + have hpath' : path (DenseTime.castOrderEmbedding (0 : DenseTime)) = + ContinuousPath.densePastTerminal S history := by + convert hpath using 1 + norm_num [DenseTime.castOrderEmbedding, NNRat.castOrderEmbedding_apply] + simpa [F, H, Function.comp_apply, Kernel.finitePastDenseFuture, + MixedPastFuture.pullbackCutCoordinates, MixedPastFuture.cutCoordinateIndex, + MixedPastFuture.restrictPastWithTerminal, Prod.map_apply, + ContinuousPath.densePastTerminal, ContinuousPath.denseRestriction_apply] + using hpath' + · simp [F, H, Function.comp_apply, Kernel.finitePastDenseFuture, + MixedPastFuture.pullbackCutCoordinates, MixedPastFuture.cutCoordinateIndex, + MixedPastFuture.restrictPositiveFuture, Prod.map_apply, ht, + ContinuousPath.denseRestriction_apply] + +/-- Mapping the rational restart kernel to any finite set of mixed past/future coordinates gives +the cut-factorized finite-time kernel, reindexed back to the original mixed labels. -/ +theorem rationalPastFutureRestartKernel_map_finitePastDenseFuture_restrict + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (S : DenseTime) (I : Finset (Set.Iic S ⊕ DenseTime)) : + (ContinuousPath.rationalPastFutureRestartKernel + (continuousPathTrajectory P hP default) S).map + (I.restrict ∘ Kernel.finitePastDenseFuture) = + ((finiteTimeKernel P (MixedPastFuture.cutPastOrderedPhysicalTimes S I)) ⊗ₖ + (finiteTimeKernel P + (MixedPastFuture.positiveFutureOrderedPhysicalTimes S I)).comap + (splitPastTerminal (alpha := alpha) + (m := MixedPastFuture.pastPredecessorCard S I)) + measurable_splitPastTerminal).map + (MixedPastFuture.pullbackCutCoordinates S I ∘ + MixedPastFuture.orderedSplitToCutCoordinates S I) := by + let Q := continuousPathTrajectory P hP default + let f := MixedPastFuture.restrictPastWithTerminal (alpha := alpha) S I + let g := MixedPastFuture.restrictPositiveFuture (alpha := alpha) S I + let terminal' : (MixedPastFuture.pastWithTerminalFinset S I → alpha) → alpha := + fun path ↦ path ⟨S, Finset.mem_union_right _ (Finset.mem_singleton_self S)⟩ + have hterminal' : Measurable terminal' := measurable_pi_apply _ + have hcompat : terminal' ∘ f = ContinuousPath.densePastTerminal S := + MixedPastFuture.restrictPast_terminal S I + have hrestartSplit : + (ContinuousPath.rationalPastFutureRestartKernel Q S).map (Prod.map f g) = + ((Q.map (ContinuousPath.densePastRestriction S)).map f) ⊗ₖ + Kernel.prodMkLeft alpha ((Q.map g).comap terminal' hterminal') := by + rw [ContinuousPath.rationalPastFutureRestartKernel] + exact Kernel.map_compProd_prodMkLeft_comap + (Q.map (ContinuousPath.densePastRestriction S)) Q + (ContinuousPath.densePastTerminal S) terminal' hterminal' f + (MixedPastFuture.measurable_restrictPastWithTerminal S I) g + (MixedPastFuture.measurable_restrictPositiveFuture S I) hcompat + let Kp := finiteTimeKernel P (MixedPastFuture.cutPastOrderedPhysicalTimes S I) + let Kf := finiteTimeKernel P + (MixedPastFuture.positiveFutureOrderedPhysicalTimes S I) + let : IsMarkovKernel Kp := + hP.isMarkovKernel_finiteTimeKernel P + (MixedPastFuture.cutPastOrderedPhysicalTimes S I) + let : IsMarkovKernel Kf := + hP.isMarkovKernel_finiteTimeKernel P + (MixedPastFuture.positiveFutureOrderedPhysicalTimes S I) + let rp := MixedPastFuture.reindexCutPast (alpha := alpha) S I + let rf := MixedPastFuture.reindexPositiveFuture (alpha := alpha) S I + let last : (Fin (MixedPastFuture.pastPredecessorCard S I + 1) → alpha) → alpha := + fun path ↦ path (Fin.last (MixedPastFuture.pastPredecessorCard S I)) + have hlast : Measurable last := measurable_pi_apply _ + have hrcompat : terminal' ∘ rp = last := + MixedPastFuture.reindexCutPast_terminal S I + have hfactorSplit : + (Kp ⊗ₖ (Kf.comap + (splitPastTerminal (alpha := alpha) + (m := MixedPastFuture.pastPredecessorCard S I)) + measurable_splitPastTerminal)).map + (MixedPastFuture.orderedSplitToCutCoordinates S I) = + (Kp.map rp) ⊗ₖ + Kernel.prodMkLeft alpha ((Kf.map rf).comap terminal' hterminal') := by + change + (Kp ⊗ₖ Kernel.prodMkLeft alpha (Kf.comap last hlast)).map + (Prod.map rp rf) = _ + exact Kernel.map_compProd_prodMkLeft_comap Kp Kf last terminal' + hterminal' rp (MixedPastFuture.measurable_reindexCutPast S I) + rf (MixedPastFuture.measurable_reindexPositiveFuture S I) hrcompat + have hsplit : + (ContinuousPath.rationalPastFutureRestartKernel Q S).map (Prod.map f g) = + (Kp ⊗ₖ (Kf.comap + (splitPastTerminal (alpha := alpha) + (m := MixedPastFuture.pastPredecessorCard S I)) + measurable_splitPastTerminal)).map + (MixedPastFuture.orderedSplitToCutCoordinates S I) := by + rw [hrestartSplit, + map_restrictPastWithTerminal P hP default hK S I, + map_restrictPositiveFuture P hP default hK S I, + hfactorSplit] + have hzero : ∀ x, ∀ᵐ path ∂Q x, path (0 : NNReal) = x := by + intro x + let evalZero : ContinuousPath alpha → alpha := fun path ↦ path 0 + have hEvalZero : Measurable evalZero := + ContinuousPath.measurable_coordinateProcess 0 + have hmap : Measure.map evalZero (Q x) = Measure.dirac x := by + have h := congrArg (fun K : Kernel alpha alpha ↦ K x) + (continuousPathTrajectory_map_eval P hP default hK 0) + have hcast : DenseTime.castOrderEmbedding (0 : DenseTime) = (0 : NNReal) := by + norm_num [DenseTime.castOrderEmbedding, NNRat.castOrderEmbedding_apply] + rw [hcast, P.zero] at h + change (Q.map evalZero) x = Kernel.id x at h + rw [Kernel.id_apply, Kernel.map_apply Q hEvalZero x] at h + exact h + let : IsProbabilityMeasure (Q x) := IsMarkovKernel.isProbabilityMeasure x + apply (mem_ae_iff_prob_eq_one + (hEvalZero (MeasurableSet.singleton x))).mpr + rw [← Measure.map_apply hEvalZero (MeasurableSet.singleton x), hmap] + simp + rw [rationalRestart_map_restrict_eq_cutPullback Q S I hzero] + calc + (ContinuousPath.rationalPastFutureRestartKernel Q S).map + (MixedPastFuture.pullbackCutCoordinates S I ∘ Prod.map f g) = + ((ContinuousPath.rationalPastFutureRestartKernel Q S).map + (Prod.map f g)).map (MixedPastFuture.pullbackCutCoordinates S I) := by + exact Kernel.map_comp_right _ + ((MixedPastFuture.measurable_restrictPastWithTerminal S I).prodMap + (MixedPastFuture.measurable_restrictPositiveFuture S I)) + (MixedPastFuture.measurable_pullbackCutCoordinates S I) + _ = ((Kp ⊗ₖ (Kf.comap + (splitPastTerminal (alpha := alpha) + (m := MixedPastFuture.pastPredecessorCard S I)) + measurable_splitPastTerminal)).map + (MixedPastFuture.orderedSplitToCutCoordinates S I)).map + (MixedPastFuture.pullbackCutCoordinates S I) := by rw [hsplit] + _ = _ := (Kernel.map_comp_right _ + (MixedPastFuture.measurable_orderedSplitToCutCoordinates S I) + (MixedPastFuture.measurable_pullbackCutCoordinates S I)).symm + +end SubMarkovKernelSemigroup.IsConservative +end + +end RationalRestartFiniteMarginals + +section RationalJointLaw + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace SubMarkovKernelSemigroup +namespace IsConservative + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [StandardBorelSpace alpha] [Nonempty alpha] + +/-- The complete rational past and shifted future of the canonical continuous trajectory have +the rational restart-kernel law. -/ +theorem continuousPathTrajectory_map_densePastRestriction_prod_shift + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (S : DenseTime) : + (continuousPathTrajectory P hP default).map (fun omega ↦ + (ContinuousPath.densePastRestriction S omega, + ContinuousPath.shift (DenseTime.castOrderEmbedding S) omega)) = + ContinuousPath.rationalPastFutureRestartKernel + (continuousPathTrajectory P hP default) S := by + apply Kernel.eq_of_map_finitePastDenseFutureRestriction_eq default + intro I + rw [← Kernel.map_comp_right] + · have hcoordinates : + (I.restrict ∘ Kernel.finitePastDenseFuture + (index := Set.Iic S) (alpha := alpha)) ∘ (fun omega ↦ + (ContinuousPath.densePastRestriction S omega, + ContinuousPath.shift (DenseTime.castOrderEmbedding S) omega)) = + I.restrict ∘ ContinuousPath.mixedPastShiftedCoordinates S := by + funext omega + exact congrArg I.restrict + (ContinuousPath.finitePastDenseFuture_densePastRestriction_shift S omega) + rw [hcoordinates] + rw [continuousPathTrajectory_map_mixedPastShiftedCoordinates_restrict + P hP default hK S I] + rw [finiteSetKernel_map_pullbackAbsolutePhysical_eq_cutFactorized P hP S I] + exact (rationalPastFutureRestartKernel_map_finitePastDenseFuture_restrict + P hP default hK S I).symm + · exact (ContinuousPath.measurable_densePastRestriction S).prodMk + (ContinuousPath.measurable_shift_fixed (DenseTime.castOrderEmbedding S)) + · exact (Finset.measurable_restrict I).comp + (Kernel.measurable_finitePastDenseFuture + (index := Set.Iic S) (alpha := alpha)) + +end +end IsConservative +end SubMarkovKernelSemigroup + +end RationalJointLaw + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestrictedRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestrictedRestart.lean new file mode 100644 index 0000000000..11c7aa106a --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestrictedRestart.lean @@ -0,0 +1,94 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration +import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint + +/-! +# Restricted restart at rational times + +This file turns a full joint-law factorization of the rational past and shifted future into the +event-restricted restart identity on the canonical continuous-path filtration. The joint-law +factorization remains an explicit input; proving it from the finite-dimensional Markov laws is the +next process-construction step. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess +namespace ContinuousPath + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] + +/-- Evaluation of a rational past at its terminal coordinate. -/ +def densePastTerminal (S : DenseTime) (history : Set.Iic S → alpha) : alpha := + history ⟨S, Set.mem_Iic.mpr le_rfl⟩ + +omit [MetricSpace alpha] [BorelSpace alpha] in +/-- Terminal-coordinate evaluation on rational pasts is measurable. -/ +theorem measurable_densePastTerminal (S : DenseTime) : + Measurable (densePastTerminal (alpha := alpha) S) := + measurable_pi_apply (⟨S, Set.mem_Iic.mpr le_rfl⟩ : Set.Iic S) + +omit [MeasurableSpace alpha] [BorelSpace alpha] in +/-- The terminal coordinate of the rational-past restriction is the physical-time coordinate at +the rational terminal time. -/ +@[simp] +theorem densePastTerminal_densePastRestriction (S : DenseTime) (omega : ContinuousPath alpha) : + densePastTerminal S (densePastRestriction S omega) = + coordinateProcess (alpha := alpha) (DenseTime.castOrderEmbedding S) omega := + rfl + +/-- A joint factorization of rational past and shifted future yields the restart identity after +restriction to every event in the canonical filtration at the rational terminal time. -/ +theorem restrict_map_shift_eq_pathKernel_comp_of_rational_joint + (Q : Kernel alpha (ContinuousPath alpha)) [IsMarkovKernel Q] + (x : alpha) (S : DenseTime) + (hJoint : + (Q x).map (fun omega ↦ + (densePastRestriction S omega, + shift (DenseTime.castOrderEmbedding S) omega)) = + ((Q x).map (densePastRestriction S)) ⊗ₘ + Kernel.comap Q (densePastTerminal S) (measurable_densePastTerminal S)) : + ∀ A : Set (ContinuousPath alpha), + MeasurableSet[canonicalFiltration (alpha := alpha) + (DenseTime.castOrderEmbedding S)] A → + ((Q x).restrict A).map (shift (DenseTime.castOrderEmbedding S)) = + Kernel.comap Q + (coordinateProcess (alpha := alpha) (DenseTime.castOrderEmbedding S)) + (measurable_coordinateProcess (DenseTime.castOrderEmbedding S)) ∘ₘ + ((Q x).restrict A) := by + have hPast : Measurable (densePastRestriction (alpha := alpha) S) := by + apply Measurable.of_comap_le + rw [comap_densePastRestriction_eq_canonicalFiltration] + exact (canonicalFiltration (alpha := alpha)).le (DenseTime.castOrderEmbedding S) + have hRestricted := restrict_map_eq_comap_comp_of_map_prodMk_eq_compProd + (Q x) (densePastRestriction S) hPast + (shift (DenseTime.castOrderEmbedding S)) + (measurable_shift_fixed (DenseTime.castOrderEmbedding S)) + (Kernel.comap Q (densePastTerminal S) (measurable_densePastTerminal S)) hJoint + intro A hA + have hA' : MeasurableSet[ + MeasurableSpace.comap (densePastRestriction (alpha := alpha) S) inferInstance] A := by + rw [comap_densePastRestriction_eq_canonicalFiltration] + exact hA + have hKernel : + (Kernel.comap Q (densePastTerminal S) (measurable_densePastTerminal S)).comap + (densePastRestriction S) hPast = + Kernel.comap Q + (coordinateProcess (alpha := alpha) (DenseTime.castOrderEmbedding S)) + (measurable_coordinateProcess (DenseTime.castOrderEmbedding S)) := by + rw [← Kernel.comap_comp_right Q hPast (measurable_densePastTerminal S)] + congr 1 + rw [← hKernel] + exact hRestricted A hA' + +end +end ContinuousPath +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/RestrictedRestartOfJoint.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/RestrictedRestartOfJoint.lean new file mode 100644 index 0000000000..5985f546c6 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/RestrictedRestartOfJoint.lean @@ -0,0 +1,54 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Probability.Kernel.Composition.MeasureCompProd +import Mathlib.Probability.Kernel.Composition.CompNotation + +/-! +# Restricted restart laws from a joint-law factorization + +This file gives a generic measure-theoretic bridge from factorization of the joint law of a +conditioning variable and a future variable to the corresponding future-law identity after +restriction to any event measurable with respect to the conditioning variable. + +No stochastic process or Markov property is asserted here. +-/ + +open MeasureTheory ProbabilityTheory + +namespace MarkovProcess + +noncomputable section + +variable {Omega beta gamma : Type*} {mOmega : MeasurableSpace Omega} + {mBeta : MeasurableSpace beta} {mGamma : MeasurableSpace gamma} + +/-- A factorization of the joint law of `X` and `Y` through `kappa` implies the future-law +restart identity after restriction to every event measurable with respect to `X`. -/ +theorem restrict_map_eq_comap_comp_of_map_prodMk_eq_compProd + (mu : @Measure Omega mOmega) [SFinite mu] + (X : Omega → beta) (hX : @Measurable Omega beta mOmega mBeta X) + (Y : Omega → gamma) (hY : @Measurable Omega gamma mOmega mGamma Y) + (kappa : @Kernel beta gamma mBeta mGamma) [IsSFiniteKernel kappa] + (hJoint : mu.map (fun omega ↦ (X omega, Y omega)) = (mu.map X) ⊗ₘ kappa) : + ∀ A : Set Omega, MeasurableSet[mBeta.comap X] A → + (mu.restrict A).map Y = + (Kernel.comap kappa X hX) ∘ₘ (mu.restrict A) := by + rintro A ⟨C, hC, rfl⟩ + ext B hB + rw [Measure.map_apply hY hB, Measure.bind_apply hB (Kernel.aemeasurable _)] + simp_rw [Kernel.comap_apply] + rw [Measure.restrict_apply (hY hB), Set.inter_comm] + calc + mu (X ⁻¹' C ∩ Y ⁻¹' B) = + (mu.map (fun omega ↦ (X omega, Y omega))) (C ×ˢ B) := by + rw [Measure.map_apply (hX.prodMk hY) (hC.prod hB), Set.mk_preimage_prod] + _ = ((mu.map X) ⊗ₘ kappa) (C ×ˢ B) := by rw [hJoint] + _ = ∫⁻ x in C, kappa x B ∂(mu.map X) := Measure.compProd_apply_prod hC hB + _ = ∫⁻ omega in X ⁻¹' C, kappa (X omega) B ∂mu := + setLIntegral_map hC (kappa.measurable_coe hB) hX + +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup.lean new file mode 100644 index 0000000000..757d04f0bf --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup.lean @@ -0,0 +1,37 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialComparison +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit + +/-! +# Semigroup + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Basic.lean new file mode 100644 index 0000000000..92cf80d634 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Basic.lean @@ -0,0 +1,103 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Analysis.Normed.Operator.Basic + +/-! +# Strongly continuous contraction semigroups + +This file provides a small reusable interface for strongly continuous contraction +semigroups on real normed spaces, parametrized by nonnegative real time. +-/ + +open Filter Topology + +namespace MarkovProcess.Semigroup + +/-- A strongly continuous contraction semigroup on a real normed space. -/ +structure StronglyContinuousContractionSemigroup (E : Type*) + [NormedAddCommGroup E] [NormedSpace ℝ E] where + /-- The continuous linear time-evolution operator. -/ + operator : NNReal → E →L[ℝ] E + operator_zero : operator 0 = ContinuousLinearMap.id ℝ E + operator_add : ∀ s t, operator (s + t) = (operator s).comp (operator t) + opNorm_le_one : ∀ t, ‖operator t‖ ≤ 1 + continuous_orbit : ∀ x, Continuous (fun t ↦ operator t x) + +namespace StronglyContinuousContractionSemigroup + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + +instance : CoeFun (StronglyContinuousContractionSemigroup E) + (fun _ ↦ NNReal → E →L[ℝ] E) where + coe S := S.operator + +@[ext] +theorem ext {S T : StronglyContinuousContractionSemigroup E} + (h : ∀ t, S t = T t) : S = T := by + cases S with + | mk S _ _ _ _ => + cases T with + | mk T _ _ _ _ => + have : S = T := funext h + cases this + rfl + +variable (S : StronglyContinuousContractionSemigroup E) + +@[simp] +theorem zero : S 0 = ContinuousLinearMap.id ℝ E := + S.operator_zero + +@[simp] +theorem zero_apply (x : E) : S 0 x = x := by + rw [S.zero] + rfl + +@[simp] +theorem add (s t : NNReal) : S (s + t) = (S s).comp (S t) := + S.operator_add s t + +@[simp] +theorem add_apply (s t : NNReal) (x : E) : S (s + t) x = S s (S t x) := by + rw [S.add] + rfl + +theorem norm_operator_le_one (t : NNReal) : ‖S t‖ ≤ 1 := + S.opNorm_le_one t + +theorem norm_apply_le (t : NNReal) (x : E) : ‖S t x‖ ≤ ‖x‖ := by + calc + ‖S t x‖ ≤ ‖S t‖ * ‖x‖ := (S t).le_opNorm x + _ ≤ 1 * ‖x‖ := mul_le_mul_of_nonneg_right (S.norm_operator_le_one t) (norm_nonneg x) + _ = ‖x‖ := one_mul _ + +theorem dist_apply_le (t : NNReal) (x y : E) : dist (S t x) (S t y) ≤ dist x y := by + calc + dist (S t x) (S t y) ≤ ‖S t‖ * dist x y := (S t).dist_le_opNorm x y + _ ≤ 1 * dist x y := + mul_le_mul_of_nonneg_right (S.norm_operator_le_one t) dist_nonneg + _ = dist x y := one_mul _ + +theorem continuous (x : E) : Continuous (fun t ↦ S t x) := + S.continuous_orbit x + +theorem continuousAt (t : NNReal) (x : E) : ContinuousAt (fun s ↦ S s x) t := + (S.continuous x).continuousAt + +theorem tendsto (t : NNReal) (x : E) : + Tendsto (fun s ↦ S s x) (nhds t) (nhds (S t x)) := + S.continuousAt t x + +theorem commute (s t : NNReal) : (S s).comp (S t) = (S t).comp (S s) := by + rw [← S.add, ← S.add, add_comm] + +theorem commute_apply (s t : NNReal) (x : E) : S s (S t x) = S t (S s x) := by + change ((S s).comp (S t)) x = ((S t).comp (S s)) x + rw [S.commute] + +end StronglyContinuousContractionSemigroup + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/CompactStrongConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/CompactStrongConvergence.lean new file mode 100644 index 0000000000..fc5a3b3ff9 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/CompactStrongConvergence.lean @@ -0,0 +1,75 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Analysis.Normed.Operator.Basic + +/-! +# Equibounded strong convergence is uniform on compact sets + +A family of continuous linear operators whose operator norms share one common bound and which +converges to zero at every point converges to zero uniformly on every compact set. The common +bound makes the family equi-Lipschitz, so a finite `δ`-net of the compact set reduces the uniform +assertion to finitely many pointwise ones. + +Main results: `eventually_forall_mem_norm_apply_le_of_isCompact`. + +Neither completeness of the spaces nor countable generation of the index filter is used, and +nothing is asserted about convergence in the operator norm, which is strictly stronger. +-/ + +open Filter Topology + +namespace MarkovProcess.Semigroup + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + [NormedAddCommGroup F] [NormedSpace ℝ F] + +/-- **Equibounded strong convergence to zero is uniform on compact sets.** If the operators +`T i` share the bound `‖T i‖ ≤ C` and `T i x → 0` for every vector `x`, then for every compact +set `K` and every `ε > 0` the estimate `‖T i x‖ ≤ ε` holds for all `x ∈ K` simultaneously, +eventually along the index filter. -/ +theorem eventually_forall_mem_norm_apply_le_of_isCompact {ι : Type*} {l : Filter ι} + (T : ι → E →L[ℝ] F) {C : ℝ} (hC : ∀ i, ‖T i‖ ≤ C) + (hT : ∀ x, Tendsto (fun i ↦ T i x) l (𝓝 0)) + {K : Set E} (hK : IsCompact K) {ε : ℝ} (hε : 0 < ε) : + ∀ᶠ i in l, ∀ x ∈ K, ‖T i x‖ ≤ ε := by + have hCpos : (0 : ℝ) < |C| + 1 := by positivity + set δ : ℝ := ε / (2 * (|C| + 1)) with hδdef + have hδ : 0 < δ := by positivity + obtain ⟨s, -, hsfin, hcover⟩ := + hK.elim_finite_subcover_image (c := fun y : E ↦ Metric.ball y δ) + (fun _ _ ↦ Metric.isOpen_ball) + (fun y hy ↦ Set.mem_iUnion₂.2 ⟨y, hy, Metric.mem_ball_self hδ⟩) + have hfin : ∀ᶠ i in l, ∀ y ∈ s, ‖T i y‖ ≤ ε / 2 := by + rw [Filter.eventually_all_finite hsfin] + intro y _ + filter_upwards [NormedAddGroup.tendsto_nhds_zero.mp (hT y) (ε / 2) (by positivity)] + with i hi + exact hi.le + filter_upwards [hfin] with i hi x hx + obtain ⟨y, hy, hxy⟩ := Set.mem_iUnion₂.1 (hcover hx) + have hdist : ‖x - y‖ ≤ δ := by + rw [← dist_eq_norm] + exact (Metric.mem_ball.1 hxy).le + have hsplit : T i x = T i y + T i (x - y) := by + rw [← map_add] + congr 1 + abel + have hbound : ‖T i (x - y)‖ ≤ ε / 2 := by + calc + ‖T i (x - y)‖ ≤ ‖T i‖ * ‖x - y‖ := (T i).le_opNorm _ + _ ≤ (|C| + 1) * δ := by + refine mul_le_mul ?_ hdist (norm_nonneg _) hCpos.le + exact (hC i).trans (by linarith [le_abs_self C]) + _ = ε / 2 := by + rw [hδdef] + field_simp + calc + ‖T i x‖ = ‖T i y + T i (x - y)‖ := by rw [hsplit] + _ ≤ ‖T i y‖ + ‖T i (x - y)‖ := norm_add_le _ _ + _ ≤ ε / 2 + ε / 2 := add_le_add (hi y hy) hbound + _ = ε := add_halves ε + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ContractiveResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ContractiveResolvent.lean new file mode 100644 index 0000000000..3ec1e37f8e --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ContractiveResolvent.lean @@ -0,0 +1,146 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence + +/-! +# Contractive resolvent families + +This module packages the elementary resolvent identity, the Hille--Yosida +bound, and dense range, then derives normalization at large positive shifts. +-/ + +open Filter Topology + +namespace MarkovProcess.Semigroup + +/-- A resolvent family on a real normed space with the contraction bound and +dense range needed for normalization at large positive shifts. -/ +structure ContractiveResolvent (E : Type*) [NormedAddCommGroup E] [NormedSpace ℝ E] where + /-- The resolvent at a positive real shift. -/ + operator : PositiveShift → E →L[ℝ] E + /-- The resolvent identity, with the sign convention for `(α + A)⁻¹`. -/ + resolvent_identity : ∀ α β, + operator α - operator β = + ((β : ℝ) - (α : ℝ)) • ((operator α).comp (operator β)) + /-- The Hille--Yosida contraction estimate. -/ + opNorm_le_inv : ∀ α, ‖operator α‖ ≤ (α : ℝ)⁻¹ + /-- Every resolvent has dense range. -/ + denseRange : ∀ α, DenseRange (operator α) + +namespace ContractiveResolvent + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + +/-- The normalized resolvent `α R_α`. -/ +def scaledOperator (R : ContractiveResolvent E) (α : PositiveShift) : E →L[ℝ] E := + (α : ℝ) • R.operator α + +/-- The normalized resolvent is a contraction in operator norm. -/ +theorem opNorm_scaledOperator_le_one (R : ContractiveResolvent E) (α : PositiveShift) : + ‖R.scaledOperator α‖ ≤ 1 := by + have hα : 0 ≤ (α : ℝ) := α.property.le + calc + ‖R.scaledOperator α‖ ≤ ‖(α : ℝ)‖ * ‖R.operator α‖ := + ContinuousLinearMap.opNorm_smul_le _ _ + _ = (α : ℝ) * ‖R.operator α‖ := by rw [Real.norm_eq_abs, abs_of_nonneg hα] + _ ≤ (α : ℝ) * (α : ℝ)⁻¹ := + mul_le_mul_of_nonneg_left (R.opNorm_le_inv α) hα + _ = 1 := mul_inv_cancel₀ α.property.ne' + +/-- Pointwise contraction of the normalized resolvent. -/ +theorem norm_scaledOperator_apply_le (R : ContractiveResolvent E) + (α : PositiveShift) (x : E) : + ‖R.scaledOperator α x‖ ≤ ‖x‖ := by + calc + ‖R.scaledOperator α x‖ ≤ ‖R.scaledOperator α‖ * ‖x‖ := + R.scaledOperator α |>.le_opNorm x + _ ≤ 1 * ‖x‖ := + mul_le_mul_of_nonneg_right (R.opNorm_scaledOperator_le_one α) (norm_nonneg x) + _ = ‖x‖ := one_mul _ + +/-- Resolvents at two positive shifts commute. -/ +theorem operator_comm (R : ContractiveResolvent E) (α β : PositiveShift) : + (R.operator α).comp (R.operator β) = + (R.operator β).comp (R.operator α) := by + by_cases hαβ : (α : ℝ) = (β : ℝ) + · have : α = β := Subtype.ext hαβ + subst β + rfl + · have hβα : (β : ℝ) - (α : ℝ) ≠ 0 := sub_ne_zero.mpr (Ne.symm hαβ) + apply (smul_right_injective (E →L[ℝ] E) hβα) + calc + ((β : ℝ) - (α : ℝ)) • ((R.operator α).comp (R.operator β)) = + R.operator α - R.operator β := (R.resolvent_identity α β).symm + _ = ((β : ℝ) - (α : ℝ)) • ((R.operator β).comp (R.operator α)) := by + calc + R.operator α - R.operator β = -(R.operator β - R.operator α) := by abel + _ = -((α : ℝ) - (β : ℝ)) • + ((R.operator β).comp (R.operator α)) := by + rw [R.resolvent_identity β α, neg_smul] + _ = ((β : ℝ) - (α : ℝ)) • + ((R.operator β).comp (R.operator α)) := by + rw [neg_sub] + +/-- The resolvent identity arranged as the core normalization formula. -/ +theorem scaledOperator_apply_sub_on_range (R : ContractiveResolvent E) + (α β : PositiveShift) (y : E) : + R.scaledOperator α (R.operator β y) - R.operator β y = + R.operator α ((β : ℝ) • R.operator β y - y) := by + have h := DFunLike.congr_fun (R.resolvent_identity α β) y + change + R.operator α y - R.operator β y = + ((β : ℝ) - (α : ℝ)) • R.operator α (R.operator β y) at h + change + (α : ℝ) • R.operator α (R.operator β y) - R.operator β y = + R.operator α ((β : ℝ) • R.operator β y - y) + rw [map_sub, map_smul] + change + (α : ℝ) • R.operator α (R.operator β y) - R.operator β y = + (β : ℝ) • R.operator α (R.operator β y) - R.operator α y + calc + (α : ℝ) • R.operator α (R.operator β y) - R.operator β y = + (α : ℝ) • R.operator α (R.operator β y) + + (R.operator α y - R.operator β y) - R.operator α y := by abel + _ = (α : ℝ) • R.operator α (R.operator β y) + + ((β : ℝ) - (α : ℝ)) • R.operator α (R.operator β y) - + R.operator α y := by rw [h] + _ = (β : ℝ) • R.operator α (R.operator β y) - R.operator α y := by module + +/-- Normalization converges on the range of any fixed resolvent. -/ +theorem tendsto_scaledOperator_apply_on_range (R : ContractiveResolvent E) + (μ : PositiveShift) (y : E) : + Tendsto (fun α : PositiveShift ↦ R.scaledOperator α (R.operator μ y)) + atTop (nhds (R.operator μ y)) := by + rw [tendsto_iff_dist_tendsto_zero] + have hbound : ∀ α : PositiveShift, + ‖R.scaledOperator α (R.operator μ y) - R.operator μ y‖ ≤ + ‖(μ : ℝ) • R.operator μ y - y‖ * (α : ℝ)⁻¹ := by + intro α + rw [R.scaledOperator_apply_sub_on_range α μ y] + calc + ‖R.operator α ((μ : ℝ) • R.operator μ y - y)‖ ≤ + ‖R.operator α‖ * ‖(μ : ℝ) • R.operator μ y - y‖ := + (R.operator α).le_opNorm _ + _ ≤ (α : ℝ)⁻¹ * ‖(μ : ℝ) • R.operator μ y - y‖ := + mul_le_mul_of_nonneg_right (R.opNorm_le_inv α) (norm_nonneg _) + _ = ‖(μ : ℝ) • R.operator μ y - y‖ * (α : ℝ)⁻¹ := mul_comm _ _ + simpa only [dist_eq_norm] using + squeeze_zero (fun α => norm_nonneg _) hbound + (tendsto_const_mul_positiveShift_inv_atTop_zero + ‖(μ : ℝ) • R.operator μ y - y‖) + +/-- The normalized resolvents converge strongly to the identity. -/ +theorem tendsto_scaledOperator_apply (R : ContractiveResolvent E) (x : E) : + Tendsto (fun α : PositiveShift ↦ R.scaledOperator α x) atTop (nhds x) := by + exact MarkovProcess.tendsto_of_denseRange_of_opNorm_le_one + R.scaledOperator (R.operator ⟨1, by norm_num⟩) + R.opNorm_scaledOperator_le_one (R.denseRange ⟨1, by norm_num⟩) + (R.tendsto_scaledOperator_apply_on_range ⟨1, by norm_num⟩) x + +end ContractiveResolvent + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/DenseCoreConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/DenseCoreConvergence.lean new file mode 100644 index 0000000000..fdc6a4e4db --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/DenseCoreConvergence.lean @@ -0,0 +1,102 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Analysis.Normed.Operator.Basic + +/-! +# Convergence from a dense core + +This module extends pointwise convergence of uniformly contractive continuous +linear maps from the range of a dense map to the whole ambient space. +-/ + +open Filter Topology + +namespace MarkovProcess + +/-- A family of continuous linear contractions that converges to the identity +on the range of a dense continuous linear map converges to the identity +everywhere. -/ +theorem tendsto_of_denseRange_of_opNorm_le_one + {E F ι : Type*} + [NormedAddCommGroup E] [NormedSpace ℝ E] + [NormedAddCommGroup F] [NormedSpace ℝ F] + {l : Filter ι} (T : ι → E →L[ℝ] E) (D : F →L[ℝ] E) + (hT : ∀ i, ‖T i‖ ≤ 1) (hD : DenseRange D) + (hcore : ∀ v, Tendsto (fun i ↦ T i (D v)) l (nhds (D v))) : + ∀ f, Tendsto (fun i ↦ T i f) l (nhds f) := by + intro f + rw [Metric.tendsto_nhds] + intro ε hε + obtain ⟨v, hv⟩ := hD.exists_dist_lt f (div_pos hε (by norm_num : (0 : ℝ) < 3)) + have hv' : dist (D v) f < ε / 3 := by + rw [dist_comm] + exact hv + have hcore_eventually : ∀ᶠ i in l, dist (T i (D v)) (D v) < ε / 3 := + (Metric.tendsto_nhds.mp (hcore v)) (ε / 3) (div_pos hε (by norm_num)) + filter_upwards [hcore_eventually] with i hi + have hcontract : dist (T i f) (T i (D v)) ≤ dist f (D v) := by + calc + dist (T i f) (T i (D v)) ≤ ‖T i‖ * dist f (D v) := (T i).dist_le_opNorm f (D v) + _ ≤ 1 * dist f (D v) := + mul_le_mul_of_nonneg_right (hT i) dist_nonneg + _ = dist f (D v) := one_mul _ + calc + dist (T i f) f ≤ dist (T i f) (T i (D v)) + dist (T i (D v)) f := + dist_triangle _ _ _ + _ ≤ dist (T i f) (T i (D v)) + + (dist (T i (D v)) (D v) + dist (D v) f) := + add_le_add le_rfl (dist_triangle _ _ _) + _ ≤ dist f (D v) + (dist (T i (D v)) (D v) + dist (D v) f) := + add_le_add hcontract le_rfl + _ < ε / 3 + (ε / 3 + ε / 3) := by + exact add_lt_add hv (add_lt_add hi hv') + _ = ε := by ring + +/-- Pointwise Cauchy convergence on the range of a dense continuous linear map +extends to the whole space for a sequence of contractions. -/ +theorem cauchySeq_of_denseRange_of_opNorm_le_one + {E F : Type*} + [NormedAddCommGroup E] [NormedSpace ℝ E] + [NormedAddCommGroup F] [NormedSpace ℝ F] + (T : ℕ → E →L[ℝ] E) (D : F →L[ℝ] E) + (hT : ∀ n, ‖T n‖ ≤ 1) (hD : DenseRange D) + (hcore : ∀ v, CauchySeq (fun n ↦ T n (D v))) : + ∀ x, CauchySeq (fun n ↦ T n x) := by + intro x + rw [Metric.cauchySeq_iff] + intro ε hε + obtain ⟨v, hv⟩ := hD.exists_dist_lt x (div_pos hε (by norm_num : (0 : ℝ) < 3)) + obtain ⟨N, hN⟩ := Metric.cauchySeq_iff.mp (hcore v) (ε / 3) + (div_pos hε (by norm_num)) + refine ⟨N, fun m hm n hn ↦ ?_⟩ + have hm_contract : dist (T m x) (T m (D v)) ≤ dist x (D v) := by + calc + dist (T m x) (T m (D v)) ≤ ‖T m‖ * dist x (D v) := + (T m).dist_le_opNorm x (D v) + _ ≤ 1 * dist x (D v) := mul_le_mul_of_nonneg_right (hT m) dist_nonneg + _ = dist x (D v) := one_mul _ + have hn_contract : dist (T n (D v)) (T n x) ≤ dist (D v) x := by + calc + dist (T n (D v)) (T n x) ≤ ‖T n‖ * dist (D v) x := + (T n).dist_le_opNorm (D v) x + _ ≤ 1 * dist (D v) x := mul_le_mul_of_nonneg_right (hT n) dist_nonneg + _ = dist (D v) x := one_mul _ + have hv' : dist (D v) x < ε / 3 := by + rw [dist_comm] + exact hv + calc + dist (T m x) (T n x) ≤ + dist (T m x) (T m (D v)) + dist (T m (D v)) (T n x) := + dist_triangle _ _ _ + _ ≤ dist (T m x) (T m (D v)) + + (dist (T m (D v)) (T n (D v)) + dist (T n (D v)) (T n x)) := + add_le_add le_rfl (dist_triangle _ _ _) + _ < ε / 3 + (ε / 3 + ε / 3) := by + exact add_lt_add (lt_of_le_of_lt hm_contract hv) + (add_lt_add (hN m hm n hn) (lt_of_le_of_lt hn_contract hv')) + _ = ε := by ring + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Duhamel.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Duhamel.lean new file mode 100644 index 0000000000..d1b6d50cb6 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Duhamel.lean @@ -0,0 +1,119 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Analysis.SpecialFunctions.Exponential +import Mathlib.Analysis.Calculus.Deriv.Mul +import Mathlib.MeasureTheory.Integral.IntervalIntegral.FundThmCalculus + +/-! +# Duhamel estimates for bounded generators + +This file gives the variation identity and contraction bounds needed to compare +exponentials of commuting bounded generators. The identity is oriented as +`exp (t B) - exp (t A)`, so its integrand acts on `(B - A) x` and the resulting +estimate is immediately applicable to Yosida approximants. +-/ + +open MeasureTheory NormedSpace Set + +namespace MarkovProcess.Semigroup + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] + +/- Head-class caches: the repeated closed instance searches in this file are all +rooted at the operator type `E →L[ℝ] E`; resolving each once here keeps the +normed-hierarchy walk on `E` from being replayed at every `•` and `exp`. -/ +private instance cacheSMulCLM : SMul ℝ (E →L[ℝ] E) := inferInstance +private instance cacheAlgebraCLM : Algebra ℝ (E →L[ℝ] E) := inferInstance +private instance cacheIsTopologicalRingCLM : IsTopologicalRing (E →L[ℝ] E) := inferInstance +private instance cacheCompleteSpaceCLM : CompleteSpace (E →L[ℝ] E) := inferInstance +/- `NormedSpace.exp`'s continuity lemma is now stated for a `ℚ`-normed algebra (the field +argument was dropped); this restricts the existing `NormedAlgebra ℝ (E →L[ℝ] E)` instance +along `ℚ ↪ ℝ` so `exp_continuous`/`fun_prop` can find it on `E →L[ℝ] E`. -/ +private noncomputable instance cacheNormedAlgebraRatCLM : NormedAlgebra ℚ (E →L[ℝ] E) := + NormedAlgebra.restrictScalars ℚ ℝ (E →L[ℝ] E) + +/-- Duhamel's identity for two commuting bounded generators, applied to a vector. -/ +theorem exp_sub_exp_apply_eq_integral (A B : E →L[ℝ] E) (hAB : Commute A B) + (t : ℝ) (x : E) : + exp (t • B) x - exp (t • A) x = + ∫ s in 0..t, exp ((t - s) • A) (exp (s • B) ((B - A) x)) := by + let F : ℝ → E := fun s ↦ exp ((t - s) • A) (exp (s • B) x) + let F' : ℝ → E := + fun s ↦ exp ((t - s) • A) (exp (s • B) ((B - A) x)) + have hderiv : ∀ s : ℝ, + HasDerivAt F (exp ((t - s) • A) (exp (s • B) ((B - A) x))) s := by + intro s + have haffine : HasDerivAt (fun u : ℝ ↦ t - u) (-1) s := + by simpa only [Pi.sub_apply, id_eq, zero_sub] using! + (hasDerivAt_const s t).sub (hasDerivAt_id s) + have hleft := HasDerivAt.scomp (𝕜 := ℝ) s + (hasDerivAt_exp_smul_const A (t - s)) haffine + have hright := HasDerivAt.clm_apply (hasDerivAt_exp_smul_const B s) + (hasDerivAt_const s x) + have hproduct := HasDerivAt.clm_apply hleft hright + have hmove : A (exp (s • B) x) = exp (s • B) (A x) := by + have hscaled : Commute A (s • B) := by + calc + A * (s • B) = s • (A * B) := Algebra.mul_smul_comm s A B + _ = s • (B * A) := congrArg (fun C : E →L[ℝ] E ↦ s • C) hAB.eq + _ = (s • B) * A := (Algebra.smul_mul_assoc s B A).symm + have heq : A * exp (s • B) = exp (s • B) * A := hscaled.exp_right + exact DFunLike.congr_fun heq x + refine hproduct.congr_deriv ?_ + simp only [one_smul, neg_smul, ContinuousLinearMap.map_zero, add_zero, + neg_apply, mul_apply_eq_comp, Function.comp_apply, sub_apply, hmove, map_sub] + abel + have hint : IntervalIntegrable F' volume 0 t := + (by fun_prop : Continuous F').intervalIntegrable 0 t + have hFTC := intervalIntegral.integral_eq_sub_of_hasDerivAt + (fun s _ ↦ hderiv s) hint + dsimp only [F] at hFTC + simpa only [sub_zero, sub_self, zero_smul, exp_zero, one_apply_eq_self] + using hFTC.symm + +/-- Duhamel's contraction estimate for two commuting bounded generators. -/ +theorem norm_exp_sub_exp_apply_le (A B : E →L[ℝ] E) (hAB : Commute A B) + {t : ℝ} (ht : 0 ≤ t) + (hA : ∀ s ∈ Icc (0 : ℝ) t, ‖exp (s • A)‖ ≤ 1) + (hB : ∀ s ∈ Icc (0 : ℝ) t, ‖exp (s • B)‖ ≤ 1) (x : E) : + ‖exp (t • B) x - exp (t • A) x‖ ≤ t * ‖(B - A) x‖ := by + rw [exp_sub_exp_apply_eq_integral A B hAB t x] + calc + ‖∫ s in 0..t, exp ((t - s) • A) (exp (s • B) ((B - A) x))‖ + ≤ ‖(B - A) x‖ * |t - 0| := by + refine intervalIntegral.norm_integral_le_of_norm_le_const fun s hs ↦ ?_ + rw [uIoc_of_le ht] at hs + have hsIcc : s ∈ Icc (0 : ℝ) t := ⟨hs.1.le, hs.2⟩ + have hts : t - s ∈ Icc (0 : ℝ) t := + ⟨sub_nonneg.mpr hs.2, sub_le_self t hs.1.le⟩ + calc + ‖exp ((t - s) • A) (exp (s • B) ((B - A) x))‖ + ≤ ‖exp ((t - s) • A)‖ * ‖exp (s • B) ((B - A) x)‖ := + (exp ((t - s) • A)).le_opNorm _ + _ ≤ 1 * ‖exp (s • B) ((B - A) x)‖ := + mul_le_mul_of_nonneg_right (hA (t - s) hts) (norm_nonneg _) + _ = ‖exp (s • B) ((B - A) x)‖ := one_mul _ + _ ≤ ‖exp (s • B)‖ * ‖(B - A) x‖ := + (exp (s • B)).le_opNorm _ + _ ≤ 1 * ‖(B - A) x‖ := + mul_le_mul_of_nonneg_right (hB s hsIcc) (norm_nonneg _) + _ = ‖(B - A) x‖ := one_mul _ + _ = t * ‖(B - A) x‖ := by rw [sub_zero, abs_of_nonneg ht, mul_comm] + +/-- A contractive bounded exponential moves a vector by at most time times the +norm of its generator applied to that vector. -/ +theorem norm_exp_apply_sub_le (A : E →L[ℝ] E) {t : ℝ} (ht : 0 ≤ t) + (hA : ∀ s ∈ Icc (0 : ℝ) t, ‖exp (s • A)‖ ≤ 1) (x : E) : + ‖exp (t • A) x - x‖ ≤ t * ‖A x‖ := by + have hzero : ∀ s ∈ Icc (0 : ℝ) t, + ‖exp (s • (0 : E →L[ℝ] E))‖ ≤ 1 := by + intro s hs + simpa only [smul_zero, exp_zero] using! ContinuousLinearMap.norm_id_le (𝕜 := ℝ) (E := E) + have h := norm_exp_sub_exp_apply_le (0 : E →L[ℝ] E) A + (Commute.zero_left A) ht hzero hA x + simpa only [smul_zero, exp_zero, one_apply_eq_self, sub_zero] using h + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialBounds.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialBounds.lean new file mode 100644 index 0000000000..35180d4238 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialBounds.lean @@ -0,0 +1,102 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Analysis.Normed.Algebra.Exponential +import Mathlib.Analysis.SpecialFunctions.Exponential + +/-! +# Norm bounds for Banach-algebra exponentials + +This file records elementary estimates for the exponential in a real Banach algebra. The +contraction estimate is tailored to exponentials of bounded Yosida-type generators. +-/ + +namespace MarkovProcess.Semigroup + +open NormedSpace + +variable {A : Type*} [NormedRing A] [NormedAlgebra ℝ A] + +/- `NormedSpace.exp_add_of_commute`'s continuity lemma is now stated for a `ℚ`-normed algebra +(the field argument was dropped); this restricts the existing `NormedAlgebra ℝ A` instance +along `ℚ ↪ ℝ` so it can be found on `A`. -/ +private noncomputable instance cacheNormedAlgebraRatA : NormedAlgebra ℚ A := + NormedAlgebra.restrictScalars ℚ ℝ A + +/-- The norm of a Banach-algebra exponential is bounded by the scalar exponential of the norm +when the multiplicative identity has norm at most one. -/ +theorem norm_exp_le_exp_norm_of_norm_one_le (hOne : ‖(1 : A)‖ ≤ 1) (a : A) : + ‖exp a‖ ≤ Real.exp ‖a‖ := by + have hscalar : HasSum (fun n : ℕ ↦ (Nat.factorial n : ℝ)⁻¹ * ‖a‖ ^ n) + (Real.exp ‖a‖) := by + rw [Real.exp_eq_exp_ℝ] + simpa only [smul_eq_mul] using! + (NormedSpace.exp_series_hasSum_exp' (𝕂 := ℝ) (𝔸 := ℝ) ‖a‖) + rw [exp_eq_tsum ℝ] + calc + ‖∑' n : ℕ, (Nat.factorial n : ℝ)⁻¹ • a ^ n‖ ≤ + ∑' n : ℕ, ‖(Nat.factorial n : ℝ)⁻¹ • a ^ n‖ := + norm_tsum_le_tsum_norm (norm_expSeries_summable' a) + _ ≤ ∑' n : ℕ, (Nat.factorial n : ℝ)⁻¹ * ‖a‖ ^ n := by + exact (norm_expSeries_summable' a).tsum_le_tsum (fun n ↦ by + rw [norm_smul, Real.norm_eq_abs, abs_of_nonneg (inv_nonneg.mpr (Nat.cast_nonneg _))] + refine mul_le_mul_of_nonneg_left ?_ (inv_nonneg.mpr (Nat.cast_nonneg _)) + cases n with + | zero => simpa only [pow_zero] using hOne + | succ n => exact norm_pow_le' a (Nat.succ_pos n)) + hscalar.summable + _ = Real.exp ‖a‖ := hscalar.tsum_eq + +/-- The norm of a normalized Banach-algebra exponential is bounded by the scalar exponential of +the norm. -/ +theorem norm_exp_le_exp_norm [NormOneClass A] (a : A) : ‖exp a‖ ≤ Real.exp ‖a‖ := + norm_exp_le_exp_norm_of_norm_one_le (by rw [norm_one]) a + +/-- If `Q` is a contraction and `c` is nonnegative, then `exp (c (Q - 1))` is a contraction. -/ +theorem norm_exp_smul_sub_one_le_one_of_norm_one_le [CompleteSpace A] + (hOne : ‖(1 : A)‖ ≤ 1) {c : ℝ} (hc : 0 ≤ c) {Q : A} (hQ : ‖Q‖ ≤ 1) : + ‖exp (c • (Q - 1))‖ ≤ 1 := by + have hsplit : c • (Q - 1) = c • Q + (-c) • (1 : A) := by module + have hcomm : Commute (c • Q) ((-c) • (1 : A)) := by + exact (Commute.one_right Q).smul_left c |>.smul_right (-c) + have hexp_scalar : exp ((-c) • (1 : A)) = algebraMap ℝ A (Real.exp (-c)) := by + have harg : (-c) • (1 : A) = algebraMap ℝ A (-c) := by + rw [Algebra.smul_def, mul_one] + rw [harg, Real.exp_eq_exp_ℝ] + exact (algebraMap_exp_comm (-c)).symm + calc + ‖exp (c • (Q - 1))‖ = + ‖exp (c • Q) * exp ((-c) • (1 : A))‖ := by + rw [hsplit, exp_add_of_commute hcomm] + _ ≤ ‖exp (c • Q)‖ * ‖exp ((-c) • (1 : A))‖ := norm_mul_le _ _ + _ ≤ + Real.exp ‖c • Q‖ * ‖exp ((-c) • (1 : A))‖ := + mul_le_mul_of_nonneg_right + (norm_exp_le_exp_norm_of_norm_one_le hOne (c • Q)) (norm_nonneg _) + _ ≤ Real.exp c * ‖exp ((-c) • (1 : A))‖ := by + refine mul_le_mul_of_nonneg_right (Real.exp_le_exp.mpr ?_) (norm_nonneg _) + rw [norm_smul, Real.norm_eq_abs, abs_of_nonneg hc] + exact mul_le_of_le_one_right hc hQ + _ ≤ Real.exp c * Real.exp (-c) := by + refine mul_le_mul_of_nonneg_left ?_ (Real.exp_pos c).le + rw [hexp_scalar, norm_algebraMap, Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] + exact mul_le_of_le_one_right (Real.exp_pos (-c)).le hOne + _ = 1 := by rw [← Real.exp_add, add_neg_cancel, Real.exp_zero] + +/-- The normalized version of `norm_exp_smul_sub_one_le_one_of_norm_one_le`. -/ +theorem norm_exp_smul_sub_one_le_one [CompleteSpace A] [NormOneClass A] + {c : ℝ} (hc : 0 ≤ c) {Q : A} (hQ : ‖Q‖ ≤ 1) : + ‖exp (c • (Q - 1))‖ ≤ 1 := + norm_exp_smul_sub_one_le_one_of_norm_one_le (by rw [norm_one]) hc hQ + +/-- Exponentiating a nonnegative multiple of a contractive endomorphism minus the identity gives +a contractive endomorphism. This includes the trivial ambient space. -/ +theorem norm_exp_continuousLinearMap_smul_sub_id_le_one + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] + {c : ℝ} (hc : 0 ≤ c) {Q : E →L[ℝ] E} (hQ : ‖Q‖ ≤ 1) : + ‖exp (c • (Q - ContinuousLinearMap.id ℝ E))‖ ≤ 1 := + norm_exp_smul_sub_one_le_one_of_norm_one_le ContinuousLinearMap.norm_id_le hc hQ + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialComparison.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialComparison.lean new file mode 100644 index 0000000000..238298b4ad --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialComparison.lean @@ -0,0 +1,229 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent + +/-! +# Exponential comparison under resolvent generation + +A pointwise exponential supersolution estimate for every sufficiently large normalized positive +resolvent passes through the Poisson representation of the Yosida approximants and then through +their strong limit to the generated semigroup. The represented kernel semigroup inherits the +same comparison for `C₀` observables. + +Public declarations: + +* `PositiveC0ContractiveResolvent.generatedSemigroup_apply_le_exp_mul`; +* `PositiveC0ContractiveResolvent.integral_kernelSemigroup_le_exp_mul`. + +No comparison for indicators of arbitrary measurable sets is asserted. +-/ + +open Filter Set Topology +open scoped NNReal ZeroAtInfty +open NormedSpace + +noncomputable section + +namespace MarkovProcess + +open _root_.MarkovProcess.Semigroup + +namespace PositiveC0ContractiveResolvent + +variable {X : Type*} [TopologicalSpace X] + +/-- Iterating a positive operator preserves a scalar pointwise supersolution estimate. -/ +private theorem pow_apply_le_pow_mul + (T : C₀(X, ℝ) →L[ℝ] C₀(X, ℝ)) (hT : PositiveC0OperatorMeasure.IsPositive T) + (v : C₀(X, ℝ)) (a : ℝ) (ha : 0 ≤ a) + (hTv : ∀ x, T v x ≤ a * v x) : + ∀ n x, (T ^ n) v x ≤ a ^ n * v x := by + intro n + induction n with + | zero => + intro x + simp only [pow_zero, one_apply_eq_self, one_mul] + exact le_rfl + | succ n ih => + intro x + rw [pow_succ', mul_apply_eq_comp] + calc + T ((T ^ n) v) x ≤ T (a ^ n • v) x := + PositiveC0OperatorMeasure.apply_le_apply_of_isPositive T hT (fun y ↦ by + simpa only [ContinuousMap.coe_smul, Pi.smul_apply, smul_eq_mul] using! ih y) x + _ = a ^ n * T v x := by rw [map_smul]; rfl + _ ≤ a ^ n * (a * v x) := + mul_le_mul_of_nonneg_left (hTv x) (pow_nonneg ha n) + _ = a ^ (n + 1) * v x := by rw [pow_succ]; ring + +/-- The scalar sum obtained by weighting geometric powers with the Poisson coefficients. -/ +private theorem tsum_poissonWeight_mul_pow (c a : ℝ) : + ∑' n : ℕ, poissonWeight c n * a ^ n = Real.exp (c * (a - 1)) := by + have hsum : ∑' n : ℕ, (c * a) ^ n / n.factorial = Real.exp (c * a) := by + rw [Real.exp_eq_exp_ℝ, NormedSpace.exp_eq_tsum ℝ] + apply tsum_congr + intro n + simp only [div_eq_mul_inv, smul_eq_mul] + ring + unfold poissonWeight + rw [show (fun n : ℕ ↦ Real.exp (-c) * (c ^ n / n.factorial) * a ^ n) = + fun n ↦ Real.exp (-c) * ((c * a) ^ n / n.factorial) by + funext n + rw [mul_pow] + ring] + rw [tsum_mul_left, hsum, ← Real.exp_add] + congr 1 + ring + +/-- The scalar exponent in the Yosida comparison converges to its semigroup counterpart. -/ +private theorem tendsto_mul_naturalShift_div_sub (b theta : ℝ) : + Tendsto (fun n : ℕ ↦ + b * (naturalShift n : ℝ) / ((naturalShift n : ℝ) - theta)) + atTop (nhds b) := by + have hden : Tendsto (fun n : ℕ ↦ (n : ℝ) + (1 - theta)) atTop atTop := + tendsto_atTop_add_const_right atTop (1 - theta) tendsto_natCast_atTop_atTop + have hsmall : Tendsto (fun n : ℕ ↦ theta / ((n : ℝ) + (1 - theta))) + atTop (nhds 0) := hden.const_div_atTop theta + have hone : Tendsto (fun _ : ℕ ↦ (1 : ℝ)) atTop (nhds 1) := tendsto_const_nhds + have hmain : Tendsto (fun n : ℕ ↦ + b * (1 + theta / ((n : ℝ) + (1 - theta)))) atTop (nhds b) := by + simpa only [add_zero, mul_one] using (hone.add hsmall).const_mul b + apply hmain.congr' + filter_upwards [hden.eventually (eventually_gt_atTop 0)] with n hn + rw [naturalShift_coe] + have hden' : 0 < (n : ℝ) + 1 - theta := by + linarith only [hn] + field_simp [hden'.ne'] + ring + +/-- A Yosida approximant satisfies the exponential comparison furnished by one normalized +resolvent estimate. -/ +private theorem yosidaOperator_apply_le_exp_mul + (R : PositiveC0ContractiveResolvent X) (theta : ℝ) (v : C₀(X, ℝ)) + (mu : PositiveShift) (hmu : theta < (mu : ℝ)) + (hR : ∀ x, (mu : ℝ) * R.toContractiveResolvent.operator mu v x ≤ + (mu : ℝ) / ((mu : ℝ) - theta) * v x) + (t : NNReal) (x : X) : + R.toContractiveResolvent.yosidaOperator mu t v x ≤ + Real.exp (theta * (t : ℝ) * (mu : ℝ) / ((mu : ℝ) - theta)) * v x := by + let Q := R.toContractiveResolvent.scaledOperator mu + let c : ℝ := (t : ℝ) * (mu : ℝ) + let a : ℝ := (mu : ℝ) / ((mu : ℝ) - theta) + have hden : 0 < (mu : ℝ) - theta := sub_pos.mpr hmu + have ha : 0 ≤ a := div_nonneg mu.property.le hden.le + have hQpos : PositiveC0OperatorMeasure.IsPositive Q := by + intro f hf y + exact mul_nonneg mu.property.le (R.isPositive mu f hf y) + have hQv : ∀ y, Q v y ≤ a * v y := by + intro y + exact hR y + have hpowers : ∀ n y, (Q ^ n) v y ≤ a ^ n * v y := + pow_apply_le_pow_mul Q hQpos v a ha hQv + have hleftC0 : Summable fun n : ℕ ↦ poissonWeight c n • (Q ^ n) v := + summable_poissonWeight_smul_pow_apply Q c v + have hleft : Summable fun n : ℕ ↦ poissonWeight c n * (Q ^ n) v x := by + simpa only [Function.comp_apply, smul_apply, smul_eq_mul] using! + hleftC0.map (c0EvalCLM x) (c0EvalCLM x).continuous + have hright : Summable fun n : ℕ ↦ poissonWeight c n * (a ^ n * v x) := by + have hscalar : Summable fun n : ℕ ↦ poissonWeight c n * a ^ n := by + unfold poissonWeight + rw [show (fun n : ℕ ↦ Real.exp (-c) * (c ^ n / n.factorial) * a ^ n) = + fun n ↦ Real.exp (-c) * ((c * a) ^ n / n.factorial) by + funext n + rw [mul_pow] + ring] + exact (Real.summable_pow_div_factorial (c * a)).mul_left _ + simpa only [mul_assoc] using hscalar.mul_right (v x) + rw [ContractiveResolvent.yosidaOperator, ContractiveResolvent.yosidaGenerator, smul_smul] + change exp (c • (Q - ContinuousLinearMap.id ℝ C₀(X, ℝ))) v x ≤ _ + rw [exp_smul_sub_id_apply_eq_tsum] + change (∑' n : ℕ, poissonWeight c n • (Q ^ n) v) x ≤ _ + rw [show (∑' n : ℕ, poissonWeight c n • (Q ^ n) v) x = + ∑' n : ℕ, poissonWeight c n * (Q ^ n) v x by + change c0EvalCLM x (∑' n : ℕ, poissonWeight c n • (Q ^ n) v) = _ + rw [(c0EvalCLM x).map_tsum hleftC0] + apply tsum_congr + intro n + rfl] + calc + (∑' n : ℕ, poissonWeight c n * (Q ^ n) v x) ≤ + ∑' n : ℕ, poissonWeight c n * (a ^ n * v x) := + hleft.tsum_le_tsum (fun n ↦ + mul_le_mul_of_nonneg_left (hpowers n x) (poissonWeight_nonneg + (mul_nonneg t.property mu.property.le) n)) hright + _ = (∑' n : ℕ, poissonWeight c n * a ^ n) * v x := by + rw [show (fun n : ℕ ↦ poissonWeight c n * (a ^ n * v x)) = + fun n ↦ (poissonWeight c n * a ^ n) * v x by + funext n + ring] + rw [tsum_mul_right] + _ = Real.exp (c * (a - 1)) * v x := by rw [tsum_poissonWeight_mul_pow] + _ = Real.exp (theta * (t : ℝ) * (mu : ℝ) / ((mu : ℝ) - theta)) * v x := by + congr 2 + dsimp only [c, a] + field_simp + ring + +/-- **Exponential comparison is stable under resolvent generation.** A pointwise +supersolution estimate for every normalized resolvent above `theta` passes to the canonical +semigroup generated by the resolvent. -/ +theorem generatedSemigroup_apply_le_exp_mul + (R : PositiveC0ContractiveResolvent X) (theta : ℝ) (v : C₀(X, ℝ)) + (hR : ∀ mu : PositiveShift, theta < (mu : ℝ) → ∀ x, + (mu : ℝ) * R.toContractiveResolvent.operator mu v x ≤ + (mu : ℝ) / ((mu : ℝ) - theta) * v x) + (t : NNReal) (x : X) : + R.toContractiveResolvent.generatedSemigroup t v x ≤ + Real.exp (theta * (t : ℝ)) * v x := by + have hleft : Tendsto (fun n ↦ + R.toContractiveResolvent.yosidaSemigroup (naturalShift n) t v x) + atTop (nhds (R.toContractiveResolvent.generatedSemigroup t v x)) := by + change Tendsto (fun n ↦ c0EvalCLM x + (R.toContractiveResolvent.yosidaSemigroup (naturalShift n) t v)) _ _ + exact (c0EvalCLM x).continuous.continuousAt.tendsto.comp + (R.toContractiveResolvent.tendsto_yosidaSemigroup_naturalShift_apply_generatedSemigroup + t v) + have hscalar := tendsto_mul_naturalShift_div_sub (theta * (t : ℝ)) theta + have hright : Tendsto (fun n ↦ + Real.exp (theta * (t : ℝ) * (naturalShift n : ℝ) / + ((naturalShift n : ℝ) - theta)) * v x) + atTop (nhds (Real.exp (theta * (t : ℝ)) * v x)) := + (Real.continuous_exp.continuousAt.tendsto.comp hscalar).mul_const (v x) + apply le_of_tendsto_of_tendsto hleft hright + have hmuTop : Tendsto (fun n : ℕ ↦ (naturalShift n : ℝ)) atTop atTop := + tendsto_positiveShift_coe_atTop.comp tendsto_naturalShift_atTop + filter_upwards [hmuTop.eventually (eventually_gt_atTop theta)] with n hn + exact yosidaOperator_apply_le_exp_mul R theta v (naturalShift n) hn + (hR (naturalShift n) hn) t x + +section Kernel + +variable [T2Space X] [LocallyCompactSpace X] [SecondCountableTopology X] + [MeasurableSpace X] [BorelSpace X] + +/-- The represented kernel semigroup inherits the generated semigroup's exponential comparison +for every `C₀` observable below the supersolution. -/ +theorem integral_kernelSemigroup_le_exp_mul + (R : PositiveC0ContractiveResolvent X) (theta : ℝ) (v : C₀(X, ℝ)) + (hR : ∀ mu : PositiveShift, theta < (mu : ℝ) → ∀ x, + (mu : ℝ) * R.toContractiveResolvent.operator mu v x ≤ + (mu : ℝ) / ((mu : ℝ) - theta) * v x) + (f : C₀(X, ℝ)) (hfv : ∀ x, f x ≤ v x) (t : NNReal) (x : X) : + ∫ y, f y ∂R.kernelSemigroup t x ≤ Real.exp (theta * (t : ℝ)) * v x := by + rw [R.integral_kernelSemigroup] + calc + R.toContractiveResolvent.generatedSemigroup t f x ≤ + R.toContractiveResolvent.generatedSemigroup t v x := + PositiveC0OperatorMeasure.apply_le_apply_of_isPositive _ + (R.isPositive_generatedSemigroup t) hfv x + _ ≤ Real.exp (theta * (t : ℝ)) * v x := + R.generatedSemigroup_apply_le_exp_mul theta v hR t x + +end Kernel + +end PositiveC0ContractiveResolvent + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generation.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generation.lean new file mode 100644 index 0000000000..28126e6103 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generation.lean @@ -0,0 +1,99 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity + +/-! +# Generation of a contraction semigroup from a contractive resolvent + +This file packages the strong limit of the Yosida exponential approximations +as a strongly continuous contraction semigroup. Strong continuity at zero is +first proved on the range of one resolvent and then extended by density. +-/ + +open Filter NormedSpace Set Topology + +noncomputable section + +namespace MarkovProcess.Semigroup + +namespace ContractiveResolvent + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] + +/-- On the range of a fixed resolvent, the strong Yosida limit moves a vector +by at most time times a constant independent of time. -/ +theorem exists_norm_yosidaStrongLimit_apply_sub_on_range_le + (R : ContractiveResolvent E) (mu : PositiveShift) (y : E) : + ∃ C : ℝ, ∀ t : NNReal, + ‖R.yosidaStrongLimit t (R.operator mu y) - R.operator mu y‖ ≤ (t : ℝ) * C := by + have hgen := R.cauchySeq_yosidaGenerator_naturalShift_apply_operator mu y + obtain ⟨C, hC⟩ := hgen.isBounded_range.exists_norm_le + refine ⟨C, fun t ↦ ?_⟩ + refine le_of_tendsto + ((R.tendsto_yosidaOperator_naturalShift_apply t (R.operator mu y)).sub + tendsto_const_nhds).norm ?_ + exact Eventually.of_forall fun n ↦ by + have hcontract : ∀ s ∈ Icc (0 : ℝ) (t : ℝ), + ‖exp (s • R.yosidaGenerator (naturalShift n))‖ ≤ 1 := by + intro s hs + have h := R.norm_yosidaOperator_le_one (naturalShift n) ⟨s, hs.1⟩ + simp only [yosidaOperator] at h + exact h + exact (norm_exp_apply_sub_le (R.yosidaGenerator (naturalShift n)) + (NNReal.coe_nonneg t) hcontract (R.operator mu y)).trans + (mul_le_mul_of_nonneg_left + (hC _ ⟨n, rfl⟩) (NNReal.coe_nonneg t)) + +/-- The strong Yosida limit converges to the identity at time zero on the +range of every fixed resolvent. -/ +theorem tendsto_yosidaStrongLimit_apply_operator_zero + (R : ContractiveResolvent E) (mu : PositiveShift) (y : E) : + Tendsto (fun t : NNReal ↦ R.yosidaStrongLimit t (R.operator mu y)) + (nhds 0) (nhds (R.operator mu y)) := by + rw [tendsto_iff_norm_sub_tendsto_zero] + obtain ⟨C, hC⟩ := R.exists_norm_yosidaStrongLimit_apply_sub_on_range_le mu y + refine squeeze_zero (fun t ↦ norm_nonneg _) hC ?_ + have hcoe : Tendsto (fun t : NNReal ↦ (t : ℝ)) (nhds 0) (nhds 0) := + NNReal.tendsto_coe.2 tendsto_id + simpa only [NNReal.coe_zero, zero_mul] using + (hcoe.mul (tendsto_const_nhds (x := C))) + +/-- The strong Yosida limit converges to the identity at time zero on the +whole space. -/ +theorem tendsto_yosidaStrongLimit_apply_zero + (R : ContractiveResolvent E) (x : E) : + Tendsto (fun t : NNReal ↦ R.yosidaStrongLimit t x) (nhds 0) (nhds x) := by + let one : PositiveShift := ⟨1, by norm_num⟩ + exact MarkovProcess.tendsto_of_denseRange_of_opNorm_le_one + R.yosidaStrongLimit (R.operator one) R.norm_yosidaStrongLimit_le_one + (R.denseRange one) (R.tendsto_yosidaStrongLimit_apply_operator_zero one) x + +/-- The strongly continuous contraction semigroup generated canonically by a +contractive resolvent through its Yosida approximations. -/ +def generatedSemigroup (R : ContractiveResolvent E) : + StronglyContinuousContractionSemigroup E := + StronglyContinuousContractionSemigroup.ofTendstoZero + R.yosidaStrongLimit R.yosidaStrongLimit_zero R.yosidaStrongLimit_add + R.norm_yosidaStrongLimit_le_one R.tendsto_yosidaStrongLimit_apply_zero + +@[simp] +theorem generatedSemigroup_apply (R : ContractiveResolvent E) (t : NNReal) : + R.generatedSemigroup t = R.yosidaStrongLimit t := + rfl + +/-- The canonical bounded Yosida semigroups converge strongly to the generated +semigroup. -/ +theorem tendsto_yosidaSemigroup_naturalShift_apply_generatedSemigroup + (R : ContractiveResolvent E) (t : NNReal) (x : E) : + Tendsto (fun n ↦ R.yosidaSemigroup (naturalShift n) t x) atTop + (nhds (R.generatedSemigroup t x)) := by + exact R.tendsto_yosidaOperator_naturalShift_apply t x + +end ContractiveResolvent + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generator.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generator.lean new file mode 100644 index 0000000000..99e6ffcf4b --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generator.lean @@ -0,0 +1,471 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit +import Mathlib.Analysis.Calculus.Deriv.Mul +import Mathlib.Analysis.SpecialFunctions.ExpDeriv +import Mathlib.MeasureTheory.Integral.IntervalIntegral.FundThmCalculus + +/-! +# The generator of a strongly continuous contraction semigroup + +For `S : StronglyContinuousContractionSemigroup E` this file defines the generator domain +`S.generatorDomain`, the submodule of vectors `f` whose difference quotients +`t⁻¹ • (S t f - f)` converge as `t → 0⁺`, and the generator +`S.generator : S.generatorDomain →ₗ[ℝ] E` as that limit. The main results are: + +* `tendsto_generator`: the defining limit, and `generator_eq_of_tendsto`, its uniqueness; +* `operator_mem_generatorDomain` and `generator_operator`: the domain is invariant under every + `S t`, and `S t` commutes with the generator; +* `tendsto_differenceQuotient_add`: every orbit `t ↦ S t f` of a vector in the domain is right + differentiable at every time, with derivative `S t (S.generator f)`; its real-variable forms are + `hasDerivWithinAt_Ioi` and `hasDerivWithinAt_Ici`, and at positive times the derivative is + two-sided, `hasDerivAt_operator_toNNReal`; +* `operator_sub_eq_integral` and `exp_smul_operator_sub_eq_integral`: the fundamental identity + and its exponentially weighted form; +* `orbitIntegral_mem_generatorDomain` and `generator_orbitIntegral`: for every vector `f`, the + orbit integral `∫₀ᵗ S s f ds` lies in the domain with generator `S t f - f`; hence + `dense_generatorDomain`, the domain is dense. + +Times are `NNReal` throughout the library; the real-variable statements read the semigroup at +`Real.toNNReal s`. The fundamental identity is what Dynkin's formula consumes. +-/ + +open Filter Topology +open scoped NNReal + +namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +noncomputable section + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] +variable (S : StronglyContinuousContractionSemigroup E) + +section DifferenceQuotient + +/-- The difference quotient `t⁻¹ • (S t f - f)` of the orbit of `f` at time zero. -/ +def differenceQuotient (f : E) (t : NNReal) : E := (t : ℝ)⁻¹ • (S t f - f) + +/-- The difference quotient, unfolded. -/ +theorem differenceQuotient_apply (f : E) (t : NNReal) : + S.differenceQuotient f t = (t : ℝ)⁻¹ • (S t f - f) := rfl + +/-- Difference quotients are additive in the vector. -/ +theorem differenceQuotient_add (f g : E) (t : NNReal) : + S.differenceQuotient (f + g) t = S.differenceQuotient f t + S.differenceQuotient g t := by + rw [differenceQuotient, differenceQuotient, differenceQuotient, map_add, add_sub_add_comm, + smul_add] + +/-- Difference quotients are homogeneous in the vector. -/ +theorem differenceQuotient_smul (c : ℝ) (f : E) (t : NNReal) : + S.differenceQuotient (c • f) t = c • S.differenceQuotient f t := by + rw [differenceQuotient, differenceQuotient, map_smul, ← smul_sub, smul_comm] + +/-- The difference quotient of the zero vector vanishes. -/ +theorem differenceQuotient_zero (t : NNReal) : S.differenceQuotient 0 t = 0 := by + rw [differenceQuotient, map_zero, sub_zero, smul_zero] + +/-- The operator `S s` commutes with difference quotients. -/ +theorem differenceQuotient_operator (f : E) (s t : NNReal) : + S.differenceQuotient (S s f) t = S s (S.differenceQuotient f t) := by + rw [differenceQuotient, differenceQuotient, map_smul, map_sub, S.commute_apply] + +end DifferenceQuotient + +section Domain + +/-- The generator domain of `S`: the vectors whose difference quotients `t⁻¹ • (S t f - f)` +converge as `t → 0⁺`. It is a linear subspace of `E`. -/ +def generatorDomain : Submodule ℝ E where + carrier := {f | ∃ g : E, Tendsto (S.differenceQuotient f) (𝓝[>] 0) (𝓝 g)} + add_mem' := by + rintro f g ⟨a, ha⟩ ⟨b, hb⟩ + refine ⟨a + b, (ha.add hb).congr fun t ↦ ?_⟩ + exact (S.differenceQuotient_add f g t).symm + zero_mem' := by + refine ⟨0, ?_⟩ + have hzero : S.differenceQuotient 0 = fun _ ↦ 0 := funext (S.differenceQuotient_zero) + rw [hzero] + exact tendsto_const_nhds + smul_mem' := by + rintro c f ⟨a, ha⟩ + refine ⟨c • a, (ha.const_smul c).congr fun t ↦ ?_⟩ + exact (S.differenceQuotient_smul c f t).symm + +/-- Membership in the generator domain, unfolded. -/ +theorem mem_generatorDomain_iff {f : E} : + f ∈ S.generatorDomain ↔ ∃ g : E, Tendsto (S.differenceQuotient f) (𝓝[>] 0) (𝓝 g) := + Iff.rfl + +/-- A vector whose difference quotients converge lies in the generator domain. -/ +theorem mem_generatorDomain_of_tendsto {f g : E} + (h : Tendsto (fun t : NNReal ↦ (t : ℝ)⁻¹ • (S t f - f)) (𝓝[>] 0) (𝓝 g)) : + f ∈ S.generatorDomain := + ⟨g, h⟩ + +end Domain + +section Generator + +/-- The limit of the difference quotients, for a vector of the domain. -/ +private noncomputable def generatorFun (f : S.generatorDomain) : E := + limUnder (𝓝[>] (0 : NNReal)) (S.differenceQuotient f) + +private theorem tendsto_generatorFun (f : S.generatorDomain) : + Tendsto (S.differenceQuotient f) (𝓝[>] 0) (𝓝 (S.generatorFun f)) := + tendsto_nhds_limUnder (S.mem_generatorDomain_iff.mp f.2) + +private theorem generatorFun_eq_of_tendsto (f : S.generatorDomain) {g : E} + (h : Tendsto (S.differenceQuotient f) (𝓝[>] 0) (𝓝 g)) : S.generatorFun f = g := + tendsto_nhds_unique (S.tendsto_generatorFun f) h + +/-- The generator of `S`, as a linear map on its domain: `S.generator f` is the limit of the +difference quotients `t⁻¹ • (S t f - f)` as `t → 0⁺`. -/ +noncomputable def generator : S.generatorDomain →ₗ[ℝ] E where + toFun := S.generatorFun + map_add' f g := by + apply S.generatorFun_eq_of_tendsto + refine ((S.tendsto_generatorFun f).add (S.tendsto_generatorFun g)).congr fun t ↦ ?_ + rw [Submodule.coe_add, differenceQuotient_add] + map_smul' c f := by + apply S.generatorFun_eq_of_tendsto + refine ((S.tendsto_generatorFun f).const_smul c).congr fun t ↦ ?_ + rw [Submodule.coe_smul, differenceQuotient_smul] + +/-- The defining property of the generator: the difference quotients of a vector of the domain +converge to its generator. -/ +theorem tendsto_generator (f : S.generatorDomain) : + Tendsto (S.differenceQuotient f) (𝓝[>] 0) (𝓝 (S.generator f)) := + S.tendsto_generatorFun f + +/-- The defining property of the generator, with the difference quotient written out. -/ +theorem tendsto_generator' (f : S.generatorDomain) : + Tendsto (fun t : NNReal ↦ (t : ℝ)⁻¹ • (S t f - f)) (𝓝[>] 0) (𝓝 (S.generator f)) := + S.tendsto_generatorFun f + +/-- The generator is the unique limit of the difference quotients. -/ +theorem generator_eq_of_tendsto (f : S.generatorDomain) {g : E} + (h : Tendsto (fun t : NNReal ↦ (t : ℝ)⁻¹ • (S t f - f)) (𝓝[>] 0) (𝓝 g)) : + S.generator f = g := + S.generatorFun_eq_of_tendsto f h + +/-- The generator of a vector given by a convergence proof. -/ +theorem generator_mk_eq {f g : E} + (h : Tendsto (fun t : NNReal ↦ (t : ℝ)⁻¹ • (S t f - f)) (𝓝[>] 0) (𝓝 g)) : + S.generator ⟨f, S.mem_generatorDomain_of_tendsto h⟩ = g := + S.generator_eq_of_tendsto _ h + +end Generator + +section Invariance + +/-- The generator domain is invariant under the semigroup. -/ +theorem operator_mem_generatorDomain (f : S.generatorDomain) (t : NNReal) : + S t f ∈ S.generatorDomain := by + refine ⟨S t (S.generator f), ?_⟩ + refine (((S t).continuous.tendsto _).comp (S.tendsto_generator f)).congr fun h ↦ ?_ + exact (S.differenceQuotient_operator f t h).symm + +/-- The semigroup commutes with its generator on the generator domain. -/ +theorem generator_operator (f : S.generatorDomain) (t : NNReal) : + S.generator ⟨S t f, S.operator_mem_generatorDomain f t⟩ = S t (S.generator f) := by + apply S.generator_eq_of_tendsto + refine (((S t).continuous.tendsto _).comp (S.tendsto_generator f)).congr fun h ↦ ?_ + exact (S.differenceQuotient_operator f t h).symm + +/-- Right differentiability of orbits: for `f` in the generator domain and every time `t`, the +difference quotients of `h ↦ S (t + h) f` at `h = 0⁺` converge to `S t (S.generator f)`. -/ +theorem tendsto_differenceQuotient_add (f : S.generatorDomain) (t : NNReal) : + Tendsto (fun h : NNReal ↦ (h : ℝ)⁻¹ • (S (t + h) f - S t f)) (𝓝[>] 0) + (𝓝 (S t (S.generator f))) := by + refine (((S t).continuous.tendsto _).comp (S.tendsto_generator f)).congr fun h ↦ ?_ + show S t ((h : ℝ)⁻¹ • (S h f - f)) = (h : ℝ)⁻¹ • (S (t + h) f - S t f) + rw [map_smul, map_sub, S.add_apply] + +end Invariance + +section RealVariable + +/-- Reading `NNReal` times from the right of a real time: `y ↦ Real.toNNReal (y - t)` sends the +right neighbourhood filter of `t` to the right neighbourhood filter of `0`. -/ +theorem tendsto_toNNReal_sub (t : NNReal) : + Tendsto (fun y : ℝ ↦ Real.toNNReal (y - t)) (𝓝[>] (t : ℝ)) (𝓝[>] 0) := by + apply tendsto_nhdsWithin_of_tendsto_nhds_of_eventually_within + · have h : Tendsto (fun y : ℝ ↦ Real.toNNReal (y - t)) (𝓝 (t : ℝ)) + (𝓝 (Real.toNNReal ((t : ℝ) - t))) := + (continuous_real_toNNReal.tendsto _).comp ((continuous_id.sub continuous_const).tendsto _) + rw [sub_self, Real.toNNReal_zero] at h + exact h.mono_left nhdsWithin_le_nhds + · filter_upwards [self_mem_nhdsWithin] with y hy + exact Set.mem_Ioi.mpr (Real.toNNReal_pos.mpr (sub_pos.mpr hy)) + +/-- Reading `NNReal` times from the left of a real time: `y ↦ Real.toNNReal (t - y)` sends the +left neighbourhood filter of `t` to the right neighbourhood filter of `0`. -/ +theorem tendsto_toNNReal_const_sub (t : ℝ) : + Tendsto (fun y : ℝ ↦ Real.toNNReal (t - y)) (𝓝[<] t) (𝓝[>] 0) := by + apply tendsto_nhdsWithin_of_tendsto_nhds_of_eventually_within + · have h : Tendsto (fun y : ℝ ↦ Real.toNNReal (t - y)) (𝓝 t) + (𝓝 (Real.toNNReal (t - t))) := + (continuous_real_toNNReal.tendsto _).comp ((continuous_const.sub continuous_id).tendsto _) + rw [sub_self, Real.toNNReal_zero] at h + exact h.mono_left nhdsWithin_le_nhds + · filter_upwards [self_mem_nhdsWithin] with y hy + exact Set.mem_Ioi.mpr (Real.toNNReal_pos.mpr (sub_pos.mpr hy)) + +/-- The orbit of any vector, read in the real variable, is continuous. -/ +theorem continuous_operator_toNNReal (f : E) : + Continuous fun s : ℝ ↦ S (Real.toNNReal s) f := + (S.continuous f).comp continuous_real_toNNReal + +/-- Right derivative in the real variable: for `f` in the generator domain and every +`t : NNReal`, the orbit `s ↦ S (Real.toNNReal s) f` has right derivative `S t (S.generator f)` +at `t`. -/ +theorem hasDerivWithinAt_Ioi (f : S.generatorDomain) (t : NNReal) : + HasDerivWithinAt (fun s : ℝ ↦ S (Real.toNNReal s) f) (S t (S.generator f)) + (Set.Ioi (t : ℝ)) t := by + rw [hasDerivWithinAt_iff_tendsto_slope] + have hdiff : Set.Ioi (t : ℝ) \ {(t : ℝ)} = Set.Ioi (t : ℝ) := by + ext y + simp only [Set.mem_sdiff, Set.mem_Ioi, Set.mem_singleton_iff, and_iff_left_iff_imp] + exact fun hy ↦ ne_of_gt hy + rw [hdiff] + refine ((S.tendsto_differenceQuotient_add f t).comp (tendsto_toNNReal_sub t)).congr' ?_ + filter_upwards [self_mem_nhdsWithin] with y hy + have hyt : (t : ℝ) < y := hy + have hy0 : (0 : ℝ) ≤ y := le_trans t.coe_nonneg hyt.le + have hcoe : ((Real.toNNReal (y - t) : NNReal) : ℝ) = y - t := + Real.coe_toNNReal _ (sub_nonneg.mpr hyt.le) + have htoNN : Real.toNNReal y = t + Real.toNNReal (y - t) := by + apply NNReal.coe_injective + rw [NNReal.coe_add, hcoe, Real.coe_toNNReal y hy0] + ring + show ((Real.toNNReal (y - t) : NNReal) : ℝ)⁻¹ • + (S (t + Real.toNNReal (y - t)) f - S t f) = + slope (fun s : ℝ ↦ S (Real.toNNReal s) f) (t : ℝ) y + rw [slope_def_module, hcoe, Real.toNNReal_coe, htoNN] + +/-- Right derivative in the real variable, on the closed right neighbourhood: for `f` in the +generator domain and every `t : NNReal`, the orbit `s ↦ S (Real.toNNReal s) f` has derivative +`S t (S.generator f)` within `Ici t` at `t`. This is the form consumed by Grönwall estimates. -/ +theorem hasDerivWithinAt_Ici (f : S.generatorDomain) (t : NNReal) : + HasDerivWithinAt (fun s : ℝ ↦ S (Real.toNNReal s) f) (S t (S.generator f)) + (Set.Ici (t : ℝ)) t := + (S.hasDerivWithinAt_Ioi f t).Ici_of_Ioi + +/-- Left derivative in the real variable: at a positive time `t`, the left difference quotients +of the orbit of a vector of the generator domain also converge to `S t (S.generator f)`. The +identity `S t f - S y f = S y (S (t - y) f - f)` for `y < t` moves the increment to time zero, +where the generator limit applies, and contractivity carries it back. -/ +theorem hasDerivWithinAt_Iic (f : S.generatorDomain) {t : ℝ} (ht : 0 < t) : + HasDerivWithinAt (fun s : ℝ ↦ S (Real.toNNReal s) f) + (S (Real.toNNReal t) (S.generator f)) (Set.Iic t) t := by + rw [hasDerivWithinAt_iff_tendsto_slope] + have hdiff : Set.Iic t \ {t} = Set.Iio t := by + ext y + simp only [Set.mem_sdiff, Set.mem_Iic, Set.mem_singleton_iff, Set.mem_Iio] + exact ⟨fun hy ↦ lt_of_le_of_ne hy.1 hy.2, fun hy ↦ ⟨hy.le, hy.ne⟩⟩ + rw [hdiff] + have horbit : Tendsto (fun y : ℝ ↦ S (Real.toNNReal y) (S.generator f)) (𝓝[<] t) + (𝓝 (S (Real.toNNReal t) (S.generator f))) := + ((S.continuous_operator_toNNReal (S.generator f)).tendsto t).mono_left nhdsWithin_le_nhds + have hquot : Tendsto (fun y : ℝ ↦ S.differenceQuotient f (Real.toNNReal (t - y))) (𝓝[<] t) + (𝓝 (S.generator f)) := + (S.tendsto_generator f).comp (tendsto_toNNReal_const_sub t) + have hmain := tendsto_apply_of_opNorm_le_one (fun y : ℝ ↦ S (Real.toNNReal y)) + (S (Real.toNNReal t)) (fun y : ℝ ↦ S.differenceQuotient f (Real.toNNReal (t - y))) + (S.generator f) (fun y ↦ S.norm_operator_le_one _) horbit hquot + refine hmain.congr' ?_ + filter_upwards [Ioo_mem_nhdsLT ht] with y hy + have hcoe : ((Real.toNNReal (t - y) : NNReal) : ℝ) = t - y := + Real.coe_toNNReal _ (sub_nonneg.mpr hy.2.le) + have hsum : Real.toNNReal y + Real.toNNReal (t - y) = Real.toNNReal t := by + apply NNReal.coe_injective + rw [NNReal.coe_add, hcoe, Real.coe_toNNReal y hy.1.le, + Real.coe_toNNReal t (hy.1.trans hy.2).le] + ring + have hinv : (y - t)⁻¹ = -(t - y)⁻¹ := by rw [neg_inv, neg_sub] + show S (Real.toNNReal y) (S.differenceQuotient f (Real.toNNReal (t - y))) + = slope (fun s : ℝ ↦ S (Real.toNNReal s) f) t y + rw [S.differenceQuotient_apply, map_smul, map_sub, ← S.add_apply, hsum, hcoe, + slope_def_module, hinv, neg_smul, ← smul_neg, neg_sub] + +/-- **Two-sided differentiability of orbits.** For `f` in the generator domain and every positive +time `t`, the orbit `s ↦ S (Real.toNNReal s) f` has derivative `S t (S.generator f)` at `t`. -/ +theorem hasDerivAt_operator_toNNReal (f : S.generatorDomain) {t : ℝ} (ht : 0 < t) : + HasDerivAt (fun s : ℝ ↦ S (Real.toNNReal s) f) (S (Real.toNNReal t) (S.generator f)) t := by + have hright := S.hasDerivWithinAt_Ici f (Real.toNNReal t) + rw [Real.coe_toNNReal t ht.le] at hright + have hunion := (S.hasDerivWithinAt_Iic f ht).union hright + rwa [Set.Iic_union_Ici, hasDerivWithinAt_univ] at hunion + +variable [CompleteSpace E] + +/-- **The fundamental identity of the generator.** For `f` in the generator domain and every +time `t`, `S t f - f = ∫₀ᵗ S s (S.generator f) ds`, the integral being the Bochner interval +integral of the continuous orbit of `S.generator f`. -/ +theorem operator_sub_eq_integral (f : S.generatorDomain) (t : NNReal) : + S t f - f = ∫ s in (0 : ℝ)..t, S (Real.toNNReal s) (S.generator f) := by + have hcont : ContinuousOn (fun s : ℝ ↦ S (Real.toNNReal s) f) (Set.Icc 0 t) := + (S.continuous_operator_toNNReal f).continuousOn + have hderiv : ∀ x ∈ Set.Ioo (0 : ℝ) t, + HasDerivWithinAt (fun s : ℝ ↦ S (Real.toNNReal s) f) + (S (Real.toNNReal x) (S.generator f)) (Set.Ioi x) x := by + intro x hx + have h := S.hasDerivWithinAt_Ioi f (Real.toNNReal x) + rwa [Real.coe_toNNReal x hx.1.le] at h + have hint : IntervalIntegrable (fun s : ℝ ↦ S (Real.toNNReal s) (S.generator f)) + MeasureTheory.volume 0 t := + (S.continuous_operator_toNNReal _).intervalIntegrable _ _ + have hftc := intervalIntegral.integral_eq_sub_of_hasDeriv_right_of_le t.coe_nonneg hcont + hderiv hint + rw [hftc, Real.toNNReal_coe, Real.toNNReal_zero, S.zero_apply] + +/-- The exponentially weighted fundamental identity for a strongly continuous contraction +semigroup. -/ +theorem exp_smul_operator_sub_eq_integral (f : S.generatorDomain) (lam : ℝ) (t : NNReal) : + Real.exp (-lam * (t : ℝ)) • S t (f : E) - f = + ∫ s in (0 : ℝ)..t, Real.exp (-lam * s) • + S (Real.toNNReal s) (S.generator f - lam • (f : E)) := by + let F : ℝ → E := fun s ↦ Real.exp (-lam * s) • S (Real.toNNReal s) (f : E) + let F' : ℝ → E := fun s ↦ + Real.exp (-lam * s) • S (Real.toNNReal s) (S.generator f - lam • (f : E)) + have hcont : ContinuousOn F (Set.Icc 0 (t : ℝ)) := by + exact ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).smul + (S.continuous_operator_toNNReal f)).continuousOn + have hderiv : ∀ x ∈ Set.Ioo (0 : ℝ) t, + HasDerivWithinAt F (F' x) (Set.Ioi x) x := by + intro x hx + have hexp : HasDerivAt (fun s : ℝ ↦ Real.exp (-lam * s)) + ((-lam) * Real.exp (-lam * x)) x := by + have h : HasDerivAt (fun s : ℝ ↦ Real.exp (-lam * s)) + (Real.exp (-lam * x) * (-lam * 1)) x := by + simpa only [id_eq] using ((hasDerivAt_id x).const_mul (-lam)).exp + exact h.congr_deriv (by ring) + have horbit := S.hasDerivWithinAt_Ioi f (Real.toNNReal x) + rw [Real.coe_toNNReal x hx.1.le] at horbit + have hprod := hexp.hasDerivWithinAt.smul horbit + refine hprod.congr_deriv ?_ + dsimp only [F'] + rw [map_sub, map_smul] + module + have hint : IntervalIntegrable F' MeasureTheory.volume 0 t := by + have hc : Continuous F' := + (Real.continuous_exp.comp (continuous_const.mul continuous_id)).smul + (S.continuous_operator_toNNReal _) + exact hc.intervalIntegrable _ _ + have hftc := intervalIntegral.integral_eq_sub_of_hasDeriv_right_of_le t.coe_nonneg hcont + hderiv hint + simpa only [F, F', Real.toNNReal_coe, Real.toNNReal_zero, S.zero_apply, mul_zero, + Real.exp_zero, one_smul] using hftc.symm + +end RealVariable + +section OrbitIntegral + +/-- The right difference quotients of a differentiable function, indexed by `NNReal` increments, +converge to its derivative. -/ +private theorem tendsto_slope_add_of_hasDerivAt {F : ℝ → E} {F' : E} {u : ℝ} + (hF : HasDerivAt F F' u) : + Tendsto (fun h : NNReal ↦ (h : ℝ)⁻¹ • (F (u + h) - F u)) (𝓝[>] 0) (𝓝 F') := by + have hslope := (hasDerivAt_iff_tendsto_slope.mp hF) + have hmap : Tendsto (fun h : NNReal ↦ u + (h : ℝ)) (𝓝[>] 0) (𝓝[≠] u) := by + apply tendsto_nhdsWithin_of_tendsto_nhds_of_eventually_within + · have h0 : Tendsto (fun h : NNReal ↦ u + (h : ℝ)) (𝓝 0) (𝓝 (u + ((0 : NNReal) : ℝ))) := + (continuous_const.add NNReal.continuous_coe).tendsto _ + rw [NNReal.coe_zero, add_zero] at h0 + exact h0.mono_left nhdsWithin_le_nhds + · filter_upwards [self_mem_nhdsWithin] with h hh + have hpos : (0 : ℝ) < h := NNReal.coe_pos.mpr hh + exact ne_of_gt (lt_add_of_pos_right u hpos) + refine (hslope.comp hmap).congr fun h ↦ ?_ + show slope F u (u + h) = (h : ℝ)⁻¹ • (F (u + h) - F u) + rw [slope_def_module, add_sub_cancel_left] + +/-- The orbit integral `∫₀ᵘ S s f ds` of a vector `f`, as a function of the real upper limit +`u` (the semigroup is read at `Real.toNNReal s`). -/ +def orbitIntegral (f : E) (u : ℝ) : E := ∫ s in (0 : ℝ)..u, S (Real.toNNReal s) f + +/-- The orbit integral, unfolded. -/ +theorem orbitIntegral_apply (f : E) (u : ℝ) : + S.orbitIntegral f u = ∫ s in (0 : ℝ)..u, S (Real.toNNReal s) f := rfl + +/-- The orbit integral over an empty window vanishes. -/ +theorem orbitIntegral_zero (f : E) : S.orbitIntegral f 0 = 0 := + intervalIntegral.integral_same + +variable [CompleteSpace E] + +/-- The orbit integral is differentiable in its upper limit, with derivative the orbit. -/ +theorem hasDerivAt_orbitIntegral (f : E) (u : ℝ) : + HasDerivAt (S.orbitIntegral f) (S (Real.toNNReal u) f) u := + ((S.continuous_operator_toNNReal f).integral_hasStrictDerivAt 0 u).hasDerivAt + +/-- The semigroup acting on an orbit integral shifts the integration window. -/ +theorem operator_orbitIntegral (f : E) (t h : NNReal) : + S h (S.orbitIntegral f t) = S.orbitIntegral f (t + h) - S.orbitIntegral f h := by + have hint : ∀ a b : ℝ, IntervalIntegrable (fun s : ℝ ↦ S (Real.toNNReal s) f) + MeasureTheory.volume a b := + fun a b ↦ (S.continuous_operator_toNNReal f).intervalIntegrable a b + have hshift : Set.EqOn (fun s : ℝ ↦ S h (S (Real.toNNReal s) f)) + (fun s : ℝ ↦ S (Real.toNNReal (s + h)) f) (Set.uIcc (0 : ℝ) t) := by + intro s hs + have hs0 : (0 : ℝ) ≤ s := by + rw [Set.uIcc_of_le t.coe_nonneg] at hs + exact hs.1 + have hcoe : Real.toNNReal (s + h) = h + Real.toNNReal s := by + apply NNReal.coe_injective + rw [NNReal.coe_add, Real.coe_toNNReal s hs0, Real.coe_toNNReal _ (add_nonneg hs0 h.coe_nonneg), + add_comm] + show S h (S (Real.toNNReal s) f) = S (Real.toNNReal (s + h)) f + rw [hcoe, S.add_apply] + rw [orbitIntegral, ← ContinuousLinearMap.intervalIntegral_comp_comm _ (hint 0 t), + intervalIntegral.integral_congr hshift, + intervalIntegral.integral_comp_add_right (fun s : ℝ ↦ S (Real.toNNReal s) f) (h : ℝ), zero_add, + orbitIntegral, orbitIntegral, intervalIntegral.integral_interval_sub_left (hint 0 _) (hint 0 _)] + +/-- The difference quotients of an orbit integral converge to the increment of the orbit. -/ +theorem tendsto_differenceQuotient_orbitIntegral (f : E) (t : NNReal) : + Tendsto (fun h : NNReal ↦ (h : ℝ)⁻¹ • (S h (S.orbitIntegral f t) - S.orbitIntegral f t)) + (𝓝[>] 0) (𝓝 (S t f - f)) := by + have ht := tendsto_slope_add_of_hasDerivAt (S.hasDerivAt_orbitIntegral f t) + have h0 := tendsto_slope_add_of_hasDerivAt (S.hasDerivAt_orbitIntegral f 0) + rw [Real.toNNReal_coe] at ht + rw [Real.toNNReal_zero, S.zero_apply] at h0 + refine (ht.sub h0).congr fun h ↦ ?_ + rw [S.operator_orbitIntegral, zero_add, S.orbitIntegral_zero, sub_zero, ← smul_sub, + sub_right_comm] + +/-- Every orbit integral lies in the generator domain. -/ +theorem orbitIntegral_mem_generatorDomain (f : E) (t : NNReal) : + S.orbitIntegral f t ∈ S.generatorDomain := + S.mem_generatorDomain_of_tendsto (S.tendsto_differenceQuotient_orbitIntegral f t) + +/-- The generator of an orbit integral is the increment of the orbit: +`L (∫₀ᵗ S s f ds) = S t f - f`, for every `f`, in the domain or not. -/ +theorem generator_orbitIntegral (f : E) (t : NNReal) : + S.generator ⟨S.orbitIntegral f t, S.orbitIntegral_mem_generatorDomain f t⟩ = S t f - f := + S.generator_eq_of_tendsto _ (S.tendsto_differenceQuotient_orbitIntegral f t) + +/-- Time averages of the orbit converge to the vector: `t⁻¹ • ∫₀ᵗ S s f ds → f` as `t → 0⁺`. -/ +theorem tendsto_inv_smul_orbitIntegral (f : E) : + Tendsto (fun t : NNReal ↦ (t : ℝ)⁻¹ • S.orbitIntegral f t) (𝓝[>] 0) (𝓝 f) := by + have h0 := tendsto_slope_add_of_hasDerivAt (S.hasDerivAt_orbitIntegral f 0) + rw [Real.toNNReal_zero, S.zero_apply] at h0 + refine h0.congr fun t ↦ ?_ + rw [zero_add, S.orbitIntegral_zero, sub_zero] + +/-- **The generator domain is dense.** -/ +theorem dense_generatorDomain : Dense (S.generatorDomain : Set E) := by + intro f + refine mem_closure_of_tendsto (S.tendsto_inv_smul_orbitIntegral f) ?_ + exact Eventually.of_forall fun t ↦ + S.generatorDomain.smul_mem _ (S.orbitIntegral_mem_generatorDomain f t) + +end OrbitIntegral + +end + +end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorClosed.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorClosed.lean new file mode 100644 index 0000000000..5441ce66fe --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorClosed.lean @@ -0,0 +1,101 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator + +/-! +# The generator is closed + +If vectors `u i` of the generator domain of a strongly continuous contraction semigroup `S` +converge to `f` and their generators `S.generator (u i)` converge to `g`, then `f` lies in the +domain and `S.generator f = g` (`mem_generatorDomain_of_tendsto_generator`, +`generator_eq_of_tendsto_generator`). The proof passes to the limit in the fundamental identity +`S t (u i) - u i = ∫₀ᵗ S s (S.generator (u i)) ds`, using that the orbit integral over `[0, t]` +is `t`-Lipschitz in the vector (`norm_orbitIntegral_le`), and reads the generator of `f` off the +limit identity through the time averages `t⁻¹ ∫₀ᵗ S s g ds → g`. + +Main results: `orbitIntegral_sub`, `norm_orbitIntegral_le`, `tendsto_orbitIntegral`, +`operator_sub_eq_orbitIntegral_of_tendsto_generator`, `mem_generatorDomain_of_tendsto_generator`, +`generator_eq_of_tendsto_generator`. + +Nothing is asserted about the domain beyond closedness of the graph; density is proved in +`Semigroup/Generator.lean`. +-/ + +open Filter Topology +open scoped NNReal + +namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] +variable (S : StronglyContinuousContractionSemigroup E) + +/-- The orbit integral is additive in the vector. -/ +theorem orbitIntegral_sub (f g : E) (u : ℝ) : + S.orbitIntegral f u - S.orbitIntegral g u = S.orbitIntegral (f - g) u := by + simp only [orbitIntegral_apply, map_sub] + exact (intervalIntegral.integral_sub ((S.continuous_operator_toNNReal f).intervalIntegrable _ _) + ((S.continuous_operator_toNNReal g).intervalIntegrable _ _)).symm + +/-- The orbit integral over `[0, t]` is bounded by `t` times the norm of the vector. -/ +theorem norm_orbitIntegral_le (f : E) (t : NNReal) : ‖S.orbitIntegral f t‖ ≤ ‖f‖ * t := by + rw [orbitIntegral_apply] + have h := intervalIntegral.norm_integral_le_of_norm_le_const (a := 0) (b := (t : ℝ)) + (C := ‖f‖) (f := fun s : ℝ ↦ S (Real.toNNReal s) f) (fun s _ ↦ S.norm_apply_le _ f) + rwa [sub_zero, abs_of_nonneg t.coe_nonneg] at h + +/-- The orbit integral over `[0, t]` is continuous in the vector. -/ +theorem tendsto_orbitIntegral {ι : Type*} {l : Filter ι} {v : ι → E} {g : E} + (hv : Tendsto v l (𝓝 g)) (t : NNReal) : + Tendsto (fun i ↦ S.orbitIntegral (v i) t) l (𝓝 (S.orbitIntegral g t)) := by + rw [tendsto_iff_norm_sub_tendsto_zero] + refine squeeze_zero (g := fun i ↦ ‖v i - g‖ * (t : ℝ)) (fun i ↦ norm_nonneg _) (fun i ↦ ?_) ?_ + · rw [S.orbitIntegral_sub] + exact S.norm_orbitIntegral_le _ t + · simpa using (tendsto_iff_norm_sub_tendsto_zero.mp hv).mul_const (t : ℝ) + +section Closed + +variable [CompleteSpace E] +variable {ι : Type*} {l : Filter ι} [l.NeBot] {u : ι → S.generatorDomain} {f g : E} + +/-- Passing to the limit in the fundamental identity of the generator. -/ +theorem operator_sub_eq_orbitIntegral_of_tendsto_generator + (hu : Tendsto (fun i ↦ (u i : E)) l (𝓝 f)) + (hL : Tendsto (fun i ↦ S.generator (u i)) l (𝓝 g)) (t : NNReal) : + S t f - f = S.orbitIntegral g t := by + have h1 : Tendsto (fun i ↦ S t (u i : E) - (u i : E)) l (𝓝 (S t f - f)) := + (((S t).continuous.tendsto f).comp hu).sub hu + have h2 : Tendsto (fun i ↦ S t (u i : E) - (u i : E)) l (𝓝 (S.orbitIntegral g t)) := by + refine (S.tendsto_orbitIntegral hL t).congr fun i ↦ ?_ + rw [orbitIntegral_apply] + exact (S.operator_sub_eq_integral (u i) t).symm + exact tendsto_nhds_unique h1 h2 + +/-- The difference quotients of the limit vector converge to the limit of the generators. -/ +theorem tendsto_differenceQuotient_of_tendsto_generator + (hu : Tendsto (fun i ↦ (u i : E)) l (𝓝 f)) + (hL : Tendsto (fun i ↦ S.generator (u i)) l (𝓝 g)) : + Tendsto (fun t : NNReal ↦ (t : ℝ)⁻¹ • (S t f - f)) (𝓝[>] 0) (𝓝 g) := by + refine (S.tendsto_inv_smul_orbitIntegral g).congr fun t ↦ ?_ + rw [S.operator_sub_eq_orbitIntegral_of_tendsto_generator hu hL t] + +/-- **The generator is closed**: the limit of domain vectors whose generators converge lies in +the domain. -/ +theorem mem_generatorDomain_of_tendsto_generator + (hu : Tendsto (fun i ↦ (u i : E)) l (𝓝 f)) + (hL : Tendsto (fun i ↦ S.generator (u i)) l (𝓝 g)) : f ∈ S.generatorDomain := + S.mem_generatorDomain_of_tendsto (S.tendsto_differenceQuotient_of_tendsto_generator hu hL) + +/-- **The generator is closed**: its value at the limit is the limit of the generators. -/ +theorem generator_eq_of_tendsto_generator + (hu : Tendsto (fun i ↦ (u i : E)) l (𝓝 f)) + (hL : Tendsto (fun i ↦ S.generator (u i)) l (𝓝 g)) : + S.generator ⟨f, S.mem_generatorDomain_of_tendsto_generator hu hL⟩ = g := + S.generator_eq_of_tendsto _ (S.tendsto_differenceQuotient_of_tendsto_generator hu hL) + +end Closed + +end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorInjectivity.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorInjectivity.lean new file mode 100644 index 0000000000..10c43f4d4f --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorInjectivity.lean @@ -0,0 +1,117 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +import Mathlib.Analysis.ODE.Gronwall + +/-! +# Eigenvectors of a generator, and injectivity of `μ - L` + +Let `S` be a strongly continuous contraction semigroup with generator `L`. If `f` lies in the +generator domain with `L f = μ f`, then the orbit of `f` is the scalar exponential +`S t f = exp (μ t) f`: the defect `w t = S t f - exp (μ t) f` vanishes at `t = 0` and has right +derivative `μ w t`, so Grönwall's inequality forces it to vanish +(`operator_eq_exp_smul_of_generator_eq_smul`). + +Since `S` is contractive, an eigenvalue `μ > 0` therefore forces `f = 0` +(`eq_zero_of_generator_eq_smul`); equivalently, `μ - L` is injective on the generator domain +(`eq_of_smul_sub_generator_eq`). This is the uniqueness half of the assertion that the resolvent +`(μ - L)⁻¹` is a well-defined operator. +-/ + +open Filter Set Topology +open scoped NNReal + +namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +noncomputable section + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] +variable (S : StronglyContinuousContractionSemigroup E) + +/-- The defect between the orbit of a vector and the scalar exponential `exp (μ t)` times it. -/ +private def exponentialDefect (μ : ℝ) (f : E) (s : ℝ) : E := + S (Real.toNNReal s) f - Real.exp (μ * s) • f + +private theorem continuous_exponentialDefect (μ : ℝ) (f : E) : + Continuous (S.exponentialDefect μ f) := + (S.continuous_operator_toNNReal f).sub + ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).smul continuous_const) + +private theorem exponentialDefect_zero (μ : ℝ) (f : E) : S.exponentialDefect μ f 0 = 0 := by + rw [exponentialDefect, Real.toNNReal_zero, S.zero_apply, mul_zero, Real.exp_zero, one_smul, + sub_self] + +private theorem hasDerivWithinAt_exponentialDefect {μ : ℝ} (f : S.generatorDomain) + (hgen : S.generator f = μ • (f : E)) {s : ℝ} (hs : 0 ≤ s) : + HasDerivWithinAt (S.exponentialDefect μ f) (μ • S.exponentialDefect μ f s) (Ici s) s := by + have horbit := S.hasDerivWithinAt_Ici f (Real.toNNReal s) + rw [Real.coe_toNNReal s hs] at horbit + have hlin : HasDerivAt (fun u : ℝ ↦ μ * u) μ s := by + simpa using (hasDerivAt_id s).const_mul μ + have hexp : HasDerivAt (fun u : ℝ ↦ Real.exp (μ * u) • (f : E)) + ((Real.exp (μ * s) * μ) • (f : E)) s := hlin.exp.smul_const (f : E) + have hsub := horbit.sub hexp.hasDerivWithinAt + rw [hgen, map_smul] at hsub + have hval : μ • S (Real.toNNReal s) (f : E) - (Real.exp (μ * s) * μ) • (f : E) + = μ • S.exponentialDefect μ (f : E) s := by + rw [exponentialDefect, smul_sub, smul_smul, mul_comm μ (Real.exp (μ * s))] + rw [hval] at hsub + exact hsub + +/-- **An eigenvector of the generator has an exponential orbit.** If `f` lies in the generator +domain and `L f = μ f`, then `S t f = exp (μ t) f` at every time `t`. -/ +theorem operator_eq_exp_smul_of_generator_eq_smul {μ : ℝ} (f : S.generatorDomain) + (hgen : S.generator f = μ • (f : E)) (t : NNReal) : + S t (f : E) = Real.exp (μ * t) • (f : E) := by + have hzero := eq_zero_of_abs_deriv_le_mul_abs_self_of_eq_zero_right + (f := S.exponentialDefect μ f) (f' := fun s ↦ μ • S.exponentialDefect μ f s) (K := |μ|) + (a := 0) (b := (t : ℝ)) (S.continuous_exponentialDefect μ f).continuousOn + (fun s hs ↦ S.hasDerivWithinAt_exponentialDefect f hgen hs.1) + (S.exponentialDefect_zero μ f) + (fun s _ ↦ by rw [norm_smul, Real.norm_eq_abs]) + (t : ℝ) ⟨t.coe_nonneg, le_rfl⟩ + rw [exponentialDefect, Real.toNNReal_coe, sub_eq_zero] at hzero + exact hzero + +/-- **Positive eigenvalues are excluded.** For `μ > 0`, a vector of the generator domain with +`L f = μ f` vanishes: its orbit would grow like `exp (μ t)`, contradicting contractivity. -/ +theorem eq_zero_of_generator_eq_smul {μ : ℝ} (hμ : 0 < μ) (f : S.generatorDomain) + (hgen : S.generator f = μ • (f : E)) : (f : E) = 0 := by + have hcontract : Real.exp μ * ‖(f : E)‖ ≤ ‖(f : E)‖ := by + have hle := S.norm_apply_le 1 (f : E) + rw [S.operator_eq_exp_smul_of_generator_eq_smul f hgen 1, norm_smul, Real.norm_eq_abs, + abs_of_pos (Real.exp_pos _), NNReal.coe_one, mul_one] at hle + exact hle + have hone : 1 < Real.exp μ := by + have hexp := Real.add_one_le_exp μ + linarith only [hexp, hμ] + rw [← norm_le_zero_iff] + by_contra hpos + push Not at hpos + have hstrict : 1 * ‖(f : E)‖ < Real.exp μ * ‖(f : E)‖ := by + exact mul_lt_mul_of_pos_right hone hpos + rw [one_mul] at hstrict + linarith only [hstrict, hcontract] + +/-- **Injectivity of `μ - L`.** For `μ > 0`, two vectors of the generator domain with the same +image under `μ - L` are equal. Together with surjectivity onto the whole space this says that +the resolvent `(μ - L)⁻¹` is well defined. -/ +theorem eq_of_smul_sub_generator_eq {μ : ℝ} (hμ : 0 < μ) (f g : S.generatorDomain) + (h : μ • (f : E) - S.generator f = μ • (g : E) - S.generator g) : (f : E) = (g : E) := by + have hker : S.generator (f - g) = μ • ((f - g : S.generatorDomain) : E) := by + rw [map_sub, Submodule.coe_sub, smul_sub] + have h0 : μ • (f : E) - S.generator f - (μ • (g : E) - S.generator g) = 0 := + sub_eq_zero_of_eq h + refine eq_of_sub_eq_zero ?_ + rw [← neg_zero, ← h0] + abel + have hzero := S.eq_zero_of_generator_eq_smul hμ (f - g) hker + rw [Submodule.coe_sub, sub_eq_zero] at hzero + exact hzero + +end + +end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorResolvent.lean new file mode 100644 index 0000000000..c94d24f359 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorResolvent.lean @@ -0,0 +1,179 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity + +/-! +# The generator of the semigroup generated by a contractive resolvent + +Let `R` be a contractive resolvent on a Banach space, `S = R.generatedSemigroup` the strongly +continuous contraction semigroup obtained from its Yosida approximations, and `L = S.generator`. +This file identifies `L` as the operator whose resolvent is `R`, which is the identification half +of the Hille--Yosida theorem: + +* `operator_mem_generatorDomain` and `generator_operator_apply`: the range of every `R_μ` lies in + the generator domain, with `L (R_μ y) = μ R_μ y - y`; +* `generatorDomain_eq_range`: the generator domain is exactly the range of `R_μ`, for every + positive shift `μ`; +* `operator_smul_sub_generator`: `R_μ (μ f - L f) = f` for every `f` of the domain, and + `generator_apply_of_operator_eq`: `L (R_μ g) = μ R_μ g - g` read from the other side. + +Thus `R_μ = (μ - L)⁻¹` with domain `range R_μ`: this is the `(μ + A)⁻¹` convention of +`ContractiveResolvent` with `A = -L`. + +The route to the first item is the fundamental identity `S_n t x - x = ∫₀ᵗ S_n s (A_n x) ds` for +the bounded Yosida approximations `S_n = exp (t A_n)`, which is elementary calculus for a Banach +algebra exponential (`yosidaOperator_apply_sub_eq_integral`); passing to the limit along the +canonical shifts by dominated convergence gives `S t x - x = ∫₀ᵗ S s (μ x - y) ds` on the range of +`R_μ`, and time averages of the orbit then produce the difference quotient at `t = 0`. +-/ + +open Filter MeasureTheory NormedSpace Set Topology +open scoped NNReal + +noncomputable section + +namespace MarkovProcess.Semigroup + +namespace ContractiveResolvent + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] + +/-- **The fundamental identity for a bounded Yosida approximation.** The exponential semigroup +of the bounded generator `A_α` satisfies `exp (t A_α) x - x = ∫₀ᵗ exp (s A_α) (A_α x) ds` for +every vector `x`, by the fundamental theorem of calculus for the Banach-algebra exponential. -/ +theorem yosidaOperator_apply_sub_eq_integral (R : ContractiveResolvent E) + (α : PositiveShift) (t : NNReal) (x : E) : + R.yosidaOperator α t x - x = + ∫ s in (0 : ℝ)..(t : ℝ), R.yosidaOperator α (Real.toNNReal s) (R.yosidaGenerator α x) := by + have hderiv : ∀ s : ℝ, HasDerivAt (fun u : ℝ ↦ exp (u • R.yosidaGenerator α) x) + (exp (s • R.yosidaGenerator α) (R.yosidaGenerator α x)) s := by + intro s + have h := (hasDerivAt_exp_smul_const (𝕂 := ℝ) (R.yosidaGenerator α) s).clm_apply + (hasDerivAt_const s x) + simpa only [mul_apply_eq_comp, map_zero, add_zero] using h + have hcont : Continuous fun s : ℝ ↦ + exp (s • R.yosidaGenerator α) (R.yosidaGenerator α x) := by fun_prop + have hFTC := intervalIntegral.integral_eq_sub_of_hasDerivAt (fun s _ ↦ hderiv s) + (hcont.intervalIntegrable 0 (t : ℝ)) + have hcongr : + (∫ s in (0 : ℝ)..(t : ℝ), R.yosidaOperator α (Real.toNNReal s) (R.yosidaGenerator α x)) = + ∫ s in (0 : ℝ)..(t : ℝ), exp (s • R.yosidaGenerator α) (R.yosidaGenerator α x) := by + refine intervalIntegral.integral_congr fun s hs ↦ ?_ + rw [Set.uIcc_of_le t.coe_nonneg] at hs + unfold yosidaOperator + rw [Real.coe_toNNReal s hs.1] + rw [hcongr, hFTC] + unfold yosidaOperator + rw [zero_smul, exp_zero] + rfl + +/-- **The fundamental identity on the range of a resolvent.** For the generated semigroup `S`, +`S t (R_μ y) - R_μ y = ∫₀ᵗ S s (μ R_μ y - y) ds`. Both sides are limits along the canonical +shifts of the corresponding Yosida quantities, the integrals converging by dominated +convergence: the integrands are contractions applied to the convergent sequence +`A_n (R_μ y) → μ R_μ y - y`. -/ +theorem generatedSemigroup_apply_sub_eq_orbitIntegral (R : ContractiveResolvent E) + (μ : PositiveShift) (y : E) (t : NNReal) : + R.generatedSemigroup t (R.operator μ y) - R.operator μ y = + R.generatedSemigroup.orbitIntegral ((μ : ℝ) • R.operator μ y - y) t := by + obtain ⟨C, hC⟩ := + (R.cauchySeq_yosidaGenerator_naturalShift_apply_operator μ y).isBounded_range.exists_norm_le + have hnorm : ∀ (n : ℕ) (s : ℝ), ‖R.yosidaOperator (naturalShift n) (Real.toNNReal s) + (R.yosidaGenerator (naturalShift n) (R.operator μ y))‖ ≤ C := by + intro n s + refine le_trans ?_ (hC _ ⟨n, rfl⟩) + simpa only [yosidaSemigroup_apply] using + (R.yosidaSemigroup (naturalShift n)).norm_apply_le (Real.toNNReal s) + (R.yosidaGenerator (naturalShift n) (R.operator μ y)) + have hmeas : ∀ n : ℕ, AEStronglyMeasurable + (fun s : ℝ ↦ R.yosidaOperator (naturalShift n) (Real.toNNReal s) + (R.yosidaGenerator (naturalShift n) (R.operator μ y))) + (volume.restrict (Set.uIoc (0 : ℝ) (t : ℝ))) := by + intro n + exact ((R.continuous_yosidaOperator_apply (naturalShift n) _).comp + continuous_real_toNNReal).aestronglyMeasurable + have hpointwise : ∀ s : ℝ, Tendsto (fun n ↦ R.yosidaOperator (naturalShift n) (Real.toNNReal s) + (R.yosidaGenerator (naturalShift n) (R.operator μ y))) atTop + (nhds (R.generatedSemigroup (Real.toNNReal s) ((μ : ℝ) • R.operator μ y - y))) := by + intro s + exact tendsto_apply_of_opNorm_le_one + (fun n ↦ R.yosidaOperator (naturalShift n) (Real.toNNReal s)) + (R.generatedSemigroup (Real.toNNReal s)) + (fun n ↦ R.yosidaGenerator (naturalShift n) (R.operator μ y)) + ((μ : ℝ) • R.operator μ y - y) + (fun n ↦ R.norm_yosidaOperator_le_one (naturalShift n) (Real.toNNReal s)) + (R.tendsto_yosidaOperator_naturalShift_apply (Real.toNNReal s) _) + (R.tendsto_yosidaGenerator_naturalShift_apply_operator μ y) + have hlimR : Tendsto (fun n ↦ ∫ s in (0 : ℝ)..(t : ℝ), + R.yosidaOperator (naturalShift n) (Real.toNNReal s) + (R.yosidaGenerator (naturalShift n) (R.operator μ y))) atTop + (nhds (R.generatedSemigroup.orbitIntegral ((μ : ℝ) • R.operator μ y - y) t)) := by + rw [StronglyContinuousContractionSemigroup.orbitIntegral_apply] + exact intervalIntegral.tendsto_integral_filter_of_dominated_convergence (fun _ ↦ C) + (Eventually.of_forall hmeas) + (Eventually.of_forall fun n ↦ Eventually.of_forall fun s _ ↦ hnorm n s) + intervalIntegrable_const + (Eventually.of_forall fun s _ ↦ hpointwise s) + refine tendsto_nhds_unique + ((R.tendsto_yosidaOperator_naturalShift_apply t (R.operator μ y)).sub tendsto_const_nhds) + (hlimR.congr fun n ↦ ?_) + exact (R.yosidaOperator_apply_sub_eq_integral (naturalShift n) t (R.operator μ y)).symm + +/-- The range of every resolvent lies in the generator domain of the generated semigroup. -/ +theorem operator_mem_generatorDomain (R : ContractiveResolvent E) (μ : PositiveShift) (y : E) : + R.operator μ y ∈ R.generatedSemigroup.generatorDomain := by + refine R.generatedSemigroup.mem_generatorDomain_of_tendsto + (g := (μ : ℝ) • R.operator μ y - y) ?_ + refine (R.generatedSemigroup.tendsto_inv_smul_orbitIntegral + ((μ : ℝ) • R.operator μ y - y)).congr fun t ↦ ?_ + rw [R.generatedSemigroup_apply_sub_eq_orbitIntegral μ y t] + +/-- **The generator inverts the resolvent.** On the range of `R_μ`, the generator of the +generated semigroup is `L (R_μ y) = μ R_μ y - y`. -/ +theorem generator_operator_apply (R : ContractiveResolvent E) (μ : PositiveShift) (y : E) : + R.generatedSemigroup.generator ⟨R.operator μ y, R.operator_mem_generatorDomain μ y⟩ = + (μ : ℝ) • R.operator μ y - y := by + refine R.generatedSemigroup.generator_eq_of_tendsto _ ?_ + refine (R.generatedSemigroup.tendsto_inv_smul_orbitIntegral + ((μ : ℝ) • R.operator μ y - y)).congr fun t ↦ ?_ + rw [R.generatedSemigroup_apply_sub_eq_orbitIntegral μ y t] + +/-- The generator on a vector presented as a resolvent image: if `R_μ g = f`, then +`L f = μ f - g`. -/ +theorem generator_apply_of_operator_eq (R : ContractiveResolvent E) (μ : PositiveShift) {f g : E} + (hf : f ∈ R.generatedSemigroup.generatorDomain) (hfg : R.operator μ g = f) : + R.generatedSemigroup.generator ⟨f, hf⟩ = (μ : ℝ) • f - g := by + subst hfg + exact R.generator_operator_apply μ g + +/-- **The resolvent inverts `μ - L`.** For every vector `f` of the generator domain of the +generated semigroup, `R_μ (μ f - L f) = f`. -/ +theorem operator_smul_sub_generator (R : ContractiveResolvent E) (μ : PositiveShift) + (f : R.generatedSemigroup.generatorDomain) : + R.operator μ ((μ : ℝ) • (f : E) - R.generatedSemigroup.generator f) = (f : E) := by + refine R.generatedSemigroup.eq_of_smul_sub_generator_eq μ.property + ⟨R.operator μ ((μ : ℝ) • (f : E) - R.generatedSemigroup.generator f), + R.operator_mem_generatorDomain μ _⟩ f ?_ + rw [R.generator_operator_apply μ ((μ : ℝ) • (f : E) - R.generatedSemigroup.generator f)] + abel + +/-- **The generator domain is the range of any resolvent.** Together with +`operator_smul_sub_generator` this says that `R_μ` is a bijection from `E` onto the generator +domain, inverse to `μ - L`. -/ +theorem generatorDomain_eq_range (R : ContractiveResolvent E) (μ : PositiveShift) : + (R.generatedSemigroup.generatorDomain : Set E) = Set.range (R.operator μ) := by + refine Set.Subset.antisymm (fun f hf ↦ ?_) ?_ + · exact ⟨(μ : ℝ) • f - R.generatedSemigroup.generator ⟨f, hf⟩, + R.operator_smul_sub_generator μ ⟨f, hf⟩⟩ + · rintro _ ⟨y, rfl⟩ + exact R.operator_mem_generatorDomain μ y + +end ContractiveResolvent + +end MarkovProcess.Semigroup + +end diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorUniqueness.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorUniqueness.lean new file mode 100644 index 0000000000..bea578b450 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorUniqueness.lean @@ -0,0 +1,148 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity +import Mathlib.Analysis.ODE.Gronwall + +/-! +# The generator determines the semigroup + +Two strongly continuous contraction semigroups with the same generator domain and the same +generator on it are equal (`ext_of_generator`). + +The proof interpolates between the two evolutions: for a vector `f` of the common domain and a +fixed time `t`, the path `s ↦ S (t - s) (T s f)` on `[0, t]` is continuous and has right +derivative zero, because + +`S (t - s - h) (T (s + h) f) - S (t - s) (T s f) + = S (t - s - h) ((T h - 1) (T s f) - (S h - 1) (T s f))`, + +and the two difference quotients on the right converge to the common value of the generators at +`T s f`. Grönwall's inequality then makes the path constant, and its two endpoints are `S t f` +and `T t f`. Density of the generator domain extends the identity to the whole space. +-/ + +open Filter Set Topology +open scoped NNReal + +namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +noncomputable section + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] +variable (S T : StronglyContinuousContractionSemigroup E) + +/-- The interpolation `s ↦ S (t - s) (T s f)` between the orbit of `f` under `T` and its orbit +under `S`, read at real times. -/ +private def transferOrbit (f : E) (t s : ℝ) : E := + S (Real.toNNReal (t - s)) (T (Real.toNNReal s) f) + +private theorem transferOrbit_apply (f : E) (t s : ℝ) : + S.transferOrbit T f t s = S (Real.toNNReal (t - s)) (T (Real.toNNReal s) f) := rfl + +private theorem continuous_transferOrbit (f : E) (t : ℝ) : + Continuous (S.transferOrbit T f t) := + S.continuous_operator_apply + (continuous_real_toNNReal.comp (continuous_const.sub continuous_id)) + (T.continuous_operator_toNNReal f) + +private theorem transferOrbit_zero (f : E) (t : ℝ) : + S.transferOrbit T f t 0 = S (Real.toNNReal t) f := by + rw [transferOrbit_apply, sub_zero, Real.toNNReal_zero, T.zero_apply] + +private theorem transferOrbit_self (f : E) (t : ℝ) : + S.transferOrbit T f t t = T (Real.toNNReal t) f := by + rw [transferOrbit_apply, sub_self, Real.toNNReal_zero, S.zero_apply] + +/-- The interpolation has vanishing right derivative at every time of `[0, t)`. -/ +private theorem hasDerivWithinAt_transferOrbit + (hdom : S.generatorDomain = T.generatorDomain) + (hgen : ∀ (f : E) (hS : f ∈ S.generatorDomain) (hT : f ∈ T.generatorDomain), + S.generator ⟨f, hS⟩ = T.generator ⟨f, hT⟩) + {f : E} (hf : f ∈ S.generatorDomain) {t s : ℝ} (hs : 0 ≤ s) (hst : s < t) : + HasDerivWithinAt (S.transferOrbit T f t) 0 (Ici s) s := by + have hfT : f ∈ T.generatorDomain := by rwa [← hdom] + have hgT : T (Real.toNNReal s) f ∈ T.generatorDomain := + T.operator_mem_generatorDomain ⟨f, hfT⟩ (Real.toNNReal s) + have hgS : T (Real.toNNReal s) f ∈ S.generatorDomain := by rwa [hdom] + have hto : Tendsto (fun y : ℝ ↦ Real.toNNReal (y - s)) (𝓝[>] s) (𝓝[>] 0) := by + have h := tendsto_toNNReal_sub (Real.toNNReal s) + rwa [Real.coe_toNNReal s hs] at h + have hbound : Tendsto (fun y : ℝ ↦ + ‖T.differenceQuotient (T (Real.toNNReal s) f) (Real.toNNReal (y - s)) - + S.differenceQuotient (T (Real.toNNReal s) f) (Real.toNNReal (y - s))‖) + (𝓝[>] s) (𝓝 0) := by + have hT' := (T.tendsto_generator ⟨T (Real.toNNReal s) f, hgT⟩).comp hto + have hS' := (S.tendsto_generator ⟨T (Real.toNNReal s) f, hgS⟩).comp hto + have hdiff := hT'.sub hS' + rw [← hgen _ hgS hgT, sub_self] at hdiff + simpa using hdiff.norm + have hslope : ∀ y ∈ Ioo s t, slope (S.transferOrbit T f t) s y = + S (Real.toNNReal (t - y)) + (T.differenceQuotient (T (Real.toNNReal s) f) (Real.toNNReal (y - s)) - + S.differenceQuotient (T (Real.toNNReal s) f) (Real.toNNReal (y - s))) := by + intro y hy + have hsy : (0 : ℝ) ≤ y - s := sub_nonneg.mpr hy.1.le + have hcoe : ((Real.toNNReal (y - s) : NNReal) : ℝ) = y - s := Real.coe_toNNReal _ hsy + have hy0 : (0 : ℝ) ≤ y := hs.trans hy.1.le + have hsplit : Real.toNNReal y = Real.toNNReal (y - s) + Real.toNNReal s := by + apply NNReal.coe_injective + rw [NNReal.coe_add, hcoe, Real.coe_toNNReal s hs, Real.coe_toNNReal y hy0] + ring + have hwindow : Real.toNNReal (t - s) = Real.toNNReal (t - y) + Real.toNNReal (y - s) := by + apply NNReal.coe_injective + rw [NNReal.coe_add, hcoe, Real.coe_toNNReal _ (sub_nonneg.mpr hy.2.le), + Real.coe_toNNReal _ (sub_nonneg.mpr (hy.1.trans hy.2).le)] + ring + have key : S.transferOrbit T f t y - S.transferOrbit T f t s = + S (Real.toNNReal (t - y)) + (T (Real.toNNReal (y - s)) (T (Real.toNNReal s) f) - + S (Real.toNNReal (y - s)) (T (Real.toNNReal s) f)) := by + rw [transferOrbit_apply, transferOrbit_apply, hsplit, T.add_apply, hwindow, S.add_apply, + ← map_sub] + rw [slope_def_module, key, T.differenceQuotient_apply, S.differenceQuotient_apply, hcoe, + ← smul_sub, map_smul, sub_sub_sub_cancel_right] + rw [hasDerivWithinAt_iff_tendsto_slope] + have hdiff : Ici s \ {s} = Ioi s := by + ext y + simp only [Set.mem_sdiff, Set.mem_Ici, Set.mem_singleton_iff, Set.mem_Ioi] + exact ⟨fun hy ↦ lt_of_le_of_ne hy.1 (Ne.symm hy.2), fun hy ↦ ⟨hy.le, hy.ne'⟩⟩ + rw [hdiff] + refine squeeze_zero_norm' ?_ hbound + filter_upwards [Ioo_mem_nhdsGT hst] with y hy + rw [hslope y hy] + exact S.norm_apply_le _ _ + +variable [CompleteSpace E] + +/-- **The generator determines the semigroup.** Two strongly continuous contraction semigroups +with the same generator domain, on which their generators agree, are equal. -/ +theorem ext_of_generator (hdom : S.generatorDomain = T.generatorDomain) + (hgen : ∀ (f : E) (hS : f ∈ S.generatorDomain) (hT : f ∈ T.generatorDomain), + S.generator ⟨f, hS⟩ = T.generator ⟨f, hT⟩) : + S = T := by + have hcore : ∀ (t : NNReal) (f : E), f ∈ S.generatorDomain → S t f = T t f := by + intro t f hf + have hconst := eq_zero_of_abs_deriv_le_mul_abs_self_of_eq_zero_right + (f := fun s ↦ S.transferOrbit T f t s - S.transferOrbit T f t 0) + (f' := fun _ ↦ (0 : E)) (K := 0) (a := 0) (b := (t : ℝ)) + (((S.continuous_transferOrbit T f t).sub continuous_const).continuousOn) + (fun s hs ↦ + (S.hasDerivWithinAt_transferOrbit T hdom hgen hf hs.1 hs.2).sub_const _) + (sub_self _) + (fun s _ ↦ by rw [norm_zero, zero_mul]) + (t : ℝ) ⟨t.coe_nonneg, le_rfl⟩ + rw [sub_eq_zero, transferOrbit_self, transferOrbit_zero, Real.toNNReal_coe] at hconst + exact hconst.symm + refine StronglyContinuousContractionSemigroup.ext fun t ↦ ?_ + refine DFunLike.coe_injective ?_ + refine Continuous.ext_on S.dense_generatorDomain (S t).continuous (T t).continuous ?_ + intro f hf + exact hcore t f hf + +end + +end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean new file mode 100644 index 0000000000..83ac34a64b --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean @@ -0,0 +1,164 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation +import Mathlib.Analysis.Convex.Combination + +/-! +# Invariant sets and strong semigroup limits + +This file isolates the topological part of transferring an invariant set from +bounded Yosida approximations to the generated semigroup. It also records the +finite-iterate consequence of invariance under a normalized resolvent. The +Poisson-series argument transferring the latter invariance to each exponential +approximant is in `Semigroup/PoissonInvariant.lean`. +-/ + +open Filter Set Topology + +noncomputable section + +namespace MarkovProcess.Semigroup + +/-- A map preserves a set if it sends every member of the set back into it. -/ +def PreservesSet {E F : Type*} (T : E → F) (C : Set E) (D : Set F) : Prop := + ∀ ⦃x⦄, x ∈ C → T x ∈ D + +namespace PreservesSet + +variable {E F G : Type*} {C : Set E} {D : Set F} {K : Set G} + +theorem id : PreservesSet (fun x : E ↦ x) C C := + fun _ hx ↦ hx + +theorem comp {S : F → G} {T : E → F} + (hS : PreservesSet S D K) (hT : PreservesSet T C D) : + PreservesSet (S ∘ T) C K := + fun _ hx ↦ hS (hT hx) + +/-- A closed set is preserved by the pointwise limit of preserving maps. -/ +theorem of_tendsto {ι : Type*} {l : Filter ι} [l.NeBot] + [TopologicalSpace F] [T2Space F] {T : ι → E → F} {S : E → F} + (hD : IsClosed D) (hT : ∀ i, PreservesSet (T i) C D) + (hlim : ∀ x, Tendsto (fun i ↦ T i x) l (nhds (S x))) : + PreservesSet S C D := by + intro x hx + exact hD.mem_of_tendsto (hlim x) (Eventually.of_forall fun i ↦ hT i hx) + +end PreservesSet + +end MarkovProcess.Semigroup + +namespace Convex + +variable {E ι : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + +/-- A finite subprobability barycenter of points in a convex set containing +zero belongs to the set. -/ +theorem sum_mem_of_sum_le_one {C : Set E} (hC : Convex ℝ C) (hzero : 0 ∈ C) + (s : Finset ι) (w : ι → ℝ) (z : ι → E) + (hw : ∀ i ∈ s, 0 ≤ w i) (hsum : ∑ i ∈ s, w i ≤ 1) + (hz : ∀ i ∈ s, z i ∈ C) : + ∑ i ∈ s, w i • z i ∈ C := by + classical + let s' : Finset (Option ι) := insert none (s.image some) + let w' : Option ι → ℝ + | none => 1 - ∑ i ∈ s, w i + | some i => w i + let z' : Option ι → E + | none => 0 + | some i => z i + have hnone : none ∉ s.image some := by + simp + have hw' : ∀ i ∈ s', 0 ≤ w' i := by + intro i hi + rcases i with _ | i + · exact sub_nonneg.mpr hsum + · exact hw i (by + have : some i ∈ s.image some := by + simpa only [s', Finset.mem_insert, Option.some_ne_none, false_or] using hi + simpa only [Finset.mem_image, Option.some.injEq, exists_eq_right] using this) + have hz' : ∀ i ∈ s', z' i ∈ C := by + intro i hi + rcases i with _ | i + · exact hzero + · exact hz i (by + have : some i ∈ s.image some := by + simpa only [s', Finset.mem_insert, Option.some_ne_none, false_or] using hi + simpa only [Finset.mem_image, Option.some.injEq, exists_eq_right] using this) + have hsum' : ∑ i ∈ s', w' i = 1 := by + simp [s', hnone, w'] + have hmem := hC.sum_mem hw' hsum' hz' + simpa [s', hnone, z', w'] using hmem + +/-- A convergent countable subprobability barycenter of points in a closed +convex set containing zero belongs to the set. -/ +theorem tsum_mem_of_tsum_le_one {C : Set E} (hclosed : IsClosed C) + (hC : Convex ℝ C) (hzero : 0 ∈ C) (w : ℕ → ℝ) (z : ℕ → E) + (hw : ∀ n, 0 ≤ w n) (hsum : Summable w) (htsum : ∑' n, w n ≤ 1) + (hz : ∀ n, z n ∈ C) (hweighted : Summable fun n ↦ w n • z n) : + ∑' n, w n • z n ∈ C := by + apply hclosed.mem_of_tendsto hweighted.hasSum.tendsto_sum_nat + exact Eventually.of_forall fun n ↦ + Convex.sum_mem_of_sum_le_one + hC hzero (Finset.range n) w z + (fun i _ ↦ hw i) + ((hsum.sum_le_tsum (Finset.range n) (fun i _ ↦ hw i)).trans htsum) + (fun i _ ↦ hz i) + +end Convex + +namespace MarkovProcess.Semigroup + +namespace ContractiveResolvent + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + +/-- Invariance under a normalized resolvent propagates to all of its finite +iterates. These are the atoms in the Poisson representation of a bounded +Yosida exponential. -/ +theorem preservesSet_scaledOperator_pow (R : ContractiveResolvent E) + (C : Set E) (α : PositiveShift) + (hQ : PreservesSet (R.scaledOperator α) C C) (n : ℕ) : + PreservesSet ((R.scaledOperator α) ^ n) C C := by + induction n with + | zero => + simpa only [pow_zero, one_apply_eq_self] using! + (PreservesSet.id (C := C)) + | succ n ih => + intro x hx + rw [pow_succ, mul_apply_eq_comp] + exact ih (hQ hx) + +section CompleteSpace + +variable [CompleteSpace E] + +/-- If every canonical bounded Yosida approximation preserves a closed set, +then the generated strong-limit semigroup preserves it as well. This theorem +contains no semigroup-level preservation hypothesis: its input is the concrete +approximating family produced from the resolvent. -/ +theorem preservesSet_generatedSemigroup_of_yosida + (R : ContractiveResolvent E) (C : Set E) (hC : IsClosed C) + (happrox : ∀ n t, PreservesSet + (R.yosidaOperator (naturalShift n) t) C C) (t : NNReal) : + PreservesSet (R.generatedSemigroup t) C C := by + exact PreservesSet.of_tendsto hC (fun n ↦ happrox n t) + (R.tendsto_yosidaOperator_naturalShift_apply t) + +/-- A version exposing all positive shifts, convenient when the Poisson +invariance theorem has been proved uniformly in the shift. -/ +theorem preservesSet_generatedSemigroup + (R : ContractiveResolvent E) (C : Set E) (hC : IsClosed C) + (happrox : ∀ α t, PreservesSet (R.yosidaOperator α t) C C) + (t : NNReal) : PreservesSet (R.generatedSemigroup t) C C := by + exact R.preservesSet_generatedSemigroup_of_yosida C hC + (fun n s ↦ happrox (naturalShift n) s) t + +end CompleteSpace + +end ContractiveResolvent + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitContinuity.lean new file mode 100644 index 0000000000..ce7d59663e --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitContinuity.lean @@ -0,0 +1,102 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit + +/-! +# Continuity of semigroup orbits from continuity at zero + +For a contractive semigroup, strong convergence to the identity at time zero +propagates to continuity of every orbit at every nonnegative time. Contractivity also upgrades +strong continuity to joint continuity in the time and the vector, in the form +`continuous_operator_apply`. +-/ + +open Filter Topology + +namespace MarkovProcess.Semigroup + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + +/-- A contractive semigroup whose orbits converge strongly to the identity at +zero has continuous orbits on all of `NNReal`. -/ +theorem continuous_orbit_of_tendsto_zero + (T : NNReal → E →L[ℝ] E) + (hadd : ∀ s t, T (s + t) = (T s).comp (T t)) + (hcontract : ∀ t, ‖T t‖ ≤ 1) + (htend : ∀ x, Tendsto (fun t ↦ T t x) (nhds 0) (nhds x)) + (x : E) : + Continuous (fun t ↦ T t x) := by + rw [Metric.continuous_iff] + intro t ε hε + obtain ⟨δ, hδ, hnear⟩ := (Metric.tendsto_nhds_nhds.mp (htend x)) ε hε + refine ⟨δ, hδ, fun s hst ↦ ?_⟩ + rcases le_total t s with hts | hst' + · have hgap : dist (s - t) 0 < δ := by + simpa only [NNReal.dist_eq, NNReal.coe_sub hts, NNReal.coe_zero, sub_zero, + Real.dist_eq, abs_of_nonneg (sub_nonneg.mpr (NNReal.coe_le_coe.mpr hts))] using hst + have hsmall := hnear hgap + have hs : T s x = T t (T (s - t) x) := by + rw [← ContinuousLinearMap.comp_apply, ← hadd, add_comm, tsub_add_cancel_of_le hts] + rw [hs] + calc + dist (T t (T (s - t) x)) (T t x) ≤ dist (T (s - t) x) x := by + calc + _ ≤ ‖T t‖ * dist (T (s - t) x) x := (T t).dist_le_opNorm _ _ + _ ≤ 1 * dist (T (s - t) x) x := + mul_le_mul_of_nonneg_right (hcontract t) dist_nonneg + _ = _ := one_mul _ + _ < ε := hsmall + · have hgap : dist (t - s) 0 < δ := by + rw [dist_comm] at hst + simpa only [NNReal.dist_eq, NNReal.coe_sub hst', NNReal.coe_zero, sub_zero, + Real.dist_eq, abs_of_nonneg (sub_nonneg.mpr (NNReal.coe_le_coe.mpr hst'))] using hst + have hsmall := hnear hgap + have ht : T t x = T s (T (t - s) x) := by + rw [← ContinuousLinearMap.comp_apply, ← hadd, add_comm, tsub_add_cancel_of_le hst'] + rw [ht, dist_comm] + calc + dist (T s (T (t - s) x)) (T s x) ≤ dist (T (t - s) x) x := by + calc + _ ≤ ‖T s‖ * dist (T (t - s) x) x := (T s).dist_le_opNorm _ _ + _ ≤ 1 * dist (T (t - s) x) x := + mul_le_mul_of_nonneg_right (hcontract s) dist_nonneg + _ = _ := one_mul _ + _ < ε := hsmall + +namespace StronglyContinuousContractionSemigroup + +/-- Joint continuity of the evolution: for a strongly continuous contraction semigroup `S`, the +map `x ↦ S (u x) (v x)` is continuous whenever the time `u` and the vector `v` are. Only strong +continuity and contractivity are used. -/ +theorem continuous_operator_apply (S : StronglyContinuousContractionSemigroup E) + {X : Type*} [TopologicalSpace X] {u : X → NNReal} {v : X → E} + (hu : Continuous u) (hv : Continuous v) : + Continuous fun x ↦ S (u x) (v x) := by + rw [continuous_iff_continuousAt] + intro x + exact tendsto_apply_of_opNorm_le_one (fun z ↦ S (u z)) (S (u x)) v (v x) + (fun z ↦ S.norm_operator_le_one (u z)) ((S.continuous (v x)).comp hu).continuousAt + hv.continuousAt + +/-- Construct a strongly continuous contraction semigroup by checking strong +convergence to the identity only at time zero. -/ +def ofTendstoZero + (T : NNReal → E →L[ℝ] E) + (hzero : T 0 = ContinuousLinearMap.id ℝ E) + (hadd : ∀ s t, T (s + t) = (T s).comp (T t)) + (hcontract : ∀ t, ‖T t‖ ≤ 1) + (htend : ∀ x, Tendsto (fun t ↦ T t x) (nhds 0) (nhds x)) : + StronglyContinuousContractionSemigroup E where + operator := T + operator_zero := hzero + operator_add := hadd + opNorm_le_one := hcontract + continuous_orbit := continuous_orbit_of_tendsto_zero T hadd hcontract htend + +end StronglyContinuousContractionSemigroup + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitProductRule.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitProductRule.lean new file mode 100644 index 0000000000..66aee5c86c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitProductRule.lean @@ -0,0 +1,88 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator + +/-! +# The product rule for a semigroup acting along a curve + +Let `S` be a strongly continuous contraction semigroup with generator `L` and let `v` be a curve +in the Banach space which is right differentiable at a time `s ≥ 0` and whose value `v s` lies in +the generator domain. Then the evolved curve `y ↦ S y (v y)` is right differentiable at `s` with + + `d⁺/dy [ S y (v y) ] = S s (L (v s) + v' s)`. + +The proof splits the increment as `S y (v y − v s) + S s (S (y − s) (v s) − v s)`. The first +summand is handled by contractivity and strong continuity, the second is the difference quotient +that defines the generator; no differentiability of `y ↦ S y` in the operator norm is used, and +only the value of `v` at the single time `s` is required to lie in the domain. + +Main results: `hasDerivWithinAt_operator_apply`. + +Times are read from the real line at `Real.toNNReal`, as elsewhere in the library. Nothing is +asserted about the two-sided derivative, which for a general curve fails at `s = 0`. +-/ + +open Filter Topology +open scoped NNReal + +namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] +variable (S : StronglyContinuousContractionSemigroup E) + +/-- **The product rule for the evolution of a curve.** If the curve `v` has right derivative +`v'` at the nonnegative time `s` and `v s` lies in the generator domain, then `y ↦ S y (v y)` has +right derivative `S s (L (v s) + v')` at `s`. -/ +theorem hasDerivWithinAt_operator_apply {v : ℝ → E} {v' : E} {s : ℝ} (hs : 0 ≤ s) + (hmem : v s ∈ S.generatorDomain) (hv : HasDerivWithinAt v v' (Set.Ioi s) s) : + HasDerivWithinAt (fun y : ℝ ↦ S (Real.toNNReal y) (v y)) + (S (Real.toNNReal s) (S.generator ⟨v s, hmem⟩ + v')) (Set.Ioi s) s := by + have hdiff : Set.Ioi s \ {s} = Set.Ioi s := by + ext y + simp only [Set.mem_sdiff, Set.mem_Ioi, Set.mem_singleton_iff, and_iff_left_iff_imp] + exact fun hy ↦ ne_of_gt hy + have hcoe : ((Real.toNNReal s : NNReal) : ℝ) = s := Real.coe_toNNReal s hs + have hslope : Tendsto (slope v s) (𝓝[>] s) (𝓝 v') := by + have h := hasDerivWithinAt_iff_tendsto_slope.mp hv + rwa [hdiff] at h + have hA : Tendsto (fun y : ℝ ↦ S (Real.toNNReal y) (slope v s y)) (𝓝[>] s) + (𝓝 (S (Real.toNNReal s) v')) := by + refine tendsto_apply_of_opNorm_le_one (fun y : ℝ ↦ S (Real.toNNReal y)) + (S (Real.toNNReal s)) (slope v s) v' (fun y ↦ S.norm_operator_le_one _) ?_ hslope + exact ((S.continuous_operator_toNNReal v').tendsto s).mono_left nhdsWithin_le_nhds + have hsub : Tendsto (fun y : ℝ ↦ Real.toNNReal (y - s)) (𝓝[>] s) (𝓝[>] 0) := by + have h := tendsto_toNNReal_sub (Real.toNNReal s) + rwa [hcoe] at h + have hB : Tendsto (fun y : ℝ ↦ + S (Real.toNNReal s) (S.differenceQuotient (v s) (Real.toNNReal (y - s)))) (𝓝[>] s) + (𝓝 (S (Real.toNNReal s) (S.generator ⟨v s, hmem⟩))) := + ((S (Real.toNNReal s)).continuous.tendsto _).comp + ((S.tendsto_generator ⟨v s, hmem⟩).comp hsub) + have hlim : S (Real.toNNReal s) v' + S (Real.toNNReal s) (S.generator ⟨v s, hmem⟩) = + S (Real.toNNReal s) (S.generator ⟨v s, hmem⟩ + v') := by + rw [map_add] + abel + rw [hasDerivWithinAt_iff_tendsto_slope, hdiff, ← hlim] + refine (hA.add hB).congr' ?_ + filter_upwards [self_mem_nhdsWithin] with y hy + have hys : s < y := hy + have hk : ((Real.toNNReal (y - s) : NNReal) : ℝ) = y - s := + Real.coe_toNNReal _ (sub_nonneg.mpr hys.le) + have hsum : Real.toNNReal s + Real.toNNReal (y - s) = Real.toNNReal y := by + apply NNReal.coe_injective + rw [NNReal.coe_add, hk, hcoe, Real.coe_toNNReal y (hs.trans hys.le)] + ring + have hshift : S (Real.toNNReal s) (S (Real.toNNReal (y - s)) (v s)) = + S (Real.toNNReal y) (v s) := by + rw [← S.add_apply, hsum] + show S (Real.toNNReal y) (slope v s y) + + S (Real.toNNReal s) (S.differenceQuotient (v s) (Real.toNNReal (y - s))) = + slope (fun y : ℝ ↦ S (Real.toNNReal y) (v y)) s y + rw [slope_def_module, slope_def_module, S.differenceQuotient_apply, hk, map_smul, map_smul, + map_sub, map_sub, hshift] + module + +end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PoissonInvariant.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PoissonInvariant.lean new file mode 100644 index 0000000000..5c16fd18f7 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PoissonInvariant.lean @@ -0,0 +1,194 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet + +/-! +# Poisson invariance of bounded Yosida exponentials + +This file proves the uniformization argument: a normalized resolvent preserving +a closed convex set containing zero has Yosida exponentials preserving that set. +-/ + +open Filter Set Topology +open NormedSpace + +noncomputable section + +namespace MarkovProcess.Semigroup + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + +/-- The exponential of a scalar multiple of the identity is scalar +multiplication by the real exponential. -/ +theorem exp_smul_id_apply (a : ℝ) (x : E) : + exp (a • ContinuousLinearMap.id ℝ E) x = Real.exp a • x := by + have hmap := NormedSpace.map_exp + (algebraMap ℝ (E →L[ℝ] E)) + (continuous_algebraMap ℝ (E →L[ℝ] E)) a + rw [← Real.exp_eq_exp_ℝ] at hmap + have halg : algebraMap ℝ (E →L[ℝ] E) a = + a • ContinuousLinearMap.id ℝ E := by + ext y + simp only [ContinuousLinearMap.algebraMap_apply, + smul_apply, ContinuousLinearMap.id_apply] + rw [halg] at hmap + rw [← hmap] + exact ContinuousLinearMap.algebraMap_apply _ _ + +/-- The operator exponential applied to a vector is its power-series sum. -/ +theorem exp_apply_eq_tsum [CompleteSpace E] (A : E →L[ℝ] E) (x : E) : + exp A x = ∑' n : ℕ, ((n.factorial : ℝ)⁻¹) • (A ^ n) x := by + have hop : Summable fun n : ℕ ↦ ((n.factorial : ℝ)⁻¹) • A ^ n := by + simpa [NormedSpace.expSeries, + ContinuousMultilinearMap.mkPiAlgebraFin_apply] using + (NormedSpace.expSeries_summable (𝕂 := ℝ) (𝔸 := E →L[ℝ] E) A) + rw [NormedSpace.exp_eq_tsum ℝ] + change (∑' n : ℕ, ((n.factorial : ℝ)⁻¹) • A ^ n) x = _ + exact (ContinuousLinearMap.apply ℝ E x).map_tsum hop + +private theorem smul_pow_apply (c : ℝ) (Q : E →L[ℝ] E) (n : ℕ) (x : E) : + ((c • Q) ^ n) x = c ^ n • (Q ^ n) x := by + induction n generalizing x with + | zero => simp only [pow_zero, one_apply_eq_self, one_smul] + | succ n ih => + rw [pow_succ, pow_succ, mul_apply_eq_comp, ih, + smul_apply, map_smul, smul_smul] + rw [mul_comm (c ^ n) c] + rw [pow_succ, mul_apply_eq_comp] + +/-- Poisson-series representation of a bounded uniformization exponential. -/ +theorem exp_smul_sub_id_apply_eq_tsum [CompleteSpace E] + (Q : E →L[ℝ] E) (c : ℝ) (x : E) : + exp (c • (Q - ContinuousLinearMap.id ℝ E)) x = + ∑' n : ℕ, (Real.exp (-c) * (c ^ n / n.factorial)) • (Q ^ n) x := by + have hcomm : Commute + ((-c) • ContinuousLinearMap.id ℝ E) (c • Q) := by + ext y + simp only [mul_apply_eq_comp, smul_apply, + ContinuousLinearMap.id_apply, map_smul, smul_smul] + rw [mul_comm (-c) c] + have hsplit : c • (Q - ContinuousLinearMap.id ℝ E) = + (-c) • ContinuousLinearMap.id ℝ E + c • Q := by + ext y + simp only [smul_apply, add_apply, + sub_eq_add_neg, smul_add, smul_neg, neg_smul] + exact add_comm _ _ + rw [hsplit, NormedSpace.exp_add_of_commute hcomm, + mul_apply_eq_comp, exp_smul_id_apply] + rw [exp_apply_eq_tsum] + have hsum : Summable fun n : ℕ ↦ + ((n.factorial : ℝ)⁻¹) • ((c • Q) ^ n) x := by + have hop : Summable fun n : ℕ ↦ + ((n.factorial : ℝ)⁻¹) • (c • Q) ^ n := + by + simpa [NormedSpace.expSeries, + ContinuousMultilinearMap.mkPiAlgebraFin_apply] using + (NormedSpace.expSeries_summable (𝕂 := ℝ) + (𝔸 := E →L[ℝ] E) (c • Q)) + simpa only [Function.comp_apply, smul_apply] using! + hop.map (ContinuousLinearMap.apply ℝ E x) + (ContinuousLinearMap.continuous _) + change ((Real.exp (-c)) • ContinuousLinearMap.id ℝ E) + (∑' n : ℕ, ((n.factorial : ℝ)⁻¹) • ((c • Q) ^ n) x) = _ + rw [((Real.exp (-c)) • ContinuousLinearMap.id ℝ E).map_tsum hsum] + · apply tsum_congr + intro n + simp only [smul_apply, ContinuousLinearMap.id_apply, smul_smul] + rw [smul_pow_apply] + simp only [div_eq_mul_inv, smul_smul] + congr 1 + ring + +/-- The Poisson coefficients with parameter `c`. -/ +def poissonWeight (c : ℝ) (n : ℕ) : ℝ := + Real.exp (-c) * (c ^ n / n.factorial) + +theorem poissonWeight_nonneg {c : ℝ} (hc : 0 ≤ c) (n : ℕ) : + 0 ≤ poissonWeight c n := by + exact mul_nonneg (Real.exp_pos _).le + (div_nonneg (pow_nonneg hc n) (Nat.cast_nonneg n.factorial)) + +theorem summable_poissonWeight (c : ℝ) : Summable (poissonWeight c) := by + unfold poissonWeight + exact (Real.summable_pow_div_factorial c).mul_left (Real.exp (-c)) + +theorem tsum_poissonWeight (c : ℝ) : ∑' n, poissonWeight c n = 1 := by + have hseries : ∑' n : ℕ, c ^ n / n.factorial = Real.exp c := by + rw [Real.exp_eq_exp_ℝ, NormedSpace.exp_eq_tsum ℝ] + apply tsum_congr + intro n + simp only [div_eq_mul_inv, smul_eq_mul] + ring + unfold poissonWeight + rw [tsum_mul_left, hseries, ← Real.exp_add] + simp only [neg_add_cancel, Real.exp_zero] + +theorem summable_poissonWeight_smul_pow_apply + [CompleteSpace E] (Q : E →L[ℝ] E) (c : ℝ) (x : E) : + Summable fun n : ℕ ↦ poissonWeight c n • (Q ^ n) x := by + have hop : Summable fun n : ℕ ↦ + ((n.factorial : ℝ)⁻¹) • (c • Q) ^ n := by + simpa [NormedSpace.expSeries, + ContinuousMultilinearMap.mkPiAlgebraFin_apply] using + (NormedSpace.expSeries_summable (𝕂 := ℝ) + (𝔸 := E →L[ℝ] E) (c • Q)) + have happ : Summable fun n : ℕ ↦ + ((n.factorial : ℝ)⁻¹) • ((c • Q) ^ n) x := by + simpa only [Function.comp_apply, smul_apply] using! + hop.map (ContinuousLinearMap.apply ℝ E x) + (ContinuousLinearMap.continuous _) + have hscaled := happ.map + ((Real.exp (-c)) • ContinuousLinearMap.id ℝ E) + (ContinuousLinearMap.continuous _) + apply hscaled.congr + intro n + simp only [Function.comp_apply, smul_apply, + ContinuousLinearMap.id_apply, smul_smul, poissonWeight, div_eq_mul_inv, + smul_pow_apply] + congr 1 + ring + +namespace ContractiveResolvent + +variable [CompleteSpace E] + +/-- A normalized-resolvent invariant closed convex set containing zero is +invariant under every bounded Yosida exponential. -/ +theorem preservesSet_yosidaOperator_of_scaledOperator + (R : ContractiveResolvent E) (C : Set E) (hclosed : IsClosed C) + (hconvex : Convex ℝ C) (hzero : 0 ∈ C) (α : PositiveShift) + (hQ : PreservesSet (R.scaledOperator α) C C) (t : NNReal) : + PreservesSet (R.yosidaOperator α t) C C := by + intro x hx + let c : ℝ := (t : ℝ) * (α : ℝ) + have hc : 0 ≤ c := mul_nonneg t.property α.property.le + have hpowers : ∀ n, ((R.scaledOperator α) ^ n) x ∈ C := + fun n ↦ R.preservesSet_scaledOperator_pow C α hQ n hx + have hmem := Convex.tsum_mem_of_tsum_le_one + hclosed hconvex hzero (poissonWeight c) + (fun n ↦ ((R.scaledOperator α) ^ n) x) + (poissonWeight_nonneg hc) (summable_poissonWeight c) + (by rw [tsum_poissonWeight]) hpowers + (summable_poissonWeight_smul_pow_apply (R.scaledOperator α) c x) + rw [yosidaOperator, yosidaGenerator, smul_smul] + change exp (c • (R.scaledOperator α - ContinuousLinearMap.id ℝ E)) x ∈ C + rw [exp_smul_sub_id_apply_eq_tsum] + exact hmem + +/-- Direct invariant-set transfer from all normalized resolvents to the +canonically generated contraction semigroup. -/ +theorem preservesSet_generatedSemigroup_of_scaledOperator + (R : ContractiveResolvent E) (C : Set E) (hclosed : IsClosed C) + (hconvex : Convex ℝ C) (hzero : 0 ∈ C) + (hQ : ∀ α, PreservesSet (R.scaledOperator α) C C) (t : NNReal) : + PreservesSet (R.generatedSemigroup t) C C := by + exact R.preservesSet_generatedSemigroup C hclosed + (fun α s ↦ R.preservesSet_yosidaOperator_of_scaledOperator + C hclosed hconvex hzero α (hQ α) s) t + +end ContractiveResolvent + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PositiveShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PositiveShift.lean new file mode 100644 index 0000000000..924e0af062 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PositiveShift.lean @@ -0,0 +1,61 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Analysis.SpecificLimits.Basic + +/-! +# Limits along positive real parameters + +This module provides elementary filter limits for positive real resolvent +parameters and a filter-generic criterion that turns a vanishing square bound +into convergence to zero. +-/ + +namespace MarkovProcess.Semigroup + +open Filter Set Topology + +/-- Positive real parameters, ordered by their underlying real values. -/ +abbrev PositiveShift := Set.Ioi (0 : ℝ) + +/-- Positive parameters tend to infinity in the ambient real line. -/ +theorem tendsto_positiveShift_coe_atTop : + Tendsto (fun α : PositiveShift ↦ (α : ℝ)) atTop atTop := by + exact (tendsto_comp_val_Ioi_atTop (a := (0 : ℝ))).2 tendsto_id + +/-- The inverse of a positive parameter tends to zero as the parameter tends to infinity. -/ +theorem tendsto_positiveShift_inv_atTop_zero : + Tendsto (fun α : PositiveShift ↦ (α : ℝ)⁻¹) atTop (nhds 0) := by + exact (tendsto_comp_val_Ioi_atTop (a := (0 : ℝ))).2 tendsto_inv_atTop_zero + +/-- A fixed real constant times the inverse parameter tends to zero. -/ +theorem tendsto_const_mul_positiveShift_inv_atTop_zero (C : ℝ) : + Tendsto (fun α : PositiveShift ↦ C * (α : ℝ)⁻¹) atTop (nhds 0) := by + simpa only [mul_zero] using + (tendsto_const_nhds (x := C)).mul tendsto_positiveShift_inv_atTop_zero + +/-- A nonnegative quantity tends to zero if its square is bounded by a quantity +that tends to zero. This avoids introducing square roots in limit estimates. -/ +theorem tendsto_zero_of_nonneg_sq_le {ι : Type*} {l : Filter ι} + {e r : ι → ℝ} + (he : ∀ i, 0 ≤ e i) + (her : ∀ i, (e i) ^ 2 ≤ r i) + (hr : Tendsto r l (nhds 0)) : + Tendsto e l (nhds 0) := by + rw [Metric.tendsto_nhds] at hr ⊢ + intro ε hε + filter_upwards [hr (ε ^ 2) (sq_pos_of_pos hε)] with i hi + have he_sq_lt : (e i) ^ 2 < ε ^ 2 := by + calc + (e i) ^ 2 ≤ r i := her i + _ ≤ |r i| := le_abs_self (r i) + _ = dist (r i) 0 := by rw [Real.dist_eq, sub_zero] + _ < ε ^ 2 := hi + have he_lt : e i < ε := + (sq_lt_sq₀ (he i) hε.le).1 he_sq_lt + rw [Real.dist_eq, sub_zero, abs_of_nonneg (he i)] + exact he_lt + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Resolvent.lean new file mode 100644 index 0000000000..59bdb11946 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Resolvent.lean @@ -0,0 +1,314 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent +import Mathlib.MeasureTheory.Integral.ExpDecay +import Mathlib.Analysis.SpecialFunctions.ImproperIntegrals + +/-! +# The resolvent of a strongly continuous contraction semigroup + +For a strongly continuous contraction semigroup `S` on a real Banach space and a positive shift +`μ`, the resolvent is the Laplace transform of the orbits, + + `S.resolvent μ x = ∫₀^∞ e^{-μ t} S t x dt`, + +a bounded operator of norm at most `μ⁻¹` (`opNorm_resolvent_le`). The resolvent inverts `μ − L` +on the generator domain, `R_μ (μ f − L f) = f` (`resolvent_smul_sub_generator`, by the product +rule and the fundamental theorem of calculus on `[0, ∞)`), and `μ − L` inverts it on the whole +space: `R_μ x` lies in the domain with `L (R_μ x) = μ R_μ x − x` (`resolvent_mem_generatorDomain`, +`generator_resolvent`). The latter is proved first for `x` in the domain, where `R_μ` commutes +with the difference quotients, and extended to all `x` by density of the domain and closedness of +the generator (`Semigroup/GeneratorClosed.lean`). + +Consequently the domain is the range of every resolvent (`generatorDomain_eq_range_resolvent`), +the resolvents satisfy the resolvent identity (`resolvent_sub_resolvent`) and have dense range +(`denseRange_resolvent`), so they form a contractive resolvent in the sense of +`Semigroup/ContractiveResolvent.lean` (`toContractiveResolvent`). That the semigroup generated by +this contractive resolvent is `S` itself is proved in `Semigroup/ResolventGeneration.lean`. + +Main results: `laplaceIntegrand` and its integrability, `resolvent`, `resolvent_apply`, +`opNorm_resolvent_le`, `operator_resolvent`, `resolvent_smul_sub_generator`, +`resolvent_mem_generatorDomain`, `generator_resolvent`, `generator_eq_of_resolvent_eq`, +`generatorDomain_eq_range_resolvent`, `resolvent_sub_resolvent`, `denseRange_resolvent`, +`toContractiveResolvent`. + +The shift `μ` is a positive real; nothing is asserted for complex shifts or for the spectrum of the +generator beyond the half-line `(0, ∞)`. +-/ + +open MeasureTheory Filter Topology Set +open scoped NNReal + +namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] +variable (S : StronglyContinuousContractionSemigroup E) + +noncomputable section + +section Integrand + +/-- The integrand of the Laplace transform of the orbit of `x` at the shift `μ`, read in the real +time variable. -/ +def laplaceIntegrand (μ : ℝ) (x : E) (t : ℝ) : E := Real.exp (-μ * t) • S (Real.toNNReal t) x + +omit [CompleteSpace E] in +/-- The Laplace integrand, unfolded. -/ +theorem laplaceIntegrand_apply (μ : ℝ) (x : E) (t : ℝ) : + S.laplaceIntegrand μ x t = Real.exp (-μ * t) • S (Real.toNNReal t) x := + rfl + +omit [CompleteSpace E] in +/-- The Laplace integrand is continuous in time. -/ +theorem continuous_laplaceIntegrand (μ : ℝ) (x : E) : Continuous (S.laplaceIntegrand μ x) := + (Real.continuous_exp.comp (continuous_const.mul continuous_id)).smul + (S.continuous_operator_toNNReal x) + +omit [CompleteSpace E] in +/-- The Laplace integrand is dominated by the exponential weight. -/ +theorem norm_laplaceIntegrand_le (μ : ℝ) (x : E) (t : ℝ) : + ‖S.laplaceIntegrand μ x t‖ ≤ Real.exp (-μ * t) * ‖x‖ := by + rw [laplaceIntegrand_apply, norm_smul, Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] + exact mul_le_mul_of_nonneg_left (S.norm_apply_le _ x) (Real.exp_pos _).le + +omit [CompleteSpace E] in +/-- The Laplace integrand is integrable on `(0, ∞)` for a positive shift. -/ +theorem integrableOn_laplaceIntegrand {μ : ℝ} (hμ : 0 < μ) (x : E) : + IntegrableOn (S.laplaceIntegrand μ x) (Ioi 0) := + Integrable.mono' ((exp_neg_integrableOn_Ioi 0 hμ).mul_const ‖x‖) + (S.continuous_laplaceIntegrand μ x).aestronglyMeasurable.restrict + (Eventually.of_forall fun t ↦ S.norm_laplaceIntegrand_le μ x t) + +omit [CompleteSpace E] in +/-- The Laplace integrand is additive in the vector. -/ +theorem laplaceIntegrand_add (μ : ℝ) (x y : E) : + S.laplaceIntegrand μ (x + y) = S.laplaceIntegrand μ x + S.laplaceIntegrand μ y := by + funext t + simp only [laplaceIntegrand_apply, map_add, smul_add, Pi.add_apply] + +omit [CompleteSpace E] in +/-- The Laplace integrand is homogeneous in the vector. -/ +theorem laplaceIntegrand_smul (μ : ℝ) (c : ℝ) (x : E) : + S.laplaceIntegrand μ (c • x) = c • S.laplaceIntegrand μ x := by + funext t + simp only [laplaceIntegrand_apply, map_smul, Pi.smul_apply] + exact smul_comm _ _ _ + +omit [CompleteSpace E] in +/-- The semigroup commutes with the Laplace integrand. -/ +theorem laplaceIntegrand_operator (μ : ℝ) (h : NNReal) (x : E) (t : ℝ) : + S h (S.laplaceIntegrand μ x t) = S.laplaceIntegrand μ (S h x) t := by + simp only [laplaceIntegrand_apply, map_smul, S.commute_apply] + +omit [CompleteSpace E] in +/-- The Laplace integrand tends to zero at infinity for a positive shift. -/ +theorem tendsto_laplaceIntegrand_atTop {μ : ℝ} (hμ : 0 < μ) (x : E) : + Tendsto (S.laplaceIntegrand μ x) atTop (𝓝 0) := by + have hexp : Tendsto (fun t : ℝ ↦ Real.exp (-μ * t)) atTop (𝓝 0) := by + have := Real.tendsto_exp_atBot.comp + (tendsto_neg_atTop_atBot.comp (tendsto_id.const_mul_atTop hμ)) + refine this.congr fun t ↦ ?_ + simp only [Function.comp, id, neg_mul] + refine squeeze_zero_norm (fun t ↦ S.norm_laplaceIntegrand_le μ x t) ?_ + simpa using hexp.mul_const ‖x‖ + +/-- The Laplace transform of the exponential weight. -/ +theorem integral_exp_neg_mul_Ioi_zero {μ : ℝ} (hμ : 0 < μ) : + ∫ t in Ioi (0 : ℝ), Real.exp (-μ * t) = μ⁻¹ := by + have h := integral_comp_mul_left_Ioi (fun t : ℝ ↦ Real.exp (-t)) 0 hμ + simp only [mul_zero, integral_exp_neg_Ioi_zero, smul_eq_mul, mul_one] at h + rw [← h] + refine setIntegral_congr_fun measurableSet_Ioi fun t _ ↦ ?_ + rw [neg_mul] + +omit [CompleteSpace E] in +/-- The Laplace transform of the orbit is bounded by `μ⁻¹ ‖x‖`. -/ +theorem norm_integral_laplaceIntegrand_le {μ : ℝ} (hμ : 0 < μ) (x : E) : + ‖∫ t in Ioi (0 : ℝ), S.laplaceIntegrand μ x t‖ ≤ μ⁻¹ * ‖x‖ := by + rw [← integral_exp_neg_mul_Ioi_zero hμ, ← integral_mul_const] + exact norm_integral_le_of_norm_le ((exp_neg_integrableOn_Ioi 0 hμ).mul_const ‖x‖) + (Eventually.of_forall fun t ↦ S.norm_laplaceIntegrand_le μ x t) + +end Integrand + +section Resolvent + +/-- **The resolvent of the semigroup** at the positive shift `μ`: the Laplace transform of the +orbits, `R_μ x = ∫₀^∞ e^{-μ t} S t x dt`, as a bounded operator. -/ +def resolvent (μ : PositiveShift) : E →L[ℝ] E := + LinearMap.mkContinuous + { toFun := fun x ↦ ∫ t in Ioi (0 : ℝ), S.laplaceIntegrand μ x t + map_add' := fun x y ↦ by + rw [laplaceIntegrand_add] + show ∫ t in Ioi (0 : ℝ), (S.laplaceIntegrand μ x t + S.laplaceIntegrand μ y t) = _ + exact integral_add (S.integrableOn_laplaceIntegrand μ.2 x) + (S.integrableOn_laplaceIntegrand μ.2 y) + map_smul' := fun c x ↦ by + rw [laplaceIntegrand_smul, RingHom.id_apply] + show ∫ t in Ioi (0 : ℝ), c • S.laplaceIntegrand μ x t = _ + exact integral_smul c _ } + (μ : ℝ)⁻¹ (fun x ↦ S.norm_integral_laplaceIntegrand_le μ.2 x) + +omit [CompleteSpace E] in +/-- The resolvent, unfolded as the Laplace transform of the orbit. -/ +theorem resolvent_apply (μ : PositiveShift) (x : E) : + S.resolvent μ x = ∫ t in Ioi (0 : ℝ), S.laplaceIntegrand μ x t := + rfl + +omit [CompleteSpace E] in +/-- The Hille–Yosida bound `‖R_μ‖ ≤ μ⁻¹`. -/ +theorem opNorm_resolvent_le (μ : PositiveShift) : ‖S.resolvent μ‖ ≤ (μ : ℝ)⁻¹ := + LinearMap.mkContinuous_norm_le _ (inv_nonneg.mpr μ.2.le) _ + +/-- The semigroup commutes with its resolvent. -/ +theorem operator_resolvent (μ : PositiveShift) (h : NNReal) (x : E) : + S h (S.resolvent μ x) = S.resolvent μ (S h x) := by + rw [resolvent_apply, resolvent_apply, + ← ContinuousLinearMap.integral_comp_comm (S h) (S.integrableOn_laplaceIntegrand μ.2 x)] + exact setIntegral_congr_fun measurableSet_Ioi fun t _ ↦ S.laplaceIntegrand_operator μ h x t + +/-- **The resolvent inverts `μ − L` on the domain**: `R_μ (μ f − L f) = f`. -/ +theorem resolvent_smul_sub_generator (μ : PositiveShift) (f : S.generatorDomain) : + S.resolvent μ ((μ : ℝ) • (f : E) - S.generator f) = f := by + have hμ : (0 : ℝ) < μ := μ.2 + have hderiv : ∀ t ∈ Ioi (0 : ℝ), HasDerivAt (S.laplaceIntegrand μ f) + (S.laplaceIntegrand μ (S.generator f) t - (μ : ℝ) • S.laplaceIntegrand μ f t) t := by + intro t ht + have hexp : HasDerivAt (fun s : ℝ ↦ Real.exp (-(μ : ℝ) * s)) + (Real.exp (-(μ : ℝ) * t) * (-(μ : ℝ) * 1)) t := + ((hasDerivAt_id t).const_mul (-(μ : ℝ))).exp + refine (hexp.smul (S.hasDerivAt_operator_toNNReal f ht)).congr_deriv ?_ + simp only [laplaceIntegrand_apply, smul_smul] + module + have hcont : ContinuousWithinAt (S.laplaceIntegrand μ f) (Ici 0) 0 := + (S.continuous_laplaceIntegrand μ f).continuousWithinAt + have hint1 : IntegrableOn (fun t ↦ S.laplaceIntegrand μ (S.generator f) t) (Ioi 0) := + S.integrableOn_laplaceIntegrand hμ _ + have hint2 : IntegrableOn (fun t ↦ (μ : ℝ) • S.laplaceIntegrand μ f t) (Ioi 0) := + (S.integrableOn_laplaceIntegrand hμ (f : E)).smul (μ : ℝ) + have hkey := integral_Ioi_of_hasDerivAt_of_tendsto hcont hderiv (hint1.sub hint2) + (S.tendsto_laplaceIntegrand_atTop hμ (f : E)) + rw [integral_sub hint1 hint2, integral_smul, zero_sub, laplaceIntegrand_apply, mul_zero, + Real.exp_zero, one_smul, Real.toNNReal_zero, S.zero_apply] at hkey + rw [map_sub, map_smul, resolvent_apply, resolvent_apply, ← neg_sub, hkey, neg_neg] + +/-- On the domain, the difference quotients of `R_μ f` converge to `R_μ (L f)`. -/ +theorem tendsto_differenceQuotient_resolvent_of_mem (μ : PositiveShift) (f : S.generatorDomain) : + Tendsto (fun t : NNReal ↦ (t : ℝ)⁻¹ • (S t (S.resolvent μ f) - S.resolvent μ f)) (𝓝[>] 0) + (𝓝 (S.resolvent μ (S.generator f))) := by + refine (((S.resolvent μ).continuous.tendsto _).comp (S.tendsto_generator' f)).congr + fun t ↦ ?_ + simp only [Function.comp, map_smul, map_sub, operator_resolvent] + +/-- The resolvent maps the domain into the domain. -/ +theorem resolvent_mem_generatorDomain_of_mem (μ : PositiveShift) (f : S.generatorDomain) : + S.resolvent μ f ∈ S.generatorDomain := + S.mem_generatorDomain_of_tendsto (S.tendsto_differenceQuotient_resolvent_of_mem μ f) + +/-- On the domain, `L (R_μ f) = μ R_μ f − f`. -/ +theorem generator_resolvent_of_mem (μ : PositiveShift) (f : S.generatorDomain) : + S.generator ⟨S.resolvent μ f, S.resolvent_mem_generatorDomain_of_mem μ f⟩ = + (μ : ℝ) • S.resolvent μ f - f := by + have h1 : S.generator ⟨S.resolvent μ f, S.resolvent_mem_generatorDomain_of_mem μ f⟩ = + S.resolvent μ (S.generator f) := + S.generator_eq_of_tendsto ⟨S.resolvent μ f, S.resolvent_mem_generatorDomain_of_mem μ f⟩ + (S.tendsto_differenceQuotient_resolvent_of_mem μ f) + rw [h1] + have h := S.resolvent_smul_sub_generator μ f + rw [map_sub, map_smul] at h + calc S.resolvent μ (S.generator f) + = (μ : ℝ) • S.resolvent μ f - + ((μ : ℝ) • S.resolvent μ f - S.resolvent μ (S.generator f)) := by abel + _ = (μ : ℝ) • S.resolvent μ f - f := by rw [h] + +/-- Approximation of `R_μ x` by resolvents of domain vectors, with convergent generators. -/ +theorem exists_seq_tendsto_resolvent (μ : PositiveShift) (x : E) : + ∃ v : ℕ → S.generatorDomain, + Tendsto (fun n ↦ (v n : E)) atTop (𝓝 (S.resolvent μ x)) ∧ + Tendsto (fun n ↦ S.generator (v n)) atTop (𝓝 ((μ : ℝ) • S.resolvent μ x - x)) := by + obtain ⟨u, hu_mem, hu⟩ := mem_closure_iff_seq_limit.mp (S.dense_generatorDomain x) + have hRu : Tendsto (fun n ↦ S.resolvent μ (u n)) atTop (𝓝 (S.resolvent μ x)) := + ((S.resolvent μ).continuous.tendsto x).comp hu + refine ⟨fun n ↦ ⟨S.resolvent μ (u n), + S.resolvent_mem_generatorDomain_of_mem μ ⟨u n, hu_mem n⟩⟩, hRu, ?_⟩ + have hgen : ∀ n, S.generator ⟨S.resolvent μ (u n), + S.resolvent_mem_generatorDomain_of_mem μ ⟨u n, hu_mem n⟩⟩ = + (μ : ℝ) • S.resolvent μ (u n) - u n := + fun n ↦ S.generator_resolvent_of_mem μ ⟨u n, hu_mem n⟩ + simp_rw [hgen] + exact (hRu.const_smul (μ : ℝ)).sub hu + +/-- **The resolvent maps into the domain.** -/ +theorem resolvent_mem_generatorDomain (μ : PositiveShift) (x : E) : + S.resolvent μ x ∈ S.generatorDomain := by + obtain ⟨v, hv, hL⟩ := S.exists_seq_tendsto_resolvent μ x + exact S.mem_generatorDomain_of_tendsto_generator hv hL + +/-- **`μ − L` inverts the resolvent**: `L (R_μ x) = μ R_μ x − x` for every `x`. -/ +theorem generator_resolvent (μ : PositiveShift) (x : E) : + S.generator ⟨S.resolvent μ x, S.resolvent_mem_generatorDomain μ x⟩ = + (μ : ℝ) • S.resolvent μ x - x := by + obtain ⟨v, hv, hL⟩ := S.exists_seq_tendsto_resolvent μ x + exact S.generator_eq_of_tendsto_generator hv hL + +/-- The generator of a vector exhibited as a resolvent value. -/ +theorem generator_eq_of_resolvent_eq (μ : PositiveShift) {f g : E} (hf : f ∈ S.generatorDomain) + (h : S.resolvent μ g = f) : S.generator ⟨f, hf⟩ = (μ : ℝ) • f - g := by + subst h + exact S.generator_resolvent μ g + +/-- **The domain is the range of the resolvent**, at every positive shift. -/ +theorem generatorDomain_eq_range_resolvent (μ : PositiveShift) : + (S.generatorDomain : Set E) = Set.range (S.resolvent μ) := by + refine Set.Subset.antisymm (fun f hf ↦ ?_) ?_ + · exact ⟨(μ : ℝ) • f - S.generator ⟨f, hf⟩, S.resolvent_smul_sub_generator μ ⟨f, hf⟩⟩ + · rintro _ ⟨y, rfl⟩ + exact S.resolvent_mem_generatorDomain μ y + +/-- **The resolvent identity** `R_α − R_β = (β − α) R_α R_β`. -/ +theorem resolvent_sub_resolvent (α β : PositiveShift) : + S.resolvent α - S.resolvent β = + ((β : ℝ) - (α : ℝ)) • (S.resolvent α).comp (S.resolvent β) := by + ext y + have hz : S.resolvent α ((α : ℝ) • S.resolvent β y - ((β : ℝ) • S.resolvent β y - y)) = + S.resolvent β y := by + have h := S.resolvent_smul_sub_generator α + ⟨S.resolvent β y, S.resolvent_mem_generatorDomain β y⟩ + rw [S.generator_resolvent β y] at h + exact h + rw [map_sub, map_smul, map_sub, map_smul] at hz + simp only [sub_apply, smul_apply, ContinuousLinearMap.comp_apply] + calc S.resolvent α y - S.resolvent β y + = S.resolvent α y - ((α : ℝ) • S.resolvent α (S.resolvent β y) - + ((β : ℝ) • S.resolvent α (S.resolvent β y) - S.resolvent α y)) := by rw [hz] + _ = ((β : ℝ) - (α : ℝ)) • S.resolvent α (S.resolvent β y) := by module + +/-- The resolvent has dense range. -/ +theorem denseRange_resolvent (μ : PositiveShift) : DenseRange (S.resolvent μ) := by + show Dense (Set.range (S.resolvent μ)) + rw [← S.generatorDomain_eq_range_resolvent μ] + exact S.dense_generatorDomain + +/-- **The resolvent family of a strongly continuous contraction semigroup is a contractive +resolvent.** -/ +def toContractiveResolvent : ContractiveResolvent E where + operator := S.resolvent + resolvent_identity := S.resolvent_sub_resolvent + opNorm_le_inv := S.opNorm_resolvent_le + denseRange := S.denseRange_resolvent + +/-- The operators of the contractive resolvent of `S` are its resolvents. -/ +theorem toContractiveResolvent_operator (μ : PositiveShift) : + S.toContractiveResolvent.operator μ = S.resolvent μ := + rfl + +end Resolvent + +end + +end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventComparison.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventComparison.lean new file mode 100644 index 0000000000..b3c8e6d95a --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventComparison.lean @@ -0,0 +1,140 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent + +/-! +# Comparing two semigroups through their resolvents + +Two strongly continuous contraction semigroups `S` and `S'` on the same Banach space have, in +general, unrelated generator domains, so the naive Duhamel comparison of their orbits is not +available. Inserting one resolvent of each semigroup repairs this: the curve + + `y ↦ S y (R_μ (S' (t − y) (R'_μ z)))`, + +where `R_μ` and `R'_μ` are the resolvents of `S` and of `S'` at a positive shift `μ`, takes values +in the generator domain of `S` at every time, is differentiable because `R'_μ z` lies in the +generator domain of `S'`, and its derivative telescopes to the difference of the two resolvents: + + `S t (R_μ (R'_μ z)) − R_μ (S' t (R'_μ z)) = ∫₀ᵗ S y ((R_μ − R'_μ) (S' (t − y) z)) dy.` + +Consequently the left-hand side is bounded by `t` times the largest value of `‖(R_μ − R'_μ) v‖` +over the orbit `{S' u z : 0 ≤ u ≤ t}`, which is a compact set. This is the mechanism behind the +Trotter--Kato theorem in `Semigroup/TrotterKato.lean`. + +Main results: `operator_resolvent_sub_resolvent_operator_eq_integral`, +`norm_operator_resolvent_sub_resolvent_operator_le`. + +Both semigroups are read at the same shift `μ`; nothing is asserted when the two resolvents are +taken at different shifts, and no relation between the two generators is assumed. +-/ + +open Filter MeasureTheory Topology +open scoped NNReal + +namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +noncomputable section + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] + +/-- The derivative of the comparison curve `u ↦ S u (R_μ (S' (t − u) (R'_μ z)))` at an interior +time is `S y ((R_μ − R'_μ) (S' (t − y) z))`: the generator of `S` acting on the resolvent value +and the derivative of the inner orbit cancel except for the difference of the resolvents. -/ +private theorem hasDerivWithinAt_comparison + (S S' : StronglyContinuousContractionSemigroup E) (μ : PositiveShift) (t : ℝ) (z : E) + {y : ℝ} (hy0 : 0 ≤ y) (hyt : y < t) : + HasDerivWithinAt + (fun u : ℝ ↦ S (Real.toNNReal u) + (S.resolvent μ (S' (Real.toNNReal (t - u)) (S'.resolvent μ z)))) + (S (Real.toNNReal y) + (S.resolvent μ (S' (Real.toNNReal (t - y)) z) - + S'.resolvent μ (S' (Real.toNNReal (t - y)) z))) + (Set.Ioi y) y := by + have hwmem : S'.resolvent μ z ∈ S'.generatorDomain := S'.resolvent_mem_generatorDomain μ z + have hmem : S.resolvent μ (S' (Real.toNNReal (t - y)) (S'.resolvent μ z)) ∈ + S.generatorDomain := S.resolvent_mem_generatorDomain μ _ + have hty : (0 : ℝ) < t - y := sub_pos.mpr hyt + have h1 : HasDerivAt (fun u : ℝ ↦ S' (Real.toNNReal u) (S'.resolvent μ z)) + (S' (Real.toNNReal (t - y)) (S'.generator ⟨S'.resolvent μ z, hwmem⟩)) (t - y) := + S'.hasDerivAt_operator_toNNReal ⟨S'.resolvent μ z, hwmem⟩ hty + have h2 : HasDerivAt (fun u : ℝ ↦ t - u) (-1) y := by + simpa using! (hasDerivAt_const y t).sub (hasDerivAt_id y) + have h3 := h1.scomp (𝕜 := ℝ) y h2 + have hd : HasDerivWithinAt + (fun u : ℝ ↦ S.resolvent μ (S' (Real.toNNReal (t - u)) (S'.resolvent μ z))) + (S.resolvent μ ((-1 : ℝ) • + S' (Real.toNNReal (t - y)) (S'.generator ⟨S'.resolvent μ z, hwmem⟩))) + (Set.Ioi y) y := + ((S.resolvent μ).hasFDerivAt.comp_hasDerivAt y h3).hasDerivWithinAt + refine (S.hasDerivWithinAt_operator_apply hy0 hmem hd).congr_deriv ?_ + have hgen1 : S.generator ⟨S.resolvent μ (S' (Real.toNNReal (t - y)) (S'.resolvent μ z)), + hmem⟩ = + (μ : ℝ) • S.resolvent μ (S' (Real.toNNReal (t - y)) (S'.resolvent μ z)) - + S' (Real.toNNReal (t - y)) (S'.resolvent μ z) := + S.generator_eq_of_resolvent_eq μ hmem rfl + have hgen2 : S'.generator ⟨S'.resolvent μ z, hwmem⟩ = (μ : ℝ) • S'.resolvent μ z - z := + S'.generator_eq_of_resolvent_eq μ hwmem rfl + have hcomm : S' (Real.toNNReal (t - y)) (S'.resolvent μ z) = + S'.resolvent μ (S' (Real.toNNReal (t - y)) z) := + S'.operator_resolvent μ _ z + congr 1 + rw [hgen1, hgen2] + simp only [map_sub, map_smul, hcomm] + module + +/-- **The resolvent comparison identity.** For two strongly continuous contraction semigroups +`S` and `S'` with resolvents `R_μ` and `R'_μ` at a common positive shift, +`S t (R_μ (R'_μ z)) − R_μ (S' t (R'_μ z)) = ∫₀ᵗ S y ((R_μ − R'_μ) (S' (t − y) z)) dy`. -/ +theorem operator_resolvent_sub_resolvent_operator_eq_integral + (S S' : StronglyContinuousContractionSemigroup E) (μ : PositiveShift) (t : NNReal) (z : E) : + S t (S.resolvent μ (S'.resolvent μ z)) - S.resolvent μ (S' t (S'.resolvent μ z)) = + ∫ y in (0 : ℝ)..(t : ℝ), S (Real.toNNReal y) + (S.resolvent μ (S' (Real.toNNReal ((t : ℝ) - y)) z) - + S'.resolvent μ (S' (Real.toNNReal ((t : ℝ) - y)) z)) := by + have hcurve : Continuous fun u : ℝ ↦ S (Real.toNNReal u) + (S.resolvent μ (S' (Real.toNNReal ((t : ℝ) - u)) (S'.resolvent μ z))) := by + refine S.continuous_operator_apply continuous_real_toNNReal ?_ + exact (S.resolvent μ).continuous.comp + ((S'.continuous_operator_toNNReal (S'.resolvent μ z)).comp + (continuous_const.sub continuous_id)) + have hderiv : Continuous fun u : ℝ ↦ S (Real.toNNReal u) + (S.resolvent μ (S' (Real.toNNReal ((t : ℝ) - u)) z) - + S'.resolvent μ (S' (Real.toNNReal ((t : ℝ) - u)) z)) := by + refine S.continuous_operator_apply continuous_real_toNNReal ?_ + have h : Continuous fun u : ℝ ↦ S' (Real.toNNReal ((t : ℝ) - u)) z := + (S'.continuous_operator_toNNReal z).comp (continuous_const.sub continuous_id) + exact ((S.resolvent μ).continuous.comp h).sub ((S'.resolvent μ).continuous.comp h) + have hFTC := intervalIntegral.integral_eq_sub_of_hasDeriv_right_of_le t.coe_nonneg + hcurve.continuousOn + (fun y hy ↦ hasDerivWithinAt_comparison S S' μ (t : ℝ) z hy.1.le hy.2) + (hderiv.intervalIntegrable 0 (t : ℝ)) + rw [hFTC] + simp only [sub_self, sub_zero, Real.toNNReal_zero, Real.toNNReal_coe, zero_apply] + +/-- **The resolvent comparison estimate.** If the two resolvents differ by at most `ε` along the +orbit `{S' u z : 0 ≤ u ≤ t}`, then the comparison identity is bounded by `t ε`. -/ +theorem norm_operator_resolvent_sub_resolvent_operator_le + (S S' : StronglyContinuousContractionSemigroup E) (μ : PositiveShift) (t : NNReal) (z : E) + {ε : ℝ} (h : ∀ u ∈ Set.Icc (0 : ℝ) (t : ℝ), + ‖S.resolvent μ (S' (Real.toNNReal u) z) - S'.resolvent μ (S' (Real.toNNReal u) z)‖ ≤ ε) : + ‖S t (S.resolvent μ (S'.resolvent μ z)) - S.resolvent μ (S' t (S'.resolvent μ z))‖ ≤ + (t : ℝ) * ε := by + rw [operator_resolvent_sub_resolvent_operator_eq_integral] + have hbound : ∀ y ∈ Set.uIoc (0 : ℝ) (t : ℝ), + ‖S (Real.toNNReal y) (S.resolvent μ (S' (Real.toNNReal ((t : ℝ) - y)) z) - + S'.resolvent μ (S' (Real.toNNReal ((t : ℝ) - y)) z))‖ ≤ ε := by + intro y hy + rw [Set.uIoc_of_le t.coe_nonneg] at hy + exact le_trans (S.norm_apply_le _ _) + (h _ ⟨by linarith [hy.2], by linarith [hy.1]⟩) + refine le_trans (intervalIntegral.norm_integral_le_of_norm_le_const hbound) (le_of_eq ?_) + rw [sub_zero, abs_of_nonneg t.coe_nonneg, mul_comm] + +end + +end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventGeneration.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventGeneration.lean new file mode 100644 index 0000000000..44b2b034cb --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventGeneration.lean @@ -0,0 +1,86 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness + +/-! +# The semigroup generated by the resolvent of a semigroup + +The two halves of the Hille–Yosida correspondence close up: the contractive resolvent of a +strongly continuous contraction semigroup `S` (`Semigroup/Resolvent.lean`) generates, through +`Semigroup/Generation.lean`, a semigroup whose generator is the generator of `S` +(`Semigroup/GeneratorResolvent.lean`, `generatorDomain_eq_range_resolvent`), and a strongly +continuous contraction semigroup is determined by its generator +(`Semigroup/GeneratorUniqueness.lean`). Hence the generated semigroup is `S` itself +(`generatedSemigroup_toContractiveResolvent`). + +Conversely the resolvent of the semigroup generated by a contractive resolvent `R` is `R` +(`ContractiveResolvent.resolvent_generatedSemigroup`), because both invert `μ − L` and `μ − L` is +injective. + +Main results: `generatorDomain_generatedSemigroup_toContractiveResolvent`, +`generatedSemigroup_toContractiveResolvent`, `ContractiveResolvent.resolvent_generatedSemigroup`, +`ContractiveResolvent.toContractiveResolvent_generatedSemigroup`. + +Nothing is asserted about resolvents that do not come from a semigroup; for those, the +generation theorem of `Semigroup/Generation.lean` is the statement. +-/ + +open scoped NNReal + +namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] +variable (S : StronglyContinuousContractionSemigroup E) + +/-- The semigroup generated by the resolvent of `S` has the generator domain of `S`. -/ +theorem generatorDomain_generatedSemigroup_toContractiveResolvent : + S.toContractiveResolvent.generatedSemigroup.generatorDomain = S.generatorDomain := by + have μ₁ : PositiveShift := ⟨1, Set.mem_Ioi.mpr one_pos⟩ + apply SetLike.coe_injective + exact (S.toContractiveResolvent.generatorDomain_eq_range μ₁).trans + (S.generatorDomain_eq_range_resolvent μ₁).symm + +/-- **The semigroup generated by the resolvent of `S` is `S`.** -/ +theorem generatedSemigroup_toContractiveResolvent : + S.toContractiveResolvent.generatedSemigroup = S := by + have μ₁ : PositiveShift := ⟨1, Set.mem_Ioi.mpr one_pos⟩ + refine S.toContractiveResolvent.generatedSemigroup.ext_of_generator S + S.generatorDomain_generatedSemigroup_toContractiveResolvent ?_ + intro f hT hS + obtain ⟨g, rfl⟩ : f ∈ Set.range (S.resolvent μ₁) := by + rw [← S.generatorDomain_eq_range_resolvent μ₁] + exact hS + rw [S.toContractiveResolvent.generator_apply_of_operator_eq μ₁ (g := g) hT rfl, + S.generator_eq_of_resolvent_eq μ₁ hS rfl] + +end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +namespace MarkovProcess.Semigroup.ContractiveResolvent + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] + +/-- **The resolvent of the generated semigroup is the given resolvent.** -/ +theorem resolvent_generatedSemigroup (R : ContractiveResolvent E) (μ : PositiveShift) : + R.generatedSemigroup.resolvent μ = R.operator μ := by + ext y + apply R.generatedSemigroup.eq_of_smul_sub_generator_eq μ.2 + ⟨R.generatedSemigroup.resolvent μ y, R.generatedSemigroup.resolvent_mem_generatorDomain μ y⟩ + ⟨R.operator μ y, R.operator_mem_generatorDomain μ y⟩ + rw [R.generatedSemigroup.generator_resolvent μ y, R.generator_operator_apply μ y] + simp only [sub_sub_cancel] + +/-- The contractive resolvent of the generated semigroup is the given contractive resolvent. -/ +theorem toContractiveResolvent_generatedSemigroup (R : ContractiveResolvent E) : + R.generatedSemigroup.toContractiveResolvent = R := by + cases R + simp only [StronglyContinuousContractionSemigroup.toContractiveResolvent, + ContractiveResolvent.mk.injEq] + funext μ + exact resolvent_generatedSemigroup _ μ + +end MarkovProcess.Semigroup.ContractiveResolvent diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/StrongOperatorLimit.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/StrongOperatorLimit.lean new file mode 100644 index 0000000000..7831f819d2 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/StrongOperatorLimit.lean @@ -0,0 +1,122 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Analysis.Normed.Operator.Completeness + +/-! +# Strong operator limits of contractions + +This module constructs the pointwise limit of a sequence of continuous linear +contractions on a complete real normed space and records the small convergence +API needed to pass algebraic identities to the limit. +-/ + +open Filter Topology + +namespace MarkovProcess.Semigroup + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + +section Completeness + +variable [CompleteSpace E] + +/-- The continuous linear map obtained as the pointwise limit of a pointwise +Cauchy sequence of contractions. -/ +noncomputable def strongOperatorLimit (T : ℕ → E →L[ℝ] E) + (hT : ∀ n, ‖T n‖ ≤ 1) (hcauchy : ∀ x, CauchySeq (fun n ↦ T n x)) : + E →L[ℝ] E := + ContinuousLinearMap.ofTendstoOfBoundedRange + (fun x ↦ limUnder atTop (fun n ↦ T n x)) T + (tendsto_pi_nhds.2 fun x ↦ (hcauchy x).tendsto_limUnder) + (isBounded_iff_forall_norm_le.2 + ⟨1, Set.forall_mem_range.2 fun n ↦ hT n⟩) + +/-- The defining pointwise convergence of `strongOperatorLimit`. -/ +theorem tendsto_strongOperatorLimit_apply (T : ℕ → E →L[ℝ] E) + (hT : ∀ n, ‖T n‖ ≤ 1) (hcauchy : ∀ x, CauchySeq (fun n ↦ T n x)) (x : E) : + Tendsto (fun n ↦ T n x) atTop (nhds (strongOperatorLimit T hT hcauchy x)) := by + change Tendsto (fun n ↦ T n x) atTop + (nhds (limUnder atTop (fun n ↦ T n x))) + exact (hcauchy x).tendsto_limUnder + +/-- The strong operator limit of contractions is again a contraction pointwise. -/ +theorem norm_strongOperatorLimit_apply_le (T : ℕ → E →L[ℝ] E) + (hT : ∀ n, ‖T n‖ ≤ 1) (hcauchy : ∀ x, CauchySeq (fun n ↦ T n x)) (x : E) : + ‖strongOperatorLimit T hT hcauchy x‖ ≤ ‖x‖ := by + refine le_of_tendsto (tendsto_strongOperatorLimit_apply T hT hcauchy x).norm ?_ + exact Eventually.of_forall fun n ↦ + calc + ‖T n x‖ ≤ ‖T n‖ * ‖x‖ := (T n).le_opNorm x + _ ≤ 1 * ‖x‖ := mul_le_mul_of_nonneg_right (hT n) (norm_nonneg x) + _ = ‖x‖ := one_mul _ + +/-- The strong operator limit of contractions has operator norm at most one. -/ +theorem norm_strongOperatorLimit_le_one (T : ℕ → E →L[ℝ] E) + (hT : ∀ n, ‖T n‖ ≤ 1) (hcauchy : ∀ x, CauchySeq (fun n ↦ T n x)) : + ‖strongOperatorLimit T hT hcauchy‖ ≤ 1 := by + exact ContinuousLinearMap.opNorm_le_bound _ (by norm_num) + (fun x ↦ by + simpa only [one_mul] using norm_strongOperatorLimit_apply_le T hT hcauchy x) + +end Completeness + +/-- A pointwise operator limit may be evaluated along a convergent family of vectors, provided +the approximating operators are contractions. Only the convergence of the operators at the +limiting vector is needed. -/ +theorem tendsto_apply_of_opNorm_le_one {ι : Type*} {l : Filter ι} + (T : ι → E →L[ℝ] E) (Tlim : E →L[ℝ] E) (v : ι → E) (w : E) + (hT : ∀ i, ‖T i‖ ≤ 1) + (hTlim : Tendsto (fun i ↦ T i w) l (nhds (Tlim w))) + (hv : Tendsto v l (nhds w)) : + Tendsto (fun i ↦ T i (v i)) l (nhds (Tlim w)) := by + rw [Metric.tendsto_nhds] + intro ε hε + have hε2 : 0 < ε / 2 := half_pos hε + filter_upwards [Metric.tendsto_nhds.mp hv (ε / 2) hε2, + Metric.tendsto_nhds.mp hTlim (ε / 2) hε2] with i hvi hTi + have hcontract : dist (T i (v i)) (T i w) ≤ dist (v i) w := by + calc + dist (T i (v i)) (T i w) ≤ ‖T i‖ * dist (v i) w := (T i).dist_le_opNorm _ _ + _ ≤ 1 * dist (v i) w := mul_le_mul_of_nonneg_right (hT i) dist_nonneg + _ = dist (v i) w := one_mul _ + calc + dist (T i (v i)) (Tlim w) ≤ dist (T i (v i)) (T i w) + dist (T i w) (Tlim w) := + dist_triangle _ _ _ + _ < ε / 2 + ε / 2 := add_lt_add (hcontract.trans_lt hvi) hTi + _ = ε := add_halves ε + +/-- Two pointwise operator limits may be composed when the outer approximating +operators are contractions. -/ +theorem tendsto_apply_comp_of_opNorm_le_one + (T U : ℕ → E →L[ℝ] E) (Tlim Ulim : E →L[ℝ] E) + (hT : ∀ n, ‖T n‖ ≤ 1) + (hTlim : ∀ x, Tendsto (fun n ↦ T n x) atTop (nhds (Tlim x))) + (hUlim : ∀ x, Tendsto (fun n ↦ U n x) atTop (nhds (Ulim x))) (x : E) : + Tendsto (fun n ↦ T n (U n x)) atTop (nhds (Tlim (Ulim x))) := by + rw [Metric.tendsto_nhds] + intro ε hε + have hε2 : 0 < ε / 2 := half_pos hε + have hU_eventually : ∀ᶠ n in atTop, dist (U n x) (Ulim x) < ε / 2 := + Metric.tendsto_nhds.mp (hUlim x) (ε / 2) hε2 + have hT_eventually : ∀ᶠ n in atTop, dist (T n (Ulim x)) (Tlim (Ulim x)) < ε / 2 := + Metric.tendsto_nhds.mp (hTlim (Ulim x)) (ε / 2) hε2 + filter_upwards [hU_eventually, hT_eventually] with n hUn hTn + have hcontract : dist (T n (U n x)) (T n (Ulim x)) ≤ dist (U n x) (Ulim x) := by + calc + dist (T n (U n x)) (T n (Ulim x)) ≤ ‖T n‖ * dist (U n x) (Ulim x) := + (T n).dist_le_opNorm (U n x) (Ulim x) + _ ≤ 1 * dist (U n x) (Ulim x) := + mul_le_mul_of_nonneg_right (hT n) dist_nonneg + _ = dist (U n x) (Ulim x) := one_mul _ + calc + dist (T n (U n x)) (Tlim (Ulim x)) ≤ + dist (T n (U n x)) (T n (Ulim x)) + + dist (T n (Ulim x)) (Tlim (Ulim x)) := dist_triangle _ _ _ + _ < ε / 2 + ε / 2 := + lt_of_le_of_lt (add_le_add hcontract le_rfl) (add_lt_add hUn hTn) + _ = ε := add_halves ε + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/TrotterKato.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/TrotterKato.lean new file mode 100644 index 0000000000..0fb5c1c968 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/TrotterKato.lean @@ -0,0 +1,224 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison + +/-! +# The Trotter--Kato theorem + +Let `S i` be a family of strongly continuous contraction semigroups on a Banach space, indexed +along a filter, and let `S'` be one more such semigroup. Convergence of the semigroups and +convergence of their resolvents are equivalent: + +* if the resolvents converge strongly at **one** positive shift `μ`, then the semigroups converge + strongly, uniformly on every bounded interval of times + (`tendstoUniformlyOn_operator_of_tendsto_resolvent`, `tendsto_operator_of_tendsto_resolvent`); +* conversely, if the orbits converge at every time, then the resolvents converge at every positive + shift (`tendsto_resolvent_of_tendsto_operator`), by dominated convergence in the Laplace + transform that defines the resolvent. + +The first implication is proved on the range of the twofold resolvent `R'_μ ∘ R'_μ`, which is +dense (`denseRange_resolvent_resolvent`): there the comparison identity of +`Semigroup/ResolventComparison.lean` expresses the difference of the two orbits through the +difference of the two resolvents evaluated along a compact piece of one fixed orbit, where +equibounded strong convergence is uniform (`Semigroup/CompactStrongConvergence.lean`). The +contraction bound then transports the conclusion from the dense set to the whole space, uniformly +in the time. + +Main results: `denseRange_resolvent_resolvent`, +`tendstoUniformlyOn_operator_of_tendsto_resolvent`, `tendsto_operator_of_tendsto_resolvent`, +`tendsto_resolvent_of_tendsto_operator`, `tendsto_resolvent_of_tendsto_resolvent`. + +The converse implication, and the transfer of resolvent convergence from one shift to every +shift that goes through it (`tendsto_resolvent_of_tendsto_resolvent`), read the limit under an +integral and therefore assume the index filter countably generated; the direct implication +assumes nothing about the filter. This is the same-space Trotter--Kato theorem; the version for +semigroups on a sequence of different spaces (Trotter--Kurtz) is not stated. Nothing is asserted +about convergence in the operator norm, nor about families that are merely uniformly bounded +rather than contractive. +-/ + +open Filter MeasureTheory Topology +open scoped NNReal + +namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +noncomputable section + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] +variable {ι : Type*} {l : Filter ι} + +/-- **The twofold resolvent has dense range.** The range of `R_μ` is dense and `R_μ` is +continuous, so the range of `R_μ ∘ R_μ` is dense as well. -/ +theorem denseRange_resolvent_resolvent (S : StronglyContinuousContractionSemigroup E) + (μ : PositiveShift) : DenseRange fun z ↦ S.resolvent μ (S.resolvent μ z) := + (S.denseRange_resolvent μ).comp (S.denseRange_resolvent μ) (S.resolvent μ).continuous + +omit [CompleteSpace E] in +/-- Uniform convergence of the orbits on a bounded interval of times extends from a dense set of +vectors to every vector, by the contraction bound. -/ +private theorem tendstoUniformlyOn_of_dense + {S : ι → StronglyContinuousContractionSemigroup E} + {S' : StronglyContinuousContractionSemigroup E} {b : NNReal} {D : Set E} (hD : Dense D) + (hgood : ∀ y ∈ D, TendstoUniformlyOn (fun i (t : NNReal) ↦ (S i) t y) + (fun t ↦ S' t y) l (Set.Iic b)) (x : E) : + TendstoUniformlyOn (fun i (t : NNReal) ↦ (S i) t x) (fun t ↦ S' t x) l (Set.Iic b) := by + rw [Metric.tendstoUniformlyOn_iff] + intro ε hε + obtain ⟨y, hyD, hxy⟩ := Metric.mem_closure_iff.mp (hD x) (ε / 3) (by positivity) + filter_upwards [Metric.tendstoUniformlyOn_iff.mp (hgood y hyD) (ε / 3) (by positivity)] + with i hi t ht + have hyx : dist y x < ε / 3 := by rwa [dist_comm] at hxy + calc + dist (S' t x) ((S i) t x) ≤ + dist (S' t x) (S' t y) + dist (S' t y) ((S i) t y) + dist ((S i) t y) ((S i) t x) := + dist_triangle4 _ _ _ _ + _ < ε / 3 + ε / 3 + ε / 3 := + add_lt_add (add_lt_add (lt_of_le_of_lt (S'.dist_apply_le t x y) hxy) (hi t ht)) + (lt_of_le_of_lt ((S i).dist_apply_le t y x) hyx) + _ = ε := by ring + +/-- On the range of the twofold resolvent of the limit semigroup, strong convergence of the +resolvents forces uniform convergence of the orbits on a bounded interval of times. -/ +private theorem tendstoUniformlyOn_resolvent_resolvent + {S : ι → StronglyContinuousContractionSemigroup E} + {S' : StronglyContinuousContractionSemigroup E} {μ : PositiveShift} + (hres : ∀ y : E, Tendsto (fun i ↦ (S i).resolvent μ y) l (𝓝 (S'.resolvent μ y))) + (z : E) (b : NNReal) : + TendstoUniformlyOn (fun i (t : NNReal) ↦ (S i) t (S'.resolvent μ (S'.resolvent μ z))) + (fun t ↦ S' t (S'.resolvent μ (S'.resolvent μ z))) l (Set.Iic b) := by + rw [Metric.tendstoUniformlyOn_iff] + intro ε hε + set ε₁ : ℝ := ε / (3 * ((b : ℝ) + 1)) with hε₁def + have hε₁ : 0 < ε₁ := by rw [hε₁def]; positivity + have key : (b : ℝ) * ε₁ + ε₁ = ε / 3 := by + rw [hε₁def] + field_simp + have hDbound : ∀ i, ‖(S i).resolvent μ - S'.resolvent μ‖ ≤ 2 * (μ : ℝ)⁻¹ := by + intro i + calc + ‖(S i).resolvent μ - S'.resolvent μ‖ ≤ ‖(S i).resolvent μ‖ + ‖S'.resolvent μ‖ := + norm_sub_le _ _ + _ ≤ (μ : ℝ)⁻¹ + (μ : ℝ)⁻¹ := + add_le_add ((S i).opNorm_resolvent_le μ) (S'.opNorm_resolvent_le μ) + _ = 2 * (μ : ℝ)⁻¹ := by ring + have hDzero : ∀ y : E, Tendsto (fun i ↦ ((S i).resolvent μ - S'.resolvent μ) y) l (𝓝 0) := by + intro y + simp only [sub_apply] + simpa using (hres y).sub (tendsto_const_nhds (x := S'.resolvent μ y)) + have hK₁ : IsCompact ((fun u : ℝ ↦ S' (Real.toNNReal u) z) '' Set.Icc (0 : ℝ) (b : ℝ)) := + isCompact_Icc.image (S'.continuous_operator_toNNReal z) + have hK₂ : IsCompact + ((fun u : ℝ ↦ S' (Real.toNNReal u) (S'.resolvent μ z)) '' Set.Icc (0 : ℝ) (b : ℝ)) := + isCompact_Icc.image (S'.continuous_operator_toNNReal (S'.resolvent μ z)) + have h1 := eventually_forall_mem_norm_apply_le_of_isCompact + (fun i ↦ (S i).resolvent μ - S'.resolvent μ) hDbound hDzero hK₁ hε₁ + have h2 := eventually_forall_mem_norm_apply_le_of_isCompact + (fun i ↦ (S i).resolvent μ - S'.resolvent μ) hDbound hDzero hK₂ hε₁ + have h3 : ∀ᶠ i in l, ‖(S i).resolvent μ (S'.resolvent μ z) - + S'.resolvent μ (S'.resolvent μ z)‖ < ε / 3 := by + have h := NormedAddGroup.tendsto_nhds_zero.mp (hDzero (S'.resolvent μ z)) (ε / 3) + (by positivity) + simpa only [sub_apply] using h + filter_upwards [h1, h2, h3] with i hi1 hi2 hi3 t ht + have htb : (t : ℝ) ≤ (b : ℝ) := NNReal.coe_le_coe.mpr ht + have hterm1 : ‖(S i) t (S'.resolvent μ (S'.resolvent μ z)) - + (S i) t ((S i).resolvent μ (S'.resolvent μ z))‖ < ε / 3 := by + have hle := (S i).norm_apply_le t + (S'.resolvent μ (S'.resolvent μ z) - (S i).resolvent μ (S'.resolvent μ z)) + rw [map_sub] at hle + refine lt_of_le_of_lt hle ?_ + rwa [norm_sub_rev] + have hterm2 : ‖(S i) t ((S i).resolvent μ (S'.resolvent μ z)) - + (S i).resolvent μ (S' t (S'.resolvent μ z))‖ ≤ (t : ℝ) * ε₁ := by + refine norm_operator_resolvent_sub_resolvent_operator_le (S i) S' μ t z ?_ + intro u hu + have hmem : S' (Real.toNNReal u) z ∈ + (fun u : ℝ ↦ S' (Real.toNNReal u) z) '' Set.Icc (0 : ℝ) (b : ℝ) := + ⟨u, ⟨hu.1, hu.2.trans htb⟩, rfl⟩ + simpa only [sub_apply] using hi1 _ hmem + have hterm3 : ‖(S i).resolvent μ (S' t (S'.resolvent μ z)) - + S' t (S'.resolvent μ (S'.resolvent μ z))‖ ≤ ε₁ := by + rw [S'.operator_resolvent μ t (S'.resolvent μ z)] + have hmem : S' t (S'.resolvent μ z) ∈ + (fun u : ℝ ↦ S' (Real.toNNReal u) (S'.resolvent μ z)) '' Set.Icc (0 : ℝ) (b : ℝ) := + ⟨(t : ℝ), ⟨t.coe_nonneg, htb⟩, by simp only [Real.toNNReal_coe]⟩ + simpa only [sub_apply] using hi2 _ hmem + have htri : ‖(S i) t (S'.resolvent μ (S'.resolvent μ z)) - + S' t (S'.resolvent μ (S'.resolvent μ z))‖ ≤ + ‖(S i) t (S'.resolvent μ (S'.resolvent μ z)) - + (S i) t ((S i).resolvent μ (S'.resolvent μ z))‖ + + ‖(S i) t ((S i).resolvent μ (S'.resolvent μ z)) - + (S i).resolvent μ (S' t (S'.resolvent μ z))‖ + + ‖(S i).resolvent μ (S' t (S'.resolvent μ z)) - + S' t (S'.resolvent μ (S'.resolvent μ z))‖ := by + simpa only [dist_eq_norm] using + dist_triangle4 ((S i) t (S'.resolvent μ (S'.resolvent μ z))) + ((S i) t ((S i).resolvent μ (S'.resolvent μ z))) + ((S i).resolvent μ (S' t (S'.resolvent μ z))) + (S' t (S'.resolvent μ (S'.resolvent μ z))) + have hsplit : (t : ℝ) * ε₁ + ε₁ ≤ ε / 3 := by + have hmul := mul_le_mul_of_nonneg_right htb hε₁.le + linarith [key] + rw [dist_eq_norm, norm_sub_rev] + linarith [hterm1, hterm2, hterm3, htri] + +/-- **The Trotter--Kato theorem.** If the resolvents of the semigroups `S i` converge strongly to +the resolvent of `S'` at one positive shift, then the orbits converge uniformly on every bounded +interval of times. -/ +theorem tendstoUniformlyOn_operator_of_tendsto_resolvent + {S : ι → StronglyContinuousContractionSemigroup E} + {S' : StronglyContinuousContractionSemigroup E} {μ : PositiveShift} + (hres : ∀ y : E, Tendsto (fun i ↦ (S i).resolvent μ y) l (𝓝 (S'.resolvent μ y))) + (x : E) (b : NNReal) : + TendstoUniformlyOn (fun i (t : NNReal) ↦ (S i) t x) (fun t ↦ S' t x) l (Set.Iic b) := by + refine tendstoUniformlyOn_of_dense (S := S) (S' := S') (b := b) + (D := Set.range fun z ↦ S'.resolvent μ (S'.resolvent μ z)) + (S'.denseRange_resolvent_resolvent μ) ?_ x + rintro _ ⟨z, rfl⟩ + exact tendstoUniformlyOn_resolvent_resolvent hres z b + +/-- **Strong convergence of the semigroups from strong convergence of the resolvents.** -/ +theorem tendsto_operator_of_tendsto_resolvent + {S : ι → StronglyContinuousContractionSemigroup E} + {S' : StronglyContinuousContractionSemigroup E} {μ : PositiveShift} + (hres : ∀ y : E, Tendsto (fun i ↦ (S i).resolvent μ y) l (𝓝 (S'.resolvent μ y))) + (x : E) (t : NNReal) : Tendsto (fun i ↦ (S i) t x) l (𝓝 (S' t x)) := + (tendstoUniformlyOn_operator_of_tendsto_resolvent hres x t).tendsto_at (Set.mem_Iic.2 le_rfl) + +omit [CompleteSpace E] in +/-- **Strong convergence of the resolvents from strong convergence of the semigroups**, by +dominated convergence in the Laplace transform of the orbit. -/ +theorem tendsto_resolvent_of_tendsto_operator [l.IsCountablyGenerated] + {S : ι → StronglyContinuousContractionSemigroup E} + {S' : StronglyContinuousContractionSemigroup E} {x : E} + (hop : ∀ t : NNReal, Tendsto (fun i ↦ (S i) t x) l (𝓝 (S' t x))) (μ : PositiveShift) : + Tendsto (fun i ↦ (S i).resolvent μ x) l (𝓝 (S'.resolvent μ x)) := by + simp only [resolvent_apply] + refine tendsto_integral_filter_of_dominated_convergence + (fun s : ℝ ↦ Real.exp (-(μ : ℝ) * s) * ‖x‖) + (Eventually.of_forall fun i ↦ + ((S i).continuous_laplaceIntegrand μ x).aestronglyMeasurable.restrict) + (Eventually.of_forall fun i ↦ Eventually.of_forall fun s ↦ + (S i).norm_laplaceIntegrand_le (μ : ℝ) x s) + ((exp_neg_integrableOn_Ioi 0 μ.2).mul_const ‖x‖) (Eventually.of_forall fun s ↦ ?_) + simp only [laplaceIntegrand_apply] + exact (hop (Real.toNNReal s)).const_smul (Real.exp (-(μ : ℝ) * s)) + +/-- Strong convergence of the resolvents at one positive shift propagates to every positive +shift. -/ +theorem tendsto_resolvent_of_tendsto_resolvent [l.IsCountablyGenerated] + {S : ι → StronglyContinuousContractionSemigroup E} + {S' : StronglyContinuousContractionSemigroup E} {μ : PositiveShift} + (hres : ∀ y : E, Tendsto (fun i ↦ (S i).resolvent μ y) l (𝓝 (S'.resolvent μ y))) + (ν : PositiveShift) (x : E) : + Tendsto (fun i ↦ (S i).resolvent ν x) l (𝓝 (S'.resolvent ν x)) := + tendsto_resolvent_of_tendsto_operator + (fun t ↦ tendsto_operator_of_tendsto_resolvent hres x t) ν + +end + +end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean new file mode 100644 index 0000000000..bcac49b1b8 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean @@ -0,0 +1,152 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic + +/-! +# Bounded Yosida approximations + +For a contractive resolvent `R`, this file defines the bounded generator +`G_α = α (α R_α - I)` and its exponential contraction semigroup. It also +records commutation and the exact formula on the range of a fixed resolvent. +-/ + +open Filter Topology +open NormedSpace + +noncomputable section + +namespace MarkovProcess.Semigroup + +namespace ContractiveResolvent + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + +/- Head-class caches for the operator type. Every repeated closed instance +search in this file is rooted at `E →L[ℝ] E`; resolving each head class once +here stops the normed-hierarchy walk on `E` from being replayed at every `•`, +`exp` and `comp`. -/ +private instance cacheSMulCLM : SMul ℝ (E →L[ℝ] E) := inferInstance +private instance cacheModuleCLM : Module ℝ (E →L[ℝ] E) := inferInstance +private instance cacheAlgebraCLM : Algebra ℝ (E →L[ℝ] E) := inferInstance +private instance cacheIsTopologicalRingCLM : IsTopologicalRing (E →L[ℝ] E) := inferInstance + +/-- The bounded Yosida generator `G_α = α (α R_α - I)`. -/ +def yosidaGenerator (R : ContractiveResolvent E) (α : PositiveShift) : E →L[ℝ] E := + (α : ℝ) • (R.scaledOperator α - ContinuousLinearMap.id ℝ E) + +private theorem commute_smul_smul_of_comp_eq (A B : E →L[ℝ] E) + (h : A.comp B = B.comp A) (a b : ℝ) : + Commute (a • A) (b • B) := by + change (a • A).comp (b • B) = (b • B).comp (a • A) + ext x + change a • A (b • B x) = b • B (a • A x) + rw [map_smul, map_smul, smul_smul, smul_smul, mul_comm a b] + exact congrArg (fun z : E ↦ (b * a) • z) (DFunLike.congr_fun h x) + +section CompleteSpace + +variable [CompleteSpace E] + +/-- The exponential of the bounded Yosida generator at nonnegative time. -/ +def yosidaOperator (R : ContractiveResolvent E) (α : PositiveShift) (t : NNReal) : + E →L[ℝ] E := + exp ((t : ℝ) • R.yosidaGenerator α) + +omit [CompleteSpace E] in +@[simp] +theorem yosidaOperator_zero (R : ContractiveResolvent E) (α : PositiveShift) : + R.yosidaOperator α 0 = ContinuousLinearMap.id ℝ E := by + rw [yosidaOperator, NNReal.coe_zero, zero_smul, exp_zero] + rfl + +/-- The bounded Yosida exponential satisfies the semigroup law. -/ +theorem yosidaOperator_add (R : ContractiveResolvent E) (α : PositiveShift) (s t : NNReal) : + R.yosidaOperator α (s + t) = + (R.yosidaOperator α s).comp (R.yosidaOperator α t) := by + rw [yosidaOperator, yosidaOperator, yosidaOperator, NNReal.coe_add, add_smul] + exact exp_add_of_commute + (commute_smul_smul_of_comp_eq _ _ rfl (s : ℝ) (t : ℝ)) + +/-- Every bounded Yosida exponential is contractive in operator norm. -/ +theorem norm_yosidaOperator_le_one (R : ContractiveResolvent E) + (α : PositiveShift) (t : NNReal) : + ‖R.yosidaOperator α t‖ ≤ 1 := by + have htime : 0 ≤ (t : ℝ) * (α : ℝ) := + mul_nonneg t.property α.property.le + rw [yosidaOperator, yosidaGenerator, smul_smul] + exact norm_exp_continuousLinearMap_smul_sub_id_le_one htime + (R.opNorm_scaledOperator_le_one α) + +/-- Orbits of the bounded Yosida exponential are continuous in nonnegative time. -/ +theorem continuous_yosidaOperator_apply (R : ContractiveResolvent E) + (α : PositiveShift) (x : E) : + Continuous (fun t : NNReal ↦ R.yosidaOperator α t x) := by + unfold yosidaOperator + fun_prop + +/-- The exponential Yosida approximation as a strongly continuous contraction semigroup. -/ +def yosidaSemigroup (R : ContractiveResolvent E) (α : PositiveShift) : + StronglyContinuousContractionSemigroup E where + operator := R.yosidaOperator α + operator_zero := R.yosidaOperator_zero α + operator_add := R.yosidaOperator_add α + opNorm_le_one := R.norm_yosidaOperator_le_one α + continuous_orbit := R.continuous_yosidaOperator_apply α + +@[simp] +theorem yosidaSemigroup_apply (R : ContractiveResolvent E) + (α : PositiveShift) (t : NNReal) : + R.yosidaSemigroup α t = R.yosidaOperator α t := + rfl + +end CompleteSpace + +/-- Yosida generators at different shifts commute. -/ +theorem yosidaGenerator_commute (R : ContractiveResolvent E) (α β : PositiveShift) : + Commute (R.yosidaGenerator α) (R.yosidaGenerator β) := by + have hscaled : Commute (R.scaledOperator α) (R.scaledOperator β) := by + unfold scaledOperator + exact commute_smul_smul_of_comp_eq _ _ (R.operator_comm α β) (α : ℝ) (β : ℝ) + have hsub : Commute + (R.scaledOperator α - ContinuousLinearMap.id ℝ E) + (R.scaledOperator β - ContinuousLinearMap.id ℝ E) := + (hscaled.sub_right (Commute.one_right _)).sub_left (Commute.one_left _) + exact commute_smul_smul_of_comp_eq _ _ hsub.eq (α : ℝ) (β : ℝ) + +/-- Yosida exponential approximants at arbitrary shifts and times commute. -/ +theorem yosidaOperator_commute (R : ContractiveResolvent E) + (α β : PositiveShift) (s t : NNReal) : + Commute (R.yosidaOperator α s) (R.yosidaOperator β t) := by + exact (commute_smul_smul_of_comp_eq _ _ (R.yosidaGenerator_commute α β).eq + (s : ℝ) (t : ℝ)).exp + +/-- Exact action of a Yosida generator on the range of a fixed resolvent. -/ +theorem yosidaGenerator_apply_operator (R : ContractiveResolvent E) + (α μ : PositiveShift) (y : E) : + R.yosidaGenerator α (R.operator μ y) = + R.scaledOperator α ((μ : ℝ) • R.operator μ y - y) := by + rw [yosidaGenerator] + change + (α : ℝ) • + (R.scaledOperator α (R.operator μ y) - R.operator μ y) = + R.scaledOperator α ((μ : ℝ) • R.operator μ y - y) + rw [R.scaledOperator_apply_sub_on_range α μ y] + rfl + +/-- On a fixed resolvent range, bounded Yosida generators converge to the +corresponding core value. -/ +theorem tendsto_yosidaGenerator_apply_operator (R : ContractiveResolvent E) + (μ : PositiveShift) (y : E) : + Tendsto (fun α : PositiveShift ↦ R.yosidaGenerator α (R.operator μ y)) + atTop (nhds ((μ : ℝ) • R.operator μ y - y)) := by + simpa only [yosidaGenerator_apply_operator] using + R.tendsto_scaledOperator_apply ((μ : ℝ) • R.operator μ y - y) + +end ContractiveResolvent + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaStrongLimit.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaStrongLimit.lean new file mode 100644 index 0000000000..afc643c161 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaStrongLimit.lean @@ -0,0 +1,174 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit + +/-! +# Strong limits of Yosida approximations + +This file constructs the canonical contraction obtained by taking the strong +limit of the Yosida exponentials along the shifts `n + 1`. Continuity of its +orbits is proved in `Semigroup/Generation.lean`, from the criterion of +`Semigroup/OrbitContinuity.lean`. +-/ + +open Filter NormedSpace Set Topology + +noncomputable section + +namespace MarkovProcess.Semigroup + +/-- The canonical sequence of positive shifts, `n + 1`. -/ +def naturalShift (n : ℕ) : PositiveShift := + ⟨(n : ℝ) + 1, by + change 0 < (n : ℝ) + 1 + exact add_pos_of_nonneg_of_pos (Nat.cast_nonneg n) zero_lt_one⟩ + +@[simp] +theorem naturalShift_coe (n : ℕ) : (naturalShift n : ℝ) = n + 1 := + rfl + +/-- The canonical positive shifts tend to infinity. -/ +theorem tendsto_naturalShift_atTop : Tendsto naturalShift atTop atTop := by + rw [tendsto_atTop_atTop] + intro α + obtain ⟨n, hn⟩ := exists_nat_ge (α : ℝ) + exact ⟨n, fun m hm ↦ by + change (α : ℝ) ≤ (m : ℝ) + 1 + exact hn.trans (le_add_of_nonneg_right zero_le_one) |>.trans + (add_le_add (Nat.cast_le.2 hm) le_rfl)⟩ + +namespace ContractiveResolvent + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + +/-- Along the canonical shifts, Yosida generators converge on every fixed +resolvent range. -/ +theorem tendsto_yosidaGenerator_naturalShift_apply_operator + (R : ContractiveResolvent E) (mu : PositiveShift) (y : E) : + Tendsto (fun n ↦ R.yosidaGenerator (naturalShift n) (R.operator mu y)) + atTop (nhds ((mu : ℝ) • R.operator mu y - y)) := by + exact (R.tendsto_yosidaGenerator_apply_operator mu y).comp tendsto_naturalShift_atTop + +/-- Along the canonical shifts, Yosida generators are Cauchy on every fixed +resolvent range. -/ +theorem cauchySeq_yosidaGenerator_naturalShift_apply_operator + (R : ContractiveResolvent E) (mu : PositiveShift) (y : E) : + CauchySeq (fun n ↦ R.yosidaGenerator (naturalShift n) (R.operator mu y)) := + (R.tendsto_yosidaGenerator_naturalShift_apply_operator mu y).cauchySeq + +section CompleteSpace + +variable [CompleteSpace E] + +/-- At a fixed time, the canonical Yosida exponentials are Cauchy on every +fixed resolvent range. -/ +theorem cauchySeq_yosidaOperator_naturalShift_apply_operator + (R : ContractiveResolvent E) (mu : PositiveShift) (t : NNReal) (y : E) : + CauchySeq (fun n ↦ R.yosidaOperator (naturalShift n) t (R.operator mu y)) := by + by_cases ht : t = 0 + · subst t + simpa only [R.yosidaOperator_zero, ContinuousLinearMap.id_apply] using + (cauchySeq_const (R.operator mu y)) + · rw [Metric.cauchySeq_iff] + intro eps heps + have htpos : 0 < (t : ℝ) := NNReal.coe_pos.2 (pos_iff_ne_zero.2 ht) + obtain ⟨N, hN⟩ := Metric.cauchySeq_iff.mp + (R.cauchySeq_yosidaGenerator_naturalShift_apply_operator mu y) + (eps / (t : ℝ)) (div_pos heps htpos) + refine ⟨N, fun m hm n hn ↦ ?_⟩ + have hcontract (k : ℕ) (s : ℝ) (hs : s ∈ Icc (0 : ℝ) (t : ℝ)) : + ‖exp (s • R.yosidaGenerator (naturalShift k))‖ ≤ 1 := by + simpa only [yosidaOperator] using! + R.norm_yosidaOperator_le_one (naturalShift k) ⟨s, hs.1⟩ + have hestimate := norm_exp_sub_exp_apply_le + (R.yosidaGenerator (naturalShift n)) + (R.yosidaGenerator (naturalShift m)) + (R.yosidaGenerator_commute (naturalShift n) (naturalShift m)) + (NNReal.coe_nonneg t) (hcontract n) (hcontract m) (R.operator mu y) + rw [dist_eq_norm] + change + ‖exp ((t : ℝ) • R.yosidaGenerator (naturalShift m)) (R.operator mu y) - + exp ((t : ℝ) • R.yosidaGenerator (naturalShift n)) (R.operator mu y)‖ < eps + refine lt_of_le_of_lt hestimate ?_ + rw [sub_apply, ← dist_eq_norm] + calc + (t : ℝ) * dist + (R.yosidaGenerator (naturalShift m) (R.operator mu y)) + (R.yosidaGenerator (naturalShift n) (R.operator mu y)) + < (t : ℝ) * (eps / (t : ℝ)) := + mul_lt_mul_of_pos_left (hN m hm n hn) htpos + _ = eps := mul_div_cancel₀ eps htpos.ne' + +/-- The canonical Yosida exponential sequence at a fixed time. -/ +def yosidaOperatorSequence (R : ContractiveResolvent E) (t : NNReal) : + ℕ → E →L[ℝ] E := + fun n ↦ R.yosidaOperator (naturalShift n) t + +theorem norm_yosidaOperatorSequence_le_one (R : ContractiveResolvent E) (t : NNReal) (n : ℕ) : + ‖R.yosidaOperatorSequence t n‖ ≤ 1 := + R.norm_yosidaOperator_le_one (naturalShift n) t + +theorem cauchySeq_yosidaOperatorSequence_apply + (R : ContractiveResolvent E) (t : NNReal) (x : E) : + CauchySeq (fun n ↦ R.yosidaOperatorSequence t n x) := by + let one : PositiveShift := ⟨1, by norm_num⟩ + exact MarkovProcess.cauchySeq_of_denseRange_of_opNorm_le_one + (R.yosidaOperatorSequence t) (R.operator one) + (R.norm_yosidaOperatorSequence_le_one t) (R.denseRange one) + (R.cauchySeq_yosidaOperator_naturalShift_apply_operator one t) x + +/-- The canonical strong limit of the Yosida exponential approximants. -/ +def yosidaStrongLimit (R : ContractiveResolvent E) (t : NNReal) : E →L[ℝ] E := + strongOperatorLimit (R.yosidaOperatorSequence t) + (R.norm_yosidaOperatorSequence_le_one t) + (R.cauchySeq_yosidaOperatorSequence_apply t) + +/-- The canonical Yosida exponential approximants converge strongly. -/ +theorem tendsto_yosidaOperator_naturalShift_apply + (R : ContractiveResolvent E) (t : NNReal) (x : E) : + Tendsto (fun n ↦ R.yosidaOperator (naturalShift n) t x) atTop + (nhds (R.yosidaStrongLimit t x)) := by + exact tendsto_strongOperatorLimit_apply (R.yosidaOperatorSequence t) + (R.norm_yosidaOperatorSequence_le_one t) + (R.cauchySeq_yosidaOperatorSequence_apply t) x + +/-- The canonical strong limit is a contraction. -/ +theorem norm_yosidaStrongLimit_le_one (R : ContractiveResolvent E) (t : NNReal) : + ‖R.yosidaStrongLimit t‖ ≤ 1 := by + exact norm_strongOperatorLimit_le_one (R.yosidaOperatorSequence t) + (R.norm_yosidaOperatorSequence_le_one t) + (R.cauchySeq_yosidaOperatorSequence_apply t) + +@[simp] +theorem yosidaStrongLimit_zero (R : ContractiveResolvent E) : + R.yosidaStrongLimit 0 = ContinuousLinearMap.id ℝ E := by + ext x + exact tendsto_nhds_unique (R.tendsto_yosidaOperator_naturalShift_apply 0 x) + (by simpa only [R.yosidaOperator_zero, ContinuousLinearMap.id_apply] using + (tendsto_const_nhds : Tendsto (fun _ : ℕ ↦ x) atTop (nhds x))) + +/-- The canonical strong limits satisfy the semigroup law. -/ +theorem yosidaStrongLimit_add (R : ContractiveResolvent E) (s t : NNReal) : + R.yosidaStrongLimit (s + t) = + (R.yosidaStrongLimit s).comp (R.yosidaStrongLimit t) := by + ext x + apply tendsto_nhds_unique (R.tendsto_yosidaOperator_naturalShift_apply (s + t) x) + have hcomp := tendsto_apply_comp_of_opNorm_le_one + (R.yosidaOperatorSequence s) (R.yosidaOperatorSequence t) + (R.yosidaStrongLimit s) (R.yosidaStrongLimit t) + (R.norm_yosidaOperatorSequence_le_one s) + (R.tendsto_yosidaOperator_naturalShift_apply s) + (R.tendsto_yosidaOperator_naturalShift_apply t) x + simpa only [yosidaOperatorSequence, R.yosidaOperator_add, + ContinuousLinearMap.comp_apply] using hcomp + +end CompleteSpace + +end ContractiveResolvent + +end MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time.lean b/LeanPool/MarkovProcess/MarkovProcess/Time.lean new file mode 100644 index 0000000000..5eca3a2d2a --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Time.lean @@ -0,0 +1,20 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove +import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes +import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid + +/-! +# Time + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean new file mode 100644 index 0000000000..d5a87a9bca --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean @@ -0,0 +1,146 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Data.NNRat.Defs +import Mathlib.Data.NNReal.Defs +import Mathlib.Data.Rat.Cast.Order +import Mathlib.Data.Rat.Encodable +import Mathlib.Logic.Denumerable +import Mathlib.MeasureTheory.MeasurableSpace.Embedding + +/-! +# Countable dense time indices + +This file gives finite prefixes and measurable path reindexings for an arbitrary enumeration of +a countably infinite type. The fixed enumeration of nonnegative rational times below is arbitrary, +not increasing. No probability law, projective limit, stochastic process, continuity, or path +regularity is constructed here. +-/ + +namespace MarkovProcess + +noncomputable section + +namespace CountableEnumeration + +variable {D : Type*} + +/-- The first `n` values of an enumeration. -/ +def «prefix» (e : ℕ ≃ D) (n : ℕ) : Finset D := + Finset.map e.toEmbedding (Finset.range n) + +@[simp] +theorem mem_prefix_iff (e : ℕ ≃ D) (n : ℕ) (d : D) : + d ∈ «prefix» e n ↔ e.symm d < n := by + simp only [«prefix», Finset.mem_map, Finset.mem_range] + constructor + · rintro ⟨k, hk, hkd⟩ + rw [← hkd] + change e.symm (e k) < n + rw [e.symm_apply_apply] + exact hk + · intro hd + exact ⟨e.symm d, hd, e.apply_symm_apply d⟩ + +@[simp] +theorem prefix_zero (e : ℕ ≃ D) : «prefix» e 0 = ∅ := by + rw [«prefix», Finset.range_zero, Finset.map_empty] + +@[simp] +theorem prefix_succ (e : ℕ ≃ D) (n : ℕ) : + «prefix» e (n + 1) = + Finset.cons (e n) («prefix» e n) (by + rw [mem_prefix_iff, e.symm_apply_apply] + exact Nat.lt_irrefl n) := by + ext d + rw [mem_prefix_iff, Finset.mem_cons, mem_prefix_iff, Nat.lt_succ_iff] + constructor + · intro h + obtain h | h := h.eq_or_lt + · left + apply e.symm.injective + simpa only [e.symm_apply_apply] using h + · exact Or.inr h + · rintro (rfl | h) + · rw [e.symm_apply_apply] + · exact h.le + +theorem prefix_mono (e : ℕ ≃ D) : Monotone («prefix» e) := by + intro m n hmn d + simp only [mem_prefix_iff] + exact fun hd ↦ hd.trans_le hmn + +@[simp] +theorem card_prefix (e : ℕ ≃ D) (n : ℕ) : («prefix» e n).card = n := by + rw [«prefix», Finset.card_map, Finset.card_range] + +theorem mem_prefix_self (e : ℕ ≃ D) (d : D) : d ∈ «prefix» e (e.symm d + 1) := by + rw [mem_prefix_iff] + exact Nat.lt_succ_self _ + +theorem exists_mem_prefix (e : ℕ ≃ D) (d : D) : ∃ n, d ∈ «prefix» e n := + ⟨e.symm d + 1, mem_prefix_self e d⟩ + +/-- The enumeration equivalence between `Fin n` and its first `n` values. -/ +noncomputable def finEquivPrefix (e : ℕ ≃ D) (n : ℕ) : Fin n ≃ «prefix» e n := + Equiv.ofBijective + (fun i ↦ ⟨e i, by rw [mem_prefix_iff]; simpa only [e.symm_apply_apply] using i.isLt⟩) + ⟨fun _ _ h ↦ Fin.ext (e.injective (congrArg Subtype.val h)), fun d ↦ by + refine ⟨⟨e.symm d, ?_⟩, ?_⟩ + · exact (mem_prefix_iff e n d).mp d.property + · apply Subtype.ext + exact e.apply_symm_apply d⟩ + +/-- Measurable reindexing between an ordered prefix path and an enumeration-prefix path. -/ +noncomputable def measurableEquivFinPrefix (e : ℕ ≃ D) (n : ℕ) (α : Type*) + [MeasurableSpace α] : (Fin n → α) ≃ᵐ («prefix» e n → α) := + MeasurableEquiv.piCongrLeft (fun _ : «prefix» e n ↦ α) (finEquivPrefix e n) + +/-- Measurable reindexing between paths on `ℕ` and paths on the enumerated type. -/ +def measurableEquivPath (e : ℕ ≃ D) (α : Type*) [MeasurableSpace α] : + (ℕ → α) ≃ᵐ (D → α) := + MeasurableEquiv.piCongrLeft (fun _ : D ↦ α) e + +end CountableEnumeration + +/-- The countable dense carrier of nonnegative rational times. -/ +abbrev DenseTime := NNRat + +namespace DenseTime + +/-- The order embedding of nonnegative rational times into nonnegative real times. -/ +noncomputable def castOrderEmbedding : DenseTime ↪o NNReal := + NNRat.castOrderEmbedding + +/-- Between two distinct nonnegative real times lies a nonnegative rational time. -/ +theorem exists_cast_btwn {a b : NNReal} (hab : a < b) : + ∃ q : DenseTime, a < castOrderEmbedding q ∧ castOrderEmbedding q < b := by + obtain ⟨q, hq, haq, hqb⟩ := (NNReal.lt_iff_exists_rat_btwn a b).mp hab + have hcast : NNRat.cast (K := NNReal) ⟨q, hq⟩ = Real.toNNReal q := by + apply NNReal.eq + rw [Real.coe_toNNReal _ (Rat.cast_nonneg.mpr hq)] + norm_cast + have hcoe : castOrderEmbedding ⟨q, hq⟩ = NNRat.cast (K := NNReal) ⟨q, hq⟩ := rfl + refine ⟨⟨q, hq⟩, ?_, ?_⟩ + · rw [hcoe, hcast] + exact haq + · rw [hcoe, hcast] + exact hqb + +private instance : Infinite DenseTime := + Infinite.of_injective (fun n : ℕ ↦ (n : DenseTime)) Nat.cast_injective + +private instance : Countable DenseTime where + exists_injective_nat' := + ⟨fun q ↦ Encodable.encode (q : ℚ), fun _ _ h ↦ + NNRat.ext (Encodable.encode_injective h)⟩ + +/-- A fixed arbitrary enumeration of nonnegative rational times. It is not order-preserving. -/ +noncomputable def enumeration : ℕ ≃ DenseTime := + nonempty_equiv_of_countable.some + +end DenseTime +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeApproximationFromAbove.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeApproximationFromAbove.lean new file mode 100644 index 0000000000..b0ff173de5 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeApproximationFromAbove.lean @@ -0,0 +1,37 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension + +/-! +# Dense-time approximation from above + +Every nonnegative real time is the limit of a strictly decreasing sequence of dense times whose +physical values stay strictly above the limit. This includes time zero and times that already +belong to the dense carrier; choosing strict upper approximants gives one uniform API for all +cuts. + +This is deterministic order-topological infrastructure and makes no stochastic-process claim. +-/ + +open Filter Topology +open scoped NNReal + +namespace MarkovProcess + +/-- Every nonnegative real time admits strictly decreasing dense-time approximants whose physical +values remain strictly above it. -/ +theorem exists_denseTime_seq_strictAnti_tendsto (s : NNReal) : + ∃ q : ℕ → DenseTime, + StrictAnti q ∧ + (∀ n, s < DenseTime.castOrderEmbedding (q n)) ∧ + Tendsto (fun n ↦ DenseTime.castOrderEmbedding (q n)) atTop (nhds s) := by + obtain ⟨q, hqAnti, hqAbove, hq⟩ := + ContinuousPath.denseRange_castOrderEmbedding.exists_seq_strictAnti_tendsto + DenseTime.castOrderEmbedding.monotone s + exact ⟨q, hqAnti, fun n ↦ hqAbove n, by + simpa only [Function.comp_apply] using! hq⟩ + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeHistory.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeHistory.lean new file mode 100644 index 0000000000..91f02bf0de --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeHistory.lean @@ -0,0 +1,97 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.MeasureTheory.MeasurableSpace.Embedding + +/-! +# Finite dense-time histories + +This file provides measurable coordinate equivalences for histories indexed by an initial +segment of the natural numbers. It makes no probability-law, kernel, or stochastic-process claim. +-/ + +namespace MarkovProcess + +/-- A history through natural-number time `n`, including both endpoints. -/ +abbrev DenseTimeHistory (α : Type*) (n : ℕ) := Set.Iic n → α + +namespace DenseTimeHistory + +variable {α : Type*} [MeasurableSpace α] + +/-- The value-preserving equivalence from natural numbers at most `n` to `Fin (n + 1)`. -/ +def iicEquivFin (n : ℕ) : Set.Iic n ≃ Fin (n + 1) where + toFun i := ⟨i, Nat.lt_succ_iff.mpr i.property⟩ + invFun i := ⟨i, Nat.le_of_lt_succ i.isLt⟩ + left_inv _ := rfl + right_inv _ := rfl + +@[simp] +theorem iicEquivFin_apply_val (n : ℕ) (i : Set.Iic n) : (iicEquivFin n i).val = i.val := + rfl + +@[simp] +theorem iicEquivFin_symm_apply_val (n : ℕ) (i : Fin (n + 1)) : + ((iicEquivFin n).symm i).val = i.val := + rfl + +/-- Split a history into its time-zero value and its positive-time coordinates. -/ +def historyEquiv (n : ℕ) : DenseTimeHistory α n ≃ᵐ α × (Fin n → α) := + (MeasurableEquiv.piCongrLeft (fun _ : Fin (n + 1) ↦ α) (iicEquivFin n)).trans + (MeasurableEquiv.piFinSuccAbove (fun _ : Fin (n + 1) ↦ α) 0) + +@[simp] +theorem historyEquiv_fst (n : ℕ) (history : DenseTimeHistory α n) : + (historyEquiv n history).1 = history ⟨0, Nat.zero_le n⟩ := + rfl + +@[simp] +theorem historyEquiv_snd_apply (n : ℕ) (history : DenseTimeHistory α n) (i : Fin n) : + (historyEquiv n history).2 i = history ⟨i.succ, i.isLt⟩ := + rfl + +@[simp] +theorem historyEquiv_symm_apply_zero (n : ℕ) (x : α) (path : Fin n → α) : + (historyEquiv n).symm (x, path) ⟨0, Nat.zero_le n⟩ = x := + rfl + +@[simp] +theorem historyEquiv_symm_apply_succ (n : ℕ) (x : α) (path : Fin n → α) (i : Fin n) : + (historyEquiv n).symm (x, path) ⟨i.succ, i.isLt⟩ = path i := + rfl + +/-- Split a finite path into its proper prefix and its last coordinate. -/ +def splitLast (n : ℕ) : (Fin (n + 1) → α) ≃ᵐ (Fin n → α) × α := + (MeasurableEquiv.piFinSuccAbove (fun _ : Fin (n + 1) ↦ α) (Fin.last n)).trans + MeasurableEquiv.prodComm + +@[simp] +theorem splitLast_fst_apply (n : ℕ) (path : Fin (n + 1) → α) (i : Fin n) : + (splitLast n path).1 i = path i.castSucc := by + change path ((Fin.last n).succAbove i) = path i.castSucc + rw [Fin.succAbove_last_apply] + +@[simp] +theorem splitLast_snd (n : ℕ) (path : Fin (n + 1) → α) : + (splitLast n path).2 = path (Fin.last n) := + rfl + +@[simp] +theorem splitLast_symm_apply_castSucc (n : ℕ) (path : Fin n → α) (x : α) (i : Fin n) : + (splitLast n).symm (path, x) i.castSucc = path i := by + have h := splitLast_fst_apply n ((splitLast n).symm (path, x)) i + rw [MeasurableEquiv.apply_symm_apply] at h + exact h.symm + +@[simp] +theorem splitLast_symm_apply_last (n : ℕ) (path : Fin n → α) (x : α) : + (splitLast n).symm (path, x) (Fin.last n) = x := by + have h := splitLast_snd n ((splitLast n).symm (path, x)) + rw [MeasurableEquiv.apply_symm_apply] at h + exact h.symm + +end DenseTimeHistory + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteDenseApproximationOrdered.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteDenseApproximationOrdered.lean new file mode 100644 index 0000000000..240e2f0099 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteDenseApproximationOrdered.lean @@ -0,0 +1,118 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals + +/-! +# Ordered form of finite dense approximations + +This file expresses a finite dense-approximation kernel as a finite-time kernel at its +increasing physical times. The final coordinate reindexing is the fixed map +`orderedPathToFiniteSet I`; it does not depend on the chosen dense approximation `q`. + +The construction also covers `I = ∅`. In that case the ordered time family and both path +coordinate types are empty. +-/ + +open MeasureTheory ProbabilityTheory Topology Filter +open scoped NNReal + +namespace MarkovProcess.SubMarkovKernelSemigroup + +noncomputable section + +/-- The physical times of a finite dense approximation, listed in the increasing order inherited +from the original finite set. For an empty finite set this is the empty ordered family. -/ +def finiteDenseApproximationOrderedTimes {I : Finset NNReal} (q : I ↪o DenseTime) : + FiniteOrderedTimes I.card := + ((I.orderIsoOfFin rfl).toOrderEmbedding.trans q).trans DenseTime.castOrderEmbedding + +@[simp] +theorem finiteDenseApproximationOrderedTimes_apply {I : Finset NNReal} + (q : I ↪o DenseTime) (i : Fin I.card) : + finiteDenseApproximationOrderedTimes q i = + DenseTime.castOrderEmbedding (q (I.orderIsoOfFin rfl i)) := + rfl + +private theorem approximation_mem {I : Finset NNReal} (q : I ↪o DenseTime) (t : I) : + DenseTime.castOrderEmbedding (q t) ∈ finiteDenseApproximationPhysicalSet q := by + rw [finiteDenseApproximationPhysicalSet, denseTimePhysicalSet, Finset.mem_map] + refine ⟨q t, ?_, rfl⟩ + rw [finiteDenseApproximationIndexSet, Finset.mem_map] + exact ⟨t, Finset.mem_univ t, rfl⟩ + +private def finiteDenseApproximationOrderEmb {I : Finset NNReal} (q : I ↪o DenseTime) : + Fin I.card ↪o Fin (finiteDenseApproximationPhysicalSet q).card := + (I.orderIsoOfFin rfl).toOrderEmbedding |>.trans + (OrderEmbedding.ofStrictMono + (fun t : I => (⟨DenseTime.castOrderEmbedding (q t), approximation_mem q t⟩ : + finiteDenseApproximationPhysicalSet q)) + (fun _ _ h => DenseTime.castOrderEmbedding.strictMono (q.strictMono h))) |>.trans + ((finiteDenseApproximationPhysicalSet q).orderIsoOfFin rfl).symm.toOrderEmbedding + +private theorem finiteSetTimes_restrict_approximationOrderEmb + {I : Finset NNReal} (q : I ↪o DenseTime) : + (finiteSetTimes (finiteDenseApproximationPhysicalSet q)).restrict + (finiteDenseApproximationOrderEmb q) = + finiteDenseApproximationOrderedTimes q := by + apply DFunLike.ext _ _ + intro i + change finiteSetTimes (finiteDenseApproximationPhysicalSet q) + (finiteDenseApproximationOrderEmb q i) = _ + simp only [finiteSetTimes, finiteDenseApproximationOrderEmb, + finiteDenseApproximationOrderedTimes, RelEmbedding.trans_apply] + exact congrArg Subtype.val + ((finiteDenseApproximationPhysicalSet q).orderIsoOfFin rfl |>.apply_symm_apply + ⟨DenseTime.castOrderEmbedding (q (I.orderIsoOfFin rfl i)), + approximation_mem q (I.orderIsoOfFin rfl i)⟩) + +private theorem reindex_comp_orderedPathToFiniteSet + {gamma : Type*} {I : Finset NNReal} (q : I ↪o DenseTime) : + finiteDenseApproximationReindex (γ := gamma) q ∘ + orderedPathToFiniteSet (finiteDenseApproximationPhysicalSet q) = + orderedPathToFiniteSet I ∘ + FiniteOrderedTimes.restrictPath (finiteDenseApproximationOrderEmb q) := by + funext path t + simp only [Function.comp_apply, finiteDenseApproximationReindex, + orderedPathToFiniteSet, FiniteOrderedTimes.restrictPath, + finiteDenseApproximationOrderEmb, RelEmbedding.trans_apply, + OrderIso.coe_toOrderEmbedding, OrderIso.apply_symm_apply] + rfl + +/-- A conservative finite dense-approximation kernel is the finite-time kernel at its canonical +ordered physical times, mapped by the fixed, `q`-independent reindexing to `I`-indexed paths. +The statement includes the empty finite set. -/ +theorem finiteDenseApproximationKernel_eq_map_finiteTimeKernel + {alpha : Type*} [MeasurableSpace alpha] + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + {I : Finset NNReal} (q : I ↪o DenseTime) : + finiteDenseApproximationKernel P q = + (finiteTimeKernel P (finiteDenseApproximationOrderedTimes q)).map + (orderedPathToFiniteSet I) := by + rw [finiteDenseApproximationKernel, finiteSetKernel_eq_map, ← Kernel.map_comp_right] + · rw [reindex_comp_orderedPathToFiniteSet q, Kernel.map_comp_right] + · rw [hP.finiteTimeKernel_map_restrictPath P, + finiteSetTimes_restrict_approximationOrderEmb q] + · exact FiniteOrderedTimes.measurable_restrictPath _ + · exact measurable_orderedPathToFiniteSet _ + · exact measurable_orderedPathToFiniteSet _ + · exact measurable_finiteDenseApproximationReindex q + +/-- Coordinatewise convergence of dense approximations gives convergence of each coordinate of +their canonical ordered physical-time families. This is vacuous when `I` is empty. -/ +theorem tendsto_finiteDenseApproximationOrderedTimes + {I : Finset NNReal} (q : ℕ → I ↪o DenseTime) + (hq : ∀ t, Tendsto (fun k ↦ DenseTime.castOrderEmbedding (q k t)) atTop + (nhds (t : NNReal))) (i : Fin I.card) : + Tendsto (fun k ↦ finiteDenseApproximationOrderedTimes (q k) i) atTop + (nhds (finiteSetTimes I i)) := by + change Tendsto + (fun k ↦ DenseTime.castOrderEmbedding (q k (I.orderIsoOfFin rfl i))) atTop + (nhds ((I.orderIsoOfFin rfl i : I) : NNReal)) + exact hq (I.orderIsoOfFin rfl i) + +end + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteGridIncrement.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteGridIncrement.lean new file mode 100644 index 0000000000..d0d9dae1d4 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteGridIncrement.lean @@ -0,0 +1,93 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.MeasureTheory.Integral.Lebesgue.Markov +import Mathlib.Probability.Process.Kolmogorov + +/-! +# Finite-grid increment bounds + +This file supplies the finite union-bound step in a Kolmogorov--Chentsov argument. It is +independent of a particular dyadic-grid encoding: a later specialization only has to bound the +distance between adjacent grid times. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal + +namespace MarkovProcess + +variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] + +/-- The event that at least one adjacent increment of a finite time grid has `p`-th power at +least `ε ^ p`. -/ +def finiteGridBadIncrement {T : Type*} {N : ℕ} (X : T → Ω → E) + (grid : Fin (N + 1) → T) (p : ℝ) (ε : ℝ≥0∞) : Set Ω := + ⋃ i : Fin N, + {ω | ε ^ p ≤ edist (X (grid i.castSucc) ω) (X (grid i.succ) ω) ^ p} + +/-- A finite-grid union bound obtained directly from the Kolmogorov moment condition. -/ +theorem IsKolmogorovProcess.measure_finiteGridBadIncrement_le + {T : Type*} [PseudoEMetricSpace T] {N : ℕ} {P : Measure Ω} + {X : T → Ω → E} {p q : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) + (grid : Fin (N + 1) → T) (δ ε : ℝ≥0∞) + (hgrid : ∀ i : Fin N, edist (grid i.castSucc) (grid i.succ) ≤ δ) + (hε0 : ε ≠ 0) (hεtop : ε ≠ ∞) : + P (finiteGridBadIncrement X grid p ε) ≤ N * (M * δ ^ q / ε ^ p) := by + unfold finiteGridBadIncrement + calc + P (⋃ i : Fin N, + {ω | ε ^ p ≤ edist (X (grid i.castSucc) ω) (X (grid i.succ) ω) ^ p}) ≤ + ∑ i : Fin N, + P {ω | ε ^ p ≤ edist (X (grid i.castSucc) ω) (X (grid i.succ) ω) ^ p} := + measure_iUnion_fintype_le P _ + _ ≤ ∑ _i : Fin N, (M * δ ^ q / ε ^ p) := by + apply Finset.sum_le_sum + intro i _hi + calc + P {ω | ε ^ p ≤ edist (X (grid i.castSucc) ω) (X (grid i.succ) ω) ^ p} ≤ + (∫⁻ ω, edist (X (grid i.castSucc) ω) (X (grid i.succ) ω) ^ p ∂P) / + ε ^ p := by + apply meas_ge_le_lintegral_div + · exact (hX.measurable_edist.pow_const p).aemeasurable + · exact (ENNReal.rpow_eq_zero_iff_of_pos hX.p_pos).not.mpr hε0 + · exact (ENNReal.rpow_eq_top_iff_of_pos hX.p_pos).not.mpr hεtop + _ ≤ (M * δ ^ q) / ε ^ p := by + gcongr + exact (hX.kolmogorovCondition _ _).trans + (mul_le_mul_right (ENNReal.rpow_le_rpow (hgrid i) hX.q_pos.le) M) + _ = N * (M * δ ^ q / ε ^ p) := by simp + +/-- The dyadic grid of mesh `2⁻ⁿ` on the unit time interval. -/ +def unitDyadicGrid (n : ℕ) : Fin (2 ^ n + 1) → NNRat := + fun i ↦ (i : ℕ) / (2 ^ n : NNRat) + +/-- Adjacent points of the level-`n` unit dyadic grid are at most `2⁻ⁿ` apart. -/ +theorem unitDyadicGrid_edist_adjacent_le (n : ℕ) (i : Fin (2 ^ n)) : + edist (unitDyadicGrid n i.castSucc) (unitDyadicGrid n i.succ) ≤ + ((2 : ℝ≥0∞) ^ n)⁻¹ := by + rw [edist_dist, ENNReal.ofReal_le_iff_le_toReal] + · rw [NNRat.dist_eq, Rat.dist_eq] + simp only [unitDyadicGrid] + push_cast + rw [div_sub_div_same] + simp only [Fin.val_castSucc, Fin.val_succ] + push_cast + norm_num [abs_div, abs_of_nonneg] + · simp + +/-- The Kolmogorov finite-grid bound on the level-`n` unit dyadic grid. -/ +theorem IsKolmogorovProcess.measure_unitDyadicGridBadIncrement_le + {P : Measure Ω} {X : NNRat → Ω → E} {p q : ℝ} {M : ℝ≥0} + (hX : IsKolmogorovProcess X P p q M) (n : ℕ) (ε : ℝ≥0∞) + (hε0 : ε ≠ 0) (hεtop : ε ≠ ∞) : + P (finiteGridBadIncrement X (unitDyadicGrid n) p ε) ≤ + 2 ^ n * (M * (((2 : ℝ≥0∞) ^ n)⁻¹) ^ q / ε ^ p) := by + simpa only [Nat.cast_pow, Nat.cast_ofNat] using + IsKolmogorovProcess.measure_finiteGridBadIncrement_le hX (unitDyadicGrid n) _ ε + (unitDyadicGrid_edist_adjacent_le n) hε0 hεtop + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderEmbedding.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderEmbedding.lean new file mode 100644 index 0000000000..2e3eba3f75 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderEmbedding.lean @@ -0,0 +1,65 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Data.Fintype.Card +import Mathlib.Order.Fin.Basic + +/-! +# Factoring finite order embeddings through one deletion + +This file records the elementary finite-order factorization obtained by deleting a point outside +the range of an order embedding. It is ordinary combinatorial infrastructure and makes no +probability-law or stochastic-process claim. +-/ + +namespace MarkovProcess + +/-- An order embedding `Fin m ↪ Fin (n + 1)` with `m ≤ n` factors through deletion of a +single point. -/ +theorem exists_factor_succAboveOrderEmb {m n : ℕ} (e : Fin m ↪o Fin (n + 1)) (h : m ≤ n) : + ∃ (p : Fin (n + 1)) (d : Fin m ↪o Fin n), d.trans (Fin.succAboveOrderEmb p) = e := by + classical + have hns : ¬ Function.Surjective e := by + intro he + have hcard := Fintype.card_le_of_surjective e he + simp only [Fintype.card_fin] at hcard + exact (Nat.not_succ_le_self n) (hcard.trans h) + rw [Function.Surjective] at hns + push Not at hns + obtain ⟨p, hp⟩ := hns + by_cases plast : p = Fin.last n + · have hlast : ∀ i, e i ≠ Fin.last n := by + intro i + simpa only [plast] using hp i + let d : Fin m ↪o Fin n := + OrderEmbedding.ofStrictMono + (fun i ↦ (e i).castPred (hlast i)) + (Fin.strictMono_castPred_comp hlast e.strictMono) + refine ⟨p, d, ?_⟩ + apply DFunLike.ext _ _ + intro i + change Fin.succAbove p ((e i).castPred (hlast i)) = e i + rw [plast, Fin.succAbove_last_apply, Fin.castSucc_castPred] + · let q : Fin n := p.castPred plast + have hqp : q.castSucc = p := Fin.castSucc_castPred p plast + have havoid : ∀ i, e i ≠ q.castSucc := by + intro i + rw [hqp] + exact hp i + have hmono : StrictMono (fun i ↦ q.predAbove (e i)) := by + intro i j hij + rw [← (Fin.succAboveOrderEmb p).lt_iff_lt] + simpa only [Fin.succAboveOrderEmb_apply, ← hqp, + Fin.succAbove_predAbove (havoid i), Fin.succAbove_predAbove (havoid j)] using + e.strictMono hij + let d : Fin m ↪o Fin n := + OrderEmbedding.ofStrictMono (fun i ↦ q.predAbove (e i)) hmono + refine ⟨p, d, ?_⟩ + apply DFunLike.ext _ _ + intro i + change Fin.succAbove p (q.predAbove (e i)) = e i + rw [← hqp, Fin.succAbove_predAbove (havoid i)] + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean new file mode 100644 index 0000000000..59eee22504 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean @@ -0,0 +1,145 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Algebra.Order.Sub.Basic +import Mathlib.Data.NNReal.Defs +import Mathlib.MeasureTheory.MeasurableSpace.Constructions +import Mathlib.Order.Fin.Basic + +/-! +# Finite ordered time families + +This file provides increasing finite families of nonnegative times and the elementary operations +for restricting such families and their coordinate paths along order embeddings. It is an +ordinary finite-dimensional API and makes no probability-law or stochastic-process claim. +-/ + +namespace MarkovProcess + +/-- A strictly increasing family of `n` nonnegative times. -/ +abbrev FiniteOrderedTimes (n : ℕ) := Fin n ↪o NNReal + +namespace FiniteOrderedTimes + +/-- The times after the first one, shifted so that the first time becomes zero. -/ +def relativeTail {n : ℕ} (times : FiniteOrderedTimes (n + 1)) : FiniteOrderedTimes n := + OrderEmbedding.ofStrictMono (fun i ↦ times i.succ - times 0) fun _ _ hij ↦ + tsub_lt_tsub_right_of_le (times.monotone (Fin.zero_le _)) + (times.strictMono (Fin.strictMono_succ hij)) + +@[simp] +theorem relativeTail_apply {n : ℕ} (times : FiniteOrderedTimes (n + 1)) (i : Fin n) : + times.relativeTail i = times i.succ - times 0 := + rfl + +/-- Translate every time in a finite ordered family by the same nonnegative amount. -/ +def translate {n : ℕ} (s : NNReal) (times : FiniteOrderedTimes n) : FiniteOrderedTimes n := + OrderEmbedding.ofStrictMono (fun i ↦ s + times i) fun _ _ hij ↦ + by simpa only [add_comm] using add_lt_add_left (times.strictMono hij) s + +@[simp] +theorem translate_apply {n : ℕ} (s : NNReal) (times : FiniteOrderedTimes n) (i : Fin n) : + times.translate s i = s + times i := + rfl + +/-- The original successor time is the first time plus its relative-tail coordinate. -/ +theorem add_relativeTail {n : ℕ} (times : FiniteOrderedTimes (n + 1)) (i : Fin n) : + times 0 + times.relativeTail i = times i.succ := + add_tsub_cancel_of_le (times.monotone (Fin.zero_le _)) + +/-- Translation does not change the relative tail of a finite ordered time family. -/ +@[simp] +theorem relativeTail_translate {n : ℕ} (s : NNReal) + (times : FiniteOrderedTimes (n + 1)) : + (times.translate s).relativeTail = times.relativeTail := by + apply DFunLike.ext _ _ + intro i + exact add_tsub_add_eq_tsub_left s (times i.succ) (times 0) + +/-- Translation by zero does not change a finite ordered time family. -/ +@[simp] +theorem translate_zero {n : ℕ} (times : FiniteOrderedTimes n) : times.translate 0 = times := by + apply DFunLike.ext _ _ + intro i + exact zero_add (times i) + +/-- Successive translations combine by addition. -/ +@[simp] +theorem translate_translate {n : ℕ} (s r : NNReal) (times : FiniteOrderedTimes n) : + (times.translate r).translate s = times.translate (s + r) := by + apply DFunLike.ext _ _ + intro i + exact (add_assoc s r (times i)).symm + +/-- Restrict a finite ordered time family along an order embedding of its indices. -/ +def restrict {m n : ℕ} (times : FiniteOrderedTimes n) (e : Fin m ↪o Fin n) : + FiniteOrderedTimes m := + e.trans times + +@[simp] +theorem restrict_apply {m n : ℕ} (times : FiniteOrderedTimes n) (e : Fin m ↪o Fin n) + (i : Fin m) : times.restrict e i = times (e i) := + rfl + +/-- Restriction along the identity order embedding does not change the time family. -/ +@[simp] +theorem restrict_id {n : ℕ} (times : FiniteOrderedTimes n) : + times.restrict (OrderIso.refl (Fin n)).toOrderEmbedding = times := + rfl + +/-- Successive restrictions agree with restriction along the composite embedding. -/ +@[simp] +theorem restrict_trans {k m n : ℕ} (times : FiniteOrderedTimes n) + (e : Fin m ↪o Fin n) (d : Fin k ↪o Fin m) : + (times.restrict e).restrict d = times.restrict (d.trans e) := + rfl + +/-- Restrict a coordinate path along an embedding of finite index sets. -/ +def restrictPath {m n : ℕ} (e : Fin m ↪o Fin n) {α : Type*} (path : Fin n → α) : + Fin m → α := + fun i ↦ path (e i) + +@[simp] +theorem restrictPath_apply {m n : ℕ} (e : Fin m ↪o Fin n) {α : Type*} + (path : Fin n → α) (i : Fin m) : restrictPath e path i = path (e i) := + rfl + +/-- Path restriction along the identity embedding is the identity. -/ +@[simp] +theorem restrictPath_id {n : ℕ} {α : Type*} (path : Fin n → α) : + restrictPath (OrderIso.refl (Fin n)).toOrderEmbedding path = path := + rfl + +/-- Successive path restrictions agree with restriction along the composite embedding. -/ +@[simp] +theorem restrictPath_trans {k m n : ℕ} (e : Fin m ↪o Fin n) (d : Fin k ↪o Fin m) + {α : Type*} (path : Fin n → α) : + restrictPath d (restrictPath e path) = restrictPath (d.trans e) path := + rfl + +/-- Restriction of finite coordinate paths is measurable for product measurable spaces. -/ +theorem measurable_restrictPath {m n : ℕ} (e : Fin m ↪o Fin n) + {α : Type*} [MeasurableSpace α] : + Measurable (restrictPath e : (Fin n → α) → Fin m → α) := + measurable_pi_iff.mpr fun i ↦ measurable_pi_apply (e i) + +/-- The unique path indexed by the empty finite type. -/ +def emptyPath (α : Type*) : Fin 0 → α := + Fin.elim0 + +/-- Every path on the empty finite index type is the canonical empty path. -/ +@[simp] +theorem eq_emptyPath {α : Type*} (path : Fin 0 → α) : path = emptyPath α := + Subsingleton.elim _ _ + +/-- Restricting any path to an empty index family gives the canonical empty path. -/ +@[simp] +theorem restrictPath_empty {n : ℕ} (e : Fin 0 ↪o Fin n) {α : Type*} + (path : Fin n → α) : restrictPath e path = emptyPath α := + Subsingleton.elim _ _ + +end FiniteOrderedTimes + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/OrderedGrid.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/OrderedGrid.lean new file mode 100644 index 0000000000..752aed6ee0 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/OrderedGrid.lean @@ -0,0 +1,128 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Probability.Kernel.IonescuTulcea.Traj +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup + +/-! +# Trajectory laws on a fixed ordered time grid + +This file applies the Ionescu--Tulcea theorem to a conservative sub-Markov +kernel semigroup on one fixed nondecreasing `NNReal`-valued time grid. The +result is only a discrete trajectory law on `ℕ → α` for that grid. +-/ + +open MeasureTheory +open ProbabilityTheory + +namespace MarkovProcess + +variable {α : Type*} [MeasurableSpace α] + +/-- A fixed nondecreasing grid of nonnegative times. -/ +structure OrderedGrid where + /-- The time assigned to each discrete index. -/ + time : ℕ → NNReal + /-- Grid times are nondecreasing. -/ + monotone_time : Monotone time + +namespace OrderedGrid + +/-- The time increment from index `n` to index `n + 1`. -/ +def increment (grid : OrderedGrid) (n : ℕ) : NNReal := + grid.time (n + 1) - grid.time n + +end OrderedGrid + +/-- The singleton history at index zero determined by a starting state. -/ +def initialHistory (x : α) : (i : Finset.Iic 0) → α := + fun _ => x + +/-- The singleton-history map is measurable. -/ +theorem measurable_initialHistory : Measurable (initialHistory : α → (i : Finset.Iic 0) → α) := + measurable_pi_iff.mpr fun _ => measurable_id + +namespace SubMarkovKernelSemigroup + +variable (P : SubMarkovKernelSemigroup α) + +private def lastIndex (n : ℕ) : Finset.Iic n := + ⟨n, Finset.mem_Iic.mpr le_rfl⟩ + +/-- The history-dependent Ionescu--Tulcea step kernel on `grid`. + +Only the current state, the last coordinate of the supplied history, is used. +-/ +def orderedGridStepKernel (grid : OrderedGrid) (n : ℕ) : + Kernel ((i : Finset.Iic n) → α) α := + (P (grid.increment n)).comap + (fun history => history (lastIndex n)) + (measurable_pi_apply (lastIndex n)) + +/-- Conservativity makes every ordered-grid step kernel a Markov kernel. -/ +theorem IsConservative.isMarkovKernel_orderedGridStepKernel + (hP : P.IsConservative) (grid : OrderedGrid) (n : ℕ) : + IsMarkovKernel (orderedGridStepKernel P grid n) := by + let : IsMarkovKernel (P (grid.increment n)) := hP.isMarkovKernel (grid.increment n) + rw [orderedGridStepKernel] + infer_instance + +/-- The Ionescu--Tulcea kernel from a starting state to trajectories on one +fixed ordered grid. -/ +noncomputable def orderedGridTrajectoryKernel + (hP : P.IsConservative) (grid : OrderedGrid) : Kernel α (ℕ → α) := by + letI (n : ℕ) : IsMarkovKernel (orderedGridStepKernel P grid n) := + IsConservative.isMarkovKernel_orderedGridStepKernel P hP grid n + exact (Kernel.traj (orderedGridStepKernel P grid) 0).comap + initialHistory measurable_initialHistory + +/-- The ordered-grid trajectory kernel is a Markov kernel. -/ +theorem IsConservative.isMarkovKernel_orderedGridTrajectoryKernel + (hP : P.IsConservative) (grid : OrderedGrid) : + IsMarkovKernel (orderedGridTrajectoryKernel P hP grid) := by + let (n : ℕ) : IsMarkovKernel (orderedGridStepKernel P grid n) := + IsConservative.isMarkovKernel_orderedGridStepKernel P hP grid n + rw [orderedGridTrajectoryKernel] + infer_instance + +/-- The trajectory law on one fixed ordered grid, started from `x`. -/ +noncomputable def orderedGridTrajectoryLaw + (hP : P.IsConservative) (grid : OrderedGrid) (x : α) : Measure (ℕ → α) := + orderedGridTrajectoryKernel P hP grid x + +/-- The ordered-grid trajectory law is a probability measure. -/ +theorem IsConservative.isProbabilityMeasure_orderedGridTrajectoryLaw + (hP : P.IsConservative) (grid : OrderedGrid) (x : α) : + IsProbabilityMeasure (orderedGridTrajectoryLaw P hP grid x) := by + let : IsMarkovKernel (orderedGridTrajectoryKernel P hP grid) := + IsConservative.isMarkovKernel_orderedGridTrajectoryKernel P hP grid + exact IsMarkovKernel.isProbabilityMeasure x + +/-- Every finite prefix of the ordered-grid law is the corresponding finite +Ionescu--Tulcea trajectory law. -/ +theorem IsConservative.orderedGridTrajectoryLaw_map_frestrictLe + (hP : P.IsConservative) (grid : OrderedGrid) (x : α) (n : ℕ) : + (orderedGridTrajectoryLaw P hP grid x).map + (fun path : ℕ → α => fun i : Finset.Iic n => path i) = + Kernel.partialTraj (X := fun _ => α) (orderedGridStepKernel P grid) 0 n + (initialHistory x) := by + let (k : ℕ) : IsMarkovKernel (orderedGridStepKernel P grid k) := + IsConservative.isMarkovKernel_orderedGridStepKernel P hP grid k + exact Kernel.traj_map_frestrictLe_apply + (X := fun _ => α) (κ := orderedGridStepKernel P grid) 0 n (initialHistory x) + +/-- The prefix consisting of the zeroth coordinate is the deterministic +singleton history at the starting state. -/ +theorem IsConservative.orderedGridTrajectoryLaw_map_frestrictLe_zero + (hP : P.IsConservative) (grid : OrderedGrid) (x : α) : + (orderedGridTrajectoryLaw P hP grid x).map + (fun path : ℕ → α => fun i : Finset.Iic 0 => path i) = + Measure.dirac (initialHistory x) := by + simpa only [Kernel.partialTraj_self, Kernel.id_apply] using + IsConservative.orderedGridTrajectoryLaw_map_frestrictLe P hP grid x 0 + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory.lean new file mode 100644 index 0000000000..cf5462a445 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory.lean @@ -0,0 +1,54 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ + +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExcessiveStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeExponentialMoment +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKac +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalShift +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakConvergence + +/-! +# Trajectory + +Supporting modules for MarkovProcess. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean new file mode 100644 index 0000000000..ee099c553a --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean @@ -0,0 +1,342 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals + +/-! +# Arbitrary-time finite marginals of continuous-path trajectories + +This file develops the simultaneous rational approximation needed to pass from the already +identified rational finite-dimensional distributions to finite families of arbitrary +nonnegative real times. It proves the path-side dominated-convergence argument, identifies every +rational approximating law with the existing finite-set kernel, and reduces the desired equality +to compactly-supported-test convergence of those finite-set kernels. + +The remaining Feller analytic statement is not claimed here: one must still prove that the +recursively composed finite-time kernels have that convergence under simultaneous convergence of +their strictly ordered time coordinates. No continuous-time Markov or Hunt property is assumed +or asserted. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped NNReal + +namespace MarkovProcess + +noncomputable section + +/-- Every finite linearly ordered family embedded in nonnegative real time admits strictly +ordered rational approximations converging coordinatewise. A common tail shift makes the +independently chosen approximations preserve all finitely many strict inequalities at every +level. -/ +theorem exists_denseTime_finiteOrderEmbedding_seq_tendsto + {ι : Type*} [Finite ι] [LinearOrder ι] (times : ι ↪o NNReal) : + ∃ q : ℕ → ι ↪o DenseTime, + ∀ i, Tendsto (fun k ↦ DenseTime.castOrderEmbedding (q k i)) + atTop (nhds (times i)) := by + choose q hq using fun i : ι ↦ exists_denseTime_seq_tendsto (times i) + have hordered : ∀ᶠ k in atTop, + ∀ i j : ι, i < j → + DenseTime.castOrderEmbedding (q i k) < + DenseTime.castOrderEmbedding (q j k) := by + rw [Filter.eventually_all] + intro i + rw [Filter.eventually_all] + intro j + by_cases hij : i < j + · exact ((hq i).eventually_lt (hq j) (times.strictMono hij)).mono + fun k hk _ ↦ hk + · exact Filter.Eventually.of_forall fun _ hij' ↦ (hij hij').elim + rw [Filter.eventually_atTop] at hordered + obtain ⟨N, hN⟩ := hordered + let qOrdered : ℕ → ι ↪o DenseTime := fun k ↦ + OrderEmbedding.ofStrictMono (fun i ↦ q i (k + N)) fun i j hij ↦ by + apply DenseTime.castOrderEmbedding.lt_iff_lt.mp + exact hN (k + N) (Nat.le_add_left N k) i j hij + refine ⟨qOrdered, fun i ↦ ?_⟩ + have hshift := (hq i).comp (Filter.tendsto_add_atTop_nat N) + simpa only [qOrdered, Function.comp_apply] using! hshift + +/-- Every finite strictly ordered family of nonnegative real times admits strictly ordered +rational approximations converging coordinatewise. -/ +theorem exists_denseTime_finiteOrdered_seq_tendsto {n : ℕ} + (times : FiniteOrderedTimes n) : + ∃ q : ℕ → Fin n ↪o DenseTime, + ∀ i, Tendsto (fun k ↦ DenseTime.castOrderEmbedding (q k i)) + atTop (nhds (times i)) := + exists_denseTime_finiteOrderEmbedding_seq_tendsto times + +/-- Every finite set of nonnegative real times has a simultaneous strictly ordered rational +approximation on its fixed subtype of coordinates. -/ +theorem exists_denseTime_finset_seq_tendsto (I : Finset NNReal) : + ∃ q : ℕ → I ↪o DenseTime, + ∀ t, Tendsto (fun k ↦ DenseTime.castOrderEmbedding (q k t)) + atTop (nhds (t : NNReal)) := by + simpa only using! exists_denseTime_finiteOrderEmbedding_seq_tendsto + (OrderEmbedding.subtype (fun t : NNReal ↦ t ∈ I)) + +namespace ContinuousPath + +/-- Evaluate a continuous path at a finite family of times. -/ +def finiteEvaluation {ι α : Type*} [TopologicalSpace α] + (τ : ι → NNReal) : ContinuousPath α → (ι → α) := + fun path i ↦ path (τ i) + +/-- Simultaneous evaluation at finitely many fixed times is continuous in the path. -/ +theorem continuous_finiteEvaluation {ι α : Type*} [Finite ι] + [TopologicalSpace α] (τ : ι → NNReal) : + Continuous (finiteEvaluation (α := α) τ) := by + apply continuous_pi + intro i + exact continuous_eval (alpha := α) (τ i) + +/-- If each time in a finite family converges, then simultaneous evaluation along any +continuous path converges in the finite product topology. -/ +theorem tendsto_finiteEvaluation {ι α : Type*} [Finite ι] + [TopologicalSpace α] (τ : ι → NNReal) (q : ℕ → ι → NNReal) + (hq : ∀ i, Tendsto (fun k ↦ q k i) atTop (nhds (τ i))) + (path : ContinuousPath α) : + Tendsto (fun k ↦ finiteEvaluation (α := α) (q k) path) atTop + (nhds (finiteEvaluation (α := α) τ path)) := by + apply tendsto_pi_nhds.2 + intro i + exact Filter.Tendsto.comp path.continuous.continuousAt (hq i) + +end ContinuousPath + +section KernelLimits + +variable {α : Type*} [MetricSpace α] [MeasurableSpace α] [BorelSpace α] + [SecondCountableTopology α] [LocallyCompactSpace α] + +omit [SecondCountableTopology α] [LocallyCompactSpace α] in +/-- Simultaneous evaluation at finitely many fixed times is Borel measurable. -/ +theorem ContinuousPath.measurable_finiteEvaluation {ι : Type*} [Finite ι] + (τ : ι → NNReal) : Measurable (finiteEvaluation (α := α) τ) := by + rw [measurable_pi_iff] + intro i + exact measurable_coordinateProcess (alpha := α) (τ i) + +omit [MeasurableSpace α] [BorelSpace α] [SecondCountableTopology α] + [LocallyCompactSpace α] in +/-- Dominated convergence for a compactly supported test function evaluated at a convergent +finite family of times along a continuous-path probability kernel. This is the path-side limit +needed in every finite-dimensional rational approximation argument. -/ +theorem tendsto_integral_continuousPath_finiteEvaluation + {β ι : Type*} [MeasurableSpace β] [Fintype ι] + (K : Kernel β (ContinuousPath α)) (hK : IsMarkovKernel K) + (x : β) (f : CompactlySupportedContinuousMap (ι → α) ℝ) + (τ : ι → NNReal) + (q : ℕ → ι → NNReal) + (hq : ∀ i, Tendsto (fun k ↦ q k i) atTop (nhds (τ i))) : + Tendsto + (fun k ↦ ∫ path, f (ContinuousPath.finiteEvaluation (α := α) (q k) path) ∂K x) + atTop + (nhds (∫ path, f (ContinuousPath.finiteEvaluation (α := α) τ path) ∂K x)) := by + let : IsMarkovKernel K := hK + let f0 : ZeroAtInftyContinuousMap (ι → α) ℝ := + PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f + apply tendsto_integral_filter_of_norm_le_const + · filter_upwards [] with k + exact (f.continuous.comp + (ContinuousPath.continuous_finiteEvaluation (q k))).aestronglyMeasurable + · refine ⟨‖f0‖, Filter.Eventually.of_forall fun k ↦ ?_⟩ + filter_upwards [] with path + simpa only [f0, PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap_apply, + Real.norm_eq_abs] using! f0.toBCF.norm_coe_le_norm + (ContinuousPath.finiteEvaluation (α := α) (q k) path) + · filter_upwards [] with path + exact Filter.Tendsto.comp f.continuous.continuousAt + (ContinuousPath.tendsto_finiteEvaluation τ q hq path) + +/-- Equality of finite-dimensional laws passes from approximating time families to their limit +once the comparison kernels have the corresponding compactly-supported-test convergence. + +The convergence premise is deliberately stated at precisely the analytic seam: it says nothing +about a Markov property and is exactly the weak/vague continuity of the candidate finite-time +laws needed by the proof. -/ +theorem Kernel.map_finiteEvaluation_eq_of_integral_tendsto + {β ι : Type*} [MeasurableSpace β] [Fintype ι] + (K : Kernel β (ContinuousPath α)) (hK : IsMarkovKernel K) + (Lseq : ℕ → Kernel β (ι → α)) (L : Kernel β (ι → α)) + (hL : IsMarkovKernel L) (τ : ι → NNReal) (q : ℕ → ι → NNReal) + (hq : ∀ i, Tendsto (fun k ↦ q k i) atTop (nhds (τ i))) + (hlaw : ∀ k, K.map (ContinuousPath.finiteEvaluation (q k)) = Lseq k) + (hfinite : ∀ (x : β) (f : CompactlySupportedContinuousMap (ι → α) ℝ), + Tendsto (fun k ↦ ∫ y, f y ∂Lseq k x) atTop (nhds (∫ y, f y ∂L x))) : + K.map (ContinuousPath.finiteEvaluation τ) = L := by + let : IsMarkovKernel K := hK + let : IsMarkovKernel L := hL + apply Kernel.ext + intro x + apply Measure.ext_of_integral_eq_on_compactlySupported + intro f + have hpath := tendsto_integral_continuousPath_finiteEvaluation + K hK x f τ q hq + have heq : ∀ k, + (∫ path, f (ContinuousPath.finiteEvaluation (q k) path) ∂K x) = + ∫ y, f y ∂Lseq k x := by + intro k + have hm := congrArg (fun κ : Kernel β (ι → α) ↦ κ x) (hlaw k) + have hi := congrArg (fun μ : Measure (ι → α) ↦ ∫ y, f y ∂μ) hm + change (∫ y, f y ∂(K.map (ContinuousPath.finiteEvaluation (q k))) x) = + ∫ y, f y ∂Lseq k x at hi + have heval : Measurable (ContinuousPath.finiteEvaluation (α := α) (q k)) := + ContinuousPath.measurable_finiteEvaluation (q k) + have hmap : + (K.map (ContinuousPath.finiteEvaluation (q k))) x = + (K x).map (ContinuousPath.finiteEvaluation (q k)) := + Kernel.map_apply K heval x + rw [hmap, integral_map] at hi + · exact hi + · exact heval.aemeasurable + · exact f.continuous.aestronglyMeasurable + have hsame : + (fun k ↦ ∫ path, f (ContinuousPath.finiteEvaluation (q k) path) ∂K x) = + fun k ↦ ∫ y, f y ∂Lseq k x := + funext heq + rw [hsame] at hpath + have hlimit := tendsto_nhds_unique hpath (hfinite x f) + have heval : Measurable (ContinuousPath.finiteEvaluation (α := α) τ) := + ContinuousPath.measurable_finiteEvaluation τ + have hmap : + (K.map (ContinuousPath.finiteEvaluation τ)) x = + (K x).map (ContinuousPath.finiteEvaluation τ) := + Kernel.map_apply K heval x + rw [hmap, integral_map] + · exact hlimit + · exact heval.aemeasurable + · exact f.continuous.aestronglyMeasurable + +namespace SubMarkovKernelSemigroup + +/-- The rational index set used by one finite ordered rational approximation. -/ +def finiteDenseApproximationIndexSet {I : Finset NNReal} (q : I ↪o DenseTime) : + Finset DenseTime := + Finset.univ.map q.toEmbedding + +/-- The corresponding finite set of physical nonnegative-real times. -/ +def finiteDenseApproximationPhysicalSet {I : Finset NNReal} (q : I ↪o DenseTime) : + Finset NNReal := + denseTimePhysicalSet (finiteDenseApproximationIndexSet q) + +private theorem finiteDenseApproximation_mem {I : Finset NNReal} (q : I ↪o DenseTime) + (t : I) : + DenseTime.castOrderEmbedding (q t) ∈ finiteDenseApproximationPhysicalSet q := by + rw [finiteDenseApproximationPhysicalSet, denseTimePhysicalSet, Finset.mem_map] + refine ⟨q t, ?_, rfl⟩ + rw [finiteDenseApproximationIndexSet, Finset.mem_map] + exact ⟨t, Finset.mem_univ t, rfl⟩ + +/-- Reindex a path on an approximating physical-time set by the original finite set. -/ +def finiteDenseApproximationReindex {γ : Type*} {I : Finset NNReal} + (q : I ↪o DenseTime) : + (finiteDenseApproximationPhysicalSet q → γ) → I → γ := + fun path t ↦ path ⟨DenseTime.castOrderEmbedding (q t), + finiteDenseApproximation_mem q t⟩ + +/-- The approximating-set reindexing map is measurable. -/ +theorem measurable_finiteDenseApproximationReindex + {γ : Type*} [MeasurableSpace γ] {I : Finset NNReal} (q : I ↪o DenseTime) : + Measurable (finiteDenseApproximationReindex (γ := γ) q) := by + rw [measurable_pi_iff] + intro t + let s : finiteDenseApproximationPhysicalSet q := + ⟨DenseTime.castOrderEmbedding (q t), finiteDenseApproximation_mem q t⟩ + exact measurable_pi_apply s + +/-- The candidate finite law at one rational approximation, transported back to the fixed +coordinate type indexed by the original time set. -/ +noncomputable def finiteDenseApproximationKernel + (P : SubMarkovKernelSemigroup α) {I : Finset NNReal} (q : I ↪o DenseTime) : + Kernel α (I → α) := + (finiteSetKernel P (finiteDenseApproximationPhysicalSet q)).map + (finiteDenseApproximationReindex q) + +namespace IsConservative + +variable [CompleteSpace α] [StandardBorelSpace α] [Nonempty α] + +omit [LocallyCompactSpace α] in +/-- At every finite ordered rational approximation, the continuous-path trajectory has exactly +the transported finite-set kernel law on the fixed original coordinate type. -/ +theorem continuousPathTrajectory_map_finiteDenseApproximation + (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + (default : ContinuousPath α) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + {I : Finset NNReal} (q : I ↪o DenseTime) : + (continuousPathTrajectory P hP default).map + (ContinuousPath.finiteEvaluation + (fun t : I ↦ DenseTime.castOrderEmbedding (q t))) = + finiteDenseApproximationKernel P q := by + let evalPhysical : ContinuousPath α → + (finiteDenseApproximationPhysicalSet q → α) := + fun path t ↦ path t + have hevalPhysical : Measurable evalPhysical := by + rw [measurable_pi_iff] + intro t + exact ContinuousPath.measurable_coordinateProcess (alpha := α) t + have hcomp : + finiteDenseApproximationReindex (γ := α) q ∘ evalPhysical = + ContinuousPath.finiteEvaluation + (fun t : I ↦ DenseTime.castOrderEmbedding (q t)) := by + rfl + rw [← hcomp, Kernel.map_comp_right] + · have hrational := continuousPathTrajectory_map_finiteDenseTimeSet + P hP default hK (finiteDenseApproximationIndexSet q) + change (continuousPathTrajectory P hP default).map evalPhysical = + finiteSetKernel P (finiteDenseApproximationPhysicalSet q) at hrational + rw [hrational] + rfl + · exact hevalPhysical + · exact measurable_finiteDenseApproximationReindex q + +/-- The arbitrary-time finite-marginal theorem reduced to convergence of the already constructed +finite-set kernels along one simultaneous rational approximation. The remaining premise is an +analytic continuity statement about the Feller finite-time kernels, not a pathwise or Markov +assumption. -/ +theorem continuousPathTrajectory_map_finiteTimeSet_of_integral_tendsto + (P : SubMarkovKernelSemigroup α) (hP : P.IsConservative) + (default : ContinuousPath α) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (I : Finset NNReal) (q : ℕ → I ↪o DenseTime) + (hq : ∀ t, Tendsto + (fun k ↦ DenseTime.castOrderEmbedding (q k t)) atTop (nhds (t : NNReal))) + (hfinite : ∀ (x : α) (f : CompactlySupportedContinuousMap (I → α) ℝ), + Tendsto + (fun k ↦ ∫ y, f y ∂finiteDenseApproximationKernel P (q k) x) + atTop (nhds (∫ y, f y ∂finiteSetKernel P I x))) : + (continuousPathTrajectory P hP default).map + (ContinuousPath.finiteEvaluation (fun t : I ↦ (t : NNReal))) = + finiteSetKernel P I := by + let K := continuousPathTrajectory P hP default + have hmarkovK : IsMarkovKernel K := by infer_instance + have hmarkovFinite : IsMarkovKernel (finiteSetKernel P I) := + hP.isMarkovKernel_finiteSetKernel P I + apply Kernel.map_finiteEvaluation_eq_of_integral_tendsto + K hmarkovK (fun k ↦ finiteDenseApproximationKernel P (q k)) + (finiteSetKernel P I) hmarkovFinite + (fun t : I ↦ (t : NNReal)) + (fun k t ↦ DenseTime.castOrderEmbedding (q k t)) hq + · intro k + exact continuousPathTrajectory_map_finiteDenseApproximation P hP default hK (q k) + · exact hfinite + +end IsConservative +end SubMarkovKernelSemigroup + +end KernelLimits + +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeMarginals.lean new file mode 100644 index 0000000000..07dc43c463 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeMarginals.lean @@ -0,0 +1,140 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic +import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint +import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +import Mathlib.MeasureTheory.Integral.DominatedConvergence +import Mathlib.MeasureTheory.Integral.RieszMarkovKakutani.Real +import Mathlib.MeasureTheory.Measure.RegularityCompacts +import Mathlib.Topology.Order.IsLUB + +/-! +# All-time marginals of continuous-path trajectories + +This file supplies the rational-approximation input for extending the already proved dense-time +marginals to arbitrary nonnegative real times. The extension uses path continuity on one side +and Feller `C₀`-orbit continuity on the other. + +No continuous-time Markov, strong Markov, or Hunt-process assertion is made here. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped NNReal ZeroAtInfty + +namespace MarkovProcess + +noncomputable section + +/-- Nonnegative rational times admit a sequence converging to every nonnegative real time. -/ +theorem exists_denseTime_seq_tendsto (t : NNReal) : + ∃ q : ℕ → DenseTime, + Tendsto (fun n ↦ DenseTime.castOrderEmbedding (q n)) atTop (nhds t) := by + obtain ⟨q, _, _, hq⟩ := ContinuousPath.denseRange_castOrderEmbedding + |>.exists_seq_strictAnti_tendsto + DenseTime.castOrderEmbedding.monotone t + exact ⟨q, by simpa only [Function.comp_apply] using! hq⟩ + +namespace SubMarkovKernelSemigroup +namespace IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [LocallyCompactSpace alpha] [StandardBorelSpace alpha] [Nonempty alpha] + +/-- Feller time continuity upgrades the rational marginals of the continuous-path trajectory to +every nonnegative real time. -/ +theorem continuousPathTrajectory_map_eval_nnreal + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (hF : P.IsFellerKernelSemigroup) (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (t : NNReal) : + (continuousPathTrajectory P hP default).map (fun path ↦ path t) = P t := by + obtain ⟨q, hq⟩ := exists_denseTime_seq_tendsto t + let : IsMarkovKernel (P t) := hP.isMarkovKernel t + apply Kernel.ext + intro x + apply Measure.ext_of_integral_eq_on_compactlySupported + intro f + let K := continuousPathTrajectory P hP default + let f0 : C₀(alpha, ℝ) := + PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f + have hpath : Tendsto + (fun n ↦ ∫ omega, f (omega (DenseTime.castOrderEmbedding (q n))) ∂K x) + atTop (nhds (∫ omega, f (omega t) ∂K x)) := by + apply tendsto_integral_filter_of_norm_le_const + · filter_upwards [] with n + exact (f.continuous.comp + (ContinuousPath.continuous_eval (alpha := alpha) + (DenseTime.castOrderEmbedding (q n)))).aestronglyMeasurable + · refine ⟨‖f0‖, Filter.Eventually.of_forall fun n ↦ ?_⟩ + filter_upwards [] with omega + simpa only [f0, PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap_apply, + Real.norm_eq_abs] using! f0.toBCF.norm_coe_le_norm + (omega (DenseTime.castOrderEmbedding (q n))) + · filter_upwards [] with omega + exact Filter.Tendsto.comp f.continuous.continuousAt + (Filter.Tendsto.comp omega.continuous.continuousAt hq) + have hsemigroup : Tendsto + (fun n ↦ kernelIntegral (P (DenseTime.castOrderEmbedding (q n))) f x) + atTop (nhds (kernelIntegral (P t) f x)) := by + have hpair : Tendsto + (fun n ↦ (DenseTime.castOrderEmbedding (q n), x)) atTop (nhds (t, x)) := + hq.prodMk_nhds tendsto_const_nhds + have horbit := + (hF.c0Semigroup.continuous_apply_apply f0).tendsto (t, x) |>.comp hpair + simpa only [IsFellerKernelSemigroup.c0Semigroup_apply_apply, + PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap_apply] using! horbit + have heq : ∀ n, + (∫ omega, f (omega (DenseTime.castOrderEmbedding (q n))) ∂K x) = + kernelIntegral (P (DenseTime.castOrderEmbedding (q n))) f x := by + intro n + have hm := congrArg (fun L : Kernel alpha alpha ↦ L x) + (continuousPathTrajectory_map_eval P hP default hK (q n)) + have hi := congrArg (fun mu : Measure alpha ↦ ∫ y, f y ∂mu) hm + change (∫ y, f y ∂(K.map + (ContinuousPath.eval (DenseTime.castOrderEmbedding (q n)))) x) = + kernelIntegral (P (DenseTime.castOrderEmbedding (q n))) f x at hi + have heval : Measurable (ContinuousPath.eval (alpha := alpha) + (DenseTime.castOrderEmbedding (q n))) := + (ContinuousPath.continuous_eval (alpha := alpha) + (DenseTime.castOrderEmbedding (q n))).borel_measurable.mono + le_rfl (le_of_eq BorelSpace.measurable_eq) + have hmap : + (K.map (ContinuousPath.eval (DenseTime.castOrderEmbedding (q n)))) x = + (K x).map (ContinuousPath.eval (DenseTime.castOrderEmbedding (q n))) := + Kernel.map_apply K heval x + rw [hmap, integral_map] at hi + · exact hi + · exact heval.aemeasurable + · exact f.continuous.aestronglyMeasurable + have hsame : + (fun n ↦ ∫ omega, f (omega (DenseTime.castOrderEmbedding (q n))) ∂K x) = + fun n ↦ kernelIntegral (P (DenseTime.castOrderEmbedding (q n))) f x := + funext heq + rw [hsame] at hpath + have hlimit := tendsto_nhds_unique hpath hsemigroup + change (∫ y, f y ∂(K.map (ContinuousPath.eval t)) x) = + kernelIntegral (P t) f x + have heval : Measurable (ContinuousPath.eval (alpha := alpha) t) := + (ContinuousPath.continuous_eval (alpha := alpha) t).borel_measurable.mono + le_rfl (le_of_eq BorelSpace.measurable_eq) + have hmap : (K.map (ContinuousPath.eval t)) x = (K x).map (ContinuousPath.eval t) := + Kernel.map_apply K heval x + rw [hmap, integral_map] + · exact hlimit + · exact heval.aemeasurable + · exact f.continuous.aestronglyMeasurable + +end IsConservative +end SubMarkovKernelSemigroup + +end +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Basic.lean new file mode 100644 index 0000000000..4022497c62 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Basic.lean @@ -0,0 +1,134 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport + +/-! +# Continuous-path trajectory kernels + +This file transports the canonical dense-time trajectory of a conservative kernel semigroup to +continuous paths. The explicit default is used only by the previously established measurable +extension away from the continuous-restriction range. A coordinate Kolmogorov condition makes +that fallback irrelevant and transports the proved rational-time marginal identities. + +No continuous-time Markov property, strong Markov property, Hunt-process assertion, or PDE +increment estimate is claimed. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup +namespace IsConservative + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [StandardBorelSpace alpha] [Nonempty alpha] + +/-- The canonical dense-time trajectory transported through the measurable continuous-extension +map. Under the Kolmogorov hypothesis used below, its law is independent of `default`. -/ +def continuousPathTrajectory (P : SubMarkovKernelSemigroup alpha) + (hP : P.IsConservative) (default : ContinuousPath alpha) : + Kernel alpha (ContinuousPath alpha) := + Kernel.toContinuousPathKernel + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding) default + +/-- The transported continuous-path trajectory is a Markov kernel in its initial-state +parameter. -/ +instance isMarkovKernel_continuousPathTrajectory + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) : + IsMarkovKernel (continuousPathTrajectory P hP default) := by + unfold continuousPathTrajectory + exact Kernel.isMarkovKernel_toContinuousPathKernel _ default + +/-- Under the coordinate Kolmogorov estimate, the continuous-path trajectory law is independent +of the explicit fallback path used by the measurable extension. -/ +theorem continuousPathTrajectory_eq + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default₁ default₂ : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) : + continuousPathTrajectory P hP default₁ = + continuousPathTrajectory P hP default₂ := by + let kappa := denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding + exact Kernel.IsSupportedOnContinuousPaths.toContinuousPathKernel_eq kappa + (Kernel.IsSupportedOnContinuousPaths.of_isKolmogorovCoordinate kappa hK) + default₁ default₂ + +/-- Every rational-time evaluation of the continuous-path transport has the prescribed +semigroup marginal, provided the canonical dense-time coordinate process satisfies the +parameterwise Kolmogorov condition. -/ +theorem continuousPathTrajectory_map_eval + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (r : DenseTime) : + (continuousPathTrajectory P hP default).map + (fun path ↦ path (DenseTime.castOrderEmbedding r)) = + P (DenseTime.castOrderEmbedding r) := by + let kappa := denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding + have hback : + (continuousPathTrajectory P hP default).map ContinuousPath.denseRestriction = kappa := by + exact Kernel.map_denseRestriction_toContinuousPathKernel_of_isKolmogorovCoordinate + kappa default hK + have hfun : + (fun path : ContinuousPath alpha ↦ path (DenseTime.castOrderEmbedding r)) = + (fun path : DenseTime → alpha ↦ path r) ∘ ContinuousPath.denseRestriction := by + rfl + rw [hfun, Kernel.map_comp_right] + · rw [hback] + exact denseTimeTrajectory_map_eval P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding r + · exact ContinuousPath.measurable_denseRestriction + · exact measurable_pi_apply r + +/-- Every finite enumeration-prefix marginal of the continuous-path transport is the already +constructed dense-time prefix law. -/ +theorem continuousPathTrajectory_map_prefix + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (n : ℕ) : + (continuousPathTrajectory P hP default).map + (denseTimeTrajectoryPrefix DenseTime.enumeration n ∘ + ContinuousPath.denseRestriction) = + denseTimePrefixKernel P DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding n := by + let kappa := denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding + have hback : + (continuousPathTrajectory P hP default).map ContinuousPath.denseRestriction = kappa := by + exact Kernel.map_denseRestriction_toContinuousPathKernel_of_isKolmogorovCoordinate + kappa default hK + rw [Kernel.map_comp_right] + · rw [hback] + exact denseTimeTrajectory_map_prefix P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding n + · exact ContinuousPath.measurable_denseRestriction + · exact measurable_denseTimeTrajectoryPrefix DenseTime.enumeration n + +end +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ClampedCoordinate.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ClampedCoordinate.lean new file mode 100644 index 0000000000..259ab007b2 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ClampedCoordinate.lean @@ -0,0 +1,43 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability + +/-! +# Measurability of clamped path coordinates + +This file records the joint measurability of a continuous-path coordinate whose time argument is +clamped at a deterministic horizon. It is the common progressive-measurability input for +adapted integral functionals. + +Main result: `ContinuousPath.measurable_clampedCoordinate`. + +No stochastic-process law or stopping-time identity is asserted. +-/ + +open MeasureTheory +open scoped NNReal + +namespace MarkovProcess.ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] [TopologicalSpace.PseudoMetrizableSpace alpha] + [SecondCountableTopology alpha] [MeasurableSpace alpha] [BorelSpace alpha] + +/-- The coordinate at a real time clamped to `[0, t]` is jointly measurable for the Borel +structure in time and the canonical filtration at `t`. -/ +theorem measurable_clampedCoordinate (t : NNReal) : + Measurable[(borel ℝ).prod (canonicalFiltration (alpha := alpha) t)] + (fun p : ℝ × ContinuousPath alpha ↦ p.2 (min (Real.toNNReal p.1) t)) := by + have htime : Measurable[(borel ℝ).prod (canonicalFiltration (alpha := alpha) t)] + (fun p : ℝ × ContinuousPath alpha ↦ min (Real.toNNReal p.1) t) := + (measurable_real_toNNReal.comp measurable_fst).min measurable_const + have hpair : Measurable[(borel ℝ).prod (canonicalFiltration (alpha := alpha) t), + Subtype.instMeasurableSpace.prod (canonicalFiltration (alpha := alpha) t)] + (fun p : ℝ × ContinuousPath alpha ↦ + ((⟨min (Real.toNNReal p.1) t, Set.mem_Iic.mpr (min_le_right _ _)⟩ : Set.Iic t), p.2)) := + (Measurable.subtype_mk htime).prodMk measurable_snd + exact ((progMeasurable_coordinateProcess (alpha := alpha) t).comp_measurable hpair).measurable + +end MarkovProcess.ContinuousPath diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Convergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Convergence.lean new file mode 100644 index 0000000000..a328c6d957 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Convergence.lean @@ -0,0 +1,96 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence +import LeanPool.MarkovProcess.MarkovProcess.Main +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties + +/-! +# Convergence of the finite-dimensional distributions of Feller processes + +Let `P i` be conservative Feller kernel semigroups and `Q` one more such semigroup, with +continuous-path processes `continuousProcess (P i)` and `continuousProcess Q`. If the `C₀` +semigroups converge strongly -- by `Semigroup/TrotterKato.lean` this follows from convergence of +their resolvents at one +positive shift -- then the finite-dimensional distributions of the processes converge weakly from +every starting point: for every finite set `I` of times and every bounded continuous functional +of the coordinates at those times, the expectations converge. + +The route is the identification of the finite-dimensional distributions with the finite-set +kernels (`continuousProcess_map_finiteEvaluation`), where the statement is +`Feller/FiniteSetConvergence.lean`. + +Main results: `tendsto_integral_finsetEvaluation_continuousProcess`, +`tendsto_integral_eval_continuousProcess`. + +Convergence of the finite-dimensional distributions is not convergence on path space, which needs +in addition a tightness estimate for the family of laws; that is not asserted here. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped BoundedContinuousFunction NNReal ZeroAtInfty + +namespace MarkovProcess.SubMarkovKernelSemigroup + +noncomputable section + +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + [LocallyCompactSpace alpha] +variable {iota : Type*} {l : Filter iota} +variable {P : iota → SubMarkovKernelSemigroup alpha} {Q : SubMarkovKernelSemigroup alpha} + +/-- **Weak convergence of the finite-dimensional distributions of the processes.** Strong +convergence of the `C₀` semigroups makes the joint law of the coordinates at any finite set of +times converge weakly, from every starting point. -/ +theorem tendsto_integral_finsetEvaluation_continuousProcess + (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hPc : ∀ i, (P i).IsConservative) + (hPK : ∀ i, (P i).KolmogorovRegular (hPc i)) + (hQ : Q.IsFellerKernelSemigroup) (hQc : Q.IsConservative) (hQK : Q.KolmogorovRegular hQc) + (hconv : ∀ (t : NNReal) (f : C₀(alpha, ℝ)), + Tendsto (fun i ↦ (hP i).c0Semigroup t f) l (nhds (hQ.c0Semigroup t f))) + (I : Finset NNReal) (f : (I → alpha) →ᵇ ℝ) (x : alpha) : + Tendsto (fun i ↦ ∫ omega, f (ContinuousPath.finsetEvaluation I omega) + ∂(continuousProcess (P i) (hPc i) x)) l + (nhds (∫ omega, f (ContinuousPath.finsetEvaluation I omega) + ∂(continuousProcess Q hQc x))) := by + have hrewrite : ∀ (R : SubMarkovKernelSemigroup alpha) (hRc : R.IsConservative) + (hRF : R.IsFellerKernelSemigroup) (hRK : R.KolmogorovRegular hRc), + ∫ omega, f (ContinuousPath.finsetEvaluation I omega) + ∂(continuousProcess R hRc x) = ∫ path, f path ∂finiteSetKernel R I x := by + intro R hRc hRF hRK + have hmap : ((continuousProcess R hRc) x).map (ContinuousPath.finsetEvaluation I) = + finiteSetKernel R I x := by + rw [← Kernel.map_apply _ (ContinuousPath.measurable_finsetEvaluation I), + hRF.continuousProcess_map_finiteEvaluation R hRc hRK I] + rw [← hmap, integral_map (ContinuousPath.measurable_finsetEvaluation I).aemeasurable + f.continuous.aestronglyMeasurable] + have hsteps : ∀ i : iota, ∫ omega, f (ContinuousPath.finsetEvaluation I omega) + ∂(continuousProcess (P i) (hPc i) x) = ∫ path, f path ∂finiteSetKernel (P i) I x := + fun i ↦ hrewrite (P i) (hPc i) (hP i) (hPK i) + rw [hrewrite Q hQc hQ hQK] + simp only [hsteps] + exact tendsto_integral_boundedContinuous_finiteSetKernel hP hPc hQ hQc hconv I f x + +/-- Convergence of the one-time laws: for a bounded continuous function on the state space and a +nonnegative time, the expectations of its value along the path converge. -/ +theorem tendsto_integral_eval_continuousProcess + (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hPc : ∀ i, (P i).IsConservative) + (hPK : ∀ i, (P i).KolmogorovRegular (hPc i)) + (hQ : Q.IsFellerKernelSemigroup) (hQc : Q.IsConservative) (hQK : Q.KolmogorovRegular hQc) + (hconv : ∀ (t : NNReal) (f : C₀(alpha, ℝ)), + Tendsto (fun i ↦ (hP i).c0Semigroup t f) l (nhds (hQ.c0Semigroup t f))) + (t : NNReal) (g : alpha →ᵇ ℝ) (x : alpha) : + Tendsto (fun i ↦ ∫ omega, g (omega t) ∂(continuousProcess (P i) (hPc i) x)) l + (nhds (∫ omega, g (omega t) ∂(continuousProcess Q hQc x))) := by + have hmem : t ∈ ({t} : Finset NNReal) := Finset.mem_singleton_self t + exact tendsto_integral_finsetEvaluation_continuousProcess hP hPc hPK hQ hQc hQK hconv {t} + (g.compContinuous ⟨fun path ↦ path ⟨t, hmem⟩, continuous_apply _⟩) x + +end + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/CylinderAlgebra.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/CylinderAlgebra.lean new file mode 100644 index 0000000000..fb212f2335 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/CylinderAlgebra.lean @@ -0,0 +1,208 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass +import LeanPool.MarkovProcess.MarkovProcess.Main + +/-! +# Cylinder test functions on continuous-path space + +A *cylinder* functional of a continuous path reads the path at finitely many times and applies a +bounded continuous function to the values there. These functionals form an algebra, they +separate points of path space (two distinct continuous paths differ at some time, and functions +vanishing at infinity separate the two values), and therefore, by Stone--Weierstrass, they are +uniformly dense on every compact set of paths. + +The approximation is stated in the form that a tightness argument consumes: given a bounded +continuous functional `F` and a compact set of paths `K`, there is a *bounded* cylinder functional +that is uniformly `eps`-close to `F` on `K` and whose norm exceeds `‖F‖` by at most `eps`. The +norm control matters, because the approximation error off `K` is paid for by the total mass +outside `K` times the sum of the two norms; without it the argument would be circular. + +Main results: + +* `MarkovProcess.ContinuousPath.IsBoundedCylinder`, the cylinder property, closed under sums, + products and constants; +* `MarkovProcess.ContinuousPath.coordinateSubalgebra`, the generated algebra of test functions, + with `coordinateSubalgebra_separatesPoints` and + `isBoundedCylinder_of_mem_coordinateSubalgebra`; +* `MarkovProcess.ContinuousPath.exists_boundedCylinder_approx`, the Stone--Weierstrass + approximation with norm control. + +Nothing here mentions a probability law, and no continuity in a starting point is asserted. +-/ + +open scoped BoundedContinuousFunction NNReal ZeroAtInfty + +namespace MarkovProcess + +namespace ContinuousPath + +section Cylinder + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- A functional of a continuous path that reads finitely many times and applies a bounded +continuous function to the values read. -/ +def IsBoundedCylinder (G : ContinuousPath alpha → ℝ) : Prop := + ∃ (I : Finset ℝ≥0) (g : (I → alpha) →ᵇ ℝ), + ∀ omega, G omega = g (finsetEvaluation I omega) + +/-- Restriction of a family of states indexed by a finite set of times to a smaller set. -/ +def finsetRestrict {I J : Finset ℝ≥0} (hIJ : I ⊆ J) : C(J → alpha, I → alpha) := + ⟨fun path i ↦ path ⟨(i : ℝ≥0), hIJ i.2⟩, + continuous_pi fun i ↦ continuous_apply (⟨(i : ℝ≥0), hIJ i.2⟩ : J)⟩ + +@[simp] +theorem finsetRestrict_finsetEvaluation {I J : Finset ℝ≥0} (hIJ : I ⊆ J) + (omega : ContinuousPath alpha) : + finsetRestrict (alpha := alpha) hIJ (finsetEvaluation J omega) = finsetEvaluation I omega := + rfl + +theorem isBoundedCylinder_const (c : ℝ) : + IsBoundedCylinder (alpha := alpha) fun _ ↦ c := + ⟨∅, BoundedContinuousFunction.const _ c, fun _ ↦ rfl⟩ + +theorem IsBoundedCylinder.add {G H : ContinuousPath alpha → ℝ} (hG : IsBoundedCylinder G) + (hH : IsBoundedCylinder H) : IsBoundedCylinder fun omega ↦ G omega + H omega := by + obtain ⟨I, g, hg⟩ := hG + obtain ⟨J, h, hh⟩ := hH + refine ⟨I ∪ J, + g.compContinuous (finsetRestrict (alpha := alpha) Finset.subset_union_left) + + h.compContinuous (finsetRestrict (alpha := alpha) Finset.subset_union_right), + fun omega ↦ ?_⟩ + simp only [BoundedContinuousFunction.add_apply, + BoundedContinuousFunction.compContinuous_apply, finsetRestrict_finsetEvaluation] + rw [hg, hh] + +theorem IsBoundedCylinder.mul {G H : ContinuousPath alpha → ℝ} (hG : IsBoundedCylinder G) + (hH : IsBoundedCylinder H) : IsBoundedCylinder fun omega ↦ G omega * H omega := by + obtain ⟨I, g, hg⟩ := hG + obtain ⟨J, h, hh⟩ := hH + refine ⟨I ∪ J, + g.compContinuous (finsetRestrict (alpha := alpha) Finset.subset_union_left) * + h.compContinuous (finsetRestrict (alpha := alpha) Finset.subset_union_right), + fun omega ↦ ?_⟩ + simp only [BoundedContinuousFunction.mul_apply, + BoundedContinuousFunction.compContinuous_apply, finsetRestrict_finsetEvaluation] + rw [hg, hh] + +theorem isBoundedCylinder_coordinate (t : ℝ≥0) (f : C₀(alpha, ℝ)) : + IsBoundedCylinder fun omega : ContinuousPath alpha ↦ f (omega t) := + ⟨{t}, f.toBCF.compContinuous + ⟨fun path ↦ path ⟨t, Finset.mem_singleton_self t⟩, continuous_apply _⟩, fun _ ↦ rfl⟩ + +variable (alpha) in +/-- The algebra of real test functions on path space generated by the coordinate pullbacks of +functions vanishing at infinity on the state space. -/ +def coordinateSubalgebra : Subalgebra ℝ C(ContinuousPath alpha, ℝ) := + Algebra.adjoin ℝ {G | ∃ (t : ℝ≥0) (f : C₀(alpha, ℝ)), + G = (f : C(alpha, ℝ)).comp ⟨fun omega ↦ omega t, continuous_eval t⟩} + +/-- Every element of the coordinate algebra is a bounded cylinder functional. -/ +theorem isBoundedCylinder_of_mem_coordinateSubalgebra {G : C(ContinuousPath alpha, ℝ)} + (hG : G ∈ coordinateSubalgebra alpha) : + IsBoundedCylinder fun omega ↦ G omega := by + induction hG using Algebra.adjoin_induction with + | mem G hGmem => + obtain ⟨t, f, rfl⟩ := hGmem + exact isBoundedCylinder_coordinate t f + | algebraMap r => + have hconst : (fun omega : ContinuousPath alpha ↦ + (algebraMap ℝ C(ContinuousPath alpha, ℝ) r) omega) = fun _ ↦ r := by + funext omega + simp + rw [hconst] + exact isBoundedCylinder_const r + | add G H _ _ ihG ihH => exact ihG.add ihH + | mul G H _ _ ihG ihH => exact ihG.mul ihH + +/-- The coordinate algebra separates points of path space: two distinct continuous paths differ +at some time, and a function vanishing at infinity separates the two values there. -/ +theorem coordinateSubalgebra_separatesPoints [T3Space alpha] [LocallyCompactSpace alpha] : + (coordinateSubalgebra alpha).SeparatesPoints := by + intro omega eta homega + have hexists : ∃ t : ℝ≥0, omega t ≠ eta t := by + by_contra hcon + exact homega (ContinuousPath.ext fun t ↦ not_ne_iff.mp (not_exists.mp hcon t)) + obtain ⟨t, ht⟩ := hexists + obtain ⟨f, hfone, hfzero, hfcompact, -⟩ := + exists_continuous_one_zero_of_isCompact (isCompact_singleton : IsCompact ({omega t} : Set alpha)) + (isClosed_singleton : IsClosed ({eta t} : Set alpha)) (Set.disjoint_singleton.mpr ht) + let f0 : C₀(alpha, ℝ) := ⟨f, HasCompactSupport.is_zero_at_infty hfcompact⟩ + let G : C(ContinuousPath alpha, ℝ) := + (f0 : C(alpha, ℝ)).comp ⟨fun path ↦ path t, continuous_eval t⟩ + refine ⟨G, ⟨G, ⟨Algebra.subset_adjoin ⟨t, f0, rfl⟩, rfl⟩⟩, ?_⟩ + show f (omega t) ≠ f (eta t) + rw [hfone (Set.mem_singleton _), hfzero (Set.mem_singleton _)] + exact one_ne_zero + +end Cylinder + +section Approximation + +variable {alpha : Type*} [MetricSpace alpha] [LocallyCompactSpace alpha] + +/-- **Cylinder approximation on a compact set of paths.** A bounded continuous functional `F` of +the path is, on any compact set of paths, uniformly `eps`-close to a bounded cylinder functional +whose norm is at most `‖F‖ + eps`. + +Density comes from Stone--Weierstrass applied to `coordinateSubalgebra`; the norm bound comes from +truncating the approximant at height `‖F‖ + eps`, which changes nothing on the compact set. -/ +theorem exists_boundedCylinder_approx (F : ContinuousPath alpha →ᵇ ℝ) + {K : Set (ContinuousPath alpha)} (hK : IsCompact K) {eps : ℝ} (heps : 0 < eps) : + ∃ G : ContinuousPath alpha →ᵇ ℝ, IsBoundedCylinder (fun omega ↦ G omega) ∧ + ‖G‖ ≤ ‖F‖ + eps ∧ ∀ omega ∈ K, |G omega - F omega| ≤ eps := by + obtain ⟨G0, hG0mem, hG0approx⟩ := + ContinuousMap.exists_mem_subalgebra_near_continuous_of_isCompact_of_separatesPoints + (coordinateSubalgebra_separatesPoints (alpha := alpha)) F.toContinuousMap hK heps + obtain ⟨I, g0, hg0⟩ := isBoundedCylinder_of_mem_coordinateSubalgebra hG0mem + set C : ℝ := ‖F‖ + eps with hCdef + have hC0 : 0 ≤ C := by positivity + set clampC : ℝ → ℝ := fun y ↦ max (-C) (min C y) with hclampdef + have hclampcont : Continuous clampC := + continuous_const.max (continuous_const.min continuous_id) + have hclampabs : ∀ y, |clampC y| ≤ C := by + intro y + rw [abs_le] + exact ⟨le_max_left _ _, max_le (by linarith) (min_le_left _ _)⟩ + have hclampeq : ∀ y, |y| ≤ C → clampC y = y := by + intro y hy + rw [abs_le] at hy + simp only [hclampdef, min_eq_right hy.2, max_eq_right hy.1] + set g : (I → alpha) →ᵇ ℝ := + BoundedContinuousFunction.ofNormedAddCommGroup (fun path ↦ clampC (g0 path)) + (hclampcont.comp g0.continuous) C (fun path ↦ by + rw [Real.norm_eq_abs]; exact hclampabs _) with hgdef + set G : ContinuousPath alpha →ᵇ ℝ := + g.compContinuous ⟨finsetEvaluation (alpha := alpha) I, continuous_finiteEvaluation _⟩ with hGdef + have hGapply : ∀ omega : ContinuousPath alpha, G omega = clampC (G0 omega) := by + intro omega + rw [hGdef] + show clampC (g0 (finsetEvaluation I omega)) = clampC (G0 omega) + congr 1 + exact (hg0 omega).symm + refine ⟨G, ⟨I, g, fun omega ↦ rfl⟩, ?_, ?_⟩ + · refine (BoundedContinuousFunction.norm_le hC0).mpr fun omega ↦ ?_ + rw [Real.norm_eq_abs, hGapply omega] + exact hclampabs _ + · intro omega homega + have hnear : |G0 omega - F omega| < eps := by + simpa only [Real.norm_eq_abs] using! hG0approx omega homega + have hFbound : |F omega| ≤ ‖F‖ := by + simpa only [Real.norm_eq_abs] using F.norm_coe_le_norm omega + have hG0bound : |G0 omega| ≤ C := by + have habs : |G0 omega| - |F omega| ≤ |G0 omega - F omega| := + abs_sub_abs_le_abs_sub _ _ + rw [hCdef] + linarith + rw [hGapply omega, hclampeq _ hG0bound] + exact hnear.le + +end Approximation + +end ContinuousPath + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionIntegral.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionIntegral.lean new file mode 100644 index 0000000000..db5009a385 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionIntegral.lean @@ -0,0 +1,85 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity +import LeanPool.MarkovProcess.MarkovProcess.Path.Polish + +/-! +# Finite dense-time marginals of a restarted trajectory law + +Composing the canonical continuous trajectory kernel with a measurable evaluation of the path +and pushing to a finite set of dense times integrates a compactly supported test through the +mapped finite-set kernel at the evaluated state. The evaluation is arbitrary, so the identity +serves deterministic coordinates and stopping-time evaluations alike. + +This is a kernel-level identity of finite-dimensional integrals. No conditional or +stopping-time statement is proved here; those are in `Trajectory/FellerConditional.lean` and +`Trajectory/FellerStoppingConditional.lean`. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal CompactlySupported + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup +namespace IsConservative + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [LocallyCompactSpace alpha] [StandardBorelSpace alpha] [Nonempty alpha] + +/-- Pushing the trajectory kernel restarted at a measurable evaluation to finitely many dense +times integrates a compact test through the mapped finite-set kernel at the evaluated state. -/ +theorem continuousPathTrajectory_integral_map_denseRestriction_map_restrict_comp_comap + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (mu : Measure (ContinuousPath alpha)) [IsFiniteMeasure mu] + (e : ContinuousPath alpha → alpha) (he : Measurable e) + (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) : + ∫ z, f z ∂(((Kernel.comap (continuousPathTrajectory P hP default) e he ∘ₘ mu).map + ContinuousPath.denseRestriction).map J.restrict) = + ∫ omega, (∫ z, f z ∂((finiteSetKernel P (denseTimePhysicalSet J)).map + (DenseTimePath.pullbackPhysicalSet J)) (e omega)) ∂mu := by + let Q := continuousPathTrajectory P hP default + let KJ := (finiteSetKernel P (denseTimePhysicalSet J)).map + (DenseTimePath.pullbackPhysicalSet J) + have hdense := ContinuousPath.measurable_denseRestriction (alpha := alpha) + have hrestrict := Finset.measurable_restrict (X := fun _ ↦ alpha) J + have hQJ : (Q.map ContinuousPath.denseRestriction).map J.restrict = KJ := + continuousPathTrajectory_map_denseRestriction_map_restrict P hP default hK J + have hkernel : + ((Kernel.comap Q e he).map ContinuousPath.denseRestriction).map J.restrict = + Kernel.comap KJ e he := by + rw [← Kernel.comap_map_comm Q he hdense, + ← Kernel.comap_map_comm (Q.map ContinuousPath.denseRestriction) he hrestrict, hQJ] + have hmeasure : + (((Kernel.comap Q e he ∘ₘ mu).map ContinuousPath.denseRestriction).map J.restrict) = + Kernel.comap KJ e he ∘ₘ mu := by + rw [Measure.map_comp mu _ hdense, Measure.map_comp mu _ hrestrict, hkernel] + rw [hmeasure, Measure.comp_eq_comp_const_apply] + let : IsMarkovKernel KJ := by + dsimp only [KJ] + let : IsMarkovKernel (finiteSetKernel P (denseTimePhysicalSet J)) := + hP.isMarkovKernel_finiteSetKernel P (denseTimePhysicalSet J) + exact Kernel.IsMarkovKernel.map _ (DenseTimePath.measurable_pullbackPhysicalSet J) + let : IsMarkovKernel (Kernel.comap KJ e he) := inferInstance + let : IsFiniteMeasure ((Kernel.comap KJ e he ∘ₘ mu)) := inferInstance + have hfint : Integrable f (Kernel.comap KJ e he ∘ₘ mu) := f.integrable + rw [Measure.comp_eq_comp_const_apply] at hfint + have hi := Kernel.integral_comp hfint + simpa only [Kernel.const_apply, Kernel.comap_apply, Q, KJ] using hi + +end +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionMarginals.lean new file mode 100644 index 0000000000..06b2a8b6fb --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionMarginals.lean @@ -0,0 +1,71 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex + +/-! +# Finite marginals of dense restrictions of continuous trajectories + +The finite-coordinate laws of the dense-time restriction of the canonical continuous trajectory +are the existing finite-set kernels, reindexed from physical time back to rational labels. This +file makes no shift, Markov, strong Markov, or Hunt-process assertion. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup +namespace IsConservative + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [StandardBorelSpace alpha] [Nonempty alpha] + +/-- Every finite restriction of the dense-time pushforward of the continuous trajectory has the +finite-set transition law at the corresponding physical times, reindexed by rational labels. -/ +theorem continuousPathTrajectory_map_denseRestriction_map_restrict + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (I : Finset DenseTime) : + ((continuousPathTrajectory P hP default).map + ContinuousPath.denseRestriction).map I.restrict = + (finiteSetKernel P (denseTimePhysicalSet I)).map + (DenseTimePath.pullbackPhysicalSet I) := by + let evaluatePhysical : ContinuousPath alpha → denseTimePhysicalSet I → alpha := + fun path t ↦ path t + have hEvaluate : Measurable evaluatePhysical := by + rw [measurable_pi_iff] + intro t + rw [BorelSpace.measurable_eq (α := alpha)] + exact (ContinuousPath.continuous_eval (alpha := alpha) (t : NNReal)).borel_measurable + have hfun : + I.restrict ∘ ContinuousPath.denseRestriction = + DenseTimePath.pullbackPhysicalSet I ∘ evaluatePhysical := by + funext path + exact (DenseTimePath.pullbackPhysicalSet_evaluation I path).symm + rw [← Kernel.map_comp_right] + · rw [hfun, Kernel.map_comp_right] + · change + ((continuousPathTrajectory P hP default).map + (fun path (t : denseTimePhysicalSet I) ↦ path t)).map + (DenseTimePath.pullbackPhysicalSet I) = _ + rw [continuousPathTrajectory_map_finiteDenseTimeSet P hP default hK I] + · exact hEvaluate + · exact DenseTimePath.measurable_pullbackPhysicalSet I + · exact ContinuousPath.measurable_denseRestriction + · exact Finset.measurable_restrict I + +end +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseStoppingRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseStoppingRestart.lean new file mode 100644 index 0000000000..ffef05166d --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseStoppingRestart.lean @@ -0,0 +1,78 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional +import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart + +/-! +# Conditional restart at dense-time-valued stopping times + +This file specializes the countable-range stopping-time restart theorem to stopping times valued +in `DenseTime`. The associated physical stopping time is obtained through +`DenseTime.castOrderEmbedding`; its range is countable, and deterministic restart is required and +proved only at physical times attained by that range. + +The result is a conditional-expectation identity for the canonical continuous trajectory at +dense-time-valued stopping times. An arbitrary finite `NNReal`-valued stopping time is covered +in `Trajectory/FellerStoppingConditional.lean`, and a stopping time that may be infinite in +`Trajectory/StoppingLtTop.lean`. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup +namespace IsConservative + +noncomputable section + +variable {alpha E : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [StandardBorelSpace alpha] [Nonempty alpha] + [NormedAddCommGroup E] [NormedSpace Real E] [CompleteSpace E] + +/-- A bounded functional of the trajectory shifted at a dense-time-valued stopping time satisfies +the path-kernel conditional-expectation formula at the corresponding physical stopping time. -/ +theorem continuousPathTrajectory_condExp_shift_denseStoppingTime + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (x : alpha) (tau : ContinuousPath alpha → DenseTime) + (htau : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ + ((DenseTime.castOrderEmbedding (tau omega) : NNReal) : WithTop NNReal))) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : Real) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + ((continuousPathTrajectory P hP default) x)[fun omega ↦ + F (ContinuousPath.shift (DenseTime.castOrderEmbedding (tau omega)) omega)| + htau.measurableSpace] =ᵐ[(continuousPathTrajectory P hP default) x] + fun omega ↦ ∫ eta, F eta ∂(continuousPathTrajectory P hP default) + (omega (DenseTime.castOrderEmbedding (tau omega))) := by + let tauPhysical : ContinuousPath alpha → NNReal := + fun omega ↦ DenseTime.castOrderEmbedding (tau omega) + have htauRange : (Set.range tauPhysical).Countable := by + apply (Set.countable_range + (fun t : DenseTime ↦ DenseTime.castOrderEmbedding t)).mono + rintro S ⟨omega, rfl⟩ + exact ⟨tau omega, rfl⟩ + apply ContinuousPath.condExp_shift_stoppingTime_ae_eq_integral_pathKernel_of_restart_on_range + (continuousPathTrajectory P hP default) x tauPhysical htau htauRange + · intro S hS + obtain ⟨omega, homega⟩ := hS + subst S + exact continuousPathTrajectory_restrict_map_shift_denseTime + P hP default hK x (tau omega) + · exact hF + · exact hFC + +end +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DiscountedDynkin.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DiscountedDynkin.lean new file mode 100644 index 0000000000..08f1117e35 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DiscountedDynkin.lean @@ -0,0 +1,628 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale + +/-! +# The discounted Dynkin formula + +For the continuous-path process of a conservative Feller semigroup, this file proves that the +Dynkin process with exponential discount is a martingale and applies optional stopping at an exit +time truncated by a deterministic horizon. At zero discount it agrees with the Dynkin process +of `Trajectory/DynkinMartingale.lean`. + +Main results: `IsFellerKernelSemigroup.discountedDynkinProcess`, +`discountedDynkinProcess_apply`, `discountedDynkinProcess_zero`, +`norm_discountedDynkinProcess_le`, `continuous_discountedDynkinProcess`, +`stronglyMeasurable_integral_discountedGenerator`, +`stronglyMeasurable_discountedDynkinProcess_canonicalFiltration`, +`stronglyMeasurable_discountedDynkinProcess`, `adapted_discountedDynkinProcess`, +`integrable_discountedDynkinProcess`, `integral_discountedDynkinProcess`, +`discountedDynkinProcess_eq_add_shift`, `martingale_discountedDynkinProcess`, +`progMeasurable_discountedDynkinProcess`, `measurable_discountedDynkinProcess_stoppingTime`, +`integral_discountedDynkinProcess_stoppingTime`, and +`integral_exp_eval_exitTimeTrunc_sub_eq_integral_integral`. + +No assertion is made at an unbounded stopping time or about passage to an infinite horizon. +-/ + +open Filter MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal ZeroAtInfty + +namespace MarkovProcess.SubMarkovKernelSemigroup + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [LocallyCompactSpace alpha] + +variable {P : SubMarkovKernelSemigroup alpha} + +section ProcessDefinition + +/-- The discounted Dynkin process associated with a generator-domain function. -/ +def IsFellerKernelSemigroup.discountedDynkinProcess + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) (t : NNReal) (omega : ContinuousPath alpha) : ℝ := + Real.exp (-lam * (t : ℝ)) * (f : C₀(alpha, ℝ)) (omega t) - + ∫ s in (0 : ℝ)..t, Real.exp (-lam * s) * + (hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))) + (omega (Real.toNNReal s)) + +/-- The discounted Dynkin process, unfolded. -/ +theorem IsFellerKernelSemigroup.discountedDynkinProcess_apply + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) (t : NNReal) (omega : ContinuousPath alpha) : + hFeller.discountedDynkinProcess f lam t omega = + Real.exp (-lam * (t : ℝ)) * (f : C₀(alpha, ℝ)) (omega t) - + ∫ s in (0 : ℝ)..t, Real.exp (-lam * s) * + (hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))) + (omega (Real.toNNReal s)) := + rfl + +/-- At zero discount, the discounted Dynkin process is the ordinary Dynkin process. -/ +theorem IsFellerKernelSemigroup.discountedDynkinProcess_zero + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) : + hFeller.discountedDynkinProcess f 0 = hFeller.dynkinProcess f := by + funext t omega + simp only [IsFellerKernelSemigroup.discountedDynkinProcess_apply, + IsFellerKernelSemigroup.dynkinProcess_apply, zero_mul, neg_zero, Real.exp_zero, one_mul, + zero_smul, sub_zero] + +/-- The exponential discount is bounded on a nonnegative bounded interval. -/ +private theorem exp_neg_mul_le_exp_abs_mul {lam s v : ℝ} (hs : 0 ≤ s) (hsv : s ≤ v) : + Real.exp (-lam * s) ≤ Real.exp (|lam| * v) := by + apply Real.exp_le_exp.mpr + calc + -lam * s ≤ |lam| * s := + mul_le_mul_of_nonneg_right (neg_le_abs lam) hs + _ ≤ |lam| * v := mul_le_mul_of_nonneg_left hsv (abs_nonneg lam) + +/-- The discounted Dynkin process is bounded uniformly in the path on bounded time intervals. -/ +theorem IsFellerKernelSemigroup.norm_discountedDynkinProcess_le + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) (t : NNReal) (omega : ContinuousPath alpha) : + ‖hFeller.discountedDynkinProcess f lam t omega‖ ≤ + Real.exp (|lam| * (t : ℝ)) * + (‖(f : C₀(alpha, ℝ))‖ + (t : ℝ) * + ‖hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))‖) := by + let g : C₀(alpha, ℝ) := + hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ)) + have hexp : Real.exp (-lam * (t : ℝ)) ≤ Real.exp (|lam| * (t : ℝ)) := + exp_neg_mul_le_exp_abs_mul t.coe_nonneg le_rfl + have hterm : ‖Real.exp (-lam * (t : ℝ)) * (f : C₀(alpha, ℝ)) (omega t)‖ ≤ + Real.exp (|lam| * (t : ℝ)) * ‖(f : C₀(alpha, ℝ))‖ := by + rw [norm_mul, Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] + exact (mul_le_mul hexp (norm_c0_apply_le _ _) (norm_nonneg _) (Real.exp_pos _).le) + have hint : ‖∫ s in (0 : ℝ)..t, Real.exp (-lam * s) * g (omega (Real.toNNReal s))‖ ≤ + (t : ℝ) * (Real.exp (|lam| * (t : ℝ)) * ‖g‖) := by + have h := intervalIntegral.norm_integral_le_of_norm_le_const + (a := (0 : ℝ)) (b := (t : ℝ)) + (C := Real.exp (|lam| * (t : ℝ)) * ‖g‖) + (f := fun s : ℝ ↦ Real.exp (-lam * s) * g (omega (Real.toNNReal s))) + (fun s hs ↦ by + rw [Set.uIoc_of_le t.coe_nonneg] at hs + rw [norm_mul, Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] + exact mul_le_mul (exp_neg_mul_le_exp_abs_mul hs.1.le hs.2) + (norm_c0_apply_le _ _) (norm_nonneg _) (Real.exp_pos _).le) + rwa [sub_zero, abs_of_nonneg t.coe_nonneg, mul_comm] at h + rw [hFeller.discountedDynkinProcess_apply] + change ‖_ - ∫ s in (0 : ℝ)..t, Real.exp (-lam * s) * g (omega (Real.toNNReal s))‖ ≤ _ + calc + ‖_ - ∫ s in (0 : ℝ)..t, Real.exp (-lam * s) * g (omega (Real.toNNReal s))‖ + ≤ _ := norm_sub_le _ _ + _ ≤ Real.exp (|lam| * (t : ℝ)) * ‖(f : C₀(alpha, ℝ))‖ + + (t : ℝ) * (Real.exp (|lam| * (t : ℝ)) * ‖g‖) := add_le_add hterm hint + _ = Real.exp (|lam| * (t : ℝ)) * + (‖(f : C₀(alpha, ℝ))‖ + (t : ℝ) * ‖g‖) := by ring + +/-- The discounted Dynkin process is continuous in time along every path. -/ +theorem IsFellerKernelSemigroup.continuous_discountedDynkinProcess + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) (omega : ContinuousPath alpha) : + Continuous fun t : NNReal ↦ hFeller.discountedDynkinProcess f lam t omega := by + let g : C₀(alpha, ℝ) := + hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ)) + have hIntegrand : Continuous fun s : ℝ ↦ + Real.exp (-lam * s) * g (omega (Real.toNNReal s)) := + (Real.continuous_exp.comp (continuous_const.mul continuous_id)).mul + (g.continuous.comp (omega.continuous.comp continuous_real_toNNReal)) + have hIntegral : Continuous fun u : ℝ ↦ + ∫ s in (0 : ℝ)..u, Real.exp (-lam * s) * g (omega (Real.toNNReal s)) := by + rw [continuous_iff_continuousAt] + intro u + exact ((hIntegrand.integral_hasStrictDerivAt 0 u).hasDerivAt).continuousAt + exact (((Real.continuous_exp.comp (continuous_const.mul NNReal.continuous_coe)).mul + ((f : C₀(alpha, ℝ)).continuous.comp omega.continuous)).sub + (hIntegral.comp NNReal.continuous_coe)) + +end ProcessDefinition + +section Adapted + +variable [SecondCountableTopology alpha] + +/-- The discounted generator integrand, clamped to a deterministic horizon, is jointly strongly +measurable for time and the canonical filtration at that horizon. -/ +private theorem stronglyMeasurable_discountedGenerator_min + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) (t : NNReal) : + StronglyMeasurable[(borel ℝ).prod (ContinuousPath.canonicalFiltration (alpha := alpha) t)] + (fun p : ℝ × ContinuousPath alpha ↦ Real.exp (-lam * p.1) * + (hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))) + (p.2 (min (Real.toNNReal p.1) t))) := by + exact ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.comp + measurable_fst).stronglyMeasurable.mul + ((hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))).continuous.comp_stronglyMeasurable + (ContinuousPath.measurable_clampedCoordinate (alpha := alpha) t).stronglyMeasurable) + +/-- The correction term of the discounted Dynkin process is strongly measurable at its horizon. -/ +theorem IsFellerKernelSemigroup.stronglyMeasurable_integral_discountedGenerator + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) (t : NNReal) : + StronglyMeasurable[ContinuousPath.canonicalFiltration (alpha := alpha) t] + (fun omega : ContinuousPath alpha ↦ + ∫ s in (0 : ℝ)..t, Real.exp (-lam * s) * + (hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))) + (omega (Real.toNNReal s))) := by + let g : C₀(alpha, ℝ) := + hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ)) + have hprod := stronglyMeasurable_integral_prod (volume.restrict (Set.Ioc (0 : ℝ) t)) + (stronglyMeasurable_discountedGenerator_min hFeller f lam t) + have hfun : (fun omega : ContinuousPath alpha ↦ + ∫ s in (0 : ℝ)..t, Real.exp (-lam * s) * g (omega (Real.toNNReal s))) = + fun omega : ContinuousPath alpha ↦ ∫ s, + Real.exp (-lam * s) * g (omega (min (Real.toNNReal s) t)) + ∂(volume.restrict (Set.Ioc (0 : ℝ) t)) := by + funext omega + rw [intervalIntegral.integral_of_le t.coe_nonneg] + refine setIntegral_congr_fun measurableSet_Ioc fun s hs ↦ ?_ + rw [min_eq_left (Real.toNNReal_le_iff_le_coe.mpr hs.2)] + rw [hfun] + exact hprod + +/-- The discounted Dynkin process is strongly measurable for the canonical filtration at time +`t`. -/ +theorem IsFellerKernelSemigroup.stronglyMeasurable_discountedDynkinProcess_canonicalFiltration + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) (t : NNReal) : + StronglyMeasurable[ContinuousPath.canonicalFiltration (alpha := alpha) t] + (hFeller.discountedDynkinProcess f lam t) := + (((f : C₀(alpha, ℝ)).continuous.comp_stronglyMeasurable + (ContinuousPath.measurable_coordinateProcess_canonicalFiltration + (alpha := alpha) t).stronglyMeasurable).const_mul + (Real.exp (-lam * (t : ℝ)))).sub + (hFeller.stronglyMeasurable_integral_discountedGenerator f lam t) + +/-- The discounted Dynkin process at a deterministic time is Borel strongly measurable. -/ +theorem IsFellerKernelSemigroup.stronglyMeasurable_discountedDynkinProcess + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) (t : NNReal) : + StronglyMeasurable (hFeller.discountedDynkinProcess f lam t) := + (hFeller.stronglyMeasurable_discountedDynkinProcess_canonicalFiltration f lam t).mono + ((ContinuousPath.canonicalFiltration (alpha := alpha)).le t) + +/-- The discounted Dynkin process is adapted to the canonical filtration. -/ +theorem IsFellerKernelSemigroup.adapted_discountedDynkinProcess + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) : + StronglyAdapted (ContinuousPath.canonicalFiltration (alpha := alpha)) + (hFeller.discountedDynkinProcess f lam) := + fun t ↦ hFeller.stronglyMeasurable_discountedDynkinProcess_canonicalFiltration f lam t + +end Adapted + +section Expectation + +variable [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] +variable (hP : P.IsConservative) + +/-- The discounted Dynkin process is integrable under the continuous-path process. -/ +theorem IsFellerKernelSemigroup.integrable_discountedDynkinProcess + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) (t : NNReal) (y : alpha) : + Integrable (hFeller.discountedDynkinProcess f lam t) + (IsConservative.continuousProcess P hP y) := + Integrable.of_bound + (hFeller.stronglyMeasurable_discountedDynkinProcess f lam t).aestronglyMeasurable _ + (Eventually.of_forall (hFeller.norm_discountedDynkinProcess_le f lam t)) + +/-- The expectation of the discounted Dynkin process is its initial value. -/ +theorem IsFellerKernelSemigroup.integral_discountedDynkinProcess + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (lam : ℝ) (t : NNReal) (y : alpha) : + ∫ omega, hFeller.discountedDynkinProcess f lam t omega + ∂(IsConservative.continuousProcess P hP y) = + (f : C₀(alpha, ℝ)) y := by + let Q : Measure (ContinuousPath alpha) := IsConservative.continuousProcess P hP y + let g : C₀(alpha, ℝ) := + hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ)) + have hterm : Integrable (fun omega : ContinuousPath alpha ↦ + Real.exp (-lam * (t : ℝ)) * (f : C₀(alpha, ℝ)) (omega t)) Q := by + have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ + Real.exp (-lam * (t : ℝ)) * (f : C₀(alpha, ℝ)) (omega t)) := + ((f : C₀(alpha, ℝ)).continuous.measurable.comp + (ContinuousPath.measurable_coordinateProcess (alpha := alpha) t)).const_mul _ + exact Integrable.of_bound hmeas.aestronglyMeasurable _ + (Eventually.of_forall fun omega ↦ by + rw [norm_mul] + exact mul_le_mul_of_nonneg_left (norm_c0_apply_le _ _) (norm_nonneg _)) + have hcorr : Integrable (fun omega : ContinuousPath alpha ↦ + ∫ s in (0 : ℝ)..t, Real.exp (-lam * s) * g (omega (Real.toNNReal s))) Q := by + have hmeas := (hFeller.stronglyMeasurable_integral_discountedGenerator f lam t).mono + ((ContinuousPath.canonicalFiltration (alpha := alpha)).le t) + refine Integrable.of_bound hmeas.aestronglyMeasurable + ((t : ℝ) * (Real.exp (|lam| * (t : ℝ)) * ‖g‖)) + (Eventually.of_forall fun omega ↦ ?_) + have h := intervalIntegral.norm_integral_le_of_norm_le_const + (a := (0 : ℝ)) (b := (t : ℝ)) + (C := Real.exp (|lam| * (t : ℝ)) * ‖g‖) + (f := fun s : ℝ ↦ Real.exp (-lam * s) * g (omega (Real.toNNReal s))) + (fun s hs ↦ by + rw [Set.uIoc_of_le t.coe_nonneg] at hs + rw [norm_mul, Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] + exact mul_le_mul (exp_neg_mul_le_exp_abs_mul hs.1.le hs.2) + (norm_c0_apply_le _ _) (norm_nonneg _) (Real.exp_pos _).le) + rwa [sub_zero, abs_of_nonneg t.coe_nonneg, mul_comm] at h + have hstep : + (∫ omega, Real.exp (-lam * (t : ℝ)) * (f : C₀(alpha, ℝ)) (omega t) ∂Q) - + (f : C₀(alpha, ℝ)) y = + ∫ s in (0 : ℝ)..t, ∫ omega, Real.exp (-lam * s) * + g (omega (Real.toNNReal s)) ∂Q := by + calc + (∫ omega, Real.exp (-lam * (t : ℝ)) * (f : C₀(alpha, ℝ)) (omega t) ∂Q) - + (f : C₀(alpha, ℝ)) y + = c0EvalCLM y (Real.exp (-lam * (t : ℝ)) • + hFeller.c0Semigroup t (f : C₀(alpha, ℝ)) - f) := by + rw [map_sub, map_smul, c0EvalCLM_apply, c0EvalCLM_apply, + smul_eq_mul, hFeller.c0Semigroup_apply_eq_integral P hP hK] + rw [MeasureTheory.integral_const_mul] + _ = c0EvalCLM y (∫ s in (0 : ℝ)..t, Real.exp (-lam * s) • + hFeller.c0Semigroup (Real.toNNReal s) g) := by + rw [hFeller.c0Semigroup.exp_smul_operator_sub_eq_integral f lam t] + _ = ∫ s in (0 : ℝ)..t, c0EvalCLM y + (Real.exp (-lam * s) • hFeller.c0Semigroup (Real.toNNReal s) g) := by + rw [← (c0EvalCLM y).intervalIntegral_comp_comm] + exact ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).smul + (hFeller.c0Semigroup.continuous_operator_toNNReal g)).intervalIntegrable _ _ + _ = ∫ s in (0 : ℝ)..t, ∫ omega, Real.exp (-lam * s) * + g (omega (Real.toNNReal s)) ∂Q := by + refine intervalIntegral.integral_congr fun s _ ↦ ?_ + rw [map_smul, c0EvalCLM_apply, smul_eq_mul, + hFeller.c0Semigroup_apply_eq_integral P hP hK, MeasureTheory.integral_const_mul] + have hcont : Continuous fun p : ℝ × ContinuousPath alpha ↦ + Real.exp (-lam * p.1) * g (p.2 (Real.toNNReal p.1)) := + (Real.continuous_exp.comp (continuous_const.mul continuous_fst)).mul + (g.continuous.comp ((ContinuousEval.continuous_eval.comp continuous_swap).comp + (continuous_real_toNNReal.fst'.prodMk continuous_snd))) + have hprodint : Integrable + (Function.uncurry fun (s : ℝ) (omega : ContinuousPath alpha) ↦ + Real.exp (-lam * s) * g (omega (Real.toNNReal s))) + ((volume.restrict (Set.Ioc (0 : ℝ) t)).prod Q) := by + let C := Real.exp (|lam| * (t : ℝ)) * ‖g‖ + refine Integrable.of_bound hcont.aestronglyMeasurable C ?_ + change ∀ᵐ p : ℝ × ContinuousPath alpha + ∂((volume.restrict (Set.Ioc (0 : ℝ) t)).prod Q), + ‖Real.exp (-lam * p.1) * g (p.2 (Real.toNNReal p.1))‖ ≤ C + rw [Measure.ae_prod_iff_ae_ae (measurableSet_le + (hcont.norm.measurable) measurable_const)] + filter_upwards [ae_restrict_mem measurableSet_Ioc] with s hs + exact Eventually.of_forall fun omega ↦ by + rw [norm_mul, Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] + exact mul_le_mul (exp_neg_mul_le_exp_abs_mul hs.1.le hs.2) + (norm_c0_apply_le _ _) (norm_nonneg _) (Real.exp_pos _).le + have hswap : + ∫ omega, (∫ s in (0 : ℝ)..t, Real.exp (-lam * s) * + g (omega (Real.toNNReal s))) ∂Q = + ∫ s in (0 : ℝ)..t, ∫ omega, Real.exp (-lam * s) * + g (omega (Real.toNNReal s)) ∂Q := by + calc + ∫ omega, (∫ s in (0 : ℝ)..t, Real.exp (-lam * s) * + g (omega (Real.toNNReal s))) ∂Q = + ∫ omega, (∫ s in Set.Ioc (0 : ℝ) t, Real.exp (-lam * s) * + g (omega (Real.toNNReal s))) ∂Q := by + refine integral_congr_ae (Eventually.of_forall fun omega ↦ ?_) + exact intervalIntegral.integral_of_le t.coe_nonneg + _ = ∫ s in Set.Ioc (0 : ℝ) t, ∫ omega, Real.exp (-lam * s) * + g (omega (Real.toNNReal s)) ∂Q := (integral_integral_swap hprodint).symm + _ = ∫ s in (0 : ℝ)..t, ∫ omega, Real.exp (-lam * s) * + g (omega (Real.toNNReal s)) ∂Q := + (intervalIntegral.integral_of_le t.coe_nonneg).symm + change ∫ omega, (Real.exp (-lam * (t : ℝ)) * (f : C₀(alpha, ℝ)) (omega t) - + ∫ s in (0 : ℝ)..t, Real.exp (-lam * s) * g (omega (Real.toNNReal s))) ∂Q = _ + rw [integral_sub hterm hcorr] + linarith only [hstep, hswap] + +end Expectation + +section Decomposition + +/-- The discounted Dynkin process decomposes at an intermediate deterministic time. -/ +theorem IsFellerKernelSemigroup.discountedDynkinProcess_eq_add_shift + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) (s t : NNReal) (hst : s ≤ t) (omega : ContinuousPath alpha) : + hFeller.discountedDynkinProcess f lam t omega = + hFeller.discountedDynkinProcess f lam s omega - + Real.exp (-lam * (s : ℝ)) * (f : C₀(alpha, ℝ)) (omega s) + + Real.exp (-lam * (s : ℝ)) * + hFeller.discountedDynkinProcess f lam (t - s) (ContinuousPath.shift s omega) := by + let g : C₀(alpha, ℝ) := + hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ)) + let q : ℝ → ℝ := fun v ↦ Real.exp (-lam * v) * g (omega (Real.toNNReal v)) + have hscaledTail : Real.exp (-lam * (s : ℝ)) * + (∫ u in (0 : ℝ)..((t - s : NNReal) : ℝ), Real.exp (-lam * u) * + g (omega (s + Real.toNNReal u))) = + ∫ v in (s : ℝ)..(t : ℝ), q v := by + rw [← intervalIntegral.integral_const_mul] + have hcongr : (∫ u in (0 : ℝ)..((t - s : NNReal) : ℝ), + Real.exp (-lam * (s : ℝ)) * + (Real.exp (-lam * u) * g (omega (s + Real.toNNReal u)))) = + ∫ u in (0 : ℝ)..((t - s : NNReal) : ℝ), q (u + s) := by + refine intervalIntegral.integral_congr fun u hu ↦ ?_ + have hu0 : (0 : ℝ) ≤ u := by + rw [Set.uIcc_of_le (t - s : NNReal).coe_nonneg] at hu + exact hu.1 + have hcoe : Real.toNNReal (u + s) = s + Real.toNNReal u := by + apply NNReal.coe_injective + rw [NNReal.coe_add, Real.coe_toNNReal u hu0, + Real.coe_toNNReal _ (add_nonneg hu0 s.coe_nonneg)] + ring + dsimp only [q] + rw [hcoe, ← mul_assoc, ← Real.exp_add] + congr 2 + ring + rw [hcongr, intervalIntegral.integral_comp_add_right q (s : ℝ), zero_add] + congr 1 + rw [NNReal.coe_sub hst] + ring + have hcont : Continuous q := + (Real.continuous_exp.comp (continuous_const.mul continuous_id)).mul + (g.continuous.comp (omega.continuous.comp continuous_real_toNNReal)) + have hsplit : (∫ v in (0 : ℝ)..(s : ℝ), q v) + + (∫ v in (s : ℝ)..(t : ℝ), q v) = ∫ v in (0 : ℝ)..(t : ℝ), q v := + intervalIntegral.integral_add_adjacent_intervals (hcont.intervalIntegrable _ _) + (hcont.intervalIntegrable _ _) + have hExp : Real.exp (-lam * (t : ℝ)) = + Real.exp (-lam * (s : ℝ)) * Real.exp (-lam * ((t - s : NNReal) : ℝ)) := by + rw [← Real.exp_add] + congr 1 + rw [NNReal.coe_sub hst] + ring + simp only [IsFellerKernelSemigroup.discountedDynkinProcess_apply, + ContinuousPath.shift_apply, add_tsub_cancel_of_le hst] + change _ - ∫ v in (0 : ℝ)..(t : ℝ), q v = + (_ - ∫ v in (0 : ℝ)..(s : ℝ), q v) - _ + + Real.exp (-lam * (s : ℝ)) * + (_ - ∫ u in (0 : ℝ)..((t - s : NNReal) : ℝ), + Real.exp (-lam * u) * g (omega (s + Real.toNNReal u))) + rw [hExp, mul_assoc, mul_sub, hscaledTail] + linarith only [hsplit] + +end Decomposition + +section Martingale + +variable [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] +variable (hP : P.IsConservative) + +/-- The exponentially discounted Dynkin process is a martingale for the canonical filtration. -/ +theorem IsFellerKernelSemigroup.martingale_discountedDynkinProcess + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (lam : ℝ) (x : alpha) : + Martingale (hFeller.discountedDynkinProcess f lam) + (ContinuousPath.canonicalFiltration (alpha := alpha)) + (IsConservative.continuousProcess P hP x) := by + refine ⟨hFeller.adapted_discountedDynkinProcess f lam, fun s t hst ↦ ?_⟩ + let c : ℝ := Real.exp (-lam * (s : ℝ)) + let A : ContinuousPath alpha → ℝ := fun omega ↦ + hFeller.discountedDynkinProcess f lam s omega - c * (f : C₀(alpha, ℝ)) (omega s) + let F : ContinuousPath alpha → ℝ := fun eta ↦ + c * hFeller.discountedDynkinProcess f lam (t - s) eta + have hdecomp : hFeller.discountedDynkinProcess f lam t = + A + fun omega ↦ F (ContinuousPath.shift s omega) := by + funext omega + exact hFeller.discountedDynkinProcess_eq_add_shift f lam s t hst omega + have hmeasA : StronglyMeasurable[ContinuousPath.canonicalFiltration (alpha := alpha) s] A := + (hFeller.stronglyMeasurable_discountedDynkinProcess_canonicalFiltration f lam s).sub + (((f : C₀(alpha, ℝ)).continuous.comp_stronglyMeasurable + (ContinuousPath.measurable_coordinateProcess_canonicalFiltration + (alpha := alpha) s).stronglyMeasurable).const_mul c) + have hintA : Integrable A (IsConservative.continuousProcess P hP x) := by + refine Integrable.of_bound + (hmeasA.mono + ((ContinuousPath.canonicalFiltration (alpha := alpha)).le s)).aestronglyMeasurable + (Real.exp (|lam| * (s : ℝ)) * + (‖(f : C₀(alpha, ℝ))‖ + (s : ℝ) * + ‖hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))‖) + + ‖c‖ * ‖(f : C₀(alpha, ℝ))‖) + (Eventually.of_forall fun omega ↦ ?_) + exact (norm_sub_le _ _).trans (add_le_add + (hFeller.norm_discountedDynkinProcess_le f lam s omega) + (by rw [norm_mul]; exact mul_le_mul_of_nonneg_left (norm_c0_apply_le _ _) (norm_nonneg _))) + have hmeasF : StronglyMeasurable F := + (hFeller.stronglyMeasurable_discountedDynkinProcess f lam (t - s)).const_mul c + have hboundF : ∀ eta : ContinuousPath alpha, ‖F eta‖ ≤ + ‖c‖ * (Real.exp (|lam| * ((t - s : NNReal) : ℝ)) * + (‖(f : C₀(alpha, ℝ))‖ + ((t - s : NNReal) : ℝ) * + ‖hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))‖)) := by + intro eta + dsimp only [F] + rw [norm_mul] + exact mul_le_mul_of_nonneg_left + (hFeller.norm_discountedDynkinProcess_le f lam (t - s) eta) (norm_nonneg _) + have hintB : Integrable (fun omega : ContinuousPath alpha ↦ + F (ContinuousPath.shift s omega)) (IsConservative.continuousProcess P hP x) := + Integrable.of_bound + (hmeasF.comp_measurable + (ContinuousPath.measurable_shift_fixed (alpha := alpha) s)).aestronglyMeasurable + _ (Eventually.of_forall fun omega ↦ hboundF (ContinuousPath.shift s omega)) + have hcondA := condExp_of_stronglyMeasurable + ((ContinuousPath.canonicalFiltration (alpha := alpha)).le s) hmeasA hintA + have hcondB := hFeller.continuousProcess_condExp_shift P hP hK x s F hmeasF _ hboundF + have hcondB' : (IsConservative.continuousProcess P hP x)[fun omega ↦ + F (ContinuousPath.shift s omega) | ContinuousPath.canonicalFiltration (alpha := alpha) s] + =ᵐ[IsConservative.continuousProcess P hP x] + fun omega : ContinuousPath alpha ↦ c * (f : C₀(alpha, ℝ)) (omega s) := by + refine hcondB.trans (Eventually.of_forall fun omega ↦ ?_) + dsimp only [F] + rw [MeasureTheory.integral_const_mul] + congr 1 + exact hFeller.integral_discountedDynkinProcess hP hK f lam (t - s) (omega s) + rw [hdecomp] + refine (condExp_add hintA hintB _).trans ?_ + rw [hcondA] + refine (EventuallyEq.add (EventuallyEq.refl _ _) hcondB').trans + (Eventually.of_forall fun omega ↦ ?_) + simp only [Pi.add_apply, A] + ring + +end Martingale + +section OptionalStopping + +variable [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] +variable (hP : P.IsConservative) + +omit [CompleteSpace alpha] [Nonempty alpha] in +/-- The discounted Dynkin process is progressively measurable. -/ +theorem IsFellerKernelSemigroup.progMeasurable_discountedDynkinProcess + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) : + IsStronglyProgressive (ContinuousPath.canonicalFiltration (alpha := alpha)) + (hFeller.discountedDynkinProcess f lam) := + (hFeller.adapted_discountedDynkinProcess f lam).isStronglyProgressive_of_continuous fun omega ↦ + hFeller.continuous_discountedDynkinProcess f lam omega + +omit [CompleteSpace alpha] [Nonempty alpha] in +/-- The discounted Dynkin process evaluated at a finite stopping time is Borel measurable. -/ +theorem IsFellerKernelSemigroup.measurable_discountedDynkinProcess_stoppingTime + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (lam : ℝ) (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) : + Measurable fun omega ↦ hFeller.discountedDynkinProcess f lam (T omega) omega := by + have h := (measurable_stoppedValue (hFeller.progMeasurable_discountedDynkinProcess f lam) hT).mono + hT.measurableSpace_le le_rfl + simpa only [stoppedValue] using! h + +/-- Optional stopping for the discounted Dynkin process at a bounded finite stopping time. -/ +theorem IsFellerKernelSemigroup.integral_discountedDynkinProcess_stoppingTime + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (lam : ℝ) + (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + {K : NNReal} (hTK : ∀ omega, T omega ≤ K) (x : alpha) : + ∫ omega, hFeller.discountedDynkinProcess f lam (T omega) omega + ∂(IsConservative.continuousProcess P hP x) = + (f : C₀(alpha, ℝ)) x := by + let g : C₀(alpha, ℝ) := + hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ)) + have hbound : ∀ v : NNReal, ∃ C : ℝ, ∀ t ≤ v, ∀ omega : ContinuousPath alpha, + ‖hFeller.discountedDynkinProcess f lam t omega‖ ≤ C := by + intro v + refine ⟨Real.exp (|lam| * (v : ℝ)) * + (‖(f : C₀(alpha, ℝ))‖ + (v : ℝ) * ‖g‖), fun t ht omega ↦ + (hFeller.norm_discountedDynkinProcess_le f lam t omega).trans ?_⟩ + have hexp : Real.exp (|lam| * (t : ℝ)) ≤ Real.exp (|lam| * (v : ℝ)) := by + apply Real.exp_le_exp.mpr + exact mul_le_mul_of_nonneg_left (NNReal.coe_le_coe.mpr ht) (abs_nonneg lam) + have hinside : ‖(f : C₀(alpha, ℝ))‖ + (t : ℝ) * ‖g‖ ≤ + ‖(f : C₀(alpha, ℝ))‖ + (v : ℝ) * ‖g‖ := + add_le_add (le_refl _) (mul_le_mul_of_nonneg_right + (NNReal.coe_le_coe.mpr ht) (norm_nonneg g)) + exact mul_le_mul hexp hinside + (add_nonneg (norm_nonneg _) (mul_nonneg t.coe_nonneg (norm_nonneg g))) + (Real.exp_pos _).le + have hright : ∀ (omega : ContinuousPath alpha) (v : NNReal), + ContinuousWithinAt (fun t : NNReal ↦ hFeller.discountedDynkinProcess f lam t omega) + (Set.Ici v) v := + fun omega _ ↦ (hFeller.continuous_discountedDynkinProcess f lam omega).continuousWithinAt + rw [MarkovProcess.integral_stoppedValue_eq_of_locallyBounded + (hFeller.martingale_discountedDynkinProcess hP hK f lam x) hbound hright hT hTK] + exact hFeller.integral_discountedDynkinProcess hP hK f lam 0 x + +/-- **The discounted Dynkin formula at a truncated exit time.** -/ +theorem IsFellerKernelSemigroup.integral_exp_eval_exitTimeTrunc_sub_eq_integral_integral + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (U : Set alpha) (hU : IsOpen U) + (K : NNReal) (lam : ℝ) (x : alpha) : + ∫ omega, Real.exp (-lam * (ContinuousPath.exitTimeTrunc U K omega : ℝ)) * + (f : C₀(alpha, ℝ)) (omega (ContinuousPath.exitTimeTrunc U K omega)) + ∂(IsConservative.continuousProcess P hP x) - (f : C₀(alpha, ℝ)) x = + ∫ omega, (∫ s in (0 : ℝ)..(ContinuousPath.exitTimeTrunc U K omega : ℝ), + Real.exp (-lam * s) * + (hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))) + (omega (Real.toNNReal s))) + ∂(IsConservative.continuousProcess P hP x) := by + let T := ContinuousPath.exitTimeTrunc U K + let Q : Measure (ContinuousPath alpha) := IsConservative.continuousProcess P hP x + have hT := ContinuousPath.isStoppingTime_exitTimeTrunc U hU K + have hTK := ContinuousPath.exitTimeTrunc_le U K + have hstop := hFeller.integral_discountedDynkinProcess_stoppingTime hP hK f lam T hT hTK x + have hterminal : Integrable (fun omega : ContinuousPath alpha ↦ + Real.exp (-lam * (T omega : ℝ)) * (f : C₀(alpha, ℝ)) (omega (T omega))) Q := by + have hmeasT : Measurable T := ContinuousPath.measurable_of_isStoppingTime T hT + have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ + Real.exp (-lam * (T omega : ℝ)) * (f : C₀(alpha, ℝ)) (omega (T omega))) := + (Real.continuous_exp.measurable.comp + (measurable_const.mul (measurable_coe_nnreal_real.comp hmeasT))).mul + ((f : C₀(alpha, ℝ)).continuous.measurable.comp + (ContinuousPath.measurable_eval_stoppingTime_borel T hT)) + refine Integrable.of_bound hmeas.aestronglyMeasurable + (Real.exp (|lam| * (K : ℝ)) * ‖(f : C₀(alpha, ℝ))‖) + (Eventually.of_forall fun omega ↦ ?_) + rw [norm_mul, Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] + exact mul_le_mul (exp_neg_mul_le_exp_abs_mul (T omega).coe_nonneg + (NNReal.coe_le_coe.mpr (hTK omega))) (norm_c0_apply_le _ _) + (norm_nonneg _) (Real.exp_pos _).le + have hcorrection : Integrable (fun omega : ContinuousPath alpha ↦ + ∫ s in (0 : ℝ)..(T omega : ℝ), Real.exp (-lam * s) * + (hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))) + (omega (Real.toNNReal s))) Q := by + have hdiff : (fun omega : ContinuousPath alpha ↦ + ∫ s in (0 : ℝ)..(T omega : ℝ), Real.exp (-lam * s) * + (hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))) + (omega (Real.toNNReal s))) = + fun omega ↦ Real.exp (-lam * (T omega : ℝ)) * + (f : C₀(alpha, ℝ)) (omega (T omega)) - + hFeller.discountedDynkinProcess f lam (T omega) omega := by + funext omega + rw [hFeller.discountedDynkinProcess_apply] + ring + rw [hdiff] + exact hterminal.sub (Integrable.of_bound + (hFeller.measurable_discountedDynkinProcess_stoppingTime f lam T hT).aestronglyMeasurable + (Real.exp (|lam| * (K : ℝ)) * + (‖(f : C₀(alpha, ℝ))‖ + (K : ℝ) * + ‖hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))‖)) + (Eventually.of_forall fun omega ↦ + (hFeller.norm_discountedDynkinProcess_le f lam (T omega) omega).trans + (mul_le_mul + (by apply Real.exp_le_exp.mpr + exact mul_le_mul_of_nonneg_left (NNReal.coe_le_coe.mpr (hTK omega)) + (abs_nonneg lam)) + (add_le_add (le_refl _) (mul_le_mul_of_nonneg_right + (NNReal.coe_le_coe.mpr (hTK omega)) (norm_nonneg _))) + (add_nonneg (norm_nonneg _) (mul_nonneg (T omega).coe_nonneg (norm_nonneg _))) + (Real.exp_pos _).le))) + change (∫ omega, _ ∂Q) - _ = ∫ omega, _ ∂Q + have hsplit : ∫ omega, hFeller.discountedDynkinProcess f lam (T omega) omega ∂Q = + (∫ omega, Real.exp (-lam * (T omega : ℝ)) * + (f : C₀(alpha, ℝ)) (omega (T omega)) ∂Q) - + ∫ omega, (∫ s in (0 : ℝ)..(T omega : ℝ), Real.exp (-lam * s) * + (hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))) + (omega (Real.toNNReal s))) ∂Q := by + simp only [IsFellerKernelSemigroup.discountedDynkinProcess_apply] + exact integral_sub hterminal hcorrection + linarith only [hstop, hsplit] + +end OptionalStopping + +end + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Dynkin.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Dynkin.lean new file mode 100644 index 0000000000..053e16c94f --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Dynkin.lean @@ -0,0 +1,164 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Main +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals +import Mathlib.MeasureTheory.Integral.Prod + +/-! +# Dynkin's formula at deterministic times + +For the continuous-path process `Q = continuousProcess P hP` of a conservative Feller semigroup +`P`, the `C₀` semigroup `hFeller.c0Semigroup` acts by `(S t f) x = E_x f(ω_t)` +(`c0Semigroup_apply_eq_integral`, from the one-time marginal `continuousProcess_map_eval_nnreal` +at every real time). Combining this with the fundamental identity of the generator +`S t f - f = ∫₀ᵗ S s (L f) ds` and Fubini's theorem gives **Dynkin's formula** +(`integral_eval_sub_eq_integral_integral_generator`): for `f` in the generator domain, + + `E_x f(ω_t) - f x = E_x ∫₀ᵗ (L f)(ω_s) ds`. + +The evaluation functional `c0EvalCLM x : C₀(α, ℝ) →L[ℝ] ℝ` is the tool that moves the Bochner +integral in `C₀` to a pointwise integral; `evalC0CLM` is the same functional under its original +name, kept for consumers. +-/ + +open MeasureTheory ProbabilityTheory Filter +open scoped ENNReal NNReal ZeroAtInfty + +namespace MarkovProcess.SubMarkovKernelSemigroup + +section Eval + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- Evaluation at a point, as a continuous linear functional on `C₀(α, ℝ)`. -/ +noncomputable def evalC0CLM (x : alpha) : C₀(alpha, ℝ) →L[ℝ] ℝ := + LinearMap.mkContinuous + { toFun := fun f ↦ f x + map_add' := fun _ _ ↦ rfl + map_smul' := fun _ _ ↦ rfl } + 1 (fun f ↦ by + rw [one_mul, ← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + exact BoundedContinuousFunction.norm_coe_le_norm f.toBCF x) + +/-- Evaluation, unfolded. -/ +@[simp] +theorem evalC0CLM_apply (x : alpha) (f : C₀(alpha, ℝ)) : evalC0CLM x f = f x := rfl + +end Eval + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + [LocallyCompactSpace alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- One-time marginal at every real time: evaluating the continuous-path process at time `t` +gives the transition kernel of `P` at `t`. -/ +theorem IsFellerKernelSemigroup.continuousProcess_map_eval_nnreal + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) (t : NNReal) : + (IsConservative.continuousProcess P hP).map (fun omega ↦ omega t) = P t := + IsConservative.continuousPathTrajectory_map_eval_nnreal P hP hFeller _ hK t + +/-- The expectation of a `C₀` function of the position at time `t` is its integral against the +transition measure at time `t`. -/ +theorem IsFellerKernelSemigroup.integral_eval_continuousProcess + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) (t : NNReal) (x : alpha) + (f : C₀(alpha, ℝ)) : + ∫ omega, f (omega t) ∂(IsConservative.continuousProcess P hP x) = ∫ y, f y ∂(P t x) := by + have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ omega t) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) t + have h := integral_map (μ := IsConservative.continuousProcess P hP x) hmeas.aemeasurable + (f := fun y ↦ f y) f.continuous.aestronglyMeasurable + rw [← h, ← Kernel.map_apply _ hmeas, hFeller.continuousProcess_map_eval_nnreal P hP hK t] + +/-- A measurable real-valued observable evaluated at a deterministic time has the corresponding +transition-kernel integral. -/ +theorem IsFellerKernelSemigroup.integral_eval_continuousProcess_of_measurable + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (t : NNReal) (x : alpha) {f : alpha → ℝ} (hf : Measurable f) : + ∫ omega, f (omega t) ∂(IsConservative.continuousProcess P hP x) = + ∫ y, f y ∂(P t x) := by + have heval := ContinuousPath.measurable_coordinateProcess (alpha := alpha) t + calc + (∫ omega, f (omega t) ∂(IsConservative.continuousProcess P hP x)) = + ∫ y, f y ∂Measure.map (fun omega : ContinuousPath alpha ↦ omega t) + (IsConservative.continuousProcess P hP x) := + (integral_map heval.aemeasurable hf.stronglyMeasurable.aestronglyMeasurable).symm + _ = ∫ y, f y ∂(P t x) := by + change ∫ y, f y ∂Measure.map (ContinuousPath.coordinateProcess (alpha := alpha) t) + (IsConservative.continuousProcess P hP x) = _ + rw [← Kernel.map_apply _ heval] + exact congrArg (fun K : Kernel alpha alpha ↦ ∫ y, f y ∂K x) + (hFeller.continuousProcess_map_eval_nnreal P hP hK t) + +/-- The `C₀` semigroup of a Feller semigroup is the expectation semigroup of its continuous-path +process: `(S t f) x = E_x f(ω_t)`. -/ +theorem IsFellerKernelSemigroup.c0Semigroup_apply_eq_integral + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) (t : NNReal) (x : alpha) + (f : C₀(alpha, ℝ)) : + hFeller.c0Semigroup t f x = + ∫ omega, f (omega t) ∂(IsConservative.continuousProcess P hP x) := by + rw [IsFellerKernelSemigroup.c0Semigroup_apply_apply, kernelIntegral, + hFeller.integral_eval_continuousProcess P hP hK t x f] + +/-- **Dynkin's formula at a deterministic time.** For `f` in the generator domain of the `C₀` +semigroup of `P`, with generator `L f`, and every starting point `x`, + + `E_x f(ω_t) - f x = E_x ∫₀ᵗ (L f)(ω_s) ds`. -/ +theorem IsFellerKernelSemigroup.integral_eval_sub_eq_integral_integral_generator + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (t : NNReal) (x : alpha) : + ∫ omega, (f : C₀(alpha, ℝ)) (omega t) ∂(IsConservative.continuousProcess P hP x) - + (f : C₀(alpha, ℝ)) x = + ∫ omega, (∫ s in (0 : ℝ)..t, (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) + ∂(IsConservative.continuousProcess P hP x) := by + have hint : IntervalIntegrable + (fun s : ℝ ↦ hFeller.c0Semigroup (Real.toNNReal s) (hFeller.c0Semigroup.generator f)) + volume 0 t := + (hFeller.c0Semigroup.continuous_operator_toNNReal _).intervalIntegrable _ _ + have hstep : ∫ omega, (f : C₀(alpha, ℝ)) (omega t) ∂(IsConservative.continuousProcess P hP x) - + (f : C₀(alpha, ℝ)) x = + ∫ s in (0 : ℝ)..t, ∫ omega, (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) + ∂(IsConservative.continuousProcess P hP x) := by + calc ∫ omega, (f : C₀(alpha, ℝ)) (omega t) ∂(IsConservative.continuousProcess P hP x) - + (f : C₀(alpha, ℝ)) x + = c0EvalCLM x (hFeller.c0Semigroup t (f : C₀(alpha, ℝ)) - (f : C₀(alpha, ℝ))) := by + rw [map_sub, c0EvalCLM_apply, c0EvalCLM_apply, + hFeller.c0Semigroup_apply_eq_integral P hP hK t x] + _ = c0EvalCLM x (∫ s in (0 : ℝ)..t, + hFeller.c0Semigroup (Real.toNNReal s) (hFeller.c0Semigroup.generator f)) := by + rw [hFeller.c0Semigroup.operator_sub_eq_integral f t] + _ = ∫ s in (0 : ℝ)..t, + c0EvalCLM x (hFeller.c0Semigroup (Real.toNNReal s) (hFeller.c0Semigroup.generator f)) := + ((c0EvalCLM x).intervalIntegral_comp_comm hint).symm + _ = ∫ s in (0 : ℝ)..t, ∫ omega, (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) + ∂(IsConservative.continuousProcess P hP x) := by + refine intervalIntegral.integral_congr fun s _ ↦ ?_ + rw [c0EvalCLM_apply, hFeller.c0Semigroup_apply_eq_integral P hP hK] + rw [hstep] + have hcont : Continuous fun p : ℝ × ContinuousPath alpha ↦ + (hFeller.c0Semigroup.generator f) (p.2 (Real.toNNReal p.1)) := + (hFeller.c0Semigroup.generator f).continuous.comp + ((ContinuousEval.continuous_eval.comp continuous_swap).comp + (continuous_real_toNNReal.fst'.prodMk continuous_snd)) + have hbound : ∀ p : ℝ × ContinuousPath alpha, + ‖(hFeller.c0Semigroup.generator f) (p.2 (Real.toNNReal p.1))‖ ≤ + ‖hFeller.c0Semigroup.generator f‖ := fun p ↦ by + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + exact BoundedContinuousFunction.norm_coe_le_norm (hFeller.c0Semigroup.generator f).toBCF + (p.2 (Real.toNNReal p.1)) + have hprodint : Integrable + (Function.uncurry fun (s : ℝ) (omega : ContinuousPath alpha) ↦ + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) + ((volume.restrict (Set.Ioc (0 : ℝ) t)).prod (IsConservative.continuousProcess P hP x)) := + Integrable.of_bound hcont.aestronglyMeasurable _ (Eventually.of_forall hbound) + rw [intervalIntegral.integral_of_le t.coe_nonneg, integral_integral_swap hprodint] + refine integral_congr_ae (Eventually.of_forall fun omega ↦ ?_) + exact (intervalIntegral.integral_of_le t.coe_nonneg).symm + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinMartingale.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinMartingale.lean new file mode 100644 index 0000000000..a85b85ac78 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinMartingale.lean @@ -0,0 +1,376 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin +import Mathlib.Probability.Martingale.Basic + +/-! +# The Dynkin martingale + +For the continuous-path process `Q = continuousProcess P hP` of a conservative Feller semigroup +`P` and a function `f` in the generator domain of the `C₀` semigroup of `P`, with generator +`L f`, the **Dynkin process** + + `M t omega = f (omega t) - ∫₀ᵗ (L f) (omega s) ds` + +is a martingale for the canonical filtration under `Q x`, for every starting point `x` +(`IsFellerKernelSemigroup.martingale_dynkinProcess`). + +The route is the deterministic-time Dynkin identity +(`integral_eval_sub_eq_integral_integral_generator`), which says exactly that +`E_y M u = f y` for every time `u` and starting point `y` (`integral_dynkinProcess`), together +with the additive decomposition + + `M t omega = M s omega - f (omega s) + M (t - s) (shift s omega)` (`s ≤ t`) + +(`dynkinProcess_eq_add_shift`) and the simple Markov property in conditional-expectation form +(`continuousProcess_condExp_shift`): conditionally on the canonical filtration at time `s`, the +expectation of the last term is `f (omega s)`, which cancels the middle term. + +The auxiliary facts proved on the way are of independent use: the Dynkin process is bounded by +`‖f‖ + t ‖L f‖` on `[0, t]` (`norm_dynkinProcess_le`), it is adapted to the canonical filtration +(`adapted_dynkinProcess`), and it is continuous in time along every path +(`continuous_dynkinProcess`). Adaptedness of the time-integral term comes from progressive +measurability of the coordinate process together with measurability of Bochner integrals in a +parameter. + +The exponentially discounted extension is developed in `Trajectory/DiscountedDynkin.lean`; +its zero-discount process is identified with this one by `discountedDynkinProcess_zero`. +-/ + +open MeasureTheory ProbabilityTheory Filter +open scoped ENNReal NNReal ZeroAtInfty + +namespace MarkovProcess.SubMarkovKernelSemigroup + +noncomputable section + +section C0Bound + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- The `C₀` norm bounds the values of a `C₀` function. -/ +theorem norm_c0_apply_le (g : C₀(alpha, ℝ)) (y : alpha) : ‖g y‖ ≤ ‖g‖ := by + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + exact BoundedContinuousFunction.norm_coe_le_norm g.toBCF y + +end C0Bound + +variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [LocallyCompactSpace alpha] + +variable {P : SubMarkovKernelSemigroup alpha} + +section Definition + +/-- The **Dynkin process** of a function `f` in the generator domain: the position functional +`f (omega t)` corrected by the time integral `∫₀ᵗ (L f) (omega s) ds` of the generator along the +path. Under the continuous-path process of `P` this is a martingale +(`martingale_dynkinProcess`). -/ +def IsFellerKernelSemigroup.dynkinProcess (hFeller : P.IsFellerKernelSemigroup) + (f : hFeller.c0Semigroup.generatorDomain) (t : NNReal) (omega : ContinuousPath alpha) : ℝ := + (f : C₀(alpha, ℝ)) (omega t) - + ∫ s in (0 : ℝ)..t, (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) + +/-- The Dynkin process, written out. -/ +theorem IsFellerKernelSemigroup.dynkinProcess_apply (hFeller : P.IsFellerKernelSemigroup) + (f : hFeller.c0Semigroup.generatorDomain) (t : NNReal) (omega : ContinuousPath alpha) : + hFeller.dynkinProcess f t omega = + (f : C₀(alpha, ℝ)) (omega t) - + ∫ s in (0 : ℝ)..t, (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) := + rfl + +/-- The integrand of the Dynkin correction term is continuous in the time variable. -/ +private theorem continuous_generator_path (hFeller : P.IsFellerKernelSemigroup) + (f : hFeller.c0Semigroup.generatorDomain) (omega : ContinuousPath alpha) : + Continuous fun s : ℝ ↦ (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) := + (hFeller.c0Semigroup.generator f).continuous.comp + (omega.continuous.comp continuous_real_toNNReal) + +/-- **The Dynkin process is bounded on bounded time intervals**: at time `t` it is bounded by +`‖f‖ + t ‖L f‖`, uniformly in the path. -/ +theorem IsFellerKernelSemigroup.norm_dynkinProcess_le (hFeller : P.IsFellerKernelSemigroup) + (f : hFeller.c0Semigroup.generatorDomain) (t : NNReal) (omega : ContinuousPath alpha) : + ‖hFeller.dynkinProcess f t omega‖ ≤ + ‖(f : C₀(alpha, ℝ))‖ + (t : ℝ) * ‖hFeller.c0Semigroup.generator f‖ := by + have hint : ‖∫ s in (0 : ℝ)..t, + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))‖ ≤ + (t : ℝ) * ‖hFeller.c0Semigroup.generator f‖ := by + have h := intervalIntegral.norm_integral_le_of_norm_le_const + (a := (0 : ℝ)) (b := (t : ℝ)) (C := ‖hFeller.c0Semigroup.generator f‖) + (f := fun s : ℝ ↦ (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) + (fun s _ ↦ norm_c0_apply_le _ _) + rwa [sub_zero, abs_of_nonneg t.coe_nonneg, mul_comm] at h + rw [hFeller.dynkinProcess_apply] + exact (norm_sub_le _ _).trans (add_le_add (norm_c0_apply_le _ _) hint) + +/-- The Dynkin process is continuous in time along every path: the position term is continuous +because paths and `f` are, and the correction term is continuous because it is the integral of a +continuous integrand over `[0, t]`. -/ +theorem IsFellerKernelSemigroup.continuous_dynkinProcess (hFeller : P.IsFellerKernelSemigroup) + (f : hFeller.c0Semigroup.generatorDomain) (omega : ContinuousPath alpha) : + Continuous fun t : NNReal ↦ hFeller.dynkinProcess f t omega := by + have hcont := continuous_generator_path hFeller f omega + have hinteg : Continuous fun u : ℝ ↦ + ∫ s in (0 : ℝ)..u, (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) := by + rw [continuous_iff_continuousAt] + intro u + exact ((hcont.integral_hasStrictDerivAt 0 u).hasDerivAt).continuousAt + exact ((f : C₀(alpha, ℝ)).continuous.comp omega.continuous).sub + (hinteg.comp NNReal.continuous_coe) + +end Definition + +section Adapted + +variable [SecondCountableTopology alpha] + +/-- The coordinate at a time clamped to `[0, t]`, read jointly in the time and the path, is +strongly measurable for the product of the Borel structure of the time variable with the +canonical filtration at time `t`. This is progressive measurability of the coordinate process, +transported along the clamping map. -/ +private theorem stronglyMeasurable_generator_min (hFeller : P.IsFellerKernelSemigroup) + (f : hFeller.c0Semigroup.generatorDomain) (t : NNReal) : + StronglyMeasurable[(borel ℝ).prod (ContinuousPath.canonicalFiltration (alpha := alpha) t)] + (fun p : ℝ × ContinuousPath alpha ↦ + (hFeller.c0Semigroup.generator f) (p.2 (min (Real.toNNReal p.1) t))) := by + exact (hFeller.c0Semigroup.generator f).continuous.comp_stronglyMeasurable + (ContinuousPath.measurable_clampedCoordinate (alpha := alpha) t).stronglyMeasurable + +/-- Measurability of a Bochner integral in a parameter, with the parameter sigma-algebra given by +a variable so that it can be instantiated at a filtration. -/ +theorem stronglyMeasurable_integral_prod {Omega : Type*} {mOmega : MeasurableSpace Omega} + (mu : Measure ℝ) [SFinite mu] {phi : ℝ × Omega → ℝ} + (hphi : StronglyMeasurable[(borel ℝ).prod mOmega] phi) : + StronglyMeasurable[mOmega] fun omega : Omega ↦ ∫ s, phi (s, omega) ∂mu := + hphi.integral_prod_left' + +/-- The Dynkin correction term at time `t` is strongly measurable for the canonical filtration at +time `t`: it is a Bochner integral over `[0, t]` of a jointly measurable integrand. -/ +theorem IsFellerKernelSemigroup.stronglyMeasurable_integral_generator + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) (t : NNReal) : + StronglyMeasurable[ContinuousPath.canonicalFiltration (alpha := alpha) t] + (fun omega : ContinuousPath alpha ↦ + ∫ s in (0 : ℝ)..t, (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) := by + have hprod := stronglyMeasurable_integral_prod (volume.restrict (Set.Ioc (0 : ℝ) t)) + (stronglyMeasurable_generator_min hFeller f t) + have hfun : (fun omega : ContinuousPath alpha ↦ + ∫ s in (0 : ℝ)..t, (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) = + fun omega : ContinuousPath alpha ↦ + ∫ s, (hFeller.c0Semigroup.generator f) (omega (min (Real.toNNReal s) t)) + ∂(volume.restrict (Set.Ioc (0 : ℝ) t)) := by + funext omega + rw [intervalIntegral.integral_of_le t.coe_nonneg] + refine setIntegral_congr_fun measurableSet_Ioc fun s hs ↦ ?_ + rw [min_eq_left (Real.toNNReal_le_iff_le_coe.mpr hs.2)] + rw [hfun] + exact hprod + +/-- The Dynkin process at time `t` is strongly measurable for the canonical filtration at time +`t`. -/ +theorem IsFellerKernelSemigroup.stronglyMeasurable_dynkinProcess_canonicalFiltration + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) (t : NNReal) : + StronglyMeasurable[ContinuousPath.canonicalFiltration (alpha := alpha) t] + (hFeller.dynkinProcess f t) := + ((f : C₀(alpha, ℝ)).continuous.comp_stronglyMeasurable + (ContinuousPath.measurable_coordinateProcess_canonicalFiltration + (alpha := alpha) t).stronglyMeasurable).sub + (hFeller.stronglyMeasurable_integral_generator f t) + +/-- The Dynkin process at time `t` is Borel measurable on path space. -/ +theorem IsFellerKernelSemigroup.stronglyMeasurable_dynkinProcess + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) (t : NNReal) : + StronglyMeasurable (hFeller.dynkinProcess f t) := + (hFeller.stronglyMeasurable_dynkinProcess_canonicalFiltration f t).mono + ((ContinuousPath.canonicalFiltration (alpha := alpha)).le t) + +/-- **The Dynkin process is adapted** to the canonical filtration. -/ +theorem IsFellerKernelSemigroup.adapted_dynkinProcess (hFeller : P.IsFellerKernelSemigroup) + (f : hFeller.c0Semigroup.generatorDomain) : + StronglyAdapted (ContinuousPath.canonicalFiltration (alpha := alpha)) + (hFeller.dynkinProcess f) := + fun t ↦ hFeller.stronglyMeasurable_dynkinProcess_canonicalFiltration f t + +end Adapted + +section Decomposition + +/-- **Additive decomposition of the Dynkin process at an intermediate time.** For `s ≤ t` the +Dynkin process at time `t` is the Dynkin process at time `s`, corrected by the position at time +`s`, plus the Dynkin process at time `t - s` of the path shifted by `s`. -/ +theorem IsFellerKernelSemigroup.dynkinProcess_eq_add_shift (hFeller : P.IsFellerKernelSemigroup) + (f : hFeller.c0Semigroup.generatorDomain) (s t : NNReal) (hst : s ≤ t) + (omega : ContinuousPath alpha) : + hFeller.dynkinProcess f t omega = + hFeller.dynkinProcess f s omega - (f : C₀(alpha, ℝ)) (omega s) + + hFeller.dynkinProcess f (t - s) (ContinuousPath.shift s omega) := by + have hcont := continuous_generator_path hFeller f omega + have hshift : (∫ u in (0 : ℝ)..((t - s : NNReal) : ℝ), + (hFeller.c0Semigroup.generator f) (omega (s + Real.toNNReal u))) = + ∫ v in (s : ℝ)..(t : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal v)) := by + have hcongr : (∫ u in (0 : ℝ)..((t - s : NNReal) : ℝ), + (hFeller.c0Semigroup.generator f) (omega (s + Real.toNNReal u))) = + ∫ u in (0 : ℝ)..((t - s : NNReal) : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal (u + s))) := by + refine intervalIntegral.integral_congr fun u hu ↦ ?_ + have hu0 : (0 : ℝ) ≤ u := by + rw [Set.uIcc_of_le (t - s : NNReal).coe_nonneg] at hu + exact hu.1 + have hcoe : Real.toNNReal (u + s) = s + Real.toNNReal u := by + apply NNReal.coe_injective + rw [NNReal.coe_add, Real.coe_toNNReal u hu0, + Real.coe_toNNReal _ (add_nonneg hu0 s.coe_nonneg)] + ring + rw [hcoe] + rw [hcongr, + intervalIntegral.integral_comp_add_right + (fun v : ℝ ↦ (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal v))) (s : ℝ), + zero_add] + congr 1 + rw [NNReal.coe_sub hst] + ring + have hsplit : (∫ v in (0 : ℝ)..(s : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal v))) + + (∫ v in (s : ℝ)..(t : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal v))) = + ∫ v in (0 : ℝ)..(t : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal v)) := + intervalIntegral.integral_add_adjacent_intervals (hcont.intervalIntegrable _ _) + (hcont.intervalIntegrable _ _) + simp only [IsFellerKernelSemigroup.dynkinProcess_apply, ContinuousPath.shift_apply, + add_tsub_cancel_of_le hst] + rw [hshift] + linarith only [hsplit] + +end Decomposition + +section Process + +variable [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] +variable (hP : P.IsConservative) + +section Expectation + +/-- Integrability of the Dynkin process under the continuous-path process: it is Borel measurable +and bounded, and the law of the process is a probability measure. -/ +theorem IsFellerKernelSemigroup.integrable_dynkinProcess (hFeller : P.IsFellerKernelSemigroup) + (f : hFeller.c0Semigroup.generatorDomain) (t : NNReal) (y : alpha) : + Integrable (hFeller.dynkinProcess f t) (IsConservative.continuousProcess P hP y) := + Integrable.of_bound (hFeller.stronglyMeasurable_dynkinProcess f t).aestronglyMeasurable _ + (Eventually.of_forall (hFeller.norm_dynkinProcess_le f t)) + +/-- **The expectation of the Dynkin process is the initial value**: `E_y M u = f y` for every +time `u`. This is Dynkin's formula at a deterministic time, rearranged. -/ +theorem IsFellerKernelSemigroup.integral_dynkinProcess (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) (f : hFeller.c0Semigroup.generatorDomain) (u : NNReal) + (y : alpha) : + ∫ omega, hFeller.dynkinProcess f u omega ∂(IsConservative.continuousProcess P hP y) = + (f : C₀(alpha, ℝ)) y := by + have hpos : Integrable (fun omega : ContinuousPath alpha ↦ (f : C₀(alpha, ℝ)) (omega u)) + (IsConservative.continuousProcess P hP y) := + Integrable.of_bound + (StronglyMeasurable.aestronglyMeasurable + ((f : C₀(alpha, ℝ)).continuous.comp_stronglyMeasurable + (ContinuousPath.measurable_coordinateProcess (alpha := alpha) u).stronglyMeasurable)) + ‖(f : C₀(alpha, ℝ))‖ (Eventually.of_forall fun omega ↦ norm_c0_apply_le _ _) + have hcorr : Integrable (fun omega : ContinuousPath alpha ↦ + ∫ s in (0 : ℝ)..u, (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) + (IsConservative.continuousProcess P hP y) := by + refine Integrable.of_bound + ((hFeller.stronglyMeasurable_integral_generator f u).mono + ((ContinuousPath.canonicalFiltration (alpha := alpha)).le u)).aestronglyMeasurable + ((u : ℝ) * ‖hFeller.c0Semigroup.generator f‖) (Eventually.of_forall fun omega ↦ ?_) + have h := intervalIntegral.norm_integral_le_of_norm_le_const + (a := (0 : ℝ)) (b := (u : ℝ)) (C := ‖hFeller.c0Semigroup.generator f‖) + (f := fun s : ℝ ↦ (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) + (fun s _ ↦ norm_c0_apply_le _ _) + rwa [sub_zero, abs_of_nonneg u.coe_nonneg, mul_comm] at h + have hdynkin := hFeller.integral_eval_sub_eq_integral_integral_generator P hP hK f u y + simp only [IsFellerKernelSemigroup.dynkinProcess_apply] + rw [integral_sub hpos hcorr] + linarith only [hdynkin] + +end Expectation + +section Martingale + +/-- **The Dynkin martingale.** For a conservative, Kolmogorov-regular Feller semigroup `P` and +`f` in the generator domain of its `C₀` semigroup, the Dynkin process + + `M t omega = f (omega t) - ∫₀ᵗ (L f) (omega s) ds` + +is a martingale for the canonical filtration under the continuous-path process of `P` started at +any point `x`. -/ +theorem IsFellerKernelSemigroup.martingale_dynkinProcess (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) (f : hFeller.c0Semigroup.generatorDomain) (x : alpha) : + Martingale (hFeller.dynkinProcess f) + (ContinuousPath.canonicalFiltration (alpha := alpha)) + (IsConservative.continuousProcess P hP x) := by + refine ⟨hFeller.adapted_dynkinProcess f, fun s t hst ↦ ?_⟩ + have hdecomp : hFeller.dynkinProcess f t = + (fun omega : ContinuousPath alpha ↦ + hFeller.dynkinProcess f s omega - (f : C₀(alpha, ℝ)) (omega s)) + + fun omega : ContinuousPath alpha ↦ + hFeller.dynkinProcess f (t - s) (ContinuousPath.shift s omega) := by + funext omega + exact hFeller.dynkinProcess_eq_add_shift f s t hst omega + have hmeasA : StronglyMeasurable[ContinuousPath.canonicalFiltration (alpha := alpha) s] + (fun omega : ContinuousPath alpha ↦ + hFeller.dynkinProcess f s omega - (f : C₀(alpha, ℝ)) (omega s)) := + (hFeller.stronglyMeasurable_dynkinProcess_canonicalFiltration f s).sub + ((f : C₀(alpha, ℝ)).continuous.comp_stronglyMeasurable + (ContinuousPath.measurable_coordinateProcess_canonicalFiltration + (alpha := alpha) s).stronglyMeasurable) + have hintA : Integrable (fun omega : ContinuousPath alpha ↦ + hFeller.dynkinProcess f s omega - (f : C₀(alpha, ℝ)) (omega s)) + (IsConservative.continuousProcess P hP x) := by + refine Integrable.of_bound + (hmeasA.mono + ((ContinuousPath.canonicalFiltration (alpha := alpha)).le s)).aestronglyMeasurable + (‖(f : C₀(alpha, ℝ))‖ + (s : ℝ) * ‖hFeller.c0Semigroup.generator f‖ + + ‖(f : C₀(alpha, ℝ))‖) (Eventually.of_forall fun omega ↦ ?_) + exact (norm_sub_le _ _).trans + (add_le_add (hFeller.norm_dynkinProcess_le f s omega) (norm_c0_apply_le _ _)) + have hmeasF : StronglyMeasurable (hFeller.dynkinProcess f (t - s)) := + hFeller.stronglyMeasurable_dynkinProcess f (t - s) + have hintB : Integrable (fun omega : ContinuousPath alpha ↦ + hFeller.dynkinProcess f (t - s) (ContinuousPath.shift s omega)) + (IsConservative.continuousProcess P hP x) := + Integrable.of_bound + (hmeasF.comp_measurable + (ContinuousPath.measurable_shift_fixed (alpha := alpha) s)).aestronglyMeasurable + _ (Eventually.of_forall fun omega ↦ + hFeller.norm_dynkinProcess_le f (t - s) (ContinuousPath.shift s omega)) + have hcondA := condExp_of_stronglyMeasurable + ((ContinuousPath.canonicalFiltration (alpha := alpha)).le s) hmeasA hintA + have hcondB := hFeller.continuousProcess_condExp_shift P hP hK x s + (hFeller.dynkinProcess f (t - s)) hmeasF + (‖(f : C₀(alpha, ℝ))‖ + ((t - s : NNReal) : ℝ) * ‖hFeller.c0Semigroup.generator f‖) + (hFeller.norm_dynkinProcess_le f (t - s)) + have hcondB' : (IsConservative.continuousProcess P hP x)[fun omega ↦ + hFeller.dynkinProcess f (t - s) (ContinuousPath.shift s omega)| + ContinuousPath.canonicalFiltration (alpha := alpha) s] =ᵐ[ + IsConservative.continuousProcess P hP x] + fun omega : ContinuousPath alpha ↦ (f : C₀(alpha, ℝ)) (omega s) := by + refine hcondB.trans (Eventually.of_forall fun omega ↦ ?_) + exact hFeller.integral_dynkinProcess hP hK f (t - s) (omega s) + rw [hdecomp] + refine (condExp_add hintA hintB _).trans ?_ + rw [hcondA] + refine (EventuallyEq.add (EventuallyEq.refl _ _) hcondB').trans + (Eventually.of_forall fun omega ↦ ?_) + show hFeller.dynkinProcess f s omega - (f : C₀(alpha, ℝ)) (omega s) + + (f : C₀(alpha, ℝ)) (omega s) = hFeller.dynkinProcess f s omega + ring + +end Martingale + +end Process + +end + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinStopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinStopping.lean new file mode 100644 index 0000000000..ec2282fb5c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinStopping.lean @@ -0,0 +1,290 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin + +/-! +# Dynkin's formula at a bounded stopping time, and the expected exit time + +The Dynkin process of `f` in the generator domain is a martingale for the canonical filtration +under the continuous-path process `Q = continuousProcess P hP` (`martingale_dynkinProcess`), it is +bounded on bounded time intervals, and it is continuous in time along every path. Optional +stopping (`MarkovProcess.integral_stoppedValue_eq_of_locallyBounded`) therefore applies at every +finite stopping time `T` bounded by a deterministic horizon, and gives **Dynkin's formula at a +bounded stopping time**: + + `E_x f(omega (T omega)) - f x = E_x ∫₀^{T omega} (L f)(omega s) ds` + +(`integral_eval_stoppingTime_sub_eq_integral_integral_generator`, with the equivalent compact form +`integral_dynkinProcess_stoppingTime`). + +The classical consequence is the **expected exit time bound**: if `L f ≤ -1` on an open set `U` +and `f` is bounded below by `m`, then the exit time from `U`, truncated at any horizon `K`, has +expectation at most `f x - m` from every starting point `x` +(`integral_exitTimeTrunc_le`). The proof uses that strictly before the exit time the path is +still inside `U`, so the integrand of Dynkin's formula is at most `-1` there. + +The truncation at `K` is what keeps the stopping time finite; the bound is uniform in `K`, and +`Trajectory/ExpectedExitTime.lean` removes the truncation by monotone convergence +(`lintegral_exitTime_le`, `ae_exitTime_lt_top`). + +The progressive-measurability and optional-stopping statements below are the zero-discount +specializations of the corresponding results in `Trajectory/DiscountedDynkin.lean`. +-/ + +open Filter MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal ZeroAtInfty + +namespace MarkovProcess.SubMarkovKernelSemigroup + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [LocallyCompactSpace alpha] + +variable {P : SubMarkovKernelSemigroup alpha} + +section ProgressiveMeasurability + +variable [SecondCountableTopology alpha] + +/-- The Dynkin process is progressively measurable: it is adapted and continuous in time. -/ +theorem IsFellerKernelSemigroup.progMeasurable_dynkinProcess (hFeller : P.IsFellerKernelSemigroup) + (f : hFeller.c0Semigroup.generatorDomain) : + IsStronglyProgressive (ContinuousPath.canonicalFiltration (alpha := alpha)) + (hFeller.dynkinProcess f) := by + simpa only [hFeller.discountedDynkinProcess_zero f] using! + hFeller.progMeasurable_discountedDynkinProcess f 0 + +/-- The Dynkin process evaluated at a finite stopping time is Borel measurable. -/ +theorem IsFellerKernelSemigroup.measurable_dynkinProcess_stoppingTime + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) : + Measurable fun omega ↦ hFeller.dynkinProcess f (T omega) omega := by + simpa only [hFeller.discountedDynkinProcess_zero f] using + hFeller.measurable_discountedDynkinProcess_stoppingTime f 0 T hT + +end ProgressiveMeasurability + +section Stopping + +variable [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (hP : P.IsConservative) + +/-- **Dynkin's formula at a bounded finite stopping time, in compact form**: the expectation of +the Dynkin process at a finite stopping time bounded by a deterministic horizon is the initial +value `f x`. This is optional stopping applied to the Dynkin martingale. -/ +theorem IsFellerKernelSemigroup.integral_dynkinProcess_stoppingTime + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + {K : NNReal} (hTK : ∀ omega, T omega ≤ K) (x : alpha) : + ∫ omega, hFeller.dynkinProcess f (T omega) omega + ∂(IsConservative.continuousProcess P hP x) = + (f : C₀(alpha, ℝ)) x := by + simpa only [hFeller.discountedDynkinProcess_zero f] using + hFeller.integral_discountedDynkinProcess_stoppingTime hP hK f 0 T hT hTK x + +/-- The position at a finite stopping time is integrable: it is Borel measurable and bounded by +the `C₀` norm of `f`. -/ +theorem IsFellerKernelSemigroup.integrable_eval_stoppingTime + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) (x : alpha) : + Integrable (fun omega : ContinuousPath alpha ↦ (f : C₀(alpha, ℝ)) (omega (T omega))) + (IsConservative.continuousProcess P hP x) := by + refine Integrable.of_bound + (((f : C₀(alpha, ℝ)).continuous.measurable.comp + (ContinuousPath.measurable_eval_stoppingTime_borel T hT)).aestronglyMeasurable) + ‖(f : C₀(alpha, ℝ))‖ (Eventually.of_forall fun omega ↦ ?_) + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + exact BoundedContinuousFunction.norm_coe_le_norm (f : C₀(alpha, ℝ)).toBCF _ + +/-- The Dynkin correction term at a finite stopping time bounded by `K` is integrable: it is +Borel measurable, being the difference of the position at the stopping time and the Dynkin +process there, and bounded by `K ‖L f‖`. -/ +theorem IsFellerKernelSemigroup.integrable_integral_generator_stoppingTime + (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) + (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + {K : NNReal} (hTK : ∀ omega, T omega ≤ K) (x : alpha) : + Integrable (fun omega : ContinuousPath alpha ↦ ∫ s in (0 : ℝ)..(T omega : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) + (IsConservative.continuousProcess P hP x) := by + have hdiff : (fun omega : ContinuousPath alpha ↦ ∫ s in (0 : ℝ)..(T omega : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) = + fun omega : ContinuousPath alpha ↦ + (f : C₀(alpha, ℝ)) (omega (T omega)) - hFeller.dynkinProcess f (T omega) omega := by + funext omega + rw [hFeller.dynkinProcess_apply] + ring + have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ ∫ s in (0 : ℝ)..(T omega : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) := by + rw [hdiff] + exact ((f : C₀(alpha, ℝ)).continuous.measurable.comp + (ContinuousPath.measurable_eval_stoppingTime_borel T hT)).sub + (hFeller.measurable_dynkinProcess_stoppingTime f T hT) + refine Integrable.of_bound hmeas.aestronglyMeasurable + ((K : ℝ) * ‖hFeller.c0Semigroup.generator f‖) (Eventually.of_forall fun omega ↦ ?_) + have hb := intervalIntegral.norm_integral_le_of_norm_le_const + (a := (0 : ℝ)) (b := ((T omega : NNReal) : ℝ)) (C := ‖hFeller.c0Semigroup.generator f‖) + (f := fun s : ℝ ↦ (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) + (fun s _ ↦ by + rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] + exact BoundedContinuousFunction.norm_coe_le_norm + (hFeller.c0Semigroup.generator f).toBCF _) + rw [sub_zero, abs_of_nonneg (T omega).coe_nonneg, mul_comm] at hb + refine hb.trans (mul_le_mul_of_nonneg_right (NNReal.coe_le_coe.mpr (hTK omega)) + (norm_nonneg (hFeller.c0Semigroup.generator f))) + +/-- **Dynkin's formula at a bounded finite stopping time.** For `f` in the generator domain and +a finite stopping time `T` bounded by a deterministic horizon `K`, + + `E_x f(omega (T omega)) - f x = E_x ∫₀^{T omega} (L f)(omega s) ds`. -/ +theorem IsFellerKernelSemigroup.integral_eval_stoppingTime_sub_eq_integral_integral_generator + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + {K : NNReal} (hTK : ∀ omega, T omega ≤ K) (x : alpha) : + ∫ omega, (f : C₀(alpha, ℝ)) (omega (T omega)) + ∂(IsConservative.continuousProcess P hP x) - (f : C₀(alpha, ℝ)) x = + ∫ omega, (∫ s in (0 : ℝ)..(T omega : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) + ∂(IsConservative.continuousProcess P hP x) := by + have hstop := hFeller.integral_dynkinProcess_stoppingTime hP hK f T hT hTK x + have hsplit : ∫ omega, hFeller.dynkinProcess f (T omega) omega + ∂(IsConservative.continuousProcess P hP x) = + (∫ omega, (f : C₀(alpha, ℝ)) (omega (T omega)) + ∂(IsConservative.continuousProcess P hP x)) - + ∫ omega, (∫ s in (0 : ℝ)..(T omega : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) + ∂(IsConservative.continuousProcess P hP x) := by + simp only [IsFellerKernelSemigroup.dynkinProcess_apply] + exact integral_sub (hFeller.integrable_eval_stoppingTime hP f T hT x) + (hFeller.integrable_integral_generator_stoppingTime hP f T hT hTK x) + linarith only [hstop, hsplit] + +end Stopping + +section ExitTime + +variable [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (hP : P.IsConservative) + +omit [MeasurableSpace alpha] [BorelSpace alpha] [LocallyCompactSpace alpha] [CompleteSpace alpha] + [SecondCountableTopology alpha] [Nonempty alpha] in +/-- Strictly before the truncated exit time, the path is still inside the open set `U`. -/ +private theorem mem_of_lt_exitTimeTrunc (U : Set alpha) (K : NNReal) + (omega : ContinuousPath alpha) (t : NNReal) (ht : t < ContinuousPath.exitTimeTrunc U K omega) : + omega t ∈ U := by + have hlt : ((t : NNReal) : ℝ≥0∞) < + ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ≥0∞) := ENNReal.coe_lt_coe.mpr ht + have hle : ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ≥0∞) ≤ + ContinuousPath.exitTime U omega := by + have h : ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : WithTop NNReal) ≤ + ContinuousPath.exitTimeTop U omega := by + rw [ContinuousPath.coe_exitTimeTrunc] + exact min_le_left _ _ + exact h + exact ContinuousPath.mem_of_lt_exitTime U omega t (hlt.trans_le hle) + +omit [LocallyCompactSpace alpha] in +/-- The truncated exit time is integrable: it is Borel measurable and bounded by its horizon. -/ +private theorem integrable_exitTimeTrunc (U : Set alpha) (hU : IsOpen U) (K : NNReal) + (x : alpha) : + Integrable (fun omega : ContinuousPath alpha ↦ + ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ)) + (IsConservative.continuousProcess P hP x) := by + have hmeas : Measurable (ContinuousPath.exitTimeTrunc U K : ContinuousPath alpha → NNReal) := + ContinuousPath.measurable_of_isStoppingTime _ + (ContinuousPath.isStoppingTime_exitTimeTrunc U hU K) + refine Integrable.of_bound (NNReal.continuous_coe.measurable.comp hmeas).aestronglyMeasurable + (K : ℝ) (Eventually.of_forall fun omega ↦ ?_) + rw [Real.norm_eq_abs, abs_of_nonneg (ContinuousPath.exitTimeTrunc U K omega).coe_nonneg] + exact NNReal.coe_le_coe.mpr (ContinuousPath.exitTimeTrunc_le U K omega) + +omit [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] in +/-- Along a path, the Dynkin integrand is at most `-1` almost everywhere on `[0, T]`, where `T` +is the truncated exit time: strictly before `T` the path is inside `U`, and the endpoint is a +null set. -/ +private theorem integral_generator_exitTimeTrunc_le (hFeller : P.IsFellerKernelSemigroup) + (f : hFeller.c0Semigroup.generatorDomain) (U : Set alpha) + (hLf : ∀ y ∈ U, (hFeller.c0Semigroup.generator f) y ≤ -1) (K : NNReal) + (omega : ContinuousPath alpha) : + (∫ s in (0 : ℝ)..((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) ≤ + -((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ) := by + have hb0 : (0 : ℝ) ≤ ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ) := + (ContinuousPath.exitTimeTrunc U K omega).coe_nonneg + have hcont : Continuous fun s : ℝ ↦ + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) := + (hFeller.c0Semigroup.generator f).continuous.comp + (omega.continuous.comp continuous_real_toNNReal) + have hsingleton : ∀ᵐ s : ℝ ∂(volume : Measure ℝ), + s ≠ ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ) := by + rw [ae_iff] + simpa only [Ne, not_not, Set.ofPred_eq_eq_singleton] using + measure_singleton ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ) + have hae : ∀ᵐ s : ℝ ∂(volume.restrict + (Set.Icc (0 : ℝ) ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ))), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) ≤ -1 := by + rw [ae_restrict_iff' measurableSet_Icc] + filter_upwards [hsingleton] with s hs hsmem + refine hLf _ (mem_of_lt_exitTimeTrunc U K omega (Real.toNNReal s) ?_) + exact (Real.toNNReal_lt_iff_lt_coe hsmem.1).mpr (lt_of_le_of_ne hsmem.2 hs) + have hmono := intervalIntegral.integral_mono_ae_restrict hb0 + (hcont.intervalIntegrable _ _) (intervalIntegrable_const (c := (-1 : ℝ))) hae + rw [intervalIntegral.integral_const, sub_zero, smul_eq_mul] at hmono + linarith only [hmono] + +/-- **The expected exit time bound.** If `f` lies in the generator domain, `L f ≤ -1` on the +open set `U`, and `m` is a lower bound for `f`, then the exit time from `U` truncated at any +horizon `K` has expectation at most `f x - m` under the process started at `x`. The bound does +not depend on the horizon `K`. -/ +theorem IsFellerKernelSemigroup.integral_exitTimeTrunc_le + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (U : Set alpha) (hU : IsOpen U) + (hLf : ∀ y ∈ U, (hFeller.c0Semigroup.generator f) y ≤ -1) + {m : ℝ} (hm : ∀ y, m ≤ (f : C₀(alpha, ℝ)) y) (K : NNReal) (x : alpha) : + ∫ omega, ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ) + ∂(IsConservative.continuousProcess P hP x) ≤ (f : C₀(alpha, ℝ)) x - m := by + have hT := ContinuousPath.isStoppingTime_exitTimeTrunc U hU K + have hTK := ContinuousPath.exitTimeTrunc_le U K + have hdynkin := hFeller.integral_eval_stoppingTime_sub_eq_integral_integral_generator hP hK f + (ContinuousPath.exitTimeTrunc U K) hT hTK x + have hlow : m ≤ ∫ omega, (f : C₀(alpha, ℝ)) (omega (ContinuousPath.exitTimeTrunc U K omega)) + ∂(IsConservative.continuousProcess P hP x) := by + have hconst : ∫ _omega : ContinuousPath alpha, m + ∂(IsConservative.continuousProcess P hP x) = m := by + rw [integral_const, probReal_univ, smul_eq_mul, one_mul] + rw [← hconst] + exact integral_mono (integrable_const m) + (hFeller.integrable_eval_stoppingTime hP f _ hT x) fun omega ↦ hm _ + have hupper : (∫ omega, (∫ s in (0 : ℝ)..((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) + ∂(IsConservative.continuousProcess P hP x)) ≤ + ∫ omega, -((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ) + ∂(IsConservative.continuousProcess P hP x) := + integral_mono (hFeller.integrable_integral_generator_stoppingTime hP f _ hT hTK x) + (integrable_exitTimeTrunc hP U hU K x).neg + fun omega ↦ integral_generator_exitTimeTrunc_le hFeller f U hLf K omega + rw [integral_neg] at hupper + linarith only [hdynkin, hlow, hupper] + +end ExitTime + +end + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean new file mode 100644 index 0000000000..ae91c96fd6 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean @@ -0,0 +1,296 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance +import LeanPool.MarkovProcess.MarkovProcess.Main + +/-! +# Equivariance of the continuous-path process + +Let `P` be a conservative Feller sub-Markov kernel semigroup on `alpha` with a Kolmogorov-regular +continuous-path process, let `e : alpha ≃ₜ beta` be a homeomorphism onto a second state space and +`c > 0` a time factor, and let `P'` be the rescaled conjugate of `P` on `beta`, that is +`P' t x = ((P (c * t)) (e.symm x)).map e`. Then the continuous-path process of `P'` is the +continuous-path process of `P` started at `e.symm x` and pushed forward by the path map +`omega ↦ fun t ↦ e (omega (c * t))`. + +The proof goes through the uniqueness theorem of `MarkovProcess/Main.lean`: the pushed-forward +kernel is a Markov kernel whose finite-dimensional distributions are computed from the Feller +marginal theorem for `P` at the rescaled times together with the finite-dimensional transfer +`SubMarkovKernelSemigroup.IsRescaledConjugate.finiteSetKernel_eq`. + +Main results: `ContinuousPath.rescale` and its continuity and measurability; +`SubMarkovKernelSemigroup.IsFellerKernelSemigroup.continuousProcess_map_finiteEvaluation_ordered`, +the marginal of the continuous-path process at an arbitrary strictly increasing finite family of +times; `SubMarkovKernelSemigroup.IsConservative.continuousProcess_eq_map_rescale` and its +pointwise form `continuousProcess_apply_rescale`; the intrinsic form +`continuousProcess_eq_map_rescale_of_hasKolmogorovMoments`, whose only regularity hypothesis is a +Kolmogorov moment bound on `P` when `e` is an isometry; and the two degenerate corollaries, pure +time rescaling (`continuousProcess_eq_map_timeRescale`) and pure conjugation +(`continuousProcess_eq_map_conjugate`). + +No scaling limit is asserted: `c` is a fixed positive factor and both semigroups are given in +advance. The two state spaces may coincide; the degenerate corollaries are stated on one space. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess + +namespace ContinuousPath + +section Rescale + +variable {alpha beta gamma : Type*} [TopologicalSpace alpha] [TopologicalSpace beta] + [TopologicalSpace gamma] + +/-- Multiplication of nonnegative time by a fixed factor, as a continuous self-map of `NNReal`. -/ +def timeScaling (c : NNReal) : C(NNReal, NNReal) where + toFun t := c * t + continuous_toFun := continuous_const.mul continuous_id + +/-- Time scaling, evaluated. -/ +@[simp] +theorem timeScaling_apply (c t : NNReal) : timeScaling c t = c * t := rfl + +/-- Speed a continuous path up by the factor `c` and conjugate its state by the homeomorphism +`e`. -/ +def rescale (e : alpha ≃ₜ beta) (c : NNReal) (omega : ContinuousPath alpha) : + ContinuousPath beta := + (e : C(alpha, beta)).comp (omega.comp (timeScaling c)) + +/-- The rescaled path, evaluated: `e` applied to the path at the sped-up time. -/ +@[simp] +theorem rescale_apply (e : alpha ≃ₜ beta) (c : NNReal) (omega : ContinuousPath alpha) + (t : NNReal) : rescale e c omega t = e (omega (c * t)) := + rfl + +/-- Rescaling by the identity homeomorphism and the factor one is the identity. -/ +@[simp] +theorem rescale_refl_one (omega : ContinuousPath alpha) : + rescale (Homeomorph.refl alpha) 1 omega = omega := by + ext t + simp only [rescale_apply, Homeomorph.refl_apply, id_eq, one_mul] + +/-- Rescaling by the identity homeomorphism speeds the path up without touching the state. -/ +@[simp] +theorem rescale_refl_apply (c : NNReal) (omega : ContinuousPath alpha) (t : NNReal) : + rescale (Homeomorph.refl alpha) c omega t = omega (c * t) := + rfl + +/-- Rescaling by the time factor one conjugates the state without touching the time. -/ +@[simp] +theorem rescale_one_apply (e : alpha ≃ₜ beta) (omega : ContinuousPath alpha) (t : NNReal) : + rescale e 1 omega t = e (omega t) := by + simp only [rescale_apply, one_mul] + +/-- Rescaling is jointly functorial in the homeomorphism and the time factor. -/ +theorem rescale_rescale (e : beta ≃ₜ gamma) (d : alpha ≃ₜ beta) (c b : NNReal) + (omega : ContinuousPath alpha) : + rescale e c (rescale d b omega) = rescale (d.trans e) (b * c) omega := by + ext t + simp only [rescale_apply, Homeomorph.trans_apply, mul_assoc] + +/-- Rescaling is continuous for the compact-open topology. -/ +theorem continuous_rescale (e : alpha ≃ₜ beta) (c : NNReal) : + Continuous (rescale e c : ContinuousPath alpha → ContinuousPath beta) := + (ContinuousMap.continuous_postcomp (e : C(alpha, beta))).comp + (ContinuousMap.continuous_precomp (timeScaling c)) + +/-- Rescaling is Borel measurable on continuous-path space. -/ +theorem measurable_rescale (e : alpha ≃ₜ beta) (c : NNReal) : + Measurable (rescale e c : ContinuousPath alpha → ContinuousPath beta) := + (continuous_rescale e c).measurable + +/-- Reading a rescaled path at a finite set of times reads the original path at the sped-up +times and conjugates the states. -/ +theorem finsetEvaluation_rescale (e : alpha ≃ₜ beta) (c : NNReal) (I : Finset NNReal) + (omega : ContinuousPath alpha) : + finsetEvaluation I (rescale e c omega) = fun t : I ↦ e (omega (c * (t : NNReal))) := + rfl + +end Rescale + +end ContinuousPath + +namespace SubMarkovKernelSemigroup + +noncomputable section + +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [Nonempty alpha] [LocallyCompactSpace alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- **Marginals at arbitrary ordered times.** The law of the continuous-path process of a +conservative Feller semigroup, read at a strictly increasing finite family of nonnegative times, +is the finite-time kernel of `P` at those times. This is the finite-set marginal theorem of +`MarkovProcess/Main.lean` transported to an arbitrary strictly increasing indexing. -/ +theorem IsFellerKernelSemigroup.continuousProcess_map_finiteEvaluation_ordered + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) {n : ℕ} + (times : FiniteOrderedTimes n) : + (continuousProcess P hP).map (ContinuousPath.finiteEvaluation (fun i ↦ times i)) = + finiteTimeKernel P times := by + classical + have hmem : ∀ i : Fin n, + times i ∈ Finset.image (fun j ↦ times j) (Finset.univ : Finset (Fin n)) := + fun i ↦ Finset.mem_image_of_mem _ (Finset.mem_univ i) + let I : Finset NNReal := Finset.image (fun j ↦ times j) (Finset.univ : Finset (Fin n)) + let phi : Fin n ↪o I := + OrderEmbedding.ofStrictMono (fun i ↦ (⟨times i, hmem i⟩ : I)) + (fun _ _ hij ↦ times.strictMono hij) + let emb : Fin n ↪o Fin I.card := phi.trans (I.orderIsoOfFin rfl).symm.toOrderEmbedding + have hphi : ∀ i : Fin n, ((phi i : I) : NNReal) = times i := fun _ ↦ rfl + have hsel : Measurable (fun w : I → alpha ↦ w ∘ (phi : Fin n → I)) := + measurable_pi_iff.mpr fun i ↦ measurable_pi_apply (phi i) + have hfinset : Measurable (ContinuousPath.finsetEvaluation (alpha := alpha) I) := + ContinuousPath.measurable_finiteEvaluation _ + have hcomp : ContinuousPath.finiteEvaluation (α := alpha) (fun i ↦ times i) = + (fun w : I → alpha ↦ w ∘ (phi : Fin n → I)) ∘ + ContinuousPath.finsetEvaluation (alpha := alpha) I := rfl + have hrestrict : (fun w : I → alpha ↦ w ∘ (phi : Fin n → I)) ∘ + orderedPathToFiniteSet (α := alpha) I = FiniteOrderedTimes.restrictPath emb := rfl + have htimes : (finiteSetTimes I).restrict emb = times := by + apply DFunLike.ext _ _ + intro i + show finiteSetTimes I ((I.orderIsoOfFin rfl).symm (phi i)) = times i + rw [finiteSetTimes_orderIsoOfFin_symm_apply, hphi i] + rw [hcomp, Kernel.map_comp_right _ hfinset hsel, + hFeller.continuousProcess_map_finiteEvaluation P hP hK I, finiteSetKernel_eq_map, + ← Kernel.map_comp_right _ (measurable_orderedPathToFiniteSet I) hsel, hrestrict, + hP.finiteTimeKernel_map_restrictPath P (finiteSetTimes I) emb, htimes] + +section TwoSpaces + +variable {beta : Type*} [MetricSpace beta] [CompleteSpace beta] + [MeasurableSpace beta] [BorelSpace beta] [SecondCountableTopology beta] [Nonempty beta] + +variable (P' : SubMarkovKernelSemigroup beta) (hP' : P'.IsConservative) + +/-- **Equivariance of the continuous-path process.** If `P'` is the rescaled conjugate of a +conservative Feller semigroup `P` by the homeomorphism `e` and the positive time factor `c`, then +the continuous-path process of `P'` is the continuous-path process of `P`, started at the +`e`-preimage of the initial state and pushed forward by the path map `ContinuousPath.rescale e c`. + +The Feller hypothesis is needed only for `P`, because only the marginals of `P` at arbitrary real +times are used; `P'` enters through its Kolmogorov regularity alone. -/ +theorem IsConservative.continuousProcess_eq_map_rescale + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (hK' : P'.KolmogorovRegular hP') {e : alpha ≃ₜ beta} {c : NNReal} (hc : 0 < c) + (h : IsRescaledConjugate P P' e c) : + continuousProcess P' hP' = + (Kernel.comap (continuousProcess P hP) e.symm e.symm.measurable).map + (ContinuousPath.rescale e c) := by + classical + let : IsMarkovKernel + ((Kernel.comap (continuousProcess P hP) e.symm e.symm.measurable).map + (ContinuousPath.rescale e c)) := + Kernel.IsMarkovKernel.map _ (ContinuousPath.measurable_rescale e c) + refine (IsConservative.eq_continuousProcess_of_map_finiteEvaluation P' hP' hK' _ ?_).symm + intro I + have hmapPath : Measurable + ((FiniteOrderedTimes.mapPath e : (I → alpha) → I → beta) ∘ + orderedPathToFiniteSet (α := alpha) I) := + (FiniteOrderedTimes.measurable_mapPath e.measurable).comp + (measurable_orderedPathToFiniteSet I) + have hfinite : Measurable (ContinuousPath.finiteEvaluation (α := alpha) + (fun i ↦ ((finiteSetTimes I).rescale c hc) i)) := + ContinuousPath.measurable_finiteEvaluation _ + have hcomp : ContinuousPath.finsetEvaluation (alpha := beta) I ∘ + ContinuousPath.rescale e c = + ((FiniteOrderedTimes.mapPath e : (I → alpha) → I → beta) ∘ + orderedPathToFiniteSet (α := alpha) I) ∘ + ContinuousPath.finiteEvaluation (α := alpha) + (fun i ↦ ((finiteSetTimes I).rescale c hc) i) := by + funext omega t + show e (omega (c * (t : NNReal))) = + e (omega (c * finiteSetTimes I ((I.orderIsoOfFin rfl).symm t))) + rw [finiteSetTimes_orderIsoOfFin_symm_apply] + rw [← Kernel.map_comp_right _ (ContinuousPath.measurable_rescale e c) + (ContinuousPath.measurable_finiteEvaluation (fun t : I ↦ (t : NNReal))), hcomp, + Kernel.map_comp_right _ hfinite hmapPath, + ← Kernel.comap_map_comm _ e.symm.measurable hfinite, + IsFellerKernelSemigroup.continuousProcess_map_finiteEvaluation_ordered P hP hFeller hK + ((finiteSetTimes I).rescale c hc), + IsRescaledConjugate.finiteSetKernel_eq h hc hP I] + +/-- The equivariance identity at a fixed starting state: the law of the process of `P'` started at +`x` is the law of the process of `P` started at `e.symm x`, pushed forward by the rescaling map. -/ +theorem IsConservative.continuousProcess_apply_rescale + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (hK' : P'.KolmogorovRegular hP') {e : alpha ≃ₜ beta} {c : NNReal} (hc : 0 < c) + (h : IsRescaledConjugate P P' e c) (x : beta) : + continuousProcess P' hP' x = + ((continuousProcess P hP) (e.symm x)).map (ContinuousPath.rescale e c) := by + rw [IsConservative.continuousProcess_eq_map_rescale P hP P' hP' hFeller hK hK' hc h, + Kernel.map_apply _ (ContinuousPath.measurable_rescale e c), Kernel.comap_apply] + +/-- **Intrinsic form of the equivariance theorem.** When the state map is an isometry, the +Kolmogorov moment criterion for `P` alone gives the regularity of both processes, by +`IsRescaledConjugate.hasKolmogorovMoments`; no hypothesis on `P'` beyond conservativity and the +intertwining is then needed. -/ +theorem IsConservative.continuousProcess_eq_map_rescale_of_hasKolmogorovMoments + (hFeller : P.IsFellerKernelSemigroup) {p q : ℝ} {M : ℝ≥0} + (hmom : P.HasKolmogorovMoments p q M) {e : alpha ≃ₜ beta} + (he : Isometry (e : alpha → beta)) {c : NNReal} (hc : 0 < c) + (h : IsRescaledConjugate P P' e c) : + continuousProcess P' hP' = + (Kernel.comap (continuousProcess P hP) e.symm e.symm.measurable).map + (ContinuousPath.rescale e c) := + IsConservative.continuousProcess_eq_map_rescale P hP P' hP' hFeller + (KolmogorovRegular.of_hasKolmogorovMoments P hP hmom) + (KolmogorovRegular.of_hasKolmogorovMoments P' hP' (h.hasKolmogorovMoments he hmom)) hc h + +end TwoSpaces + +section OneSpace + +variable (P' : SubMarkovKernelSemigroup alpha) (hP' : P'.IsConservative) + +/-- **Pure time rescaling.** If the transition kernels of `P'` are those of `P` at the sped-up +times, then the continuous-path process of `P'` is the continuous-path process of `P` pushed +forward by the time change `omega ↦ fun t ↦ omega (c * t)`. No state map is involved, so no +starting point has to be relabelled. -/ +theorem IsConservative.continuousProcess_eq_map_timeRescale + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (hK' : P'.KolmogorovRegular hP') {c : NNReal} (hc : 0 < c) + (htime : ∀ t, P' t = P (c * t)) : + continuousProcess P' hP' = + (continuousProcess P hP).map (ContinuousPath.rescale (Homeomorph.refl alpha) c) := by + have hid : (⇑(Homeomorph.refl alpha) : alpha → alpha) = id := rfl + have h : IsRescaledConjugate P P' (Homeomorph.refl alpha) c := by + intro t x + rw [htime t, hid, Measure.map_id] + rfl + have hcomap : Kernel.comap (continuousProcess P hP) + (⇑(Homeomorph.refl alpha).symm) (Homeomorph.refl alpha).symm.measurable = + continuousProcess P hP := Kernel.comap_id' _ + rw [IsConservative.continuousProcess_eq_map_rescale P hP P' hP' hFeller hK hK' hc h, hcomap] + +/-- **Pure conjugation.** If the transition kernels of `P'` are those of `P` conjugated by a +homeomorphism `e` of the state space, then the continuous-path process of `P'` is the process of +`P` started at `e.symm x` and read through `e` at every time. -/ +theorem IsConservative.continuousProcess_eq_map_conjugate + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (hK' : P'.KolmogorovRegular hP') {e : alpha ≃ₜ alpha} + (hconj : ∀ t x, P' t x = ((P t) (e.symm x)).map e) : + continuousProcess P' hP' = + (Kernel.comap (continuousProcess P hP) e.symm e.symm.measurable).map + (ContinuousPath.rescale e 1) := by + refine IsConservative.continuousProcess_eq_map_rescale P hP P' hP' hFeller hK hK' one_pos ?_ + intro t x + rw [hconj t x, one_mul] + +end OneSpace + +end + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExcessiveStopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExcessiveStopping.lean new file mode 100644 index 0000000000..da895d3bc4 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExcessiveStopping.lean @@ -0,0 +1,424 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime + +/-! +# Excessive functions and stopping + +This file turns the semigroup definition of an exponentially excessive `C₀` function into a +supermartingale along the canonical continuous process. Continuous-time optional stopping then +gives the corresponding inequality at bounded stopping times and, by Fatou's lemma, at the finite +exit time from an open set. + +The exit inequality is the lower-bound half paired with +`IsFellerKernelSemigroup.lintegral_pathResolvent_eq_killedResolvent_add`. No model-specific +assumptions enter here. + +Main results: `IsFellerKernelSemigroup.resolvent_isLambdaExcessive`, +`IsLambdaExcessive.supermartingale_discountedValueProcess`, +`IsLambdaExcessive.integral_discountedValueProcess_stoppingTime_le`, and +`IsLambdaExcessive.lintegral_discountedValue_exitTime_le`. + +No converse characterization of excessive functions is asserted. +-/ + +open Filter MeasureTheory ProbabilityTheory Set Topology +open scoped ENNReal NNReal ZeroAtInfty + +namespace MarkovProcess.SubMarkovKernelSemigroup + +noncomputable section + +section Supermedian + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + +variable {P : SubMarkovKernelSemigroup alpha} + +/-- A nonnegative `C₀` function is `lam`-supermedian when its discounted semigroup orbit lies +below the function. In the Feller setting used below, continuity of `C₀` orbits supplies the +zero-time limit in the usual definition of `lam`-excessiveness; see +`IsFellerKernelSemigroup.tendsto_exp_neg_mul_c0Semigroup_zero`. -/ +def IsLambdaExcessive (P : SubMarkovKernelSemigroup alpha) (lam : ℝ) (v : C₀(alpha, ℝ)) : Prop := + (∀ x, 0 ≤ v x) ∧ ∀ (t : NNReal) (x : alpha), + Real.exp (-lam * (t : ℝ)) * ∫ y, v y ∂(P t x) ≤ v x + +/-- A semigroup comparison `S(t)v ≤ exp(lam t)v` gives `lam`-excessiveness. -/ +theorem isLambdaExcessive_of_c0Semigroup_apply_le_exp_mul + (lam : ℝ) (v : C₀(alpha, ℝ)) + (hv : ∀ x, 0 ≤ v x) + (hcomp : ∀ (t : NNReal) (x : alpha), + kernelIntegral (P t) v x ≤ Real.exp (lam * (t : ℝ)) * v x) : + P.IsLambdaExcessive lam v := by + refine ⟨hv, fun t x ↦ ?_⟩ + calc + Real.exp (-lam * (t : ℝ)) * kernelIntegral (P t) v x + ≤ Real.exp (-lam * (t : ℝ)) * (Real.exp (lam * (t : ℝ)) * v x) := + mul_le_mul_of_nonneg_left (hcomp t x) (Real.exp_pos _).le + _ = v x := by rw [← mul_assoc, ← Real.exp_add]; ring_nf; simp only [Real.exp_zero, one_mul] + +end Supermedian + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [Nonempty alpha] [LocallyCompactSpace alpha] + +variable {P : SubMarkovKernelSemigroup alpha} + +omit [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] in +/-- For a Feller semigroup, every exponentially discounted `C₀` orbit converges in `C₀` norm to +its initial function at time zero. Thus `IsLambdaExcessive` includes the usual excessive +zero-time condition automatically. -/ +theorem IsFellerKernelSemigroup.tendsto_exp_neg_mul_c0Semigroup_zero + (hFeller : P.IsFellerKernelSemigroup) (lam : ℝ) (v : C₀(alpha, ℝ)) : + Tendsto (fun t : NNReal ↦ Real.exp (-lam * (t : ℝ)) • hFeller.c0Semigroup t v) + (𝓝 0) (𝓝 v) := by + have hcontinuous : Continuous fun t : NNReal ↦ + Real.exp (-lam * (t : ℝ)) • hFeller.c0Semigroup t v := + (Real.continuous_exp.comp (continuous_const.mul NNReal.continuous_coe)).smul + (hFeller.c0Semigroup.continuous v) + have hzero : Tendsto + (fun t : NNReal ↦ Real.exp (-lam * (t : ℝ)) • hFeller.c0Semigroup t v) + (𝓝 0) (𝓝 (Real.exp (-lam * ((0 : NNReal) : ℝ)) • hFeller.c0Semigroup 0 v)) := + hcontinuous.continuousAt + simpa only [NNReal.coe_zero, mul_zero, neg_zero, Real.exp_zero, one_smul, + Semigroup.StronglyContinuousContractionSemigroup.zero_apply] using hzero + +omit [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] in +/-- The resolvent of a nonnegative `C₀` function at a positive shift is excessive at that shift. -/ +theorem IsFellerKernelSemigroup.resolvent_isLambdaExcessive + (hFeller : P.IsFellerKernelSemigroup) (lam : ℝ) (hlam : 0 < lam) + (f : C₀(alpha, ℝ)) (hf : ∀ x, 0 ≤ f x) : + P.IsLambdaExcessive lam + (hFeller.c0Semigroup.resolvent (⟨lam, hlam⟩ : Semigroup.PositiveShift) f) := by + let mu : Semigroup.PositiveShift := ⟨lam, hlam⟩ + let S := hFeller.c0Semigroup + let v : C₀(alpha, ℝ) := S.resolvent mu f + have hv : ∀ x, 0 ≤ v x := by + intro x + dsimp only [v, S] + rw [hFeller.resolvent_apply_apply] + exact integral_nonneg fun t ↦ mul_nonneg (Real.exp_pos _).le (integral_nonneg hf) + change P.IsLambdaExcessive lam v + refine ⟨hv, fun t x ↦ ?_⟩ + change Real.exp (-lam * (t : ℝ)) * S t v x ≤ v x + let vdom : S.generatorDomain := ⟨v, by + dsimp only [v] + exact S.resolvent_mem_generatorDomain mu f⟩ + have hgen : S.generator vdom - lam • (vdom : C₀(alpha, ℝ)) = -f := by + have hgenerator : S.generator vdom = lam • v - f := by + dsimp only [vdom, v] + exact S.generator_resolvent mu f + rw [hgenerator] + change (lam • v - f) - lam • v = -f + module + have hidentity : Real.exp (-lam * (t : ℝ)) * S t v x - v x = + ∫ s in (0 : ℝ)..t, + Real.exp (-lam * s) * S (Real.toNNReal s) (-f) x := by + calc + Real.exp (-lam * (t : ℝ)) * S t v x - v x = + c0EvalCLM x (Real.exp (-lam * (t : ℝ)) • S t (vdom : C₀(alpha, ℝ)) - vdom) := by + rw [map_sub, map_smul, c0EvalCLM_apply, c0EvalCLM_apply, smul_eq_mul] + _ = c0EvalCLM x (∫ s in (0 : ℝ)..t, Real.exp (-lam * s) • + S (Real.toNNReal s) (S.generator vdom - lam • (vdom : C₀(alpha, ℝ)))) := by + rw [S.exp_smul_operator_sub_eq_integral vdom lam t] + _ = c0EvalCLM x (∫ s in (0 : ℝ)..t, + Real.exp (-lam * s) • S (Real.toNNReal s) (-f)) := by rw [hgen] + _ = ∫ s in (0 : ℝ)..t, + c0EvalCLM x (Real.exp (-lam * s) • S (Real.toNNReal s) (-f)) := by + rw [← (c0EvalCLM x).intervalIntegral_comp_comm] + exact ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).smul + (S.continuous_operator_toNNReal (-f))).intervalIntegrable _ _ + _ = ∫ s in (0 : ℝ)..t, + Real.exp (-lam * s) * S (Real.toNNReal s) (-f) x := by + refine intervalIntegral.integral_congr fun s _ ↦ ?_ + rw [map_smul, c0EvalCLM_apply, smul_eq_mul] + have hnonneg : 0 ≤ ∫ s in (0 : ℝ)..t, + Real.exp (-lam * s) * S (Real.toNNReal s) f x := by + refine intervalIntegral.integral_nonneg t.coe_nonneg fun s _ ↦ + mul_nonneg (Real.exp_pos _).le ?_ + change 0 ≤ P.c0Operator hFeller.mapsC0 (Real.toNNReal s) f x + exact P.c0Operator_apply_nonneg hFeller.mapsC0 _ hf x + have hneg : (∫ s in (0 : ℝ)..t, + Real.exp (-lam * s) * S (Real.toNNReal s) (-f) x) = + -(∫ s in (0 : ℝ)..t, Real.exp (-lam * s) * S (Real.toNNReal s) f x) := by + rw [← intervalIntegral.integral_neg] + refine intervalIntegral.integral_congr fun s _ ↦ ?_ + rw [map_neg] + change Real.exp (-lam * s) * (-S (Real.toNNReal s) f x) = + -(Real.exp (-lam * s) * S (Real.toNNReal s) f x) + ring + apply sub_nonpos.mp + rw [hidentity, hneg] + exact neg_nonpos.mpr hnonneg + +/-- The exponentially discounted value of `v` along a continuous path. -/ +def discountedValueProcess (lam : ℝ) (v : C₀(alpha, ℝ)) + (t : NNReal) (omega : ContinuousPath alpha) : ℝ := + Real.exp (-lam * (t : ℝ)) * v (omega t) + +omit [CompleteSpace alpha] [Nonempty alpha] [LocallyCompactSpace alpha] in +/-- The discounted value process is adapted to the canonical filtration. -/ +theorem adapted_discountedValueProcess (lam : ℝ) (v : C₀(alpha, ℝ)) : + StronglyAdapted (ContinuousPath.canonicalFiltration (alpha := alpha)) + (discountedValueProcess lam v) := by + intro t + exact ((v.continuous.comp_stronglyMeasurable + (ContinuousPath.measurable_coordinateProcess_canonicalFiltration + (alpha := alpha) t).stronglyMeasurable).const_mul _) + +omit [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [Nonempty alpha] [LocallyCompactSpace alpha] in +/-- The discounted value process is uniformly bounded in the path at each time. -/ +theorem norm_discountedValueProcess_le (lam : ℝ) (v : C₀(alpha, ℝ)) + (t : NNReal) (omega : ContinuousPath alpha) : + ‖discountedValueProcess lam v t omega‖ ≤ Real.exp (-lam * (t : ℝ)) * ‖v‖ := by + rw [discountedValueProcess, norm_mul, Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] + exact mul_le_mul_of_nonneg_left (norm_c0_apply_le v (omega t)) (Real.exp_pos _).le + +omit [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [Nonempty alpha] [LocallyCompactSpace alpha] in +/-- The discounted value process has continuous sample paths. -/ +theorem continuous_discountedValueProcess (lam : ℝ) (v : C₀(alpha, ℝ)) + (omega : ContinuousPath alpha) : + Continuous fun t : NNReal ↦ discountedValueProcess lam v t omega := + (Real.continuous_exp.comp (continuous_const.mul NNReal.continuous_coe)).mul + (v.continuous.comp omega.continuous) + +/-- **Excessive functions give supermartingales.** -/ +theorem IsLambdaExcessive.supermartingale_discountedValueProcess + (hP : P.IsConservative) (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) {lam : ℝ} {v : C₀(alpha, ℝ)} + (hv : P.IsLambdaExcessive lam v) (x : alpha) : + Supermartingale (discountedValueProcess lam v) + (ContinuousPath.canonicalFiltration (alpha := alpha)) + (IsConservative.continuousProcess P hP x) := by + refine ⟨adapted_discountedValueProcess lam v, ?_, ?_⟩ + · intro s t hst + let c : ℝ := Real.exp (-lam * (s : ℝ)) + let F : ContinuousPath alpha → ℝ := fun eta ↦ + Real.exp (-lam * ((t - s : NNReal) : ℝ)) * v (eta (t - s)) + have hdecomp : discountedValueProcess lam v t = + fun omega ↦ c * F (ContinuousPath.shift s omega) := by + funext omega + dsimp only [discountedValueProcess, c, F] + rw [ContinuousPath.shift_apply, add_tsub_cancel_of_le hst] + rw [← mul_assoc, ← Real.exp_add] + congr 2 + rw [NNReal.coe_sub hst] + ring + have hmeasF : StronglyMeasurable F := + (v.continuous.comp_stronglyMeasurable + (ContinuousPath.measurable_coordinateProcess (t - s)).stronglyMeasurable).const_mul _ + have hboundF : ∀ eta : ContinuousPath alpha, ‖F eta‖ ≤ + Real.exp (-lam * ((t - s : NNReal) : ℝ)) * ‖v‖ := fun eta ↦ by + exact norm_discountedValueProcess_le lam v (t - s) eta + have hcond := hFeller.continuousProcess_condExp_shift P hP hK x s F hmeasF _ hboundF + rw [hdecomp] + refine (condExp_smul c (fun omega ↦ F (ContinuousPath.shift s omega)) _).trans_le ?_ + refine (EventuallyEq.const_smul hcond c).trans_le (Eventually.of_forall fun omega ↦ ?_) + change c * (∫ eta, F eta ∂IsConservative.continuousProcess P hP (omega s)) ≤ + discountedValueProcess lam v s omega + have hinner : ∫ eta, F eta ∂IsConservative.continuousProcess P hP (omega s) ≤ + v (omega s) := by + dsimp only [F] + rw [MeasureTheory.integral_const_mul, + hFeller.integral_eval_continuousProcess P hP hK] + exact hv.2 (t - s) (omega s) + dsimp only [c, discountedValueProcess] + exact mul_le_mul_of_nonneg_left hinner (Real.exp_pos _).le + · intro t + exact Integrable.of_bound + ((adapted_discountedValueProcess lam v t).mono + ((ContinuousPath.canonicalFiltration (alpha := alpha)).le t)).aestronglyMeasurable + (Real.exp (-lam * (t : ℝ)) * ‖v‖) + (Eventually.of_forall (norm_discountedValueProcess_le lam v t)) + +/-- **Optional stopping for an excessive function.** At every bounded finite stopping time, the +expected discounted terminal value is at most its initial value. -/ +theorem IsLambdaExcessive.integral_discountedValueProcess_stoppingTime_le + (hP : P.IsConservative) (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) {lam : ℝ} {v : C₀(alpha, ℝ)} + (hv : P.IsLambdaExcessive lam v) (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + {K : NNReal} (hTK : ∀ omega, T omega ≤ K) (x : alpha) : + ∫ omega, Real.exp (-lam * (T omega : ℝ)) * v (omega (T omega)) + ∂(IsConservative.continuousProcess P hP x) ≤ v x := by + have hlocal : ∀ u : NNReal, ∃ C : ℝ, ∀ t ≤ u, ∀ omega : ContinuousPath alpha, + ‖discountedValueProcess lam v t omega‖ ≤ C := by + intro u + refine ⟨Real.exp (|lam| * (u : ℝ)) * ‖v‖, fun t htu omega ↦ ?_⟩ + refine (norm_discountedValueProcess_le lam v t omega).trans ?_ + exact mul_le_mul_of_nonneg_right (Real.exp_le_exp.mpr <| calc + -lam * (t : ℝ) ≤ |lam| * (t : ℝ) := + mul_le_mul_of_nonneg_right (neg_le_abs lam) t.coe_nonneg + _ ≤ |lam| * (u : ℝ) := + mul_le_mul_of_nonneg_left (NNReal.coe_le_coe.mpr htu) (abs_nonneg lam)) (norm_nonneg v) + have hstop := MarkovProcess.integral_stoppedValue_le_of_locallyBounded + (hv.supermartingale_discountedValueProcess hP hFeller hK x) hlocal + (fun omega u ↦ (continuous_discountedValueProcess lam v omega).continuousWithinAt) + hT hTK + have hzero : + ∫ omega, v (omega 0) ∂(IsConservative.continuousProcess P hP x) = v x := by + rw [← hFeller.c0Semigroup_apply_eq_integral P hP hK] + simp only [Semigroup.StronglyContinuousContractionSemigroup.zero_apply] + simpa only [discountedValueProcess, NNReal.coe_zero, mul_zero, neg_zero, Real.exp_zero, + one_mul, hzero] using hstop + +omit [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [Nonempty alpha] [LocallyCompactSpace alpha] in +private theorem exitTimeTrunc_eq_untopD_of_le (U : Set alpha) (omega : ContinuousPath alpha) + {K : NNReal} (hfinite : ContinuousPath.exitTime U omega ≠ ⊤) + (hle : (ContinuousPath.exitTime U omega).toNNReal ≤ K) : + ContinuousPath.exitTimeTrunc U K omega = + (ContinuousPath.exitTime U omega).untopD 0 := by + have hexit : ContinuousPath.exitTime U omega ≤ (K : ℝ≥0∞) := by + rw [← ENNReal.coe_toNNReal hfinite] + exact ENNReal.coe_le_coe.mpr hle + apply ENNReal.coe_injective + rw [ContinuousPath.coe_exitTimeTrunc_ennreal, min_eq_left hexit] + exact (ENNReal.coe_toNNReal hfinite).symm + +/-- **Exit inequality for an excessive function.** The discounted value at the finite exit time +from an open set has `ℝ≥0∞` expectation at most the initial value. Together with +`IsFellerKernelSemigroup.lintegral_pathResolvent_eq_killedResolvent_add`, this is the lower-bound +half of the resolvent comparison. -/ +theorem IsLambdaExcessive.lintegral_discountedValue_exitTime_le + (hP : P.IsConservative) (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) {lam : ℝ} {v : C₀(alpha, ℝ)} + (hv : P.IsLambdaExcessive lam v) (U : Set alpha) (hU : IsOpen U) (x : alpha) : + ∫⁻ omega, ({omega | ContinuousPath.exitTime U omega < ⊤} : Set _).indicator + (fun omega ↦ + ENNReal.ofReal (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal)) * + ENNReal.ofReal (v (omega ((ContinuousPath.exitTime U omega).untopD 0)))) omega + ∂(IsConservative.continuousProcess P hP x) ≤ ENNReal.ofReal (v x) := by + let Q : Measure (ContinuousPath alpha) := IsConservative.continuousProcess P hP x + let T : ℕ → ContinuousPath alpha → NNReal := fun n omega ↦ + ContinuousPath.exitTimeTrunc U n omega + let g : ℕ → ContinuousPath alpha → ℝ≥0∞ := fun n omega ↦ + ENNReal.ofReal (Real.exp (-lam * (T n omega : ℝ))) * + ENNReal.ofReal (v (omega (T n omega))) + have hTstop : ∀ n, IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T n omega : WithTop NNReal)) := fun n ↦ + ContinuousPath.isStoppingTime_exitTimeTrunc U hU n + have hTle : ∀ n omega, T n omega ≤ n := fun n omega ↦ + ContinuousPath.exitTimeTrunc_le U n omega + have hrealMeas : ∀ n, Measurable fun omega ↦ + Real.exp (-lam * (T n omega : ℝ)) * v (omega (T n omega)) := by + intro n + have htime : Measurable fun omega : ContinuousPath alpha ↦ (T n omega : ℝ) := + measurable_coe_nnreal_real.comp + (ContinuousPath.measurable_of_isStoppingTime _ (hTstop n)) + exact (Real.continuous_exp.measurable.comp (measurable_const.mul htime)).mul + (v.continuous.measurable.comp + (ContinuousPath.measurable_eval_stoppingTime_borel _ (hTstop n))) + have hgMeas : ∀ n, Measurable (g n) := fun n ↦ + (ENNReal.measurable_ofReal.comp + (Real.continuous_exp.measurable.comp (measurable_const.mul + (measurable_coe_nnreal_real.comp + (ContinuousPath.measurable_of_isStoppingTime _ (hTstop n)))))).mul + (ENNReal.measurable_ofReal.comp (v.continuous.measurable.comp + (ContinuousPath.measurable_eval_stoppingTime_borel _ (hTstop n)))) + have hnonneg : ∀ n omega, + 0 ≤ Real.exp (-lam * (T n omega : ℝ)) * v (omega (T n omega)) := fun n omega ↦ + mul_nonneg (Real.exp_pos _).le (hv.1 _) + have hint : ∀ n, Integrable (fun omega ↦ + Real.exp (-lam * (T n omega : ℝ)) * v (omega (T n omega))) Q := by + intro n + refine Integrable.of_bound (hrealMeas n).aestronglyMeasurable + (Real.exp (|lam| * (n : ℝ)) * ‖v‖) + (Eventually.of_forall fun omega ↦ ?_) + rw [norm_mul, Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] + calc + Real.exp (-lam * (T n omega : ℝ)) * ‖v (omega (T n omega))‖ + ≤ Real.exp (-lam * (T n omega : ℝ)) * ‖v‖ := + mul_le_mul_of_nonneg_left (norm_c0_apply_le v _) (Real.exp_pos _).le + _ ≤ Real.exp (|lam| * (n : ℝ)) * ‖v‖ := + mul_le_mul_of_nonneg_right (Real.exp_le_exp.mpr <| calc + -lam * (T n omega : ℝ) ≤ |lam| * (T n omega : ℝ) := + mul_le_mul_of_nonneg_right (neg_le_abs lam) NNReal.zero_le_coe + _ ≤ |lam| * (n : ℝ) := + mul_le_mul_of_nonneg_left + (by exact_mod_cast hTle n omega) (abs_nonneg lam)) (norm_nonneg v) + have hbound : ∀ n, ∫⁻ omega, g n omega ∂Q ≤ ENNReal.ofReal (v x) := by + intro n + have hreal : ∫⁻ omega, ENNReal.ofReal + (Real.exp (-lam * (T n omega : ℝ)) * v (omega (T n omega))) ∂Q ≤ + ENNReal.ofReal (v x) := by + rw [← ofReal_integral_eq_lintegral_ofReal (hint n) + (Eventually.of_forall (hnonneg n))] + exact ENNReal.ofReal_le_ofReal + (hv.integral_discountedValueProcess_stoppingTime_le hP hFeller hK + (T n) (hTstop n) (hTle n) x) + simpa only [g, ENNReal.ofReal_mul (Real.exp_pos _).le] using hreal + have htarget : ∀ omega : ContinuousPath alpha, + ({omega | ContinuousPath.exitTime U omega < ⊤} : Set _).indicator + (fun omega ↦ + ENNReal.ofReal (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal)) * + ENNReal.ofReal (v (omega + ((ContinuousPath.exitTime U omega).untopD 0)))) omega ≤ + liminf (fun n ↦ g n omega) atTop := by + intro omega + by_cases hfinite : ContinuousPath.exitTime U omega < ⊤ + · simp only [Set.indicator_of_mem (show omega ∈ + {omega | ContinuousPath.exitTime U omega < ⊤} from hfinite)] + have hne : ContinuousPath.exitTime U omega ≠ ⊤ := ne_top_of_lt hfinite + obtain ⟨N, hN⟩ := exists_nat_ge (ContinuousPath.exitTime U omega).toNNReal + have hevent : ∀ᶠ n : ℕ in atTop, + g n omega = ENNReal.ofReal + (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal)) * + ENNReal.ofReal (v (omega + ((ContinuousPath.exitTime U omega).untopD 0))) := by + filter_upwards [eventually_ge_atTop N] with n hn + have htime : T n omega = (ContinuousPath.exitTime U omega).untopD 0 := + exitTimeTrunc_eq_untopD_of_le U omega hne (hN.trans (by exact_mod_cast hn)) + dsimp only [g] + rw [htime] + rw [show (((ContinuousPath.exitTime U omega).untopD (0 : NNReal) : NNReal) : ℝ) = + (ContinuousPath.exitTime U omega).toReal by + rw [← ENNReal.coe_toNNReal hne] + rfl] + have htend : Tendsto (fun n ↦ g n omega) atTop + (𝓝 (ENNReal.ofReal + (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal)) * + ENNReal.ofReal (v (omega + ((ContinuousPath.exitTime U omega).untopD 0))))) := + tendsto_const_nhds.congr' (hevent.mono fun _ hn ↦ hn.symm) + exact le_of_eq htend.liminf_eq.symm + · simp only [Set.indicator_of_notMem (show omega ∉ + {omega | ContinuousPath.exitTime U omega < ⊤} from hfinite)] + exact zero_le + calc + ∫⁻ omega, ({omega | ContinuousPath.exitTime U omega < ⊤} : Set _).indicator + (fun omega ↦ + ENNReal.ofReal (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal)) * + ENNReal.ofReal (v (omega + ((ContinuousPath.exitTime U omega).untopD 0)))) omega ∂Q + ≤ ∫⁻ omega, liminf (fun n ↦ g n omega) atTop ∂Q := lintegral_mono htarget + _ ≤ liminf (fun n ↦ ∫⁻ omega, g n omega ∂Q) atTop := lintegral_liminf_le hgMeas + _ ≤ ENNReal.ofReal (v x) := + liminf_le_of_frequently_le' (Frequently.of_forall hbound) + +/-- The finite-exit inequality with the nonnegative factors combined inside `ENNReal.ofReal`. -/ +theorem IsLambdaExcessive.lintegral_ofReal_discountedValue_exitTime_le + (hP : P.IsConservative) (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) {lam : ℝ} {v : C₀(alpha, ℝ)} + (hv : P.IsLambdaExcessive lam v) (U : Set alpha) (hU : IsOpen U) (x : alpha) : + ∫⁻ omega, ({omega | ContinuousPath.exitTime U omega < ⊤} : Set _).indicator + (fun omega ↦ ENNReal.ofReal + (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal) * + v (omega ((ContinuousPath.exitTime U omega).untopD 0)))) omega + ∂(IsConservative.continuousProcess P hP x) ≤ ENNReal.ofReal (v x) := by + simpa only [ENNReal.ofReal_mul (Real.exp_pos _).le] using + hv.lintegral_discountedValue_exitTime_le hP hFeller hK U hU x + +end + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitLaw.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitLaw.lean new file mode 100644 index 0000000000..e7a8cfd37f --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitLaw.lean @@ -0,0 +1,225 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop + +/-! +# Stopped laws and exit distributions + +For the continuous-path process `Q` of a conservative semigroup, this file packages as kernels the +laws that the strong Markov property and the boundary value problems of a domain consume: + +* `stoppedLaw T hT : Kernel alpha (NNReal × alpha)`, the joint law of a finite stopping time and + the position at that time, with its two marginals; +* `exitLawTrunc U hU K : Kernel alpha alpha`, the law of the position at the exit time of an open + set `U` truncated at the horizon `K`; from a starting point in `U` it lives on the closure of `U` + (`exitLawTrunc_apply_compl_closure`); +* `exitLaw U hU : Kernel alpha alpha`, the exit distribution (harmonic measure): the law of the + position at the exit time on the event that the path leaves `U`; its total mass is the exit + probability, and from a starting point in `U` it lives on the frontier of `U` + (`exitLaw_apply_compl_frontier`). + +The harmonic representation of `Trajectory/HarmonicRepresentation.lean` reads, in these terms, +`∫ f d(exitLawTrunc U hU K x) = f x` whenever `L f = 0` on `U` +(`integral_exitLawTrunc_eq_of_generator_eq_zero`). +-/ + +open MeasureTheory ProbabilityTheory Filter +open scoped ENNReal NNReal ZeroAtInfty + +namespace MarkovProcess + +namespace ContinuousPath + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +/-- The finite value of a finite exit time, read through `untopD`, is its `toNNReal`. -/ +theorem untopD_exitTimeTop_eq_toNNReal (U : Set alpha) (omega : ContinuousPath alpha) + (h : exitTime U omega ≠ ⊤) : + (exitTimeTop U omega).untopD 0 = (exitTime U omega).toNNReal := by + rw [exitTimeTop_apply, ← ENNReal.coe_toNNReal h] + rfl + +variable [MeasurableSpace alpha] [BorelSpace alpha] + +/-- The event that a path leaves the open set `U` is measurable. -/ +theorem measurableSet_exitTime_lt_top (U : Set alpha) (hU : IsOpen U) : + MeasurableSet {omega : ContinuousPath alpha | exitTime U omega < ⊤} := + measurableSet_lt (measurable_exitTime U hU) measurable_const + +/-- The pair of a finite stopping time and the position at that time is measurable. -/ +theorem measurable_prodMk_stoppingTime (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) : + Measurable fun omega : ContinuousPath alpha ↦ (T omega, omega (T omega)) := + (measurable_of_isStoppingTime T hT).prodMk (measurable_eval_stoppingTime_borel T hT) + +/-- The position at the exit time of an open set, on the event that the path leaves it, is +measurable. -/ +theorem measurable_eval_untopD_exitTimeTop (U : Set alpha) (hU : IsOpen U) : + Measurable fun omega : ContinuousPath alpha ↦ omega ((exitTimeTop U omega).untopD 0) := + measurable_eval_untopD_stoppingTime _ (isStoppingTime_exitTime U hU) + +end ContinuousPath + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable {P : SubMarkovKernelSemigroup alpha} (hP : P.IsConservative) + +section StoppedLaw + +variable (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + +/-- The stopped law: the joint law of a finite stopping time and the position at that time, as a +kernel from the starting point. -/ +noncomputable def IsConservative.stoppedLaw : Kernel alpha (NNReal × alpha) := + Kernel.mapOfMeasurable (IsConservative.continuousProcess P hP) + (fun omega ↦ (T omega, omega (T omega))) (ContinuousPath.measurable_prodMk_stoppingTime T hT) + +theorem IsConservative.stoppedLaw_apply (x : alpha) : + IsConservative.stoppedLaw hP T hT x = + (IsConservative.continuousProcess P hP x).map (fun omega ↦ (T omega, omega (T omega))) := by + rw [IsConservative.stoppedLaw, Kernel.mapOfMeasurable_eq_map, + Kernel.map_apply _ (ContinuousPath.measurable_prodMk_stoppingTime T hT)] + +/-- The stopped law is a Markov kernel. -/ +instance isMarkovKernel_stoppedLaw : IsMarkovKernel (IsConservative.stoppedLaw hP T hT) := by + rw [IsConservative.stoppedLaw, Kernel.mapOfMeasurable_eq_map] + exact Kernel.IsMarkovKernel.map _ (ContinuousPath.measurable_prodMk_stoppingTime T hT) + +/-- The first marginal of the stopped law is the law of the stopping time. -/ +theorem IsConservative.stoppedLaw_map_fst : + (IsConservative.stoppedLaw hP T hT).map Prod.fst = + (IsConservative.continuousProcess P hP).map T := by + refine Kernel.ext fun x ↦ ?_ + rw [Kernel.map_apply _ measurable_fst, IsConservative.stoppedLaw_apply, + Measure.map_map measurable_fst (ContinuousPath.measurable_prodMk_stoppingTime T hT), + Kernel.map_apply _ (ContinuousPath.measurable_of_isStoppingTime T hT)] + rfl + +/-- The second marginal of the stopped law is the law of the stopped position. -/ +theorem IsConservative.stoppedLaw_map_snd : + (IsConservative.stoppedLaw hP T hT).map Prod.snd = + (IsConservative.continuousProcess P hP).map (fun omega ↦ omega (T omega)) := by + refine Kernel.ext fun x ↦ ?_ + rw [Kernel.map_apply _ measurable_snd, IsConservative.stoppedLaw_apply, + Measure.map_map measurable_snd (ContinuousPath.measurable_prodMk_stoppingTime T hT), + Kernel.map_apply _ (ContinuousPath.measurable_eval_stoppingTime_borel T hT)] + rfl + +end StoppedLaw + +section ExitLaw + +variable (U : Set alpha) (hU : IsOpen U) + +/-- The law of the position at the exit time of `U` truncated at the horizon `K`. -/ +noncomputable def IsConservative.exitLawTrunc (K : NNReal) : Kernel alpha alpha := + Kernel.mapOfMeasurable (IsConservative.continuousProcess P hP) + (fun omega ↦ omega (ContinuousPath.exitTimeTrunc U K omega)) + (ContinuousPath.measurable_eval_stoppingTime_borel _ + (ContinuousPath.isStoppingTime_exitTimeTrunc U hU K)) + +theorem IsConservative.exitLawTrunc_apply (K : NNReal) (x : alpha) : + IsConservative.exitLawTrunc hP U hU K x = + (IsConservative.continuousProcess P hP x).map + (fun omega ↦ omega (ContinuousPath.exitTimeTrunc U K omega)) := by + rw [IsConservative.exitLawTrunc, Kernel.mapOfMeasurable_eq_map, Kernel.map_apply _ + (ContinuousPath.measurable_eval_stoppingTime_borel _ + (ContinuousPath.isStoppingTime_exitTimeTrunc U hU K))] + +/-- The truncated exit law is a Markov kernel. -/ +instance isMarkovKernel_exitLawTrunc (K : NNReal) : + IsMarkovKernel (IsConservative.exitLawTrunc hP U hU K) := by + rw [IsConservative.exitLawTrunc, Kernel.mapOfMeasurable_eq_map] + exact Kernel.IsMarkovKernel.map _ + (ContinuousPath.measurable_eval_stoppingTime_borel _ + (ContinuousPath.isStoppingTime_exitTimeTrunc U hU K)) + +/-- Integrals against the truncated exit law are expectations of the stopped position. -/ +theorem IsConservative.integral_exitLawTrunc (K : NNReal) (x : alpha) {E : Type*} + [NormedAddCommGroup E] [NormedSpace ℝ E] (f : alpha → E) (hf : StronglyMeasurable f) : + ∫ y, f y ∂(IsConservative.exitLawTrunc hP U hU K x) = + ∫ omega, f (omega (ContinuousPath.exitTimeTrunc U K omega)) + ∂(IsConservative.continuousProcess P hP x) := by + rw [IsConservative.exitLawTrunc_apply] + exact integral_map (ContinuousPath.measurable_eval_stoppingTime_borel _ + (ContinuousPath.isStoppingTime_exitTimeTrunc U hU K)).aemeasurable hf.aestronglyMeasurable + +/-- From a starting point in `U`, the truncated exit law lives on the closure of `U`. -/ +theorem IsConservative.exitLawTrunc_apply_compl_closure (hK : P.KolmogorovRegular hP) + (K : NNReal) {x : alpha} (hx : x ∈ U) : + IsConservative.exitLawTrunc hP U hU K x (closure U)ᶜ = 0 := by + rw [IsConservative.exitLawTrunc_apply, + Measure.map_apply (ContinuousPath.measurable_eval_stoppingTime_borel _ + (ContinuousPath.isStoppingTime_exitTimeTrunc U hU K)) isClosed_closure.measurableSet.compl] + refine measure_mono_null (fun omega homega ↦ ?_) ((ae_iff).mp + (IsConservative.ae_eval_zero_eq hP hK x)) + intro h0 + exact homega (ContinuousPath.stopped_exitTimeTrunc_mem_closure U hU K omega (h0 ▸ hx)) + +/-- The exit distribution (harmonic measure) of `U`: the law of the position at the exit time, on +the event that the path leaves `U`. -/ +noncomputable def IsConservative.exitLaw : Kernel alpha alpha := + ((IsConservative.continuousProcess P hP).restrict + (ContinuousPath.measurableSet_exitTime_lt_top U hU)).map + (fun omega ↦ omega ((ContinuousPath.exitTimeTop U omega).untopD 0)) + +/-- The exit distribution evaluated on a measurable set. -/ +theorem IsConservative.exitLaw_apply (x : alpha) {B : Set alpha} (hB : MeasurableSet B) : + IsConservative.exitLaw hP U hU x B = + IsConservative.continuousProcess P hP x + {omega | ContinuousPath.exitTime U omega < ⊤ ∧ + omega ((ContinuousPath.exitTimeTop U omega).untopD 0) ∈ B} := by + rw [IsConservative.exitLaw, + Kernel.map_apply' _ (ContinuousPath.measurable_eval_untopD_exitTimeTop U hU) _ hB, + Kernel.restrict_apply' _ _ _ ((ContinuousPath.measurable_eval_untopD_exitTimeTop U hU) hB)] + congr 1 + ext omega + simp only [Set.mem_inter_iff, Set.mem_preimage, Set.mem_ofPred_eq] + exact and_comm + +/-- The total mass of the exit distribution is the probability of leaving `U`. -/ +theorem IsConservative.exitLaw_apply_univ (x : alpha) : + IsConservative.exitLaw hP U hU x Set.univ = + IsConservative.continuousProcess P hP x {omega | ContinuousPath.exitTime U omega < ⊤} := by + rw [IsConservative.exitLaw_apply hP U hU x MeasurableSet.univ] + simp only [Set.mem_univ, and_true] + +/-- From a starting point in `U`, the exit distribution lives on the frontier of `U`. -/ +theorem IsConservative.exitLaw_apply_compl_frontier (hK : P.KolmogorovRegular hP) {x : alpha} + (hx : x ∈ U) : IsConservative.exitLaw hP U hU x (frontier U)ᶜ = 0 := by + rw [IsConservative.exitLaw_apply hP U hU x isClosed_frontier.measurableSet.compl] + refine measure_mono_null (fun omega homega ↦ ?_) ((ae_iff).mp + (IsConservative.ae_eval_zero_eq hP hK x)) + intro h0 + obtain ⟨hfin, hnot⟩ := homega + rw [ContinuousPath.untopD_exitTimeTop_eq_toNNReal U omega hfin.ne] at hnot + exact hnot (ContinuousPath.coordinate_exitTime_mem_frontier U hU omega (h0 ▸ hx) hfin.ne) + +variable [LocallyCompactSpace alpha] + +/-- **Harmonic representation in kernel form.** If `L f = 0` on `U`, then `f x` is the integral of +`f` against the truncated exit law from `x`, for every horizon. -/ +theorem IsFellerKernelSemigroup.integral_exitLawTrunc_eq_of_generator_eq_zero + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) + (hLf : ∀ y ∈ U, (hFeller.c0Semigroup.generator f) y = 0) (K : NNReal) (x : alpha) : + ∫ y, (f : C₀(alpha, ℝ)) y ∂(IsConservative.exitLawTrunc hP U hU K x) = (f : C₀(alpha, ℝ)) x := by + rw [IsConservative.integral_exitLawTrunc hP U hU K x (fun y ↦ (f : C₀(alpha, ℝ)) y) + (f : C₀(alpha, ℝ)).continuous.stronglyMeasurable] + exact hFeller.integral_eval_exitTimeTrunc_eq_of_generator_eq_zero hP hK f U hU hLf K x + +end ExitLaw + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeExponentialMoment.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeExponentialMoment.lean new file mode 100644 index 0000000000..02e049a498 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeExponentialMoment.lean @@ -0,0 +1,517 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel + +/-! +# A positive exponential moment for the exit time + +A uniform bound on the survival probability at one horizon `t0` propagates to the multiples of +that horizon by the Chapman--Kolmogorov law for the killed kernels: if the process started +anywhere survives the horizon `t0` inside the open set `U` with probability at most `q`, then it +survives `k` horizons with probability at most `q ^ k` +(`IsConservative.measure_lt_exitTime_nsmul_le`). Summing the resulting geometric layers bounds a +*positive* exponential moment of the exit time +(`IsConservative.lintegral_exponentialStoppingWeight_exitTime_le`), for every rate `lam` with +`q * exp (lam * t0) < 1`. + +The positive exponential weight is `ContinuousPath.exponentialStoppingWeight`, which takes the +value `⊤` where the time is infinite. That branch is forced: reading the extended time through +`ENNReal.toReal` would return `1` at `⊤` and silently discard the paths that never leave `U`. A +finite integral of the weight therefore certifies almost-sure finiteness +(`ContinuousPath.ae_lt_top_of_lintegral_exponentialStoppingWeight_ne_top`), which the survival +bound supplies on its own +(`IsConservative.ae_exitTime_lt_top_of_measure_lt_exitTime_le`). + +Two consequences are recorded. An expected-exit-time bound `E_y τ_U ≤ M` valid from every +starting point supplies the survival hypothesis at the horizon `t0 = K M` with `q = K⁻¹` by +Markov's inequality, for every multiplier `K > 1` +(`IsConservative.lintegral_exponentialStoppingWeight_exitTime_le_of_lintegral_le_mul`; the +multiplier `K = 2` is +`IsConservative.lintegral_exponentialStoppingWeight_exitTime_le_of_lintegral_le`), and a large +multiplier normalizes the moment to `2` at a rate that is still positive +(`IsConservative.lintegral_exponentialStoppingWeight_exitTime_le_two_of_lintegral_le`). The +elementary pointwise bound `t ^ p ≤ (p / (lam * e)) ^ p * exp (lam * t)` converts an +exponential moment into every polynomial moment +(`IsConservative.lintegral_exitTime_pow_le`). + +Every statement is an inequality of `ℝ≥0∞`-valued integrals; no integrability side condition and +no real-valued restatement appears. +-/ + +open MeasureTheory ProbabilityTheory Set +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] + +/-- The exponential weight at rate `lam` of an extended-real time functional, with the value `⊤` +on the infinite branch. -/ +noncomputable def exponentialStoppingWeight (lam : ℝ) (sigma : ContinuousPath alpha → ℝ≥0∞) + (omega : ContinuousPath alpha) : ℝ≥0∞ := + if sigma omega = ⊤ then ⊤ else ENNReal.ofReal (Real.exp (lam * (sigma omega).toReal)) + +/-- On the finite branch the exponential weight is the ordinary exponential. -/ +theorem exponentialStoppingWeight_of_ne_top (lam : ℝ) (sigma : ContinuousPath alpha → ℝ≥0∞) + {omega : ContinuousPath alpha} (h : sigma omega ≠ ⊤) : + exponentialStoppingWeight lam sigma omega = + ENNReal.ofReal (Real.exp (lam * (sigma omega).toReal)) := + if_neg h + +/-- On the infinite branch the exponential weight is `⊤`. -/ +theorem exponentialStoppingWeight_of_eq_top (lam : ℝ) (sigma : ContinuousPath alpha → ℝ≥0∞) + {omega : ContinuousPath alpha} (h : sigma omega = ⊤) : + exponentialStoppingWeight lam sigma omega = ⊤ := + if_pos h + +/-- At a nonnegative rate the exponential weight is at least one. -/ +theorem one_le_exponentialStoppingWeight (lam : ℝ) (hlam : 0 ≤ lam) + (sigma : ContinuousPath alpha → ℝ≥0∞) (omega : ContinuousPath alpha) : + 1 ≤ exponentialStoppingWeight lam sigma omega := by + by_cases h : sigma omega = ⊤ + · rw [exponentialStoppingWeight_of_eq_top lam sigma h] + exact le_top + · rw [exponentialStoppingWeight_of_ne_top lam sigma h, ENNReal.one_le_ofReal] + exact Real.one_le_exp (mul_nonneg hlam ENNReal.toReal_nonneg) + +/-- The exponential weight of a measurable time functional is measurable. -/ +theorem measurable_exponentialStoppingWeight (lam : ℝ) {sigma : ContinuousPath alpha → ℝ≥0∞} + (hsigma : Measurable sigma) : Measurable (exponentialStoppingWeight lam sigma) := by + classical + refine Measurable.ite (hsigma (measurableSet_singleton ⊤)) measurable_const ?_ + exact ENNReal.measurable_ofReal.comp (Real.continuous_exp.measurable.comp + (measurable_const.mul (ENNReal.measurable_toReal.comp hsigma))) + +/-- A finite integral of the positive exponential weight forces the time to be finite almost +everywhere. -/ +theorem ae_lt_top_of_lintegral_exponentialStoppingWeight_ne_top (lam : ℝ) + {sigma : ContinuousPath alpha → ℝ≥0∞} (hsigma : Measurable sigma) + {mu : Measure (ContinuousPath alpha)} + (h : ∫⁻ omega, exponentialStoppingWeight lam sigma omega ∂mu ≠ ⊤) : + ∀ᵐ omega ∂mu, sigma omega < ⊤ := by + have hfin := ae_lt_top (measurable_exponentialStoppingWeight lam hsigma) h + filter_upwards [hfin] with omega homega + by_contra hnot + rw [exponentialStoppingWeight_of_eq_top lam sigma (top_unique (not_lt.mp hnot))] at homega + exact homega.ne rfl + +end ContinuousPath + +namespace SubMarkovKernelSemigroup + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [Nonempty alpha] [LocallyCompactSpace alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- **Submultiplicativity of survival.** A uniform bound `q` on the probability of remaining in +the open set `U` past the horizon `t0`, valid from every starting point, gives the bound `q ^ k` +at the `k`-th multiple of that horizon. -/ +theorem IsConservative.measure_lt_exitTime_nsmul_le + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (U : Set alpha) (hU : IsOpen U) (q : ℝ≥0∞) (t0 : NNReal) + (hq : ∀ y, IsConservative.continuousProcess P hP y + {omega | (t0 : ℝ≥0∞) < ContinuousPath.exitTime U omega} ≤ q) + (k : ℕ) (x : alpha) : + IsConservative.continuousProcess P hP x + {omega | ((k • t0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} ≤ q ^ k := by + have hstep : ∀ y, IsConservative.killedKernel P hP U hU t0 y Set.univ ≤ q := by + intro y + rw [IsConservative.killedKernel_apply_univ] + exact hq y + have hkey : ∀ (n : ℕ) (y : alpha), + IsConservative.killedKernel P hP U hU (n • t0) y Set.univ ≤ q ^ n := by + intro n + induction n with + | zero => + intro y + rw [pow_zero, zero_nsmul, IsConservative.killedKernel_apply_univ] + exact prob_le_one + | succ n ih => + intro y + rw [succ_nsmul, IsConservative.killedKernel_add P hP U hU hFeller hK (n • t0) t0, + Kernel.comp_apply' _ _ _ MeasurableSet.univ] + calc + ∫⁻ z, IsConservative.killedKernel P hP U hU t0 z Set.univ + ∂(IsConservative.killedKernel P hP U hU (n • t0) y) + ≤ ∫⁻ _z, q ∂(IsConservative.killedKernel P hP U hU (n • t0) y) := + lintegral_mono hstep + _ = q * IsConservative.killedKernel P hP U hU (n • t0) y Set.univ := by + rw [lintegral_const] + _ ≤ q * q ^ n := mul_le_mul_right (ih y) q + _ = q ^ (n + 1) := by rw [pow_succ, mul_comm] + have hx := hkey k x + rwa [IsConservative.killedKernel_apply_univ] at hx + +/-- The pointwise geometric layering behind the exponential moment: the exponential weight of an +extended time is dominated by one initial layer plus the layers indexed by the multiples of the +horizon which the time exceeds. -/ +private theorem exponentialWeight_le_add_tsum (lam : ℝ) (hlam : 0 ≤ lam) (t0 : NNReal) + (tau : ℝ≥0∞) : + (if tau = ⊤ then ⊤ else ENNReal.ofReal (Real.exp (lam * tau.toReal))) ≤ + ENNReal.ofReal (Real.exp (lam * (t0 : ℝ))) + + ∑' k : ℕ, ({u : ℝ≥0∞ | (((k + 1) • t0 : NNReal) : ℝ≥0∞) < u}.indicator + (fun _ ↦ ENNReal.ofReal (Real.exp (lam * (t0 : ℝ))) ^ (k + 2)) tau) := by + classical + set a : ℝ≥0∞ := ENNReal.ofReal (Real.exp (lam * (t0 : ℝ))) with ha + have ha1 : 1 ≤ a := by + rw [ha, ENNReal.one_le_ofReal] + exact Real.one_le_exp (mul_nonneg hlam t0.coe_nonneg) + have hpow : ∀ m : ℕ, ENNReal.ofReal (Real.exp (lam * ((m • t0 : NNReal) : ℝ))) = a ^ m := by + intro m + rw [ha, ← ENNReal.ofReal_pow (Real.exp_pos _).le, ← Real.exp_nat_mul] + congr 2 + push_cast [nsmul_eq_mul] + ring + by_cases hall : ∀ m : ℕ, ((m • t0 : NNReal) : ℝ≥0∞) < tau + · have hterm : ∀ k : ℕ, (1 : ℝ≥0∞) ≤ + {u : ℝ≥0∞ | (((k + 1) • t0 : NNReal) : ℝ≥0∞) < u}.indicator (fun _ ↦ a ^ (k + 2)) tau := by + intro k + have hmem : tau ∈ {u : ℝ≥0∞ | (((k + 1) • t0 : NNReal) : ℝ≥0∞) < u} := hall (k + 1) + rw [Set.indicator_of_mem hmem] + exact one_le_pow₀ ha1 + have htop : (∑' k : ℕ, ({u : ℝ≥0∞ | (((k + 1) • t0 : NNReal) : ℝ≥0∞) < u}.indicator + (fun _ ↦ a ^ (k + 2)) tau)) = ⊤ := by + refine top_unique ?_ + calc + (⊤ : ℝ≥0∞) = ∑' _k : ℕ, (1 : ℝ≥0∞) := + (ENNReal.tsum_const_eq_top_of_ne_zero one_ne_zero).symm + _ ≤ _ := ENNReal.tsum_le_tsum hterm + rw [htop, add_top] + exact le_top + · push Not at hall + obtain ⟨m0, hm0⟩ := hall + have hex : ∃ m : ℕ, tau ≤ ((m • t0 : NNReal) : ℝ≥0∞) := ⟨m0, hm0⟩ + set m := Nat.find hex with hm + have hmspec : tau ≤ ((m • t0 : NNReal) : ℝ≥0∞) := Nat.find_spec hex + have hne : tau ≠ ⊤ := ne_top_of_le_ne_top ENNReal.coe_ne_top hmspec + rw [if_neg hne] + have hle : ENNReal.ofReal (Real.exp (lam * tau.toReal)) ≤ a ^ m := by + rw [← hpow m] + refine ENNReal.ofReal_le_ofReal (Real.exp_le_exp.mpr ?_) + refine mul_le_mul_of_nonneg_left ?_ hlam + exact (ENNReal.toReal_le_coe_of_le_coe hmspec) + refine hle.trans ?_ + match hmatch : m with + | 0 => simpa only [pow_zero] using le_add_right ha1 + | 1 => simpa only [pow_one] using le_add_right le_rfl + | (j + 2) => + have hlt : ((((j + 1) : ℕ) • t0 : NNReal) : ℝ≥0∞) < tau := by + have := Nat.find_min hex (m := j + 1) (by omega) + exact not_le.mp this + refine le_add_left ?_ + refine le_trans (le_of_eq ?_) + (ENNReal.le_tsum (f := fun k : ℕ ↦ + {u : ℝ≥0∞ | (((k + 1) • t0 : NNReal) : ℝ≥0∞) < u}.indicator + (fun _ ↦ a ^ (k + 2)) tau) j) + have hmem : tau ∈ {u : ℝ≥0∞ | (((j + 1) • t0 : NNReal) : ℝ≥0∞) < u} := hlt + rw [Set.indicator_of_mem hmem] + +/-- **A positive exponential moment for the exit time.** Under a uniform survival bound `q` at +the horizon `t0` and a rate `lam` small enough that `q * exp (lam * t0) < 1`, the exponential +weight of the exit time is integrable with an explicit geometric bound. -/ +theorem IsConservative.lintegral_exponentialStoppingWeight_exitTime_le + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (U : Set alpha) (hU : IsOpen U) (q : ℝ≥0∞) (t0 : NNReal) (lam : ℝ) (hlam : 0 ≤ lam) + (hcontr : q * ENNReal.ofReal (Real.exp (lam * (t0 : ℝ))) < 1) + (hq : ∀ y, IsConservative.continuousProcess P hP y + {omega | (t0 : ℝ≥0∞) < ContinuousPath.exitTime U omega} ≤ q) + (x : alpha) : + ∫⁻ omega, ContinuousPath.exponentialStoppingWeight lam (ContinuousPath.exitTime U) omega + ∂(IsConservative.continuousProcess P hP x) + ≤ ENNReal.ofReal (Real.exp (lam * (t0 : ℝ))) * + (1 - q * ENNReal.ofReal (Real.exp (lam * (t0 : ℝ))))⁻¹ := by + classical + set Q : Measure (ContinuousPath alpha) := IsConservative.continuousProcess P hP x with hQ + set a : ℝ≥0∞ := ENNReal.ofReal (Real.exp (lam * (t0 : ℝ))) with ha + have hExit : Measurable fun omega : ContinuousPath alpha ↦ ContinuousPath.exitTime U omega := + ContinuousPath.measurable_exitTime U hU + set B : ℕ → Set (ContinuousPath alpha) := fun k ↦ + {omega | (((k + 1) • t0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} with hB + have hBmeas : ∀ k, MeasurableSet (B k) := fun k ↦ measurableSet_lt measurable_const hExit + have hpoint : ∀ omega : ContinuousPath alpha, + ContinuousPath.exponentialStoppingWeight lam (ContinuousPath.exitTime U) omega ≤ + a + ∑' k : ℕ, (B k).indicator (fun _ ↦ a ^ (k + 2)) omega := by + intro omega + have h := exponentialWeight_le_add_tsum lam hlam t0 (ContinuousPath.exitTime U omega) + refine h.trans (le_of_eq ?_) + congr 1 + have hlayer : ∀ k : ℕ, ∫⁻ omega, (B k).indicator (fun _ ↦ a ^ (k + 2)) omega ∂Q ≤ + a ^ (k + 2) * q ^ (k + 1) := by + intro k + rw [lintegral_indicator_const (hBmeas k)] + exact mul_le_mul_right (hP.measure_lt_exitTime_nsmul_le P hFeller hK U hU q t0 hq (k + 1) x) + (a ^ (k + 2)) + have hsum : (∑' k : ℕ, a ^ (k + 2) * q ^ (k + 1)) = a * ((a * q) * (1 - a * q)⁻¹) := by + rw [← ENNReal.tsum_geometric_add_one (a * q), ← ENNReal.tsum_mul_left] + refine tsum_congr fun k ↦ ?_ + rw [mul_pow, ← mul_assoc, ← pow_succ'] + have hcontr' : a * q < 1 := by rwa [mul_comm] + have hfinal : a + a * ((a * q) * (1 - a * q)⁻¹) = a * (1 - q * a)⁻¹ := by + have hne : (1 : ℝ≥0∞) - a * q ≠ 0 := by + simp only [ne_eq, tsub_eq_zero_iff_le, not_le] + exact hcontr' + have htop : (1 : ℝ≥0∞) - a * q ≠ ⊤ := by + exact ne_top_of_le_ne_top ENNReal.one_ne_top tsub_le_self + have hid : (1 : ℝ≥0∞) - a * q + a * q = 1 := tsub_add_cancel_of_le hcontr'.le + have hgeom : (1 : ℝ≥0∞) + (a * q) * (1 - a * q)⁻¹ = (1 - a * q)⁻¹ := by + calc + (1 : ℝ≥0∞) + (a * q) * (1 - a * q)⁻¹ + = (1 - a * q) * (1 - a * q)⁻¹ + (a * q) * (1 - a * q)⁻¹ := by + rw [ENNReal.mul_inv_cancel hne htop] + _ = ((1 - a * q) + a * q) * (1 - a * q)⁻¹ := (add_mul _ _ _).symm + _ = (1 - a * q)⁻¹ := by rw [hid, one_mul] + calc + a + a * ((a * q) * (1 - a * q)⁻¹) = a * (1 + (a * q) * (1 - a * q)⁻¹) := by ring + _ = a * (1 - a * q)⁻¹ := by rw [hgeom] + _ = a * (1 - q * a)⁻¹ := by rw [mul_comm a q] + calc + ∫⁻ omega, ContinuousPath.exponentialStoppingWeight lam (ContinuousPath.exitTime U) omega ∂Q + ≤ ∫⁻ omega, (a + ∑' k : ℕ, (B k).indicator (fun _ ↦ a ^ (k + 2)) omega) ∂Q := + lintegral_mono hpoint + _ = a + ∫⁻ omega, ∑' k : ℕ, (B k).indicator (fun _ ↦ a ^ (k + 2)) omega ∂Q := by + rw [lintegral_add_left measurable_const, lintegral_const, measure_univ, mul_one] + _ = a + ∑' k : ℕ, ∫⁻ omega, (B k).indicator (fun _ ↦ a ^ (k + 2)) omega ∂Q := by + rw [lintegral_tsum fun k ↦ (measurable_const.indicator (hBmeas k)).aemeasurable] + _ ≤ a + ∑' k : ℕ, a ^ (k + 2) * q ^ (k + 1) := + add_le_add le_rfl (ENNReal.tsum_le_tsum hlayer) + _ = a + a * ((a * q) * (1 - a * q)⁻¹) := by rw [hsum] + _ = a * (1 - q * a)⁻¹ := hfinal + +/-- **A uniform survival bound makes the exit time almost surely finite.** The geometric bound +`a * (1 - q * a)⁻¹` of the exponential moment is finite exactly because `q * a < 1`, so the +exponential weight is almost everywhere finite and hence so is the exit time. -/ +theorem IsConservative.ae_exitTime_lt_top_of_measure_lt_exitTime_le + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (U : Set alpha) (hU : IsOpen U) (q : ℝ≥0∞) (t0 : NNReal) (lam : ℝ) (hlam : 0 ≤ lam) + (hcontr : q * ENNReal.ofReal (Real.exp (lam * (t0 : ℝ))) < 1) + (hq : ∀ y, IsConservative.continuousProcess P hP y + {omega | (t0 : ℝ≥0∞) < ContinuousPath.exitTime U omega} ≤ q) + (x : alpha) : + ∀ᵐ omega ∂(IsConservative.continuousProcess P hP x), + ContinuousPath.exitTime U omega < ⊤ := by + refine ContinuousPath.ae_lt_top_of_lintegral_exponentialStoppingWeight_ne_top lam + (ContinuousPath.measurable_exitTime U hU) ?_ + refine ne_top_of_le_ne_top ?_ (hP.lintegral_exponentialStoppingWeight_exitTime_le P hFeller hK + U hU q t0 lam hlam hcontr hq x) + refine ENNReal.mul_ne_top ENNReal.ofReal_ne_top (ENNReal.inv_ne_top.mpr ?_) + simpa only [ne_eq, tsub_eq_zero_iff_le, not_le] using hcontr + +/-- **Markov's inequality at a free multiple of the mean.** A uniform bound `M` on the expected +exit time from `U` bounds the probability of surviving the horizon `K * M` by `K⁻¹`, for every +multiplier `K > 1`, hence gives an exponential moment at every rate with `exp (lam * K * M) < K`. +Enlarging `K` makes the survival probability at one horizon as small as one likes, at the price of +a longer horizon; the normalized form is +`IsConservative.lintegral_exponentialStoppingWeight_exitTime_le_two_of_lintegral_le`. -/ +theorem IsConservative.lintegral_exponentialStoppingWeight_exitTime_le_of_lintegral_le_mul + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (U : Set alpha) (hU : IsOpen U) (M : NNReal) + (hM : ∀ y, ∫⁻ omega, ContinuousPath.exitTime U omega + ∂(IsConservative.continuousProcess P hP y) ≤ (M : ℝ≥0∞)) + (K : ℝ≥0) (hK1 : 1 < K) (lam : ℝ) (hlam : 0 ≤ lam) + (hrate : Real.exp (lam * ((K : ℝ) * (M : ℝ))) < (K : ℝ)) (x : alpha) : + ∫⁻ omega, ContinuousPath.exponentialStoppingWeight lam (ContinuousPath.exitTime U) omega + ∂(IsConservative.continuousProcess P hP x) + ≤ ENNReal.ofReal (Real.exp (lam * ((K : ℝ) * (M : ℝ)))) * + (1 - (K : ℝ≥0∞)⁻¹ * ENNReal.ofReal (Real.exp (lam * ((K : ℝ) * (M : ℝ)))))⁻¹ := by + have hKpos : (0 : ℝ≥0) < K := lt_trans zero_lt_one hK1 + have hK0 : ((K : ℝ≥0) : ℝ≥0∞) ≠ 0 := by + simpa only [ne_eq, ENNReal.coe_eq_zero] using hKpos.ne' + have hcast : (((K * M : NNReal) : ℝ)) = (K : ℝ) * (M : ℝ) := by push_cast; ring + have hExit : Measurable fun omega : ContinuousPath alpha ↦ ContinuousPath.exitTime U omega := + ContinuousPath.measurable_exitTime U hU + have hq : ∀ y, IsConservative.continuousProcess P hP y + {omega | ((K * M : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} ≤ (K : ℝ≥0∞)⁻¹ := by + intro y + rcases eq_or_lt_of_le (zero_le : (0 : NNReal) ≤ M) with hM0 | hM0 + · have hzero : ∫⁻ omega, ContinuousPath.exitTime U omega + ∂(IsConservative.continuousProcess P hP y) = 0 := by + refine le_antisymm ?_ zero_le + simpa only [← hM0, ENNReal.coe_zero] using! hM y + have hae : ∀ᵐ omega ∂(IsConservative.continuousProcess P hP y), + ContinuousPath.exitTime U omega = 0 := (lintegral_eq_zero_iff hExit).mp hzero + have hnull : IsConservative.continuousProcess P hP y + {omega | ((K * M : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} = 0 := + measure_mono_null (fun omega homega ↦ (zero_le.trans_lt homega).ne') (ae_iff.mp hae) + rw [hnull] + exact zero_le + · have hpos : ((K * M : NNReal) : ℝ≥0∞) ≠ 0 := by + simp only [ne_eq, ENNReal.coe_eq_zero, mul_eq_zero, not_or] + exact ⟨hKpos.ne', hM0.ne'⟩ + have hmarkov := mul_meas_ge_le_lintegral₀ (μ := IsConservative.continuousProcess P hP y) + hExit.aemeasurable ((K * M : NNReal) : ℝ≥0∞) + have hquot : ((K * M : NNReal) : ℝ≥0∞) * (K : ℝ≥0∞)⁻¹ = (M : ℝ≥0∞) := by + rw [ENNReal.coe_mul, mul_comm ((K : ℝ≥0∞)) ((M : ℝ≥0∞)), mul_assoc, + ENNReal.mul_inv_cancel hK0 ENNReal.coe_ne_top, mul_one] + have hle : ((K * M : NNReal) : ℝ≥0∞) * IsConservative.continuousProcess P hP y + {omega | ((K * M : NNReal) : ℝ≥0∞) ≤ ContinuousPath.exitTime U omega} ≤ + ((K * M : NNReal) : ℝ≥0∞) * (K : ℝ≥0∞)⁻¹ := by + rw [hquot] + exact hmarkov.trans (hM y) + have hcancel := (ENNReal.mul_le_mul_iff_right hpos ENNReal.coe_ne_top).mp hle + refine le_trans (measure_mono ?_) hcancel + intro omega homega + exact le_of_lt (Set.mem_ofPred_eq ▸ homega) + have hcontr : (K : ℝ≥0∞)⁻¹ * ENNReal.ofReal (Real.exp (lam * ((K : ℝ) * (M : ℝ)))) < 1 := by + have hlt : ENNReal.ofReal (Real.exp (lam * ((K : ℝ) * (M : ℝ)))) < (K : ℝ≥0∞) := by + rw [← ENNReal.ofReal_coe_nnreal] + exact (ENNReal.ofReal_lt_ofReal_iff (by exact_mod_cast hKpos)).mpr hrate + calc + (K : ℝ≥0∞)⁻¹ * ENNReal.ofReal (Real.exp (lam * ((K : ℝ) * (M : ℝ)))) + < (K : ℝ≥0∞)⁻¹ * (K : ℝ≥0∞) := + ENNReal.mul_lt_mul_right (ENNReal.inv_ne_zero.mpr ENNReal.coe_ne_top) + (ENNReal.inv_ne_top.mpr hK0) hlt + _ = 1 := ENNReal.inv_mul_cancel hK0 ENNReal.coe_ne_top + have hmain := hP.lintegral_exponentialStoppingWeight_exitTime_le P hFeller hK U hU + ((K : ℝ≥0∞)⁻¹) (K * M) lam hlam (by rwa [hcast]) hq x + rwa [hcast] at hmain + +/-- **A normalized exponential moment.** The rate condition +`exp (lam * K * M) * (K + 2) ≤ 2 * K`, that is `lam ≤ log (2 K / (K + 2)) / (K M)`, normalizes the +exponential moment of the exit time to `2`. It leaves room for a positive rate as soon as +`K > 2` and `M > 0`; for instance `lam = log (19 / 10) / (K M)` is admissible whenever +`38 ≤ K`. -/ +theorem IsConservative.lintegral_exponentialStoppingWeight_exitTime_le_two_of_lintegral_le + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (U : Set alpha) (hU : IsOpen U) (M : NNReal) + (hM : ∀ y, ∫⁻ omega, ContinuousPath.exitTime U omega + ∂(IsConservative.continuousProcess P hP y) ≤ (M : ℝ≥0∞)) + (K : ℝ≥0) (hK1 : 1 < K) (lam : ℝ) (hlam : 0 ≤ lam) + (hrate : Real.exp (lam * ((K : ℝ) * (M : ℝ))) * ((K : ℝ) + 2) ≤ 2 * (K : ℝ)) (x : alpha) : + ∫⁻ omega, ContinuousPath.exponentialStoppingWeight lam (ContinuousPath.exitTime U) omega + ∂(IsConservative.continuousProcess P hP x) ≤ 2 := by + set A : ℝ := Real.exp (lam * ((K : ℝ) * (M : ℝ))) with hA + have hApos : (0 : ℝ) < A := Real.exp_pos _ + have hKpos : (0 : ℝ) < (K : ℝ) := by + exact_mod_cast lt_trans zero_lt_one hK1 + have hKne : (K : ℝ) ≠ 0 := hKpos.ne' + have hKsq : (0 : ℝ) < (K : ℝ) * (K : ℝ) := mul_pos hKpos hKpos + have hK2 : (0 : ℝ) < (K : ℝ) + 2 := by linarith only [hKpos] + have hAK : A < (K : ℝ) := by + have hwide : 2 * (K : ℝ) < (K : ℝ) * ((K : ℝ) + 2) := by linarith only [hKsq] + exact lt_of_mul_lt_mul_right (hrate.trans_lt hwide) hK2.le + refine (hP.lintegral_exponentialStoppingWeight_exitTime_le_of_lintegral_le_mul P hFeller hK + U hU M hM K hK1 lam hlam hAK x).trans ?_ + have hstep : (K : ℝ≥0∞)⁻¹ * ENNReal.ofReal A = ENNReal.ofReal (A / (K : ℝ)) := by + rw [← ENNReal.ofReal_coe_nnreal, ← ENNReal.ofReal_inv_of_pos hKpos, + ← ENNReal.ofReal_mul (by positivity), div_eq_inv_mul] + have hsub : (1 : ℝ≥0∞) - ENNReal.ofReal (A / (K : ℝ)) = ENNReal.ofReal (1 - A / (K : ℝ)) := by + rw [ENNReal.ofReal_sub _ (by positivity), ENNReal.ofReal_one] + have hgoal : A ≤ 2 * (1 - A / (K : ℝ)) := by + rw [← sub_nonneg] + have hid : 2 * (1 - A / (K : ℝ)) - A = (2 * (K : ℝ) - A * ((K : ℝ) + 2)) / (K : ℝ) := by + field_simp + ring + rw [hid] + exact div_nonneg (by linarith only [hrate]) hKpos.le + rw [hstep, hsub, ← div_eq_mul_inv, + ENNReal.div_le_iff_le_mul (Or.inr (by simp)) (Or.inl ENNReal.ofReal_ne_top), + show (2 : ℝ≥0∞) = ENNReal.ofReal 2 by simp, ← ENNReal.ofReal_mul (by norm_num)] + exact ENNReal.ofReal_le_ofReal hgoal + +/-- **Markov's inequality supplies the survival hypothesis.** A uniform bound `M` on the expected +exit time from `U` bounds the probability of surviving the horizon `2 M` by one half, hence gives +an exponential moment at every rate with `exp (lam * 2 M) < 2`. This is the multiplier `K = 2` of +`IsConservative.lintegral_exponentialStoppingWeight_exitTime_le_of_lintegral_le_mul`. -/ +theorem IsConservative.lintegral_exponentialStoppingWeight_exitTime_le_of_lintegral_le + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (U : Set alpha) (hU : IsOpen U) (M : NNReal) + (hM : ∀ y, ∫⁻ omega, ContinuousPath.exitTime U omega + ∂(IsConservative.continuousProcess P hP y) ≤ (M : ℝ≥0∞)) + (lam : ℝ) (hlam : 0 ≤ lam) (hrate : Real.exp (lam * (2 * (M : ℝ))) < 2) (x : alpha) : + ∫⁻ omega, ContinuousPath.exponentialStoppingWeight lam (ContinuousPath.exitTime U) omega + ∂(IsConservative.continuousProcess P hP x) + ≤ ENNReal.ofReal (Real.exp (lam * (2 * (M : ℝ)))) * + (1 - 2⁻¹ * ENNReal.ofReal (Real.exp (lam * (2 * (M : ℝ)))))⁻¹ := by + have hmain := hP.lintegral_exponentialStoppingWeight_exitTime_le_of_lintegral_le_mul P hFeller + hK U hU M hM 2 one_lt_two lam hlam (by simpa only [NNReal.coe_ofNat] using hrate) x + simpa only [NNReal.coe_ofNat, ENNReal.coe_ofNat] using hmain + +/-- The elementary bound `t ^ p ≤ (p / (lam * e)) ^ p * exp (lam * t)` on the nonnegative +half-line. -/ +private theorem pow_le_mul_exp (lam : ℝ) (hlam : 0 < lam) (p : ℕ) (t : ℝ) (ht : 0 ≤ t) : + t ^ p ≤ ((p : ℝ) / (lam * Real.exp 1)) ^ p * Real.exp (lam * t) := by + rcases Nat.eq_zero_or_pos p with hp | hp + · subst hp + simpa only [pow_zero, one_mul] using Real.one_le_exp (mul_nonneg hlam.le ht) + have hpR : (0 : ℝ) < (p : ℝ) := Nat.cast_pos.mpr hp + have hst : 0 ≤ lam * t := mul_nonneg hlam.le ht + have h1 : lam * t / (p : ℝ) ≤ Real.exp (lam * t / (p : ℝ) - 1) := by + have h := Real.add_one_le_exp (lam * t / (p : ℝ) - 1) + linarith only [h] + have h2 : (lam * t / (p : ℝ)) ^ p ≤ Real.exp (lam * t / (p : ℝ) - 1) ^ p := + pow_le_pow_left₀ (by positivity) h1 p + have h3 : Real.exp (lam * t / (p : ℝ) - 1) ^ p = Real.exp (lam * t) / Real.exp 1 ^ p := by + rw [← Real.exp_nat_mul, ← Real.exp_nat_mul, ← Real.exp_sub] + congr 1 + field_simp + rw [h3] at h2 + have h4 := mul_le_mul_of_nonneg_left h2 + (by positivity : (0 : ℝ) ≤ ((p : ℝ) / lam) ^ p) + have h5 : ((p : ℝ) / lam) ^ p * (lam * t / (p : ℝ)) ^ p = t ^ p := by + rw [← mul_pow] + congr 1 + field_simp + have h6 : ((p : ℝ) / lam) ^ p * (Real.exp (lam * t) / Real.exp 1 ^ p) = + ((p : ℝ) / (lam * Real.exp 1)) ^ p * Real.exp (lam * t) := by + rw [div_pow, div_pow, mul_pow] + field_simp + rw [h5, h6] at h4 + exact h4 + +omit [LocallyCompactSpace alpha] in +/-- **Every polynomial moment from one exponential moment.** For a positive rate the exit time +has all its moments controlled by the exponential moment, with the explicit constant +`(p / (lam * e)) ^ p`. Taking `p = 2` bounds the second moment. -/ +theorem IsConservative.lintegral_exitTime_pow_le + (U : Set alpha) (lam : ℝ) (hlam : 0 < lam) (p : ℕ) (x : alpha) : + ∫⁻ omega, ContinuousPath.exitTime U omega ^ p ∂(IsConservative.continuousProcess P hP x) + ≤ ENNReal.ofReal (((p : ℝ) / (lam * Real.exp 1)) ^ p) * + ∫⁻ omega, ContinuousPath.exponentialStoppingWeight lam (ContinuousPath.exitTime U) omega + ∂(IsConservative.continuousProcess P hP x) := by + have hconst : (0 : ℝ) < ((p : ℝ) / (lam * Real.exp 1)) ^ p := by + rcases Nat.eq_zero_or_pos p with hp | hp + · simp only [hp, pow_zero] + norm_num + · have : (0 : ℝ) < (p : ℝ) / (lam * Real.exp 1) := by + have hpR : (0 : ℝ) < (p : ℝ) := Nat.cast_pos.mpr hp + positivity + exact pow_pos this p + have hpoint : ∀ omega : ContinuousPath alpha, + ContinuousPath.exitTime U omega ^ p ≤ + ENNReal.ofReal (((p : ℝ) / (lam * Real.exp 1)) ^ p) * + ContinuousPath.exponentialStoppingWeight lam (ContinuousPath.exitTime U) omega := by + intro omega + by_cases hne : ContinuousPath.exitTime U omega = ⊤ + · rw [ContinuousPath.exponentialStoppingWeight_of_eq_top lam _ hne, + ENNReal.mul_top (by simpa only [ne_eq, ENNReal.ofReal_eq_zero, not_le] using hconst)] + exact le_top + · rw [ContinuousPath.exponentialStoppingWeight_of_ne_top lam _ hne, + ← ENNReal.ofReal_mul hconst.le] + nth_rewrite 1 [← ENNReal.ofReal_toReal hne] + rw [← ENNReal.ofReal_pow ENNReal.toReal_nonneg] + exact ENNReal.ofReal_le_ofReal + (pow_le_mul_exp lam hlam p _ ENNReal.toReal_nonneg) + calc + ∫⁻ omega, ContinuousPath.exitTime U omega ^ p ∂(IsConservative.continuousProcess P hP x) + ≤ ∫⁻ omega, ENNReal.ofReal (((p : ℝ) / (lam * Real.exp 1)) ^ p) * + ContinuousPath.exponentialStoppingWeight lam (ContinuousPath.exitTime U) omega + ∂(IsConservative.continuousProcess P hP x) := lintegral_mono hpoint + _ = ENNReal.ofReal (((p : ℝ) / (lam * Real.exp 1)) ^ p) * + ∫⁻ omega, ContinuousPath.exponentialStoppingWeight lam + (ContinuousPath.exitTime U) omega ∂(IsConservative.continuousProcess P hP x) := + lintegral_const_mul' _ _ ENNReal.ofReal_ne_top + +end + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeLaplace.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeLaplace.lean new file mode 100644 index 0000000000..65f0dbb828 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeLaplace.lean @@ -0,0 +1,253 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw + +/-! +# The Laplace transform of an exit time + +For the continuous-path process of a conservative semigroup, this file identifies the Laplace +transform of the finite exit time from an open set with one minus the killed resolvent of the +constant function one. It also gives the resulting Chernoff bound on the early-exit event +`{exitTime U ≤ t}`. + +Main results: `IsConservative.lintegral_exp_neg_exitTime` and +`IsConservative.measure_exitTime_le_le`. + +No moment bound or almost-sure finiteness of the exit time is asserted. +-/ + +open Filter MeasureTheory ProbabilityTheory Set +open scoped ENNReal NNReal + +namespace MarkovProcess.SubMarkovKernelSemigroup + +noncomputable section + +/-- The integral of a decaying exponential over a finite interval. -/ +private theorem integral_exp_neg_mul_Ioc_zero (lam : ℝ) (hlam : 0 < lam) (A : ℝ) + (hA : 0 ≤ A) : + ∫ t in Set.Ioc (0 : ℝ) A, Real.exp (-lam * t) = + (1 - Real.exp (-lam * A)) / lam := by + rw [← intervalIntegral.integral_of_le hA] + have hn : -lam ≠ 0 := neg_ne_zero.mpr hlam.ne' + have h := intervalIntegral.integral_comp_mul_left + (f := Real.exp) (a := 0) (b := A) hn + rw [mul_zero, integral_exp] at h + rw [show (fun t : ℝ ↦ Real.exp (-lam * t)) = + fun t ↦ Real.exp ((-lam) * t) by funext t; rw [neg_mul], h] + simp only [smul_eq_mul, Real.exp_zero] + field_simp + ring + +/-- The improper integral of a decaying exponential on the positive half-line. -/ +private theorem integral_exp_neg_mul_Ioi_zero (lam : ℝ) (hlam : 0 < lam) : + ∫ t in Set.Ioi (0 : ℝ), Real.exp (-lam * t) = lam⁻¹ := + Semigroup.StronglyContinuousContractionSemigroup.integral_exp_neg_mul_Ioi_zero hlam + +/-- The `ℝ≥0∞` integral of a decaying exponential over a finite interval. -/ +private theorem lintegral_exp_neg_mul_Ioc_zero (lam : ℝ) (hlam : 0 < lam) (A : ℝ) + (hA : 0 ≤ A) : + ∫⁻ t in Set.Ioc (0 : ℝ) A, ENNReal.ofReal (Real.exp (-lam * t)) = + ENNReal.ofReal ((1 - Real.exp (-lam * A)) / lam) := by + rw [← integral_exp_neg_mul_Ioc_zero lam hlam A hA] + exact (ofReal_integral_eq_lintegral_ofReal + ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).integrableOn_Ioc) + (Eventually.of_forall fun t ↦ (Real.exp_pos _).le)).symm + +/-- The `ℝ≥0∞` integral of a decaying exponential on the positive half-line. -/ +private theorem lintegral_exp_neg_mul_Ioi_zero (lam : ℝ) (hlam : 0 < lam) : + ∫⁻ t in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) = + ENNReal.ofReal lam⁻¹ := by + rw [← integral_exp_neg_mul_Ioi_zero lam hlam] + exact (ofReal_integral_eq_lintegral_ofReal + (exp_neg_integrableOn_Ioi 0 hlam) + (Eventually.of_forall fun t ↦ (Real.exp_pos _).le)).symm + +/-- Multiplying the discounted occupation time below an extended horizon by the discount rate +gives one minus the discounted terminal weight, with the latter set to zero at infinity. -/ +private theorem ofReal_mul_lintegral_exp_neg_mul_indicator (lam : ℝ) (hlam : 0 < lam) + (tau : ℝ≥0∞) : + ENNReal.ofReal lam * + (∫⁻ t in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau}.indicator 1 t) = + 1 - ({tau | tau < ⊤} : Set ℝ≥0∞).indicator + (fun tau ↦ ENNReal.ofReal (Real.exp (-lam * tau.toReal))) tau := by + let S : Set ℝ := {t | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau} + have hS : MeasurableSet S := measurableSet_lt + (measurable_coe_nnreal_ennreal.comp measurable_real_toNNReal) measurable_const + have hfun : (fun t : ℝ ↦ ENNReal.ofReal (Real.exp (-lam * t)) * S.indicator 1 t) = + S.indicator (fun t ↦ ENNReal.ofReal (Real.exp (-lam * t))) := by + funext t + by_cases ht : t ∈ S + · simp only [neg_mul, Set.indicator_of_mem ht, Pi.one_apply, mul_one] + · simp only [neg_mul, Set.indicator_of_notMem ht, mul_zero] + rw [hfun, setLIntegral_indicator hS] + by_cases htau : tau = ⊤ + · rw [ContinuousPath.survivalSet tau, if_pos htau, + lintegral_exp_neg_mul_Ioi_zero lam hlam] + subst tau + have hnot : (⊤ : ℝ≥0∞) ∉ {tau | tau < ⊤} := by + simp only [mem_ofPred_eq, lt_self_iff_false, not_false_eq_true] + rw [Set.indicator_of_notMem hnot, tsub_zero] + rw [← ENNReal.ofReal_mul hlam.le] + simp only [mul_inv_cancel₀ hlam.ne', ENNReal.ofReal_one] + · rw [ContinuousPath.survivalSet tau, if_neg htau] + rw [show volume.restrict (Set.Ioo (0 : ℝ) tau.toReal) = + volume.restrict (Set.Ioc 0 tau.toReal) from + Measure.restrict_congr_set Ioo_ae_eq_Ioc] + rw [lintegral_exp_neg_mul_Ioc_zero lam hlam tau.toReal ENNReal.toReal_nonneg] + have hmem : tau ∈ {tau | tau < ⊤} := lt_top_iff_ne_top.mpr htau + rw [Set.indicator_of_mem hmem] + rw [← ENNReal.ofReal_mul hlam.le, mul_div_cancel₀ _ hlam.ne', + ENNReal.ofReal_sub _ (Real.exp_pos _).le, ENNReal.ofReal_one] + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) +variable (U : Set alpha) (hU : IsOpen U) + +/-- The killed resolvent of one is the expected discounted occupation time before exit. -/ +private theorem killedResolvent_one_eq_lintegral (lam : ℝ) (x : alpha) : + IsConservative.killedResolvent P hP U hU lam (fun _ ↦ 1) x = + ∫⁻ omega, (∫⁻ t in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < + ContinuousPath.exitTime U omega}.indicator 1 t) + ∂(IsConservative.continuousProcess P hP x) := by + rw [IsConservative.killedResolvent_eq_lintegral P hP U hU lam measurable_const x] + refine lintegral_congr fun omega ↦ ?_ + refine setLIntegral_congr_fun measurableSet_Ioi fun t _ ↦ ?_ + simp only [Set.indicator_apply, Pi.one_apply] + +/-- **The Laplace transform of the exit time.** The discounted mass of paths which leave the +open set in finite time is one minus the discount rate times the killed resolvent of one. -/ +theorem IsConservative.lintegral_exp_neg_exitTime (lam : ℝ) (hlam : 0 < lam) (x : alpha) : + ∫⁻ omega, ({omega | ContinuousPath.exitTime U omega < ⊤} : Set _).indicator + (fun omega ↦ ENNReal.ofReal + (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal))) omega + ∂(IsConservative.continuousProcess P hP x) = + 1 - ENNReal.ofReal lam * + IsConservative.killedResolvent P hP U hU lam (fun _ ↦ 1) x := by + let Q : Measure (ContinuousPath alpha) := IsConservative.continuousProcess P hP x + let S : Set (ContinuousPath alpha) := + {omega | ContinuousPath.exitTime U omega < ⊤} + let W : ContinuousPath alpha → ℝ≥0∞ := S.indicator fun omega ↦ + ENNReal.ofReal (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal)) + let H : ContinuousPath alpha → ℝ≥0∞ := fun omega ↦ + ∫⁻ t in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < + ContinuousPath.exitTime U omega}.indicator 1 t + have hExit : Measurable fun omega : ContinuousPath alpha ↦ ContinuousPath.exitTime U omega := + ContinuousPath.measurable_exitTime U hU + have hS : MeasurableSet S := measurableSet_lt hExit measurable_const + have hW : Measurable W := by + exact (ENNReal.measurable_ofReal.comp + (Real.continuous_exp.measurable.comp + (measurable_const.mul (ENNReal.measurable_toReal.comp hExit)))).indicator hS + have hJoint : Measurable (fun p : ℝ × ContinuousPath alpha ↦ + ENNReal.ofReal (Real.exp (-lam * p.1)) * + {p : ℝ × ContinuousPath alpha | + ((Real.toNNReal p.1 : NNReal) : ℝ≥0∞) < + ContinuousPath.exitTime U p.2}.indicator 1 p) := by + have hset : MeasurableSet {p : ℝ × ContinuousPath alpha | + ((Real.toNNReal p.1 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U p.2} := + measurableSet_lt + (measurable_coe_nnreal_ennreal.comp (measurable_real_toNNReal.comp measurable_fst)) + (hExit.comp measurable_snd) + exact (ENNReal.measurable_ofReal.comp + ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.comp + measurable_fst)).mul (measurable_const.indicator hset) + have hH : Measurable H := by + exact hJoint.lintegral_prod_left' (μ := volume.restrict (Set.Ioi 0)) + have hWle : W ≤ fun _ ↦ 1 := by + intro omega + by_cases homega : omega ∈ S + · change S.indicator (fun omega ↦ ENNReal.ofReal + (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal))) omega ≤ 1 + rw [Set.indicator_of_mem homega] + rw [← ENNReal.ofReal_one] + exact ENNReal.ofReal_le_ofReal ((Real.exp_le_one_iff).mpr + (mul_nonpos_of_nonpos_of_nonneg (neg_nonpos.mpr hlam.le) ENNReal.toReal_nonneg)) + · change S.indicator (fun omega ↦ ENNReal.ofReal + (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal))) omega ≤ 1 + rw [Set.indicator_of_notMem homega] + exact zero_le + have hWint : ∫⁻ omega, W omega ∂Q ≤ 1 := by + calc + ∫⁻ omega, W omega ∂Q ≤ ∫⁻ _omega, 1 ∂Q := lintegral_mono hWle + _ = 1 := by simp only [lintegral_one, measure_univ] + have hWtop : ∫⁻ omega, W omega ∂Q ≠ ⊤ := + ne_top_of_le_ne_top ENNReal.one_ne_top hWint + have hSub : ∫⁻ omega, 1 - W omega ∂Q = 1 - ∫⁻ omega, W omega ∂Q := by + rw [lintegral_sub hW hWtop (Eventually.of_forall hWle)] + simp only [lintegral_one, measure_univ] + change ∫⁻ omega, W omega ∂Q = + 1 - ENNReal.ofReal lam * IsConservative.killedResolvent P hP U hU lam (fun _ ↦ 1) x + rw [killedResolvent_one_eq_lintegral P hP U hU lam x] + change ∫⁻ omega, W omega ∂Q = 1 - ENNReal.ofReal lam * ∫⁻ omega, H omega ∂Q + rw [← lintegral_const_mul _ hH] + have hKey : (fun omega ↦ ENNReal.ofReal lam * H omega) = fun omega ↦ 1 - W omega := by + funext omega + exact ofReal_mul_lintegral_exp_neg_mul_indicator lam hlam + (ContinuousPath.exitTime U omega) + rw [hKey, hSub] + exact (ENNReal.sub_sub_cancel ENNReal.one_ne_top hWint).symm + +include hU in +/-- The early-exit event satisfies a Chernoff bound by the discounted finite-exit mass. -/ +theorem IsConservative.measure_exitTime_le_le (lam : ℝ) (hlam : 0 ≤ lam) + (t : NNReal) (x : alpha) : + IsConservative.continuousProcess P hP x + {omega | ContinuousPath.exitTime U omega ≤ (t : ℝ≥0∞)} ≤ + ENNReal.ofReal (Real.exp (lam * (t : ℝ))) * + ∫⁻ omega, ({omega | ContinuousPath.exitTime U omega < ⊤} : Set _).indicator + (fun omega ↦ ENNReal.ofReal + (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal))) omega + ∂(IsConservative.continuousProcess P hP x) := by + let Q : Measure (ContinuousPath alpha) := IsConservative.continuousProcess P hP x + let A : Set (ContinuousPath alpha) := + {omega | ContinuousPath.exitTime U omega ≤ (t : ℝ≥0∞)} + let S : Set (ContinuousPath alpha) := + {omega | ContinuousPath.exitTime U omega < ⊤} + let W : ContinuousPath alpha → ℝ≥0∞ := S.indicator fun omega ↦ + ENNReal.ofReal (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal)) + have hExit : Measurable fun omega : ContinuousPath alpha ↦ ContinuousPath.exitTime U omega := + ContinuousPath.measurable_exitTime U hU + have hA : MeasurableSet A := measurableSet_le hExit measurable_const + have hS : MeasurableSet S := measurableSet_lt hExit measurable_const + have hW : Measurable W := by + exact (ENNReal.measurable_ofReal.comp + (Real.continuous_exp.measurable.comp + (measurable_const.mul (ENNReal.measurable_toReal.comp hExit)))).indicator hS + change Q A ≤ ENNReal.ofReal (Real.exp (lam * (t : ℝ))) * ∫⁻ omega, W omega ∂Q + rw [← lintegral_indicator_one hA, ← lintegral_const_mul _ hW] + refine lintegral_mono fun omega ↦ ?_ + by_cases homega : omega ∈ A + · rw [Set.indicator_of_mem homega] + have htauTop : ContinuousPath.exitTime U omega ≠ ⊤ := + ne_top_of_le_ne_top ENNReal.coe_ne_top homega + have homegaS : omega ∈ S := lt_top_iff_ne_top.mpr htauTop + change 1 ≤ ENNReal.ofReal (Real.exp (lam * (t : ℝ))) * + S.indicator (fun omega ↦ ENNReal.ofReal + (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal))) omega + rw [Set.indicator_of_mem homegaS, ← ENNReal.ofReal_mul (Real.exp_pos _).le, + ← Real.exp_add] + rw [← ENNReal.ofReal_one] + refine ENNReal.ofReal_le_ofReal (Real.one_le_exp ?_) + have htau : (ContinuousPath.exitTime U omega).toReal ≤ (t : ℝ) := by + exact (ENNReal.toReal_le_toReal htauTop ENNReal.coe_ne_top).mpr homega + calc + 0 ≤ lam * ((t : ℝ) - (ContinuousPath.exitTime U omega).toReal) := + mul_nonneg hlam (sub_nonneg.mpr htau) + _ = lam * (t : ℝ) + -lam * (ContinuousPath.exitTime U omega).toReal := by ring + · rw [Set.indicator_of_notMem homega] + exact zero_le + +end + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExpectedExitTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExpectedExitTime.lean new file mode 100644 index 0000000000..f8f9016529 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExpectedExitTime.lean @@ -0,0 +1,153 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop + +/-! +# The expected exit time, untruncated + +The expected exit time bound of `Trajectory/DynkinStopping.lean` is stated for the exit time +truncated at a deterministic horizon `K`, uniformly in `K`. This file removes the truncation by +monotone convergence: under the same hypotheses (`L f ≤ -1` on the open set `U`, `f ≥ m`), + + `E_x τ_U ≤ f x - m` (`IsFellerKernelSemigroup.lintegral_exitTime_le`), + +as an `ℝ≥0∞`-valued integral of the `ℝ≥0∞`-valued exit time, so in particular the exit time from +`U` is almost surely finite from every starting point (`ae_exitTime_lt_top`). + +It also records that the truncated exit time of `Path/ExitTime.lean` is the generic truncation +`StoppingTime.truncTime` of `Trajectory/StoppingLtTop.lean` applied to `exitTimeTop` +(`ContinuousPath.exitTimeTrunc_eq_truncTime`), and the monotone limit +`ContinuousPath.iSup_exitTimeTrunc : ⨆ n, exitTimeTrunc U n ω = exitTime U ω`. +-/ + +open MeasureTheory ProbabilityTheory Filter +open scoped ENNReal NNReal ZeroAtInfty + +namespace MarkovProcess + +namespace ContinuousPath + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +/-- The truncated exit time is the generic truncation of the `WithTop`-valued exit time. -/ +theorem exitTimeTrunc_eq_truncTime (U : Set alpha) (K : NNReal) (omega : ContinuousPath alpha) : + exitTimeTrunc U K omega = StoppingTime.truncTime (exitTimeTop U) K omega := by + apply WithTop.coe_injective + rw [coe_exitTimeTrunc, StoppingTime.coe_truncTime] + +/-- The truncated exit time, read in `ℝ≥0∞`, is the minimum of the exit time and the horizon. -/ +theorem coe_exitTimeTrunc_ennreal (U : Set alpha) (K : NNReal) (omega : ContinuousPath alpha) : + ((exitTimeTrunc U K omega : NNReal) : ℝ≥0∞) = min (exitTime U omega) (K : ℝ≥0∞) := + coe_exitTimeTrunc U K omega + +/-- Truncations at the natural horizons increase to the exit time. -/ +theorem iSup_exitTimeTrunc (U : Set alpha) (omega : ContinuousPath alpha) : + ⨆ n : ℕ, ((exitTimeTrunc U n omega : NNReal) : ℝ≥0∞) = exitTime U omega := by + have hmin : ∀ n : ℕ, ((exitTimeTrunc U n omega : NNReal) : ℝ≥0∞) = + min (exitTime U omega) (n : ℝ≥0∞) := by + intro n + rw [coe_exitTimeTrunc_ennreal, ENNReal.coe_natCast] + simp only [hmin] + apply le_antisymm + · exact iSup_le fun n ↦ min_le_left _ _ + · rcases eq_or_ne (exitTime U omega) ⊤ with htop | hne + · rw [htop] + simp only [le_top, min_eq_right, ENNReal.iSup_natCast] + · obtain ⟨n, hn⟩ := exists_nat_ge (exitTime U omega).toNNReal + refine le_iSup_of_le n (le_of_eq ?_) + rw [min_eq_left] + rw [← ENNReal.coe_toNNReal hne, ← ENNReal.coe_natCast, ENNReal.coe_le_coe] + exact_mod_cast hn + +/-- Truncations at the natural horizons are monotone in the horizon. -/ +theorem monotone_exitTimeTrunc (U : Set alpha) (omega : ContinuousPath alpha) : + Monotone fun n : ℕ ↦ ((exitTimeTrunc U n omega : NNReal) : ℝ≥0∞) := by + intro m n hmn + simp only [coe_exitTimeTrunc_ennreal, ENNReal.coe_natCast] + exact min_le_min_left _ (Nat.cast_le.mpr hmn) + +end ContinuousPath + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + [LocallyCompactSpace alpha] + +variable {P : SubMarkovKernelSemigroup alpha} + +omit [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + [LocallyCompactSpace alpha] in +/-- The truncated exit time is measurable on path space. -/ +theorem measurable_coe_exitTimeTrunc (U : Set alpha) (hU : IsOpen U) (K : NNReal) : + Measurable fun omega : ContinuousPath alpha ↦ + ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ≥0∞) := + measurable_coe_nnreal_ennreal.comp + (ContinuousPath.measurable_of_isStoppingTime _ + (ContinuousPath.isStoppingTime_exitTimeTrunc U hU K)) + +omit [LocallyCompactSpace alpha] in +/-- The `ℝ≥0∞`-valued expectation of the truncated exit time is the `ofReal` of its real +expectation. -/ +theorem lintegral_exitTimeTrunc_eq (hP : P.IsConservative) (U : Set alpha) (hU : IsOpen U) + (K : NNReal) (x : alpha) : + ∫⁻ omega, ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ≥0∞) + ∂(IsConservative.continuousProcess P hP x) = + ENNReal.ofReal (∫ omega, ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ) + ∂(IsConservative.continuousProcess P hP x)) := by + have hmeas : Measurable fun omega : ContinuousPath alpha ↦ + ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ) := + measurable_coe_nnreal_real.comp + (ContinuousPath.measurable_of_isStoppingTime _ + (ContinuousPath.isStoppingTime_exitTimeTrunc U hU K)) + have hint : Integrable (fun omega : ContinuousPath alpha ↦ + ((ContinuousPath.exitTimeTrunc U K omega : NNReal) : ℝ)) + (IsConservative.continuousProcess P hP x) := by + refine Integrable.of_bound hmeas.aestronglyMeasurable (K : ℝ) + (Eventually.of_forall fun omega ↦ ?_) + rw [Real.norm_of_nonneg NNReal.zero_le_coe] + exact NNReal.coe_le_coe.mpr (ContinuousPath.exitTimeTrunc_le U K omega) + rw [ofReal_integral_eq_lintegral_ofReal hint + (Eventually.of_forall fun omega ↦ NNReal.zero_le_coe)] + refine lintegral_congr fun omega ↦ ?_ + rw [ENNReal.ofReal_coe_nnreal] + +/-- **The expected exit time is bounded, without truncation.** If `L f ≤ -1` on the open set `U` +and `f ≥ m`, then the exit time from `U` has expectation at most `f x - m` from every starting +point, as an `ℝ≥0∞`-valued integral. -/ +theorem IsFellerKernelSemigroup.lintegral_exitTime_le (hP : P.IsConservative) + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (U : Set alpha) (hU : IsOpen U) + (hLf : ∀ y ∈ U, (hFeller.c0Semigroup.generator f) y ≤ -1) {m : ℝ} + (hm : ∀ y, m ≤ (f : C₀(alpha, ℝ)) y) (x : alpha) : + ∫⁻ omega, ContinuousPath.exitTime U omega ∂(IsConservative.continuousProcess P hP x) ≤ + ENNReal.ofReal ((f : C₀(alpha, ℝ)) x - m) := by + have hsup : (fun omega : ContinuousPath alpha ↦ ContinuousPath.exitTime U omega) = + fun omega ↦ ⨆ n : ℕ, ((ContinuousPath.exitTimeTrunc U n omega : NNReal) : ℝ≥0∞) := + funext fun omega ↦ (ContinuousPath.iSup_exitTimeTrunc U omega).symm + rw [hsup, lintegral_iSup (fun n ↦ measurable_coe_exitTimeTrunc U hU n) + (fun m n hmn omega ↦ ContinuousPath.monotone_exitTimeTrunc U omega hmn)] + refine iSup_le fun n ↦ ?_ + rw [lintegral_exitTimeTrunc_eq hP U hU n x] + exact ENNReal.ofReal_le_ofReal (hFeller.integral_exitTimeTrunc_le hP hK f U hU hLf hm n x) + +/-- Under the hypotheses of the expected exit time bound, the exit time from `U` is almost surely +finite from every starting point. -/ +theorem IsFellerKernelSemigroup.ae_exitTime_lt_top (hP : P.IsConservative) + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (U : Set alpha) (hU : IsOpen U) + (hLf : ∀ y ∈ U, (hFeller.c0Semigroup.generator f) y ≤ -1) {m : ℝ} + (hm : ∀ y, m ≤ (f : C₀(alpha, ℝ)) y) (x : alpha) : + ∀ᵐ omega ∂(IsConservative.continuousProcess P hP x), ContinuousPath.exitTime U omega < ⊤ := + ae_lt_top (ContinuousPath.measurable_exitTime U hU) + (ne_top_of_le_ne_top ENNReal.ofReal_ne_top + (hFeller.lintegral_exitTime_le hP hK f U hU hLf hm x)) + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerConditional.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerConditional.lean new file mode 100644 index 0000000000..d888267a5b --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerConditional.lean @@ -0,0 +1,62 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart + +/-! +# Deterministic-time conditional expectation for the Feller trajectory + +At every physical time, the conditional expectation of a bounded strongly measurable functional +of the shifted canonical Feller trajectory, given the canonical filtration at that time, is the +path-kernel expectation started from the current state. The proof passes the event-restricted +deterministic restart identity through the generic continuous-path conditional-expectation +bridge. + +The time here is deterministic. The corresponding statement at a finite stopping time is in +`Trajectory/FellerStoppingConditional.lean`, and at a stopping time that may be infinite in +`Trajectory/StoppingLtTop.lean`. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess.SubMarkovKernelSemigroup +noncomputable section +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [LocallyCompactSpace alpha] [StandardBorelSpace alpha] [Nonempty alpha] +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace Real E] [CompleteSpace E] + +/-- At every physical time, the conditional expectation of a bounded functional of the shifted +Feller trajectory given the canonical filtration is its path-kernel expectation started from the +current state. -/ +theorem IsFellerKernelSemigroup.continuousPathTrajectory_condExp_shift + (P : SubMarkovKernelSemigroup alpha) (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (x : alpha) (s : NNReal) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : ℝ) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + ((continuousPathTrajectory P hP default) x)[fun omega ↦ + F (ContinuousPath.shift s omega)| + ContinuousPath.canonicalFiltration (alpha := alpha) s] =ᵐ[ + (continuousPathTrajectory P hP default) x] + fun omega ↦ ∫ eta, F eta ∂(continuousPathTrajectory P hP default) + (omega s) := by + apply ContinuousPath.condExp_shift_ae_eq_integral_pathKernel_of_restrict_map + (continuousPathTrajectory P hP default) x s + · exact hFeller.continuousPathTrajectory_restrict_map_shift + P hP default hK x s + · exact hF + · exact hFC + +end +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerCountableStoppingRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerCountableStoppingRestart.lean new file mode 100644 index 0000000000..cdcb171dbf --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerCountableStoppingRestart.lean @@ -0,0 +1,67 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart + +/-! +# Conditional restart of the Feller trajectory at countable-range stopping times + +For a finite `NNReal`-valued stopping time with countable range, the conditional expectation of a +bounded strongly measurable functional of the canonical Feller trajectory shifted at that time, +given the stopped sigma-algebra, is the path-kernel expectation started from the state at that +time. The proof feeds the all-time event-restricted deterministic restart identity into the +generic countable-range stopping-time bridge. + +The stopping time here has countable range. An arbitrary finite stopping time is covered in +`Trajectory/FellerStoppingConditional.lean`, and a `WithTop`-valued time that can be infinite in +`Trajectory/StoppingLtTop.lean`. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess.SubMarkovKernelSemigroup +noncomputable section +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [LocallyCompactSpace alpha] [StandardBorelSpace alpha] [Nonempty alpha] +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace Real E] [CompleteSpace E] + +/-- At a finite stopping time with countable range, the conditional expectation of a bounded +functional of the shifted Feller trajectory given the stopped sigma-algebra is its path-kernel +expectation started from the state at that time. -/ +theorem IsFellerKernelSemigroup.continuousPathTrajectory_condExp_shift_countableStoppingTime + (P : SubMarkovKernelSemigroup alpha) (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (x : alpha) (tau : ContinuousPath alpha → NNReal) + (htau : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (tau omega : WithTop NNReal))) + (htauRange : (Set.range tau).Countable) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : ℝ) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + ((continuousPathTrajectory P hP default) x)[fun omega ↦ + F (ContinuousPath.shift (tau omega) omega)|htau.measurableSpace] =ᵐ[ + (continuousPathTrajectory P hP default) x] + fun omega ↦ ∫ eta, F eta ∂(continuousPathTrajectory P hP default) + (omega (tau omega)) := by + apply + ContinuousPath.condExp_shift_stoppingTime_ae_eq_integral_pathKernel_of_restart_on_range + (continuousPathTrajectory P hP default) x tau htau htauRange + · intro S _ + exact hFeller.continuousPathTrajectory_restrict_map_shift + P hP default hK x S + · exact hF + · exact hFC + +end +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerFiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerFiniteMarginals.lean new file mode 100644 index 0000000000..1cb4cd919e --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerFiniteMarginals.lean @@ -0,0 +1,61 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity + +/-! +# Arbitrary-time finite marginals of Feller trajectories + +This file removes the compact-test convergence premise from the earlier arbitrary-time +finite-marginal reduction. For a conservative Feller kernel semigroup whose dense trajectory has +the stated Kolmogorov control, every finite family of continuous-path coordinates has exactly the +finite-set-kernel law. + +The theorem is stated for an arbitrary such semigroup; no particular semigroup is singled out, +and no Hunt-process property is asserted. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped NNReal + +namespace MarkovProcess + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [LocallyCompactSpace alpha] + +namespace SubMarkovKernelSemigroup + +open IsConservative + +variable [CompleteSpace alpha] [StandardBorelSpace alpha] [Nonempty alpha] + +/-- A conservative Feller trajectory with the required Kolmogorov control has the prescribed +finite-dimensional law at every finite set of nonnegative-real times. -/ +theorem IsFellerKernelSemigroup.continuousPathTrajectory_map_finiteTimeSet + (P : SubMarkovKernelSemigroup alpha) (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (I : Finset NNReal) : + (continuousPathTrajectory P hP default).map + (ContinuousPath.finiteEvaluation (fun t : I ↦ (t : NNReal))) = + finiteSetKernel P I := by + obtain ⟨q, hq⟩ := exists_denseTime_finset_seq_tendsto I + apply IsConservative.continuousPathTrajectory_map_finiteTimeSet_of_integral_tendsto + P hP default hK I q hq + intro x f + exact hFeller.tendsto_integral_compactlySupported_finiteDenseApproximationKernel + hP q hq f x + +end SubMarkovKernelSemigroup + +end + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerRestrictedRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerRestrictedRestart.lean new file mode 100644 index 0000000000..6654f46c13 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerRestrictedRestart.lean @@ -0,0 +1,196 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional +import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove +import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification +import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification + + +/-! +# Event-restricted deterministic restart for the Feller trajectory + +The canonical continuous trajectory of a conservative Feller kernel semigroup restarts after +restriction to an event in the deterministic-time canonical filtration. The proof approaches the +time strictly from above by dense times, identifies every finite dense future marginal by compact +tests, and then uses measure identification on dense restrictions. + +The time here is deterministic. The strong Markov property at a finite stopping time is in +`Trajectory/FellerStoppingRestart.lean`. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped NNReal CompactlySupported ZeroAtInfty + +namespace MarkovProcess.SubMarkovKernelSemigroup +noncomputable section +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [LocallyCompactSpace alpha] [StandardBorelSpace alpha] [Nonempty alpha] + +omit [CompleteSpace alpha] [LocallyCompactSpace alpha] [StandardBorelSpace alpha] + [Nonempty alpha] in +private theorem map_denseRestriction_restrict_integral + (nu : Measure (ContinuousPath alpha)) (J : Finset DenseTime) + (f : C_c(J → alpha, ℝ)) : + ∫ z, f z ∂((nu.map ContinuousPath.denseRestriction).map J.restrict) = + ∫ omega, f (J.restrict (ContinuousPath.denseRestriction omega)) ∂nu := by + have hdense := ContinuousPath.measurable_denseRestriction (alpha := alpha) + have hrestrict := Finset.measurable_restrict (X := fun _ ↦ alpha) J + rw [Measure.map_map hrestrict hdense] + exact integral_map (hrestrict.comp hdense).aemeasurable + f.continuous.stronglyMeasurable.aestronglyMeasurable + +private theorem composed_denseRestriction_integral + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (mu : Measure (ContinuousPath alpha)) [IsFiniteMeasure mu] + (r : NNReal) (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) : + ∫ z, f z ∂(((Kernel.comap (continuousPathTrajectory P hP default) + (ContinuousPath.coordinateProcess (alpha := alpha) r) + (ContinuousPath.measurable_coordinateProcess r) ∘ₘ mu).map + ContinuousPath.denseRestriction).map J.restrict) = + MeasureTheory.integral mu (fun omega ↦ + MeasureTheory.integral + (((finiteSetKernel P (denseTimePhysicalSet J)).map + (DenseTimePath.pullbackPhysicalSet J)) (omega r)) f) := by + let Q := continuousPathTrajectory P hP default + let KJ := (finiteSetKernel P (denseTimePhysicalSet J)).map + (DenseTimePath.pullbackPhysicalSet J) + have heval := ContinuousPath.measurable_coordinateProcess (alpha := alpha) r + have hdense := ContinuousPath.measurable_denseRestriction (alpha := alpha) + have hrestrict := Finset.measurable_restrict (X := fun _ ↦ alpha) J + have hQJ : (Q.map ContinuousPath.denseRestriction).map J.restrict = KJ := by + exact IsConservative.continuousPathTrajectory_map_denseRestriction_map_restrict + P hP default hK J + have hkernel : + ((Kernel.comap Q (ContinuousPath.coordinateProcess r) heval).map + ContinuousPath.denseRestriction).map J.restrict = + Kernel.comap KJ (ContinuousPath.coordinateProcess r) heval := by + rw [← Kernel.comap_map_comm Q heval hdense, + ← Kernel.comap_map_comm (Q.map ContinuousPath.denseRestriction) heval hrestrict, + hQJ] + have hmeasure : + (((Kernel.comap Q (ContinuousPath.coordinateProcess r) heval ∘ₘ mu).map + ContinuousPath.denseRestriction).map J.restrict) = + Kernel.comap KJ (ContinuousPath.coordinateProcess r) heval ∘ₘ mu := by + rw [Measure.map_comp mu _ hdense, Measure.map_comp mu _ hrestrict, hkernel] + rw [hmeasure, Measure.comp_eq_comp_const_apply] + let : IsMarkovKernel KJ := by + dsimp only [KJ] + let : IsMarkovKernel (finiteSetKernel P (denseTimePhysicalSet J)) := + hP.isMarkovKernel_finiteSetKernel P (denseTimePhysicalSet J) + exact Kernel.IsMarkovKernel.map _ (DenseTimePath.measurable_pullbackPhysicalSet J) + let : IsMarkovKernel + (Kernel.comap KJ (ContinuousPath.coordinateProcess r) heval) := inferInstance + let : IsFiniteMeasure + ((Kernel.comap KJ (ContinuousPath.coordinateProcess r) heval ∘ₘ mu)) := inferInstance + have hfint : Integrable f + (Kernel.comap KJ (ContinuousPath.coordinateProcess r) heval ∘ₘ mu) := + f.integrable + rw [Measure.comp_eq_comp_const_apply] at hfint + have hi := Kernel.integral_comp hfint + simpa only [Kernel.const_apply, Kernel.comap_apply, ContinuousPath.coordinateProcess_apply, + Q, KJ] using hi + +/-- Restricting the Feller trajectory to a deterministic-past event and then shifting gives +the trajectory kernel restarted from the state at that deterministic time. -/ +theorem IsFellerKernelSemigroup.continuousPathTrajectory_restrict_map_shift + (P : SubMarkovKernelSemigroup alpha) (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (x : alpha) (s : NNReal) : + ∀ A : Set (ContinuousPath alpha), + MeasurableSet[ContinuousPath.canonicalFiltration (alpha := alpha) s] A → + ((((continuousPathTrajectory P hP default) x).restrict A).map + (ContinuousPath.shift s)) = + Kernel.comap (continuousPathTrajectory P hP default) + (ContinuousPath.coordinateProcess (alpha := alpha) s) + (ContinuousPath.measurable_coordinateProcess s) ∘ₘ + (((continuousPathTrajectory P hP default) x).restrict A) := by + intro A hA + let Q := continuousPathTrajectory P hP default + let mu := (Q x).restrict A + obtain ⟨q, _, hqAbove, hq⟩ := exists_denseTime_seq_strictAnti_tendsto s + have hAq (n : ℕ) : MeasurableSet[ContinuousPath.canonicalFiltration (alpha := alpha) + (DenseTime.castOrderEmbedding (q n))] A := + (ContinuousPath.canonicalFiltration (alpha := alpha)).mono + (le_of_lt (hqAbove n)) A hA + have hr (n : ℕ) : + mu.map (ContinuousPath.shift (DenseTime.castOrderEmbedding (q n))) = + Kernel.comap Q (ContinuousPath.coordinateProcess (alpha := alpha) + (DenseTime.castOrderEmbedding (q n))) + (ContinuousPath.measurable_coordinateProcess + (DenseTime.castOrderEmbedding (q n))) ∘ₘ mu := by + exact continuousPathTrajectory_restrict_map_shift_denseTime + P hP default hK x (q n) A (hAq n) + apply MarkovProcess.Measure.map_denseRestriction_injective + apply MarkovProcess.Measure.eq_of_map_finiteRestriction_eq + intro J + apply Measure.ext_of_integral_eq_on_compactlySupported + intro f + let L : Kernel alpha (J → alpha) := + (finiteSetKernel P (denseTimePhysicalSet J)).map + (DenseTimePath.pullbackPhysicalSet J) + let g : alpha → ℝ := fun y ↦ ∫ z, f z ∂L y + have hg_cont : Continuous g := by + exact hFeller.continuous_integral_map_finiteSetKernel_pullbackPhysicalSet hP J f + let C := ‖PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f‖ + have hg_bound (y : alpha) : ‖g y‖ ≤ C := by + exact hP.norm_integral_map_finiteSetKernel_pullbackPhysicalSet_le J f y + have hright := tendsto_integral_continuousPath_eval_of_tendsto + mu s q hq g hg_cont C hg_bound + have hleft := tendsto_integral_continuousPath_finiteDenseEvaluation_shift + mu s q hq J f + have heq (n : ℕ) : + (∫ omega, f (fun j : J ↦ omega + (DenseTime.castOrderEmbedding (q n) + DenseTime.castOrderEmbedding j)) ∂mu) = + ∫ omega, g (omega (DenseTime.castOrderEmbedding (q n))) ∂mu := by + have hm := congrArg (fun rho : Measure (ContinuousPath alpha) ↦ + (rho.map ContinuousPath.denseRestriction).map J.restrict) (hr n) + have hi := congrArg (fun rho : Measure (J → alpha) ↦ ∫ z, f z ∂rho) hm + rw [map_denseRestriction_restrict_integral, + composed_denseRestriction_integral P hP default hK] at hi + have htest : StronglyMeasurable (fun omega : ContinuousPath alpha ↦ + f (J.restrict (ContinuousPath.denseRestriction omega))) := + (f.continuous.comp (ContinuousPath.continuous_finiteEvaluation + (fun j : J ↦ DenseTime.castOrderEmbedding j))).stronglyMeasurable + rw [integral_map + (ContinuousPath.measurable_shift_fixed + (DenseTime.castOrderEmbedding (q n))).aemeasurable + htest.aestronglyMeasurable] at hi + simpa only [g, L, ContinuousPath.denseRestriction_apply, + ContinuousPath.shift_apply] using! hi + have hlimits : + (∫ omega, f (fun j : J ↦ omega (s + DenseTime.castOrderEmbedding j)) ∂mu) = + ∫ omega, g (omega s) ∂mu := + tendsto_nhds_unique hleft (by simpa only [heq] using hright) + rw [map_denseRestriction_restrict_integral, + composed_denseRestriction_integral P hP default hK] + have htest : StronglyMeasurable (fun omega : ContinuousPath alpha ↦ + f (J.restrict (ContinuousPath.denseRestriction omega))) := + (f.continuous.comp (ContinuousPath.continuous_finiteEvaluation + (fun j : J ↦ DenseTime.castOrderEmbedding j))).stronglyMeasurable + rw [integral_map (ContinuousPath.measurable_shift_fixed s).aemeasurable + htest.aestronglyMeasurable] + simpa only [ContinuousPath.denseRestriction_apply, + ContinuousPath.shift_apply] using! hlimits + +end +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerShift.lean new file mode 100644 index 0000000000..ecae4732a4 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerShift.lean @@ -0,0 +1,116 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift +import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification + +/-! +# Deterministic shifts of Feller trajectory laws + +The canonical continuous trajectory of a conservative Feller kernel semigroup restarts after +every deterministic nonnegative time. The proof identifies all finite coordinates of the dense +restriction and then uses injectivity of dense restriction on continuous-path kernels. + +This is an unconditional kernel-law identity. The conditional form is in +`Trajectory/FellerConditional.lean` and the strong Markov property in +`Trajectory/FellerStoppingRestart.lean`; no Hunt-process property is asserted. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +noncomputable section + +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [LocallyCompactSpace alpha] [StandardBorelSpace alpha] [Nonempty alpha] + +/-- Shifting the canonical continuous trajectory by a deterministic nonnegative time gives the +trajectory law mixed against the transition kernel at that time. -/ +theorem IsFellerKernelSemigroup.continuousPathTrajectory_map_shift + (P : SubMarkovKernelSemigroup alpha) (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (s : NNReal) : + (continuousPathTrajectory P hP default).map (ContinuousPath.shift s) = + (continuousPathTrajectory P hP default).comp (P s) := by + let Q := continuousPathTrajectory P hP default + apply Kernel.map_denseRestriction_injective + apply Kernel.eq_of_map_finiteRestriction_eq + intro I + let S := denseTimePhysicalSet I + let U := finiteSetTranslate s S + have hShift := ContinuousPath.measurable_shift_fixed (alpha := alpha) s + have hDense := ContinuousPath.measurable_denseRestriction (alpha := alpha) + have hRestrict := Finset.measurable_restrict (X := fun _ ↦ alpha) I + have hEval : Measurable + (ContinuousPath.finiteEvaluation (α := alpha) (fun t : U ↦ (t : NNReal))) := + (ContinuousPath.continuous_finiteEvaluation + (α := alpha) (fun t : U ↦ (t : NNReal))).measurable + have hTranslate := measurable_pullbackFiniteSetTranslate (alpha := alpha) s S + have hPhysical := DenseTimePath.measurable_pullbackPhysicalSet (alpha := alpha) I + have hcoordinates : + I.restrict ∘ (ContinuousPath.denseRestriction (alpha := alpha) ∘ + ContinuousPath.shift (alpha := alpha) s) = + (DenseTimePath.pullbackPhysicalSet (alpha := alpha) I ∘ + pullbackFiniteSetTranslate (alpha := alpha) s S) ∘ + ContinuousPath.finiteEvaluation (α := alpha) + (fun t : U ↦ (t : NNReal)) := by + funext omega t + change omega (s + DenseTime.castOrderEmbedding t) = + omega ((finiteSetTranslateEquiv s S + (DenseTime.physicalSetEquiv I t) : U) : NNReal) + rw [finiteSetTranslateEquiv_apply] + rw [DenseTime.physicalSetEquiv_apply] + calc + (((Q.map (ContinuousPath.shift s)).map ContinuousPath.denseRestriction).map + I.restrict) = + Q.map (I.restrict ∘ + (ContinuousPath.denseRestriction ∘ ContinuousPath.shift s)) := by + rw [← Kernel.map_comp_right (Q.map (ContinuousPath.shift s)) hDense hRestrict, + ← Kernel.map_comp_right Q hShift (hRestrict.comp hDense)] + rw [Function.comp_assoc] + _ = Q.map ((DenseTimePath.pullbackPhysicalSet I ∘ + pullbackFiniteSetTranslate s S) ∘ + ContinuousPath.finiteEvaluation (fun t : U ↦ (t : NNReal))) := by + rw [hcoordinates] + _ = ((Q.map (ContinuousPath.finiteEvaluation + (fun t : U ↦ (t : NNReal)))).map + (pullbackFiniteSetTranslate s S)).map + (DenseTimePath.pullbackPhysicalSet I) := by + rw [Kernel.map_comp_right Q hEval (hPhysical.comp hTranslate), + Kernel.map_comp_right (Q.map + (ContinuousPath.finiteEvaluation (fun t : U ↦ (t : NNReal)))) + hTranslate hPhysical] + _ = ((finiteSetKernel P U).map (pullbackFiniteSetTranslate s S)).map + (DenseTimePath.pullbackPhysicalSet I) := by + rw [hFeller.continuousPathTrajectory_map_finiteTimeSet P hP default hK U] + _ = ((finiteSetKernel P S).comp (P s)).map + (DenseTimePath.pullbackPhysicalSet I) := by + rw [hP.finiteSetKernel_map_pullback_translate P s S] + _ = ((finiteSetKernel P S).map + (DenseTimePath.pullbackPhysicalSet I)).comp (P s) := by + rw [Kernel.map_comp] + _ = (((Q.map ContinuousPath.denseRestriction).map I.restrict).comp (P s)) := by + rw [IsConservative.continuousPathTrajectory_map_denseRestriction_map_restrict + P hP default hK I] + _ = (((Q.comp (P s)).map ContinuousPath.denseRestriction).map I.restrict) := by + rw [Kernel.map_comp, Kernel.map_comp] + +end +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingConditional.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingConditional.lean new file mode 100644 index 0000000000..8e012ceb02 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingConditional.lean @@ -0,0 +1,73 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability + +/-! +# Conditional expectation of the Feller trajectory at finite stopping times + +For every finite `NNReal`-valued stopping time of the canonical filtration, the conditional +expectation of a bounded strongly measurable functional of the shifted canonical Feller +trajectory, given the stopped sigma-algebra, is the path-kernel expectation started from the +state at the stopping time. The proof feeds the event-restricted stopping-time restart identity +into the generic conditional-expectation bridge; measurability of the restarted expectation for +the stopped sigma-algebra comes from progressive measurability of the coordinate process. + +The stopping time here is finite and `NNReal`-valued. A `WithTop`-valued time that can be +infinite is covered, on the event where it is finite, in `Trajectory/StoppingLtTop.lean`; no +Hunt-process property is asserted. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess.SubMarkovKernelSemigroup +noncomputable section +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [LocallyCompactSpace alpha] [StandardBorelSpace alpha] [Nonempty alpha] + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace Real E] [CompleteSpace E] + +/-- At a finite stopping time, the conditional expectation of a bounded functional of the shifted +Feller trajectory given the stopped sigma-algebra is its path-kernel expectation started from the +state at the stopping time. -/ +theorem IsFellerKernelSemigroup.continuousPathTrajectory_condExp_shift_stoppingTime + (P : SubMarkovKernelSemigroup alpha) (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (x : alpha) (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : ℝ) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + ((continuousPathTrajectory P hP default) x)[fun omega ↦ + F (ContinuousPath.shift (T omega) omega)|hT.measurableSpace] =ᵐ[ + (continuousPathTrajectory P hP default) x] + fun omega ↦ ∫ eta, F eta ∂(continuousPathTrajectory P hP default) + (omega (T omega)) := by + apply condExp_comp_ae_eq_integral_kernel_of_restrict_map + ((continuousPathTrajectory P hP default) x) + (Kernel.comap (continuousPathTrajectory P hP default) (fun omega ↦ omega (T omega)) + (ContinuousPath.measurable_eval_stoppingTime_borel T hT)) + (fun omega ↦ ContinuousPath.shift (T omega) omega) + (ContinuousPath.measurable_shift_stoppingTime T hT) + hT.measurableSpace_le + (hFeller.continuousPathTrajectory_restrict_map_shift_stoppingTime P hP default hK x T hT) + F hF ?_ C hFC + have hBase : StronglyMeasurable[hT.measurableSpace] + (fun omega ↦ ∫ eta, F eta ∂(continuousPathTrajectory P hP default) (omega (T omega))) := + hF.integral_kernel.comp_measurable (ContinuousPath.measurable_eval_stoppingTime T hT) + simpa only [Kernel.comap_apply] using hBase + +end +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingRestart.lean new file mode 100644 index 0000000000..cf5fe55b87 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingRestart.lean @@ -0,0 +1,132 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure +import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence +import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral +import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling + +/-! +# Event-restricted restart of the Feller trajectory at finite stopping times + +The canonical continuous trajectory of a conservative Feller kernel semigroup restarts after +restriction to an event in the stopped sigma-algebra of any finite `NNReal`-valued stopping time +for the canonical filtration. The proof approximates the stopping time from above by its dyadic +ceilings, which have countable range, applies the all-time deterministic restart identity on +their level sets, identifies every finite dense future marginal by compact tests and dominated +convergence, and concludes by measure identification on dense restrictions. + +The stopping time here is finite and `NNReal`-valued. A `WithTop`-valued time that can be +infinite is covered, on the event where it is finite, in `Trajectory/StoppingLtTop.lean`; no +Hunt-process property is asserted. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped NNReal CompactlySupported ZeroAtInfty + +namespace MarkovProcess.SubMarkovKernelSemigroup +noncomputable section +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [LocallyCompactSpace alpha] [StandardBorelSpace alpha] [Nonempty alpha] + +/-- Restricting the Feller trajectory to an event in the stopped sigma-algebra of a finite +stopping time and then shifting by that stopping time gives the trajectory kernel restarted +from the state at the stopping time. -/ +theorem IsFellerKernelSemigroup.continuousPathTrajectory_restrict_map_shift_stoppingTime + (P : SubMarkovKernelSemigroup alpha) (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (x : alpha) (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) : + ∀ A : Set (ContinuousPath alpha), MeasurableSet[hT.measurableSpace] A → + (((continuousPathTrajectory P hP default) x).restrict A).map + (fun omega ↦ ContinuousPath.shift (T omega) omega) = + Kernel.comap (continuousPathTrajectory P hP default) + (fun omega ↦ omega (T omega)) + (ContinuousPath.measurable_eval_stoppingTime_borel T hT) ∘ₘ + (((continuousPathTrajectory P hP default) x).restrict A) := by + intro A hA + set Q := continuousPathTrajectory P hP default with hQ + set mu := (Q x).restrict A with hmu + set Tn : ℕ → ContinuousPath alpha → NNReal := fun n omega ↦ dyadicCeiling n (T omega) with hTn + have hTnStop : ∀ n, IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ ((Tn n omega : NNReal) : WithTop NNReal)) := + fun n ↦ isStoppingTime_dyadicCeiling hT n + have hTnMeas : ∀ n, Measurable (Tn n) := + fun n ↦ ContinuousPath.measurable_of_isStoppingTime _ (hTnStop n) + have hATn : ∀ n, MeasurableSet[(hTnStop n).measurableSpace] A := fun n ↦ + IsStoppingTime.measurableSpace_mono hT (hTnStop n) + (fun omega ↦ WithTop.coe_le_coe.mpr (le_dyadicCeiling n (T omega))) A hA + have hstep : ∀ n, mu.map (fun omega ↦ ContinuousPath.shift (Tn n omega) omega) = + Kernel.comap Q (fun omega ↦ omega (Tn n omega)) + (ContinuousPath.measurable_eval_stoppingTime_borel _ (hTnStop n)) ∘ₘ mu := fun n ↦ + ContinuousPath.restrict_map_shift_stoppingTime_eq_pathKernel_comp_of_restart_on_range + Q x (Tn n) (hTnStop n) (countable_range_dyadicCeiling_comp n T) + (fun S _ ↦ hFeller.continuousPathTrajectory_restrict_map_shift P hP default hK x S) + A (hATn n) + apply MarkovProcess.Measure.map_denseRestriction_injective + apply MarkovProcess.Measure.eq_of_map_finiteRestriction_eq + intro J + apply Measure.ext_of_integral_eq_on_compactlySupported + intro f + set L : Kernel alpha (J → alpha) := + (finiteSetKernel P (denseTimePhysicalSet J)).map + (DenseTimePath.pullbackPhysicalSet J) with hL + set g : alpha → ℝ := fun y ↦ ∫ z, f z ∂L y with hg + have hg_cont : Continuous g := + hFeller.continuous_integral_map_finiteSetKernel_pullbackPhysicalSet hP J f + set C := ‖PositiveC0OperatorMeasure.compactlySupportedToC0LinearMap f‖ with hC + have hg_bound : ∀ y, ‖g y‖ ≤ C := fun y ↦ + hP.norm_integral_map_finiteSetKernel_pullbackPhysicalSet_le J f y + have hlimT : ∀ omega, Tendsto (fun n ↦ Tn n omega) atTop (nhds (T omega)) := + fun omega ↦ tendsto_dyadicCeiling (T omega) + have hright := tendsto_integral_continuousPath_eval_randomTime_of_tendsto + mu Tn T hTnMeas hlimT g hg_cont C hg_bound + have hleft := tendsto_integral_continuousPath_finiteDenseEvaluation_shift_randomTime_of_tendsto + mu Tn T hTnMeas hlimT J f + have htest : StronglyMeasurable (fun omega : ContinuousPath alpha ↦ + f (J.restrict (ContinuousPath.denseRestriction omega))) := + (f.continuous.comp (ContinuousPath.continuous_finiteEvaluation + (fun j : J ↦ DenseTime.castOrderEmbedding j))).stronglyMeasurable + have heq : ∀ n, (∫ omega, f (fun j : J ↦ + omega (Tn n omega + DenseTime.castOrderEmbedding j)) ∂mu) = + ∫ omega, g (omega (Tn n omega)) ∂mu := by + intro n + have hm := congrArg (fun rho : Measure (ContinuousPath alpha) ↦ + (rho.map ContinuousPath.denseRestriction).map J.restrict) (hstep n) + have hi := congrArg (fun rho : Measure (J → alpha) ↦ ∫ z, f z ∂rho) hm + rw [ContinuousPath.integral_map_denseRestriction_map_restrict, + continuousPathTrajectory_integral_map_denseRestriction_map_restrict_comp_comap + P hP default hK] at hi + rw [integral_map + (ContinuousPath.measurable_shift_of_measurable (Tn n) (hTnMeas n)).aemeasurable + htest.aestronglyMeasurable] at hi + simpa only [ContinuousPath.denseRestriction_apply, ContinuousPath.shift_apply, hg, hL] + using! hi + have hlimits : + (∫ omega, f (fun j : J ↦ omega (T omega + DenseTime.castOrderEmbedding j)) ∂mu) = + ∫ omega, g (omega (T omega)) ∂mu := + tendsto_nhds_unique hleft (by simpa only [heq] using hright) + rw [ContinuousPath.integral_map_denseRestriction_map_restrict, + continuousPathTrajectory_integral_map_denseRestriction_map_restrict_comp_comap + P hP default hK] + rw [integral_map + (ContinuousPath.measurable_shift_stoppingTime T hT).aemeasurable + htest.aestronglyMeasurable] + simpa only [ContinuousPath.denseRestriction_apply, ContinuousPath.shift_apply, hg, hL] + using! hlimits + +end +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKac.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKac.lean new file mode 100644 index 0000000000..0ae5979d07 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKac.lean @@ -0,0 +1,17 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination + +/-! +# Feynman--Kac semigroups and resolvents + +This facade imports the path functional, operator, semigroup, real and extended-nonnegative +resolvent, comparison, perturbation, and uniqueness interfaces for bounded nonnegative measurable +potentials. +-/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacFunctional.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacFunctional.lean new file mode 100644 index 0000000000..eccd6e02f5 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacFunctional.lean @@ -0,0 +1,649 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale + +/-! +# Feynman--Kac functionals and semigroups + +For the continuous-path process of a conservative Feller semigroup, this file constructs the +Feynman--Kac operators associated with a bounded nonnegative measurable potential. It proves +measurability and bounds for the accumulated potential and operators, the identity at time zero, +and the Feynman--Kac semigroup law. + +Main results: `feynmanKacAdditiveFunctional`, +`stronglyMeasurable_feynmanKacAdditiveFunctional`, +`continuous_feynmanKacAdditiveFunctional`, `feynmanKacAdditiveFunctional_add`, +`IsConservative.feynmanKac`, `IsConservative.feynmanKac_zero`, +`IsConservative.measurable_feynmanKac`, `IsConservative.feynmanKac_nonneg`, +`IsConservative.feynmanKac_le`, `IsConservative.feynmanKac_add_apply`, +`IsConservative.feynmanKac_smul_apply`, and `IsFellerKernelSemigroup.feynmanKac_add`. + +The resolvent and perturbation identities are developed in `Trajectory/FeynmanKacResolvent.lean`. +-/ + +open Filter MeasureTheory ProbabilityTheory Set +open scoped ENNReal NNReal + +namespace MarkovProcess.SubMarkovKernelSemigroup + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + +/-- The accumulated potential along a continuous path up to time `t`. -/ +def feynmanKacAdditiveFunctional (q : alpha → ℝ) (t : NNReal) + (omega : ContinuousPath alpha) : ℝ := + ∫ s in (0 : ℝ)..t, q (omega (Real.toNNReal s)) + +omit [MeasurableSpace alpha] [BorelSpace alpha] in +/-- The accumulated potential is unfolded as its path integral. -/ +theorem feynmanKacAdditiveFunctional_apply (q : alpha → ℝ) (t : NNReal) + (omega : ContinuousPath alpha) : + feynmanKacAdditiveFunctional q t omega = + ∫ s in (0 : ℝ)..t, q (omega (Real.toNNReal s)) := + rfl + +variable [SecondCountableTopology alpha] + +/-- The accumulated potential at a deterministic time is strongly measurable for the canonical +filtration at that time. -/ +theorem stronglyMeasurable_feynmanKacAdditiveFunctional_canonicalFiltration {q : alpha → ℝ} + (hq : Measurable q) (t : NNReal) : + StronglyMeasurable[ContinuousPath.canonicalFiltration (alpha := alpha) t] + (feynmanKacAdditiveFunctional q t) := by + have hclamp := ContinuousPath.measurable_clampedCoordinate (alpha := alpha) t + have hprod : StronglyMeasurable[ContinuousPath.canonicalFiltration (alpha := alpha) t] + (fun omega : ContinuousPath alpha ↦ + ∫ s, q (omega (min (Real.toNNReal s) t)) + ∂(volume.restrict (Ioc (0 : ℝ) t))) := + stronglyMeasurable_integral_prod (volume.restrict (Ioc (0 : ℝ) t)) + ((hq.comp hclamp).stronglyMeasurable) + have hfun : feynmanKacAdditiveFunctional q t = fun omega : ContinuousPath alpha ↦ + ∫ s, q (omega (min (Real.toNNReal s) t)) + ∂(volume.restrict (Ioc (0 : ℝ) t)) := by + funext omega + rw [feynmanKacAdditiveFunctional_apply, intervalIntegral.integral_of_le t.coe_nonneg] + refine setIntegral_congr_fun measurableSet_Ioc fun s hs ↦ ?_ + rw [min_eq_left (Real.toNNReal_le_iff_le_coe.mpr hs.2)] + rw [hfun] + exact hprod + +/-- The accumulated potential at a deterministic time is strongly measurable on path space. -/ +theorem stronglyMeasurable_feynmanKacAdditiveFunctional {q : alpha → ℝ} + (hq : Measurable q) (t : NNReal) : + StronglyMeasurable (feynmanKacAdditiveFunctional q t) := + (stronglyMeasurable_feynmanKacAdditiveFunctional_canonicalFiltration hq t).mono + ((ContinuousPath.canonicalFiltration (alpha := alpha)).le t) + +/-- The accumulated potential is jointly strongly measurable in time and path. -/ +theorem stronglyMeasurable_feynmanKacAdditiveFunctional_joint {q : alpha → ℝ} + (hq : Measurable q) : + StronglyMeasurable fun p : NNReal × ContinuousPath alpha ↦ + feynmanKacAdditiveFunctional q p.1 p.2 := by + let phi : (NNReal × ContinuousPath alpha) × ℝ → ℝ := fun p ↦ + if 0 < p.2 ∧ p.2 ≤ (p.1.1 : ℝ) + then q (p.1.2 (Real.toNNReal p.2)) else 0 + have hset : MeasurableSet {p : (NNReal × ContinuousPath alpha) × ℝ | + 0 < p.2 ∧ p.2 ≤ (p.1.1 : ℝ)} := + (measurableSet_lt measurable_const measurable_snd).inter + (measurableSet_le measurable_snd + (NNReal.continuous_coe.measurable.comp (measurable_fst.comp measurable_fst))) + have heval : Measurable fun p : (NNReal × ContinuousPath alpha) × ℝ ↦ + q (p.1.2 (Real.toNNReal p.2)) := by + have hpath : Measurable fun p : (NNReal × ContinuousPath alpha) × ℝ ↦ + p.1.2 (Real.toNNReal p.2) := + (ContinuousEval.continuous_eval.comp continuous_swap).measurable.comp + ((measurable_real_toNNReal.comp measurable_snd).prodMk + (measurable_snd.comp measurable_fst)) + exact hq.comp hpath + have hphi : StronglyMeasurable phi := by + exact (heval.ite hset measurable_const).stronglyMeasurable + have hint : StronglyMeasurable fun p : NNReal × ContinuousPath alpha ↦ + ∫ s, phi (p, s) := hphi.integral_prod_right' + have heq : (fun p : NNReal × ContinuousPath alpha ↦ + feynmanKacAdditiveFunctional q p.1 p.2) = fun p ↦ ∫ s, phi (p, s) := by + funext p + rw [feynmanKacAdditiveFunctional_apply, + intervalIntegral.integral_of_le p.1.coe_nonneg] + change (∫ s in Ioc (0 : ℝ) (p.1 : ℝ), q (p.2 (Real.toNNReal s))) = + ∫ s, phi (p, s) + rw [← integral_indicator measurableSet_Ioc] + apply integral_congr_ae + exact Eventually.of_forall fun s ↦ by + by_cases hs : s ∈ Ioc (0 : ℝ) (p.1 : ℝ) + · have hs' : 0 < s ∧ s ≤ (p.1 : ℝ) := hs + simp only [indicator_of_mem hs, phi, if_pos hs'] + · have hs' : ¬(0 < s ∧ s ≤ (p.1 : ℝ)) := hs + simp only [indicator_of_notMem hs, phi, if_neg hs'] + rw [heq] + exact hint + +omit [SecondCountableTopology alpha] in +/-- A bounded measurable potential is interval integrable along every continuous path. -/ +private theorem intervalIntegrable_potential_path {q : alpha → ℝ} (hq : Measurable q) + {C : ℝ} (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + (omega : ContinuousPath alpha) (a b : ℝ) : + IntervalIntegrable (fun s : ℝ ↦ q (omega (Real.toNNReal s))) volume a b := by + rw [intervalIntegrable_iff] + refine IntegrableOn.of_bound (by simpa only [uIoc] using + (measure_Ioc_lt_top : volume (Ioc (min a b) (max a b)) < ∞)) + (((hq.comp (omega.continuous.measurable.comp measurable_real_toNNReal)).stronglyMeasurable + ).aestronglyMeasurable.restrict) C ?_ + filter_upwards [ae_restrict_mem measurableSet_uIoc] with s _ + rw [Real.norm_eq_abs, abs_of_nonneg (hq0 _)] + exact hqC _ + +omit [SecondCountableTopology alpha] in +/-- Along every path, the accumulated potential is continuous in its time argument. -/ +theorem continuous_feynmanKacAdditiveFunctional {q : alpha → ℝ} (hq : Measurable q) + {C : ℝ} (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + (omega : ContinuousPath alpha) : + Continuous fun t : NNReal ↦ feynmanKacAdditiveFunctional q t omega := by + have hcont : Continuous fun t : ℝ ↦ + ∫ s in (0 : ℝ)..t, q (omega (Real.toNNReal s)) := + intervalIntegral.continuous_primitive + (fun a b ↦ intervalIntegrable_potential_path hq hq0 hqC omega a b) 0 + exact hcont.comp NNReal.continuous_coe + +omit [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] in +/-- The accumulated potential is nonnegative. -/ +theorem feynmanKacAdditiveFunctional_nonneg {q : alpha → ℝ} (hq0 : ∀ y, 0 ≤ q y) + (t : NNReal) (omega : ContinuousPath alpha) : + 0 ≤ feynmanKacAdditiveFunctional q t omega := by + rw [feynmanKacAdditiveFunctional_apply] + exact intervalIntegral.integral_nonneg t.coe_nonneg fun s _ ↦ hq0 _ + +omit [SecondCountableTopology alpha] in +/-- The accumulated potential is at most the uniform potential bound times elapsed time. -/ +theorem feynmanKacAdditiveFunctional_le {q : alpha → ℝ} {C : ℝ} + (hq : Measurable q) (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + (t : NNReal) (omega : ContinuousPath alpha) : + feynmanKacAdditiveFunctional q t omega ≤ C * t := by + rw [feynmanKacAdditiveFunctional_apply] + calc + (∫ s in (0 : ℝ)..t, q (omega (Real.toNNReal s))) ≤ ∫ _s in (0 : ℝ)..t, C := by + apply intervalIntegral.integral_mono_on t.coe_nonneg + (intervalIntegrable_potential_path hq hq0 hqC omega 0 t) + continuousOn_const.intervalIntegrable + intro s _ + exact hqC _ + _ = C * t := by + rw [intervalIntegral.integral_const, smul_eq_mul] + ring + +omit [SecondCountableTopology alpha] in +/-- Accumulated potentials add under deterministic path shifts. -/ +theorem feynmanKacAdditiveFunctional_add {q : alpha → ℝ} (hq : Measurable q) + {C : ℝ} (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + (s t : NNReal) (omega : ContinuousPath alpha) : + feynmanKacAdditiveFunctional q (s + t) omega = + feynmanKacAdditiveFunctional q s omega + + feynmanKacAdditiveFunctional q t (ContinuousPath.shift s omega) := by + let g : ℝ → ℝ := fun u ↦ q (omega (Real.toNNReal u)) + have hshift : (∫ u in (0 : ℝ)..(t : ℝ), q (omega (s + Real.toNNReal u))) = + ∫ v in (s : ℝ)..((s + t : NNReal) : ℝ), g v := by + have hcongr : (∫ u in (0 : ℝ)..(t : ℝ), q (omega (s + Real.toNNReal u))) = + ∫ u in (0 : ℝ)..(t : ℝ), g (u + s) := by + refine intervalIntegral.integral_congr fun u hu ↦ ?_ + have hu0 : 0 ≤ u := by + rw [uIcc_of_le t.coe_nonneg] at hu + exact hu.1 + have hcoe : Real.toNNReal (u + s) = s + Real.toNNReal u := by + apply NNReal.coe_injective + rw [NNReal.coe_add, Real.coe_toNNReal u hu0, + Real.coe_toNNReal _ (add_nonneg hu0 s.coe_nonneg)] + ring + simp only [g] + rw [hcoe] + rw [hcongr, intervalIntegral.integral_comp_add_right g (s : ℝ), zero_add] + congr 1 + simp only [NNReal.coe_add, add_comm] + have hsplit : (∫ v in (0 : ℝ)..(s : ℝ), g v) + + (∫ v in (s : ℝ)..((s + t : NNReal) : ℝ), g v) = + ∫ v in (0 : ℝ)..((s + t : NNReal) : ℝ), g v := + intervalIntegral.integral_add_adjacent_intervals + (intervalIntegrable_potential_path hq hq0 hqC omega 0 s) + (intervalIntegrable_potential_path hq hq0 hqC omega s (s + t)) + simp only [feynmanKacAdditiveFunctional_apply, ContinuousPath.shift_apply] + change (∫ v in (0 : ℝ)..((s + t : NNReal) : ℝ), g v) = + (∫ v in (0 : ℝ)..(s : ℝ), g v) + + ∫ u in (0 : ℝ)..(t : ℝ), q (omega (s + Real.toNNReal u)) + rw [hshift] + exact hsplit.symm + +omit [SecondCountableTopology alpha] in +/-- The accumulated potential is monotone in time for a nonnegative potential. -/ +theorem feynmanKacAdditiveFunctional_mono {q : alpha → ℝ} (hq : Measurable q) + {C : ℝ} (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + {s t : NNReal} (hst : s ≤ t) (omega : ContinuousPath alpha) : + feynmanKacAdditiveFunctional q s omega ≤ feynmanKacAdditiveFunctional q t omega := by + rw [← add_tsub_cancel_of_le hst, + feynmanKacAdditiveFunctional_add hq hq0 hqC] + exact le_add_of_nonneg_right + (feynmanKacAdditiveFunctional_nonneg hq0 (t - s) (ContinuousPath.shift s omega)) + +omit [SecondCountableTopology alpha] in +/-- The increment of the accumulated potential is the accumulated potential of the shifted +path. -/ +theorem feynmanKacAdditiveFunctional_sub {q : alpha → ℝ} (hq : Measurable q) + {C : ℝ} (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + {s t : NNReal} (hst : s ≤ t) (omega : ContinuousPath alpha) : + feynmanKacAdditiveFunctional q t omega - feynmanKacAdditiveFunctional q s omega = + feynmanKacAdditiveFunctional q (t - s) (ContinuousPath.shift s omega) := by + have hadd := feynmanKacAdditiveFunctional_add hq hq0 hqC s (t - s) omega + rw [add_tsub_cancel_of_le hst] at hadd + linarith only [hadd] + +omit [SecondCountableTopology alpha] in +/-- Pathwise exponential-integral identity for the accumulated potential. -/ +theorem one_sub_exp_neg_feynmanKacAdditiveFunctional {q : alpha → ℝ} + (hq : Measurable q) {C : ℝ} (hq0 : ∀ y, 0 ≤ q y) + (hqC : ∀ y, q y ≤ C) (t : NNReal) (omega : ContinuousPath alpha) : + 1 - Real.exp (-feynmanKacAdditiveFunctional q t omega) = + ∫ s in (0 : ℝ)..t, q (omega (Real.toNNReal s)) * + Real.exp (-(feynmanKacAdditiveFunctional q t omega - + feynmanKacAdditiveFunctional q (Real.toNNReal s) omega)) := by + let a : ℝ → ℝ := fun s ↦ q (omega (Real.toNNReal s)) + have ha : IntegrableOn a (Icc (0 : ℝ) (t : ℝ)) := by + rw [integrableOn_Icc_iff_integrableOn_Ioc] + exact (intervalIntegrable_iff_integrableOn_Ioc_of_le t.coe_nonneg).mp + (intervalIntegrable_potential_path hq hq0 hqC omega 0 t) + have hprimitive := intervalIntegral.integral_mul_exp_primitive + (right_mem_Icc.mpr t.coe_nonneg) ha + (fun s _ ↦ hq0 _) (fun s _ ↦ hqC _) + have hscaled := congrArg (fun z : ℝ ↦ Real.exp + (-feynmanKacAdditiveFunctional q t omega) * z) hprimitive + change Real.exp (-feynmanKacAdditiveFunctional q t omega) * + (∫ s in (0 : ℝ)..t, a s * Real.exp (∫ r in (0 : ℝ)..s, a r)) = + Real.exp (-feynmanKacAdditiveFunctional q t omega) * + (Real.exp (∫ r in (0 : ℝ)..t, a r) - 1) at hscaled + rw [← intervalIntegral.integral_const_mul] at hscaled + simp only [a, ← feynmanKacAdditiveFunctional_apply] at hscaled + calc + 1 - Real.exp (-feynmanKacAdditiveFunctional q t omega) = + Real.exp (-feynmanKacAdditiveFunctional q t omega) * + (Real.exp (feynmanKacAdditiveFunctional q t omega) - 1) := by + rw [mul_sub, ← Real.exp_add] + simp only [neg_add_cancel, Real.exp_zero, mul_one] + _ = ∫ s in (0 : ℝ)..t, Real.exp (-feynmanKacAdditiveFunctional q t omega) * + (q (omega (Real.toNNReal s)) * + Real.exp (∫ r in (0 : ℝ)..s, q (omega (Real.toNNReal r)))) := hscaled.symm + _ = ∫ s in (0 : ℝ)..t, q (omega (Real.toNNReal s)) * + Real.exp (-(feynmanKacAdditiveFunctional q t omega - + feynmanKacAdditiveFunctional q (Real.toNNReal s) omega)) := by + refine intervalIntegral.integral_congr fun s hs ↦ ?_ + have hs0 : 0 ≤ s := by + rw [uIcc_of_le t.coe_nonneg] at hs + exact hs.1 + have hAs : feynmanKacAdditiveFunctional q (Real.toNNReal s) omega = + ∫ r in (0 : ℝ)..s, q (omega (Real.toNNReal r)) := by + rw [feynmanKacAdditiveFunctional_apply, Real.coe_toNNReal s hs0] + rw [hAs] + rw [neg_sub, Real.exp_sub, Real.exp_neg] + field_simp [Real.exp_ne_zero] + +variable [CompleteSpace alpha] [Nonempty alpha] [LocallyCompactSpace alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- The real-valued Feynman--Kac operator associated with a potential. -/ +def IsConservative.feynmanKac (q : alpha → ℝ) (t : NNReal) (f : alpha → ℝ) + (x : alpha) : ℝ := + ∫ omega, Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t) + ∂(IsConservative.continuousProcess P hP x) + +omit [LocallyCompactSpace alpha] in +/-- The Feynman--Kac operator is unfolded as a path expectation. -/ +theorem IsConservative.feynmanKac_apply (q : alpha → ℝ) (t : NNReal) + (f : alpha → ℝ) (x : alpha) : + IsConservative.feynmanKac P hP q t f x = + ∫ omega, Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t) + ∂(IsConservative.continuousProcess P hP x) := + rfl + +omit [LocallyCompactSpace alpha] in +/-- At time zero the Feynman--Kac operator is the identity on measurable observables. -/ +theorem IsConservative.feynmanKac_zero (hK : P.KolmogorovRegular hP) + (q : alpha → ℝ) {f : alpha → ℝ} (hf : Measurable f) : + IsConservative.feynmanKac P hP q 0 f = f := by + funext x + simp only [IsConservative.feynmanKac_apply, feynmanKacAdditiveFunctional, + NNReal.coe_zero, intervalIntegral.integral_same, neg_zero, Real.exp_zero, one_mul] + have heval := ContinuousPath.measurable_coordinateProcess (alpha := alpha) 0 + calc + (∫ omega, f (omega 0) ∂(IsConservative.continuousProcess P hP x)) = + ∫ y, f y ∂Measure.map (fun omega : ContinuousPath alpha ↦ omega 0) + (IsConservative.continuousProcess P hP x) := + (integral_map heval.aemeasurable hf.stronglyMeasurable.aestronglyMeasurable).symm + _ = ∫ y, f y ∂(Kernel.id x) := by + change ∫ y, f y ∂Measure.map (ContinuousPath.coordinateProcess (alpha := alpha) 0) + (IsConservative.continuousProcess P hP x) = _ + rw [← Kernel.map_apply _ heval] + have hmap : (IsConservative.continuousProcess P hP).map + (ContinuousPath.coordinateProcess (alpha := alpha) 0) = Kernel.id := by + simpa only [ContinuousPath.coordinateProcess] using! + IsConservative.continuousProcess_map_eval_zero P hP hK + rw [hmap] + _ = f x := by + rw [Kernel.id_apply] + exact integral_dirac' f x hf.stronglyMeasurable + +omit [LocallyCompactSpace alpha] in +/-- The Feynman--Kac operator of a bounded measurable function is measurable in the starting +point. -/ +theorem IsConservative.measurable_feynmanKac {q : alpha → ℝ} (hq : Measurable q) + (t : NNReal) {f : alpha → ℝ} (hf : Measurable f) : + Measurable (IsConservative.feynmanKac P hP q t f) := by + have hpath : StronglyMeasurable (fun omega : ContinuousPath alpha ↦ + Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t)) := + (((stronglyMeasurable_feynmanKacAdditiveFunctional hq t).measurable.neg.exp).mul + (hf.comp (ContinuousPath.measurable_coordinateProcess (alpha := alpha) t))).stronglyMeasurable + exact hpath.integral_kernel.measurable + +omit [LocallyCompactSpace alpha] in +/-- The Feynman--Kac operator preserves nonnegativity. -/ +theorem IsConservative.feynmanKac_nonneg {q : alpha → ℝ} {t : NNReal} + {f : alpha → ℝ} (hf0 : ∀ y, 0 ≤ f y) (x : alpha) : + 0 ≤ IsConservative.feynmanKac P hP q t f x := by + exact integral_nonneg fun omega ↦ mul_nonneg (Real.exp_pos _).le (hf0 _) + +omit [LocallyCompactSpace alpha] in +/-- A nonnegative Feynman--Kac operator is bounded by the uniform bound of its observable. -/ +theorem IsConservative.feynmanKac_le {q : alpha → ℝ} (hq0 : ∀ y, 0 ≤ q y) + {t : NNReal} {f : alpha → ℝ} (hf0 : ∀ y, 0 ≤ f y) {D : ℝ} + (hfD : ∀ y, f y ≤ D) (x : alpha) : + IsConservative.feynmanKac P hP q t f x ≤ D := by + calc + IsConservative.feynmanKac P hP q t f x ≤ ∫ _omega, D + ∂(IsConservative.continuousProcess P hP x) := by + apply integral_mono_of_nonneg + · exact Eventually.of_forall fun omega ↦ mul_nonneg (Real.exp_pos _).le (hf0 _) + · exact integrable_const D + · exact Eventually.of_forall fun omega ↦ by + calc + Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t) ≤ + 1 * f (omega t) := by + exact mul_le_mul_of_nonneg_right + ((Real.exp_le_one_iff).mpr + (neg_nonpos.mpr (feynmanKacAdditiveFunctional_nonneg hq0 t omega))) + (hf0 _) + _ ≤ D := by simpa only [one_mul] using hfD _ + _ = D := by simp only [integral_const, probReal_univ, one_smul] + +omit [LocallyCompactSpace alpha] in +/-- The Feynman--Kac operator sends the constant one to a function bounded above by one. -/ +theorem IsConservative.feynmanKac_one_le_one {q : alpha → ℝ} (hq0 : ∀ y, 0 ≤ q y) + (t : NNReal) (x : alpha) : + IsConservative.feynmanKac P hP q t (fun _ ↦ 1) x ≤ 1 := + IsConservative.feynmanKac_le P hP hq0 (fun _ ↦ zero_le_one) (fun _ ↦ le_rfl) x + +/-- The nonnegative-extended-real Feynman--Kac operator. -/ +def IsConservative.feynmanKacENNReal (q : alpha → ℝ) (t : NNReal) + (f : alpha → ℝ≥0∞) (x : alpha) : ℝ≥0∞ := + ∫⁻ omega, ENNReal.ofReal (Real.exp (-feynmanKacAdditiveFunctional q t omega)) * + f (omega t) ∂(IsConservative.continuousProcess P hP x) + +omit [LocallyCompactSpace alpha] in +/-- The extended-real Feynman--Kac operator is unfolded as a path integral. -/ +theorem IsConservative.feynmanKacENNReal_apply (q : alpha → ℝ) (t : NNReal) + (f : alpha → ℝ≥0∞) (x : alpha) : + IsConservative.feynmanKacENNReal P hP q t f x = + ∫⁻ omega, ENNReal.ofReal (Real.exp (-feynmanKacAdditiveFunctional q t omega)) * + f (omega t) ∂(IsConservative.continuousProcess P hP x) := + rfl + +omit [LocallyCompactSpace alpha] in +/-- The extended-real Feynman--Kac operator is jointly measurable in time and starting point. -/ +theorem IsConservative.measurable_feynmanKacENNReal_joint {q : alpha → ℝ} + (hq : Measurable q) {f : alpha → ℝ≥0∞} (hf : Measurable f) : + Measurable fun p : NNReal × alpha ↦ + IsConservative.feynmanKacENNReal P hP q p.1 f p.2 := by + let Q : Kernel alpha (ContinuousPath alpha) := IsConservative.continuousProcess P hP + let Q' : Kernel (NNReal × alpha) (ContinuousPath alpha) := Kernel.comap Q Prod.snd measurable_snd + have hA : Measurable fun p : (NNReal × alpha) × ContinuousPath alpha ↦ + feynmanKacAdditiveFunctional q p.1.1 p.2 := + (stronglyMeasurable_feynmanKacAdditiveFunctional_joint hq).measurable.comp + ((measurable_fst.comp measurable_fst).prodMk measurable_snd) + have heval : Measurable fun p : (NNReal × alpha) × ContinuousPath alpha ↦ + p.2 p.1.1 := + (ContinuousEval.continuous_eval.comp continuous_swap).measurable.comp + ((measurable_fst.comp measurable_fst).prodMk measurable_snd) + have hint : Measurable fun p : (NNReal × alpha) × ContinuousPath alpha ↦ + ENNReal.ofReal (Real.exp (-feynmanKacAdditiveFunctional q p.1.1 p.2)) * f (p.2 p.1.1) := + (hA.neg.exp.ennreal_ofReal).mul (hf.comp heval) + have hlin := hint.lintegral_kernel_prod_right' (κ := Q') + simpa only [Q', Kernel.comap_apply, IsConservative.feynmanKacENNReal_apply] using hlin + +omit [LocallyCompactSpace alpha] in +/-- The extended-real Feynman--Kac operator is measurable in the starting point. -/ +theorem IsConservative.measurable_feynmanKacENNReal {q : alpha → ℝ} (hq : Measurable q) + (t : NNReal) {f : alpha → ℝ≥0∞} (hf : Measurable f) : + Measurable (IsConservative.feynmanKacENNReal P hP q t f) := + (IsConservative.measurable_feynmanKacENNReal_joint P hP hq hf).comp + (measurable_const.prodMk measurable_id) + +omit [LocallyCompactSpace alpha] in +/-- For nonnegative bounded real observables, the two versions of the Feynman--Kac operator agree +after applying `ENNReal.ofReal`. -/ +theorem IsConservative.ofReal_feynmanKac_eq_feynmanKacENNReal {q : alpha → ℝ} + (hq : Measurable q) (hq0 : ∀ y, 0 ≤ q y) (t : NNReal) {f : alpha → ℝ} (hf : Measurable f) + (hf0 : ∀ y, 0 ≤ f y) {D : ℝ} (hfD : ∀ y, f y ≤ D) (x : alpha) : + ENNReal.ofReal (IsConservative.feynmanKac P hP q t f x) = + IsConservative.feynmanKacENNReal P hP q t (fun y ↦ ENNReal.ofReal (f y)) x := by + let g : ContinuousPath alpha → ℝ := fun omega ↦ + Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t) + have hg : Integrable g (IsConservative.continuousProcess P hP x) := by + refine Integrable.of_bound ?_ D (Eventually.of_forall fun omega ↦ ?_) + · exact ((((stronglyMeasurable_feynmanKacAdditiveFunctional hq t).measurable.neg.exp).mul + (hf.comp (ContinuousPath.measurable_coordinateProcess + (alpha := alpha) t))).stronglyMeasurable + ).aestronglyMeasurable + · rw [Real.norm_eq_abs, abs_of_nonneg (mul_nonneg (Real.exp_pos _).le (hf0 _))] + exact (mul_le_mul_of_nonneg_right + ((Real.exp_le_one_iff).mpr + (neg_nonpos.mpr (feynmanKacAdditiveFunctional_nonneg hq0 t omega))) (hf0 _)).trans + (by simpa only [one_mul] using hfD _) + rw [IsConservative.feynmanKac_apply, IsConservative.feynmanKacENNReal_apply, + ofReal_integral_eq_lintegral_ofReal hg + (Eventually.of_forall fun omega ↦ mul_nonneg (Real.exp_pos _).le (hf0 _))] + refine lintegral_congr fun omega ↦ ?_ + rw [ENNReal.ofReal_mul (Real.exp_pos _).le] + +omit [LocallyCompactSpace alpha] in +/-- The path integrand defining a Feynman--Kac operator is integrable for a bounded observable +and a nonnegative potential. -/ +theorem IsConservative.integrable_feynmanKac_integrand {q : alpha → ℝ} + (hq : Measurable q) (hq0 : ∀ y, 0 ≤ q y) (t : NNReal) {f : alpha → ℝ} + (hf : Measurable f) {D : ℝ} (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + Integrable (fun omega : ContinuousPath alpha ↦ + Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t)) + (IsConservative.continuousProcess P hP x) := by + exact Integrable.of_bound + (((((stronglyMeasurable_feynmanKacAdditiveFunctional hq t).measurable.neg.exp).mul + (hf.comp (ContinuousPath.measurable_coordinateProcess (alpha := alpha) t)) + ).stronglyMeasurable).aestronglyMeasurable) D (Eventually.of_forall fun omega ↦ by + rw [Real.norm_eq_abs, abs_mul, abs_of_pos (Real.exp_pos _)] + calc + Real.exp (-feynmanKacAdditiveFunctional q t omega) * |f (omega t)| ≤ + 1 * |f (omega t)| := mul_le_mul_of_nonneg_right + ((Real.exp_le_one_iff).mpr + (neg_nonpos.mpr (feynmanKacAdditiveFunctional_nonneg hq0 t omega))) + (abs_nonneg _) + _ ≤ D := by simpa only [one_mul] using hfD _) + +omit [LocallyCompactSpace alpha] in +/-- Feynman--Kac operators are additive on bounded measurable real observables. -/ +theorem IsConservative.feynmanKac_add_apply {q : alpha → ℝ} (hq : Measurable q) + (hq0 : ∀ y, 0 ≤ q y) (t : NNReal) {f g : alpha → ℝ} + (hf : Measurable f) (hg : Measurable g) {D E : ℝ} + (hfD : ∀ y, |f y| ≤ D) (hgE : ∀ y, |g y| ≤ E) : + IsConservative.feynmanKac P hP q t (f + g) = + IsConservative.feynmanKac P hP q t f + IsConservative.feynmanKac P hP q t g := by + funext x + change (∫ omega, Real.exp (-feynmanKacAdditiveFunctional q t omega) * + (f + g) (omega t) ∂(IsConservative.continuousProcess P hP x)) = + (∫ omega, Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t) + ∂(IsConservative.continuousProcess P hP x)) + + ∫ omega, Real.exp (-feynmanKacAdditiveFunctional q t omega) * g (omega t) + ∂(IsConservative.continuousProcess P hP x) + rw [← integral_add + (IsConservative.integrable_feynmanKac_integrand P hP hq hq0 t hf hfD x) + (IsConservative.integrable_feynmanKac_integrand P hP hq hq0 t hg hgE x)] + apply integral_congr_ae + exact Eventually.of_forall fun omega ↦ by + simp only [Pi.add_apply] + ring + +omit [LocallyCompactSpace alpha] in +/-- Feynman--Kac operators are real homogeneous. -/ +theorem IsConservative.feynmanKac_smul_apply (q : alpha → ℝ) (t : NNReal) (a : ℝ) + (f : alpha → ℝ) : + IsConservative.feynmanKac P hP q t (a • f) = + a • IsConservative.feynmanKac P hP q t f := by + funext x + change (∫ omega, Real.exp (-feynmanKacAdditiveFunctional q t omega) * + (a • f) (omega t) ∂(IsConservative.continuousProcess P hP x)) = + a • (∫ omega, Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t) + ∂(IsConservative.continuousProcess P hP x)) + rw [← integral_smul] + apply integral_congr_ae + exact Eventually.of_forall fun omega ↦ by + simp only [Pi.smul_apply, smul_eq_mul] + ring + +omit [LocallyCompactSpace alpha] in +/-- A Feynman--Kac operator contracts the uniform bound of a bounded observable when +the potential is nonnegative. -/ +theorem IsConservative.norm_feynmanKac_le {q : alpha → ℝ} (hq0 : ∀ y, 0 ≤ q y) + (t : NNReal) {f : alpha → ℝ} {D : ℝ} (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + |IsConservative.feynmanKac P hP q t f x| ≤ D := by + rw [← Real.norm_eq_abs] + calc + ‖IsConservative.feynmanKac P hP q t f x‖ ≤ ∫ _omega, D + ∂(IsConservative.continuousProcess P hP x) := by + rw [IsConservative.feynmanKac_apply] + apply norm_integral_le_of_norm_le (integrable_const D) + exact Eventually.of_forall fun omega ↦ by + rw [Real.norm_eq_abs, abs_mul, abs_of_pos (Real.exp_pos _)] + exact (mul_le_mul_of_nonneg_right + ((Real.exp_le_one_iff).mpr + (neg_nonpos.mpr (feynmanKacAdditiveFunctional_nonneg hq0 t omega))) + (abs_nonneg _)).trans (by simpa only [one_mul] using hfD _) + _ = D := by simp only [integral_const, probReal_univ, one_smul] + +omit [LocallyCompactSpace alpha] in +/-- A Feynman--Kac operator applied to a bounded measurable observable is jointly measurable in +time and starting point. -/ +theorem IsConservative.measurable_feynmanKac_joint {q : alpha → ℝ} + (hq : Measurable q) : ∀ {f : alpha → ℝ}, Measurable f → + Measurable fun p : NNReal × alpha ↦ + IsConservative.feynmanKac P hP q p.1 f p.2 := by + intro f hf + let Q : Kernel alpha (ContinuousPath alpha) := IsConservative.continuousProcess P hP + let Q' : Kernel (NNReal × alpha) (ContinuousPath alpha) := + Kernel.comap Q Prod.snd measurable_snd + have hA : Measurable fun p : (NNReal × alpha) × ContinuousPath alpha ↦ + feynmanKacAdditiveFunctional q p.1.1 p.2 := + (stronglyMeasurable_feynmanKacAdditiveFunctional_joint hq).measurable.comp + ((measurable_fst.comp measurable_fst).prodMk measurable_snd) + have heval : Measurable fun p : (NNReal × alpha) × ContinuousPath alpha ↦ + p.2 p.1.1 := + (ContinuousEval.continuous_eval.comp continuous_swap).measurable.comp + ((measurable_fst.comp measurable_fst).prodMk measurable_snd) + have hint : StronglyMeasurable fun p : (NNReal × alpha) × ContinuousPath alpha ↦ + Real.exp (-feynmanKacAdditiveFunctional q p.1.1 p.2) * f (p.2 p.1.1) := + ((hA.neg.exp).mul (hf.comp heval)).stronglyMeasurable + have hInt := hint.integral_kernel_prod_right' (κ := Q') + simpa only [Q', Kernel.comap_apply, IsConservative.feynmanKac_apply] using hInt.measurable + + +/-- The Feynman--Kac operators satisfy the semigroup law. -/ +theorem IsFellerKernelSemigroup.feynmanKac_add (hFeller : P.IsFellerKernelSemigroup) + (hK : P.KolmogorovRegular hP) {q : alpha → ℝ} (hq : Measurable q) + {C : ℝ} (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + (s t : NNReal) {f : alpha → ℝ} (hf : Measurable f) {D : ℝ} + (hfD : ∀ y, ‖f y‖ ≤ D) (x : alpha) : + IsConservative.feynmanKac P hP q (s + t) f x = + IsConservative.feynmanKac P hP q s + (IsConservative.feynmanKac P hP q t f) x := by + let W : ContinuousPath alpha → ℝ := fun omega ↦ + Real.exp (-feynmanKacAdditiveFunctional q s omega) + let F : ContinuousPath alpha → ℝ := fun eta ↦ + Real.exp (-feynmanKacAdditiveFunctional q t eta) * f (eta t) + let mu : Measure (ContinuousPath alpha) := IsConservative.continuousProcess P hP x + have hW : StronglyMeasurable[ContinuousPath.canonicalFiltration (alpha := alpha) s] W := by + have hA : Measurable[ContinuousPath.canonicalFiltration (alpha := alpha) s] + (fun omega ↦ -feynmanKacAdditiveFunctional q s omega) := + (stronglyMeasurable_feynmanKacAdditiveFunctional_canonicalFiltration hq s).measurable.neg + exact hA.exp.stronglyMeasurable + have hF : StronglyMeasurable F := by + have hweight : StronglyMeasurable fun eta : ContinuousPath alpha ↦ + Real.exp (-feynmanKacAdditiveFunctional q t eta) := + (stronglyMeasurable_feynmanKacAdditiveFunctional hq t).measurable.neg.exp.stronglyMeasurable + exact hweight.mul ((hf.comp + (ContinuousPath.measurable_coordinateProcess (alpha := alpha) t)).stronglyMeasurable) + have hFbound : ∀ eta : ContinuousPath alpha, ‖F eta‖ ≤ D := by + intro eta + dsimp only [F] + rw [norm_mul, Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] + calc + Real.exp (-feynmanKacAdditiveFunctional q t eta) * ‖f (eta t)‖ ≤ 1 * ‖f (eta t)‖ := + mul_le_mul_of_nonneg_right + ((Real.exp_le_one_iff).mpr + (neg_nonpos.mpr (feynmanKacAdditiveFunctional_nonneg hq0 t eta))) (norm_nonneg _) + _ ≤ D := by simpa only [one_mul] using hfD _ + have hWFbound : ∀ omega : ContinuousPath alpha, + ‖W omega * F (ContinuousPath.shift s omega)‖ ≤ D := by + intro omega + rw [norm_mul] + calc + ‖W omega‖ * ‖F (ContinuousPath.shift s omega)‖ ≤ 1 * ‖F (ContinuousPath.shift s omega)‖ := by + apply mul_le_mul_of_nonneg_right _ (norm_nonneg _) + dsimp only [W] + rw [Real.norm_eq_abs, abs_of_pos (Real.exp_pos _)] + exact (Real.exp_le_one_iff).mpr + (neg_nonpos.mpr (feynmanKacAdditiveFunctional_nonneg hq0 s omega)) + _ ≤ D := by simpa only [one_mul] using hFbound _ + have hIntFshift : Integrable (fun omega ↦ F (ContinuousPath.shift s omega)) mu := + Integrable.of_bound + (hF.comp_measurable + (ContinuousPath.measurable_shift_fixed (alpha := alpha) s)).aestronglyMeasurable + D (Eventually.of_forall fun omega ↦ hFbound _) + have hIntWF : Integrable (fun omega ↦ W omega * F (ContinuousPath.shift s omega)) mu := + Integrable.of_bound + ((hW.mono ((ContinuousPath.canonicalFiltration (alpha := alpha)).le s)).mul + (hF.comp_measurable + (ContinuousPath.measurable_shift_fixed (alpha := alpha) s))).aestronglyMeasurable + D (Eventually.of_forall hWFbound) + have hcond := hFeller.continuousProcess_condExp_shift P hP hK x s F hF D hFbound + have hpull := condExp_mul_of_stronglyMeasurable_left (μ := mu) hW hIntWF hIntFshift + have htotal : (fun omega ↦ + Real.exp (-feynmanKacAdditiveFunctional q (s + t) omega) * f (omega (s + t))) = + fun omega ↦ W omega * F (ContinuousPath.shift s omega) := by + funext omega + dsimp only [W, F] + rw [ContinuousPath.shift_apply, feynmanKacAdditiveFunctional_add hq hq0 hqC] + rw [neg_add, Real.exp_add] + ring + rw [IsConservative.feynmanKac_apply, htotal] + calc + (∫ omega, W omega * F (ContinuousPath.shift s omega) ∂mu) = + ∫ omega, mu[fun eta ↦ W eta * F (ContinuousPath.shift s eta)| + ContinuousPath.canonicalFiltration (alpha := alpha) s] omega ∂mu := by + rw [integral_condExp ((ContinuousPath.canonicalFiltration (alpha := alpha)).le s)] + _ = ∫ omega, W omega * + (∫ eta, F eta ∂IsConservative.continuousProcess P hP (omega s)) ∂mu := by + refine integral_congr_ae (hpull.trans ?_) + exact EventuallyEq.mul (EventuallyEq.refl _ _) hcond + _ = IsConservative.feynmanKac P hP q s + (IsConservative.feynmanKac P hP q t f) x := by + rfl + +end + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacRealResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacRealResolvent.lean new file mode 100644 index 0000000000..e59547608d --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacRealResolvent.lean @@ -0,0 +1,750 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent +import Mathlib.Analysis.Calculus.Deriv.Mul +import Mathlib.Analysis.SpecialFunctions.ExpDeriv +import Mathlib.MeasureTheory.Integral.IntervalIntegral.FundThmCalculus + +/-! +# Real Feynman--Kac resolvents + +This file defines the real Feynman--Kac resolvent on bounded measurable observables. It proves +its uniform bound, linearity, the resolvent identity, and the bounded-potential perturbation +identity. + +Main results: `IsConservative.feynmanKacResolventReal`, +`IsFellerKernelSemigroup.feynmanKacResolventReal_resolvent_identity`, and +`IsFellerKernelSemigroup.feynmanKacResolventReal_perturbation`. + +Together with `perturbed_eq_of_resolventFamilies`, these identities characterize the +Feynman--Kac resolvent among bounded measurable resolvent families solving the same perturbation +equation at all sufficiently large shifts. No model-specific realization is assumed. +-/ + +open Filter MeasureTheory ProbabilityTheory Set +open scoped ENNReal NNReal + +namespace MarkovProcess.SubMarkovKernelSemigroup + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [CompleteSpace alpha] [Nonempty alpha] + [LocallyCompactSpace alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- The real Feynman--Kac resolvent on bounded measurable observables. -/ +def IsConservative.feynmanKacResolventReal (q : alpha → ℝ) (lam : ℝ) + (f : alpha → ℝ) (x : alpha) : ℝ := + ∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) f x + +omit [LocallyCompactSpace alpha] in +private theorem IsConservative.integrableOn_feynmanKacResolventReal_integrand + {q : alpha → ℝ} (hq : Measurable q) (hq0 : ∀ y, 0 ≤ q y) {lam : ℝ} (hlam : 0 < lam) + {f : alpha → ℝ} (hf : Measurable f) {D : ℝ} (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + IntegrableOn (fun t : ℝ ↦ Real.exp (-lam * t) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) f x) (Ioi 0) := by + apply Integrable.mono' ((exp_neg_integrableOn_Ioi 0 hlam).mul_const D) + · exact (((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.mul + ((IsConservative.measurable_feynmanKac_joint P hP hq hf).comp + (measurable_real_toNNReal.prodMk measurable_const))).stronglyMeasurable + ).aestronglyMeasurable.restrict + · exact Eventually.of_forall fun t ↦ by + rw [Real.norm_eq_abs, abs_mul, abs_of_pos (Real.exp_pos _)] + exact mul_le_mul_of_nonneg_left + (IsConservative.norm_feynmanKac_le P hP hq0 (Real.toNNReal t) hfD x) + (Real.exp_pos _).le + +omit [LocallyCompactSpace alpha] in +/-- The real Feynman--Kac resolvent of a bounded measurable observable is measurable in the +starting point. -/ +theorem IsConservative.measurable_feynmanKacResolventReal {q : alpha → ℝ} + (hq : Measurable q) (lam : ℝ) {f : alpha → ℝ} (hf : Measurable f) : + Measurable (IsConservative.feynmanKacResolventReal P hP q lam f) := by + have hjoint : StronglyMeasurable fun p : ℝ × alpha ↦ + Real.exp (-lam * p.1) * + IsConservative.feynmanKac P hP q (Real.toNNReal p.1) f p.2 := + ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.comp + measurable_fst).mul + ((IsConservative.measurable_feynmanKac_joint P hP hq hf).comp + ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_snd) + ) |>.stronglyMeasurable + exact (hjoint.integral_prod_left' (μ := volume.restrict (Ioi 0))).measurable + +omit [LocallyCompactSpace alpha] in +/-- The real Feynman--Kac resolvent is additive on bounded measurable observables. -/ +theorem IsConservative.feynmanKacResolventReal_add {q : alpha → ℝ} + (hq : Measurable q) (hq0 : ∀ y, 0 ≤ q y) {lam : ℝ} (hlam : 0 < lam) + {f g : alpha → ℝ} (hf : Measurable f) (hg : Measurable g) {D E : ℝ} + (hfD : ∀ y, |f y| ≤ D) (hgE : ∀ y, |g y| ≤ E) : + IsConservative.feynmanKacResolventReal P hP q lam (f + g) = + IsConservative.feynmanKacResolventReal P hP q lam f + + IsConservative.feynmanKacResolventReal P hP q lam g := by + funext x + unfold IsConservative.feynmanKacResolventReal + change (∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) (f + g) x) = + (∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) f x) + + ∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) g x + rw [← integral_add + (IsConservative.integrableOn_feynmanKacResolventReal_integrand + P hP hq hq0 hlam hf hfD x) + (IsConservative.integrableOn_feynmanKacResolventReal_integrand + P hP hq hq0 hlam hg hgE x)] + apply setIntegral_congr_fun measurableSet_Ioi + intro t _ht + dsimp only + rw [congrFun (IsConservative.feynmanKac_add_apply P hP hq hq0 + (Real.toNNReal t) hf hg hfD hgE) x] + simp only [Pi.add_apply] + ring + +omit [LocallyCompactSpace alpha] in +/-- The real Feynman--Kac resolvent is real homogeneous. -/ +theorem IsConservative.feynmanKacResolventReal_smul (q : alpha → ℝ) (lam a : ℝ) + (f : alpha → ℝ) : + IsConservative.feynmanKacResolventReal P hP q lam (a • f) = + a • IsConservative.feynmanKacResolventReal P hP q lam f := by + funext x + unfold IsConservative.feynmanKacResolventReal + change (∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) (a • f) x) = + a • (∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) f x) + rw [← integral_smul] + apply setIntegral_congr_fun measurableSet_Ioi + intro t _ht + dsimp only + rw [congrFun (IsConservative.feynmanKac_smul_apply P hP q + (Real.toNNReal t) a f) x] + simp only [Pi.smul_apply, smul_eq_mul] + ring + +omit [LocallyCompactSpace alpha] in +/-- The uniform bound for the real Feynman--Kac resolvent at a positive shift. -/ +theorem IsConservative.norm_feynmanKacResolventReal_le {q : alpha → ℝ} + (hq0 : ∀ y, 0 ≤ q y) {lam : ℝ} (hlam : 0 < lam) + {f : alpha → ℝ} {D : ℝ} (hfD : ∀ y, |f y| ≤ D) + (x : alpha) : |IsConservative.feynmanKacResolventReal P hP q lam f x| ≤ D / lam := by + rw [← Real.norm_eq_abs] + unfold IsConservative.feynmanKacResolventReal + calc + ‖∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) f x‖ ≤ + ∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * D := by + apply norm_integral_le_of_norm_le + ((exp_neg_integrableOn_Ioi 0 hlam).mul_const D) + filter_upwards [ae_restrict_mem measurableSet_Ioi] with t _ht + rw [Real.norm_eq_abs, abs_mul, abs_of_pos (Real.exp_pos _)] + exact mul_le_mul_of_nonneg_left + (IsConservative.norm_feynmanKac_le P hP hq0 (Real.toNNReal t) hfD x) + (Real.exp_pos _).le + _ = D / lam := by + rw [integral_mul_const, + Semigroup.StronglyContinuousContractionSemigroup.integral_exp_neg_mul_Ioi_zero hlam] + field_simp + +omit [LocallyCompactSpace alpha] in +/-- For a bounded nonnegative real observable, applying `ENNReal.ofReal` to the real +Feynman--Kac resolvent gives the extended-real Feynman--Kac resolvent. -/ +theorem IsConservative.ofReal_feynmanKacResolventReal_eq_feynmanKacResolvent + {q : alpha → ℝ} (hq : Measurable q) (hq0 : ∀ y, 0 ≤ q y) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ} (hf : Measurable f) + (hf0 : ∀ y, 0 ≤ f y) {D : ℝ} (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + ENNReal.ofReal (IsConservative.feynmanKacResolventReal P hP q lam f x) = + IsConservative.feynmanKacResolvent P hP q lam + (fun y ↦ ENNReal.ofReal (f y)) x := by + have hint := IsConservative.integrableOn_feynmanKacResolventReal_integrand + P hP hq hq0 hlam hf hfD x + rw [IsConservative.feynmanKacResolventReal, + ofReal_integral_eq_lintegral_ofReal hint + (Eventually.of_forall fun t ↦ mul_nonneg (Real.exp_pos _).le + (IsConservative.feynmanKac_nonneg P hP hf0 x))] + unfold IsConservative.feynmanKacResolvent + apply setLIntegral_congr_fun measurableSet_Ioi + intro t _ht + dsimp only + rw [ENNReal.ofReal_mul (Real.exp_pos _).le, + IsConservative.ofReal_feynmanKac_eq_feynmanKacENNReal P hP hq hq0 + (Real.toNNReal t) hf hf0 (fun y ↦ (le_abs_self (f y)).trans (hfD y)) x] + +/-- With zero potential, the real Feynman--Kac resolvent is the real kernel resolvent. -/ +theorem IsFellerKernelSemigroup.feynmanKacResolventReal_zero_eq_kernelResolventReal + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (lam : ℝ) {f : alpha → ℝ} (hf : Measurable f) : + IsConservative.feynmanKacResolventReal P hP (fun _ ↦ 0) lam f = + P.kernelResolventReal lam f := by + funext x + unfold IsConservative.feynmanKacResolventReal SubMarkovKernelSemigroup.kernelResolventReal + apply setIntegral_congr_fun measurableSet_Ioi + intro t _ht + have heval := hFeller.integral_eval_continuousProcess_of_measurable + P hP hK (Real.toNNReal t) x hf + simp only [IsConservative.feynmanKac_apply, feynmanKacAdditiveFunctional, + intervalIntegral.integral_zero, neg_zero, Real.exp_zero, one_mul] + rw [heval] + rfl + +/-- The real kernel resolvent of a bounded measurable observable is measurable. -/ +theorem IsFellerKernelSemigroup.measurable_kernelResolventReal + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (lam : ℝ) {f : alpha → ℝ} (hf : Measurable f) : + Measurable (P.kernelResolventReal lam f) := by + rw [← hFeller.feynmanKacResolventReal_zero_eq_kernelResolventReal P hP hK lam hf] + exact IsConservative.measurable_feynmanKacResolventReal P hP measurable_const lam hf + +private theorem IsFellerKernelSemigroup.feynmanKac_comp_feynmanKacResolventReal + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + {q : alpha → ℝ} (hq : Measurable q) {C : ℝ} + (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) {mu : ℝ} (hmu : 0 < mu) + (s : NNReal) {f : alpha → ℝ} (hf : Measurable f) {D : ℝ} + (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + IsConservative.feynmanKac P hP q s + (IsConservative.feynmanKacResolventReal P hP q mu f) x = + ∫ t in Ioi (0 : ℝ), Real.exp (-mu * t) * + IsConservative.feynmanKac P hP q (s + Real.toNNReal t) f x := by + let Qx : Measure (ContinuousPath alpha) := IsConservative.continuousProcess P hP x + let H : ContinuousPath alpha × ℝ → ℝ := fun p ↦ + Real.exp (-feynmanKacAdditiveFunctional q s p.1) * Real.exp (-mu * p.2) * + IsConservative.feynmanKac P hP q (Real.toNNReal p.2) f (p.1 s) + have hHmeas : StronglyMeasurable H := by + have hstart : Measurable fun p : ContinuousPath alpha × ℝ ↦ p.1 s := + (ContinuousPath.measurable_coordinateProcess (alpha := alpha) s).comp measurable_fst + have htime : Measurable fun p : ContinuousPath alpha × ℝ ↦ Real.toNNReal p.2 := + measurable_real_toNNReal.comp measurable_snd + have hW : Measurable fun p : ContinuousPath alpha × ℝ ↦ + Real.exp (-feynmanKacAdditiveFunctional q s p.1) := + (stronglyMeasurable_feynmanKacAdditiveFunctional hq s).measurable.neg.exp.comp + measurable_fst + have hE : Measurable fun p : ContinuousPath alpha × ℝ ↦ Real.exp (-mu * p.2) := + (Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.comp + measurable_snd + have hFK : Measurable fun p : ContinuousPath alpha × ℝ ↦ + IsConservative.feynmanKac P hP q (Real.toNNReal p.2) f (p.1 s) := + (IsConservative.measurable_feynmanKac_joint P hP hq hf).comp + (htime.prodMk hstart) + exact ((hW.mul hE).mul hFK).stronglyMeasurable + have htimeInt : IntegrableOn (fun t : ℝ ↦ Real.exp (-mu * t) * D) (Ioi 0) := + (exp_neg_integrableOn_Ioi 0 hmu).mul_const D + have hdom : Integrable (fun p : ContinuousPath alpha × ℝ ↦ + (1 : ℝ) * (Real.exp (-mu * p.2) * D)) + (Qx.prod (volume.restrict (Ioi 0))) := + (integrable_const (μ := Qx) (1 : ℝ)).mul_prod htimeInt + have hHint : Integrable H (Qx.prod (volume.restrict (Ioi 0))) := by + apply Integrable.mono' hdom hHmeas.aestronglyMeasurable + exact Eventually.of_forall fun p ↦ by + dsimp only [H] + rw [Real.norm_eq_abs, abs_mul, abs_mul, abs_of_pos (Real.exp_pos _), + abs_of_pos (Real.exp_pos _), one_mul] + calc + Real.exp (-feynmanKacAdditiveFunctional q s p.1) * + Real.exp (-mu * p.2) * + |IsConservative.feynmanKac P hP q (Real.toNNReal p.2) f (p.1 s)| ≤ + 1 * Real.exp (-mu * p.2) * D := by + calc + Real.exp (-feynmanKacAdditiveFunctional q s p.1) * + Real.exp (-mu * p.2) * + |IsConservative.feynmanKac P hP q + (Real.toNNReal p.2) f (p.1 s)| ≤ + (1 * Real.exp (-mu * p.2)) * + |IsConservative.feynmanKac P hP q + (Real.toNNReal p.2) f (p.1 s)| := by + exact mul_le_mul_of_nonneg_right + (mul_le_mul_of_nonneg_right + ((Real.exp_le_one_iff).mpr + (neg_nonpos.mpr (feynmanKacAdditiveFunctional_nonneg hq0 s p.1))) + (Real.exp_pos _).le) (abs_nonneg _) + _ ≤ (1 * Real.exp (-mu * p.2)) * D := + mul_le_mul_of_nonneg_left + (IsConservative.norm_feynmanKac_le P hP hq0 + (Real.toNNReal p.2) hfD (p.1 s)) + (mul_nonneg zero_le_one (Real.exp_pos _).le) + _ = Real.exp (-mu * p.2) * D := by ring + rw [IsConservative.feynmanKac_apply] + unfold IsConservative.feynmanKacResolventReal + change (∫ omega, Real.exp (-feynmanKacAdditiveFunctional q s omega) * + (∫ t in Ioi (0 : ℝ), Real.exp (-mu * t) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) f (omega s)) ∂Qx) = _ + calc + (∫ omega, Real.exp (-feynmanKacAdditiveFunctional q s omega) * + (∫ t in Ioi (0 : ℝ), Real.exp (-mu * t) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) f (omega s)) ∂Qx) = + ∫ omega, (∫ t in Ioi (0 : ℝ), H (omega, t)) ∂Qx := by + apply integral_congr_ae + exact Eventually.of_forall fun omega ↦ by + dsimp only + rw [← integral_const_mul] + apply setIntegral_congr_fun measurableSet_Ioi + intro t _ht + dsimp only [H] + ring + _ = ∫ t in Ioi (0 : ℝ), ∫ omega, H (omega, t) ∂Qx := + integral_integral_swap hHint + _ = _ := by + apply setIntegral_congr_fun measurableSet_Ioi + intro t _ht + dsimp only [H] + calc + (∫ omega, Real.exp (-feynmanKacAdditiveFunctional q s omega) * + Real.exp (-mu * t) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) f (omega s) ∂Qx) = + ∫ omega, Real.exp (-mu * t) * + (Real.exp (-feynmanKacAdditiveFunctional q s omega) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) f (omega s)) ∂Qx := by + apply integral_congr_ae + exact Eventually.of_forall fun omega ↦ by ring + _ = Real.exp (-mu * t) * + ∫ omega, Real.exp (-feynmanKacAdditiveFunctional q s omega) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) f (omega s) ∂Qx := by + rw [integral_const_mul] + _ = Real.exp (-mu * t) * + IsConservative.feynmanKac P hP q (s + Real.toNNReal t) f x := by + rw [← IsConservative.feynmanKac_apply] + rw [← hFeller.feynmanKac_add P hP hK hq hq0 hqC s + (Real.toNNReal t) hf hfD x] + +private theorem exp_sub_mul_integral_exp_mul_exp_sub (lam mu u : ℝ) (hu : 0 ≤ u) : + (lam - mu) * (∫ s in Ioo (0 : ℝ) u, + Real.exp (-lam * s) * Real.exp (-mu * (u - s))) = + Real.exp (-mu * u) - Real.exp (-lam * u) := by + let phi : ℝ → ℝ := fun s ↦ + Real.exp (-lam * s) * Real.exp (-mu * (u - s)) + have hderiv (s : ℝ) : HasDerivAt phi ((mu - lam) * phi s) s := by + dsimp only [phi] + have hd := (((hasDerivAt_const s (-lam)).mul (hasDerivAt_id s)).exp.mul + ((hasDerivAt_const s (-mu)).mul + ((hasDerivAt_const s u).sub (hasDerivAt_id s))).exp) + convert hd using 1 + all_goals first + | rfl + | (simp only [Pi.mul_apply, Pi.sub_apply, id_eq]; ring) + have hint : IntervalIntegrable (fun s ↦ (mu - lam) * phi s) volume 0 u := + (continuous_const.mul + (continuous_iff_continuousAt.mpr fun s ↦ (hderiv s).continuousAt)).intervalIntegrable 0 u + have hFTC := intervalIntegral.integral_eq_sub_of_hasDerivAt + (fun s _hs ↦ hderiv s) hint + rw [intervalIntegral.integral_of_le hu, integral_Ioc_eq_integral_Ioo, + MeasureTheory.integral_const_mul] at hFTC + dsimp only [phi] at hFTC ⊢ + simp only [sub_self, mul_zero, Real.exp_zero, mul_one, sub_zero, one_mul] at hFTC + linarith only [hFTC] + +/-- The real Feynman--Kac resolvents satisfy the resolvent identity on bounded measurable +observables. -/ +theorem IsFellerKernelSemigroup.feynmanKacResolventReal_resolvent_identity + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + {q : alpha → ℝ} (hq : Measurable q) {C : ℝ} + (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + {mu lam : ℝ} (hmu : 0 < mu) (hlam : 0 < lam) {f : alpha → ℝ} + (hf : Measurable f) {D : ℝ} (hfD : ∀ y, |f y| ≤ D) : + IsConservative.feynmanKacResolventReal P hP q mu f = + IsConservative.feynmanKacResolventReal P hP q lam f + + (lam - mu) • IsConservative.feynmanKacResolventReal P hP q lam + (IsConservative.feynmanKacResolventReal P hP q mu f) := by + funext x + let H : ℝ × ℝ → ℝ := fun p ↦ + Real.exp (-lam * p.1) * Real.exp (-mu * p.2) * + IsConservative.feynmanKac P hP q + (Real.toNNReal p.1 + Real.toNNReal p.2) f x + let K : ℝ → ℝ := fun u ↦ ∫ s in Ioo (0 : ℝ) u, H (s, u - s) + have hHmeas : Measurable H := by + exact (((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.comp + measurable_fst).mul + ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.comp + measurable_snd)).mul + ((IsConservative.measurable_feynmanKac_joint P hP hq hf).comp + (((measurable_real_toNNReal.comp measurable_fst).add + (measurable_real_toNNReal.comp measurable_snd)).prodMk measurable_const)) + have hQ : MeasurableSet (Ioi (0 : ℝ) ×ˢ Ioi (0 : ℝ)) := + measurableSet_Ioi.prod measurableSet_Ioi + have hHquad : Integrable H + ((volume.restrict (Ioi (0 : ℝ))).prod (volume.restrict (Ioi (0 : ℝ)))) := by + have hbase := (exp_neg_integrableOn_Ioi 0 hlam).mul_prod + ((exp_neg_integrableOn_Ioi 0 hmu).mul_const D) + apply Integrable.mono' hbase hHmeas.aestronglyMeasurable + exact Eventually.of_forall fun p ↦ by + dsimp only [H] + rw [Real.norm_eq_abs, abs_mul, abs_mul, abs_of_pos (Real.exp_pos _), + abs_of_pos (Real.exp_pos _)] + exact mul_le_mul_of_nonneg_left + (IsConservative.norm_feynmanKac_le P hP hq0 + (Real.toNNReal p.1 + Real.toNNReal p.2) hfD x) + (mul_nonneg (Real.exp_pos _).le (Real.exp_pos _).le) |>.trans_eq (by ring) + have hHind : Integrable ((Ioi (0 : ℝ) ×ˢ Ioi (0 : ℝ)).indicator H) + (volume.prod volume) := by + apply (integrable_indicator_iff hQ).2 + change Integrable H ((volume.prod volume).restrict (Ioi (0 : ℝ) ×ˢ Ioi (0 : ℝ))) + rw [← Measure.prod_restrict] + exact hHquad + have htriangle := intervalIntegral.integral_timeTriangle_sub hHmeas hHind + have hmuInt := IsConservative.integrableOn_feynmanKacResolventReal_integrand + P hP hq hq0 hmu hf hfD x + have hlamInt := IsConservative.integrableOn_feynmanKacResolventReal_integrand + P hP hq hq0 hlam hf hfD x + have hpoint (u : ℝ) (hu : u ∈ Ioi (0 : ℝ)) : + Real.exp (-mu * u) * IsConservative.feynmanKac P hP q (Real.toNNReal u) f x = + Real.exp (-lam * u) * IsConservative.feynmanKac P hP q (Real.toNNReal u) f x + + (lam - mu) * K u := by + have hK : K u = (∫ s in Ioo (0 : ℝ) u, + Real.exp (-lam * s) * Real.exp (-mu * (u - s))) * + IsConservative.feynmanKac P hP q (Real.toNNReal u) f x := by + dsimp only [K] + rw [← MeasureTheory.integral_mul_const] + apply setIntegral_congr_fun measurableSet_Ioo + intro s hs + dsimp only [H] + have hs0 : 0 ≤ s := hs.1.le + have hus0 : 0 ≤ u - s := sub_nonneg.mpr hs.2.le + have htime : Real.toNNReal s + Real.toNNReal (u - s) = Real.toNNReal u := by + apply NNReal.coe_injective + rw [NNReal.coe_add, Real.coe_toNNReal s hs0, Real.coe_toNNReal (u - s) hus0, + Real.coe_toNNReal u hu.le] + ring + rw [htime] + rw [hK] + have hexp := exp_sub_mul_integral_exp_mul_exp_sub lam mu u hu.le + calc + Real.exp (-mu * u) * IsConservative.feynmanKac P hP q (Real.toNNReal u) f x = + (Real.exp (-lam * u) + + (lam - mu) * (∫ s in Ioo (0 : ℝ) u, + Real.exp (-lam * s) * Real.exp (-mu * (u - s)))) * + IsConservative.feynmanKac P hP q (Real.toNNReal u) f x := by + rw [hexp] + ring + _ = _ := by ring + have hsecond : IntegrableOn (fun u ↦ (lam - mu) * K u) (Ioi (0 : ℝ)) := by + apply (hmuInt.sub hlamInt).congr + filter_upwards [ae_restrict_mem measurableSet_Ioi] with u hu + change Real.exp (-mu * u) * IsConservative.feynmanKac P hP q (Real.toNNReal u) f x - + Real.exp (-lam * u) * IsConservative.feynmanKac P hP q (Real.toNNReal u) f x = + (lam - mu) * K u + linarith only [hpoint u hu] + have hcomp : IsConservative.feynmanKacResolventReal P hP q lam + (IsConservative.feynmanKacResolventReal P hP q mu f) x = + ∫ s in Ioi (0 : ℝ), ∫ t in Ioi (0 : ℝ), H (s, t) := by + change (∫ s in Ioi (0 : ℝ), Real.exp (-lam * s) * + IsConservative.feynmanKac P hP q (Real.toNNReal s) + (IsConservative.feynmanKacResolventReal P hP q mu f) x) = _ + apply setIntegral_congr_fun measurableSet_Ioi + intro s _hs + dsimp only + rw [hFeller.feynmanKac_comp_feynmanKacResolventReal + P hP hK hq hq0 hqC hmu (Real.toNNReal s) hf hfD x] + rw [← MeasureTheory.integral_const_mul] + apply setIntegral_congr_fun measurableSet_Ioi + intro t _ht + dsimp only [H] + ring + have htriangle' : (∫ u in Ioi (0 : ℝ), K u) = + ∫ s in Ioi (0 : ℝ), ∫ t in Ioi (0 : ℝ), H (s, t) := by + simpa only [K] using htriangle + change (∫ u in Ioi (0 : ℝ), Real.exp (-mu * u) * + IsConservative.feynmanKac P hP q (Real.toNNReal u) f x) = + (∫ u in Ioi (0 : ℝ), Real.exp (-lam * u) * + IsConservative.feynmanKac P hP q (Real.toNNReal u) f x) + + (lam - mu) * IsConservative.feynmanKacResolventReal P hP q lam + (IsConservative.feynmanKacResolventReal P hP q mu f) x + rw [hcomp, ← htriangle', ← MeasureTheory.integral_const_mul, + ← integral_add hlamInt hsecond] + apply setIntegral_congr_fun measurableSet_Ioi + exact hpoint + +/-- The real kernel resolvents satisfy the resolvent identity on bounded measurable +observables. -/ +theorem IsFellerKernelSemigroup.kernelResolventReal_resolvent_identity + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + {mu lam : ℝ} (hmu : 0 < mu) (hlam : 0 < lam) {f : alpha → ℝ} + (hf : Measurable f) {D : ℝ} (hfD : ∀ y, |f y| ≤ D) : + P.kernelResolventReal mu f = P.kernelResolventReal lam f + + (lam - mu) • P.kernelResolventReal lam (P.kernelResolventReal mu f) := by + have hmuEq := hFeller.feynmanKacResolventReal_zero_eq_kernelResolventReal + P hP hK mu hf + have hlamEq := hFeller.feynmanKacResolventReal_zero_eq_kernelResolventReal + P hP hK lam hf + have hRmeas := hFeller.measurable_kernelResolventReal P hP hK mu hf + have hcompEq := hFeller.feynmanKacResolventReal_zero_eq_kernelResolventReal + P hP hK lam hRmeas + calc + P.kernelResolventReal mu f = + IsConservative.feynmanKacResolventReal P hP (fun _ ↦ 0) mu f := hmuEq.symm + _ = IsConservative.feynmanKacResolventReal P hP (fun _ ↦ 0) lam f + + (lam - mu) • IsConservative.feynmanKacResolventReal P hP (fun _ ↦ 0) lam + (IsConservative.feynmanKacResolventReal P hP (fun _ ↦ 0) mu f) := + hFeller.feynmanKacResolventReal_resolvent_identity P hP hK measurable_const + (fun _ ↦ le_rfl) (fun _ ↦ le_rfl) hmu hlam hf hfD + _ = P.kernelResolventReal lam f + + (lam - mu) • P.kernelResolventReal lam (P.kernelResolventReal mu f) := by + rw [hlamEq, hmuEq, hcompEq] + +omit [LocallyCompactSpace alpha] in +private theorem IsConservative.kernelIntegral_mul_feynmanKacResolventReal + {q : alpha → ℝ} (hq : Measurable q) + {C : ℝ} (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + {lam : ℝ} (hlam : 0 < lam) (s : NNReal) {f : alpha → ℝ} + (hf : Measurable f) {D : ℝ} (hfD : ∀ y, |f y| ≤ D) (x : alpha) : + kernelIntegral (P s) + (fun y ↦ q y * IsConservative.feynmanKacResolventReal P hP q lam f y) x = + ∫ u in Ioi (0 : ℝ), Real.exp (-lam * u) * + kernelIntegral (P s) + (fun y ↦ q y * IsConservative.feynmanKac P hP q (Real.toNNReal u) f y) x := by + let H : alpha × ℝ → ℝ := fun p ↦ + q p.1 * Real.exp (-lam * p.2) * + IsConservative.feynmanKac P hP q (Real.toNNReal p.2) f p.1 + have hHmeas : StronglyMeasurable H := by + exact (((hq.comp measurable_fst).mul + ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.comp + measurable_snd)).mul + ((IsConservative.measurable_feynmanKac_joint P hP hq hf).comp + ((measurable_real_toNNReal.comp measurable_snd).prodMk measurable_fst) + )).stronglyMeasurable + let : IsFiniteKernel (P s) := (P.isSubMarkovKernel s).isFiniteKernel + have hC0 : 0 ≤ C := (hq0 x).trans (hqC x) + have hD0 : 0 ≤ D := (abs_nonneg (f x)).trans (hfD x) + have hbase : Integrable (fun p : alpha × ℝ ↦ + C * (Real.exp (-lam * p.2) * D)) + ((P s x).prod (volume.restrict (Ioi 0))) := + (integrable_const (C : ℝ)).mul_prod ((exp_neg_integrableOn_Ioi 0 hlam).mul_const D) + have hHint : Integrable H ((P s x).prod (volume.restrict (Ioi 0))) := by + apply Integrable.mono' hbase hHmeas.aestronglyMeasurable + exact Eventually.of_forall fun p ↦ by + dsimp only [H] + rw [Real.norm_eq_abs, abs_mul, abs_mul, abs_of_nonneg (hq0 p.1), + abs_of_pos (Real.exp_pos _)] + calc + q p.1 * Real.exp (-lam * p.2) * + |IsConservative.feynmanKac P hP q (Real.toNNReal p.2) f p.1| ≤ + C * Real.exp (-lam * p.2) * D := by + exact mul_le_mul + (mul_le_mul (hqC p.1) le_rfl (Real.exp_pos _).le hC0) + (IsConservative.norm_feynmanKac_le P hP hq0 + (Real.toNNReal p.2) hfD p.1) (abs_nonneg _) + (mul_nonneg hC0 (Real.exp_pos _).le) + _ = C * (Real.exp (-lam * p.2) * D) := by ring + unfold IsConservative.feynmanKacResolventReal + change (∫ y, q y * (∫ u in Ioi (0 : ℝ), Real.exp (-lam * u) * + IsConservative.feynmanKac P hP q (Real.toNNReal u) f y) ∂(P s x)) = _ + calc + (∫ y, q y * (∫ u in Ioi (0 : ℝ), Real.exp (-lam * u) * + IsConservative.feynmanKac P hP q (Real.toNNReal u) f y) ∂(P s x)) = + ∫ y, (∫ u in Ioi (0 : ℝ), H (y, u)) ∂(P s x) := by + apply integral_congr_ae + exact Eventually.of_forall fun y ↦ by + dsimp only + rw [← MeasureTheory.integral_const_mul] + apply setIntegral_congr_fun measurableSet_Ioi + intro u _hu + dsimp only [H] + ring + _ = ∫ u in Ioi (0 : ℝ), ∫ y, H (y, u) ∂(P s x) := + integral_integral_swap hHint + _ = _ := by + apply setIntegral_congr_fun measurableSet_Ioi + intro u _hu + dsimp only [H] + calc + (∫ y, q y * Real.exp (-lam * u) * + IsConservative.feynmanKac P hP q (Real.toNNReal u) f y ∂(P s x)) = + ∫ y, Real.exp (-lam * u) * + (q y * IsConservative.feynmanKac P hP q (Real.toNNReal u) f y) + ∂(P s x) := by + apply integral_congr_ae + exact Eventually.of_forall fun y ↦ by ring + _ = Real.exp (-lam * u) * + ∫ y, q y * IsConservative.feynmanKac P hP q (Real.toNNReal u) f y + ∂(P s x) := MeasureTheory.integral_const_mul _ _ + +/-- The real Feynman--Kac resolvent satisfies the bounded-potential perturbation equation against +the real kernel resolvent. This supplies the Feynman--Kac fixed-point input to +`perturbed_eq_of_resolventFamilies`. -/ +theorem IsFellerKernelSemigroup.feynmanKacResolventReal_perturbation + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + {q : alpha → ℝ} (hq : Measurable q) {C : ℝ} + (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + {lam : ℝ} (hlam : 0 < lam) {f : alpha → ℝ} (hf : Measurable f) + {D : ℝ} (hfD : ∀ y, |f y| ≤ D) : + IsConservative.feynmanKacResolventReal P hP q lam f = + P.kernelResolventReal lam f - P.kernelResolventReal lam + (fun y ↦ q y * IsConservative.feynmanKacResolventReal P hP q lam f y) := by + funext x + let H : ℝ × ℝ → ℝ := fun p ↦ + Real.exp (-lam * (p.1 + p.2)) * + kernelIntegral (P (Real.toNNReal p.1)) + (fun y ↦ q y * IsConservative.feynmanKac P hP q (Real.toNNReal p.2) f y) x + have hHmeas : Measurable H := by + have hintegrand : Measurable fun p : (ℝ × ℝ) × alpha ↦ + q p.2 * IsConservative.feynmanKac P hP q (Real.toNNReal p.1.2) f p.2 := + (hq.comp measurable_snd).mul + ((IsConservative.measurable_feynmanKac_joint P hP hq hf).comp + (((measurable_real_toNNReal.comp measurable_snd).comp measurable_fst).prodMk + measurable_snd)) + let K : Kernel (ℝ × ℝ) alpha := + { toFun := fun p ↦ P (Real.toNNReal p.1) x + measurable' := P.measurable_toMeasure.comp + ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_const) } + let : IsFiniteKernel K := + { exists_univ_le := ⟨1, ENNReal.one_lt_top, fun p ↦ P.measure_univ_le_one _ _⟩ } + have hkernel : Measurable fun p : ℝ × ℝ ↦ + kernelIntegral (P (Real.toNNReal p.1)) + (fun y ↦ q y * IsConservative.feynmanKac P hP q (Real.toNNReal p.2) f y) x := by + have hlin := hintegrand.stronglyMeasurable.integral_kernel_prod_right' (κ := K) + simpa only [K, kernelIntegral] using! hlin.measurable + exact ((Real.continuous_exp.comp + (continuous_const.mul (continuous_fst.add continuous_snd))).measurable.mul hkernel) + have hC0 : 0 ≤ C := (hq0 x).trans (hqC x) + have hD0 : 0 ≤ D := (abs_nonneg (f x)).trans (hfD x) + have hinnerBound (s u : ℝ) : + |kernelIntegral (P (Real.toNNReal s)) + (fun y ↦ q y * IsConservative.feynmanKac P hP q (Real.toNNReal u) f y) x| ≤ + C * D := by + rw [← Real.norm_eq_abs] + let : IsFiniteKernel (P (Real.toNNReal s)) := + (P.isSubMarkovKernel (Real.toNNReal s)).isFiniteKernel + calc + ‖kernelIntegral (P (Real.toNNReal s)) + (fun y ↦ q y * IsConservative.feynmanKac P hP q (Real.toNNReal u) f y) x‖ ≤ + ∫ _y, C * D ∂(P (Real.toNNReal s) x) := by + apply norm_integral_le_of_norm_le (integrable_const (C * D)) + exact Eventually.of_forall fun y ↦ by + rw [Real.norm_eq_abs, abs_mul, abs_of_nonneg (hq0 y)] + exact mul_le_mul (hqC y) + (IsConservative.norm_feynmanKac_le P hP hq0 (Real.toNNReal u) hfD y) + (abs_nonneg _) hC0 + _ ≤ C * D := by + rw [integral_const, smul_eq_mul] + apply mul_le_of_le_one_left (mul_nonneg hC0 hD0) + rw [measureReal_def, ← ENNReal.toReal_one] + apply (ENNReal.toReal_le_toReal (measure_ne_top _ _) ENNReal.one_ne_top).2 + exact (P.isSubMarkovKernel (Real.toNNReal s)).measure_le_one x Set.univ + have hQ : MeasurableSet (Ioi (0 : ℝ) ×ˢ Ioi (0 : ℝ)) := + measurableSet_Ioi.prod measurableSet_Ioi + have hHquad : Integrable H + ((volume.restrict (Ioi (0 : ℝ))).prod (volume.restrict (Ioi (0 : ℝ)))) := by + have hbase := (exp_neg_integrableOn_Ioi 0 hlam).mul_prod + ((exp_neg_integrableOn_Ioi 0 hlam).mul_const (C * D)) + apply Integrable.mono' hbase hHmeas.stronglyMeasurable.aestronglyMeasurable + exact Eventually.of_forall fun p ↦ by + dsimp only [H] + rw [Real.norm_eq_abs, abs_mul, abs_of_pos (Real.exp_pos _)] + calc + Real.exp (-lam * (p.1 + p.2)) * + |kernelIntegral (P (Real.toNNReal p.1)) + (fun y ↦ q y * IsConservative.feynmanKac P hP q + (Real.toNNReal p.2) f y) x| ≤ + Real.exp (-lam * (p.1 + p.2)) * (C * D) := + mul_le_mul_of_nonneg_left (hinnerBound p.1 p.2) (Real.exp_pos _).le + _ = Real.exp (-lam * p.1) * (Real.exp (-lam * p.2) * (C * D)) := by + rw [show -lam * (p.1 + p.2) = -lam * p.1 + -lam * p.2 by ring, + Real.exp_add] + ring + have hHind : Integrable ((Ioi (0 : ℝ) ×ˢ Ioi (0 : ℝ)).indicator H) + (volume.prod volume) := by + apply (integrable_indicator_iff hQ).2 + change Integrable H ((volume.prod volume).restrict (Ioi (0 : ℝ) ×ˢ Ioi (0 : ℝ))) + rw [← Measure.prod_restrict] + exact hHquad + have htriangle := intervalIntegral.integral_timeTriangle_sub hHmeas hHind + have hFKInt := IsConservative.integrableOn_feynmanKacResolventReal_integrand + P hP hq hq0 hlam hf hfD x + have hKernelInt : IntegrableOn (fun t : ℝ ↦ Real.exp (-lam * t) * + kernelIntegral (P (Real.toNNReal t)) f x) (Ioi 0) := by + have hzero := IsConservative.integrableOn_feynmanKacResolventReal_integrand + P hP measurable_const (fun _ ↦ le_rfl) hlam hf hfD x + apply hzero.congr + filter_upwards [ae_restrict_mem measurableSet_Ioi] with t _ht + have heval := hFeller.integral_eval_continuousProcess_of_measurable + P hP hK (Real.toNNReal t) x hf + simp only [IsConservative.feynmanKac_apply, feynmanKacAdditiveFunctional, + intervalIntegral.integral_zero, neg_zero, Real.exp_zero, one_mul] + rw [heval] + rfl + have htime (t : ℝ) (ht : t ∈ Ioi (0 : ℝ)) : + Real.exp (-lam * t) * + (kernelIntegral (P (Real.toNNReal t)) f x - + IsConservative.feynmanKac P hP q (Real.toNNReal t) f x) = + ∫ s in Ioo (0 : ℝ) t, H (s, t - s) := by + have hfinite := hFeller.integral_sub_feynmanKac_eq_integral_of_norm_le + P hP hK hq hq0 hqC hf hfD (Real.toNNReal t) x + rw [intervalIntegral.integral_of_le (Real.toNNReal t).coe_nonneg, + integral_Ioc_eq_integral_Ioo, Real.coe_toNNReal t ht.le] at hfinite + change kernelIntegral (P (Real.toNNReal t)) f x - + IsConservative.feynmanKac P hP q (Real.toNNReal t) f x = _ at hfinite + calc + Real.exp (-lam * t) * + (kernelIntegral (P (Real.toNNReal t)) f x - + IsConservative.feynmanKac P hP q (Real.toNNReal t) f x) = + Real.exp (-lam * t) * + ∫ s in Ioo (0 : ℝ) t, kernelIntegral (P (Real.toNNReal s)) + (fun y ↦ q y * IsConservative.feynmanKac P hP q + (Real.toNNReal t - Real.toNNReal s) f y) x := by + rw [hfinite] + congr 2 + _ = ∫ s in Ioo (0 : ℝ) t, Real.exp (-lam * t) * + kernelIntegral (P (Real.toNNReal s)) + (fun y ↦ q y * IsConservative.feynmanKac P hP q + (Real.toNNReal t - Real.toNNReal s) f y) x := by + rw [MeasureTheory.integral_const_mul] + _ = ∫ s in Ioo (0 : ℝ) t, H (s, t - s) := by + apply setIntegral_congr_fun measurableSet_Ioo + intro s hs + have hs0 : 0 ≤ s := hs.1.le + have hsub0 : 0 ≤ t - s := sub_nonneg.mpr hs.2.le + have hsub : Real.toNNReal t - Real.toNNReal s = Real.toNNReal (t - s) := by + apply NNReal.coe_injective + rw [NNReal.coe_sub (Real.toNNReal_le_toNNReal hs.2.le), + Real.coe_toNNReal t ht.le, Real.coe_toNNReal s hs0, + Real.coe_toNNReal (t - s) hsub0] + dsimp only [H] + rw [hsub] + congr 2 + ring + have hcorr : P.kernelResolventReal lam + (fun y ↦ q y * IsConservative.feynmanKacResolventReal P hP q lam f y) x = + ∫ s in Ioi (0 : ℝ), ∫ u in Ioi (0 : ℝ), H (s, u) := by + unfold SubMarkovKernelSemigroup.kernelResolventReal + apply setIntegral_congr_fun measurableSet_Ioi + intro s hs + dsimp only + rw [hP.kernelIntegral_mul_feynmanKacResolventReal + P hq hq0 hqC hlam (Real.toNNReal s) hf hfD x] + rw [← MeasureTheory.integral_const_mul] + apply setIntegral_congr_fun measurableSet_Ioi + intro u _hu + dsimp only [H] + rw [show -lam * (s + u) = -lam * s + -lam * u by ring, Real.exp_add] + ring + have hdiff : P.kernelResolventReal lam f x - + IsConservative.feynmanKacResolventReal P hP q lam f x = + P.kernelResolventReal lam + (fun y ↦ q y * IsConservative.feynmanKacResolventReal P hP q lam f y) x := by + unfold SubMarkovKernelSemigroup.kernelResolventReal + unfold IsConservative.feynmanKacResolventReal + rw [← integral_sub hKernelInt hFKInt] + calc + (∫ t in Ioi (0 : ℝ), + Real.exp (-lam * t) * kernelIntegral (P (Real.toNNReal t)) f x - + Real.exp (-lam * t) * + IsConservative.feynmanKac P hP q (Real.toNNReal t) f x) = + ∫ t in Ioi (0 : ℝ), ∫ s in Ioo (0 : ℝ) t, H (s, t - s) := by + apply setIntegral_congr_fun measurableSet_Ioi + intro t ht + dsimp only + rw [← mul_sub] + exact htime t ht + _ = ∫ s in Ioi (0 : ℝ), ∫ u in Ioi (0 : ℝ), H (s, u) := htriangle + _ = _ := hcorr.symm + simp only [Pi.sub_apply] + linarith only [hdiff] + +end + + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacResolvent.lean new file mode 100644 index 0000000000..ad3de92cff --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacResolvent.lean @@ -0,0 +1,748 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import Mathlib.Analysis.SpecialFunctions.ImproperIntegrals +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition + +/-! +# Feynman--Kac resolvents + +This file Laplace-transforms the nonnegative extended-real Feynman--Kac operators and proves their +path-occupation formula, comparison with killed resolvents, and perturbation identities against +the unperturbed kernel resolvent. + +Main results: `IsConservative.feynmanKacResolvent`, +`IsConservative.feynmanKacResolvent_eq_lintegral_path`, +`IsConservative.killedResolvent_le_feynmanKacResolvent`, +`IsFellerKernelSemigroup.integral_sub_feynmanKac_eq_integral_of_norm_le`, +`IsFellerKernelSemigroup.kernelResolvent_eq_feynmanKacResolvent_add`, and +`IsFellerKernelSemigroup.feynmanKacResolvent_eq_kernelResolvent_sub`. + +No uniqueness statement for the associated resolvent equation is asserted. +-/ + +open Filter MeasureTheory ProbabilityTheory Set +open scoped ENNReal NNReal + +namespace MarkovProcess.SubMarkovKernelSemigroup + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [CompleteSpace alpha] [Nonempty alpha] + [LocallyCompactSpace alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- The Feynman--Kac resolvent, obtained by Laplace-transforming the extended-real operators. -/ +def IsConservative.feynmanKacResolvent (q : alpha → ℝ) (lam : ℝ) + (f : alpha → ℝ≥0∞) (x : alpha) : ℝ≥0∞ := + ∫⁻ t in Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + IsConservative.feynmanKacENNReal P hP q (Real.toNNReal t) f x + +omit [LocallyCompactSpace alpha] in +/-- The Feynman--Kac resolvent is measurable in the starting point. -/ +theorem IsConservative.measurable_feynmanKacResolvent {q : alpha → ℝ} + (hq : Measurable q) (lam : ℝ) {f : alpha → ℝ≥0∞} (hf : Measurable f) : + Measurable (IsConservative.feynmanKacResolvent P hP q lam f) := by + have hjoint : Measurable fun p : ℝ × alpha ↦ + ENNReal.ofReal (Real.exp (-lam * p.1)) * + IsConservative.feynmanKacENNReal P hP q (Real.toNNReal p.1) f p.2 := by + exact (ENNReal.measurable_ofReal.comp + ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.comp + measurable_fst)).mul + ((IsConservative.measurable_feynmanKacENNReal_joint P hP hq hf).comp + ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_snd)) + exact hjoint.lintegral_prod_left' (μ := volume.restrict (Ioi 0)) + +omit [LocallyCompactSpace alpha] in +/-- The Feynman--Kac resolvent is the expected discounted weighted path occupation. -/ +theorem IsConservative.feynmanKacResolvent_eq_lintegral_path {q : alpha → ℝ} + (hq : Measurable q) (lam : ℝ) {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + IsConservative.feynmanKacResolvent P hP q lam f x = + ∫⁻ omega, (∫⁻ t in Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + (ENNReal.ofReal (Real.exp + (-feynmanKacAdditiveFunctional q (Real.toNNReal t) omega)) * + f (omega (Real.toNNReal t)))) + ∂(IsConservative.continuousProcess P hP x) := by + have hA : Measurable fun p : ℝ × ContinuousPath alpha ↦ + feynmanKacAdditiveFunctional q (Real.toNNReal p.1) p.2 := + (stronglyMeasurable_feynmanKacAdditiveFunctional_joint hq).measurable.comp + ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_snd) + have heval : Measurable fun p : ℝ × ContinuousPath alpha ↦ + p.2 (Real.toNNReal p.1) := + (ContinuousEval.continuous_eval.comp continuous_swap).measurable.comp + ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_snd) + have hjoint : Measurable fun p : ℝ × ContinuousPath alpha ↦ + ENNReal.ofReal (Real.exp (-lam * p.1)) * + (ENNReal.ofReal (Real.exp + (-feynmanKacAdditiveFunctional q (Real.toNNReal p.1) p.2)) * + f (p.2 (Real.toNNReal p.1))) := + (ENNReal.measurable_ofReal.comp + ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.comp + measurable_fst)).mul + ((hA.neg.exp.ennreal_ofReal).mul (hf.comp heval)) + unfold IsConservative.feynmanKacResolvent IsConservative.feynmanKacENNReal + calc + (∫⁻ t in Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + ∫⁻ omega, ENNReal.ofReal (Real.exp + (-feynmanKacAdditiveFunctional q (Real.toNNReal t) omega)) * + f (omega (Real.toNNReal t)) + ∂(IsConservative.continuousProcess P hP x)) = + ∫⁻ t in Ioi (0 : ℝ), ∫⁻ omega, + ENNReal.ofReal (Real.exp (-lam * t)) * + (ENNReal.ofReal (Real.exp + (-feynmanKacAdditiveFunctional q (Real.toNNReal t) omega)) * + f (omega (Real.toNNReal t))) + ∂(IsConservative.continuousProcess P hP x) := by + apply setLIntegral_congr_fun measurableSet_Ioi + intro t _ht + exact (lintegral_const_mul' _ _ (by finiteness)).symm + _ = _ := lintegral_lintegral_swap hjoint.aemeasurable + +/-- The kernel resolvent is the killed resolvent for the whole state space. -/ +theorem IsFellerKernelSemigroup.kernelResolvent_eq_killedResolvent_univ + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (lam : ℝ) {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + P.kernelResolvent lam f x = + IsConservative.killedResolvent P hP Set.univ isOpen_univ lam f x := by + have hzero : P.kernelResolvent lam f x = + IsConservative.feynmanKacResolvent P hP (fun _ ↦ 0) lam f x := by + unfold SubMarkovKernelSemigroup.kernelResolvent IsConservative.feynmanKacResolvent + apply setLIntegral_congr_fun measurableSet_Ioi + intro t _ht + unfold IsConservative.feynmanKacENNReal + simp only [feynmanKacAdditiveFunctional, intervalIntegral.integral_zero, + neg_zero, Real.exp_zero, ENNReal.ofReal_one, one_mul] + have heval := ContinuousPath.measurable_coordinateProcess + (alpha := alpha) (Real.toNNReal t) + have hin : + (∫⁻ y, f y ∂(P (Real.toNNReal t) x)) = + ∫⁻ omega, f (omega (Real.toNNReal t)) + ∂(IsConservative.continuousProcess P hP x) := by + calc + (∫⁻ y, f y ∂(P (Real.toNNReal t) x)) = + ∫⁻ y, f y ∂((IsConservative.continuousProcess P hP).map + (ContinuousPath.coordinateProcess (alpha := alpha) (Real.toNNReal t))) x := by + have hmap : (IsConservative.continuousProcess P hP).map + (ContinuousPath.coordinateProcess (alpha := alpha) (Real.toNNReal t)) = + P (Real.toNNReal t) := by + simpa only [ContinuousPath.coordinateProcess] using! + hFeller.continuousProcess_map_eval_nnreal P hP hK (Real.toNNReal t) + rw [hmap] + _ = ∫⁻ omega, f (omega (Real.toNNReal t)) + ∂(IsConservative.continuousProcess P hP x) := by + rw [Kernel.map_apply _ heval] + exact lintegral_map hf heval + exact congrArg (fun z ↦ ENNReal.ofReal (Real.exp (-lam * t)) * z) hin + calc + P.kernelResolvent lam f x = + IsConservative.feynmanKacResolvent P hP (fun _ ↦ 0) lam f x := hzero + _ = ∫⁻ omega, ContinuousPath.pathResolvent lam f omega + ∂(IsConservative.continuousProcess P hP x) := by + simpa only [ContinuousPath.pathResolvent, feynmanKacAdditiveFunctional, + intervalIntegral.integral_zero, neg_zero, Real.exp_zero, ENNReal.ofReal_one, + one_mul] using + IsConservative.feynmanKacResolvent_eq_lintegral_path P hP + (q := fun _ ↦ 0) measurable_const lam hf x + _ = IsConservative.killedResolvent P hP Set.univ isOpen_univ lam f x := + IsConservative.lintegral_pathResolvent_eq_killedResolvent_univ P hP lam hf x + +omit [LocallyCompactSpace alpha] in +/-- The Feynman--Kac resolvent dominates the resolvent of the process killed on leaving an open +set when the potential vanishes there. No sign condition on the potential is needed away from +the open set. -/ +theorem IsConservative.killedResolvent_le_feynmanKacResolvent + {q : alpha → ℝ} (hq : Measurable q) + {U : Set alpha} (hU : IsOpen U) (hqU : ∀ y ∈ U, q y = 0) + (lam : ℝ) {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + IsConservative.killedResolvent P hP U hU lam f x ≤ + IsConservative.feynmanKacResolvent P hP q lam f x := by + rw [IsConservative.killedResolvent_eq_lintegral P hP U hU lam hf x, + IsConservative.feynmanKacResolvent_eq_lintegral_path P hP hq lam hf x] + apply lintegral_mono + intro omega + apply setLIntegral_mono' measurableSet_Ioi + intro t ht + have ht0 : 0 < t := ht + let u : NNReal := Real.toNNReal t + by_cases hsurv : (u : ℝ≥0∞) < ContinuousPath.exitTime U omega + · have hA0 : feynmanKacAdditiveFunctional q u omega = 0 := by + rw [feynmanKacAdditiveFunctional_apply] + calc + (∫ s in (0 : ℝ)..u, q (omega (Real.toNNReal s))) = ∫ _s in (0 : ℝ)..u, 0 := by + apply intervalIntegral.integral_congr + intro s hs + have hsu : Real.toNNReal s ≤ u := by + apply Real.toNNReal_le_iff_le_coe.mpr + rw [uIcc_of_le u.coe_nonneg] at hs + exact hs.2 + exact hqU _ (ContinuousPath.mem_of_lt_exitTime U omega (Real.toNNReal s) + ((ENNReal.coe_le_coe.mpr hsu).trans_lt hsurv)) + _ = 0 := intervalIntegral.integral_zero + have hsurv' : t ∈ {r : ℝ | ((Real.toNNReal r : NNReal) : ℝ≥0∞) < + ContinuousPath.exitTime U omega} := by simpa only [u] using! hsurv + rw [indicator_of_mem hsurv', show feynmanKacAdditiveFunctional q (Real.toNNReal t) omega = 0 + by simpa only [u] using hA0, neg_zero, Real.exp_zero, ENNReal.ofReal_one, + one_mul] + · have hsurv' : t ∉ {r : ℝ | ((Real.toNNReal r : NNReal) : ℝ≥0∞) < + ContinuousPath.exitTime U omega} := by simpa only [u] using! hsurv + simp only [indicator_of_notMem hsurv', mul_zero, zero_le] + +/-- Finite-time perturbation formula for the Feynman--Kac operators on bounded real +observables. -/ +theorem IsFellerKernelSemigroup.integral_sub_feynmanKac_eq_integral_of_norm_le + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + {q : alpha → ℝ} (hq : Measurable q) {C : ℝ} + (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + {f : alpha → ℝ} (hf : Measurable f) + {D : ℝ} (hfD : ∀ y, |f y| ≤ D) (t : NNReal) (x : alpha) : + (∫ y, f y ∂(P t x)) - IsConservative.feynmanKac P hP q t f x = + ∫ s in (0 : ℝ)..t, ∫ y, q y * + IsConservative.feynmanKac P hP q (t - Real.toNNReal s) f y + ∂(P (Real.toNNReal s) x) := by + have hC : 0 ≤ C := (hq0 x).trans (hqC x) + let mu : Measure (ContinuousPath alpha) := IsConservative.continuousProcess P hP x + let H : ℝ × ContinuousPath alpha → ℝ := fun p ↦ + q (p.2 (Real.toNNReal p.1)) * + Real.exp (-(feynmanKacAdditiveFunctional q t p.2 - + feynmanKacAdditiveFunctional q (Real.toNNReal p.1) p.2)) * f (p.2 t) + have hevalJoint : Measurable fun p : ℝ × ContinuousPath alpha ↦ + p.2 (Real.toNNReal p.1) := + (ContinuousEval.continuous_eval.comp continuous_swap).measurable.comp + ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_snd) + have hAs : Measurable fun p : ℝ × ContinuousPath alpha ↦ + feynmanKacAdditiveFunctional q (Real.toNNReal p.1) p.2 := + (stronglyMeasurable_feynmanKacAdditiveFunctional_joint hq).measurable.comp + ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_snd) + have hAt : Measurable fun p : ℝ × ContinuousPath alpha ↦ + feynmanKacAdditiveFunctional q t p.2 := + (stronglyMeasurable_feynmanKacAdditiveFunctional hq t).measurable.comp measurable_snd + have hH : StronglyMeasurable H := by + exact (((hq.comp hevalJoint).mul ((hAt.sub hAs).neg.exp)).mul + ((hf.comp (ContinuousPath.measurable_coordinateProcess (alpha := alpha) t)).comp + measurable_snd)).stronglyMeasurable + have hD0 : 0 ≤ D := (abs_nonneg (f x)).trans (hfD x) + have hHbound (s : ℝ) (hs : s ∈ Icc (0 : ℝ) (t : ℝ)) + (omega : ContinuousPath alpha) : ‖H (s, omega)‖ ≤ C * D := by + have hsNN : Real.toNNReal s ≤ t := Real.toNNReal_le_iff_le_coe.mpr hs.2 + have hAdiff : 0 ≤ feynmanKacAdditiveFunctional q t omega - + feynmanKacAdditiveFunctional q (Real.toNNReal s) omega := + sub_nonneg.mpr (feynmanKacAdditiveFunctional_mono hq hq0 hqC hsNN omega) + dsimp only [H] + rw [Real.norm_eq_abs, abs_mul, abs_mul, abs_of_nonneg (hq0 _), + abs_of_pos (Real.exp_pos _)] + calc + q (omega (Real.toNNReal s)) * Real.exp (-_) * |f (omega t)| ≤ + C * 1 * D := by + exact mul_le_mul + (mul_le_mul (hqC _) + ((Real.exp_le_one_iff).mpr (neg_nonpos.mpr hAdiff)) + (Real.exp_pos _).le hC) (hfD _) (abs_nonneg _) (mul_nonneg hC zero_le_one) + _ = C * D := by ring + have hProdInt : Integrable (Function.uncurry fun (s : ℝ) + (omega : ContinuousPath alpha) ↦ H (s, omega)) + ((volume.restrict (Ioc (0 : ℝ) t)).prod mu) := by + refine Integrable.of_bound hH.aestronglyMeasurable (C * D) ?_ + change ∀ᵐ p : ℝ × ContinuousPath alpha + ∂((volume.restrict (Ioc (0 : ℝ) t)).prod mu), ‖H p‖ ≤ C * D + rw [Measure.ae_prod_iff_ae_ae (measurableSet_le hH.norm.measurable measurable_const)] + filter_upwards [ae_restrict_mem measurableSet_Ioc] with s hs + exact Eventually.of_forall fun omega ↦ hHbound s ⟨hs.1.le, hs.2⟩ omega + have hInner (s : ℝ) (hs : s ∈ Icc (0 : ℝ) (t : ℝ)) : + ∫ omega, H (s, omega) ∂mu = + ∫ y, q y * IsConservative.feynmanKac P hP q + (t - Real.toNNReal s) f y ∂(P (Real.toNNReal s) x) := by + let u : NNReal := Real.toNNReal s + let r : NNReal := t - u + let W : ContinuousPath alpha → ℝ := fun omega ↦ q (omega u) + let F : ContinuousPath alpha → ℝ := fun eta ↦ + Real.exp (-feynmanKacAdditiveFunctional q r eta) * f (eta r) + have hu : u ≤ t := Real.toNNReal_le_iff_le_coe.mpr hs.2 + have hW : StronglyMeasurable[ContinuousPath.canonicalFiltration (alpha := alpha) u] W := + (hq.comp (ContinuousPath.measurable_coordinateProcess_canonicalFiltration + (alpha := alpha) u)).stronglyMeasurable + have hF : StronglyMeasurable F := by + exact (((stronglyMeasurable_feynmanKacAdditiveFunctional hq r).measurable.neg.exp).mul + (hf.comp (ContinuousPath.measurable_coordinateProcess + (alpha := alpha) r))).stronglyMeasurable + have hFbound : ∀ eta : ContinuousPath alpha, ‖F eta‖ ≤ D := by + intro eta + dsimp only [F] + rw [Real.norm_eq_abs, abs_mul, abs_of_pos (Real.exp_pos _)] + exact (mul_le_mul_of_nonneg_right + ((Real.exp_le_one_iff).mpr + (neg_nonpos.mpr (feynmanKacAdditiveFunctional_nonneg hq0 r eta))) (abs_nonneg _)).trans + (by simpa only [one_mul] using hfD _) + have hIntFshift : Integrable (fun omega ↦ F (ContinuousPath.shift u omega)) mu := + Integrable.of_bound + (((hF.comp_measurable (ContinuousPath.measurable_shift_fixed (alpha := alpha) u)) + ).aestronglyMeasurable) D (Eventually.of_forall fun omega ↦ hFbound _) + have hIntWF : Integrable (fun omega ↦ W omega * F (ContinuousPath.shift u omega)) mu := by + refine Integrable.of_bound + ((((hW.mono ((ContinuousPath.canonicalFiltration (alpha := alpha)).le u)).mul + (hF.comp_measurable (ContinuousPath.measurable_shift_fixed (alpha := alpha) u))) + ).aestronglyMeasurable) (C * D) ?_ + exact Eventually.of_forall fun omega ↦ by + rw [norm_mul, Real.norm_eq_abs, abs_of_nonneg (hq0 _)] + exact mul_le_mul (hqC _) (hFbound _) (norm_nonneg _) hC + have hcond := hFeller.continuousProcess_condExp_shift P hP hK x u F hF D hFbound + have hpull := condExp_mul_of_stronglyMeasurable_left (μ := mu) hW hIntWF hIntFshift + have hfactor : (fun omega ↦ H (s, omega)) = + fun omega ↦ W omega * F (ContinuousPath.shift u omega) := by + funext omega + dsimp only [H, W, F, u, r] + rw [ContinuousPath.shift_apply, add_tsub_cancel_of_le hu, + feynmanKacAdditiveFunctional_sub hq hq0 hqC hu] + ring + rw [hfactor] + calc + (∫ omega, W omega * F (ContinuousPath.shift u omega) ∂mu) = + ∫ omega, mu[fun eta ↦ W eta * F (ContinuousPath.shift u eta)| + ContinuousPath.canonicalFiltration (alpha := alpha) u] omega ∂mu := by + rw [integral_condExp ((ContinuousPath.canonicalFiltration (alpha := alpha)).le u)] + _ = ∫ omega, W omega * + (∫ eta, F eta ∂IsConservative.continuousProcess P hP (omega u)) ∂mu := by + refine integral_congr_ae (hpull.trans ?_) + exact EventuallyEq.mul (EventuallyEq.refl _ _) hcond + _ = ∫ omega, q (omega u) * IsConservative.feynmanKac P hP q r f (omega u) ∂mu := by + rfl + _ = ∫ y, q y * IsConservative.feynmanKac P hP q r f y ∂(P u x) := by + simpa only [mu] using! + (hFeller.integral_eval_continuousProcess_of_measurable P hP hK u x + (hq.mul (IsConservative.measurable_feynmanKac P hP hq r hf))) + _ = ∫ y, q y * IsConservative.feynmanKac P hP q + (t - Real.toNNReal s) f y ∂(P (Real.toNNReal s) x) := by rfl + have hPath : (∫ omega, f (omega t) ∂mu) - + IsConservative.feynmanKac P hP q t f x = + ∫ omega, (∫ s in (0 : ℝ)..t, H (s, omega)) ∂mu := by + have hPlain : Integrable (fun omega : ContinuousPath alpha ↦ f (omega t)) mu := + Integrable.of_bound + (((hf.comp (ContinuousPath.measurable_coordinateProcess + (alpha := alpha) t)).stronglyMeasurable + ).aestronglyMeasurable) D (Eventually.of_forall fun omega ↦ by + rw [Real.norm_eq_abs] + exact hfD _) + have hWeighted : Integrable (fun omega : ContinuousPath alpha ↦ + Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t)) mu := + have hmeasWeighted : StronglyMeasurable fun omega : ContinuousPath alpha ↦ + Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t) := by + have hmeas : Measurable fun omega : ContinuousPath alpha ↦ + Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t) := + ((stronglyMeasurable_feynmanKacAdditiveFunctional hq t).measurable.neg.exp).mul + (hf.comp (ContinuousPath.measurable_coordinateProcess (alpha := alpha) t)) + exact hmeas.stronglyMeasurable + Integrable.of_bound hmeasWeighted.aestronglyMeasurable D (Eventually.of_forall fun omega ↦ by + rw [Real.norm_eq_abs, abs_mul, abs_of_pos (Real.exp_pos _)] + exact (mul_le_mul_of_nonneg_right + ((Real.exp_le_one_iff).mpr + (neg_nonpos.mpr (feynmanKacAdditiveFunctional_nonneg hq0 t omega))) + (abs_nonneg _)).trans + (by simpa only [one_mul] using hfD _)) + change (∫ omega, f (omega t) ∂mu) - + (∫ omega, Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t) ∂mu) = _ + rw [← integral_sub hPlain hWeighted] + refine integral_congr_ae (Eventually.of_forall fun omega ↦ ?_) + change f (omega t) - Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t) = + ∫ s in (0 : ℝ)..t, H (s, omega) + have halg : f (omega t) - Real.exp (-feynmanKacAdditiveFunctional q t omega) * f (omega t) = + (1 - Real.exp (-feynmanKacAdditiveFunctional q t omega)) * f (omega t) := by ring + rw [halg, one_sub_exp_neg_feynmanKacAdditiveFunctional hq hq0 hqC, + ← intervalIntegral.integral_mul_const] + have hEval := hFeller.integral_eval_continuousProcess_of_measurable P hP hK t x hf + calc + (∫ y, f y ∂(P t x)) - IsConservative.feynmanKac P hP q t f x = + (∫ omega, f (omega t) ∂mu) - IsConservative.feynmanKac P hP q t f x := by + rw [hEval] + _ = ∫ omega, (∫ s in (0 : ℝ)..t, H (s, omega)) ∂mu := hPath + _ = + ∫ s in (0 : ℝ)..t, ∫ omega, H (s, omega) ∂mu := by + calc + (∫ omega, (∫ s in (0 : ℝ)..t, H (s, omega)) ∂mu) = + ∫ omega, (∫ s in Ioc (0 : ℝ) t, H (s, omega)) ∂mu := by + refine integral_congr_ae (Eventually.of_forall fun omega ↦ ?_) + exact intervalIntegral.integral_of_le t.coe_nonneg + _ = ∫ s in Ioc (0 : ℝ) t, ∫ omega, H (s, omega) ∂mu := + (integral_integral_swap hProdInt).symm + _ = ∫ s in (0 : ℝ)..t, ∫ omega, H (s, omega) ∂mu := + (intervalIntegral.integral_of_le t.coe_nonneg).symm + _ = ∫ s in (0 : ℝ)..t, ∫ y, q y * + IsConservative.feynmanKac P hP q (t - Real.toNNReal s) f y + ∂(P (Real.toNNReal s) x) := by + refine intervalIntegral.integral_congr fun s hs ↦ ?_ + rw [uIcc_of_le t.coe_nonneg] at hs + exact hInner s hs + +/-- Finite-time perturbation formula for a bounded nonnegative observable. -/ +theorem IsFellerKernelSemigroup.integral_sub_feynmanKac_eq_integral + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + {q : alpha → ℝ} (hq : Measurable q) {C : ℝ} + (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + {f : alpha → ℝ} (hf : Measurable f) (hf0 : ∀ y, 0 ≤ f y) + {D : ℝ} (hfD : ∀ y, f y ≤ D) (t : NNReal) (x : alpha) : + (∫ y, f y ∂(P t x)) - IsConservative.feynmanKac P hP q t f x = + ∫ s in (0 : ℝ)..t, ∫ y, q y * + IsConservative.feynmanKac P hP q (t - Real.toNNReal s) f y + ∂(P (Real.toNNReal s) x) := by + apply hFeller.integral_sub_feynmanKac_eq_integral_of_norm_le P hP hK hq hq0 hqC hf + (fun y ↦ by rw [abs_of_nonneg (hf0 y)]; exact hfD y) + +/-- Extended-real finite-time perturbation formula for bounded nonnegative observables. -/ +theorem IsFellerKernelSemigroup.lintegral_eq_feynmanKacENNReal_add_lintegral + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + {q : alpha → ℝ} (hq : Measurable q) {C : ℝ} + (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + {f : alpha → ℝ≥0∞} (hf : Measurable f) {D : NNReal} + (hfD : ∀ y, f y ≤ (D : ℝ≥0∞)) (t : NNReal) (x : alpha) : + (∫⁻ y, f y ∂(P t x)) = + IsConservative.feynmanKacENNReal P hP q t f x + + ∫⁻ s in Ioc (0 : ℝ) t, ∫⁻ y, ENNReal.ofReal (q y) * + IsConservative.feynmanKacENNReal P hP q (t - Real.toNNReal s) f y + ∂(P (Real.toNNReal s) x) := by + have hC : 0 ≤ C := (hq0 x).trans (hqC x) + let g : alpha → ℝ := fun y ↦ (f y).toReal + let kR : ℝ → ℝ := fun s ↦ ∫ y, q y * + IsConservative.feynmanKac P hP q (t - Real.toNNReal s) g y + ∂(P (Real.toNNReal s) x) + let kE : ℝ → ℝ≥0∞ := fun s ↦ ∫⁻ y, ENNReal.ofReal (q y) * + IsConservative.feynmanKacENNReal P hP q (t - Real.toNNReal s) f y + ∂(P (Real.toNNReal s) x) + have hftop (y : alpha) : f y ≠ ∞ := + ne_of_lt ((hfD y).trans_lt ENNReal.coe_lt_top) + have hg : Measurable g := hf.ennreal_toReal + have hg0 (y : alpha) : 0 ≤ g y := ENNReal.toReal_nonneg + have hgD (y : alpha) : g y ≤ D := by + exact (ENNReal.toReal_le_toReal (hftop y) ENNReal.coe_ne_top).mpr (hfD y) + have hgf : (fun y ↦ ENNReal.ofReal (g y)) = f := by + funext y + exact ENNReal.ofReal_toReal (hftop y) + have hreal := hFeller.integral_sub_feynmanKac_eq_integral P hP hK hq hq0 hqC + hg hg0 hgD t x + have hrealAdd : (∫ y, g y ∂(P t x)) = + IsConservative.feynmanKac P hP q t g x + ∫ s in (0 : ℝ)..t, kR s := by + exact (sub_eq_iff_eq_add').mp hreal + have hkR0 (s : ℝ) : 0 ≤ kR s := by + dsimp only [kR] + exact integral_nonneg fun y ↦ mul_nonneg (hq0 y) + (IsConservative.feynmanKac_nonneg P hP hg0 y) + have hkpoint (s : ℝ) : ENNReal.ofReal (kR s) = kE s := by + let u : NNReal := Real.toNNReal s + let r : NNReal := t - u + let hMarkovU : IsMarkovKernel (P u) := hP.isMarkovKernel u + have hterm : Integrable (fun y ↦ q y * IsConservative.feynmanKac P hP q r g y) + (P u x) := by + refine Integrable.of_bound + ((hq.mul (IsConservative.measurable_feynmanKac P hP hq r hg)).stronglyMeasurable + ).aestronglyMeasurable (C * D) ?_ + exact Eventually.of_forall fun y ↦ by + rw [Real.norm_eq_abs, abs_of_nonneg + (mul_nonneg (hq0 y) (IsConservative.feynmanKac_nonneg P hP hg0 y))] + exact mul_le_mul (hqC y) + (IsConservative.feynmanKac_le P hP hq0 hg0 hgD y) + (IsConservative.feynmanKac_nonneg P hP hg0 y) hC + change ENNReal.ofReal + (∫ y, q y * IsConservative.feynmanKac P hP q r g y ∂(P u x)) = + ∫⁻ y, ENNReal.ofReal (q y) * + IsConservative.feynmanKacENNReal P hP q r f y ∂(P u x) + rw [ofReal_integral_eq_lintegral_ofReal hterm + (Eventually.of_forall fun y ↦ mul_nonneg (hq0 y) + (IsConservative.feynmanKac_nonneg P hP hg0 y))] + apply lintegral_congr + intro y + rw [ENNReal.ofReal_mul (hq0 y), + IsConservative.ofReal_feynmanKac_eq_feynmanKacENNReal P hP hq hq0 r hg hg0 hgD y, + hgf] + have hkEmeas : Measurable kE := by + let hFiniteJoint : IsFiniteKernel P.jointKernel := ⟨⟨1, ENNReal.one_lt_top, fun p ↦ by + rw [jointKernel_apply] + exact P.measure_univ_le_one p.1 p.2⟩⟩ + let K : Kernel ℝ alpha := Kernel.comap P.jointKernel + (fun s ↦ (Real.toNNReal s, x)) (measurable_real_toNNReal.prodMk measurable_const) + have hint : Measurable fun p : ℝ × alpha ↦ ENNReal.ofReal (q p.2) * + IsConservative.feynmanKacENNReal P hP q + (t - Real.toNNReal p.1) f p.2 := by + exact (hq.ennreal_ofReal.comp measurable_snd).mul + ((IsConservative.measurable_feynmanKacENNReal_joint P hP hq hf).comp + ((measurable_const.sub (measurable_real_toNNReal.comp measurable_fst)).prodMk + measurable_snd)) + have hlin := hint.lintegral_kernel_prod_right' (κ := K) + simpa only [kE, K, Kernel.comap_apply, jointKernel_apply] using hlin + have hkR_eq_toReal : kR = fun s ↦ (kE s).toReal := by + funext s + rw [← hkpoint s, ENNReal.toReal_ofReal (hkR0 s)] + have hkRmeas : Measurable kR := by + rw [hkR_eq_toReal] + exact hkEmeas.ennreal_toReal + have hkRle (s : ℝ) : kR s ≤ C * D := by + let u : NNReal := Real.toNNReal s + let r : NNReal := t - u + let hMarkovU : IsMarkovKernel (P u) := hP.isMarkovKernel u + dsimp only [kR] + calc + (∫ y, q y * IsConservative.feynmanKac P hP q r g y ∂(P u x)) ≤ + ∫ _y, C * D ∂(P u x) := by + apply integral_mono_of_nonneg + · exact Eventually.of_forall fun y ↦ mul_nonneg (hq0 y) + (IsConservative.feynmanKac_nonneg P hP hg0 y) + · exact integrable_const (C * D) + · exact Eventually.of_forall fun y ↦ mul_le_mul (hqC y) + (IsConservative.feynmanKac_le P hP hq0 hg0 hgD y) + (IsConservative.feynmanKac_nonneg P hP hg0 y) hC + _ = C * D := by simp only [integral_const, probReal_univ, one_smul] + have hkRInt : IntervalIntegrable kR volume (0 : ℝ) t := by + rw [intervalIntegrable_iff_integrableOn_Ioc_of_le t.coe_nonneg] + refine IntegrableOn.of_bound (by simpa only [uIoc] using + (measure_Ioc_lt_top : volume (Ioc (0 : ℝ) t) < ∞)) + hkRmeas.stronglyMeasurable.aestronglyMeasurable.restrict (C * D) ?_ + filter_upwards [ae_restrict_mem measurableSet_Ioc] with s _hs + rw [Real.norm_eq_abs, abs_of_nonneg (hkR0 s)] + exact hkRle s + have hplainInt : Integrable g (P t x) := by + let hMarkovT : IsMarkovKernel (P t) := hP.isMarkovKernel t + refine Integrable.of_bound hg.stronglyMeasurable.aestronglyMeasurable D ?_ + exact Eventually.of_forall fun y ↦ by + rw [Real.norm_eq_abs, abs_of_nonneg (hg0 y)] + exact hgD y + have hplain : ENNReal.ofReal (∫ y, g y ∂(P t x)) = ∫⁻ y, f y ∂(P t x) := by + rw [ofReal_integral_eq_lintegral_ofReal hplainInt (Eventually.of_forall hg0), hgf] + have hfk : ENNReal.ofReal (IsConservative.feynmanKac P hP q t g x) = + IsConservative.feynmanKacENNReal P hP q t f x := by + rw [IsConservative.ofReal_feynmanKac_eq_feynmanKacENNReal P hP hq hq0 t hg hg0 hgD x, + hgf] + have hcorr : ENNReal.ofReal (∫ s in (0 : ℝ)..t, kR s) = + ∫⁻ s in Ioc (0 : ℝ) t, kE s := by + rw [intervalIntegral.integral_of_le t.coe_nonneg, + ofReal_integral_eq_lintegral_ofReal + ((intervalIntegrable_iff_integrableOn_Ioc_of_le t.coe_nonneg).mp hkRInt) + (Eventually.of_forall hkR0)] + exact lintegral_congr hkpoint + have hof := congrArg ENNReal.ofReal hrealAdd + rw [ENNReal.ofReal_add + (IsConservative.feynmanKac_nonneg P hP hg0 x) (intervalIntegral.integral_nonneg + t.coe_nonneg fun s _hs ↦ hkR0 s), hplain, hfk, hcorr] at hof + exact hof + +/-- Resolvent perturbation formula in its subtraction-free extended-real form. -/ +theorem IsFellerKernelSemigroup.kernelResolvent_eq_feynmanKacResolvent_add + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + {q : alpha → ℝ} (hq : Measurable q) {C : ℝ} + (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + {f : alpha → ℝ≥0∞} (hf : Measurable f) {D : NNReal} + (hfD : ∀ y, f y ≤ (D : ℝ≥0∞)) (lam : ℝ) (x : alpha) : + P.kernelResolvent lam f x = + IsConservative.feynmanKacResolvent P hP q lam f x + + P.kernelResolvent lam (fun y ↦ ENNReal.ofReal (q y) * + IsConservative.feynmanKacResolvent P hP q lam f y) x := by + have hC : 0 ≤ C := (hq0 x).trans (hqC x) + let W : ℝ → ℝ≥0∞ := fun t ↦ ENNReal.ofReal (Real.exp (-lam * t)) + let B : ℝ × ℝ → ℝ≥0∞ := fun p ↦ ∫⁻ y, ENNReal.ofReal (q y) * + IsConservative.feynmanKacENNReal P hP q (Real.toNNReal p.2) f y + ∂(P (Real.toNNReal p.1) x) + let H : ℝ × ℝ → ℝ≥0∞ := fun p ↦ W (p.1 + p.2) * B p + let hFiniteJoint : IsFiniteKernel P.jointKernel := ⟨⟨1, ENNReal.one_lt_top, fun p ↦ by + rw [jointKernel_apply] + exact P.measure_univ_le_one p.1 p.2⟩⟩ + let K : Kernel (ℝ × ℝ) alpha := Kernel.comap P.jointKernel + (fun p ↦ (Real.toNNReal p.1, x)) + ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_const) + have hB : Measurable B := by + have hint : Measurable fun p : (ℝ × ℝ) × alpha ↦ ENNReal.ofReal (q p.2) * + IsConservative.feynmanKacENNReal P hP q (Real.toNNReal p.1.2) f p.2 := by + exact (hq.ennreal_ofReal.comp measurable_snd).mul + ((IsConservative.measurable_feynmanKacENNReal_joint P hP hq hf).comp + ((measurable_real_toNNReal.comp (measurable_snd.comp measurable_fst)).prodMk + measurable_snd)) + have hlin := hint.lintegral_kernel_prod_right' (κ := K) + simpa only [B, K, Kernel.comap_apply, jointKernel_apply] using hlin + have hW : Measurable W := by + exact ENNReal.measurable_ofReal.comp + (Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable + have hH : Measurable H := (hW.comp measurable_add).mul hB + have hsets (t : ℝ) : Ioc (0 : ℝ) t =ᶠ[ae volume] Ioo (0 : ℝ) t := by + filter_upwards [volume.ae_ne t] with s hst + apply propext + constructor + · intro hs + exact ⟨hs.1, hs.2.lt_of_ne hst⟩ + · exact fun hs ↦ ⟨hs.1, hs.2.le⟩ + have htriangle : + (∫⁻ t in Ioi (0 : ℝ), W t * + ∫⁻ s in Ioc (0 : ℝ) t, ∫⁻ y, ENNReal.ofReal (q y) * + IsConservative.feynmanKacENNReal P hP q + (Real.toNNReal t - Real.toNNReal s) f y + ∂(P (Real.toNNReal s) x)) = + ∫⁻ s in Ioi (0 : ℝ), ∫⁻ u in Ioi (0 : ℝ), H (s, u) := by + calc + (∫⁻ t in Ioi (0 : ℝ), W t * + ∫⁻ s in Ioc (0 : ℝ) t, ∫⁻ y, ENNReal.ofReal (q y) * + IsConservative.feynmanKacENNReal P hP q + (Real.toNNReal t - Real.toNNReal s) f y + ∂(P (Real.toNNReal s) x)) = + ∫⁻ t in Ioi (0 : ℝ), ∫⁻ s in Ioo (0 : ℝ) t, H (s, t - s) := by + apply setLIntegral_congr_fun measurableSet_Ioi + intro t ht + change W t * + (∫⁻ s in Ioc (0 : ℝ) t, ∫⁻ y, ENNReal.ofReal (q y) * + IsConservative.feynmanKacENNReal P hP q + (Real.toNNReal t - Real.toNNReal s) f y + ∂(P (Real.toNNReal s) x)) = ∫⁻ s in Ioo (0 : ℝ) t, H (s, t - s) + rw [← lintegral_const_mul' (μ := volume.restrict (Ioc (0 : ℝ) t)) + (W t) _ (by dsimp only [W]; finiteness), Measure.restrict_congr_set (hsets t)] + apply lintegral_congr_ae + filter_upwards [ae_restrict_mem measurableSet_Ioo] with s hs + have htime : Real.toNNReal t - Real.toNNReal s = Real.toNNReal (t - s) := by + apply NNReal.coe_injective + rw [NNReal.coe_sub (Real.toNNReal_le_toNNReal hs.2.le), + Real.coe_toNNReal t ht.le, Real.coe_toNNReal s hs.1.le, + Real.coe_toNNReal (t - s) (sub_nonneg.mpr hs.2.le)] + dsimp only [H, B] + rw [← htime] + congr 2 + ring + _ = _ := intervalIntegral.lintegral_timeTriangle_sub hH + have hWadd (s u : ℝ) : W (s + u) = W s * W u := by + dsimp only [W] + rw [← ENNReal.ofReal_mul (Real.exp_pos _).le, ← Real.exp_add] + congr 2 + ring + have hquadrant : (∫⁻ s in Ioi (0 : ℝ), ∫⁻ u in Ioi (0 : ℝ), H (s, u)) = + P.kernelResolvent lam (fun y ↦ ENNReal.ofReal (q y) * + IsConservative.feynmanKacResolvent P hP q lam f y) x := by + unfold SubMarkovKernelSemigroup.kernelResolvent + apply setLIntegral_congr_fun measurableSet_Ioi + intro s _hs + let hMarkovS : IsMarkovKernel (P (Real.toNNReal s)) := + hP.isMarkovKernel (Real.toNNReal s) + have hG : Measurable fun p : ℝ × alpha ↦ W p.1 * + (ENNReal.ofReal (q p.2) * + IsConservative.feynmanKacENNReal P hP q (Real.toNNReal p.1) f p.2) := by + exact (hW.comp measurable_fst).mul + ((hq.ennreal_ofReal.comp measurable_snd).mul + ((IsConservative.measurable_feynmanKacENNReal_joint P hP hq hf).comp + ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_snd))) + calc + (∫⁻ u in Ioi (0 : ℝ), H (s, u)) = + W s * ∫⁻ u in Ioi (0 : ℝ), ∫⁻ y, W u * + (ENNReal.ofReal (q y) * + IsConservative.feynmanKacENNReal P hP q (Real.toNNReal u) f y) + ∂(P (Real.toNNReal s) x) := by + rw [← lintegral_const_mul' (μ := volume.restrict (Ioi (0 : ℝ))) + (W s) _ (by dsimp only [W]; finiteness)] + apply lintegral_congr + intro u + dsimp only [H, B] + rw [hWadd] + rw [lintegral_const_mul' (W u) _ (by dsimp only [W]; finiteness)] + simp only [mul_assoc] + _ = W s * ∫⁻ y, (∫⁻ u in Ioi (0 : ℝ), W u * + (ENNReal.ofReal (q y) * + IsConservative.feynmanKacENNReal P hP q (Real.toNNReal u) f y)) + ∂(P (Real.toNNReal s) x) := by + congr 1 + exact lintegral_lintegral_swap (μ := volume.restrict (Ioi (0 : ℝ))) + (ν := P (Real.toNNReal s) x) hG.aemeasurable + _ = W s * ∫⁻ y, ENNReal.ofReal (q y) * + IsConservative.feynmanKacResolvent P hP q lam f y + ∂(P (Real.toNNReal s) x) := by + congr 1 + apply lintegral_congr + intro y + unfold IsConservative.feynmanKacResolvent + rw [← lintegral_const_mul' (μ := volume.restrict (Ioi (0 : ℝ))) + (ENNReal.ofReal (q y)) _ (by finiteness)] + apply lintegral_congr + intro u + ring + unfold SubMarkovKernelSemigroup.kernelResolvent IsConservative.feynmanKacResolvent + have hFKmeas : Measurable fun t : ℝ ↦ W t * + IsConservative.feynmanKacENNReal P hP q (Real.toNNReal t) f x := + hW.mul ((IsConservative.measurable_feynmanKacENNReal_joint P hP hq hf).comp + (measurable_real_toNNReal.prodMk measurable_const)) + calc + (∫⁻ t in Ioi (0 : ℝ), W t * ∫⁻ y, f y ∂(P (Real.toNNReal t) x)) = + ∫⁻ t in Ioi (0 : ℝ), W t * + (IsConservative.feynmanKacENNReal P hP q (Real.toNNReal t) f x + + ∫⁻ s in Ioc (0 : ℝ) (Real.toNNReal t), ∫⁻ y, ENNReal.ofReal (q y) * + IsConservative.feynmanKacENNReal P hP q + (Real.toNNReal t - Real.toNNReal s) f y + ∂(P (Real.toNNReal s) x)) := by + apply setLIntegral_congr_fun measurableSet_Ioi + intro t ht + have hslice := hFeller.lintegral_eq_feynmanKacENNReal_add_lintegral P hP hK hq + hq0 hqC hf hfD (Real.toNNReal t) x + exact congrArg (fun z ↦ W t * z) (by + simpa only [Real.coe_toNNReal t ht.le] using hslice) + _ = (∫⁻ t in Ioi (0 : ℝ), W t * + IsConservative.feynmanKacENNReal P hP q (Real.toNNReal t) f x) + + ∫⁻ t in Ioi (0 : ℝ), W t * + ∫⁻ s in Ioc (0 : ℝ) t, ∫⁻ y, ENNReal.ofReal (q y) * + IsConservative.feynmanKacENNReal P hP q + (Real.toNNReal t - Real.toNNReal s) f y + ∂(P (Real.toNNReal s) x) := by + rw [← lintegral_add_left (μ := volume.restrict (Ioi (0 : ℝ))) hFKmeas] + apply lintegral_congr_ae + filter_upwards [ae_restrict_mem measurableSet_Ioi] with t ht + rw [mul_add, Real.coe_toNNReal t ht.le] + _ = _ := by + rw [htriangle, hquadrant] + simp only [W, SubMarkovKernelSemigroup.kernelResolvent, + IsConservative.feynmanKacResolvent] + +omit [MetricSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [CompleteSpace alpha] [Nonempty alpha] [LocallyCompactSpace alpha] in +/-- The kernel resolvent of a bounded observable is finite at a positive shift. -/ +theorem IsConservative.kernelResolvent_lt_top (hP : P.IsConservative) (lam : ℝ) (hlam : 0 < lam) + {f : alpha → ℝ≥0∞} {D : NNReal} (hfD : ∀ y, f y ≤ (D : ℝ≥0∞)) (x : alpha) : + P.kernelResolvent lam f x < ∞ := by + have hinner (t : ℝ) : (∫⁻ y, f y ∂(P (Real.toNNReal t) x)) ≤ (D : ℝ≥0∞) := by + let hMarkovT : IsMarkovKernel (P (Real.toNNReal t)) := + hP.isMarkovKernel (Real.toNNReal t) + calc + (∫⁻ y, f y ∂(P (Real.toNNReal t) x)) ≤ ∫⁻ _y, (D : ℝ≥0∞) + ∂(P (Real.toNNReal t) x) := lintegral_mono hfD + _ = D := by simp only [lintegral_const, measure_univ, mul_one] + have hweightInt : IntegrableOn (fun t : ℝ ↦ Real.exp (-lam * t) * (D : ℝ)) + (Ioi (0 : ℝ)) := by + exact (integrableOn_exp_mul_Ioi (show -lam < 0 by linarith only [hlam]) 0).mul_const D + unfold SubMarkovKernelSemigroup.kernelResolvent + calc + (∫⁻ t in Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + ∫⁻ y, f y ∂(P (Real.toNNReal t) x)) ≤ + ∫⁻ t in Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t) * (D : ℝ)) := by + apply setLIntegral_mono' + · exact measurableSet_Ioi + · intro t _ht + rw [ENNReal.ofReal_mul (Real.exp_pos _).le, + show ENNReal.ofReal (D : ℝ) = (D : ℝ≥0∞) by simp only [ENNReal.ofReal_coe_nnreal]] + exact mul_le_mul_of_nonneg_left (hinner t) bot_le + _ = ENNReal.ofReal (∫ t in Ioi (0 : ℝ), Real.exp (-lam * t) * (D : ℝ)) := by + exact (ofReal_integral_eq_lintegral_ofReal hweightInt + (Eventually.of_forall fun t ↦ mul_nonneg (Real.exp_pos _).le D.coe_nonneg)).symm + _ < ∞ := ENNReal.ofReal_lt_top + +/-- The Feynman--Kac resolvent is the kernel resolvent minus its potential correction. -/ +theorem IsFellerKernelSemigroup.feynmanKacResolvent_eq_kernelResolvent_sub + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + {q : alpha → ℝ} (hq : Measurable q) {C : ℝ} + (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + {f : alpha → ℝ≥0∞} (hf : Measurable f) {D : NNReal} + (hfD : ∀ y, f y ≤ (D : ℝ≥0∞)) (lam : ℝ) (hlam : 0 < lam) (x : alpha) : + IsConservative.feynmanKacResolvent P hP q lam f x = + P.kernelResolvent lam f x - + P.kernelResolvent lam (fun y ↦ ENNReal.ofReal (q y) * + IsConservative.feynmanKacResolvent P hP q lam f y) x := by + have hadd := hFeller.kernelResolvent_eq_feynmanKacResolvent_add P hP hK hq hq0 hqC + hf hfD lam x + exact ENNReal.eq_sub_of_add_eq' + (IsConservative.kernelResolvent_lt_top P hP lam hlam hfD x).ne hadd.symm + + + +end + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FiniteMarginals.lean new file mode 100644 index 0000000000..b27218071c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FiniteMarginals.lean @@ -0,0 +1,194 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic + +/-! +# Finite rational-time marginals of continuous-path trajectories + +This file transports the finite-dimensional laws of the canonical dense-time trajectory to +arbitrary finite sets of nonnegative rational times. The target coordinates are indexed by the +corresponding finite set of physical `NNReal` times, exactly as in `finiteSetKernel`. + +No assertion is made at irrational times or about a Markov, strong Markov, or Hunt property of +the continuous-path law. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup + +noncomputable section + +/-- The finite set of physical nonnegative-real times represented by rational times in `I`. -/ +def denseTimePhysicalSet (I : Finset DenseTime) : Finset NNReal := + I.map DenseTime.castOrderEmbedding.toEmbedding + +private theorem exists_denseTimePhysicalSet_subset_prefix + (e : ℕ ≃ DenseTime) (I : Finset DenseTime) : + ∃ n, denseTimePhysicalSet I ⊆ + denseTimePhysicalPrefix e DenseTime.castOrderEmbedding.toEmbedding n := by + classical + induction I using Finset.induction_on with + | empty => + refine ⟨0, ?_⟩ + intro t ht + simp only [denseTimePhysicalSet, Finset.map_empty, Finset.notMem_empty] at ht + | @insert a I ha ih => + obtain ⟨n, hn⟩ := ih + refine ⟨max n (e.symm a + 1), ?_⟩ + intro t ht + rw [denseTimePhysicalSet, Finset.mem_map] at ht + obtain ⟨d, hd, rfl⟩ := ht + rw [denseTimePhysicalPrefix, Finset.mem_map] + refine ⟨d, ?_, rfl⟩ + rw [CountableEnumeration.mem_prefix_iff] + rw [Finset.mem_insert] at hd + rcases hd with rfl | hd + · exact Nat.lt_of_lt_of_le (Nat.lt_succ_self _) (le_max_right _ _) + · have hmem : DenseTime.castOrderEmbedding d ∈ denseTimePhysicalSet I := by + rw [denseTimePhysicalSet, Finset.mem_map] + exact ⟨d, hd, rfl⟩ + have hprefix := hn hmem + rw [denseTimePhysicalPrefix, Finset.mem_map] at hprefix + obtain ⟨d', hd', heq⟩ := hprefix + have hdd' : d = d' := DenseTime.castOrderEmbedding.injective heq.symm + subst d' + rw [CountableEnumeration.mem_prefix_iff] at hd' + exact Nat.lt_of_lt_of_le hd' (le_max_left _ _) + +private noncomputable def finEquivDenseTimePhysicalPrefix + (e : ℕ ≃ DenseTime) (n : ℕ) : + Fin n ≃ denseTimePhysicalPrefix e DenseTime.castOrderEmbedding.toEmbedding n := + Equiv.ofBijective + (fun i ↦ + ⟨DenseTime.castOrderEmbedding (e i), by + rw [denseTimePhysicalPrefix, Finset.mem_map] + exact ⟨e i, by + rw [CountableEnumeration.mem_prefix_iff, e.symm_apply_apply] + exact i.isLt, rfl⟩⟩) + ⟨by + intro i j hij + apply Fin.ext + apply e.injective + apply DenseTime.castOrderEmbedding.injective + exact congrArg Subtype.val hij, + by + intro t + have ht := t.property + change t.val ∈ (CountableEnumeration.prefix e n).map + DenseTime.castOrderEmbedding.toEmbedding at ht + rw [Finset.mem_map] at ht + obtain ⟨d, hd, hdt⟩ := ht + let i : Fin n := ⟨e.symm d, by + rw [CountableEnumeration.mem_prefix_iff] at hd + exact hd⟩ + refine ⟨i, Subtype.ext ?_⟩ + change DenseTime.castOrderEmbedding (e i) = t + rw [show e i = d by exact e.apply_symm_apply d] + exact hdt⟩ + +variable {α : Type*} + +private def physicalPrefixPathOfFinPath + (e : ℕ ≃ DenseTime) (n : ℕ) (path : Fin n → α) : + denseTimePhysicalPrefix e DenseTime.castOrderEmbedding.toEmbedding n → α := + fun t ↦ path ((finEquivDenseTimePhysicalPrefix e n).symm t) + +private theorem measurable_physicalPrefixPathOfFinPath + [MeasurableSpace α] (e : ℕ ≃ DenseTime) (n : ℕ) : + Measurable (physicalPrefixPathOfFinPath (α := α) e n) := + measurable_pi_iff.mpr fun t ↦ + measurable_pi_apply ((finEquivDenseTimePhysicalPrefix e n).symm t) + +namespace IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [StandardBorelSpace alpha] [Nonempty alpha] + +private theorem continuousPathTrajectory_map_physicalPrefix + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (n : ℕ) : + (continuousPathTrajectory P hP default).map + (fun path (t : denseTimePhysicalPrefix DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding n) ↦ path t) = + finiteSetKernel P (denseTimePhysicalPrefix DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding n) := by + let equiv := finEquivDenseTimePhysicalPrefix DenseTime.enumeration n + have hleft : + physicalPrefixPathOfFinPath (α := alpha) DenseTime.enumeration n ∘ + (denseTimeTrajectoryPrefix DenseTime.enumeration n ∘ + ContinuousPath.denseRestriction) = + fun path (t : denseTimePhysicalPrefix DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding n) ↦ path t := by + funext path t + change path (DenseTime.castOrderEmbedding + (DenseTime.enumeration (equiv.symm t))) = path t + have heq := equiv.apply_symm_apply t + exact congrArg path (congrArg Subtype.val heq) + have hright : + physicalPrefixPathOfFinPath (α := alpha) DenseTime.enumeration n ∘ + denseTimePrefixReindex DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding n = id := by + funext path t + change path (equiv (equiv.symm t)) = path t + rw [equiv.apply_symm_apply] + rw [← hleft, Kernel.map_comp_right] + · rw [continuousPathTrajectory_map_prefix P hP default hK n, + denseTimePrefixKernel_eq_map, ← Kernel.map_comp_right] + · rw [hright, Kernel.map_id] + · exact measurable_denseTimePrefixReindex DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding n + · exact measurable_physicalPrefixPathOfFinPath DenseTime.enumeration n + · exact (measurable_denseTimeTrajectoryPrefix DenseTime.enumeration n).comp + ContinuousPath.measurable_denseRestriction + · exact measurable_physicalPrefixPathOfFinPath DenseTime.enumeration n + +/-- Every finite rational-time marginal of the continuous-path trajectory is the existing +finite-set kernel at the corresponding physical times. -/ +theorem continuousPathTrajectory_map_finiteDenseTimeSet + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (I : Finset DenseTime) : + (continuousPathTrajectory P hP default).map + (fun path (t : denseTimePhysicalSet I) ↦ path t) = + finiteSetKernel P (denseTimePhysicalSet I) := by + obtain ⟨n, hsubset⟩ := + exists_denseTimePhysicalSet_subset_prefix DenseTime.enumeration I + have hfun : + (fun path : ContinuousPath alpha ↦ + fun t : denseTimePhysicalSet I ↦ path t) = + Finset.restrict₂ (π := fun _ ↦ alpha) hsubset ∘ + (fun path : ContinuousPath alpha ↦ + fun t : denseTimePhysicalPrefix DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding n ↦ path t) := by + rfl + rw [hfun, Kernel.map_comp_right] + · rw [continuousPathTrajectory_map_physicalPrefix P hP default hK n] + exact (hP.finiteSetKernel_map_restrict₂ P hsubset).symm + · apply measurable_pi_iff.mpr + intro t + rw [BorelSpace.measurable_eq (α := alpha)] + exact (ContinuousPath.continuous_eval (alpha := alpha) (t : NNReal)).borel_measurable + · exact Finset.measurable_restrict₂ (X := fun _ ↦ alpha) hsubset + +end IsConservative +end +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/HarmonicRepresentation.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/HarmonicRepresentation.lean new file mode 100644 index 0000000000..34f9007707 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/HarmonicRepresentation.lean @@ -0,0 +1,187 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime + +/-! +# Harmonic and Poisson representations, and the localized Dynkin formula + +Consequences of Dynkin's formula at the exit time of an open set `U` truncated at a horizon `K` +(`Trajectory/DynkinStopping.lean`), for the continuous-path process `Q` of a conservative Feller +semigroup and `f` in the generator domain of its `C₀` semigroup, with generator `L f`: + +* `integral_eval_exitTimeTrunc_eq_of_generator_eq_zero` (**harmonic representation**): if + `L f = 0` on `U`, then `E_x f(ω_{τ ∧ K}) = f x`; +* `integral_eval_exitTimeTrunc_add_eq_of_generator_eq_neg` (**Poisson representation**): if + `L f = -g` on `U`, then `E_x f(ω_{τ ∧ K}) + E_x ∫_0^{τ ∧ K} g(ω_s) ds = f x`; +* `stopped_exitTimeTrunc_mem_closure`: from a starting point in `U`, the position at `τ ∧ K` lies + in the closure of `U`, so a continuous function that agrees with `f` on the closure of `U` + has the same stopped expectation; this gives the **localized Dynkin formula** + `integral_eval_exitTimeTrunc_sub_eq_of_eqOn_closure`, which is how test functions outside `C₀` + (agreeing with a domain element near the closure of a bounded set) enter moment identities. + +The integrand of Dynkin's formula is only ever evaluated strictly before the exit time, where the +path is inside `U`; this is the observation behind all three statements. +-/ + +open MeasureTheory ProbabilityTheory Filter +open scoped ENNReal NNReal ZeroAtInfty + +namespace MarkovProcess + +namespace ContinuousPath + +variable {alpha : Type*} [PseudoMetricSpace alpha] + +/-- Strictly before the truncated exit time the path is inside `U`. -/ +theorem mem_of_lt_exitTimeTrunc (U : Set alpha) (K : NNReal) (omega : ContinuousPath alpha) + {s : NNReal} (hs : s < exitTimeTrunc U K omega) : omega s ∈ U := by + apply mem_of_lt_exitTime U omega s + have h : ((s : NNReal) : ℝ≥0∞) < ((exitTimeTrunc U K omega : NNReal) : ℝ≥0∞) := + ENNReal.coe_lt_coe.mpr hs + rw [coe_exitTimeTrunc_ennreal] at h + exact lt_of_lt_of_le h (min_le_left _ _) + +/-- From a starting point in the open set `U`, the position at the truncated exit time lies in the +closure of `U`: inside `U` if the horizon comes first, on the frontier if the exit comes first. -/ +theorem stopped_exitTimeTrunc_mem_closure (U : Set alpha) (hU : IsOpen U) (K : NNReal) + (omega : ContinuousPath alpha) (h0 : omega 0 ∈ U) : + omega (exitTimeTrunc U K omega) ∈ closure U := by + rcases lt_or_ge (K : ℝ≥0∞) (exitTime U omega) with hK | hexit + · have hT : exitTimeTrunc U K omega = K := by + apply WithTop.coe_injective + rw [coe_exitTimeTrunc, exitTimeTop_apply] + exact min_eq_right hK.le + rw [hT] + exact subset_closure (mem_of_lt_exitTime U omega K hK) + · have hfin : exitTime U omega ≠ ⊤ := ne_top_of_le_ne_top ENNReal.coe_ne_top hexit + have hT : exitTimeTrunc U K omega = (exitTime U omega).toNNReal := by + apply ENNReal.coe_injective + rw [coe_exitTimeTrunc_ennreal, min_eq_left hexit, ENNReal.coe_toNNReal hfin] + rw [hT] + exact (hU.frontier_eq ▸ coordinate_exitTime_mem_frontier U hU omega h0 hfin).1 + +/-- The time integral of a function of the path up to the truncated exit time only sees the values +of the function on `U`: two functions agreeing on `U` give the same integral. -/ +theorem integral_exitTimeTrunc_congr (U : Set alpha) (K : NNReal) + {g₁ g₂ : alpha → ℝ} (hg : Set.EqOn g₁ g₂ U) (omega : ContinuousPath alpha) : + ∫ s in (0 : ℝ)..(exitTimeTrunc U K omega : ℝ), g₁ (omega (Real.toNNReal s)) = + ∫ s in (0 : ℝ)..(exitTimeTrunc U K omega : ℝ), + g₂ (omega (Real.toNNReal s)) := by + rw [intervalIntegral.integral_of_le NNReal.zero_le_coe, + intervalIntegral.integral_of_le NNReal.zero_le_coe, + ← Measure.restrict_congr_set Ioo_ae_eq_Ioc] + refine setIntegral_congr_fun measurableSet_Ioo fun s hs ↦ ?_ + refine hg (mem_of_lt_exitTimeTrunc U K omega ?_) + rw [← NNReal.coe_lt_coe, Real.coe_toNNReal s hs.1.le] + exact hs.2 + +end ContinuousPath + +namespace SubMarkovKernelSemigroup + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + [LocallyCompactSpace alpha] + +variable {P : SubMarkovKernelSemigroup alpha} (hP : P.IsConservative) + +omit [LocallyCompactSpace alpha] in +/-- Under the process started at `x`, the path starts at `x` almost surely. -/ +theorem IsConservative.ae_eval_zero_eq (hK : P.KolmogorovRegular hP) (x : alpha) : + ∀ᵐ omega ∂(IsConservative.continuousProcess P hP x), omega 0 = x := by + have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ omega 0) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) 0 + have hmap : (IsConservative.continuousProcess P hP x).map (fun omega ↦ omega 0) = + Measure.dirac x := by + rw [← Kernel.map_apply _ hmeas, IsConservative.continuousProcess_map_eval_zero P hP hK, + Kernel.id_apply] + rw [ae_iff] + have hset : {omega : ContinuousPath alpha | ¬ omega 0 = x} = + (fun omega : ContinuousPath alpha ↦ omega 0) ⁻¹' ({x}ᶜ : Set alpha) := by + ext omega + simp only [Set.mem_ofPred_eq, Set.mem_preimage, Set.mem_compl_iff, Set.mem_singleton_iff] + rw [hset, ← Measure.map_apply hmeas (measurableSet_singleton x).compl, hmap, + Measure.dirac_apply' _ (measurableSet_singleton x).compl, + Set.indicator_of_notMem (by simp only [Set.mem_compl_iff, Set.mem_singleton_iff, + not_true_eq_false, not_false_eq_true])] + +/-- **Harmonic representation.** If `L f = 0` on the open set `U`, the value of `f` at a starting +point is the expectation of `f` at the exit time truncated at any horizon. -/ +theorem IsFellerKernelSemigroup.integral_eval_exitTimeTrunc_eq_of_generator_eq_zero + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (U : Set alpha) (hU : IsOpen U) + (hLf : ∀ y ∈ U, (hFeller.c0Semigroup.generator f) y = 0) (K : NNReal) (x : alpha) : + ∫ omega, (f : C₀(alpha, ℝ)) (omega (ContinuousPath.exitTimeTrunc U K omega)) + ∂(IsConservative.continuousProcess P hP x) = (f : C₀(alpha, ℝ)) x := by + have hdynkin := hFeller.integral_eval_stoppingTime_sub_eq_integral_integral_generator hP hK f + (ContinuousPath.exitTimeTrunc U K) (ContinuousPath.isStoppingTime_exitTimeTrunc U hU K) + (ContinuousPath.exitTimeTrunc_le U K) x + have hzero : ∀ omega : ContinuousPath alpha, + ∫ s in (0 : ℝ)..(ContinuousPath.exitTimeTrunc U K omega : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) = 0 := by + intro omega + rw [ContinuousPath.integral_exitTimeTrunc_congr U K (g₂ := fun _ ↦ 0) (fun y hy ↦ hLf y hy) omega, + intervalIntegral.integral_zero] + simp only [hzero, integral_zero] at hdynkin + exact sub_eq_zero.mp hdynkin + +/-- **Poisson representation.** If `L f = -g` on the open set `U`, then +`f x = E_x f(ω_{τ ∧ K}) + E_x ∫_0^{τ ∧ K} g(ω_s) ds` for every horizon `K`. -/ +theorem IsFellerKernelSemigroup.integral_eval_exitTimeTrunc_add_eq_of_generator_eq_neg + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (U : Set alpha) (hU : IsOpen U) + {g : alpha → ℝ} (hLf : ∀ y ∈ U, (hFeller.c0Semigroup.generator f) y = -g y) (K : NNReal) + (x : alpha) : + ∫ omega, (f : C₀(alpha, ℝ)) (omega (ContinuousPath.exitTimeTrunc U K omega)) + ∂(IsConservative.continuousProcess P hP x) + + ∫ omega, (∫ s in (0 : ℝ)..(ContinuousPath.exitTimeTrunc U K omega : ℝ), + g (omega (Real.toNNReal s))) ∂(IsConservative.continuousProcess P hP x) = + (f : C₀(alpha, ℝ)) x := by + have hdynkin := hFeller.integral_eval_stoppingTime_sub_eq_integral_integral_generator hP hK f + (ContinuousPath.exitTimeTrunc U K) (ContinuousPath.isStoppingTime_exitTimeTrunc U hU K) + (ContinuousPath.exitTimeTrunc_le U K) x + have hneg : ∀ omega : ContinuousPath alpha, + ∫ s in (0 : ℝ)..(ContinuousPath.exitTimeTrunc U K omega : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) = + -∫ s in (0 : ℝ)..(ContinuousPath.exitTimeTrunc U K omega : ℝ), + g (omega (Real.toNNReal s)) := by + intro omega + rw [ContinuousPath.integral_exitTimeTrunc_congr U K (g₂ := fun y ↦ -g y) (fun y hy ↦ hLf y hy) omega, + intervalIntegral.integral_neg] + simp only [hneg, integral_neg] at hdynkin + linarith only [hdynkin] + +/-- **Localized Dynkin formula.** For a starting point in the open set `U` and a function `φ` +that agrees with the domain element `f` on the closure of `U`, Dynkin's formula at the truncated +exit time holds for `φ` with the generator of `f`: the stopped path sits in the closure of `U`, +where `φ` and `f` agree, and the generator is only ever evaluated inside `U`. -/ +theorem IsFellerKernelSemigroup.integral_eval_exitTimeTrunc_sub_eq_of_eqOn_closure + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (f : hFeller.c0Semigroup.generatorDomain) (U : Set alpha) (hU : IsOpen U) + {φ : alpha → ℝ} (hφ : Set.EqOn φ (f : C₀(alpha, ℝ)) (closure U)) (K : NNReal) {x : alpha} + (hx : x ∈ U) : + ∫ omega, φ (omega (ContinuousPath.exitTimeTrunc U K omega)) + ∂(IsConservative.continuousProcess P hP x) - φ x = + ∫ omega, (∫ s in (0 : ℝ)..(ContinuousPath.exitTimeTrunc U K omega : ℝ), + (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s))) + ∂(IsConservative.continuousProcess P hP x) := by + have hdynkin := hFeller.integral_eval_stoppingTime_sub_eq_integral_integral_generator hP hK f + (ContinuousPath.exitTimeTrunc U K) (ContinuousPath.isStoppingTime_exitTimeTrunc U hU K) + (ContinuousPath.exitTimeTrunc_le U K) x + have hstopped : ∫ omega, φ (omega (ContinuousPath.exitTimeTrunc U K omega)) + ∂(IsConservative.continuousProcess P hP x) = + ∫ omega, (f : C₀(alpha, ℝ)) (omega (ContinuousPath.exitTimeTrunc U K omega)) + ∂(IsConservative.continuousProcess P hP x) := by + refine integral_congr_ae ?_ + filter_upwards [IsConservative.ae_eval_zero_eq hP hK x] with omega h0 + exact hφ (ContinuousPath.stopped_exitTimeTrunc_mem_closure U hU K omega (h0 ▸ hx)) + rw [hstopped, hφ (subset_closure hx)] + exact hdynkin + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathModulus.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathModulus.lean new file mode 100644 index 0000000000..93a82ff6a8 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathModulus.lean @@ -0,0 +1,175 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus +import LeanPool.MarkovProcess.MarkovProcess.Main +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals + +/-! +# The continuous-path process as a Kolmogorov process, and its uniform modulus + +The intrinsic moment criterion `HasKolmogorovMoments p q M` is a statement about the transition +kernels. This file transports it to the continuous-path process itself, at *all* nonnegative +real times and with the very same constants: the coordinate process of `continuousProcess P hP x` +is a Kolmogorov process with exponents `p`, `q` and constant `M`, for every starting point `x`. +Rational times come from the identification of the dense-time projection of the process with the +dense-time trajectory; irrational times follow by path continuity and Fatou's lemma, so no Feller +hypothesis and no local compactness are needed. + +Combining this with the quantitative chaining estimate of `Continuity/PathModulus.lean` gives the +modulus statement that tightness on path space consumes: for a horizon `T`, an oscillation +tolerance `r` and a mass tolerance `eps` there is one scale `delta > 0` that works simultaneously +at every starting point. + +Main results: + +* `IsConservative.map_denseRestriction_continuousProcess`, the dense-time projection of the + process; +* `IsConservative.isKolmogorovProcess_continuousProcess`, the moment bound at all real times; +* `IsConservative.exists_measure_compl_modulusSet_le`, the modulus estimate uniform in the + starting point. + +No tightness, weak continuity, or Hölder-path statement is proved here. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace SubMarkovKernelSemigroup + +noncomputable section + +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- The dense-time projection of the continuous-path process is the canonical dense-time +trajectory of `P`. -/ +theorem IsConservative.map_denseRestriction_continuousProcess (hK : P.KolmogorovRegular hP) : + (continuousProcess P hP).map ContinuousPath.denseRestriction = + denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding := by + unfold IsConservative.continuousProcess IsConservative.continuousPathTrajectory + exact Kernel.map_denseRestriction_toContinuousPathKernel_of_isKolmogorovCoordinate _ _ hK + +/-- The Kolmogorov increment bound for the continuous-path process at rational times. -/ +theorem IsConservative.lintegral_edist_continuousProcess_denseTime + {p q : ℝ} {M : ℝ≥0} (hmom : P.HasKolmogorovMoments p q M) (hK : P.KolmogorovRegular hP) + (x : alpha) (r r' : DenseTime) : + ∫⁻ omega, edist (omega (DenseTime.castOrderEmbedding r)) + (omega (DenseTime.castOrderEmbedding r')) ^ p ∂(continuousProcess P hP x) ≤ + (M : ℝ≥0∞) * edist (DenseTime.castOrderEmbedding r) + (DenseTime.castOrderEmbedding r') ^ q := by + have hcoord : Measurable + (fun path : DenseTime → alpha ↦ edist (path r) (path r') ^ p) := + ((measurable_pi_apply r).edist (measurable_pi_apply r')).pow_const p + have hmap := congrArg (fun kappa : Kernel alpha (DenseTime → alpha) ↦ kappa x) + (IsConservative.map_denseRestriction_continuousProcess P hP hK) + simp only [Kernel.map_apply _ ContinuousPath.measurable_denseRestriction] at hmap + calc ∫⁻ omega, edist (omega (DenseTime.castOrderEmbedding r)) + (omega (DenseTime.castOrderEmbedding r')) ^ p ∂(continuousProcess P hP x) + = ∫⁻ path, edist (path r) (path r') ^ p + ∂(((continuousProcess P hP) x).map ContinuousPath.denseRestriction) := + (lintegral_map hcoord ContinuousPath.measurable_denseRestriction).symm + _ = ∫⁻ path, edist (path r) (path r') ^ p + ∂(denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) := by rw [hmap] + _ ≤ (M : ℝ≥0∞) * edist r r' ^ q := + (IsConservative.isKolmogorovProcess_denseTimeTrajectory P hP hmom x).kolmogorovCondition + r r' + _ = (M : ℝ≥0∞) * edist (DenseTime.castOrderEmbedding r) + (DenseTime.castOrderEmbedding r') ^ q := by + rw [DenseTime.edist_castOrderEmbedding] + +/-- **The continuous-path process is a Kolmogorov process with the semigroup's own constants.** +For a conservative Kolmogorov-regular semigroup satisfying the intrinsic moment bound +`HasKolmogorovMoments p q M`, the coordinate process of `continuousProcess P hP x` satisfies the +Kolmogorov increment condition at all pairs of nonnegative real times, with the exponents and the +constant of that bound and uniformly in the starting point `x`. + +Rational times are read off the dense-time trajectory; the passage to arbitrary real times uses +only path continuity and Fatou's lemma, so neither the Feller property nor local compactness of +the state space is used. -/ +theorem IsConservative.isKolmogorovProcess_continuousProcess + {p q : ℝ} {M : ℝ≥0} (hmom : P.HasKolmogorovMoments p q M) (hK : P.KolmogorovRegular hP) + (x : alpha) : + IsKolmogorovProcess (fun (t : ℝ≥0) (omega : ContinuousPath alpha) ↦ omega t) + (continuousProcess P hP x) p q M := by + have hcont : ∀ a b : ℝ≥0, + Continuous fun omega : ContinuousPath alpha ↦ edist (omega a) (omega b) ^ p := fun a b ↦ + ENNReal.continuous_rpow_const.comp + ((ContinuousPath.continuous_eval (alpha := alpha) a).edist (ContinuousPath.continuous_eval b)) + refine IsKolmogorovProcess.mk_of_secondCountableTopology + (fun t ↦ ContinuousPath.measurable_coordinateProcess (alpha := alpha) t) ?_ hmom.p_pos + hmom.q_pos + intro s t + obtain ⟨rs, hrs⟩ := exists_denseTime_seq_tendsto s + obtain ⟨rt, hrt⟩ := exists_denseTime_seq_tendsto t + have hptwise : ∀ omega : ContinuousPath alpha, + Tendsto (fun n ↦ edist (omega (DenseTime.castOrderEmbedding (rs n))) + (omega (DenseTime.castOrderEmbedding (rt n))) ^ p) atTop + (nhds (edist (omega s) (omega t) ^ p)) := by + intro omega + refine ENNReal.continuous_rpow_const.continuousAt.tendsto.comp (Tendsto.edist ?_ ?_) + · exact (omega.continuous.tendsto s).comp hrs + · exact (omega.continuous.tendsto t).comp hrt + have hbound : ∀ n : ℕ, ∫⁻ omega, edist (omega (DenseTime.castOrderEmbedding (rs n))) + (omega (DenseTime.castOrderEmbedding (rt n))) ^ p ∂(continuousProcess P hP x) ≤ + (M : ℝ≥0∞) * edist (DenseTime.castOrderEmbedding (rs n)) + (DenseTime.castOrderEmbedding (rt n)) ^ q := fun n ↦ + IsConservative.lintegral_edist_continuousProcess_denseTime P hP hmom hK x (rs n) (rt n) + have hlimit : Tendsto (fun n ↦ (M : ℝ≥0∞) * edist (DenseTime.castOrderEmbedding (rs n)) + (DenseTime.castOrderEmbedding (rt n)) ^ q) atTop + (nhds ((M : ℝ≥0∞) * edist s t ^ q)) := + ENNReal.Tendsto.const_mul + (ENNReal.continuous_rpow_const.continuousAt.tendsto.comp (Tendsto.edist hrs hrt)) + (Or.inr ENNReal.coe_ne_top) + calc ∫⁻ omega, edist (omega s) (omega t) ^ p ∂(continuousProcess P hP x) + = ∫⁻ omega, liminf (fun n ↦ edist (omega (DenseTime.castOrderEmbedding (rs n))) + (omega (DenseTime.castOrderEmbedding (rt n))) ^ p) atTop + ∂(continuousProcess P hP x) := by + exact lintegral_congr fun omega ↦ ((hptwise omega).liminf_eq).symm + _ ≤ liminf (fun n ↦ ∫⁻ omega, edist (omega (DenseTime.castOrderEmbedding (rs n))) + (omega (DenseTime.castOrderEmbedding (rt n))) ^ p ∂(continuousProcess P hP x)) + atTop := + lintegral_liminf_le fun n ↦ (hcont _ _).measurable + _ ≤ liminf (fun n ↦ (M : ℝ≥0∞) * edist (DenseTime.castOrderEmbedding (rs n)) + (DenseTime.castOrderEmbedding (rt n)) ^ q) atTop := + liminf_le_liminf (Eventually.of_forall hbound) + _ = (M : ℝ≥0∞) * edist s t ^ q := hlimit.liminf_eq + +/-- **A modulus of continuity uniform in the starting point.** For a conservative semigroup +satisfying the intrinsic Kolmogorov moment bound, fix a horizon `T`, an oscillation tolerance +`r > 0` and a mass tolerance `eps > 0`. Then there is a single scale `delta > 0` such that, from +*every* starting point, the process gives mass at most `eps` to the paths that oscillate by more +than `r` at scale `delta` on `[0, T]`. + +This is the quantitative form of the Kolmogorov--Chentsov estimate: the constants produced by the +dyadic chaining depend only on `p`, `q`, `M`, the Hölder exponent and the displayed tolerances, +never on the starting point. -/ +theorem IsConservative.exists_measure_compl_modulusSet_le + {p q : ℝ} {M : ℝ≥0} (hmom : P.HasKolmogorovMoments p q M) (T : ℝ≥0) {r : ℝ≥0∞} (hr : 0 < r) + {eps : ℝ≥0∞} (heps : 0 < eps) : + ∃ delta : ℝ≥0∞, 0 < delta ∧ ∀ x : alpha, + continuousProcess P hP x (ContinuousPath.modulusSet T delta r)ᶜ ≤ eps := by + obtain ⟨gamma, hgamma, hgammaq⟩ := hmom.exists_holderExponent + obtain ⟨delta, hdelta, hmu⟩ := + ContinuousPath.exists_measure_compl_modulusSet_le (alpha := alpha) (M := M) hmom.p_pos hgamma + hgammaq T hr heps + refine ⟨delta, hdelta, fun x ↦ hmu _ ?_⟩ + exact IsConservative.isKolmogorovProcess_continuousProcess P hP hmom + (KolmogorovRegular.of_hasKolmogorovMoments P hP hmom) x + +end + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathTightness.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathTightness.lean new file mode 100644 index 0000000000..a0edb5fa78 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathTightness.lean @@ -0,0 +1,108 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus + +/-! +# Tightness of the path laws of a continuous-path Markov process + +The modulus estimate of `Trajectory/PathModulus.lean` is uniform in the starting point, and the +process starts where it is told, so the laws `continuousProcess P hP x` for `x` in a compact set +of starting points satisfy both hypotheses of the Arzelà--Ascoli tightness criterion of +`Continuity/PathTightness.lean`. This file records the resulting tightness statement. + +Tightness is asserted for the starting points ranging over a *compact* set. Over all starting +points at once it is false in general already at time zero: the time-zero laws are the Dirac +measures `delta_x`, and `{delta_x : x ∈ alpha}` is tight exactly when `alpha` is compact. A compact set of starting points is also all that weak continuity in the +starting point needs, since continuity at a point only sees a neighbourhood of it. + +The state space is assumed *proper* (closed balls are compact). This is what discharges the +compact containment condition: the modulus confines a path to a bounded neighbourhood of its +starting point, and over a proper space bounded closed sets are compact. On a general complete +separable metric state space the compact containment condition has to be supplied separately; +`ContinuousPath.isCompact_moduliSet_of_forall_isCompact` is the interface for that. + +Main results: + +* `IsConservative.measure_eval_zero_notMem_eq_zero`, the process starts where it is told; +* `IsConservative.isTightMeasureSet_continuousProcess`, tightness of the path laws over a compact + set of starting points; +* `IsConservative.exists_isCompact_measure_compl_le`, the same in epsilon form. + +No compactness theorem for measures (Prokhorov's theorem) is proved or used, and no weak +convergence statement is made here. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace SubMarkovKernelSemigroup + +noncomputable section + +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- The process starts where it is told: from a starting point of a measurable set `A`, almost +every path has its time-zero value in `A`. -/ +theorem IsConservative.measure_eval_zero_notMem_eq_zero (hK : P.KolmogorovRegular hP) + {A : Set alpha} (hA : MeasurableSet A) {x : alpha} (hx : x ∈ A) : + continuousProcess P hP x {omega : ContinuousPath alpha | omega 0 ∉ A} = 0 := by + have hmeas : Measurable fun omega : ContinuousPath alpha ↦ omega (0 : ℝ≥0) := + ContinuousPath.measurable_coordinateProcess (alpha := alpha) 0 + have hval : (((continuousProcess P hP) x).map fun omega ↦ omega (0 : ℝ≥0)) Aᶜ = 0 := by + rw [← Kernel.map_apply _ hmeas, IsConservative.continuousProcess_map_eval_zero P hP hK, + Kernel.id_apply] + rw [Measure.dirac_apply' _ hA.compl, Set.indicator_of_notMem (by simpa using hx)] + rwa [Measure.map_apply hmeas hA.compl, Set.preimage_compl] at hval + +variable [ProperSpace alpha] + +/-- **Tightness of the path laws over a compact set of starting points.** For a conservative +semigroup on a proper metric state space satisfying the intrinsic Kolmogorov moment criterion, the +family `{continuousProcess P hP x : x ∈ K0}` of laws on continuous-path space is tight whenever +`K0` is compact. + +The two inputs are the modulus estimate `exists_measure_compl_modulusSet_le`, whose scale does not +depend on the starting point, and the fact that the process starts in `K0`. -/ +theorem IsConservative.isTightMeasureSet_continuousProcess {p q : ℝ} {M : ℝ≥0} + (hmom : P.HasKolmogorovMoments p q M) {K0 : Set alpha} (hK0 : IsCompact K0) : + IsTightMeasureSet ((fun x ↦ continuousProcess P hP x) '' K0) := by + refine ContinuousPath.isTightMeasureSet_of_measure_compl_modulusSet_le hK0 ?_ ?_ + · rintro mu ⟨x, hx, rfl⟩ + exact IsConservative.measure_eval_zero_notMem_eq_zero P hP + (KolmogorovRegular.of_hasKolmogorovMoments P hP hmom) hK0.isClosed.measurableSet hx + · intro T r hr eps heps + obtain ⟨delta, hdelta, hbound⟩ := + IsConservative.exists_measure_compl_modulusSet_le P hP hmom T hr heps + refine ⟨delta, hdelta, ?_⟩ + rintro mu ⟨x, hx, rfl⟩ + exact hbound x + +/-- Epsilon form of tightness: one compact set of paths carries all but `eps` of the mass from +every starting point of a compact set. -/ +theorem IsConservative.exists_isCompact_measure_compl_le {p q : ℝ} {M : ℝ≥0} + (hmom : P.HasKolmogorovMoments p q M) {K0 : Set alpha} (hK0 : IsCompact K0) {eps : ℝ≥0∞} + (heps : 0 < eps) : + ∃ K : Set (ContinuousPath alpha), IsCompact K ∧ + ∀ x ∈ K0, continuousProcess P hP x Kᶜ ≤ eps := by + obtain ⟨K, hKcompact, hKmass⟩ := + isTightMeasureSet_iff_exists_isCompact_measure_compl_le.mp + (IsConservative.isTightMeasureSet_continuousProcess P hP hmom hK0) eps heps + exact ⟨K, hKcompact, fun x hx ↦ hKmass _ ⟨x, hx, rfl⟩⟩ + +end + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PenalizationDomination.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PenalizationDomination.lean new file mode 100644 index 0000000000..64c9f236f3 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PenalizationDomination.lean @@ -0,0 +1,109 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent + +/-! +# Penalization domination for killed resolvents + +A resolvent family preserving measurable bounded functions, satisfying the resolvent identity, +and solving the same bounded-potential perturbation equation as the real Feynman--Kac resolvent +dominates the killed resolvent of every open set on which the potential vanishes. The process-side +inputs are conservativity, the Feller property, and Kolmogorov regularity on a locally compact +Polish space. + +Main result: `IsFellerKernelSemigroup.killedResolvent_le_of_perturbed_resolventFamily`. +-/ + +open MeasureTheory Set +open scoped ENNReal + +namespace MarkovProcess.SubMarkovKernelSemigroup + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [CompleteSpace alpha] [Nonempty alpha] + [LocallyCompactSpace alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- A real resolvent family satisfying the kernel-resolvent perturbation identity for a bounded +nonnegative potential dominates the killed resolvent on every open set where that potential +vanishes. On the process side this requires conservativity, the Feller property, and Kolmogorov +regularity. The comparison family preserves measurability and boundedness, satisfies the +resolvent identity, and obeys the large-shift perturbation equation. -/ +theorem IsFellerKernelSemigroup.killedResolvent_le_of_perturbed_resolventFamily + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + {U : Set alpha} (hU : IsOpen U) {q : alpha → ℝ} (hq : Measurable q) + (hqU : ∀ y ∈ U, q y = 0) {C : ℝ} (hq0 : ∀ y, 0 ≤ q y) (hqC : ∀ y, q y ≤ C) + (Y : ℝ → (alpha → ℝ) → alpha → ℝ) + (hY_meas : ∀ {lam : ℝ}, 0 < lam → ∀ {f : alpha → ℝ}, Measurable f → + (∃ D, ∀ x, |f x| ≤ D) → Measurable (Y lam f)) + (hY_bound : ∀ {lam : ℝ}, 0 < lam → ∀ {f : alpha → ℝ}, Measurable f → + (∃ D, ∀ x, |f x| ≤ D) → ∃ D, ∀ x, |Y lam f x| ≤ D) + (hY_resolvent : ∀ {mu lam : ℝ}, 0 < mu → 0 < lam → ∀ {f : alpha → ℝ}, + Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + Y mu f = Y lam f + (lam - mu) • Y lam (Y mu f)) + (hY_perturbation : ∀ {lam : ℝ}, C < lam → ∀ {f : alpha → ℝ}, + Measurable f → (∃ D, ∀ x, |f x| ≤ D) → + Y lam f = P.kernelResolventReal lam f - + P.kernelResolventReal lam (fun y ↦ q y * Y lam f y)) + {f : alpha → ℝ} (hf : Measurable f) (hf0 : ∀ y, 0 ≤ f y) + {D : ℝ} (hfD : ∀ y, |f y| ≤ D) {lam : ℝ} (hlam : 0 < lam) (x : alpha) : + IsConservative.killedResolvent P hP U hU lam (fun y ↦ ENNReal.ofReal (f y)) x ≤ + ENNReal.ofReal (Y lam f x) := by + have hEq : IsConservative.feynmanKacResolventReal P hP q lam f = Y lam f := by + apply MarkovProcess.perturbed_eq_of_resolventFamilies + (fun mu ↦ P.kernelResolventReal mu) + (fun mu ↦ IsConservative.feynmanKacResolventReal P hP q mu) Y + · intro mu _hCmu hmu g k hgm hgk hgmBound hgkBound + obtain ⟨E, hgE⟩ := hgmBound + obtain ⟨F, hkF⟩ := hgkBound + exact P.kernelResolventReal_add hmu hgm hgk hgE hkF + · intro mu _hCmu hmu g hg E hgE + exact P.norm_kernelResolventReal_le hmu hgE + · exact hq + · exact hq0 + · exact hqC + · intro mu hmu g k hgm hgk hgmBound hgkBound + obtain ⟨E, hgE⟩ := hgmBound + obtain ⟨F, hkF⟩ := hgkBound + exact IsConservative.feynmanKacResolventReal_add P hP hq hq0 hmu hgm hgk hgE hkF + · intro mu _hmu g hg _hgb + exact IsConservative.measurable_feynmanKacResolventReal P hP hq mu hg + · exact hY_meas + · intro mu hmu g _hg E hgE + exact IsConservative.norm_feynmanKacResolventReal_le P hP hq0 hmu hgE + · exact hY_bound + · intro mu nu hmu hnu g hg hgb + obtain ⟨E, hgE⟩ := hgb + exact hFeller.feynmanKacResolventReal_resolvent_identity + P hP hK hq hq0 hqC hmu hnu hg hgE + · exact hY_resolvent + · intro mu _hCmu hmu g hg hgb + obtain ⟨E, hgE⟩ := hgb + exact hFeller.feynmanKacResolventReal_perturbation + P hP hK hq hq0 hqC hmu hg hgE + · intro mu hCmu _hmu + exact hY_perturbation hCmu + · exact hlam + · exact hf + · exact hfD + calc + IsConservative.killedResolvent P hP U hU lam + (fun y ↦ ENNReal.ofReal (f y)) x ≤ + IsConservative.feynmanKacResolvent P hP q lam + (fun y ↦ ENNReal.ofReal (f y)) x := + IsConservative.killedResolvent_le_feynmanKacResolvent + P hP hq hU hqU lam hf.ennreal_ofReal x + _ = ENNReal.ofReal (IsConservative.feynmanKacResolventReal P hP q lam f x) := + (IsConservative.ofReal_feynmanKacResolventReal_eq_feynmanKacResolvent + P hP hq hq0 hlam hf hf0 hfD x).symm + _ = ENNReal.ofReal (Y lam f x) := by rw [hEq] + +end + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalConditional.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalConditional.lean new file mode 100644 index 0000000000..79aaf80844 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalConditional.lean @@ -0,0 +1,125 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov + +/-! +# Rational-time conditional Markov identities for the continuous trajectory + +This file derives two local consequences of the rational joint restart law for the canonical +continuous-path trajectory. First, restricting to any event in the canonical filtration and +then shifting at a rational time gives the path kernel restarted from the state at that time. +Second, every bounded strongly measurable functional of the shifted path satisfies the +corresponding conditional-expectation formula. + +The times here are rational. The strong Markov property at an arbitrary finite stopping time +is in `Trajectory/FellerStoppingRestart.lean`. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup +namespace IsConservative + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [StandardBorelSpace alpha] [Nonempty alpha] + +private theorem continuousPathTrajectory_rationalJoint_apply + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (x : alpha) (S : DenseTime) : + ((continuousPathTrajectory P hP default) x).map (fun omega ↦ + (ContinuousPath.densePastRestriction S omega, + ContinuousPath.shift (DenseTime.castOrderEmbedding S) omega)) = + (((continuousPathTrajectory P hP default) x).map + (ContinuousPath.densePastRestriction S)) ⊗ₘ + Kernel.comap (continuousPathTrajectory P hP default) + (ContinuousPath.densePastTerminal S) + (ContinuousPath.measurable_densePastTerminal S) := by + have h := congrArg (fun K : Kernel alpha + ((Set.Iic S → alpha) × ContinuousPath alpha) ↦ K x) + (continuousPathTrajectory_map_densePastRestriction_prod_shift + P hP default hK S) + change ((continuousPathTrajectory P hP default).map (fun omega ↦ + (ContinuousPath.densePastRestriction S omega, + ContinuousPath.shift (DenseTime.castOrderEmbedding S) omega))) x = + ContinuousPath.rationalPastFutureRestartKernel + (continuousPathTrajectory P hP default) S x at h + rw [Kernel.map_apply (continuousPathTrajectory P hP default) + ((ContinuousPath.measurable_densePastRestriction S).prodMk + (ContinuousPath.measurable_shift_fixed (DenseTime.castOrderEmbedding S))) x, + ContinuousPath.rationalPastFutureRestartKernel_apply + (continuousPathTrajectory P hP default) S x] at h + exact h + +/-- At a rational time, shifting the continuous trajectory after restriction to a past event is +the continuous path kernel restarted from the state at that time. -/ +theorem continuousPathTrajectory_restrict_map_shift_denseTime + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (x : alpha) (S : DenseTime) : + ∀ A : Set (ContinuousPath alpha), + MeasurableSet[ContinuousPath.canonicalFiltration (alpha := alpha) + (DenseTime.castOrderEmbedding S)] A → + (((continuousPathTrajectory P hP default) x).restrict A).map + (ContinuousPath.shift (DenseTime.castOrderEmbedding S)) = + Kernel.comap (continuousPathTrajectory P hP default) + (ContinuousPath.coordinateProcess (alpha := alpha) + (DenseTime.castOrderEmbedding S)) + (ContinuousPath.measurable_coordinateProcess + (DenseTime.castOrderEmbedding S)) ∘ₘ + (((continuousPathTrajectory P hP default) x).restrict A) := by + exact ContinuousPath.restrict_map_shift_eq_pathKernel_comp_of_rational_joint + (continuousPathTrajectory P hP default) x S + (continuousPathTrajectory_rationalJoint_apply P hP default hK x S) + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace Real E] [CompleteSpace E] + +/-- At a rational time, the conditional expectation of a bounded functional of the shifted +trajectory is its path-kernel expectation started from the current state. -/ +theorem continuousPathTrajectory_condExp_shift_denseTime + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (x : alpha) (S : DenseTime) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : Real) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + ((continuousPathTrajectory P hP default) x)[fun omega ↦ + F (ContinuousPath.shift (DenseTime.castOrderEmbedding S) omega)| + ContinuousPath.canonicalFiltration (alpha := alpha) + (DenseTime.castOrderEmbedding S)] =ᵐ[(continuousPathTrajectory P hP default) x] + fun omega ↦ ∫ eta, F eta ∂(continuousPathTrajectory P hP default) + (omega (DenseTime.castOrderEmbedding S)) := by + apply ContinuousPath.condExp_shift_ae_eq_integral_pathKernel_of_restrict_map + (continuousPathTrajectory P hP default) x (DenseTime.castOrderEmbedding S) + · exact continuousPathTrajectory_restrict_map_shift_denseTime P hP default hK x S + · exact hF + · exact hFC + +end +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalShift.lean new file mode 100644 index 0000000000..8d049127f8 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalShift.lean @@ -0,0 +1,116 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification + +/-! +# Rational-time shifts of continuous trajectory laws + +The canonical continuous trajectory kernel restarts after every nonnegative rational time. The +proof first identifies all finite rational-coordinate marginals of the shifted path and then uses +uniqueness on the dense product path space and injectivity of dense restriction. This is an +unconditional law identity; conditional and strong Markov statements require additional work. +-/ + +open MeasureTheory ProbabilityTheory +open scoped NNReal + +namespace MarkovProcess +namespace SubMarkovKernelSemigroup +namespace IsConservative + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [StandardBorelSpace alpha] [Nonempty alpha] + +/-- Shifting the canonical continuous trajectory by a rational time gives the trajectory law +mixed against the transition kernel at that time. -/ +theorem continuousPathTrajectory_map_shift_denseTime + (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + (default : ContinuousPath alpha) + (hK : ∀ x, ∃ p q gamma : ℝ, ∃ M : ℝ≥0, + IsKolmogorovProcess (fun r omega ↦ omega r) + (denseTimeTrajectory P hP DenseTime.enumeration + DenseTime.castOrderEmbedding.toEmbedding x) p q M ∧ + 0 < gamma ∧ gamma < (q - 1) / p) + (s : DenseTime) : + (continuousPathTrajectory P hP default).map + (ContinuousPath.shift (DenseTime.castOrderEmbedding s)) = + (continuousPathTrajectory P hP default).comp + (P (DenseTime.castOrderEmbedding s)) := by + apply Kernel.map_denseRestriction_injective + apply Kernel.eq_of_map_finiteRestriction_eq + intro I + have hShift := + ContinuousPath.measurable_shift_fixed (alpha := alpha) (DenseTime.castOrderEmbedding s) + have hDense := ContinuousPath.measurable_denseRestriction (alpha := alpha) + have hRestrict := Finset.measurable_restrict (X := fun _ ↦ alpha) I + have hRestrictAdd := + Finset.measurable_restrict (X := fun _ ↦ alpha) (DenseTime.addFinset s I) + have hPullback := DenseTimePath.measurable_pullbackAddFinset (alpha := alpha) s I + have hleft : + I.restrict ∘ (ContinuousPath.denseRestriction (alpha := alpha) ∘ + ContinuousPath.shift (alpha := alpha) (DenseTime.castOrderEmbedding s)) = + DenseTimePath.pullbackAddFinset (alpha := alpha) s I ∘ + ((DenseTime.addFinset s I).restrict ∘ + ContinuousPath.denseRestriction (alpha := alpha)) := by + funext omega + change + I.restrict (ContinuousPath.denseRestriction + (ContinuousPath.shift (DenseTime.castOrderEmbedding s) omega)) = + DenseTimePath.pullbackAddFinset s I + ((DenseTime.addFinset s I).restrict (ContinuousPath.denseRestriction omega)) + rw [ContinuousPath.denseRestriction_shift] + exact DenseTimePath.restrict_shift s I (ContinuousPath.denseRestriction omega) + let Q := continuousPathTrajectory P hP default + calc + (((Q.map (ContinuousPath.shift (DenseTime.castOrderEmbedding s))).map + ContinuousPath.denseRestriction).map I.restrict) = + Q.map (I.restrict ∘ (ContinuousPath.denseRestriction ∘ + ContinuousPath.shift (DenseTime.castOrderEmbedding s))) := by + rw [← Kernel.map_comp_right + (Q.map (ContinuousPath.shift (DenseTime.castOrderEmbedding s))) hDense hRestrict, + ← Kernel.map_comp_right Q hShift (hRestrict.comp hDense)] + rw [Function.comp_assoc] + _ = Q.map (DenseTimePath.pullbackAddFinset s I ∘ + ((DenseTime.addFinset s I).restrict ∘ ContinuousPath.denseRestriction)) := by + rw [hleft] + _ = (((Q.map ContinuousPath.denseRestriction).map + (DenseTime.addFinset s I).restrict).map + (DenseTimePath.pullbackAddFinset s I)) := by + rw [← Function.comp_assoc, + Kernel.map_comp_right Q hDense (hPullback.comp hRestrictAdd), + Kernel.map_comp_right (Q.map ContinuousPath.denseRestriction) hRestrictAdd hPullback] + _ = ((finiteSetKernel P (denseTimePhysicalSet (DenseTime.addFinset s I))).map + (DenseTimePath.pullbackPhysicalSet (DenseTime.addFinset s I))).map + (DenseTimePath.pullbackAddFinset s I) := by + rw [continuousPathTrajectory_map_denseRestriction_map_restrict P hP default hK] + _ = (finiteSetKernel P (denseTimePhysicalSet (DenseTime.addFinset s I))).map + (DenseTimePath.pullbackAddFinset s I ∘ + DenseTimePath.pullbackPhysicalSet (DenseTime.addFinset s I)) := by + rw [Kernel.map_comp_right _ + (DenseTimePath.measurable_pullbackPhysicalSet (alpha := alpha) + (DenseTime.addFinset s I)) hPullback] + _ = ((finiteSetKernel P (denseTimePhysicalSet I)).map + (DenseTimePath.pullbackPhysicalSet I)).comp + (P (DenseTime.castOrderEmbedding s)) := + finiteSetKernel_map_pullback_addFinset P hP s I + _ = ((Q.map ContinuousPath.denseRestriction).map I.restrict).comp + (P (DenseTime.castOrderEmbedding s)) := by + rw [continuousPathTrajectory_map_denseRestriction_map_restrict P hP default hK] + _ = (((Q.comp (P (DenseTime.castOrderEmbedding s))).map + ContinuousPath.denseRestriction).map I.restrict) := by + rw [Kernel.map_comp, Kernel.map_comp] + +end +end IsConservative +end SubMarkovKernelSemigroup +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ResolventExitDecomposition.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ResolventExitDecomposition.lean new file mode 100644 index 0000000000..adf31cca3c --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ResolventExitDecomposition.lean @@ -0,0 +1,308 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop + +/-! +# Resolvent decomposition at an exit time + +This file splits the whole-space path resolvent at the first exit time from an open set. The +occupation before exit is the killed resolvent; on finite exit, the remaining occupation is the +discounted whole-space resolvent restarted from the exit location. The restart step uses the +strong Markov property on `{exitTime U < ⊤}` and is valid for arbitrary nonnegative extended +measurable observables. + +Main definitions and results: `ContinuousPath.pathResolvent`, +`ContinuousPath.measurable_pathResolvent`, +`IsConservative.lintegral_pathResolvent_eq_killedResolvent_univ`, and +`IsFellerKernelSemigroup.lintegral_pathResolvent_eq_killedResolvent_add`. + +No integrability or almost-sure finiteness of the exit time is asserted. +-/ + +open Filter MeasureTheory ProbabilityTheory Set +open scoped ENNReal NNReal + +namespace MarkovProcess + +namespace ContinuousPath + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + [LocallyCompactSpace alpha] + +/-- The discounted occupation of a nonnegative extended observable along one continuous path. -/ +def pathResolvent (lam : ℝ) (f : alpha → ℝ≥0∞) + (omega : ContinuousPath alpha) : ℝ≥0∞ := + ∫⁻ t in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + f (omega (Real.toNNReal t)) + +omit [CompleteSpace alpha] [Nonempty alpha] [LocallyCompactSpace alpha] in +/-- The path resolvent is measurable when its observable is measurable. -/ +theorem measurable_pathResolvent (lam : ℝ) {f : alpha → ℝ≥0∞} + (hf : Measurable f) : Measurable (pathResolvent lam f) := by + have heval : Measurable fun p : ℝ × ContinuousPath alpha ↦ p.2 (Real.toNNReal p.1) := + (ContinuousEval.continuous_eval.comp continuous_swap).measurable.comp + ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_snd) + have hjoint : Measurable (fun p : ℝ × ContinuousPath alpha ↦ + ENNReal.ofReal (Real.exp (-lam * p.1)) * f (p.2 (Real.toNNReal p.1))) := by + exact (ENNReal.measurable_ofReal.comp + ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.comp + measurable_fst)).mul (hf.comp heval) + exact hjoint.lintegral_prod_left' (μ := volume.restrict (Set.Ioi 0)) + +end + +end ContinuousPath + +namespace SubMarkovKernelSemigroup + +noncomputable section + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] + [LocallyCompactSpace alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +omit [LocallyCompactSpace alpha] in +/-- Expected discounted path occupation is the killed resolvent for the whole state space. -/ +theorem IsConservative.lintegral_pathResolvent_eq_killedResolvent_univ + (lam : ℝ) {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + ∫⁻ omega, ContinuousPath.pathResolvent lam f omega + ∂(IsConservative.continuousProcess P hP x) = + IsConservative.killedResolvent P hP Set.univ isOpen_univ lam f x := by + rw [IsConservative.killedResolvent_eq_lintegral P hP Set.univ isOpen_univ lam hf x] + refine lintegral_congr fun omega ↦ setLIntegral_congr_fun measurableSet_Ioi fun t _ ↦ ?_ + rw [(ContinuousPath.exitTime_eq_top_iff Set.univ omega).mpr fun _ ↦ Set.mem_univ _] + have ht : t ∈ {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < ⊤} := ENNReal.coe_lt_top + rw [Set.indicator_of_mem ht] + +/-- Translation of a nonnegative Lebesgue integral on a right half-line. -/ +private theorem lintegral_comp_add_right_Ioi (h : ℝ → ℝ≥0∞) (A : ℝ) : + ∫⁻ s in Set.Ioi (0 : ℝ), h (s + A) = ∫⁻ t in Set.Ioi A, h t := by + have hcv := (MeasureTheory.measurePreserving_add_right volume A).setLIntegral_comp_emb + (measurableEmbedding_addRight A) h (Set.Ioi (0 : ℝ)) + simpa only [zero_add, Set.image_add_const_Ioi] using hcv + +/-- A nonnegative integral on the positive half-line splits at a nonnegative time. -/ +private theorem lintegral_Ioi_zero_eq_Ioo_add_Ioi (h : ℝ → ℝ≥0∞) (A : ℝ) (hA : 0 ≤ A) : + ∫⁻ t in Set.Ioi (0 : ℝ), h t = + (∫⁻ t in Set.Ioo (0 : ℝ) A, h t) + ∫⁻ t in Set.Ioi A, h t := by + rcases hA.eq_or_lt with rfl | hA + · simp only [lt_self_iff_false, not_false_eq_true, Ioo_eq_empty, Measure.restrict_empty, + lintegral_zero_measure, zero_add] + · rw [show volume.restrict (Set.Ioi A) = volume.restrict (Set.Ici A) from + Measure.restrict_congr_set Ioi_ae_eq_Ici] + rw [← lintegral_union measurableSet_Ici + ((Iio_disjoint_Ici le_rfl).mono Set.Ioo_subset_Iio_self le_rfl)] + rw [Set.Ioo_union_Ici_eq_Ioi hA] + +omit [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [Nonempty alpha] [LocallyCompactSpace alpha] in +/-- Pathwise splitting of discounted occupation into the part before exit and the shifted tail. -/ +private theorem pathResolvent_eq_preExit_add_restart + (U : Set alpha) (lam : ℝ) (f : alpha → ℝ≥0∞) + (omega : ContinuousPath alpha) : + ContinuousPath.pathResolvent lam f omega = + (∫⁻ t in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < + ContinuousPath.exitTime U omega}.indicator + (fun t ↦ f (omega (Real.toNNReal t))) t) + + ({omega | ContinuousPath.exitTime U omega < ⊤} : Set _).indicator + (fun omega ↦ ENNReal.ofReal + (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal)) * + ContinuousPath.pathResolvent lam f + (ContinuousPath.shift ((ContinuousPath.exitTime U omega).untopD 0) omega)) omega := by + let tau := ContinuousPath.exitTime U omega + let H : ℝ → ℝ≥0∞ := fun t ↦ + ENNReal.ofReal (Real.exp (-lam * t)) * f (omega (Real.toNNReal t)) + let T : Set ℝ := {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau} + have hfun : (fun t ↦ ENNReal.ofReal (Real.exp (-lam * t)) * + T.indicator (fun t ↦ f (omega (Real.toNNReal t))) t) = T.indicator H := by + funext t + by_cases ht : t ∈ T + · simp only [neg_mul, Set.indicator_of_mem ht, H] + · simp only [neg_mul, Set.indicator_of_notMem ht, mul_zero, H] + by_cases htau : tau = ⊤ + · have hnot : omega ∉ {omega | ContinuousPath.exitTime U omega < ⊤} := by + change ¬tau < ⊤ + rw [htau] + exact lt_irrefl _ + rw [Set.indicator_of_notMem hnot, add_zero] + change (∫⁻ t in Set.Ioi (0 : ℝ), H t) = _ + rw [hfun, setLIntegral_indicator] + · have hT : T ∩ Set.Ioi (0 : ℝ) = Set.Ioi 0 := by + change {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau} ∩ Set.Ioi 0 = _ + rw [htau] + exact ContinuousPath.survivalSet_top + rw [hT] + · exact measurableSet_lt + (measurable_coe_nnreal_ennreal.comp measurable_real_toNNReal) measurable_const + · lift tau to NNReal using htau with a ha + have htau' : tau ≠ ⊤ := by rw [← ha]; exact WithTop.coe_ne_top + have haReal : tau.toReal = (a : ℝ) := by rw [← ha]; simp only [ENNReal.coe_toReal] + have hmem : omega ∈ {omega | ContinuousPath.exitTime U omega < ⊤} := by + change tau < ⊤ + rw [← ha] + exact WithTop.coe_lt_top a + rw [Set.indicator_of_mem hmem] + change (∫⁻ t in Set.Ioi (0 : ℝ), H t) = _ + have hpre : (∫⁻ t in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + T.indicator (fun t ↦ f (omega (Real.toNNReal t))) t) = + ∫⁻ t in Set.Ioo (0 : ℝ) (a : ℝ), H t := by + rw [hfun, setLIntegral_indicator] + · rw [ContinuousPath.survivalSet_ne_top tau htau', haReal] + · exact measurableSet_lt + (measurable_coe_nnreal_ennreal.comp measurable_real_toNNReal) measurable_const + rw [lintegral_Ioi_zero_eq_Ioo_add_Ioi H (a : ℝ) a.coe_nonneg] + congr 1 + · exact hpre.symm + · rw [← lintegral_comp_add_right_Ioi H (a : ℝ)] + have hexit : ContinuousPath.exitTime U omega = (a : ℝ≥0∞) := ha.symm + rw [hexit] + simp only [ENNReal.coe_toReal] + change (∫⁻ s in Set.Ioi (0 : ℝ), H (s + (a : ℝ))) = + ENNReal.ofReal (Real.exp (-lam * (a : ℝ))) * + (∫⁻ s in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * s)) * + f (ContinuousPath.shift a omega (Real.toNNReal s))) + have hweight_ne_top : ENNReal.ofReal (Real.exp (-lam * (a : ℝ))) ≠ ⊤ := + ENNReal.ofReal_ne_top + rw [← lintegral_const_mul' + (ENNReal.ofReal (Real.exp (-lam * (a : ℝ)))) _ + hweight_ne_top] + refine setLIntegral_congr_fun measurableSet_Ioi fun s hs ↦ ?_ + have hs0 : 0 ≤ s := (Set.mem_Ioi.mp hs).le + simp only [H, ContinuousPath.shift_apply] + rw [← mul_assoc, ← ENNReal.ofReal_mul (Real.exp_pos _).le, ← Real.exp_add] + have hexp : -lam * (s + (a : ℝ)) = -lam * (a : ℝ) + -lam * s := by ring + rw [hexp] + congr 1 + rw [Real.toNNReal_add hs0 a.coe_nonneg, Real.toNNReal_of_nonneg a.coe_nonneg] + apply congrArg (fun u : NNReal ↦ f (omega u)) + exact add_comm (Real.toNNReal s) a + +/-- **Strong-Markov resolvent decomposition at an exit time.** The expected discounted path +occupation is the killed resolvent plus, on finite exit, the discounted occupation restarted from +the exit location. At discount `lam = 0` this is the corresponding Green-function decomposition. -/ +theorem IsFellerKernelSemigroup.lintegral_pathResolvent_eq_killedResolvent_add + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (U : Set alpha) (hU : IsOpen U) (lam : ℝ) + {f : alpha → ℝ≥0∞} (hf : Measurable f) (x : alpha) : + ∫⁻ omega, ContinuousPath.pathResolvent lam f omega + ∂(IsConservative.continuousProcess P hP x) = + IsConservative.killedResolvent P hP U hU lam f x + + ∫⁻ omega, ({omega | ContinuousPath.exitTime U omega < ⊤} : Set _).indicator + (fun omega ↦ ENNReal.ofReal + (Real.exp (-lam * (ContinuousPath.exitTime U omega).toReal)) * + (∫⁻ eta, ContinuousPath.pathResolvent lam f eta + ∂(IsConservative.continuousProcess P hP + (omega ((ContinuousPath.exitTime U omega).untopD 0))))) omega + ∂(IsConservative.continuousProcess P hP x) := by + let Q : Kernel alpha (ContinuousPath alpha) := IsConservative.continuousProcess P hP + let tau : ContinuousPath alpha → ℝ≥0∞ := ContinuousPath.exitTime U + let S : Set (ContinuousPath alpha) := {omega | tau omega < ⊤} + let W : ContinuousPath alpha → ℝ≥0∞ := fun omega ↦ + ENNReal.ofReal (Real.exp (-lam * (tau omega).toReal)) + let F : ContinuousPath alpha → ℝ≥0∞ := ContinuousPath.pathResolvent lam f + have htau := ContinuousPath.isStoppingTime_exitTime U hU + have hS : MeasurableSet[htau.measurableSpace] S := by + exact StoppingTime.measurableSet_stoppingTime_lt_top htau + have hW : Measurable[htau.measurableSpace] W := by + exact ENNReal.measurable_ofReal.comp + (Real.continuous_exp.measurable.comp + (measurable_const.mul (ENNReal.measurable_toReal.comp htau.measurable))) + have hF : Measurable F := ContinuousPath.measurable_pathResolvent lam hf + have hPre : Measurable (fun omega : ContinuousPath alpha ↦ + ∫⁻ t in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau omega}.indicator + (fun t ↦ f (omega (Real.toNNReal t))) t) := by + have heval : Measurable fun p : ℝ × ContinuousPath alpha ↦ + p.2 (Real.toNNReal p.1) := + (ContinuousEval.continuous_eval.comp continuous_swap).measurable.comp + ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_snd) + have hset : MeasurableSet {p : ℝ × ContinuousPath alpha | + ((Real.toNNReal p.1 : NNReal) : ℝ≥0∞) < tau p.2} := + measurableSet_lt + (measurable_coe_nnreal_ennreal.comp + (measurable_real_toNNReal.comp measurable_fst)) + ((ContinuousPath.measurable_exitTime U hU).comp measurable_snd) + have hjoint : Measurable (fun p : ℝ × ContinuousPath alpha ↦ + ENNReal.ofReal (Real.exp (-lam * p.1)) * + {p : ℝ × ContinuousPath alpha | + ((Real.toNNReal p.1 : NNReal) : ℝ≥0∞) < tau p.2}.indicator + (fun p ↦ f (p.2 (Real.toNNReal p.1))) p) := by + exact (ENNReal.measurable_ofReal.comp + ((Real.continuous_exp.comp (continuous_const.mul continuous_id)).measurable.comp + measurable_fst)).mul ((hf.comp heval).indicator hset) + exact hjoint.lintegral_prod_left' (μ := volume.restrict (Set.Ioi 0)) + have hRestart : + ∫⁻ omega, W omega * S.indicator + (fun omega ↦ F (ContinuousPath.shift ((tau omega).untopD 0) omega)) omega ∂Q x = + ∫⁻ omega, W omega * S.indicator + (fun omega ↦ ∫⁻ eta, F eta ∂Q (omega ((tau omega).untopD 0))) omega ∂Q x := by + apply StoppingTime.lintegral_mul_indicator_of_restrict_map + (mu := Q x) + (kappa := Kernel.comap Q (fun omega ↦ omega ((tau omega).untopD 0)) + (ContinuousPath.measurable_eval_untopD_stoppingTime tau htau)) + (Y := fun omega ↦ ContinuousPath.shift ((tau omega).untopD 0) omega) + (m := htau.measurableSpace) (S := S) (F := F) (W := W) + · exact ContinuousPath.measurable_shift_untopD_stoppingTime tau htau + · exact htau.measurableSpace_le + · exact hS + · intro A hA + exact hFeller.continuousProcess_restrict_map_shift_stoppingTime_lt_top + P hP hK x tau htau A hA + · exact hF + · exact hW + have hRestart' : + ∫⁻ omega, S.indicator + (fun omega ↦ W omega * F + (ContinuousPath.shift ((tau omega).untopD 0) omega)) omega ∂Q x = + ∫⁻ omega, S.indicator + (fun omega ↦ W omega * ∫⁻ eta, F eta ∂Q + (omega ((tau omega).untopD 0))) omega ∂Q x := by + rw [show S.indicator (fun omega ↦ W omega * F + (ContinuousPath.shift ((tau omega).untopD 0) omega)) = + fun omega ↦ W omega * S.indicator + (fun omega ↦ F (ContinuousPath.shift ((tau omega).untopD 0) omega)) omega by + funext omega + by_cases hs : omega ∈ S + · simp only [hs, Set.indicator_of_mem] + · simp only [hs, not_false_eq_true, Set.indicator_of_notMem, mul_zero]] + rw [show S.indicator (fun omega ↦ W omega * ∫⁻ eta, F eta ∂Q + (omega ((tau omega).untopD 0))) = + fun omega ↦ W omega * S.indicator + (fun omega ↦ ∫⁻ eta, F eta ∂Q (omega ((tau omega).untopD 0))) omega by + funext omega + by_cases hs : omega ∈ S + · simp only [hs, Set.indicator_of_mem] + · simp only [hs, not_false_eq_true, Set.indicator_of_notMem, mul_zero]] + exact hRestart + change (∫⁻ omega, F omega ∂Q x) = _ + have hSplit : ∀ omega, F omega = + (∫⁻ t in Set.Ioi (0 : ℝ), ENNReal.ofReal (Real.exp (-lam * t)) * + {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau omega}.indicator + (fun t ↦ f (omega (Real.toNNReal t))) t) + + S.indicator (fun omega ↦ W omega * F + (ContinuousPath.shift ((tau omega).untopD 0) omega)) omega := by + intro omega + exact pathResolvent_eq_preExit_add_restart U lam f omega + rw [lintegral_congr hSplit, lintegral_add_left hPre] + rw [← IsConservative.killedResolvent_eq_lintegral P hP U hU lam hf x] + change IsConservative.killedResolvent P hP U hU lam f x + + ∫⁻ omega, S.indicator + (fun omega ↦ W omega * F + (ContinuousPath.shift ((tau omega).untopD 0) omega)) omega ∂Q x = _ + rw [hRestart'] + +end + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StartingPointContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StartingPointContinuity.lean new file mode 100644 index 0000000000..0b69ed5d8a --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StartingPointContinuity.lean @@ -0,0 +1,211 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence +import LeanPool.MarkovProcess.MarkovProcess.Main +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties +import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction +import Mathlib.MeasureTheory.Measure.Tight + +/-! +# Measurable and continuous dependence on the starting point + +Two regularity statements for the continuous-path process of a conservative sub-Markov kernel +semigroup, both in the starting point. + +*Measurability.* For a strongly measurable functional `F` of the path, the expectation +`x ↦ ∫ F d(continuousProcess P hP x)` is strongly measurable, hence measurable into a Borel +target: `IsConservative.stronglyMeasurable_integral_continuousProcess` and +`IsConservative.measurable_integral_continuousProcess`. The same holds for the two functionals +that the strong Markov property produces, the shifted path and the state at a finite stopping +time: `IsConservative.measurable_integral_shift_stoppingTime_continuousProcess` and +`IsConservative.measurable_integral_eval_stoppingTime_continuousProcess`. + +*Continuity.* For a Feller semigroup the finite-dimensional laws depend weakly continuously on +the starting point: `IsFellerKernelSemigroup.continuous_integral_boundedContinuous_finiteSetKernel` +upgrades compact-test continuity to all bounded continuous test functions. The +upgrade is a tightness argument: a finite-dimensional law on a Polish coordinate space is tight, +so a compactly supported continuous cutoff `g` with `1_K ≤ g ≤ 1` captures all but `epsilon` of the +mass at the reference starting point, the truncated integral `∫ f * g` is continuous by the +compact-test theorem, and the discarded part is bounded by `‖f‖ * (1 - ∫ g)`, itself continuous +and small. On the process this reads as continuity of cylinder expectations, +`IsFellerKernelSemigroup.continuous_integral_finsetEvaluation_continuousProcess`, with the +one-time case `IsFellerKernelSemigroup.continuous_integral_eval_continuousProcess`. + +Nothing here asserts weak continuity of the full path law `x ↦ continuousProcess P hP x` on path +space; that needs tightness on path space itself, which is not proved here. No statement covers +a stopping time that can be infinite. +-/ + +open Filter MeasureTheory ProbabilityTheory +open scoped BoundedContinuousFunction CompactlySupported NNReal + +namespace MarkovProcess + + +namespace SubMarkovKernelSemigroup + +section BoundedContinuousTest + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [SecondCountableTopology alpha] [LocallyCompactSpace alpha] + +/-- **Weak continuity of the finite-dimensional laws in the starting point.** For a conservative +Feller semigroup on a locally compact Polish state space, the integral of a *bounded continuous* +test function against the finite-set kernel `finiteSetKernel P I` is a continuous function of the +starting point. + +The compact-test version +`IsFellerKernelSemigroup.continuous_integral_compactlySupported_finiteSetKernel` only sees +compactly supported tests; conservativity supplies the missing total mass one, and tightness of +the finite-dimensional law at the reference point turns vague continuity into weak continuity. -/ +theorem IsFellerKernelSemigroup.continuous_integral_boundedContinuous_finiteSetKernel + {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) + (hP : P.IsConservative) (I : Finset NNReal) (f : (I → alpha) →ᵇ ℝ) : + Continuous fun x ↦ ∫ path, f path ∂finiteSetKernel P I x := by + let : IsMarkovKernel (finiteSetKernel P I) := hP.isMarkovKernel_finiteSetKernel P I + have hcompact : ∀ g : C_c(I → alpha, ℝ), + Continuous fun x ↦ ∫ path, g path ∂finiteSetKernel P I x := + fun g ↦ hFeller.continuous_integral_compactlySupported_finiteSetKernel hP I g + refine continuous_iff_continuousAt.mpr fun x0 ↦ Metric.tendsto_nhds.mpr fun eps heps ↦ ?_ + have hnorm : (0 : ℝ) ≤ ‖f‖ := norm_nonneg f + have hdpos : 0 < eps / (3 * (‖f‖ + 1)) := by positivity + obtain ⟨g, hg01, hgint⟩ := + exists_compactlySupported_one_sub_lt_integral (finiteSetKernel P I x0) hdpos + have hsmall : ‖f‖ * (eps / (3 * (‖f‖ + 1))) ≤ eps / 3 := by + rw [mul_div_assoc', div_le_div_iff₀ (by positivity) (by norm_num : (0 : ℝ) < 3)] + have hexpand : eps * (3 * (‖f‖ + 1)) - ‖f‖ * eps * 3 = 3 * eps := by ring + linarith only [hexpand, heps] + have htrunc : ∀ᶠ x in nhds x0, + |(∫ path, (f • g) path ∂finiteSetKernel P I x) + - ∫ path, (f • g) path ∂finiteSetKernel P I x0| < eps / 3 := by + have h := Metric.tendsto_nhds.mp ((hcompact (f • g)).continuousAt (x := x0)) (eps / 3) + (by positivity) + simpa only [Real.dist_eq] using h + have hmass : ∀ᶠ x in nhds x0, + 1 - (∫ path, g path ∂finiteSetKernel P I x) < eps / (3 * (‖f‖ + 1)) := + Tendsto.eventually_lt_const (by simp only [Pi.sub_apply]; linarith only [hgint]) + ((continuous_const.sub (hcompact g)).continuousAt (x := x0)) + filter_upwards [htrunc, hmass] with x hxtrunc hxmass + rw [Real.dist_eq] + have hkey := abs_integral_sub_integral_smul_le (finiteSetKernel P I x) f g hg01 + have hkey0 := abs_integral_sub_integral_smul_le (finiteSetKernel P I x0) f g hg01 + have hbound : ‖f‖ * (1 - ∫ path, g path ∂finiteSetKernel P I x) + ≤ ‖f‖ * (eps / (3 * (‖f‖ + 1))) := + mul_le_mul_of_nonneg_left hxmass.le hnorm + have hbound0 : ‖f‖ * (1 - ∫ path, g path ∂finiteSetKernel P I x0) + ≤ ‖f‖ * (eps / (3 * (‖f‖ + 1))) := + mul_le_mul_of_nonneg_left (by linarith only [hgint]) hnorm + have htri := abs_sub_le (∫ path, f path ∂finiteSetKernel P I x) + (∫ path, (f • g) path ∂finiteSetKernel P I x) (∫ path, f path ∂finiteSetKernel P I x0) + have htri0 := abs_sub_le (∫ path, (f • g) path ∂finiteSetKernel P I x) + (∫ path, (f • g) path ∂finiteSetKernel P I x0) (∫ path, f path ∂finiteSetKernel P I x0) + have hcomm := abs_sub_comm (∫ path, (f • g) path ∂finiteSetKernel P I x0) + (∫ path, f path ∂finiteSetKernel P I x0) + linarith only [hkey, hkey0, hxtrunc, hbound, hbound0, hsmall, htri, htri0, hcomm] + +end BoundedContinuousTest + +noncomputable section Process + +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [Nonempty alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +section Measurability + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + +/-- **Expectations of the process are strongly measurable in the starting point.** For a +strongly measurable functional `F` on continuous paths, `x ↦ ∫ F d(continuousProcess P hP x)` is +strongly measurable; this is the kernel integral of a strongly measurable function, so no +regularity hypothesis on `P` beyond conservativity is needed. -/ +theorem IsConservative.stronglyMeasurable_integral_continuousProcess + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) : + StronglyMeasurable fun x ↦ ∫ eta, F eta ∂(continuousProcess P hP x) := + hF.integral_kernel (κ := continuousProcess P hP) + +variable [MeasurableSpace E] [BorelSpace E] + +/-- **Expectations of the process are measurable in the starting point.** Borel-target form of +`stronglyMeasurable_integral_continuousProcess`: the map `x ↦ ∫ F d(continuousProcess P hP x)` is +measurable for every strongly measurable functional `F` on continuous paths. -/ +theorem IsConservative.measurable_integral_continuousProcess + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) : + Measurable fun x ↦ ∫ eta, F eta ∂(continuousProcess P hP x) := + (IsConservative.stronglyMeasurable_integral_continuousProcess P hP F hF).measurable + +/-- Expectations of a functional of the path shifted at a finite stopping time are measurable in +the starting point. This is the measurability that makes the right-hand side of the strong +Markov property a legitimate integrand. -/ +theorem IsConservative.measurable_integral_shift_stoppingTime_continuousProcess + (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) : + Measurable fun x ↦ ∫ omega, F (ContinuousPath.shift (T omega) omega) + ∂(continuousProcess P hP x) := + IsConservative.measurable_integral_continuousProcess P hP _ + (hF.comp_measurable (ContinuousPath.measurable_shift_stoppingTime T hT)) + +/-- Expectations of a functional of the state at a finite stopping time are measurable in the +starting point. -/ +theorem IsConservative.measurable_integral_eval_stoppingTime_continuousProcess + (T : ContinuousPath alpha → NNReal) + (hT : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) + (fun omega ↦ (T omega : WithTop NNReal))) + (G : alpha → E) (hG : StronglyMeasurable G) : + Measurable fun x ↦ ∫ omega, G (omega (T omega)) ∂(continuousProcess P hP x) := + IsConservative.measurable_integral_continuousProcess P hP _ + (hG.comp_measurable (ContinuousPath.measurable_eval_stoppingTime_borel T hT)) + +end Measurability + +section Continuity + +variable [LocallyCompactSpace alpha] + +/-- **Continuity of cylinder expectations in the starting point.** For a conservative Feller +semigroup with a continuous modification, the expectation of a bounded continuous function of the +coordinates at a finite set `I` of times is a continuous function of the starting point. This is +the process form of `continuous_integral_boundedContinuous_finiteSetKernel`, transported through +the finite-dimensional distributions of `continuousProcess P hP`. -/ +theorem IsFellerKernelSemigroup.continuous_integral_finsetEvaluation_continuousProcess + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) (I : Finset NNReal) + (f : (I → alpha) →ᵇ ℝ) : + Continuous fun x ↦ ∫ omega, f (ContinuousPath.finsetEvaluation I omega) + ∂(continuousProcess P hP x) := by + refine (hFeller.continuous_integral_boundedContinuous_finiteSetKernel hP I f).congr fun x ↦ ?_ + have hmap : ((continuousProcess P hP) x).map (ContinuousPath.finsetEvaluation I) = + finiteSetKernel P I x := by + rw [← Kernel.map_apply _ (ContinuousPath.measurable_finsetEvaluation I), + hFeller.continuousProcess_map_finiteEvaluation P hP hK I] + rw [← hmap, integral_map (ContinuousPath.measurable_finsetEvaluation I).aemeasurable + f.continuous.aestronglyMeasurable] + +/-- Continuity of a one-time expectation in the starting point: for a bounded continuous `g` on +the state space and a nonnegative time `t`, the expectation of `g (omega t)` under the process is +continuous in the starting point. -/ +theorem IsFellerKernelSemigroup.continuous_integral_eval_continuousProcess + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) (t : NNReal) + (g : alpha →ᵇ ℝ) : + Continuous fun x ↦ ∫ omega, g (omega t) ∂(continuousProcess P hP x) := by + have hmem : t ∈ ({t} : Finset NNReal) := Finset.mem_singleton_self t + have h := hFeller.continuous_integral_finsetEvaluation_continuousProcess P hP hK {t} + (g.compContinuous ⟨fun path ↦ path ⟨t, hmem⟩, continuous_apply _⟩) + exact h.congr fun x ↦ rfl + +end Continuity + +end Process + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean new file mode 100644 index 0000000000..d4ead1fec1 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean @@ -0,0 +1,590 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Main + +/-! +# The strong Markov property at a stopping time that may be infinite + +Mathlib's stopping times take values in `WithTop ℝ≥0`, so a stopping time of the canonical +filtration on continuous-path space may be infinite, while the strong Markov property of +`MarkovProcess/Main.lean` is stated for finite, `ℝ≥0`-valued stopping times. This file removes +that restriction on the event `{tau < ⊤}` where the time is finite, writing the finite value as +`(tau omega).untopD 0`: + +* `IsFellerKernelSemigroup.continuousProcess_restrict_map_shift_stoppingTime_lt_top`: the + restart identity, after restricting the law of the process to `A ∩ {tau < ⊤}` for an event `A` + of the stopped sigma-algebra; +* `IsFellerKernelSemigroup.continuousProcess_condExp_shift_stoppingTime_lt_top`: the same fact + in conditional-expectation form, for a bounded strongly measurable functional of the shifted + path, with the indicator of `{tau < ⊤}` on both sides. +* `StoppingTime.lintegral_mul_indicator_of_restrict_map`: integration of a restricted restart + identity against a nonnegative weight measurable at the conditioning sigma-algebra. + +The route is truncation: `truncTime tau K` is the finite stopping time `min tau K`, and the +slices `stoppingTimeSlice A tau K` partition `A ∩ {tau < ⊤}` into countably many events on which +`tau` is finite and bounded by `K`. On each slice the finite theorems of `Main.lean` apply, and +both sides of the restart identity are countably additive in the restricted measure; the +conditional-expectation form is then obtained from the slicewise restart identity through a +generic indicator bridge, `condExp_indicator_ae_eq_integral_kernel_of_restrict_map`. + +Nothing is asserted about the event `{tau = ⊤}`: on it the shifted path is the path itself, and +neither statement constrains it. No Hunt-process property is claimed. +-/ + +open MeasureTheory ProbabilityTheory +open scoped ENNReal NNReal Function + +namespace MarkovProcess + +/-! Generic stopping-time material: truncation at a deterministic horizon, the countable slicing +of the event where a `WithTop`-valued stopping time is finite, and the reassembly of restart +identities over the slices. Nothing here is specific to path space. -/ + +namespace StoppingTime + +section RestrictedRestartIntegral + +variable {Omega beta : Type*} {m mOmega : MeasurableSpace Omega} + {mBeta : MeasurableSpace beta} + +/-- A restricted restart identity may be integrated against an arbitrary nonnegative weight +measurable at the conditioning sigma-algebra. -/ +theorem lintegral_mul_indicator_of_restrict_map + (mu : @Measure Omega mOmega) (kappa : @Kernel Omega beta mOmega mBeta) + (Y : Omega → beta) (hY : @Measurable Omega beta mOmega mBeta Y) + (hm : m ≤ mOmega) (S : Set Omega) (hS : MeasurableSet[m] S) + (hJoint : ∀ A : Set Omega, MeasurableSet[m] A → + (mu.restrict (A ∩ S)).map Y = kappa ∘ₘ (mu.restrict (A ∩ S))) + (F : beta → ℝ≥0∞) (hF : Measurable F) + (W : Omega → ℝ≥0∞) (hW : Measurable[m] W) : + ∫⁻ omega, W omega * S.indicator (fun omega ↦ F (Y omega)) omega ∂mu = + ∫⁻ omega, W omega * S.indicator + (fun omega ↦ ∫⁻ y, F y ∂kappa omega) omega ∂mu := by + have hSm : MeasurableSet S := hm S hS + have hSet : ∀ A : Set Omega, MeasurableSet[m] A → + ∫⁻ omega in A ∩ S, F (Y omega) ∂mu = + ∫⁻ omega in A ∩ S, (∫⁻ y, F y ∂kappa omega) ∂mu := by + intro A hA + calc + ∫⁻ omega in A ∩ S, F (Y omega) ∂mu = + ∫⁻ y, F y ∂((mu.restrict (A ∩ S)).map Y) := by + rw [lintegral_map hF hY] + _ = ∫⁻ y, F y ∂(kappa ∘ₘ (mu.restrict (A ∩ S))) := by rw [hJoint A hA] + _ = ∫⁻ omega in A ∩ S, (∫⁻ y, F y ∂kappa omega) ∂mu := by + rw [Measure.comp_eq_comp_const_apply] + exact Measure.lintegral_bind kappa.aemeasurable hF.aemeasurable + refine @Measurable.ennreal_induction Omega m + (fun W ↦ ∫⁻ omega, W omega * S.indicator (fun omega ↦ F (Y omega)) omega ∂mu = + ∫⁻ omega, W omega * S.indicator + (fun omega ↦ ∫⁻ y, F y ∂kappa omega) omega ∂mu) ?_ ?_ ?_ W hW + · intro c A hA + have hA' : MeasurableSet A := hm A hA + have hAS : MeasurableSet (A ∩ S) := hA'.inter hSm + have hleft : (fun omega ↦ A.indicator (fun _ ↦ c) omega * + S.indicator (fun omega ↦ F (Y omega)) omega) = + (A ∩ S).indicator (fun omega ↦ c * F (Y omega)) := by + funext omega + by_cases ha : omega ∈ A <;> by_cases hs : omega ∈ S <;> + simp [Set.indicator_of_mem, Set.indicator_of_notMem, ha, hs] + have hright : (fun omega ↦ A.indicator (fun _ ↦ c) omega * + S.indicator (fun omega ↦ ∫⁻ y, F y ∂kappa omega) omega) = + (A ∩ S).indicator (fun omega ↦ c * ∫⁻ y, F y ∂kappa omega) := by + funext omega + by_cases ha : omega ∈ A <;> by_cases hs : omega ∈ S <;> + simp [Set.indicator_of_mem, Set.indicator_of_notMem, ha, hs] + rw [hleft, hright, lintegral_indicator hAS, lintegral_indicator hAS] + calc + ∫⁻ omega in A ∩ S, c * F (Y omega) ∂mu = + c * ∫⁻ omega in A ∩ S, F (Y omega) ∂mu := + lintegral_const_mul c (hF.comp hY) + _ = c * ∫⁻ omega in A ∩ S, (∫⁻ y, F y ∂kappa omega) ∂mu := by + rw [hSet A hA] + _ = ∫⁻ omega in A ∩ S, c * (∫⁻ y, F y ∂kappa omega) ∂mu := + (lintegral_const_mul c hF.lintegral_kernel).symm + · intro W Z _hdisj hWm hZm hWi hZi + simp_rw [Pi.add_apply, add_mul] + rw [lintegral_add_left] + · rw [lintegral_add_left] + · exact congrArg₂ (· + ·) hWi hZi + · exact (hWm.mono hm le_rfl).mul (hF.lintegral_kernel.indicator hSm) + · exact (hWm.mono hm le_rfl).mul ((hF.comp hY).indicator hSm) + · intro W hWm hmono hWi + change (∫⁻ omega, (⨆ n, W n omega) * + S.indicator (fun omega ↦ F (Y omega)) omega ∂mu) = _ + rw [show (fun omega ↦ (⨆ n, W n omega) * + S.indicator (fun omega ↦ F (Y omega)) omega) = + fun omega ↦ ⨆ n, W n omega * S.indicator (fun omega ↦ F (Y omega)) omega by + funext omega; exact ENNReal.iSup_mul (fun n ↦ W n omega) _] + rw [show (fun omega ↦ (⨆ n, W n omega) * S.indicator + (fun omega ↦ ∫⁻ y, F y ∂kappa omega) omega) = + fun omega ↦ ⨆ n, W n omega * S.indicator + (fun omega ↦ ∫⁻ y, F y ∂kappa omega) omega by + funext omega; exact ENNReal.iSup_mul (fun n ↦ W n omega) _] + rw [lintegral_iSup] + · rw [lintegral_iSup] + · exact iSup_congr fun n ↦ hWi n + · exact fun n ↦ (hWm n).mono hm le_rfl |>.mul + (hF.lintegral_kernel.indicator hSm) + · exact fun i j hij omega ↦ mul_le_mul_left (hmono hij omega) _ + · exact fun n ↦ (hWm n).mono hm le_rfl |>.mul + ((hF.comp hY).indicator hSm) + · exact fun i j hij omega ↦ mul_le_mul_left (hmono hij omega) _ + +end RestrictedRestartIntegral + +section Trunc + +variable {Omega : Type*} {mOmega : MeasurableSpace Omega} + +/-- A `WithTop ℝ≥0`-valued time truncated at the deterministic horizon `K`: the finite, +`ℝ≥0`-valued time equal to `tau omega` when that is at most `K`, and to `K` otherwise. -/ +def truncTime (tau : Omega → WithTop NNReal) (K : NNReal) (omega : Omega) : NNReal := + (min (tau omega) (K : WithTop NNReal)).untopD 0 + +/-- The truncated time, read back in `WithTop ℝ≥0`, is the minimum of the time and the +horizon. -/ +theorem coe_truncTime (tau : Omega → WithTop NNReal) (K : NNReal) (omega : Omega) : + ((truncTime tau K omega : NNReal) : WithTop NNReal) = min (tau omega) (K : WithTop NNReal) := by + have hne : min (tau omega) (K : WithTop NNReal) ≠ ⊤ := by + intro htop + have hle := min_le_right (tau omega) (K : WithTop NNReal) + rw [htop, top_le_iff] at hle + exact WithTop.coe_ne_top hle + rw [truncTime] + lift min (tau omega) (K : WithTop NNReal) to NNReal using hne with a ha + rw [WithTop.untopD_coe] + +/-- Below the horizon the truncated time is the untopped time itself. -/ +theorem truncTime_eq_untopD {tau : Omega → WithTop NNReal} {K : NNReal} {omega : Omega} + (h : tau omega ≤ (K : WithTop NNReal)) : + truncTime tau K omega = (tau omega).untopD 0 := by + rw [truncTime, min_eq_left h] + +/-- The truncation of a stopping time at a deterministic horizon is a finite stopping time. -/ +theorem isStoppingTime_truncTime {f : Filtration NNReal mOmega} {tau : Omega → WithTop NNReal} + (htau : IsStoppingTime f tau) (K : NNReal) : + IsStoppingTime f (fun omega ↦ ((truncTime tau K omega : NNReal) : WithTop NNReal)) := by + simp only [coe_truncTime] + exact htau.min_const K + +/-- Pointwise equal stopping times have the same stopped sigma-algebra. -/ +theorem measurableSpace_stoppingTime_congr {f : Filtration NNReal mOmega} + {tau sigma : Omega → WithTop NNReal} + (htau : IsStoppingTime f tau) (hsigma : IsStoppingTime f sigma) + (h : ∀ omega, tau omega = sigma omega) : + htau.measurableSpace = hsigma.measurableSpace := by + have hfun : tau = sigma := funext h + subst hfun + rfl + +/-- The stopped sigma-algebra of a truncated stopping time is the stopped sigma-algebra of the +minimum of the time and the constant horizon. -/ +theorem measurableSpace_truncTime {f : Filtration NNReal mOmega} {tau : Omega → WithTop NNReal} + (htau : IsStoppingTime f tau) (K : NNReal) : + (isStoppingTime_truncTime htau K).measurableSpace = (htau.min_const K).measurableSpace := + measurableSpace_stoppingTime_congr _ _ (coe_truncTime tau K) + +end Trunc + +section Slices + +variable {Omega : Type*} {mOmega : MeasurableSpace Omega} {f : Filtration NNReal mOmega} + {tau : Omega → WithTop NNReal} + +/-- The event that a stopping time is finite belongs to its stopped sigma-algebra: intersecting +it with `{tau ≤ i}` leaves that event unchanged. -/ +theorem measurableSet_stoppingTime_lt_top (htau : IsStoppingTime f tau) : + MeasurableSet[htau.measurableSpace] {omega | tau omega < ⊤} := by + refine ⟨?_, fun i ↦ ?_⟩ + · have h : {omega | tau omega < ⊤} = {omega | tau omega = ⊤}ᶜ := by + ext omega + simp only [Set.mem_ofPred_eq, Set.mem_compl_iff, lt_top_iff_ne_top] + rw [h] + exact htau.measurableSet_eq_top'.compl + · have h : {omega | tau omega < ⊤} ∩ {omega | tau omega ≤ (i : WithTop NNReal)} = + {omega | tau omega ≤ (i : WithTop NNReal)} := + Set.inter_eq_right.mpr fun omega homega ↦ lt_of_le_of_lt homega (WithTop.coe_lt_top i) + rw [h] + exact htau i + +/-- The time-zero sigma-algebra of the filtration is contained in the stopped sigma-algebra of +every stopping time. -/ +theorem filtration_zero_le_measurableSpace_stoppingTime (htau : IsStoppingTime f tau) : + f 0 ≤ htau.measurableSpace := by + intro s hs + exact ⟨le_iSup f 0 s hs, fun i ↦ (f.mono zero_le s hs).inter (htau i)⟩ + +/-- The `K`-th slice of an event `A` of the stopped sigma-algebra of `tau`: the part of `A` on +which `tau` is at most `K` but larger than every smaller natural number. These slices are +pairwise disjoint and exhaust `A ∩ {tau < ⊤}`. -/ +def stoppingTimeSlice (A : Set Omega) (tau : Omega → WithTop NNReal) (K : ℕ) : Set Omega := + (A ∩ ⋂ j ∈ Set.Iio K, {omega | ((j : NNReal) : WithTop NNReal) < tau omega}) ∩ + {omega | tau omega ≤ ((K : NNReal) : WithTop NNReal)} + +/-- Each slice of an event of the stopped sigma-algebra of `tau` lies in the stopped +sigma-algebra of `tau` truncated at the corresponding horizon. -/ +theorem measurableSet_stoppingTimeSlice (htau : IsStoppingTime f tau) {A : Set Omega} + (hA : MeasurableSet[htau.measurableSpace] A) (K : ℕ) : + MeasurableSet[(htau.min_const ((K : NNReal))).measurableSpace] (stoppingTimeSlice A tau K) := by + refine (htau.measurableSet_inter_le_const_iff _ ((K : NNReal))).mp ?_ + refine (hA.inter ?_).inter (htau.measurableSet_le' (K : NNReal)) + refine MeasurableSet.biInter (Set.to_countable _) fun j _ ↦ ?_ + exact htau.measurableSet_gt' (j : NNReal) + +/-- Each slice of an event of the stopped sigma-algebra is measurable in the ambient +sigma-algebra. -/ +theorem measurableSet_stoppingTimeSlice' (htau : IsStoppingTime f tau) {A : Set Omega} + (hA : MeasurableSet[htau.measurableSpace] A) (K : ℕ) : + MeasurableSet (stoppingTimeSlice A tau K) := + (htau.min_const ((K : NNReal))).measurableSpace_le _ + (measurableSet_stoppingTimeSlice htau hA K) + +/-- The slices of an event are pairwise disjoint. -/ +theorem pairwise_disjoint_stoppingTimeSlice (A : Set Omega) : + Pairwise (Disjoint on (stoppingTimeSlice A tau)) := by + have key : ∀ K L : ℕ, K < L → + Disjoint (stoppingTimeSlice A tau K) (stoppingTimeSlice A tau L) := by + intro K L h + refine Set.disjoint_left.mpr fun omega hK hL ↦ ?_ + have h1 : tau omega ≤ ((K : NNReal) : WithTop NNReal) := hK.2 + have h2 : ((K : NNReal) : WithTop NNReal) < tau omega := by + have hmem := hL.1.2 + simp only [Set.mem_iInter, Set.mem_ofPred_eq] at hmem + exact hmem K (Set.mem_Iio.mpr h) + exact absurd h1 (not_le_of_gt h2) + intro K L hKL + rcases lt_or_gt_of_ne hKL with h | h + · exact key K L h + · exact (key L K h).symm + +/-- The slices of an event `A` exhaust the part of `A` on which the stopping time is finite. -/ +theorem iUnion_stoppingTimeSlice (A : Set Omega) : + ⋃ K : ℕ, stoppingTimeSlice A tau K = A ∩ {omega | tau omega < ⊤} := by + classical + apply Set.eq_of_subset_of_subset + · refine Set.iUnion_subset fun K omega homega ↦ ⟨homega.1.1, ?_⟩ + have hle : tau omega ≤ ((K : NNReal) : WithTop NNReal) := homega.2 + exact lt_top_iff_ne_top.mpr (ne_top_of_le_ne_top (WithTop.coe_ne_top) hle) + · rintro omega ⟨hA, hlt⟩ + lift tau omega to NNReal using hlt.ne with t ht + have hex : ∃ K : ℕ, t ≤ (K : NNReal) := by + obtain ⟨K, hK⟩ := exists_nat_ge (t : ℝ) + exact ⟨K, by exact_mod_cast hK⟩ + refine Set.mem_iUnion.mpr ⟨Nat.find hex, ⟨hA, ?_⟩, ?_⟩ + · refine Set.mem_iInter₂.mpr fun j hj ↦ ?_ + show ((j : NNReal) : WithTop NNReal) < tau omega + rw [← ht, WithTop.coe_lt_coe] + exact lt_of_not_ge (Nat.find_min hex (Set.mem_Iio.mp hj)) + · show tau omega ≤ ((Nat.find hex : NNReal) : WithTop NNReal) + rw [← ht, WithTop.coe_le_coe] + exact Nat.find_spec hex + +/-- On the `K`-th slice the time truncated at `K` is the untopped time itself. -/ +theorem truncTime_eq_untopD_of_mem_stoppingTimeSlice {A : Set Omega} {K : ℕ} {omega : Omega} + (h : omega ∈ stoppingTimeSlice A tau K) : + truncTime tau (K : NNReal) omega = (tau omega).untopD 0 := + truncTime_eq_untopD h.2 + +end Slices + +section Reassembly + +variable {Omega beta : Type*} [MeasurableSpace Omega] [MeasurableSpace beta] + +/-- A restart identity for the measure restricted to each member of a countable disjoint family +of measurable events holds for the measure restricted to their union: both sides of the identity +are countably additive in the restricted measure. -/ +theorem map_restrict_iUnion_eq_comp_of_forall (mu : Measure Omega) (kappa : Kernel Omega beta) + (g : Omega → beta) (hg : Measurable g) (D : ℕ → Set Omega) + (hD : ∀ i, MeasurableSet (D i)) (hdisj : Pairwise (Disjoint on D)) + (h : ∀ i, (mu.restrict (D i)).map g = kappa ∘ₘ (mu.restrict (D i))) : + (mu.restrict (⋃ i, D i)).map g = kappa ∘ₘ (mu.restrict (⋃ i, D i)) := by + ext s hs + rw [Measure.bind_apply hs kappa.aemeasurable, Measure.map_apply hg hs, + Measure.restrict_apply (hg hs), Set.inter_iUnion, + measure_iUnion (fun i j hij ↦ (hdisj hij).mono Set.inter_subset_right Set.inter_subset_right) + (fun i ↦ (hg hs).inter (hD i)), + lintegral_iUnion hD hdisj] + refine tsum_congr fun i ↦ ?_ + rw [← Measure.restrict_apply (hg hs), ← Measure.map_apply hg hs, h i, + Measure.bind_apply hs kappa.aemeasurable] + +end Reassembly + +end StoppingTime + +open StoppingTime + +namespace ContinuousPath + +variable {alpha : Type*} [TopologicalSpace alpha] + [TopologicalSpace.PseudoMetrizableSpace alpha] [SecondCountableTopology alpha] + [MeasurableSpace alpha] [BorelSpace alpha] + +omit [TopologicalSpace.PseudoMetrizableSpace alpha] [SecondCountableTopology alpha] in +/-- The untopped value of a stopping time of the canonical filtration is Borel measurable. -/ +theorem measurable_untopD_stoppingTime (tau : ContinuousPath alpha → WithTop NNReal) + (htau : IsStoppingTime (canonicalFiltration (alpha := alpha)) tau) : + Measurable (fun omega ↦ (tau omega).untopD 0) := + htau.measurable'.untopD 0 + +omit [TopologicalSpace.PseudoMetrizableSpace alpha] [SecondCountableTopology alpha] in +/-- Shifting a path by the untopped value of a stopping time of the canonical filtration is +Borel measurable. -/ +theorem measurable_shift_untopD_stoppingTime (tau : ContinuousPath alpha → WithTop NNReal) + (htau : IsStoppingTime (canonicalFiltration (alpha := alpha)) tau) : + Measurable (fun omega ↦ shift ((tau omega).untopD 0) omega) := + measurable_shift_of_measurable _ (measurable_untopD_stoppingTime tau htau) + +omit [TopologicalSpace.PseudoMetrizableSpace alpha] [SecondCountableTopology alpha] in +/-- Evaluating a path at the untopped value of a stopping time of the canonical filtration is +Borel measurable. -/ +theorem measurable_eval_untopD_stoppingTime (tau : ContinuousPath alpha → WithTop NNReal) + (htau : IsStoppingTime (canonicalFiltration (alpha := alpha)) tau) : + Measurable (fun omega : ContinuousPath alpha ↦ omega ((tau omega).untopD 0)) := + measurable_eval_of_measurable _ (measurable_untopD_stoppingTime tau htau) + +/-- The state at the untopped value of a stopping time of the canonical filtration is measurable +for the stopped sigma-algebra: where the time is finite this is the stopped value of the +progressively measurable coordinate process, and where it is infinite it is the time-zero +state. -/ +theorem measurable_eval_untopD_stoppingTime_stopped + (tau : ContinuousPath alpha → WithTop NNReal) + (htau : IsStoppingTime (canonicalFiltration (alpha := alpha)) tau) : + Measurable[htau.measurableSpace] + (fun omega : ContinuousPath alpha ↦ omega ((tau omega).untopD 0)) := by + intro B hB + have hsplit : (fun omega : ContinuousPath alpha ↦ omega ((tau omega).untopD 0)) ⁻¹' B = + ((stoppedValue (coordinateProcess (alpha := alpha)) tau) ⁻¹' B ∩ + {omega | tau omega < ⊤}) ∪ + ((coordinateProcess (alpha := alpha) 0) ⁻¹' B ∩ {omega | tau omega < ⊤}ᶜ) := by + ext omega + simp only [Set.mem_union, Set.mem_inter_iff, Set.mem_preimage, Set.mem_ofPred_eq, + Set.mem_compl_iff, stoppedValue, coordinateProcess] + by_cases h : tau omega = ⊤ + · rw [h] + simp only [WithTop.untopD_top, lt_self_iff_false, and_false, not_false_eq_true, and_true, + false_or] + · have hlt : tau omega < ⊤ := lt_top_iff_ne_top.mpr h + have hval : (tau omega).untopD 0 = (tau omega).untopA := by + lift tau omega to NNReal using h with t + rfl + rw [hval] + simp only [hlt, and_true, not_true_eq_false, and_false, or_false] + rw [hsplit] + refine MeasurableSet.union ?_ ?_ + · exact (measurable_stoppedValue progMeasurable_coordinateProcess htau hB).inter + (measurableSet_stoppingTime_lt_top htau) + · exact (filtration_zero_le_measurableSpace_stoppingTime htau _ + (measurable_coordinateProcess_canonicalFiltration 0 hB)).inter + (measurableSet_stoppingTime_lt_top htau).compl + +end ContinuousPath + +namespace StoppingTime + +section Bridge + +variable {Omega beta E : Type*} {m : MeasurableSpace Omega} + {mOmega : MeasurableSpace Omega} {mBeta : MeasurableSpace beta} + [NormedAddCommGroup E] [NormedSpace Real E] [CompleteSpace E] + +omit [CompleteSpace E] in +/-- If the law of `Y` after restriction to an event is obtained by mixing `kappa`, then the +integral over that event of a bounded strongly measurable observable of `Y` is the integral over +it of the `kappa`-expectation of the observable. -/ +theorem setIntegral_integral_kernel_of_restrict_map + (mu : @Measure Omega mOmega) [IsFiniteMeasure mu] + (kappa : @Kernel Omega beta mOmega mBeta) [IsMarkovKernel kappa] + (Y : Omega → beta) (hY : @Measurable Omega beta mOmega mBeta Y) (A : Set Omega) + (hJoint : (mu.restrict A).map Y = kappa ∘ₘ (mu.restrict A)) + (F : beta → E) (hF : StronglyMeasurable F) (C : Real) (hFC : ∀ y, ‖F y‖ ≤ C) : + ∫ omega in A, (∫ y, F y ∂kappa omega) ∂mu = ∫ omega in A, F (Y omega) ∂mu := by + have hfMeas : AEStronglyMeasurable (fun omega ↦ F (Y omega)) mu := + (hF.comp_measurable hY).aestronglyMeasurable + have hfInt : Integrable (fun omega ↦ F (Y omega)) mu := + Integrable.of_bound hfMeas C (ae_of_all _ fun omega ↦ hFC (Y omega)) + have hFA : Integrable F ((mu.restrict A).map Y) := by + rw [integrable_map_measure hF.aestronglyMeasurable hY.aemeasurable] + exact hfInt.restrict + have hFAComp : Integrable F (kappa ∘ₘ (mu.restrict A)) := by + rw [← hJoint] + exact hFA + rw [Measure.comp_eq_comp_const_apply] at hFAComp + have hIntegralComp := Kernel.integral_comp hFAComp + calc + ∫ omega in A, (∫ y, F y ∂kappa omega) ∂mu = + ∫ omega, (∫ y, F y ∂kappa omega) ∂(mu.restrict A) := rfl + _ = ∫ y, F y ∂(kappa ∘ₘ (mu.restrict A)) := by + rw [Measure.comp_eq_comp_const_apply] + simpa only [Kernel.const_apply] using hIntegralComp.symm + _ = ∫ y, F y ∂((mu.restrict A).map Y) := by rw [hJoint] + _ = ∫ omega, F (Y omega) ∂(mu.restrict A) := by + rw [integral_map hY.aemeasurable hF.aestronglyMeasurable] + _ = ∫ omega in A, F (Y omega) ∂mu := rfl + +/-- If the law of `Y` after restriction to the intersection of `S` with every conditioning event +is obtained by mixing `kappa`, then the conditional expectation of the `S`-indicator of a bounded +strongly measurable observable of `Y` is the `S`-indicator of that observable's +`kappa`-expectation. This is the indicator form of +`condExp_comp_ae_eq_integral_kernel_of_restrict_map`; nothing is asserted off `S`. -/ +theorem condExp_indicator_ae_eq_integral_kernel_of_restrict_map + (mu : @Measure Omega mOmega) [IsFiniteMeasure mu] + (kappa : @Kernel Omega beta mOmega mBeta) [IsMarkovKernel kappa] + (Y : Omega → beta) (hY : @Measurable Omega beta mOmega mBeta Y) + (hm : m ≤ mOmega) (S : Set Omega) (hS : MeasurableSet[m] S) + (hJoint : ∀ A : Set Omega, MeasurableSet[m] A → + (mu.restrict (A ∩ S)).map Y = kappa ∘ₘ (mu.restrict (A ∩ S))) + (F : beta → E) (hF : StronglyMeasurable F) + (hFm : StronglyMeasurable[m] (fun omega ↦ ∫ y, F y ∂kappa omega)) + (C : Real) (hFC : ∀ y, ‖F y‖ ≤ C) : + mu[S.indicator (fun omega ↦ F (Y omega))|m] =ᵐ[mu] + S.indicator (fun omega ↦ ∫ y, F y ∂kappa omega) := by + have hSm : MeasurableSet S := hm S hS + have hfMeas : AEStronglyMeasurable (S.indicator (fun omega ↦ F (Y omega))) mu := + ((hF.comp_measurable hY).indicator hSm).aestronglyMeasurable + have hbound : ∀ omega, ‖S.indicator (fun omega ↦ F (Y omega)) omega‖ ≤ max C 0 := by + intro omega + by_cases homega : omega ∈ S + · rw [Set.indicator_of_mem homega] + exact le_trans (hFC (Y omega)) (le_max_left C 0) + · rw [Set.indicator_of_notMem homega, norm_zero] + exact le_max_right C 0 + have hfInt : Integrable (S.indicator (fun omega ↦ F (Y omega))) mu := + Integrable.of_bound hfMeas (max C 0) (ae_of_all _ hbound) + have hgMeas : AEStronglyMeasurable[m] (S.indicator (fun omega ↦ ∫ y, F y ∂kappa omega)) mu := + (hFm.indicator hS).aestronglyMeasurable + have hgbound : ∀ omega, ‖S.indicator (fun omega ↦ ∫ y, F y ∂kappa omega) omega‖ ≤ max C 0 := by + intro omega + by_cases homega : omega ∈ S + · rw [Set.indicator_of_mem homega] + refine le_trans ?_ (le_max_left C 0) + simpa only [measureReal_def, measure_univ, ENNReal.toReal_one, mul_one] using + norm_integral_le_of_norm_le_const (μ := kappa omega) (ae_of_all _ hFC) + · rw [Set.indicator_of_notMem homega, norm_zero] + exact le_max_right C 0 + refine (ae_eq_condExp_of_forall_setIntegral_eq + (m := m) (m₀ := mOmega) (μ := mu) hm hfInt ?_ ?_ hgMeas).symm + · intro A _hA _hmuA + exact (Integrable.of_bound (hgMeas.mono hm) (max C 0) (ae_of_all _ hgbound)).restrict + · intro A hA _hmuA + rw [setIntegral_indicator hSm, setIntegral_indicator hSm] + exact setIntegral_integral_kernel_of_restrict_map mu kappa Y hY (A ∩ S) (hJoint A hA) F hF C hFC + +end Bridge + +end StoppingTime + +namespace SubMarkovKernelSemigroup + +noncomputable section + +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [Nonempty alpha] [LocallyCompactSpace alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- **Strong Markov property at a stopping time that may be infinite, in restart form.** Let +`tau` be a stopping time of the canonical filtration on continuous-path space, possibly taking +the value `⊤`, and let `A` be an event of its stopped sigma-algebra. After restricting the law +of the process to the part of `A` on which `tau` is finite, the law of the path shifted by +`(tau omega).untopD 0` is the process started from the state at that time. On the event +`{tau = ⊤}` nothing is asserted. -/ +theorem IsFellerKernelSemigroup.continuousProcess_restrict_map_shift_stoppingTime_lt_top + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (x : alpha) (tau : ContinuousPath alpha → WithTop NNReal) + (htau : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) tau) + (A : Set (ContinuousPath alpha)) (hA : MeasurableSet[htau.measurableSpace] A) : + (((continuousProcess P hP) x).restrict (A ∩ {omega | tau omega < ⊤})).map + (fun omega ↦ ContinuousPath.shift ((tau omega).untopD 0) omega) = + Kernel.comap (continuousProcess P hP) (fun omega ↦ omega ((tau omega).untopD 0)) + (ContinuousPath.measurable_eval_untopD_stoppingTime tau htau) ∘ₘ + (((continuousProcess P hP) x).restrict (A ∩ {omega | tau omega < ⊤})) := by + have hslice : ∀ K : ℕ, + ((((continuousProcess P hP) x).restrict (stoppingTimeSlice A tau K)).map + (fun omega ↦ ContinuousPath.shift ((tau omega).untopD 0) omega)) = + Kernel.comap (continuousProcess P hP) (fun omega ↦ omega ((tau omega).untopD 0)) + (ContinuousPath.measurable_eval_untopD_stoppingTime tau htau) ∘ₘ + (((continuousProcess P hP) x).restrict (stoppingTimeSlice A tau K)) := by + intro K + have hDK : MeasurableSet (stoppingTimeSlice A tau K) := + measurableSet_stoppingTimeSlice' htau hA K + have hAK : MeasurableSet[(isStoppingTime_truncTime htau (K : NNReal)).measurableSpace] + (stoppingTimeSlice A tau K) := by + rw [measurableSpace_truncTime htau (K : NNReal)] + exact measurableSet_stoppingTimeSlice htau hA K + have hmain := hFeller.continuousProcess_restrict_map_shift_stoppingTime P hP hK x + (truncTime tau (K : NNReal)) (isStoppingTime_truncTime htau (K : NNReal)) + (stoppingTimeSlice A tau K) hAK + have hL : ((((continuousProcess P hP) x).restrict (stoppingTimeSlice A tau K)).map + (fun omega ↦ ContinuousPath.shift (truncTime tau (K : NNReal) omega) omega)) = + ((((continuousProcess P hP) x).restrict (stoppingTimeSlice A tau K)).map + (fun omega ↦ ContinuousPath.shift ((tau omega).untopD 0) omega)) := by + refine Measure.map_congr ((ae_restrict_iff' hDK).mpr (ae_of_all _ fun omega homega ↦ ?_)) + exact congrArg (fun s ↦ ContinuousPath.shift s omega) + (truncTime_eq_untopD_of_mem_stoppingTimeSlice homega) + have hR : (Kernel.comap (continuousProcess P hP) + (fun omega ↦ omega (truncTime tau (K : NNReal) omega)) + (ContinuousPath.measurable_eval_stoppingTime_borel (truncTime tau (K : NNReal)) + (isStoppingTime_truncTime htau (K : NNReal))) ∘ₘ + (((continuousProcess P hP) x).restrict (stoppingTimeSlice A tau K))) = + Kernel.comap (continuousProcess P hP) (fun omega ↦ omega ((tau omega).untopD 0)) + (ContinuousPath.measurable_eval_untopD_stoppingTime tau htau) ∘ₘ + (((continuousProcess P hP) x).restrict (stoppingTimeSlice A tau K)) := by + refine Measure.comp_congr ((ae_restrict_iff' hDK).mpr (ae_of_all _ fun omega homega ↦ ?_)) + simp only [Kernel.comap_apply] + rw [truncTime_eq_untopD_of_mem_stoppingTimeSlice homega] + rw [← hL, hmain, hR] + rw [← iUnion_stoppingTimeSlice (tau := tau) A] + exact map_restrict_iUnion_eq_comp_of_forall _ _ _ + (ContinuousPath.measurable_shift_untopD_stoppingTime tau htau) (stoppingTimeSlice A tau) + (fun K ↦ measurableSet_stoppingTimeSlice' htau hA K) + (pairwise_disjoint_stoppingTimeSlice A) hslice + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace Real E] [CompleteSpace E] + +/-- **Strong Markov property at a stopping time that may be infinite, in +conditional-expectation form.** For a bounded strongly measurable functional `F` of the path +and a stopping time `tau` of the canonical filtration that may take the value `⊤`, the +conditional expectation, given the stopped sigma-algebra, of the indicator of `{tau < ⊤}` times +`F` of the path shifted by `(tau omega).untopD 0` is the indicator of `{tau < ⊤}` times the +expectation of `F` under the process started from the state at that time. -/ +theorem IsFellerKernelSemigroup.continuousProcess_condExp_shift_stoppingTime_lt_top + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + (x : alpha) (tau : ContinuousPath alpha → WithTop NNReal) + (htau : IsStoppingTime (ContinuousPath.canonicalFiltration (alpha := alpha)) tau) + (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) + (C : Real) (hFC : ∀ eta, ‖F eta‖ ≤ C) : + ((continuousProcess P hP) x)[Set.indicator {omega | tau omega < ⊤} + (fun omega ↦ F (ContinuousPath.shift ((tau omega).untopD 0) omega))| + htau.measurableSpace] =ᵐ[(continuousProcess P hP) x] + Set.indicator {omega | tau omega < ⊤} + (fun omega ↦ ∫ eta, F eta ∂(continuousProcess P hP) (omega ((tau omega).untopD 0))) := by + have hkappa := condExp_indicator_ae_eq_integral_kernel_of_restrict_map + ((continuousProcess P hP) x) + (Kernel.comap (continuousProcess P hP) (fun omega ↦ omega ((tau omega).untopD 0)) + (ContinuousPath.measurable_eval_untopD_stoppingTime tau htau)) + (fun omega ↦ ContinuousPath.shift ((tau omega).untopD 0) omega) + (ContinuousPath.measurable_shift_untopD_stoppingTime tau htau) + htau.measurableSpace_le {omega | tau omega < ⊤} (measurableSet_stoppingTime_lt_top htau) + (fun A hA ↦ hFeller.continuousProcess_restrict_map_shift_stoppingTime_lt_top P hP hK x tau + htau A hA) + F hF ?_ C hFC + · simpa only [Kernel.comap_apply] using hkappa + · have hBase : StronglyMeasurable[htau.measurableSpace] + (fun omega ↦ ∫ eta, F eta ∂(continuousProcess P hP) (omega ((tau omega).untopD 0))) := + hF.integral_kernel.comp_measurable + (ContinuousPath.measurable_eval_untopD_stoppingTime_stopped tau htau) + simpa only [Kernel.comap_apply] using hBase + +end + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakContinuity.lean new file mode 100644 index 0000000000..050a84afc7 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakContinuity.lean @@ -0,0 +1,203 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity +import Mathlib.MeasureTheory.Measure.ProbabilityMeasure + +/-! +# Weak continuity of the path law in the starting point + +`Trajectory/StartingPointContinuity.lean` proves that cylinder expectations of the +continuous-path process depend continuously on the starting point. This file upgrades that to +*every* bounded continuous functional of the path, which is weak continuity of the path law +itself. + +The route needs no compactness theorem for measures. Fix a starting point `x0` and a compact +neighbourhood `K0` of it. Tightness (`Trajectory/PathTightness.lean`) produces one compact set of +paths carrying all but `eta` of the mass from every starting point of `K0`. On that compact set +Stone--Weierstrass replaces the given functional by a bounded cylinder functional, with a norm +bound that makes the discarded mass cheap (`Trajectory/CylinderAlgebra.lean`), and the cylinder +functional is already known to have continuous expectations. Three epsilons and a triangle +inequality finish the argument. + +Main results: + +* `IsFellerKernelSemigroup.continuous_integral_boundedCylinder`, continuity for cylinder + functionals; +* `IsFellerKernelSemigroup.continuous_integral_continuousProcess`, continuity for every bounded + continuous functional of the path; +* `IsConservative.pathLaw` and `IsFellerKernelSemigroup.continuous_pathLaw`, the same statement + read as continuity into the space of probability measures on path space with its topology of + convergence in distribution. + +Nothing here asserts relative compactness of a family of laws, and no convergence of a sequence +of semigroups is treated. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped BoundedContinuousFunction ENNReal NNReal + +namespace MarkovProcess + +section TruncationError + +variable {X : Type*} [TopologicalSpace X] [MeasurableSpace X] [OpensMeasurableSpace X] + +/-- Two bounded continuous functionals that agree to within `eps` on a measurable set have +integrals that agree to within `eps` plus the mass off that set times the sum of the norms. -/ +theorem abs_integral_sub_le_of_approx_on (mu : Measure X) [IsProbabilityMeasure mu] + (F G : X →ᵇ ℝ) {K : Set X} (hK : MeasurableSet K) {eps : ℝ} (heps : 0 ≤ eps) + (happrox : ∀ x ∈ K, |G x - F x| ≤ eps) : + |(∫ x, F x ∂mu) - ∫ x, G x ∂mu| ≤ eps + (‖F‖ + ‖G‖) * mu.real Kᶜ := by + have hF : Integrable (fun x ↦ F x) mu := F.integrable mu + have hG : Integrable (fun x ↦ G x) mu := G.integrable mu + have hKc : MeasurableSet Kᶜ := hK.compl + have hind : Integrable (Set.indicator Kᶜ (1 : X → ℝ)) mu := + (integrable_const (1 : ℝ)).indicator hKc + have hbound : ∀ x, ‖F x - G x‖ ≤ + eps + (‖F‖ + ‖G‖) * Set.indicator Kᶜ (1 : X → ℝ) x := by + intro x + by_cases hx : x ∈ K + · rw [Set.indicator_of_notMem (by simpa using hx), mul_zero, add_zero, Real.norm_eq_abs, + abs_sub_comm] + exact happrox x hx + · rw [Set.indicator_of_mem (by simpa using hx), Pi.one_apply, mul_one] + have h1 : ‖F x - G x‖ ≤ ‖F x‖ + ‖G x‖ := norm_sub_le _ _ + have h2 : ‖F x‖ ≤ ‖F‖ := F.norm_coe_le_norm x + have h3 : ‖G x‖ ≤ ‖G‖ := G.norm_coe_le_norm x + linarith + have hmaj : Integrable + (fun x ↦ eps + (‖F‖ + ‖G‖) * Set.indicator Kᶜ (1 : X → ℝ) x) mu := + (integrable_const eps).add (hind.const_mul _) + rw [← integral_sub hF hG, ← Real.norm_eq_abs] + refine (norm_integral_le_of_norm_le hmaj (Eventually.of_forall hbound)).trans_eq ?_ + rw [integral_add (integrable_const eps) (hind.const_mul _), integral_const, integral_const_mul, + integral_indicator_one hKc, probReal_univ, smul_eq_mul, one_mul] + +end TruncationError + +namespace SubMarkovKernelSemigroup + +noncomputable section + +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [Nonempty alpha] [ProperSpace alpha] + +variable (P : SubMarkovKernelSemigroup alpha) (hP : P.IsConservative) + +/-- Expectations of a bounded cylinder functional depend continuously on the starting point. -/ +theorem IsFellerKernelSemigroup.continuous_integral_boundedCylinder + (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) + {G : ContinuousPath alpha → ℝ} (hG : ContinuousPath.IsBoundedCylinder G) : + Continuous fun x ↦ ∫ omega, G omega ∂(continuousProcess P hP x) := by + obtain ⟨I, g, hg⟩ := hG + simp only [hg] + exact hFeller.continuous_integral_finsetEvaluation_continuousProcess P hP hK I g + +/-- **Weak continuity of the path law in the starting point.** For a conservative Feller +semigroup on a proper metric state space satisfying the intrinsic Kolmogorov moment criterion, the +expectation of *every* bounded continuous functional of the path is a continuous function of the +starting point. + +This extends the cylinder-expectation continuity of +`continuous_integral_finsetEvaluation_continuousProcess` to all of path space. The proof is the +direct one: tightness over a compact neighbourhood of the reference point produces a compact set +of paths carrying all but a prescribed mass, Stone--Weierstrass replaces the functional by a +bounded cylinder functional on that compact set, and the cylinder case is already known. No +compactness theorem for measures is used. -/ +theorem IsFellerKernelSemigroup.continuous_integral_continuousProcess + (hFeller : P.IsFellerKernelSemigroup) {p q : ℝ} {M : ℝ≥0} + (hmom : P.HasKolmogorovMoments p q M) (F : ContinuousPath alpha →ᵇ ℝ) : + Continuous fun x ↦ ∫ omega, F omega ∂(continuousProcess P hP x) := by + have hKreg := KolmogorovRegular.of_hasKolmogorovMoments P hP hmom + refine continuous_iff_continuousAt.mpr fun x0 ↦ Metric.tendsto_nhds.mpr fun eps heps ↦ ?_ + set eps5 : ℝ := eps / 5 with heps5def + have heps5 : 0 < eps5 := by positivity + set Ctot : ℝ := ‖F‖ + (‖F‖ + eps5) with hCtotdef + have hCtotpos : 0 < Ctot := by + rw [hCtotdef] + have := norm_nonneg F + linarith + set eta : ℝ := eps5 / Ctot with hetadef + have hetapos : 0 < eta := div_pos heps5 hCtotpos + obtain ⟨K0, hK0compact, hK0nhds⟩ := exists_compact_mem_nhds x0 + obtain ⟨Kp, hKpcompact, hKpmass⟩ := + IsConservative.exists_isCompact_measure_compl_le P hP hmom hK0compact + (eps := ENNReal.ofReal eta) (ENNReal.ofReal_pos.mpr hetapos) + obtain ⟨G, hGcyl, hGnorm, hGapprox⟩ := + ContinuousPath.exists_boundedCylinder_approx F hKpcompact heps5 + have hKpmeas : MeasurableSet Kp := hKpcompact.isClosed.measurableSet + have herror : ∀ x ∈ K0, |(∫ omega, F omega ∂(continuousProcess P hP x)) - + ∫ omega, G omega ∂(continuousProcess P hP x)| ≤ 2 * eps5 := by + intro x hx + have hmass : (continuousProcess P hP x).real Kpᶜ ≤ eta := by + rw [measureReal_def] + exact ENNReal.toReal_le_of_le_ofReal hetapos.le (hKpmass x hx) + have hbase := abs_integral_sub_le_of_approx_on (continuousProcess P hP x) F G hKpmeas + heps5.le hGapprox + have hFG : ‖F‖ + ‖G‖ ≤ Ctot := by + rw [hCtotdef] + linarith [hGnorm] + have hprod : (‖F‖ + ‖G‖) * (continuousProcess P hP x).real Kpᶜ ≤ eps5 := by + calc (‖F‖ + ‖G‖) * (continuousProcess P hP x).real Kpᶜ ≤ Ctot * eta := + mul_le_mul hFG hmass measureReal_nonneg hCtotpos.le + _ = eps5 := by + rw [hetadef] + field_simp + linarith [hbase, hprod] + have hcylinder := + IsFellerKernelSemigroup.continuous_integral_boundedCylinder P hP hFeller hKreg hGcyl + have hnear : ∀ᶠ x in nhds x0, |(∫ omega, G omega ∂(continuousProcess P hP x)) - + ∫ omega, G omega ∂(continuousProcess P hP x0)| < eps5 := by + have h := Metric.tendsto_nhds.mp (hcylinder.continuousAt (x := x0)) eps5 heps5 + simpa only [Real.dist_eq] using h + filter_upwards [hnear, hK0nhds] with x hxnear hxK0 + rw [Real.dist_eq] + have h1 := herror x hxK0 + have h2 := herror x0 (mem_of_mem_nhds hK0nhds) + have h2' : |(∫ omega, G omega ∂(continuousProcess P hP x0)) - + ∫ omega, F omega ∂(continuousProcess P hP x0)| ≤ 2 * eps5 := by + rw [abs_sub_comm] + exact h2 + have htri1 := abs_sub_le (∫ omega, F omega ∂(continuousProcess P hP x)) + (∫ omega, G omega ∂(continuousProcess P hP x)) + (∫ omega, F omega ∂(continuousProcess P hP x0)) + have htri2 := abs_sub_le (∫ omega, G omega ∂(continuousProcess P hP x)) + (∫ omega, G omega ∂(continuousProcess P hP x0)) + (∫ omega, F omega ∂(continuousProcess P hP x0)) + rw [heps5def] at h1 h2' hxnear + linarith [htri1, htri2, h1, h2', hxnear] + +/-- The law of the continuous-path process, read as a probability measure on path space. -/ +def IsConservative.pathLaw (x : alpha) : ProbabilityMeasure (ContinuousPath alpha) := + ⟨continuousProcess P hP x, inferInstance⟩ + +omit [ProperSpace alpha] in +@[simp] +theorem IsConservative.pathLaw_toMeasure (x : alpha) : + ((IsConservative.pathLaw P hP x : ProbabilityMeasure (ContinuousPath alpha)) : + Measure (ContinuousPath alpha)) = continuousProcess P hP x := + rfl + +/-- **The path law is weakly continuous in the starting point.** Read on the space of +probability measures on path space with its topology of convergence in distribution, the map +`x ↦ pathLaw P hP x` is continuous. -/ +theorem IsFellerKernelSemigroup.continuous_pathLaw + (hFeller : P.IsFellerKernelSemigroup) {p q : ℝ} {M : ℝ≥0} + (hmom : P.HasKolmogorovMoments p q M) : + Continuous (IsConservative.pathLaw P hP) := by + refine ProbabilityMeasure.continuous_iff_forall_continuous_integral.mpr fun F ↦ ?_ + exact IsFellerKernelSemigroup.continuous_integral_continuousProcess P hP hFeller hmom F + +end + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakConvergence.lean new file mode 100644 index 0000000000..61c2286484 --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakConvergence.lean @@ -0,0 +1,223 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity + +/-! +# Weak convergence of Feller processes on path space + +`Trajectory/Convergence.lean` proves that strong convergence of the `C₀` semigroups makes the +finite-dimensional distributions of the continuous-path processes converge. This file upgrades +that to convergence of the whole path laws, provided the approximating semigroups and the limit +semigroup satisfy **one common** intrinsic Kolmogorov moment bound `HasKolmogorovMoments p q M`. + +The common moment bound is what makes the family of path laws at a fixed starting point tight: +the scale in the modulus estimate of `Continuity/PathModulus.lean` depends only on the exponents, +the constant and the tolerances, never on the semigroup, so one compact set of paths carries all +but a prescribed mass of every law of the family at once. On that compact set Stone--Weierstrass +replaces a bounded continuous functional of the path by a bounded cylinder functional +(`Trajectory/CylinderAlgebra.lean`), whose expectations converge by the finite-dimensional +theorem. Three epsilons finish the argument; no compactness theorem for measures is used. + +Main results: + +* `isTightMeasureSet_insert_continuousProcess` and + `exists_isCompact_measure_compl_le_insert`, tightness of the family of path laws at a fixed + starting point; +* `tendsto_integral_continuousProcess`, convergence of the expectation of every bounded + continuous functional of the path; +* `tendsto_pathLaw`, the same statement read in the space of probability measures on path space + with its topology of convergence in distribution, and + `tendsto_pathLaw_of_tendsto_resolvent`, its form starting from the resolvents. + +The state space is assumed proper, as in `Trajectory/PathTightness.lean`, and the moment bound is +assumed with the same exponents and constant for every member of the family; nothing is asserted +when the constants are allowed to vary, nor for a family whose limit is not itself the process of +a Feller semigroup. +-/ + +open Filter MeasureTheory ProbabilityTheory Topology +open scoped BoundedContinuousFunction ENNReal NNReal ZeroAtInfty + +namespace MarkovProcess + + +namespace SubMarkovKernelSemigroup + +noncomputable section + +open IsConservative + +variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] + [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] + [Nonempty alpha] [ProperSpace alpha] +variable {iota : Type*} {l : Filter iota} +variable {P : iota → SubMarkovKernelSemigroup alpha} {Q : SubMarkovKernelSemigroup alpha} + +/-- **Tightness of the path laws of a family of semigroups at a fixed starting point.** One +common intrinsic Kolmogorov moment bound gives one modulus of continuity for the whole family, so +the family of path laws from a fixed starting point, together with the law of the limit +semigroup, is tight on path space. -/ +theorem isTightMeasureSet_insert_continuousProcess + (hPc : ∀ i, (P i).IsConservative) (hQc : Q.IsConservative) {p q : ℝ} {M : ℝ≥0} + (hPmom : ∀ i, (P i).HasKolmogorovMoments p q M) (hQmom : Q.HasKolmogorovMoments p q M) + (x : alpha) : + IsTightMeasureSet (insert (continuousProcess Q hQc x) + (Set.range fun i ↦ continuousProcess (P i) (hPc i) x)) := by + refine ContinuousPath.isTightMeasureSet_of_measure_compl_modulusSet_le + (isCompact_singleton (x := x)) ?_ ?_ + · rintro mu (rfl | ⟨i, rfl⟩) + · exact IsConservative.measure_eval_zero_notMem_eq_zero Q hQc + (KolmogorovRegular.of_hasKolmogorovMoments Q hQc hQmom) + (measurableSet_singleton x) rfl + · exact IsConservative.measure_eval_zero_notMem_eq_zero (P i) (hPc i) + (KolmogorovRegular.of_hasKolmogorovMoments (P i) (hPc i) (hPmom i)) + (measurableSet_singleton x) rfl + · intro T r hr eps heps + obtain ⟨gamma, hgamma, hgammaq⟩ := hQmom.exists_holderExponent + obtain ⟨delta, hdelta, hmu⟩ := + ContinuousPath.exists_measure_compl_modulusSet_le (alpha := alpha) (M := M) + hQmom.p_pos hgamma hgammaq T hr heps + refine ⟨delta, hdelta, ?_⟩ + rintro mu (rfl | ⟨i, rfl⟩) + · exact hmu _ (IsConservative.isKolmogorovProcess_continuousProcess Q hQc hQmom + (KolmogorovRegular.of_hasKolmogorovMoments Q hQc hQmom) x) + · exact hmu _ (IsConservative.isKolmogorovProcess_continuousProcess (P i) (hPc i) (hPmom i) + (KolmogorovRegular.of_hasKolmogorovMoments (P i) (hPc i) (hPmom i)) x) + +/-- Epsilon form of tightness: one compact set of paths carries all but `eps` of every law of the +family and of the law of the limit semigroup. -/ +theorem exists_isCompact_measure_compl_le_insert + (hPc : ∀ i, (P i).IsConservative) (hQc : Q.IsConservative) {p q : ℝ} {M : ℝ≥0} + (hPmom : ∀ i, (P i).HasKolmogorovMoments p q M) (hQmom : Q.HasKolmogorovMoments p q M) + (x : alpha) {eps : ℝ≥0∞} (heps : 0 < eps) : + ∃ K : Set (ContinuousPath alpha), IsCompact K ∧ + (∀ i, continuousProcess (P i) (hPc i) x Kᶜ ≤ eps) ∧ + continuousProcess Q hQc x Kᶜ ≤ eps := by + obtain ⟨K, hKcompact, hKmass⟩ := + isTightMeasureSet_iff_exists_isCompact_measure_compl_le.mp + (isTightMeasureSet_insert_continuousProcess hPc hQc hPmom hQmom x) eps heps + exact ⟨K, hKcompact, fun i ↦ hKmass _ (Set.mem_insert_of_mem _ ⟨i, rfl⟩), + hKmass _ (Set.mem_insert _ _)⟩ + +/-- **Weak convergence of Feller processes on path space.** Let `P i` be conservative Feller +kernel semigroups with one common intrinsic Kolmogorov moment bound, and let `Q` be one more such +semigroup. If the `C₀` semigroups converge strongly, then from every starting point the +expectation of every bounded continuous functional of the path converges. + +The proof combines the tightness of the family at that starting point with the cylinder +approximation on a compact set of paths and the convergence of the finite-dimensional +distributions; no compactness theorem for measures is used. -/ +theorem tendsto_integral_continuousProcess + (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hPc : ∀ i, (P i).IsConservative) + (hQ : Q.IsFellerKernelSemigroup) (hQc : Q.IsConservative) {p q : ℝ} {M : ℝ≥0} + (hPmom : ∀ i, (P i).HasKolmogorovMoments p q M) (hQmom : Q.HasKolmogorovMoments p q M) + (hconv : ∀ (t : NNReal) (f : C₀(alpha, ℝ)), + Tendsto (fun i ↦ (hP i).c0Semigroup t f) l (nhds (hQ.c0Semigroup t f))) + (F : ContinuousPath alpha →ᵇ ℝ) (x : alpha) : + Tendsto (fun i ↦ ∫ omega, F omega ∂(continuousProcess (P i) (hPc i) x)) l + (nhds (∫ omega, F omega ∂(continuousProcess Q hQc x))) := by + rw [Metric.tendsto_nhds] + intro eps heps + set eps5 : ℝ := eps / 5 with heps5def + have heps5 : 0 < eps5 := by positivity + set Ctot : ℝ := ‖F‖ + (‖F‖ + eps5) with hCtotdef + have hCtotpos : 0 < Ctot := by + rw [hCtotdef] + have := norm_nonneg F + linarith + set eta : ℝ := eps5 / Ctot with hetadef + have hetapos : 0 < eta := div_pos heps5 hCtotpos + obtain ⟨Kp, hKpcompact, hKmassP, hKmassQ⟩ := + exists_isCompact_measure_compl_le_insert hPc hQc hPmom hQmom x + (eps := ENNReal.ofReal eta) (ENNReal.ofReal_pos.mpr hetapos) + obtain ⟨G, hGcyl, hGnorm, hGapprox⟩ := + ContinuousPath.exists_boundedCylinder_approx F hKpcompact heps5 + have hKpmeas : MeasurableSet Kp := hKpcompact.isClosed.measurableSet + have herror : ∀ mu : Measure (ContinuousPath alpha), ∀ _ : IsProbabilityMeasure mu, + mu Kpᶜ ≤ ENNReal.ofReal eta → + |(∫ omega, F omega ∂mu) - ∫ omega, G omega ∂mu| ≤ 2 * eps5 := by + intro mu hmuprob hmass + have hmassreal : mu.real Kpᶜ ≤ eta := by + rw [measureReal_def] + exact ENNReal.toReal_le_of_le_ofReal hetapos.le hmass + have hbase := abs_integral_sub_le_of_approx_on mu F G hKpmeas heps5.le hGapprox + have hFG : ‖F‖ + ‖G‖ ≤ Ctot := by + rw [hCtotdef] + linarith [hGnorm] + have hprod : (‖F‖ + ‖G‖) * mu.real Kpᶜ ≤ eps5 := by + calc (‖F‖ + ‖G‖) * mu.real Kpᶜ ≤ Ctot * eta := + mul_le_mul hFG hmassreal measureReal_nonneg hCtotpos.le + _ = eps5 := by + rw [hetadef] + field_simp + linarith [hbase, hprod] + obtain ⟨I, g, hg⟩ := hGcyl + have hcyl : Tendsto (fun i ↦ ∫ omega, G omega ∂(continuousProcess (P i) (hPc i) x)) l + (nhds (∫ omega, G omega ∂(continuousProcess Q hQc x))) := by + simp only [hg] + exact tendsto_integral_finsetEvaluation_continuousProcess hP hPc + (fun i ↦ KolmogorovRegular.of_hasKolmogorovMoments (P i) (hPc i) (hPmom i)) hQ hQc + (KolmogorovRegular.of_hasKolmogorovMoments Q hQc hQmom) hconv I g x + have hnear : ∀ᶠ i in l, |(∫ omega, G omega ∂(continuousProcess (P i) (hPc i) x)) - + ∫ omega, G omega ∂(continuousProcess Q hQc x)| < eps5 := by + have h := Metric.tendsto_nhds.mp hcyl eps5 heps5 + simpa only [Real.dist_eq] using h + filter_upwards [hnear] with i hinear + rw [Real.dist_eq] + have h1 := herror (continuousProcess (P i) (hPc i) x) inferInstance (hKmassP i) + have h2 := herror (continuousProcess Q hQc x) inferInstance hKmassQ + have h2' : |(∫ omega, G omega ∂(continuousProcess Q hQc x)) - + ∫ omega, F omega ∂(continuousProcess Q hQc x)| ≤ 2 * eps5 := by + rw [abs_sub_comm] + exact h2 + have htri1 := abs_sub_le (∫ omega, F omega ∂(continuousProcess (P i) (hPc i) x)) + (∫ omega, G omega ∂(continuousProcess (P i) (hPc i) x)) + (∫ omega, F omega ∂(continuousProcess Q hQc x)) + have htri2 := abs_sub_le (∫ omega, G omega ∂(continuousProcess (P i) (hPc i) x)) + (∫ omega, G omega ∂(continuousProcess Q hQc x)) + (∫ omega, F omega ∂(continuousProcess Q hQc x)) + rw [heps5def] at h1 h2' hinear + linarith [htri1, htri2, h1, h2', hinear] + +/-- **The path laws converge in distribution.** Read in the space of probability measures on path +space with its topology of convergence in distribution, the laws of the approximating processes +converge to the law of the limit process, from every starting point. -/ +theorem tendsto_pathLaw + (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hPc : ∀ i, (P i).IsConservative) + (hQ : Q.IsFellerKernelSemigroup) (hQc : Q.IsConservative) {p q : ℝ} {M : ℝ≥0} + (hPmom : ∀ i, (P i).HasKolmogorovMoments p q M) (hQmom : Q.HasKolmogorovMoments p q M) + (hconv : ∀ (t : NNReal) (f : C₀(alpha, ℝ)), + Tendsto (fun i ↦ (hP i).c0Semigroup t f) l (nhds (hQ.c0Semigroup t f))) + (x : alpha) : + Tendsto (fun i ↦ IsConservative.pathLaw (P i) (hPc i) x) l + (nhds (IsConservative.pathLaw Q hQc x)) := by + refine ProbabilityMeasure.tendsto_iff_forall_integral_tendsto.mpr fun F ↦ ?_ + simpa only [IsConservative.pathLaw_toMeasure] using + tendsto_integral_continuousProcess hP hPc hQ hQc hPmom hQmom hconv F x + +/-- **Weak convergence on path space from convergence of the resolvents.** Combining the +Trotter--Kato theorem with the previous statement: strong convergence of the `C₀` resolvents at +one positive shift already forces the path laws to converge in distribution. -/ +theorem tendsto_pathLaw_of_tendsto_resolvent + (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hPc : ∀ i, (P i).IsConservative) + (hQ : Q.IsFellerKernelSemigroup) (hQc : Q.IsConservative) {p q : ℝ} {M : ℝ≥0} + (hPmom : ∀ i, (P i).HasKolmogorovMoments p q M) (hQmom : Q.HasKolmogorovMoments p q M) + {mu : Semigroup.PositiveShift} + (hres : ∀ f : C₀(alpha, ℝ), Tendsto (fun i ↦ (hP i).c0Semigroup.resolvent mu f) l + (nhds (hQ.c0Semigroup.resolvent mu f))) (x : alpha) : + Tendsto (fun i ↦ IsConservative.pathLaw (P i) (hPc i) x) l + (nhds (IsConservative.pathLaw Q hQc x)) := by + refine tendsto_pathLaw hP hPc hQ hQc hPmom hQmom (fun t f ↦ ?_) x + exact Semigroup.StronglyContinuousContractionSemigroup.tendsto_operator_of_tendsto_resolvent + hres f t + +end + +end SubMarkovKernelSemigroup + +end MarkovProcess diff --git a/LeanPool/projects.yml b/LeanPool/projects.yml index 95e0c8ad83..c494ca66cb 100644 --- a/LeanPool/projects.yml +++ b/LeanPool/projects.yml @@ -9966,3 +9966,36 @@ projects: msc: - '90C35' - '05C21' + - slug: markovprocess + title: MarkovProcess + summary: A Lean formalization of continuous-path Markov processes associated with conservative + Feller transition semigroups on nonempty locally compact Polish spaces. A uniform Kolmogorov + displacement-moment bound yields a unique measurable kernel from each starting point to + continuous-path space, with the prescribed finite-dimensional distributions. The library + also develops strong Markov properties, generators and resolvents, stopping and killing, + and Brownian motion as an example. The existence and uniqueness theorem is independently + checked using Audit/ContinuousMarkovProcess/comparator.json. + branch: probability + entry_module: LeanPool.MarkovProcess + authors: + - Scott Armstrong + source: + url: https://github.com/scottnarmstrong/markovprocess + github_repo: scottnarmstrong/markovprocess + commit: dbade0d12c4f84179441a9df7d7147df7a8bcaa0 + license: Apache-2.0 + status: verified + main_declarations: + - MarkovProcess.SubMarkovKernelSemigroup.IsFellerKernelSemigroup.existsUnique_continuousProcess_of_hasKolmogorovMoments + main_results: + - declaration: MarkovProcess.SubMarkovKernelSemigroup.IsFellerKernelSemigroup.existsUnique_continuousProcess_of_hasKolmogorovMoments + informal: A conservative Feller transition semigroup on a nonempty locally compact Polish + space satisfying the Kolmogorov moment criterion determines a unique continuous-path + Markov kernel with its prescribed finite-dimensional distributions. + tags: + - probability + msc: + - 60J25 + - 60J35 + - 60G17 + provenance: AI From 686694453b631706fb83040ac62f1b475a8b796a Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Mon, 21 Sep 2026 18:21:09 +0000 Subject: [PATCH 02/11] Advance markovprocess port to Lean 4.34 --- .../MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean index d5a87a9bca..4decc0549b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean @@ -7,7 +7,7 @@ import Mathlib.Data.NNRat.Defs import Mathlib.Data.NNReal.Defs import Mathlib.Data.Rat.Cast.Order import Mathlib.Data.Rat.Encodable -import Mathlib.Logic.Denumerable +import Mathlib.Basic.Denumerable import Mathlib.MeasureTheory.MeasurableSpace.Embedding /-! From 8cc92c5be233582b3af01cbdd094ffa4b26fb048 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Mon, 21 Sep 2026 19:23:42 +0000 Subject: [PATCH 03/11] Complete full source compatibility build for MarkovProcess --- .../Continuity/KolmogorovTimeShift.lean | 1 - .../DenseTime/CemeteryExtension.lean | 2 -- .../PhysicalCompactTestTransport.lean | 2 +- .../DenseTime/PrefixRecursion.lean | 2 +- .../MarkovProcess/DenseTime/Trajectory.lean | 2 +- .../Examples/BrownianMotion.lean | 16 +++++++------- .../MarkovProcess/Examples/HeatOnePoint.lean | 10 ++++----- .../Feller/BackwardC0Integral.lean | 2 +- .../MarkovProcess/Feller/Semigroup.lean | 3 +-- ...iteProductCompactSupportApproximation.lean | 2 +- .../FiniteProductCoordinateNormalForm.lean | 2 ++ .../FiniteProductStoneWeierstrass.lean | 4 ++-- .../FiniteSetKernelCompactTestTransport.lean | 2 +- .../MarkovProcess/FiniteTime/Kernel.lean | 1 - .../FiniteTime/KernelConcatenation.lean | 2 +- .../MarkovProcess/Kernel/Lp.lean | 12 +++++----- .../MarkovProcess/Kernel/LpFinite.lean | 22 +++++++++---------- .../MarkovProcess/Kernel/LpTop.lean | 12 +++++----- .../Kernel/OnePointExtension.lean | 2 +- .../Kernel/OperatorSemigroup.lean | 10 ++++----- .../Kernel/PositiveC0OperatorKernel.lean | 1 - .../MarkovProcess/Killed/Marginals.lean | 6 ++--- .../MarkovProcess/Killed/Nested.lean | 6 ++--- .../MarkovProcess/Killed/Process.lean | 2 +- .../MarkovProcess/Lifetime/Shift.lean | 1 - .../MarkovProcess/Parameterized/Annealed.lean | 2 +- .../Parameterized/DenseTimeTrajectory.lean | 12 +++++----- .../MarkovProcess/Path/Stopping.lean | 2 -- .../MarkovProcess/Semigroup/Basic.lean | 2 -- .../MarkovProcess/Semigroup/InvariantSet.lean | 2 +- .../MarkovProcess/Time/DenseTimeHistory.lean | 1 - .../Time/FiniteOrderedTimes.lean | 1 - .../MarkovProcess/Time/OrderedGrid.lean | 4 ++-- .../Trajectory/AllTimeFiniteMarginals.lean | 6 ++--- .../Trajectory/Equivariance.lean | 2 -- .../Trajectory/StoppingLtTop.lean | 2 +- 36 files changed, 76 insertions(+), 87 deletions(-) diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean index f5cc12d708..a0b015e99d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean @@ -58,7 +58,6 @@ noncomputable def shiftedUnitDyadicFloorValue (k : NNRat) (n : ℕ) (t : Set.Icc (0 : ℝ) 1) : NNRat := k + unitDyadicFloorValue n t -@[simp] theorem timeShift_unitDyadicFloorValue_apply (k : NNRat) (X : NNRat → Ω → E) (ω : Ω) (n : ℕ) (t : Set.Icc (0 : ℝ) 1) : diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryExtension.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryExtension.lean index 81d4a34638..8639061cc0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryExtension.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryExtension.lean @@ -112,7 +112,6 @@ theorem cemeteryExtension_alive_singleton_delta (κ : ProbabilityTheory.Kernel rw [hpre, measure_empty] simp only [Set.indicator_of_mem, Set.mem_singleton_iff, Pi.one_apply, mul_one, zero_add] -@[simp] theorem cemeteryExtension_delta_apply' (κ : ProbabilityTheory.Kernel α α) {s : Set (Cemetery α)} (hs : MeasurableSet s) : cemeteryExtension κ Cemetery.delta s = s.indicator 1 Cemetery.delta := by @@ -126,7 +125,6 @@ theorem cemeteryExtension_alive_univ (κ : ProbabilityTheory.Kernel α α) rw [add_comm] exact tsub_add_cancel_of_le (hκ x) -@[simp] theorem cemeteryExtension_delta_univ (κ : ProbabilityTheory.Kernel α α) : cemeteryExtension κ Cemetery.delta Set.univ = 1 := by rw [cemeteryExtension_delta_apply' κ MeasurableSet.univ] diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean index 14d24457ff..f1af188b6f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean @@ -98,7 +98,7 @@ theorem pullbackPhysicalSetHomeomorph_apply /-- Pull a compactly supported test on dense-time labels back to physical-time labels. -/ noncomputable def pullbackPhysicalSetCompactTest - {alpha : Type*} [TopologicalSpace alpha] [T2Space alpha] + {alpha : Type*} [TopologicalSpace alpha] (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) : C_c(denseTimePhysicalSet J → alpha, ℝ) := f.comp (pullbackPhysicalSetHomeomorph J).toCocompactMap diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean index bedf7cb1d8..9f93e4ea8a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean @@ -20,7 +20,7 @@ namespace ProbabilityTheory.Kernel private theorem step_transport {X H Z Y T : Type*} [MeasurableSpace X] [MeasurableSpace H] [MeasurableSpace Z] [MeasurableSpace Y] [MeasurableSpace T] - (κ : Kernel X Z) [IsSFiniteKernel κ] + (κ : Kernel X Z) (η : Kernel Z Y) [IsSFiniteKernel η] (E : H ≃ᵐ Z) (g : H × Y → T) (hg : Measurable g) (q : Z × Y → T) (hcompat : g ∘ Prod.map E.symm id = q) : diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean index 538474db76..1ef29f313c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean @@ -151,7 +151,7 @@ private theorem denseTimeHistoryMeasurableEquiv_rawTrajAppend (n : ℕ) : private theorem transport_traj_step {X H Z Y T : Type*} [MeasurableSpace X] [MeasurableSpace H] [MeasurableSpace Z] [MeasurableSpace Y] [MeasurableSpace T] - (κ : Kernel X Z) [IsSFiniteKernel κ] + (κ : Kernel X Z) (η : Kernel Z Y) [IsSFiniteKernel η] (E : H ≃ᵐ Z) (g : H × Y → T) (hg : Measurable g) (q : Z × Y → T) (hcompat : g ∘ Prod.map E.symm id = q) : diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean index ae4347070d..201dbc626a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean @@ -62,8 +62,8 @@ private theorem map_prodMk_eq_compProd_of_restrict_map (mu.restrict (X ⁻¹' C)).map Y = kappa.comap X hX ∘ₘ (mu.restrict (X ⁻¹' C))) : mu.map (fun omega ↦ (X omega, Y omega)) = (mu.map X) ⊗ₘ kappa := by have : IsProbabilityMeasure (mu.map (fun omega ↦ (X omega, Y omega))) := - Measure.isProbabilityMeasure_map (hX.prodMk hY).aemeasurable - have : IsProbabilityMeasure (mu.map X) := Measure.isProbabilityMeasure_map hX.aemeasurable + inferInstance + have : IsProbabilityMeasure (mu.map X) := inferInstance refine MeasureTheory.ext_of_generate_finite _ generateFrom_prod.symm isPiSystem_prod ?_ ?_ · rintro _ ⟨C, hC, B, hB, rfl⟩ @@ -141,7 +141,7 @@ theorem incrementsMap_eq_cons {n : ℕ} (x : ℝ) (path : Fin (n + 1) → ℝ) : theorem measurable_incrementsMap {n : ℕ} : Measurable (fun p : ℝ × (Fin n → ℝ) ↦ incrementsMap p.1 p.2) := by cases n with - | zero => exact measurable_pi_lambda _ fun i ↦ i.elim0 + | zero => exact Measurable.of_eval fun i ↦ i.elim0 | succ n => simp_rw [incrementsMap_eq_cons] refine measurable_pi_iff.mpr fun i ↦ ?_ @@ -189,7 +189,7 @@ theorem timeIncrements_succ_apply : ∀ {n : ℕ} {s : Fin (n + 1) → NNReal}, theorem measurable_incrementsMap_eval {n : ℕ} (s : Fin n → NNReal) (x : ℝ) : Measurable (fun omega : ContinuousPath ℝ ↦ incrementsMap x (fun i ↦ omega (s i))) := measurable_incrementsMap.comp (measurable_const.prodMk - (measurable_pi_lambda _ fun i ↦ ContinuousPath.measurable_coordinateProcess (s i))) + (Measurable.of_eval fun i ↦ ContinuousPath.measurable_coordinateProcess (s i))) /-- **The joint law of the increments of Brownian motion is a product of centred Gaussians.** Reading the path of `brownianMotion x` at a monotone family of times and taking the increments, @@ -204,7 +204,7 @@ theorem brownianMotion_map_incrementsMap : ∀ {n : ℕ} {s : Fin n → NNReal}, intro s _ x have : IsProbabilityMeasure ((brownianMotion x).map (fun omega ↦ incrementsMap x (fun i ↦ omega (s i)))) := - Measure.isProbabilityMeasure_map (measurable_incrementsMap_eval s x).aemeasurable + inferInstance exact (Measure.pi_eq fun A _ ↦ by simp).symm | succ n ih => intro s hs x @@ -215,7 +215,7 @@ theorem brownianMotion_map_incrementsMap : ∀ {n : ℕ} {s : Fin n → NNReal}, (incrementsMap p.1 (fun i : Fin n ↦ p.2 (s i.succ - s 0)))) := by refine measurable_finCons.comp ((measurable_fst.sub measurable_const).prodMk ?_) exact measurable_incrementsMap.comp (measurable_fst.prodMk - (measurable_pi_lambda _ fun i ↦ + (Measurable.of_eval fun i ↦ (ContinuousPath.measurable_coordinateProcess (s i.succ - s 0)).comp measurable_snd)) have hpair : Measurable (fun omega : ContinuousPath ℝ ↦ (omega (s 0), ContinuousPath.shift (s 0) omega)) := @@ -301,7 +301,7 @@ section IndependentIncrements /-- Dropping the first coordinate of a finite coordinate path is measurable. -/ theorem measurable_finTail {n : ℕ} : Measurable (Fin.tail : (Fin (n + 1) → ℝ) → (Fin n → ℝ)) := - measurable_pi_lambda _ fun i ↦ measurable_pi_apply i.succ + Measurable.of_eval fun i ↦ measurable_pi_apply i.succ /-- Dropping the first coordinate of a product of probability measures gives the product of the remaining ones. -/ @@ -346,7 +346,7 @@ theorem brownianMotion_map_increment (x : ℝ) (a b : NNReal) (hab : a ≤ b) : have h := brownianMotion_map_increments (n := 1) (t := ![a, b]) ht x have hmeas : Measurable (fun (omega : ContinuousPath ℝ) (i : Fin 1) ↦ omega ((![a, b] : Fin 2 → NNReal) i.succ) - omega ((![a, b] : Fin 2 → NNReal) i.castSucc)) := - measurable_pi_lambda _ fun i ↦ + Measurable.of_eval fun i ↦ (ContinuousPath.measurable_coordinateProcess _).sub (ContinuousPath.measurable_coordinateProcess _) have hproj := congrArg (fun mu : Measure (Fin 1 → ℝ) ↦ mu.map (Function.eval (0 : Fin 1))) h diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean index 346fef9f1c..b270620858 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean @@ -19,7 +19,7 @@ the local Kolmogorov criterion on the compactification (`hasLocalKolmogorovMoments_onePointKernelSemigroup_heatResolvent`). This assembles the regularity data from which the continuous-path process of the compactified -heat semigroup is formed (`onePointRegular_heatResolvent`), the witness that those data are +heat semigroup is formed (`onePointRegularHeatResolvent`), the witness that those data are available for a genuine example. Because the heat semigroup is conservative, the compactified process started at a live point almost surely never reaches the added point (`ae_exitTime_eq_top_heatResolvent`). @@ -136,7 +136,7 @@ end Moments /-- **The regularity data of the compactified heat process**: the exhaustion `1 / (1 + |x|)` and the Kolmogorov regularity which its metric gives the compactified heat semigroup. -/ -def onePointRegular_heatResolvent : heatResolvent.OnePointRegular where +def onePointRegularHeatResolvent : heatResolvent.OnePointRegular where rho := heatExhaustion continuous_rho := continuous_heatExhaustion rho_pos := heatExhaustion_pos @@ -156,13 +156,13 @@ def onePointRegular_heatResolvent : heatResolvent.OnePointRegular where semigroup is conservative, so the shift times its kernel resolvent of the constant observable one is one, which is the criterion for no escape. -/ theorem ae_exitTime_eq_top_heatResolvent (x : ℝ) : - letI := onePointRegular_heatResolvent.metricSpace - letI := onePointRegular_heatResolvent.completeSpace + letI := onePointRegularHeatResolvent.metricSpace + letI := onePointRegularHeatResolvent.completeSpace ∀ᵐ omega ∂SubMarkovKernelSemigroup.IsConservative.continuousProcess heatResolvent.onePointKernelSemigroup heatResolvent.isConservative_onePointKernelSemigroup (x : OnePoint ℝ), ContinuousPath.exitTime (Set.range ((↑) : ℝ → OnePoint ℝ)) omega = ⊤ := - onePointRegular_heatResolvent.ae_exitTime_eq_top one_pos x (by + onePointRegularHeatResolvent.ae_exitTime_eq_top one_pos x (by rw [kernelSemigroup_heatResolvent] exact isConservative_heatSemigroup.ofReal_mul_kernelResolvent_one one_pos x) diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean index bc6b4b0357..5403d30d65 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean @@ -39,7 +39,7 @@ private theorem integrable_coordinateProduct ((measurable_pi_apply i).comp heval)).stronglyMeasurable).aestronglyMeasurable · filter_upwards [] with omega rw [norm_prod] - apply Finset.prod_le_prod (fun _ _ ↦ norm_nonneg _) + apply Finset.prod_le_prod₀ (fun _ _ ↦ norm_nonneg _) intro i _ simpa only [ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] using! (factors i).toBCF.norm_coe_le_norm (eval omega i) diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean index 517609ee93..52dc57dfd6 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean @@ -33,7 +33,7 @@ def HasContinuousC0Orbits (P : SubMarkovKernelSemigroup α) (hC0 : P.MapsC0) : P Feller-semigroup properties when it maps `C₀` into itself and its resulting `C₀` operator orbits are continuous in time. Conservativity is not part of this predicate. -/ def IsFellerKernelSemigroup (P : SubMarkovKernelSemigroup α) - [LocallyCompactSpace α] [T2Space α] : Prop := + : Prop := ∃ hC0 : P.MapsC0, P.HasContinuousC0Orbits hC0 variable (P : SubMarkovKernelSemigroup α) (hC0 : P.MapsC0) @@ -52,7 +52,6 @@ theorem c0Semigroup_operator (hTime : P.HasContinuousC0Orbits hC0) (t : NNReal) (P.c0Semigroup hC0 hTime) t = P.c0Operator hC0 t := rfl -@[simp] theorem c0Semigroup_apply (hTime : P.HasContinuousC0Orbits hC0) (t : NNReal) (f : C₀(α, ℝ)) : (P.c0Semigroup hC0 hTime) t f = P.c0KernelIntegral hC0 t f := diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean index 6d6ee7b88c..ff2897c545 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean @@ -96,7 +96,7 @@ theorem exists_coordinateC0Subalgebra_near_compactlySupported have hq_le_one : q x ≤ 1 := by dsimp only [q] simp only [ContinuousMap.prod_apply, coordinate_apply] - exact Finset.prod_le_one (fun i _ ↦ (hφrange i (x i)).1) + exact Finset.prod_le_one₀ (fun i _ ↦ (hφrange i (x i)).1) (fun i _ ↦ (hφrange i (x i)).2) have hqf : q x * f x = f x := by by_cases hxsupport : x ∈ tsupport f diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean index 7abe6bda00..7263b7ce52 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean @@ -23,7 +23,9 @@ variable {I α : Type*} [TopologicalSpace α] /-- A scalar coefficient together with a finite ordered list of one-coordinate `C₀` factors. -/ structure CoordinateProductTerm (I α : Type*) [TopologicalSpace α] where + /-- The scalar multiplier of the coordinate product. -/ coefficient : ℝ + /-- The coordinate indices and compactly supported factors, in product order. -/ factors : List (I × C₀(α, ℝ)) /-- The continuous function represented by one coordinate-product term. -/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductStoneWeierstrass.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductStoneWeierstrass.lean index 4696aa589a..4739a46151 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductStoneWeierstrass.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductStoneWeierstrass.lean @@ -115,14 +115,14 @@ theorem exists_coordinateC0Subalgebra_near_on_isCompact /-- Finite algebraic combinations of one-coordinate continuous functions are uniformly dense in the continuous real functions on a compact finite product. -/ theorem coordinateSubalgebra_topologicalClosure_eq_top - [Fintype I] [T35Space α] [CompactSpace α] : + [T35Space α] [CompactSpace α] : (coordinateSubalgebra (I := I) (α := α)).topologicalClosure = ⊤ := ContinuousMap.subalgebra_topologicalClosure_eq_top_of_separatesPoints _ coordinateSubalgebra_separatesPoints /-- Epsilon form of finite-product test-function density. -/ theorem exists_coordinateSubalgebra_near - [Fintype I] [T35Space α] [CompactSpace α] + [T35Space α] [CompactSpace α] (f : C(I → α, ℝ)) {epsilon : ℝ} (hepsilon : 0 < epsilon) : ∃ g : coordinateSubalgebra (I := I) (α := α), ‖(g : C(I → α, ℝ)) - f‖ < epsilon := diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean index 098d462d36..91b20d6091 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean @@ -99,7 +99,7 @@ theorem orderedPathToFiniteSetHomeomorph_apply /-- Pull a compactly supported test on finite-set coordinates back to increasing coordinates. -/ noncomputable def pullbackFiniteSetCompactTest - {alpha : Type*} [TopologicalSpace alpha] [T2Space alpha] + {alpha : Type*} [TopologicalSpace alpha] (I : Finset NNReal) (f : C_c(I → alpha, ℝ)) : C_c(Fin I.card → alpha, ℝ) := f.comp (orderedPathToFiniteSetHomeomorph I).toCocompactMap diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/Kernel.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/Kernel.lean index 469a235ead..8090e9566a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/Kernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/Kernel.lean @@ -99,7 +99,6 @@ theorem IsConservative.isProbabilityMeasure_finiteTimeLaw /-- The unique coordinate of a singleton finite-time kernel has transition kernel `P` at that time. -/ -@[simp] theorem finiteTimeKernel_one_map_eval (P : SubMarkovKernelSemigroup α) (times : FiniteOrderedTimes 1) : (finiteTimeKernel P times).map (fun path ↦ path 0) = P (times 0) := by diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean index af168de7b0..b4167ef252 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean @@ -220,7 +220,7 @@ private theorem map_compProd_prodMkLeft_right private theorem compProd_prodMkLeft_assoc {X A B C : Type*} [MeasurableSpace X] [MeasurableSpace A] [MeasurableSpace B] [MeasurableSpace C] - (kappa : Kernel X A) [IsSFiniteKernel kappa] + (kappa : Kernel X A) (eta : Kernel A B) [IsSFiniteKernel eta] (xi : Kernel (A × B) C) [IsSFiniteKernel xi] : (kappa ⊗ₖ Kernel.prodMkLeft X (eta ⊗ₖ xi)).map diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean index ba7bebd656..db3ff1bdaf 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean @@ -31,7 +31,7 @@ and burns a failing search for `SeminormedAddCommGroup (α →ₘ[μ] ℝ)`. -/ private noncomputable instance cacheSeminormedLp (p : ℝ≥0∞) [Fact (1 ≤ p)] (μ : Measure α) : SeminormedAddCommGroup (Lp ℝ p μ) := inferInstance -private noncomputable instance cacheAddCommMonoidLp (p : ℝ≥0∞) [Fact (1 ≤ p)] +private noncomputable instance cacheAddCommMonoidLp (p : ℝ≥0∞) (μ : Measure α) : AddCommMonoid (Lp ℝ p μ) := inferInstance private noncomputable instance cacheModuleLp (p : ℝ≥0∞) [Fact (1 ≤ p)] @@ -45,15 +45,15 @@ private theorem ae_integrable_kernel_finite {μ : Measure α} {κ : Kernel α α (hp : 1 ≤ p) (f : Lp ℝ (p : ℝ≥0∞) μ) : ∀ᵐ x ∂μ, Integrable f (κ x) := by let : IsFiniteKernel κ := hκ.isFiniteKernel have hfComp : MemLp f p (κ ∘ₘ μ) := (Lp.memLp f).mono_measure hκμ - have hFiberEq := Measure.ae_ae_of_ae_comp hfComp.1.ae_eq_mk + have hFiberEq := Measure.ae_ae_of_ae_comp hfComp.aestronglyMeasurable.ae_eq_mk have hp0 : (p : ℝ≥0∞) ≠ 0 := by exact_mod_cast ne_of_gt (zero_lt_one.trans_le hp) have hpowInt := hfComp.integrable_norm_rpow hp0 ENNReal.coe_ne_top have hFiberInt := Measure.ae_integrable_of_integrable_comp hpowInt filter_upwards [hFiberEq, hFiberInt] with x hxEq hxInt - have hxEq' : f =ᵐ[κ x] hfComp.1.mk f := hxEq + have hxEq' : f =ᵐ[κ x] hfComp.aestronglyMeasurable.mk f := hxEq have hxMeas : AEStronglyMeasurable f (κ x) := - hfComp.1.stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq'.symm + hfComp.aestronglyMeasurable.stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq'.symm have hxMemLp : MemLp f p (κ x) := (integrable_norm_rpow_iff hxMeas hp0 ENNReal.coe_ne_top).mp hxInt exact hxMemLp.integrable (by exact_mod_cast hp) @@ -62,8 +62,8 @@ private theorem ae_integrable_kernel_top {μ : Measure α} {κ : Kernel α α} (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) (f : Lp ℝ ∞ μ) : ∀ᵐ x ∂μ, Integrable f (κ x) := by have hCtop : eLpNormEssSup f μ ≠ ∞ := by - rw [← eLpNorm_exponent_top] - exact (Lp.memLp f).2.ne + rw [← eLpNorm_exponent_top (Lp.aestronglyMeasurable f)] + exact (Lp.memLp f).eLpNorm_lt_top.ne have hCcoe : ((eLpNormEssSup f μ).toNNReal : ℝ≥0∞) = eLpNormEssSup f μ := ENNReal.coe_toNNReal hCtop have hFiberEq : ∀ᵐ x ∂μ, f =ᵐ[κ x] (Lp.aestronglyMeasurable f).mk f := diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean index e027cc772c..ef62d067fd 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean @@ -26,7 +26,7 @@ variable {α : Type*} [MeasurableSpace α] /-- On a finite measure of mass at most one, the `L¹` seminorm is bounded by every finite `Lᵖ` seminorm with `p ≥ 1`. -/ theorem eLpNorm_one_le_of_measure_univ_le_one {ν : Measure α} {f : α → ℝ} - [IsFiniteMeasure ν] {p : NNReal} (hp : 1 ≤ p) (hν : ν Set.univ ≤ 1) + {p : NNReal} (hp : 1 ≤ p) (hν : ν Set.univ ≤ 1) (hf : AEStronglyMeasurable f ν) : eLpNorm f 1 ν ≤ eLpNorm f p ν := by have hcompare := eLpNorm_le_eLpNorm_mul_rpow_measure_univ @@ -57,12 +57,12 @@ theorem enorm_integral_rpow_le_lintegral_enorm_rpow have hnorm : ‖∫ y, f y ∂ν‖ₑ ≤ eLpNorm f p ν := by calc ‖∫ y, f y ∂ν‖ₑ ≤ ∫⁻ y, ‖f y‖ₑ ∂ν := enorm_integral_le_lintegral_enorm f - _ = eLpNorm f 1 ν := eLpNorm_one_eq_lintegral_enorm.symm - _ ≤ eLpNorm f p ν := eLpNorm_one_le_of_measure_univ_le_one hp hν hf.1 + _ = eLpNorm f 1 ν := (eLpNorm_one_eq_lintegral_enorm hf.aestronglyMeasurable).symm + _ ≤ eLpNorm f p ν := eLpNorm_one_le_of_measure_univ_le_one hp hν hf.aestronglyMeasurable calc ‖∫ y, f y ∂ν‖ₑ ^ (p : ℝ) ≤ eLpNorm f p ν ^ (p : ℝ) := by exact ENNReal.rpow_le_rpow hnorm (by positivity) - _ = ∫⁻ y, ‖f y‖ₑ ^ (p : ℝ) ∂ν := eLpNorm_nnreal_pow_eq_lintegral hp0 + _ = ∫⁻ y, ‖f y‖ₑ ^ (p : ℝ) ∂ν := eLpNorm_nnreal_pow_eq_lintegral hp0 hf.aestronglyMeasurable /-- The integrated fibrewise power estimate for a sub-Markov kernel. -/ theorem lintegral_enorm_kernelIntegral_rpow_le @@ -74,15 +74,15 @@ theorem lintegral_enorm_kernelIntegral_rpow_le let : IsFiniteKernel κ := hκ.isFiniteKernel have hfComp : MemLp f p (κ ∘ₘ μ) := hf.mono_measure hκμ have hfFiber : ∀ᵐ x ∂μ, MemLp f p (κ x) := by - have hFiberEq := Measure.ae_ae_of_ae_comp hfComp.1.ae_eq_mk + have hFiberEq := Measure.ae_ae_of_ae_comp hfComp.aestronglyMeasurable.ae_eq_mk have hp0 : (p : ℝ≥0∞) ≠ 0 := by exact_mod_cast ne_of_gt (zero_lt_one.trans_le hp) have hpowInt := hfComp.integrable_norm_rpow hp0 ENNReal.coe_ne_top have hFiberInt := Measure.ae_integrable_of_integrable_comp hpowInt filter_upwards [hFiberEq, hFiberInt] with x hxEq hxInt - have hxEq' : f =ᵐ[κ x] hfComp.1.mk f := hxEq + have hxEq' : f =ᵐ[κ x] hfComp.aestronglyMeasurable.mk f := hxEq have hxMeas : AEStronglyMeasurable f (κ x) := - hfComp.1.stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq'.symm + hfComp.aestronglyMeasurable.stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq'.symm exact (integrable_norm_rpow_iff hxMeas hp0 ENNReal.coe_ne_top).mp hxInt calc ∫⁻ x, ‖kernelIntegral κ f x‖ₑ ^ (p : ℝ) ∂μ @@ -93,7 +93,7 @@ theorem lintegral_enorm_kernelIntegral_rpow_le _ = ∫⁻ y, ‖f y‖ₑ ^ (p : ℝ) ∂(κ ∘ₘ μ) := by symm exact Measure.lintegral_bind (Kernel.aemeasurable κ) - (hfComp.1.enorm.pow_const (p : ℝ)) + (hfComp.aestronglyMeasurable.enorm.pow_const (p : ℝ)) _ ≤ ∫⁻ y, ‖f y‖ₑ ^ (p : ℝ) ∂μ := lintegral_mono' hκμ le_rfl @@ -105,7 +105,8 @@ theorem eLpNorm_kernelIntegral_le (hp : 1 ≤ p) (hf : MemLp f p μ) : eLpNorm (kernelIntegral κ f) p μ ≤ eLpNorm f p μ := by have hp0 : p ≠ 0 := ne_of_gt (zero_lt_one.trans_le hp) - rw [eLpNorm_nnreal_eq_lintegral hp0, eLpNorm_nnreal_eq_lintegral hp0] + rw [eLpNorm_nnreal_eq_lintegral hp0 (AEStronglyMeasurable.kernelIntegral hf.aestronglyMeasurable hκμ), + eLpNorm_nnreal_eq_lintegral hp0 hf.aestronglyMeasurable] apply ENNReal.rpow_le_rpow · exact lintegral_enorm_kernelIntegral_rpow_le hκ hκμ hp hf · positivity @@ -117,7 +118,6 @@ theorem MemLp.kernelIntegral (hκμ : κ ∘ₘ μ ≤ μ) {f : α → ℝ} {p : NNReal} (hp : 1 ≤ p) (hf : MemLp f p μ) : MemLp (kernelIntegral κ f) p μ := by - refine ⟨AEStronglyMeasurable.kernelIntegral hf.1 hκμ, ?_⟩ - exact (eLpNorm_kernelIntegral_le hκ hκμ hp hf).trans_lt hf.2 + exact (eLpNorm_kernelIntegral_le hκ hκμ hp hf).trans_lt hf.eLpNorm_lt_top end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpTop.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpTop.lean index 17765fbd34..3fd89c8768 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpTop.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpTop.lean @@ -53,9 +53,12 @@ theorem eLpNorm_kernelIntegral_top_le {μ : Measure α} {κ : ProbabilityTheory.Kernel α α} (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) (f : α → ℝ) : eLpNorm (kernelIntegral κ f) ∞ μ ≤ eLpNorm f ∞ μ := by - rw [eLpNorm_exponent_top, eLpNorm_exponent_top] - exact eLpNormEssSup_le_of_ae_enorm_bound - (enorm_kernelIntegral_ae_le_eLpNormEssSup hκ hκμ f) + by_cases hf : AEStronglyMeasurable f μ + · rw [eLpNorm_exponent_top (AEStronglyMeasurable.kernelIntegral hf hκμ), eLpNorm_exponent_top hf] + exact eLpNormEssSup_le_of_ae_enorm_bound + (enorm_kernelIntegral_ae_le_eLpNormEssSup hκ hκμ f) + · rw [eLpNorm_of_not_aestronglyMeasurable hf] + exact le_top /-- Integration against a sub-Markov kernel sends `L^∞` functions to `L^∞` functions under subinvariance. -/ @@ -63,7 +66,6 @@ theorem MemLp.kernelIntegral_top {μ : Measure α} {κ : ProbabilityTheory.Kernel α α} (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) {f : α → ℝ} (hf : MemLp f ∞ μ) : MemLp (kernelIntegral κ f) ∞ μ := by - refine ⟨AEStronglyMeasurable.kernelIntegral hf.aestronglyMeasurable hκμ, ?_⟩ - exact (eLpNorm_kernelIntegral_top_le hκ hκμ f).trans_lt hf.2 + exact (eLpNorm_kernelIntegral_top_le hκ hκμ f).trans_lt hf.eLpNorm_lt_top end MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean index 7544dcd484..051e56871e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean @@ -558,7 +558,7 @@ omit [MeasurableSpace X] [BorelSpace X] [LocallyCompactSpace X] [SecondCountable ZeroAtInftyContinuousMap.zero_apply, zero_add] /-- The compactified semigroup fixes the constants. -/ -@[simp] theorem onePointSemigroup_constant (t : NNReal) (c : ℝ) : +theorem onePointSemigroup_constant (t : NNReal) (c : ℝ) : R.onePointSemigroup t (onePointConstant c) = onePointConstant c := by rw [onePointSemigroup_apply, onePointSemigroupAction, onePointConstant, onePointRemainder_assemble] diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean index 6373ec9c2e..d55a3b404f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean @@ -43,15 +43,15 @@ private theorem ae_integrable_kernel_finite {μ : Measure α} {κ : Kernel α α (hp : 1 ≤ p) (f : Lp ℝ (p : ℝ≥0∞) μ) : ∀ᵐ x ∂μ, Integrable f (κ x) := by let : IsFiniteKernel κ := hκ.isFiniteKernel have hfComp : MemLp f p (κ ∘ₘ μ) := (Lp.memLp f).mono_measure hκμ - have hFiberEq := Measure.ae_ae_of_ae_comp hfComp.1.ae_eq_mk + have hFiberEq := Measure.ae_ae_of_ae_comp hfComp.aestronglyMeasurable.ae_eq_mk have hp0 : (p : ℝ≥0∞) ≠ 0 := by exact_mod_cast ne_of_gt (zero_lt_one.trans_le hp) have hpowInt := hfComp.integrable_norm_rpow hp0 ENNReal.coe_ne_top have hFiberInt := Measure.ae_integrable_of_integrable_comp hpowInt filter_upwards [hFiberEq, hFiberInt] with x hxEq hxInt - have hxEq' : f =ᵐ[κ x] hfComp.1.mk f := hxEq + have hxEq' : f =ᵐ[κ x] hfComp.aestronglyMeasurable.mk f := hxEq have hxMeas : AEStronglyMeasurable f (κ x) := - hfComp.1.stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq'.symm + hfComp.aestronglyMeasurable.stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq'.symm have hxMemLp : MemLp f p (κ x) := (integrable_norm_rpow_iff hxMeas hp0 ENNReal.coe_ne_top).mp hxInt exact hxMemLp.integrable (by exact_mod_cast hp) @@ -60,8 +60,8 @@ private theorem ae_integrable_kernel_top {μ : Measure α} {κ : Kernel α α} (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) (f : Lp ℝ ∞ μ) : ∀ᵐ x ∂μ, Integrable f (κ x) := by have hCtop : eLpNormEssSup f μ ≠ ∞ := by - rw [← eLpNorm_exponent_top] - exact (Lp.memLp f).2.ne + rw [← eLpNorm_exponent_top (Lp.aestronglyMeasurable f)] + exact (Lp.memLp f).eLpNorm_lt_top.ne have hCcoe : ((eLpNormEssSup f μ).toNNReal : ℝ≥0∞) = eLpNormEssSup f μ := ENNReal.coe_toNNReal hCtop have hFiberEq : ∀ᵐ x ∂μ, f =ᵐ[κ x] (Lp.aestronglyMeasurable f).mk f := diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorKernel.lean index 8ecb04e1cb..a8de2a8be3 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorKernel.lean @@ -90,7 +90,6 @@ theorem isSubMarkovKernel_kernel (hT_norm : ‖T‖ ≤ 1) : exact PositiveC0OperatorMeasure.measure_univ_le_one T hT hT_norm x /-- The kernel represents `T` on compactly supported continuous functions. -/ -@[simp] theorem integral_kernel_compactlySupported (hT_norm : ‖T‖ ≤ 1) (x : α) (f : C_c(α, ℝ)) : ∫ y, f y ∂kernel T hT hT_norm x = diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean index b043ccc5fb..074fb8c032 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean @@ -193,12 +193,12 @@ theorem IsConservative.killedProcess_map_coordinates_ordered {n : ℕ} | succ n ih => have hmeasTimes : Measurable (fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) := - measurable_pi_lambda _ fun i ↦ + Measurable.of_eval fun i ↦ ContinuousPath.measurable_coordinate_killAtExit U hU (times i) have hmeasTail : Measurable (fun omega : ContinuousPath alpha ↦ fun i : Fin n ↦ LifetimePath.coordinate (times.relativeTail i) (ContinuousPath.killAtExit U omega)) := - measurable_pi_lambda _ fun i ↦ + Measurable.of_eval fun i ↦ ContinuousPath.measurable_coordinate_killAtExit U hU (times.relativeTail i) have hRcons : (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)).IsConservative := isConservative_cemeterySemigroup _ let : IsMarkovKernel (finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times) := @@ -210,7 +210,7 @@ theorem IsConservative.killedProcess_map_coordinates_ordered {n : ℕ} have : IsProbabilityMeasure ((IsConservative.continuousProcess P hP (x : alpha)).map (fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega))) := - Measure.isProbabilityMeasure_map hmeasTimes.aemeasurable + inferInstance refine MeasureTheory.ext_of_generate_finite _ generateFrom_pi.symm isPiSystem_pi ?_ ?_ · rintro _ ⟨B, hB, rfl⟩ have hBmeas : ∀ i : Fin (n + 1), MeasurableSet (B i) := fun i ↦ hB i (Set.mem_univ i) diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean index f624aa2e8e..63d36807e3 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean @@ -217,11 +217,11 @@ theorem IsConservative.killedProcess_map_killedCoordinates (hUV : U ⊆ V) (hU : have hW : IsOpen (Subtype.val ⁻¹' U : Set V) := hU.preimage continuous_subtype_val have hm1 : Measurable fun eta : LifetimePath V ↦ fun i ↦ LifetimePath.killedCoordinate (Subtype.val ⁻¹' U : Set V) (tau i) eta := - measurable_pi_lambda _ fun i ↦ + Measurable.of_eval fun i ↦ LifetimePath.measurable_killedCoordinate _ hW (tau i) have hm2 : Measurable fun omega : LifetimePath U ↦ fun i ↦ Sum.map (Set.inclusion hUV) id (LifetimePath.coordinate (tau i) omega) := - measurable_pi_lambda _ fun i ↦ + Measurable.of_eval fun i ↦ ((measurable_inclusion hUV).sumMap measurable_id).comp (LifetimePath.measurable_coordinate (tau i)) have hfun : (fun eta : LifetimePath V ↦ fun i ↦ @@ -254,7 +254,7 @@ theorem IsConservative.killedProcess_map_killedFinsetCoordinates (fun p ↦ fun i : I ↦ Sum.map (Set.inclusion hUV) id (p i)) := by have hmap : Measurable fun p : I → Cemetery U ↦ fun i : I ↦ Sum.map (Set.inclusion hUV) id (p i) := - measurable_pi_lambda _ fun i ↦ + Measurable.of_eval fun i ↦ ((measurable_inclusion hUV).sumMap measurable_id).comp (measurable_pi_apply i) rw [IsConservative.killedProcess_map_killedCoordinates P hP U V hUV hU hV x (fun i : I ↦ (i : NNReal)), diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean index ea3a079cb6..2d59564ffc 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean @@ -37,7 +37,7 @@ namespace LifetimePath theorem measurable_coordinateFamily {beta : Type*} [TopologicalSpace beta] [MeasurableSpace beta] {iota : Type*} (tau : iota → NNReal) : Measurable fun omega : LifetimePath beta ↦ fun i ↦ coordinate (tau i) omega := - measurable_pi_lambda _ fun i ↦ measurable_coordinate (tau i) + Measurable.of_eval fun i ↦ measurable_coordinate (tau i) end LifetimePath diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean index 6fefaae786..ee36918569 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean @@ -48,7 +48,6 @@ theorem coordinate_shift_of_lt (S t : NNReal) (ω : LifetimePath α) rfl /-- At and after the shifted lifetime, the shifted coordinate is the cemetery state. -/ -@[simp] theorem coordinate_shift_of_le (S t : NNReal) (ω : LifetimePath α) (ht : (shift S ω).lifetime ≤ (t : ENNReal)) : coordinate t (shift S ω) = Cemetery.delta := diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean index 219a3ebf57..3d3d0b3f7c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean @@ -79,7 +79,7 @@ theorem IsConservative.lintegral_annealedProcess (x : alpha) {g : ContinuousPath /-- Annealed expectations of bounded strongly measurable functionals are the averages of the quenched expectations: `∫ F d(annealed x) = ∫ (∫ F dQ(theta, x)) mu(dtheta)`. -/ theorem IsConservative.integral_annealedProcess [IsProbabilityMeasure mu] (x : alpha) - {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) (C : ℝ) (hFC : ∀ eta, ‖F eta‖ ≤ C) : ∫ omega, F omega ∂(IsConservative.annealedProcess P hP mu x) = diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean index 9e5d361570..ef3962bd0a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean @@ -35,8 +35,8 @@ omit [StandardBorelSpace alpha] [Nonempty alpha] in /-- Bridging lemma: `ULift.down` out of the `(n + 1)`-st trajectory coordinate is measurable w.r.t. the project's registered `MeasurableSpace (trajectoryCoordinate (n + 1))` instance, not just the generic `ULift.instMeasurableSpace` instance that `measurable_down` is stated for. -/ -private theorem measurable_down_trajectoryCoordinate (n : ℕ) : - Measurable (ULift.down : trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1) → alpha) := by +private theorem measurable_down_trajectoryCoordinate : + Measurable (ULift.down : ULift.{max uTheta uAlpha} alpha → alpha) := by simpa only [trajectoryCoordinate] using! measurable_down private def historyInitial (n : ℕ) @@ -251,7 +251,7 @@ private theorem historyEquiv_rawTrajAppend (n : ℕ) private theorem transport_traj_step {X H Z Y T : Type*} [MeasurableSpace X] [MeasurableSpace H] [MeasurableSpace Z] [MeasurableSpace Y] [MeasurableSpace T] - (kappa : Kernel X Z) [IsSFiniteKernel kappa] + (kappa : Kernel X Z) (eta : Kernel Z Y) [IsSFiniteKernel eta] (E : H ≃ᵐ Z) (g : H × Y → T) (hg : Measurable g) (q : Z × Y → T) (hcompat : g ∘ Prod.map E.symm id = q) : @@ -429,7 +429,7 @@ private theorem partialTraj_map_historyEquiv have hr_meas : Measurable r := measurable_fst.prodMk ((DenseTimeHistory.splitLast n).symm.measurable.comp ((measurable_fst.comp measurable_snd).prodMk - ((measurable_down_trajectoryCoordinate n).comp + (measurable_down_trajectoryCoordinate.comp (measurable_snd.comp measurable_snd)))) rw [hq, Kernel.map_comp_right _ MeasurableEquiv.prodAssoc.measurable hr_meas] rw [prod_comp_prod_map_prodAssoc] @@ -445,12 +445,12 @@ private theorem partialTraj_map_historyEquiv (γ := trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) ULift.up) measurable_id ((DenseTimeHistory.splitLast n).symm.measurable.comp - (measurable_id.prodMap (measurable_down_trajectoryCoordinate n)))] + (measurable_id.prodMap measurable_down_trajectoryCoordinate))] rw [Kernel.map_comp_right (P.parameterizedDenseTimePrefixKernel e iota n ⊗ₖ (P.parameterizedObservationCondKernel hP e iota n).map (γ := trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) ULift.up) - (measurable_id.prodMap (measurable_down_trajectoryCoordinate n)) + (measurable_id.prodMap measurable_down_trajectoryCoordinate) (DenseTimeHistory.splitLast n).symm.measurable] have hcpmud : (P.parameterizedDenseTimePrefixKernel e iota n ⊗ₖ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Stopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Stopping.lean index a78487eb42..b031a92eab 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/Stopping.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Stopping.lean @@ -36,12 +36,10 @@ theorem stoppedPath_apply (T : NNReal) (omega : ContinuousPath alpha) (t : NNRea stoppedPath T omega t = omega (min t T) := rfl -@[simp] theorem stoppedPath_apply_of_le (T : NNReal) (omega : ContinuousPath alpha) (t : NNReal) (ht : t ≤ T) : stoppedPath T omega t = omega t := by rw [stoppedPath_apply, min_eq_left ht] -@[simp] theorem stoppedPath_apply_of_ge (T : NNReal) (omega : ContinuousPath alpha) (t : NNReal) (ht : T ≤ t) : stoppedPath T omega t = omega T := by rw [stoppedPath_apply, min_eq_right ht] diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Basic.lean index 92cf80d634..1bd864a46d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Basic.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Basic.lean @@ -51,7 +51,6 @@ variable (S : StronglyContinuousContractionSemigroup E) theorem zero : S 0 = ContinuousLinearMap.id ℝ E := S.operator_zero -@[simp] theorem zero_apply (x : E) : S 0 x = x := by rw [S.zero] rfl @@ -60,7 +59,6 @@ theorem zero_apply (x : E) : S 0 x = x := by theorem add (s t : NNReal) : S (s + t) = (S s).comp (S t) := S.operator_add s t -@[simp] theorem add_apply (s t : NNReal) (x : E) : S (s + t) x = S s (S t x) := by rw [S.add] rfl diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean index 83ac34a64b..60499c962f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean @@ -40,7 +40,7 @@ theorem comp {S : F → G} {T : E → F} /-- A closed set is preserved by the pointwise limit of preserving maps. -/ theorem of_tendsto {ι : Type*} {l : Filter ι} [l.NeBot] - [TopologicalSpace F] [T2Space F] {T : ι → E → F} {S : E → F} + [TopologicalSpace F] {T : ι → E → F} {S : E → F} (hD : IsClosed D) (hT : ∀ i, PreservesSet (T i) C D) (hlim : ∀ x, Tendsto (fun i ↦ T i x) l (nhds (S x))) : PreservesSet S C D := by diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeHistory.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeHistory.lean index 91f02bf0de..3e5e910bb0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeHistory.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeHistory.lean @@ -57,7 +57,6 @@ theorem historyEquiv_symm_apply_zero (n : ℕ) (x : α) (path : Fin n → α) : (historyEquiv n).symm (x, path) ⟨0, Nat.zero_le n⟩ = x := rfl -@[simp] theorem historyEquiv_symm_apply_succ (n : ℕ) (x : α) (path : Fin n → α) (i : Fin n) : (historyEquiv n).symm (x, path) ⟨i.succ, i.isLt⟩ = path i := rfl diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean index 59eee22504..5586cbd3c5 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean @@ -135,7 +135,6 @@ theorem eq_emptyPath {α : Type*} (path : Fin 0 → α) : path = emptyPath α := Subsingleton.elim _ _ /-- Restricting any path to an empty index family gives the canonical empty path. -/ -@[simp] theorem restrictPath_empty {n : ℕ} (e : Fin 0 ↪o Fin n) {α : Type*} (path : Fin n → α) : restrictPath e path = emptyPath α := Subsingleton.elim _ _ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/OrderedGrid.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/OrderedGrid.lean index 752aed6ee0..20b4a06d0e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/OrderedGrid.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/OrderedGrid.lean @@ -37,11 +37,11 @@ def increment (grid : OrderedGrid) (n : ℕ) : NNReal := end OrderedGrid /-- The singleton history at index zero determined by a starting state. -/ -def initialHistory (x : α) : (i : Finset.Iic 0) → α := +def initialHistory (x : α) : Finset.Iic 0 → α := fun _ => x /-- The singleton-history map is measurable. -/ -theorem measurable_initialHistory : Measurable (initialHistory : α → (i : Finset.Iic 0) → α) := +theorem measurable_initialHistory : Measurable (initialHistory : α → Finset.Iic 0 → α) := measurable_pi_iff.mpr fun _ => measurable_id namespace SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean index ee099c553a..d435e88c10 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean @@ -86,7 +86,7 @@ def finiteEvaluation {ι α : Type*} [TopologicalSpace α] fun path i ↦ path (τ i) /-- Simultaneous evaluation at finitely many fixed times is continuous in the path. -/ -theorem continuous_finiteEvaluation {ι α : Type*} [Finite ι] +theorem continuous_finiteEvaluation {ι α : Type*} [TopologicalSpace α] (τ : ι → NNReal) : Continuous (finiteEvaluation (α := α) τ) := by apply continuous_pi @@ -95,7 +95,7 @@ theorem continuous_finiteEvaluation {ι α : Type*} [Finite ι] /-- If each time in a finite family converges, then simultaneous evaluation along any continuous path converges in the finite product topology. -/ -theorem tendsto_finiteEvaluation {ι α : Type*} [Finite ι] +theorem tendsto_finiteEvaluation {ι α : Type*} [TopologicalSpace α] (τ : ι → NNReal) (q : ℕ → ι → NNReal) (hq : ∀ i, Tendsto (fun k ↦ q k i) atTop (nhds (τ i))) (path : ContinuousPath α) : @@ -114,7 +114,7 @@ variable {α : Type*} [MetricSpace α] [MeasurableSpace α] [BorelSpace α] omit [SecondCountableTopology α] [LocallyCompactSpace α] in /-- Simultaneous evaluation at finitely many fixed times is Borel measurable. -/ -theorem ContinuousPath.measurable_finiteEvaluation {ι : Type*} [Finite ι] +theorem ContinuousPath.measurable_finiteEvaluation {ι : Type*} (τ : ι → NNReal) : Measurable (finiteEvaluation (α := α) τ) := by rw [measurable_pi_iff] intro i diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean index ae91c96fd6..8dbf22839b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean @@ -76,13 +76,11 @@ theorem rescale_refl_one (omega : ContinuousPath alpha) : simp only [rescale_apply, Homeomorph.refl_apply, id_eq, one_mul] /-- Rescaling by the identity homeomorphism speeds the path up without touching the state. -/ -@[simp] theorem rescale_refl_apply (c : NNReal) (omega : ContinuousPath alpha) (t : NNReal) : rescale (Homeomorph.refl alpha) c omega t = omega (c * t) := rfl /-- Rescaling by the time factor one conjugates the state without touching the time. -/ -@[simp] theorem rescale_one_apply (e : alpha ≃ₜ beta) (omega : ContinuousPath alpha) (t : NNReal) : rescale e 1 omega t = e (omega t) := by simp only [rescale_apply, one_mul] diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean index d4ead1fec1..ed5a639f4a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean @@ -398,7 +398,7 @@ integral over that event of a bounded strongly measurable observable of `Y` is t it of the `kappa`-expectation of the observable. -/ theorem setIntegral_integral_kernel_of_restrict_map (mu : @Measure Omega mOmega) [IsFiniteMeasure mu] - (kappa : @Kernel Omega beta mOmega mBeta) [IsMarkovKernel kappa] + (kappa : @Kernel Omega beta mOmega mBeta) (Y : Omega → beta) (hY : @Measurable Omega beta mOmega mBeta Y) (A : Set Omega) (hJoint : (mu.restrict A).map Y = kappa ∘ₘ (mu.restrict A)) (F : beta → E) (hF : StronglyMeasurable F) (C : Real) (hFC : ∀ y, ‖F y‖ ≤ C) : From 771190e64c61056d0478c5087feea9e1155335cf Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Mon, 21 Sep 2026 20:37:28 +0000 Subject: [PATCH 04/11] Complete Markov process import audits and warning cleanup --- LeanPool.lean | 265 ++++++++++++++++++ LeanPool/MarkovProcess.lean | 2 +- .../MarkovProcess/Analysis/ExpPrimitive.lean | 69 +++-- .../DenseTimeContinuousExtension.lean | 6 +- .../Continuity/DenseTimeContinuousLaw.lean | 6 +- .../DenseTimeContinuousSupport.lean | 6 +- .../Continuity/DyadicChaining.lean | 2 +- .../MarkovProcess/Continuity/DyadicFloor.lean | 22 +- .../Continuity/DyadicIncrements.lean | 2 +- .../GlobalDyadicFloorModification.lean | 12 +- .../KolmogorovDenseTimeContinuousSupport.lean | 6 +- .../Continuity/KolmogorovTimeShift.lean | 6 +- .../Continuity/PathTightness.lean | 2 +- .../Continuity/ShiftedUnitModification.lean | 6 +- .../DenseTime/CemeteryDenseTimeMarginals.lean | 6 +- .../DenseTime/CemeterySemigroup.lean | 11 +- .../DenseTime/ConditionalKernel.lean | 6 +- .../PhysicalCompactTestTransport.lean | 10 +- .../DenseTime/PhysicalReindex.lean | 6 +- .../MarkovProcess/DenseTime/PrefixKernel.lean | 6 +- .../DenseTime/PrefixRecursion.lean | 56 ++-- .../MarkovProcess/DenseTime/Shift.lean | 6 +- .../MarkovProcess/DenseTime/Trajectory.lean | 27 +- .../DenseTime/TrajectoryMarginals.lean | 6 +- .../DenseTime/TwoPointMarginals.lean | 8 +- .../Examples/BrownianMotion.lean | 21 +- .../MarkovProcess/Examples/Drift.lean | 10 +- .../MarkovProcess/Examples/HeatGenerator.lean | 6 +- .../MarkovProcess/Examples/HeatOnePoint.lean | 9 +- .../MarkovProcess/Examples/HeatSemigroup.lean | 8 +- .../MarkovProcess/Examples/Identity.lean | 11 +- .../Feller/BackwardC0Convergence.lean | 2 + .../Feller/BackwardC0Integral.lean | 1 + .../Feller/BackwardC0Recursion.lean | 3 + .../CoordinatePolynomialContinuity.lean | 1 + .../Feller/CoordinateProductContinuity.lean | 1 + .../Feller/FiniteTimeContinuityBase.lean | 1 + .../Feller/FiniteTimeConvergence.lean | 3 + .../FiniteTimeJointCompactTestContinuity.lean | 2 + .../Feller/FiniteTimeKernelContinuity.lean | 2 + .../MarkovProcess/Feller/Resolvent.lean | 5 + .../MarkovProcess/Feller/Semigroup.lean | 3 + .../CoordinateProductNormalization.lean | 4 +- .../DenseTimeFiniteSetKernelShift.lean | 6 +- .../FiniteTime/DenseTimeFiniteShift.lean | 6 +- ...iteProductCompactSupportApproximation.lean | 7 +- .../FiniteProductCoordinateNormalForm.lean | 7 +- .../FiniteSetKernelCompactTestTransport.lean | 12 +- .../FiniteTime/FiniteSetKernelShift.lean | 6 +- .../FiniteTime/KernelConcatenation.lean | 3 +- .../FiniteTime/KernelEquivariance.lean | 13 +- ...easureFiniteRestrictionIdentification.lean | 6 +- .../Kernel/ConservativeResolvent.lean | 8 +- .../FiniteRestrictionIdentification.lean | 6 +- .../MarkovProcess/Kernel/KernelSemigroup.lean | 8 +- .../Kernel/KolmogorovMoments.lean | 3 +- .../MarkovProcess/Kernel/Lp.lean | 8 +- .../MarkovProcess/Kernel/LpFinite.lean | 5 +- .../Kernel/MeasurableRadonFamily.lean | 2 +- .../Kernel/OnePointConservative.lean | 8 +- .../Kernel/OnePointExtension.lean | 8 +- .../MarkovProcess/Kernel/OnePointKilled.lean | 22 +- .../Kernel/OnePointKolmogorov.lean | 9 +- .../Kernel/PositiveC0Resolvent.lean | 8 +- .../Kernel/ResolventUniqueness.lean | 6 +- .../MarkovProcess/Kernel/WeakConvergence.lean | 2 +- .../Killed/ExitTimeIdentification.lean | 10 +- .../MarkovProcess/Killed/GluingC0.lean | 8 +- .../MarkovProcess/Killed/GluingLinearity.lean | 8 +- .../MarkovProcess/Killed/GluingLocal.lean | 12 +- .../MarkovProcess/Killed/GluingMeasure.lean | 8 +- .../MarkovProcess/Killed/GluingMinimal.lean | 8 +- .../MarkovProcess/Killed/GluingPotential.lean | 8 +- .../Killed/GluingRealResolvent.lean | 10 +- .../Killed/GluingResolventEquation.lean | 8 +- .../MarkovProcess/Killed/GluingTransfer.lean | 8 +- .../MarkovProcess/Killed/Kernel.lean | 3 +- .../MarkovProcess/Killed/KillAtExit.lean | 18 +- .../MarkovProcess/Killed/Marginals.lean | 138 +++++---- .../MarkovProcess/Killed/Nested.lean | 19 +- .../MarkovProcess/Killed/Process.lean | 3 +- .../MarkovProcess/Killed/Resolvent.lean | 12 +- .../MarkovProcess/Killed/Semigroup.lean | 3 +- .../MarkovProcess/Lifetime/Basic.lean | 12 +- .../Lifetime/CountablySeparated.lean | 6 +- .../MarkovProcess/Lifetime/ExitTime.lean | 6 +- .../Lifetime/ExitTimeStopping.lean | 24 +- .../MarkovProcess/Lifetime/Filtration.lean | 2 +- .../MarkovProcess/Lifetime/Killing.lean | 6 +- .../MarkovProcess/Lifetime/Law.lean | 6 +- .../MarkovProcess/Lifetime/Nonexplosion.lean | 6 +- .../Lifetime/NonexplosiveTransport.lean | 6 +- .../MarkovProcess/Lifetime/Shift.lean | 6 +- .../MarkovProcess/MarkovProcess/Main.lean | 19 +- .../MarkovProcess/Parameterized/Annealed.lean | 7 +- .../CemeteryDenseTimeMarginals.lean | 6 +- .../CemeteryDenseTimeSupport.lean | 6 +- .../Parameterized/CemeterySemigroup.lean | 8 +- .../Parameterized/ContinuousProcess.lean | 6 +- .../DenseTimeConditionalKernel.lean | 6 +- .../Parameterized/DenseTimePrefixKernel.lean | 6 +- .../Parameterized/DenseTimeTrajectory.lean | 53 ++-- .../DenseTimeTrajectoryMarginals.lean | 6 +- .../Parameterized/Equivariance.lean | 6 +- .../MarkovProcess/Parameterized/Killed.lean | 5 +- .../Parameterized/Semigroup.lean | 8 +- .../Path/ClosedSetDetection.lean | 12 +- .../MarkovProcess/Path/DenseFiltration.lean | 7 +- .../MarkovProcess/Path/ExitTime.lean | 12 +- .../Path/KernelIdentification.lean | 6 +- .../Path/MeasureIdentification.lean | 6 +- .../Path/MixedFiniteMarginals.lean | 6 +- .../MarkovProcess/Path/OptionalStopping.lean | 9 +- .../RandomTimeCompactTestConvergence.lean | 6 +- .../MarkovProcess/Path/RelativeHitting.lean | 8 +- .../Path/ShiftCompactTestConvergence.lean | 6 +- .../Path/StoppingTimeDyadicCeiling.lean | 6 +- .../Restart/ConditionalExpectation.lean | 6 +- .../Restart/ConditionalMarkov.lean | 6 +- .../Restart/CountableStoppingRestart.lean | 6 +- .../Restart/FinitePastRestart.lean | 6 +- .../Restart/MixedPastFuture.lean | 11 +- .../Restart/RationalRestart.lean | 18 +- .../Restart/RationalRestrictedRestart.lean | 6 +- .../Restart/RestrictedRestartOfJoint.lean | 6 +- .../Semigroup/ExponentialComparison.lean | 8 +- .../MarkovProcess/Semigroup/Generation.lean | 8 +- .../MarkovProcess/Semigroup/Generator.lean | 19 +- .../Semigroup/GeneratorInjectivity.lean | 6 +- .../Semigroup/GeneratorResolvent.lean | 6 +- .../Semigroup/GeneratorUniqueness.lean | 6 +- .../MarkovProcess/Semigroup/InvariantSet.lean | 10 +- .../Semigroup/OrbitProductRule.lean | 2 +- .../Semigroup/PoissonInvariant.lean | 8 +- .../MarkovProcess/Semigroup/Resolvent.lean | 12 +- .../Semigroup/ResolventComparison.lean | 6 +- .../MarkovProcess/Semigroup/TrotterKato.lean | 6 +- .../Semigroup/YosidaApproximation.lean | 8 +- .../Semigroup/YosidaStrongLimit.lean | 8 +- .../Time/CountableDenseTime.lean | 8 +- .../Time/FiniteDenseApproximationOrdered.lean | 6 +- .../Time/FiniteOrderedTimes.lean | 3 +- .../Trajectory/AllTimeFiniteMarginals.lean | 24 +- .../Trajectory/AllTimeMarginals.lean | 6 +- .../MarkovProcess/Trajectory/Basic.lean | 6 +- .../MarkovProcess/Trajectory/Convergence.lean | 6 +- .../Trajectory/CylinderAlgebra.lean | 7 +- .../Trajectory/DenseRestrictionIntegral.lean | 6 +- .../Trajectory/DenseRestrictionMarginals.lean | 6 +- .../Trajectory/DenseStoppingRestart.lean | 6 +- .../Trajectory/DiscountedDynkin.lean | 19 +- .../Trajectory/DynkinMartingale.lean | 19 +- .../Trajectory/DynkinStopping.lean | 11 +- .../Trajectory/Equivariance.lean | 10 +- .../Trajectory/ExcessiveStopping.lean | 8 +- .../MarkovProcess/Trajectory/ExitLaw.lean | 3 +- .../Trajectory/ExitTimeExponentialMoment.lean | 12 +- .../Trajectory/ExitTimeLaplace.lean | 10 +- .../Trajectory/FellerConditional.lean | 6 +- .../FellerCountableStoppingRestart.lean | 6 +- .../Trajectory/FellerFiniteMarginals.lean | 6 +- .../Trajectory/FellerRestrictedRestart.lean | 6 +- .../MarkovProcess/Trajectory/FellerShift.lean | 6 +- .../Trajectory/FellerStoppingConditional.lean | 6 +- .../Trajectory/FellerStoppingRestart.lean | 6 +- .../Trajectory/FeynmanKacFunctional.lean | 10 +- .../Trajectory/FeynmanKacRealResolvent.lean | 6 +- .../Trajectory/FeynmanKacResolvent.lean | 6 +- .../Trajectory/FiniteMarginals.lean | 6 +- .../Trajectory/HarmonicRepresentation.lean | 6 +- .../MarkovProcess/Trajectory/PathModulus.lean | 6 +- .../Trajectory/PathTightness.lean | 9 +- .../Trajectory/PenalizationDomination.lean | 6 +- .../Trajectory/RationalConditional.lean | 6 +- .../Trajectory/RationalShift.lean | 6 +- .../ResolventExitDecomposition.lean | 8 +- .../Trajectory/StartingPointContinuity.lean | 6 +- .../Trajectory/StoppingLtTop.lean | 10 +- .../Trajectory/WeakContinuity.lean | 6 +- .../Trajectory/WeakConvergence.lean | 6 +- LeanPool/projects.yml | 4 +- 181 files changed, 1464 insertions(+), 451 deletions(-) diff --git a/LeanPool.lean b/LeanPool.lean index 68ac6936df..4eb5bc8bdc 100644 --- a/LeanPool.lean +++ b/LeanPool.lean @@ -3550,6 +3550,271 @@ import LeanPool.MRiscX.Tactics.SplitLastSeq import LeanPool.MRiscX.Tactics.TacticUtil import LeanPool.MRiscX.Util.BasicTheorems import LeanPool.MarkovProcess +import LeanPool.MarkovProcess.MarkovProcess +import LeanPool.MarkovProcess.MarkovProcess.Analysis +import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive +import LeanPool.MarkovProcess.MarkovProcess.Analysis.PaleyZygmund +import LeanPool.MarkovProcess.MarkovProcess.Continuity +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements +import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining +import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification +import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport +import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift +import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus +import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness +import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification +import LeanPool.MarkovProcess.MarkovProcess.DenseTime +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscreteLaw +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryDenseTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals +import LeanPool.MarkovProcess.MarkovProcess.Examples +import LeanPool.MarkovProcess.MarkovProcess.Examples.BrownianMotion +import LeanPool.MarkovProcess.MarkovProcess.Examples.Drift +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatGenerator +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatOnePoint +import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Examples.Identity +import LeanPool.MarkovProcess.MarkovProcess.Feller +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral +import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion +import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeContinuityBase +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity +import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification +import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +import LeanPool.MarkovProcess.MarkovProcess.Kernel +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 +import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint +import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativityAE +import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpConsistency +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite +import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop +import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +import LeanPool.MarkovProcess.MarkovProcess.Kernel.OperatorSemigroup +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller +import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel +import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness +import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence +import LeanPool.MarkovProcess.MarkovProcess.Killed +import LeanPool.MarkovProcess.MarkovProcess.Killed.ExitTimeIdentification +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingC0 +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation +import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer +import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel +import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit +import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals +import LeanPool.MarkovProcess.MarkovProcess.Killed.Minimal +import LeanPool.MarkovProcess.MarkovProcess.Killed.Nested +import LeanPool.MarkovProcess.MarkovProcess.Killed.Process +import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Lifetime +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.CountablySeparated +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Killing +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Nonexplosion +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.NonexplosiveTransport +import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift +import LeanPool.MarkovProcess.MarkovProcess.Main +import LeanPool.MarkovProcess.MarkovProcess.Parameterized +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Annealed +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeSupport +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Equivariance +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Killed +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid +import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Path +import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration +import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral +import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift +import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification +import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +import LeanPool.MarkovProcess.MarkovProcess.Path.Polish +import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability +import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence +import LeanPool.MarkovProcess.MarkovProcess.Path.RelativeHitting +import LeanPool.MarkovProcess.MarkovProcess.Path.Sampling +import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence +import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability +import LeanPool.MarkovProcess.MarkovProcess.Path.Stopping +import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling +import LeanPool.MarkovProcess.MarkovProcess.Restart +import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation +import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov +import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure +import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture +import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint +import LeanPool.MarkovProcess.MarkovProcess.Semigroup +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialComparison +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation +import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit +import LeanPool.MarkovProcess.MarkovProcess.Time +import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove +import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding +import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes +import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid +import LeanPool.MarkovProcess.MarkovProcess.Trajectory +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExcessiveStopping +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeExponentialMoment +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKac +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalShift +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity +import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakConvergence import LeanPool.MassFormula import LeanPool.MassFormula.Convergence import LeanPool.MassFormula.Defs diff --git a/LeanPool/MarkovProcess.lean b/LeanPool/MarkovProcess.lean index f91e9bfc06..682e9b7e34 100644 --- a/LeanPool/MarkovProcess.lean +++ b/LeanPool/MarkovProcess.lean @@ -276,7 +276,7 @@ import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakConvergence Source: url:https://github.com/scottnarmstrong/markovprocess Authors: Scott Armstrong Status: verified -Main declarations: `MarkovProcess.SubMarkovKernelSemigroup.IsFellerKernelSemigroup.existsUnique_continuousProcess_of_hasKolmogorovMoments` +Main declarations: `MarkovProcess.existsUnique_continuousProcess` Tags: probability MSC: 60J25, 60J35, 60G17 -/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Analysis/ExpPrimitive.lean b/LeanPool/MarkovProcess/MarkovProcess/Analysis/ExpPrimitive.lean index f0962f30b8..4633e638fd 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Analysis/ExpPrimitive.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Analysis/ExpPrimitive.lean @@ -22,12 +22,14 @@ Main results: `intervalIntegral.integral_mul_exp_primitive`, No probabilistic structure is used or asserted. -/ +noncomputable section PortComputability + open MeasureTheory Set open scoped ENNReal namespace intervalIntegral -noncomputable section +section -- The namespace placement is upstream-facing: this is a pure companion to interval integrals. /-- Tonelli's theorem on the time triangle, followed by the volume-preserving shear @@ -238,6 +240,40 @@ private theorem sub_exp_le_exp_mul_sub {x y : ℝ} : simpa only [add_comm] using add_le_add_right h' (Real.exp y * (y - x)) _ = Real.exp y * (y - x) + Real.exp x := add_comm _ _ +private theorem eq_of_two_sided_nat_error {x y B : ℝ} (hB : 0 ≤ B) + (hApprox : ∀ N : ℕ, 0 < N → x ≤ y + B / N ∧ y ≤ x + B / N) : x = y := by + apply le_antisymm + · refine le_of_forall_pos_le_add fun epsilon hepsilon ↦ ?_ + obtain ⟨N, hN⟩ := exists_nat_gt (B / epsilon) + have hNposReal : (0 : ℝ) < N := (div_nonneg hB hepsilon.le).trans_lt hN + have hNpos : 0 < N := by exact_mod_cast hNposReal + have hBN : B / N < epsilon := by + rw [div_lt_iff₀ hNposReal] + have := (div_lt_iff₀ hepsilon).mp hN + nlinarith only [this] + exact (hApprox N hNpos).1.trans (add_le_add_right hBN.le _) + · refine le_of_forall_pos_le_add fun epsilon hepsilon ↦ ?_ + obtain ⟨N, hN⟩ := exists_nat_gt (B / epsilon) + have hNposReal : (0 : ℝ) < N := (div_nonneg hB hepsilon.le).trans_lt hN + have hNpos : 0 < N := by exact_mod_cast hNposReal + have hBN : B / N < epsilon := by + rw [div_lt_iff₀ hNposReal] + have := (div_lt_iff₀ hepsilon).mp hN + nlinarith only [this] + exact (hApprox N hNpos).2.trans (add_le_add_right hBN.le _) + +private theorem intervalIntegrable_between {a : ℝ → ℝ} {T u v : ℝ} + (hT : 0 ≤ T) (hInt0T : IntervalIntegrable a volume (0 : ℝ) T) + (hu : u ∈ Icc (0 : ℝ) T) (hv : v ∈ Icc (0 : ℝ) T) : + IntervalIntegrable a volume u v := by + apply hInt0T.mono_set + rw [uIcc_of_le hT] + intro z hz + rw [mem_uIcc] at hz + rcases hz with hz | hz + · exact ⟨hu.1.trans hz.1, hz.2.trans hv.2⟩ + · exact ⟨hv.1.trans hz.1, hz.2.trans hu.2⟩ + /-- For a bounded nonnegative integrable function on `[0, T]`, integrating the function times the exponential of its integral primitive gives the exponential increment. The upper bound is used only to control the mesh error in the derivative-free uniform-partition proof. -/ @@ -255,14 +291,7 @@ theorem integral_mul_exp_primitive {a : ℝ → ℝ} {C T t : ℝ} rw [intervalIntegrable_iff, uIoc_of_le hT] exact ha.mono_set Ioc_subset_Icc_self have hInt (u v : ℝ) (hu : u ∈ Icc (0 : ℝ) T) (hv : v ∈ Icc (0 : ℝ) T) : - IntervalIntegrable a volume u v := by - apply hInt0T.mono_set - rw [uIcc_of_le hT] - intro z hz - rw [mem_uIcc] at hz - rcases hz with hz | hz - · exact ⟨hu.1.trans hz.1, hz.2.trans hv.2⟩ - · exact ⟨hv.1.trans hz.1, hz.2.trans hu.2⟩ + IntervalIntegrable a volume u v := intervalIntegrable_between hT hInt0T hu hv have hA_sub (u v : ℝ) (hu : u ∈ Icc (0 : ℝ) T) (hv : v ∈ Icc (0 : ℝ) T) : A v - A u = ∫ r in u..v, a r := by exact integral_interval_sub_left (hInt 0 v ⟨le_rfl, hT⟩ hv) @@ -447,26 +476,10 @@ theorem integral_mul_exp_primitive {a : ℝ → ℝ} {C T t : ℝ} _ ≤ (∫ s in (0 : ℝ)..t, a s * Real.exp (A s)) + B / N := by simpa only [add_comm] using add_le_add_right hL_target (B / N) change (∫ s in (0 : ℝ)..t, a s * Real.exp (A s)) = Real.exp (A t) - 1 - apply le_antisymm - · refine le_of_forall_pos_le_add fun epsilon hepsilon ↦ ?_ - obtain ⟨N, hN⟩ := exists_nat_gt (B / epsilon) - have hNposReal : (0 : ℝ) < N := (div_nonneg hB hepsilon.le).trans_lt hN - have hNpos : 0 < N := by exact_mod_cast hNposReal - have hBN : B / N < epsilon := by - rw [div_lt_iff₀ hNposReal] - have := (div_lt_iff₀ hepsilon).mp hN - nlinarith only [this] - exact (hApprox N hNpos).1.trans (add_le_add_right hBN.le _) - · refine le_of_forall_pos_le_add fun epsilon hepsilon ↦ ?_ - obtain ⟨N, hN⟩ := exists_nat_gt (B / epsilon) - have hNposReal : (0 : ℝ) < N := (div_nonneg hB hepsilon.le).trans_lt hN - have hNpos : 0 < N := by exact_mod_cast hNposReal - have hBN : B / N < epsilon := by - rw [div_lt_iff₀ hNposReal] - have := (div_lt_iff₀ hepsilon).mp hN - nlinarith only [this] - exact (hApprox N hNpos).2.trans (add_le_add_right hBN.le _) + exact eq_of_two_sided_nat_error hB hApprox end end intervalIntegral + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousExtension.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousExtension.lean index c3156436a2..296682d236 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousExtension.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousExtension.lean @@ -19,11 +19,13 @@ No probability law is shown to be supported on this image, and no continuous mod stochastic-process association, or path-regularity claim is made here. -/ +noncomputable section PortComputability + open MeasureTheory Set namespace MarkovProcess -noncomputable section +section namespace ContinuousPath @@ -114,3 +116,5 @@ end Measurable end ContinuousPath end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousLaw.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousLaw.lean index f5a1e150d5..7630e95aa4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousLaw.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousLaw.lean @@ -13,11 +13,13 @@ This file transports a kernel on dense-time trajectories to ordinary continuous explicit support-on-the-continuous-range hypothesis. It does not prove that support hypothesis. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory Set namespace MarkovProcess -noncomputable section +section namespace Kernel @@ -93,3 +95,5 @@ theorem IsSupportedOnContinuousPaths.map_denseRestriction end Kernel end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousSupport.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousSupport.lean index fbec35a11b..0086626b37 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousSupport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousSupport.lean @@ -18,11 +18,13 @@ argument of `Continuity/GlobalDyadicFloorModification.lean`, applied to dense-ti kernels in `Continuity/KolmogorovDenseTimeContinuousSupport.lean`. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory Set namespace MarkovProcess -noncomputable section +section namespace Kernel @@ -55,3 +57,5 @@ theorem IsSupportedOnContinuousPaths.of_continuousModification end Kernel end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicChaining.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicChaining.lean index dad71b4b64..bb6ddf90d9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicChaining.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicChaining.lean @@ -41,7 +41,7 @@ theorem edist_unitDyadicGrid_le_natCast_mul_of_adjacent_le else X (unitDyadicGrid n i) ω have hf (k : ℕ) (hk : k < 2 ^ n + 1) : f k = X (unitDyadicGrid n ⟨k, hk⟩) ω := by - simp only [f, dif_pos hk] + simp only [f, dite_eq_left hk] calc edist (X (unitDyadicGrid n i) ω) (X (unitDyadicGrid n j) ω) = edist (f i) (f j) := by rw [hf i i.isLt, hf j j.isLt] diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicFloor.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicFloor.lean index 6045e7f1a9..3b61018d5d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicFloor.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicFloor.lean @@ -24,12 +24,14 @@ This file merges the following former modules, one section each: * `DyadicFloorUnitModification`: A continuous modification on the unit interval -/ +noncomputable section PortComputability + namespace MarkovProcess section DyadicFloorApproximation -noncomputable section +section /-- The index of the left endpoint of the level-`n` dyadic cell containing `t ∈ [0, 1]`. -/ def unitDyadicFloorIndex (n : ℕ) (t : Set.Icc (0 : ℝ) 1) : Fin (2 ^ n + 1) := @@ -113,7 +115,7 @@ open Filter MeasureTheory ProbabilityTheory open scoped ENNReal NNReal -noncomputable section +section /-- Dyadic floor indices preserve the order of their represented times. -/ theorem unitDyadicFloorIndex_mono (n : ℕ) {s t : Set.Icc (0 : ℝ) 1} @@ -284,7 +286,7 @@ end DyadicFloorSampleCauchy section DyadicFloorDenseTime -noncomputable section +section /-- A point of the level-`n` unit dyadic grid, regarded as a real time in `[0, 1]`. -/ def unitDyadicGridTime (n : ℕ) (i : Fin (2 ^ n + 1)) : Set.Icc (0 : ℝ) 1 := @@ -396,7 +398,7 @@ open Filter MeasureTheory ProbabilityTheory Topology open scoped ENNReal NNReal -noncomputable section +section variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoEMetricSpace E] @@ -510,7 +512,7 @@ open Filter MeasureTheory ProbabilityTheory Topology open scoped ENNReal NNReal -noncomputable section +section variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [PseudoMetricSpace E] [CompleteSpace E] @@ -711,7 +713,7 @@ open Filter MeasureTheory ProbabilityTheory Topology open scoped ENNReal NNReal -noncomputable section +section variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [MetricSpace E] [CompleteSpace E] [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] @@ -756,8 +758,8 @@ theorem continuous_continuousUnitDyadicFloorLimit (X : NNRat → Ω → E) (ω : Ω) : Continuous (continuousUnitDyadicFloorLimit X ω) := by by_cases h : Continuous (unitDyadicFloorLimit X ω) - · simpa only [continuousUnitDyadicFloorLimit, if_pos h] using h - · simp only [continuousUnitDyadicFloorLimit, if_neg h] + · simpa only [continuousUnitDyadicFloorLimit, ite_eq_left h] using h + · simp only [continuousUnitDyadicFloorLimit, ite_eq_right h] exact continuous_const /-- At each fixed unit-interval rational time, the totalized continuous path remains a @@ -772,10 +774,12 @@ theorem IsKolmogorovProcess.ae_eq_continuousUnitDyadicFloorLimit [IsKolmogorovProcess.ae_eq_unitDyadicFloorLimit hX hγ hγq t ht, IsKolmogorovProcess.ae_continuous_unitDyadicFloorLimit hX hγ hγq] with ω hident hcont - simpa only [continuousUnitDyadicFloorLimit, if_pos hcont] using hident + simpa only [continuousUnitDyadicFloorLimit, ite_eq_left hcont] using hident end end DyadicFloorUnitModification end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicIncrements.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicIncrements.lean index 9c224e99bd..9bc45d8a81 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicIncrements.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicIncrements.lean @@ -104,7 +104,7 @@ theorem dyadic_bound_normalization (p q γ : ℝ) (M : ℝ≥0) (n : ℕ) : dyadicIncrementThreshold, dyadicIncrementDecayRatio] rw [← ENNReal.toReal_rpow, ← ENNReal.toReal_rpow, ← ENNReal.toReal_rpow, ENNReal.toReal_inv, ENNReal.toReal_pow, ENNReal.toReal_ofNat] - simp [← Real.rpow_natCast, ← Real.rpow_mul] + simp? [← Real.rpow_natCast, ← Real.rpow_mul] rw [← Real.rpow_neg (by positivity), ← Real.rpow_mul (by positivity), ← Real.rpow_mul (by positivity), div_eq_mul_inv, ← Real.rpow_neg (by positivity), ← Real.rpow_mul (by positivity)] diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/GlobalDyadicFloorModification.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/GlobalDyadicFloorModification.lean index 7fd540dad0..260f6883a6 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/GlobalDyadicFloorModification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/GlobalDyadicFloorModification.lean @@ -20,12 +20,14 @@ No measurability of the path-valued map, path-space law, Markov property, or Hun asserted here. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped ENNReal NNReal namespace MarkovProcess -noncomputable section +section variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [MetricSpace E] [CompleteSpace E] [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] @@ -181,8 +183,8 @@ theorem continuous_continuousGlobalDyadicFloorLimit (X : NNRat → Ω → E) (ω : Ω) : Continuous (continuousGlobalDyadicFloorLimit X ω) := by by_cases h : Continuous (globalDyadicFloorLimit X ω) - · simpa only [continuousGlobalDyadicFloorLimit, if_pos h] using h - · simp only [continuousGlobalDyadicFloorLimit, if_neg h] + · simpa only [continuousGlobalDyadicFloorLimit, ite_eq_left h] using h + · simp only [continuousGlobalDyadicFloorLimit, ite_eq_right h] exact continuous_const /-- At a fixed rational time written as a natural shift plus a local time in `[0,1]`, the @@ -216,7 +218,7 @@ theorem IsKolmogorovProcess.ae_eq_continuousGlobalDyadicFloorLimit_nat_add (IsKolmogorovProcess.timeShift hX n) hγ hγq t ht, IsKolmogorovProcess.ae_continuous_globalDyadicFloorLimit hX hγ hγq] with ω hident hcont - rw [continuousGlobalDyadicFloorLimit, if_pos hcont] + rw [continuousGlobalDyadicFloorLimit, ite_eq_left hcont] rw [show (↑((n : NNRat) + t) : ℝ≥0) = x by rfl, globalDyadicFloorLimit_coe X ω n ⟨x, hx⟩, globalDyadicFloorPiece, hcoord] simpa only [timeShift_apply] using! hident @@ -257,3 +259,5 @@ theorem IsKolmogorovProcess.ae_eq_continuousGlobalDyadicFloorLimit end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovDenseTimeContinuousSupport.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovDenseTimeContinuousSupport.lean index 8bd22b931e..a17954b852 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovDenseTimeContinuousSupport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovDenseTimeContinuousSupport.lean @@ -18,12 +18,14 @@ No measurability of the totalized modification as a path-valued map, PDE increme Markov property of the resulting paths, or Hunt-process assertion is made here. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal namespace MarkovProcess -noncomputable section +section namespace Kernel @@ -72,3 +74,5 @@ end ContinuousPathKernel end Kernel end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean index a0b015e99d..b7e2440d44 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean @@ -18,6 +18,8 @@ No global path is glued here, and no measurability of the canonical limit or mod assertion is made. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped ENNReal NNReal @@ -65,7 +67,7 @@ theorem timeShift_unitDyadicFloorValue_apply X (shiftedUnitDyadicFloorValue k n t) ω := rfl -noncomputable section +section variable [PseudoMetricSpace E] @@ -97,3 +99,5 @@ theorem tendsto_shiftedUnitDyadicFloorLimit_of_cauchySeq end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathTightness.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathTightness.lean index ac95d19d1a..ca87cf3567 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathTightness.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathTightness.lean @@ -66,7 +66,7 @@ theorem edist_le_of_modulus {T d : ℝ≥0} (hd : 0 < d) {rho : ℝ≥0∞} {f : set u : ℕ → ℝ≥0 := fun k ↦ t * k / K with hu have hu0 : u 0 = 0 := by simp [hu] have huK : u K = t := by - show t * (K : ℝ≥0) / (K : ℝ≥0) = t + change t * (K : ℝ≥0) / (K : ℝ≥0) = t rw [mul_div_assoc, div_self hKne, mul_one] have hule : ∀ k, k ≤ K → u k ≤ T := by intro k hk diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/ShiftedUnitModification.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/ShiftedUnitModification.lean index b336f00e1c..6998c4fcc1 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/ShiftedUnitModification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/ShiftedUnitModification.lean @@ -17,12 +17,14 @@ No global path is glued here, and no path-space measurability, law, or Hunt-proc asserted. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped ENNReal NNReal namespace MarkovProcess -noncomputable section +section variable {Ω E : Type*} {mΩ : MeasurableSpace Ω} [MetricSpace E] [CompleteSpace E] [MeasurableSpace E] [BorelSpace E] [SecondCountableTopology E] @@ -102,3 +104,5 @@ theorem shiftedUnitDyadicFloorLimit_one end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryDenseTimeMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryDenseTimeMarginals.lean index e9e954d249..ad3a1a1003 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryDenseTimeMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryDenseTimeMarginals.lean @@ -14,6 +14,8 @@ at any dense-time coordinate when started from a live state. This is a finite-c it does not assert that a dense-time path has a continuous lifetime-path extension. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped ENNReal @@ -21,7 +23,7 @@ namespace MarkovProcess namespace SubMarkovKernelSemigroup namespace IsConservative -noncomputable section +section variable {D alpha : Type*} [MeasurableSpace alpha] [StandardBorelSpace (Cemetery alpha)] @@ -40,3 +42,5 @@ end end IsConservative end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeterySemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeterySemigroup.lean index c1a5181487..8da46fc036 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeterySemigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeterySemigroup.lean @@ -15,11 +15,13 @@ extension at every time turns any sub-Markov kernel semigroup into a conservative semigroup on the cemetery state space. -/ +noncomputable section PortComputability + open MeasureTheory open ProbabilityTheory open scoped ENNReal -noncomputable section +section namespace MarkovProcess @@ -194,7 +196,8 @@ theorem cemeterySemigroup_apply (t : NNReal) : theorem isConservative_cemeterySemigroup : (cemeterySemigroup P).IsConservative := by intro t z rw [cemeterySemigroup_apply] - exact (Kernel.isMarkovKernel_cemeteryExtension (P t) (P.isSubMarkovKernel t)).isProbabilityMeasure z |>.measure_univ + exact (Kernel.isMarkovKernel_cemeteryExtension (P t) (P.isSubMarkovKernel + t)).isProbabilityMeasure z |>.measure_univ /-- The cemetery state is absorbing at every time in the extension semigroup. -/ theorem cemeterySemigroup_absorbing (t : NNReal) : @@ -204,3 +207,7 @@ theorem cemeterySemigroup_absorbing (t : NNReal) : end SubMarkovKernelSemigroup end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/ConditionalKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/ConditionalKernel.lean index 39247b75f1..326ad20045 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/ConditionalKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/ConditionalKernel.lean @@ -14,12 +14,14 @@ This file augments finite prefix laws by their starting point and disintegrates a prefix and its next observation. It makes no infinite-process or path-regularity claim. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace SubMarkovKernelSemigroup -noncomputable section +section variable {D α : Type*} [MeasurableSpace α] @@ -137,3 +139,5 @@ end IsConservative end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean index f1af188b6f..53c05de1b0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean @@ -48,9 +48,11 @@ private theorem stronglyMeasurable_coordinatePolynomial exact hprod.const_mul term.coefficient private theorem stronglyMeasurable_compactlySupported_pi - {I alpha : Type*} [Fintype I] [TopologicalSpace alpha] [MeasurableSpace alpha] + {I alpha : Type*} [Finite I] [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [T3Space alpha] [LocallyCompactSpace alpha] (f : C_c(I → alpha, ℝ)) : StronglyMeasurable f := by + classical + let := Fintype.ofFinite I have hexists (m : ℕ) : ∃ terms : List (PiContinuousMap.CoordinateProductTerm I alpha), ∀ x, ‖PiContinuousMap.coordinatePolynomial terms x - f x‖ < @@ -98,16 +100,14 @@ theorem pullbackPhysicalSetHomeomorph_apply /-- Pull a compactly supported test on dense-time labels back to physical-time labels. -/ noncomputable def pullbackPhysicalSetCompactTest - {alpha : Type*} [TopologicalSpace alpha] - (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) : + {alpha : Type*} [TopologicalSpace alpha] (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) : C_c(denseTimePhysicalSet J → alpha, ℝ) := f.comp (pullbackPhysicalSetHomeomorph J).toCocompactMap /-- Evaluation of a compact test pulled back to physical-time labels. -/ @[simp] theorem pullbackPhysicalSetCompactTest_apply - {alpha : Type*} [TopologicalSpace alpha] [T2Space alpha] - (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) + {alpha : Type*} [TopologicalSpace alpha] (J : Finset DenseTime) (f : C_c(J → alpha, ℝ)) (path : denseTimePhysicalSet J → alpha) : pullbackPhysicalSetCompactTest J f path = f (pullbackPhysicalSet J path) := by rw [pullbackPhysicalSetCompactTest] diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalReindex.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalReindex.lean index f205893676..ae868955be 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalReindex.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalReindex.lean @@ -13,9 +13,11 @@ file records the induced measurable path reindexing and its compatibility with c evaluation. No probability-law or Markov claim is made. -/ +noncomputable section PortComputability + namespace MarkovProcess -noncomputable section +section namespace DenseTime @@ -84,3 +86,5 @@ theorem pullbackPhysicalSet_evaluation (I : Finset DenseTime) end DenseTimePath end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean index 2cf8eb84ca..38aef371da 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean @@ -14,12 +14,14 @@ enumeration, with coordinates retained in enumeration order. The enumeration nee the order of physical time. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace SubMarkovKernelSemigroup -noncomputable section +section variable {D α : Type*} [MeasurableSpace α] @@ -117,3 +119,5 @@ end IsConservative end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean index 9f93e4ea8a..241ab4fa14 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean @@ -13,6 +13,8 @@ This file identifies the result of adjoining one conditionally sampled observati augmented finite history. It makes no infinite-process or path-regularity claim. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace ProbabilityTheory.Kernel @@ -20,8 +22,7 @@ namespace ProbabilityTheory.Kernel private theorem step_transport {X H Z Y T : Type*} [MeasurableSpace X] [MeasurableSpace H] [MeasurableSpace Z] [MeasurableSpace Y] [MeasurableSpace T] - (κ : Kernel X Z) - (η : Kernel Z Y) [IsSFiniteKernel η] (E : H ≃ᵐ Z) + (κ : Kernel X Z) (η : Kernel Z Y) [IsSFiniteKernel η] (E : H ≃ᵐ Z) (g : H × Y → T) (hg : Measurable g) (q : Z × Y → T) (hcompat : g ∘ Prod.map E.symm id = q) : (((Kernel.id ×ₖ η.comap E E.measurable) ∘ₖ κ.map E.symm).map g) = @@ -40,11 +41,12 @@ private theorem step_transport {X H Z Y T : Type*} rw [hcomap] rw [← Kernel.map_id' η] rw [Kernel.map_prod_map] - rw [← Kernel.map_comp] - rw [← Kernel.map_comp_right] - rw [Kernel.map_id'] - change (Kernel.id ×ₖ η ∘ₖ κ).map (g ∘ Prod.map E.symm id) = _ - rw [hcompat] + · rw [← Kernel.map_comp] + · rw [← Kernel.map_comp_right] + · rw [Kernel.map_id'] + change (Kernel.id ×ₖ η ∘ₖ κ).map (g ∘ Prod.map E.symm id) = _ + rw [hcompat] + all_goals first | exact hg | fun_prop all_goals first | exact hg | fun_prop private theorem prod_comp_prod_map_prodAssoc {X A B : Type*} @@ -117,7 +119,7 @@ end DenseTimeHistory namespace SubMarkovKernelSemigroup -noncomputable section +section variable {D α : Type*} [MeasurableSpace α] @@ -161,23 +163,25 @@ theorem augmentedPrefixKernel_step (P : SubMarkovKernelSemigroup α) have hq : q = r ∘ MeasurableEquiv.prodAssoc := by rfl rw [hq, Kernel.map_comp_right] - rw [Kernel.prod_comp_prod_map_prodAssoc] - rw [compProd_observationCondKernel P hP e ι n] - rw [nextObservationJoint] - rw [Kernel.mapOfMeasurable_eq_map] - rw [← Kernel.map_id' Kernel.id] - rw [Kernel.map_prod_map] - rw [← Kernel.map_comp_right] - change (Kernel.id ×ₖ denseTimePrefixKernel P e ι (n + 1)).map - (r ∘ Prod.map id (DenseTimeHistory.splitLast n)) = _ - have hr : r ∘ Prod.map id (DenseTimeHistory.splitLast n) = - (DenseTimeHistory.historyEquiv (n + 1)).symm := by - funext z - dsimp only [r, Function.comp_apply, Prod.map_apply, id_eq] - change (DenseTimeHistory.historyEquiv (n + 1)).symm - (z.1, (DenseTimeHistory.splitLast n).symm (DenseTimeHistory.splitLast n z.2)) = _ - rw [MeasurableEquiv.symm_apply_apply] - rw [hr, augmentedPrefixKernel, Kernel.mapOfMeasurable_eq_map] + · rw [Kernel.prod_comp_prod_map_prodAssoc] + rw [compProd_observationCondKernel P hP e ι n] + rw [nextObservationJoint] + rw [Kernel.mapOfMeasurable_eq_map] + rw [← Kernel.map_id' Kernel.id] + rw [Kernel.map_prod_map] + · rw [← Kernel.map_comp_right] + · change (Kernel.id ×ₖ denseTimePrefixKernel P e ι (n + 1)).map + (r ∘ Prod.map id (DenseTimeHistory.splitLast n)) = _ + have hr : r ∘ Prod.map id (DenseTimeHistory.splitLast n) = + (DenseTimeHistory.historyEquiv (n + 1)).symm := by + funext z + dsimp only [r, Function.comp_apply, Prod.map_apply, id_eq] + change (DenseTimeHistory.historyEquiv (n + 1)).symm + (z.1, (DenseTimeHistory.splitLast n).symm (DenseTimeHistory.splitLast n z.2)) = _ + rw [MeasurableEquiv.symm_apply_apply] + rw [hr, augmentedPrefixKernel, Kernel.mapOfMeasurable_eq_map] + all_goals fun_prop + all_goals fun_prop all_goals fun_prop end IsConservative @@ -185,3 +189,5 @@ end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Shift.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Shift.lean index 87435231a5..cf86295e34 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Shift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Shift.lean @@ -14,9 +14,11 @@ induced shift of dense-time paths. Restriction of a continuous path commutes wi No probability law or Markov property is asserted. -/ +noncomputable section PortComputability + namespace MarkovProcess -noncomputable section +section namespace DenseTime @@ -87,3 +89,5 @@ theorem denseRestriction_shift (s : DenseTime) (omega : ContinuousPath alpha) : end ContinuousPath end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean index 1ef29f313c..e01e703e1f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean @@ -14,13 +14,15 @@ Mathlib's Ionescu--Tulcea construction, starts the resulting trajectory at a det and reindexes its positive coordinates by a countable dense-time enumeration. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace SubMarkovKernelSemigroup namespace IsConservative -noncomputable section +section variable {D α : Type*} [MeasurableSpace α] [StandardBorelSpace α] [Nonempty α] @@ -143,7 +145,7 @@ private theorem denseTimeHistoryMeasurableEquiv_rawTrajAppend (n : ℕ) : let j : Set.Iic n := ⟨i, hil⟩ simp only [rawTrajAppend, Function.comp_apply, IicProdIoc_def, MeasurableEquiv.piSingleton] - rw [dif_pos hil] + rw [dite_eq_left hil] rw [DenseTimeHistory.append_apply_castSucc n (denseTimeHistoryMeasurableEquiv n z.1) z.2 j] rfl @@ -151,8 +153,7 @@ private theorem denseTimeHistoryMeasurableEquiv_rawTrajAppend (n : ℕ) : private theorem transport_traj_step {X H Z Y T : Type*} [MeasurableSpace X] [MeasurableSpace H] [MeasurableSpace Z] [MeasurableSpace Y] [MeasurableSpace T] - (κ : Kernel X Z) - (η : Kernel Z Y) [IsSFiniteKernel η] (E : H ≃ᵐ Z) + (κ : Kernel X Z) (η : Kernel Z Y) [IsSFiniteKernel η] (E : H ≃ᵐ Z) (g : H × Y → T) (hg : Measurable g) (q : Z × Y → T) (hcompat : g ∘ Prod.map E.symm id = q) : (((Kernel.id ×ₖ η.comap E E.measurable) ∘ₖ κ.map E.symm).map g) = @@ -168,8 +169,8 @@ private theorem transport_traj_step {X H Z Y T : Type*} rw [E.apply_symm_apply] rw [hcomap, ← Kernel.map_id' η, Kernel.map_prod_map, ← Kernel.map_comp, ← Kernel.map_comp_right, Kernel.map_id'] - change (Kernel.id ×ₖ η ∘ₖ κ).map (g ∘ Prod.map E.symm id) = _ - rw [hcompat] + · change (Kernel.id ×ₖ η ∘ₖ κ).map (g ∘ Prod.map E.symm id) = _ + rw [hcompat] all_goals first | exact hg | fun_prop omit [StandardBorelSpace α] [Nonempty α] in @@ -209,12 +210,12 @@ theorem partialTraj_map_denseTimeHistoryMeasurableEquiv rw [initialTrajHistoryKernel, Kernel.deterministic_map, hconst, Kernel.id, Kernel.deterministic_prod_deterministic, Kernel.mapOfMeasurable_eq_map, Kernel.deterministic_map] - apply Kernel.deterministic_congr - funext x i - rcases i with ⟨i, hi⟩ - have hi0 : i = 0 := Nat.eq_zero_of_le_zero hi - subst i - rfl + · apply Kernel.deterministic_congr + funext x i + rcases i with ⟨i, hi⟩ + have hi0 : i = 0 := Nat.eq_zero_of_le_zero hi + subst i + rfl all_goals fun_prop | succ n ih => let : IsMarkovKernel (denseStep P hP e ι n) := @@ -351,3 +352,5 @@ end end IsConservative end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TrajectoryMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TrajectoryMarginals.lean index d2c032455a..1c6820effb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TrajectoryMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TrajectoryMarginals.lean @@ -12,13 +12,15 @@ This file identifies every coordinate marginal of the dense-time trajectory kern corresponding transition kernel. The result is derived from the exact finite-prefix identity. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace SubMarkovKernelSemigroup namespace IsConservative -noncomputable section +section variable {D α : Type*} [MeasurableSpace α] [StandardBorelSpace α] [Nonempty α] @@ -108,3 +110,5 @@ end end IsConservative end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TwoPointMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TwoPointMarginals.lean index f50164fe6f..0a0b57c9cc 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TwoPointMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TwoPointMarginals.lean @@ -25,12 +25,14 @@ No continuity, modification, Markov-property, or path-regularity statement is pr the two-point law and the moment estimate it transports. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped ENNReal NNReal namespace MarkovProcess -noncomputable section +section namespace DenseTime @@ -189,7 +191,7 @@ private theorem denseTimeTrajectory_map_pair_aux intro m have hm : m = 0 := Subsingleton.elim m 0 subst hm - simpa only [Fin.castSucc_zero, if_pos rfl, Fin.succ_zero_eq_one] using! hab) with hselect + simpa only [Fin.castSucc_zero, ite_eq_left rfl, Fin.succ_zero_eq_one] using! hab) with hselect have hpair2 : Measurable (fun path : Fin 2 → alpha ↦ (path 0, path 1)) := by fun_prop have hstep4 : (fun path : Fin 2 → alpha ↦ (path 0, path 1)) ∘ @@ -334,3 +336,5 @@ end SubMarkovKernelSemigroup end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean index 201dbc626a..67ae638541 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean @@ -34,16 +34,19 @@ the form that Mathlib's `Mathlib/Probability/BrownianMotion/Basic.lean` proves e own definition of `IsBrownianReal` (`HasIndepIncrements.isPreBrownianReal_of_hasLaw` and the converse lemmas `IsPreBrownianReal.hasLaw_eval`, `IsPreBrownianReal.hasIndepIncrements`). Neither is available at the pinned revision, and `IsBrownianReal` here is stated through Gaussian -marginals and independent increments, not through a projective family. Only one space dimension is treated, and no +marginals and independent increments, not through a projective family. Only one space dimension + is treated, and no Levy characterization, quadratic variation, or stochastic integral is asserted. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped ENNReal NNReal namespace MarkovProcess -noncomputable section +section section MarkovProperty @@ -205,7 +208,11 @@ theorem brownianMotion_map_incrementsMap : ∀ {n : ℕ} {s : Fin n → NNReal}, have : IsProbabilityMeasure ((brownianMotion x).map (fun omega ↦ incrementsMap x (fun i ↦ omega (s i)))) := inferInstance - exact (Measure.pi_eq fun A _ ↦ by simp).symm + exact (Measure.pi_eq fun A _ ↦ by + have hpi : Set.univ.pi A = Set.univ := by + ext p + simp [Set.mem_pi] + simp [hpi]).symm | succ n ih => intro s hs x have hs' : Monotone (fun i : Fin n ↦ s i.succ - s 0) := fun a b hab ↦ @@ -230,9 +237,9 @@ theorem brownianMotion_map_incrementsMap : ∀ {n : ℕ} {s : Fin n → NNReal}, have harg : (fun i : Fin n ↦ (ContinuousPath.shift (s 0) omega) (s i.succ - s 0)) = Fin.tail (fun i ↦ omega (s i)) := by funext i - show omega (s 0 + (s i.succ - s 0)) = omega (s i.succ) + change omega (s 0 + (s i.succ - s 0)) = omega (s i.succ) rw [add_tsub_cancel_of_le (hs (Fin.zero_le _))] - show incrementsMap x (fun i ↦ omega (s i)) = + change incrementsMap x (fun i ↦ omega (s i)) = Fin.cons (omega (s 0) - x) (incrementsMap (omega (s 0)) (fun i : Fin n ↦ (ContinuousPath.shift (s 0) omega) (s i.succ - s 0))) @@ -372,7 +379,7 @@ theorem hasIndepIncrements_brownianMotion (x : ℝ) : fun (i : Fin n) (omega : ContinuousPath ℝ) ↦ omega (t i.succ) - omega (t i.castSucc) := by funext i omega ring - show iIndepFun (fun (i : Fin n) (omega : ContinuousPath ℝ) ↦ + change iIndepFun (fun (i : Fin n) (omega : ContinuousPath ℝ) ↦ (omega (t i.succ) - x) - (omega (t i.castSucc) - x)) (brownianMotion x) rw [hsimp] have hmeasi : ∀ i : Fin n, Measurable (fun omega : ContinuousPath ℝ ↦ @@ -427,3 +434,5 @@ end Identification end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/Drift.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/Drift.lean index f02f75f419..5dd4eb795b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/Drift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/Drift.lean @@ -19,12 +19,14 @@ theorem are satisfiable by a semigroup that genuinely moves. Nothing here is cl semigroup with a nonzero diffusion part; for that see `MarkovProcess.Examples.HeatSemigroup`. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped ENNReal NNReal ZeroAtInfty namespace MarkovProcess -noncomputable section +section variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [FiniteDimensional ℝ E] [MeasurableSpace E] [BorelSpace E] @@ -122,7 +124,7 @@ theorem hasContinuousC0Orbits_driftSemigroup (v : E) : ((driftSemigroup v).c0Operator (mapsC0_driftSemigroup v) b f) ≤ eps / 2 := by rw [← ZeroAtInftyContinuousMap.dist_toBCF_eq_dist] refine (BoundedContinuousFunction.dist_le (le_of_lt (half_pos heps))).2 fun x ↦ ?_ - show dist ((driftSemigroup v).c0Operator (mapsC0_driftSemigroup v) a f x) + change dist ((driftSemigroup v).c0Operator (mapsC0_driftSemigroup v) a f x) ((driftSemigroup v).c0Operator (mapsC0_driftSemigroup v) b f x) ≤ eps / 2 rw [SubMarkovKernelSemigroup.c0Operator_apply, SubMarkovKernelSemigroup.c0Operator_apply, kernelIntegral_driftSemigroup_apply, kernelIntegral_driftSemigroup_apply] @@ -208,7 +210,7 @@ private theorem ae_eq_driftPath (v : E) (x : E) : set y := driftPath v x (DenseTime.castOrderEmbedding q) with hy have hsingleton : MeasurableSet ({y}ᶜ : Set E) := (isClosed_singleton (x := y)).measurableSet.compl - show mu ((fun omega : ContinuousPath E ↦ + change mu ((fun omega : ContinuousPath E ↦ omega (DenseTime.castOrderEmbedding q)) ⁻¹' ({y}ᶜ : Set E)) = 0 rw [← Measure.map_apply hmeas hsingleton, hmapx, Measure.dirac_apply' y hsingleton, Set.indicator_of_notMem (by simp only [Set.mem_compl_iff, Set.mem_singleton_iff, @@ -242,3 +244,5 @@ end Process end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatGenerator.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatGenerator.lean index eb365135df..b8f9b537df 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatGenerator.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatGenerator.lean @@ -43,12 +43,14 @@ contained), and nothing is claimed in dimension greater than one or for a functi stated smoothness class. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped NNReal ZeroAtInfty namespace MarkovProcess -noncomputable section +section section Taylor @@ -424,3 +426,5 @@ end C0 end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean index b270620858..d872229865 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean @@ -25,10 +25,12 @@ process started at a live point almost surely never reaches the added point (`ae_exitTime_eq_top_heatResolvent`). -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory Set Topology open scoped ENNReal NNReal ZeroAtInfty -noncomputable section +section namespace MarkovProcess @@ -97,6 +99,7 @@ theorem hasLocalKolmogorovMoments_onePointKernelSemigroup_heatResolvent : heatExhaustion_pos lipschitzWith_one_heatExhaustion isCompact_heatExhaustion_superlevel heatResolvent.onePointKernelSemigroup.HasLocalKolmogorovMoments 4 2 gaussianFourthMoment 16 := by + have : MeasurableSingletonClass (OnePoint ℝ) := inferInstance let := OnePoint.exhaustionMetricSpace heatExhaustion continuous_heatExhaustion heatExhaustion_pos lipschitzWith_one_heatExhaustion isCompact_heatExhaustion_superlevel refine ⟨by norm_num, by norm_num, ?_, ?_⟩ @@ -167,3 +170,7 @@ theorem ae_exitTime_eq_top_heatResolvent (x : ℝ) : exact isConservative_heatSemigroup.ofReal_mul_kernelResolvent_one one_pos x) end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatSemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatSemigroup.lean index fc22941077..60ed1320f6 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatSemigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatSemigroup.lean @@ -34,12 +34,14 @@ Nothing in this file asserts independence of increments; that is proved in `MarkovProcess.Examples.BrownianMotion`. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped ENNReal NNReal ZeroAtInfty namespace MarkovProcess -noncomputable section +section section Gaussian @@ -264,7 +266,7 @@ theorem exists_norm_c0Operator_sub_le_heatSemigroup (f : C₀(ℝ, ℝ)) {eps : _ = delta0 := div_mul_cancel₀ delta0 (ne_of_gt hR) rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] refine (BoundedContinuousFunction.norm_le (le_of_lt heps)).2 fun x ↦ ?_ - show ‖heatSemigroup.c0Operator mapsC0_heatSemigroup h f x - f x‖ ≤ eps + change ‖heatSemigroup.c0Operator mapsC0_heatSemigroup h f x - f x‖ ≤ eps rw [SubMarkovKernelSemigroup.c0Operator_apply, kernelIntegral_heatSemigroup] have hsub : (∫ z, f (x + Real.sqrt h * z) ∂(gaussianReal 0 1)) - f x = ∫ z, (f (x + Real.sqrt h * z) - f x) ∂(gaussianReal 0 1) := by @@ -537,3 +539,5 @@ end Process end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/Identity.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/Identity.lean index e1210891ce..4808206d7e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/Identity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/Identity.lean @@ -19,12 +19,14 @@ nothing about any other semigroup, and it makes no claim about a semigroup that (see `MarkovProcess.Examples.Drift` for that). -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped ENNReal NNReal ZeroAtInfty namespace MarkovProcess -noncomputable section +section section Definition @@ -72,6 +74,7 @@ theorem mapsC0_idSemigroup : (idSemigroup (alpha := alpha)).MapsC0 := by variable [LocallyCompactSpace alpha] +omit [LocallyCompactSpace alpha] in /-- The identity semigroup is a Feller semigroup: its `C₀` operators are all the identity, so they map `C₀` into itself and have constant, hence continuous, time orbits. -/ theorem isFellerKernelSemigroup_idSemigroup : @@ -122,9 +125,7 @@ theorem kolmogorovRegular_idSemigroup : /-- **The main theorem, applied to the identity semigroup.** There is exactly one Markov kernel from the state space to continuous paths whose finite-dimensional distributions are those of the -identity semigroup. In particular the hypotheses of -`SubMarkovKernelSemigroup.IsFellerKernelSemigroup.existsUnique_continuousProcess_of_hasKolmogorovMoments` -are jointly satisfiable. -/ +identity semigroup. This supplies a model of the main existence theorem’s hypotheses. -/ theorem existsUnique_continuousProcess_idSemigroup : ∃! Q : Kernel alpha (ContinuousPath alpha), IsMarkovKernel Q ∧ ∀ I : Finset NNReal, @@ -192,3 +193,5 @@ end Process end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Convergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Convergence.lean index 41907f3346..edf7f69bde 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Convergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Convergence.lean @@ -48,6 +48,7 @@ variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] variable {iota : Type*} {l : Filter iota} +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- **Strong convergence of the `C₀` semigroups propagates through the backward recursion.** For a fixed nonempty ordered family of times and fixed one-coordinate factors, the backward recursions of a family of Feller kernel semigroups converge in the `C₀` norm to the backward @@ -72,6 +73,7 @@ theorem tendsto_backwardC0_of_tendsto_c0Semigroup (fun i ↦ ((hP i).c0Semigroup).norm_operator_le_one _) (hconv (times 0) _) (tendsto_const_nhds.mul (ih times.relativeTail (Fin.tail factors))) +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- **Uniform convergence of the coordinate-product integrals.** Strong convergence of the `C₀` semigroups makes the finite-time integral of a product of one-coordinate `C₀` functions converge uniformly in the starting point. -/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean index 5403d30d65..fd9bb643e1 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean @@ -61,6 +61,7 @@ private theorem isFiniteKernel_finiteTimeKernel rw [finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map] infer_instance +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- Evaluation of the backward `C₀` recursion is the coordinate-product integral against the finite-time kernel. -/ theorem IsFellerKernelSemigroup.backwardC0_apply_eq_integral_finiteTimeKernel diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Recursion.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Recursion.lean index bb6ac8b745..80eea01169 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Recursion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Recursion.lean @@ -38,6 +38,7 @@ noncomputable def IsFellerKernelSemigroup.backwardC0 hP.c0Semigroup (times 0) (factors 0 * hP.backwardC0 times.relativeTail (Fin.tail factors)) +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- The backward recursion for a singleton family is one Feller-semigroup application. -/ @[simp] theorem IsFellerKernelSemigroup.backwardC0_zero @@ -46,6 +47,7 @@ theorem IsFellerKernelSemigroup.backwardC0_zero hP.backwardC0 times factors = hP.c0Semigroup (times 0) (factors 0) := rfl +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- At a successor length, the backward recursion multiplies the first factor by the recursively evolved relative tail before applying the first transition. -/ @[simp] @@ -57,6 +59,7 @@ theorem IsFellerKernelSemigroup.backwardC0_succ (factors 0 * hP.backwardC0 times.relativeTail (Fin.tail factors)) := rfl +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- The backward recursion is continuous in the `C₀` norm under coordinatewise convergence of a nonempty ordered time family. -/ theorem IsFellerKernelSemigroup.tendsto_backwardC0 diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean index e7efc79571..6d7149c119 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean @@ -82,6 +82,7 @@ private theorem integrable_coordinatePolynomial rw [PiContinuousMap.coordinatePolynomial_cons] exact (integrable_coordinateProductTerm term mu).add ih +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- Finite-time integrals of an explicit coordinate polynomial vary continuously under coordinatewise convergence of the ordered observation times. -/ theorem IsFellerKernelSemigroup.tendsto_integral_coordinatePolynomial_finiteTimeKernel diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinateProductContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinateProductContinuity.lean index b4086989c2..ec7e3d5489 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinateProductContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinateProductContinuity.lean @@ -28,6 +28,7 @@ namespace MarkovProcess.SubMarkovKernelSemigroup variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- The finite-time integral of a coordinate-product term varies continuously when every ordered time coordinate varies continuously. -/ theorem IsFellerKernelSemigroup.tendsto_integral_coordinateProductTerm_finiteTimeKernel diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeContinuityBase.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeContinuityBase.lean index e77ad56f26..6c6f8d53de 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeContinuityBase.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeContinuityBase.lean @@ -24,6 +24,7 @@ namespace SubMarkovKernelSemigroup variable {alpha X : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- Kernel integrals of `C₀` tests against singleton finite-time laws vary continuously with the unique observation time. -/ theorem IsFellerKernelSemigroup.tendsto_kernelIntegral_finiteTimeKernel_one_map_eval diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean index 47021f3160..81e354c126 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean @@ -158,6 +158,7 @@ private theorem integral_coordinateProductTerm_eq_coefficient rw [integral_congr_ae (ae_of_all _ hTerm)] simp only [integral_const, probReal_univ, one_smul] +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- A coordinate-product term with active coordinates integrates to its coefficient times the backward `C₀` recursion at the active times. -/ private theorem integral_coordinateProductTerm_eq_backwardC0 @@ -215,6 +216,7 @@ end ActiveReduction variable {P : iota → SubMarkovKernelSemigroup alpha} {Q : SubMarkovKernelSemigroup alpha} +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- **Uniform convergence of the finite-time integral of a coordinate-product term.** -/ theorem tendstoUniformly_integral_coordinateProductTerm_finiteTimeKernel (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hPc : ∀ i, (P i).IsConservative) @@ -255,6 +257,7 @@ theorem tendstoUniformly_integral_coordinateProductTerm_finiteTimeKernel (times.restrict (activeEmbedding term.factors hk)) (activeFactor term.factors hk))) term.coefficient +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- **Uniform convergence of the finite-time integral of a coordinate polynomial.** -/ theorem tendstoUniformly_integral_coordinatePolynomial_finiteTimeKernel (hP : ∀ i, (P i).IsFellerKernelSemigroup) (hPc : ∀ i, (P i).IsConservative) diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean index 60cf4cdcc2..6bfb77c500 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean @@ -161,6 +161,7 @@ private theorem stronglyMeasurable_compactlySupported_fin_joint rw [Real.dist_eq, sub_zero, abs_of_pos (by positivity)] at hm exact (hterms m x).trans_le hm.le +omit [LocallyCompactSpace alpha] [T2Space alpha] in private theorem tendsto_integral_coordinateProductTerm_joint {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) (hP : P.IsConservative) {X : Type*} {l : Filter X} {n : ℕ} @@ -239,6 +240,7 @@ private theorem tendsto_integral_coordinateProductTerm_joint exact tendsto_c0_apply_of_tendsto (hFeller.tendsto_backwardC0 htimes factors) hx +omit [LocallyCompactSpace alpha] [T2Space alpha] in private theorem tendsto_integral_coordinatePolynomial_joint {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) (hP : P.IsConservative) {X : Type*} {l : Filter X} {n : ℕ} diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeKernelContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeKernelContinuity.lean index f7a830c4a3..3b2928e00e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeKernelContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeKernelContinuity.lean @@ -68,6 +68,7 @@ namespace SubMarkovKernelSemigroup variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- Feller continuity permits both the time and the `C₀` integrand to vary. -/ theorem IsFellerKernelSemigroup.tendsto_kernelIntegral_c0 {P : SubMarkovKernelSemigroup alpha} (hP : P.IsFellerKernelSemigroup) @@ -83,6 +84,7 @@ theorem IsFellerKernelSemigroup.tendsto_kernelIntegral_c0 simpa only [IsFellerKernelSemigroup.c0Semigroup_apply_apply] using! heval.continuousAt.tendsto.comp haction +omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- The two-transition backward recursion is continuous for product `C₀` tests. The inner transition acts on `g`; multiplication by the first-coordinate test `f` gives the varying `C₀` test seen by the outer transition. This is the successor-step analytic mechanism in the diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/Resolvent.lean index de32463224..3121096370 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/Resolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/Resolvent.lean @@ -49,6 +49,7 @@ variable {α : Type*} [TopologicalSpace α] [MeasurableSpace α] [BorelSpace α] [LocallyCompactSpace α] [T2Space α] variable {P : SubMarkovKernelSemigroup α} (hP : P.IsFellerKernelSemigroup) +omit [LocallyCompactSpace α] [T2Space α] in /-- **The resolvent of the `C₀` semigroup, evaluated at a point**: the Laplace transform of the transition integrals. -/ theorem IsFellerKernelSemigroup.resolvent_apply_apply (μ : Semigroup.PositiveShift) @@ -73,6 +74,7 @@ noncomputable def IsFellerKernelSemigroup.positiveC0ContractiveResolvent : hP.resolvent_apply_apply] exact integral_nonneg fun t ↦ mul_nonneg (Real.exp_pos _).le (integral_nonneg hf) +omit [LocallyCompactSpace α] [T2Space α] in /-- Generating a semigroup from the positive resolvent of a Feller semigroup recovers its original `C₀` semigroup. -/ theorem IsFellerKernelSemigroup.generatedSemigroup_positiveC0ContractiveResolvent : @@ -80,6 +82,7 @@ theorem IsFellerKernelSemigroup.generatedSemigroup_positiveC0ContractiveResolven hP.c0Semigroup := hP.c0Semigroup.generatedSemigroup_toContractiveResolvent +omit [LocallyCompactSpace α] [T2Space α] in /-- The real kernel resolvent of a `C₀` observable is the pointwise resolvent of the associated `C₀` semigroup. -/ theorem IsFellerKernelSemigroup.kernelResolventReal_eq_resolvent @@ -89,6 +92,7 @@ theorem IsFellerKernelSemigroup.kernelResolventReal_eq_resolvent hP.c0Semigroup.resolvent μ f x := by exact (hP.resolvent_apply_apply μ f x).symm +omit [LocallyCompactSpace α] [T2Space α] in /-- The extended-real kernel resolvent of a nonnegative `C₀` observable agrees with the pointwise `C₀`-semigroup resolvent after applying `ENNReal.ofReal`. -/ theorem IsFellerKernelSemigroup.kernelResolvent_ofReal_eq_resolvent @@ -146,6 +150,7 @@ theorem IsFellerKernelSemigroup.kernelSemigroup_positiveC0ContractiveResolvent hP.generatedSemigroup_positiveC0ContractiveResolvent, hP.c0Semigroup_apply_apply t g x] rfl +omit [LocallyCompactSpace α] [T2Space α] in /-- **The generator domain of the `C₀` semigroup is the range of its resolvent**, at every positive shift. -/ theorem IsFellerKernelSemigroup.mem_generatorDomain_iff_exists_resolvent diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean index 52dc57dfd6..89bb37eb4a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean @@ -68,11 +68,13 @@ section Feller variable [LocallyCompactSpace α] [T2Space α] +omit [LocallyCompactSpace α] [T2Space α] in /-- A combined Feller predicate supplies its spatial `C₀` property. -/ theorem IsFellerKernelSemigroup.mapsC0 {P : SubMarkovKernelSemigroup α} (hP : P.IsFellerKernelSemigroup) : P.MapsC0 := hP.choose +omit [LocallyCompactSpace α] [T2Space α] in /-- A combined Feller predicate supplies continuity of the corresponding `C₀` orbits. -/ theorem IsFellerKernelSemigroup.hasContinuousC0Orbits {P : SubMarkovKernelSemigroup α} (hP : P.IsFellerKernelSemigroup) : P.HasContinuousC0Orbits hP.mapsC0 := @@ -84,6 +86,7 @@ noncomputable def IsFellerKernelSemigroup.c0Semigroup {P : SubMarkovKernelSemigr Semigroup.StronglyContinuousContractionSemigroup C₀(α, ℝ) := P.c0Semigroup hP.mapsC0 hP.hasContinuousC0Orbits +omit [LocallyCompactSpace α] [T2Space α] in @[simp] theorem IsFellerKernelSemigroup.c0Semigroup_apply_apply {P : SubMarkovKernelSemigroup α} (hP : P.IsFellerKernelSemigroup) diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductNormalization.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductNormalization.lean index 34f53bae92..b4a63fcf0f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductNormalization.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductNormalization.lean @@ -50,8 +50,8 @@ private theorem prod_update_mul (i : Fin n) (a : ℝ) (v : Fin n → ℝ) : funext j by_cases h : i = j · subst j - simp only [Function.update_self, if_pos] - · simp only [Function.update, h, Ne.symm h, dite_false, if_false, one_mul] + simp only [Function.update_self, ite_eq_left] + · simp only [Function.update, h, Ne.symm h, dite_false, ite_false, one_mul] rw [hfun, Finset.prod_mul_distrib, Fintype.prod_ite_eq] private theorem evalOptionalFactor_merge (f : C₀(alpha, ℝ)) diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteSetKernelShift.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteSetKernelShift.lean index cae3a260cb..fe69dbf3e3 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteSetKernelShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteSetKernelShift.lean @@ -13,12 +13,14 @@ This file transports the finite-set kernel translation law from physical nonnega to finite sets of dense times, using the canonical coordinate reindexings. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace SubMarkovKernelSemigroup -noncomputable section +section namespace IsConservative @@ -70,3 +72,5 @@ end IsConservative end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteShift.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteShift.lean index 8dddd418fe..4d36bcc6df 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteShift.lean @@ -13,9 +13,11 @@ provides the resulting coordinate equivalence and relates restriction after shif path to restriction on the translated finite set. It makes no probability-law or Markov claim. -/ +noncomputable section PortComputability + namespace MarkovProcess -noncomputable section +section namespace DenseTime @@ -89,3 +91,5 @@ theorem restrict_shift (s : DenseTime) (I : Finset DenseTime) (path : DenseTime end DenseTimePath end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean index ff2897c545..82abd128a0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean @@ -52,7 +52,7 @@ theorem exists_coordinate_cutoffs_of_hasCompactSupport exact hφone i ⟨x, hx, rfl⟩ · intro x hx i hi apply subset_tsupport - show φ i (x i) ≠ 0 + change φ i (x i) ≠ 0 rw [hφone i ⟨x, hx, rfl⟩] exact one_ne_zero · intro x hx @@ -61,14 +61,17 @@ theorem exists_coordinate_cutoffs_of_hasCompactSupport obtain ⟨i, hi⟩ := hx exact Finset.prod_eq_zero (Finset.mem_univ i) (image_eq_zero_of_notMem_tsupport hi) +omit [Fintype I] in /-- A compactly supported continuous function on a finite product can be approximated uniformly on the whole product by the coordinate `C₀` algebra. -/ -theorem exists_coordinateC0Subalgebra_near_compactlySupported +theorem exists_coordinateC0Subalgebra_near_compactlySupported [Finite I] [T3Space α] [LocallyCompactSpace α] (f : C_c(I → α, ℝ)) {epsilon : ℝ} (hepsilon : 0 < epsilon) : ∃ h ∈ coordinateC0Subalgebra (I := I) (α := α), ∀ x, ‖h x - f x‖ < epsilon := by classical + let := Fintype.ofFinite I + classical obtain ⟨φ, B, hBcompact, hφrange, hcutoff_one, hsupport_subset, hcutoff_zero⟩ := exists_coordinate_cutoffs_of_hasCompactSupport f let q : C(I → α, ℝ) := ∏ i, coordinate i (((φ i : C₀(α, ℝ)) : C(α, ℝ))) diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean index 7263b7ce52..207d186c6c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean @@ -75,7 +75,8 @@ theorem coordinatePolynomial_cons (t : CoordinateProductTerm I α) @[simp] theorem coordinatePolynomial_append (left right : List (CoordinateProductTerm I α)) : - coordinatePolynomial (left ++ right) = coordinatePolynomial left + coordinatePolynomial right := by + coordinatePolynomial (left ++ right) = coordinatePolynomial left + coordinatePolynomial + right := by simp only [coordinatePolynomial, List.map_append, List.sum_append] /-- Multiply two terms by multiplying coefficients and concatenating their factor lists. -/ @@ -150,11 +151,13 @@ theorem exists_coordinateProductTerms_of_mem_coordinateC0Subalgebra /-- Every compactly supported continuous finite-product test is uniformly approximable on the whole product by an explicit finite sum of scalar multiples of coordinate products. -/ theorem exists_coordinateProductTerms_near_compactlySupported - [Fintype I] [T3Space α] [LocallyCompactSpace α] + [Finite I] [T3Space α] [LocallyCompactSpace α] (f : C_c(I → α, ℝ)) {epsilon : ℝ} (hepsilon : 0 < epsilon) : ∃ terms : List (CoordinateProductTerm I α), ∀ x, ‖(terms.map fun t ↦ t.coefficient * (t.factors.map fun p ↦ p.2 (x p.1)).prod).sum - f x‖ < epsilon := by + classical + let := Fintype.ofFinite I obtain ⟨h, hh, hnear⟩ := exists_coordinateC0Subalgebra_near_compactlySupported f hepsilon obtain ⟨terms, rfl⟩ := exists_coordinateProductTerms_of_mem_coordinateC0Subalgebra hh diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean index 91b20d6091..a8de81bb3f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean @@ -51,9 +51,11 @@ private theorem stronglyMeasurable_coordinatePolynomial exact hprod.const_mul term.coefficient private theorem stronglyMeasurable_compactlySupported_pi - {I alpha : Type*} [Fintype I] [TopologicalSpace alpha] [MeasurableSpace alpha] + {I alpha : Type*} [Finite I] [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [T3Space alpha] [LocallyCompactSpace alpha] (f : C_c(I → alpha, ℝ)) : StronglyMeasurable f := by + classical + let := Fintype.ofFinite I have hexists (m : ℕ) : ∃ terms : List (PiContinuousMap.CoordinateProductTerm I alpha), ∀ x, ‖PiContinuousMap.coordinatePolynomial terms x - f x‖ < @@ -99,15 +101,15 @@ theorem orderedPathToFiniteSetHomeomorph_apply /-- Pull a compactly supported test on finite-set coordinates back to increasing coordinates. -/ noncomputable def pullbackFiniteSetCompactTest - {alpha : Type*} [TopologicalSpace alpha] - (I : Finset NNReal) (f : C_c(I → alpha, ℝ)) : C_c(Fin I.card → alpha, ℝ) := + {alpha : Type*} [TopologicalSpace alpha] (I : Finset NNReal) + (f : C_c(I → alpha, ℝ)) : C_c(Fin I.card → alpha, ℝ) := f.comp (orderedPathToFiniteSetHomeomorph I).toCocompactMap /-- Evaluation of a compact test pulled back to increasing coordinates. -/ @[simp] theorem pullbackFiniteSetCompactTest_apply - {alpha : Type*} [TopologicalSpace alpha] [T2Space alpha] - (I : Finset NNReal) (f : C_c(I → alpha, ℝ)) (path : Fin I.card → alpha) : + {alpha : Type*} [TopologicalSpace alpha] (I : Finset NNReal) + (f : C_c(I → alpha, ℝ)) (path : Fin I.card → alpha) : pullbackFiniteSetCompactTest I f path = f (orderedPathToFiniteSet I path) := by rw [pullbackFiniteSetCompactTest] exact congr_arg f (orderedPathToFiniteSetHomeomorph_apply I path) diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelShift.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelShift.lean index 49852690d8..9101b4e66e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelShift.lean @@ -16,12 +16,14 @@ for conservative transition-kernel semigroups. It is finite-dimensional kernel it does not assert a path-space Markov property. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace SubMarkovKernelSemigroup -noncomputable section +section /-- The image of a finite set of nonnegative times under translation by `s`. -/ def finiteSetTranslate (s : NNReal) (I : Finset NNReal) : Finset NNReal := @@ -181,3 +183,5 @@ theorem map_castOrderEmbedding_addFinset (s : DenseTime) (I : Finset DenseTime) end DenseTime end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean index b4167ef252..4334cf07ed 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean @@ -220,8 +220,7 @@ private theorem map_compProd_prodMkLeft_right private theorem compProd_prodMkLeft_assoc {X A B C : Type*} [MeasurableSpace X] [MeasurableSpace A] [MeasurableSpace B] [MeasurableSpace C] - (kappa : Kernel X A) - (eta : Kernel A B) [IsSFiniteKernel eta] + (kappa : Kernel X A) (eta : Kernel A B) [IsSFiniteKernel eta] (xi : Kernel (A × B) C) [IsSFiniteKernel xi] : (kappa ⊗ₖ Kernel.prodMkLeft X (eta ⊗ₖ xi)).map MeasurableEquiv.prodAssoc.symm = diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelEquivariance.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelEquivariance.lean index 7e9fc27020..d75a70505c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelEquivariance.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelEquivariance.lean @@ -12,7 +12,8 @@ import Mathlib.MeasureTheory.Function.SpecialFunctions.Basic # Rescaled conjugation of finite-time kernels A sub-Markov kernel semigroup `P'` on a state space `beta` is the *rescaled conjugate* of `P` on -`alpha` when it is obtained from `P` by conjugating the state with a homeomorphism `e : alpha ≃ₜ beta` +`alpha` when it is obtained from `P` by conjugating the state with a homeomorphism `e : alpha ≃ₜ + beta` and speeding time up by a positive factor `c`, that is `P' t x = ((P (c * t)) (e.symm x)).map e`. This file transfers the finite-dimensional laws across such a relation. The main result is @@ -116,7 +117,7 @@ namespace SubMarkovKernelSemigroup elements, returns that element. -/ theorem finiteSetTimes_orderIsoOfFin_symm_apply (I : Finset NNReal) (t : I) : finiteSetTimes I ((I.orderIsoOfFin rfl).symm t) = (t : NNReal) := by - show I.orderEmbOfFin rfl ((I.orderIsoOfFin rfl).symm t) = (t : NNReal) + change I.orderEmbOfFin rfl ((I.orderIsoOfFin rfl).symm t) = (t : NNReal) rw [← Finset.coe_orderIsoOfFin_apply, OrderIso.apply_symm_apply] section CompProd @@ -156,7 +157,7 @@ theorem map_compProd_prodMkLeft_conjugate (kappa : Kernel X Y) [IsSFiniteKernel MeasureTheory.lintegral_map_equiv _ F] refine lintegral_congr fun y ↦ ?_ have hsection : MeasurableSet (Prod.mk (f y) ⁻¹' s) := measurable_prodMk_left hs - show eta y (Prod.mk y ⁻¹' ((fun z : Y × Z ↦ (f z.1, g z.2)) ⁻¹' s)) = + change eta y (Prod.mk y ⁻¹' ((fun z : Y × Z ↦ (f z.1, g z.2)) ⁻¹' s)) = ((Kernel.comap eta f' hf').map g) (f y) (Prod.mk (f y) ⁻¹' s) rw [Kernel.map_apply' _ hg _ hsection, Kernel.comap_apply, hleft y] rfl @@ -178,7 +179,8 @@ def IsRescaledConjugate (P : SubMarkovKernelSemigroup alpha) (P' : SubMarkovKern namespace IsRescaledConjugate -variable {P : SubMarkovKernelSemigroup alpha} {P' : SubMarkovKernelSemigroup beta} {e : alpha ≃ₜ beta} +variable {P : SubMarkovKernelSemigroup alpha} {P' : SubMarkovKernelSemigroup beta} {e : alpha ≃ₜ + beta} {c : NNReal} /-- The rescaled-conjugacy relation in kernel form: at every time the transition kernel of `P'` is @@ -270,7 +272,8 @@ section Moments variable {alpha beta : Type*} [PseudoEMetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [PseudoEMetricSpace beta] [MeasurableSpace beta] [BorelSpace beta] -variable {P : SubMarkovKernelSemigroup alpha} {P' : SubMarkovKernelSemigroup beta} {e : alpha ≃ₜ beta} +variable {P : SubMarkovKernelSemigroup alpha} {P' : SubMarkovKernelSemigroup beta} {e : alpha ≃ₜ + beta} {c : NNReal} /-- **Transfer of the Kolmogorov moment criterion.** If the state map `e` is an isometry, then diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/MeasureFiniteRestrictionIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/MeasureFiniteRestrictionIdentification.lean index 0f8187fc47..48b6e2eb2f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/MeasureFiniteRestrictionIdentification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/MeasureFiniteRestrictionIdentification.lean @@ -15,12 +15,14 @@ unequal mass cannot satisfy the hypothesis. This is generic measure-theoretic infrastructure and requires no topology. -/ +noncomputable section PortComputability + open MeasureTheory namespace MarkovProcess namespace Measure -noncomputable section +section variable {index alpha : Type*} [MeasurableSpace alpha] @@ -45,3 +47,5 @@ theorem eq_of_map_finiteRestriction_eq end end Measure end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativeResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativeResolvent.lean index ab416e4982..a80d0aef10 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativeResolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativeResolvent.lean @@ -27,10 +27,12 @@ equivalence and not merely a sufficient condition. No topology on the state space is used. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set open scoped ENNReal NNReal -noncomputable section +section namespace MarkovProcess.SubMarkovKernelSemigroup @@ -153,3 +155,7 @@ theorem IsConservative.ofReal_mul_kernelResolvent_one {P : SubMarkovKernelSemigr mul_inv_cancel₀ hlam.ne', ENNReal.ofReal_one] end MarkovProcess.SubMarkovKernelSemigroup + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/FiniteRestrictionIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/FiniteRestrictionIdentification.lean index 518be44f14..7ad8c1d580 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/FiniteRestrictionIdentification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/FiniteRestrictionIdentification.lean @@ -14,12 +14,14 @@ pushforwards. The proof applies uniqueness of finite projective limits pointwis parameter. No topology, time order, path regularity, or Markov property is used. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace Kernel -noncomputable section +section variable {index alpha beta : Type*} [MeasurableSpace alpha] [MeasurableSpace beta] @@ -48,3 +50,5 @@ theorem eq_of_map_finiteRestriction_eq end end Kernel end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/KernelSemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/KernelSemigroup.lean index 9732b4d84c..f28925d819 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/KernelSemigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/KernelSemigroup.lean @@ -16,10 +16,12 @@ Conservativity is deliberately a separate predicate. A killed transition family has mass at most one, while a conservative family has mass exactly one. -/ +noncomputable section PortComputability + open Set open scoped ENNReal ProbabilityTheory -noncomputable section +section namespace MarkovProcess @@ -125,3 +127,7 @@ end IsConservative end SubMarkovKernelSemigroup end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/KolmogorovMoments.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/KolmogorovMoments.lean index cec3c0563c..32d160861e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/KolmogorovMoments.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/KolmogorovMoments.lean @@ -31,7 +31,8 @@ variable {alpha : Type*} [PseudoEMetricSpace alpha] [MeasurableSpace alpha] /-- A uniform `p`-th moment bound on the displacement of `P` over time `h`, of order `h ^ q`. The exponents are constrained by `0 < p` and `1 < q`, exactly the range in which the -Kolmogorov--Chentsov threshold `(q - 1) / p` is a positive Hölder exponent. The bound is demanded for every time `h ≥ 0`, not only +Kolmogorov--Chentsov threshold `(q - 1) / p` is a positive Hölder exponent. +The bound is demanded for every time `h ≥ 0`, not only for small `h`; this is stronger than the local criterion the Kolmogorov--Chentsov theorem needs, and it is what the bridge to `KolmogorovRegular` consumes. -/ def HasKolmogorovMoments (P : SubMarkovKernelSemigroup alpha) (p q : ℝ) (M : ℝ≥0) : Prop := diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean index db3ff1bdaf..1382231bf0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean @@ -31,11 +31,11 @@ and burns a failing search for `SeminormedAddCommGroup (α →ₘ[μ] ℝ)`. -/ private noncomputable instance cacheSeminormedLp (p : ℝ≥0∞) [Fact (1 ≤ p)] (μ : Measure α) : SeminormedAddCommGroup (Lp ℝ p μ) := inferInstance -private noncomputable instance cacheAddCommMonoidLp (p : ℝ≥0∞) - (μ : Measure α) : AddCommMonoid (Lp ℝ p μ) := inferInstance +private noncomputable instance cacheAddCommMonoidLp (p : ℝ≥0∞) (μ : Measure α) : + AddCommMonoid (Lp ℝ p μ) := inferInstance -private noncomputable instance cacheModuleLp (p : ℝ≥0∞) [Fact (1 ≤ p)] - (μ : Measure α) : Module ℝ (Lp ℝ p μ) := inferInstance +private noncomputable instance cacheModuleLp (p : ℝ≥0∞) (μ : Measure α) : + Module ℝ (Lp ℝ p μ) := inferInstance private noncomputable instance cacheTopologicalSpaceLp (p : ℝ≥0∞) [Fact (1 ≤ p)] (μ : Measure α) : TopologicalSpace (Lp ℝ p μ) := inferInstance diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean index ef62d067fd..fac4791b41 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean @@ -50,7 +50,7 @@ theorem eLpNorm_one_le_of_measure_univ_le_one {ν : Measure α} {f : α → ℝ} /-- Jensen's power estimate for a finite subprobability measure. This form is well suited to fibrewise use because both sides take values in `ℝ≥0∞`. -/ theorem enorm_integral_rpow_le_lintegral_enorm_rpow - {ν : Measure α} [IsFiniteMeasure ν] {f : α → ℝ} {p : NNReal} + {ν : Measure α} {f : α → ℝ} {p : NNReal} (hp : 1 ≤ p) (hν : ν Set.univ ≤ 1) (hf : MemLp f p ν) : ‖∫ y, f y ∂ν‖ₑ ^ (p : ℝ) ≤ ∫⁻ y, ‖f y‖ₑ ^ (p : ℝ) ∂ν := by have hp0 : p ≠ 0 := ne_of_gt (zero_lt_one.trans_le hp) @@ -105,7 +105,8 @@ theorem eLpNorm_kernelIntegral_le (hp : 1 ≤ p) (hf : MemLp f p μ) : eLpNorm (kernelIntegral κ f) p μ ≤ eLpNorm f p μ := by have hp0 : p ≠ 0 := ne_of_gt (zero_lt_one.trans_le hp) - rw [eLpNorm_nnreal_eq_lintegral hp0 (AEStronglyMeasurable.kernelIntegral hf.aestronglyMeasurable hκμ), + rw [eLpNorm_nnreal_eq_lintegral hp0 (AEStronglyMeasurable.kernelIntegral + hf.aestronglyMeasurable hκμ), eLpNorm_nnreal_eq_lintegral hp0 hf.aestronglyMeasurable] apply ENNReal.rpow_le_rpow · exact lintegral_enorm_kernelIntegral_rpow_le hκ hκμ hp hf diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/MeasurableRadonFamily.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/MeasurableRadonFamily.lean index 2e9cd5c765..cc3012908e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/MeasurableRadonFamily.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/MeasurableRadonFamily.lean @@ -135,7 +135,7 @@ theorem measurable_measure_of_measurable_integral_compactlySupported {Q X : Type*} [MeasurableSpace Q] [TopologicalSpace X] [T2Space X] [LocallyCompactSpace X] [SecondCountableTopology X] [MeasurableSpace X] [BorelSpace X] - (μ : Q → Measure X) [∀ q, (μ q).Regular] [∀ q, IsFiniteMeasure (μ q)] + (μ : Q → Measure X) [∀ q, IsFiniteMeasure (μ q)] (hμ : ∀ f : C_c(X, ℝ), Measurable fun q ↦ ∫ x, f x ∂μ q) : Measurable μ := by refine Measurable.measure_of_isPiSystem (S := generatePiSystem (countableBasis X)) diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointConservative.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointConservative.lean index d326632bd9..d46948ed66 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointConservative.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointConservative.lean @@ -23,10 +23,12 @@ The regularity data of the compactification are an explicit hypothesis, as every continuous-path process is formed. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set Topology open scoped ENNReal NNReal ZeroAtInfty -noncomputable section +section namespace MarkovProcess.PositiveC0ContractiveResolvent @@ -80,3 +82,7 @@ theorem OnePointRegular.ae_exitTime_eq_top (h : R.OnePointRegular) {lam : ℝ} ( exact Real.exp_pos _) end MarkovProcess.PositiveC0ContractiveResolvent + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean index 051e56871e..7e15dc8977 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean @@ -27,9 +27,11 @@ This construction does not assert a Kolmogorov moment bound or construct a conti process. -/ +noncomputable section PortComputability + open Filter Set Topology TopologicalSpace -noncomputable section +section namespace OnePoint @@ -591,3 +593,7 @@ theorem onePointKernelSemigroup_absorbing (t : NNReal) : end MarkovProcess.PositiveC0ContractiveResolvent + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKilled.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKilled.lean index cfe1061f5c..f39b85092e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKilled.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKilled.lean @@ -18,10 +18,12 @@ This file identifies the continuous process of the one-point extension of a posi `C₀`-contractive resolvent with the process killed on leaving its live part. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set Topology open scoped ENNReal NNReal ZeroAtInfty -noncomputable section +section namespace MarkovProcess.SubMarkovKernelSemigroup @@ -497,15 +499,16 @@ theorem killedSemigroup_onePointLive_image filter_upwards [hevent] with omega homega exact propext homega rw [hmeasure] - show (IsConservative.continuousProcess R.onePointKernelSemigroup + change (IsConservative.continuousProcess R.onePointKernelSemigroup R.isConservative_onePointKernelSemigroup (x : OnePoint X)) (ContinuousPath.coordinateProcess t ⁻¹' (((↑) : X → OnePoint X) '' B)) = R.kernelSemigroup t x B rw [← Kernel.map_apply' (IsConservative.continuousProcess R.onePointKernelSemigroup - R.isConservative_onePointKernelSemigroup) (hf := ContinuousPath.measurable_coordinateProcess t) + R.isConservative_onePointKernelSemigroup) (hf := + ContinuousPath.measurable_coordinateProcess t) (x : OnePoint X) hcoeB] - show ((IsConservative.continuousProcess R.onePointKernelSemigroup + change ((IsConservative.continuousProcess R.onePointKernelSemigroup R.isConservative_onePointKernelSemigroup).map (fun omega => omega t) (x : OnePoint X)) (((↑) : X → OnePoint X) '' B) = R.kernelSemigroup t x B @@ -571,15 +574,16 @@ theorem killedKernel_onePointLive_eq_map filter_upwards [hevent] with omega homega exact propext homega rw [hmeasure] - show (IsConservative.continuousProcess R.onePointKernelSemigroup + change (IsConservative.continuousProcess R.onePointKernelSemigroup R.isConservative_onePointKernelSemigroup (x : OnePoint X)) (ContinuousPath.coordinateProcess t ⁻¹' (A ∩ live)) = (R.kernelSemigroup t x).map ((↑) : X → OnePoint X) A rw [← Kernel.map_apply' (IsConservative.continuousProcess R.onePointKernelSemigroup - R.isConservative_onePointKernelSemigroup) (hf := ContinuousPath.measurable_coordinateProcess t) + R.isConservative_onePointKernelSemigroup) (hf := + ContinuousPath.measurable_coordinateProcess t) (x : OnePoint X) hAlive] - show ((IsConservative.continuousProcess R.onePointKernelSemigroup + change ((IsConservative.continuousProcess R.onePointKernelSemigroup R.isConservative_onePointKernelSemigroup).map (fun omega => omega t) (x : OnePoint X)) (A ∩ live) = (R.kernelSemigroup t x).map ((↑) : X → OnePoint X) A @@ -782,3 +786,7 @@ theorem lintegral_exp_neg_onePoint_exitTime lintegral_map measurable_const OnePoint.continuous_coe.measurable] end MarkovProcess.PositiveC0ContractiveResolvent + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean index aa3a177902..e529b85ec2 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean @@ -24,10 +24,12 @@ The tail bounds and their scalar integral budget remain hypotheses for the consu estimate for a particular semigroup is asserted here. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set Topology open scoped ENNReal NNReal ZeroAtInfty -noncomputable section +section namespace OnePoint @@ -220,6 +222,7 @@ private theorem isOpen_iff_exhaustionDist {rho : X → ℝ} (hrho_cont : Continu /-- The explicit metric on the one-point compactification determined by a positive Lipschitz exhaustion function with compact positive superlevel sets. -/ +@[implicit_reducible] noncomputable def exhaustionMetricSpace (rho : X → ℝ) (hrho_cont : Continuous rho) (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) : @@ -535,3 +538,7 @@ theorem kolmogorovRegular_onePointKernelSemigroup R.onePointKernelSemigroup_absorbing end MarkovProcess.PositiveC0ContractiveResolvent + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0Resolvent.lean index 5d408ba190..0df2e29777 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0Resolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0Resolvent.lean @@ -17,10 +17,12 @@ The package in this file starts from the resolvent identity, the Hille--Yosida b and positivity of the actual shifted resolvents. It assumes neither a semigroup nor a kernel. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory Set open scoped ZeroAtInfty -noncomputable section +section namespace MarkovProcess @@ -122,3 +124,7 @@ end Kernel end PositiveC0ContractiveResolvent end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ResolventUniqueness.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ResolventUniqueness.lean index f2abb2a699..ce7856861c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ResolventUniqueness.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ResolventUniqueness.lean @@ -19,11 +19,13 @@ Main results: `perturbed_unique`, `resolventFamily_eq_of_eventually`, and The operators are plain maps on functions; no Banach-space carrier or continuity is asserted. -/ +noncomputable section PortComputability + open Filter namespace MarkovProcess -noncomputable section +section private theorem function_eq_zero_of_geometric_bound {alpha : Type*} {d : alpha → ℝ} {r D : ℝ} (hr0 : 0 ≤ r) (hr1 : r < 1) (hD0 : 0 ≤ D) @@ -349,3 +351,5 @@ theorem perturbed_eq_of_resolventFamilies end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/WeakConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/WeakConvergence.lean index 920ad72a41..7ca52249bb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/WeakConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/WeakConvergence.lean @@ -47,7 +47,7 @@ theorem exists_compactlySupported_one_sub_lt_integral [PseudoEMetricSpace X] obtain ⟨g, hgK, -, hgsupp, hg01⟩ := exists_continuous_one_zero_of_isCompact hK isClosed_empty (Set.disjoint_empty K) refine ⟨⟨g, hgsupp⟩, hg01, ?_⟩ - show (1 : ℝ) - eps < ∫ y, g y ∂mu + change (1 : ℝ) - eps < ∫ y, g y ∂mu have hKmeas : MeasurableSet K := hK.isClosed.measurableSet have hKcompl : mu.real Kᶜ ≤ eps / 2 := by have h := ENNReal.toReal_mono (by simp) hKmu diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/ExitTimeIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/ExitTimeIdentification.lean index 00af7ac810..0c419e8e93 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/ExitTimeIdentification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/ExitTimeIdentification.lean @@ -32,12 +32,14 @@ The consumer-supplied resolvent and its limit are `ℝ≥0∞`-valued, so no int hypothesis appears; a consumer working with real-valued solutions bridges with `ENNReal.ofReal`. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set open scoped ENNReal NNReal Topology namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section /-- The exponential discounts at the shifts `1 / (n + 1)` increase to one on the nonnegative half-line. -/ @@ -95,8 +97,8 @@ theorem IsConservative.lintegral_exitTime_eq_killedResolvent_zero (U : Set alpha Measure.restrict_apply hS] rw [hinner, ContinuousPath.survivalSet tau] by_cases htop : tau = ⊤ - · rw [if_pos htop, htop, Real.volume_Ioi] - · rw [if_neg htop, Real.volume_Ioo, sub_zero, ENNReal.ofReal_toReal htop] + · rw [ite_eq_left htop, htop, Real.volume_Ioi] + · rw [ite_eq_right htop, Real.volume_Ioo, sub_zero, ENNReal.ofReal_toReal htop] /-- The killed resolvent at the shift zero is the increasing limit of the killed resolvents at the positive shifts `1 / (n + 1)`. -/ @@ -208,3 +210,5 @@ theorem IsConservative.le_lintegral_exitTime_of_killedResolvent_eq (U : Set alph end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingC0.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingC0.lean index a9560a42a2..5124fc37ca 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingC0.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingC0.lean @@ -31,10 +31,12 @@ the compactified process started at any point almost surely never reaches the ad space is produced from that statement. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set Topology open scoped ENNReal NNReal ZeroAtInfty -noncomputable section +section namespace MarkovProcess @@ -264,3 +266,7 @@ theorem ae_exitTime_eq_top_minimalC0Resolvent end Conservativity end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLinearity.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLinearity.lean index 9dc9a3b1df..c68507850a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLinearity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLinearity.lean @@ -26,10 +26,12 @@ suprema once the family is monotone in the index (`minimalResolvent_comm`). Nothing here uses the part-process identity; monotonicity in the index is a bare hypothesis. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set Topology open scoped ENNReal NNReal ZeroAtInfty -noncomputable section +section namespace MarkovProcess @@ -150,3 +152,7 @@ theorem minimalResolvent_zero (hemb : ∀ m, MeasurableEmbedding (emb m)) {lam : (f := fun _ : alpha ↦ (0 : ℝ≥0∞)) (c := 0) (fun _ ↦ le_rfl) x end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLocal.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLocal.lean index 48fe337fe4..8d4e393e1f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLocal.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLocal.lean @@ -27,10 +27,12 @@ The regularity data are an explicit hypothesis: positivity, contractivity and th identity do not by themselves give the compactified semigroup a continuous-path process. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set Topology open scoped ENNReal NNReal ZeroAtInfty -noncomputable section +section namespace MarkovProcess.PositiveC0ContractiveResolvent @@ -68,6 +70,7 @@ namespace OnePointRegular variable {R : PositiveC0ContractiveResolvent X} /-- The metric on the compactification determined by the exhaustion function. -/ +@[implicit_reducible] noncomputable def metricSpace (h : R.OnePointRegular) : MetricSpace (OnePoint X) := OnePoint.exhaustionMetricSpace h.rho h.continuous_rho h.rho_pos h.lipschitz_rho h.isCompact_superlevel @@ -77,7 +80,8 @@ noncomputable def metricSpace (h : R.OnePointRegular) : MetricSpace (OnePoint X) exhaustion metric's topology coincides with the canonical one-point topology, which is always compact). -/ private instance instCompactSpaceMetricSpace (h : R.OnePointRegular) : - @CompactSpace (OnePoint X) h.metricSpace.toPseudoMetricSpace.toUniformSpace.toTopologicalSpace := by + @CompactSpace (OnePoint X) + h.metricSpace.toPseudoMetricSpace.toUniformSpace.toTopologicalSpace := by unfold OnePointRegular.metricSpace rw [OnePoint.exhaustionMetricSpace_toTopologicalSpace] infer_instance @@ -285,3 +289,7 @@ theorem kernelResolvent_le_of_partProcess (R₀ : PositiveC0ContractiveResolvent end Comparison end MarkovProcess.PositiveC0ContractiveResolvent + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMeasure.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMeasure.lean index 783148d627..f77a75baaa 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMeasure.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMeasure.lean @@ -20,10 +20,12 @@ to all nonnegative measurable observables through the two potential measures. Monotonicity of the transported resolvents in the index is a bare hypothesis throughout. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set open scoped ENNReal NNReal -noncomputable section +section namespace MarkovProcess @@ -155,3 +157,7 @@ theorem isFiniteMeasure_minimalPotential (hemb : ∀ m, MeasurableEmbedding (emb (minimalResolvent_one_le R emb (fun m ↦ (hemb m).injective) hlam x) ENNReal.ofReal_lt_top end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMinimal.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMinimal.lean index 35975978d4..69058b709d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMinimal.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMinimal.lean @@ -38,10 +38,12 @@ No transition semigroup, no process on the ambient space, and no conservativity here. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set Topology open scoped ENNReal NNReal ZeroAtInfty -noncomputable section +section namespace MarkovProcess @@ -341,3 +343,7 @@ theorem minimalResolvent_resolventEquation (hemb : ∀ m, MeasurableEmbedding (e end ResolventEquation end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingPotential.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingPotential.lean index efcd78e464..62e99150c9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingPotential.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingPotential.lean @@ -33,10 +33,12 @@ homogeneous on measurable observables (`SubMarkovKernelSemigroup.kernelResolvent No resolvent identity and no topology on the state space are used here. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set open scoped ENNReal NNReal -noncomputable section +section namespace MarkovProcess @@ -279,3 +281,7 @@ end Killed end SubMarkovKernelSemigroup end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingRealResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingRealResolvent.lean index 41b9e3c67b..1912bbe6bb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingRealResolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingRealResolvent.lean @@ -25,10 +25,12 @@ Additivity, and with it the resolvent equation, is available exactly when the tr resolvents are monotone in the index; that monotonicity is a bare hypothesis here. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set Topology open scoped ENNReal NNReal ZeroAtInfty -noncomputable section +section namespace MarkovProcess @@ -283,7 +285,7 @@ theorem minimalResolventReal_sub (hemb : ∀ m, MeasurableEmbedding (emb m)) minimalResolventReal R emb lam f x - minimalResolventReal R emb lam g x := by have hrewrite : (fun y ↦ f y - g y) = fun y ↦ f y + (-g) y := by funext y - show f y - g y = f y + -g y + change f y - g y = f y + -g y ring have hneg : minimalResolventReal R emb lam (-g) x = - minimalResolventReal R emb lam g x := by @@ -404,3 +406,7 @@ theorem minimalResolventReal_resolventEquation (hemb : ∀ m, MeasurableEmbeddin end ResolventEquation end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingResolventEquation.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingResolventEquation.lean index dd755ff8bd..c2086f6236 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingResolventEquation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingResolventEquation.lean @@ -33,10 +33,12 @@ Main results: `expWeight_convolution`, `SubMarkovKernelSemigroup.kernelResolvent_resolventEquation`. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set open scoped ENNReal NNReal -noncomputable section +section namespace MarkovProcess @@ -278,3 +280,7 @@ theorem kernelResolvent_resolventEquation {lam mu : ℝ} (hlt : lam < mu) end SubMarkovKernelSemigroup end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingTransfer.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingTransfer.lean index b7e49ef63f..26cd7f02e3 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingTransfer.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingTransfer.lean @@ -27,10 +27,12 @@ No topology on the target space is used, and no relation between the two measure tested identity is assumed. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set Topology open scoped ENNReal NNReal ZeroAtInfty CompactlySupported -noncomputable section +section namespace MarkovProcess @@ -131,3 +133,7 @@ theorem lintegral_extend_eq_of_forall_zeroAtInfty {i : X → Y} (hi : Measurable end Transfer end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Kernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Kernel.lean index 33e449bd49..807cd4e6e4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Kernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Kernel.lean @@ -211,7 +211,8 @@ variable [LocallyCompactSpace alpha] /-- **Chapman--Kolmogorov law for the killed kernels**: `killedKernel (s + t) = killedKernel t ∘ₖ killedKernel s`. It follows from the Markov property of the process at the deterministic time `s` -on the `𝓕_s`-event `{s < τ_U}`, and the path identity `{s + t < τ_U} = {s < τ_U} ∩ {t < τ_U ∘ θ_s}`. -/ +on the `𝓕_s`-event `{s < τ_U}`, and the path identity `{s + t < τ_U} = {s < τ_U} ∩ {t < τ_U ∘ + θ_s}`. -/ theorem IsConservative.killedKernel_add (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) (s t : NNReal) : IsConservative.killedKernel P hP U hU (s + t) = diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/KillAtExit.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/KillAtExit.lean index bb782f5a38..b7bb690809 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/KillAtExit.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/KillAtExit.lean @@ -25,6 +25,8 @@ lifetime-path measurable structure generated by the lifetime and the coordinates This file constructs no probability law. -/ +noncomputable section PortComputability + open MeasureTheory open scoped ENNReal NNReal @@ -45,7 +47,7 @@ end SubtypeImage namespace ContinuousPath -noncomputable section +section variable {alpha : Type*} [PseudoMetricSpace alpha] @@ -91,8 +93,8 @@ theorem coordinate_killAtExit (U : Set alpha) (omega : ContinuousPath alpha) (t Cemetery.alive ⟨omega t, mem_of_lt_exitTime U omega t ht⟩ else Cemetery.delta := by by_cases ht : (t : ℝ≥0∞) < exitTime U omega - · rw [dif_pos ht, coordinate_killAtExit_of_lt U omega t ht] - · rw [dif_neg ht, coordinate_killAtExit_of_le U omega t (not_lt.mp ht)] + · rw [dite_eq_left ht, coordinate_killAtExit_of_lt U omega t ht] + · rw [dite_eq_right ht, coordinate_killAtExit_of_le U omega t (not_lt.mp ht)] /-- **Shift identity for the killed path.** Strictly before the exit time of `U`, killing the path shifted by `t` and reading it at time `s` is the same as killing the path and reading it at @@ -125,12 +127,12 @@ theorem preimage_coordinate_killAtExit_of_notMem {S : Set (Cemetery U)} ext omega rw [Set.mem_preimage, coordinate_killAtExit, Set.mem_ofPred_eq] by_cases ht : (t : ℝ≥0∞) < exitTime U omega - · rw [dif_pos ht] + · rw [dite_eq_left ht] have hmem := mem_image_val_iff U (C := Cemetery.alive ⁻¹' S) (mem_of_lt_exitTime U omega t ht) rw [hmem] exact ⟨fun h ↦ ⟨ht, h⟩, fun h ↦ h.2⟩ - · rw [dif_neg ht] + · rw [dite_eq_right ht] exact ⟨fun h ↦ absurd h hS, fun h ↦ absurd h.1 ht⟩ /-- The event that the killed path is at the cemetery at time `t`, or is alive with live @@ -144,7 +146,7 @@ theorem preimage_coordinate_killAtExit_of_mem {S : Set (Cemetery U)} ext omega rw [Set.mem_preimage, coordinate_killAtExit, Set.mem_union, Set.mem_ofPred_eq, Set.mem_ofPred_eq] by_cases ht : (t : ℝ≥0∞) < exitTime U omega - · rw [dif_pos ht] + · rw [dite_eq_left ht] have hmem := mem_image_val_iff U (C := Cemetery.alive ⁻¹' S) (mem_of_lt_exitTime U omega t ht) rw [hmem] @@ -153,7 +155,7 @@ theorem preimage_coordinate_killAtExit_of_mem {S : Set (Cemetery U)} · rintro (h | h) · exact h.2 · exact absurd ht h - · rw [dif_neg ht] + · rw [dite_eq_right ht] exact ⟨fun _ ↦ Or.inr ht, fun _ ↦ hS⟩ end Preimage @@ -208,3 +210,5 @@ end end ContinuousPath end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean index 074fb8c032..8f23137678 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean @@ -169,6 +169,46 @@ theorem IsConservative.killedProcess_map_coordinates {iota : Type*} (tau : iota rfl variable [LocallyCompactSpace alpha] +omit [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + [SecondCountableTopology alpha] [Nonempty alpha] [LocallyCompactSpace alpha] in +private theorem killed_coordinate_survival_event {n : ℕ} + (times : FiniteOrderedTimes (n + 1)) (B : Fin (n + 1) → Set (Cemetery U)) : +(fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' + Set.univ.pi B ∩ {omega : ContinuousPath alpha | + ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} = + ContinuousPath.killedEvent U (times 0) (Subtype.val '' (Cemetery.alive ⁻¹' (B 0) : + Set U)) ∩ + ContinuousPath.shift (times 0) ⁻¹' ((fun omega : ContinuousPath alpha ↦ fun i : + Fin n ↦ + LifetimePath.coordinate (times.relativeTail i) + (ContinuousPath.killAtExit U omega)) ⁻¹' (Set.univ.pi fun i : Fin n ↦ B i.succ)) := by + ext omega + simp only [Set.mem_inter_iff, Set.mem_preimage, Set.mem_univ_pi, Set.mem_ofPred_eq, + ContinuousPath.mem_killedEvent_iff] + constructor + · rintro ⟨hmem, hsurv⟩ + refine ⟨⟨hsurv, ?_⟩, fun i ↦ ?_⟩ + · have h0 := hmem 0 + rw [ContinuousPath.coordinate_killAtExit_of_lt U omega (times 0) hsurv] at h0 + exact (mem_image_val_iff U + (ContinuousPath.mem_of_lt_exitTime U omega (times 0) hsurv)).mpr h0 + · have hi := hmem i.succ + rw [← FiniteOrderedTimes.add_relativeTail times i, + ← ContinuousPath.coordinate_killAtExit_shift U omega (times 0) + (times.relativeTail i) hsurv] at hi + exact hi + · rintro ⟨⟨hsurv, h0⟩, htail⟩ + refine ⟨fun i ↦ ?_, hsurv⟩ + refine Fin.cases ?_ (fun j ↦ ?_) i + · rw [ContinuousPath.coordinate_killAtExit_of_lt U omega (times 0) hsurv] + exact (mem_image_val_iff U + (ContinuousPath.mem_of_lt_exitTime U omega (times 0) hsurv)).mp h0 + · rw [← FiniteOrderedTimes.add_relativeTail times j, + ← ContinuousPath.coordinate_killAtExit_shift U omega (times 0) + (times.relativeTail j) hsurv] + exact htail j + variable (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) /-- **Finite-dimensional distributions of the killed process, at ordered times.** Read at a @@ -200,15 +240,20 @@ theorem IsConservative.killedProcess_map_coordinates_ordered {n : ℕ} (ContinuousPath.killAtExit U omega)) := Measurable.of_eval fun i ↦ ContinuousPath.measurable_coordinate_killAtExit U hU (times.relativeTail i) - have hRcons : (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)).IsConservative := isConservative_cemeterySemigroup _ - let : IsMarkovKernel (finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times) := + have hRcons : (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller + hK)).IsConservative := isConservative_cemeterySemigroup _ + let : IsMarkovKernel (finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup + P hP U hU hFeller hK)) times) := hRcons.isMarkovKernel_finiteTimeKernel _ times - let : IsMarkovKernel (finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail) := + let : IsMarkovKernel (finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup + P hP U hU hFeller hK)) times.relativeTail) := hRcons.isMarkovKernel_finiteTimeKernel _ _ - let : IsMarkovKernel ((cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) (times 0)) := hRcons.isMarkovKernel (times 0) + let : IsMarkovKernel ((cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller + hK)) (times 0)) := hRcons.isMarkovKernel (times 0) rw [IsConservative.killedProcess_map_coordinates P hP U hU _ x] have : IsProbabilityMeasure - ((IsConservative.continuousProcess P hP (x : alpha)).map (fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ + ((IsConservative.continuousProcess P hP (x : alpha)).map (fun omega : ContinuousPath + alpha ↦ fun i : Fin (n + 1) ↦ LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega))) := inferInstance refine MeasureTheory.ext_of_generate_finite _ generateFrom_pi.symm isPiSystem_pi ?_ ?_ @@ -222,8 +267,10 @@ theorem IsConservative.killedProcess_map_coordinates_ordered {n : ℕ} ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} := ContinuousPath.measurableSet_lt_exitTime U hU (times 0) have hg : Measurable fun z : Cemetery U ↦ - finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail z (Set.univ.pi fun i : Fin n ↦ B i.succ) := - (finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail).measurable_coe hbox' + finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU + hFeller hK)) times.relativeTail z (Set.univ.pi fun i : Fin n ↦ B i.succ) := + (finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller + hK)) times.relativeTail).measurable_coe hbox' have hinl : Measurable (Cemetery.alive : U → Cemetery U) := measurable_inl have hcoorddead : ∀ omega : ContinuousPath alpha, omega ∉ {omega : ContinuousPath alpha | @@ -232,44 +279,16 @@ theorem IsConservative.killedProcess_map_coordinates_ordered {n : ℕ} (ContinuousPath.killAtExit U omega) = Cemetery.delta := fun omega homega i ↦ ContinuousPath.coordinate_killAtExit_of_exitTime_le U omega (not_lt.mp homega) (times.monotone (Fin.zero_le i)) - have hliveset : (fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ - LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' Set.univ.pi B ∩ {omega : ContinuousPath alpha | - ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} = - ContinuousPath.killedEvent U (times 0) (Subtype.val '' (Cemetery.alive ⁻¹' (B 0) : Set U)) ∩ - ContinuousPath.shift (times 0) ⁻¹' ((fun omega : ContinuousPath alpha ↦ fun i : Fin n ↦ - LifetimePath.coordinate (times.relativeTail i) - (ContinuousPath.killAtExit U omega)) ⁻¹' (Set.univ.pi fun i : Fin n ↦ B i.succ)) := by - ext omega - simp only [Set.mem_inter_iff, Set.mem_preimage, Set.mem_univ_pi, Set.mem_ofPred_eq, - ContinuousPath.mem_killedEvent_iff] - constructor - · rintro ⟨hmem, hsurv⟩ - refine ⟨⟨hsurv, ?_⟩, fun i ↦ ?_⟩ - · have h0 := hmem 0 - rw [ContinuousPath.coordinate_killAtExit_of_lt U omega (times 0) hsurv] at h0 - exact (mem_image_val_iff U - (ContinuousPath.mem_of_lt_exitTime U omega (times 0) hsurv)).mpr h0 - · have hi := hmem i.succ - rw [← FiniteOrderedTimes.add_relativeTail times i, - ← ContinuousPath.coordinate_killAtExit_shift U omega (times 0) - (times.relativeTail i) hsurv] at hi - exact hi - · rintro ⟨⟨hsurv, h0⟩, htail⟩ - refine ⟨fun i ↦ ?_, hsurv⟩ - refine Fin.cases ?_ (fun j ↦ ?_) i - · rw [ContinuousPath.coordinate_killAtExit_of_lt U omega (times 0) hsurv] - exact (mem_image_val_iff U - (ContinuousPath.mem_of_lt_exitTime U omega (times 0) hsurv)).mp h0 - · rw [← FiniteOrderedTimes.add_relativeTail times j, - ← ContinuousPath.coordinate_killAtExit_shift U omega (times 0) - (times.relativeTail j) hsurv] - exact htail j + have hliveset := killed_coordinate_survival_event U times B have hliveval : IsConservative.continuousProcess P hP (x : alpha) ((fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ - LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' Set.univ.pi B ∩ {omega : ContinuousPath alpha | + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' + Set.univ.pi B ∩ {omega : ContinuousPath alpha | ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega}) = - ∫⁻ y in (Cemetery.alive ⁻¹' (B 0) : Set U), finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail - (Cemetery.alive y) (Set.univ.pi fun i : Fin n ↦ B i.succ) ∂(IsConservative.killedKernelOn P hP U hU (times 0) x) := by + ∫⁻ y in (Cemetery.alive ⁻¹' (B 0) : Set U), finiteTimeKernel (cemeterySemigroup + (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail + (Cemetery.alive y) (Set.univ.pi fun i : Fin n ↦ B i.succ) + ∂(IsConservative.killedKernelOn P hP U hU (times 0) x) := by rw [hliveset, IsConservative.continuousProcess_killedEvent_inter_shift P hP U hU hFeller hK (times 0) x hC0 (hmeasTail hbox')] refine lintegral_congr fun y ↦ ?_ @@ -278,20 +297,25 @@ theorem IsConservative.killedProcess_map_coordinates_ordered {n : ℕ} ih times.relativeTail y] have hdeadval : IsConservative.continuousProcess P hP (x : alpha) ((fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ - LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' Set.univ.pi B \ {omega : ContinuousPath alpha | + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' + Set.univ.pi B \ {omega : ContinuousPath alpha | ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega}) = (1 - IsConservative.killedKernelOn P hP U hU (times 0) x Set.univ) * - (B 0).indicator (fun z ↦ finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail z + (B 0).indicator (fun z ↦ finiteTimeKernel (cemeterySemigroup + (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail z (Set.univ.pi fun i : Fin n ↦ B i.succ)) Cemetery.delta := by - have hQA : IsConservative.continuousProcess P hP (x : alpha) ({omega : ContinuousPath alpha | + have hQA : IsConservative.continuousProcess P hP (x : alpha) ({omega : ContinuousPath + alpha | ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega})ᶜ = 1 - IsConservative.killedKernelOn P hP U hU (times 0) x Set.univ := by rw [IsConservative.killedKernelOn_univ_eq_continuousProcess P hP U hU (times 0) x] exact prob_compl_eq_one_sub hA by_cases hdelta : ∀ i : Fin (n + 1), (Cemetery.delta : Cemetery U) ∈ B i · have hset : (fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ - LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' Set.univ.pi B \ {omega : ContinuousPath alpha | - ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} = ({omega : ContinuousPath alpha | + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' + Set.univ.pi B \ {omega : ContinuousPath alpha | + ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} = ({omega : + ContinuousPath alpha | ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega})ᶜ := by refine Set.eq_of_subset_of_subset (fun omega homega ↦ homega.2) fun omega homega ↦ ?_ refine ⟨fun i _ ↦ ?_, homega⟩ @@ -308,7 +332,8 @@ theorem IsConservative.killedProcess_map_coordinates_ordered {n : ℕ} Pi.one_apply, mul_one] · obtain ⟨i, hi⟩ := not_forall.mp hdelta have hset : (fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ - LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' Set.univ.pi B \ {omega : ContinuousPath alpha | + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' + Set.univ.pi B \ {omega : ContinuousPath alpha | ((times 0 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega} = ∅ := by refine Set.eq_empty_iff_forall_notMem.mpr fun omega homega ↦ ?_ have h1 : LifetimePath.coordinate (times i) @@ -317,17 +342,20 @@ theorem IsConservative.killedProcess_map_coordinates_ordered {n : ℕ} exact hi h1 rw [hset, measure_empty] by_cases h0 : (Cemetery.delta : Cemetery U) ∈ B 0 - · have hnotbox : (fun _ ↦ Cemetery.delta : Fin n → Cemetery U) ∉ (Set.univ.pi fun i : Fin n ↦ B i.succ) := by + · have hnotbox : (fun _ ↦ Cemetery.delta : Fin n → Cemetery U) ∉ (Set.univ.pi fun i + : Fin n ↦ B i.succ) := by intro hmem exact hdelta fun k ↦ Fin.cases h0 (fun j ↦ hmem j (Set.mem_univ j)) k rw [Set.indicator_of_mem h0, finiteTimeKernel_cemeterySemigroup_delta, Measure.dirac_apply' _ hbox', Set.indicator_of_notMem hnotbox, mul_zero] · rw [Set.indicator_of_notMem h0, mul_zero] have hintegrand : ∀ z : Cemetery U, - finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail z + finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU + hFeller hK)) times.relativeTail z (Prod.mk z ⁻¹' ((fun w : Cemetery U × (Fin n → Cemetery U) ↦ @Fin.cons n (fun _ : Fin (n + 1) ↦ Cemetery U) w.1 w.2) ⁻¹' Set.univ.pi B)) = - (B 0).indicator (fun z ↦ finiteTimeKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail z + (B 0).indicator (fun z ↦ finiteTimeKernel (cemeterySemigroup + (IsConservative.killedSemigroup P hP U hU hFeller hK)) times.relativeTail z (Set.univ.pi fun i : Fin n ↦ B i.succ)) z := by intro z by_cases hz : z ∈ B 0 @@ -358,7 +386,8 @@ theorem IsConservative.killedProcess_map_coordinates_ordered {n : ℕ} rw [Measure.map_apply hmeasTimes hbox, ← measure_inter_add_sdiff (μ := IsConservative.continuousProcess P hP (x : alpha)) ((fun omega : ContinuousPath alpha ↦ fun i : Fin (n + 1) ↦ - LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' Set.univ.pi B) hA, + LifetimePath.coordinate (times i) (ContinuousPath.killAtExit U omega)) ⁻¹' + Set.univ.pi B) hA, hliveval, hdeadval, finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map, Kernel.map_apply _ measurable_finCons, Measure.map_apply measurable_finCons hbox, Kernel.compProd_apply (measurable_finCons hbox)] @@ -381,13 +410,14 @@ the cemetery recording the time at which the path leaves `U`. -/ theorem IsConservative.killedProcess_map_finiteEvaluation (I : Finset NNReal) (x : U) : (IsConservative.killedProcess P hP U hU x).map (fun omega ↦ fun i : I ↦ LifetimePath.coordinate (i : NNReal) omega) = - finiteSetKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) I (Cemetery.alive x) := by + finiteSetKernel (cemeterySemigroup (IsConservative.killedSemigroup P hP U hU hFeller hK)) + I (Cemetery.alive x) := by have hfun : orderedPathToFiniteSet (α := Cemetery U) I ∘ (fun omega : LifetimePath U ↦ fun j : Fin I.card ↦ LifetimePath.coordinate (finiteSetTimes I j) omega) = fun omega : LifetimePath U ↦ fun t : I ↦ LifetimePath.coordinate (t : NNReal) omega := by funext omega t - show LifetimePath.coordinate (finiteSetTimes I ((I.orderIsoOfFin rfl).symm t)) omega = + change LifetimePath.coordinate (finiteSetTimes I ((I.orderIsoOfFin rfl).symm t)) omega = LifetimePath.coordinate (t : NNReal) omega rw [finiteSetTimes_orderIsoOfFin_symm_apply] rw [finiteSetKernel_eq_map, Kernel.map_apply _ (measurable_orderedPathToFiniteSet I), diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean index 63d36807e3..cacb9c8057 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean @@ -49,20 +49,21 @@ variable {beta : Type*} [PseudoMetricSpace beta] /-- The coordinate at time `t` of a lifetime path killed once more at the exit of `W`: the coordinate of the path strictly before the first time it is not a live point of `W`, and the cemetery state from that time on. -/ -noncomputable def killedCoordinate (W : Set beta) (t : NNReal) (eta : LifetimePath beta) : Cemetery beta := +noncomputable def killedCoordinate (W : Set beta) (t : NNReal) (eta : LifetimePath beta) : + Cemetery beta := if (t : ℝ≥0∞) < exitTime W eta then coordinate t eta else Cemetery.delta /-- Before the exit time of `W`, killing again at the exit of `W` changes no coordinate. -/ theorem killedCoordinate_of_lt (W : Set beta) (t : NNReal) (eta : LifetimePath beta) (ht : (t : ℝ≥0∞) < exitTime W eta) : killedCoordinate W t eta = coordinate t eta := - if_pos ht + ite_eq_left ht /-- From the exit time of `W` on, the path killed again at the exit of `W` is at the cemetery. -/ theorem killedCoordinate_of_le (W : Set beta) (t : NNReal) (eta : LifetimePath beta) (ht : exitTime W eta ≤ (t : ℝ≥0∞)) : killedCoordinate W t eta = Cemetery.delta := - if_neg (not_lt.mpr ht) + ite_eq_right (not_lt.mpr ht) end Killing @@ -99,9 +100,9 @@ theorem measurable_killedCoordinate (W : Set beta) (hW : IsOpen W) (t : NNReal) simp only [Set.mem_preimage, Set.mem_union, Set.mem_inter_iff, Set.mem_ofPred_eq, Set.mem_compl_iff, killedCoordinate] by_cases hlt : (t : ℝ≥0∞) < exitTime W eta - · rw [if_pos hlt] + · rw [ite_eq_left hlt] exact ⟨fun h ↦ Or.inl ⟨hlt, h⟩, fun h ↦ h.elim (fun h ↦ h.2) fun h ↦ absurd hlt h⟩ - · rw [if_neg hlt] + · rw [ite_eq_right hlt] exact ⟨fun _ ↦ Or.inr hlt, fun _ ↦ hdelta⟩ rw [hpre] exact (hA.inter (measurable_coordinate t hS)).union hA.compl @@ -110,9 +111,9 @@ theorem measurable_killedCoordinate (W : Set beta) (hW : IsOpen W) (t : NNReal) ext eta simp only [Set.mem_preimage, Set.mem_inter_iff, Set.mem_ofPred_eq, killedCoordinate] by_cases hlt : (t : ℝ≥0∞) < exitTime W eta - · rw [if_pos hlt] + · rw [ite_eq_left hlt] exact ⟨fun h ↦ ⟨hlt, h⟩, fun h ↦ h.2⟩ - · rw [if_neg hlt] + · rw [ite_eq_right hlt] exact ⟨fun h ↦ absurd h hdelta, fun h ↦ absurd h.1 hlt⟩ rw [hpre] exact hA.inter (measurable_coordinate t hS) @@ -168,10 +169,10 @@ theorem killedCoordinate_killAtExit (hUV : U ⊆ V) (omega : ContinuousPath alph Sum.map (Set.inclusion hUV) id (LifetimePath.coordinate t (killAtExit U omega)) := by rw [LifetimePath.killedCoordinate, lifetimePath_exitTime_killAtExit hUV omega] by_cases hlt : (t : ℝ≥0∞) < exitTime U omega - · rw [if_pos hlt, coordinate_killAtExit_inclusion hUV omega t hlt, + · rw [ite_eq_left hlt, coordinate_killAtExit_inclusion hUV omega t hlt, coordinate_killAtExit_of_lt U omega t hlt] rfl - · rw [if_neg hlt, coordinate_killAtExit_of_le U omega t (not_lt.mp hlt)] + · rw [ite_eq_right hlt, coordinate_killAtExit_of_le U omega t (not_lt.mp hlt)] rfl end Nested diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean index 2d59564ffc..ef7b2182de 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean @@ -123,7 +123,8 @@ theorem IsConservative.killedProcess_map_coordinate (t : NNReal) (x : U) : rw [IsConservative.killedProcess_map_coordinate_eq P hP U hU t x] refine Measure.ext fun S hS ↦ ?_ have hC : MeasurableSet (Cemetery.alive ⁻¹' S : Set U) := measurable_inl hS - have hlive : IsConservative.continuousProcess P hP (x : alpha) {omega : ContinuousPath alpha | (t : ℝ≥0∞) < ContinuousPath.exitTime U omega ∧ + have hlive : IsConservative.continuousProcess P hP (x : alpha) {omega : ContinuousPath alpha | + (t : ℝ≥0∞) < ContinuousPath.exitTime U omega ∧ omega t ∈ Subtype.val '' (Cemetery.alive ⁻¹' S)} = IsConservative.killedKernelOn P hP U hU t x (Cemetery.alive ⁻¹' S) := (IsConservative.killedKernelOn_apply_eq_continuousProcess P hP U hU t x hC).symm diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Resolvent.lean index 0bfc99e936..21e8b296d7 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Resolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Resolvent.lean @@ -51,7 +51,8 @@ noncomputable def IsConservative.killedResolvent (lam : ℝ) (f : alpha → ℝ theorem IsConservative.lintegral_killedKernel (t : NNReal) (x : alpha) {f : alpha → ℝ≥0∞} (hf : Measurable f) : ∫⁻ y, f y ∂(IsConservative.killedKernel P hP U hU t x) = - ∫⁻ omega, {omega : ContinuousPath alpha | (t : ℝ≥0∞) < ContinuousPath.exitTime U omega}.indicator + ∫⁻ omega, {omega : ContinuousPath alpha | (t : ℝ≥0∞) < ContinuousPath.exitTime U + omega}.indicator (fun omega ↦ f (omega t)) omega ∂(IsConservative.continuousProcess P hP x) := by have hmeas : Measurable (fun omega : ContinuousPath alpha ↦ omega t) := ContinuousPath.measurable_coordinateProcess (alpha := alpha) t @@ -74,7 +75,8 @@ theorem IsConservative.killedResolvent_eq_lintegral (lam : ℝ) {f : alpha → ((measurable_real_toNNReal.comp measurable_fst).prodMk measurable_snd) have hS : MeasurableSet {p : ℝ × ContinuousPath alpha | ((Real.toNNReal p.1 : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U p.2} := - measurableSet_lt (measurable_coe_nnreal_ennreal.comp (measurable_real_toNNReal.comp measurable_fst)) + measurableSet_lt (measurable_coe_nnreal_ennreal.comp (measurable_real_toNNReal.comp + measurable_fst)) ((ContinuousPath.measurable_exitTime U hU).comp measurable_snd) have hjoint : Measurable (Function.uncurry fun (t : ℝ) (omega : ContinuousPath alpha) ↦ ENNReal.ofReal (Real.exp (-lam * t)) * @@ -102,12 +104,14 @@ theorem IsConservative.killedResolvent_eq_lintegral (lam : ℝ) {f : alpha → ∫⁻ omega, ENNReal.ofReal (Real.exp (-lam * t)) * {omega : ContinuousPath alpha | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < ContinuousPath.exitTime U omega}.indicator - (fun omega ↦ f (omega (Real.toNNReal t))) omega ∂(IsConservative.continuousProcess P hP x) := by + (fun omega ↦ f (omega (Real.toNNReal t))) omega ∂(IsConservative.continuousProcess P + hP x) := by intro t have hg : Measurable (fun omega : ContinuousPath alpha ↦ f (omega (Real.toNNReal t))) := hf.comp (ContinuousPath.measurable_coordinateProcess (alpha := alpha) _) rw [IsConservative.lintegral_killedKernel P hP U hU _ x hf] - exact (lintegral_const_mul _ (hg.indicator (ContinuousPath.measurableSet_lt_exitTime U hU _))).symm + exact (lintegral_const_mul _ (hg.indicator (ContinuousPath.measurableSet_lt_exitTime U hU + _))).symm unfold IsConservative.killedResolvent simp_rw [hinner] rw [lintegral_lintegral_swap hjoint.aemeasurable] diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Semigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Semigroup.lean index 871acd5b13..711fd1397d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Semigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Semigroup.lean @@ -124,7 +124,8 @@ theorem IsConservative.killedKernelOn_zero (hK : P.KolmogorovRegular hP) : refine Kernel.ext fun x ↦ Measure.ext fun B hB ↦ ?_ have hB' : MeasurableSet (Subtype.val '' B) := (MeasurableEmbedding.subtype_coe hU.measurableSet).measurableSet_image.mpr hB - rw [IsConservative.killedKernelOn_apply P hP U hU 0 x hB, IsConservative.killedKernel_zero P hP U hU hK, + rw [IsConservative.killedKernelOn_apply P hP U hU 0 x hB, IsConservative.killedKernel_zero P + hP U hU hK, Kernel.restrict_apply' _ _ _ hB', Kernel.id_apply, Kernel.id_apply, Measure.dirac_apply' _ (hB'.inter hU.measurableSet), Measure.dirac_apply' _ hB] rw [Set.inter_eq_left.mpr (Subtype.coe_image_subset U B), diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Basic.lean index f55f85fab6..5e727e6483 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Basic.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Basic.lean @@ -17,12 +17,14 @@ The canonical measurable structure is generated by the lifetime and all fixed-ti No countable-generation or standard-Borel claim for the lifetime-path carrier is made here. -/ +noncomputable section PortComputability + open MeasureTheory open scoped ENNReal namespace MarkovProcess -noncomputable section +section /-- A path with a possibly infinite lifetime, continuous on its open live-time interval. -/ structure LifetimePath (α : Type*) [TopologicalSpace α] where @@ -47,12 +49,12 @@ def coordinate (t : NNReal) (ω : LifetimePath α) : Cemetery α := theorem coordinate_of_lt (ω : LifetimePath α) (t : NNReal) (ht : (t : ENNReal) < ω.lifetime) : coordinate t ω = Cemetery.alive (ω.livePath ⟨t, ht⟩) := by - rw [coordinate, dif_pos ht] + rw [coordinate, dite_eq_left ht] @[simp] theorem coordinate_of_le (ω : LifetimePath α) (t : NNReal) (ht : ω.lifetime ≤ (t : ENNReal)) : coordinate t ω = Cemetery.delta := by - rw [coordinate, dif_neg (not_lt_of_ge ht)] + rw [coordinate, dite_eq_right (not_lt_of_ge ht)] /-- Coordinates strictly before the lifetime are live. -/ theorem coordinate_ne_delta_of_lt (ω : LifetimePath α) (t : NNReal) @@ -149,7 +151,7 @@ theorem lifetime_ofContinuousPath (ω : C(NNReal, α)) : theorem coordinate_ofContinuousPath (ω : C(NNReal, α)) (t : NNReal) : coordinate t (ofContinuousPath ω) = Cemetery.alive (ω t) := by rw [coordinate_of_lt] - simp only [ofContinuousPath] + · simp only [ofContinuousPath] exact ENNReal.coe_lt_top /-- The infinite-lifetime embedding of ordinary continuous paths is injective. -/ @@ -233,3 +235,5 @@ end LifetimePath end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/CountablySeparated.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/CountablySeparated.lean index b1aead5f4b..d2c3c82b7f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/CountablySeparated.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/CountablySeparated.lean @@ -13,13 +13,15 @@ Lifetime and the coordinates at the fixed countable dense time set separate cont paths. Their measurable coding therefore gives a countable separating family. -/ +noncomputable section PortComputability + open MeasureTheory Set open scoped ENNReal namespace MarkovProcess namespace LifetimePath -noncomputable section +section variable {alpha : Type*} [TopologicalSpace alpha] [T2Space alpha] [MeasurableSpace alpha] @@ -124,3 +126,5 @@ instance instCountablySeparated end end LifetimePath end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTime.lean index 33e35bc235..9046223b4a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTime.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTime.lean @@ -16,12 +16,14 @@ Only deterministic order properties are proved here. No measurability or stoppin made. -/ +noncomputable section PortComputability + open Set open scoped ENNReal namespace MarkovProcess -noncomputable section +section namespace LifetimePath @@ -108,3 +110,5 @@ end LifetimePath end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTimeStopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTimeStopping.lean index 49941beae2..7d3bfe978a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTimeStopping.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTimeStopping.lean @@ -9,12 +9,14 @@ import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration /-! # Exit times as stopping times -/ +noncomputable section PortComputability + open MeasureTheory Set open scoped ENNReal namespace MarkovProcess.LifetimePath -noncomputable section +section variable {alpha : Type*} [PseudoMetricSpace alpha] @@ -218,12 +220,12 @@ private theorem measurableSet_detectsLiveClosedSetBy (t : NNReal) (F : Set alpha {omega | DetectsLiveClosedSetBy t F omega} := by by_cases hFnonempty : F.Nonempty swap - have hevent : {omega | DetectsLiveClosedSetBy t F omega} = ∅ := by - ext omega - change DetectsLiveClosedSetBy t F omega ↔ False - simp only [DetectsLiveClosedSetBy, hFnonempty, false_and] - rw [hevent] - exact @MeasurableSet.empty _ (canonicalFiltration (alpha := alpha) t) + · have hevent : {omega | DetectsLiveClosedSetBy t F omega} = ∅ := by + ext omega + change DetectsLiveClosedSetBy t F omega ↔ False + simp only [DetectsLiveClosedSetBy, hFnonempty, false_and] + rw [hevent] + exact @MeasurableSet.empty _ (canonicalFiltration (alpha := alpha) t) have hmeas (n : ℕ) : MeasurableSet[canonicalFiltration (alpha := alpha) t] ({omega | liveInfDist F (coordinate t omega) < detectionThreshold n} ∪ ⋃ k : ℕ, if h : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t then @@ -253,13 +255,13 @@ private theorem measurableSet_detectsLiveClosedSetBy (t : NNReal) (F : Set alpha · intro h n rcases h n with hendpoint | ⟨k, hkt, hk⟩ · exact Or.inl hendpoint - · exact Or.inr ⟨k, by rw [dif_pos hkt]; exact hk⟩ + · exact Or.inr ⟨k, by rw [dite_eq_left hkt]; exact hk⟩ · intro h n rcases h n with hendpoint | ⟨k, hk⟩ · exact Or.inl hendpoint · by_cases hkt : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t - · exact Or.inr ⟨k, hkt, by simpa only [dif_pos hkt] using! hk⟩ - · simp only [dif_neg hkt, Set.notMem_empty] at hk + · exact Or.inr ⟨k, hkt, by simpa only [dite_eq_left hkt] using! hk⟩ + · simp only [dite_eq_right hkt, Set.notMem_empty] at hk rw [hevent] exact MeasurableSet.iInter hmeas @@ -305,3 +307,5 @@ end Measurable end end MarkovProcess.LifetimePath + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean index 4c90e491c0..433cd017a8 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean @@ -81,7 +81,7 @@ theorem isStoppingTime_lifetime : ext omega simpa only [Set.mem_ofPred_eq, Set.mem_preimage, Set.mem_singleton_iff] using (coordinate_eq_delta_iff omega t).symm - show MeasurableSet[canonicalFiltration (alpha := alpha) t] + change MeasurableSet[canonicalFiltration (alpha := alpha) t] {omega : LifetimePath alpha | omega.lifetime ≤ (t : ENNReal)} rw [hevent] exact (measurable_coordinate_canonicalFiltration t) hdelta diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Killing.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Killing.lean index 789700e360..fc7e037c3b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Killing.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Killing.lean @@ -13,12 +13,14 @@ killing time itself is the cemetery state, so this operation is distinct from en stopping. -/ +noncomputable section PortComputability + open MeasureTheory open scoped ENNReal namespace MarkovProcess.LifetimePath -noncomputable section +section variable {α : Type*} [TopologicalSpace α] @@ -108,3 +110,5 @@ end Measurable end end MarkovProcess.LifetimePath + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Law.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Law.lean index 4251f74e4e..f2e55cd4c3 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Law.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Law.lean @@ -14,12 +14,14 @@ embedding. It records the resulting nonexplosion and coordinate identities witho that any particular dense-time or PDE law has continuous paths. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped ENNReal namespace MarkovProcess -noncomputable section +section namespace Kernel @@ -78,3 +80,5 @@ theorem toLifetimePathKernel_map_coordinate end Kernel end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Nonexplosion.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Nonexplosion.lean index 7359a855ac..91417484fd 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Nonexplosion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Nonexplosion.lean @@ -14,12 +14,14 @@ almost-sure coordinate statements. This is the measure-theoretic reduction later conservativity of transition laws into nonexplosion. -/ +noncomputable section PortComputability + open MeasureTheory open scoped ENNReal NNReal namespace MarkovProcess -noncomputable section +section namespace LifetimePath @@ -92,3 +94,5 @@ theorem isNonexplosive_iff_map_coordinate_nat_delta end Kernel end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/NonexplosiveTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/NonexplosiveTransport.lean index e575c00a5a..a9c94a0450 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/NonexplosiveTransport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/NonexplosiveTransport.lean @@ -13,12 +13,14 @@ lifetime paths whose lifetime is almost surely infinite therefore gives a canoni ordinary continuous paths, independent of the off-support default. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory Set open scoped ENNReal namespace MarkovProcess -noncomputable section +section namespace LifetimePath @@ -157,3 +159,5 @@ theorem fromLifetimePathKernel_toLifetimePathKernel end Kernel end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean index ee36918569..2e279f21ac 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean @@ -12,12 +12,14 @@ This file shifts a lifetime path forward by a fixed finite time. A shift beyond lifetime produces a path with zero lifetime, hence with cemetery state at every coordinate. -/ +noncomputable section PortComputability + open MeasureTheory open scoped ENNReal namespace MarkovProcess.LifetimePath -noncomputable section +section variable {α : Type*} [TopologicalSpace α] @@ -134,3 +136,5 @@ end Measurable end end MarkovProcess.LifetimePath + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Main.lean b/LeanPool/MarkovProcess/MarkovProcess/Main.lean index 71450474c8..0b5aba0c7b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Main.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Main.lean @@ -34,6 +34,8 @@ Nothing here asserts a Hunt-process property, and no statement covers a stopping infinite. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal @@ -56,7 +58,7 @@ end FinsetEvaluation namespace Kernel -noncomputable section DenseFiniteEvaluation +section DenseFiniteEvaluation variable {alpha beta : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [MeasurableSpace beta] @@ -111,7 +113,7 @@ end Kernel namespace SubMarkovKernelSemigroup -noncomputable section +section open IsConservative @@ -397,9 +399,22 @@ theorem IsFellerKernelSemigroup.existsUnique_continuousProcess_of_hasKolmogorovM Q.map (ContinuousPath.finsetEvaluation I) = finiteSetKernel P I := hFeller.existsUnique_continuousProcess P hP (KolmogorovRegular.of_hasKolmogorovMoments P hP hmom) +include hP in +/-- A conservative Feller semigroup satisfying the Kolmogorov moment criterion has a unique +continuous-path Markov kernel realizing all of its finite-dimensional distributions. -/ +theorem _root_.MarkovProcess.existsUnique_continuousProcess + (hFeller : P.IsFellerKernelSemigroup) {p q : ℝ} {M : ℝ≥0} + (hmom : P.HasKolmogorovMoments p q M) : + ∃! Q : Kernel alpha (ContinuousPath alpha), IsMarkovKernel Q ∧ + ∀ I : Finset NNReal, + Q.map (ContinuousPath.finsetEvaluation I) = finiteSetKernel P I := + hFeller.existsUnique_continuousProcess_of_hasKolmogorovMoments P hP hmom + end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean index 3d3d0b3f7c..f5c50f083c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean @@ -79,8 +79,8 @@ theorem IsConservative.lintegral_annealedProcess (x : alpha) {g : ContinuousPath /-- Annealed expectations of bounded strongly measurable functionals are the averages of the quenched expectations: `∫ F d(annealed x) = ∫ (∫ F dQ(theta, x)) mu(dtheta)`. -/ theorem IsConservative.integral_annealedProcess [IsProbabilityMeasure mu] (x : alpha) - {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] - (F : ContinuousPath alpha → E) (hF : StronglyMeasurable F) (C : ℝ) + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] (F : ContinuousPath alpha → E) + (hF : StronglyMeasurable F) (C : ℝ) (hFC : ∀ eta, ‖F eta‖ ≤ C) : ∫ omega, F omega ∂(IsConservative.annealedProcess P hP mu x) = ∫ theta, ∫ omega, F omega ∂(IsConservative.continuousProcess P hP (theta, x)) ∂mu := by @@ -109,7 +109,8 @@ theorem IsConservative.annealedProcess_map_finiteEvaluation_apply have hphi : Measurable (ContinuousPath.finsetEvaluation (alpha := alpha) I) := ContinuousPath.measurable_finsetEvaluation I rw [Measure.map_apply hphi hs, IsConservative.annealedProcess_apply, - Measure.bind_apply (hphi hs) (IsConservative.measurable_continuousProcess_prodMk P hP x).aemeasurable] + Measure.bind_apply (hphi hs) (IsConservative.measurable_continuousProcess_prodMk P hP + x).aemeasurable] refine lintegral_congr fun theta ↦ ?_ rw [← Measure.map_apply hphi hs, IsConservative.continuousProcess_map_finiteEvaluation P hP hFeller hK theta x I] diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeMarginals.lean index cc33b06b8c..3323264cbc 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeMarginals.lean @@ -13,12 +13,14 @@ This file proves a one-time marginal identity. It makes no simultaneous path-su lifetime claim. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace ParameterizedSubMarkovKernelSemigroup -noncomputable section +section variable {Theta D alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] [StandardBorelSpace (Cemetery alpha)] @@ -42,3 +44,5 @@ theorem parameterizedCemeteryDenseTimeTrajectory_map_eval_singleton_delta end end ParameterizedSubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeSupport.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeSupport.lean index 8fbc9acab0..21fb9455a9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeSupport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeSupport.lean @@ -15,11 +15,13 @@ This is only a statement about the countable trajectory. It makes no continuous- lifetime-path, or spatial support claim. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess -noncomputable section +section /-- A cemetery-valued path is live at every point of its index set. -/ def IsLiveAtEveryTime {D alpha : Type*} (path : D → Cemetery alpha) : Prop := @@ -62,3 +64,5 @@ end ParameterizedSubMarkovKernelSemigroup end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeterySemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeterySemigroup.lean index 567d6cc868..ce7edcdb40 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeterySemigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeterySemigroup.lean @@ -13,10 +13,12 @@ This file extends a jointly measurable family of sub-Markov semigroups by one ab cemetery state. The construction is jointly measurable in the parameter, time, and state. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped ENNReal -noncomputable section +section namespace MarkovProcess namespace ParameterizedSubMarkovKernelSemigroup @@ -83,3 +85,7 @@ theorem isConservative_cemeterySemigroup (theta : Theta) : end ParameterizedSubMarkovKernelSemigroup end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcess.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcess.lean index 1c95dc92d0..22c698c17e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcess.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcess.lean @@ -30,13 +30,15 @@ No Markov, strong Markov, Feller, equivariance, annealed or killed statement is of those is a separate transport through the fibre identity. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal namespace MarkovProcess namespace ParameterizedSubMarkovKernelSemigroup -noncomputable section +section section Conservativity @@ -271,3 +273,5 @@ end ContinuousProcess end end ParameterizedSubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeConditionalKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeConditionalKernel.lean index f13f12939c..1e4f1cf9c0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeConditionalKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeConditionalKernel.lean @@ -15,12 +15,14 @@ observation. The resulting conditional kernel is one jointly measurable version. with separately chosen fixed-parameter conditional versions is asserted. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace ParameterizedSubMarkovKernelSemigroup -noncomputable section +section variable {Theta D alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] @@ -101,3 +103,5 @@ theorem compProd_parameterizedObservationCondKernel end end ParameterizedSubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimePrefixKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimePrefixKernel.lean index a6133c91bf..3b0082ef47 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimePrefixKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimePrefixKernel.lean @@ -14,12 +14,14 @@ enumeration. Coordinates remain in enumeration order; the enumeration need not b physical time. Fiberwise conservativity is used only for Markovness and prefix consistency. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace ParameterizedSubMarkovKernelSemigroup -noncomputable section +section variable {Theta D alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] @@ -100,3 +102,5 @@ theorem parameterizedDenseTimePrefixKernel_map_restrictPath end end ParameterizedSubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean index ef3962bd0a..5a36d0520b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean @@ -9,12 +9,14 @@ import Mathlib.Probability.Kernel.IonescuTulcea.Traj /-! # Parameterized trajectories on countable dense time -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace ParameterizedSubMarkovKernelSemigroup -noncomputable section +section universe uTheta uAlpha @@ -178,7 +180,7 @@ private theorem rawTrajAppend_apply_cast (n : ℕ) (z) (i : ↑(Finset.Iic n)) : rawTrajAppend (Theta := Theta) (alpha := alpha) n z ⟨i, Finset.mem_Iic.mpr ((Finset.mem_Iic.mp i.2).trans n.le_succ)⟩ = z.1 i := by simp only [rawTrajAppend, Function.comp_apply, IicProdIoc_def] - rw [dif_pos (Finset.mem_Iic.mp i.2)] + rw [dite_eq_left (Finset.mem_Iic.mp i.2)] rfl omit [StandardBorelSpace alpha] [Nonempty alpha] in @@ -186,7 +188,7 @@ private theorem rawTrajAppend_apply_last (n : ℕ) (z) : rawTrajAppend (Theta := Theta) (alpha := alpha) n z ⟨n + 1, Finset.mem_Iic.mpr (Nat.le_refl (n + 1))⟩ = z.2 := by simp only [rawTrajAppend, Function.comp_apply, IicProdIoc_def] - rw [dif_neg (Nat.not_succ_le_self n)] + rw [dite_eq_right (Nat.not_succ_le_self n)] change (MeasurableEquiv.piSingleton (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) n).symm (MeasurableEquiv.piSingleton n z.2) = z.2 @@ -251,8 +253,7 @@ private theorem historyEquiv_rawTrajAppend (n : ℕ) private theorem transport_traj_step {X H Z Y T : Type*} [MeasurableSpace X] [MeasurableSpace H] [MeasurableSpace Z] [MeasurableSpace Y] [MeasurableSpace T] - (kappa : Kernel X Z) - (eta : Kernel Z Y) [IsSFiniteKernel eta] (E : H ≃ᵐ Z) + (kappa : Kernel X Z) (eta : Kernel Z Y) [IsSFiniteKernel eta] (E : H ≃ᵐ Z) (g : H × Y → T) (hg : Measurable g) (q : Z × Y → T) (hcompat : g ∘ Prod.map E.symm id = q) : (((Kernel.id ×ₖ eta.comap E E.measurable) ∘ₖ kappa.map E.symm).map g) = @@ -268,8 +269,8 @@ private theorem transport_traj_step {X H Z Y T : Type*} rw [E.apply_symm_apply] rw [hcomap, ← Kernel.map_id' eta, Kernel.map_prod_map, ← Kernel.map_comp, ← Kernel.map_comp_right, Kernel.map_id'] - change (Kernel.id ×ₖ eta ∘ₖ kappa).map (g ∘ Prod.map E.symm id) = _ - rw [hcompat] + · change (Kernel.id ×ₖ eta ∘ₖ kappa).map (g ∘ Prod.map E.symm id) = _ + rw [hcompat] all_goals first | exact hg | fun_prop private theorem prod_comp_prod_map_prodAssoc {X A B : Type*} @@ -345,24 +346,24 @@ private theorem partialTraj_map_historyEquiv | zero => rw [Kernel.partialTraj_self, Kernel.id_comp, initialHistoryKernel, Kernel.deterministic_map] - let _ : IsMarkovKernel (P.parameterizedDenseTimePrefixKernel e iota 0) := - P.isMarkovKernel_parameterizedDenseTimePrefixKernel hP e iota 0 - rw [markovKernel_finZero (P.parameterizedDenseTimePrefixKernel e iota 0)] - have hconst : Kernel.const (Theta × alpha) - (Measure.dirac (FiniteOrderedTimes.emptyPath alpha)) = - Kernel.deterministic (fun _ : Theta × alpha ↦ FiniteOrderedTimes.emptyPath alpha) - measurable_const := by - ext q s hs - simp only [Kernel.const_apply, Kernel.deterministic_apply, - Measure.dirac_apply' _ hs] - rw [hconst, Kernel.id, Kernel.deterministic_prod_deterministic] - apply Kernel.deterministic_congr - funext q - apply Prod.ext - · change (historyEquiv 0 (initialHistory q)).1 = q - rw [historyEquiv_fst] - rfl - · exact Subsingleton.elim _ _ + · let _ : IsMarkovKernel (P.parameterizedDenseTimePrefixKernel e iota 0) := + P.isMarkovKernel_parameterizedDenseTimePrefixKernel hP e iota 0 + rw [markovKernel_finZero (P.parameterizedDenseTimePrefixKernel e iota 0)] + have hconst : Kernel.const (Theta × alpha) + (Measure.dirac (FiniteOrderedTimes.emptyPath alpha)) = + Kernel.deterministic (fun _ : Theta × alpha ↦ FiniteOrderedTimes.emptyPath alpha) + measurable_const := by + ext q s hs + simp only [Kernel.const_apply, Kernel.deterministic_apply, + Measure.dirac_apply' _ hs] + rw [hconst, Kernel.id, Kernel.deterministic_prod_deterministic] + apply Kernel.deterministic_congr + funext q + apply Prod.ext + · change (historyEquiv 0 (initialHistory q)).1 = q + rw [historyEquiv_fst] + rfl + · exact Subsingleton.elim _ _ all_goals fun_prop | succ n ih => let _ : IsMarkovKernel (P.parameterizedDenseTimePrefixKernel e iota n) := @@ -546,3 +547,5 @@ theorem parameterizedDenseTimeTrajectory_map_prefix end end ParameterizedSubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectoryMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectoryMarginals.lean index 04b1f2ddcb..b6faad9123 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectoryMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectoryMarginals.lean @@ -13,12 +13,14 @@ This file identifies every coordinate marginal of the jointly measurable paramet trajectory kernel. No standard-Borel assumption is imposed on the parameter space. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace ParameterizedSubMarkovKernelSemigroup -noncomputable section +section variable {Theta D alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] [StandardBorelSpace alpha] [Nonempty alpha] @@ -70,3 +72,5 @@ theorem parameterizedDenseTimeTrajectory_map_eval end end ParameterizedSubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Equivariance.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Equivariance.lean index c18a9aa910..5def8bc3e4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Equivariance.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Equivariance.lean @@ -32,13 +32,15 @@ No scaling limit and no ergodic statement is asserted: the environment map `g`, and both families are given in advance, and nothing is claimed about the law of the environment. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal namespace MarkovProcess namespace ParameterizedSubMarkovKernelSemigroup -noncomputable section +section section Measurability @@ -193,3 +195,5 @@ end end ParameterizedSubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Killed.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Killed.lean index 134591e114..ffaca2c82c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Killed.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Killed.lean @@ -59,7 +59,8 @@ theorem IsConservative.measurable_killedKernelOn_family : (p.1.2.1 : ℝ≥0∞) < ContinuousPath.exitTime U p.2 ∧ p.2 p.1.2.1 ∈ Subtype.val '' B} := by refine MeasurableSet.inter ?_ ?_ · exact measurableSet_lt - (measurable_coe_nnreal_ennreal.comp (measurable_fst.comp (measurable_snd.comp measurable_fst))) + (measurable_coe_nnreal_ennreal.comp (measurable_fst.comp (measurable_snd.comp + measurable_fst))) ((ContinuousPath.measurable_exitTime U hU).comp measurable_snd) · exact (heval.comp ((measurable_fst.comp (measurable_snd.comp measurable_fst)).prodMk measurable_snd)) hB' @@ -86,7 +87,7 @@ noncomputable def IsConservative.killedFamily SubMarkovKernelSemigroup.IsConservative.isSubMarkovKernel_killedKernelOn (P.toSubMarkovKernelSemigroup theta) (hP theta) U hU t -/-- The fibre of the killed family at `theta` is the killed semigroup of the semigroup at `theta`. -/ +/-- The fibre at `theta` is the killed semigroup of the semigroup at that parameter. -/ theorem IsConservative.killedFamily_toSubMarkovKernelSemigroup (hFeller : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) (theta : Theta) : diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Semigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Semigroup.lean index f12e26afa7..d53393e212 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Semigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Semigroup.lean @@ -17,10 +17,12 @@ No parameter family is selected here, and no concrete coefficient, domain, Felle or stochastic-process assertion is made. -/ +noncomputable section PortComputability + open Set open scoped ENNReal ProbabilityTheory -noncomputable section +section namespace MarkovProcess @@ -154,3 +156,7 @@ theorem measure_le_one (theta : Theta) (t : NNReal) (x : alpha) (s : Set alpha) end ParameterizedSubMarkovKernelSemigroup end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean index 3a081456d6..89b9520edb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean @@ -9,11 +9,13 @@ import Mathlib.Topology.MetricSpace.HausdorffDistance /-! # Detecting closed sets from countably many path coordinates -/ +noncomputable section PortComputability + open MeasureTheory Set namespace MarkovProcess -noncomputable section +section namespace ContinuousPath @@ -308,13 +310,13 @@ theorem measurableSet_hitsSetBy (t : NNReal) (F : Set alpha) (hF : IsClosed F) : · intro hdetect n rcases hdetect n with hendpoint | ⟨k, hkt, hk⟩ · exact Or.inl hendpoint - · exact Or.inr ⟨k, by rw [dif_pos hkt]; exact hk⟩ + · exact Or.inr ⟨k, by rw [dite_eq_left hkt]; exact hk⟩ · intro h n rcases h n with hendpoint | ⟨k, hk⟩ · exact Or.inl hendpoint · by_cases hkt : DenseTime.castOrderEmbedding (DenseTime.enumeration k) < t - · exact Or.inr ⟨k, hkt, by simpa only [dif_pos hkt] using! hk⟩ - · simp only [dif_neg hkt, Set.notMem_empty] at hk + · exact Or.inr ⟨k, hkt, by simpa only [dite_eq_left hkt] using! hk⟩ + · simp only [dite_eq_right hkt, Set.notMem_empty] at hk rw [hevent] exact MeasurableSet.iInter fun n ↦ (hA n).union (MeasurableSet.iUnion (hB n)) @@ -322,3 +324,5 @@ end ContinuousPath end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/DenseFiltration.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/DenseFiltration.lean index 5ffc838c5c..f7a908266c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/DenseFiltration.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/DenseFiltration.lean @@ -14,17 +14,20 @@ fact is the filtration bridge needed to extend finite-cylinder restart identitie events. No probability law or Markov property is asserted here. -/ +noncomputable section PortComputability + open Filter MeasureTheory namespace MarkovProcess namespace ContinuousPath -noncomputable section +section variable {alpha : Type*} [PseudoMetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] /-- The measurable space generated by rational-time path coordinates up to `S`. -/ +@[implicit_reducible] def denseCanonicalFiltration (S : DenseTime) : MeasurableSpace (ContinuousPath alpha) := ⨆ r : Set.Iic S, MeasurableSpace.comap @@ -107,3 +110,5 @@ theorem comap_densePastRestriction_eq_canonicalFiltration (S : DenseTime) : end end ContinuousPath end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTime.lean index 84bb7e1615..d95ea1ebfa 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTime.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTime.lean @@ -28,6 +28,8 @@ This file constructs no probability law and proves no probabilistic statement; i does not claim that the exit time is almost surely finite for any process. -/ +noncomputable section PortComputability + open MeasureTheory Set Filter open scoped ENNReal NNReal Topology @@ -35,7 +37,7 @@ namespace MarkovProcess namespace ContinuousPath -noncomputable section +section section SurvivalSets @@ -69,9 +71,9 @@ theorem survivalSet (tau : ℝ≥0∞) : {t : ℝ | ((Real.toNNReal t : NNReal) : ℝ≥0∞) < tau} ∩ Set.Ioi 0 = if tau = ⊤ then Set.Ioi 0 else Set.Ioo 0 tau.toReal := by by_cases htau : tau = ⊤ - · rw [if_pos htau, htau] + · rw [ite_eq_left htau, htau] exact survivalSet_top - · rw [if_neg htau] + · rw [ite_eq_right htau] exact survivalSet_ne_top tau htau end SurvivalSets @@ -261,7 +263,7 @@ theorem isStoppingTime_exitTime (U : Set alpha) (hU : IsOpen U) : ext omega simp only [Set.mem_ofPred_eq] exact exitTime_le_iff_mem_hitsSetBy U hU t omega - show MeasurableSet[canonicalFiltration (alpha := alpha) t] + change MeasurableSet[canonicalFiltration (alpha := alpha) t] {omega : ContinuousPath alpha | exitTimeTop U omega ≤ (t : WithTop NNReal)} rw [hevent] exact measurableSet_hitsSetBy t Uᶜ hU.isClosed_compl @@ -282,3 +284,5 @@ end end ContinuousPath end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/KernelIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/KernelIdentification.lean index 4a7c227d53..e3a6d5f554 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/KernelIdentification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/KernelIdentification.lean @@ -15,12 +15,14 @@ deterministic property of continuous paths; it makes no stochastic-process, Mark claim. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace Kernel -noncomputable section +section variable {alpha beta : Type*} [TopologicalSpace alpha] [T2Space alpha] [MeasurableSpace alpha] [BorelSpace alpha] [MeasurableSpace beta] @@ -77,3 +79,5 @@ theorem map_denseRestriction_eq_iff {kappa eta : Kernel beta (ContinuousPath alp end end Kernel end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/MeasureIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/MeasureIdentification.lean index df1bb8f315..2a4a27cf97 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/MeasureIdentification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/MeasureIdentification.lean @@ -13,12 +13,14 @@ carrier. This is the measure-level counterpart of continuous-path kernel identif deterministic property of continuous paths. -/ +noncomputable section PortComputability + open MeasureTheory namespace MarkovProcess namespace Measure -noncomputable section +section variable {alpha : Type*} [TopologicalSpace alpha] [T2Space alpha] [MeasurableSpace alpha] [BorelSpace alpha] @@ -61,3 +63,5 @@ theorem map_denseRestriction_eq_iff end end Measure end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/MixedFiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/MixedFiniteMarginals.lean index 0f9cb8f7ba..a3a77e12db 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/MixedFiniteMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/MixedFiniteMarginals.lean @@ -19,6 +19,8 @@ This is a finite-dimensional law identity. The conditional factorization of tha the state at `S` is in `Restart/RationalRestart.lean`. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal @@ -26,7 +28,7 @@ namespace MarkovProcess namespace SubMarkovKernelSemigroup namespace IsConservative -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] @@ -73,3 +75,5 @@ end end IsConservative end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/OptionalStopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/OptionalStopping.lean index f5c252a9b1..ac28b9d83e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/OptionalStopping.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/OptionalStopping.lean @@ -35,12 +35,14 @@ a filtration indexed by `ℝ≥0`. No optional-stopping result for unbounded st asserted. -/ +noncomputable section PortComputability + open Filter MeasureTheory Topology open scoped NNReal namespace MarkovProcess -noncomputable section +section variable {Omega : Type*} {m : MeasurableSpace Omega} {mu : Measure Omega} {ℱ : Filtration NNReal m} {M : NNReal → Omega → ℝ} @@ -77,7 +79,8 @@ theorem measurableSet_eq_of_finite_range {S : Omega → NNReal} exact hS.measurableSet_eq_of_countable_range hcount v /-- The value of an adapted process at a stopping time with finite range is measurable. -/ -theorem stronglyMeasurable_apply_of_finite_range (hadapted : StronglyAdapted ℱ M) {S : Omega → NNReal} +theorem stronglyMeasurable_apply_of_finite_range (hadapted : StronglyAdapted ℱ M) {S : Omega → + NNReal} (hS : IsStoppingTime ℱ fun omega ↦ ((S omega : NNReal) : WithTop NNReal)) (hfin : (Set.range S).Finite) : StronglyMeasurable fun omega ↦ M (S omega) omega := by @@ -309,3 +312,5 @@ end OptionalStopping end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/RandomTimeCompactTestConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/RandomTimeCompactTestConvergence.lean index 06532458d2..635c9cc6a9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/RandomTimeCompactTestConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/RandomTimeCompactTestConvergence.lean @@ -16,12 +16,14 @@ continuous-path space; no Markov or kernel assumption is used. The deterministi versions are in `ContinuousPathShiftCompactTestConvergence.lean`. -/ +noncomputable section PortComputability + open Filter MeasureTheory Topology open scoped NNReal ZeroAtInfty CompactlySupported namespace MarkovProcess -noncomputable section +section variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] @@ -84,3 +86,5 @@ theorem tendsto_integral_continuousPath_finiteDenseEvaluation_shift_randomTime_o end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/RelativeHitting.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/RelativeHitting.lean index 5a2573e95f..28a21c21e2 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/RelativeHitting.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/RelativeHitting.lean @@ -20,12 +20,14 @@ Public declarations: * `ContinuousPath.measurableSet_hitsSetBetween`. -/ +noncomputable section PortComputability + open MeasureTheory Set open scoped ENNReal NNReal namespace MarkovProcess -noncomputable section +section namespace ContinuousPath @@ -158,7 +160,7 @@ theorem measurableSet_hitsSetBetween exact hu · exact Or.inl (Or.inr (by simpa only [B] using! ht)) · refine Or.inr ⟨k, ?_⟩ - simp only [C, dif_pos hkt, Set.mem_inter_iff, Set.mem_ofPred_eq] + simp only [C, dite_eq_left hkt, Set.mem_inter_iff, Set.mem_ofPred_eq] exact ⟨huEq.symm ▸ huk, hk⟩ · rintro ⟨hTt, hdetect⟩ have hTne : T omega ≠ ⊤ := ne_top_of_le_ne_top (WithTop.coe_ne_top) hTt @@ -198,3 +200,5 @@ end ContinuousPath end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/ShiftCompactTestConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/ShiftCompactTestConvergence.lean index 2c5a56e9cb..8cf485b709 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/ShiftCompactTestConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/ShiftCompactTestConvergence.lean @@ -13,12 +13,14 @@ dense times. The measure is any finite measure on continuous-path space; no Mark assumption is used. -/ +noncomputable section PortComputability + open Filter MeasureTheory Topology open scoped NNReal ZeroAtInfty CompactlySupported namespace MarkovProcess -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [LocallyCompactSpace alpha] @@ -84,3 +86,5 @@ theorem tendsto_integral_continuousPath_finiteDenseEvaluation_shift end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/StoppingTimeDyadicCeiling.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/StoppingTimeDyadicCeiling.lean index f30cefce5d..52cfc54b09 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/StoppingTimeDyadicCeiling.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/StoppingTimeDyadicCeiling.lean @@ -16,12 +16,14 @@ infrastructure and proves no restart identity; the restart identity obtained fro approximation is in `Trajectory/FellerStoppingRestart.lean`. -/ +noncomputable section PortComputability + open MeasureTheory Filter Topology open scoped NNReal namespace MarkovProcess -noncomputable section +section /-- The level-`n` dyadic ceiling of a nonnegative real time. -/ def dyadicCeiling (n : ℕ) (t : NNReal) : NNReal := @@ -175,3 +177,5 @@ theorem isStoppingTime_dyadicCeiling {f : Filtration NNReal m} {T : Omega → NN end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalExpectation.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalExpectation.lean index a3d0bfe06d..2279f98c08 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalExpectation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalExpectation.lean @@ -17,11 +17,13 @@ only an unconditional distributional identity and is not enough for this conclus No stochastic process, Markov property, or path-space construction is asserted here. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess -noncomputable section +section variable {Omega beta E : Type*} {m : MeasurableSpace Omega} {mOmega : MeasurableSpace Omega} {mBeta : MeasurableSpace beta} @@ -79,3 +81,5 @@ theorem condExp_comp_ae_eq_integral_kernel_of_restrict_map end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalMarkov.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalMarkov.lean index b4463aca01..5f3ca066a4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalMarkov.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalMarkov.lean @@ -18,12 +18,14 @@ The theorem is a conditional API: it does not prove its restricted restart-law h not by itself associate a Markov or Hunt process with a transition semigroup. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace ContinuousPath -noncomputable section +section variable {alpha E : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] @@ -65,3 +67,5 @@ theorem condExp_shift_ae_eq_integral_pathKernel_of_restrict_map end end ContinuousPath end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestart.lean index 11cb30473d..3bf4201def 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestart.lean @@ -16,12 +16,14 @@ infrastructure: the deterministic-time restart identity is a hypothesis here, pr continuous-path process in `Trajectory/FellerRestrictedRestart.lean`. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace ContinuousPath -noncomputable section +section variable {alpha E : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] @@ -187,3 +189,5 @@ theorem condExp_shift_stoppingTime_ae_eq_integral_pathKernel end end ContinuousPath end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/FinitePastRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/FinitePastRestart.lean index fa11a385bc..fe9d074cae 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/FinitePastRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/FinitePastRestart.lean @@ -16,12 +16,14 @@ joint-law factorization. It does not assert that any particular stochastic proc finite-dimensional identities. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace Kernel -noncomputable section +section variable {index alpha beta : Type*} [TopologicalSpace alpha] [T2Space alpha] [MeasurableSpace alpha] [BorelSpace alpha] [MeasurableSpace beta] @@ -110,3 +112,5 @@ theorem eq_of_map_finitePastDenseFutureRestriction_eq end end Kernel end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/MixedPastFuture.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/MixedPastFuture.lean index e3cda96174..57f36dfe94 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/MixedPastFuture.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/MixedPastFuture.lean @@ -16,9 +16,12 @@ This file merges the following former modules, one section each: * `MixedPastFutureCoordinates`: Finite coordinates mixing a rational past and shifted future * `MixedPastFutureCutCoordinates`: Finite mixed coordinates split at their rational terminal time -* `MixedPastFutureCutFactorization`: Factoring finite mixed past/future coordinates at a rational cut +* `MixedPastFutureCutFactorization`: Factoring finite mixed past/future coordinates at a + rational cut -/ +noncomputable section PortComputability + namespace MarkovProcess section MixedPastFutureCoordinates @@ -26,7 +29,7 @@ section MixedPastFutureCoordinates open MeasureTheory -noncomputable section +section namespace MixedPastFuture @@ -242,7 +245,7 @@ open scoped ProbabilityTheory namespace MixedPastFuture -noncomputable section +section private theorem sort_union_eq_append {beta : Type*} [LinearOrder beta] (A B : Finset beta) (hAB : ∀ a ∈ A, ∀ b ∈ B, a < b) : @@ -1120,3 +1123,5 @@ end SubMarkovKernelSemigroup end MixedPastFutureCutFactorization end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestart.lean index 0b8db02202..0d78dc0ea2 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestart.lean @@ -20,6 +20,8 @@ This file merges the following former modules, one section each: * `RationalJointLaw`: Rational-time joint restart law -/ +noncomputable section PortComputability + namespace MarkovProcess section RationalJointKernel @@ -29,7 +31,7 @@ open scoped ProbabilityTheory namespace ContinuousPath -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] @@ -100,7 +102,7 @@ open scoped ProbabilityTheory open scoped NNReal -noncomputable section +section namespace MixedPastFuture @@ -320,18 +322,16 @@ private theorem rationalRestart_map_restrict_eq_cutPullback Kernel.compProd_apply (hA.preimage hH)] congr with history rw [Kernel.prodMkLeft_apply', Kernel.prodMkLeft_apply'] - apply Filter.EventuallyEq.measure_eq + apply Filter.EventuallyEqSet.measure_eq filter_upwards [hzero (ContinuousPath.densePastTerminal S history)] with path hpath apply congrArg (fun z ↦ z ∈ A) funext i rcases i with ⟨i, hi⟩ rcases i with r | t - · - simp [F, H, Function.comp_apply, Kernel.finitePastDenseFuture, + · simp [F, H, Function.comp_apply, Kernel.finitePastDenseFuture, MixedPastFuture.pullbackCutCoordinates, MixedPastFuture.cutCoordinateIndex, MixedPastFuture.restrictPastWithTerminal, Prod.map_apply] - · - by_cases ht : t = 0 + · by_cases ht : t = 0 · subst t have hpath' : path (DenseTime.castOrderEmbedding (0 : DenseTime)) = ContinuousPath.densePastTerminal S history := by @@ -480,7 +480,7 @@ open scoped NNReal namespace SubMarkovKernelSemigroup namespace IsConservative -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] @@ -533,3 +533,5 @@ end SubMarkovKernelSemigroup end RationalJointLaw end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestrictedRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestrictedRestart.lean index 11c7aa106a..26cd24d6ab 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestrictedRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestrictedRestart.lean @@ -16,12 +16,14 @@ factorization remains an explicit input; proving it from the finite-dimensional next process-construction step. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess namespace ContinuousPath -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] @@ -92,3 +94,5 @@ theorem restrict_map_shift_eq_pathKernel_comp_of_rational_joint end end ContinuousPath end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/RestrictedRestartOfJoint.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/RestrictedRestartOfJoint.lean index 5985f546c6..d57ea6029c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/RestrictedRestartOfJoint.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/RestrictedRestartOfJoint.lean @@ -16,11 +16,13 @@ restriction to any event measurable with respect to the conditioning variable. No stochastic process or Markov property is asserted here. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory namespace MarkovProcess -noncomputable section +section variable {Omega beta gamma : Type*} {mOmega : MeasurableSpace Omega} {mBeta : MeasurableSpace beta} {mGamma : MeasurableSpace gamma} @@ -52,3 +54,5 @@ theorem restrict_map_eq_comap_comp_of_map_prodMk_eq_compProd end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialComparison.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialComparison.lean index 238298b4ad..091403e107 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialComparison.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialComparison.lean @@ -21,11 +21,13 @@ Public declarations: No comparison for indicators of arbitrary measurable sets is asserted. -/ +noncomputable section PortComputability + open Filter Set Topology open scoped NNReal ZeroAtInfty open NormedSpace -noncomputable section +section namespace MarkovProcess @@ -227,3 +229,7 @@ end Kernel end PositiveC0ContractiveResolvent end MarkovProcess + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generation.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generation.lean index 28126e6103..d057a2919d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generation.lean @@ -15,9 +15,11 @@ as a strongly continuous contraction semigroup. Strong continuity at zero is first proved on the range of one resolvent and then extended by density. -/ +noncomputable section PortComputability + open Filter NormedSpace Set Topology -noncomputable section +section namespace MarkovProcess.Semigroup @@ -97,3 +99,7 @@ theorem tendsto_yosidaSemigroup_naturalShift_apply_generatedSemigroup end ContractiveResolvent end MarkovProcess.Semigroup + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generator.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generator.lean index 99e6ffcf4b..e4ad869035 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generator.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generator.lean @@ -34,12 +34,14 @@ Times are `NNReal` throughout the library; the real-variable statements read the `Real.toNNReal s`. The fundamental identity is what Dynkin's formula consumes. -/ +noncomputable section PortComputability + open Filter Topology open scoped NNReal namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup -noncomputable section +section variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] variable (S : StronglyContinuousContractionSemigroup E) @@ -182,7 +184,7 @@ theorem tendsto_differenceQuotient_add (f : S.generatorDomain) (t : NNReal) : Tendsto (fun h : NNReal ↦ (h : ℝ)⁻¹ • (S (t + h) f - S t f)) (𝓝[>] 0) (𝓝 (S t (S.generator f))) := by refine (((S t).continuous.tendsto _).comp (S.tendsto_generator f)).congr fun h ↦ ?_ - show S t ((h : ℝ)⁻¹ • (S h f - f)) = (h : ℝ)⁻¹ • (S (t + h) f - S t f) + change S t ((h : ℝ)⁻¹ • (S h f - f)) = (h : ℝ)⁻¹ • (S (t + h) f - S t f) rw [map_smul, map_sub, S.add_apply] end Invariance @@ -242,7 +244,7 @@ theorem hasDerivWithinAt_Ioi (f : S.generatorDomain) (t : NNReal) : apply NNReal.coe_injective rw [NNReal.coe_add, hcoe, Real.coe_toNNReal y hy0] ring - show ((Real.toNNReal (y - t) : NNReal) : ℝ)⁻¹ • + change ((Real.toNNReal (y - t) : NNReal) : ℝ)⁻¹ • (S (t + Real.toNNReal (y - t)) f - S t f) = slope (fun s : ℝ ↦ S (Real.toNNReal s) f) (t : ℝ) y rw [slope_def_module, hcoe, Real.toNNReal_coe, htoNN] @@ -287,7 +289,7 @@ theorem hasDerivWithinAt_Iic (f : S.generatorDomain) {t : ℝ} (ht : 0 < t) : Real.coe_toNNReal t (hy.1.trans hy.2).le] ring have hinv : (y - t)⁻¹ = -(t - y)⁻¹ := by rw [neg_inv, neg_sub] - show S (Real.toNNReal y) (S.differenceQuotient f (Real.toNNReal (t - y))) + change S (Real.toNNReal y) (S.differenceQuotient f (Real.toNNReal (t - y))) = slope (fun s : ℝ ↦ S (Real.toNNReal s) f) t y rw [S.differenceQuotient_apply, map_smul, map_sub, ← S.add_apply, hsum, hcoe, slope_def_module, hinv, neg_smul, ← smul_neg, neg_sub] @@ -381,7 +383,7 @@ private theorem tendsto_slope_add_of_hasDerivAt {F : ℝ → E} {F' : E} {u : have hpos : (0 : ℝ) < h := NNReal.coe_pos.mpr hh exact ne_of_gt (lt_add_of_pos_right u hpos) refine (hslope.comp hmap).congr fun h ↦ ?_ - show slope F u (u + h) = (h : ℝ)⁻¹ • (F (u + h) - F u) + change slope F u (u + h) = (h : ℝ)⁻¹ • (F (u + h) - F u) rw [slope_def_module, add_sub_cancel_left] /-- The orbit integral `∫₀ᵘ S s f ds` of a vector `f`, as a function of the real upper limit @@ -417,9 +419,10 @@ theorem operator_orbitIntegral (f : E) (t h : NNReal) : exact hs.1 have hcoe : Real.toNNReal (s + h) = h + Real.toNNReal s := by apply NNReal.coe_injective - rw [NNReal.coe_add, Real.coe_toNNReal s hs0, Real.coe_toNNReal _ (add_nonneg hs0 h.coe_nonneg), + rw [NNReal.coe_add, Real.coe_toNNReal s hs0, Real.coe_toNNReal _ (add_nonneg hs0 + h.coe_nonneg), add_comm] - show S h (S (Real.toNNReal s) f) = S (Real.toNNReal (s + h)) f + change S h (S (Real.toNNReal s) f) = S (Real.toNNReal (s + h)) f rw [hcoe, S.add_apply] rw [orbitIntegral, ← ContinuousLinearMap.intervalIntegral_comp_comm _ (hint 0 t), intervalIntegral.integral_congr hshift, @@ -469,3 +472,5 @@ end OrbitIntegral end end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorInjectivity.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorInjectivity.lean index 10c43f4d4f..e55b5bfa39 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorInjectivity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorInjectivity.lean @@ -21,12 +21,14 @@ Since `S` is contractive, an eigenvalue `μ > 0` therefore forces `f = 0` `(μ - L)⁻¹` is a well-defined operator. -/ +noncomputable section PortComputability + open Filter Set Topology open scoped NNReal namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup -noncomputable section +section variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] variable (S : StronglyContinuousContractionSemigroup E) @@ -115,3 +117,5 @@ theorem eq_of_smul_sub_generator_eq {μ : ℝ} (hμ : 0 < μ) (f g : S.generator end end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorResolvent.lean index c94d24f359..d032736715 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorResolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorResolvent.lean @@ -31,10 +31,12 @@ canonical shifts by dominated convergence gives `S t x - x = ∫₀ᵗ S s (μ x `R_μ`, and time averages of the orbit then produce the difference quotient at `t = 0`. -/ +noncomputable section PortComputability + open Filter MeasureTheory NormedSpace Set Topology open scoped NNReal -noncomputable section +section namespace MarkovProcess.Semigroup @@ -177,3 +179,5 @@ end ContractiveResolvent end MarkovProcess.Semigroup end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorUniqueness.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorUniqueness.lean index bea578b450..4550be2aae 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorUniqueness.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorUniqueness.lean @@ -25,12 +25,14 @@ and the two difference quotients on the right converge to the common value of th and `T t f`. Density of the generator domain extends the identity to the whole space. -/ +noncomputable section PortComputability + open Filter Set Topology open scoped NNReal namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup -noncomputable section +section variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] variable (S T : StronglyContinuousContractionSemigroup E) @@ -146,3 +148,5 @@ theorem ext_of_generator (hdom : S.generatorDomain = T.generatorDomain) end end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean index 60499c962f..7090bd54d5 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean @@ -16,9 +16,11 @@ Poisson-series argument transferring the latter invariance to each exponential approximant is in `Semigroup/PoissonInvariant.lean`. -/ +noncomputable section PortComputability + open Filter Set Topology -noncomputable section +section namespace MarkovProcess.Semigroup @@ -40,7 +42,7 @@ theorem comp {S : F → G} {T : E → F} /-- A closed set is preserved by the pointwise limit of preserving maps. -/ theorem of_tendsto {ι : Type*} {l : Filter ι} [l.NeBot] - [TopologicalSpace F] {T : ι → E → F} {S : E → F} + [TopologicalSpace F] {T : ι → E → F} {S : E → F} (hD : IsClosed D) (hT : ∀ i, PreservesSet (T i) C D) (hlim : ∀ x, Tendsto (fun i ↦ T i x) l (nhds (S x))) : PreservesSet S C D := by @@ -162,3 +164,7 @@ end CompleteSpace end ContractiveResolvent end MarkovProcess.Semigroup + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitProductRule.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitProductRule.lean index 66aee5c86c..478fd0b99b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitProductRule.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitProductRule.lean @@ -78,7 +78,7 @@ theorem hasDerivWithinAt_operator_apply {v : ℝ → E} {v' : E} {s : ℝ} (hs : have hshift : S (Real.toNNReal s) (S (Real.toNNReal (y - s)) (v s)) = S (Real.toNNReal y) (v s) := by rw [← S.add_apply, hsum] - show S (Real.toNNReal y) (slope v s y) + + change S (Real.toNNReal y) (slope v s y) + S (Real.toNNReal s) (S.differenceQuotient (v s) (Real.toNNReal (y - s))) = slope (fun y : ℝ ↦ S (Real.toNNReal y) (v y)) s y rw [slope_def_module, slope_def_module, S.differenceQuotient_apply, hk, map_smul, map_smul, diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PoissonInvariant.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PoissonInvariant.lean index 5c16fd18f7..b76022e86a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PoissonInvariant.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PoissonInvariant.lean @@ -12,10 +12,12 @@ This file proves the uniformization argument: a normalized resolvent preserving a closed convex set containing zero has Yosida exponentials preserving that set. -/ +noncomputable section PortComputability + open Filter Set Topology open NormedSpace -noncomputable section +section namespace MarkovProcess.Semigroup @@ -192,3 +194,7 @@ theorem preservesSet_generatedSemigroup_of_scaledOperator end ContractiveResolvent end MarkovProcess.Semigroup + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Resolvent.lean index 59bdb11946..30434089c8 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Resolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Resolvent.lean @@ -41,6 +41,8 @@ The shift `μ` is a positive real; nothing is asserted for complex shifts or for generator beyond the half-line `(0, ∞)`. -/ +noncomputable section PortComputability + open MeasureTheory Filter Topology Set open scoped NNReal @@ -49,7 +51,7 @@ namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] variable (S : StronglyContinuousContractionSemigroup E) -noncomputable section +section section Integrand @@ -145,12 +147,12 @@ def resolvent (μ : PositiveShift) : E →L[ℝ] E := { toFun := fun x ↦ ∫ t in Ioi (0 : ℝ), S.laplaceIntegrand μ x t map_add' := fun x y ↦ by rw [laplaceIntegrand_add] - show ∫ t in Ioi (0 : ℝ), (S.laplaceIntegrand μ x t + S.laplaceIntegrand μ y t) = _ + change ∫ t in Ioi (0 : ℝ), (S.laplaceIntegrand μ x t + S.laplaceIntegrand μ y t) = _ exact integral_add (S.integrableOn_laplaceIntegrand μ.2 x) (S.integrableOn_laplaceIntegrand μ.2 y) map_smul' := fun c x ↦ by rw [laplaceIntegrand_smul, RingHom.id_apply] - show ∫ t in Ioi (0 : ℝ), c • S.laplaceIntegrand μ x t = _ + change ∫ t in Ioi (0 : ℝ), c • S.laplaceIntegrand μ x t = _ exact integral_smul c _ } (μ : ℝ)⁻¹ (fun x ↦ S.norm_integral_laplaceIntegrand_le μ.2 x) @@ -290,7 +292,7 @@ theorem resolvent_sub_resolvent (α β : PositiveShift) : /-- The resolvent has dense range. -/ theorem denseRange_resolvent (μ : PositiveShift) : DenseRange (S.resolvent μ) := by - show Dense (Set.range (S.resolvent μ)) + change Dense (Set.range (S.resolvent μ)) rw [← S.generatorDomain_eq_range_resolvent μ] exact S.dense_generatorDomain @@ -312,3 +314,5 @@ end Resolvent end end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventComparison.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventComparison.lean index b3c8e6d95a..71c6bdd08f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventComparison.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventComparison.lean @@ -33,12 +33,14 @@ Both semigroups are read at the same shift `μ`; nothing is asserted when the tw taken at different shifts, and no relation between the two generators is assumed. -/ +noncomputable section PortComputability + open Filter MeasureTheory Topology open scoped NNReal namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup -noncomputable section +section variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] @@ -138,3 +140,5 @@ theorem norm_operator_resolvent_sub_resolvent_operator_le end end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/TrotterKato.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/TrotterKato.lean index 0fb5c1c968..bc88d84025 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/TrotterKato.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/TrotterKato.lean @@ -41,12 +41,14 @@ about convergence in the operator norm, nor about families that are merely unifo rather than contractive. -/ +noncomputable section PortComputability + open Filter MeasureTheory Topology open scoped NNReal namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup -noncomputable section +section variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] variable {ι : Type*} {l : Filter ι} @@ -222,3 +224,5 @@ theorem tendsto_resolvent_of_tendsto_resolvent [l.IsCountablyGenerated] end end MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean index bcac49b1b8..2102729323 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean @@ -15,10 +15,12 @@ For a contractive resolvent `R`, this file defines the bounded generator records commutation and the exact formula on the range of a fixed resolvent. -/ +noncomputable section PortComputability + open Filter Topology open NormedSpace -noncomputable section +section namespace MarkovProcess.Semigroup @@ -150,3 +152,7 @@ theorem tendsto_yosidaGenerator_apply_operator (R : ContractiveResolvent E) end ContractiveResolvent end MarkovProcess.Semigroup + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaStrongLimit.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaStrongLimit.lean index afc643c161..2623a6c1a0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaStrongLimit.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaStrongLimit.lean @@ -16,9 +16,11 @@ orbits is proved in `Semigroup/Generation.lean`, from the criterion of `Semigroup/OrbitContinuity.lean`. -/ +noncomputable section PortComputability + open Filter NormedSpace Set Topology -noncomputable section +section namespace MarkovProcess.Semigroup @@ -172,3 +174,7 @@ end CompleteSpace end ContractiveResolvent end MarkovProcess.Semigroup + +end + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean index 4decc0549b..3200a2292b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ import Mathlib.Data.NNRat.Defs -import Mathlib.Data.NNReal.Defs +import Mathlib.Basic.NNReal.Defs import Mathlib.Data.Rat.Cast.Order import Mathlib.Data.Rat.Encodable import Mathlib.Basic.Denumerable @@ -19,9 +19,11 @@ not increasing. No probability law, projective limit, stochastic process, contin regularity is constructed here. -/ +noncomputable section PortComputability + namespace MarkovProcess -noncomputable section +section namespace CountableEnumeration @@ -144,3 +146,5 @@ noncomputable def enumeration : ℕ ≃ DenseTime := end DenseTime end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteDenseApproximationOrdered.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteDenseApproximationOrdered.lean index 240e2f0099..38f10038cf 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteDenseApproximationOrdered.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteDenseApproximationOrdered.lean @@ -16,12 +16,14 @@ The construction also covers `I = ∅`. In that case the ordered time family and coordinate types are empty. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory Topology Filter open scoped NNReal namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section /-- The physical times of a finite dense approximation, listed in the increasing order inherited from the original finite set. For an empty finite set this is the empty ordered family. -/ @@ -116,3 +118,5 @@ theorem tendsto_finiteDenseApproximationOrderedTimes end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean index 5586cbd3c5..c2e82def7a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ import Mathlib.Algebra.Order.Sub.Basic -import Mathlib.Data.NNReal.Defs +import Mathlib.Basic.NNReal.Defs import Mathlib.MeasureTheory.MeasurableSpace.Constructions import Mathlib.Order.Fin.Basic @@ -130,7 +130,6 @@ def emptyPath (α : Type*) : Fin 0 → α := Fin.elim0 /-- Every path on the empty finite index type is the canonical empty path. -/ -@[simp] theorem eq_emptyPath {α : Type*} (path : Fin 0 → α) : path = emptyPath α := Subsingleton.elim _ _ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean index d435e88c10..b7b53093cb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean @@ -21,12 +21,14 @@ their strictly ordered time coordinates. No continuous-time Markov or Hunt prop or asserted. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped NNReal namespace MarkovProcess -noncomputable section +section /-- Every finite linearly ordered family embedded in nonnegative real time admits strictly ordered rational approximations converging coordinatewise. A common tail shift makes the @@ -86,8 +88,7 @@ def finiteEvaluation {ι α : Type*} [TopologicalSpace α] fun path i ↦ path (τ i) /-- Simultaneous evaluation at finitely many fixed times is continuous in the path. -/ -theorem continuous_finiteEvaluation {ι α : Type*} - [TopologicalSpace α] (τ : ι → NNReal) : +theorem continuous_finiteEvaluation {ι α : Type*} [TopologicalSpace α] (τ : ι → NNReal) : Continuous (finiteEvaluation (α := α) τ) := by apply continuous_pi intro i @@ -95,8 +96,8 @@ theorem continuous_finiteEvaluation {ι α : Type*} /-- If each time in a finite family converges, then simultaneous evaluation along any continuous path converges in the finite product topology. -/ -theorem tendsto_finiteEvaluation {ι α : Type*} - [TopologicalSpace α] (τ : ι → NNReal) (q : ℕ → ι → NNReal) +theorem tendsto_finiteEvaluation {ι α : Type*} [TopologicalSpace α] + (τ : ι → NNReal) (q : ℕ → ι → NNReal) (hq : ∀ i, Tendsto (fun k ↦ q k i) atTop (nhds (τ i))) (path : ContinuousPath α) : Tendsto (fun k ↦ finiteEvaluation (α := α) (q k) path) atTop @@ -114,8 +115,8 @@ variable {α : Type*} [MetricSpace α] [MeasurableSpace α] [BorelSpace α] omit [SecondCountableTopology α] [LocallyCompactSpace α] in /-- Simultaneous evaluation at finitely many fixed times is Borel measurable. -/ -theorem ContinuousPath.measurable_finiteEvaluation {ι : Type*} - (τ : ι → NNReal) : Measurable (finiteEvaluation (α := α) τ) := by +theorem ContinuousPath.measurable_finiteEvaluation {ι : Type*} (τ : ι → NNReal) : + Measurable (finiteEvaluation (α := α) τ) := by rw [measurable_pi_iff] intro i exact measurable_coordinateProcess (alpha := α) (τ i) @@ -126,8 +127,7 @@ omit [MeasurableSpace α] [BorelSpace α] [SecondCountableTopology α] finite family of times along a continuous-path probability kernel. This is the path-side limit needed in every finite-dimensional rational approximation argument. -/ theorem tendsto_integral_continuousPath_finiteEvaluation - {β ι : Type*} [MeasurableSpace β] [Fintype ι] - (K : Kernel β (ContinuousPath α)) (hK : IsMarkovKernel K) + {β ι : Type*} [MeasurableSpace β] (K : Kernel β (ContinuousPath α)) (hK : IsMarkovKernel K) (x : β) (f : CompactlySupportedContinuousMap (ι → α) ℝ) (τ : ι → NNReal) (q : ℕ → ι → NNReal) @@ -159,7 +159,7 @@ The convergence premise is deliberately stated at precisely the analytic seam: i about a Markov property and is exactly the weak/vague continuity of the candidate finite-time laws needed by the proof. -/ theorem Kernel.map_finiteEvaluation_eq_of_integral_tendsto - {β ι : Type*} [MeasurableSpace β] [Fintype ι] + {β ι : Type*} [MeasurableSpace β] [Finite ι] (K : Kernel β (ContinuousPath α)) (hK : IsMarkovKernel K) (Lseq : ℕ → Kernel β (ι → α)) (L : Kernel β (ι → α)) (hL : IsMarkovKernel L) (τ : ι → NNReal) (q : ℕ → ι → NNReal) @@ -168,6 +168,8 @@ theorem Kernel.map_finiteEvaluation_eq_of_integral_tendsto (hfinite : ∀ (x : β) (f : CompactlySupportedContinuousMap (ι → α) ℝ), Tendsto (fun k ↦ ∫ y, f y ∂Lseq k x) atTop (nhds (∫ y, f y ∂L x))) : K.map (ContinuousPath.finiteEvaluation τ) = L := by + classical + let := Fintype.ofFinite ι let : IsMarkovKernel K := hK let : IsMarkovKernel L := hL apply Kernel.ext @@ -340,3 +342,5 @@ end KernelLimits end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeMarginals.lean index 07dc43c463..3bb0b573fe 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeMarginals.lean @@ -22,12 +22,14 @@ and Feller `C₀`-orbit continuity on the other. No continuous-time Markov, strong Markov, or Hunt-process assertion is made here. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped NNReal ZeroAtInfty namespace MarkovProcess -noncomputable section +section /-- Nonnegative rational times admit a sequence converging to every nonnegative real time. -/ theorem exists_denseTime_seq_tendsto (t : NNReal) : @@ -138,3 +140,5 @@ end SubMarkovKernelSemigroup end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Basic.lean index 4022497c62..ca35cee4e3 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Basic.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Basic.lean @@ -18,6 +18,8 @@ No continuous-time Markov property, strong Markov property, Hunt-process asserti increment estimate is claimed. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal @@ -25,7 +27,7 @@ namespace MarkovProcess namespace SubMarkovKernelSemigroup namespace IsConservative -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] @@ -132,3 +134,5 @@ end end IsConservative end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Convergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Convergence.lean index a328c6d957..306ddcca2c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Convergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Convergence.lean @@ -29,12 +29,14 @@ Convergence of the finite-dimensional distributions is not convergence on path s in addition a tightness estimate for the family of laws; that is not asserted here. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped BoundedContinuousFunction NNReal ZeroAtInfty namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section open IsConservative @@ -94,3 +96,5 @@ theorem tendsto_integral_eval_continuousProcess end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/CylinderAlgebra.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/CylinderAlgebra.lean index fb212f2335..9f82d17408 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/CylinderAlgebra.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/CylinderAlgebra.lean @@ -129,13 +129,14 @@ theorem coordinateSubalgebra_separatesPoints [T3Space alpha] [LocallyCompactSpac exact homega (ContinuousPath.ext fun t ↦ not_ne_iff.mp (not_exists.mp hcon t)) obtain ⟨t, ht⟩ := hexists obtain ⟨f, hfone, hfzero, hfcompact, -⟩ := - exists_continuous_one_zero_of_isCompact (isCompact_singleton : IsCompact ({omega t} : Set alpha)) + exists_continuous_one_zero_of_isCompact (isCompact_singleton : IsCompact ({omega t} : Set + alpha)) (isClosed_singleton : IsClosed ({eta t} : Set alpha)) (Set.disjoint_singleton.mpr ht) let f0 : C₀(alpha, ℝ) := ⟨f, HasCompactSupport.is_zero_at_infty hfcompact⟩ let G : C(ContinuousPath alpha, ℝ) := (f0 : C(alpha, ℝ)).comp ⟨fun path ↦ path t, continuous_eval t⟩ refine ⟨G, ⟨G, ⟨Algebra.subset_adjoin ⟨t, f0, rfl⟩, rfl⟩⟩, ?_⟩ - show f (omega t) ≠ f (eta t) + change f (omega t) ≠ f (eta t) rw [hfone (Set.mem_singleton _), hfzero (Set.mem_singleton _)] exact one_ne_zero @@ -181,7 +182,7 @@ theorem exists_boundedCylinder_approx (F : ContinuousPath alpha →ᵇ ℝ) have hGapply : ∀ omega : ContinuousPath alpha, G omega = clampC (G0 omega) := by intro omega rw [hGdef] - show clampC (g0 (finsetEvaluation I omega)) = clampC (G0 omega) + change clampC (g0 (finsetEvaluation I omega)) = clampC (G0 omega) congr 1 exact (hg0 omega).symm refine ⟨G, ⟨I, g, fun omega ↦ rfl⟩, ?_, ?_⟩ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionIntegral.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionIntegral.lean index db5009a385..cd52a2e0b1 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionIntegral.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionIntegral.lean @@ -20,6 +20,8 @@ stopping-time statement is proved here; those are in `Trajectory/FellerCondition `Trajectory/FellerStoppingConditional.lean`. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal CompactlySupported @@ -27,7 +29,7 @@ namespace MarkovProcess namespace SubMarkovKernelSemigroup namespace IsConservative -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] @@ -83,3 +85,5 @@ end end IsConservative end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionMarginals.lean index 06b2a8b6fb..5694e99949 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionMarginals.lean @@ -13,6 +13,8 @@ are the existing finite-set kernels, reindexed from physical time back to ration file makes no shift, Markov, strong Markov, or Hunt-process assertion. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal @@ -20,7 +22,7 @@ namespace MarkovProcess namespace SubMarkovKernelSemigroup namespace IsConservative -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] @@ -69,3 +71,5 @@ end end IsConservative end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseStoppingRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseStoppingRestart.lean index ffef05166d..0292c500ee 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseStoppingRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseStoppingRestart.lean @@ -20,6 +20,8 @@ in `Trajectory/FellerStoppingConditional.lean`, and a stopping time that may be `Trajectory/StoppingLtTop.lean`. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal @@ -27,7 +29,7 @@ namespace MarkovProcess namespace SubMarkovKernelSemigroup namespace IsConservative -noncomputable section +section variable {alpha E : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] @@ -76,3 +78,5 @@ end end IsConservative end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DiscountedDynkin.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DiscountedDynkin.lean index 08f1117e35..7bbe5656d9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DiscountedDynkin.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DiscountedDynkin.lean @@ -30,12 +30,14 @@ Main results: `IsFellerKernelSemigroup.discountedDynkinProcess`, No assertion is made at an unbounded stopping time or about passage to an infinite horizon. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory open scoped ENNReal NNReal ZeroAtInfty namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [LocallyCompactSpace alpha] @@ -53,6 +55,7 @@ def IsFellerKernelSemigroup.discountedDynkinProcess (hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))) (omega (Real.toNNReal s)) +omit [LocallyCompactSpace alpha] in /-- The discounted Dynkin process, unfolded. -/ theorem IsFellerKernelSemigroup.discountedDynkinProcess_apply (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) @@ -64,6 +67,7 @@ theorem IsFellerKernelSemigroup.discountedDynkinProcess_apply (omega (Real.toNNReal s)) := rfl +omit [LocallyCompactSpace alpha] in /-- At zero discount, the discounted Dynkin process is the ordinary Dynkin process. -/ theorem IsFellerKernelSemigroup.discountedDynkinProcess_zero (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) : @@ -82,6 +86,7 @@ private theorem exp_neg_mul_le_exp_abs_mul {lam s v : ℝ} (hs : 0 ≤ s) (hsv : mul_le_mul_of_nonneg_right (neg_le_abs lam) hs _ ≤ |lam| * v := mul_le_mul_of_nonneg_left hsv (abs_nonneg lam) +omit [LocallyCompactSpace alpha] in /-- The discounted Dynkin process is bounded uniformly in the path on bounded time intervals. -/ theorem IsFellerKernelSemigroup.norm_discountedDynkinProcess_le (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) @@ -120,6 +125,7 @@ theorem IsFellerKernelSemigroup.norm_discountedDynkinProcess_le _ = Real.exp (|lam| * (t : ℝ)) * (‖(f : C₀(alpha, ℝ))‖ + (t : ℝ) * ‖g‖) := by ring +omit [LocallyCompactSpace alpha] in /-- The discounted Dynkin process is continuous in time along every path. -/ theorem IsFellerKernelSemigroup.continuous_discountedDynkinProcess (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) @@ -146,6 +152,7 @@ section Adapted variable [SecondCountableTopology alpha] +omit [LocallyCompactSpace alpha] in /-- The discounted generator integrand, clamped to a deterministic horizon, is jointly strongly measurable for time and the canonical filtration at that horizon. -/ private theorem stronglyMeasurable_discountedGenerator_min @@ -160,6 +167,7 @@ private theorem stronglyMeasurable_discountedGenerator_min ((hFeller.c0Semigroup.generator f - lam • (f : C₀(alpha, ℝ))).continuous.comp_stronglyMeasurable (ContinuousPath.measurable_clampedCoordinate (alpha := alpha) t).stronglyMeasurable) +omit [LocallyCompactSpace alpha] in /-- The correction term of the discounted Dynkin process is strongly measurable at its horizon. -/ theorem IsFellerKernelSemigroup.stronglyMeasurable_integral_discountedGenerator (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) @@ -185,6 +193,7 @@ theorem IsFellerKernelSemigroup.stronglyMeasurable_integral_discountedGenerator rw [hfun] exact hprod +omit [LocallyCompactSpace alpha] in /-- The discounted Dynkin process is strongly measurable for the canonical filtration at time `t`. -/ theorem IsFellerKernelSemigroup.stronglyMeasurable_discountedDynkinProcess_canonicalFiltration @@ -198,6 +207,7 @@ theorem IsFellerKernelSemigroup.stronglyMeasurable_discountedDynkinProcess_canon (Real.exp (-lam * (t : ℝ)))).sub (hFeller.stronglyMeasurable_integral_discountedGenerator f lam t) +omit [LocallyCompactSpace alpha] in /-- The discounted Dynkin process at a deterministic time is Borel strongly measurable. -/ theorem IsFellerKernelSemigroup.stronglyMeasurable_discountedDynkinProcess (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) @@ -206,6 +216,7 @@ theorem IsFellerKernelSemigroup.stronglyMeasurable_discountedDynkinProcess (hFeller.stronglyMeasurable_discountedDynkinProcess_canonicalFiltration f lam t).mono ((ContinuousPath.canonicalFiltration (alpha := alpha)).le t) +omit [LocallyCompactSpace alpha] in /-- The discounted Dynkin process is adapted to the canonical filtration. -/ theorem IsFellerKernelSemigroup.adapted_discountedDynkinProcess (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) @@ -221,6 +232,7 @@ section Expectation variable [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] variable (hP : P.IsConservative) +omit [LocallyCompactSpace alpha] in /-- The discounted Dynkin process is integrable under the continuous-path process. -/ theorem IsFellerKernelSemigroup.integrable_discountedDynkinProcess (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) @@ -341,6 +353,7 @@ end Expectation section Decomposition +omit [LocallyCompactSpace alpha] in /-- The discounted Dynkin process decomposes at an intermediate deterministic time. -/ theorem IsFellerKernelSemigroup.discountedDynkinProcess_eq_add_shift (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) @@ -488,6 +501,7 @@ variable [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] variable (hP : P.IsConservative) omit [CompleteSpace alpha] [Nonempty alpha] in +omit [LocallyCompactSpace alpha] in /-- The discounted Dynkin process is progressively measurable. -/ theorem IsFellerKernelSemigroup.progMeasurable_discountedDynkinProcess (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) @@ -498,6 +512,7 @@ theorem IsFellerKernelSemigroup.progMeasurable_discountedDynkinProcess hFeller.continuous_discountedDynkinProcess f lam omega omit [CompleteSpace alpha] [Nonempty alpha] in +omit [LocallyCompactSpace alpha] in /-- The discounted Dynkin process evaluated at a finite stopping time is Borel measurable. -/ theorem IsFellerKernelSemigroup.measurable_discountedDynkinProcess_stoppingTime (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) @@ -626,3 +641,5 @@ end OptionalStopping end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinMartingale.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinMartingale.lean index a85b85ac78..4758ad9c55 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinMartingale.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinMartingale.lean @@ -41,12 +41,14 @@ The exponentially discounted extension is developed in `Trajectory/DiscountedDyn its zero-discount process is identified with this one by `discountedDynkinProcess_zero`. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory Filter open scoped ENNReal NNReal ZeroAtInfty namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section section C0Bound @@ -75,6 +77,7 @@ def IsFellerKernelSemigroup.dynkinProcess (hFeller : P.IsFellerKernelSemigroup) (f : C₀(alpha, ℝ)) (omega t) - ∫ s in (0 : ℝ)..t, (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) +omit [LocallyCompactSpace alpha] in /-- The Dynkin process, written out. -/ theorem IsFellerKernelSemigroup.dynkinProcess_apply (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) (t : NNReal) (omega : ContinuousPath alpha) : @@ -83,6 +86,7 @@ theorem IsFellerKernelSemigroup.dynkinProcess_apply (hFeller : P.IsFellerKernelS ∫ s in (0 : ℝ)..t, (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) := rfl +omit [LocallyCompactSpace alpha] in /-- The integrand of the Dynkin correction term is continuous in the time variable. -/ private theorem continuous_generator_path (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) (omega : ContinuousPath alpha) : @@ -90,6 +94,7 @@ private theorem continuous_generator_path (hFeller : P.IsFellerKernelSemigroup) (hFeller.c0Semigroup.generator f).continuous.comp (omega.continuous.comp continuous_real_toNNReal) +omit [LocallyCompactSpace alpha] in /-- **The Dynkin process is bounded on bounded time intervals**: at time `t` it is bounded by `‖f‖ + t ‖L f‖`, uniformly in the path. -/ theorem IsFellerKernelSemigroup.norm_dynkinProcess_le (hFeller : P.IsFellerKernelSemigroup) @@ -107,6 +112,7 @@ theorem IsFellerKernelSemigroup.norm_dynkinProcess_le (hFeller : P.IsFellerKerne rw [hFeller.dynkinProcess_apply] exact (norm_sub_le _ _).trans (add_le_add (norm_c0_apply_le _ _) hint) +omit [LocallyCompactSpace alpha] in /-- The Dynkin process is continuous in time along every path: the position term is continuous because paths and `f` are, and the correction term is continuous because it is the integral of a continuous integrand over `[0, t]`. -/ @@ -128,6 +134,7 @@ section Adapted variable [SecondCountableTopology alpha] +omit [LocallyCompactSpace alpha] in /-- The coordinate at a time clamped to `[0, t]`, read jointly in the time and the path, is strongly measurable for the product of the Borel structure of the time variable with the canonical filtration at time `t`. This is progressive measurability of the coordinate process, @@ -148,6 +155,7 @@ theorem stronglyMeasurable_integral_prod {Omega : Type*} {mOmega : MeasurableSpa StronglyMeasurable[mOmega] fun omega : Omega ↦ ∫ s, phi (s, omega) ∂mu := hphi.integral_prod_left' +omit [LocallyCompactSpace alpha] in /-- The Dynkin correction term at time `t` is strongly measurable for the canonical filtration at time `t`: it is a Bochner integral over `[0, t]` of a jointly measurable integrand. -/ theorem IsFellerKernelSemigroup.stronglyMeasurable_integral_generator @@ -169,6 +177,7 @@ theorem IsFellerKernelSemigroup.stronglyMeasurable_integral_generator rw [hfun] exact hprod +omit [LocallyCompactSpace alpha] in /-- The Dynkin process at time `t` is strongly measurable for the canonical filtration at time `t`. -/ theorem IsFellerKernelSemigroup.stronglyMeasurable_dynkinProcess_canonicalFiltration @@ -180,6 +189,7 @@ theorem IsFellerKernelSemigroup.stronglyMeasurable_dynkinProcess_canonicalFiltra (alpha := alpha) t).stronglyMeasurable).sub (hFeller.stronglyMeasurable_integral_generator f t) +omit [LocallyCompactSpace alpha] in /-- The Dynkin process at time `t` is Borel measurable on path space. -/ theorem IsFellerKernelSemigroup.stronglyMeasurable_dynkinProcess (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) (t : NNReal) : @@ -187,6 +197,7 @@ theorem IsFellerKernelSemigroup.stronglyMeasurable_dynkinProcess (hFeller.stronglyMeasurable_dynkinProcess_canonicalFiltration f t).mono ((ContinuousPath.canonicalFiltration (alpha := alpha)).le t) +omit [LocallyCompactSpace alpha] in /-- **The Dynkin process is adapted** to the canonical filtration. -/ theorem IsFellerKernelSemigroup.adapted_dynkinProcess (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) : @@ -198,6 +209,7 @@ end Adapted section Decomposition +omit [LocallyCompactSpace alpha] in /-- **Additive decomposition of the Dynkin process at an intermediate time.** For `s ≤ t` the Dynkin process at time `t` is the Dynkin process at time `s`, corrected by the position at time `s`, plus the Dynkin process at time `t - s` of the path shifted by `s`. -/ @@ -255,6 +267,7 @@ variable (hP : P.IsConservative) section Expectation +omit [LocallyCompactSpace alpha] in /-- Integrability of the Dynkin process under the continuous-path process: it is Borel measurable and bounded, and the law of the process is a probability measure. -/ theorem IsFellerKernelSemigroup.integrable_dynkinProcess (hFeller : P.IsFellerKernelSemigroup) @@ -363,7 +376,7 @@ theorem IsFellerKernelSemigroup.martingale_dynkinProcess (hFeller : P.IsFellerKe rw [hcondA] refine (EventuallyEq.add (EventuallyEq.refl _ _) hcondB').trans (Eventually.of_forall fun omega ↦ ?_) - show hFeller.dynkinProcess f s omega - (f : C₀(alpha, ℝ)) (omega s) + + change hFeller.dynkinProcess f s omega - (f : C₀(alpha, ℝ)) (omega s) + (f : C₀(alpha, ℝ)) (omega s) = hFeller.dynkinProcess f s omega ring @@ -374,3 +387,5 @@ end Process end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinStopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinStopping.lean index ec2282fb5c..83c45dfb60 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinStopping.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinStopping.lean @@ -36,12 +36,14 @@ The progressive-measurability and optional-stopping statements below are the zer specializations of the corresponding results in `Trajectory/DiscountedDynkin.lean`. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory open scoped ENNReal NNReal ZeroAtInfty namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [LocallyCompactSpace alpha] @@ -52,6 +54,7 @@ section ProgressiveMeasurability variable [SecondCountableTopology alpha] +omit [LocallyCompactSpace alpha] in /-- The Dynkin process is progressively measurable: it is adapted and continuous in time. -/ theorem IsFellerKernelSemigroup.progMeasurable_dynkinProcess (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) : @@ -60,6 +63,7 @@ theorem IsFellerKernelSemigroup.progMeasurable_dynkinProcess (hFeller : P.IsFell simpa only [hFeller.discountedDynkinProcess_zero f] using! hFeller.progMeasurable_discountedDynkinProcess f 0 +omit [LocallyCompactSpace alpha] in /-- The Dynkin process evaluated at a finite stopping time is Borel measurable. -/ theorem IsFellerKernelSemigroup.measurable_dynkinProcess_stoppingTime (hFeller : P.IsFellerKernelSemigroup) (f : hFeller.c0Semigroup.generatorDomain) @@ -93,6 +97,7 @@ theorem IsFellerKernelSemigroup.integral_dynkinProcess_stoppingTime simpa only [hFeller.discountedDynkinProcess_zero f] using hFeller.integral_discountedDynkinProcess_stoppingTime hP hK f 0 T hT hTK x +omit [LocallyCompactSpace alpha] in /-- The position at a finite stopping time is integrable: it is Borel measurable and bounded by the `C₀` norm of `f`. -/ theorem IsFellerKernelSemigroup.integrable_eval_stoppingTime @@ -109,6 +114,7 @@ theorem IsFellerKernelSemigroup.integrable_eval_stoppingTime rw [← ZeroAtInftyContinuousMap.norm_toBCF_eq_norm] exact BoundedContinuousFunction.norm_coe_le_norm (f : C₀(alpha, ℝ)).toBCF _ +omit [LocallyCompactSpace alpha] in /-- The Dynkin correction term at a finite stopping time bounded by `K` is integrable: it is Borel measurable, being the difference of the position at the stopping time and the Dynkin process there, and bounded by `K ‖L f‖`. -/ @@ -216,6 +222,7 @@ private theorem integrable_exitTimeTrunc (U : Set alpha) (hU : IsOpen U) (K : NN exact NNReal.coe_le_coe.mpr (ContinuousPath.exitTimeTrunc_le U K omega) omit [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] in +omit [LocallyCompactSpace alpha] in /-- Along a path, the Dynkin integrand is at most `-1` almost everywhere on `[0, T]`, where `T` is the truncated exit time: strictly before `T` the path is inside `U`, and the endpoint is a null set. -/ @@ -288,3 +295,5 @@ end ExitTime end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean index 8dbf22839b..b5141f1a1f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean @@ -35,6 +35,8 @@ No scaling limit is asserted: `c` is a fixed positive factor and both semigroups advance. The two state spaces may coincide; the degenerate corollaries are stated on one space. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal @@ -116,7 +118,7 @@ end ContinuousPath namespace SubMarkovKernelSemigroup -noncomputable section +section open IsConservative @@ -157,7 +159,7 @@ theorem IsFellerKernelSemigroup.continuousProcess_map_finiteEvaluation_ordered have htimes : (finiteSetTimes I).restrict emb = times := by apply DFunLike.ext _ _ intro i - show finiteSetTimes I ((I.orderIsoOfFin rfl).symm (phi i)) = times i + change finiteSetTimes I ((I.orderIsoOfFin rfl).symm (phi i)) = times i rw [finiteSetTimes_orderIsoOfFin_symm_apply, hphi i] rw [hcomp, Kernel.map_comp_right _ hfinset hsel, hFeller.continuousProcess_map_finiteEvaluation P hP hK I, finiteSetKernel_eq_map, @@ -207,7 +209,7 @@ theorem IsConservative.continuousProcess_eq_map_rescale ContinuousPath.finiteEvaluation (α := alpha) (fun i ↦ ((finiteSetTimes I).rescale c hc) i) := by funext omega t - show e (omega (c * (t : NNReal))) = + change e (omega (c * (t : NNReal))) = e (omega (c * finiteSetTimes I ((I.orderIsoOfFin rfl).symm t))) rw [finiteSetTimes_orderIsoOfFin_symm_apply] rw [← Kernel.map_comp_right _ (ContinuousPath.measurable_rescale e c) @@ -292,3 +294,5 @@ end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExcessiveStopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExcessiveStopping.lean index da895d3bc4..14e1fac0e0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExcessiveStopping.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExcessiveStopping.lean @@ -28,12 +28,14 @@ Main results: `IsFellerKernelSemigroup.resolvent_isLambdaExcessive`, No converse characterization of excessive functions is asserted. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set Topology open scoped ENNReal NNReal ZeroAtInfty namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section section Supermedian @@ -72,6 +74,7 @@ variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] variable {P : SubMarkovKernelSemigroup alpha} omit [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] in +omit [LocallyCompactSpace alpha] in /-- For a Feller semigroup, every exponentially discounted `C₀` orbit converges in `C₀` norm to its initial function at time zero. Thus `IsLambdaExcessive` includes the usual excessive zero-time condition automatically. -/ @@ -91,6 +94,7 @@ theorem IsFellerKernelSemigroup.tendsto_exp_neg_mul_c0Semigroup_zero Semigroup.StronglyContinuousContractionSemigroup.zero_apply] using hzero omit [CompleteSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] in +omit [LocallyCompactSpace alpha] in /-- The resolvent of a nonnegative `C₀` function at a positive shift is excessive at that shift. -/ theorem IsFellerKernelSemigroup.resolvent_isLambdaExcessive (hFeller : P.IsFellerKernelSemigroup) (lam : ℝ) (hlam : 0 < lam) @@ -422,3 +426,5 @@ theorem IsLambdaExcessive.lintegral_ofReal_discountedValue_exitTime_le end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitLaw.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitLaw.lean index e7a8cfd37f..3b57a762ba 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitLaw.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitLaw.lean @@ -213,7 +213,8 @@ theorem IsFellerKernelSemigroup.integral_exitLawTrunc_eq_of_generator_eq_zero (hFeller : P.IsFellerKernelSemigroup) (hK : P.KolmogorovRegular hP) (f : hFeller.c0Semigroup.generatorDomain) (hLf : ∀ y ∈ U, (hFeller.c0Semigroup.generator f) y = 0) (K : NNReal) (x : alpha) : - ∫ y, (f : C₀(alpha, ℝ)) y ∂(IsConservative.exitLawTrunc hP U hU K x) = (f : C₀(alpha, ℝ)) x := by + ∫ y, (f : C₀(alpha, ℝ)) y ∂(IsConservative.exitLawTrunc hP U hU K x) = (f : C₀(alpha, ℝ)) x + := by rw [IsConservative.integral_exitLawTrunc hP U hU K x (fun y ↦ (f : C₀(alpha, ℝ)) y) (f : C₀(alpha, ℝ)).continuous.stronglyMeasurable] exact hFeller.integral_eval_exitTimeTrunc_eq_of_generator_eq_zero hP hK f U hU hLf K x diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeExponentialMoment.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeExponentialMoment.lean index 02e049a498..e831aeaead 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeExponentialMoment.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeExponentialMoment.lean @@ -41,6 +41,8 @@ Every statement is an inequality of `ℝ≥0∞`-valued integrals; no integrabil no real-valued restatement appears. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory Set open scoped ENNReal NNReal @@ -61,13 +63,13 @@ theorem exponentialStoppingWeight_of_ne_top (lam : ℝ) (sigma : ContinuousPath {omega : ContinuousPath alpha} (h : sigma omega ≠ ⊤) : exponentialStoppingWeight lam sigma omega = ENNReal.ofReal (Real.exp (lam * (sigma omega).toReal)) := - if_neg h + ite_eq_right h /-- On the infinite branch the exponential weight is `⊤`. -/ theorem exponentialStoppingWeight_of_eq_top (lam : ℝ) (sigma : ContinuousPath alpha → ℝ≥0∞) {omega : ContinuousPath alpha} (h : sigma omega = ⊤) : exponentialStoppingWeight lam sigma omega = ⊤ := - if_pos h + ite_eq_left h /-- At a nonnegative rate the exponential weight is at least one. -/ theorem one_le_exponentialStoppingWeight (lam : ℝ) (hlam : 0 ≤ lam) @@ -104,7 +106,7 @@ end ContinuousPath namespace SubMarkovKernelSemigroup -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] @@ -193,7 +195,7 @@ private theorem exponentialWeight_le_add_tsum (lam : ℝ) (hlam : 0 ≤ lam) (t0 set m := Nat.find hex with hm have hmspec : tau ≤ ((m • t0 : NNReal) : ℝ≥0∞) := Nat.find_spec hex have hne : tau ≠ ⊤ := ne_top_of_le_ne_top ENNReal.coe_ne_top hmspec - rw [if_neg hne] + rw [ite_eq_right hne] have hle : ENNReal.ofReal (Real.exp (lam * tau.toReal)) ≤ a ^ m := by rw [← hpow m] refine ENNReal.ofReal_le_ofReal (Real.exp_le_exp.mpr ?_) @@ -515,3 +517,5 @@ end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeLaplace.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeLaplace.lean index 65f0dbb828..deeb08cf3b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeLaplace.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeLaplace.lean @@ -21,12 +21,14 @@ Main results: `IsConservative.lintegral_exp_neg_exitTime` and No moment bound or almost-sure finiteness of the exit time is asserted. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set open scoped ENNReal NNReal namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section /-- The integral of a decaying exponential over a finite interval. -/ private theorem integral_exp_neg_mul_Ioc_zero (lam : ℝ) (hlam : 0 < lam) (A : ℝ) @@ -88,7 +90,7 @@ private theorem ofReal_mul_lintegral_exp_neg_mul_indicator (lam : ℝ) (hlam : 0 · simp only [neg_mul, Set.indicator_of_notMem ht, mul_zero] rw [hfun, setLIntegral_indicator hS] by_cases htau : tau = ⊤ - · rw [ContinuousPath.survivalSet tau, if_pos htau, + · rw [ContinuousPath.survivalSet tau, ite_eq_left htau, lintegral_exp_neg_mul_Ioi_zero lam hlam] subst tau have hnot : (⊤ : ℝ≥0∞) ∉ {tau | tau < ⊤} := by @@ -96,7 +98,7 @@ private theorem ofReal_mul_lintegral_exp_neg_mul_indicator (lam : ℝ) (hlam : 0 rw [Set.indicator_of_notMem hnot, tsub_zero] rw [← ENNReal.ofReal_mul hlam.le] simp only [mul_inv_cancel₀ hlam.ne', ENNReal.ofReal_one] - · rw [ContinuousPath.survivalSet tau, if_neg htau] + · rw [ContinuousPath.survivalSet tau, ite_eq_right htau] rw [show volume.restrict (Set.Ioo (0 : ℝ) tau.toReal) = volume.restrict (Set.Ioc 0 tau.toReal) from Measure.restrict_congr_set Ioo_ae_eq_Ioc] @@ -251,3 +253,5 @@ theorem IsConservative.measure_exitTime_le_le (lam : ℝ) (hlam : 0 ≤ lam) end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerConditional.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerConditional.lean index d888267a5b..0d49cdbbbf 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerConditional.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerConditional.lean @@ -19,11 +19,13 @@ The time here is deterministic. The corresponding statement at a finite stoppin `Trajectory/StoppingLtTop.lean`. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section open IsConservative variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] @@ -60,3 +62,5 @@ theorem IsFellerKernelSemigroup.continuousPathTrajectory_condExp_shift end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerCountableStoppingRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerCountableStoppingRestart.lean index cdcb171dbf..f38ac17d86 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerCountableStoppingRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerCountableStoppingRestart.lean @@ -20,11 +20,13 @@ The stopping time here has countable range. An arbitrary finite stopping time i `Trajectory/StoppingLtTop.lean`. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section open IsConservative variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] @@ -65,3 +67,5 @@ theorem IsFellerKernelSemigroup.continuousPathTrajectory_condExp_shift_countable end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerFiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerFiniteMarginals.lean index 1cb4cd919e..e2da7f9782 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerFiniteMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerFiniteMarginals.lean @@ -17,12 +17,14 @@ The theorem is stated for an arbitrary such semigroup; no particular semigroup i and no Hunt-process property is asserted. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped NNReal namespace MarkovProcess -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [LocallyCompactSpace alpha] @@ -59,3 +61,5 @@ end SubMarkovKernelSemigroup end end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerRestrictedRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerRestrictedRestart.lean index 6654f46c13..0a62775a9a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerRestrictedRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerRestrictedRestart.lean @@ -24,11 +24,13 @@ The time here is deterministic. The strong Markov property at a finite stopping `Trajectory/FellerStoppingRestart.lean`. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped NNReal CompactlySupported ZeroAtInfty namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section open IsConservative variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] @@ -194,3 +196,5 @@ theorem IsFellerKernelSemigroup.continuousPathTrajectory_restrict_map_shift end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerShift.lean index ecae4732a4..83c56597c4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerShift.lean @@ -21,13 +21,15 @@ This is an unconditional kernel-law identity. The conditional form is in `Trajectory/FellerStoppingRestart.lean`; no Hunt-process property is asserted. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal namespace MarkovProcess namespace SubMarkovKernelSemigroup -noncomputable section +section open IsConservative @@ -114,3 +116,5 @@ theorem IsFellerKernelSemigroup.continuousPathTrajectory_map_shift end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingConditional.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingConditional.lean index 8e012ceb02..94e7195b1c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingConditional.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingConditional.lean @@ -21,11 +21,13 @@ infinite is covered, on the event where it is finite, in `Trajectory/StoppingLtT Hunt-process property is asserted. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section open IsConservative variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] @@ -71,3 +73,5 @@ theorem IsFellerKernelSemigroup.continuousPathTrajectory_condExp_shift_stoppingT end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingRestart.lean index cf5fe55b87..dcad8688e1 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingRestart.lean @@ -25,11 +25,13 @@ infinite is covered, on the event where it is finite, in `Trajectory/StoppingLtT Hunt-process property is asserted. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped NNReal CompactlySupported ZeroAtInfty namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section open IsConservative variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] @@ -130,3 +132,5 @@ theorem IsFellerKernelSemigroup.continuousPathTrajectory_restrict_map_shift_stop end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacFunctional.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacFunctional.lean index eccd6e02f5..b0e730215a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacFunctional.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacFunctional.lean @@ -26,12 +26,14 @@ Main results: `feynmanKacAdditiveFunctional`, The resolvent and perturbation identities are developed in `Trajectory/FeynmanKacResolvent.lean`. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set open scoped ENNReal NNReal namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] @@ -117,9 +119,9 @@ theorem stronglyMeasurable_feynmanKacAdditiveFunctional_joint {q : alpha → ℝ exact Eventually.of_forall fun s ↦ by by_cases hs : s ∈ Ioc (0 : ℝ) (p.1 : ℝ) · have hs' : 0 < s ∧ s ≤ (p.1 : ℝ) := hs - simp only [indicator_of_mem hs, phi, if_pos hs'] + simp only [indicator_of_mem hs, phi, ite_eq_left hs'] · have hs' : ¬(0 < s ∧ s ≤ (p.1 : ℝ)) := hs - simp only [indicator_of_notMem hs, phi, if_neg hs'] + simp only [indicator_of_notMem hs, phi, ite_eq_right hs'] rw [heq] exact hint @@ -647,3 +649,5 @@ theorem IsFellerKernelSemigroup.feynmanKac_add (hFeller : P.IsFellerKernelSemigr end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacRealResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacRealResolvent.lean index e59547608d..bf26fec601 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacRealResolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacRealResolvent.lean @@ -26,12 +26,14 @@ Feynman--Kac resolvent among bounded measurable resolvent families solving the s equation at all sufficiently large shifts. No model-specific realization is assumed. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set open scoped ENNReal NNReal namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [CompleteSpace alpha] [Nonempty alpha] @@ -748,3 +750,5 @@ end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacResolvent.lean index ad3de92cff..549601fd24 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacResolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacResolvent.lean @@ -26,12 +26,14 @@ Main results: `IsConservative.feynmanKacResolvent`, No uniqueness statement for the associated resolvent equation is asserted. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set open scoped ENNReal NNReal namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [CompleteSpace alpha] [Nonempty alpha] @@ -746,3 +748,5 @@ theorem IsFellerKernelSemigroup.feynmanKacResolvent_eq_kernelResolvent_sub end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FiniteMarginals.lean index b27218071c..d97d84b475 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FiniteMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FiniteMarginals.lean @@ -16,13 +16,15 @@ No assertion is made at irrational times or about a Markov, strong Markov, or Hu the continuous-path law. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal namespace MarkovProcess namespace SubMarkovKernelSemigroup -noncomputable section +section /-- The finite set of physical nonnegative-real times represented by rational times in `I`. -/ def denseTimePhysicalSet (I : Finset DenseTime) : Finset NNReal := @@ -192,3 +194,5 @@ end IsConservative end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/HarmonicRepresentation.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/HarmonicRepresentation.lean index 34f9007707..000f0ddb95 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/HarmonicRepresentation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/HarmonicRepresentation.lean @@ -124,7 +124,8 @@ theorem IsFellerKernelSemigroup.integral_eval_exitTimeTrunc_eq_of_generator_eq_z ∫ s in (0 : ℝ)..(ContinuousPath.exitTimeTrunc U K omega : ℝ), (hFeller.c0Semigroup.generator f) (omega (Real.toNNReal s)) = 0 := by intro omega - rw [ContinuousPath.integral_exitTimeTrunc_congr U K (g₂ := fun _ ↦ 0) (fun y hy ↦ hLf y hy) omega, + rw [ContinuousPath.integral_exitTimeTrunc_congr U K (g₂ := fun _ ↦ 0) (fun y hy ↦ hLf y hy) + omega, intervalIntegral.integral_zero] simp only [hzero, integral_zero] at hdynkin exact sub_eq_zero.mp hdynkin @@ -150,7 +151,8 @@ theorem IsFellerKernelSemigroup.integral_eval_exitTimeTrunc_add_eq_of_generator_ -∫ s in (0 : ℝ)..(ContinuousPath.exitTimeTrunc U K omega : ℝ), g (omega (Real.toNNReal s)) := by intro omega - rw [ContinuousPath.integral_exitTimeTrunc_congr U K (g₂ := fun y ↦ -g y) (fun y hy ↦ hLf y hy) omega, + rw [ContinuousPath.integral_exitTimeTrunc_congr U K (g₂ := fun y ↦ -g y) (fun y hy ↦ hLf y + hy) omega, intervalIntegral.integral_neg] simp only [hneg, integral_neg] at hdynkin linarith only [hdynkin] diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathModulus.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathModulus.lean index 93a82ff6a8..8dc0a4909c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathModulus.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathModulus.lean @@ -34,6 +34,8 @@ Main results: No tightness, weak continuity, or Hölder-path statement is proved here. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped ENNReal NNReal @@ -41,7 +43,7 @@ namespace MarkovProcess namespace SubMarkovKernelSemigroup -noncomputable section +section open IsConservative @@ -173,3 +175,5 @@ end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathTightness.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathTightness.lean index a0edb5fa78..b365e6c220 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathTightness.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathTightness.lean @@ -16,7 +16,8 @@ of starting points satisfy both hypotheses of the Arzelà--Ascoli tightness crit Tightness is asserted for the starting points ranging over a *compact* set. Over all starting points at once it is false in general already at time zero: the time-zero laws are the Dirac -measures `delta_x`, and `{delta_x : x ∈ alpha}` is tight exactly when `alpha` is compact. A compact set of starting points is also all that weak continuity in the +measures `delta_x`, and `{delta_x : x ∈ alpha}` is tight exactly when `alpha` is compact. A + compact set of starting points is also all that weak continuity in the starting point needs, since continuity at a point only sees a neighbourhood of it. The state space is assumed *proper* (closed balls are compact). This is what discharges the @@ -36,6 +37,8 @@ No compactness theorem for measures (Prokhorov's theorem) is proved or used, and convergence statement is made here. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped ENNReal NNReal @@ -43,7 +46,7 @@ namespace MarkovProcess namespace SubMarkovKernelSemigroup -noncomputable section +section open IsConservative @@ -106,3 +109,5 @@ end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PenalizationDomination.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PenalizationDomination.lean index 64c9f236f3..d5bc80fa31 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PenalizationDomination.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PenalizationDomination.lean @@ -17,12 +17,14 @@ Polish space. Main result: `IsFellerKernelSemigroup.killedResolvent_le_of_perturbed_resolventFamily`. -/ +noncomputable section PortComputability + open MeasureTheory Set open scoped ENNReal namespace MarkovProcess.SubMarkovKernelSemigroup -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [CompleteSpace alpha] [Nonempty alpha] @@ -107,3 +109,5 @@ theorem IsFellerKernelSemigroup.killedResolvent_le_of_perturbed_resolventFamily end end MarkovProcess.SubMarkovKernelSemigroup + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalConditional.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalConditional.lean index 79aaf80844..6dbe9bbf5d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalConditional.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalConditional.lean @@ -20,6 +20,8 @@ The times here are rational. The strong Markov property at an arbitrary finite is in `Trajectory/FellerStoppingRestart.lean`. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal @@ -27,7 +29,7 @@ namespace MarkovProcess namespace SubMarkovKernelSemigroup namespace IsConservative -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] @@ -123,3 +125,5 @@ end end IsConservative end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalShift.lean index 8d049127f8..f704c77127 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalShift.lean @@ -18,6 +18,8 @@ uniqueness on the dense product path space and injectivity of dense restriction. unconditional law identity; conditional and strong Markov statements require additional work. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped NNReal @@ -25,7 +27,7 @@ namespace MarkovProcess namespace SubMarkovKernelSemigroup namespace IsConservative -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] @@ -114,3 +116,5 @@ end end IsConservative end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ResolventExitDecomposition.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ResolventExitDecomposition.lean index adf31cca3c..23adc3a54c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ResolventExitDecomposition.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ResolventExitDecomposition.lean @@ -23,6 +23,8 @@ Main definitions and results: `ContinuousPath.pathResolvent`, No integrability or almost-sure finiteness of the exit time is asserted. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Set open scoped ENNReal NNReal @@ -30,7 +32,7 @@ namespace MarkovProcess namespace ContinuousPath -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] @@ -62,7 +64,7 @@ end ContinuousPath namespace SubMarkovKernelSemigroup -noncomputable section +section variable {alpha : Type*} [MetricSpace alpha] [CompleteSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [SecondCountableTopology alpha] [Nonempty alpha] @@ -306,3 +308,5 @@ end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StartingPointContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StartingPointContinuity.lean index 0b69ed5d8a..43e9f0a243 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StartingPointContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StartingPointContinuity.lean @@ -40,6 +40,8 @@ space; that needs tightness on path space itself, which is not proved here. No a stopping time that can be infinite. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory open scoped BoundedContinuousFunction CompactlySupported NNReal @@ -109,7 +111,7 @@ theorem IsFellerKernelSemigroup.continuous_integral_boundedContinuous_finiteSetK end BoundedContinuousTest -noncomputable section Process +section Process open IsConservative @@ -209,3 +211,5 @@ end Process end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean index ed5a639f4a..accc52e46d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean @@ -34,6 +34,8 @@ Nothing is asserted about the event `{tau = ⊤}`: on it the shifted path is the neither statement constrains it. No Hunt-process property is claimed. -/ +noncomputable section PortComputability + open MeasureTheory ProbabilityTheory open scoped ENNReal NNReal Function @@ -275,10 +277,10 @@ theorem iUnion_stoppingTimeSlice (A : Set Omega) : exact ⟨K, by exact_mod_cast hK⟩ refine Set.mem_iUnion.mpr ⟨Nat.find hex, ⟨hA, ?_⟩, ?_⟩ · refine Set.mem_iInter₂.mpr fun j hj ↦ ?_ - show ((j : NNReal) : WithTop NNReal) < tau omega + change ((j : NNReal) : WithTop NNReal) < tau omega rw [← ht, WithTop.coe_lt_coe] exact lt_of_not_ge (Nat.find_min hex (Set.mem_Iio.mp hj)) - · show tau omega ≤ ((Nat.find hex : NNReal) : WithTop NNReal) + · change tau omega ≤ ((Nat.find hex : NNReal) : WithTop NNReal) rw [← ht, WithTop.coe_le_coe] exact Nat.find_spec hex @@ -480,7 +482,7 @@ end StoppingTime namespace SubMarkovKernelSemigroup -noncomputable section +section open IsConservative @@ -588,3 +590,5 @@ end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakContinuity.lean index 050a84afc7..231fcd129b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakContinuity.lean @@ -38,6 +38,8 @@ Nothing here asserts relative compactness of a family of laws, and no convergenc of semigroups is treated. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped BoundedContinuousFunction ENNReal NNReal @@ -82,7 +84,7 @@ end TruncationError namespace SubMarkovKernelSemigroup -noncomputable section +section open IsConservative @@ -201,3 +203,5 @@ end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakConvergence.lean index 61c2286484..ba6eab7201 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakConvergence.lean @@ -40,6 +40,8 @@ when the constants are allowed to vary, nor for a family whose limit is not itse a Feller semigroup. -/ +noncomputable section PortComputability + open Filter MeasureTheory ProbabilityTheory Topology open scoped BoundedContinuousFunction ENNReal NNReal ZeroAtInfty @@ -48,7 +50,7 @@ namespace MarkovProcess namespace SubMarkovKernelSemigroup -noncomputable section +section open IsConservative @@ -221,3 +223,5 @@ end end SubMarkovKernelSemigroup end MarkovProcess + +end PortComputability diff --git a/LeanPool/projects.yml b/LeanPool/projects.yml index c494ca66cb..50797458a8 100644 --- a/LeanPool/projects.yml +++ b/LeanPool/projects.yml @@ -9986,9 +9986,9 @@ projects: license: Apache-2.0 status: verified main_declarations: - - MarkovProcess.SubMarkovKernelSemigroup.IsFellerKernelSemigroup.existsUnique_continuousProcess_of_hasKolmogorovMoments + - MarkovProcess.existsUnique_continuousProcess main_results: - - declaration: MarkovProcess.SubMarkovKernelSemigroup.IsFellerKernelSemigroup.existsUnique_continuousProcess_of_hasKolmogorovMoments + - declaration: MarkovProcess.existsUnique_continuousProcess informal: A conservative Feller transition semigroup on a nonempty locally compact Polish space satisfying the Kolmogorov moment criterion determines a unique continuous-path Markov kernel with its prescribed finite-dimensional distributions. From 26610c271e3e996f3811061e0156a306643c1b01 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 25 Sep 2026 18:49:18 +0000 Subject: [PATCH 05/11] Preserve MarkovProcess module migration checkpoint --- LeanPool/MarkovProcess.lean | 533 +++++++++--------- LeanPool/MarkovProcess/MarkovProcess.lean | 500 ++++++++-------- .../MarkovProcess/MarkovProcess/Analysis.lean | 7 +- .../MarkovProcess/Analysis/ExpPrimitive.lean | 13 +- .../MarkovProcess/Analysis/PaleyZygmund.lean | 9 +- .../MarkovProcess/Continuity.lean | 29 +- .../DenseTimeContinuousExtension.lean | 11 +- .../Continuity/DenseTimeContinuousLaw.lean | 9 +- .../DenseTimeContinuousSupport.lean | 7 +- .../Continuity/DyadicChaining.lean | 7 +- .../MarkovProcess/Continuity/DyadicFloor.lean | 13 +- .../Continuity/DyadicIncrements.lean | 11 +- .../Continuity/DyadicPathChaining.lean | 9 +- .../GlobalDyadicFloorModification.lean | 9 +- .../KolmogorovDenseTimeContinuousSupport.lean | 11 +- .../Continuity/KolmogorovTimeShift.lean | 7 +- .../MarkovProcess/Continuity/PathModulus.lean | 11 +- .../Continuity/PathTightness.lean | 11 +- .../Continuity/ShiftedUnitModification.lean | 9 +- .../MarkovProcess/DenseTime.lean | 31 +- .../DenseTime/CanonicalDiscreteLaw.lean | 9 +- .../DenseTime/CanonicalDiscretePath.lean | 7 +- .../DenseTime/CemeteryDenseTimeMarginals.lean | 9 +- .../DenseTime/CemeteryExtension.lean | 11 +- .../DenseTime/CemeterySemigroup.lean | 9 +- .../DenseTime/ConditionalKernel.lean | 11 +- .../PhysicalCompactTestTransport.lean | 11 +- .../DenseTime/PhysicalReindex.lean | 7 +- .../MarkovProcess/DenseTime/PrefixKernel.lean | 9 +- .../DenseTime/PrefixRecursion.lean | 9 +- .../MarkovProcess/DenseTime/Shift.lean | 9 +- .../MarkovProcess/DenseTime/Trajectory.lean | 9 +- .../DenseTime/TrajectoryMarginals.lean | 7 +- .../DenseTime/TwoPointMarginals.lean | 13 +- .../MarkovProcess/MarkovProcess/Examples.lean | 15 +- .../Examples/BrownianMotion.lean | 9 +- .../MarkovProcess/Examples/Drift.lean | 7 +- .../MarkovProcess/Examples/HeatGenerator.lean | 11 +- .../MarkovProcess/Examples/HeatOnePoint.lean | 11 +- .../MarkovProcess/Examples/HeatSemigroup.lean | 11 +- .../MarkovProcess/Examples/Identity.lean | 7 +- .../MarkovProcess/MarkovProcess/Feller.lean | 35 +- .../Feller/BackwardC0Convergence.lean | 9 +- .../Feller/BackwardC0Integral.lean | 9 +- .../Feller/BackwardC0Recursion.lean | 9 +- .../CoordinatePolynomialContinuity.lean | 7 +- .../Feller/CoordinateProductContinuity.lean | 11 +- .../DensePhysicalFiniteSetContinuity.lean | 11 +- .../FiniteDenseApproximationContinuity.lean | 11 +- .../FiniteSetCompactTestContinuity.lean | 9 +- .../Feller/FiniteSetConvergence.lean | 11 +- .../FiniteTimeCompactTestContinuity.lean | 9 +- .../Feller/FiniteTimeContinuityBase.lean | 9 +- .../Feller/FiniteTimeConvergence.lean | 15 +- .../FiniteTimeJointCompactTestContinuity.lean | 7 +- .../Feller/FiniteTimeKernelContinuity.lean | 9 +- .../MarkovProcess/Feller/Resolvent.lean | 15 +- .../MarkovProcess/Feller/Semigroup.lean | 9 +- .../MarkovProcess/FiniteTime.lean | 39 +- .../CoordinateProductActiveReduction.lean | 7 +- .../CoordinateProductNormalization.lean | 7 +- .../DenseTimeFiniteSetKernelShift.lean | 9 +- .../FiniteTime/DenseTimeFiniteShift.lean | 7 +- ...iteProductCompactSupportApproximation.lean | 7 +- .../FiniteProductCoordinateNormalForm.lean | 7 +- .../FiniteProductStoneWeierstrass.lean | 13 +- .../FiniteSetKernelCompactTestTransport.lean | 11 +- .../FiniteTime/FiniteSetKernelShift.lean | 11 +- .../MarkovProcess/FiniteTime/Kernel.lean | 13 +- .../FiniteTime/KernelConcatenation.lean | 9 +- .../FiniteTime/KernelDeletion.lean | 9 +- .../FiniteTime/KernelEquivariance.lean | 13 +- .../FiniteTime/KernelMixedPullback.lean | 7 +- .../FiniteTime/KernelRestriction.lean | 9 +- .../MarkovProcess/FiniteTime/KernelShift.lean | 9 +- ...easureFiniteRestrictionIdentification.lean | 7 +- .../FiniteTime/ProjectiveFamily.lean | 11 +- .../MarkovProcess/MarkovProcess/Kernel.lean | 63 ++- .../MarkovProcess/Kernel/Basic.lean | 7 +- .../MarkovProcess/Kernel/C0.lean | 15 +- .../Kernel/C0SemigroupJoint.lean | 11 +- .../MarkovProcess/Kernel/CompProdReindex.lean | 7 +- .../Kernel/ConservativeResolvent.lean | 7 +- .../Kernel/ConservativityAE.lean | 9 +- .../FiniteRestrictionIdentification.lean | 9 +- .../MarkovProcess/Kernel/Integral.lean | 11 +- .../MarkovProcess/Kernel/KernelSemigroup.lean | 7 +- .../Kernel/KolmogorovMoments.lean | 9 +- .../MarkovProcess/Kernel/Lp.lean | 13 +- .../MarkovProcess/Kernel/LpConsistency.lean | 7 +- .../MarkovProcess/Kernel/LpFinite.lean | 13 +- .../MarkovProcess/Kernel/LpTop.lean | 9 +- .../Kernel/MeasurableRadonFamily.lean | 15 +- .../Kernel/OnePointConservative.lean | 11 +- .../Kernel/OnePointExtension.lean | 15 +- .../MarkovProcess/Kernel/OnePointKilled.lean | 19 +- .../Kernel/OnePointKolmogorov.lean | 15 +- .../MarkovProcess/Kernel/Operator.lean | 9 +- .../Kernel/OperatorSemigroup.lean | 7 +- .../Kernel/PositiveC0OperatorKernel.lean | 13 +- .../Kernel/PositiveC0OperatorMass.lean | 7 +- .../Kernel/PositiveC0OperatorMeasure.lean | 9 +- .../Kernel/PositiveC0Resolvent.lean | 9 +- .../Kernel/PositiveC0SemigroupFeller.lean | 9 +- .../Kernel/PositiveC0SemigroupKernel.lean | 15 +- .../MarkovProcess/Kernel/Resolvent.lean | 11 +- .../Kernel/ResolventUniqueness.lean | 7 +- .../MarkovProcess/Kernel/WeakConvergence.lean | 15 +- .../MarkovProcess/MarkovProcess/Killed.lean | 39 +- .../Killed/ExitTimeIdentification.lean | 7 +- .../MarkovProcess/Killed/GluingC0.lean | 13 +- .../MarkovProcess/Killed/GluingLinearity.lean | 7 +- .../MarkovProcess/Killed/GluingLocal.lean | 9 +- .../MarkovProcess/Killed/GluingMeasure.lean | 7 +- .../MarkovProcess/Killed/GluingMinimal.lean | 9 +- .../MarkovProcess/Killed/GluingPotential.lean | 11 +- .../Killed/GluingRealResolvent.lean | 7 +- .../Killed/GluingResolventEquation.lean | 7 +- .../MarkovProcess/Killed/GluingTransfer.lean | 11 +- .../MarkovProcess/Killed/Kernel.lean | 9 +- .../MarkovProcess/Killed/KillAtExit.lean | 7 +- .../MarkovProcess/Killed/Marginals.lean | 11 +- .../MarkovProcess/Killed/Minimal.lean | 11 +- .../MarkovProcess/Killed/Nested.lean | 11 +- .../MarkovProcess/Killed/Process.lean | 9 +- .../MarkovProcess/Killed/Resolvent.lean | 7 +- .../MarkovProcess/Killed/Semigroup.lean | 7 +- .../MarkovProcess/MarkovProcess/Lifetime.lean | 23 +- .../MarkovProcess/Lifetime/Basic.lean | 11 +- .../Lifetime/CountablySeparated.lean | 9 +- .../MarkovProcess/Lifetime/ExitTime.lean | 7 +- .../Lifetime/ExitTimeStopping.lean | 11 +- .../MarkovProcess/Lifetime/Filtration.lean | 11 +- .../MarkovProcess/Lifetime/Killing.lean | 7 +- .../MarkovProcess/Lifetime/Law.lean | 9 +- .../MarkovProcess/Lifetime/Nonexplosion.lean | 7 +- .../Lifetime/NonexplosiveTransport.lean | 7 +- .../MarkovProcess/Lifetime/Shift.lean | 7 +- .../MarkovProcess/MarkovProcess/Main.lean | 29 +- .../MarkovProcess/Parameterized.lean | 35 +- .../MarkovProcess/Parameterized/Annealed.lean | 7 +- .../CemeteryDenseTimeMarginals.lean | 9 +- .../CemeteryDenseTimeSupport.lean | 7 +- .../Parameterized/CemeterySemigroup.lean | 9 +- .../Parameterized/ContinuousProcess.lean | 11 +- .../ContinuousProcessProperties.lean | 7 +- .../DenseTimeConditionalKernel.lean | 11 +- .../Parameterized/DenseTimePrefixKernel.lean | 9 +- .../Parameterized/DenseTimeTrajectory.lean | 11 +- .../DenseTimeTrajectoryMarginals.lean | 9 +- .../Parameterized/Equivariance.lean | 9 +- .../Parameterized/FiniteTimeKernel.lean | 9 +- .../FiniteTimeProjectiveFamily.lean | 9 +- .../MarkovProcess/Parameterized/Killed.lean | 9 +- .../Parameterized/OrderedGrid.lean | 9 +- .../Parameterized/Semigroup.lean | 7 +- .../MarkovProcess/MarkovProcess/Path.lean | 45 +- .../MarkovProcess/Path/Basic.lean | 9 +- .../Path/ClosedSetDetection.lean | 11 +- .../MarkovProcess/Path/DenseFiltration.lean | 7 +- .../Path/DenseRestrictionIntegral.lean | 9 +- .../MarkovProcess/Path/Exhaustion.lean | 7 +- .../MarkovProcess/Path/ExitTime.lean | 11 +- .../MarkovProcess/Path/ExitTimeShift.lean | 9 +- .../Path/KernelIdentification.lean | 9 +- .../Path/MeasureIdentification.lean | 7 +- .../Path/MixedFiniteMarginals.lean | 9 +- .../MarkovProcess/Path/OptionalStopping.lean | 11 +- .../MarkovProcess/Path/Polish.lean | 11 +- .../Path/RandomShiftMeasurability.lean | 9 +- .../RandomTimeCompactTestConvergence.lean | 11 +- .../MarkovProcess/Path/RelativeHitting.lean | 9 +- .../MarkovProcess/Path/Sampling.lean | 7 +- .../MarkovProcess/Path/Shift.lean | 9 +- .../Path/ShiftCompactTestConvergence.lean | 7 +- .../Path/StoppedValueMeasurability.lean | 9 +- .../MarkovProcess/Path/Stopping.lean | 7 +- .../Path/StoppingTimeDyadicCeiling.lean | 9 +- .../MarkovProcess/MarkovProcess/Restart.lean | 21 +- .../Restart/ConditionalExpectation.lean | 9 +- .../Restart/ConditionalMarkov.lean | 9 +- .../Restart/CountableStoppingRestart.lean | 11 +- .../CountableStoppingRestartMeasure.lean | 9 +- .../Restart/FinitePastRestart.lean | 9 +- .../Restart/MixedPastFuture.lean | 15 +- .../Restart/RationalRestart.lean | 17 +- .../Restart/RationalRestrictedRestart.lean | 11 +- .../Restart/RestrictedRestartOfJoint.lean | 9 +- .../MarkovProcess/Semigroup.lean | 53 +- .../MarkovProcess/Semigroup/Basic.lean | 7 +- .../Semigroup/CompactStrongConvergence.lean | 7 +- .../Semigroup/ContractiveResolvent.lean | 9 +- .../Semigroup/DenseCoreConvergence.lean | 7 +- .../MarkovProcess/Semigroup/Duhamel.lean | 11 +- .../Semigroup/ExponentialBounds.lean | 9 +- .../Semigroup/ExponentialComparison.lean | 7 +- .../MarkovProcess/Semigroup/Generation.lean | 11 +- .../MarkovProcess/Semigroup/Generator.lean | 17 +- .../Semigroup/GeneratorClosed.lean | 7 +- .../Semigroup/GeneratorInjectivity.lean | 9 +- .../Semigroup/GeneratorResolvent.lean | 9 +- .../Semigroup/GeneratorUniqueness.lean | 11 +- .../MarkovProcess/Semigroup/InvariantSet.lean | 9 +- .../Semigroup/OrbitContinuity.lean | 9 +- .../Semigroup/OrbitProductRule.lean | 7 +- .../Semigroup/PoissonInvariant.lean | 7 +- .../Semigroup/PositiveShift.lean | 7 +- .../MarkovProcess/Semigroup/Resolvent.lean | 15 +- .../Semigroup/ResolventComparison.lean | 11 +- .../Semigroup/ResolventGeneration.lean | 11 +- .../Semigroup/StrongOperatorLimit.lean | 7 +- .../MarkovProcess/Semigroup/TrotterKato.lean | 9 +- .../Semigroup/YosidaApproximation.lean | 14 +- .../Semigroup/YosidaStrongLimit.lean | 11 +- .../MarkovProcess/MarkovProcess/Time.lean | 19 +- .../Time/CountableDenseTime.lean | 20 +- .../Time/DenseTimeApproximationFromAbove.lean | 7 +- .../MarkovProcess/Time/DenseTimeHistory.lean | 7 +- .../Time/FiniteDenseApproximationOrdered.lean | 7 +- .../Time/FiniteGridIncrement.lean | 9 +- .../Time/FiniteOrderEmbedding.lean | 9 +- .../Time/FiniteOrderedTimes.lean | 13 +- .../MarkovProcess/Time/OrderedGrid.lean | 12 +- .../MarkovProcess/Trajectory.lean | 87 +-- .../Trajectory/AllTimeFiniteMarginals.lean | 9 +- .../Trajectory/AllTimeMarginals.lean | 21 +- .../MarkovProcess/Trajectory/Basic.lean | 9 +- .../Trajectory/ClampedCoordinate.lean | 7 +- .../MarkovProcess/Trajectory/Convergence.lean | 11 +- .../Trajectory/CylinderAlgebra.lean | 9 +- .../Trajectory/DenseRestrictionIntegral.lean | 11 +- .../Trajectory/DenseRestrictionMarginals.lean | 7 +- .../Trajectory/DenseStoppingRestart.lean | 9 +- .../Trajectory/DiscountedDynkin.lean | 11 +- .../MarkovProcess/Trajectory/Dynkin.lean | 15 +- .../Trajectory/DynkinMartingale.lean | 11 +- .../Trajectory/DynkinStopping.lean | 11 +- .../Trajectory/Equivariance.lean | 9 +- .../Trajectory/ExcessiveStopping.lean | 13 +- .../MarkovProcess/Trajectory/ExitLaw.lean | 9 +- .../Trajectory/ExitTimeExponentialMoment.lean | 7 +- .../Trajectory/ExitTimeLaplace.lean | 11 +- .../Trajectory/ExpectedExitTime.lean | 11 +- .../Trajectory/FellerConditional.lean | 7 +- .../FellerCountableStoppingRestart.lean | 9 +- .../Trajectory/FellerFiniteMarginals.lean | 7 +- .../Trajectory/FellerRestrictedRestart.lean | 19 +- .../MarkovProcess/Trajectory/FellerShift.lean | 15 +- .../Trajectory/FellerStoppingConditional.lean | 9 +- .../Trajectory/FellerStoppingRestart.lean | 17 +- .../MarkovProcess/Trajectory/FeynmanKac.lean | 11 +- .../Trajectory/FeynmanKacFunctional.lean | 11 +- .../Trajectory/FeynmanKacRealResolvent.lean | 17 +- .../Trajectory/FeynmanKacResolvent.lean | 15 +- .../Trajectory/FiniteMarginals.lean | 7 +- .../Trajectory/HarmonicRepresentation.lean | 9 +- .../MarkovProcess/Trajectory/PathModulus.lean | 11 +- .../Trajectory/PathTightness.lean | 9 +- .../Trajectory/PenalizationDomination.lean | 7 +- .../Trajectory/RationalConditional.lean | 11 +- .../Trajectory/RationalShift.lean | 15 +- .../ResolventExitDecomposition.lean | 9 +- .../Trajectory/StartingPointContinuity.lean | 17 +- .../Trajectory/StoppingLtTop.lean | 7 +- .../Trajectory/WeakContinuity.lean | 13 +- .../Trajectory/WeakConvergence.lean | 11 +- 266 files changed, 2670 insertions(+), 1372 deletions(-) diff --git a/LeanPool/MarkovProcess.lean b/LeanPool/MarkovProcess.lean index 682e9b7e34..bee1fa9056 100644 --- a/LeanPool/MarkovProcess.lean +++ b/LeanPool/MarkovProcess.lean @@ -4,271 +4,274 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess -import LeanPool.MarkovProcess.MarkovProcess.Analysis -import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive -import LeanPool.MarkovProcess.MarkovProcess.Analysis.PaleyZygmund -import LeanPool.MarkovProcess.MarkovProcess.Continuity -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining -import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification -import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport -import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift -import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus -import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness -import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification -import LeanPool.MarkovProcess.MarkovProcess.DenseTime -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscreteLaw -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryDenseTimeMarginals -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals -import LeanPool.MarkovProcess.MarkovProcess.Examples -import LeanPool.MarkovProcess.MarkovProcess.Examples.BrownianMotion -import LeanPool.MarkovProcess.MarkovProcess.Examples.Drift -import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatGenerator -import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatOnePoint -import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup -import LeanPool.MarkovProcess.MarkovProcess.Examples.Identity -import LeanPool.MarkovProcess.MarkovProcess.Feller -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion -import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeContinuityBase -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily -import LeanPool.MarkovProcess.MarkovProcess.Kernel -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic -import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 -import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint -import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex -import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent -import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativityAE -import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp -import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpConsistency -import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite -import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop -import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OperatorSemigroup -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness -import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence -import LeanPool.MarkovProcess.MarkovProcess.Killed -import LeanPool.MarkovProcess.MarkovProcess.Killed.ExitTimeIdentification -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingC0 -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer -import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel -import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit -import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals -import LeanPool.MarkovProcess.MarkovProcess.Killed.Minimal -import LeanPool.MarkovProcess.MarkovProcess.Killed.Nested -import LeanPool.MarkovProcess.MarkovProcess.Killed.Process -import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.Lifetime -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.CountablySeparated -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Killing -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Nonexplosion -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.NonexplosiveTransport -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift -import LeanPool.MarkovProcess.MarkovProcess.Main -import LeanPool.MarkovProcess.MarkovProcess.Parameterized -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Annealed -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeSupport -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Equivariance -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Killed -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.Path -import LeanPool.MarkovProcess.MarkovProcess.Path.Basic -import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection -import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration -import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral -import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift -import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification -import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification -import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping -import LeanPool.MarkovProcess.MarkovProcess.Path.Polish -import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability -import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence -import LeanPool.MarkovProcess.MarkovProcess.Path.RelativeHitting -import LeanPool.MarkovProcess.MarkovProcess.Path.Sampling -import LeanPool.MarkovProcess.MarkovProcess.Path.Shift -import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence -import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability -import LeanPool.MarkovProcess.MarkovProcess.Path.Stopping -import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling -import LeanPool.MarkovProcess.MarkovProcess.Restart -import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation -import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov -import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure -import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture -import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint -import LeanPool.MarkovProcess.MarkovProcess.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialComparison -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit -import LeanPool.MarkovProcess.MarkovProcess.Time -import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime -import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove -import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes -import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid -import LeanPool.MarkovProcess.MarkovProcess.Trajectory -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExcessiveStopping -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeExponentialMoment -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKac -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalShift -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakConvergence +module + +public import LeanPool.MarkovProcess.MarkovProcess +public import LeanPool.MarkovProcess.MarkovProcess.Analysis +public import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive +public import LeanPool.MarkovProcess.MarkovProcess.Analysis.PaleyZygmund +public import LeanPool.MarkovProcess.MarkovProcess.Continuity +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscreteLaw +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryDenseTimeMarginals +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Examples +public import LeanPool.MarkovProcess.MarkovProcess.Examples.BrownianMotion +public import LeanPool.MarkovProcess.MarkovProcess.Examples.Drift +public import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatGenerator +public import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatOnePoint +public import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Examples.Identity +public import LeanPool.MarkovProcess.MarkovProcess.Feller +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion +public import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeContinuityBase +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +public import LeanPool.MarkovProcess.MarkovProcess.Kernel +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativityAE +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpConsistency +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OperatorSemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Killed +public import LeanPool.MarkovProcess.MarkovProcess.Killed.ExitTimeIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingC0 +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel +public import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Minimal +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Nested +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Process +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.CountablySeparated +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Killing +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Nonexplosion +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.NonexplosiveTransport +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift +public import LeanPool.MarkovProcess.MarkovProcess.Main +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Annealed +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeSupport +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Equivariance +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Killed +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.Path +public import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +public import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration +public import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral +public import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift +public import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +public import LeanPool.MarkovProcess.MarkovProcess.Path.Polish +public import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability +public import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Path.RelativeHitting +public import LeanPool.MarkovProcess.MarkovProcess.Path.Sampling +public import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +public import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability +public import LeanPool.MarkovProcess.MarkovProcess.Path.Stopping +public import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling +public import LeanPool.MarkovProcess.MarkovProcess.Restart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation +public import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov +public import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialComparison +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit +public import LeanPool.MarkovProcess.MarkovProcess.Time +public import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +public import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove +public import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes +public import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExcessiveStopping +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeExponentialMoment +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKac +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalShift +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakConvergence + /-! # MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess.lean b/LeanPool/MarkovProcess/MarkovProcess.lean index c0252e3c2d..40a4cea4a1 100644 --- a/LeanPool/MarkovProcess/MarkovProcess.lean +++ b/LeanPool/MarkovProcess/MarkovProcess.lean @@ -3,252 +3,254 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive -import LeanPool.MarkovProcess.MarkovProcess.Analysis.PaleyZygmund -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining -import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification -import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport -import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift -import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus -import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness -import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscreteLaw -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryDenseTimeMarginals -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals -import LeanPool.MarkovProcess.MarkovProcess.Examples.BrownianMotion -import LeanPool.MarkovProcess.MarkovProcess.Examples.Drift -import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatGenerator -import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup -import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatOnePoint -import LeanPool.MarkovProcess.MarkovProcess.Examples.Identity -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion -import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeContinuityBase -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic -import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 -import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint -import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex -import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativityAE -import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp -import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpConsistency -import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite -import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop -import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled -import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OperatorSemigroup -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness -import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence -import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel -import LeanPool.MarkovProcess.MarkovProcess.Killed.ExitTimeIdentification -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingC0 -import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit -import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals -import LeanPool.MarkovProcess.MarkovProcess.Killed.Minimal -import LeanPool.MarkovProcess.MarkovProcess.Killed.Nested -import LeanPool.MarkovProcess.MarkovProcess.Killed.Process -import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.CountablySeparated -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Killing -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Nonexplosion -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.NonexplosiveTransport -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift -import LeanPool.MarkovProcess.MarkovProcess.Main -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Annealed -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeSupport -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Equivariance -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Killed -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.Path.Basic -import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection -import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration -import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral -import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift -import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification -import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification -import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping -import LeanPool.MarkovProcess.MarkovProcess.Path.Polish -import LeanPool.MarkovProcess.MarkovProcess.Path.Sampling -import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability -import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence -import LeanPool.MarkovProcess.MarkovProcess.Path.RelativeHitting -import LeanPool.MarkovProcess.MarkovProcess.Path.Shift -import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence -import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability -import LeanPool.MarkovProcess.MarkovProcess.Path.Stopping -import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling -import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation -import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov -import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure -import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture -import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialComparison -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit -import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime -import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove -import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes -import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExcessiveStopping -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeExponentialMoment -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKac -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalShift -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakConvergence +module + +public import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive +public import LeanPool.MarkovProcess.MarkovProcess.Analysis.PaleyZygmund +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscreteLaw +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryDenseTimeMarginals +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Examples.BrownianMotion +public import LeanPool.MarkovProcess.MarkovProcess.Examples.Drift +public import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatGenerator +public import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatOnePoint +public import LeanPool.MarkovProcess.MarkovProcess.Examples.Identity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion +public import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeContinuityBase +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativityAE +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpConsistency +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OperatorSemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel +public import LeanPool.MarkovProcess.MarkovProcess.Killed.ExitTimeIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingC0 +public import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Minimal +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Nested +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Process +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.CountablySeparated +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Killing +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Nonexplosion +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.NonexplosiveTransport +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift +public import LeanPool.MarkovProcess.MarkovProcess.Main +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Annealed +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeSupport +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Equivariance +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Killed +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +public import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration +public import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral +public import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift +public import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +public import LeanPool.MarkovProcess.MarkovProcess.Path.Polish +public import LeanPool.MarkovProcess.MarkovProcess.Path.Sampling +public import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability +public import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Path.RelativeHitting +public import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +public import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability +public import LeanPool.MarkovProcess.MarkovProcess.Path.Stopping +public import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling +public import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation +public import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov +public import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialComparison +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit +public import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +public import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove +public import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes +public import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExcessiveStopping +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeExponentialMoment +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKac +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalShift +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakConvergence diff --git a/LeanPool/MarkovProcess/MarkovProcess/Analysis.lean b/LeanPool/MarkovProcess/MarkovProcess/Analysis.lean index 7305dfd612..af0d34486c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Analysis.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Analysis.lean @@ -4,8 +4,11 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive -import LeanPool.MarkovProcess.MarkovProcess.Analysis.PaleyZygmund +module + +public import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive +public import LeanPool.MarkovProcess.MarkovProcess.Analysis.PaleyZygmund + /-! # Analysis diff --git a/LeanPool/MarkovProcess/MarkovProcess/Analysis/ExpPrimitive.lean b/LeanPool/MarkovProcess/MarkovProcess/Analysis/ExpPrimitive.lean index 4633e638fd..af0b2dccf6 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Analysis/ExpPrimitive.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Analysis/ExpPrimitive.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Analysis.SpecialFunctions.Exp -import Mathlib.MeasureTheory.Integral.DominatedConvergence -import Mathlib.MeasureTheory.Integral.Prod -import Mathlib.MeasureTheory.Group.Prod +module + +public import Mathlib.Analysis.SpecialFunctions.Exp +public import Mathlib.MeasureTheory.Integral.DominatedConvergence +public import Mathlib.MeasureTheory.Integral.Prod +public import Mathlib.MeasureTheory.Group.Prod + /-! # Exponential of an integral primitive @@ -22,6 +25,8 @@ Main results: `intervalIntegral.integral_mul_exp_primitive`, No probabilistic structure is used or asserted. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Analysis/PaleyZygmund.lean b/LeanPool/MarkovProcess/MarkovProcess/Analysis/PaleyZygmund.lean index 66fb3227fb..c35cf85f77 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Analysis/PaleyZygmund.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Analysis/PaleyZygmund.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.MeasureTheory.Integral.MeanInequalities -import Mathlib.MeasureTheory.Measure.Typeclasses.Probability +module + +public import Mathlib.MeasureTheory.Integral.MeanInequalities +public import Mathlib.MeasureTheory.Measure.Typeclasses.Probability + /-! # The Paley--Zygmund inequality @@ -26,6 +29,8 @@ supplied by the second moment through the Cauchy--Schwarz inequality Everything is stated for `ℝ≥0∞`-valued functions and carries no integrability side condition. -/ +@[expose] public section + open scoped ENNReal NNReal -- The namespace placement is upstream-facing: this is pure measure theory, with no process diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity.lean index 6084ea45ad..b97c69becf 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity.lean @@ -4,19 +4,22 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining -import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification -import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport -import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift -import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus -import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness -import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification + /-! # Continuity diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousExtension.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousExtension.lean index 296682d236..d01fb828a8 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousExtension.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousExtension.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.Basic -import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime -import Mathlib.MeasureTheory.Constructions.Polish.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +public import Mathlib.MeasureTheory.Constructions.Polish.Basic + /-! # Continuous extension from dense-time paths @@ -19,6 +22,8 @@ No probability law is shown to be supported on this image, and no continuous mod stochastic-process association, or path-regularity claim is made here. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousLaw.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousLaw.lean index 7630e95aa4..f852b68e98 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousLaw.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousLaw.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension -import Mathlib.Probability.Kernel.Composition.MapComap +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +public import Mathlib.Probability.Kernel.Composition.MapComap + /-! # Transporting dense-time laws to continuous paths @@ -13,6 +16,8 @@ This file transports a kernel on dense-time trajectories to ordinary continuous explicit support-on-the-continuous-range hypothesis. It does not prove that support hypothesis. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousSupport.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousSupport.lean index 0086626b37..ce726b3db4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousSupport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DenseTimeContinuousSupport.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousLaw + /-! # Continuous support from a continuous modification @@ -18,6 +21,8 @@ argument of `Continuity/GlobalDyadicFloorModification.lean`, applied to dense-ti kernels in `Continuity/KolmogorovDenseTimeContinuousSupport.lean`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicChaining.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicChaining.lean index bb6ddf90d9..2c62ba51c1 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicChaining.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicChaining.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicIncrements + /-! # Chaining across unit dyadic grids @@ -16,6 +19,8 @@ This file merges the following former modules, one section each: * `DyadicAncestorTail`: Uniform tail bounds for finite dyadic ancestor chains -/ +@[expose] public section + namespace MarkovProcess section DyadicGridChaining diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicFloor.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicFloor.lean index 3b61018d5d..603f82ee44 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicFloor.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicFloor.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining -import Mathlib.Algebra.Order.Floor.Semiring -import Mathlib.MeasureTheory.Function.ConvergenceInMeasure -import Mathlib.MeasureTheory.Integral.Lebesgue.Markov +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining +public import Mathlib.Algebra.Order.Floor.Semiring +public import Mathlib.MeasureTheory.Function.ConvergenceInMeasure +public import Mathlib.MeasureTheory.Integral.Lebesgue.Markov + /-! # Dyadic floor approximation and the unit-interval continuous modification @@ -24,6 +27,8 @@ This file merges the following former modules, one section each: * `DyadicFloorUnitModification`: A continuous modification on the unit interval -/ +@[expose] public section + noncomputable section PortComputability namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicIncrements.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicIncrements.lean index 9bc45d8a81..8980c1df8e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicIncrements.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicIncrements.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement -import Mathlib.Analysis.SpecificLimits.Basic -import Mathlib.MeasureTheory.OuterMeasure.BorelCantelli +module + +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement +public import Mathlib.Analysis.SpecificLimits.Basic +public import Mathlib.MeasureTheory.OuterMeasure.BorelCantelli + /-! # Dyadic increment bounds for the Kolmogorov--Chentsov argument @@ -18,6 +21,8 @@ This file merges the following former modules, one section each: * `DyadicThresholdTail`: Geometric tails of dyadic increment thresholds -/ +@[expose] public section + namespace MarkovProcess section DyadicIncrementSummability diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicPathChaining.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicPathChaining.lean index 7f28b12d2e..a8c108fd32 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicPathChaining.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/DyadicPathChaining.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Analysis.SpecificLimits.Basic -import Mathlib.Topology.EMetricSpace.Basic +module + +public import Mathlib.Analysis.SpecificLimits.Basic +public import Mathlib.Topology.EMetricSpace.Basic + /-! # Dyadic chaining on a bounded interval of nonnegative time @@ -32,6 +35,8 @@ Everything here is a statement about a fixed function of time. No measure, no p and no continuity of `f` is used or asserted. -/ +@[expose] public section + open Filter Topology open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/GlobalDyadicFloorModification.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/GlobalDyadicFloorModification.lean index 260f6883a6..74a4f2b5dc 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/GlobalDyadicFloorModification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/GlobalDyadicFloorModification.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification -import Mathlib.Topology.LocallyFinite +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.ShiftedUnitModification +public import Mathlib.Topology.LocallyFinite + /-! # A global continuous modification assembled from canonical unit paths @@ -20,6 +23,8 @@ No measurability of the path-valued map, path-space law, Markov property, or Hun asserted here. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovDenseTimeContinuousSupport.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovDenseTimeContinuousSupport.lean index a17954b852..6f716bfa44 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovDenseTimeContinuousSupport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovDenseTimeContinuousSupport.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.Polish -import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.Polish +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.GlobalDyadicFloorModification +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousSupport + /-! # Kolmogorov support for dense-time trajectory kernels @@ -18,6 +21,8 @@ No measurability of the totalized modification as a path-valued map, PDE increme Markov property of the resulting paths, or Hunt-process assertion is made here. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean index b7e2440d44..8333edebd7 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/KolmogorovTimeShift.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor + /-! # Nonnegative-rational time shifts @@ -18,6 +21,8 @@ No global path is glued here, and no measurability of the canonical limit or mod assertion is made. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathModulus.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathModulus.lean index 1047a2d61d..5a9fff0e59 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathModulus.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathModulus.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining -import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicChaining +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicPathChaining +public import LeanPool.MarkovProcess.MarkovProcess.Path.Basic + /-! # A quantitative modulus of continuity from a Kolmogorov moment bound @@ -31,6 +34,8 @@ Nothing here constructs a law, asserts a Hölder exponent for individual paths, tightness; tightness is assembled from this estimate elsewhere. -/ +@[expose] public section + open Filter MeasureTheory ProbabilityTheory Topology open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathTightness.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathTightness.lean index ca87cf3567..7241c4bc35 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathTightness.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/PathTightness.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus -import Mathlib.MeasureTheory.Measure.Tight -import Mathlib.Topology.UniformSpace.Ascoli +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus +public import Mathlib.MeasureTheory.Measure.Tight +public import Mathlib.Topology.UniformSpace.Ascoli + /-! # Compact sets of paths, and tightness on continuous-path space @@ -38,6 +41,8 @@ Nothing here constructs a law, and no compactness theorem for measures (Prokhoro proved or used. -/ +@[expose] public section + open Filter MeasureTheory Metric Topology open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Continuity/ShiftedUnitModification.lean b/LeanPool/MarkovProcess/MarkovProcess/Continuity/ShiftedUnitModification.lean index 6998c4fcc1..cde09476c3 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Continuity/ShiftedUnitModification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Continuity/ShiftedUnitModification.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovTimeShift +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DyadicFloor + /-! # Continuous modifications on shifted unit intervals @@ -17,6 +20,8 @@ No global path is glued here, and no path-space measurability, law, or Hunt-proc asserted. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime.lean index 9908dbf50d..f0894b2341 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime.lean @@ -4,20 +4,23 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscreteLaw -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryDenseTimeMarginals -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscreteLaw +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryDenseTimeMarginals +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals + /-! # DenseTime diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscreteLaw.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscreteLaw.lean index 00aa5152b5..f7bba6e8bb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscreteLaw.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscreteLaw.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath -import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CanonicalDiscretePath +public import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid + /-! # Canonical discrete trajectory laws @@ -15,6 +18,8 @@ records exact finite-prefix and coordinate marginal identities. No conditional-expectation Markov property is asserted here. -/ +@[expose] public section + open MeasureTheory open ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscretePath.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscretePath.lean index dc28d2b030..435c116c15 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscretePath.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CanonicalDiscretePath.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Probability.Process.Adapted +module + +public import Mathlib.Probability.Process.Adapted + /-! # Canonical discrete path space @@ -20,6 +23,8 @@ assert any Markov property. * `DiscretePath.canonicalFiltration`: the natural filtration of the coordinate process. -/ +@[expose] public section + open MeasureTheory open TopologicalSpace diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryDenseTimeMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryDenseTimeMarginals.lean index ad3a1a1003..94e1b606cb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryDenseTimeMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryDenseTimeMarginals.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals + /-! # Cemetery marginals of dense-time trajectories @@ -14,6 +17,8 @@ at any dense-time coordinate when started from a live state. This is a finite-c it does not assert that a dense-time path has a continuous lifetime-path extension. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryExtension.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryExtension.lean index 8639061cc0..54a6a4571b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryExtension.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeteryExtension.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic -import Mathlib.Probability.Kernel.Composition.MapComap -import Mathlib.Topology.Constructions.SumProd +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +public import Mathlib.Probability.Kernel.Composition.MapComap +public import Mathlib.Topology.Constructions.SumProd + /-! # Conservative cemetery extension of a sub-Markov kernel @@ -15,6 +18,8 @@ extends one sub-Markov kernel to a Markov kernel. It deliberately makes no claim about preservation of kernel composition or semigroup laws. -/ +@[expose] public section + open MeasureTheory open ProbabilityTheory open scoped ENNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeterySemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeterySemigroup.lean index 8da46fc036..294ff2cafe 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeterySemigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/CemeterySemigroup.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup + /-! # Cemetery extensions of sub-Markov kernel semigroups @@ -15,6 +18,8 @@ extension at every time turns any sub-Markov kernel semigroup into a conservative semigroup on the cemetery state space. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/ConditionalKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/ConditionalKernel.lean index 326ad20045..aa3a79ccff 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/ConditionalKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/ConditionalKernel.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel -import Mathlib.Probability.Kernel.Disintegration.StandardBorel +module + +public import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel +public import Mathlib.Probability.Kernel.Disintegration.StandardBorel + /-! # Conditional kernels for finite dense-time histories @@ -14,6 +17,8 @@ This file augments finite prefix laws by their starting point and disintegrates a prefix and its next observation. It makes no infinite-process or path-regularity claim. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean index 53c05de1b0..3928f39498 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm -import Mathlib.MeasureTheory.Integral.CompactlySupported +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +public import Mathlib.MeasureTheory.Integral.CompactlySupported + /-! # Compact-test transport from physical to dense-time coordinates @@ -15,6 +18,8 @@ corresponding dense times. It pulls compactly supported tests back across this h rewrites integrals against mapped finite-set kernels. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped NNReal CompactlySupported diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalReindex.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalReindex.lean index ae868955be..9d0ef2ce00 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalReindex.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalReindex.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals + /-! # Reindexing finite rational coordinates by physical time @@ -13,6 +16,8 @@ file records the induced measurable path reindexing and its compatibility with c evaluation. No probability-law or Markov claim is made. -/ +@[expose] public section + noncomputable section PortComputability namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean index 38aef371da..f51f0f688e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +module + +public import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily + /-! # Kernels on finite prefixes of a countable time enumeration @@ -14,6 +17,8 @@ enumeration, with coordinates retained in enumeration order. The enumeration nee the order of physical time. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean index 241ab4fa14..8a973fae15 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixRecursion.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel -import Mathlib.Probability.Kernel.Composition.Lemmas +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.ConditionalKernel +public import Mathlib.Probability.Kernel.Composition.Lemmas + /-! # One-step recursion for finite dense-time histories @@ -13,6 +16,8 @@ This file identifies the result of adjoining one conditionally sampled observati augmented finite history. It makes no infinite-process or path-regularity claim. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Shift.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Shift.lean index cf86295e34..d1f667502e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Shift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Shift.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.Shift -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension + /-! # Shifts of dense-time paths @@ -14,6 +17,8 @@ induced shift of dense-time paths. Restriction of a continuous path commutes wi No probability law or Markov property is asserted. -/ +@[expose] public section + noncomputable section PortComputability namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean index e01e703e1f..38e3894482 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/Trajectory.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion -import Mathlib.Probability.Kernel.IonescuTulcea.Traj +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixRecursion +public import Mathlib.Probability.Kernel.IonescuTulcea.Traj + /-! # Trajectories on countable dense time @@ -14,6 +17,8 @@ Mathlib's Ionescu--Tulcea construction, starts the resulting trajectory at a det and reindexes its positive coordinates by a countable dense-time enumeration. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TrajectoryMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TrajectoryMarginals.lean index 1c6820effb..407b560fcb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TrajectoryMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TrajectoryMarginals.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory + /-! # One-time marginals of the dense-time trajectory @@ -12,6 +15,8 @@ This file identifies every coordinate marginal of the dense-time trajectory kern corresponding transition kernel. The result is derived from the exact finite-prefix identity. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TwoPointMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TwoPointMarginals.lean index 0a0b57c9cc..967b021581 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TwoPointMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/TwoPointMarginals.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments -import Mathlib.Probability.Kernel.Composition.Lemmas -import Mathlib.Probability.Process.Kolmogorov +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments +public import Mathlib.Probability.Kernel.Composition.Lemmas +public import Mathlib.Probability.Process.Kolmogorov + /-! # Two-point marginals of the dense-time trajectory, and the intrinsic Kolmogorov bridge @@ -25,6 +28,8 @@ No continuity, modification, Markov-property, or path-regularity statement is pr the two-point law and the moment estimate it transports. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples.lean index 07e3c48c64..bf44f26507 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples.lean @@ -4,12 +4,15 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Examples.BrownianMotion -import LeanPool.MarkovProcess.MarkovProcess.Examples.Drift -import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatGenerator -import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatOnePoint -import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup -import LeanPool.MarkovProcess.MarkovProcess.Examples.Identity +module + +public import LeanPool.MarkovProcess.MarkovProcess.Examples.BrownianMotion +public import LeanPool.MarkovProcess.MarkovProcess.Examples.Drift +public import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatGenerator +public import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatOnePoint +public import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Examples.Identity + /-! # Examples diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean index 67ae638541..a6ddc1efe3 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/BrownianMotion.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup -import Mathlib.Probability.HasLaw +module + +public import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +public import Mathlib.Probability.HasLaw + /-! # The process of the heat semigroup is a Brownian motion @@ -39,6 +42,8 @@ marginals and independent increments, not through a projective family. Only one Levy characterization, quadratic variation, or stochastic integral is asserted. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/Drift.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/Drift.lean index 5dd4eb795b..c2fc018140 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/Drift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/Drift.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Main +module + +public import LeanPool.MarkovProcess.MarkovProcess.Main + /-! # The deterministic drift semigroup and its continuous-path process @@ -19,6 +22,8 @@ theorem are satisfiable by a semigroup that genuinely moves. Nothing here is cl semigroup with a nonzero diffusion part; for that see `MarkovProcess.Examples.HeatSemigroup`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatGenerator.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatGenerator.lean index b8f9b537df..0b75a0e436 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatGenerator.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatGenerator.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup -import Mathlib.Analysis.Calculus.MeanValue -import Mathlib.Analysis.Calculus.IteratedDeriv.Lemmas +module + +public import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +public import Mathlib.Analysis.Calculus.MeanValue +public import Mathlib.Analysis.Calculus.IteratedDeriv.Lemmas + /-! # Gaussian averages and half the Laplacian on the line @@ -43,6 +46,8 @@ contained), and nothing is claimed in dimension greater than one or for a functi stated smoothness class. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean index d872229865..6602b5d9a4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatOnePoint.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal +module + +public import LeanPool.MarkovProcess.MarkovProcess.Examples.HeatSemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal + /-! # The compactified heat process @@ -25,6 +28,8 @@ process started at a live point almost surely never reaches the added point (`ae_exitTime_eq_top_heatResolvent`). -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatSemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatSemigroup.lean index 60ed1320f6..bb8b5528a2 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatSemigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/HeatSemigroup.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin -import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent -import Mathlib.Probability.Distributions.Gaussian.Real +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +public import Mathlib.Probability.Distributions.Gaussian.Real + /-! # The one-dimensional heat semigroup and its continuous-path process @@ -34,6 +37,8 @@ Nothing in this file asserts independence of increments; that is proved in `MarkovProcess.Examples.BrownianMotion`. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Examples/Identity.lean b/LeanPool/MarkovProcess/MarkovProcess/Examples/Identity.lean index 4808206d7e..4278974ba5 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Examples/Identity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Examples/Identity.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Main +module + +public import LeanPool.MarkovProcess.MarkovProcess.Main + /-! # The identity semigroup and its continuous-path process @@ -19,6 +22,8 @@ nothing about any other semigroup, and it makes no claim about a semigroup that (see `MarkovProcess.Examples.Drift` for that). -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller.lean index 2560d4fff7..1a6d83f64c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller.lean @@ -4,22 +4,25 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion -import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeContinuityBase -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity -import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion +public import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeContinuityBase +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup + /-! # Feller diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Convergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Convergence.lean index edf7f69bde..8ae6fc4a23 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Convergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Convergence.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit + /-! # Convergence of the backward `C₀` recursion along a family of semigroups @@ -26,6 +29,8 @@ The factors and the observation times are fixed; nothing is asserted when they v filter as well, and no rate of convergence is claimed. -/ +@[expose] public section + open Filter MeasureTheory Topology open scoped NNReal ZeroAtInfty BigOperators diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean index fd9bb643e1..c7d135aeb4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Integral.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion -import Mathlib.Probability.Kernel.Composition.IntegralCompProd +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Recursion +public import Mathlib.Probability.Kernel.Composition.IntegralCompProd + /-! # Finite-time integral represented by the backward `C₀` recursion @@ -18,6 +21,8 @@ measures, which suffice for bounded integrability. This is an analytic identifi statement about path space is proved here, and the process itself is built in `Trajectory/`. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped NNReal ProbabilityTheory ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Recursion.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Recursion.lean index 80eea01169..1e2a8377a4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Recursion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/BackwardC0Recursion.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel + /-! # Backward `C₀` recursion for finite Feller transitions @@ -19,6 +22,8 @@ integral against a finite-time kernel is in `Feller/BackwardC0Integral.lean`; no path space is proved here. -/ +@[expose] public section + open Filter Topology open scoped NNReal ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean index 6d7149c119..59099e672f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity + /-! # Continuity of finite coordinate polynomials @@ -16,6 +19,8 @@ This file handles only explicit finite coordinate polynomials. The passage to a compactly supported continuous tests is in `Feller/FiniteTimeCompactTestContinuity.lean`. -/ +@[expose] public section + open Filter MeasureTheory ProbabilityTheory Topology open scoped NNReal ZeroAtInfty BigOperators diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinateProductContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinateProductContinuity.lean index ec7e3d5489..d223b21fba 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinateProductContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinateProductContinuity.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Integral +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction + /-! # Continuity of finite-time integrals of coordinate-product terms @@ -20,6 +23,8 @@ it never attempts to construct a constant-one element of `C₀`. This is finite analytic infrastructure; no statement about path space is proved here. -/ +@[expose] public section + open Filter MeasureTheory ProbabilityTheory Topology open scoped NNReal ZeroAtInfty BigOperators diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/DensePhysicalFiniteSetContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/DensePhysicalFiniteSetContinuity.lean index 7ab5339307..b1fedaf5db 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/DensePhysicalFiniteSetContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/DensePhysicalFiniteSetContinuity.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalCompactTestTransport +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure + /-! # Compact-test bounds for finite dense-time laws @@ -18,6 +21,8 @@ This is finite-dimensional analytic infrastructure; no statement about path spac here. The continuous-path process is built in `Trajectory/`. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped NNReal CompactlySupported ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteDenseApproximationContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteDenseApproximationContinuity.lean index 123ee789f4..f0c5e2867e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteDenseApproximationContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteDenseApproximationContinuity.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport + /-! # Feller continuity of finite dense approximations @@ -19,6 +22,8 @@ This is finite-dimensional infrastructure. No path-space Markov property is asse Markov and strong Markov statements are in `MarkovProcess/Main.lean`. -/ +@[expose] public section + open Filter MeasureTheory ProbabilityTheory Topology open scoped NNReal CompactlySupported diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetCompactTestContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetCompactTestContinuity.lean index 744eca1e37..4f9704c0f7 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetCompactTestContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetCompactTestContinuity.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeJointCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport + /-! # Continuity of finite-set compact-test integrals @@ -18,6 +21,8 @@ This is finite-dimensional analytic infrastructure; no statement about path spac here. The continuous-path process is built in `Trajectory/`. -/ +@[expose] public section + open MeasureTheory open scoped NNReal CompactlySupported diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetConvergence.lean index 67d378e6b2..9bb600d664 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteSetConvergence.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport -import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeConvergence +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence + /-! # Convergence of the finite-dimensional laws of Feller semigroups @@ -27,6 +30,8 @@ The set of observation times is fixed; nothing is asserted about joint convergen and the semigroups. -/ +@[expose] public section + open Filter MeasureTheory ProbabilityTheory Topology open scoped BoundedContinuousFunction CompactlySupported NNReal ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeCompactTestContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeCompactTestContinuity.lean index 3df21eb34f..25a0c1b13a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeCompactTestContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeCompactTestContinuity.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity -import Mathlib.MeasureTheory.Integral.CompactlySupported +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinatePolynomialContinuity +public import Mathlib.MeasureTheory.Integral.CompactlySupported + /-! # Continuity of finite-time integrals of compactly supported tests @@ -19,6 +22,8 @@ coordinate-polynomial approximants instead of adding that extra assumption. This finite-dimensional analytic infrastructure; no statement about path space is proved here. -/ +@[expose] public section + open Filter MeasureTheory ProbabilityTheory Topology open scoped NNReal ZeroAtInfty BigOperators CompactlySupported diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeContinuityBase.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeContinuityBase.lean index 6c6f8d53de..8c59317f03 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeContinuityBase.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeContinuityBase.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContinuity +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel + /-! # Singleton finite-time Feller continuity @@ -15,6 +18,8 @@ integrals as the observation time varies. This is the base case for a recursive continuity argument; no higher-dimensional continuity is asserted here. -/ +@[expose] public section + open Filter MeasureTheory Topology open scoped NNReal ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean index 81e354c126..d7e50bdabf 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction -import Mathlib.MeasureTheory.Integral.CompactlySupported +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +public import Mathlib.MeasureTheory.Integral.CompactlySupported + /-! # Convergence of finite-time laws along a family of Feller semigroups @@ -33,6 +36,8 @@ bounded and continuous, which needs the tightness of the limiting law and is the uniform in the starting point. -/ +@[expose] public section + open Filter MeasureTheory ProbabilityTheory Topology open scoped NNReal ZeroAtInfty BigOperators CompactlySupported diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean index 6bfb77c500..89f257285d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeCompactTestContinuity + /-! # Joint continuity of finite-time compact-test integrals @@ -16,6 +19,8 @@ This is finite-dimensional analytic infrastructure; no statement about path spac here. The continuous-path process is built in `Trajectory/`. -/ +@[expose] public section + open Filter MeasureTheory ProbabilityTheory Topology open scoped NNReal ZeroAtInfty BigOperators CompactlySupported diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeKernelContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeKernelContinuity.lean index 3b2928e00e..8bf0fccf3c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeKernelContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeKernelContinuity.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint + /-! # Continuity tools for finite-time Feller kernels @@ -18,6 +21,8 @@ The extension from product tests to arbitrary compactly supported tests on a fin not asserted here. -/ +@[expose] public section + open Filter MeasureTheory Topology open scoped NNReal ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/Resolvent.lean index 3121096370..aa9900b7ff 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/Resolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/Resolvent.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration + /-! # The resolvent of a Feller kernel semigroup @@ -38,6 +41,8 @@ The bridge to `SubMarkovKernelSemigroup.kernelResolvent` is pointwise on nonnega no kernel-valued resolvent is constructed. -/ +@[expose] public section + open Filter MeasureTheory ProbabilityTheory Set open scoped NNReal ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean index 89bb37eb4a..43432eff46 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/Semigroup.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic + /-! # Strongly continuous `C₀` semigroups from kernels @@ -15,6 +18,8 @@ packages those operators as a strongly continuous contraction semigroup. Spatial No stochastic process or Hunt process is constructed here. -/ +@[expose] public section + open Topology open scoped ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime.lean index cd4a5ad531..f4f3cc2540 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime.lean @@ -4,24 +4,27 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelCompactTestTransport +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily + /-! # FiniteTime diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductActiveReduction.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductActiveReduction.lean index 4b60b4e65e..e99f0ab8b0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductActiveReduction.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductActiveReduction.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization + /-! # Restricting normalized coordinate products to active coordinates @@ -19,6 +22,8 @@ product is one. No constant-one element of `C₀` is constructed. This is pure finite-product infrastructure: it involves no measure and no kernel. -/ +@[expose] public section + open scoped CompactlySupported ZeroAtInfty BigOperators namespace MarkovProcess.PiContinuousMap diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductNormalization.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductNormalization.lean index b4a63fcf0f..84f6b64f97 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductNormalization.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinateProductNormalization.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm + /-! # Normalizing finite coordinate products @@ -20,6 +23,8 @@ recursions that branch only over active coordinates. This is purely algebraic finite-product infrastructure: it involves no measure and no kernel. -/ +@[expose] public section + open scoped CompactlySupported ZeroAtInfty BigOperators namespace MarkovProcess.PiContinuousMap diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteSetKernelShift.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteSetKernelShift.lean index fe69dbf3e3..4eeff33a1c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteSetKernelShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteSetKernelShift.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift + /-! # Translation of finite dense-time kernels @@ -13,6 +16,8 @@ This file transports the finite-set kernel translation law from physical nonnega to finite sets of dense times, using the canonical coordinate reindexings. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteShift.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteShift.lean index 4d36bcc6df..0cc9f6bd26 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/DenseTimeFiniteShift.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Shift + /-! # Finite-coordinate shifts on dense-time paths @@ -13,6 +16,8 @@ provides the resulting coordinate equivalence and relates restriction after shif path to restriction on the translated finite set. It makes no probability-law or Markov claim. -/ +@[expose] public section + noncomputable section PortComputability namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean index 82abd128a0..359b3d5818 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCompactSupportApproximation.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass + /-! # Compactly supported approximation on a finite product @@ -13,6 +16,8 @@ whole product. The key device is a product of one-coordinate compactly supporte coordinate cutoff is one on the corresponding projection of the target's compact support. -/ +@[expose] public section + open Topology open scoped CompactlySupported ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean index 207d186c6c..081e44e46e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductCoordinateNormalForm.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCompactSupportApproximation + /-! # Explicit coordinate-product normal forms @@ -15,6 +18,8 @@ the constant function `1`; in particular the representation treats constants and coordinate type without exceptional cases. -/ +@[expose] public section + open scoped CompactlySupported ZeroAtInfty namespace MarkovProcess.PiContinuousMap diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductStoneWeierstrass.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductStoneWeierstrass.lean index 4739a46151..7303bc333f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductStoneWeierstrass.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteProductStoneWeierstrass.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Topology.ContinuousMap.StoneWeierstrass -import Mathlib.Topology.ContinuousMap.CompactlySupported -import Mathlib.Topology.Separation.CompletelyRegular -import Mathlib.Topology.UrysohnsLemma +module + +public import Mathlib.Topology.ContinuousMap.StoneWeierstrass +public import Mathlib.Topology.ContinuousMap.CompactlySupported +public import Mathlib.Topology.Separation.CompletelyRegular +public import Mathlib.Topology.UrysohnsLemma + /-! # Stone--Weierstrass on products @@ -25,6 +28,8 @@ whole product. Accordingly, `coordinateC0Subalgebra` is a subalgebra of continu `C₀` designation records its one-coordinate generators, not its ambient carrier. -/ +@[expose] public section + open Topology open scoped ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean index a8de81bb3f..5d0db0c033 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily -import Mathlib.MeasureTheory.Integral.CompactlySupported +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +public import Mathlib.MeasureTheory.Integral.CompactlySupported + /-! # Compact-test transport for finite-set kernels @@ -20,6 +23,8 @@ product. These declarations are finite-dimensional infrastructure; no statement is proved here. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped NNReal CompactlySupported diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelShift.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelShift.lean index 9101b4e66e..b57636ddc4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelShift.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily + /-! # Translation of finite-set kernels @@ -16,6 +19,8 @@ for conservative transition-kernel semigroups. It is finite-dimensional kernel it does not assert a path-space Markov property. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/Kernel.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/Kernel.lean index 8090e9566a..78ccd6b13c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/Kernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/Kernel.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup -import Mathlib.Data.Fin.Tuple.Basic -import Mathlib.Probability.Kernel.Composition.CompProd +module + +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +public import Mathlib.Data.Fin.Tuple.Basic +public import Mathlib.Probability.Kernel.Composition.CompProd + /-! # Finite-time kernels on strictly ordered time families @@ -20,6 +23,8 @@ This file constructs finite-dimensional kernels only. It makes no path-space, p conservativity, or stochastic-process existence claim beyond the explicitly stated results. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean index 4334cf07ed..56ffdc0d37 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction -import Mathlib.Probability.Kernel.Composition.Lemmas +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +public import Mathlib.Probability.Kernel.Composition.Lemmas + /-! # Concatenating finite-time kernels at an ordered cut @@ -15,6 +18,8 @@ from the terminal coordinate of the past. This is finite-dimensional kernel inf does not assert a path-space or conditional Markov theorem. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelDeletion.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelDeletion.lean index d2ef4c0a9a..db826716f2 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelDeletion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelDeletion.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift -import Mathlib.Probability.Kernel.Composition.KernelLemmas +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift +public import Mathlib.Probability.Kernel.Composition.KernelLemmas + /-! # Deleting one coordinate from a finite-time kernel @@ -14,6 +17,8 @@ gives the law on the remaining ordered times. This is finite-dimensional kernel it does not construct a path-space law or a stochastic process. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelEquivariance.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelEquivariance.lean index d75a70505c..ff2eba29ac 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelEquivariance.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelEquivariance.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments -import Mathlib.MeasureTheory.Constructions.BorelSpace.Basic -import Mathlib.MeasureTheory.Function.SpecialFunctions.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments +public import Mathlib.MeasureTheory.Constructions.BorelSpace.Basic +public import Mathlib.MeasureTheory.Function.SpecialFunctions.Basic + /-! # Rescaled conjugation of finite-time kernels @@ -29,6 +32,8 @@ Kolmogorov moment criterion also transfers, with the constant multiplied by `c ^ (`IsRescaledConjugate.hasKolmogorovMoments`). -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped NNReal ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelMixedPullback.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelMixedPullback.lean index d9d9df3f20..53d5a7ce35 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelMixedPullback.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelMixedPullback.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelConcatenation + /-! # Pulling a finite-time concatenation back to mixed labels @@ -17,6 +20,8 @@ The result is pure finite-dimensional Chapman--Kolmogorov algebra. In particula continuity, density, path-space, or Feller hypothesis. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelRestriction.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelRestriction.lean index fe91b4d115..953d76f8ae 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelRestriction.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelRestriction.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion +module + +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelDeletion + /-! # Restricting finite-time kernels @@ -14,6 +17,8 @@ gives the finite-time kernel at the selected times. This is finite-dimensional k infrastructure and does not construct a path-space law or a stochastic process. -/ +@[expose] public section + open ProbabilityTheory namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelShift.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelShift.lean index 59bb6d6c20..977c69e40c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelShift.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel -import Mathlib.Probability.Kernel.Composition.KernelLemmas +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +public import Mathlib.Probability.Kernel.Composition.KernelLemmas + /-! # Translation of finite-time kernels @@ -13,6 +16,8 @@ This file proves the finite-dimensional translation identity for a conservative semigroup. It is ordinary kernel infrastructure and makes no path-space or process-existence claim. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/MeasureFiniteRestrictionIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/MeasureFiniteRestrictionIdentification.lean index 48b6e2eb2f..0ba00f92bf 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/MeasureFiniteRestrictionIdentification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/MeasureFiniteRestrictionIdentification.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.MeasureTheory.Constructions.Projective +module + +public import Mathlib.MeasureTheory.Constructions.Projective + /-! # Identifying measures from finite-coordinate restrictions @@ -15,6 +18,8 @@ unequal mass cannot satisfy the hypothesis. This is generic measure-theoretic infrastructure and requires no topology. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/ProjectiveFamily.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/ProjectiveFamily.lean index 44b7ddf543..ff5ef1f84e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/ProjectiveFamily.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/ProjectiveFamily.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction -import Mathlib.Data.Finset.Sort -import Mathlib.MeasureTheory.Constructions.Projective +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction +public import Mathlib.Data.Finset.Sort +public import Mathlib.MeasureTheory.Constructions.Projective + /-! # Finite-set finite-time laws @@ -14,6 +17,8 @@ This file reindexes the ordered finite-time kernels by finite sets of times and Mathlib-native projectivity. It does not assert or construct a projective-limit measure. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel.lean index fd4de87b6b..d887dd0fd9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel.lean @@ -4,36 +4,39 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic -import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 -import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint -import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex -import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent -import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativityAE -import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp -import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpConsistency -import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite -import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop -import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OperatorSemigroup -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness -import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0 +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativityAE +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KolmogorovMoments +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpConsistency +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OperatorSemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence + /-! # Kernel diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Basic.lean index 36e9a6312f..dc7f7292fd 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Basic.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Basic.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Probability.Kernel.Composition.Comp +module + +public import Mathlib.Probability.Kernel.Composition.Comp + /-! # Sub-Markov kernels @@ -13,6 +16,8 @@ not define transition families or connect kernels to operator semigroups or stochastic processes. -/ +@[expose] public section + open MeasureTheory open scoped ENNReal ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0.lean index 08310c5dfc..6e84f42177 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction -import Mathlib.Probability.Kernel.Composition.IntegralCompProd -import Mathlib.Topology.ContinuousMap.ZeroAtInfty -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +module + +public import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction +public import Mathlib.Probability.Kernel.Composition.IntegralCompProd +public import Mathlib.Topology.ContinuousMap.ZeroAtInfty +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup + /-! # Kernel operators on continuous functions vanishing at infinity @@ -17,6 +20,8 @@ raw integral as a contractive continuous linear map on `C₀(α, ℝ)`. It make continuity in time or the existence of an associated stochastic process. -/ +@[expose] public section + open Filter MeasureTheory ProbabilityTheory Topology open scoped ENNReal ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0SemigroupJoint.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0SemigroupJoint.lean index daa29dc32f..ba547a8f53 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0SemigroupJoint.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/C0SemigroupJoint.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic -import Mathlib.MeasureTheory.Constructions.BorelSpace.Basic -import Mathlib.Topology.ContinuousMap.ZeroAtInfty +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +public import Mathlib.MeasureTheory.Constructions.BorelSpace.Basic +public import Mathlib.Topology.ContinuousMap.ZeroAtInfty + /-! # Joint regularity of strongly continuous semigroups on `C₀` @@ -19,6 +22,8 @@ This is a generic functional-analytic API. It makes no representation claim about the semigroup. -/ +@[expose] public section + open scoped ZeroAtInfty namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/CompProdReindex.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/CompProdReindex.lean index 15d4d82cc4..0b66eb7aaa 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/CompProdReindex.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/CompProdReindex.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Probability.Kernel.Composition.CompProd +module + +public import Mathlib.Probability.Kernel.Composition.CompProd + /-! # Mapping product kernels by coordinate maps @@ -13,6 +16,8 @@ product. They are measure-kernel infrastructure and make no assertion about a s process. -/ +@[expose] public section + open MeasureTheory open scoped ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativeResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativeResolvent.lean index a80d0aef10..7f38554ea0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativeResolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativeResolvent.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential + /-! # Conservativity from the resolvent of the constant observable @@ -27,6 +30,8 @@ equivalence and not merely a sufficient condition. No topology on the state space is used. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativityAE.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativityAE.lean index 5fd34f4c3e..763b5b320a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativityAE.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ConservativityAE.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.MeasureTheory.Measure.OpenPos -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +module + +public import Mathlib.MeasureTheory.Measure.OpenPos +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator + /-! # Conservativity from preservation of constants @@ -16,6 +19,8 @@ transition mass and positivity of the reference measure on nonempty open sets upgrade it to pointwise conservativity. -/ +@[expose] public section + open MeasureTheory open ProbabilityTheory open scoped ENNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/FiniteRestrictionIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/FiniteRestrictionIdentification.lean index 7ad8c1d580..4402f31420 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/FiniteRestrictionIdentification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/FiniteRestrictionIdentification.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.MeasureTheory.Constructions.Projective -import Mathlib.Probability.Kernel.Composition.MapComap +module + +public import Mathlib.MeasureTheory.Constructions.Projective +public import Mathlib.Probability.Kernel.Composition.MapComap + /-! # Identifying path kernels from finite-coordinate restrictions @@ -14,6 +17,8 @@ pushforwards. The proof applies uniqueness of finite projective limits pointwis parameter. No topology, time order, path regularity, or Markov property is used. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Integral.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Integral.lean index 6ae3cf3f63..1918bb5c70 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Integral.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Integral.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic -import Mathlib.Probability.Kernel.Composition.MeasureComp -import Mathlib.Probability.Kernel.MeasurableIntegral +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +public import Mathlib.Probability.Kernel.Composition.MeasureComp +public import Mathlib.Probability.Kernel.MeasurableIntegral + /-! # Integration against a kernel @@ -15,6 +18,8 @@ kernel. Subinvariance of a measure makes this operator independent, almost everywhere, of the chosen representative of its input. -/ +@[expose] public section + open MeasureTheory open ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/KernelSemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/KernelSemigroup.lean index f28925d819..ed2418e487 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/KernelSemigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/KernelSemigroup.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic + /-! # Sub-Markov transition-kernel semigroups @@ -16,6 +19,8 @@ Conservativity is deliberately a separate predicate. A killed transition family has mass at most one, while a conservative family has mass exactly one. -/ +@[expose] public section + noncomputable section PortComputability open Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/KolmogorovMoments.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/KolmogorovMoments.lean index 32d160861e..dda79b50f1 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/KolmogorovMoments.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/KolmogorovMoments.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup -import Mathlib.Analysis.SpecialFunctions.Pow.NNReal +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +public import Mathlib.Analysis.SpecialFunctions.Pow.NNReal + /-! # Intrinsic Kolmogorov moment bounds for a transition semigroup @@ -19,6 +22,8 @@ continuity, or stochastic-process claim; the transport of this bound to the cano dense-time coordinate process is proved elsewhere. -/ +@[expose] public section + open MeasureTheory open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean index 1382231bf0..69ccfa09e5 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite -import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop -import Mathlib.MeasureTheory.Function.LpSpace.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpFinite +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.LpTop +public import Mathlib.MeasureTheory.Function.LpSpace.Basic + /-! # Kernel integral operators on real `Lᵖ` @@ -14,6 +17,8 @@ This file packages the raw kernel integral as continuous linear contractions on finite-exponent and infinite-exponent real `Lᵖ` spaces. -/ +@[expose] public section + open MeasureTheory open ProbabilityTheory open scoped ENNReal @@ -22,7 +27,7 @@ namespace MarkovProcess variable {α : Type*} [MeasurableSpace α] -private instance fact_one_le_coe_nnreal (p : NNReal) [Fact (1 ≤ p)] : +instance fact_one_le_coe_nnreal (p : NNReal) [Fact (1 ≤ p)] : Fact (1 ≤ (p : ℝ≥0∞)) := ⟨by exact_mod_cast Fact.out⟩ /- Head-class caches for the `Lᵖ` carrier. Without them every normed-group diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpConsistency.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpConsistency.lean index 0bd80e010f..bb57e22c59 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpConsistency.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpConsistency.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp + /-! # Cross-exponent consistency of kernel integral operators @@ -14,6 +17,8 @@ whenever their inputs do, even when the inputs and outputs inhabit different `Lp` types. -/ +@[expose] public section + open MeasureTheory open ProbabilityTheory open scoped ENNReal ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean index fac4791b41..b59f93035f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpFinite.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral -import Mathlib.MeasureTheory.Function.L1Space.Integrable -import Mathlib.MeasureTheory.Function.LpSeminorm.CompareExp -import Mathlib.Probability.Kernel.Composition.IntegralCompProd +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +public import Mathlib.MeasureTheory.Function.L1Space.Integrable +public import Mathlib.MeasureTheory.Function.LpSeminorm.CompareExp +public import Mathlib.Probability.Kernel.Composition.IntegralCompProd + /-! # Finite-exponent contraction for sub-Markov kernels @@ -15,6 +18,8 @@ This file proves the scalar subprobability estimate behind contraction of a sub-Markov kernel on finite `Lᵖ` spaces, and its fibrewise integrated form. -/ +@[expose] public section + open MeasureTheory open ProbabilityTheory open scoped ENNReal ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpTop.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpTop.lean index 3fd89c8768..8b22b7b72d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpTop.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/LpTop.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral -import Mathlib.MeasureTheory.Function.LpSeminorm.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Integral +public import Mathlib.MeasureTheory.Function.LpSeminorm.Basic + /-! # The kernel integral on `L^∞` @@ -15,6 +18,8 @@ itself is packaged as a continuous linear map by `kernelLpTop` in `Kernel/Lp.lean`. -/ +@[expose] public section + open MeasureTheory open ProbabilityTheory open scoped ENNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/MeasurableRadonFamily.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/MeasurableRadonFamily.lean index cc3012908e..67ed11c7ee 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/MeasurableRadonFamily.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/MeasurableRadonFamily.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.MeasureTheory.Integral.RieszMarkovKakutani.Real -import Mathlib.MeasureTheory.Measure.GiryMonad +module + +public import Mathlib.MeasureTheory.Integral.RieszMarkovKakutani.Real +public import Mathlib.MeasureTheory.Measure.GiryMonad + /-! # Measurability of finite Radon measure families @@ -19,6 +22,8 @@ supremum of measurable test integrals, then applies Mathlib's Giry The compact exhaustion and cutoff choices are private implementation details. -/ +@[expose] public section + open scoped CompactlySupported ENNReal NNReal Topology open Set MeasureTheory TopologicalSpace @@ -144,9 +149,9 @@ theorem measurable_measure_of_measurable_integral_compactlySupported (isPiSystem_generatePiSystem _) ?_ ?_ · intro U hU have hU_open : IsOpen U := by - induction hU with - | base h => exact isOpen_of_mem_countableBasis h - | inter _ _ _ hs ht => exact hs.inter ht + induction hU using generatePiSystem_induction with + | base _ h => exact isOpen_of_mem_countableBasis h + | inter _ _ _ _ _ hs ht => exact hs.inter ht have heval : (fun q ↦ μ q U) = fun q ↦ ⨆ n, ENNReal.ofReal (∫ x, MeasurableRadonFamily.openCutoff U hU_open n x ∂μ q) := by funext q diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointConservative.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointConservative.lean index d46948ed66..354b7d64d8 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointConservative.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointConservative.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.ConservativeResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal + /-! # A conservative resolvent keeps the compactified process in the live space @@ -23,6 +26,8 @@ The regularity data of the compactification are an explicit hypothesis, as every continuous-path process is formed. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean index 7e15dc8977..37a50ac447 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Topology.Compactification.OnePoint.Basic -import Mathlib.Topology.Compactness.SigmaCompact -import Mathlib.Topology.Metrizable.Urysohn -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration +module + +public import Mathlib.Topology.Compactification.OnePoint.Basic +public import Mathlib.Topology.Compactness.SigmaCompact +public import Mathlib.Topology.Metrizable.Urysohn +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration + /-! # One-point extension of a positive `C₀` resolvent @@ -27,6 +30,8 @@ This construction does not assert a Kolmogorov moment bound or construct a conti process. -/ +@[expose] public section + noncomputable section PortComputability open Filter Set Topology TopologicalSpace diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKilled.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKilled.lean index f39b85092e..ff5c9b2ac0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKilled.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKilled.lean @@ -3,13 +3,16 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov -import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace -import Mathlib.Topology.Homeomorph.Lemmas -import Mathlib.MeasureTheory.Measure.RegularityCompacts +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKolmogorov +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace +public import Mathlib.Topology.Homeomorph.Lemmas +public import Mathlib.MeasureTheory.Measure.RegularityCompacts + /-! # Killing the one-point process at infinity @@ -18,6 +21,8 @@ This file identifies the continuous process of the one-point extension of a posi `C₀`-contractive resolvent with the process killed on leaving its live part. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean index e529b85ec2..6bb28852c7 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Analysis.SpecialFunctions.Pow.Integral -import Mathlib.MeasureTheory.Integral.Lebesgue.Markov -import Mathlib.Topology.MetricSpace.Lipschitz -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension -import LeanPool.MarkovProcess.MarkovProcess.Main +module + +public import Mathlib.Analysis.SpecialFunctions.Pow.Integral +public import Mathlib.MeasureTheory.Integral.Lebesgue.Markov +public import Mathlib.Topology.MetricSpace.Lipschitz +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointExtension +public import LeanPool.MarkovProcess.MarkovProcess.Main + /-! # Kolmogorov bounds on a one-point compactification @@ -24,6 +27,8 @@ The tail bounds and their scalar integral budget remain hypotheses for the consu estimate for a particular semigroup is asserted here. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Operator.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Operator.lean index 7688536948..ef7886fa98 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Operator.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Operator.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Lp + /-! # Operators associated with a sub-Markov kernel semigroup @@ -14,6 +17,8 @@ canonical contractive operator families on real `Lᵖ`. It deliberately makes no claim here about the operator semigroup laws or strong continuity. -/ +@[expose] public section + open MeasureTheory open ProbabilityTheory open scoped ENNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean index d55a3b404f..2e74b95294 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator + /-! # Semigroup laws for the canonical kernel operators @@ -12,6 +15,8 @@ This file proves only the algebraic zero- and add-time laws for the canonical real `Lᵖ` operator families. It makes no strong-continuity claim. -/ +@[expose] public section + open MeasureTheory open ProbabilityTheory open scoped ENNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorKernel.lean index a8de2a8be3..de051390df 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorKernel.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic -import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass -import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.MeasurableRadonFamily +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMass +public import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction + /-! # Kernels represented by positive operators on `C₀` @@ -15,6 +18,8 @@ A positive contraction on real continuous functions vanishing at infinity determ sub-Markov kernel. Its values are the pointwise Riesz measures of the evaluation functionals. -/ +@[expose] public section + open CompactlySupported Filter MeasureTheory ProbabilityTheory Set open scoped ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMass.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMass.lean index 167a55b843..b2843774c9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMass.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMass.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure + /-! # Total mass of pointwise Riesz measures @@ -16,6 +19,8 @@ This file proves only a pointwise total-mass bound and finiteness. It does not or prove any regularity in the evaluation point. -/ +@[expose] public section + open CompactlySupported MeasureTheory open scoped ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMeasure.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMeasure.lean index d7b1ebc107..3e96f07c83 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMeasure.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0OperatorMeasure.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.MeasureTheory.Integral.RieszMarkovKakutani.Real -import Mathlib.Topology.ContinuousMap.ZeroAtInfty +module + +public import Mathlib.MeasureTheory.Integral.RieszMarkovKakutani.Real +public import Mathlib.Topology.ContinuousMap.ZeroAtInfty + /-! # Pointwise Riesz measures of positive operators on `C₀` @@ -19,6 +22,8 @@ measurably on the evaluation point, have bounded total mass, form a kernel, or s semigroup or stochastic-process law. -/ +@[expose] public section + open CompactlySupported MeasureTheory open scoped ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0Resolvent.lean index 0df2e29777..5dc1317ca6 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0Resolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0Resolvent.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupFeller + /-! # Positive `C₀` resolvents and their Feller kernels @@ -17,6 +20,8 @@ The package in this file starts from the resolvent identity, the Hille--Yosida b and positivity of the actual shifted resolvents. It assumes neither a semigroup nor a kernel. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupFeller.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupFeller.lean index ba2b80747c..46b4112e0c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupFeller.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupFeller.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0SemigroupKernel + /-! # Feller property of kernels represented by positive `C₀` semigroups @@ -14,6 +17,8 @@ recovers the original operators on `C₀` and therefore satisfies the existing F This file makes no conservativity, stochastic-process, or Hunt-process claim. -/ +@[expose] public section + open Filter MeasureTheory ProbabilityTheory Topology open scoped ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupKernel.lean index 5cb23cf97a..0bc436ccf0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/PositiveC0SemigroupKernel.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup -import Mathlib.Probability.Kernel.Composition.IntegralCompProd -import Mathlib.Topology.Metrizable.Urysohn +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorKernel +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +public import Mathlib.Probability.Kernel.Composition.IntegralCompProd +public import Mathlib.Topology.Metrizable.Urysohn + /-! # Kernel semigroups represented by positive contraction semigroups on `C₀` @@ -16,6 +19,8 @@ A strongly continuous semigroup of positive contractions on real continuous func at infinity determines a jointly measurable sub-Markov kernel semigroup. -/ +@[expose] public section + open CompactlySupported MeasureTheory ProbabilityTheory open scoped ENNReal ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Resolvent.lean index 2e548324ba..bab022e571 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Resolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Resolvent.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Analysis.SpecialFunctions.ImproperIntegrals -import Mathlib.MeasureTheory.Integral.ExpDecay -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +module + +public import Mathlib.Analysis.SpecialFunctions.ImproperIntegrals +public import Mathlib.MeasureTheory.Integral.ExpDecay +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator + /-! # Resolvents of kernel semigroups @@ -19,6 +22,8 @@ Main definitions: `SubMarkovKernelSemigroup.kernelResolvent` and No conservativity, topology, or finiteness of the resolvent is asserted. -/ +@[expose] public section + open Filter MeasureTheory ProbabilityTheory Set open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ResolventUniqueness.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ResolventUniqueness.lean index ce7856861c..66447f7936 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/ResolventUniqueness.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/ResolventUniqueness.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator + /-! # Uniqueness for resolvents on bounded measurable functions @@ -19,6 +22,8 @@ Main results: `perturbed_unique`, `resolventFamily_eq_of_eventually`, and The operators are plain maps on functions; no Banach-space carrier or continuity is asserted. -/ +@[expose] public section + noncomputable section PortComputability open Filter diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/WeakConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/WeakConvergence.lean index 7ca52249bb..7f5028a0a2 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/WeakConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/WeakConvergence.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.MeasureTheory.Integral.Bochner.Set -import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction -import Mathlib.MeasureTheory.Integral.CompactlySupported -import Mathlib.MeasureTheory.Measure.Tight -import Mathlib.Topology.UrysohnsLemma +module + +public import Mathlib.MeasureTheory.Integral.Bochner.Set +public import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction +public import Mathlib.MeasureTheory.Integral.CompactlySupported +public import Mathlib.MeasureTheory.Measure.Tight +public import Mathlib.Topology.UrysohnsLemma + /-! # Vague convergence to a probability measure is weak convergence @@ -26,6 +29,8 @@ Nothing is asserted for families that are not probability measures: for sub-prob the conclusion is false, since mass may escape to infinity. -/ +@[expose] public section + open Filter MeasureTheory Topology open scoped BoundedContinuousFunction CompactlySupported diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed.lean index e9e08375ff..a8adb2cf7e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed.lean @@ -4,24 +4,27 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.ExitTimeIdentification -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingC0 -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer -import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel -import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit -import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals -import LeanPool.MarkovProcess.MarkovProcess.Killed.Minimal -import LeanPool.MarkovProcess.MarkovProcess.Killed.Nested -import LeanPool.MarkovProcess.MarkovProcess.Killed.Process -import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.ExitTimeIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingC0 +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel +public import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Minimal +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Nested +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Process +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup + /-! # Killed diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/ExitTimeIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/ExitTimeIdentification.lean index 0c419e8e93..d908d83feb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/ExitTimeIdentification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/ExitTimeIdentification.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent + /-! # Identifying the expected exit time with a Dirichlet resolvent @@ -32,6 +35,8 @@ The consumer-supplied resolvent and its limit are `ℝ≥0∞`-valued, so no int hypothesis appears; a consumer working with real-valued solutions bridges with `ENNReal.ofReal`. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingC0.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingC0.lean index 5124fc37ca..47a2d40c88 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingC0.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingC0.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointConservative +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingRealResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer + /-! # The supremum resolvent as a positive `C₀`-contractive resolvent @@ -31,6 +34,8 @@ the compactified process started at any point almost surely never reaches the ad space is produced from that statement. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLinearity.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLinearity.lean index c68507850a..556bd457c2 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLinearity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLinearity.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingMinimal + /-! # Linearity of the transported local resolvents and of their supremum @@ -26,6 +29,8 @@ suprema once the family is monotone in the index (`minimalResolvent_comm`). Nothing here uses the part-process identity; monotonicity in the index is a bare hypothesis. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLocal.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLocal.lean index 8d4e393e1f..741393140f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLocal.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingLocal.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.OnePointKilled +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingTransfer + /-! # Comparing two local resolvents through the part-process identity @@ -27,6 +30,8 @@ The regularity data are an explicit hypothesis: positivity, contractivity and th identity do not by themselves give the compactified semigroup a continuous-path process. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMeasure.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMeasure.lean index f77a75baaa..2b2de869bb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMeasure.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMeasure.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity + /-! # The potential measure of the supremum resolvent @@ -20,6 +23,8 @@ to all nonnegative measurable observables through the two potential measures. Monotonicity of the transported resolvents in the index is a bare hypothesis throughout. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMinimal.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMinimal.lean index 69058b709d..5d1bf12af8 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMinimal.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingMinimal.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLocal +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingResolventEquation + /-! # The supremum resolvent (the minimal process of Blumenthal--Getoor, in name only) @@ -38,6 +41,8 @@ No transition semigroup, no process on the ambient space, and no conservativity here. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingPotential.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingPotential.lean index 62e99150c9..ccefb9c40e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingPotential.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingPotential.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion + /-! # Potential measures @@ -33,6 +36,8 @@ homogeneous on measurable observables (`SubMarkovKernelSemigroup.kernelResolvent No resolvent identity and no topology on the state space are used here. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingRealResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingRealResolvent.lean index 1912bbe6bb..23735008fe 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingRealResolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingRealResolvent.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingLinearity + /-! # The supremum resolvent on bounded real observables @@ -25,6 +28,8 @@ Additivity, and with it the resolvent equation, is available exactly when the tr resolvents are monotone in the index; that monotonicity is a bare hypothesis here. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingResolventEquation.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingResolventEquation.lean index c2086f6236..499e29ddf5 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingResolventEquation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingResolventEquation.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential + /-! # The resolvent equation for a kernel resolvent @@ -33,6 +36,8 @@ Main results: `expWeight_convolution`, `SubMarkovKernelSemigroup.kernelResolvent_resolventEquation`. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingTransfer.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingTransfer.lean index 26cd7f02e3..0a6540554b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingTransfer.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/GluingTransfer.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.MeasureTheory.Integral.RieszMarkovKakutani.NNReal -import Mathlib.Topology.ContinuousMap.CompactlySupported -import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential +module + +public import Mathlib.MeasureTheory.Integral.RieszMarkovKakutani.NNReal +public import Mathlib.Topology.ContinuousMap.CompactlySupported +public import LeanPool.MarkovProcess.MarkovProcess.Killed.GluingPotential + /-! # From vanishing observables to measurable ones @@ -27,6 +30,8 @@ No topology on the target space is used, and no relation between the two measure tested identity is assumed. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Kernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Kernel.lean index 807cd4e6e4..5187520d2d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Kernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Kernel.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Main -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift +module + +public import LeanPool.MarkovProcess.MarkovProcess.Main +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift + /-! # The process killed at the exit time of an open set: transition kernels @@ -31,6 +34,8 @@ the identity only on `U` (it is `0` off `U`); the semigroup structure on the car separate packaging. No Feller property of the killed family is claimed. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/KillAtExit.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/KillAtExit.lean index b7bb690809..d939ed6f99 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/KillAtExit.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/KillAtExit.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift + /-! # Killing a continuous path at the exit time of a set @@ -25,6 +28,8 @@ lifetime-path measurable structure generated by the lifetime and the coordinates This file constructs no probability law. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean index 8f23137678..d7b42bb97a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Marginals.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance -import LeanPool.MarkovProcess.MarkovProcess.Killed.Process +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Process + /-! # Finite-dimensional distributions of the killed process @@ -35,6 +38,8 @@ No Feller property, strong continuity, or regularity of the killed semigroup is statement here covers a random time. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Minimal.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Minimal.lean index 62440afb71..52c831f69d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Minimal.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Minimal.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel -import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel +public import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin + /-! # The semigroup as the limit of its killed parts @@ -25,6 +28,8 @@ The killed kernels are monotone in the open set (`killedKernel_mono`); no other used. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory Filter open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean index cacb9c8057..95acc44158 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Nested.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping -import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Marginals +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping +public import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion + /-! # Nested domains: killing at the exit of a smaller set @@ -35,6 +38,8 @@ the statements here compare them through the inclusion of `U` in `V` rather than two killed processes as laws on a common carrier. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean index ef7b2182de..9e1639d57e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Process.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit -import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.KillAtExit +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup + /-! # The process killed at the exit of an open set, as a law on lifetime paths @@ -26,6 +29,8 @@ No finite-dimensional distribution of the killed process is identified here, and regularity property of the killed family is claimed. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Resolvent.lean index 21e8b296d7..e38baf10c8 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Resolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Resolvent.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel + /-! # The killed resolvent @@ -29,6 +32,8 @@ antitone in the shift (`IsConservative.killedResolvent_antitone`), because a lar discounts the future more. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory Filter open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Killed/Semigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Killed/Semigroup.lean index 711fd1397d..0803cf350b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Killed/Semigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Killed/Semigroup.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel + /-! # The killed semigroup on the domain @@ -25,6 +28,8 @@ No Feller property, strong continuity, or regularity of the killed semigroup is process is not identified with the cemetery-extended process on lifetime paths. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime.lean index 67a2bb5091..3d0c25288b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime.lean @@ -4,16 +4,19 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.CountablySeparated -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Killing -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Nonexplosion -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.NonexplosiveTransport -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift +module + +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.CountablySeparated +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTimeStopping +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Killing +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Nonexplosion +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.NonexplosiveTransport +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift + /-! # Lifetime diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Basic.lean index 5e727e6483..7c827847ac 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Basic.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Basic.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension -import LeanPool.MarkovProcess.MarkovProcess.Path.Basic -import Mathlib.MeasureTheory.Constructions.Polish.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeteryExtension +public import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +public import Mathlib.MeasureTheory.Constructions.Polish.Basic + /-! # Paths with a lifetime @@ -17,6 +20,8 @@ The canonical measurable structure is generated by the lifetime and all fixed-ti No countable-generation or standard-Borel claim for the lifetime-path carrier is made here. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/CountablySeparated.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/CountablySeparated.lean index d2c3c82b7f..0b96ea279c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/CountablySeparated.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/CountablySeparated.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic + /-! # Countable separation of lifetime paths @@ -13,6 +16,8 @@ Lifetime and the coordinates at the fixed countable dense time set separate cont paths. Their measurable coding therefore gives a countable separating family. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTime.lean index 9046223b4a..6122d52c83 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTime.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTime.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic + /-! # Exit times of lifetime paths @@ -16,6 +19,8 @@ Only deterministic order properties are proved here. No measurability or stoppin made. -/ +@[expose] public section + noncomputable section PortComputability open Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTimeStopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTimeStopping.lean index 7d3bfe978a..c16313839b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTimeStopping.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/ExitTimeStopping.lean @@ -3,12 +3,17 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Filtration + /-! # Exit times as stopping times -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean index 433cd017a8..842c2bf15c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift -import Mathlib.Probability.Process.Stopping +module + +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Shift +public import Mathlib.Probability.Process.Stopping + /-! # Canonical filtration of lifetime paths @@ -14,6 +17,8 @@ The lifetime is a stopping time because death by time `t` is exactly the event t coordinate is the cemetery state. -/ +@[expose] public section + open MeasureTheory open scoped ENNReal @@ -64,7 +69,7 @@ theorem measurable_shift_canonicalFiltration (S t : NNReal) : exact coordinate_shift S u omega rw [hfun] exact le_iSup_of_le - (⟨S + u, by simpa only [add_comm] using! add_le_add_left u.property S⟩ : + (⟨S + u, by exact add_le_add_left u.property S⟩ : Set.Iic (S + t)) le_rfl /-- The lifetime is a stopping time for the raw canonical filtration. -/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Killing.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Killing.lean index fc7e037c3b..9b4e939c9c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Killing.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Killing.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic + /-! # Deterministic killing of lifetime paths @@ -13,6 +16,8 @@ killing time itself is the cemetery state, so this operation is distinct from en stopping. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Law.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Law.lean index f2e55cd4c3..7d2f83c4b6 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Law.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Law.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic -import Mathlib.Probability.Kernel.Composition.MapComap +module + +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +public import Mathlib.Probability.Kernel.Composition.MapComap + /-! # Continuous laws as nonexplosive lifetime-path laws @@ -14,6 +17,8 @@ embedding. It records the resulting nonexplosion and coordinate identities witho that any particular dense-time or PDE law has continuous paths. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Nonexplosion.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Nonexplosion.lean index 91417484fd..27dea1408c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Nonexplosion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Nonexplosion.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law +module + +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law + /-! # Detecting nonexplosion from countably many coordinates @@ -14,6 +17,8 @@ almost-sure coordinate statements. This is the measure-theoretic reduction later conservativity of transition laws into nonexplosion. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/NonexplosiveTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/NonexplosiveTransport.lean index a9c94a0450..7eba5f904a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/NonexplosiveTransport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/NonexplosiveTransport.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law +module + +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Law + /-! # Transporting nonexplosive lifetime laws to continuous paths @@ -13,6 +16,8 @@ lifetime paths whose lifetime is almost surely infinite therefore gives a canoni ordinary continuous paths, independent of the off-support default. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean index 2e279f21ac..43f1956722 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Shift.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.Basic + /-! # Deterministic time shifts of lifetime paths @@ -12,6 +15,8 @@ This file shifts a lifetime path forward by a fixed finite time. A shift beyond lifetime produces a path with zero lifetime, hence with cemetery state at every coordinate. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Main.lean b/LeanPool/MarkovProcess/MarkovProcess/Main.lean index 0b5aba0c7b..bcfb8e8627 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Main.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Main.lean @@ -3,18 +3,21 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification -import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification -import LeanPool.MarkovProcess.MarkovProcess.Path.Polish -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Path.Polish +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TwoPointMarginals + /-! # The continuous-path Markov process of a Feller semigroup @@ -34,6 +37,8 @@ Nothing here asserts a Hunt-process property, and no statement covers a stopping infinite. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized.lean index 17460bad85..a6747111b9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized.lean @@ -4,22 +4,25 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Annealed -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeSupport -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Equivariance -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Killed -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup +module + +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Annealed +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeSupport +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Equivariance +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Killed +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup + /-! # Parameterized diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean index f5c50f083c..cc45ef9323 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Annealed.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties +module + +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties + /-! # The annealed law of a parameterized continuous-path process @@ -26,6 +29,8 @@ The annealed process is in general not Markov in the probabilistic sense (the av not have the Markov property); nothing of that kind is claimed. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory Filter open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeMarginals.lean index 3323264cbc..ce05d90f8b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeMarginals.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals +module + +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeterySemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectoryMarginals + /-! # Cemetery marginals of parameterized dense-time trajectories @@ -13,6 +16,8 @@ This file proves a one-time marginal identity. It makes no simultaneous path-su lifetime claim. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeSupport.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeSupport.lean index 21fb9455a9..d478b622f3 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeSupport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeteryDenseTimeSupport.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals +module + +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.CemeteryDenseTimeMarginals + /-! # Simultaneous dense-time cemetery avoidance @@ -15,6 +18,8 @@ This is only a statement about the countable trajectory. It makes no continuous- lifetime-path, or spatial support claim. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeterySemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeterySemigroup.lean index ce7edcdb40..7b71bc307b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeterySemigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/CemeterySemigroup.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.CemeterySemigroup +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup + /-! # Parameterized cemetery-extension semigroups @@ -13,6 +16,8 @@ This file extends a jointly measurable family of sub-Markov semigroups by one ab cemetery state. The construction is jointly measurable in the parameter, time, and state. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcess.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcess.lean index 22c698c17e..51517ce880 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcess.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcess.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification -import LeanPool.MarkovProcess.MarkovProcess.Main -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Main +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory + /-! # The continuous-path process of a measurably parameterized semigroup @@ -30,6 +33,8 @@ No Markov, strong Markov, Feller, equivariance, annealed or killed statement is of those is a separate transport through the fibre identity. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcessProperties.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcessProperties.lean index f75e8e2870..179b6702b8 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcessProperties.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/ContinuousProcessProperties.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess +module + +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess + /-! # Properties of the parameterized continuous-path process @@ -28,6 +31,8 @@ form `continuousProcess_map_eval_zero'`), `continuousProcess_map_finiteEvaluatio `continuousProcess_condExp_shift_countableStoppingTime`. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeConditionalKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeConditionalKernel.lean index 1e4f1cf9c0..468117dd1b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeConditionalKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeConditionalKernel.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel -import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory -import Mathlib.Probability.Kernel.Disintegration.StandardBorel +module + +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimePrefixKernel +public import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory +public import Mathlib.Probability.Kernel.Disintegration.StandardBorel + /-! # Conditional kernels for parameterized finite dense-time prefixes @@ -15,6 +18,8 @@ observation. The resulting conditional kernel is one jointly measurable version. with separately chosen fixed-parameter conditional versions is asserted. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimePrefixKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimePrefixKernel.lean index 3b0082ef47..e85884d48c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimePrefixKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimePrefixKernel.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PrefixKernel +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeProjectiveFamily + /-! # Parameterized kernels on finite prefixes of a countable time enumeration @@ -14,6 +17,8 @@ enumeration. Coordinates remain in enumeration order; the enumeration need not b physical time. Fiberwise conservativity is used only for Markovness and prefix consistency. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean index 5a36d0520b..8edc00221f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean @@ -3,12 +3,17 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory -import Mathlib.Probability.Kernel.IonescuTulcea.Traj +module + +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeConditionalKernel +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.Trajectory +public import Mathlib.Probability.Kernel.IonescuTulcea.Traj + /-! # Parameterized trajectories on countable dense time -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectoryMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectoryMarginals.lean index b6faad9123..9938237d00 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectoryMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectoryMarginals.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.DenseTimeTrajectory + /-! # One-time marginals of parameterized dense-time trajectories @@ -13,6 +16,8 @@ This file identifies every coordinate marginal of the jointly measurable paramet trajectory kernel. No standard-Borel assumption is imposed on the parameter space. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Equivariance.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Equivariance.lean index 5def8bc3e4..8ff12374c2 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Equivariance.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Equivariance.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance +module + +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcess +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance + /-! # Equivariance of the parameterized continuous-path process @@ -32,6 +35,8 @@ No scaling limit and no ergodic statement is asserted: the environment map `g`, and both families are given in advance, and nothing is claimed about the law of the environment. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeKernel.lean index 5923264951..91fc2a9a22 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeKernel.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.Kernel +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.OrderedGrid + /-! # Parameterized finite-time kernels @@ -19,6 +22,8 @@ nonparameterized finite-time kernel of the fixed-parameter semigroup. No path-sp stochastic-process existence claim is made here. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeProjectiveFamily.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeProjectiveFamily.lean index 201d0ffe59..cd242b2b19 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeProjectiveFamily.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeProjectiveFamily.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.FiniteTimeKernel + /-! # Parameterized finite-set finite-time kernels @@ -15,6 +18,8 @@ derives projectivity under fiberwise conservativity. It does not construct a pro measure or a stochastic process. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Killed.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Killed.lean index ffaca2c82c..e24c4d74dc 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Killed.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Killed.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties + /-! # The killed parameterized family @@ -22,6 +25,8 @@ parameterized continuous-path process through the fibre identity. The killed process on lifetime paths (with a cemetery state) is not constructed here. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/OrderedGrid.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/OrderedGrid.lean index ce7467477e..f734d35d6c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/OrderedGrid.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/OrderedGrid.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup +module + +public import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.Semigroup + /-! # Parameterized trajectory laws on a fixed ordered time grid @@ -18,6 +21,8 @@ The result is a path-law kernel on `Theta × alpha` with values in measures on ` It is not a continuous-time path law and does not assert measurability in the grid. -/ +@[expose] public section + open MeasureTheory open ProbabilityTheory open scoped ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Semigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Semigroup.lean index d53393e212..57aa00b792 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Semigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/Semigroup.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup + /-! # Measurably parameterized sub-Markov kernel semigroups @@ -17,6 +20,8 @@ No parameter family is selected here, and no concrete coefficient, domain, Felle or stochastic-process assertion is made. -/ +@[expose] public section + noncomputable section PortComputability open Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path.lean b/LeanPool/MarkovProcess/MarkovProcess/Path.lean index c393ab25b4..949af91231 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path.lean @@ -4,27 +4,30 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.Basic -import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection -import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration -import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral -import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift -import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification -import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification -import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping -import LeanPool.MarkovProcess.MarkovProcess.Path.Polish -import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability -import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence -import LeanPool.MarkovProcess.MarkovProcess.Path.RelativeHitting -import LeanPool.MarkovProcess.MarkovProcess.Path.Sampling -import LeanPool.MarkovProcess.MarkovProcess.Path.Shift -import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence -import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability -import LeanPool.MarkovProcess.MarkovProcess.Path.Stopping -import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +public import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration +public import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral +public import LeanPool.MarkovProcess.MarkovProcess.Path.Exhaustion +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift +public import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +public import LeanPool.MarkovProcess.MarkovProcess.Path.Polish +public import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability +public import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Path.RelativeHitting +public import LeanPool.MarkovProcess.MarkovProcess.Path.Sampling +public import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +public import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability +public import LeanPool.MarkovProcess.MarkovProcess.Path.Stopping +public import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling + /-! # Path diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Basic.lean index f42fdd19ee..f795bbc3de 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/Basic.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Basic.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Probability.Process.Filtration -import Mathlib.Topology.CompactOpen +module + +public import Mathlib.Probability.Process.Filtration +public import Mathlib.Topology.CompactOpen + /-! # Canonical continuous-path space @@ -14,6 +17,8 @@ coordinate process, and the filtration generated by coordinates up to each time. no probability law and makes no stochastic-process association or path-regularity claim. -/ +@[expose] public section + open MeasureTheory namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean index 89b9520edb..69ef336fcb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean @@ -3,12 +3,17 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.Basic -import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime -import Mathlib.Topology.MetricSpace.HausdorffDistance +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +public import Mathlib.Topology.MetricSpace.HausdorffDistance + /-! # Detecting closed sets from countably many path coordinates -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/DenseFiltration.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/DenseFiltration.lean index f7a908266c..a971f684fd 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/DenseFiltration.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/DenseFiltration.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension + /-! # Dense-time generation of the continuous-path filtration @@ -14,6 +17,8 @@ fact is the filtration bridge needed to extend finite-cylinder restart identitie events. No probability law or Markov property is asserted here. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/DenseRestrictionIntegral.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/DenseRestrictionIntegral.lean index 433549f4c1..fcefc549c8 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/DenseRestrictionIntegral.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/DenseRestrictionIntegral.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension -import Mathlib.Topology.ContinuousMap.CompactlySupported +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +public import Mathlib.Topology.ContinuousMap.CompactlySupported + /-! # Integrals of finite dense-time marginals of a path measure @@ -14,6 +17,8 @@ continuous-path space is integrating the composed test against the measure itsel change-of-variables identity with no probabilistic content. -/ +@[expose] public section + open MeasureTheory open scoped CompactlySupported diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Exhaustion.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Exhaustion.lean index f9aa83f0ea..962a108101 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/Exhaustion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Exhaustion.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift + /-! # Exit times along an exhaustion @@ -17,6 +20,8 @@ interval for every `n ≥ N` (`tendsto_exitTime_atTop`). Exit times are monoton This is the path-space fact behind nonexplosion arguments: no probability law is involved here. -/ +@[expose] public section + open Filter Topology open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTime.lean index d95ea1ebfa..e64bb687ac 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTime.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTime.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection -import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime -import Mathlib.Probability.Process.Stopping +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +public import LeanPool.MarkovProcess.MarkovProcess.Lifetime.ExitTime +public import Mathlib.Probability.Process.Stopping + /-! # Exit times of open sets on continuous-path space @@ -28,6 +31,8 @@ This file constructs no probability law and proves no probabilistic statement; i does not claim that the exit time is almost surely finite for any process. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory Set Filter diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTimeShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTimeShift.lean index cfbebc008d..e3677cf0ae 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTimeShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/ExitTimeShift.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime -import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Path.Shift + /-! # Exit times under shifts @@ -23,6 +26,8 @@ shift `ContinuousPath.shift t`, and the measurability of the survival events the Nothing here involves a probability law. -/ +@[expose] public section + open MeasureTheory Set open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/KernelIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/KernelIdentification.lean index e3a6d5f554..5f0f5ca5d9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/KernelIdentification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/KernelIdentification.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension -import Mathlib.Probability.Kernel.Composition.MapComap +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +public import Mathlib.Probability.Kernel.Composition.MapComap + /-! # Identifying continuous-path kernels from dense-time restrictions @@ -15,6 +18,8 @@ deterministic property of continuous paths; it makes no stochastic-process, Mark claim. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/MeasureIdentification.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/MeasureIdentification.lean index 2a4a27cf97..006e8d6031 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/MeasureIdentification.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/MeasureIdentification.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension + /-! # Identifying continuous-path measures from dense-time restrictions @@ -13,6 +16,8 @@ carrier. This is the measure-level counterpart of continuous-path kernel identif deterministic property of continuous paths. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/MixedFiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/MixedFiniteMarginals.lean index a3a77e12db..4d3251b2e1 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/MixedFiniteMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/MixedFiniteMarginals.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture + /-! # Finite mixed past/future marginals of continuous trajectories @@ -19,6 +22,8 @@ This is a finite-dimensional law identity. The conditional factorization of tha the state at `S` is in `Restart/RationalRestart.lean`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/OptionalStopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/OptionalStopping.lean index ac28b9d83e..7fdea02348 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/OptionalStopping.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/OptionalStopping.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling -import Mathlib.MeasureTheory.Integral.DominatedConvergence -import Mathlib.Probability.Martingale.OptionalStopping +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling +public import Mathlib.MeasureTheory.Integral.DominatedConvergence +public import Mathlib.Probability.Martingale.OptionalStopping + /-! # Optional stopping in continuous time, at a bounded finite stopping time @@ -35,6 +38,8 @@ a filtration indexed by `ℝ≥0`. No optional-stopping result for unbounded st asserted. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Polish.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Polish.lean index ba39b3bbca..a8d9f88ff5 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/Polish.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Polish.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.Basic -import Mathlib.Topology.ContinuousMap.SecondCountableSpace -import Mathlib.MeasureTheory.Constructions.Polish.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +public import Mathlib.Topology.ContinuousMap.SecondCountableSpace +public import Mathlib.MeasureTheory.Constructions.Polish.Basic + /-! # Polish structure of continuous-path space @@ -18,6 +21,8 @@ With the Borel sigma-algebra the path space is therefore a standard Borel space. This is ordinary topological infrastructure. It proves no probabilistic statement. -/ +@[expose] public section + namespace MarkovProcess namespace ContinuousPath diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/RandomShiftMeasurability.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/RandomShiftMeasurability.lean index 28d52088c0..21417aef5e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/RandomShiftMeasurability.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/RandomShiftMeasurability.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.Shift -import Mathlib.Probability.Process.Stopping +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +public import Mathlib.Probability.Process.Stopping + /-! # Measurability of random shifts of continuous paths @@ -19,6 +22,8 @@ expectation formula; those are in `Trajectory/FellerStoppingRestart.lean` and `Trajectory/FellerStoppingConditional.lean`. -/ +@[expose] public section + open MeasureTheory namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/RandomTimeCompactTestConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/RandomTimeCompactTestConvergence.lean index 635c9cc6a9..aa9aaf28b2 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/RandomTimeCompactTestConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/RandomTimeCompactTestConvergence.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure -import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability + /-! # Dominated convergence for tests along random times @@ -16,6 +19,8 @@ continuous-path space; no Markov or kernel assumption is used. The deterministi versions are in `ContinuousPathShiftCompactTestConvergence.lean`. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/RelativeHitting.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/RelativeHitting.lean index 28a21c21e2..35753df545 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/RelativeHitting.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/RelativeHitting.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.ClosedSetDetection +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop + /-! # Closed-set detection after a stopping time @@ -20,6 +23,8 @@ Public declarations: * `ContinuousPath.measurableSet_hitsSetBetween`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Sampling.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Sampling.lean index 82932ec1b2..0e12341a6b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/Sampling.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Sampling.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime + /-! # Uniform sampling of a continuous path @@ -26,6 +29,8 @@ No lattice, no covering family and no discrete geometry appears here: the sampli metric. -/ +@[expose] public section + open Set open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean index b14ac41e00..2113c03e15 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.Basic + /-! # Deterministic shifts of continuous paths @@ -15,6 +18,8 @@ records the corresponding deterministic relation between the canonical filtratio No random-time shift, Markov property, strong Markov property, or Hunt-process assertion is made. -/ +@[expose] public section + open MeasureTheory namespace MarkovProcess @@ -87,7 +92,7 @@ theorem measurable_shift_canonicalFiltration [MeasurableSpace alpha] [BorelSpace exact shift_apply S u omega rw [hfun] exact le_iSup_of_le - (⟨S + u.1, by simpa only [add_comm] using! add_le_add_left u.2 S⟩ : + (⟨S + u.1, by exact add_le_add_left u.2 S⟩ : Set.Iic (S + t)) le_rfl end ContinuousPath diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/ShiftCompactTestConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/ShiftCompactTestConvergence.lean index 8cf485b709..4a3db448a2 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/ShiftCompactTestConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/ShiftCompactTestConvergence.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals + /-! # Dominated convergence for shifted continuous-path tests @@ -13,6 +16,8 @@ dense times. The measure is any finite measure on continuous-path space; no Mark assumption is used. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/StoppedValueMeasurability.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/StoppedValueMeasurability.lean index 504f974058..71f8473c62 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/StoppedValueMeasurability.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/StoppedValueMeasurability.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.Basic -import Mathlib.Probability.Process.Stopping +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +public import Mathlib.Probability.Process.Stopping + /-! # Measurability of the state at a stopping time @@ -20,6 +23,8 @@ expectation formula; those are in `Trajectory/FellerStoppingRestart.lean` and `Trajectory/FellerStoppingConditional.lean`. -/ +@[expose] public section + open MeasureTheory namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Stopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Stopping.lean index b031a92eab..6ac88939e9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/Stopping.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Stopping.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.Basic + /-! # Deterministic stopping of continuous paths @@ -13,6 +16,8 @@ topological and Borel-measurability properties of this operation; it introduces times or stochastic laws. -/ +@[expose] public section + namespace MarkovProcess namespace ContinuousPath diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/StoppingTimeDyadicCeiling.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/StoppingTimeDyadicCeiling.lean index 52cfc54b09..488d300561 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/StoppingTimeDyadicCeiling.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/StoppingTimeDyadicCeiling.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Probability.Process.Stopping -import Mathlib.Topology.Instances.NNReal.Lemmas +module + +public import Mathlib.Probability.Process.Stopping +public import Mathlib.Topology.Instances.NNReal.Lemmas + /-! # Dyadic ceiling approximation of finite stopping times @@ -16,6 +19,8 @@ infrastructure and proves no restart identity; the restart identity obtained fro approximation is in `Trajectory/FellerStoppingRestart.lean`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory Filter Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart.lean index aa6b02197c..eea5137836 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart.lean @@ -4,15 +4,18 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation -import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov -import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure -import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture -import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint +module + +public import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation +public import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov +public import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint + /-! # Restart diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalExpectation.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalExpectation.lean index 2279f98c08..cc0a329a41 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalExpectation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalExpectation.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.MeasureTheory.Function.ConditionalExpectation.Basic -import Mathlib.Probability.Kernel.Composition.IntegralCompProd +module + +public import Mathlib.MeasureTheory.Function.ConditionalExpectation.Basic +public import Mathlib.Probability.Kernel.Composition.IntegralCompProd + /-! # Conditional expectation from restricted restart laws @@ -17,6 +20,8 @@ only an unconditional distributional identity and is not enough for this conclus No stochastic process, Markov property, or path-space construction is asserted here. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalMarkov.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalMarkov.lean index 5f3ca066a4..aa2f186264 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalMarkov.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/ConditionalMarkov.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation -import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +module + +public import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalExpectation +public import LeanPool.MarkovProcess.MarkovProcess.Path.Shift + /-! # Deterministic-time conditional restart on continuous paths @@ -18,6 +21,8 @@ The theorem is a conditional API: it does not prove its restricted restart-law h not by itself associate a Markov or Hunt process with a transition semigroup. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestart.lean index 3bf4201def..28d13097e5 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestart.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov -import Mathlib.MeasureTheory.Function.ConditionalExpectation.Indicator -import Mathlib.Probability.Process.Stopping +module + +public import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov +public import Mathlib.MeasureTheory.Function.ConditionalExpectation.Indicator +public import Mathlib.Probability.Process.Stopping + /-! # Conditional restart at countable-valued stopping times @@ -16,6 +19,8 @@ infrastructure: the deterministic-time restart identity is a hypothesis here, pr continuous-path process in `Trajectory/FellerRestrictedRestart.lean`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestartMeasure.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestartMeasure.lean index 1f16544ec4..0deb703b9a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestartMeasure.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/CountableStoppingRestartMeasure.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability +module + +public import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Path.RandomShiftMeasurability + /-! # Measure-level restart at countable-range stopping times @@ -19,6 +22,8 @@ This is ordinary conditional infrastructure. The restart hypothesis is an assum is proved for the continuous-path process in `Trajectory/FellerRestrictedRestart.lean`. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/FinitePastRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/FinitePastRestart.lean index fe9d074cae..508bf4f07b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/FinitePastRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/FinitePastRestart.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification -import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification + /-! # Identifying joint laws of a finite past and a continuous future @@ -16,6 +19,8 @@ joint-law factorization. It does not assert that any particular stochastic proc finite-dimensional identities. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/MixedPastFuture.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/MixedPastFuture.lean index 57f36dfe94..894244e2be 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/MixedPastFuture.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/MixedPastFuture.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex -import Mathlib.Data.Finset.Sum -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +public import Mathlib.Data.Finset.Sum +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelMixedPullback + /-! # Mixed past-future coordinates and the cut factorization @@ -20,6 +23,8 @@ This file merges the following former modules, one section each: rational cut -/ +@[expose] public section + noncomputable section PortComputability namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestart.lean index 0d78dc0ea2..20303afdf4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestart.lean @@ -3,12 +3,15 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture -import Mathlib.Probability.Kernel.Composition.KernelLemmas -import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex -import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals +module + +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.FinitePastRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.MixedPastFuture +public import Mathlib.Probability.Kernel.Composition.KernelLemmas +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex +public import LeanPool.MarkovProcess.MarkovProcess.Path.MixedFiniteMarginals + /-! # The rational-time restart kernel and its joint law @@ -20,6 +23,8 @@ This file merges the following former modules, one section each: * `RationalJointLaw`: Rational-time joint restart law -/ +@[expose] public section + noncomputable section PortComputability namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestrictedRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestrictedRestart.lean index 26cd24d6ab..87b4074c37 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestrictedRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/RationalRestrictedRestart.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration -import LeanPool.MarkovProcess.MarkovProcess.Path.Shift -import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.DenseFiltration +public import LeanPool.MarkovProcess.MarkovProcess.Path.Shift +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RestrictedRestartOfJoint + /-! # Restricted restart at rational times @@ -16,6 +19,8 @@ factorization remains an explicit input; proving it from the finite-dimensional next process-construction step. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Restart/RestrictedRestartOfJoint.lean b/LeanPool/MarkovProcess/MarkovProcess/Restart/RestrictedRestartOfJoint.lean index d57ea6029c..2fe68160c3 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Restart/RestrictedRestartOfJoint.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Restart/RestrictedRestartOfJoint.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Probability.Kernel.Composition.MeasureCompProd -import Mathlib.Probability.Kernel.Composition.CompNotation +module + +public import Mathlib.Probability.Kernel.Composition.MeasureCompProd +public import Mathlib.Probability.Kernel.Composition.CompNotation + /-! # Restricted restart laws from a joint-law factorization @@ -16,6 +19,8 @@ restriction to any event measurable with respect to the conditioning variable. No stochastic process or Markov property is asserted here. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup.lean index 757d04f0bf..492a73605d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup.lean @@ -4,31 +4,34 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialComparison -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialComparison +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PoissonInvariant +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventGeneration +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit + /-! # Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Basic.lean index 1bd864a46d..9bc1ab1587 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Basic.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Basic.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Analysis.Normed.Operator.Basic +module + +public import Mathlib.Analysis.Normed.Operator.Basic + /-! # Strongly continuous contraction semigroups @@ -12,6 +15,8 @@ This file provides a small reusable interface for strongly continuous contractio semigroups on real normed spaces, parametrized by nonnegative real time. -/ +@[expose] public section + open Filter Topology namespace MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/CompactStrongConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/CompactStrongConvergence.lean index fc5a3b3ff9..4855385ca3 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/CompactStrongConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/CompactStrongConvergence.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Analysis.Normed.Operator.Basic +module + +public import Mathlib.Analysis.Normed.Operator.Basic + /-! # Equibounded strong convergence is uniform on compact sets @@ -19,6 +22,8 @@ Neither completeness of the spaces nor countable generation of the index filter nothing is asserted about convergence in the operator norm, which is strictly stronger. -/ +@[expose] public section + open Filter Topology namespace MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ContractiveResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ContractiveResolvent.lean index 3ec1e37f8e..4fa2eaf8d0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ContractiveResolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ContractiveResolvent.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.PositiveShift +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.DenseCoreConvergence + /-! # Contractive resolvent families @@ -13,6 +16,8 @@ This module packages the elementary resolvent identity, the Hille--Yosida bound, and dense range, then derives normalization at large positive shifts. -/ +@[expose] public section + open Filter Topology namespace MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/DenseCoreConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/DenseCoreConvergence.lean index fdc6a4e4db..c1259ffd37 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/DenseCoreConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/DenseCoreConvergence.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Analysis.Normed.Operator.Basic +module + +public import Mathlib.Analysis.Normed.Operator.Basic + /-! # Convergence from a dense core @@ -12,6 +15,8 @@ This module extends pointwise convergence of uniformly contractive continuous linear maps from the range of a dense map to the whole ambient space. -/ +@[expose] public section + open Filter Topology namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Duhamel.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Duhamel.lean index d1b6d50cb6..b5e738bed5 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Duhamel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Duhamel.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Analysis.SpecialFunctions.Exponential -import Mathlib.Analysis.Calculus.Deriv.Mul -import Mathlib.MeasureTheory.Integral.IntervalIntegral.FundThmCalculus +module + +public import Mathlib.Analysis.SpecialFunctions.Exponential +public import Mathlib.Analysis.Calculus.Deriv.Mul +public import Mathlib.MeasureTheory.Integral.IntervalIntegral.FundThmCalculus + /-! # Duhamel estimates for bounded generators @@ -16,6 +19,8 @@ exponentials of commuting bounded generators. The identity is oriented as estimate is immediately applicable to Yosida approximants. -/ +@[expose] public section + open MeasureTheory NormedSpace Set namespace MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialBounds.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialBounds.lean index 35180d4238..eaf36c43aa 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialBounds.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialBounds.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Analysis.Normed.Algebra.Exponential -import Mathlib.Analysis.SpecialFunctions.Exponential +module + +public import Mathlib.Analysis.Normed.Algebra.Exponential +public import Mathlib.Analysis.SpecialFunctions.Exponential + /-! # Norm bounds for Banach-algebra exponentials @@ -13,6 +16,8 @@ This file records elementary estimates for the exponential in a real Banach alge contraction estimate is tailored to exponentials of bounded Yosida-type generators. -/ +@[expose] public section + namespace MarkovProcess.Semigroup open NormedSpace diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialComparison.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialComparison.lean index 091403e107..cc49256479 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialComparison.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ExponentialComparison.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0Resolvent + /-! # Exponential comparison under resolvent generation @@ -21,6 +24,8 @@ Public declarations: No comparison for indicators of arbitrary measurable sets is asserted. -/ +@[expose] public section + noncomputable section PortComputability open Filter Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generation.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generation.lean index d057a2919d..e436d945d5 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generation.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaStrongLimit +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity + /-! # Generation of a contraction semigroup from a contractive resolvent @@ -15,6 +18,8 @@ as a strongly continuous contraction semigroup. Strong continuity at zero is first proved on the range of one resolvent and then extended by density. -/ +@[expose] public section + noncomputable section PortComputability open Filter NormedSpace Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generator.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generator.lean index e4ad869035..09c2397063 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generator.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Generator.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit -import Mathlib.Analysis.Calculus.Deriv.Mul -import Mathlib.Analysis.SpecialFunctions.ExpDeriv -import Mathlib.MeasureTheory.Integral.IntervalIntegral.FundThmCalculus +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit +public import Mathlib.Analysis.Calculus.Deriv.Mul +public import Mathlib.Analysis.SpecialFunctions.ExpDeriv +public import Mathlib.MeasureTheory.Integral.IntervalIntegral.FundThmCalculus + /-! # The generator of a strongly continuous contraction semigroup @@ -34,6 +37,8 @@ Times are `NNReal` throughout the library; the real-variable statements read the `Real.toNNReal s`. The fundamental identity is what Dynkin's formula consumes. -/ +@[expose] public section + noncomputable section PortComputability open Filter Topology @@ -113,7 +118,7 @@ end Domain section Generator /-- The limit of the difference quotients, for a vector of the domain. -/ -private noncomputable def generatorFun (f : S.generatorDomain) : E := +noncomputable def generatorFun (f : S.generatorDomain) : E := limUnder (𝓝[>] (0 : NNReal)) (S.differenceQuotient f) private theorem tendsto_generatorFun (f : S.generatorDomain) : diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorClosed.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorClosed.lean index 5441ce66fe..8333156f4d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorClosed.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorClosed.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator + /-! # The generator is closed @@ -24,6 +27,8 @@ Nothing is asserted about the domain beyond closedness of the graph; density is `Semigroup/Generator.lean`. -/ +@[expose] public section + open Filter Topology open scoped NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorInjectivity.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorInjectivity.lean index e55b5bfa39..23fb491495 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorInjectivity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorInjectivity.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator -import Mathlib.Analysis.ODE.Gronwall +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +public import Mathlib.Analysis.ODE.Gronwall + /-! # Eigenvectors of a generator, and injectivity of `μ - L` @@ -21,6 +24,8 @@ Since `S` is contractive, an eigenvalue `μ > 0` therefore forces `f = 0` `(μ - L)⁻¹` is a well-defined operator. -/ +@[expose] public section + noncomputable section PortComputability open Filter Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorResolvent.lean index d032736715..62be264435 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorResolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorResolvent.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity + /-! # The generator of the semigroup generated by a contractive resolvent @@ -31,6 +34,8 @@ canonical shifts by dominated convergence gives `S t x - x = ∫₀ᵗ S s (μ x `R_μ`, and time averages of the orbit then produce the difference quotient at `t = 0`. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory NormedSpace Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorUniqueness.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorUniqueness.lean index 4550be2aae..9aef292889 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorUniqueness.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/GeneratorUniqueness.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity -import Mathlib.Analysis.ODE.Gronwall +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity +public import Mathlib.Analysis.ODE.Gronwall + /-! # The generator determines the semigroup @@ -25,6 +28,8 @@ and the two difference quotients on the right converge to the common value of th and `T t f`. Density of the generator domain extends the identity to the whole space. -/ +@[expose] public section + noncomputable section PortComputability open Filter Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean index 7090bd54d5..d37cb1bf4c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/InvariantSet.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation -import Mathlib.Analysis.Convex.Combination +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generation +public import Mathlib.Analysis.Convex.Combination + /-! # Invariant sets and strong semigroup limits @@ -16,6 +19,8 @@ Poisson-series argument transferring the latter invariance to each exponential approximant is in `Semigroup/PoissonInvariant.lean`. -/ +@[expose] public section + noncomputable section PortComputability open Filter Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitContinuity.lean index ce7d59663e..d288b66c81 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitContinuity.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit + /-! # Continuity of semigroup orbits from continuity at zero @@ -15,6 +18,8 @@ strong continuity to joint continuity in the time and the vector, in the form `continuous_operator_apply`. -/ +@[expose] public section + open Filter Topology namespace MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitProductRule.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitProductRule.lean index 478fd0b99b..f1afecef24 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitProductRule.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/OrbitProductRule.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator + /-! # The product rule for a semigroup acting along a curve @@ -25,6 +28,8 @@ Times are read from the real line at `Real.toNNReal`, as elsewhere in the librar asserted about the two-sided derivative, which for a general curve fails at `s = 0`. -/ +@[expose] public section + open Filter Topology open scoped NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PoissonInvariant.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PoissonInvariant.lean index b76022e86a..2ca8ccdaae 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PoissonInvariant.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PoissonInvariant.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.InvariantSet + /-! # Poisson invariance of bounded Yosida exponentials @@ -12,6 +15,8 @@ This file proves the uniformization argument: a normalized resolvent preserving a closed convex set containing zero has Yosida exponentials preserving that set. -/ +@[expose] public section + noncomputable section PortComputability open Filter Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PositiveShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PositiveShift.lean index 924e0af062..617cb13ddb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PositiveShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/PositiveShift.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Analysis.SpecificLimits.Basic +module + +public import Mathlib.Analysis.SpecificLimits.Basic + /-! # Limits along positive real parameters @@ -13,6 +16,8 @@ parameters and a filter-generic criterion that turns a vanishing square bound into convergence to zero. -/ +@[expose] public section + namespace MarkovProcess.Semigroup open Filter Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Resolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Resolvent.lean index 30434089c8..71a250b340 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Resolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/Resolvent.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent -import Mathlib.MeasureTheory.Integral.ExpDecay -import Mathlib.Analysis.SpecialFunctions.ImproperIntegrals +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorClosed +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorInjectivity +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent +public import Mathlib.MeasureTheory.Integral.ExpDecay +public import Mathlib.Analysis.SpecialFunctions.ImproperIntegrals + /-! # The resolvent of a strongly continuous contraction semigroup @@ -41,6 +44,8 @@ The shift `μ` is a positive real; nothing is asserted for complex shifts or for generator beyond the half-line `(0, ∞)`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory Filter Topology Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventComparison.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventComparison.lean index 71c6bdd08f..6a8c6d2e78 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventComparison.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventComparison.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.OrbitProductRule +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent + /-! # Comparing two semigroups through their resolvents @@ -33,6 +36,8 @@ Both semigroups are read at the same shift `μ`; nothing is asserted when the tw taken at different shifts, and no relation between the two generators is assumed. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventGeneration.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventGeneration.lean index 44b2b034cb..17ae99cf88 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventGeneration.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/ResolventGeneration.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.GeneratorUniqueness + /-! # The semigroup generated by the resolvent of a semigroup @@ -30,6 +33,8 @@ Nothing is asserted about resolvents that do not come from a semigroup; for thos generation theorem of `Semigroup/Generation.lean` is the statement. -/ +@[expose] public section + open scoped NNReal namespace MarkovProcess.Semigroup.StronglyContinuousContractionSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/StrongOperatorLimit.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/StrongOperatorLimit.lean index 7831f819d2..2284d8a9e7 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/StrongOperatorLimit.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/StrongOperatorLimit.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Analysis.Normed.Operator.Completeness +module + +public import Mathlib.Analysis.Normed.Operator.Completeness + /-! # Strong operator limits of contractions @@ -13,6 +16,8 @@ contractions on a complete real normed space and records the small convergence API needed to pass algebraic identities to the limit. -/ +@[expose] public section + open Filter Topology namespace MarkovProcess.Semigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/TrotterKato.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/TrotterKato.lean index bc88d84025..cccff0edde 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/TrotterKato.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/TrotterKato.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.CompactStrongConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ResolventComparison + /-! # The Trotter--Kato theorem @@ -41,6 +44,8 @@ about convergence in the operator norm, nor about families that are merely unifo rather than contractive. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean index 2102729323..447272eceb 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ContractiveResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.ExponentialBounds +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Basic + /-! # Bounded Yosida approximations @@ -15,6 +18,8 @@ For a contractive resolvent `R`, this file defines the bounded generator records commutation and the exact formula on the range of a fixed resolvent. -/ +@[expose] public section + noncomputable section PortComputability open Filter Topology @@ -54,6 +59,9 @@ section CompleteSpace variable [CompleteSpace E] +private instance : NormedAlgebra ℚ (E →L[ℝ] E) := + NormedAlgebra.restrictScalars ℚ ℝ (E →L[ℝ] E) + /-- The exponential of the bounded Yosida generator at nonnegative time. -/ def yosidaOperator (R : ContractiveResolvent E) (α : PositiveShift) (t : NNReal) : E →L[ℝ] E := diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaStrongLimit.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaStrongLimit.lean index 2623a6c1a0..c018d174c9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaStrongLimit.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaStrongLimit.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.YosidaApproximation +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Duhamel +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.StrongOperatorLimit + /-! # Strong limits of Yosida approximations @@ -16,6 +19,8 @@ orbits is proved in `Semigroup/Generation.lean`, from the criterion of `Semigroup/OrbitContinuity.lean`. -/ +@[expose] public section + noncomputable section PortComputability open Filter NormedSpace Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time.lean b/LeanPool/MarkovProcess/MarkovProcess/Time.lean index 5eca3a2d2a..e1133630c4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time.lean @@ -4,14 +4,17 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime -import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove -import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding -import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes -import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid +module + +public import LeanPool.MarkovProcess.MarkovProcess.Time.CountableDenseTime +public import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove +public import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeHistory +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteDenseApproximationOrdered +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteGridIncrement +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderEmbedding +public import LeanPool.MarkovProcess.MarkovProcess.Time.FiniteOrderedTimes +public import LeanPool.MarkovProcess.MarkovProcess.Time.OrderedGrid + /-! # Time diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean index 3200a2292b..56a04de2a8 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean @@ -3,12 +3,15 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Data.NNRat.Defs -import Mathlib.Basic.NNReal.Defs -import Mathlib.Data.Rat.Cast.Order -import Mathlib.Data.Rat.Encodable -import Mathlib.Basic.Denumerable -import Mathlib.MeasureTheory.MeasurableSpace.Embedding +module + +public import Mathlib.Data.NNRat.Defs +public import Mathlib.Basic.NNReal.Defs +public import Mathlib.Data.Rat.Cast.Order +public import Mathlib.Data.Rat.Encodable +public import Mathlib.Basic.Denumerable +public import Mathlib.MeasureTheory.MeasurableSpace.Embedding + /-! # Countable dense time indices @@ -19,6 +22,8 @@ not increasing. No probability law, projective limit, stochastic process, contin regularity is constructed here. -/ +@[expose] public section + noncomputable section PortComputability namespace MarkovProcess @@ -141,7 +146,8 @@ private instance : Countable DenseTime where /-- A fixed arbitrary enumeration of nonnegative rational times. It is not order-preserving. -/ noncomputable def enumeration : ℕ ≃ DenseTime := - nonempty_equiv_of_countable.some + Classical.choice (show Nonempty (ℕ ≃ DenseTime) from by + exact nonempty_equiv_of_countable) end DenseTime end diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeApproximationFromAbove.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeApproximationFromAbove.lean index b0ff173de5..787302ebf7 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeApproximationFromAbove.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeApproximationFromAbove.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.DenseTimeContinuousExtension + /-! # Dense-time approximation from above @@ -16,6 +19,8 @@ cuts. This is deterministic order-topological infrastructure and makes no stochastic-process claim. -/ +@[expose] public section + open Filter Topology open scoped NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeHistory.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeHistory.lean index 3e5e910bb0..4bc372ebe9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeHistory.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/DenseTimeHistory.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.MeasureTheory.MeasurableSpace.Embedding +module + +public import Mathlib.MeasureTheory.MeasurableSpace.Embedding + /-! # Finite dense-time histories @@ -12,6 +15,8 @@ This file provides measurable coordinate equivalences for histories indexed by a segment of the natural numbers. It makes no probability-law, kernel, or stochastic-process claim. -/ +@[expose] public section + namespace MarkovProcess /-- A history through natural-number time `n`, including both endpoints. -/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteDenseApproximationOrdered.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteDenseApproximationOrdered.lean index 38f10038cf..1792e8b84a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteDenseApproximationOrdered.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteDenseApproximationOrdered.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals + /-! # Ordered form of finite dense approximations @@ -16,6 +19,8 @@ The construction also covers `I = ∅`. In that case the ordered time family and coordinate types are empty. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory Topology Filter diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteGridIncrement.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteGridIncrement.lean index d0d9dae1d4..3534064586 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteGridIncrement.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteGridIncrement.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.MeasureTheory.Integral.Lebesgue.Markov -import Mathlib.Probability.Process.Kolmogorov +module + +public import Mathlib.MeasureTheory.Integral.Lebesgue.Markov +public import Mathlib.Probability.Process.Kolmogorov + /-! # Finite-grid increment bounds @@ -14,6 +17,8 @@ independent of a particular dyadic-grid encoding: a later specialization only ha distance between adjacent grid times. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory open scoped ENNReal NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderEmbedding.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderEmbedding.lean index 2e3eba3f75..f54e270e5c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderEmbedding.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderEmbedding.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Data.Fintype.Card -import Mathlib.Order.Fin.Basic +module + +public import Mathlib.Data.Fintype.Card +public import Mathlib.Order.Fin.Basic + /-! # Factoring finite order embeddings through one deletion @@ -14,6 +17,8 @@ the range of an order embedding. It is ordinary combinatorial infrastructure and probability-law or stochastic-process claim. -/ +@[expose] public section + namespace MarkovProcess /-- An order embedding `Fin m ↪ Fin (n + 1)` with `m ≤ n` factors through deletion of a diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean index c2e82def7a..b138f284af 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/FiniteOrderedTimes.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Algebra.Order.Sub.Basic -import Mathlib.Basic.NNReal.Defs -import Mathlib.MeasureTheory.MeasurableSpace.Constructions -import Mathlib.Order.Fin.Basic +module + +public import Mathlib.Algebra.Order.Sub.Basic +public import Mathlib.Basic.NNReal.Defs +public import Mathlib.MeasureTheory.MeasurableSpace.Constructions +public import Mathlib.Order.Fin.Basic + /-! # Finite ordered time families @@ -16,6 +19,8 @@ for restricting such families and their coordinate paths along order embeddings. ordinary finite-dimensional API and makes no probability-law or stochastic-process claim. -/ +@[expose] public section + namespace MarkovProcess /-- A strictly increasing family of `n` nonnegative times. -/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/OrderedGrid.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/OrderedGrid.lean index 20b4a06d0e..5f4c9e648f 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/OrderedGrid.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/OrderedGrid.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Probability.Kernel.IonescuTulcea.Traj -import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup +module + +public import Mathlib.Probability.Kernel.IonescuTulcea.Traj +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.KernelSemigroup + /-! # Trajectory laws on a fixed ordered time grid @@ -14,6 +17,8 @@ kernel semigroup on one fixed nondecreasing `NNReal`-valued time grid. The result is only a discrete trajectory law on `ℕ → α` for that grid. -/ +@[expose] public section + open MeasureTheory open ProbabilityTheory @@ -48,7 +53,8 @@ namespace SubMarkovKernelSemigroup variable (P : SubMarkovKernelSemigroup α) -private def lastIndex (n : ℕ) : Finset.Iic n := +/-- The final index in a finite initial segment of the natural numbers. -/ +def lastIndex (n : ℕ) : Finset.Iic n := ⟨n, Finset.mem_Iic.mpr le_rfl⟩ /-- The history-dependent Ionescu--Tulcea step kernel on `grid`. diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory.lean index cf5462a445..ef413ce5dc 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory.lean @@ -4,48 +4,51 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExcessiveStopping -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeExponentialMoment -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKac -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalShift -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakConvergence +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeFiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Equivariance +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExcessiveStopping +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeExponentialMoment +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerConditional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerCountableStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerShift +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingConditional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKac +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalShift +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakConvergence + /-! # Trajectory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean index b7b53093cb..e325b6a010 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FiniteMarginals + /-! # Arbitrary-time finite marginals of continuous-path trajectories @@ -21,6 +24,8 @@ their strictly ordered time coordinates. No continuous-time Markov or Hunt prop or asserted. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeMarginals.lean index 3bb0b573fe..e8cb4d0030 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeMarginals.lean @@ -3,14 +3,17 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic -import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint -import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure -import Mathlib.MeasureTheory.Integral.DominatedConvergence -import Mathlib.MeasureTheory.Integral.RieszMarkovKakutani.Real -import Mathlib.MeasureTheory.Measure.RegularityCompacts -import Mathlib.Topology.Order.IsLUB +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.C0SemigroupJoint +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +public import Mathlib.MeasureTheory.Integral.DominatedConvergence +public import Mathlib.MeasureTheory.Integral.RieszMarkovKakutani.Real +public import Mathlib.MeasureTheory.Measure.RegularityCompacts +public import Mathlib.Topology.Order.IsLUB + /-! # All-time marginals of continuous-path trajectories @@ -22,6 +25,8 @@ and Feller `C₀`-orbit continuity on the other. No continuous-time Markov, strong Markov, or Hunt-process assertion is made here. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Basic.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Basic.lean index ca35cee4e3..ab27d2c25a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Basic.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Basic.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals -import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.TrajectoryMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.KolmogorovDenseTimeContinuousSupport + /-! # Continuous-path trajectory kernels @@ -18,6 +21,8 @@ No continuous-time Markov property, strong Markov property, Hunt-process asserti increment estimate is claimed. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ClampedCoordinate.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ClampedCoordinate.lean index 259ab007b2..28663bacb9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ClampedCoordinate.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ClampedCoordinate.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability + /-! # Measurability of clamped path coordinates @@ -17,6 +20,8 @@ Main result: `ContinuousPath.measurable_clampedCoordinate`. No stochastic-process law or stopping-time identity is asserted. -/ +@[expose] public section + open MeasureTheory open scoped NNReal diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Convergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Convergence.lean index 306ddcca2c..58e6e1d6d1 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Convergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Convergence.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence -import LeanPool.MarkovProcess.MarkovProcess.Main -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Main +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties + /-! # Convergence of the finite-dimensional distributions of Feller processes @@ -29,6 +32,8 @@ Convergence of the finite-dimensional distributions is not convergence on path s in addition a tightness estimate for the family of laws; that is not asserted here. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/CylinderAlgebra.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/CylinderAlgebra.lean index 9f82d17408..4293e16ff4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/CylinderAlgebra.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/CylinderAlgebra.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass -import LeanPool.MarkovProcess.MarkovProcess.Main +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductStoneWeierstrass +public import LeanPool.MarkovProcess.MarkovProcess.Main + /-! # Cylinder test functions on continuous-path space @@ -34,6 +37,8 @@ Main results: Nothing here mentions a probability law, and no continuity in a starting point is asserted. -/ +@[expose] public section + open scoped BoundedContinuousFunction NNReal ZeroAtInfty namespace MarkovProcess diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionIntegral.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionIntegral.lean index cd52a2e0b1..25bcdda827 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionIntegral.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionIntegral.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals -import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity -import LeanPool.MarkovProcess.MarkovProcess.Path.Polish +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Path.Polish + /-! # Finite dense-time marginals of a restarted trajectory law @@ -20,6 +23,8 @@ stopping-time statement is proved here; those are in `Trajectory/FellerCondition `Trajectory/FellerStoppingConditional.lean`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionMarginals.lean index 5694e99949..1de0a16de2 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseRestrictionMarginals.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex +module + +public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex + /-! # Finite marginals of dense restrictions of continuous trajectories @@ -13,6 +16,8 @@ are the existing finite-set kernels, reindexed from physical time back to ration file makes no shift, Markov, strong Markov, or Hunt-process assertion. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseStoppingRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseStoppingRestart.lean index 0292c500ee..0927542643 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseStoppingRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DenseStoppingRestart.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional -import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional +public import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart + /-! # Conditional restart at dense-time-valued stopping times @@ -20,6 +23,8 @@ in `Trajectory/FellerStoppingConditional.lean`, and a stopping time that may be `Trajectory/StoppingLtTop.lean`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DiscountedDynkin.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DiscountedDynkin.lean index 7bbe5656d9..c35a3398cd 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DiscountedDynkin.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DiscountedDynkin.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime -import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale + /-! # The discounted Dynkin formula @@ -30,6 +33,8 @@ Main results: `IsFellerKernelSemigroup.discountedDynkinProcess`, No assertion is made at an unbounded stopping time or about passage to an infinite horizon. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Dynkin.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Dynkin.lean index 053e16c94f..ad0c44b056 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Dynkin.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Dynkin.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Main -import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals -import Mathlib.MeasureTheory.Integral.Prod +module + +public import LeanPool.MarkovProcess.MarkovProcess.Main +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.PositiveC0OperatorMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Generator +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals +public import Mathlib.MeasureTheory.Integral.Prod + /-! # Dynkin's formula at deterministic times @@ -26,6 +29,8 @@ integral in `C₀` to a pointwise integral; `evalC0CLM` is the same functional u name, kept for consumers. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory Filter open scoped ENNReal NNReal ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinMartingale.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinMartingale.lean index 4758ad9c55..07843c0546 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinMartingale.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinMartingale.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin -import Mathlib.Probability.Martingale.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ClampedCoordinate +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Dynkin +public import Mathlib.Probability.Martingale.Basic + /-! # The Dynkin martingale @@ -41,6 +44,8 @@ The exponentially discounted extension is developed in `Trajectory/DiscountedDyn its zero-discount process is identified with this one by `discountedDynkinProcess_zero`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory Filter diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinStopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinStopping.lean index 83c45dfb60..ae196ae103 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinStopping.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/DynkinStopping.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime -import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTime +public import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DiscountedDynkin + /-! # Dynkin's formula at a bounded stopping time, and the expected exit time @@ -36,6 +39,8 @@ The progressive-measurability and optional-stopping statements below are the zer specializations of the corresponding results in `Trajectory/DiscountedDynkin.lean`. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean index b5141f1a1f..9f4e6c6c6a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/Equivariance.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance -import LeanPool.MarkovProcess.MarkovProcess.Main +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelEquivariance +public import LeanPool.MarkovProcess.MarkovProcess.Main + /-! # Equivariance of the continuous-path process @@ -35,6 +38,8 @@ No scaling limit is asserted: `c` is a fixed positive factor and both semigroups advance. The two state spaces may coincide; the degenerate corollaries are stated on one space. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExcessiveStopping.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExcessiveStopping.lean index 14e1fac0e0..75b74ce97b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExcessiveStopping.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExcessiveStopping.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Path.OptionalStopping +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime + /-! # Excessive functions and stopping @@ -28,6 +31,8 @@ Main results: `IsFellerKernelSemigroup.resolvent_isLambdaExcessive`, No converse characterization of excessive functions is asserted. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitLaw.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitLaw.lean index 3b57a762ba..4107f2a9bc 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitLaw.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitLaw.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.HarmonicRepresentation +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop + /-! # Stopped laws and exit distributions @@ -27,6 +30,8 @@ The harmonic representation of `Trajectory/HarmonicRepresentation.lean` reads, i (`integral_exitLawTrunc_eq_of_generator_eq_zero`). -/ +@[expose] public section + open MeasureTheory ProbabilityTheory Filter open scoped ENNReal NNReal ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeExponentialMoment.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeExponentialMoment.lean index e831aeaead..4a98af30c9 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeExponentialMoment.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeExponentialMoment.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Kernel + /-! # A positive exponential moment for the exit time @@ -41,6 +44,8 @@ Every statement is an inequality of `ℝ≥0∞`-valued integrals; no integrabil no real-valued restatement appears. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeLaplace.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeLaplace.lean index deeb08cf3b..f6f4f531d4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeLaplace.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExitTimeLaplace.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw +module + +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitLaw + /-! # The Laplace transform of an exit time @@ -21,6 +24,8 @@ Main results: `IsConservative.lintegral_exp_neg_exitTime` and No moment bound or almost-sure finiteness of the exit time is asserted. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExpectedExitTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExpectedExitTime.lean index f8f9016529..1b1752ef2c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExpectedExitTime.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ExpectedExitTime.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.ExitTimeShift +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop + /-! # The expected exit time, untruncated @@ -25,6 +28,8 @@ It also records that the truncated exit time of `Path/ExitTime.lean` is the gene `ContinuousPath.iSup_exitTimeTrunc : ⨆ n, exitTimeTrunc U n ω = exitTime U ω`. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory Filter open scoped ENNReal NNReal ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerConditional.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerConditional.lean index 0d49cdbbbf..63de9f1cf3 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerConditional.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerConditional.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart + /-! # Deterministic-time conditional expectation for the Feller trajectory @@ -19,6 +22,8 @@ The time here is deterministic. The corresponding statement at a finite stoppin `Trajectory/StoppingLtTop.lean`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerCountableStoppingRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerCountableStoppingRestart.lean index f38ac17d86..19e589dbd4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerCountableStoppingRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerCountableStoppingRestart.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestart + /-! # Conditional restart of the Feller trajectory at countable-range stopping times @@ -20,6 +23,8 @@ The stopping time here has countable range. An arbitrary finite stopping time i `Trajectory/StoppingLtTop.lean`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerFiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerFiniteMarginals.lean index e2da7f9782..51e06a8a93 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerFiniteMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerFiniteMarginals.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteDenseApproximationContinuity + /-! # Arbitrary-time finite marginals of Feller trajectories @@ -17,6 +20,8 @@ The theorem is stated for an arbitrary such semigroup; no particular semigroup i and no Hunt-process property is asserted. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerRestrictedRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerRestrictedRestart.lean index 0a62775a9a..d09e7ace47 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerRestrictedRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerRestrictedRestart.lean @@ -3,13 +3,16 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional -import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove -import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence -import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification -import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.RationalConditional +public import LeanPool.MarkovProcess.MarkovProcess.Time.DenseTimeApproximationFromAbove +public import LeanPool.MarkovProcess.MarkovProcess.Path.ShiftCompactTestConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Feller.DensePhysicalFiniteSetContinuity +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.MeasureFiniteRestrictionIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Path.MeasureIdentification + /-! @@ -24,6 +27,8 @@ The time here is deterministic. The strong Markov property at a finite stopping `Trajectory/FellerStoppingRestart.lean`. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerShift.lean index 83c56597c4..4004e8c57b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerShift.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift -import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerFiniteMarginals +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteSetKernelShift +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification + /-! # Deterministic shifts of Feller trajectory laws @@ -21,6 +24,8 @@ This is an unconditional kernel-law identity. The conditional form is in `Trajectory/FellerStoppingRestart.lean`; no Hunt-process property is asserted. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingConditional.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingConditional.lean index 94e7195b1c..eabcdbde74 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingConditional.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingConditional.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart -import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerStoppingRestart +public import LeanPool.MarkovProcess.MarkovProcess.Path.StoppedValueMeasurability + /-! # Conditional expectation of the Feller trajectory at finite stopping times @@ -21,6 +24,8 @@ infinite is covered, on the event where it is finite, in `Trajectory/StoppingLtT Hunt-process property is asserted. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingRestart.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingRestart.lean index dcad8688e1..fcda179460 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingRestart.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FellerStoppingRestart.lean @@ -3,12 +3,15 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure -import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence -import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral -import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FellerRestrictedRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.CountableStoppingRestartMeasure +public import LeanPool.MarkovProcess.MarkovProcess.Path.RandomTimeCompactTestConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Path.DenseRestrictionIntegral +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionIntegral +public import LeanPool.MarkovProcess.MarkovProcess.Path.StoppingTimeDyadicCeiling + /-! # Event-restricted restart of the Feller trajectory at finite stopping times @@ -25,6 +28,8 @@ infinite is covered, on the event where it is finite, in `Trajectory/StoppingLtT Hunt-process property is asserted. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKac.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKac.lean index 0ae5979d07..127a1baa98 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKac.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKac.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PenalizationDomination + /-! # Feynman--Kac semigroups and resolvents diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacFunctional.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacFunctional.lean index b0e730215a..1b8ddc6766 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacFunctional.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacFunctional.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale +module + +public import LeanPool.MarkovProcess.MarkovProcess.Analysis.ExpPrimitive +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Operator +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinMartingale + /-! # Feynman--Kac functionals and semigroups @@ -26,6 +29,8 @@ Main results: `feynmanKacAdditiveFunctional`, The resolvent and perturbation identities are developed in `Trajectory/FeynmanKacResolvent.lean`. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacRealResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacRealResolvent.lean index bf26fec601..000a745af1 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacRealResolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacRealResolvent.lean @@ -3,12 +3,15 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent -import Mathlib.Analysis.Calculus.Deriv.Mul -import Mathlib.Analysis.SpecialFunctions.ExpDeriv -import Mathlib.MeasureTheory.Integral.IntervalIntegral.FundThmCalculus +module + +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.ResolventUniqueness +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacResolvent +public import Mathlib.Analysis.Calculus.Deriv.Mul +public import Mathlib.Analysis.SpecialFunctions.ExpDeriv +public import Mathlib.MeasureTheory.Integral.IntervalIntegral.FundThmCalculus + /-! # Real Feynman--Kac resolvents @@ -26,6 +29,8 @@ Feynman--Kac resolvent among bounded measurable resolvent families solving the s equation at all sufficiently large shifts. No model-specific realization is assumed. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacResolvent.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacResolvent.lean index 549601fd24..05d73ec576 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacResolvent.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FeynmanKacResolvent.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import Mathlib.Analysis.SpecialFunctions.ImproperIntegrals -import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition +module + +public import Mathlib.Analysis.SpecialFunctions.ImproperIntegrals +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Killed.Resolvent +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacFunctional +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ResolventExitDecomposition + /-! # Feynman--Kac resolvents @@ -26,6 +29,8 @@ Main results: `IsConservative.feynmanKacResolvent`, No uniqueness statement for the associated resolvent equation is asserted. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FiniteMarginals.lean index d97d84b475..1e9cde23cd 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FiniteMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/FiniteMarginals.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Basic + /-! # Finite rational-time marginals of continuous-path trajectories @@ -16,6 +19,8 @@ No assertion is made at irrational times or about a Markov, strong Markov, or Hu the continuous-path law. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/HarmonicRepresentation.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/HarmonicRepresentation.lean index 000f0ddb95..d1d07d7bc8 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/HarmonicRepresentation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/HarmonicRepresentation.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DynkinStopping +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExpectedExitTime + /-! # Harmonic and Poisson representations, and the localized Dynkin formula @@ -27,6 +30,8 @@ The integrand of Dynkin's formula is only ever evaluated strictly before the exi path is inside `U`; this is the observation behind all three statements. -/ +@[expose] public section + open MeasureTheory ProbabilityTheory Filter open scoped ENNReal NNReal ZeroAtInfty diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathModulus.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathModulus.lean index 8dc0a4909c..6262234364 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathModulus.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathModulus.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus -import LeanPool.MarkovProcess.MarkovProcess.Main -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathModulus +public import LeanPool.MarkovProcess.MarkovProcess.Main +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.AllTimeMarginals + /-! # The continuous-path process as a Kolmogorov process, and its uniform modulus @@ -34,6 +37,8 @@ Main results: No tightness, weak continuity, or Hölder-path statement is proved here. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathTightness.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathTightness.lean index b365e6c220..3e44527735 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathTightness.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PathTightness.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus +module + +public import LeanPool.MarkovProcess.MarkovProcess.Continuity.PathTightness +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathModulus + /-! # Tightness of the path laws of a continuous-path Markov process @@ -37,6 +40,8 @@ No compactness theorem for measures (Prokhorov's theorem) is proved or used, and convergence statement is made here. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PenalizationDomination.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PenalizationDomination.lean index d5bc80fa31..f5a69bb5b5 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PenalizationDomination.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/PenalizationDomination.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.FeynmanKacRealResolvent + /-! # Penalization domination for killed resolvents @@ -17,6 +20,8 @@ Polish space. Main result: `IsFellerKernelSemigroup.killedResolvent_le_of_perturbed_resolventFamily`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalConditional.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalConditional.lean index 6dbe9bbf5d..6363a63cd2 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalConditional.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalConditional.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart -import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov +module + +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.RationalRestrictedRestart +public import LeanPool.MarkovProcess.MarkovProcess.Restart.ConditionalMarkov + /-! # Rational-time conditional Markov identities for the continuous trajectory @@ -20,6 +23,8 @@ The times here are rational. The strong Markov property at an arbitrary finite is in `Trajectory/FellerStoppingRestart.lean`. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalShift.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalShift.lean index f704c77127..2a0212401c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalShift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/RationalShift.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift -import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift -import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification +module + +public import LeanPool.MarkovProcess.MarkovProcess.Path.KernelIdentification +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.DenseRestrictionMarginals +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteShift +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.FiniteRestrictionIdentification + /-! # Rational-time shifts of continuous trajectory laws @@ -18,6 +21,8 @@ uniqueness on the dense product path space and injectivity of dense restriction. unconditional law identity; conditional and strong Markov statements require additional work. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ResolventExitDecomposition.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ResolventExitDecomposition.lean index 23adc3a54c..0a69590b8a 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ResolventExitDecomposition.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/ResolventExitDecomposition.lean @@ -3,8 +3,11 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.ExitTimeLaplace +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StoppingLtTop + /-! # Resolvent decomposition at an exit time @@ -23,6 +26,8 @@ Main definitions and results: `ContinuousPath.pathResolvent`, No integrability or almost-sure finiteness of the exit time is asserted. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Set diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StartingPointContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StartingPointContinuity.lean index 43e9f0a243..f616db5f2e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StartingPointContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StartingPointContinuity.lean @@ -3,12 +3,15 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity -import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence -import LeanPool.MarkovProcess.MarkovProcess.Main -import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties -import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction -import Mathlib.MeasureTheory.Measure.Tight +module + +public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteSetCompactTestContinuity +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.WeakConvergence +public import LeanPool.MarkovProcess.MarkovProcess.Main +public import LeanPool.MarkovProcess.MarkovProcess.Parameterized.ContinuousProcessProperties +public import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction +public import Mathlib.MeasureTheory.Measure.Tight + /-! # Measurable and continuous dependence on the starting point @@ -40,6 +43,8 @@ space; that needs tightness on path space itself, which is not proved here. No a stopping time that can be infinite. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean index accc52e46d..ca004df470 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/StoppingLtTop.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Main +module + +public import LeanPool.MarkovProcess.MarkovProcess.Main + /-! # The strong Markov property at a stopping time that may be infinite @@ -34,6 +37,8 @@ Nothing is asserted about the event `{tau = ⊤}`: on it the shifted path is the neither statement constrains it. No Hunt-process property is claimed. -/ +@[expose] public section + noncomputable section PortComputability open MeasureTheory ProbabilityTheory diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakContinuity.lean index 231fcd129b..d4d50912c1 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakContinuity.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity -import Mathlib.MeasureTheory.Measure.ProbabilityMeasure +module + +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.CylinderAlgebra +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.PathTightness +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.StartingPointContinuity +public import Mathlib.MeasureTheory.Measure.ProbabilityMeasure + /-! # Weak continuity of the path law in the starting point @@ -38,6 +41,8 @@ Nothing here asserts relative compactness of a family of laws, and no convergenc of semigroups is treated. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakConvergence.lean index ba6eab7201..5d95f393b0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/WeakConvergence.lean @@ -3,9 +3,12 @@ Copyright (c) 2026 Scott Armstrong. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Armstrong -/ -import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence -import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity +module + +public import LeanPool.MarkovProcess.MarkovProcess.Semigroup.TrotterKato +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.Convergence +public import LeanPool.MarkovProcess.MarkovProcess.Trajectory.WeakContinuity + /-! # Weak convergence of Feller processes on path space @@ -40,6 +43,8 @@ when the constants are allowed to vary, nor for a family whose limit is not itse a Feller semigroup. -/ +@[expose] public section + noncomputable section PortComputability open Filter MeasureTheory ProbabilityTheory Topology From 5c38e7be7af67592b763dcfa0b074a7a1754336e Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 25 Sep 2026 18:52:06 +0000 Subject: [PATCH 06/11] Remove unsupported comparator certification from MarkovProcess summary --- LeanPool/projects.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/LeanPool/projects.yml b/LeanPool/projects.yml index b0b12095b3..0111484aec 100644 --- a/LeanPool/projects.yml +++ b/LeanPool/projects.yml @@ -10116,8 +10116,7 @@ projects: displacement-moment bound yields a unique measurable kernel from each starting point to continuous-path space, with the prescribed finite-dimensional distributions. The library also develops strong Markov properties, generators and resolvents, stopping and killing, - and Brownian motion as an example. The existence and uniqueness theorem is independently - checked using Audit/ContinuousMarkovProcess/comparator.json. + and Brownian motion as an example. branch: probability entry_module: LeanPool.MarkovProcess authors: From e602b4a5c8702996a919fe98830907c844db5ffa Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 25 Sep 2026 19:24:20 +0000 Subject: [PATCH 07/11] Restore downstream Markov instances and module-visible data --- .../MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean | 2 +- LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean | 3 ++- .../MarkovProcess/Parameterized/OrderedGrid.lean | 3 ++- .../MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean | 2 +- LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean | 3 ++- .../MarkovProcess/Semigroup/YosidaApproximation.lean | 2 +- .../MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean | 4 ++-- 7 files changed, 11 insertions(+), 8 deletions(-) diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean index f51f0f688e..cae49e933e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PrefixKernel.lean @@ -51,7 +51,7 @@ private theorem denseTime_mem_physicalPrefix (e : ℕ ≃ D) (ι : D ↪ NNReal) /-- Reindex a path on the physical prefix by its enumeration positions. -/ def denseTimePrefixReindex (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) (path : denseTimePhysicalPrefix e ι n → α) : Fin n → α := - fun i ↦ path ⟨ι (e i), denseTime_mem_physicalPrefix e ι n i⟩ + fun i ↦ path ⟨ι (e i), by exact denseTime_mem_physicalPrefix e ι n i⟩ /-- Reindexing a physical-prefix path by enumeration positions is measurable. -/ theorem measurable_denseTimePrefixReindex (e : ℕ ≃ D) (ι : D ↪ NNReal) (n : ℕ) : diff --git a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean index 842c2bf15c..ba30b8b7c0 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Lifetime/Filtration.lean @@ -69,7 +69,8 @@ theorem measurable_shift_canonicalFiltration (S t : NNReal) : exact coordinate_shift S u omega rw [hfun] exact le_iSup_of_le - (⟨S + u, by exact add_le_add_left u.property S⟩ : + (⟨S + u, by + exact add_le_add (le_refl S) (show (u : NNReal) ≤ t from u.property)⟩ : Set.Iic (S + t)) le_rfl /-- The lifetime is a stopping time for the raw canonical filtration. -/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/OrderedGrid.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/OrderedGrid.lean index f734d35d6c..c01451c043 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/OrderedGrid.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/OrderedGrid.lean @@ -35,7 +35,8 @@ variable {Theta alpha : Type*} [MeasurableSpace Theta] [MeasurableSpace alpha] variable (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) -private def lastIndex (n : ℕ) : Finset.Iic n := +/-- The final coordinate in the finite history through step `n`. -/ +def lastIndex (n : ℕ) : Finset.Iic n := ⟨n, Finset.mem_Iic.mpr le_rfl⟩ /-- The jointly measurable transition kernel at one fixed time increment. -/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean index 69ef336fcb..84b067929c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/ClosedSetDetection.lean @@ -27,7 +27,7 @@ namespace ContinuousPath variable {alpha : Type*} [PseudoMetricSpace alpha] /-- The positive thresholds used to detect zero distance to a closed set. -/ -private def detectionThreshold (n : ℕ) : ℝ := 1 / (n + 1 : ℝ) +def detectionThreshold (n : ℕ) : ℝ := 1 / (n + 1 : ℝ) private theorem detectionThreshold_pos (n : ℕ) : 0 < detectionThreshold n := by exact one_div_pos.mpr (Nat.cast_add_one_pos n) diff --git a/LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean b/LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean index 2113c03e15..a179fb8312 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Path/Shift.lean @@ -92,7 +92,8 @@ theorem measurable_shift_canonicalFiltration [MeasurableSpace alpha] [BorelSpace exact shift_apply S u omega rw [hfun] exact le_iSup_of_le - (⟨S + u.1, by exact add_le_add_left u.2 S⟩ : + (⟨S + u.1, by + exact add_le_add (le_refl S) (show (u : NNReal) ≤ t from u.property)⟩ : Set.Iic (S + t)) le_rfl end ContinuousPath diff --git a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean index 447272eceb..2e483fac44 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Semigroup/YosidaApproximation.lean @@ -59,7 +59,7 @@ section CompleteSpace variable [CompleteSpace E] -private instance : NormedAlgebra ℚ (E →L[ℝ] E) := +instance normedAlgebraRatEnd : NormedAlgebra ℚ (E →L[ℝ] E) := NormedAlgebra.restrictScalars ℚ ℝ (E →L[ℝ] E) /-- The exponential of the bounded Yosida generator at nonnegative time. -/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean b/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean index 56a04de2a8..db03eb4af4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Time/CountableDenseTime.lean @@ -136,10 +136,10 @@ theorem exists_cast_btwn {a b : NNReal} (hab : a < b) : · rw [hcoe, hcast] exact hqb -private instance : Infinite DenseTime := +instance : Infinite DenseTime := Infinite.of_injective (fun n : ℕ ↦ (n : DenseTime)) Nat.cast_injective -private instance : Countable DenseTime where +instance : Countable DenseTime where exists_injective_nat' := ⟨fun q ↦ Encodable.encode (q : ℚ), fun _ _ h ↦ NNRat.ext (Encodable.encode_injective h)⟩ From 159720caed34f9e9a74863891dac50c1e81449df Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 25 Sep 2026 19:44:34 +0000 Subject: [PATCH 08/11] Expose data used by Markov trajectory and operator constructions --- .../Kernel/OnePointExtension.lean | 3 ++- .../Parameterized/DenseTimeTrajectory.lean | 26 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean index 37a50ac447..cbc072aa9b 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean @@ -303,7 +303,8 @@ private theorem norm_onePointSemigroupAction_le (t : NNReal) (g : C₀(OnePoint (g.toBCF.norm_coe_le_norm OnePoint.infty) (sub_nonneg.mpr hmass1) _ = ‖g‖ := by ring -private noncomputable def onePointSemigroupLinearMap (t : NNReal) : +/-- The compactified semigroup action, bundled as a linear map. -/ +noncomputable def onePointSemigroupLinearMap (t : NNReal) : C₀(OnePoint X, ℝ) →ₗ[ℝ] C₀(OnePoint X, ℝ) where toFun := R.onePointSemigroupAction t map_add' g h := by diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean index 8edc00221f..95c5f295b4 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/DenseTimeTrajectory.lean @@ -28,11 +28,12 @@ universe uTheta uAlpha variable {Theta : Type uTheta} {D : Type*} {alpha : Type uAlpha} [MeasurableSpace Theta] [MeasurableSpace alpha] [StandardBorelSpace alpha] [Nonempty alpha] -private def trajectoryCoordinate : ℕ → Type (max uTheta uAlpha) +/-- The initial parameter and state at zero, followed by lifted state observations. -/ +def trajectoryCoordinate : ℕ → Type (max uTheta uAlpha) | 0 => ULift.{max uTheta uAlpha} (Theta × alpha) | _ + 1 => ULift.{max uTheta uAlpha} alpha -private instance instMeasurableSpaceTrajectoryCoordinate (n : ℕ) : MeasurableSpace +instance instMeasurableSpaceTrajectoryCoordinate (n : ℕ) : MeasurableSpace (trajectoryCoordinate (Theta := Theta) (alpha := alpha) n) := match n with | 0 => (inferInstance : MeasurableSpace (ULift.{max uTheta uAlpha} (Theta × alpha))) @@ -46,20 +47,22 @@ private theorem measurable_down_trajectoryCoordinate : Measurable (ULift.down : ULift.{max uTheta uAlpha} alpha → alpha) := by simpa only [trajectoryCoordinate] using! measurable_down -private def historyInitial (n : ℕ) +/-- Extract the immutable parameter and initial state from an augmented history. -/ +def historyInitial (n : ℕ) (path : (i : ↑(Finset.Iic n)) → trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) : ULift.{max uTheta uAlpha} (Theta × alpha) := path ⟨0, Finset.mem_Iic.mpr (Nat.zero_le n)⟩ -private def historyObservation (n : ℕ) +/-- Extract one observed state from an augmented finite history. -/ +def historyObservation (n : ℕ) (path : (i : ↑(Finset.Iic n)) → trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) (i : Fin n) : ULift.{max uTheta uAlpha} alpha := path ⟨i + 1, Finset.mem_Iic.mpr i.isLt⟩ /-- An augmented history is exactly the immutable data and its observed prefix. -/ -private def historyEquiv (n : ℕ) : +def historyEquiv (n : ℕ) : ((i : ↑(Finset.Iic n)) → trajectoryCoordinate (Theta := Theta) (alpha := alpha) i) ≃ᵐ ((Theta × alpha) × (Fin n → alpha)) where toFun path := @@ -116,7 +119,8 @@ private theorem historyEquiv_snd_apply (n : ℕ) (path) (i : Fin n) : attribute [irreducible] historyEquiv -private def parameterizedTrajStep +/-- The next conditional observation kernel, transported to augmented histories. -/ +def parameterizedTrajStep (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) (e : ℕ ≃ D) (iota : D ↪ NNReal) (n : ℕ) : @@ -126,7 +130,7 @@ private def parameterizedTrajStep (γ := trajectoryCoordinate (Theta := Theta) (alpha := alpha) (n + 1)) ULift.up).comap (historyEquiv n) (historyEquiv n).measurable -private instance isMarkovKernel_parameterizedTrajStep +instance isMarkovKernel_parameterizedTrajStep (P : ParameterizedSubMarkovKernelSemigroup Theta alpha) (hP : ∀ theta, (P.toSubMarkovKernelSemigroup theta).IsConservative) (e : ℕ ≃ D) (iota : D ↪ NNReal) (n : ℕ) : @@ -139,7 +143,8 @@ private instance isMarkovKernel_parameterizedTrajStep (by simpa only [trajectoryCoordinate] using! measurable_up) exact Kernel.IsMarkovKernel.comap _ (historyEquiv n).measurable -private def initialHistory (q : Theta × alpha) : +/-- The augmented history containing only the initial parameter and state. -/ +def initialHistory (q : Theta × alpha) : (i : ↑(Finset.Iic 0)) → trajectoryCoordinate (Theta := Theta) (alpha := alpha) i := fun i ↦ by rcases i with ⟨_ | k, hi⟩ @@ -158,7 +163,8 @@ private theorem measurable_initialHistory : · simp only [Finset.mem_Iic] at hi omega -private def eraseAugmentation (e : ℕ ≃ D) +/-- Remove the immutable coordinate and reindex observations by the dense-time labels. -/ +def eraseAugmentation (e : ℕ ≃ D) (path : (n : ℕ) → trajectoryCoordinate (Theta := Theta) (alpha := alpha) n) : D → alpha := fun d ↦ (path (e.symm d + 1)).down @@ -491,7 +497,7 @@ def parameterizedDenseTimeTrajectory (e : ℕ ≃ D) (iota : D ↪ NNReal) : Kernel (Theta × alpha) (D → alpha) := ((Kernel.traj (X := trajectoryCoordinate (Theta := Theta) (alpha := alpha)) (parameterizedTrajStep P hP e iota) 0).comap initialHistory - measurable_initialHistory).map (eraseAugmentation e) + (by exact measurable_initialHistory)).map (eraseAugmentation e) /-- The parameterized dense-time trajectory kernel is Markov. -/ theorem isMarkovKernel_parameterizedDenseTimeTrajectory From 93e6b5c8133d3ac9b23aed885a779ea731e2d3df Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 25 Sep 2026 20:39:47 +0000 Subject: [PATCH 09/11] Share Markov kernel and finite-product integration lemmas --- LeanPool.lean | 1 + .../PhysicalCompactTestTransport.lean | 56 +------ .../CoordinatePolynomialContinuity.lean | 59 +------- .../FiniteTimeCompactTestContinuity.lean | 111 +------------- .../Feller/FiniteTimeConvergence.lean | 59 +------- .../FiniteTimeJointCompactTestContinuity.lean | 119 +-------------- .../CoordinatePolynomialMeasure.lean | 143 ++++++++++++++++++ .../FiniteSetKernelCompactTestTransport.lean | 58 +------ .../FiniteTime/KernelConcatenation.lean | 49 +----- .../FiniteTime/KernelDeletion.lean | 21 +-- .../MarkovProcess/Kernel/Lp.lean | 6 +- .../Kernel/OperatorSemigroup.lean | 37 ----- 12 files changed, 165 insertions(+), 554 deletions(-) create mode 100644 LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinatePolynomialMeasure.lean diff --git a/LeanPool.lean b/LeanPool.lean index 423cd6bb5d..fb186c44e4 100644 --- a/LeanPool.lean +++ b/LeanPool.lean @@ -4496,6 +4496,7 @@ public import LeanPool.MarkovProcess.MarkovProcess.Feller.FiniteTimeKernelContin public import LeanPool.MarkovProcess.MarkovProcess.Feller.Resolvent public import LeanPool.MarkovProcess.MarkovProcess.Feller.Semigroup public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinatePolynomialMeasure public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductNormalization public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.DenseTimeFiniteSetKernelShift diff --git a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean index 3928f39498..ced5bb65e7 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/DenseTime/PhysicalCompactTestTransport.lean @@ -5,6 +5,7 @@ Authors: Scott Armstrong -/ module +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinatePolynomialMeasure public import LeanPool.MarkovProcess.MarkovProcess.DenseTime.PhysicalReindex public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm public import Mathlib.MeasureTheory.Integral.CompactlySupported @@ -27,61 +28,6 @@ namespace MarkovProcess.DenseTimePath open SubMarkovKernelSemigroup -private theorem stronglyMeasurable_coordinatePolynomial - {I alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] - (terms : List (PiContinuousMap.CoordinateProductTerm I alpha)) : - StronglyMeasurable (PiContinuousMap.coordinatePolynomial terms) := by - induction terms with - | nil => - simp only [PiContinuousMap.coordinatePolynomial_nil] - exact stronglyMeasurable_const - | cons term terms ih => - rw [PiContinuousMap.coordinatePolynomial_cons] - apply StronglyMeasurable.add _ ih - have hprod : StronglyMeasurable (fun path : I → alpha ↦ - (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by - induction term.factors with - | nil => exact stronglyMeasurable_const - | cons p factors ihFactors => - simp only [List.map_cons, List.prod_cons] - exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul - ihFactors - rw [show (term.toContinuousMap : (I → alpha) → ℝ) = fun path ↦ - term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by - funext path - exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] - exact hprod.const_mul term.coefficient - -private theorem stronglyMeasurable_compactlySupported_pi - {I alpha : Type*} [Finite I] [TopologicalSpace alpha] [MeasurableSpace alpha] - [BorelSpace alpha] [T3Space alpha] [LocallyCompactSpace alpha] - (f : C_c(I → alpha, ℝ)) : StronglyMeasurable f := by - classical - let := Fintype.ofFinite I - have hexists (m : ℕ) : - ∃ terms : List (PiContinuousMap.CoordinateProductTerm I alpha), - ∀ x, ‖PiContinuousMap.coordinatePolynomial terms x - f x‖ < - 1 / ((m : ℝ) + 1) := by - have hpositive : 0 < 1 / ((m : ℝ) + 1) := by positivity - obtain ⟨terms, hterms⟩ := - PiContinuousMap.exists_coordinateProductTerms_near_compactlySupported f hpositive - exact ⟨terms, fun x ↦ by - rw [PiContinuousMap.coordinatePolynomial_apply] - exact hterms x⟩ - choose terms hterms using hexists - apply stronglyMeasurable_of_tendsto Filter.atTop - (fun m ↦ stronglyMeasurable_coordinatePolynomial (terms m)) - rw [tendsto_pi_nhds] - intro x - rw [Metric.tendsto_nhds] - intro epsilon hepsilon - have hscalar : Filter.Tendsto (fun m : ℕ ↦ (1 : ℝ) / ((m : ℝ) + 1)) Filter.atTop - (nhds 0) := tendsto_one_div_add_atTop_nhds_zero_nat - rw [Metric.tendsto_nhds] at hscalar - filter_upwards [hscalar epsilon hepsilon] with m hm - rw [Real.dist_eq, sub_zero, abs_of_pos (by positivity)] at hm - exact (hterms m x).trans_le hm.le - /-- Reindexing finite paths from physical rational times to dense-time labels is a homeomorphism. -/ noncomputable def pullbackPhysicalSetHomeomorph diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean index 59099e672f..d008b793f1 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/CoordinatePolynomialContinuity.lean @@ -5,6 +5,7 @@ Authors: Scott Armstrong -/ module +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinatePolynomialMeasure public import LeanPool.MarkovProcess.MarkovProcess.Feller.CoordinateProductContinuity @@ -29,64 +30,6 @@ namespace MarkovProcess.SubMarkovKernelSemigroup variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] -omit [LocallyCompactSpace alpha] [T2Space alpha] in -private theorem integrable_coordinateProductTerm - {n : ℕ} (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) - (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : - Integrable term.toContinuousMap mu := by - have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ - (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by - induction term.factors with - | nil => exact stronglyMeasurable_const - | cons p factors ih => - simp only [List.map_cons, List.prod_cons] - exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul ih - have hfun : (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ - term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod := by - funext path - exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path - rw [hfun] - refine Integrable.of_bound (hprod.const_mul term.coefficient).aestronglyMeasurable - (‖term.coefficient‖ * (term.factors.map fun p ↦ ‖p.2‖).prod) ?_ - filter_upwards [] with path - rw [norm_mul, List.norm_prod] - apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) - induction term.factors with - | nil => - simp only [List.map_nil, List.prod_nil] - exact le_rfl - | cons p factors ih => - simp only [List.map_cons, List.prod_cons] - have all_nonneg : ∀ fs : List (Fin n × C₀(alpha, ℝ)), - 0 ≤ (fs.map fun q ↦ ‖q.2 (path q.1)‖).prod := by - intro fs - induction fs with - | nil => simp only [List.map_nil, List.prod_nil, zero_le_one] - | cons q fs ih_nonneg => - simp only [List.map_cons, List.prod_cons] - exact mul_nonneg (norm_nonneg _) ih_nonneg - have hnonneg : 0 ≤ - ((factors.map fun p ↦ p.2 (path p.1)).map norm).prod := by - simpa only [List.map_map, Function.comp_apply] using! all_nonneg factors - exact mul_le_mul (p.2.toBCF.norm_coe_le_norm (path p.1)) ih - hnonneg (norm_nonneg _) - -omit [LocallyCompactSpace alpha] [T2Space alpha] in -private theorem integrable_coordinatePolynomial - {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) - (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : - Integrable (PiContinuousMap.coordinatePolynomial terms) mu := by - induction terms with - | nil => - simp only [PiContinuousMap.coordinatePolynomial_nil] - change Integrable (fun _ : Fin n → alpha ↦ (0 : ℝ)) mu - refine Integrable.of_bound stronglyMeasurable_const.aestronglyMeasurable 0 ?_ - exact ae_of_all _ fun _ ↦ by - simpa only [norm_zero] using (le_refl (0 : ℝ)) - | cons term terms ih => - rw [PiContinuousMap.coordinatePolynomial_cons] - exact (integrable_coordinateProductTerm term mu).add ih - omit [LocallyCompactSpace alpha] [T2Space alpha] in /-- Finite-time integrals of an explicit coordinate polynomial vary continuously under coordinatewise convergence of the ordered observation times. -/ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeCompactTestContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeCompactTestContinuity.lean index 25a0c1b13a..6aa9e60439 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeCompactTestContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeCompactTestContinuity.lean @@ -32,115 +32,6 @@ namespace MarkovProcess.SubMarkovKernelSemigroup variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] -omit [LocallyCompactSpace alpha] [T2Space alpha] in -private theorem integrable_coordinateProductTerm - {n : ℕ} (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) - (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : - Integrable term.toContinuousMap mu := by - have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ - (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by - induction term.factors with - | nil => exact stronglyMeasurable_const - | cons p factors ih => - simp only [List.map_cons, List.prod_cons] - exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul ih - rw [show (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ - term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by - funext path - exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] - refine Integrable.of_bound (hprod.const_mul term.coefficient).aestronglyMeasurable - (‖term.coefficient‖ * (term.factors.map fun p ↦ ‖p.2‖).prod) ?_ - filter_upwards [] with path - rw [norm_mul, List.norm_prod] - apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) - induction term.factors with - | nil => - simp only [List.map_nil, List.prod_nil] - exact le_rfl - | cons p factors ih => - simp only [List.map_cons, List.prod_cons] - have all_nonneg : ∀ fs : List (Fin n × C₀(alpha, ℝ)), - 0 ≤ (fs.map fun q ↦ ‖q.2 (path q.1)‖).prod := by - intro fs - induction fs with - | nil => simp only [List.map_nil, List.prod_nil, zero_le_one] - | cons q fs ih_nonneg => - simp only [List.map_cons, List.prod_cons] - exact mul_nonneg (norm_nonneg _) ih_nonneg - have hnonneg : 0 ≤ - ((factors.map fun p ↦ p.2 (path p.1)).map norm).prod := by - simpa only [List.map_map, Function.comp_apply] using! all_nonneg factors - exact mul_le_mul (p.2.toBCF.norm_coe_le_norm (path p.1)) ih - hnonneg (norm_nonneg _) - -omit [LocallyCompactSpace alpha] [T2Space alpha] in -private theorem integrable_coordinatePolynomial - {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) - (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : - Integrable (PiContinuousMap.coordinatePolynomial terms) mu := by - induction terms with - | nil => - simp only [PiContinuousMap.coordinatePolynomial_nil] - change Integrable (fun _ : Fin n → alpha ↦ (0 : ℝ)) mu - refine Integrable.of_bound stronglyMeasurable_const.aestronglyMeasurable 0 ?_ - exact ae_of_all _ fun _ ↦ by - simpa only [norm_zero] using (le_refl (0 : ℝ)) - | cons term terms ih => - rw [PiContinuousMap.coordinatePolynomial_cons] - exact (integrable_coordinateProductTerm term mu).add ih - -omit [LocallyCompactSpace alpha] [T2Space alpha] in -private theorem stronglyMeasurable_coordinatePolynomial - {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) : - StronglyMeasurable (PiContinuousMap.coordinatePolynomial terms) := by - induction terms with - | nil => - simp only [PiContinuousMap.coordinatePolynomial_nil] - exact stronglyMeasurable_const - | cons term terms ih => - rw [PiContinuousMap.coordinatePolynomial_cons] - apply StronglyMeasurable.add _ ih - have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ - (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by - induction term.factors with - | nil => exact stronglyMeasurable_const - | cons p factors ihFactors => - simp only [List.map_cons, List.prod_cons] - exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul - ihFactors - rw [show (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ - term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by - funext path - exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] - exact hprod.const_mul term.coefficient - --- This approximation argument avoids assuming `OpensMeasurableSpace (Fin n → alpha)`. -private theorem stronglyMeasurable_compactlySupported_fin - {n : ℕ} (f : C_c(Fin n → alpha, ℝ)) : StronglyMeasurable f := by - have hexists (m : ℕ) : - ∃ terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha), - ∀ x, ‖PiContinuousMap.coordinatePolynomial terms x - f x‖ < - 1 / ((m : ℝ) + 1) := by - have hpositive : 0 < 1 / ((m : ℝ) + 1) := by positivity - obtain ⟨terms, hterms⟩ := - PiContinuousMap.exists_coordinateProductTerms_near_compactlySupported f hpositive - exact ⟨terms, fun x ↦ by - rw [PiContinuousMap.coordinatePolynomial_apply] - exact hterms x⟩ - choose terms hterms using hexists - apply stronglyMeasurable_of_tendsto atTop - (fun m ↦ stronglyMeasurable_coordinatePolynomial (terms m)) - rw [tendsto_pi_nhds] - intro x - rw [Metric.tendsto_nhds] - intro epsilon hepsilon - have hscalar : Tendsto (fun m : ℕ ↦ (1 : ℝ) / ((m : ℝ) + 1)) atTop (nhds 0) := - tendsto_one_div_add_atTop_nhds_zero_nat - rw [Metric.tendsto_nhds] at hscalar - filter_upwards [hscalar epsilon hepsilon] with m hm - rw [Real.dist_eq, sub_zero, abs_of_pos (by positivity)] at hm - exact (hterms m x).trans_le hm.le - /-- Finite-time integrals of compactly supported continuous tests vary continuously under coordinatewise convergence of the ordered observation times. -/ theorem IsFellerKernelSemigroup.tendsto_integral_compactlySupported_finiteTimeKernel @@ -169,7 +60,7 @@ theorem IsFellerKernelSemigroup.tendsto_integral_compactlySupported_finiteTimeKe (finiteTimeKernel P u x) := by apply Integrable.of_bound (C := epsilon / 3) · exact (stronglyMeasurable_coordinatePolynomial terms).sub - (stronglyMeasurable_compactlySupported_fin f) |>.aestronglyMeasurable + (stronglyMeasurable_compactlySupported_pi f) |>.aestronglyMeasurable · exact ae_of_all _ fun path ↦ (hnear path).le have hp : Integrable polynomial (finiteTimeKernel P u x) := integrable_coordinatePolynomial terms _ diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean index d7e50bdabf..6c83336c69 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeConvergence.lean @@ -5,6 +5,7 @@ Authors: Scott Armstrong -/ module +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinatePolynomialMeasure public import LeanPool.MarkovProcess.MarkovProcess.Feller.BackwardC0Convergence public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinateProductActiveReduction public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm @@ -72,64 +73,6 @@ variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] [LocallyCompactSpace alpha] [T2Space alpha] variable {iota : Type*} {l : Filter iota} -section Integrability - -omit [LocallyCompactSpace alpha] [T2Space alpha] in -private theorem integrable_coordinateProductTerm - {n : ℕ} (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) - (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : - Integrable term.toContinuousMap mu := by - have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ - (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by - induction term.factors with - | nil => exact stronglyMeasurable_const - | cons p factors ih => - simp only [List.map_cons, List.prod_cons] - exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul ih - have hfun : (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ - term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod := by - funext path - exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path - rw [hfun] - refine Integrable.of_bound (hprod.const_mul term.coefficient).aestronglyMeasurable - (‖term.coefficient‖ * (term.factors.map fun p ↦ ‖p.2‖).prod) ?_ - filter_upwards [] with path - rw [norm_mul, List.norm_prod] - apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) - induction term.factors with - | nil => - simp only [List.map_nil, List.prod_nil] - exact le_rfl - | cons p factors ih => - simp only [List.map_cons, List.prod_cons] - have all_nonneg : ∀ fs : List (Fin n × C₀(alpha, ℝ)), - 0 ≤ (fs.map fun q ↦ ‖q.2 (path q.1)‖).prod := by - intro fs - induction fs with - | nil => simp only [List.map_nil, List.prod_nil, zero_le_one] - | cons q fs ih_nonneg => - simp only [List.map_cons, List.prod_cons] - exact mul_nonneg (norm_nonneg _) ih_nonneg - have hnonneg : 0 ≤ ((factors.map fun p ↦ p.2 (path p.1)).map norm).prod := by - simpa only [List.map_map, Function.comp_apply] using! all_nonneg factors - exact mul_le_mul (p.2.toBCF.norm_coe_le_norm (path p.1)) ih hnonneg (norm_nonneg _) - -omit [LocallyCompactSpace alpha] [T2Space alpha] in -private theorem integrable_coordinatePolynomial - {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) - (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : - Integrable (PiContinuousMap.coordinatePolynomial terms) mu := by - induction terms with - | nil => - simp only [PiContinuousMap.coordinatePolynomial_nil] - change Integrable (fun _ : Fin n → alpha ↦ (0 : ℝ)) mu - exact integrable_zero _ _ _ - | cons term terms ih => - rw [PiContinuousMap.coordinatePolynomial_cons] - exact (integrable_coordinateProductTerm term mu).add ih - -end Integrability - section ActiveReduction /-- The increasing enumeration of the active coordinates of a coordinate-product term, read at a diff --git a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean index 89f257285d..64e820b137 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Feller/FiniteTimeJointCompactTestContinuity.lean @@ -57,115 +57,6 @@ private theorem tendsto_c0_apply_of_tendsto _ < epsilon / 2 + epsilon / 2 := add_lt_add ha hxa _ = epsilon := add_halves epsilon -omit [LocallyCompactSpace alpha] [T2Space alpha] in -private theorem integrable_coordinateProductTerm_joint - {n : ℕ} (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) - (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : - Integrable term.toContinuousMap mu := by - have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ - (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by - induction term.factors with - | nil => exact stronglyMeasurable_const - | cons p factors ih => - simp only [List.map_cons, List.prod_cons] - exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul ih - rw [show (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ - term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by - funext path - exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] - refine Integrable.of_bound (hprod.const_mul term.coefficient).aestronglyMeasurable - (‖term.coefficient‖ * (term.factors.map fun p ↦ ‖p.2‖).prod) ?_ - filter_upwards [] with path - rw [norm_mul, List.norm_prod] - apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) - induction term.factors with - | nil => - simp only [List.map_nil, List.prod_nil] - exact le_rfl - | cons p factors ih => - simp only [List.map_cons, List.prod_cons] - have all_nonneg : ∀ fs : List (Fin n × C₀(alpha, ℝ)), - 0 ≤ (fs.map fun q ↦ ‖q.2 (path q.1)‖).prod := by - intro fs - induction fs with - | nil => simp only [List.map_nil, List.prod_nil, zero_le_one] - | cons q fs ihFactors => - simp only [List.map_cons, List.prod_cons] - exact mul_nonneg (norm_nonneg _) ihFactors - have hnonneg : 0 ≤ - ((factors.map fun p ↦ p.2 (path p.1)).map norm).prod := by - simpa only [List.map_map, Function.comp_apply] using! all_nonneg factors - apply mul_le_mul (p.2.toBCF.norm_coe_le_norm (path p.1)) ih - · exact hnonneg - · exact norm_nonneg _ - -omit [LocallyCompactSpace alpha] [T2Space alpha] in -private theorem integrable_coordinatePolynomial_joint - {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) - (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : - Integrable (PiContinuousMap.coordinatePolynomial terms) mu := by - induction terms with - | nil => - simp only [PiContinuousMap.coordinatePolynomial_nil] - change Integrable (fun _ : Fin n → alpha ↦ (0 : ℝ)) mu - refine Integrable.of_bound stronglyMeasurable_const.aestronglyMeasurable 0 ?_ - exact ae_of_all _ fun _ ↦ by - simpa only [norm_zero] using (le_refl (0 : ℝ)) - | cons term terms ih => - rw [PiContinuousMap.coordinatePolynomial_cons] - exact (integrable_coordinateProductTerm_joint term mu).add ih - -omit [LocallyCompactSpace alpha] [T2Space alpha] in -private theorem stronglyMeasurable_coordinatePolynomial_joint - {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) : - StronglyMeasurable (PiContinuousMap.coordinatePolynomial terms) := by - induction terms with - | nil => - simp only [PiContinuousMap.coordinatePolynomial_nil] - exact stronglyMeasurable_const - | cons term terms ih => - rw [PiContinuousMap.coordinatePolynomial_cons] - apply StronglyMeasurable.add _ ih - have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ - (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by - induction term.factors with - | nil => exact stronglyMeasurable_const - | cons p factors ihFactors => - simp only [List.map_cons, List.prod_cons] - exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul - ihFactors - rw [show (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ - term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by - funext path - exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] - exact hprod.const_mul term.coefficient - -private theorem stronglyMeasurable_compactlySupported_fin_joint - {n : ℕ} (f : C_c(Fin n → alpha, ℝ)) : StronglyMeasurable f := by - have hexists (m : ℕ) : - ∃ terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha), - ∀ x, ‖PiContinuousMap.coordinatePolynomial terms x - f x‖ < - 1 / ((m : ℝ) + 1) := by - have hpositive : 0 < 1 / ((m : ℝ) + 1) := by positivity - obtain ⟨terms, hterms⟩ := - PiContinuousMap.exists_coordinateProductTerms_near_compactlySupported f hpositive - exact ⟨terms, fun x ↦ by - rw [PiContinuousMap.coordinatePolynomial_apply] - exact hterms x⟩ - choose terms hterms using hexists - apply stronglyMeasurable_of_tendsto atTop - (fun m ↦ stronglyMeasurable_coordinatePolynomial_joint (terms m)) - rw [tendsto_pi_nhds] - intro x - rw [Metric.tendsto_nhds] - intro epsilon hepsilon - have hscalar : Tendsto (fun m : ℕ ↦ (1 : ℝ) / ((m : ℝ) + 1)) atTop (nhds 0) := - tendsto_one_div_add_atTop_nhds_zero_nat - rw [Metric.tendsto_nhds] at hscalar - filter_upwards [hscalar epsilon hepsilon] with m hm - rw [Real.dist_eq, sub_zero, abs_of_pos (by positivity)] at hm - exact (hterms m x).trans_le hm.le - omit [LocallyCompactSpace alpha] [T2Space alpha] in private theorem tendsto_integral_coordinateProductTerm_joint {P : SubMarkovKernelSemigroup alpha} (hFeller : P.IsFellerKernelSemigroup) @@ -273,8 +164,8 @@ private theorem tendsto_integral_coordinatePolynomial_joint let : IsProbabilityMeasure (finiteTimeKernel P u y) := hP.isProbabilityMeasure_finiteTimeLaw P u y rw [PiContinuousMap.coordinatePolynomial_cons] - exact integral_add (integrable_coordinateProductTerm_joint term _) - (integrable_coordinatePolynomial_joint terms _) + exact integral_add (integrable_coordinateProductTerm term _) + (integrable_coordinatePolynomial terms _) simp_rw [hIntegral] exact (tendsto_integral_coordinateProductTerm_joint hFeller hP ht hx term).add ih @@ -306,11 +197,11 @@ theorem IsFellerKernelSemigroup.tendsto_integral_compactlySupported_finiteTimeKe have hdiff : Integrable (fun path ↦ polynomial path - f path) (finiteTimeKernel P u y) := by apply Integrable.of_bound (C := epsilon / 3) - · exact (stronglyMeasurable_coordinatePolynomial_joint terms).sub - (stronglyMeasurable_compactlySupported_fin_joint f) |>.aestronglyMeasurable + · exact (stronglyMeasurable_coordinatePolynomial terms).sub + (stronglyMeasurable_compactlySupported_pi f) |>.aestronglyMeasurable · exact ae_of_all _ fun path ↦ (hnear path).le have hp : Integrable polynomial (finiteTimeKernel P u y) := - integrable_coordinatePolynomial_joint terms _ + integrable_coordinatePolynomial terms _ have hf : Integrable f (finiteTimeKernel P u y) := by have hsub := hp.sub hdiff apply hsub.congr diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinatePolynomialMeasure.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinatePolynomialMeasure.lean new file mode 100644 index 0000000000..880202ba3f --- /dev/null +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/CoordinatePolynomialMeasure.lean @@ -0,0 +1,143 @@ +/- +Copyright (c) 2026 Scott Armstrong. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Armstrong +-/ +module + +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm +public import Mathlib.MeasureTheory.Integral.CompactlySupported + +/-! +# Measurability and integrability of finite-product tests + +Shared coordinate-polynomial bounds and compact-test approximation for finite-time kernels. +The approximation argument needs no extra measurable-space assumption on the product topology. +-/ + +public section + +open MeasureTheory ProbabilityTheory +open scoped NNReal ZeroAtInfty BigOperators CompactlySupported + +namespace MarkovProcess.SubMarkovKernelSemigroup + +/-- Coordinate polynomials are strongly measurable for the product measurable space. -/ +theorem stronglyMeasurable_coordinatePolynomial + {I alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] + (terms : List (PiContinuousMap.CoordinateProductTerm I alpha)) : + StronglyMeasurable (PiContinuousMap.coordinatePolynomial terms) := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil] + exact stronglyMeasurable_const + | cons term terms ih => + rw [PiContinuousMap.coordinatePolynomial_cons] + apply StronglyMeasurable.add _ ih + have hprod : StronglyMeasurable (fun path : I → alpha ↦ + (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by + induction term.factors with + | nil => exact stronglyMeasurable_const + | cons p factors ihFactors => + simp only [List.map_cons, List.prod_cons] + exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul + ihFactors + rw [show (term.toContinuousMap : (I → alpha) → ℝ) = fun path ↦ + term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by + funext path + exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] + exact hprod.const_mul term.coefficient + +/-- A compactly supported test on a finite product is strongly measurable. -/ +theorem stronglyMeasurable_compactlySupported_pi + {I alpha : Type*} [Finite I] [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] [T3Space alpha] [LocallyCompactSpace alpha] + (f : C_c(I → alpha, ℝ)) : StronglyMeasurable f := by + classical + let := Fintype.ofFinite I + have hexists (m : ℕ) : + ∃ terms : List (PiContinuousMap.CoordinateProductTerm I alpha), + ∀ x, ‖PiContinuousMap.coordinatePolynomial terms x - f x‖ < + 1 / ((m : ℝ) + 1) := by + have hpositive : 0 < 1 / ((m : ℝ) + 1) := by positivity + obtain ⟨terms, hterms⟩ := + PiContinuousMap.exists_coordinateProductTerms_near_compactlySupported f hpositive + exact ⟨terms, fun x ↦ by + rw [PiContinuousMap.coordinatePolynomial_apply] + exact hterms x⟩ + choose terms hterms using hexists + apply stronglyMeasurable_of_tendsto Filter.atTop + (fun m ↦ stronglyMeasurable_coordinatePolynomial (terms m)) + rw [tendsto_pi_nhds] + intro x + rw [Metric.tendsto_nhds] + intro epsilon hepsilon + have hscalar : Filter.Tendsto (fun m : ℕ ↦ (1 : ℝ) / ((m : ℝ) + 1)) Filter.atTop + (nhds 0) := tendsto_one_div_add_atTop_nhds_zero_nat + rw [Metric.tendsto_nhds] at hscalar + filter_upwards [hscalar epsilon hepsilon] with m hm + rw [Real.dist_eq, sub_zero, abs_of_pos (by positivity)] at hm + exact (hterms m x).trans_le hm.le + +variable {alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] + [BorelSpace alpha] + +/-- Coordinate-product terms are integrable against every finite measure. -/ +theorem integrable_coordinateProductTerm + {n : ℕ} (term : PiContinuousMap.CoordinateProductTerm (Fin n) alpha) + (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : + Integrable term.toContinuousMap mu := by + have hprod : StronglyMeasurable (fun path : Fin n → alpha ↦ + (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by + induction term.factors with + | nil => exact stronglyMeasurable_const + | cons p factors ih => + simp only [List.map_cons, List.prod_cons] + exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul ih + have hfun : (term.toContinuousMap : (Fin n → alpha) → ℝ) = fun path ↦ + term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod := by + funext path + exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path + rw [hfun] + refine Integrable.of_bound (hprod.const_mul term.coefficient).aestronglyMeasurable + (‖term.coefficient‖ * (term.factors.map fun p ↦ ‖p.2‖).prod) ?_ + filter_upwards [] with path + rw [norm_mul, List.norm_prod] + apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) + induction term.factors with + | nil => + simp only [List.map_nil, List.prod_nil] + exact le_rfl + | cons p factors ih => + simp only [List.map_cons, List.prod_cons] + have all_nonneg : ∀ fs : List (Fin n × C₀(alpha, ℝ)), + 0 ≤ (fs.map fun q ↦ ‖q.2 (path q.1)‖).prod := by + intro fs + induction fs with + | nil => simp only [List.map_nil, List.prod_nil, zero_le_one] + | cons q fs ih_nonneg => + simp only [List.map_cons, List.prod_cons] + exact mul_nonneg (norm_nonneg _) ih_nonneg + have hnonneg : 0 ≤ + ((factors.map fun p ↦ p.2 (path p.1)).map norm).prod := by + simpa only [List.map_map, Function.comp_apply] using! all_nonneg factors + exact mul_le_mul (p.2.toBCF.norm_coe_le_norm (path p.1)) ih + hnonneg (norm_nonneg _) + +/-- Coordinate polynomials are integrable against every finite measure. -/ +theorem integrable_coordinatePolynomial + {n : ℕ} (terms : List (PiContinuousMap.CoordinateProductTerm (Fin n) alpha)) + (mu : Measure (Fin n → alpha)) [IsFiniteMeasure mu] : + Integrable (PiContinuousMap.coordinatePolynomial terms) mu := by + induction terms with + | nil => + simp only [PiContinuousMap.coordinatePolynomial_nil] + change Integrable (fun _ : Fin n → alpha ↦ (0 : ℝ)) mu + refine Integrable.of_bound stronglyMeasurable_const.aestronglyMeasurable 0 ?_ + exact ae_of_all _ fun _ ↦ by + simpa only [norm_zero] using (le_refl (0 : ℝ)) + | cons term terms ih => + rw [PiContinuousMap.coordinatePolynomial_cons] + exact (integrable_coordinateProductTerm term mu).add ih + +end MarkovProcess.SubMarkovKernelSemigroup diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean index 5d0db0c033..b1666c0294 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/FiniteSetKernelCompactTestTransport.lean @@ -5,6 +5,7 @@ Authors: Scott Armstrong -/ module +public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.CoordinatePolynomialMeasure public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.FiniteProductCoordinateNormalForm public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.ProjectiveFamily public import Mathlib.MeasureTheory.Integral.CompactlySupported @@ -17,7 +18,7 @@ This file identifies the increasing-coordinate representation of a finite set wi function space by a homeomorphism. It transports compactly supported tests across that homeomorphism and rewrites their finite-set-kernel integrals as finite-time-kernel integrals. -Strong measurability of a compactly supported test is obtained privately from uniform coordinate- +Strong measurability of a compactly supported test follows from the shared uniform coordinate- polynomial approximations. This avoids adding an `OpensMeasurableSpace` assumption on the finite product. These declarations are finite-dimensional infrastructure; no statement about path space is proved here. @@ -30,61 +31,6 @@ open scoped NNReal CompactlySupported namespace MarkovProcess.SubMarkovKernelSemigroup -private theorem stronglyMeasurable_coordinatePolynomial - {I alpha : Type*} [TopologicalSpace alpha] [MeasurableSpace alpha] [BorelSpace alpha] - (terms : List (PiContinuousMap.CoordinateProductTerm I alpha)) : - StronglyMeasurable (PiContinuousMap.coordinatePolynomial terms) := by - induction terms with - | nil => - simp only [PiContinuousMap.coordinatePolynomial_nil] - exact stronglyMeasurable_const - | cons term terms ih => - rw [PiContinuousMap.coordinatePolynomial_cons] - apply StronglyMeasurable.add _ ih - have hprod : StronglyMeasurable (fun path : I → alpha ↦ - (term.factors.map fun p ↦ p.2 (path p.1)).prod) := by - induction term.factors with - | nil => exact stronglyMeasurable_const - | cons p factors ihFactors => - simp only [List.map_cons, List.prod_cons] - exact ((p.2.measurable.comp (measurable_pi_apply p.1)).stronglyMeasurable).mul - ihFactors - rw [show (term.toContinuousMap : (I → alpha) → ℝ) = fun path ↦ - term.coefficient * (term.factors.map fun p ↦ p.2 (path p.1)).prod by - funext path - exact PiContinuousMap.CoordinateProductTerm.toContinuousMap_apply term path] - exact hprod.const_mul term.coefficient - -private theorem stronglyMeasurable_compactlySupported_pi - {I alpha : Type*} [Finite I] [TopologicalSpace alpha] [MeasurableSpace alpha] - [BorelSpace alpha] [T3Space alpha] [LocallyCompactSpace alpha] - (f : C_c(I → alpha, ℝ)) : StronglyMeasurable f := by - classical - let := Fintype.ofFinite I - have hexists (m : ℕ) : - ∃ terms : List (PiContinuousMap.CoordinateProductTerm I alpha), - ∀ x, ‖PiContinuousMap.coordinatePolynomial terms x - f x‖ < - 1 / ((m : ℝ) + 1) := by - have hpositive : 0 < 1 / ((m : ℝ) + 1) := by positivity - obtain ⟨terms, hterms⟩ := - PiContinuousMap.exists_coordinateProductTerms_near_compactlySupported f hpositive - exact ⟨terms, fun x ↦ by - rw [PiContinuousMap.coordinatePolynomial_apply] - exact hterms x⟩ - choose terms hterms using hexists - apply stronglyMeasurable_of_tendsto Filter.atTop - (fun m ↦ stronglyMeasurable_coordinatePolynomial (terms m)) - rw [tendsto_pi_nhds] - intro x - rw [Metric.tendsto_nhds] - intro epsilon hepsilon - have hscalar : Filter.Tendsto (fun m : ℕ ↦ (1 : ℝ) / ((m : ℝ) + 1)) Filter.atTop - (nhds 0) := tendsto_one_div_add_atTop_nhds_zero_nat - rw [Metric.tendsto_nhds] at hscalar - filter_upwards [hscalar epsilon hepsilon] with m hm - rw [Real.dist_eq, sub_zero, abs_of_pos (by positivity)] at hm - exact (hterms m x).trans_le hm.le - /-- The increasing-coordinate representation of paths on a finite time set, as a homeomorphism. -/ noncomputable def orderedPathToFiniteSetHomeomorph {alpha : Type*} [TopologicalSpace alpha] (I : Finset NNReal) : diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean index 56ffdc0d37..72a4e5aac6 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelConcatenation.lean @@ -7,6 +7,7 @@ module public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelRestriction public import Mathlib.Probability.Kernel.Composition.Lemmas +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex /-! @@ -180,48 +181,6 @@ private theorem headTail_finCons {n : ℕ} (z : alpha × (Fin n → alpha)) : · funext i rfl -private theorem compProd_map_left_equiv - {X A B C : Type*} [MeasurableSpace X] [MeasurableSpace A] - [MeasurableSpace B] [MeasurableSpace C] - (kappa : Kernel X A) [IsSFiniteKernel kappa] - (eta : Kernel (X × A) B) [IsSFiniteKernel eta] - (E : A ≃ᵐ C) : - (kappa ⊗ₖ eta).map (Prod.map E id) = - kappa.map E ⊗ₖ eta.comap - (fun z : X × C ↦ (z.1, E.symm z.2)) - (measurable_fst.prodMk (E.symm.measurable.comp measurable_snd)) := by - ext x s hs - rw [Kernel.map_apply' _ (E.measurable.prodMap measurable_id) x hs, - Kernel.compProd_apply (hs.preimage (E.measurable.prodMap measurable_id)), - Kernel.compProd_apply hs] - rw [Kernel.map_apply kappa E.measurable x] - rw [MeasureTheory.lintegral_map] - · congr with a - rw [Kernel.comap_apply] - change eta (x, a) (Prod.mk (E a) ⁻¹' s) = _ - rw [E.symm_apply_apply] - · exact ProbabilityTheory.Kernel.measurable_kernel_prodMk_left' hs x - · exact E.measurable - -private theorem map_compProd_prodMkLeft_right - {X A B C : Type*} [MeasurableSpace X] [MeasurableSpace A] - [MeasurableSpace B] [MeasurableSpace C] - (kappa : Kernel X A) [IsSFiniteKernel kappa] - (eta : Kernel A B) [IsSFiniteKernel eta] - (f : B → C) (hf : Measurable f) : - (kappa ⊗ₖ Kernel.prodMkLeft X eta).map - (fun z ↦ (z.1, f z.2)) = - kappa ⊗ₖ Kernel.prodMkLeft X (eta.map f) := by - have hpair : Measurable (fun z : A × B ↦ (z.1, f z.2)) := - measurable_fst.prodMk (hf.comp measurable_snd) - ext x s hs - rw [Kernel.map_apply' _ hpair x hs, - Kernel.compProd_apply (hs.preimage hpair), Kernel.compProd_apply hs] - congr with a - rw [Kernel.prodMkLeft_apply', Kernel.prodMkLeft_apply', - Kernel.map_apply' _ hf _ (measurable_prodMk_left hs)] - rfl - private theorem compProd_prodMkLeft_assoc {X A B C : Type*} [MeasurableSpace X] [MeasurableSpace A] [MeasurableSpace B] [MeasurableSpace C] @@ -334,7 +293,7 @@ private theorem finiteTimeKernel_map_splitFinitePath_zero let : IsMarkovKernel (P (times 0)) := hP.isMarkovKernel (times 0) rw [hsplit, Kernel.map_comp_right _ measurable_headTail (E.measurable.prodMap measurable_id), finiteTimeKernel_map_headTail] - rw [compProd_map_left_equiv] + rw [Kernel.map_compProd_left_equiv] rw [finiteTimeKernel_one_eq_map, hfuture] congr 1 @@ -396,7 +355,7 @@ theorem finiteTimeKernel_map_splitFinitePath P (times 0) ⊗ₖ Kernel.prodMkLeft alpha ((finiteTimeKernel P times.relativeTail).map (splitFinitePath (alpha := alpha) (m := m) (n := n))) := by - simpa only [f] using! map_compProd_prodMkLeft_right + simpa only [f] using! Kernel.map_compProd_prodMkLeft_right (P (times 0)) (finiteTimeKernel P times.relativeTail) (splitFinitePath (alpha := alpha) (m := m) (n := n)) measurable_splitFinitePath @@ -412,7 +371,7 @@ theorem finiteTimeKernel_map_splitFinitePath MeasurableEquiv.prodAssoc.symm.measurable (E.measurable.prodMap measurable_id)] rw [compProd_prodMkLeft_assoc] - rw [compProd_map_left_equiv] + rw [Kernel.map_compProd_left_equiv] rw [initialSegment_relativeTail, relativeFinalSegment_relativeTail] congr 1 have hEfun : (E : alpha × (Fin (m + 1) → alpha) → diff --git a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelDeletion.lean b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelDeletion.lean index db826716f2..371b8a305d 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelDeletion.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/FiniteTime/KernelDeletion.lean @@ -7,6 +7,7 @@ module public import LeanPool.MarkovProcess.MarkovProcess.FiniteTime.KernelShift public import Mathlib.Probability.Kernel.Composition.KernelLemmas +public import LeanPool.MarkovProcess.MarkovProcess.Kernel.CompProdReindex /-! @@ -31,24 +32,6 @@ private theorem measurable_removeNth {n : ℕ} (p : Fin (n + 1)) : Measurable (Fin.removeNth p : (Fin (n + 1) → α) → Fin n → α) := FiniteOrderedTimes.measurable_restrictPath (Fin.succAboveOrderEmb p) -private theorem map_compProd_prodMkLeft_right - {X Y Z W : Type*} [MeasurableSpace X] [MeasurableSpace Y] - [MeasurableSpace Z] [MeasurableSpace W] - (κ : Kernel X Y) (η : Kernel Y Z) [IsSFiniteKernel κ] [IsSFiniteKernel η] - (f : Z → W) (hf : Measurable f) : - (κ ⊗ₖ Kernel.prodMkLeft X η).map (fun z ↦ (z.1, f z.2)) = - κ ⊗ₖ Kernel.prodMkLeft X (η.map f) := by - have hpair : Measurable (fun z : Y × Z ↦ (z.1, f z.2)) := - measurable_fst.prodMk (hf.comp measurable_snd) - ext x s hs - rw [Kernel.map_apply' _ hpair x hs, - Kernel.compProd_apply (hs.preimage hpair), Kernel.compProd_apply hs] - congr with y - have hsection : MeasurableSet (Prod.mk y ⁻¹' s) := measurable_prodMk_left hs - rw [Kernel.prodMkLeft_apply', Kernel.prodMkLeft_apply', - Kernel.map_apply' _ hf _ hsection] - rfl - omit [MeasurableSpace α] in private theorem removeNth_zero_cons {n : ℕ} (z : α × (Fin n → α)) : Fin.removeNth 0 (@Fin.cons n (fun _ ↦ α) z.1 z.2) = z.2 := by @@ -154,7 +137,7 @@ theorem finiteTimeKernel_map_removeNth (P : SubMarkovKernelSemigroup α) rw [FiniteOrderedTimes.restrict_apply, Fin.succAboveOrderEmb_apply, Fin.succ_succAbove_zero] rw [Kernel.map_comp_right _ hremovePair hcons, - map_compProd_prodMkLeft_right _ _ _ (measurable_removeNth p), + Kernel.map_compProd_prodMkLeft_right _ _ _ (measurable_removeNth p), ih times.relativeTail p, finiteTimeKernel_succ, Kernel.mapOfMeasurable_eq_map, relativeTail_restrict_succ, hhead] · exact measurable_finCons diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean index 69ccfa09e5..fee4cefe4e 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/Lp.lean @@ -45,7 +45,8 @@ private noncomputable instance cacheModuleLp (p : ℝ≥0∞) (μ : Measure α) private noncomputable instance cacheTopologicalSpaceLp (p : ℝ≥0∞) [Fact (1 ≤ p)] (μ : Measure α) : TopologicalSpace (Lp ℝ p μ) := inferInstance -private theorem ae_integrable_kernel_finite {μ : Measure α} {κ : Kernel α α} +/-- A finite-exponent Lp function is integrable along almost every subinvariant kernel fiber. -/ +theorem ae_integrable_kernel_finite {μ : Measure α} {κ : Kernel α α} (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) {p : NNReal} (hp : 1 ≤ p) (f : Lp ℝ (p : ℝ≥0∞) μ) : ∀ᵐ x ∂μ, Integrable f (κ x) := by let : IsFiniteKernel κ := hκ.isFiniteKernel @@ -63,7 +64,8 @@ private theorem ae_integrable_kernel_finite {μ : Measure α} {κ : Kernel α α (integrable_norm_rpow_iff hxMeas hp0 ENNReal.coe_ne_top).mp hxInt exact hxMemLp.integrable (by exact_mod_cast hp) -private theorem ae_integrable_kernel_top {μ : Measure α} {κ : Kernel α α} +/-- An essentially bounded function is integrable along almost every subinvariant kernel fiber. -/ +theorem ae_integrable_kernel_top {μ : Measure α} {κ : Kernel α α} (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) (f : Lp ℝ ∞ μ) : ∀ᵐ x ∂μ, Integrable f (κ x) := by have hCtop : eLpNormEssSup f μ ≠ ∞ := by diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean index 2e74b95294..a6646f637c 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OperatorSemigroup.lean @@ -43,43 +43,6 @@ private theorem kernelIntegral_id_ae {μ : Measure α} {f : α → ℝ} rw [kernelIntegral, Kernel.id_apply, integral_dirac' g x hf.stronglyMeasurable_mk] exact hx.symm -private theorem ae_integrable_kernel_finite {μ : Measure α} {κ : Kernel α α} - (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) {p : NNReal} - (hp : 1 ≤ p) (f : Lp ℝ (p : ℝ≥0∞) μ) : ∀ᵐ x ∂μ, Integrable f (κ x) := by - let : IsFiniteKernel κ := hκ.isFiniteKernel - have hfComp : MemLp f p (κ ∘ₘ μ) := (Lp.memLp f).mono_measure hκμ - have hFiberEq := Measure.ae_ae_of_ae_comp hfComp.aestronglyMeasurable.ae_eq_mk - have hp0 : (p : ℝ≥0∞) ≠ 0 := by - exact_mod_cast ne_of_gt (zero_lt_one.trans_le hp) - have hpowInt := hfComp.integrable_norm_rpow hp0 ENNReal.coe_ne_top - have hFiberInt := Measure.ae_integrable_of_integrable_comp hpowInt - filter_upwards [hFiberEq, hFiberInt] with x hxEq hxInt - have hxEq' : f =ᵐ[κ x] hfComp.aestronglyMeasurable.mk f := hxEq - have hxMeas : AEStronglyMeasurable f (κ x) := - hfComp.aestronglyMeasurable.stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq'.symm - have hxMemLp : MemLp f p (κ x) := - (integrable_norm_rpow_iff hxMeas hp0 ENNReal.coe_ne_top).mp hxInt - exact hxMemLp.integrable (by exact_mod_cast hp) - -private theorem ae_integrable_kernel_top {μ : Measure α} {κ : Kernel α α} - (hκ : IsSubMarkovKernel κ) (hκμ : κ ∘ₘ μ ≤ μ) - (f : Lp ℝ ∞ μ) : ∀ᵐ x ∂μ, Integrable f (κ x) := by - have hCtop : eLpNormEssSup f μ ≠ ∞ := by - rw [← eLpNorm_exponent_top (Lp.aestronglyMeasurable f)] - exact (Lp.memLp f).eLpNorm_lt_top.ne - have hCcoe : ((eLpNormEssSup f μ).toNNReal : ℝ≥0∞) = eLpNormEssSup f μ := - ENNReal.coe_toNNReal hCtop - have hFiberEq : ∀ᵐ x ∂μ, f =ᵐ[κ x] (Lp.aestronglyMeasurable f).mk f := - ae_ae_kernel_of_comp_le hκμ (Lp.aestronglyMeasurable f).ae_eq_mk - have hBound := ae_ae_kernel_of_comp_le hκμ (enorm_ae_le_eLpNormEssSup f μ) - let : IsFiniteKernel κ := hκ.isFiniteKernel - filter_upwards [hFiberEq, hBound] with x hxEq hxBound - have hxAS : AEStronglyMeasurable f (κ x) := - (Lp.aestronglyMeasurable f).stronglyMeasurable_mk.aestronglyMeasurable.congr hxEq.symm - apply MemLp.integrable (q := ∞) le_top - apply memLp_top_of_bound_enorm hxAS (eLpNormEssSup f μ).toNNReal - simpa only [hCcoe] using hxBound - private theorem kernelIntegral_add_ae_finite {μ : Measure α} (hμ : P.IsSubInvariant μ) (p : NNReal) [Fact (1 ≤ p)] (s t : NNReal) (f : Lp ℝ (p : ℝ≥0∞) μ) : From 098e1527a296e2aa3710514e3416c447917cced0 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 25 Sep 2026 20:39:56 +0000 Subject: [PATCH 10/11] Repair remaining Markov kernel visibility boundaries --- .../MarkovProcess/Kernel/OnePointExtension.lean | 5 +++-- .../MarkovProcess/Parameterized/FiniteTimeKernel.lean | 4 ++-- .../MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean index cbc072aa9b..03366a6cbf 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointExtension.lean @@ -482,7 +482,7 @@ private theorem isPositive_onePointResolventOperator (mu : Semigroup.PositiveShi /-- The positive contractive resolvent on the genuine one-point compactification. -/ noncomputable def onePointResolvent : PositiveC0ContractiveResolvent (OnePoint X) where toContractiveResolvent := R.onePointSemigroup.toContractiveResolvent - isPositive := R.isPositive_onePointResolventOperator + isPositive := by exact R.isPositive_onePointResolventOperator /-- The semigroup generated by the compactified resolvent is the compactified semigroup. -/ theorem generatedSemigroup_onePointResolvent : @@ -554,7 +554,8 @@ theorem integral_onePointKernelSemigroup (t : NNReal) (g : C₀(OnePoint X, ℝ) rw [onePointKernelSemigroup, R.onePointResolvent.integral_kernelSemigroup, R.generatedSemigroup_onePointResolvent] -private noncomputable def onePointConstant (c : ℝ) : C₀(OnePoint X, ℝ) := +/-- The constant function on the compact one-point extension. -/ +noncomputable def onePointConstant (c : ℝ) : C₀(OnePoint X, ℝ) := onePointAssemble 0 c omit [MeasurableSpace X] [BorelSpace X] [LocallyCompactSpace X] [SecondCountableTopology X] in diff --git a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeKernel.lean b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeKernel.lean index 91fc2a9a22..56362916aa 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeKernel.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Parameterized/FiniteTimeKernel.lean @@ -58,7 +58,7 @@ noncomputable def parameterizedFiniteTimeKernel Kernel.prodMkLeft (Theta × alpha) (parameterizedFiniteTimeKernel P times.relativeTail)) (fun z ↦ @Fin.cons n (fun _ : Fin (n + 1) ↦ alpha) z.1.2 z.2) - measurable_finCons_snd + (by exact measurable_finCons_snd) @[simp] theorem parameterizedFiniteTimeKernel_zero @@ -78,7 +78,7 @@ theorem parameterizedFiniteTimeKernel_succ Kernel.prodMkLeft (Theta × alpha) (P.parameterizedFiniteTimeKernel times.relativeTail)) (fun z ↦ @Fin.cons n (fun _ : Fin (n + 1) ↦ alpha) z.1.2 z.2) - measurable_finCons_snd := + (by exact measurable_finCons_snd) := rfl theorem isMarkovKernel_parameterizedFiniteTimeKernel diff --git a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean index e325b6a010..56b1f35995 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Trajectory/AllTimeFiniteMarginals.lean @@ -243,7 +243,7 @@ def finiteDenseApproximationReindex {γ : Type*} {I : Finset NNReal} (q : I ↪o DenseTime) : (finiteDenseApproximationPhysicalSet q → γ) → I → γ := fun path t ↦ path ⟨DenseTime.castOrderEmbedding (q t), - finiteDenseApproximation_mem q t⟩ + by exact finiteDenseApproximation_mem q t⟩ /-- The approximating-set reindexing map is measurable. -/ theorem measurable_finiteDenseApproximationReindex From 75775e2b70e31c3800d6734e4e69792f721a5a50 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 25 Sep 2026 20:46:17 +0000 Subject: [PATCH 11/11] Keep metric construction proofs inside proposition blocks --- .../MarkovProcess/Kernel/OnePointKolmogorov.lean | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean index 6bb28852c7..60b8bafacc 100644 --- a/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean +++ b/LeanPool/MarkovProcess/MarkovProcess/Kernel/OnePointKolmogorov.lean @@ -232,10 +232,11 @@ noncomputable def exhaustionMetricSpace (rho : X → ℝ) (hrho_cont : Continuou (hrho_pos : ∀ x, 0 < rho x) (hrho_lipschitz : LipschitzWith 1 rho) (hrho_compact : ∀ epsilon > 0, IsCompact {x | epsilon ≤ rho x}) : MetricSpace (OnePoint X) := - MetricSpace.ofDistTopology (exhaustionDist rho) (exhaustionDist_self rho hrho_pos) - (exhaustionDist_comm rho) (exhaustionDist_triangle rho hrho_pos hrho_lipschitz) - (isOpen_iff_exhaustionDist hrho_cont hrho_pos hrho_compact) - (exhaustionDist_eq_zero rho hrho_pos) + MetricSpace.ofDistTopology (exhaustionDist rho) (by exact exhaustionDist_self rho hrho_pos) + (by exact exhaustionDist_comm rho) + (by exact exhaustionDist_triangle rho hrho_pos hrho_lipschitz) + (by exact isOpen_iff_exhaustionDist hrho_cont hrho_pos hrho_compact) + (by exact exhaustionDist_eq_zero rho hrho_pos) /-- The exhaustion metric has definitionally the canonical one-point topology. -/ theorem exhaustionMetricSpace_toTopologicalSpace (rho : X → ℝ) (hrho_cont : Continuous rho)