l3lab/ntp-mathlib huggingface dataset:
theorem range_subtype_map {p : α → Prop} {q : β → Prop} (f : α → β) (h : ∀ x, p x → q (f x)) :
    range (Subtype.map f h) = (↑) ⁻¹' (f '' { x | p x }) := by
  ext ⟨x, hx⟩
  rw [mem_preimage, mem_range, mem_image, Subtype.exists, Subtype.coe_mk]
  apply Iff.intro
  · rintro ⟨a, b, hab⟩
    rw [Subtype.map, Subtype.mk.injEq] at hab
    use a
    trivial
  · 

Proof state:
case h.mk.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : α → Prop
q : β → Prop
f : α → β
h : ∀ (x : α), p x → q (f x)
x : β
hx : q x
⊢ (∃ x_1 ∈ {x | p x}, f x_1 = x) →
    ∃ a, ∃ (b : p a), Subtype.map f h { val := a, property := b } = { val := x, property := hx }

Next tactic:
rintro ⟨a, b, hab⟩
theorem range_subtype_map {p : α → Prop} {q : β → Prop} (f : α → β) (h : ∀ x, p x → q (f x)) :
    range (Subtype.map f h) = (↑) ⁻¹' (f '' { x | p x }) := by
  ext ⟨x, hx⟩
  rw [mem_preimage, mem_range, mem_image, Subtype.exists, Subtype.coe_mk]
  apply Iff.intro
  · rintro ⟨a, b, hab⟩
    rw [Subtype.map, Subtype.mk.injEq] at hab
    use a
    trivial
  · rintro ⟨a, b, hab⟩
    

Proof state:
case h.mk.mpr.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : α → Prop
q : β → Prop
f : α → β
h : ∀ (x : α), p x → q (f x)
x : β
hx : q x
a : α
b : a ∈ {x | p x}
hab : f a = x
⊢ ∃ a, ∃ (b : p a), Subtype.map f h { val := a, property := b } = { val := x, property := hx }

Next tactic:
use a
theorem range_subtype_map {p : α → Prop} {q : β → Prop} (f : α → β) (h : ∀ x, p x → q (f x)) :
    range (Subtype.map f h) = (↑) ⁻¹' (f '' { x | p x }) := by
  ext ⟨x, hx⟩
  rw [mem_preimage, mem_range, mem_image, Subtype.exists, Subtype.coe_mk]
  apply Iff.intro
  · rintro ⟨a, b, hab⟩
    rw [Subtype.map, Subtype.mk.injEq] at hab
    use a
    trivial
  · rintro ⟨a, b, hab⟩
    use a
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : α → Prop
q : β → Prop
f : α → β
h : ∀ (x : α), p x → q (f x)
x : β
hx : q x
a : α
b : a ∈ {x | p x}
hab : f a = x
⊢ ∃ (b : p a), Subtype.map f h { val := a, property := b } = { val := x, property := hx }

Next tactic:
use b
theorem range_subtype_map {p : α → Prop} {q : β → Prop} (f : α → β) (h : ∀ x, p x → q (f x)) :
    range (Subtype.map f h) = (↑) ⁻¹' (f '' { x | p x }) := by
  ext ⟨x, hx⟩
  rw [mem_preimage, mem_range, mem_image, Subtype.exists, Subtype.coe_mk]
  apply Iff.intro
  · rintro ⟨a, b, hab⟩
    rw [Subtype.map, Subtype.mk.injEq] at hab
    use a
    trivial
  · rintro ⟨a, b, hab⟩
    use a
    use b
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : α → Prop
q : β → Prop
f : α → β
h : ∀ (x : α), p x → q (f x)
x : β
hx : q x
a : α
b : a ∈ {x | p x}
hab : f a = x
⊢ Subtype.map f h { val := a, property := b } = { val := x, property := hx }

