Zulip Chat Archive

Stream: new members

Topic: Super basic linear algebra in Mathlib?


Arien Malec (Nov 30 2023 at 21:14):

Back at doing Axler in Lean, and I realize that I know next to nothing about how to put the Mathlib4 parts together. If I wanted to show that vectors in $R^n$ form a vector space, what is the most basic Mathlib setup?

Richard Copley (Nov 30 2023 at 21:47):

Maybe this?

import Mathlib.LinearAlgebra.Basic
import Mathlib.Data.Real.Basic

#synth (n : )  Module  (Fin n  )

There's some mention of modules in Section 8.2 of Mathematics in Lean 4, but the promised chapter on linear algebra doesn't appear to be there yet, unless I missed something.

Eric Wieser (Nov 30 2023 at 21:47):

(deleted: Richard posted a better version of the same thing!)

Eric Wieser (Nov 30 2023 at 21:49):

Though in case it's unclear, you could also write:

variable (n : )

#synth Module  (Fin n  )

Arien Malec (Nov 30 2023 at 23:02):

Cool -- but seems like magic? I get fun n => Pi.module (Fin n) (fun a => ℝ) ℝ -- have I gotten for free proofs of the various laws for vector addition and scalar multiplication? If so, where did they come from? How might I have done them myself? There's this weird space in Mathlib where doing things from first principles is easy, and doing hard things is possible but doing easy things is seemingly hard....

Eric Wieser (Nov 30 2023 at 23:03):

Yes, you did indeed get them all for free! The message is telling you where the laws for scalar multiplication came from; docs#Pi.module

Eric Wieser (Nov 30 2023 at 23:03):

#synth AddCommGroup ℝ (Fin n → ℝ) will tell you where the laws for addition came from

Eric Wieser (Nov 30 2023 at 23:05):

Though the source code for either will not be particularly insightful

Arien Malec (Nov 30 2023 at 23:05):

Yeah, that was my first stop....

Eric Wieser (Nov 30 2023 at 23:11):

https://www.youtube.com/watch?v=L_VDsP9_ty8 or https://leanprover-community.github.io/mathematics_in_lean/C06_Structures.html#algebraic-structures has an exercise that has you prove that {x, y, z} structures form an additive group

Eric Wieser (Nov 30 2023 at 23:12):

I don't know if we have any exercises for doing the analogous thing for vector spaces

Eric Wieser (Nov 30 2023 at 23:12):

(note that both links come with corresponding exercise files)

Arien Malec (Nov 30 2023 at 23:43):

Where did the instance for Add and SMul for (Fin n → ℝ) come from?

Jireh Loreaux (Dec 01 2023 at 01:40):

docs#Pi.instAdd docs#Pi.instSMul

Jireh Loreaux (Dec 01 2023 at 01:43):

Basically, when the codomain has some operation, you can put an operation onto the functions by just defining that operation pointwise.

Arien Malec (Dec 01 2023 at 21:45):

If I've got this right, this is the non-magic version?

import Mathlib.Tactic

@[ext]
structure Rn (n:  ) where
  term: Fin n  

instance addRn: Add (Rn n) where
  add a b := fun n => a.term n + b.term n

@[simp]
theorem add_ext {a b : (Rn n)} {x: Fin n}: (a + b).term x = a.term x + b.term x := rfl

instance smulRn: SMul  (Rn n) where
  smul x a := fun n => x * a.term n

@[simp]
theorem smul_ext {a : Rn n} {x: } {y: Fin n}: (x  a).term y = x  (a.term y) := rfl

instance zeroRn: Zero (Rn n) where
  zero := fun _ => 0

@[simp]
theorem zero_ext: (0 :Rn n).term x = 0 := rfl

instance addCommMonoidRn: AddCommMonoid (Rn n) where
  add_comm a b := by  ext ; simp [add_comm]
  add_assoc a b c := by ext ; simp [add_assoc]
  zero := zeroRn.zero
  add_zero a := by ext ; simp only [add_ext, add_zero, zero_ext]
  zero_add a := by ext ; simp only [add_ext, zero_add, zero_ext]

instance moduleRn: Module  (Rn n) where
  one_smul a := by ext; simp
  zero_smul a := by ext; simp
  smul_zero a := by ext; simp
  smul_add a b c := by ext; simp [mul_add]
  add_smul a b c := by ext; simp [add_mul]
  mul_smul a b c := by ext; simp [mul_assoc]

