Zulip Chat Archive

Stream: new members

Topic: Sums of subspaces (Axler's Linear Algebra Done Right)


Arien Malec (Feb 25 2024 at 00:34):

I've got Axler's Linear Algebra done up to (checks notes) page 20... at https://github.com/arienmalec/axler

I'm up to Sums of Subspaces which are defined as "the set of all possible sums of elements" of the respective subspaces. I see definitions for finite sums, and for direct sums, but not for (possibly infinite) sums, as Axler defines.

An example proof here is that if U = {<x, 0, 0>} and V = {<0, y, 0>} over R^3 then U + V = {<x, y, 0>}

What's the natural translation in Mathlib terms?

Matt Diamond (Feb 25 2024 at 01:26):

infinite sums are docs#tsum, I think...

Arien Malec (Feb 25 2024 at 01:39):

Hmm. Has a TopologicalSpace constraint....

Arien Malec (Feb 25 2024 at 01:40):

Is Axler's definition AoC under the hood?

Timo Carlin-Burns (Feb 25 2024 at 01:42):

The standard notation for this is U ⊔ V or if you open Pointwise, U + V.

Arien Malec (Feb 25 2024 at 01:42):

Googling, is this AKA the Minkowski sum

Timo Carlin-Burns (Feb 25 2024 at 01:43):

Infinite sums mean something different from pointwise sums of (possibly infinite) sets

Arien Malec (Feb 25 2024 at 22:24):

I'm down to this goal state, which should close easily, but unsure what closes it

import Mathlib.Data.Real.Basic
import Mathlib.Data.Fin.VecNotation

example {y z: }: Add.add ![y, 0, 0] ![0, z, 0] = ![y, z, 0] := by sorry

Ruben Van de Velde (Feb 25 2024 at 22:34):

Maybe ext; simp, or with fin_cases in between?

Ruben Van de Velde (Feb 25 2024 at 22:35):

Though it's odd that you have Add.add rather than +

Eric Wieser (Feb 25 2024 at 22:57):

The subspace of elements formed from finite sums of an infinite family of subspaces is ⨆ i, p i

Arien Malec (Feb 26 2024 at 01:00):

Ruben Van de Velde said:

Though it's odd that you have Add.add rather than +

Overaggressive simp

Kevin Buzzard (Feb 26 2024 at 07:08):

But simp shouldn't change + to Add.add -- it should be the other way around!

Arien Malec (Feb 26 2024 at 16:25):

I requested simp of HAdd.hAdd, Set.add -- I'm sure there's a better way here...

Arien Malec (Feb 26 2024 at 16:26):

The original setup and current proof state are:

import Mathlib.Data.Real.Basic
import Mathlib.Data.Fin.VecNotation
import Mathlib.Tactic

open Pointwise
def ex1_37_U : (Set (Fin 3  )) :=
  { ![x₁, 0, 0] | (x₁: )}
def ex1_37_V : (Set (Fin 3  )) :=
  { ![0, x₂, 0] |  (x₂ : )}

theorem ex1_37: ex1_37_U + ex1_37_V = { ![x₁, x₂, 0] | (x₁: ) (x₂: )} := by
  simp [ex1_37_U,ex1_37_V]
  simp [HAdd.hAdd, Set.add, Set.image2]
  ext x; constructor <;> intro h
  . cases' h with y h
    cases' h with z h
    simp [Set.mem_setOf_eq, *] at *
    use y; use z
    rw [h]; symm
    have h2: ![y, 0, 0] + ![0, z, 0] = ![y, z, 0] := by
      ext x ; fin_cases x <;> simp
    exact h2
  . simp at *
    rcases h with y,z, h
    use y; use z
    rw [h]
    have h2: ![y, 0, 0] + ![0, z, 0] = ![y, z, 0] := by
      ext x ; fin_cases x <;> simp
    exact h2

Damiano Testa (Feb 26 2024 at 16:29):

You could also do

theorem ex1_37: ex1_37_U + ex1_37_V = { ![x₁, x₂, 0] | (x₁: ) (x₂: )} := by
  ext x
  simp [Set.mem_add, ex1_37_U,ex1_37_V]

Damiano Testa (Feb 26 2024 at 16:31):

(and if you used abbrev instead of defs, you would not even need to explicitly unfold ex1_37_U and ex1_37_V.)

Arien Malec (Feb 26 2024 at 16:35):

That's, uh, quite a bit simpler

Damiano Testa (Feb 26 2024 at 16:37):

If you look at the statement, it is simply saying that a double existential is the same a two consecutive existentials: this is something that simp should know about and you simply have to tell it what it means to be a member of the sum of two sets. Hence, simp [Set.mem_add] (+ the unfolding).

Damiano Testa (Feb 26 2024 at 16:39):

Also, as an almost universal rule: unfolding Add.add (or similar instances) means you are making your proof harder than it should be.

Damiano Testa (Feb 26 2024 at 16:40):

You should trust that whoever defined Add.add also introduced the useful statements about it. You could be in a situation where there is missing API, but then you should look for the missing API lemma, instead of embedding it into your proof.

Arien Malec (Feb 26 2024 at 21:03):

The trick was using ext prior -- I tried mem_add previously.

Arien Malec (Feb 27 2024 at 21:30):

Here's where this got to -- weird that add_mem' required a bunch of tactics where the others are simp. Digging around, it seems like some of the core lemmata in Mathlib.Data.Fin.VecNotation were dependent on bit0/1 in Mathlib3?

Arien Malec (Feb 27 2024 at 21:30):

import Mathlib.Data.Real.Basic
import Mathlib.Data.Fin.VecNotation
import Mathlib.Tactic

open Pointwise

def subspace_ex1_37_U: Submodule  (Fin 3  ) where
  carrier :=  { ![x₁, 0, 0] | (x₁: )}
  zero_mem' := by simp
  add_mem' := by simp; intro _ _ x c y d; use (x + y); rw [c, d]; ext z; simp; fin_cases z <;> simp
  smul_mem' := by simp

def subsdpace_ex1_37_V: Submodule  (Fin 3  ) where
  carrier := { ![0, x₂, 0] |  (x₂ : )}
  zero_mem' := by simp
  smul_mem' := by simp
  add_mem' := by simp; intro _ _ x c y d; use (x + y); rw [c, d]; ext z; simp; fin_cases z <;> simp

theorem ex1_37: { ![x₁, 0, 0] | (x₁: )} + { ![0, x₂, 0] |  (x₂ : )} = { ![x₁, x₂, 0] | (x₁: ) (x₂: )} := by
  ext x ; simp [Set.mem_add]

#synth Module  (subspace_ex1_37_U + subsdpace_ex1_37_V)

Damiano Testa (Feb 27 2024 at 21:32):

aesop proves your add_mem' fields.

Arien Malec (Feb 27 2024 at 21:47):

I'm a bit burnt by hint telling me to try aesop then aesop failing to do anything :-)

Arien Malec (Feb 27 2024 at 22:17):

How do I show that U + V is Submodule ℝ (Fin 3 → ℝ)?

Arien Malec (Feb 27 2024 at 22:21):

Ah #check

Yakov Pechersky (Feb 27 2024 at 22:36):

It follows from the definition of "Submodule" and the fact it has an Add instance, so it's a bit of a tautology. I think a more "rigorous" way would be to show that

def U_plus_V : Submodule R ... where
  carrier := pointwise addition of U as a set and V as a set
  prove the axioms of a Submodule

and then show that U_plus_V = U + V (either as submodules or as sets). I bet the proof will be ext; rfl or rfl.

Yakov Pechersky (Feb 27 2024 at 22:38):

which is basically the specialization of the proof that (. + .) as defined respects the submodule conditions

Arien Malec (Feb 27 2024 at 22:40):

Yeah, the instance for AddCommMonoid does the work to show the closure....

Kim Morrison (Feb 28 2024 at 02:58):

Arien Malec said:

I'm a bit burnt by hint telling me to try aesop then aesop failing to do anything :-)

@Arien Malec, do we have a repro for this? Please ping me and/or Jannis if so.

Arien Malec (Feb 28 2024 at 04:13):

Next time I see it, I'll #MWE

Arien Malec (Feb 28 2024 at 04:19):

#MWE for @Scott Morrison

import Mathlib.Data.Real.Basic
import Mathlib.Data.Fin.VecNotation
import Mathlib.Tactic

open Pointwise
def ex4_Subspace: Submodule  (  ) where
  carrier := { f | ( x  Set.Ioo (0 : )  (3: ), DifferentiableAt  f x)  (HasDerivAt f 0 2)}
  zero_mem' := by
    constructor
    . intro _ _
      exact differentiableAt_const 0
    . apply hasDerivAtFilter_const
  add_mem' := by aesop
    -- intro a b h1 h2
    -- constructor
    -- . intro x h
    --   rcases (h1.left x h) with ⟨ f'x, f_has ⟩
    --   rcases (h2.left x h) with ⟨ g'x, g_has ⟩
    --   use f'x + g'x
    --   exact f_has.add g_has
    -- . have h3:= h1.right.add h2.right
    --   simp [@Pi.add_def] at *
    --   assumption
  smul_mem' := by
    intro a f hf
    cases' hf with hf1 hf2
    constructor
    . intro b h
      have h2 := (hf1 b h).smul_const a
      simp [@Pi.smul_def] at *
      simp_rw [mul_comm a (f _)]
      exact h2
    . have h := hf2.smul_const a
      simp [@Pi.smul_def] at *
      simp_rw [mul_comm a (f _)]
      exact h

Arien Malec (Feb 28 2024 at 04:21):

hint here says to try aesop, but aesop does nothing.

Eric Wieser (Feb 28 2024 at 10:14):

Doesn't aesop do intros?

Kevin Buzzard (Feb 28 2024 at 13:35):

Note that hint gives suggestions plus what the goal will be after you try these suggestions, if hint can't close the goal. If hint closes the goal then the suggestion is in green, and if it doesn't then the suggestion is in blue.

Arien Malec (Feb 28 2024 at 16:03):

Here, the aesop goal state is a garble

 DifferentiableAt  (_uniq.201000 + _uniq.201001) _uniq.233268
 HasDerivAt (_uniq.201000 + _uniq.201001) 0 2

It's possible I just need to update Mathlib?

Arien Malec (Feb 28 2024 at 16:09):

Anyway, the lass proof in Axler is
"Suppose 𝑉_1, ..., 𝑉_𝑚 are subspaces of 𝑉. Then 𝑉_1 + ⋯ + 𝑉_𝑚 is the smallest subspace of 𝑉 containing 𝑉_1, ..., 𝑉_𝑚."

When I translate this to Lean and Mathlib the way I understand it (post exposure to Lean and Mathlib, I find myself staring at simple definitions not understanding what they are supposed to mean), I get something like:

variable (F V: Type*) [Field F] [AddCommGroup V] [Module F V]
example axler_1_40 {U V W: (Submodule F V)}:  (x:V), x  U.carrier  x  V.carrier  x  W.carrier  (U + V).carrier  W.carrier := sorry

But not only doesn't this work, it's so set theoretic that it's certainly not the right way to express the proof statement and proofs in terms of carrier seem suspect anyway. Is this a one liner in Mathlib? What's the right way to express the proof statement?

Arien Malec (Feb 28 2024 at 16:11):

Arien Malec said:

Here, the aesop goal state is a garble

 DifferentiableAt  (_uniq.201000 + _uniq.201001) _uniq.233268
 HasDerivAt (_uniq.201000 + _uniq.201001) 0 2

It's possible I just need to update Mathlib?

Just tried to update Mathlib and same state.

Timo Carlin-Burns (Feb 28 2024 at 16:33):

Are you getting concerned because of the _uniq.N? I think those are just computer-generated variable names

Timo Carlin-Burns (Feb 28 2024 at 16:33):

That goal state is not necessarily indicative of a problem

Patrick Massot (Feb 28 2024 at 16:36):

It is definitely a bug in aseop, a missing context update.

Patrick Massot (Feb 28 2024 at 16:42):

@Arien Malec you are not getting help about your latest question because you didn’t provide a #mwe.

Patrick Massot (Feb 28 2024 at 16:43):

Otherwise I’d be happy to help.

Arien Malec (Feb 28 2024 at 16:52):

Thanks!

import Mathlib.Algebra.Module.Submodule.Basic
import Mathlib.Algebra.Module.Submodule.Pointwise


/-

Axler, Linear Algebra Done Right, Example 1.40:

"Suppose `𝑉_1, ..., 𝑉_𝑚` are subspaces of `𝑉`. Then `𝑉_1 + ⋯ + 𝑉_𝑚` is the smallest subspace of `𝑉`
containing `𝑉_1, ..., 𝑉_𝑚`."

We know `V_1 + ... + V_m` is a subspace because the `Submodule.pointwiseAddCommMonoid` instance
proves additive closure.

If we can prove the claim of "smallest" for pairs of subspaces `U` and `V` we can prove for arbitrary
additve chains by _waves hand_ *induction*
-/
open Pointwise

variable (F V: Type*) [Field F] [AddCommGroup V] [Module F V]
example {S T W: (Submodule F V)}:  (x:V), (x  S.carrier)  (x  T.carrier)  (x  W.carrier)  (S + T).carrier  W.carrier := sorry

Arien Malec (Feb 28 2024 at 16:55):

The supplied translation is absolutely wrong for the reasons I mentioned above. The Axler paper proof is intuitive : "Conversely, every subspace of 𝑉 containing 𝑉1, ..., 𝑉𝑚 contains 𝑉1 + ⋯ + 𝑉𝑚 (because subspaces must contain all finite sums of their elements). Thus 𝑉1 +⋯+𝑉𝑚 is the smallest subspace of 𝑉 containing 𝑉1, ..., 𝑉𝑚."

Arien Malec (Feb 28 2024 at 16:56):

I don't even know the Mathlibism for proof over potentially countably infinite chains of operations. The computer scientist in me is content to think about this as recursion with the base case of a pair.

Patrick Massot (Feb 28 2024 at 16:58):

Why do you write all those carrier?

Patrick Massot (Feb 28 2024 at 16:59):

And you have several things called V

Patrick Massot (Feb 28 2024 at 17:04):

And you try to name an example so Lean is completely confused. Note that your binders choices are completely random but this isn’t a problem for an example since you cannot use it anyway.

Patrick Massot (Feb 28 2024 at 17:06):

You got your operator precedence wrong to. Your statement is not what you intended, even after fixing syntax issues.

Arien Malec (Feb 28 2024 at 17:22):

The textual proof claim is that V + U is the smallest subspace containing V and U. When I try to translate what "containing" is supposed to mean, I think I want "if v is in V then v is in W" or the type theoretic version of that. The carrier stuff is admittedly wrong -- as I wrote above: "But not only doesn't this work, it's so set theoretic that it's certainly not the right way to express the proof statement and proofs in terms of carrier seem suspect anyway."

Arien Malec (Feb 28 2024 at 17:24):

Fixed the syntax issues -- the V confusion hid the fact that example isn't named...

Arien Malec (Feb 28 2024 at 17:28):

Also parenthesized to make operator precedence clearer. But again, I'm not claiming this translation is correct -- the help I'm looking for is "what is the Mathlib statement that means "every subspace of 𝑉 containing 𝑉1, ..., 𝑉𝑚 contains 𝑉1 + ⋯ + 𝑉𝑚 ... thus 𝑉1 +⋯+𝑉𝑚 is the smallest subspace of 𝑉 containing 𝑉1, ..., 𝑉𝑚"

Arien Malec (Feb 28 2024 at 17:39):

(or the translation of that down to "every subspace of V containing V_1 and V_2 contains V_1 + V_2 thus....")

Patrick Massot (Feb 28 2024 at 17:56):

The parentheses are still wrong because the implication arrow is right-associative.

Patrick Massot (Feb 28 2024 at 17:56):

What you mean is

Patrick Massot (Feb 28 2024 at 17:57):

variable {F M : Type*} [Field F] [AddCommGroup M] [Module F M]

example {U V W : Submodule F M} : ( x : M, x  U  x  V  x  W)  U + V  W

Patrick Massot (Feb 28 2024 at 18:06):

I don’t understand why aesop can’t do that without hand-holding.

example {U V W : Submodule F M} : ( x : M, x  U  x  V  x  W)  U + V  W := by
  intros h
  simp
  constructor
  all_goals
  intro x hx
  aesop

Patrick Massot (Feb 28 2024 at 18:07):

Anyway the two lemmas you wanted are docs#Submodule.add_eq_sup and the very generic docs#sup_le_iff

Patrick Massot (Feb 28 2024 at 18:08):

The first one is getting rid of the pointwise addition stuff that is the very wrong way of thinking about this, and then it becomes a completely generic reasoning.

Arien Malec (Feb 28 2024 at 18:54):

:pray:

Arien Malec (Feb 28 2024 at 21:14):

Although I'm confused in general about Sup as a binary operator (rather than as a unary operator on a set), and in specific about how add_eq_sup in this case.... Any pointers to the underlying treatment here would be helpful.

Patrick Massot (Feb 28 2024 at 21:16):

Whenever the unary on the set version exists (which is a very strong assumption on an ordered type) then the binary one on elements a and b is the unary one on sets on {a, b}.

Patrick Massot (Feb 28 2024 at 21:18):

Maybe you should watch the beginning of https://www.slmath.org/summer-schools/1021/schedules/33442 which explains this stuff.

Patrick Massot (Feb 28 2024 at 21:19):

I think I mentioned the story of sums of subspaces during that lecture.

Patrick Massot (Feb 28 2024 at 21:21):

It also appears a bit in Chapter 8 of #mil when discussing subgroups.

Arien Malec (Feb 28 2024 at 21:39):

Thank you -- your lecture is incredibly helpful! There's so much embedded in the structure of Mathlib that, particularly in the exercise that I'm trying (formalizing second year linear algebra) I need to jump from the math that's in the text book to the more abstract concepts that Mathlib is built out of...


Last updated: May 02 2025 at 03:31 UTC