Next tactic:
rw [Subtype.map, Subtype.mk.injEq]
theorem range_subtype_map {p : α → Prop} {q : β → Prop} (f : α → β) (h : ∀ x, p x → q (f x)) :
    range (Subtype.map f h) = (↑) ⁻¹' (f '' { x | p x }) := by
  ext ⟨x, hx⟩
  rw [mem_preimage, mem_range, mem_image, Subtype.exists, Subtype.coe_mk]
  apply Iff.intro
  · rintro ⟨a, b, hab⟩
    rw [Subtype.map, Subtype.mk.injEq] at hab
    use a
    trivial
  · rintro ⟨a, b, hab⟩
    use a
    use b
    rw [Subtype.map, Subtype.mk.injEq]
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : α → Prop
q : β → Prop
f : α → β
h : ∀ (x : α), p x → q (f x)
x : β
hx : q x
a : α
b : a ∈ {x | p x}
hab : f a = x
⊢ f ↑{ val := a, property := b } = x

Next tactic:
exact hab
theorem range_subset_singleton {f : ι → α} {x : α} : range f ⊆ {x} ↔ f = const ι x := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
f : ι → α
x : α
⊢ range f ⊆ {x} ↔ f = const ι x

Next tactic:
simp [range_subset_iff, funext_iff, mem_singleton]
theorem image_compl_preimage {f : α → β} {s : Set β} : f '' (f ⁻¹' s)ᶜ = range f \ s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s✝ t : Set α
f : α → β
s : Set β
⊢ f '' (f ⁻¹' s)ᶜ = range f \ s

Next tactic:
rw [compl_eq_univ_diff, image_diff_preimage, image_univ]
theorem image_eq_range (f : α → β) (s : Set α) : f '' s = range fun x : s => f x := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s✝ t : Set α
f : α → β
s : Set α
⊢ f '' s = range fun x => f ↑x

Next tactic:
ext
theorem image_eq_range (f : α → β) (s : Set α) : f '' s = range fun x : s => f x := by
  ext
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s✝ t : Set α
f : α → β
s : Set α
x✝ : β
⊢ x✝ ∈ f '' s ↔ x✝ ∈ range fun x => f ↑x

Next tactic:
constructor
theorem image_eq_range (f : α → β) (s : Set α) : f '' s = range fun x : s => f x := by
  ext
  constructor
  

Proof state:
case h.mp
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s✝ t : Set α
f : α → β
s : Set α
x✝ : β
⊢ x✝ ∈ f '' s → x✝ ∈ range fun x => f ↑x
case h.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s✝ t : Set α
f : α → β
s : Set α
x✝ : β
⊢ (x✝ ∈ range fun x => f ↑x) → x✝ ∈ f '' s

Next tactic:
rintro ⟨x, h1, h2⟩
theorem image_eq_range (f : α → β) (s : Set α) : f '' s = range fun x : s => f x := by
  ext
  constructor
  rintro ⟨x, h1, h2⟩
  

Proof state:
case h.mp.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s✝ t : Set α
f : α → β
s : Set α
x✝ : β
x : α
h1 : x ∈ s
h2 : f x = x✝
⊢ x✝ ∈ range fun x => f ↑x
case h.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s✝ t : Set α
f : α → β
s : Set α
x✝ : β
⊢ (x✝ ∈ range fun x => f ↑x) → x✝ ∈ f '' s

Next tactic:
exact ⟨⟨x, h1⟩, h2⟩
theorem image_eq_range (f : α → β) (s : Set α) : f '' s = range fun x : s => f x := by
  ext
  constructor
  rintro ⟨x, h1, h2⟩
  exact ⟨⟨x, h1⟩, h2⟩
  

Proof state:
case h.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s✝ t : Set α
f : α → β
s : Set α
x✝ : β
⊢ (x✝ ∈ range fun x => f ↑x) → x✝ ∈ f '' s

Next tactic:
rintro ⟨⟨x, h1⟩, h2⟩
theorem image_eq_range (f : α → β) (s : Set α) : f '' s = range fun x : s => f x := by
  ext
  constructor
  rintro ⟨x, h1, h2⟩
  exact ⟨⟨x, h1⟩, h2⟩
  rintro ⟨⟨x, h1⟩, h2⟩
  

Proof state:
case h.mpr.intro.mk
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s✝ t : Set α
f : α → β
s : Set α
x✝ : β
x : α
h1 : x ∈ s
h2 : (fun x => f ↑x) { val := x, property := h1 } = x✝
⊢ x✝ ∈ f '' s

Next tactic:
exact ⟨x, h1, h2⟩
theorem range_ite_subset' {p : Prop} [Decidable p] {f g : α → β} :
    range (if p then f else g) ⊆ range f ∪ range g := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : Prop
inst✝ : Decidable p
f g : α → β
⊢ range (if p then f else g) ⊆ range f ∪ range g

Next tactic:
by_cases h : p
theorem range_ite_subset' {p : Prop} [Decidable p] {f g : α → β} :
    range (if p then f else g) ⊆ range f ∪ range g := by
  by_cases h : p
  · 

Proof state:
case pos
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : Prop
inst✝ : Decidable p
f g : α → β
h : p
⊢ range (if p then f else g) ⊆ range f ∪ range g

Next tactic:
rw [if_pos h]
theorem range_ite_subset' {p : Prop} [Decidable p] {f g : α → β} :
    range (if p then f else g) ⊆ range f ∪ range g := by
  by_cases h : p
  · rw [if_pos h]
    

Proof state:
case pos
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : Prop
inst✝ : Decidable p
f g : α → β
h : p
⊢ range f ⊆ range f ∪ range g

Next tactic:
exact subset_union_left _ _
theorem range_ite_subset' {p : Prop} [Decidable p] {f g : α → β} :
    range (if p then f else g) ⊆ range f ∪ range g := by
  by_cases h : p
  · rw [if_pos h]
    exact subset_union_left _ _
  · 

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : Prop
inst✝ : Decidable p
f g : α → β
h : ¬p
⊢ range (if p then f else g) ⊆ range f ∪ range g

Next tactic:
rw [if_neg h]
theorem range_ite_subset' {p : Prop} [Decidable p] {f g : α → β} :
    range (if p then f else g) ⊆ range f ∪ range g := by
  by_cases h : p
  · rw [if_pos h]
    exact subset_union_left _ _
  · rw [if_neg h]
    

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : Prop
inst✝ : Decidable p
f g : α → β
h : ¬p
⊢ range g ⊆ range f ∪ range g

Next tactic:
exact subset_union_right _ _
theorem range_ite_subset {p : α → Prop} [DecidablePred p] {f g : α → β} :
    (range fun x => if p x then f x else g x) ⊆ range f ∪ range g := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : α → Prop
inst✝ : DecidablePred p
f g : α → β
⊢ (range fun x => if p x then f x else g x) ⊆ range f ∪ range g

Next tactic:
rw [range_subset_iff]
theorem range_ite_subset {p : α → Prop} [DecidablePred p] {f g : α → β} :
    (range fun x => if p x then f x else g x) ⊆ range f ∪ range g := by
  rw [range_subset_iff]; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : α → Prop
inst✝ : DecidablePred p
f g : α → β
⊢ ∀ (y : α), (if p y then f y else g y) ∈ range f ∪ range g

Next tactic:
intro x
theorem range_ite_subset {p : α → Prop} [DecidablePred p] {f g : α → β} :
    (range fun x => if p x then f x else g x) ⊆ range f ∪ range g := by
  rw [range_subset_iff]; intro x; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : α → Prop
inst✝ : DecidablePred p
f g : α → β
x : α
⊢ (if p x then f x else g x) ∈ range f ∪ range g

Next tactic:
by_cases h : p x
theorem range_ite_subset {p : α → Prop} [DecidablePred p] {f g : α → β} :
    (range fun x => if p x then f x else g x) ⊆ range f ∪ range g := by
  rw [range_subset_iff]; intro x; by_cases h : p x
  

Proof state:
case pos
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : α → Prop
inst✝ : DecidablePred p
f g : α → β
x : α
h : p x
⊢ (if p x then f x else g x) ∈ range f ∪ range g
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : α → Prop
inst✝ : DecidablePred p
f g : α → β
x : α
h : ¬p x
⊢ (if p x then f x else g x) ∈ range f ∪ range g

Next tactic:
simp only [if_pos h, mem_union, mem_range, exists_apply_eq_apply, true_or]
theorem range_ite_subset {p : α → Prop} [DecidablePred p] {f g : α → β} :
    (range fun x => if p x then f x else g x) ⊆ range f ∪ range g := by
  rw [range_subset_iff]; intro x; by_cases h : p x
  simp only [if_pos h, mem_union, mem_range, exists_apply_eq_apply, true_or]
  

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
p : α → Prop
inst✝ : DecidablePred p
f g : α → β
x : α
h : ¬p x
⊢ (if p x then f x else g x) ∈ range f ∪ range g

Next tactic:
simp [if_neg h, mem_union, mem_range_self]
/-- The range of a function from a `Unique` type contains just the
function applied to its single value. -/
theorem range_unique [h : Unique ι] : range f = {f default} := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : Unique ι
⊢ range f = {f default}

Next tactic:
ext x
/-- The range of a function from a `Unique` type contains just the
function applied to its single value. -/
theorem range_unique [h : Unique ι] : range f = {f default} := by
  ext x
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : Unique ι
x : α
⊢ x ∈ range f ↔ x ∈ {f default}

Next tactic:
rw [mem_range]
/-- The range of a function from a `Unique` type contains just the
function applied to its single value. -/
theorem range_unique [h : Unique ι] : range f = {f default} := by
  ext x
  rw [mem_range]
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : Unique ι
x : α
⊢ (∃ y, f y = x) ↔ x ∈ {f default}

Next tactic:
constructor
/-- The range of a function from a `Unique` type contains just the
function applied to its single value. -/
theorem range_unique [h : Unique ι] : range f = {f default} := by
  ext x
  rw [mem_range]
  constructor
  · 

Proof state:
case h.mp
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : Unique ι
x : α
⊢ (∃ y, f y = x) → x ∈ {f default}

Next tactic:
rintro ⟨i, hi⟩
/-- The range of a function from a `Unique` type contains just the
function applied to its single value. -/
theorem range_unique [h : Unique ι] : range f = {f default} := by
  ext x
  rw [mem_range]
  constructor
  · rintro ⟨i, hi⟩
    

Proof state:
case h.mp.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : Unique ι
x : α
i : ι
hi : f i = x
⊢ x ∈ {f default}

Next tactic:
rw [h.uniq i] at hi
/-- The range of a function from a `Unique` type contains just the
function applied to its single value. -/
theorem range_unique [h : Unique ι] : range f = {f default} := by
  ext x
  rw [mem_range]
  constructor
  · rintro ⟨i, hi⟩
    rw [h.uniq i] at hi
    

Proof state:
case h.mp.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : Unique ι
x : α
i : ι
hi : f default = x
⊢ x ∈ {f default}

Next tactic:
exact hi ▸ mem_singleton _
/-- The range of a function from a `Unique` type contains just the
function applied to its single value. -/
theorem range_unique [h : Unique ι] : range f = {f default} := by
  ext x
  rw [mem_range]
  constructor
  · rintro ⟨i, hi⟩
    rw [h.uniq i] at hi
    exact hi ▸ mem_singleton _
  · 

Proof state:
case h.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : Unique ι
x : α
⊢ x ∈ {f default} → ∃ y, f y = x

Next tactic:
exact fun h => ⟨default, h.symm⟩
@[simp]
theorem range_inclusion (h : s ⊆ t) : range (inclusion h) = { x : t | (x : α) ∈ s } := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : s ⊆ t
⊢ range (inclusion h) = {x | ↑x ∈ s}

Next tactic:
ext ⟨x, hx⟩
@[simp]
theorem range_inclusion (h : s ⊆ t) : range (inclusion h) = { x : t | (x : α) ∈ s } := by
  ext ⟨x, hx⟩
  -- Porting note: `simp [inclusion]` doesn't solve goal
  

Proof state:
case h.mk
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : s ⊆ t
x : α
hx : x ∈ t
⊢ { val := x, property := hx } ∈ range (inclusion h) ↔ { val := x, property := hx } ∈ {x | ↑x ∈ s}

Next tactic:
apply Iff.intro
@[simp]
theorem range_inclusion (h : s ⊆ t) : range (inclusion h) = { x : t | (x : α) ∈ s } := by
  ext ⟨x, hx⟩
  -- Porting note: `simp [inclusion]` doesn't solve goal
  apply Iff.intro
  · 

Proof state:
case h.mk.mp
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : s ⊆ t
x : α
hx : x ∈ t
⊢ { val := x, property := hx } ∈ range (inclusion h) → { val := x, property := hx } ∈ {x | ↑x ∈ s}

Next tactic:
rw [mem_range]
@[simp]
theorem range_inclusion (h : s ⊆ t) : range (inclusion h) = { x : t | (x : α) ∈ s } := by
  ext ⟨x, hx⟩
  -- Porting note: `simp [inclusion]` doesn't solve goal
  apply Iff.intro
  · rw [mem_range]
    

Proof state:
case h.mk.mp
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : s ⊆ t
x : α
hx : x ∈ t
⊢ (∃ y, inclusion h y = { val := x, property := hx }) → { val := x, property := hx } ∈ {x | ↑x ∈ s}

Next tactic:
rintro ⟨a, ha⟩
@[simp]
theorem range_inclusion (h : s ⊆ t) : range (inclusion h) = { x : t | (x : α) ∈ s } := by
  ext ⟨x, hx⟩
  -- Porting note: `simp [inclusion]` doesn't solve goal
  apply Iff.intro
  · rw [mem_range]
    rintro ⟨a, ha⟩
    

Proof state:
case h.mk.mp.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : s ⊆ t
x : α
hx : x ∈ t
a : ↑s
ha : inclusion h a = { val := x, property := hx }
⊢ { val := x, property := hx } ∈ {x | ↑x ∈ s}

Next tactic:
rw [inclusion, Subtype.mk.injEq] at ha
@[simp]
theorem range_inclusion (h : s ⊆ t) : range (inclusion h) = { x : t | (x : α) ∈ s } := by
  ext ⟨x, hx⟩
  -- Porting note: `simp [inclusion]` doesn't solve goal
  apply Iff.intro
  · rw [mem_range]
    rintro ⟨a, ha⟩
    rw [inclusion, Subtype.mk.injEq] at ha
    

Proof state:
case h.mk.mp.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : s ⊆ t
x : α
hx : x ∈ t
a : ↑s
ha : ↑a = x
⊢ { val := x, property := hx } ∈ {x | ↑x ∈ s}

Next tactic:
rw [mem_setOf, Subtype.coe_mk, ← ha]
@[simp]
theorem range_inclusion (h : s ⊆ t) : range (inclusion h) = { x : t | (x : α) ∈ s } := by
  ext ⟨x, hx⟩
  -- Porting note: `simp [inclusion]` doesn't solve goal
  apply Iff.intro
  · rw [mem_range]
    rintro ⟨a, ha⟩
    rw [inclusion, Subtype.mk.injEq] at ha
    rw [mem_setOf, Subtype.coe_mk, ← ha]
    

Proof state:
case h.mk.mp.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : s ⊆ t
x : α
hx : x ∈ t
a : ↑s
ha : ↑a = x
⊢ ↑a ∈ s

Next tactic:
exact Subtype.coe_prop _
@[simp]
theorem range_inclusion (h : s ⊆ t) : range (inclusion h) = { x : t | (x : α) ∈ s } := by
  ext ⟨x, hx⟩
  -- Porting note: `simp [inclusion]` doesn't solve goal
  apply Iff.intro
  · rw [mem_range]
    rintro ⟨a, ha⟩
    rw [inclusion, Subtype.mk.injEq] at ha
    rw [mem_setOf, Subtype.coe_mk, ← ha]
    exact Subtype.coe_prop _
  · 

Proof state:
case h.mk.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : s ⊆ t
x : α
hx : x ∈ t
⊢ { val := x, property := hx } ∈ {x | ↑x ∈ s} → { val := x, property := hx } ∈ range (inclusion h)

Next tactic:
rw [mem_setOf, Subtype.coe_mk, mem_range]
@[simp]
theorem range_inclusion (h : s ⊆ t) : range (inclusion h) = { x : t | (x : α) ∈ s } := by
  ext ⟨x, hx⟩
  -- Porting note: `simp [inclusion]` doesn't solve goal
  apply Iff.intro
  · rw [mem_range]
    rintro ⟨a, ha⟩
    rw [inclusion, Subtype.mk.injEq] at ha
    rw [mem_setOf, Subtype.coe_mk, ← ha]
    exact Subtype.coe_prop _
  · rw [mem_setOf, Subtype.coe_mk, mem_range]
    

Proof state:
case h.mk.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : s ⊆ t
x : α
hx : x ∈ t
⊢ x ∈ s → ∃ y, inclusion h y = { val := x, property := hx }

Next tactic:
intro hx'
@[simp]
theorem range_inclusion (h : s ⊆ t) : range (inclusion h) = { x : t | (x : α) ∈ s } := by
  ext ⟨x, hx⟩
  -- Porting note: `simp [inclusion]` doesn't solve goal
  apply Iff.intro
  · rw [mem_range]
    rintro ⟨a, ha⟩
    rw [inclusion, Subtype.mk.injEq] at ha
    rw [mem_setOf, Subtype.coe_mk, ← ha]
    exact Subtype.coe_prop _
  · rw [mem_setOf, Subtype.coe_mk, mem_range]
    intro hx'
    

Proof state:
case h.mk.mpr
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : s ⊆ t
x : α
hx : x ∈ t
hx' : x ∈ s
⊢ ∃ y, inclusion h y = { val := x, property := hx }

Next tactic:
use ⟨x, hx'⟩
@[simp]
theorem range_inclusion (h : s ⊆ t) : range (inclusion h) = { x : t | (x : α) ∈ s } := by
  ext ⟨x, hx⟩
  -- Porting note: `simp [inclusion]` doesn't solve goal
  apply Iff.intro
  · rw [mem_range]
    rintro ⟨a, ha⟩
    rw [inclusion, Subtype.mk.injEq] at ha
    rw [mem_setOf, Subtype.coe_mk, ← ha]
    exact Subtype.coe_prop _
  · rw [mem_setOf, Subtype.coe_mk, mem_range]
    intro hx'
    use ⟨x, hx'⟩
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f : ι → α
s t : Set α
h : s ⊆ t
x : α
hx : x ∈ t
hx' : x ∈ s
⊢ inclusion h { val := x, property := hx' } = { val := x, property := hx }

Next tactic:
trivial
@[simp]
theorem comp_rangeSplitting (f : α → β) : f ∘ rangeSplitting f = (↑) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
f : α → β
⊢ f ∘ rangeSplitting f = Subtype.val

Next tactic:
ext
@[simp]
theorem comp_rangeSplitting (f : α → β) : f ∘ rangeSplitting f = (↑) := by
  ext
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
f : α → β
x✝ : ↑(range f)
⊢ (f ∘ rangeSplitting f) x✝ = ↑x✝

Next tactic:
simp only [Function.comp_apply]
@[simp]
theorem comp_rangeSplitting (f : α → β) : f ∘ rangeSplitting f = (↑) := by
  ext
  simp only [Function.comp_apply]
  

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
f : α → β
x✝ : ↑(range f)
⊢ f (rangeSplitting f x✝) = ↑x✝

Next tactic:
apply apply_rangeSplitting
theorem leftInverse_rangeSplitting (f : α → β) :
    LeftInverse (rangeFactorization f) (rangeSplitting f) := fun x => by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
f : α → β
x : ↑(range f)
⊢ rangeFactorization f (rangeSplitting f x) = x

Next tactic:
apply Subtype.ext
theorem leftInverse_rangeSplitting (f : α → β) :
    LeftInverse (rangeFactorization f) (rangeSplitting f) := fun x => by
  apply Subtype.ext -- Porting note: why doesn't `ext` find this lemma?
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
f : α → β
x : ↑(range f)
⊢ ↑(rangeFactorization f (rangeSplitting f x)) = ↑x

Next tactic:
simp only [rangeFactorization_coe]
theorem leftInverse_rangeSplitting (f : α → β) :
    LeftInverse (rangeFactorization f) (rangeSplitting f) := fun x => by
  apply Subtype.ext -- Porting note: why doesn't `ext` find this lemma?
  simp only [rangeFactorization_coe]
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
f✝ : ι → α
s t : Set α
f : α → β
x : ↑(range f)
⊢ f (rangeSplitting f x) = ↑x

Next tactic:
apply apply_rangeSplitting
/-- If the preimage of a set under a surjective map is a subsingleton,
the set is a subsingleton. -/
theorem subsingleton_of_preimage {f : α → β} (hf : Function.Surjective f) (s : Set β)
    (hs : (f ⁻¹' s).Subsingleton) : s.Subsingleton := fun fx hx fy hy => by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
s✝ : Set α
f : α → β
hf : Surjective f
s : Set β
hs : Set.Subsingleton (f ⁻¹' s)
fx : β
hx : fx ∈ s
fy : β
hy : fy ∈ s
⊢ fx = fy

Next tactic:
rcases hf fx, hf fy with ⟨⟨x, rfl⟩, ⟨y, rfl⟩⟩
/-- If the preimage of a set under a surjective map is a subsingleton,
the set is a subsingleton. -/
theorem subsingleton_of_preimage {f : α → β} (hf : Function.Surjective f) (s : Set β)
    (hs : (f ⁻¹' s).Subsingleton) : s.Subsingleton := fun fx hx fy hy => by
  rcases hf fx, hf fy with ⟨⟨x, rfl⟩, ⟨y, rfl⟩⟩
  

Proof state:
case intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
s✝ : Set α
f : α → β
hf : Surjective f
s : Set β
hs : Set.Subsingleton (f ⁻¹' s)
x : α
hx : f x ∈ s
y : α
hy : f y ∈ s
⊢ f x = f y

Next tactic:
exact congr_arg f (hs hx hy)
/-- The preimage of a nontrivial set under a surjective map is nontrivial. -/
theorem Nontrivial.preimage {s : Set β} (hs : s.Nontrivial) {f : α → β}
    (hf : Function.Surjective f) : (f ⁻¹' s).Nontrivial := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
s✝ : Set α
s : Set β
hs : Set.Nontrivial s
f : α → β
hf : Surjective f
⊢ Set.Nontrivial (f ⁻¹' s)

Next tactic:
rcases hs with ⟨fx, hx, fy, hy, hxy⟩
/-- The preimage of a nontrivial set under a surjective map is nontrivial. -/
theorem Nontrivial.preimage {s : Set β} (hs : s.Nontrivial) {f : α → β}
    (hf : Function.Surjective f) : (f ⁻¹' s).Nontrivial := by
  rcases hs with ⟨fx, hx, fy, hy, hxy⟩
  

Proof state:
case intro.intro.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
ι' : Sort u_5
s✝ : Set α
s : Set β
f : α → β
hf : Surjective f
fx : β
hx : fx ∈ s
fy : β
hy : fy ∈ s
hxy : fx ≠ fy
⊢ Set.Nontrivial (f ⁻¹' s)

Next tactic:
rcases hf fx, hf fy with ⟨⟨x, rfl⟩, ⟨y, rfl⟩⟩