Skip to content

Commit

Permalink
feat: port Analysis.InnerProductSpace.OfNorm (#5885)
Browse files Browse the repository at this point in the history
  • Loading branch information
Parcly-Taxel authored and semorrison committed Aug 14, 2023
1 parent 3bf1e11 commit a2fecf3
Show file tree
Hide file tree
Showing 2 changed files with 357 additions and 0 deletions.
1 change: 1 addition & 0 deletions Mathlib.lean
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,7 @@ import Mathlib.Analysis.InnerProductSpace.EuclideanDist
import Mathlib.Analysis.InnerProductSpace.GramSchmidtOrtho
import Mathlib.Analysis.InnerProductSpace.LaxMilgram
import Mathlib.Analysis.InnerProductSpace.LinearPMap
import Mathlib.Analysis.InnerProductSpace.OfNorm
import Mathlib.Analysis.InnerProductSpace.Orientation
import Mathlib.Analysis.InnerProductSpace.Orthogonal
import Mathlib.Analysis.InnerProductSpace.PiL2
Expand Down
356 changes: 356 additions & 0 deletions Mathlib/Analysis/InnerProductSpace/OfNorm.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,356 @@
/-
Copyright (c) 2020 Heather Macbeth. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Heather Macbeth
! This file was ported from Lean 3 source module analysis.inner_product_space.of_norm
! leanprover-community/mathlib commit baa88307f3e699fa7054ef04ec79fa4f056169cb
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Topology.Algebra.Algebra
import Mathlib.Analysis.InnerProductSpace.Basic

/-!
# Inner product space derived from a norm
This file defines an `InnerProductSpace` instance from a norm that respects the
parallellogram identity. The parallelogram identity is a way to express the inner product of `x` and
`y` in terms of the norms of `x`, `y`, `x + y`, `x - y`.
## Main results
- `InnerProductSpace.ofNorm`: a normed space whose norm respects the parallellogram identity,
can be seen as an inner product space.
## Implementation notes
We define `inner_`
$$\langle x, y \rangle := \frac{1}{4} (β€–x + yβ€–^2 - β€–x - yβ€–^2 + i β€–ix + yβ€– ^ 2 - i β€–ix - yβ€–^2)$$
and use the parallelogram identity
$$β€–x + yβ€–^2 + β€–x - yβ€–^2 = 2 (β€–xβ€–^2 + β€–yβ€–^2)$$
to prove it is an inner product, i.e., that it is conjugate-symmetric (`Inner_.conj_symm`) and
linear in the first argument. `add_left` is proved by judicious application of the parallelogram
identity followed by tedious arithmetic. `smul_left` is proved step by step, first noting that
$\langle Ξ» x, y \rangle = Ξ» \langle x, y \rangle$ for $Ξ» ∈ β„•$, $Ξ» = -1$, hence $Ξ» ∈ β„€$ and $Ξ» ∈ β„š$
by arithmetic. Then by continuity and the fact that β„š is dense in ℝ, the same is true for ℝ.
The case of β„‚ then follows by applying the result for ℝ and more arithmetic.
## TODO
Move upstream to `Analysis.InnerProductSpace.Basic`.
## References
- [Jordan, P. and von Neumann, J., *On inner products in linear, metric spaces*][Jordan1935]
- https://math.stackexchange.com/questions/21792/norms-induced-by-inner-products-and-the-parallelogram-law
- https://math.dartmouth.edu/archive/m113w10/public_html/jordan-vneumann-thm.pdf
## Tags
inner product space, Hilbert space, norm
-/


open IsROrC

open scoped ComplexConjugate

variable {π•œ : Type _} [IsROrC π•œ] (E : Type _) [NormedAddCommGroup E]

/-- Predicate for the parallelogram identity to hold in a normed group. This is a scalar-less
version of `InnerProductSpace`. If you have an `InnerProductSpaceable` assumption, you can
locally upgrade that to `InnerProductSpace π•œ E` using `casesI nonempty_innerProductSpace π•œ E`.
-/
class InnerProductSpaceable : Prop where
parallelogram_identity :
βˆ€ x y : E, β€–x + yβ€– * β€–x + yβ€– + β€–x - yβ€– * β€–x - yβ€– = 2 * (β€–xβ€– * β€–xβ€– + β€–yβ€– * β€–yβ€–)
#align inner_product_spaceable InnerProductSpaceable

variable (π•œ) {E}

theorem InnerProductSpace.toInnerProductSpaceable [InnerProductSpace π•œ E] :
InnerProductSpaceable E :=
⟨parallelogram_law_with_norm π•œβŸ©
#align inner_product_space.to_inner_product_spaceable InnerProductSpace.toInnerProductSpaceable

-- See note [lower instance priority]
instance (priority := 100) InnerProductSpace.toInnerProductSpaceable_ofReal
[InnerProductSpace ℝ E] : InnerProductSpaceable E :=
⟨parallelogram_law_with_norm β„βŸ©
#align inner_product_space.to_inner_product_spaceable_of_real InnerProductSpace.toInnerProductSpaceable_ofReal

variable [NormedSpace π•œ E]

local notation "π“š" => algebraMap ℝ π•œ

/-- Auxiliary definition of the inner product derived from the norm. -/
private noncomputable def inner_ (x y : E) : π•œ :=
4⁻¹ * (π“š β€–x + yβ€– * π“š β€–x + yβ€– - π“š β€–x - yβ€– * π“š β€–x - yβ€– +
(I : π•œ) * π“š β€–(I : π•œ) β€’ x + yβ€– * π“š β€–(I : π•œ) β€’ x + yβ€– -
(I : π•œ) * π“š β€–(I : π•œ) β€’ x - yβ€– * π“š β€–(I : π•œ) β€’ x - yβ€–)

namespace InnerProductSpaceable

variable {π•œ} (E)

-- Porting note: prime added to avoid clashing with public `innerProp`
/-- Auxiliary definition for the `add_left` property. -/
private def innerProp' (r : π•œ) : Prop :=
βˆ€ x y : E, inner_ π•œ (r β€’ x) y = conj r * inner_ π•œ x y

variable {E}

theorem innerProp_neg_one : innerProp' E ((-1 : β„€) : π•œ) := by
intro x y
simp only [inner_, neg_mul_eq_neg_mul, one_mul, Int.cast_one, one_smul, RingHom.map_one, map_neg,
Int.cast_neg, neg_smul, neg_one_mul]
rw [neg_mul_comm]
congr 1
have h₁ : β€–-x - yβ€– = β€–x + yβ€– := by rw [← neg_add', norm_neg]
have hβ‚‚ : β€–-x + yβ€– = β€–x - yβ€– := by rw [← neg_sub, norm_neg, sub_eq_neg_add]
have h₃ : β€–(I : π•œ) β€’ -x + yβ€– = β€–(I : π•œ) β€’ x - yβ€– := by
rw [← neg_sub, norm_neg, sub_eq_neg_add, ← smul_neg]
have hβ‚„ : β€–(I : π•œ) β€’ -x - yβ€– = β€–(I : π•œ) β€’ x + yβ€– := by rw [smul_neg, ← neg_add', norm_neg]
rw [h₁, hβ‚‚, h₃, hβ‚„]
ring
#align inner_product_spaceable.inner_prop_neg_one InnerProductSpaceable.innerProp_neg_one

theorem _root_.Continuous.inner_ {f g : ℝ β†’ E} (hf : Continuous f) (hg : Continuous g) :
Continuous fun x => inner_ π•œ (f x) (g x) := by
unfold inner_
have := Continuous.const_smul (M := π•œ) hf I
continuity
#align inner_product_spaceable.continuous.inner_ Continuous.inner_

theorem Inner_.norm_sq (x : E) : β€–xβ€– ^ 2 = re (inner_ π•œ x x) := by
simp only [inner_]
have h₁ : IsROrC.normSq (4 : π•œ) = 16 := by
have : ((4 : ℝ) : π•œ) = (4 : π•œ) := by norm_cast
rw [← this, normSq_eq_def', IsROrC.norm_of_nonneg (by norm_num : (0 : ℝ) ≀ 4)]
norm_num
have hβ‚‚ : β€–x + xβ€– = 2 * β€–xβ€– := by rw [← two_smul π•œ, norm_smul, IsROrC.norm_two]
simp only [h₁, hβ‚‚, algebraMap_eq_ofReal, sub_self, norm_zero, mul_re, inv_re, ofNat_re, map_sub,
map_add, ofReal_re, ofNat_im, ofReal_im, mul_im, I_re, inv_im]
ring
#align inner_product_spaceable.inner_.norm_sq InnerProductSpaceable.Inner_.norm_sq

theorem Inner_.conj_symm (x y : E) : conj (inner_ π•œ y x) = inner_ π•œ x y := by
simp only [inner_]
have h4 : conj (4⁻¹ : π•œ) = 4⁻¹ := by norm_num
rw [map_mul, h4]
congr 1
simp only [map_sub, map_add, algebraMap_eq_ofReal, ← ofReal_mul, conj_ofReal, map_mul, conj_I]
rw [add_comm y x, norm_sub_rev]
by_cases hI : (I : π•œ) = 0
Β· simp only [hI, neg_zero, MulZeroClass.zero_mul]
-- Porting note: this replaces `norm_I_of_ne_zero` which does not exist in Lean 4
have : β€–(I : π•œ)β€– = 1 := by
rw [← mul_self_inj_of_nonneg (norm_nonneg I) zero_le_one, one_mul, ← norm_mul,
I_mul_I_of_nonzero hI, norm_neg, norm_one]
have h₁ : β€–(I : π•œ) β€’ y - xβ€– = β€–(I : π•œ) β€’ x + yβ€– := by
trans β€–(I : π•œ) β€’ ((I : π•œ) β€’ y - x)β€–
Β· rw [norm_smul, this, one_mul]
Β· rw [smul_sub, smul_smul, I_mul_I_of_nonzero hI, neg_one_smul, ← neg_add', add_comm, norm_neg]
have hβ‚‚ : β€–(I : π•œ) β€’ y + xβ€– = β€–(I : π•œ) β€’ x - yβ€– := by
trans β€–(I : π•œ) β€’ ((I : π•œ) β€’ y + x)β€–
Β· rw [norm_smul, this, one_mul]
Β· rw [smul_add, smul_smul, I_mul_I_of_nonzero hI, neg_one_smul, ← neg_add_eq_sub]
rw [h₁, hβ‚‚, ← sub_add_eq_add_sub]
simp only [neg_mul, sub_eq_add_neg, neg_neg]
#align inner_product_spaceable.inner_.conj_symm InnerProductSpaceable.Inner_.conj_symm

variable [InnerProductSpaceable E]

private theorem add_left_aux1 (x y z : E) : β€–x + y + zβ€– * β€–x + y + zβ€– =
(β€–2 β€’ x + yβ€– * β€–2 β€’ x + yβ€– + β€–2 β€’ z + yβ€– * β€–2 β€’ z + yβ€–) / 2 - β€–x - zβ€– * β€–x - zβ€– := by
rw [eq_sub_iff_add_eq, eq_div_iff (two_ne_zero' ℝ), mul_comm _ (2 : ℝ), eq_comm]
convert parallelogram_identity (x + y + z) (x - z) using 4 <;> Β· rw [two_smul]; abel

private theorem add_left_aux2 (x y z : E) : β€–x + y - zβ€– * β€–x + y - zβ€– =
(β€–2 β€’ x + yβ€– * β€–2 β€’ x + yβ€– + β€–y - 2 β€’ zβ€– * β€–y - 2 β€’ zβ€–) / 2 - β€–x + zβ€– * β€–x + zβ€– := by
rw [eq_sub_iff_add_eq, eq_div_iff (two_ne_zero' ℝ), mul_comm _ (2 : ℝ), eq_comm]
have hβ‚€ := parallelogram_identity (x + y - z) (x + z)
convert hβ‚€ using 4 <;> Β· rw [two_smul]; abel

private theorem add_left_aux2' (x y z : E) :
β€–x + y + zβ€– * β€–x + y + zβ€– - β€–x + y - zβ€– * β€–x + y - zβ€– =
β€–x + zβ€– * β€–x + zβ€– - β€–x - zβ€– * β€–x - zβ€– +
(β€–2 β€’ z + yβ€– * β€–2 β€’ z + yβ€– - β€–y - 2 β€’ zβ€– * β€–y - 2 β€’ zβ€–) / 2 := by
rw [add_left_aux1, add_left_aux2]; ring

private theorem add_left_aux3 (y z : E) :
β€–2 β€’ z + yβ€– * β€–2 β€’ z + yβ€– = 2 * (β€–y + zβ€– * β€–y + zβ€– + β€–zβ€– * β€–zβ€–) - β€–yβ€– * β€–yβ€– := by
apply eq_sub_of_add_eq
convert parallelogram_identity (y + z) z using 4 <;> (try rw [two_smul]) <;> abel

private theorem add_left_aux4 (y z : E) :
β€–y - 2 β€’ zβ€– * β€–y - 2 β€’ zβ€– = 2 * (β€–y - zβ€– * β€–y - zβ€– + β€–zβ€– * β€–zβ€–) - β€–yβ€– * β€–yβ€– := by
apply eq_sub_of_add_eq'
have hβ‚€ := parallelogram_identity (y - z) z
convert hβ‚€ using 4 <;> (try rw [two_smul]) <;> abel

private theorem add_left_aux4' (y z : E) :
(β€–2 β€’ z + yβ€– * β€–2 β€’ z + yβ€– - β€–y - 2 β€’ zβ€– * β€–y - 2 β€’ zβ€–) / 2 =
β€–y + zβ€– * β€–y + zβ€– - β€–y - zβ€– * β€–y - zβ€– := by
rw [add_left_aux3, add_left_aux4]; ring

private theorem add_left_aux5 (x y z : E) :
β€–(I : π•œ) β€’ (x + y) + zβ€– * β€–(I : π•œ) β€’ (x + y) + zβ€– =
(β€–(I : π•œ) β€’ (2 β€’ x + y)β€– * β€–(I : π•œ) β€’ (2 β€’ x + y)β€– +
β€–(I : π•œ) β€’ y + 2 β€’ zβ€– * β€–(I : π•œ) β€’ y + 2 β€’ zβ€–) / 2 -
β€–(I : π•œ) β€’ x - zβ€– * β€–(I : π•œ) β€’ x - zβ€– := by
rw [eq_sub_iff_add_eq, eq_div_iff (two_ne_zero' ℝ), mul_comm _ (2 : ℝ), eq_comm]
have hβ‚€ := parallelogram_identity ((I : π•œ) β€’ (x + y) + z) ((I : π•œ) β€’ x - z)
convert hβ‚€ using 4 <;> Β· try simp only [two_smul, smul_add]; abel

private theorem add_left_aux6 (x y z : E) :
β€–(I : π•œ) β€’ (x + y) - zβ€– * β€–(I : π•œ) β€’ (x + y) - zβ€– =
(β€–(I : π•œ) β€’ (2 β€’ x + y)β€– * β€–(I : π•œ) β€’ (2 β€’ x + y)β€– +
β€–(I : π•œ) β€’ y - 2 β€’ zβ€– * β€–(I : π•œ) β€’ y - 2 β€’ zβ€–) / 2 -
β€–(I : π•œ) β€’ x + zβ€– * β€–(I : π•œ) β€’ x + zβ€– := by
rw [eq_sub_iff_add_eq, eq_div_iff (two_ne_zero' ℝ), mul_comm _ (2 : ℝ), eq_comm]
have hβ‚€ := parallelogram_identity ((I : π•œ) β€’ (x + y) - z) ((I : π•œ) β€’ x + z)
convert hβ‚€ using 4 <;> Β· try simp only [two_smul, smul_add]; abel

private theorem add_left_aux7 (y z : E) :
β€–(I : π•œ) β€’ y + 2 β€’ zβ€– * β€–(I : π•œ) β€’ y + 2 β€’ zβ€– =
2 * (β€–(I : π•œ) β€’ y + zβ€– * β€–(I : π•œ) β€’ y + zβ€– + β€–zβ€– * β€–zβ€–) - β€–(I : π•œ) β€’ yβ€– * β€–(I : π•œ) β€’ yβ€– := by
apply eq_sub_of_add_eq
have hβ‚€ := parallelogram_identity ((I : π•œ) β€’ y + z) z
convert hβ‚€ using 4 <;> Β· try simp only [two_smul, smul_add]; abel

private theorem add_left_aux8 (y z : E) :
β€–(I : π•œ) β€’ y - 2 β€’ zβ€– * β€–(I : π•œ) β€’ y - 2 β€’ zβ€– =
2 * (β€–(I : π•œ) β€’ y - zβ€– * β€–(I : π•œ) β€’ y - zβ€– + β€–zβ€– * β€–zβ€–) - β€–(I : π•œ) β€’ yβ€– * β€–(I : π•œ) β€’ yβ€– := by
apply eq_sub_of_add_eq'
have hβ‚€ := parallelogram_identity ((I : π•œ) β€’ y - z) z
convert hβ‚€ using 4 <;> Β· try simp only [two_smul, smul_add]; abel

theorem add_left (x y z : E) : inner_ π•œ (x + y) z = inner_ π•œ x z + inner_ π•œ y z := by
simp only [inner_, ← mul_add]
congr
simp only [mul_assoc, ← map_mul, add_sub_assoc, ← mul_sub, ← map_sub]
rw [add_add_add_comm]
simp only [← map_add, ← mul_add]
congr
Β· rw [← add_sub_assoc, add_left_aux2', add_left_aux4']
Β· rw [add_left_aux5, add_left_aux6, add_left_aux7, add_left_aux8]
simp only [map_sub, map_mul, map_add, div_eq_mul_inv]
ring
#align inner_product_spaceable.add_left InnerProductSpaceable.add_left

theorem nat (n : β„•) (x y : E) : inner_ π•œ ((n : π•œ) β€’ x) y = (n : π•œ) * inner_ π•œ x y := by
induction' n with n ih
Β· simp only [inner_, Nat.zero_eq, zero_sub, Nat.cast_zero, MulZeroClass.zero_mul,
eq_self_iff_true, zero_smul, zero_add, MulZeroClass.mul_zero, sub_self, norm_neg, smul_zero]
Β· simp only [Nat.cast_succ, add_smul, one_smul]
rw [add_left, ih, add_mul, one_mul]
#align inner_product_spaceable.nat InnerProductSpaceable.nat

private theorem nat_prop (r : β„•) : innerProp' E (r : π•œ) := fun x y => by
simp only [map_natCast]; exact nat r x y

private theorem int_prop (n : β„€) : innerProp' E (n : π•œ) := by
intro x y
rw [← n.sign_mul_natAbs]
simp only [Int.cast_ofNat, map_natCast, map_intCast, Int.cast_mul, map_mul, mul_smul]
obtain hn | rfl | hn := lt_trichotomy n 0
Β· rw [Int.sign_eq_neg_one_of_neg hn, innerProp_neg_one ((n.natAbs : π•œ) β€’ x), nat]
simp only [map_neg, neg_mul, one_mul, mul_eq_mul_left_iff, true_or_iff, Int.natAbs_eq_zero,
eq_self_iff_true, Int.cast_one, map_one, neg_inj, Nat.cast_eq_zero, Int.cast_neg]
Β· simp only [inner_, Int.cast_zero, zero_sub, Nat.cast_zero, MulZeroClass.zero_mul,
eq_self_iff_true, Int.sign_zero, zero_smul, zero_add, MulZeroClass.mul_zero, smul_zero,
sub_self, norm_neg, Int.natAbs_zero]
Β· rw [Int.sign_eq_one_of_pos hn]
simp only [one_mul, mul_eq_mul_left_iff, true_or_iff, Int.natAbs_eq_zero, eq_self_iff_true,
Int.cast_one, one_smul, Nat.cast_eq_zero, nat]

private theorem rat_prop (r : β„š) : innerProp' E (r : π•œ) := by
intro x y
have : (r.den : π•œ) β‰  0 := by
haveI : CharZero π•œ := IsROrC.charZero_isROrC
exact_mod_cast r.pos.ne'
rw [← r.num_div_den, ← mul_right_inj' this, ← nat r.den _ y, smul_smul, Rat.cast_div]
simp only [map_natCast, Rat.cast_coe_nat, map_intCast, Rat.cast_coe_int, map_divβ‚€]
rw [← mul_assoc, mul_div_cancel' _ this, int_prop _ x, map_intCast]

private theorem real_prop (r : ℝ) : innerProp' E (r : π•œ) := by
intro x y
revert r
rw [← Function.funext_iff]
refine' Rat.denseEmbedding_coe_real.dense.equalizer _ _ (funext fun X => _)
Β· exact (continuous_ofReal.smul continuous_const).inner_ continuous_const
Β· exact (continuous_conj.comp continuous_ofReal).mul continuous_const
Β· simp only [Function.comp_apply, IsROrC.ofReal_ratCast, rat_prop _ _]

private theorem I_prop : innerProp' E (I : π•œ) := by
by_cases hI : (I : π•œ) = 0
Β· rw [hI, ← Nat.cast_zero]; exact nat_prop _
intro x y
have hI' : (-I : π•œ) * I = 1 := by rw [← inv_I, inv_mul_cancel hI]
rw [conj_I, inner_, inner_, mul_left_comm]
congr 1
rw [smul_smul, I_mul_I_of_nonzero hI, neg_one_smul]
rw [mul_sub, mul_add, mul_sub, mul_assoc I (π“š β€–I β€’ x - yβ€–), ← mul_assoc (-I) I, hI', one_mul,
mul_assoc I (π“š β€–I β€’ x + yβ€–), ← mul_assoc (-I) I, hI', one_mul]
have h₁ : β€–-x - yβ€– = β€–x + yβ€– := by rw [← neg_add', norm_neg]
have hβ‚‚ : β€–-x + yβ€– = β€–x - yβ€– := by rw [← neg_sub, norm_neg, sub_eq_neg_add]
rw [h₁, hβ‚‚]
simp only [sub_eq_add_neg, mul_assoc]
rw [← neg_mul_eq_neg_mul, ← neg_mul_eq_neg_mul]
abel

theorem innerProp (r : π•œ) : innerProp' E r := by
intro x y
rw [← re_add_im r, add_smul, add_left, real_prop _ x, ← smul_smul, real_prop _ _ y, I_prop,
map_add, map_mul, conj_ofReal, conj_ofReal, conj_I]
ring
#align inner_product_spaceable.inner_prop InnerProductSpaceable.innerProp

end InnerProductSpaceable

open InnerProductSpaceable

/-- **FrΓ©chet–von Neumann–Jordan Theorem**. A normed space `E` whose norm satisfies the
parallelogram identity can be given a compatible inner product. -/
noncomputable def InnerProductSpace.ofNorm
(h : βˆ€ x y : E, β€–x + yβ€– * β€–x + yβ€– + β€–x - yβ€– * β€–x - yβ€– = 2 * (β€–xβ€– * β€–xβ€– + β€–yβ€– * β€–yβ€–)) :
InnerProductSpace π•œ E :=
haveI : InnerProductSpaceable E := ⟨h⟩
{ inner := inner_ π•œ
norm_sq_eq_inner := Inner_.norm_sq
conj_symm := Inner_.conj_symm
add_left := InnerProductSpaceable.add_left
smul_left := fun _ _ _ => innerProp _ _ _ }
#align inner_product_space.of_norm InnerProductSpace.ofNorm

variable (E)

variable [InnerProductSpaceable E]

/-- **FrΓ©chet–von Neumann–Jordan Theorem**. A normed space `E` whose norm satisfies the
parallelogram identity can be given a compatible inner product. Do
`casesI nonempty_innerProductSpace π•œ E` to locally upgrade `InnerProductSpaceable E` to
`InnerProductSpace π•œ E`. -/
theorem nonempty_innerProductSpace : Nonempty (InnerProductSpace π•œ E) :=
⟨{ inner := inner_ π•œ
norm_sq_eq_inner := Inner_.norm_sq
conj_symm := Inner_.conj_symm
add_left := add_left
smul_left := fun _ _ _ => innerProp _ _ _ }⟩
#align nonempty_inner_product_space nonempty_innerProductSpace

variable {π•œ E}

variable [NormedSpace ℝ E]

-- TODO: Replace `InnerProductSpace.toUniformConvexSpace`
-- See note [lower instance priority]
instance (priority := 100) InnerProductSpaceable.to_uniformConvexSpace : UniformConvexSpace E := by
cases nonempty_innerProductSpace ℝ E; infer_instance
#align inner_product_spaceable.to_uniform_convex_space InnerProductSpaceable.to_uniformConvexSpace

0 comments on commit a2fecf3

Please sign in to comment.