Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Mathlib.lean
Original file line number Diff line number Diff line change
Expand Up @@ -1855,6 +1855,7 @@ public import Mathlib.Analysis.Complex.ValueDistribution.LogCounting.Asymptotic
public import Mathlib.Analysis.Complex.ValueDistribution.LogCounting.Basic
public import Mathlib.Analysis.Complex.ValueDistribution.Proximity.Basic
public import Mathlib.Analysis.ConstantSpeed
public import Mathlib.Analysis.ContDiffMulAction
public import Mathlib.Analysis.Convex.AmpleSet
public import Mathlib.Analysis.Convex.Approximation
public import Mathlib.Analysis.Convex.Basic
Expand Down
280 changes: 280 additions & 0 deletions Mathlib/Analysis/ContDiffMulAction.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
/-
Copyright (c) 2026 Archibald Browne. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Archibald Browne
-/
module


public import Mathlib.Analysis.Calculus.ContDiff.Operations

/-!
# Continuously differentiable monoid actions

In this file we define the class `ContDiffSMul`. `ContDiffSMul π•œ M X n` holds if `M` acts on `X` and
the map `(c, x) ↦ c β€’ x` is `n` times continuously differentiable on `M Γ— X`.

## Main definitions

* `ContDiffSMul π•œ M X n` : typeclass saying that the map `(c, x) ↦ c β€’ x` is `n` times continuously
differentiable on `M Γ— X`

## Main results

`ContDiffSMul.of_retraction`, `ContinuousLinearEquiv.contDiffSMul` and `ContDiffSMul.comp` prove
results about pullbacks of continuously differentiable actions. `ContDiff.contdiff_smul`
provides dot-syntax for `ContDiffSMul`. Many of the results here are the continuously differentiable
analogues of the results in the module `Mathlib.Topology.Algebra.MulAction`.
-/

@[expose] public section

open Topology Pointwise
open Filter


/-- The class `ContDiffVAdd π•œ M X n` says that the additive action `(+α΅₯) : M β†’ X β†’ X`
is `n` times continuously differentiable on `M Γ— X`. -/
class ContDiffVAdd (π•œ M X : Type*) (n : WithTop β„•βˆž) [VAdd M X] [NormedAddCommGroup X]
[NontriviallyNormedField π•œ] [NormedAddCommGroup M] [NormedSpace π•œ M]
[NormedSpace π•œ X] : Prop where
/-- The additive action `(+α΅₯)` is continuous. -/
contdiff_vadd : ContDiff π•œ n fun p : M Γ— X => p.1 +α΅₯ p.2



/-- The class `ContDiffSMul π•œ M X n` says that the scalar multiplication `(β€’) : M β†’ X β†’ X` is `n`
times continuously differentiable on `M Γ— X`. -/
@[to_additive]
class ContDiffSMul (π•œ M X : Type*) (n : WithTop β„•βˆž) [SMul M X] [NormedAddCommGroup X]
[NontriviallyNormedField π•œ] [NormedAddCommGroup M] [NormedSpace π•œ M]
[NormedSpace π•œ X] : Prop where
/-- The scalar multiplication `(β€’)` is continuously differentiable. -/
contdiff_smul : ContDiff π•œ n fun p : M Γ— X => p.1 β€’ p.2

export ContDiffSMul (contdiff_smul)



export ContDiffVAdd (contdiff_vadd)


attribute [continuity, fun_prop] contdiff_smul contdiff_vadd

@[to_additive]
-- Cannot be an instance: `π•œ` and `n` don't appear in the conclusion
theorem ContDiffSMul.toContinuousSMul (π•œ : Type*) {M X : Type*} (n : WithTop β„•βˆž)
[NontriviallyNormedField π•œ] [SMul M X]
[NormedAddCommGroup M] [NormedSpace π•œ M]
[NormedAddCommGroup X] [NormedSpace π•œ X]
[ContDiffSMul π•œ M X n] : ContinuousSMul M X where
continuous_smul := (contdiff_smul (π•œ := π•œ) (n := n)).continuous

section Main

variable {π•œ M X Y Ξ± : Type*} {n : WithTop β„•βˆž} [NontriviallyNormedField π•œ]
[NormedAddCommGroup M] [NormedSpace π•œ M]
[NormedAddCommGroup X] [NormedSpace π•œ X]

