Zulip Chat Archive
Stream: new members
Topic: Classical.choice vs axiom of choice
Asei Inoue (Sep 03 2024 at 11:56):
Let's think the following two propositions.
- [split surjection] let
f : A -> B
be a surjective function. then there exists a functiong : B -> A
such thatf (g b) = b
for allb
inB
. - [injection to inverse] let
f : A -> B
be an injective map. then there exists a functiong : Im f -> A
such thatf (g b) = b
for allb
inIm f
.
To prove [split surjection], we need axiom of choice in ZFC. But to prove [injection to inverse], we don't need axiom of choice.
my question
Can I prove [injection to inverse] in Lean without using Classical.choice
?
Yaël Dillies (Sep 03 2024 at 12:01):
Yes you do since g : Im f → A
is data while x ∈ Im f
is a proof, and you're trying to build the former from the latter
Luigi Massacci (Sep 03 2024 at 13:14):
You should be able to do it with [Encodable A]
and [DecidableEq B]
I think
Asei Inoue (Sep 03 2024 at 17:12):
Thanks! I will try...
Asei Inoue (Sep 03 2024 at 17:34):
ohhhh.... how can I construct g
without Classical.choice...?
import Mathlib.Tactic
variable {A B : Type} [Inhabited A]
open Function Set
theorem injection_to_inverse [Encodable A] [DecidableEq B] (f : A → B) (hinj : Injective f) :
∃ g : B → A, (∀ a : A, g (f a) = a ) := by
classical
let g := fun b =>
if h : ∃ a, f a = b then Classical.choose h else default
sorry
Ruben Van de Velde (Sep 03 2024 at 17:40):
You can't
Asei Inoue (Sep 03 2024 at 17:42):
@Ruben Van de Velde I can't create such a g
? Then, why can ZF can do it and why can't Lean?
Ruben Van de Velde (Sep 03 2024 at 18:28):
Because lean and ZF have different foundations. I'm personally not so interested in foundational stuff
Kyle Miller (Sep 03 2024 at 18:38):
It seems like the Surjective version should be possible given Encodable, but for the Injective version you have to construct a function that somehow can decide whether an element is in the image of f
or not. (Encodable is a very big assumption!)
Note: using classical
introduces Classical.choice
, so you don't want to use that.
Asei Inoue (Sep 03 2024 at 18:46):
This means that in Lean, "propositions that can be shown without the choice axiom in ZF" may not be shown without the Classical.choice axiom.
If a mathematician points this out to you and says that Lean's system has shortcomings, how can you argue with them? I can't think of any counter-arguments.
Asei Inoue (Sep 03 2024 at 18:49):
It seems like the Surjective version should be possible given Encodable
I think Encodable
hypothesis is too strong...
Jireh Loreaux (Sep 03 2024 at 18:50):
If you care about foundational things, you can just use docs#ZFSet. Then everything you want should be doable.
Jireh Loreaux (Sep 03 2024 at 18:51):
That is, if you want ZF foundations, then work in shallow embedding in Lean which encodes those foundations.
Chris Bailey (Sep 03 2024 at 20:23):
Asei Inoue said:
If a mathematician points this out to you and says that Lean's system has shortcomings, how can you argue with them? I can't think of any counter-arguments.
If the alleged shortcoming is just that this specific proof invokes an axiom accepted by both systems I would ask them to help me understand why it matters, concretely.
Kyle Miller (Sep 04 2024 at 00:21):
It's worth mentioning that Lean functions and ZF functions are different sorts of things. A ZF function is a relation with certain properties (one description is a coinjective and cosurjective relation), but Lean functions are builtin. A bijective ZF function can be inverted without choice, but a Lean function cannot (this is related to why docs#Equiv is a pair of functions rather than a bijective function).
Here's a Lean version of ZF-style functions, but I got stuck trying to prove cosurj
in RFun.splitInjection
without choice. Are you sure this is possible in ZF? I believe you need to restrict to g : Im f -> A
like in your original message.
import Lean
structure RFun (α β : Type _) where
rel : α → β → Prop
coinj : ∀ {x : α} {y y' : β}, rel x y → rel x y' → y = y'
cosurj : ∀ (x : α), ∃ (y : β), rel x y
variable {α β : Type _}
noncomputable def RFun.toFun (f : RFun α β) (x : α) : β := (f.cosurj x).choose
noncomputable instance : CoeFun (RFun α β) (fun _ => α → β) := ⟨RFun.toFun⟩
theorem RFun.toFun_rel (f : RFun α β) (x : α) : f.rel x (f x) :=
(f.cosurj x).choose_spec
theorem RFun.toFun_eq_of_rel (f : RFun α β) {x : α} {y : β} (h : f.rel x y) : f x = y :=
f.coinj (f.toFun_rel _) h
-- Establishes that `rel` really is the graph of `f`-as-a-function and vice versa
theorem RFun.toFun_eq_iff {f : RFun α β} {x : α} {y : β} : f x = y ↔ f.rel x y :=
⟨fun h => h ▸ f.toFun_rel x, f.toFun_eq_of_rel⟩
def RFun.comp {α β γ : Type _} (f : RFun β γ) (g : RFun α β) : RFun α γ where
rel x z := ∃ y, f.rel y z ∧ g.rel x y
coinj := by
intro _ _ _ ⟨y, hfy, hgy⟩ ⟨y', hfy', hgy'⟩
cases g.coinj hgy hgy'
cases f.coinj hfy hfy'
rfl
cosurj x := by
obtain ⟨y, hy⟩ := g.cosurj x
obtain ⟨z, hz⟩ := f.cosurj y
exact ⟨z, y, hz, hy⟩
def RFun.Injective {α β} (f : RFun α β) : Prop :=
∀ {x x' : α} {y : β}, f.rel x y → f.rel x' y → x = x'
--def RFun.image {α β} (f : RFun α β) : Prop
-- can omit Inhabited if restricting domain to image of `f`
def RFun.splitInjection {α β} [Inhabited α] (f : RFun α β) (hinj : f.Injective) : RFun β α where
rel y x := f.rel x y ∨ (x = default ∧ ∀ x', ¬ f.rel x' y)
coinj := by
rintro y x x' (hx | ⟨rfl, hn⟩) (hy | ⟨rfl, hn⟩)
· exact hinj hx hy
· exact absurd hx (hn _)
· exact absurd hy (hn _)
. rfl
cosurj := by
rintro y
dsimp
sorry
#print axioms RFun.splitInjection
-- only sorry so far
Kyle Miller (Sep 04 2024 at 02:14):
Here's injection splitting when restricting to the image, depending on no axioms.
def RFun.image {α β} (f : RFun α β) : Type _ := { y : β // ∃ x : α, f.rel x y }
def RFun.splitInjection {α β} (f : RFun α β) (hinj : f.Injective) :
RFun f.image α where
rel y x := f.rel x y.1
coinj := by
intro ⟨y, x, h⟩ _ _
apply hinj
cosurj := by
intro ⟨y, x, h⟩
exists x
#print axioms RFun.splitInjection
-- no axioms
Kyle Miller (Sep 04 2024 at 02:20):
I think the moral here is that Lean's function types should be thought of as being more like formulas you can quantify over (second-order quantification), which is something that ZF doesn't even have. But, with them, you can model ZF functions just fine.
Choice lets you lift these ZF-style functions to being "actual" Lean functions. (That's RFun.toFun
in my code.)
So, that's a counter-argument @Asei Inoue, you shouldn't demand that Lean's built-in functions have the same axiomatic properties as ZF-style functions, but Lean gives you everything you need to reason about them. (Take what I say with a grain of salt — I'm not a logician.)
Daniel Weber (Sep 04 2024 at 04:06):
Kyle Miller said:
It's worth mentioning that Lean functions and ZF functions are different sorts of things. A ZF function is a relation with certain properties (one description is a coinjective and cosurjective relation), but Lean functions are builtin. A bijective ZF function can be inverted without choice, but a Lean function cannot (this is related to why docs#Equiv is a pair of functions rather than a bijective function).
Here's a Lean version of ZF-style functions, but I got stuck trying to prove
cosurj
inRFun.splitInjection
without choice. Are you sure this is possible in ZF? I believe you need to restrict tog : Im f -> A
like in your original message.
In ZF you have excluded middle so you can case on exists x, f.rel x y
, but in Lean excluded middle uses choice
Last updated: May 02 2025 at 03:31 UTC