Zulip Chat Archive

Stream: maths

Topic: Symmetrized product of a real algebra


Christopher Hoskin (Dec 20 2021 at 21:32):

Hello,

I've defined a non-unital, non-associative ring as:

@[protect_proj, ancestor add_comm_group non_unital_non_assoc_semiring ]
class non_unital_non_assoc_ring (α : Type*) extends
  add_comm_group α, non_unital_non_assoc_semiring α

Given an algebra α over , I'm trying to show that α is am instance of non_unital_non_assoc_ring (forgetting about the unit) under symmetrized product:

ab = 1/2(a*b+b*a).

Inspired by how mathlib implements the opposite multiplication (algebra.opposites) I've defined:

def sym_alg (α : Type*) : Type* := α

postfix `ˢʸᵐ`:std.prec.max_plus := sym_alg

It's then possible to show

noncomputable instance (α : Type*) [semiring α] [algebra  α] : non_unital_non_assoc_ring (sym_alg  α)

except that two fields that are tripping me up are neg and add_left_neg as α is a semiring not a ring (alternatively, if I make α a ring, then I can't prove left_distrib and right_distrib).

It's easy to show that if α is a add_comm_group then so is αˢʸᵐ:

instance {α : Type*} [add_comm_group α] : add_comm_group (αˢʸᵐ) := {
  zero := sym 0,
  add := λ a b, a+b,
  add_assoc := λ a b c : α, add_assoc a b c,
  add_comm := λ a b : α, add_comm a b,
  zero_add := λ a, zero_add (unsym a),
  add_zero := λ a, add_zero (unsym a),
  neg := λ a, sym ( -(unsym a)),
  add_left_neg := λ a, add_left_neg (unsym a),
}

I know that module.add_comm_monoid_to_add_comm_group exists, but I've been warned off doing

instance  ring_module_has_add_comm_group : add_comm_group α := module.add_comm_monoid_to_add_comm_group R

as it leads to diamonds.

I can write:

#check (module.add_comm_monoid_to_add_comm_group ).neg -- add_comm_group.neg : ?M_1 → ?M_1

But not:

variables [semiring α] [algebra  α]

variables (a:α)

#check (module.add_comm_monoid_to_add_comm_group ).neg a -- invalid field notation, function 'add_comm_group.neg' does not have explicit argument with type (add_comm_group ...)

I've run out of ideas about how to proceed at this point. Any suggestions?

Thanks,

Christopher

Kevin Buzzard (Dec 20 2021 at 22:25):

Can you post a MWE of your original question with everything other than the neg and add_left_neg thrown in? My guess is that you can just define neg x to be (-1) \bub x. I'm just a bit confused about what the question is though, because if alpha is an add_comm_group then you already have neg. This is why I'm asking for something where I can see exactly what is being assumed.

Christopher Hoskin (Dec 20 2021 at 22:32):

Trying to do that... but now left_distrib has stopped working. I'm sure it was working earlier. I must have changed something, but I can't figure out what.

Kevin Buzzard (Dec 20 2021 at 22:34):

Maybe post what you have with sorried problems? But just one piece of code rather than all the fragments above.

Christopher Hoskin (Dec 20 2021 at 22:35):

I did try defining neg as you suggest, but got in a hopeless tangle trying to prove add_left_neg.

Christopher Hoskin (Dec 20 2021 at 22:38):

This is the best I can do at the moment:

import algebra.ring.basic
import algebra.lie.of_associative
import data.real.basic
set_option old_structure_cmd true

/-- A not-necessarily-unital, not-necessarily-associative ring. -/
@[protect_proj, ancestor add_comm_group non_unital_non_assoc_semiring ]
class non_unital_non_assoc_ring (α : Type*) extends
  add_comm_group α, non_unital_non_assoc_semiring α

variables {A : Type*}

def sym_alg (α : Type*) : Type* := α

postfix `ˢʸᵐ`:std.prec.max_plus := sym_alg

namespace sym_alg

variables {α : Type*}

/-- The element of `sym_alg α` that represents `a : α`. -/
@[pp_nodot]
def sym : α  αˢʸᵐ := id

/-- The element of `α` represented by `x : αᵐᵒᵖ`. -/
@[pp_nodot]
def unsym : αˢʸᵐ  α := id

@[simp] lemma unsym_sym (x : α) : unsym (sym x) = x := rfl
@[simp] lemma sym_unsym (x : α) : sym (unsym x) = x := rfl


instance [has_add α] : has_add αˢʸᵐ :=
{ add := λ a b, sym (unsym a + unsym b) }

@[simp] lemma sym_add [has_add α] (a b : α) : sym (a + b) = sym a + sym b := rfl
@[simp] lemma unsym_add [has_add α] (x y : αˢʸᵐ) : unsym (x + y) = unsym x + unsym y := rfl


instance [has_neg α] : has_neg αˢʸᵐ :=
{ neg := λ a, sym ( -(unsym a)) }

instance {R : Type*} [has_scalar R α] : has_scalar R αˢʸᵐ := {
  smul := λ r a, sym (r(unsym a))
}


@[simp] lemma sym_smul {R : Type*} [has_scalar R α] (c : R) (a : α) : sym (c  a) = c  sym a := rfl

lemma add_smul (α : Type*) [ring α] [algebra  α] (a:α) (r s : ): (r+s)a = (ra +sa)   :=
begin
  unfold algebra.smul_def',
  rw  add_mul,
  simp only [map_add, ring_hom.to_fun_eq_coe],
end

lemma smul_add' (α : Type*) [ring α] [algebra  α] (a b:α) (r : ): r(a+b) = ra + rb   :=
begin
  unfold algebra.smul_def',
  rw  mul_add,
end


instance {α : Type*} [add_comm_group α] : add_comm_group (αˢʸᵐ) := {
  zero := sym 0,
  add := λ a b, a+b,
  add_assoc := λ a b c : α, add_assoc a b c,
  add_comm := λ a b : α, add_comm a b,
  zero_add := λ a, zero_add (unsym a),
  add_zero := λ a, add_zero (unsym a),
  neg := λ a, sym ( -(unsym a)),
  add_left_neg := λ a, add_left_neg (unsym a),
}


noncomputable instance (α : Type*) [semiring α] [algebra  α] : non_unital_non_assoc_ring (αˢʸᵐ) := {
  zero := sym 0,
  add := λ a b, a+b,
  add_assoc := λ a b c : α, add_assoc a b c,
  add_comm := λ a b : α, add_comm a b,
  zero_add := λ a, zero_add (unsym a),
  add_zero := λ a, add_zero (unsym a),
  neg := λ a, sorry,
  add_left_neg := λ a, sorry,
  mul := λ a b, (sym ((1/2:)(unsym(a)*unsym(b)+unsym(b)*unsym(a)))),
  zero_mul := λ _, by simp,
  mul_zero :=  λ _, by simp,
  left_distrib := λ a b c, sorry,
  right_distrib := λ a b c, sorry,
}



end sym_alg

Thomas Browning (Dec 20 2021 at 22:54):

This is awful, but it seems to work (assuming ring rather than semiring).

noncomputable instance (α : Type*) [ring α] [algebra  α] : non_unital_non_assoc_ring (αˢʸᵐ) := {
  zero := sym 0,
  add := λ a b, a+b,
  add_assoc := λ a b c : α, add_assoc a b c,
  add_comm := λ a b : α, add_comm a b,
  zero_add := λ a, zero_add (unsym a),
  add_zero := λ a, add_zero (unsym a),
  neg := λ a, -a,
  add_left_neg := λ a, add_left_neg (unsym a),
  mul := λ a b, (sym ((1/2:)(unsym(a)*unsym(b)+unsym(b)*unsym(a)))),
  zero_mul := λ _, by simp,
  mul_zero :=  λ _, by simp,
  left_distrib := λ a b c, begin
    change (1/2:)(unsym(a)*(unsym(b)+unsym(c))+(unsym(b)+unsym(c))*unsym(a)) =
      (1/2:)(unsym(a)*unsym(b)+unsym(b)*unsym(a))+(1/2:)(unsym(a)*unsym(c)+unsym(c)*unsym(a)),
    rw [mul_add, add_mul, smul_add, smul_add, smul_add, smul_add, smul_add],
    abel,
  end,
  right_distrib := λ a b c, begin
    change (1/2:)((unsym(a)+unsym(b))*unsym(c)+unsym(c)*(unsym(a)+unsym(b))) =
      (1/2:)(unsym(a)*unsym(c)+unsym(c)*unsym(a))+(1/2:)(unsym(b)*unsym(c)+unsym(c)*unsym(b)),
    rw [mul_add, add_mul, smul_add, smul_add, smul_add, smul_add, smul_add],
    abel,
  end,
}

Kevin Buzzard (Dec 20 2021 at 22:55):

My guess is that a semiring which is an \R-algebra is a ring

Christopher Hoskin (Dec 20 2021 at 22:57):

Yes, that's true. We have module.add_comm_monoid_to_add_comm_group, but how to use it?

Thomas Browning (Dec 20 2021 at 23:02):

Here's one way:

noncomputable instance (α : Type*) [semiring α] [algebra  α] : non_unital_non_assoc_ring (αˢʸᵐ) := {
  zero := sym 0,
  add := λ a b, a+b,
  add_assoc := λ a b c : α, add_assoc a b c,
  add_comm := λ a b : α, add_comm a b,
  zero_add := λ a, zero_add (unsym a),
  add_zero := λ a, add_zero (unsym a),
  neg := λ a, (-1:)unsym(a),
  add_left_neg := λ a,
  calc (-1:)unsym(a)+unsym(a) = (-1:)unsym(a)+(1:)(unsym(a)) : by rw one_smul
    ... = ((-1:)+(1:))unsym(a) : by rw _root_.add_smul
    ... = (0:)unsym(a) : by rw neg_add_self
    ... = 0 : by rw zero_smul,
  mul := λ a b, (sym ((1/2:)(unsym(a)*unsym(b)+unsym(b)*unsym(a)))),
  zero_mul := λ _, by simp,
  mul_zero :=  λ _, by simp,
  left_distrib := λ a b c, begin
    change (1/2:)(unsym(a)*(unsym(b)+unsym(c))+(unsym(b)+unsym(c))*unsym(a)) =
      (1/2:)(unsym(a)*unsym(b)+unsym(b)*unsym(a))+(1/2:)(unsym(a)*unsym(c)+unsym(c)*unsym(a)),
    rw [mul_add, add_mul, smul_add, smul_add, smul_add, smul_add, smul_add],
    abel,
  end,
  right_distrib := λ a b c, begin
    change (1/2:)((unsym(a)+unsym(b))*unsym(c)+unsym(c)*(unsym(a)+unsym(b))) =
      (1/2:)(unsym(a)*unsym(c)+unsym(c)*unsym(a))+(1/2:)(unsym(b)*unsym(c)+unsym(c)*unsym(b)),
    rw [mul_add, add_mul, smul_add, smul_add, smul_add, smul_add, smul_add],
    abel,
  end,
}

Eric Wieser (Dec 20 2021 at 23:07):

Christopher Hoskin said:

Yes, that's true. We have module.add_comm_monoid_to_add_comm_group, but how to use it?

I can't help feeling this is an #xy problem - why do you want this vs the

noncomputable instance (α : Type*) [ring α] [algebra  α] : non_unital_non_assoc_ring (αˢʸᵐ)

instance that was suggested above?

Thomas Browning (Dec 20 2021 at 23:11):

One advantage to assuming [ring α] [algebra ℝ α] (which isn't weaker, since it is implied by [semiring α] [algebra ℝ α]) is that negation on αˢʸᵐ is defeq to negation on α.

Christopher Hoskin (Dec 20 2021 at 23:12):

[ring α] is fine with me - it's a more natural way of thinking about it. I just couldn't get it to work before, but @Thomas Browning has shown that it can be done. Thanks!

Eric Wieser (Dec 20 2021 at 23:16):

I'd also recommend starting with:

instance [has_zero α] : has_zero (αˢʸᵐ) := { zero := sym 0 }
instance [has_add α] : has_add αˢʸᵐ := { add := λ a b, sym (unsym a + unsym b) }
instance [has_sub α] : has_sub αˢʸᵐ := { sub := λ a b, sym (unsym a - unsym b) }
instance [has_neg α] : has_neg αˢʸᵐ := { neg := λ a, sym (-unsym a) }
instance [has_scalar R α] : has_scalar R αˢʸᵐ := { smul := λ r a, sym (r(unsym a)) }

-- add all the `sym_add` etc lemmas you already have here

lemma unsym_injective : function.injective (@unsym α) := λ _ _, id

-- build up all the proof structures:
instance [add_comm_semigroup α] : add_comm_semigroup (αˢʸᵐ) :=
unsym_injective.add_comm_semigroup _ (λ _ _, rfl)

instance [add_monoid α] : add_monoid (αˢʸᵐ) :=
unsym_injective.add_monoid_smul _ rfl (λ _ _, rfl) (λ _ _, rfl)

instance [add_group α] : add_group (αˢʸᵐ) :=
unsym_injective.add_group_smul _ rfl
  (λ _ _, rfl) (λ _, rfl) (λ _ _, rfl) (λ _ _, rfl) (λ _ _, rfl)

instance [add_comm_monoid α] : add_comm_monoid (αˢʸᵐ) :=
{ ..sym_alg.add_comm_semigroup, ..sym_alg.add_monoid }

instance [add_comm_group α] : add_comm_group (αˢʸᵐ) :=
{ ..sym_alg.add_comm_monoid, ..sym_alg.add_group }

instance [semiring R] [add_comm_monoid α] [module R α] : module R αˢʸᵐ :=
function.injective.module R unsym, rfl, λ _ _, rfl (λ _ _, id) (λ _ _, rfl)

This will avoid ugly instance diamonds later, and also means you don't need your own add_smul and smul_add' lemmas.

Christopher Hoskin (Dec 26 2021 at 09:44):

Thanks. I'm now stuck trying to show that the squares of both multiplications coincide (up to identification):

lemma powers [ring α] [algebra  α] (a: αˢʸᵐ) : unsym(a*a) = unsym a * unsym a :=
begin
  change (1/2:)(unsym(a)*unsym(a)+unsym(a)*unsym(a)) = unsym(a)*unsym(a),
      abel,
      --rw smul_smul,
      unfold algebra.smul_def',
      rw  mul_assoc,
      --rw ← map_mul,
      --rw ← algebra.to_ring_hom.map_mul' (1/2:ℝ) (2:ℤ),
      --rw ← (algebra_map ℝ α).map_mul' (1/2:ℝ) (2:ℤ),
      --rw ← mul_hom.map_mul' algebra.to_ring_hom,
      --rw ← map_mul algebra.to_ring_hom.to_fun (1/2:ℝ) (2:ℤ),
      sorry,
end

I get to

 algebra.to_ring_hom.to_fun (1 / 2) * algebra.to_ring_hom.to_fun 2 * (unsym a * unsym a) = unsym a * unsym a

But then can't find the correct incantation to bring the 2 and 1/2 together so that they cancel out.

Christopher

Eric Wieser (Dec 26 2021 at 09:55):

At the point you introduced to_fun into the goal you made a wrong turn

Christopher Hoskin (Dec 26 2021 at 12:03):

Yes, the problem is I don't know how to convert the (2:ℤ) that abel gives me into (2:ℝ) so that I can invoke smul_smul.

Okay:

lemma test2 [ring α] [algebra  α] (r :) (s: ) (a:α) : r(sa) = (r*s)a :=
begin
  rw smul_smul r s a,
end

Fails:

lemma test2 [ring α] [algebra  α] (r :) (s: ) (a:α) : r(sa) = (r*s)a :=
begin
  rw smul_smul r s a,
end

Yaël Dillies (Dec 26 2021 at 12:05):

norm_cast, norm_num or docs#int.cast_two should all do the job.

Eric Wieser (Dec 26 2021 at 12:30):

docs#smul_assoc should apply there

Christopher Hoskin (Dec 26 2021 at 18:00):

Finally got there with:

theorem two_rmul [ring α] [algebra  α]  (x:α) : (2 : )  x = x + x :=
begin
   rw [bit0, add_smul, one_smul],
end

lemma powers [ring α] [algebra  α] (a: αˢʸᵐ) : unsym(a*a) = unsym a * unsym a :=
begin
  rw mul_def,
  rw unsym_sym,
  rw  two_rmul,
  rw  smul_assoc,
  simp,
end

Eric Wieser (Dec 26 2021 at 22:17):

Isn't that first lemma just docs#two_smul?

Oliver Nash (Dec 28 2021 at 11:16):

Catching up on this thread (and the corresponding PR #11073) I have a question: is there a Jordan equivalent of Poisson algebras? More precisely, is it ever necessary to be able to regard a type _simultaneously_ as a Jordan ring and an associative ring?

Oliver Nash (Dec 28 2021 at 11:19):

I couldn't quite figure out what right compatibility between the two structures would be but if these structures do arise then the proposed setup might be awkward because both operations are trying to own has_mul.


Last updated: Dec 20 2023 at 11:08 UTC