l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem image_bot (s : Set α) : (⊥ : Rel α β).image s = ∅ := by
  rw [Set.eq_empty_iff_forall_not_mem]
  intro x h
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : β
h : x ∈ image ⊥ s
⊢ False

Next tactic:
simp [mem_image, Bot.bot] at h
@[simp]
theorem image_top {s : Set α} (h : Set.Nonempty s) :
    (⊤ : Rel α β).image s = Set.univ :=
  Set.eq_univ_of_forall λ x ↦ ⟨h.some, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
h : Set.Nonempty s
x : β
⊢ Set.Nonempty.some h ∈ s ∧ ⊤ (Set.Nonempty.some h) x

Next tactic:
simp [h.some_mem, Top.top]
theorem preimage_id (s : Set α) : preimage (@Eq α) s = s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
⊢ preimage Eq s = s

Next tactic:
simp only [preimage, inv_id, image_id]
theorem preimage_comp (s : Rel β γ) (t : Set γ) : preimage (r • s) t = preimage r (preimage s t) :=
  by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Rel β γ
t : Set γ
⊢ preimage (r • s) t = preimage r (preimage s t)

Next tactic:
simp only [preimage, inv_comp, image_comp]
theorem preimage_univ : r.preimage Set.univ = r.dom := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
⊢ preimage r Set.univ = dom r

Next tactic:
rw [preimage, image_univ, codom_inv]
@[simp]
theorem preimage_empty : r.preimage ∅ = ∅ := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
⊢ preimage r ∅ = ∅

Next tactic:
rw [preimage, image_empty]
@[simp]
theorem preimage_inv (s : Set α) : r.inv.preimage s = r.image s := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
⊢ preimage (inv r) s = image r s

Next tactic:
rw [preimage, inv_inv]
@[simp]
theorem preimage_bot (s : Set β) : (⊥ : Rel α β).preimage s = ∅ :=
  by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
⊢ preimage ⊥ s = ∅

Next tactic:
rw [preimage, inv_bot, image_bot]
@[simp]
theorem preimage_top {s : Set β} (h : Set.Nonempty s) :
    (⊤ : Rel α β).preimage s = Set.univ := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
h : Set.Nonempty s
⊢ preimage ⊤ s = Set.univ

Next tactic:
rwa [← inv_top, preimage, inv_inv, image_top]
theorem image_eq_dom_of_codomain_subset {s : Set β} (h : r.codom ⊆ s) : r.preimage s = r.dom := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
h : codom r ⊆ s
⊢ preimage r s = dom r

Next tactic:
rw [← preimage_univ]
theorem image_eq_dom_of_codomain_subset {s : Set β} (h : r.codom ⊆ s) : r.preimage s = r.dom := by
  rw [← preimage_univ]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
h : codom r ⊆ s
⊢ preimage r s = preimage r Set.univ

Next tactic:
apply Set.eq_of_subset_of_subset
theorem image_eq_dom_of_codomain_subset {s : Set β} (h : r.codom ⊆ s) : r.preimage s = r.dom := by
  rw [← preimage_univ]
  apply Set.eq_of_subset_of_subset
  · 

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
h : codom r ⊆ s
⊢ preimage r s ⊆ preimage r Set.univ

Next tactic:
exact image_subset _ (Set.subset_univ _)
theorem image_eq_dom_of_codomain_subset {s : Set β} (h : r.codom ⊆ s) : r.preimage s = r.dom := by
  rw [← preimage_univ]
  apply Set.eq_of_subset_of_subset
  · exact image_subset _ (Set.subset_univ _)
  · 

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
h : codom r ⊆ s
⊢ preimage r Set.univ ⊆ preimage r s

Next tactic:
intro x hx
theorem image_eq_dom_of_codomain_subset {s : Set β} (h : r.codom ⊆ s) : r.preimage s = r.dom := by
  rw [← preimage_univ]
  apply Set.eq_of_subset_of_subset
  · exact image_subset _ (Set.subset_univ _)
  · intro x hx
    

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
h : codom r ⊆ s
x : α
hx : x ∈ preimage r Set.univ
⊢ x ∈ preimage r s

