Zulip Chat Archive
Stream: lean4
Topic: Beginner question about typeclass constraints
Andrija D. (Sep 29 2022 at 07:09):
I wanted to try proving something about groups and I have
class Invertable (a : Type) where
inv : a -> a
class GroupOp (a : Type) where
op : a -> a -> a
infixl:70 " ⬝ " => GroupOp.op
notation:100 lhs:100 "⁻¹" => Invertable.inv lhs
class Group (a : Type) extends GroupOp a, Invertable a where
e : a
assoc : ∀ x y z : a, x ⬝ y ⬝ z = x ⬝ (y ⬝ z)
mul_one : ∀ x : a, x ⬝ e = x
left_inv : ∀ x : a, x⁻¹ ⬝ x = e
theorem right_inv [Group a] (a : Type) : ∀ (x : a), x ⬝ x⁻¹ = e :=
_
But the x ⬝ x⁻¹
part is highlighted with "failed to synthesize instance" for GroupOp and Invertable. Both of those should be entailed by the [Group a]
as far as I understand it, but I tried adding them explicitly just in case, yet the same error remains. This led me to ask, how do you even specify typeclass constraints in Lean 4? And ultimately of course, how do I go about solving this issue?
Kevin Buzzard (Sep 29 2022 at 07:15):
(Not that this is relevant to your question, but I think your axioms do not define a group, eg x^-1:=e and x.y:=x are a model, so your theorem is not provable)
Mario Carneiro (Sep 29 2022 at 07:17):
You introduced a
after the typeclass [Group a]
, meaning you shadowed the auto-bound a
with another a
which is not a group
Kevin Buzzard (Sep 29 2022 at 07:17):
Possibly more relevant to your question: what happens if you switch the order of [Group a]
and (a : Type)
in the theorem? Right now the order doesn't make sense to me and I'm wondering if you have two a
s.
Mario Carneiro (Sep 29 2022 at 07:18):
It should probably be an error to shadow an auto-bound variable since that's almost certainly a typo
Andrija D. (Sep 29 2022 at 07:22):
It does work, although there's type mismatch on e, I probably should qualify it somehow.
As for the axioms, maybe haha, classically at least you can prove it with those afaik, and I was going to prove it in Lean to get a hang of some basic tactics
Kevin Buzzard (Sep 29 2022 at 11:57):
Yeah if you don't set up notation for e I guess you'll have to write a.e
. You can take a look at mathlib4 for how they do it there, they use 1 and set up notation for it. I disagree with your claim that classically you can prove it. If I've not made a mistake then my original post explains why. If you make right_inv the axiom instead of left_inv you're ok (you can prove left_inv).
Andrija D. (Sep 29 2022 at 13:25):
@Kevin Buzzard
to prove e*x = x for all x
assume e*x =/= x
then
e*x = y, x =/= y
y^-1 * (e * x) = y^-1 * y
y^-1 * (e * x) = e (left inverse)
(y^-1 * e) * x = e (assoc)
y^-1 * x = e (right identity)
y^-1 * y = e (def of inverse)
y^-1 * y = y^-1 * x
x = y (contradiction to original assumption)
to prove x * x^-1 = e for all x
x^-1 * (x * x^-1) = x^-1 * e
x^-1 * (x * x^-1) = x^-1 (right identity)
(x^-1 * x) * x^-1 = x^-1 (assoc)
e * x^-1 = x^-1 (left inverse)
this is true based on that lemma above
Does this not prove it? I wrote the steps I took in the parens just to make sure I am not using any axioms I haven't defined, and it seems to work out. Or if I made a mistake somewhere along the way please correct me :pray:
Ruben Van de Velde (Sep 29 2022 at 13:35):
I don't follow your proof of x * x^-1 = e
.
(It is known that associativity + left inverse + left identity or associativity + right inverse + right identity are sufficient to be a group, but I do think the sides need to match)
Ruben Van de Velde (Sep 29 2022 at 13:37):
And Kevin's counterexample does seem to work
Ruben Van de Velde (Sep 29 2022 at 13:45):
Confirmed in lean 3:
import group_theory.abelianization
class Group (a : Type) extends has_mul a, has_inv a :=
(e : a)
(assoc : ∀ x y z : a, x * y * z = x * (y * z))
(mul_one : ∀ x : a, x * e = x)
(left_inv : ∀ x : a, x⁻¹ * x = e)
inductive counter
| One
| Two
open counter
instance : Group counter :=
{ mul := λ x y, x,
inv := λ x, One,
e := One,
assoc := λ x y z, rfl,
mul_one := λ x, rfl,
left_inv := λ x, rfl }
lemma no_right_inv : ¬(∀ (x : counter), x * x⁻¹ = One) :=
begin
push_neg,
refine ⟨Two, _⟩,
trivial,
end
Kyle Miller (Sep 29 2022 at 14:35):
Kevin Buzzard said:
Yeah if you don't set up notation for e
The quick way to use an unqualified e
for the identity is
export Group (e)
Then this works:
theorem right_inv [Group a] : ∀ (x : a), x ⬝ x⁻¹ = e :=
_
Andrija D. (Sep 29 2022 at 14:47):
@Ruben Van de Velde
Correct me if I'm wrong, but I think we have
x = y <-> z*x = z*y, for all z
Then I'll just rewrite the proof as:
Assume x * x^-1 =/= e
Then:
x^-1 * (x * x^-1) =/= x^-1 * e
(rewrite based on that assumption above)x^-1 * (x * x^-1) =/= x^-1
(rewrite rhs based on right identity)(x^-1 * x) * x^-1 =/= x^-1
(rewrite based on associativity)e * x^-1 =/= x^1
(simplify based on left inverse)
This contradicts that mini lemma from before, and as far as I see I used only my own axioms (specific steps written between parens)
Ruben Van de Velde (Sep 29 2022 at 14:51):
Andrija D. said:
Ruben Van de Velde
Correct me if I'm wrong, but I think we have
x = y <-> z*x = z*y, for all z
I'm afraid I do have to correct you :)
With the same setup as above
lemma no_cancel : ¬(∀ (x y z: counter), z * x = z * y → x = y) :=
begin
push_neg,
refine ⟨Two, One, One, rfl, _⟩,
trivial,
end
Andrija D. (Sep 29 2022 at 15:01):
But don't we have
z*x = z*y
z^-1 * (z * x) = z^-1 * (z * y)
(apply the one sided implicationx = y -> z*x = z*y
)(z^-1 * z) * x = (z^1 * z) * y
(assoc)e * x = e * y
(left inverse)e * x = x = e * y
(lemma)e*y = x
(drop leftmost, eq reflex)e*y = y = x
(lemma)x = y
(drop leftmost, eq reflex)
Since you've proven this wrong in Lean I'm confused, but I can't find the mistake in my own steps :joy:
Ruben Van de Velde (Sep 29 2022 at 15:07):
Remember that you have assumed that x*e = x
, not that e*x = x
, so step 5 goes wrong
Ruben Van de Velde (Sep 29 2022 at 15:08):
(It turns out that assuming left-cancellativity is indeed sufficient, so the rest of your argument does work. Not sure if that's surprising.)
class Group' (a : Type) extends has_mul a, has_inv a :=
(e : a)
(assoc : ∀ x y z : a, x * y * z = x * (y * z))
(mul_one : ∀ x : a, x * e = x)
(left_inv : ∀ x : a, x⁻¹ * x = e)
(cancel : ∀ (x y z: a), z * x = z * y → x = y)
namespace Group'
lemma one_mul (a) [Group' a] (x : a) : e * x = x :=
begin
apply cancel _ _ (e * x)⁻¹,
have : ((e * x)⁻¹ * e) * x = e,
{ rw [assoc, left_inv], },
rw mul_one at this,
apply eq.trans _ this.symm,
rw left_inv,
end
end Group'
Andrija D. (Sep 29 2022 at 15:09):
But e*x = x was my first lemma thingy, the first part in the message you originally replied to
Ruben Van de Velde (Sep 29 2022 at 15:11):
z * x = z * y → x = y
and e * x = x
appear to be equivalent given your other axioms - you can prove each by using the other
Ruben Van de Velde (Sep 29 2022 at 15:12):
Andrija D. said:
y^-1 * y = y^-1 * x
(true up to here)
x = y
(does not follow without assuming cancellativity)
Andrija D. (Sep 29 2022 at 15:17):
I forgot to write it, but doesn't it follow from uniqueness of the inverse?
Let a = y^-1
, then we have
a * a^-1 = a * x
e = a*x
x = a^-1 = y
Steps 1 and 3 use (y^-1)^-1 = y
which also uses the uniqueness of the inverse
Ruben Van de Velde (Sep 29 2022 at 15:17):
It's really easy to lose track of what you have and haven't proved at this early point :)
Ruben Van de Velde (Sep 29 2022 at 15:18):
(y^-1)^-1 = y
is not true given your axioms
Ruben Van de Velde (Sep 29 2022 at 15:18):
(better: "does not follow from your axioms")
Ruben Van de Velde (Sep 29 2022 at 15:27):
Anyway, it really is a nice exercise to write this proof, but you will need to change your mul_one
axiom to one_mul
Ruben Van de Velde (Sep 29 2022 at 15:28):
(I have a proof in lean3 I can link to once you've tried yourself)
Andrija D. (Sep 29 2022 at 15:33):
Ah you're right, that was the problem, I'll write the proof when I get some time. I guess the whole purpose of proof assistants is to avoid mistakes like these
Patrick Massot (Sep 29 2022 at 15:37):
It's definitely not the whole purpose, but it's part of it.
Last updated: Dec 20 2023 at 11:08 UTC