Eric Wieser (Dec 01 2023 at 22:02):

That looks good to me: though your lemmas are strangely named, we would normally call your add_ext term_add_apply since it's applying term to add

Arien Malec (Dec 02 2023 at 17:17):

How would I generalize the declaration of Rn to Fn where it works across any field? Axler wants proofs that work for what he defines as F which is real or complex (I know there's a "real or complex" type somewhere in Mathlib as well).

If I do

import Mathlib.Tactic
import Mathlib.Algebra.Field.Basic

@[ext]
structure Rn [Field F] (n: ) where
  term: Fin n  F

instance addRn: Add (Rn n) where
  add a b := fun n => a.term n + b.term n

I get a typeclass instance stuck issue.

Richard Copley (Dec 02 2023 at 17:40):

instance addRn [Field F] : Add (Rn n) where
  add a b := fun n => a.term n + b.term n

Eric Wieser (Dec 02 2023 at 18:00):

Surely that doesn't work Richard; does lean really guess F?

Eric Wieser (Dec 02 2023 at 18:00):

@Arien Malec: can you add imports and any variables to your example?

Arien Malec (Dec 02 2023 at 18:29):

Oops, forgot the MWE norms. Done.

Arien Malec (Dec 02 2023 at 18:30):

Can confirm adding [Field F] doesn't work...

Richard Copley (Dec 02 2023 at 19:07):

Eric Wieser said:

Surely that doesn't work Richard; does lean really guess F?

I assumed there was a variable {F : Type*} somewhere, rather than the F in Rn being an autoImplicit.

@Arien Malec, since the F you're implicitly passing to Rn has no name in addRn, there's no way to tell Lean that it is a field. Something like this should work:

import Mathlib.Tactic
import Mathlib.Algebra.Field.Basic

set_option autoImplicit false

@[ext]
structure Rn (F : Type*) [Field F] (n: ) where
  term: Fin n  F

instance addRn (F : Type*) [Field F] (n : ) : Add (Rn F n) where
  add a b := fun n => a.term n + b.term n

Arien Malec (Dec 02 2023 at 19:32):

Was racking my brain trying to see the difference between what I did and this until I saw the explicit F... Thanks!

Arien Malec (Dec 02 2023 at 20:44):

Also realized you need to change F from being explicit to being implicit....

Arien Malec (Dec 02 2023 at 20:45):

import Mathlib.Tactic
import Mathlib.Algebra.Field.Basic

variable (F: Type _)
variable [Field F]

@[ext]
structure Fn (n: ) where
  term: Fin n  F

variable {F}

instance addRn {n: }: Add (Fn F n) where
  add a b := fun n => a.term n + b.term n

@[simp]
theorem term_add_apply {n: } {a b : (Fn F n)} {x: Fin n}: (a + b).term x = a.term x + b.term x := rfl

instance smulRn: SMul F (Fn F n) where
  smul x a := fun n => x * a.term n

@[simp]
theorem term_smul_apply {a : Fn F n} {x: F} {y: Fin n}: (x  a).term y = x  (a.term y) := rfl

instance zeroRn: Zero (Fn F n) where
  zero := fun _ => 0

@[simp]
theorem zero_term: (0 :Fn F n).term x = 0 := rfl

instance addCommMonoidRn: AddCommMonoid (Fn F n) where
  add_comm a b := by  ext ; simp [add_comm]
  add_assoc a b c := by ext ; simp [add_assoc]
  zero := zeroRn.zero
  add_zero a := by ext ; simp only [term_add_apply, add_zero, zero_term]
  zero_add a := by ext ; simp only [term_add_apply, zero_add, zero_term]

instance moduleRn: Module F (Fn F n) where
  one_smul a := by ext; simp
  zero_smul a := by ext; simp
  smul_zero a := by ext; simp
  smul_add a b c := by ext; simp [mul_add]
  add_smul a b c := by ext; simp [add_mul]
  mul_smul a b c := by ext; simp [mul_assoc]

Arien Malec (Dec 02 2023 at 20:47):

Where again the automagic version is
#synth (n: ℕ) → Module F (Fin n → F)


Last updated: Dec 20 2023 at 11:08 UTC