Next tactic:
simp only [mem_preimage, Set.mem_univ, true_and] at hx
theorem image_eq_dom_of_codomain_subset {s : Set β} (h : r.codom ⊆ s) : r.preimage s = r.dom := by
  rw [← preimage_univ]
  apply Set.eq_of_subset_of_subset
  · exact image_subset _ (Set.subset_univ _)
  · intro x hx
    simp only [mem_preimage, Set.mem_univ, true_and] at hx
    

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
h : codom r ⊆ s
x : α
hx : ∃ y, r x y
⊢ x ∈ preimage r s

Next tactic:
rcases hx with ⟨y, ryx⟩
theorem image_eq_dom_of_codomain_subset {s : Set β} (h : r.codom ⊆ s) : r.preimage s = r.dom := by
  rw [← preimage_univ]
  apply Set.eq_of_subset_of_subset
  · exact image_subset _ (Set.subset_univ _)
  · intro x hx
    simp only [mem_preimage, Set.mem_univ, true_and] at hx
    rcases hx with ⟨y, ryx⟩
    

Proof state:
case a.intro
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
h : codom r ⊆ s
x : α
y : β
ryx : r x y
⊢ x ∈ preimage r s

Next tactic:
have hy : y ∈ s := h ⟨x, ryx⟩
theorem image_eq_dom_of_codomain_subset {s : Set β} (h : r.codom ⊆ s) : r.preimage s = r.dom := by
  rw [← preimage_univ]
  apply Set.eq_of_subset_of_subset
  · exact image_subset _ (Set.subset_univ _)
  · intro x hx
    simp only [mem_preimage, Set.mem_univ, true_and] at hx
    rcases hx with ⟨y, ryx⟩
    have hy : y ∈ s := h ⟨x, ryx⟩
    

Proof state:
case a.intro
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
h : codom r ⊆ s
x : α
y : β
ryx : r x y
hy : y ∈ s
⊢ x ∈ preimage r s

Next tactic:
exact ⟨y, ⟨hy, ryx⟩⟩
theorem preimage_eq_codom_of_domain_subset {s : Set α} (h : r.dom ⊆ s) : r.image s = r.codom :=
  by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
h : dom r ⊆ s
⊢ image r s = codom r

