Zulip Chat Archive

Stream: new members

Topic: Simplify matrix conjugate transpose


Yunong Shi (Jan 23 2024 at 00:12):

I want to prove that the multiplication of a simple column vector and its conjugate transpose results in 1.

If I do:

def my_vec: Matrix (Fin 2) (Fin 1)  := !![1; 0]

theorem my_vec_mul_one: my_vec * my_vec  = 1 := by
   ext i j
   fin_cases i <;> fin_cases j <;> simp [my_vec]

I will have 1 goal:

1 goal
case a.h.a.head.head
(((Matrix.of ![![1], ![0]]) * Matrix.of ![![1], ![0]]) 0 0).re = 1

Following the proof state, I naturally expand the definitions and extend the lastsimp [my_vec] with simp [my_vec, Matrix.conjTranspose, Matrix.map, Matrix.of, Equiv.refl] but it will give me more and more complicated proof state, and it ends up look like:

1 goal
case a.h.a.head.head
 ((({ toFun := id, invFun := id, left_inv := _, right_inv := _ } fun i j 
          (starRingEnd ) ({ toFun := id, invFun := id, left_inv := _, right_inv := _ } ![![1], ![0]] j i)) *
        { toFun := id, invFun := id, left_inv := _, right_inv := _ } ![![1], ![0]])
      0 0).re =
  1

I am wondering how to simplify matrix conjugate and matrix transpose and prove theorems like the above about them?

Eric Wieser (Jan 23 2024 at 00:53):

You should not simplify Matrix.of ever

Eric Wieser (Jan 23 2024 at 00:53):

Use of_apply instead, which is safer

Yunong Shi (Jan 23 2024 at 01:00):

Eric Wieser said:

Use of_apply instead, which is safer

Thanks. But it still doesn't help proceed with the proof.

With simp [my_vec, Matrix.conjTranspose, Matrix.map, Matrix.of_apply], I have the following proof state now.

1 goal
case a.h.a.head.head
 (((Matrix.of fun i j  (starRingEnd ) (Matrix.vecCons 1 (fun i  0) j)) * Matrix.of ![![1], ![0]]) 0 0).re = 1

(Matrix.of_apply didn't seem to help proceed the proof..)

Matt Diamond (Jan 23 2024 at 01:30):

have you tried docs#Matrix.mul_apply? what about something like this?

theorem my_vec_mul_one: my_vec * my_vec = 1 := by
   ext i j
   rw [Matrix.mul_apply]
   simp [my_vec]
   sorry

Matt Diamond (Jan 23 2024 at 01:31):

that gets you to a goal of 1 = OfNat.ofNat 1 i j which seems pretty close

Matt Diamond (Jan 23 2024 at 01:35):

actually this should get you all the way:

theorem my_vec_mul_one: my_vec * my_vec = 1 := by
   ext i j
   rw [Subsingleton.elim i j, Matrix.mul_apply]
   simp [my_vec]

Yunong Shi (Jan 23 2024 at 01:36):

Matt Diamond said:

have you tried docs#Matrix.mul_apply? what about something like this?

theorem my_vec_mul_one: my_vec * my_vec = 1 := by
   ext i j
   rw [Matrix.mul_apply]
   simp [my_vec]
   sorry

Thanks! I indeed tried Matrix.mul_apply, but only after fin_cases i <;> fin_cases j. It reported a type error. But obviously I should do multiplication before break down to different cases.

Yunong Shi (Jan 23 2024 at 01:37):

Matt Diamond said:

actually this should get you all the way:

theorem my_vec_mul_one: my_vec * my_vec = 1 := by
   ext i j
   rw [Subsingleton.elim i j, Matrix.mul_apply]
   simp [my_vec]

Thank you! However, for me, I have to repeat it,

theorem my_vec_mul_one: my_vec * my_vec = 1 := by
   ext i j
   rw [Subsingleton.elim i j, Matrix.mul_apply]
   simp [my_vec]
   rw [Subsingleton.elim i j, Matrix.mul_apply]
   simp [my_vec]

Matt Diamond (Jan 23 2024 at 01:39):

Hmm, maybe I typed something wrong... this is what I was working with:

import Mathlib.Data.Matrix.Basic
import Mathlib.Data.Complex.Basic
import Mathlib.Data.Matrix.Notation

open Matrix

def my_vec: Matrix (Fin 2) (Fin 1)  := !![1; 0]

theorem my_vec_mul_one: my_vec * my_vec = 1 := by
   ext i j
   rw [Subsingleton.elim i j, mul_apply]
   simp [my_vec]

Matt Diamond (Jan 23 2024 at 01:40):

I didn't need to repeat anything to close the goal

Matt Diamond (Jan 23 2024 at 01:42):

if that's not closing the goal for you, maybe your mathlib is out of date? I just put this together in the web editor

Yunong Shi (Jan 23 2024 at 01:43):

Matt Diamond said:

Hmm, maybe I typed something wrong... this is what I was working with:

import Mathlib.Data.Matrix.Basic
import Mathlib.Data.Complex.Basic
import Mathlib.Data.Matrix.Notation

open Matrix

def my_vec: Matrix (Fin 2) (Fin 1)  := !![1; 0]

theorem my_vec_mul_one: my_vec * my_vec = 1 := by
   ext i j
   rw [Subsingleton.elim i j, mul_apply]
   simp [my_vec]

Interesting, I have the same set up except that I didn't import Notation. If I don't repeat it, I will still have the imaginary part left as a goal:

1 goal
ij: Fin 1
 ((qubit_zero * qubit_zero) i j).im = (OfNat.ofNat 1 i j).im

Yunong Shi (Jan 23 2024 at 01:44):

Ah, Matt Diamond it's about importing Notation. If I do that, I don't have to repeat.

Matt Diamond (Jan 23 2024 at 01:45):

that's interesting... if I leave out the Notation import I get an error around !![1;0]... must be a difference in mathlib versions

Yunong Shi (Jan 23 2024 at 01:50):

Actually, having Notation didn't solve it. It was just the Lean interpreter being slow. I still have to repeat.

Yunong Shi (Jan 23 2024 at 01:50):

Screenshot-2024-01-22-at-8.54.57-PM.png
And Lean playground gives a more unexpected error..

(Now it works!)

Matt Diamond (Jan 23 2024 at 01:52):

you just forgot open Matrix

Yunong Shi (Jan 23 2024 at 01:55):

Yes, now Lean playground works!

Matt Diamond (Jan 23 2024 at 01:58):

:+1:

Yunong Shi (Jan 23 2024 at 02:02):

Matt Diamond I have a bit trouble understanding the Subsingleton.elim tactic you used. Is it that for Fin 1, there should only be 1 element in it?

Matt Diamond (Jan 23 2024 at 02:06):

Yep, are you familiar with the concept of subsingletons? I means that the type has no more than 1 possible value (it could also be empty), so we can prove that every term of the type equals every other term. Fin 1 has a subsingleton instance because the only possible value is 0.

Matt Diamond (Jan 23 2024 at 02:08):

docs#Subsingleton


Last updated: May 02 2025 at 03:31 UTC