1-- Lipschitz maps and isometries, continued: restrictions to subspaces,2-- images of balls, inverses of bijective isometries as homeomorphisms,3-- and the distance to a fixed point as a 1-Lipschitz real function4-- Part of Cumulus, the Grace17 mathematics library.5-- Copyright (c) 2026 Grant Passmore.6-- Released under the Apache License 2.0. See LICENSE in the repository root.7-- Authors: Grant Passmore89module Grace.Cumulus.Metric.Maps10import Limits1112theorem IsLipschitz.of_le (f X d Y e : Set) (K L : Real)13requires metricD : IsMetric(X, d)14requires metricE : IsMetric(Y, e)15requires lipschitz : IsLipschitz(f, X, d, Y, e, K)16requires le : K ≤ L17shows IsLipschitz(f, X, d, Y, e, L)18proof19have function := IsLipschitz.function with lipschitz20have nonnegativeK := IsLipschitz.nonnegative with lipschitz21have nonnegativeL : 0≤ L bylinarith22unfold IsLipschitz23constructor24 . exact function25 . constructor26 . exact nonnegativeL27 . intros x hx y hy28have bound := IsLipschitz.bound with lipschitz, hx, hy29have dxy := IsMetric.real with metricD, hx, hy30have imageX := FunctionBetween.apply_closed with function, hx31have imageY := FunctionBetween.apply_closed with function, hy32have exy := IsMetric.real with metricE, imageX, imageY33have nonnegative := IsMetric.nonnegative with metricD, hx, hy34have scaled := realLe.mul_right_of_nonnegative with le, nonnegative35linarith3637-- A Lipschitz map with constant zero is constant.38theorem IsLipschitz.constant_of_zero (f X d Y e x y : Set)39requires metricD : IsMetric(X, d)40requires metricE : IsMetric(Y, e)41requires lipschitz : IsLipschitz(f, X, d, Y, e, (0:R))42requires hx : x ∈ X43requires hy : y ∈ X44shows f(x) = f(y)45proof46have function := IsLipschitz.function with lipschitz47have bound := IsLipschitz.bound with lipschitz, hx, hy48have dxy := IsMetric.real with metricD, hx, hy49have imageX := FunctionBetween.apply_closed with function, hx50have imageY := FunctionBetween.apply_closed with function, hy51have exy := IsMetric.real with metricE, imageX, imageY52have nonnegative := IsMetric.nonnegative with metricE, imageX, imageY53have annihilate := realMulValue.zero_left at d(x, y)54rw annihilate at bound55have zero : e(f(x), f(y)) = (0:R) bylinarith56exact IsMetric.eq_of_zero with metricE, imageX, imageY, zero5758theorem IsLipschitz.restrict (f X d Y e S : Set) (K : Real)59requires metric : IsMetric(X, d)60requires inside : S ⊆ X61requires lipschitz : IsLipschitz(f, X, d, Y, e, K)62shows IsLipschitz(restrict(f, S), S, subspaceMetric(d, S), Y, e, K)63proof64have function := IsLipschitz.function with lipschitz65have nonnegative := IsLipschitz.nonnegative with lipschitz66unfold IsLipschitz67constructor68 . exact restrict.domain_function with function, inside69 . constructor70 . exact nonnegative71 . intros x hx y hy72have valueX := restrict.domain_apply with function, inside, hx73have valueY := restrict.domain_apply with function, inside, hy74have distance := subspaceMetric.apply with metric, inside, hx, hy75rw [valueX, valueY, distance]76exact IsLipschitz.bound with lipschitz, (inside with x, hx), (inside with77 y, hy)7879theorem IsIsometry.restrict (f X d Y e S : Set)80requires metric : IsMetric(X, d)81requires inside : S ⊆ X82requires isometry : IsIsometry(f, X, d, Y, e)83shows IsIsometry(restrict(f, S), S, subspaceMetric(d, S), Y, e)84proof85have function := IsIsometry.function with isometry86constructor87 . exact restrict.domain_function with function, inside88 . intros x hx y hy89have valueX := restrict.domain_apply with function, inside, hx90have valueY := restrict.domain_apply with function, inside, hy91have distance := subspaceMetric.apply with metric, inside, hx, hy92rw [valueX, valueY, distance]93exact IsIsometry.distance with isometry, (inside with x, hx), (inside with94 y, hy)9596theorem IsUniformlyContinuous.restrict (f X d Y e S : Set)97requires metric : IsMetric(X, d)98requires inside : S ⊆ X99requires uniform : IsUniformlyContinuous(f, X, d, Y, e)100shows IsUniformlyContinuous(restrict(f, S), S, subspaceMetric(d, S), Y, e)101proof102have function := IsUniformlyContinuous.function with uniform103apply IsUniformlyContinuous.of_control with (restrict.domain_function with104 function, inside)105intros ε hε positive106obtain⟨δ, hδ, positiveD, maps⟩:=107 IsUniformlyContinuous.control with uniform, positive108refine⟨δ, hδ, positiveD, ?_⟩109intros x hx y hy near110have valueX := restrict.domain_apply with function, inside, hx111have valueY := restrict.domain_apply with function, inside, hy112have distance := subspaceMetric.apply with metric, inside, hx, hy113rw distance at near114rw [valueX, valueY]115exact maps with x, (inside with x, hx), y, (inside with y, hy), near116117theorem MetricContinuousAt.restrict (f X d Y e S x : Set)118requires metric : IsMetric(X, d)119requires inside : S ⊆ X120requires continuous : MetricContinuousAt(f, X, d, Y, e, x)121requires hx : x ∈ S122shows MetricContinuousAt(restrict(f, S), S, subspaceMetric(d, S), Y, e, x)123proof124have function := MetricContinuousAt.function with continuous125have restricted := restrict.domain_function with function, inside126apply MetricContinuousAt.of_control with restricted, hx127intros ε hε positive128obtain⟨δ, hδ, positiveD, maps⟩:=129 MetricContinuousAt.control with continuous, positive130refine⟨δ, hδ, positiveD, ?_⟩131intros y hy near132have valueX := restrict.domain_apply with function, inside, hx133have valueY := restrict.domain_apply with function, inside, hy134have distance := subspaceMetric.apply with metric, inside, hx, hy135rw distance at near136rw [valueX, valueY]137exact maps with y, (inside with y, hy), near138139theorem inclusionMap.lipschitz (X d S : Set)140requires metric : IsMetric(X, d)141requires inside : S ⊆ X142shows IsLipschitz(inclusionMap(S, X), S, subspaceMetric(d, S), X, d, (1:R))143proof144have subspace := subspaceMetric.metric with metric, inside145exact IsIsometry.lipschitz with subspace, (inclusionMap.isometry with146 metric, inside)147148theorem inclusionMap.uniformly_continuous (X d S : Set)149requires metric : IsMetric(X, d)150requires inside : S ⊆ X151shows IsUniformlyContinuous(inclusionMap(S, X), S, subspaceMetric(d, S), X, d)152proof153exact IsIsometry.uniformly_continuous with (inclusionMap.isometry with154 metric, inside)155156-- Images of balls under Lipschitz maps and isometries.157theorem IsLipschitz.image_ball (f X d Y e x : Set) (K r : Real)158requires metricD : IsMetric(X, d)159requires metricE : IsMetric(Y, e)160requires lipschitz : IsLipschitz(f, X, d, Y, e, K)161requires positive : 0 < K162requires hx : x ∈ X163shows functionImage(f, ball(X, d, x, r), Y) ⊆ ball(Y, e, f(x), K * r)164proof165have function := IsLipschitz.function with lipschitz166intros v hv167obtain⟨hvY, y, hy, shape⟩:= functionImage.membership.forward with hv168rw shape169have hyX := ball.point with hy170have near := ball.distance with hy171have bound := IsLipschitz.bound with lipschitz, hx, hyX172have dxy := IsMetric.real with metricD, hx, hyX173have imageX := FunctionBetween.apply_closed with function, hx174have imageY := FunctionBetween.apply_closed with function, hyX175have exy := IsMetric.real with metricE, imageX, imageY176have scaled := realLess.mul_left_of_positive with near, positive177apply ball.of_distance with imageY178linarith179180theorem IsLipschitz.image_closedBall (f X d Y e x : Set) (K r : Real)181requires metricD : IsMetric(X, d)182requires metricE : IsMetric(Y, e)183requires lipschitz : IsLipschitz(f, X, d, Y, e, K)184requires hx : x ∈ X185shows186 functionImage(f, closedBall(X, d, x, r), Y) ⊆ closedBall(Y, e, f(x), K * r)187proof188have function := IsLipschitz.function with lipschitz189have nonnegative := IsLipschitz.nonnegative with lipschitz190intros v hv191obtain⟨hvY, y, hy, shape⟩:= functionImage.membership.forward with hv192rw shape193have hyX := closedBall.point with hy194have near := closedBall.distance with hy195have bound := IsLipschitz.bound with lipschitz, hx, hyX196have dxy := IsMetric.real with metricD, hx, hyX197have imageX := FunctionBetween.apply_closed with function, hx198have imageY := FunctionBetween.apply_closed with function, hyX199have exy := IsMetric.real with metricE, imageX, imageY200have scaled := realLe.mul_left_of_nonnegative with near, nonnegative201apply closedBall.of_distance with imageY202linarith203204theorem IsIsometry.image_ball_subset (f X d Y e x : Set, r : Real)205requires isometry : IsIsometry(f, X, d, Y, e)206requires hx : x ∈ X207shows functionImage(f, ball(X, d, x, r), Y) ⊆ ball(Y, e, f(x), r)208proof209intros v hv210obtain⟨hvY, y, hy, shape⟩:= functionImage.membership.forward with hv211rw shape212have hyX := ball.point with hy213have characterization := IsIsometry.ball_image at f, X, d, Y, e, x, y, r with214 isometry, hx, hyX215exact characterization.forward with hy216217theorem IsIsometry.closedBall_image (f X d Y e x y : Set, r : Real)218requires isometry : IsIsometry(f, X, d, Y, e)219requires hx : x ∈ X220requires hy : y ∈ X221shows y ∈ closedBall(X, d, x, r) ↔ f(y) ∈ closedBall(Y, e, f(x), r)222proof223have function := IsIsometry.function with isometry224have preserved := IsIsometry.distance with isometry, hx, hy225have image := FunctionBetween.apply_closed with function, hy226constructor227 . intro member228have near := closedBall.distance with member229apply closedBall.of_distance with image230 rwa preserved231 . intro member232have near := closedBall.distance with member233apply closedBall.of_distance with hy234 rwa preserved at near235236theorem IsIsometry.sphere_image (f X d Y e x y : Set, r : Real)237requires isometry : IsIsometry(f, X, d, Y, e)238requires hx : x ∈ X239requires hy : y ∈ X240shows y ∈ sphere(X, d, x, r) ↔ f(y) ∈ sphere(Y, e, f(x), r)241proof242have function := IsIsometry.function with isometry243have preserved := IsIsometry.distance with isometry, hx, hy244have image := FunctionBetween.apply_closed with function, hy245constructor246 . intro member247obtain⟨hyX, equal⟩:= sphere.membership.forward with member248apply sphere.membership.backward249refine⟨image, ?_⟩250 rwa preserved251 . intro member252obtain⟨imageY, equal⟩:= sphere.membership.forward with member253apply sphere.membership.backward254refine⟨hy, ?_⟩255 rwa preserved at equal256257theorem IsIsometry.image_bounded (f X d Y e S : Set)258requires metricD : IsMetric(X, d)259requires metricE : IsMetric(Y, e)260requires isometry : IsIsometry(f, X, d, Y, e)261requires bounded : IsBounded(X, d, S)262shows IsBounded(Y, e, functionImage(f, S, Y))263proof264have lipschitz := IsIsometry.lipschitz with metricD, isometry265exact IsLipschitz.image_bounded with metricD, metricE, lipschitz, bounded266267theorem IsLipschitz.converges (f X d Y e u x : Set) (K : Real)268requires metricD : IsMetric(X, d)269requires metricE : IsMetric(Y, e)270requires lipschitz : IsLipschitz(f, X, d, Y, e, K)271requires converges : ConvergesIn(X, d, u, x)272shows ConvergesIn(Y, e, compose(f, u, ℕ, X, Y), f(x))273proof274have continuous := IsLipschitz.continuous with metricD, metricE, lipschitz275exact ConvergesIn.map_continuous with continuous, converges276277-- The inverse of a bijective isometry is an isometry, so a bijective278-- isometry is a homeomorphism of the metric topologies.279theorem IsIsometry.inverse (f X d Y e : Set)280requires isometry : IsIsometry(f, X, d, Y, e)281requires bijective : BijectiveBetween(f, X, Y)282shows IsIsometry(converse(f, X, Y), Y, e, X, d)283proof284have inverse := converse.function_of_bijective with bijective285constructor286 . exact inverse287 . intros v hv w hw288have preimageV := FunctionBetween.apply_closed with inverse, hv289have preimageW := FunctionBetween.apply_closed with inverse, hw290have preserved := IsIsometry.distance with isometry, preimageV, preimageW291have backV := Bijective.apply_inverse with bijective, hv292have backW := Bijective.apply_inverse with bijective, hw293rw [backV, backW] at preserved294 symm at preserved295exact preserved296297theorem IsIsometry.inverse_continuous (f X d Y e : Set)298requires isometry : IsIsometry(f, X, d, Y, e)299requires bijective : BijectiveBetween(f, X, Y)300shows IsMetricContinuous(converse(f, X, Y), Y, e, X, d)301proof302exact IsIsometry.continuous with (IsIsometry.inverse with isometry, bijective)303304theorem IsIsometry.inverse_uniformly_continuous (f X d Y e : Set)305requires isometry : IsIsometry(f, X, d, Y, e)306requires bijective : BijectiveBetween(f, X, Y)307shows IsUniformlyContinuous(converse(f, X, Y), Y, e, X, d)308proof309exact IsIsometry.uniformly_continuous with (IsIsometry.inverse with310 isometry, bijective)311312theorem IsIsometry.homeomorphism (f X d Y e : Set)313requires metricD : IsMetric(X, d)314requires metricE : IsMetric(Y, e)315requires isometry : IsIsometry(f, X, d, Y, e)316requires bijective : BijectiveBetween(f, X, Y)317shows IsHomeomorphism(f, X, metricTopology(X, d), Y, metricTopology(Y, e))318proof319have forward := IsIsometry.continuous with isometry320have backward := IsIsometry.inverse_continuous with isometry, bijective321refine⟨bijective, ?_, ?_⟩322 . exact IsMetricContinuous.continuous_map with metricD, metricE, forward323 . exact IsMetricContinuous.continuous_map with metricE, metricD, backward324325-- The distance to a fixed point, as a real-valued function on the space.326defgraph distanceTo (X d y : Set) (x ∈ X) : ℝ := d(x, y)327requires metric : IsMetric(X, d)328requires hy : y ∈ X329proof330exact IsMetric.real with metric, member, hy331332theorem distanceTo.nonnegative (X d y x : Set)333requires metric : IsMetric(X, d)334requires hy : y ∈ X335requires hx : x ∈ X336shows (0:R) ≤ distanceTo(X, d, y)(x)337proof338have value := distanceTo.value at X, d, y, x with metric, hy, hx339rw value340exact IsMetric.nonnegative with metric, hx, hy341342theorem distanceTo.zero_iff (X d y x : Set)343requires metric : IsMetric(X, d)344requires hy : y ∈ X345requires hx : x ∈ X346shows distanceTo(X, d, y)(x) = (0:R) ↔ x = y347proof348have value := distanceTo.value at X, d, y, x with metric, hy, hx349rw value350exact IsMetric.eq_zero_iff with metric, hx, hy351352theorem distanceTo.lipschitz (X d y : Set)353requires metric : IsMetric(X, d)354requires hy : y ∈ X355shows IsLipschitz(distanceTo(X, d, y), X, d, ℝ, realDistance, (1:R))356proof357have one : (0:R) ≤1bylinarith358unfold IsLipschitz359constructor360 . exact distanceTo.function with metric, hy361 . constructor362 . exact one363 . intros x hx z hz364have valueX := distanceTo.value at X, d, y, x with metric, hy, hx365have valueZ := distanceTo.value at X, d, y, z with metric, hy, hz366rw [valueX, valueZ]367have dxy := IsMetric.real with metric, hx, hy368have dzy := IsMetric.real with metric, hz, hy369have dxz := IsMetric.real with metric, hx, hz370have realValue := realDistance.apply at d(x, y), d(z, y) with*371rw realValue372unfold dist373have reverse := IsMetric.abs_sub_le with metric, hx, hz, hy374have unit := realMulValue.one_left at d(x, z)375rw unit376exact reverse377378theorem distanceTo.uniformly_continuous (X d y : Set)379requires metric : IsMetric(X, d)380requires hy : y ∈ X381shows IsUniformlyContinuous(distanceTo(X, d, y), X, d, ℝ, realDistance)382proof383have lipschitz := distanceTo.lipschitz with metric, hy384exact IsLipschitz.uniformly_continuous with385 metric, realDistance.metric, lipschitz386387theorem distanceTo.continuous (X d y : Set)388requires metric : IsMetric(X, d)389requires hy : y ∈ X390shows IsMetricContinuous(distanceTo(X, d, y), X, d, ℝ, realDistance)391proof392have uniform := distanceTo.uniformly_continuous with metric, hy393exact IsUniformlyContinuous.continuous with uniform394395theorem distanceTo.converges (X d y u x : Set)396requires metric : IsMetric(X, d)397requires hy : y ∈ X398requires converges : ConvergesIn(X, d, u, x)399shows ConvergesIn(ℝ, realDistance, compose(distanceTo(X, d, y), u, ℕ, X, ℝ),400 distanceTo(X, d, y)(x))401proof402have continuous := distanceTo.continuous with metric, hy403exact ConvergesIn.map_continuous with continuous, converges404405theorem distanceTo.ball_preimage (X d y : Set, r : Real)406requires metric : IsMetric(X, d)407requires hy : y ∈ X408shows409 ball(X, d, y, r) = functionPreimage(distanceTo(X, d, y), X, openBall(0, r))410proof411ext x412constructor413 . intro hx414have hxX := ball.point with hx415have near := ball.distance with hx416have value := distanceTo.value at X, d, y, x with metric, hy, hxX417have symmetric := IsMetric.symmetric with metric, hy, hxX418have dxy := IsMetric.real with metric, hxX, hy419have nonnegative := IsMetric.nonnegative with metric, hxX, hy420apply functionPreimage.membership.backward421refine⟨hxX, ?_⟩422rw value423apply openBall.membership.backward424refine⟨dxy, ?_⟩425unfold dist426have zero := realSubValue.zero_right at d(x, y)427have unfolded := abs.of_nonnegative with nonnegative428rw [zero, unfolded]429 rwa symmetric at near430 . intro hx431obtain⟨hxX, inBall⟩:= functionPreimage.membership.forward with hx432have value := distanceTo.value at X, d, y, x with metric, hy, hxX433rw value at inBall434have symmetric := IsMetric.symmetric with metric, hy, hxX435have dxy := IsMetric.real with metric, hxX, hy436have nonnegative := IsMetric.nonnegative with metric, hxX, hy437obtain⟨valueReal, near⟩:= openBall.membership.forward with inBall438unfold dist at near439have zero := realSubValue.zero_right at d(x, y)440have unfolded := abs.of_nonnegative with nonnegative441rw [zero, unfolded] at near442apply ball.of_distance with hxX443 rwa symmetric444