Next tactic:
apply r.inv.image_eq_dom_of_codomain_subset (by rwa [← codom_inv] at h)
theorem preimage_eq_codom_of_domain_subset {s : Set α} (h : r.dom ⊆ s) : r.image s = r.codom :=
  by apply r.inv.image_eq_dom_of_codomain_subset (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
h : dom r ⊆ s
⊢ codom (inv r) ⊆ s

Next tactic:
rwa [← codom_inv] at h
theorem image_inter_dom_eq (s : Set α) : r.image (s ∩ r.dom) = r.image s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
⊢ image r (s ∩ dom r) = image r s

Next tactic:
apply Set.eq_of_subset_of_subset
theorem image_inter_dom_eq (s : Set α) : r.image (s ∩ r.dom) = r.image s := by
  apply Set.eq_of_subset_of_subset
  · 

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
⊢ image r (s ∩ dom r) ⊆ image r s

Next tactic:
apply r.image_mono (by simp)
theorem image_inter_dom_eq (s : Set α) : r.image (s ∩ r.dom) = r.image s := by
  apply Set.eq_of_subset_of_subset
  · apply r.image_mono (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
⊢ s ∩ dom r ≤ s

Next tactic:
simp
theorem image_inter_dom_eq (s : Set α) : r.image (s ∩ r.dom) = r.image s := by
  apply Set.eq_of_subset_of_subset
  · apply r.image_mono (by simp)
  · 

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
⊢ image r s ⊆ image r (s ∩ dom r)

Next tactic:
intro x h
theorem image_inter_dom_eq (s : Set α) : r.image (s ∩ r.dom) = r.image s := by
  apply Set.eq_of_subset_of_subset
  · apply r.image_mono (by simp)
  · intro x h
    

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : β
h : x ∈ image r s
⊢ x ∈ image r (s ∩ dom r)

Next tactic:
rw [mem_image] at *
theorem image_inter_dom_eq (s : Set α) : r.image (s ∩ r.dom) = r.image s := by
  apply Set.eq_of_subset_of_subset
  · apply r.image_mono (by simp)
  · intro x h
    rw [mem_image] at *
    

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : β
h : ∃ x_1 ∈ s, r x_1 x
⊢ ∃ x_1 ∈ s ∩ dom r, r x_1 x

Next tactic:
rcases h with ⟨y, hy, ryx⟩
theorem image_inter_dom_eq (s : Set α) : r.image (s ∩ r.dom) = r.image s := by
  apply Set.eq_of_subset_of_subset
  · apply r.image_mono (by simp)
  · intro x h
    rw [mem_image] at *
    rcases h with ⟨y, hy, ryx⟩
    

Proof state:
case a.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : β
y : α
hy : y ∈ s
ryx : r y x
⊢ ∃ x_1 ∈ s ∩ dom r, r x_1 x

Next tactic:
use y
theorem image_inter_dom_eq (s : Set α) : r.image (s ∩ r.dom) = r.image s := by
  apply Set.eq_of_subset_of_subset
  · apply r.image_mono (by simp)
  · intro x h
    rw [mem_image] at *
    rcases h with ⟨y, hy, ryx⟩
    use y
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : β
y : α
hy : y ∈ s
ryx : r y x
⊢ y ∈ s ∩ dom r ∧ r y x

Next tactic:
suffices h : y ∈ r.dom by simp_all only [Set.mem_inter_iff, and_self]
theorem image_inter_dom_eq (s : Set α) : r.image (s ∩ r.dom) = r.image s := by
  apply Set.eq_of_subset_of_subset
  · apply r.image_mono (by simp)
  · intro x h
    rw [mem_image] at *
    rcases h with ⟨y, hy, ryx⟩
    use y
    suffices h : y ∈ r.dom by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : β
y : α
hy : y ∈ s
ryx : r y x
h : y ∈ dom r
⊢ y ∈ s ∩ dom r ∧ r y x

Next tactic:
simp_all only [Set.mem_inter_iff, and_self]
theorem image_inter_dom_eq (s : Set α) : r.image (s ∩ r.dom) = r.image s := by
  apply Set.eq_of_subset_of_subset
  · apply r.image_mono (by simp)
  · intro x h
    rw [mem_image] at *
    rcases h with ⟨y, hy, ryx⟩
    use y
    suffices h : y ∈ r.dom by simp_all only [Set.mem_inter_iff, and_self]
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : β
y : α
hy : y ∈ s
ryx : r y x
⊢ y ∈ dom r

Next tactic:
rw [dom, Set.mem_setOf_eq]
theorem image_inter_dom_eq (s : Set α) : r.image (s ∩ r.dom) = r.image s := by
  apply Set.eq_of_subset_of_subset
  · apply r.image_mono (by simp)
  · intro x h
    rw [mem_image] at *
    rcases h with ⟨y, hy, ryx⟩
    use y
    suffices h : y ∈ r.dom by simp_all only [Set.mem_inter_iff, and_self]
    rw [dom, Set.mem_setOf_eq]
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : β
y : α
hy : y ∈ s
ryx : r y x
⊢ ∃ y_1, r y y_1

Next tactic:
use x
@[simp]
theorem preimage_inter_codom_eq (s : Set β) : r.preimage (s ∩ r.codom) = r.preimage s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
⊢ preimage r (s ∩ codom r) = preimage r s

Next tactic:
rw [← dom_inv, preimage, preimage, image_inter_dom_eq]
theorem inter_dom_subset_preimage_image (s : Set α) : s ∩ r.dom ⊆ r.preimage (r.image s) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
⊢ s ∩ dom r ⊆ preimage r (image r s)

Next tactic:
intro x hx
theorem inter_dom_subset_preimage_image (s : Set α) : s ∩ r.dom ⊆ r.preimage (r.image s) := by
  intro x hx
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : α
hx : x ∈ s ∩ dom r
⊢ x ∈ preimage r (image r s)

Next tactic:
simp only [Set.mem_inter_iff, dom] at hx
theorem inter_dom_subset_preimage_image (s : Set α) : s ∩ r.dom ⊆ r.preimage (r.image s) := by
  intro x hx
  simp only [Set.mem_inter_iff, dom] at hx
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : α
hx : x ∈ s ∧ x ∈ {x | ∃ y, r x y}
⊢ x ∈ preimage r (image r s)

Next tactic:
rcases hx with ⟨hx, ⟨y, rxy⟩⟩
theorem inter_dom_subset_preimage_image (s : Set α) : s ∩ r.dom ⊆ r.preimage (r.image s) := by
  intro x hx
  simp only [Set.mem_inter_iff, dom] at hx
  rcases hx with ⟨hx, ⟨y, rxy⟩⟩
  

Proof state:
case intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : α
hx : x ∈ s
y : β
rxy : r x y
⊢ x ∈ preimage r (image r s)

Next tactic:
use y
theorem inter_dom_subset_preimage_image (s : Set α) : s ∩ r.dom ⊆ r.preimage (r.image s) := by
  intro x hx
  simp only [Set.mem_inter_iff, dom] at hx
  rcases hx with ⟨hx, ⟨y, rxy⟩⟩
  use y
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : α
hx : x ∈ s
y : β
rxy : r x y
⊢ y ∈ image r s ∧ inv r y x

Next tactic:
simp only [image, Set.mem_setOf_eq]
theorem inter_dom_subset_preimage_image (s : Set α) : s ∩ r.dom ⊆ r.preimage (r.image s) := by
  intro x hx
  simp only [Set.mem_inter_iff, dom] at hx
  rcases hx with ⟨hx, ⟨y, rxy⟩⟩
  use y
  simp only [image, Set.mem_setOf_eq]
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
x : α
hx : x ∈ s
y : β
rxy : r x y
⊢ (∃ x ∈ s, r x y) ∧ inv r y x

Next tactic:
exact ⟨⟨x, hx, rxy⟩, rxy⟩
theorem image_preimage_subset_inter_codom (s : Set β) : s ∩ r.codom ⊆ r.image (r.preimage s) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
⊢ s ∩ codom r ⊆ image r (preimage r s)

Next tactic:
rw [← dom_inv, ← preimage_inv]
theorem image_preimage_subset_inter_codom (s : Set β) : s ∩ r.codom ⊆ r.image (r.preimage s) := by
  rw [← dom_inv, ← preimage_inv]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set β
⊢ s ∩ dom (inv r) ⊆ preimage (inv r) (preimage r s)

Next tactic:
apply inter_dom_subset_preimage_image
theorem core_inter (s t : Set β) : r.core (s ∩ t) = r.core s ∩ r.core t :=
  Set.ext (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s t : Set β
⊢ ∀ (x : α), x ∈ core r (s ∩ t) ↔ x ∈ core r s ∩ core r t

Next tactic:
simp [mem_core, imp_and, forall_and]
@[simp]
theorem core_univ : r.core Set.univ = Set.univ :=
  Set.ext (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
⊢ ∀ (x : α), x ∈ core r Set.univ ↔ x ∈ Set.univ

Next tactic:
simp [mem_core]
theorem core_id (s : Set α) : core (@Eq α) s = s := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Set α
⊢ core Eq s = s

Next tactic:
simp [core]
theorem core_comp (s : Rel β γ) (t : Set γ) : core (r • s) t = core r (core s t) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Rel β γ
t : Set γ
⊢ core (r • s) t = core r (core s t)

Next tactic:
ext x
theorem core_comp (s : Rel β γ) (t : Set γ) : core (r • s) t = core r (core s t) := by
  ext x; 

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Rel β γ
t : Set γ
x : α
⊢ x ∈ core (r • s) t ↔ x ∈ core r (core s t)

Next tactic:
simp [core, comp]
theorem core_comp (s : Rel β γ) (t : Set γ) : core (r • s) t = core r (core s t) := by
  ext x; simp [core, comp]; 

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Rel β γ
t : Set γ
x : α
⊢ (∀ (y : γ) (x_1 : β), r x x_1 → s x_1 y → y ∈ t) ↔ ∀ (y : β), r x y → ∀ (y_1 : γ), s y y_1 → y_1 ∈ t

Next tactic:
constructor
theorem core_comp (s : Rel β γ) (t : Set γ) : core (r • s) t = core r (core s t) := by
  ext x; simp [core, comp]; constructor
  · 

Proof state:
case h.mp
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Rel β γ
t : Set γ
x : α
⊢ (∀ (y : γ) (x_1 : β), r x x_1 → s x_1 y → y ∈ t) → ∀ (y : β), r x y → ∀ (y_1 : γ), s y y_1 → y_1 ∈ t

Next tactic:
exact fun h y rxy z => h z y rxy
theorem core_comp (s : Rel β γ) (t : Set γ) : core (r • s) t = core r (core s t) := by
  ext x; simp [core, comp]; constructor
  · exact fun h y rxy z => h z y rxy
  · 

Proof state:
case h.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
s : Rel β γ
t : Set γ
x : α
⊢ (∀ (y : β), r x y → ∀ (y_1 : γ), s y y_1 → y_1 ∈ t) → ∀ (y : γ) (x_1 : β), r x x_1 → s x_1 y → y ∈ t

Next tactic:
exact fun h z y rzy => h y rzy z
theorem graph_id : graph id = @Eq α := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
⊢ graph id = Eq

Next tactic:
simp  (config := { unfoldPartialApp := true }) [graph]
theorem graph_comp {f : β → γ} {g : α → β} : graph (f ∘ g) = Rel.comp (graph g) (graph f) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : β → γ
g : α → β
⊢ graph (f ∘ g) = Rel.comp (graph g) (graph f)

Next tactic:
ext x y
theorem graph_comp {f : β → γ} {g : α → β} : graph (f ∘ g) = Rel.comp (graph g) (graph f) := by
  ext x y
  

Proof state:
case a.h.a
α : Type u_1
β : Type u_2
γ : Type u_3
f : β → γ
g : α → β
x : α
y : γ
⊢ graph (f ∘ g) x y ↔ Rel.comp (graph g) (graph f) x y

Next tactic:
simp [Rel.comp]
theorem Equiv.graph_inv (f : α ≃ β) : (f.symm : β → α).graph = Rel.inv (f : α → β).graph := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α ≃ β
⊢ Function.graph ⇑f.symm = Rel.inv (Function.graph ⇑f)

Next tactic:
ext x y
theorem Equiv.graph_inv (f : α ≃ β) : (f.symm : β → α).graph = Rel.inv (f : α → β).graph := by
  ext x y
  

Proof state:
case a.h.a
α : Type u_1
β : Type u_2
γ : Type u_3
f : α ≃ β
x : β
y : α
⊢ Function.graph (⇑f.symm) x y ↔ Rel.inv (Function.graph ⇑f) x y

Next tactic:
aesop (add norm Rel.inv_def)
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
⊢ (∃! f, Function.graph f = r) ↔ ∀ (x : α), ∃! y, r x y

Next tactic:
unfold Function.graph
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
⊢ (∃! f, (fun x y => f x = y) = r) ↔ ∀ (x : α), ∃! y, r x y

Next tactic:
constructor
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · 

Proof state:
case mp
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
⊢ (∃! f, (fun x y => f x = y) = r) → ∀ (x : α), ∃! y, r x y

Next tactic:
rintro ⟨f, rfl, _⟩ x
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    

Proof state:
case mp.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
right✝ : ∀ (y : α → β), (fun f_1 => (fun x y => f_1 x = y) = fun x y => f x = y) y → y = f
x : α
⊢ ∃! y, (fun x y => f x = y) x y

Next tactic:
use f x
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    use f x
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
right✝ : ∀ (y : α → β), (fun f_1 => (fun x y => f_1 x = y) = fun x y => f x = y) y → y = f
x : α
⊢ (fun y => (fun x y => f x = y) x y) (f x) ∧ ∀ (y : β), (fun y => (fun x y => f x = y) x y) y → y = f x

Next tactic:
simp only [forall_eq', and_self]
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    use f x
    simp only [forall_eq', and_self]
  · 

Proof state:
case mpr
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
⊢ (∀ (x : α), ∃! y, r x y) → ∃! f, (fun x y => f x = y) = r

Next tactic:
intro h
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    use f x
    simp only [forall_eq', and_self]
  · intro h
    

Proof state:
case mpr
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
h : ∀ (x : α), ∃! y, r x y
⊢ ∃! f, (fun x y => f x = y) = r

Next tactic:
choose f hf using fun x ↦ (h x).exists
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    use f x
    simp only [forall_eq', and_self]
  · intro h
    choose f hf using fun x ↦ (h x).exists
    

Proof state:
case mpr
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
h : ∀ (x : α), ∃! y, r x y
f : α → β
hf : ∀ (x : α), r x (f x)
⊢ ∃! f, (fun x y => f x = y) = r

Next tactic:
use f
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    use f x
    simp only [forall_eq', and_self]
  · intro h
    choose f hf using fun x ↦ (h x).exists
    use f
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
h : ∀ (x : α), ∃! y, r x y
f : α → β
hf : ∀ (x : α), r x (f x)
⊢ (fun f => (fun x y => f x = y) = r) f ∧ ∀ (y : α → β), (fun f => (fun x y => f x = y) = r) y → y = f

Next tactic:
constructor
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    use f x
    simp only [forall_eq', and_self]
  · intro h
    choose f hf using fun x ↦ (h x).exists
    use f
    constructor
    · 

Proof state:
case h.left
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
h : ∀ (x : α), ∃! y, r x y
f : α → β
hf : ∀ (x : α), r x (f x)
⊢ (fun f => (fun x y => f x = y) = r) f

Next tactic:
ext x _
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    use f x
    simp only [forall_eq', and_self]
  · intro h
    choose f hf using fun x ↦ (h x).exists
    use f
    constructor
    · ext x _
      

Proof state:
case h.left.a.h.a
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
h : ∀ (x : α), ∃! y, r x y
f : α → β
hf : ∀ (x : α), r x (f x)
x : α
x✝ : β
⊢ f x = x✝ ↔ r x x✝

Next tactic:
constructor
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    use f x
    simp only [forall_eq', and_self]
  · intro h
    choose f hf using fun x ↦ (h x).exists
    use f
    constructor
    · ext x _
      constructor
      · 

Proof state:
case h.left.a.h.a.mp
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
h : ∀ (x : α), ∃! y, r x y
f : α → β
hf : ∀ (x : α), r x (f x)
x : α
x✝ : β
⊢ f x = x✝ → r x x✝

Next tactic:
rintro rfl
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    use f x
    simp only [forall_eq', and_self]
  · intro h
    choose f hf using fun x ↦ (h x).exists
    use f
    constructor
    · ext x _
      constructor
      · rintro rfl
        

Proof state:
case h.left.a.h.a.mp
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
h : ∀ (x : α), ∃! y, r x y
f : α → β
hf : ∀ (x : α), r x (f x)
x : α
⊢ r x (f x)

Next tactic:
exact hf x
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    use f x
    simp only [forall_eq', and_self]
  · intro h
    choose f hf using fun x ↦ (h x).exists
    use f
    constructor
    · ext x _
      constructor
      · rintro rfl
        exact hf x
      · 

Proof state:
case h.left.a.h.a.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
h : ∀ (x : α), ∃! y, r x y
f : α → β
hf : ∀ (x : α), r x (f x)
x : α
x✝ : β
⊢ r x x✝ → f x = x✝

Next tactic:
exact (h x).unique (hf x)
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    use f x
    simp only [forall_eq', and_self]
  · intro h
    choose f hf using fun x ↦ (h x).exists
    use f
    constructor
    · ext x _
      constructor
      · rintro rfl
        exact hf x
      · exact (h x).unique (hf x)
    · 

Proof state:
case h.right
α : Type u_1
β : Type u_2
γ : Type u_3
r : Rel α β
h : ∀ (x : α), ∃! y, r x y
f : α → β
hf : ∀ (x : α), r x (f x)
⊢ ∀ (y : α → β), (fun f => (fun x y => f x = y) = r) y → y = f

Next tactic:
rintro _ rfl
theorem Relation.is_graph_iff (r : Rel α β) : (∃! f, Function.graph f = r) ↔ ∀ x, ∃! y, r x y := by
  unfold Function.graph
  constructor
  · rintro ⟨f, rfl, _⟩ x
    use f x
    simp only [forall_eq', and_self]
  · intro h
    choose f hf using fun x ↦ (h x).exists
    use f
    constructor
    · ext x _
      constructor
      · rintro rfl
        exact hf x
      · exact (h x).unique (hf x)
    · rintro _ rfl
      

Proof state:
case h.right
α : Type u_1
β : Type u_2
γ : Type u_3
f y✝ : α → β
h : ∀ (x : α), ∃! y, (fun x y => y✝ x = y) x y
hf : ∀ (x : α), (fun x y => y✝ x = y) x (f x)
⊢ y✝ = f

Next tactic:
exact funext hf
theorem image_eq (f : α → β) (s : Set α) : f '' s = (Function.graph f).image s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β
s : Set α
⊢ f '' s = Rel.image (Function.graph f) s

Next tactic:
simp [Set.image, Rel.image]