Zulip Chat Archive
Stream: maths
Topic: Empty torsors
Yaël Dillies (Sep 02 2022 at 12:04):
@Joseph Myers, would it make sense to allow P
to be empty in add_torsor G P
. This is currently impossible due to docs#add_torsor.nonempty. In fact, this instance is dangerous as it loops with docs#affine_subspace.add_torsor and, as noted by @Paul Reichert, this means not all affine subspaces are add torsors.
Sebastien Gouezel (Sep 02 2022 at 12:09):
It wouldn't make sense from a mathematical point of view, at least for the usual notion: an add_torsor G P
is supposed to be a copy of G
in which you have forgotten the identity.
Joseph Myers (Sep 02 2022 at 12:20):
My guess is that the main effect would be to move around where nonempty
hypotheses are needed. I ran into that dangerous instance recently in #16339, but my best guess as to the right way to avoid the typeclass loop would have been "make [nonempty P]
an argument to add_torsor
" rather than "remove the nonempty
requirement".
Paul Reichert (Sep 02 2022 at 13:19):
It might be useful to have a class add_pseudo_torsor
, lacking the nonzero requirement. There are a lot of properties holding for pseudo-torsors and they have the nice property that there is a well-defined closure operator -- even the empty set has a well-defined closure.
However, it seems hard to tell Lean something like "an add_torsor
is an add_pseudo_torsor
with a nonzero
instance" without producing a loop because we can produce add_torsor
instances from add_pseudo_torsor
instances and vice versa. Are there some "tricks" to avoid this problem, and is this even a sensible approach?
class add_pseudo_torsor (G : out_param Type*) (P : Type*) [out_param $ add_group G]
extends add_action G P, has_vsub G P :=
(vsub_vadd' : ∀ (p1 p2 : P), (p1 -ᵥ p2 : G) +ᵥ p2 = p1)
(vadd_vsub' : ∀ (g : G) (p : P), g +ᵥ p -ᵥ p = g)
class add_torsor (G : out_param Type*) (P : Type*) [out_param $ add_group G]
extends add_pseudo_torsor G P :=
[nonempty : nonempty P]
instance nonempty_pseudo_torsor {G P : Type*} [add_group G] [add_pseudo_torsor G P] [nonempty P] :
add_torsor G P := ⟨⟩
attribute [instance, priority 100, nolint dangerous_instance] add_torsor.nonempty
-- maximum class-instance resolution depth reached
instance add_group_is_add_torsor (G : Type*) [add_group G] :
add_torsor G G :=
{ vsub := has_sub.sub,
vsub_vadd' := sub_add_cancel,
vadd_vsub' := add_sub_cancel }
Paul Reichert (Sep 02 2022 at 13:21):
For example, I'd like to tell Lean "don't worry; you already know the add_pseudo_torsor
instance obtained from the add_torsor
instance obtained from the add_pseudo_torsor
instance and so you can ignore it"
Kevin Buzzard (Sep 02 2022 at 14:04):
Following preprime and preconnected it should perhaps be called pretorsor.
Joseph Myers (Sep 02 2022 at 14:27):
If we have a class of pretorsors I'd be inclined not to have a separate one for torsors; just add nonempty
hypotheses to the few lemmas or definitions that genuinely need a torsor not a pretorsor and where nonempty
can't be deduced from the other hypotheses.
Paul A. Reichert (Sep 02 2022 at 14:35):
Okay, this post is already outdated, but for reference:
This branch is a proof of concept of the approach. I made the above-mentioned instance a def
to avoid the problems. The build succeeded but this approach would introduce a new kind of boilerplate:
variables {G : Type*} {P : Type*} {G' : Type*} {P' : Type*} [add_group G] [add_group G']
instance [add_pseudo_torsor G P] [add_pseudo_torsor G' P'] : add_pseudo_torsor (G × G') (P × P') :=
{ vadd := λ v p, (v.1 +ᵥ p.1, v.2 +ᵥ p.2),
zero_vadd := λ p, by simp,
add_vadd := by simp [add_vadd],
vsub := λ p₁ p₂, (p₁.1 -ᵥ p₂.1, p₁.2 -ᵥ p₂.2),
vsub_vadd' := λ p₁ p₂, show (p₁.1 -ᵥ p₂.1 +ᵥ p₂.1, _) = p₁, by simp,
vadd_vsub' := λ v p, show (v.1 +ᵥ p.1 -ᵥ p.1, v.2 +ᵥ p.2 -ᵥ p.2) =v, by simp }
instance [add_torsor G P] [add_torsor G' P'] : add_torsor (G × G') (P × P') :=
{ nonempty := prod.nonempty }
If this is the way to go, I'd have to look for required add_torsor
instances throughout mathlib and relax them to add_pretorsor
instances.
Paul A. Reichert (Sep 02 2022 at 14:37):
Joseph Myers said:
If we have a class of pretorsors I'd be inclined not to have a separate one for torsors; just add
nonempty
hypotheses to the few lemmas or definitions that genuinely need a torsor not a pretorsor and wherenonempty
can't be deduced from the other hypotheses.
Yes, this seems also reasonable; at the same time, I understand concerns that torsors are just a bit more familiar for mathematicians than pretorsors. Let me just emphasize that this is just a proposal, we can also reject the whole pretorsor
thing if it turns out to complicate things.
Yaël Dillies (Sep 02 2022 at 22:08):
From a purely hierarchy design point of view, it would be cleaner to not make nonempty P
a field of add_torsor
.
Kevin Buzzard (Sep 02 2022 at 22:10):
Just to be clear, if you're saying "in Lean torsors should be allowed to be empty" then torsors are nonempty by definition and you can't change that (like you can't decide that 1 is going to be prime in Lean). But if you're saying something else then sorry I misunderstood :-)
Yaël Dillies (Sep 02 2022 at 22:12):
I'm saying that maybe the way to say "P
is a torsor" should be [add_torsor G P] [nonempty P]
rather than [add_torsor G P]
.
Yaël Dillies (Sep 02 2022 at 22:13):
Even though that's not what I'm arguing about, univ
isn't a filter but we still made it one in Lean :wink:
Johan Commelin (Sep 03 2022 at 05:19):
In the real world, univ
isn't a filter for the exact same reason that ⊤
isn't an ideal. Yet we made ⊤
an ideal in Lean anyway. /s
Kevin Buzzard (Sep 03 2022 at 06:43):
The difference here is that it is known that mathematicians in the literature have two opinions on what a filter is, like they have two opinions on what the natural numbers are. As far as I know they only have one opinion on what a torsor is, like they only have one opinion on what a prime number is
Last updated: Dec 20 2023 at 11:08 UTC