Zulip Chat Archive
Stream: lean4
Topic: groups
learnerofmaths (May 19 2021 at 23:04):
Hello, I am trying to define groups in lean4 to get a sense of what it would mean to use a theorem prover for work. Here is how far I have gotten:
section groupdefs
class One (α : Type u) where
one : α
class Inv (α : Type u) where
inv : α → α
class Mul (G : Type u) where
mul : G → G
-- Set up notation typeclass using `extends`.
class has_group_notation (G : Type u) extends Mul G, One G, Inv G
-- definition of the group structure
class group (G : Type u) extends has_group_notation G where
mul_assoc (a b c : G) : a * b * c = a * (b * c)
But I am having issues here since I keep getting an error "(kernel) declaration has metavariables 'mygroup.group.mk'Lean 4" . Does anyone know what's happening? Is this the right way to start defining one's own definition of a group?
Best!
Mario Carneiro (May 19 2021 at 23:12):
I get an error on class Mul saying that Mul is already declared. What version of lean 4 are you using?
Mario Carneiro (May 19 2021 at 23:15):
You need to use the Mul declared in the core library if you want to get the * notation, or declare your own * notation in terms of your Mul
Mario Carneiro (May 19 2021 at 23:15):
Here's a version using the classes from core:
class abbrev One (α : Type u) := OfNat α 1
class Inv (α : Type u) where
inv : α → α
-- Set up notation typeclass using `extends`.
class has_group_notation (G : Type u) extends Mul G, One G, Inv G
-- definition of the group structure
class group (G : Type u) extends has_group_notation G where
mul_assoc (a b c : G) : a * b * c = a * (b * c)
learnerofmaths (May 19 2021 at 23:15):
Sorry about that you need a custom namespace. I missed that
namespace mygroup
-- definitions of the group classes
section groupdefs
class One (α : Type u) where
one : α
class Inv (α : Type u) where
inv : α → α
class Mul (G : Type u) where
mul : G → G
-- Set up notation typeclass using `extends`.
class has_group_notation (G : Type u) extends Mul G, One G, Inv G
-- definition of the group structure
class group (G : Type u) extends has_group_notation G where
mul_assoc (a b c : G) : a * b * c = a * (b * c)
The version of lean is "leanprover/lean4:4.0.0"
learnerofmaths (May 19 2021 at 23:17):
I see thank you!
learnerofmaths (May 19 2021 at 23:18):
Mario Carneiro said:
You need to use the
Muldeclared in the core library if you want to get the*notation, or declare your own*notation in terms of yourMul
Thank you!
learnerofmaths (May 19 2021 at 23:21):
section groupdefs
class abbrev One (α : Type u) := OfNat α 1
class Inv (α : Type u) where
inv : α → α
-- Set up notation typeclass using `extends`.
class has_group_notation (G : Type u) extends Mul G, One G, Inv G
-- definition of the group structure
class group (G : Type u) extends has_group_notation G where
mul_assoc (a b c : G) : a * b * c = a * (b * c)
one_mul (a : G) : 1 * a = a
mul_left_inv (a : G) : a⁻¹ * a = 1
Now almost works. But I get a strange error with using \^-1. "expected termLean 4" Screen-Shot-2021-05-19-at-7.20.50-PM.png
Mario Carneiro (May 19 2021 at 23:22):
Just like Mul, Inv doesn't itself come with any notation, especially since it was just defined
Mario Carneiro (May 19 2021 at 23:23):
notation a "⁻¹" => Inv.inv a
learnerofmaths (May 19 2021 at 23:23):
ah! Ok, starting to get the hang of that.
learnerofmaths (May 19 2021 at 23:23):
makes sense.
Mario Carneiro (May 19 2021 at 23:24):
One does work because it is abbreviating the class OfNat A 1 that is used to resolve the meaning of 1 : A
learnerofmaths (May 19 2021 at 23:25):
I see. But why is 1 not considered a type of "notation" but rather a class?
Mario Carneiro (May 19 2021 at 23:26):
Just like inv and mul, there is a notation that says that number literals are defined to be OfNat.ofNat A n where OfNat is a class
Mario Carneiro (May 19 2021 at 23:26):
it's defined somewhere in the core library and it's a bit more complicated because it has to match on number literals
learnerofmaths (May 19 2021 at 23:27):
So something like notation "1" => OfNat.ofNat 1 (This is wrong, but something like this?) ? But my 1 has nothing to do with natural numbers, right? It's just notation?
Mario Carneiro (May 19 2021 at 23:29):
Conceptually that's what it is doing, yes
Mario Carneiro (May 19 2021 at 23:29):
there are an infinite number of such notations that have to be declared though so it is written in a more complicated way
Mario Carneiro (May 19 2021 at 23:30):
the actual code is here. It is using the more low level interface that notation desugars into
Mario Carneiro (May 19 2021 at 23:31):
it's probably unreadable but you can see OfNat.ofNat getting referenced
learnerofmaths (May 19 2021 at 23:31):
Alright. Sometimes the easiest things are so fundamental they are complicated. Off to prove some theorems and excited to learn lean : )
learnerofmaths (May 23 2021 at 22:27):
Hello again, I am trying to prove some properties of groups. But I am getting hung up on various syntax issues. Here is my initial definition
-- We're overwriting inbuilt group theory here so we always work in
-- a namespace
namespace mygroup
-- definitions of the group classes
section groupdefs
-- Notation for One done in an odd way
class abbrev One (α : Type u) := OfNat α 1
-- define inverse class and notation
class Inv (α : Type u) where
inv : α → α
notation a "⁻¹" => Inv.inv a
-- Set up notation typeclass using `extends` for define classes
class has_group_notation (G : Type u) extends Mul G, One G, Inv G
-- definition of the group structure
class group (G : Type u) extends has_group_notation G where
mul_assoc (a b c : G) : a * b * c = a * (b * c)
one_mul (a : G) : 1 * a = a
mul_left_inv (a : G) : a⁻¹ * a = 1
export group (mul_assoc one_mul mul_left_inv )
-- example of abelian group
class comm_group (G : Type u) extends group G where
mul_comm (a b : G) : a * b = b * a
end groupdefs
namespace group
theorem inv_mul_cancel_left [group G] (a b : G) : a⁻¹ * (a * b) = b := by
have a⁻¹ * (a * b) = (a⁻¹ * a) * b := by rw [mul_assoc]
have (a⁻¹ * a) = 1 := by rw [mul_left_inv]
have 1 * b = b := by rw [one_mul]
end group
end mygroup
-
the first issue is that
[group G ] (a b : G)is not valid while[group α ] (a b : α )why this statement sensitive to Unicode greek letters? I get an "unknown identifier 'G'". -
My next issue is that I am not sure how to tell lean to complete a proof when I replace G with α:
theorem inv_mul_cancel_left [group α ] (a b : α ) : a⁻¹ * (a * b) = b := by
have a⁻¹ * (a * b) = (a⁻¹ * a) * b := by rw [mul_assoc]
have (a⁻¹ * a) = 1 := by rw [mul_left_inv]
have 1 * b = b := by rw [one_mul]
Gives a bunch of errors that I attached.
Thank your help. Screen-Shot-2021-05-23-at-6.25.54-PM.png
Alex J. Best (May 23 2021 at 22:54):
Mac said:
Kevin Buzzard said:
I'm on today's nightly.
example : ∀ (x : Prop), x ↔ x ↔ x := sorry -- compiles example : ∀ (A : Prop), A ↔ A ↔ A := sorry -- fails on third A example : ∀ (A : Prop), a ↔ a ↔ a := sorry -- compiles?!
This is because it is being parsed as Mario Carneiro showed and then the unbound lowercase latin letters are being auto bound as specified in https://leanprover.github.io/lean4/doc/autobound.html
I'm guessing you are seeing this behaviour and you need to add {G : Type u} to have it work
learnerofmaths (May 24 2021 at 03:18):
I checked it out. I tried that change and a different error happened. I attached it. Screen-Shot-2021-05-23-at-11.17.43-PM.png
Scott Morrison (May 24 2021 at 03:27):
Please post code blocks (ideally as #mwe), rather than screenshots! You'll get much more help. :-)
Yakov Pechersky (May 24 2021 at 03:57):
You need {G : Type u} [group G] (a b : G)
Yakov Pechersky (May 24 2021 at 03:59):
We first postulate an arbitrary type G, then postulate that it has a group structure, then say "let a and b be terms of G"
learnerofmaths (May 24 2021 at 04:40):
ahhh! I see that. Makes total sense @Yakov Pechersky . Now I get some of others with
-- We're overwriting inbuilt group theory here so we always work in
-- a namespace
namespace mygroup
-- definitions of the group classes
section groupdefs
-- Notation for One done in an odd way
class abbrev One (α : Type u) := OfNat α 1
-- define inverse class and notation
class Inv (α : Type u) where
inv : α → α
notation a "⁻¹" => Inv.inv a
-- Set up notation typeclass using `extends` for define classes
class has_group_notation (G : Type u) extends Mul G, One G, Inv G
-- definition of the group structure
class group (G : Type u) extends has_group_notation G where
mul_assoc (a b c : G) : a * b * c = a * (b * c)
one_mul (a : G) : 1 * a = a
mul_left_inv (a : G) : a⁻¹ * a = 1
export group (mul_assoc one_mul mul_left_inv )
-- example of abelian group
class comm_group (G : Type u) extends group G where
mul_comm (a b : G) : a * b = b * a
end groupdefs
namespace group
theorem inv_mul_cancel_left {G : Type u} [group G] (a b : G) : a⁻¹ * (a * b) = b := by
have a⁻¹ * (a * b) = (a⁻¹ * a) * b := by rw [mul_assoc]
have (a⁻¹ * a) = 1 := by rw [mul_left_inv]
have 1 * b = b := by rw [one_mul]
end group
end mygroup
I get two instances of "failed to synthesize instance OfNat G 1" and I can't seem to tell lean that I have proved the theorem.
Thanks for the tip @Scott Morrison ! : )
Eric Wieser (May 24 2021 at 04:50):
You haven't proved the theorem, you've proved three intermediate results without joining them together
Eric Wieser (May 24 2021 at 04:51):
Adding rw this after each have probably resolves that
Kevin Buzzard (May 24 2021 at 06:38):
Your first comment in the code is not correct. Lean 4 does not have inbuilt groups
learnerofmaths (May 24 2021 at 13:03):
Hi, @Kevin Buzzard I was referring to https://github.com/leanprover/lean4/blob/master/tests/lean/run/alg.lean and https://github.com/leanprover/lean4/blob/master/tests/lean/run/alg.lean . But these appear as tests, so I will remove that comment.
Kevin Buzzard (May 24 2021 at 13:04):
If you import Mathlib.Algebra.Group.Defs from mathlib4 you can have groups :-)
learnerofmaths (May 24 2021 at 13:15):
@Eric Wieser , awesome. But I still get "failed to synthesize instance OfNat G 1" and red squiggly lines under the ones ('1'). Have you seen that before?
Do you happen to know what "rw this" means? Is there another way without rw this? My understanding was that for lean3 there was something called 'calc' and you could write proofs using chains of implications that looked like:
calc a⁻¹ * (a * b) = (a⁻¹ * a) * b : by rw mul_assoc
... (a⁻¹ * a) * b : by rw mul_left_inv
... 1 * b = b : by rw one_mul
Here's the current code so far. Thank you for getting me on board.
-- 'If you import Mathlib.Algebra.Group.Defs from mathlib4 you can have groups :-)' ~ Kevin Buzzard
-- To get the swing of things built everything here
namespace mygroup
-- definitions of the group classes
section groupdefs
-- Notation for One done in an odd way
class abbrev One (α : Type u) := OfNat α 1
-- define inverse class and notation
class Inv (α : Type u) where
inv : α → α
notation a "⁻¹" => Inv.inv a
-- Set up notation typeclass using `extends` for define classes
class has_group_notation (G : Type u) extends Mul G, One G, Inv G
-- definition of the group structure
class group (G : Type u) extends has_group_notation G where
mul_assoc (a b c : G) : a * b * c = a * (b * c)
one_mul (a : G) : 1 * a = a
mul_left_inv (a : G) : a⁻¹ * a = 1
export group (mul_assoc one_mul mul_left_inv )
-- example of abelian group
class comm_group (G : Type u) extends group G where
mul_comm (a b : G) : a * b = b * a
end groupdefs
namespace group
theorem inv_mul_cancel_left {G : Type u} [group G] (a b : G) : a⁻¹ * (a * b) = b := by
have a⁻¹ * (a * b) = (a⁻¹ * a) * b := by rw [mul_assoc]
rw this
have (a⁻¹ * a) = 1 := by rw [mul_left_inv]
rw this
have 1 * b = b := by rw [one_mul]
rw this
end group
end mygroup
Screen-Shot-2021-05-24-at-9.14.17-AM.png
Eric Wieser (May 24 2021 at 13:19):
have some_statement := sorry is short for have this : some_statement := sorry, meaning "prove some_statement and put the proof in a hypothesis called this" (at least, it is in lean3 and I assume it hasn't changed in lean 4).
Eric Wieser (May 24 2021 at 13:20):
Someone else who actually knows lean4 will have to help you with your ofNat problem
Eric Wieser (May 24 2021 at 13:23):
The calc proof you show there doesn't work in lean3 either though - an= is in the wrong place
Kevin Buzzard (May 24 2021 at 13:27):
Check out Mathlib.Algebra.Group.Defs for how to do 1 in Lean 4.
learnerofmaths (May 24 2021 at 13:29):
I see @Eric Wieser . I am very new to lean. I saw that notation used elsewhere. I have also seen
theorem inv_mul_cancel_left (a b : G) : a⁻¹ * (a * b) = b :=
by rw [← mul_assoc, mul_left_inv, one_mul]
Is the above version with the "have" and "rw this" the same? What is "← " doing here? I am happy to look at documentation just not sure what to search for. Are there names for these different styles?
Ruben Van de Velde (May 24 2021 at 13:31):
rw mul_assoc rewrites a * b * c to a * (b * c); rw ←mul_assoc rewrites a * (b * c) to a * b * c
learnerofmaths (May 24 2021 at 13:33):
@Kevin Buzzard I tried your suggestion. But I get unknown identifier 'nat_lit'Lean 4
-- 'If you import Mathlib.Algebra.Group.Defs from mathlib4 you can have groups :-)' ~ Kevin Buzzard
-- To get the swing of things built everything here
namespace mygroup
-- definitions of the group classes
section groupdefs
-- -- Notation for One done in an odd way
-- class abbrev One (α : Type u) := OfNat α 1
class One (α : Type u) where
one : α
instance [One α] : OfNat α (nat_lit 1) where
ofNat := One.one
-- define inverse class and notation
class Inv (α : Type u) where
inv : α → α
notation a "⁻¹" => Inv.inv a
-- Set up notation typeclass using `extends` for define classes
class has_group_notation (G : Type u) extends Mul G, One G, Inv G
-- definition of the group structure
class group (G : Type u) extends has_group_notation G where
mul_assoc (a b c : G) : a * b * c = a * (b * c)
one_mul (a : G) : 1 * a = a
mul_left_inv (a : G) : a⁻¹ * a = 1
export group (mul_assoc one_mul mul_left_inv )
-- example of abelian group
class comm_group (G : Type u) extends group G where
mul_comm (a b : G) : a * b = b * a
end groupdefs
namespace group
theorem inv_mul_cancel_left {G : Type u} [group G] (a b : G) : a⁻¹ * (a * b) = b := by
have intial_assumption : a⁻¹ * (a * b) = (a⁻¹ * a) * b := by rw [mul_assoc]
rw intial_assumption
have (a⁻¹ * a) = 1 := by rw [mul_left_inv]
rw this
have 1 * b = b := by rw [one_mul]
rw this
end group
end mygroup
Julian Berman (May 24 2021 at 14:20):
I think that'll mean your lean4 is too old -- what does lean --version say? (Or just update to a more recent one). nat_lit used to be called natLit!.
learnerofmaths (May 24 2021 at 14:24):
Hi @Julian Berman . My current version of lean is
group_theory$ lean --version
Lean (version 4.0.0-m2, commit 26dda3f63d88, Release)
Julian Berman (May 24 2021 at 14:25):
Hello -- yeah natLit! got renamed about 10 days after that -- you should probably stick to the version of Lean that mathlib4 itself uses if you're going to use things from it
Julian Berman (May 24 2021 at 14:26):
which according to https://github.com/leanprover-community/mathlib4/blob/master/leanpkg.toml#L4 is leanprover/lean4:nightly-2021-05-18
learnerofmaths (May 24 2021 at 14:26):
Ah, cool! Changing to natLit! fixed it. But I will see about updating, too!
learnerofmaths (May 24 2021 at 14:26):
Thank you all!! Off to prove more theorems. Your help is really appreciated. Have a good day everyone.
Jakob von Raumer (May 24 2021 at 18:48):
To add what the others were saying: At some point we will surely have a calc and conv environment in Lean 4, they're not implemented yet, though.
Alex J. Best (May 24 2021 at 19:37):
Sebastian wrote a version of calc in a thread here: (maybe there was another one in a thread too)
Sebastian Ullrich said:
Here's one solution for a heterogeneous
calcbased on aTranstypeclass and...as a term notation:class Trans (r : α → β → Prop) (s : β → γ → Prop) (t : outParam (α → γ → Prop)) where trans {a b c} : r a b → s b c → t a c export Trans (trans) instance (r : α → γ → Prop) : Trans Eq r r where trans heq h' := heq ▸ h' instance (r : α → β → Prop) : Trans r Eq r where trans h' heq := heq ▸ h' notation "..." => _ -- enforce indentation of calc steps so we know when to stop parsing them syntax calcStep := colGe term " := " term syntax "calc " withPosition(calcStep+) : term macro_rules | `(calc $p:term := $h:term) => `(($h : $p)) | `(calc $p:term := $h:term $rest:calcStep*) => `(trans _ _ _ ($h : $p) (calc $rest:calcStep*)) variable (t1 t2 t3 t4 : Nat) variable (pf12 : t1 = t2) (pf23 : t2 = t3) (pf34 : t3 = t4) theorem foo : t1 = t4 := calc t1 = t2 := pf12 ... = t3 := pf23 ... = t4 := pf34 variable (t5 : Nat) variable (pf23' : t2 < t3) (pf45' : t4 < t5) instance [HasLess α] : Trans (α := α) Less Less Less where trans := sorry theorem foo' : t1 < t5 := calc t1 = t2 := pf12 ... < t3 := pf23' ... = t4 := pf34 ... < t5 := pf45'
Last updated: May 02 2025 at 03:31 UTC



