Zulip Chat Archive

Stream: general

Topic: mul_action and has_scalar diamond


Yakov Pechersky (Jul 18 2021 at 21:39):

Consider the following lemma. At the end, I have a diamond on two smul instances. What's the right way to avoid these?

import linear_algebra.matrix.nonsingular_inverse

variables {n α : Type*} [fintype n] [decidable_eq n] [comm_ring α]

open matrix

lemma det_eq_elem_of_subsingleton' [subsingleton n] (A : matrix n n α) (k : n) :
  det A = A k k := sorry

lemma adjugate_subsingleton' [subsingleton n] (A : matrix n n α) : adjugate A = 1 := sorry

lemma adjugate_adjugate' [subsingleton n] (A : matrix n n α) (h : is_unit A.det) :
  A.adjugate.adjugate = h.unit ^ ((fintype.card n : ) - 2)  A :=
begin
  rw adjugate_subsingleton',
  ext i j,
  have hj : i = j := subsingleton.elim i j,
  subst hj,
  have : fintype.card n = 1,
  { rw fintype.card_eq_one_iff,
    use i,
    simp },
  have hd : A i i = h.unit,
  { rw [h.unit_spec, det_eq_elem_of_subsingleton' _ i] },
  have hc : h.unit⁻¹  h.unit = 1,
  { simp },
  rw [pi.smul_apply, pi.smul_apply, hd, this, gpow_sub, gpow_bit0,
      units.coe_smul],
  simp only [mul_inv_rev, mul_inv_cancel_comm_assoc, gpow_one, int.coe_nat_zero, int.coe_nat_succ,
              one_apply_eq, zero_add],
  convert units.ext_iff.mp hc.symm,
  sorry -- diamond here
end

Yakov Pechersky (Jul 18 2021 at 21:41):

In particular, I made the hc hypothesis because smul_eq_mul wouldn't work.

Yakov Pechersky (Jul 18 2021 at 21:45):

One way, of course, is to avoid using h.unit in the lemma statement, and have only nat powers.

Eric Wieser (Jul 18 2021 at 22:35):

Can you reduce this any further?

Eric Wieser (Jul 18 2021 at 22:36):

This diamond is weird - if I do local attribute [ext] has_scalar, then I can close your goal with ext, refl

Eric Wieser (Jul 18 2021 at 22:36):

Which suggests that the two smul actions are defeq

Eric Wieser (Jul 18 2021 at 22:40):

Ah, here's the MWE:

import group_theory.group_action.units

example {α : Type*} [comm_monoid α] :
  (units.mul_action' : mul_action (units α) (units α)) = monoid.to_mul_action _ :=
rfl -- fails

attribute [ext] mul_action has_scalar

example {α : Type*} [comm_monoid α] :
  (units.mul_action' : mul_action (units α) (units α)) = monoid.to_mul_action _ :=
begin
  ext,
  refl,
end  -- succeeds

Eric Wieser (Jul 18 2021 at 22:54):

Ah, and this reveals what's going wrong:

example {α : Type*} [comm_monoid α] :
  (units.mul_action' : mul_action (units α) (units α)) = monoid.to_mul_action (units α) :=
begin
  dunfold monoid.to_mul_action units.mul_action',
  congr,
  { dunfold has_mul.mul mul_one_class.mul monoid.mul div_inv_monoid.mul ,
    dunfold group.mul,
    dsimp [units.smul_def],
    dunfold has_inv.inv div_inv_monoid.inv group.inv,
    dsimp only,
    unfold_coes,
    ext : 2,
    dsimp only,
    -- {val := x.val * x_1.val, inv := x.inv * x_1.inv, val_inv := _, inv_val := _} =
    -- {val := x.val * x_1.val, inv := x_1.inv * x.inv, val_inv := _, inv_val := _}
    sorry
    },
  sorry,
  sorry
end

The actions agree on val, but disagree on inv

Eric Wieser (Jul 18 2021 at 23:03):

So src#units.mul_action' is at fault here

Yakov Pechersky (Jul 18 2021 at 23:04):

What would the inv be then for that definition?

Eric Wieser (Jul 18 2021 at 23:05):

I think it should be using a right action, opposite.op r⁻¹ • m⁻¹

Eric Wieser (Jul 18 2021 at 23:05):

I can investigate tomorrow

Eric Wieser (Jul 19 2021 at 09:32):

I've almost fixed this, but I think the typeclass I need doesn't exist. What additional assumptions does the sorry below need?

import group_theory.group_action.units
import algebra.opposites

-- turn off the bad instance we're tring to fix
local attribute [-instance] units.mul_action'

namespace units

open opposite

variables {G M α : Type*}

/-! Right actions on units - I can't think if a good way to inherit these from anything we already
have -/

instance units.op_has_scalar [monoid M] [has_scalar Mᵒᵖ α] : has_scalar (units M)ᵒᵖ α :=
{ smul := λ um a, op (um.unop : M)  a }

instance units.op_mul_action [monoid M] [mul_action Mᵒᵖ α] : mul_action (units M)ᵒᵖ α :=
{ smul := λ um a, op (um.unop : M)  a,
  one_smul := (one_smul Mᵒᵖ : _),
  mul_smul := λ um un, mul_smul (op (um.unop : M)) (op (un.unop : M)), }

/-! Notation just to make the intent behind the sorried lemma clear. -/

notation g` •> `:73 m:72 := g  m
notation m` <• `:73 g:72 := opposite.op g  m

variables [group G] [monoid M] [mul_action G M] [mul_action Gᵒᵖ M]

lemma smul_mul_inv_smul (g : G) (m : units M) : (g •> (m : M)) * ((m⁻¹) <• g⁻¹) = 1 :=
sorry

lemma inv_smul_mul_smul (g : G) (m : units M) : ((m⁻¹) <• g⁻¹) * (g •> (m : M)) = 1 :=
opposite.op_injective $ smul_mul_inv_smul g (units.op_equiv.symm (op m))

/-- A fixed version of `units.mul_action'`. -/
instance better_mul_action' : mul_action G (units M) :=
{ smul := λ g m, g •> (m : M), (m⁻¹) <• g⁻¹, smul_mul_inv_smul _ _, inv_smul_mul_smul _ _⟩,
  one_smul := λ m, units.ext $ one_smul _ _,
  mul_smul := λ g₁ g₂ m, units.ext $ mul_smul _ _ _ }

-- note: now only needs monoid not comm_monoid!
example {α : Type*} [monoid α] :
  (units.better_mul_action' : mul_action (units α) (units α)) = monoid.to_mul_action _ :=
rfl -- ok, no diamond any more

end units

Eric Wieser (Jul 19 2021 at 09:47):

I think the sorry can be expanded as:

lemma smul_mul_inv_smul [is_scalar_tower G M M] (g : G) (m : units M)
  : (g •> (m : M)) * ((m⁻¹) <• g⁻¹) = 1 :=
calc (g •> (m : M)) * ((m⁻¹) <• g⁻¹)
    = g •> ((m : M) * ((m⁻¹) <• g⁻¹)) : by rw [smul_eq_mul, smul_eq_mul, smul_assoc]
... = g •> ((m : M) * (m⁻¹)) <• g⁻¹ : by {
    congr' 1,
    rw [op_smul_eq_mul, op_smul_eq_mul],
    sorry -- we need `is_scalar_tower` for right actions
    }
... = g •> 1 <• g⁻¹ : by rw units.mul_inv
... = (g * g⁻¹) •> 1 : sorry  -- `smul_comm_class` is too strong here
... = 1 : by rw [mul_right_inv, one_smul]

Yakov Pechersky (Jul 19 2021 at 12:14):

Does <-units.coe_mul help here?

Eric Wieser (Jul 19 2021 at 12:44):

I doubt it, that step is folded into the by rw units.mul_inv

Eric Wieser (Jul 19 2021 at 12:45):

I think the statement at the first sorry is a general statement of m1 * (m2 <• g2) = (m1 * m2) <• g2 which may or may not be something that can be expressed with existing typeclasses.

Eric Wieser (Jul 19 2021 at 12:47):

It follows from docs#smul_mul_assoc and docs#mul_smul_comm, but the requirements for those lemmas are stricter than we need as they go through the intermediate state m1 * (m2 <• g2) = (m1 <• g2) * m2 which isn't true when M and G are the same non-commutative monoid (and therefore (<•) = (*)).

Yakov Pechersky (Jul 22 2021 at 01:43):

Here is another related clash:

import linear_algebra.matrix.determinant
import data.polynomial.monic

variables {α n : Type*} [comm_ring α] [fintype n] [decidable_eq n]

open polynomial matrix finset equiv.perm

lemma coeff_finset_prod_zero {β : Type*} (f : β  polynomial α) (l : finset β) :
  coeff (l.prod f) 0 = l.prod (λ p, coeff (f p) 0) :=
let g : polynomial α →+* α := ring_hom.mk (λ p : polynomial α, coeff p 0)
  (by simp) (by simp) (by simp) (by simp) in g.map_prod f l

lemma coeff_finset_sum_zero {β : Type*} (f : β  polynomial α) (l : finset β) :
  coeff (l.sum f) 0 = l.sum (λ p, coeff (f p) 0) :=
let g : polynomial α →+* α := ring_hom.mk (λ p : polynomial α, coeff p 0)
  (by simp) (by simp) (by simp) (by simp) in g.map_sum f l

lemma coeff_det_X_add_C_zero (A B : matrix n n α) :
  coeff (det ((X : polynomial α)  C.map_matrix A + (C.map_matrix B))) 0 =
    det B :=
begin
  rw [det_apply, coeff_finset_sum_zero, det_apply],
  refine finset.sum_congr rfl _,
  simp only [algebra.id.smul_eq_mul, mem_univ, ring_hom.map_matrix_apply, forall_true_left,
             map_apply, dmatrix.add_apply, pi.smul_apply],
  intros g,
  convert coeff_smul (sign g) _ 0, -- really this should be a rewrite
  { sorry },                       -- if not for this diamond
  { rw coeff_finset_prod_zero,
    refine finset.prod_congr rfl _,
    simp },
end

Eric Wieser (Jul 22 2021 at 06:10):

(just to check: docs#polynomial.coeff_smul)

Eric Wieser (Jul 22 2021 at 06:11):

What's the type of the term in the strings m diamond?

Eric Wieser (Jul 22 2021 at 06:36):

Ah, discord clarifies the diamond is docs#units.has_scalar (introduced in #7438) vs docs#polynomial.has_scalar


Last updated: Dec 20 2023 at 11:08 UTC