Zulip Chat Archive
Stream: Is there code for X?
Topic: Complexification of a real vector space
Arien Malec (Dec 13 2023 at 18:30):
I assume this (Exercise 1B Problem 7) from Axler's Linear Algebra is a one liner in Mathlib, but what one liner is it?
Suppose π is a real vector space.
β’ The complexification of π, denoted by ππ , equals π Γ π. An element of
ππ is an ordered pair( π’,π£),whereπ’,π£ β π, but we write this as π’+ππ£.
β’ Addition on ππ is defined by
(π’1 +ππ£1)+(π’2 +ππ£2) = (π’1 +π’2)+π(π£1 +π£2) for all π’1,π£1,π’2,π£2 βπ.
β’ Complex scalar multiplication on ππ is defined by (π+ππ)(π’+ππ£) = (ππ’βππ£)+π(ππ£+ππ’)
for all π, π β π and all π’, π£ β π.
Prove that with the definitions of addition and scalar multiplication as above,
ππ is a complex vector space.
Eric Rodriguez (Dec 13 2023 at 18:48):
This will be done with the tensor product in mathlib
Arien Malec (Dec 13 2023 at 19:26):
Something like:
variable [Module β V]
#synth Module β (TensorProduct β V V)
?
Eric Wieser (Dec 13 2023 at 20:07):
No, more like:
import Mathlib
variable {V} [AddCommGroup V] [Module β V]
open scoped TensorProduct
#synth Module β (β β[β] V)
Eric Wieser (Dec 13 2023 at 20:12):
You can then prove your first bullet point as
def prodEquivComplexTensor : V Γ V β β β[β] V := sorry
and the second one as
theorem smul_def (c : β) (a : V Γ V) :
c β’ prodEquivComplexTensor b = prodEquivComplexTensor (c.re β’ a.1 - c.im β’ a.2, c.re β’ a.1 + c.im β’ a.2) := by
sorry
Arien Malec (Dec 17 2023 at 02:58):
I've been beating my head against the first theorem without seeing any cracks in the armor -- any Mathlib theorems that simply or open up the proof.
Richard Copley (Dec 17 2023 at 03:35):
TensorProduct.prodLeft
or TensorProduct.prodRight
should help.
Arien Malec (Dec 17 2023 at 04:46):
I'm having trouble getting the right types in place.... prodLeft
wants to distribute a product over a tensor product.
Richard Copley (Dec 17 2023 at 05:03):
Can you show β ββ[R] (β Γ β)
? (It's hard to guess exactly how far you've got.)
Arien Malec (Dec 17 2023 at 05:03):
huh... Nice idea...
Arien Malec (Dec 17 2023 at 05:05):
You can assume that I've been searching for relating things in Mathlib and trying to see if I can find a chain of structural decomposition to force fit.
Richard Copley (Dec 17 2023 at 05:08):
Then there's TensorProduct.rid
and TensorProduct.lid
.
Arien Malec (Feb 17 2024 at 19:49):
OK, coming back to this, I've done the brute force approach that Axler is looking for, by making a structure Vc
with addition and multiplication as designated, and showing that it's a complex vector space.
(btw, when I look at introductions to complexification, the order of the tensor product is opposite to the (β β[β] V)
but rather (V β[β] β)
?)
The more mathy flavor of this is still beyond me. I think what @Eric Wieser is asking me for as a definition is the full Equiv
structure? And I think we do this by mapping (fst,snd) = (1 β[β] fst) + (i β[β] snd)
or something like that? And v β[β] β¨re, imβ©
to (re β’ v, im β’ v)
or ???
I'm not even sure that's the right track, but if it is, I don't know the syntax to make it work?
Arien Malec (Feb 17 2024 at 19:51):
(current code at https://github.com/arienmalec/axler)
Eric Wieser (Feb 17 2024 at 21:23):
Arien Malec said:
(btw, when I look at introductions to complexification, the order of the tensor product is opposite to the
(β β[β] V)
but rather(V β[β] β)
?)
in mathlib V β[β] β
is not a β
-module, but β β[β] V
is. We can't have both without instance diamonds, and we picked the one that uses left-actions
Eric Wieser (Feb 17 2024 at 21:24):
Hopefully you can work out how to define the forward mapping. The trick with the reverse mapping is to use docs#TensorProduct.lift
Arien Malec (Feb 17 2024 at 22:13):
I think I figured out the forward mapping, but I'm swimming in a sea of notation. Like the difference between ββ[β]
and β[β]
where the first is "The canonical function M β N β M β N."
Arien Malec (Feb 17 2024 at 22:13):
toFun p := match p with
| β¨fst, sndβ© => (β¨1, 0β© ββ[β] fst) + β¨0,1β© ββ[β] snd
Jireh Loreaux (Feb 17 2024 at 22:17):
Arien, are you familiar with tensor products mathematically, aside from Lean?
The first one creates elementary tensors. The second one forms the tensor product of two modules, and this is spanned by elementary tensors.
Eric Wieser (Feb 17 2024 at 22:17):
The difference between A β[β] B
and a ββ[β] b
is like the difference between Ξ± Γ Ξ²
and (a, b)
Eric Wieser (Feb 17 2024 at 22:17):
Note that for ββ
you can almost always drop the [R]
too
Jireh Loreaux (Feb 17 2024 at 22:18):
(with the key distinction that unlike Prod
, not every element can be written this way)
Eric Wieser (Feb 17 2024 at 22:18):
(and also unlike Prod, there is usually more than one way to write the same element)
Arien Malec (Feb 17 2024 at 22:24):
Jireh Loreaux said:
Arien, are you familiar with tensor products mathematically, aside from Lean?
The first one creates elementary tensors. The second one forms the tensor product of two modules, and this is spanned by elementary tensors.
Not at any level of detail, which is certainly part of the issue here. So elementary tensors are to tensor products as vectors are to vector spaces?
Eric Wieser (Feb 17 2024 at 22:24):
I think a mildly better analogy is "as basis vectors are to vectors spaces"; not every vector is a basis vector, just as not every tensor is elementary
Eric Wieser (Feb 17 2024 at 22:27):
It may also help to know that a tensor product of vector spaces has as a basis the elementary tensors of the bases of the spaces; if is a basis for and is a basis for then (note: two indices!) is a basis for .
Arien Malec (Feb 18 2024 at 19:52):
Some syntax help, please --
Following the hint, I got to: invFun tp := TensorProduct.lift liftFun tp
where the type signature for liftFun
is β ββ[β] V ββ[β] (V Γ V)
, and I think it wants to take a complex number and a vector, and produce a Prod
in the form of the smul
definition above. But from a syntax perspective, when I write:
def liftFun: β ββ[β] V ββ[β] (V Γ V) where
the type of toFun
wants to be β β V ββ[β] V Γ V
not β β V β V Γ V
-- how do I write liftFun
to be what I'm looking for?
(or, of course, if I'm completely off track....)
Arien Malec (Feb 18 2024 at 19:54):
(not sure how to get the unicode for R-linear maps to show up correctly.)
Eric Wieser (Feb 18 2024 at 20:02):
You probably want LinearMap.mk\_2
Eric Wieser (Feb 18 2024 at 20:03):
I think it would be easier to help you if you made a #mwe
Eric Wieser (Feb 18 2024 at 20:03):
Arien Malec said:
(not sure how to get the unicode for R-linear maps to show up correctly.)
I think you're referring to an Android bug; it looks fine on desktop
Arien Malec (Feb 18 2024 at 20:22):
Firefox bug apparently.
I seem to be missing an import somewhere, but hopefully this is close enough:
import Mathlib.Data.Real.Basic
import Mathlib.Data.Complex.Basic
import Mathlib.Algebra.Module.Basic
import Mathlib.Data.Complex.Module
import Mathlib.LinearAlgebra.TensorProduct
variable {V} [AddCommGroup V] [Module β V]
open scoped TensorProduct
#synth Module β (β β[β] V)
noncomputable def toFun (p: V Γ V) : (β β[β] V) := match p with
| β¨fst, sndβ© => ((β¨1, 0β©: β) ββ[β] fst) + (β¨0,1β©: β) ββ[β] snd
def liftFun: β ββ[β] V ββ[β] (V Γ V) where
toFun := sorry
map_add' := sorry
map_smul' := sorry
def prodEquivComplexTensor: V Γ V β β β[β] V where
toFun p := toFun p
invFun tp := TensorProduct.lift liftFun tp
left_inv := sorry
right_inv := sorry
Eric Wieser (Feb 18 2024 at 20:26):
Note that the final result is not as strong as the one you want to prove, and in fact you will find the stronger result easier!
Eric Wieser (Feb 18 2024 at 20:27):
You should be showing (V Γ V) ββ[β] (β β[β] V)
Eric Wieser (Feb 18 2024 at 20:27):
And you will almost certainly want to do so with docs#LinearEquiv.ofLinear
Kevin Buzzard (Feb 18 2024 at 22:25):
Eric Wieser said:
You should be showing
(V Γ V) ββ[β] (β β[β] V)
Surely there is no -module structure on if is a real vector space? You mean -linear?
Kevin Buzzard (Feb 18 2024 at 22:29):
Arien your code is full of errors for me (on master and in the lean 4 playground). Are you missing some import/open/whatever?
Arien Malec (Feb 18 2024 at 22:41):
It's missing something but I'm not sure what. Perhaps a variable statement
earlier on in the file I extracted this from.
Arien Malec (Feb 18 2024 at 22:43):
I'll try to track down what's missing and repost.
Eric Wieser (Feb 18 2024 at 22:59):
import Mathlib.Data.Complex.Module
Eric Wieser (Feb 18 2024 at 22:59):
But note that import Mathlib
is fine for most "I can't work this out" mwes
Eric Wieser (Feb 18 2024 at 22:59):
Reducing imports is only important for "i think there is a bug" mwes
Arien Malec (Feb 18 2024 at 23:23):
Fixed the MWE
Arien Malec (Feb 18 2024 at 23:27):
It would be fun, for certain values of fun, to work out the material in https://kconrad.math.uconn.edu/blurbs/linmultialg/complexification.pdf in Mathlib...
Eric Wieser (Feb 18 2024 at 23:46):
I spent quite a lot of work on complexifying clifford algebras a few months ago
Eric Wieser (Feb 18 2024 at 23:47):
Note that in mathlib, "complexification" is usually called baseChange
Eric Wieser (Feb 18 2024 at 23:48):
@loogle "baseChange"
loogle (Feb 18 2024 at 23:48):
:search: Submodule.baseChange, Submodule.baseChange_bot, and 171 more
Arien Malec (Feb 19 2024 at 01:03):
Mathlib makes hard things possible, and really easy things elegant and things in the middle are sometimes....
Arien Malec (Feb 19 2024 at 20:27):
I've gotten to:
import Mathlib.Data.Real.Basic
import Mathlib.Data.Complex.Basic
import Mathlib.Algebra.Module.Basic
import Mathlib.Data.Complex.Module
import Mathlib.LinearAlgebra.TensorProduct
variable {V} [AddCommGroup V] [Module β V]
open scoped TensorProduct
#synth Module β (β β[β] V)
noncomputable def toFun: V Γ V ββ[β] β β[β] V where
toFun p := match p with
| β¨fst, sndβ© => ((1: β) ββ[β] fst) + Complex.I ββ[β] snd
map_add' p1 p2 := by dsimp; simp [TensorProduct.tmul_add]; abel_nf
map_smul' r p := by dsimp; simp [TensorProduct.tmul_smul]
noncomputable def invFun: β β[β] V ββ[β] V Γ V where
toFun tp := by sorry
map_add' tp1 tp1 := by dsimp; sorry
map_smul' r tp := by dsimp; sorry
but the definition of invFun
eludes me. In particular, if I had a complex number and a vector, I could create a Prod
but I'm not sure how to get these "out" of the product, if I'm thinking about that the right way.
Also, when I do theorem toFun_invFun_comp: LinearMap.comp toFun invFun = LinearMap.id := by sorry
I get
typeclass instance problem is stuck, it is often due to metavariables
AddCommMonoid (?m.21022 Γ ?m.21022)
Which I assume means I need an instance for V Γ V
Kevin Buzzard (Feb 19 2024 at 20:35):
noncomputable def invFun : β β[β] V ββ[β] V Γ V := TensorProduct.lift {
toFun := fun z β¦ {
toFun := fun v β¦ (z.re β’ v, z.im β’ v)
map_add' := sorry
map_smul' := sorry
}
map_add' := sorry
map_smul' := sorry
}
Eric Wieser (Feb 19 2024 at 21:04):
Eric Wieser said:
You probably want
LinearMap.mk\_2
This would work too
Eric Wieser (Feb 19 2024 at 21:05):
Arien Malec said:
Also, when I do
theorem toFun_invFun_comp: LinearMap.comp toFun invFun = LinearMap.id := by sorry
I gettypeclass instance problem is stuck, it is often due to metavariables AddCommMonoid (?m.21022 Γ ?m.21022)
Which I assume means I need an instance for
V Γ V
Lean is confused because you never told it you were talking about V
Arien Malec (Feb 19 2024 at 21:07):
Eric Wieser said:
Eric Wieser said:
You probably want
LinearMap.mk\_2
This would work too
I'm sure but @Kevin Buzzard put the Don't Panic sticker on his.... (I looked at the sig for mk_2
but didn't grok it :-))
Eric Wieser (Feb 19 2024 at 21:08):
It takes a two-argument function, and four proofs
Eric Wieser (Feb 19 2024 at 21:09):
You could use by apply LinearMap.mk2
to have Lean grok it for you :)
Arien Malec (Feb 19 2024 at 21:11):
Eric Wieser said:
Arien Malec said:
Also, when I do
theorem toFun_invFun_comp: LinearMap.comp toFun invFun = LinearMap.id := by sorry
I gettypeclass instance problem is stuck, it is often due to metavariables AddCommMonoid (?m.21022 Γ ?m.21022)
...
Lean is confused because you never told it you were talking about
V
Ah, theorem toFun_invFun_comp: LinearMap.comp (@toFun V _ _) invFun = LinearMap.id := by sorry
fixes it.
Eric Wieser (Feb 19 2024 at 21:12):
Using (V)
instead of {V}
above would be another solution
Kevin Buzzard (Feb 19 2024 at 21:17):
mk\2
Arien Malec (Feb 19 2024 at 21:32):
It turns out that works better -- the proofs for the plain lift
version have complicated structures in them -- I'm sure there's a way around this, but this, despite the hackery, works:
noncomputable def invFun: β β[β] V ββ[β] V Γ V :=
TensorProduct.lift <| LinearMap.mkβ
β (fun z v β¦ (z.re β’ v, z.im β’ v))
(by intros; ext <;> dsimp <;> rw [add_smul])
(by intros; ext <;> dsimp <;> simp [mul_smul])
(by intros; ext <;> dsimp <;> simp [smul_add])
(by intros; ext <;> dsimp <;> rw [smul_comm])
Arien Malec (Feb 20 2024 at 01:30):
Here's where I've gotten:
import Mathlib.Data.Real.Basic
import Mathlib.Data.Complex.Basic
import Mathlib.Algebra.Module.Basic
import Mathlib.Data.Complex.Module
import Mathlib.LinearAlgebra.TensorProduct
variable {V} [AddCommGroup V] [Module β V]
open scoped TensorProduct
#synth Module β (β β[β] V)
noncomputable def toFun: V Γ V ββ[β] β β[β] V where
toFun p := match p with
| β¨fst, sndβ© => ((1: β) ββ[β] fst) + Complex.I ββ[β] snd
map_add' p1 p2 := by dsimp; simp [TensorProduct.tmul_add]; abel_nf
map_smul' r p := by dsimp; simp [TensorProduct.tmul_smul]
noncomputable def invFun: β β[β] V ββ[β] V Γ V :=
TensorProduct.lift <| LinearMap.mkβ
β (fun z v β¦ (z.re β’ v, z.im β’ v))
(by intros; ext <;> dsimp <;> rw [add_smul])
(by intros; ext <;> dsimp <;> simp [mul_smul])
(by intros; ext <;> dsimp <;> simp [smul_add])
(by intros; ext <;> dsimp <;> rw [smul_comm])
theorem toFun_invFun_comp_eq_id: LinearMap.comp (@toFun V _ _) invFun = LinearMap.id := by
simp only [toFun, invFun]; ext z v; dsimp; simp [TensorProduct.tmul_add, TensorProduct.smul_tmul]
sorry
theorem invFun_toFun_comp_eq_id: LinearMap.comp invFun (@toFun V _ _) = LinearMap.id := by
simp only [invFun, toFun]; sorry
def prodRLinearComplexTensor: (V Γ V) ββ[β] (β β[β] V) := LinearEquiv.ofLinear toFun invFun toFun_invFun_comp_eq_id invFun_toFun_comp_eq_id
A few issues here:
- If I make the
{V}
explicit I get a world of hurt with errors like:typeclass instance problem is stuck, it is often due to metavariables RingHomCompTriple ?m.31917 (RingHom.id β) (RingHom.id β)
and friends - In
toFun_invFun_comp_eq_id
I get to a really nice goal state, but I can't getrw [βTensorProduct.add_tmul (z.re β’ 1) (z.im β’ Complex.I) v]
to accept that the pattern exists; I've tried using@
and getting super explicit, but been unable to get a non barf state.
V: Type u_1
instβΒΉ: AddCommGroup V
instβ: Module β V
z: β
v: V
β’ z.re β’ 1 ββ[β] v + z.im β’ Complex.I ββ[β] v = z ββ[β] v
-
The proof state for
invFun_toFun_comp_eq_id
by contrast is a real mess that I don't have a clue how to fix... -
Most concerning, in
prodRLinearComplexTensor
I get the error:
compiler IR check failed at 'prodRLinearComplexTensor._rarg', error: unknown declaration 'toFun'
Arien Malec (Feb 20 2024 at 01:33):
BTW, when I clear this thicket, is it going to be easy to use the proofs to do simple things like prove:
def Rn_complexified_equiv {n: β}: (β β[β] (Fin n β β)) ββ[β] (Fin n β β) := sorry
?
Eric Wieser (Feb 20 2024 at 03:27):
1 is because you need to add a bunch of V
s everywhere
Eric Wieser (Feb 20 2024 at 03:29):
I would guess your problem in 2 is that the operators don't have the parenthesization you think they do, and you need to start with an associativity lemma
Eric Wieser (Feb 20 2024 at 03:30):
4 is asking you to add noncomputable
Eric Wieser (Feb 20 2024 at 03:30):
Regarding R^n; you will most likely have to do all the work again from scratch, but you should find it much easier once you know the tricks
Arien Malec (Feb 20 2024 at 03:41):
Eric Wieser said:
I would guess your problem in 2 is that the operators don't have the parenthesization you think they do, and you need to start with an associativity lemma
I see -- the issue is that z.re β’ 1 ββ[β] v
is seen as z.re β’ (1 ββ[β] v)
?
Eric Wieser (Feb 20 2024 at 03:43):
If you hover over the goal view, vscode will tell you
Eric Wieser (Feb 20 2024 at 03:44):
I'm afraid while I can remember many lemmas names, I am unreliable at remembering operator precedence
Arien Malec (Feb 20 2024 at 03:46):
It's rfl
as it happens.
theorem toFun_invFun_comp_eq_id: LinearMap.comp (@toFun V _ _) invFun = LinearMap.id := by
simp only [toFun, invFun]; ext z v; dsimp; simp [TensorProduct.tmul_add, TensorProduct.smul_tmul]
have h1: (z.re β’ (1: β) ββ[β] v) = (z.re β’ 1) ββ[β] v := rfl
have h2: (z.im β’ (Complex.I ββ[β] v)) = ((z.im β’ Complex.I) ββ[β] v) := rfl
rw [h1, h2, βTensorProduct.add_tmul (z.re β’ 1) (z.im β’ Complex.I) v]
simp only [Complex.real_smul, mul_one, Complex.re_add_im]
Eric Wieser (Feb 20 2024 at 03:49):
I recommend using by rw?
to find the actual lemma name
Arien Malec (Feb 20 2024 at 03:55):
Wow! rw?
is a thing! TensorProduct.smul_tmul'
Eric Wieser (Feb 20 2024 at 03:57):
Just to explain why I told you to build everything as linear maps: if you hadn't, and tried to prove the inverse as f (g x) = x
instead of this comp
version, your ext z w
wouldn't have worked
Eric Wieser (Feb 20 2024 at 03:58):
You might find the proof even easier if you add attribute [ext] TensorProduct.ext'
before your proof
Arien Malec (Feb 20 2024 at 15:53):
I'm down to invFun_toFun_comp_eq_id
and I can't seem to make progress -- the first part of the goal state is:
TensorProduct.lift
(LinearMap.mkβ β --- then lots of functions to structures
and I haven't found the way around -- somehow this all normalized out in toFun_inFun_comp_eq_id
.
Eric Wieser (Feb 20 2024 at 15:54):
Can you share the full goal state, or an updated mwe?
Arien Malec (Feb 20 2024 at 15:55):
Uh, scratch that, somehow:
theorem invFun_toFun_comp_eq_id: LinearMap.comp invFun (@toFun V _ _) = LinearMap.id := by
simp only [toFun]; apply LinearMap.ext; intro p; simp [invFun]
works where
theorem invFun_toFun_comp_eq_id: LinearMap.comp invFun (@toFun V _ _) = LinearMap.id := by
simp only [toFun, invFun]; apply LinearMap.ext; intro p
was simp
resistant
Arien Malec (Feb 20 2024 at 15:56):
Oh, that's not correct either -- I never tried the literally simp
lest tactic
Arien Malec (Feb 20 2024 at 15:58):
Now what do I do with my time? Oh, yeah, show the R^n
C^n
case.
Eric Wieser (Feb 20 2024 at 16:00):
Arien Malec said:
Now what do I do with my time? Oh, yeah, show the
R^n
C^n
case.
This one should actually be easier, you should be able to compose isomorphisms already in mathlib
Arien Malec (Feb 20 2024 at 17:29):
Hmm. With your hints on baseChange
, do I want something like docs#IsBaseChange.equiv ?
Eric Wieser (Feb 20 2024 at 17:45):
I think I'm wrong, the result I'm thinking of only exists for finitely supported functions, not general functions
Arien Malec (Feb 20 2024 at 17:46):
I'll go the hard way then.
Arien Malec (Feb 20 2024 at 17:46):
What would need to be in Mathlib for this to be trivial?
Eric Wieser (Feb 20 2024 at 17:47):
docs#TensorProduct.directSumLeft for Pi types
Eric Wieser (Feb 20 2024 at 17:47):
(probably over a Fintype
index)
Eric Wieser (Feb 20 2024 at 17:48):
You'd combine that with the fact that β β[β] β
and β
are isomorphic, which Mathlib knows
Arien Malec (Feb 20 2024 at 18:30):
Oh, hey, we know docs#Complex.equivRealProd and now we know that (V Γ V) ββ[β] (β β[β] V)
Arien Malec (Feb 20 2024 at 18:30):
Can these be combined in useful ways?
Eric Wieser (Feb 20 2024 at 18:31):
Yes, you could have used that to get the isomorphism instead of your approach, I think
Eric Wieser (Feb 20 2024 at 18:32):
@loogle TensorProduct, Prod
loogle (Feb 20 2024 at 18:32):
:search: TensorProduct.SMul.aux, TensorProduct.SMul.aux_of, and 68 more
Eric Wieser (Feb 20 2024 at 18:33):
docs#TensorProduct.prodLeft is what I was looking for
Arien Malec (Feb 20 2024 at 18:33):
I played with that for a bit but didn't find the path through....
Eric Wieser (Feb 20 2024 at 18:34):
You'll need docs#TensorProduct.congr too
Eric Wieser (Feb 20 2024 at 18:34):
Eric Wieser (Feb 20 2024 at 18:35):
Last updated: May 02 2025 at 03:31 UTC