theorem ContDiffSMul.of_le {m : WithTop β„•βˆž} [SMul M X] [ContDiffSMul π•œ M X n] (h : m ≀ n) :
ContDiffSMul π•œ M X m where
contdiff_smul := contdiff_smul.of_le h


section SMul

variable [SMul M X] [ContDiffSMul π•œ M X n]

@[to_additive]
lemma IsScalarTower.contdiffSMul {M : Type*} (N : Type*) {Ξ± : Type*} [Monoid N] [SMul M N]
[MulAction N Ξ±] [SMul M Ξ±] [IsScalarTower M N Ξ±]
[NormedAddCommGroup Ξ±] [NormedAddCommGroup M] [NormedAddCommGroup N] [NormedSpace π•œ M]
[NormedSpace π•œ N] [NormedSpace π•œ Ξ±] [ContDiffSMul π•œ M N n]
[ContDiffSMul π•œ N Ξ± n] : ContDiffSMul π•œ M Ξ± n where
contdiff_smul := by
suffices ContDiff π•œ n (fun p : M Γ— Ξ± ↦ (p.1 β€’ (1 : N)) β€’ p.2) by
simpa [smul_one_smul N]
have h1 : ContDiff π•œ n (fun p : M Γ— Ξ± ↦ p.1 β€’ (1 : N)) :=
(ContDiffSMul.contdiff_smul (π•œ := π•œ) (M := M) (X := N) (n := n)).comp
(ContDiff.prodMk contDiff_fst contDiff_const)
exact (ContDiffSMul.contdiff_smul (π•œ := π•œ) (M := N) (X := Ξ±) (n := n)).comp
(ContDiff.prodMk h1 contDiff_snd)

@[to_additive]
lemma MulOpposite.contDiff_op : ContDiff π•œ n (op : M β†’ Mᡐᡒᡖ) :=
(MulOpposite.opContinuousLinearEquiv π•œ : M ≃L[π•œ] Mᡐᡒᡖ).contDiff

lemma MulOpposite.contDiff_unop : ContDiff π•œ n (unop : Mᡐᡒᡖ β†’ M) :=
(MulOpposite.opContinuousLinearEquiv π•œ : M ≃L[π•œ] Mᡐᡒᡖ).symm.contDiff

@[to_additive]
instance ContDiffSMul.op [SMul Mᡐᡒᡖ X] [IsCentralScalar M X] : ContDiffSMul π•œ Mᡐᡒᡖ X n :=
⟨by
suffices ContDiff π•œ n fun p : M Γ— X => MulOpposite.op p.fst β€’ p.snd from
this.comp ((MulOpposite.contDiff_unop (n := n)).prodMap contDiff_id)
simpa only [op_smul_eq_smul] using (contdiff_smul : ContDiff π•œ n fun p : M Γ— X => _)⟩

@[to_additive]
instance MulOpposite.contDiffSMul : ContDiffSMul π•œ M Xᡐᡒᡖ n :=
⟨(MulOpposite.contDiff_op (n := n)).comp <|
contdiff_smul.comp <| contDiff_id.prodMap (MulOpposite.contDiff_unop (n := n))⟩

section Transfer

variable {N Y : Type*} [NormedAddCommGroup N] [NormedSpace π•œ N]
[NormedAddCommGroup Y] [NormedSpace π•œ Y]


