Zulip Chat Archive
Stream: general
Topic: The opposite
deepest recursion (Jun 13 2024 at 12:44):
In lean I can write this
def fpres {f:A->B}: ∀ a b , a = b -> f a = f b := by
intro a b p
rw [p]
But I feel like I cant write this
def fcanc1 {f:A->B}: ∀ a b , f a = f b -> a = b := by
intros a b p
admit
Am I missing something obvious?
Damiano Testa (Jun 13 2024 at 12:49):
What should happen if f
is constant and a
and b
are different?
Damiano Testa (Jun 13 2024 at 12:50):
Say B = Unit
, A = Bool
and a = true
while b = false
.
deepest recursion (Jun 13 2024 at 12:50):
My initial guess was that it would be true if f is continuous. How do I add this assumption?
Damiano Testa (Jun 13 2024 at 12:50):
Constant functions are usually continuous.
Damiano Testa (Jun 13 2024 at 12:51):
The property that is what you wrote is normally called injectivity.
Damiano Testa (Jun 13 2024 at 12:54):
If continuity is what you want, this sets up an environment with a continuous function floating around:
import Mathlib
variable {A B} [TopologicalSpace A] [TopologicalSpace B] {f : A → B} (hf : Continuous f)
deepest recursion (Jun 13 2024 at 13:54):
On second thought, it would be nice if somebody showed what to do to make fcanc1
work :)
Ruben Van de Velde (Jun 13 2024 at 13:56):
import Mathlib
def fcanc1 {f:A->B} (hf : Function.Injective f) : ∀ a b , f a = f b -> a = b := by
intros a b p
apply hf
apply p
deepest recursion (Jun 13 2024 at 14:37):
But... thas just a restatement...
Maybe it's easier to show this somehow?
def l1 {f:A->B}{h:B->A}: (∀ a , a = h (f a)) -> (∀ b , b = f (h b)) := by
intro p1 b
let m := p1 (h b)
admit
Damiano Testa (Jun 13 2024 at 14:39):
I don't think that is true either: if A = Unit
and B = Bool
, this will not hold.
deepest recursion (Jun 13 2024 at 14:47):
I cant state the case when A is Unit and B is bool
def tounit := fun (_:Bool) => ()
def fromunit := fun () => false
example : ∀ a:Bool , a = fromunit (tounit a) := by
intro a
cases a
rfl
unfold tounit fromunit; simp
-- goal is false
Edward van de Meent (Jun 13 2024 at 14:50):
that is exactly the point, because it's not true. as a sidenote, why is it that you want to prove this? is there a more specific case in which you want to apply such a theorem (if there were one)?
deepest recursion (Jun 13 2024 at 15:01):
I have written this. it works, and lets me rewrite things by equivalence that is not strict
inductive sigmaprop (T:Type _)(P:T -> Prop) : Type _
| mksprop : (t:T) -> P t -> sigmaprop T P
def iscoh_map {A:Type _}{B:Type _} : (A -> B) -> Type _ :=
fun f => sigmaprop (B -> A) fun r => ∀ a , a = r (f a)
def iso : Type _ -> Type _ -> Type _ :=
fun A B => @Sigma (A -> B) fun f => iscoh_map f
def iso.bw : iso A B -> (B -> A) := fun (.mk _ d) => by
unfold iscoh_map at d; let (.mksprop bw _) := d; exact bw
def p1 : (p:iso A B) -> ∀ a , sigmaprop B fun b => a = (p.bw b) := by
intros p a; unfold iso iscoh_map at p
let (Sigma.mk f k) := p;
simp at k
let (.mksprop h r) := k
unfold iso.bw; simp
exact (.mksprop (f a) (r a))
notation "~(" L "," R ")" => ⟨ L , R ⟩
def not_iso: iso Bool Bool := by
unfold iso
exact ~(not, by unfold iscoh_map; exact (.mksprop not (by intro i; cases i <;> rfl)))
def proof : (not a) = not (not (not a)) := by cases a <;> rfl
-- notice that 'proof' is not definitionally equal to the 'a = not (not a)'
example : a = not (not a) := by
let (.mksprop b c) := p1 not_iso a
unfold iso.bw not_iso at c;
simp at c
rw [c]
exact proof
I then tried to define inversion for iso like this
def fcanc1 {f:A->B}: ∀ a b , f a = f b -> a = b := by
intros a b p
admit
def fcanc2 {h:B->A}{f:A->B}{k:B}: h k = h (f (h k)) -> k = f (h k) := by
generalize (f (h _)) = r
intro p
apply @fcanc1 _ _ h
exact p
def rev : iso A B -> iso B A := by
intro (.mk f (.mksprop b coh))
unfold iso
refine .mk b (.mksprop f ?p)
intro k
let t1 := coh (b k)
let t2 := fcanc2 t1
exact t2
but I have stuck at fcanc1
deepest recursion (Jun 13 2024 at 15:05):
Here's another example
def f : Nat -> List Unit
| .zero => .nil
| .succ a => .cons () (f a)
def b : List Unit -> Nat
| .nil => .zero
| .cons .unit t => .succ (b t)
def coh : (a : Nat) -> a = b (f a) := by
intro i
match i with
| .succ a => unfold b f; simp; exact (coh a)
| .zero => unfold b f; simp;
def int_list : iso Nat (List Unit) := by
unfold iso
exact ~(
f,
by unfold iscoh_map
exact (.mksprop b coh)
)
-- a proof about integers
-- by doing pattern matching on a list!!!!
example : (a > 0) -> (a + 1 > 0) := by
let (.mksprop k p) := p1 int_list a
rw [p]
cases k
. case nil => intro; contradiction
. case cons a b => simp
Edward van de Meent (Jun 13 2024 at 15:23):
i'm sorry to say that there is no proof of fcanc1
, because it says that for every function f
, if the result is the same, then the inputs are the same. this is the same as saying that the value of f a
cannot be equal to f b
when a
and b
are different, which is simply not true for all f
. in particular, given that there are at least two values a
and a'
, as well as some value b
, the statement is not true for the function mapping both a
and a'
to b
.
Ruben Van de Velde (Jun 13 2024 at 15:26):
What are you trying to do?
Kyle Miller (Jun 13 2024 at 15:30):
By the way, sigmatype
is known as docs#Subtype
-- def sigmaprop (T : Type _) (P : T -> Prop) := {t : T // P t}
def iscoh_map {A B : Type _} (f : A -> B) : Type _ :=
{r : B → A // ∀ a , a = r (f a)}
def iso (A B : Type _) : Type _ :=
Σ (f : A -> B), iscoh_map f
def iso.bw {A B} : iso A B -> (B -> A) := fun (.mk _ d) => d.1
-- or: def iso.bw {A B} (p : iso A B) : B -> A := p.2.1
def p1 {A B} (p : iso A B) (a : A) : {b : B // a = p.bw b} :=
let ⟨f, k⟩ := p;
let ⟨_, r⟩ := k
⟨f a, r a⟩
notation "~(" L "," R ")" => ⟨ L , R ⟩
def not_iso: iso Bool Bool :=
~(not, ⟨not, (by intro i; cases i <;> rfl)⟩)
def proof {a : Bool} : (not a) = not (not (not a)) := by cases a <;> rfl
-- notice that 'proof' is not definitionally equal to the 'a = not (not a)'
example (a : Bool) : a = not (not a) := by
let ⟨b, c⟩ := p1 not_iso a
unfold iso.bw not_iso at c;
simp at c
rw [c]
exact proof
Kyle Miller (Jun 13 2024 at 15:37):
The reason you're not able to define rev
is that the definition of iso
is not correct. You made the definition for "function with an explicit right inverse", which just means it's injective, not necessarily bijective.
def myIso : iso Bool Nat :=
⟨(fun b => if b then 1 else 0),
⟨fun n => n == 1, by
intro b
cases b <;> simp⟩⟩
deepest recursion (Jun 13 2024 at 18:32):
An illuminating simplification, thank you.
I thought that ∀ a , a = r (f a)
defines a surjection rather than an injection, and would qualify as an equivalence.
Is it not the case?
Kyle Miller (Jun 13 2024 at 18:35):
As the example shows, no that's not the case.
That proposition implies these two things: (1) f
is injective and (2) r
is surjective.
deepest recursion (Jun 13 2024 at 22:25):
In the code below I can use p
to rewrite itself to refl. Can I use this fact to show that because of this, f (h b)
has to be id
?
def i4 {f:A->B}{h:B->A}: ∀ b , h b = h (f (h b)) -> f (h b) = id b := by
intro v p
-- p : h v = h (f (h v))
rw [<-p] at p
-- p : h v = h v
admit
Kyle Miller (Jun 13 2024 at 23:02):
No, being able to rewrite to refl is to expected. If you have a = b
then you can rewrite to get a = a
or b = b
, but these are trivial conclusions that don't need a = b
.
Having h v = h v
in your local context doesn't give you anything, it's trivial. You can always introduce it with have : h v = hv := rfl
without needing to make use of p
at all.
Last updated: May 02 2025 at 03:31 UTC