# Zulip Chat Archive

## Stream: new members

### Topic: Coercion of 1x1 matrices

#### Yakov Pechersky (Jun 16 2020 at 19:35):

I'm trying to figure out how `has_lift`

and `coe_*`

work. Right now I have the following definitions.

```
import data.real.basic
import linear_algebra.matrix
open_locale big_operators
universes u v
variables {n : Type u} [fintype n] [decidable_eq n]
variables (R : Type v) [add_comm_monoid R]
noncomputable instance matrix_lift (h : fintype.card n = 1) : has_lift (matrix n n R) R :=
begin
rw fintype.card at h,
rw finset.card_eq_one at h,
rw finset.singleton_iff_unique_mem at h,
choose b hb using h,
exact ⟨λ M, M b b⟩
end
noncomputable instance matrix_lift_t (h : fintype.card n = 1) : has_lift_t (matrix n n R) R :=
begin
rw fintype.card at h,
rw finset.card_eq_one at h,
rw finset.singleton_iff_unique_mem at h,
choose b hb using h,
exact ⟨λ M, M b b⟩
end
theorem coe_singleton {M : matrix n n R} {h : fintype.card n = 1} {a : n}
[has_lift_t (matrix n n R) R]:
(↑M : R) = M a a := sorry
```

I would think `rfl`

would work, but there is a type mismatch. It also seems weird to me to be supplying a proof in the instance definition. Another issue is that I think using `[has_lift_t ...]`

is non idiomatic, from looking at mathlib source.

#### Jalex Stark (Jun 16 2020 at 19:41):

is the problem that your instances are noncomputable but your theorem is not?

#### Jalex Stark (Jun 16 2020 at 19:42):

(I usually write `noncomputable theory`

at the top of my file to avoid thinking about this)

#### Johan Commelin (Jun 16 2020 at 19:42):

I think that in practice it may be more useful to assume `[unique n]`

instead of `fintype.card n = 1`

.

#### Reid Barton (Jun 16 2020 at 19:42):

Lots of problems here, but ultimately the result can never be true by `rfl`

because it would mean that any two elements of `n`

are definitionally equal.

#### Reid Barton (Jun 16 2020 at 19:43):

You are taking a very mathematician-like attitude here: there's just one element anyways, so let's pick it.

#### Reid Barton (Jun 16 2020 at 19:45):

This works, sort of, but you will have to justify yourself to Lean later.

#### Yakov Pechersky (Jun 16 2020 at 20:37):

Thanks for the insight. Here's what I have currently. Seeing an error I haven't seen before, with "goals accomplished" yet red squiggly.

```
import data.real.basic
import linear_algebra.matrix
open_locale big_operators
universes u v
variables {n : Type u} [fintype n] [decidable_eq n]
variables (R : Type v)
instance matrix_coe [unique n] : has_coe (matrix n n R) R :=
let a := default n in ⟨λ M, M a a⟩
theorem coe_singleton {M : matrix n n R} [unique n] {a : n} :
(↑M : R) = M a a :=
by { rw unique.uniq _ a, refl }
-- having a theorem that distributes the coe like `↑(A * B) = ↑A * ↑B`
-- is probably useful for what I'm trying to prove
-- which is the commutativity of 1-dim matrices
-- this statement does not work because I don't have ↑ in the statement
-- so I can't use `rw coe_singleton` later
-- example (A : matrix (fin 1) (fin 1) ℝ) (B : matrix (fin 1) (fin 1) ℝ) :
-- A * B = B * A := sorry
-- this errors at the end with
-- tactic failed, result contains meta-variables
-- state:
-- no goals
example (A : matrix (fin 1) (fin 1) ℝ) (B : matrix (fin 1) (fin 1) ℝ) : ↑A * ↑B = ↑B * ↑A :=
begin
haveI : unique (fin 1) := by apply_instance,
haveI: has_lift_t (matrix (fin 1) (fin 1) ℝ) ℝ := by apply_instance,
rw coe_singleton,
rw coe_singleton,
rw mul_comm,
exact (default (fin 1)),
exact (default (fin 1)), -- cursor on comma says "goals accomplished"
end
```

#### Kevin Buzzard (Jun 16 2020 at 20:39):

Congratulations, you just got the "unproved invisible metavariable goal" achievement

#### Kevin Buzzard (Jun 16 2020 at 20:39):

There's some tactic which will make the invisible goal appear, I always forget what it is.

#### Kevin Buzzard (Jun 16 2020 at 20:46):

`recover`

#### Kevin Buzzard (Jun 16 2020 at 20:47):

` recover, repeat {apply_instance},`

finishes things properly. I don't really understand why this happens.

#### Reid Barton (Jun 16 2020 at 20:48):

I don't understand what the two `haveI`

s could accomplish.

#### Reid Barton (Jun 16 2020 at 20:49):

Also, I'm not sure if you are proving what you want to prove.

#### Reid Barton (Jun 16 2020 at 20:50):

You could just apply `mul_comm`

and be done.

#### Kevin Buzzard (Jun 16 2020 at 20:50):

If `apply_instance`

works then the thing you proved was already known to type class inference so you didn't need to add it with `haveI`

(and probably you should have used `letI`

?)

#### Kevin Buzzard (Jun 16 2020 at 20:50):

The `haveI`

's were in fact the problem

#### Kevin Buzzard (Jun 16 2020 at 20:51):

(it is)`matrix X X R`

might not be known to be a semigroup.

#### Reid Barton (Jun 16 2020 at 20:51):