/-- Transfer `ContDiffSMul` along a `ContinuousLinearEquiv`.
Analogue of `Topology.IsInducing.continuousSMul` for the smooth setting. -/
@[to_additive]
lemma ContinuousLinearEquiv.contDiffSMul [SMul N Y] {f : N β†’ M}
(g : Y ≃L[π•œ] X) (hf : ContDiff π•œ n f)
(hsmul : βˆ€ {c y}, g (c β€’ y) = f c β€’ g y) :
ContDiffSMul π•œ N Y n := ⟨by
set F := fun (p : N Γ— Y) => p.1 β€’ p.2 with hF
have hF' : F = (fun p ↦ g.symm (g (p.1 β€’ p.2))) := by
ext p; simp only [symm_apply_apply, hF]
simp_rw [hsmul] at hF'
rw [hF']
exact g.symm.contDiff.comp
(contdiff_smul.comp (ContDiff.prodMk (hf.comp contDiff_fst)
(g.contDiff.comp contDiff_snd)))⟩

/-- Transfer `ContDiffSMul` via a retraction (continuous linear left inverse).
Analogue of `SMulMemClass.continuousSMul` for complemented subspaces. -/
@[to_additive]
lemma ContDiffSMul.of_retraction [SMul M N]
(ΞΉ : N β†’L[π•œ] X) (Ο€ : X β†’L[π•œ] N) (hπι : βˆ€ x, Ο€ (ΞΉ x) = x)
(hsmul : βˆ€ (m : M) (x : N), ΞΉ (m β€’ x) = m β€’ ΞΉ x) : ContDiffSMul π•œ M N n := ⟨by
set F := fun (p : M Γ— N) => p.1 β€’ p.2 with hF
have hF' : F = fun p ↦ Ο€ (p.1 β€’ ΞΉ p.2) := by
ext p; rw [← hsmul p.1 p.2, hπι (p.1 β€’ p.2)]
rw [hF']
exact Ο€.contDiff.comp (contdiff_smul.comp
(ContDiff.prodMk contDiff_fst (ι.contDiff.comp contDiff_snd)))⟩

/-- Transfer `ContDiffSMul` along a continuously differentiable map on the acting type. -/
@[to_additive]
lemma ContDiffSMul.comp [SMul N X] {f : N β†’ M}
(hf : ContDiff π•œ n f)
(hsmul : βˆ€ (c : N) (x : X), c β€’ x = f c β€’ x) :
ContDiffSMul π•œ N X n := ⟨by
set F := fun p : N Γ— X => p.1 β€’ p.2 with hF
have : F = fun p => f p.1 β€’ p.2 := by
ext p; rw [← hsmul p.1 p.2]
simpa [this] using
contdiff_smul.comp (ContDiff.prodMk (hf.comp contDiff_fst) contDiff_snd)⟩

end Transfer

variable {f : Y β†’ M} {g : Y β†’ X} {b : Y} {s : Set Y} [NormedAddCommGroup Y] [NormedSpace π•œ Y]

@[to_additive]
theorem ContDiffWithinAt.contdiff_smul'
(hf : ContDiffWithinAt π•œ n f s b) (hg : ContDiffWithinAt π•œ n g s b) :
ContDiffWithinAt π•œ n (fun x => f x β€’ g x) s b :=
ContDiffSMul.contdiff_smul.comp_contDiffWithinAt (ContDiffWithinAt.prodMk hf hg)

@[to_additive]
theorem ContDiffAt.contdiff_smul (hf : ContDiffAt π•œ n f b)
(hg : ContDiffAt π•œ n g b) :
ContDiffAt π•œ n (fun x => f x β€’ g x) b :=
ContDiffSMul.contdiff_smul.comp_contDiffAt _ (ContDiffAt.prodMk hf hg)

@[to_additive]
theorem ContDiffOn.contdiff_smul (hf : ContDiffOn π•œ n f s)
(hg : ContDiffOn π•œ n g s) :
ContDiffOn π•œ n (fun x => f x β€’ g x) s :=
fun x hx => (hf x hx).contdiff_smul' (hg x hx)

@[to_additive]
theorem ContDiff.contdiff_smul (hf : ContDiff π•œ n f) (hg : ContDiff π•œ n g) :
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The correct name for this would be ContDiff.smul, but that name is already taken by the corresponding lemma for scalar multiplication on vector spaces - if possible without messing with the import structure too much, it would probably make sense to remove those lemmas and provide a ContDiffSMul instance for scalar multiplication on vector spaces instead, and then use the correct name here? The same goes for ContDiffAt.contdiff_smul etc.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I'll have a think about how to do this cleanly

ContDiff π•œ n (fun x => f x β€’ g x) :=
ContDiffSMul.contdiff_smul.comp (ContDiff.prodMk hf hg)

end SMul

section Monoid

variable [Monoid M] [MulAction M X] [ContDiffSMul π•œ M X n]

theorem MulAction.contDiffSMul_compHom {N} [NormedAddCommGroup N] [NormedSpace π•œ N]
[Monoid N] {f : N β†’* M} (hf : ContDiff π•œ n f) :
letI := MulAction.compHom X f
ContDiffSMul π•œ N X n := by
letI := MulAction.compHom X f
exact ⟨(hf.comp contDiff_fst).contdiff_smul contDiff_snd⟩


end Monoid

section Normed

variable {π•œ' : Type*} [NontriviallyNormedField π•œ'] [NormedAlgebra π•œ π•œ']

/-- Scalar multiplication by a normed field on a normed space is C^n. -/
instance NormedSpace.contDiffSMul {F : Type*} [NormedAddCommGroup F] [NormedSpace π•œ F]
[Module π•œ' F] [IsBoundedSMul π•œ' F] [IsScalarTower π•œ π•œ' F] :
ContDiffSMul π•œ π•œ' F n where
contdiff_smul := contDiff_smul


/-- Multiplication in a normed algebra is C^n as a scalar action on itself. -/
instance NormedAlgebra.contDiffSMul_self {A : Type*} [NormedRing A] [NormedAlgebra π•œ A] :
ContDiffSMul π•œ A A n where
contdiff_smul := contDiff_mul

end Normed

instance ContinuousLinearMap.contDiffSMul :
ContDiffSMul π•œ (M β†’L[π•œ] M) M n where
contdiff_smul := isBoundedBilinearMap_apply.contDiff

variable [NormedAddCommGroup Y] [NormedSpace π•œ Y]

instance Prod.contDiffSMul [SMul M X] [SMul M Y] [ContDiffSMul π•œ M X n] [ContDiffSMul π•œ M Y n] :
ContDiffSMul π•œ M (X Γ— Y) n where
contdiff_smul := by
suffices ContDiff π•œ n (fun p : M Γ— (X Γ— Y) => p.1 β€’ p.2) by
simpa only [Prod.smul_def] using this
refine ContDiff.prodMk ?_ ?_
Β· exact ContDiff.contdiff_smul contDiff_fst (ContDiff.snd' contDiff_fst)
Β· exact ContDiff.contdiff_smul contDiff_fst (ContDiff.snd' contDiff_snd)

instance {ΞΉ : Type*} [Fintype ΞΉ] {Ξ³ : ΞΉ β†’ Type*} [βˆ€ i, SMul M (Ξ³ i)]
[βˆ€ i, NormedAddCommGroup (Ξ³ i)]
[βˆ€ i, NormedSpace π•œ (Ξ³ i)] [βˆ€ i, ContDiffSMul π•œ M (Ξ³ i) n] :
ContDiffSMul π•œ M (βˆ€ i, Ξ³ i) n :=
⟨contDiff_pi.mpr fun i => by
simp only [Pi.smul_apply]
have hi : ContDiff π•œ n (fun x : M Γ— (βˆ€ i, Ξ³ i) => x.2 i) :=
(ContinuousLinearMap.proj (R := π•œ) (ΞΉ := ΞΉ) (Ο† := Ξ³) i).contDiff.comp contDiff_snd
exact contDiff_fst.contdiff_smul hi⟩

end Main

section Tendsto

variable {π•œ M X Ξ± : Type*}

@[to_additive]
theorem Filter.Tendsto.contdiff_smul (π•œ : Type*) [NontriviallyNormedField π•œ]
[NormedAddCommGroup M] [NormedSpace π•œ M] [NormedAddCommGroup X] [NormedSpace π•œ X]
[SMul M X] (n : WithTop β„•βˆž) [ContDiffSMul π•œ M X n]
{f : Ξ± β†’ M} {g : Ξ± β†’ X} {l : Filter Ξ±} {c : M} {a : X}
(hf : Tendsto f l (𝓝 c)) (hg : Tendsto g l (𝓝 a)) :
Tendsto (fun x => f x β€’ g x) l (𝓝 <| c β€’ a) :=
(ContDiffSMul.contdiff_smul (π•œ := π•œ) (n := n) |>.continuous.tendsto _).comp
(hf.prodMk_nhds hg)

@[to_additive]
theorem Filter.Tendsto.contdiff_smul_const (π•œ : Type*) [NontriviallyNormedField π•œ]
[NormedAddCommGroup M] [NormedSpace π•œ M] [NormedAddCommGroup X] [NormedSpace π•œ X]
[SMul M X] (n : WithTop β„•βˆž) [ContDiffSMul π•œ M X n]
{f : Ξ± β†’ M} {l : Filter Ξ±} {c : M}
(hf : Tendsto f l (𝓝 c)) (a : X) :
Tendsto (fun x => f x β€’ a) l (𝓝 (c β€’ a)) :=
hf.contdiff_smul π•œ n tendsto_const_nhds

end Tendsto
Loading