actually I guess I'm also not 100% sure what type `↑A`

is--if you have the `has_coe`

instance anyways, better to write `(A : ℝ)`

.

#### Kevin Buzzard (Jun 16 2020 at 20:53):

```
example (A : matrix (fin 1) (fin 1) ℝ) (B : matrix (fin 1) (fin 1) ℝ) :
(A : ℝ) * B = B * A :=
begin
apply mul_comm,
end
```

#### Kevin Buzzard (Jun 16 2020 at 20:54):

```
example (A : matrix (fin 1) (fin 1) ℝ) (B : matrix (fin 1) (fin 1) ℝ) :
(A : ℝ) * B = B * A := mul_comm _ _
```

#### Kevin Buzzard (Jun 16 2020 at 20:54):

Lean doesn't have a clue where you're coercing to, I think

#### Kevin Buzzard (Jun 16 2020 at 20:54):

If you tell it explicitly, as Reid suggests, it's much happier

#### Reid Barton (Jun 16 2020 at 20:55):

and `example`

is like `def`

in that it uses the body of the definition to elaborate the stated type of the example, so maybe that is where your metavariable(s) came from?

#### Reid Barton (Jun 16 2020 at 20:56):

anyways, all of this is just dancing around the actual work, which is proving that multiplication of 1x1 matrices corresponds to multiplication in R

#### Yakov Pechersky (Jun 16 2020 at 21:06):

Totally clear now:

```
import data.real.basic
import linear_algebra.matrix
open_locale big_operators
universes u v
variables {n : Type u} [fintype n] [decidable_eq n]
variables (R : Type v)
instance matrix_coe [unique n] : has_coe (matrix n n R) R :=
let a := default n in ⟨λ M, M a a⟩
theorem coe_singleton {M : matrix n n R} [unique n] {a : n} :
(↑M : R) = M a a :=
by { rw unique.uniq _ a, refl }
example (A : matrix (fin 1) (fin 1) ℝ) (B : matrix (fin 1) (fin 1) ℝ) :
(A : ℝ) * B = B * A :=
mul_comm _ _
```

But thinking about how to formalize the proof that n x n matrices commute over the entirety of the space, is valid only for n <= 1, one would need the theory of eigenvectors, which mathlib does not yet have. Correct?

```
example {n : ℕ} (h : ∀ (A : matrix (fin n) (fin n) ℝ) (B : matrix (fin n) (fin n) ℝ), A * B = B * A) :
n <= 1 := sorry
```

#### David Wärn (Jun 16 2020 at 21:31):

If you want to show there are non-commuting matrices for n >= 2, why not just look at an explicit example? Say

```
10 * 01
00 00
```

#### Yakov Pechersky (Jun 16 2020 at 21:51):

Sure, and show by induction ... . For a proof that did not rely on calculation, I was thinking about the one at `https://math.stackexchange.com/a/27832`

, and then show that all matrices are equal to `c * I`

for some scalar `c`

only for `n = 0 \or n = 1`

.

#### Kevin Buzzard (Jun 16 2020 at 22:10):

You don't need any induction here. David's matrices are n x n

#### Kevin Buzzard (Jun 16 2020 at 22:11):

It's just some "if first variable is 0 and second is 1 then 1 else 0" matrix

#### Yakov Pechersky (Jun 16 2020 at 22:37):

I think you still need induction to show that `fin n`

for `n >= 2`

has `has_zero`

and `has_one`

instances, so that those matrices can be defined via an `ite`

call.

#### Kevin Buzzard (Jun 16 2020 at 22:53):

This is not induction. You need to prove 0 < n and 1 < n but both of these follow directly from 2<= n

#### Kevin Buzzard (Jun 16 2020 at 22:53):

The ite doesn't care if its clause is never satisfied

#### Kevin Buzzard (Jun 16 2020 at 22:56):

The time when you care is in the proof

#### Kevin Buzzard (Jun 17 2020 at 08:56):

@Yakov Pechersky sorry, I had to sleep :-)

```
import data.matrix.notation
variables {R : Type*} [ring R] [nonzero R]
example (n : ℕ) :
∃ (S : matrix (fin (n+2)) (fin (n+2)) R) (T : matrix (fin (n+2)) (fin (n+2)) R),
S * T ≠ T * S :=
begin
use (λ a b, if a = 0 ∧ b = 1 then 1 else 0),
use (λ a b, if a = 0 ∧ b = 0 then 1 else 0),
intro h,
replace h := congr_fun (congr_fun h 0) 1,
simp [matrix.mul, matrix.dot_product] at h,
apply @zero_ne_one R,
convert h,
end
```

#### Kevin Buzzard (Jun 17 2020 at 08:58):

Poking around in the library a bit for the `has_one`

issue revealed that the trick is to work with `fin (n+2)`

.

#### Kevin Buzzard (Jun 17 2020 at 09:06):

I'm a bit unhappy with that nonterminal `simp`

: I'm slightly less unhappy, but still unhappy, with

```
begin
use (λ a b, if a = 0 ∧ b = 1 then 1 else 0),
use (λ a b, if a = 0 ∧ b = 0 then 1 else 0),
intro h,
replace h := congr_fun (congr_fun h 0) 1,
have h2 : ite ((1 : fin (n + 2)) = 0) (1 : R) 0 = 1,
simp [matrix.mul, matrix.dot_product] at h, exact h,
apply @zero_ne_one R,
convert h2,
end
```

Last updated: Dec 20 2023 at 11:08 UTC