l3lab/ntp-mathlib huggingface dataset:
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  

Proof state:
α : Type u
s : Set α
c : Cardinal.{u}
⊢ #{ t // t ⊆ s ∧ #↑t ≤ c } ≤ max #↑s ℵ₀ ^ c

Next tactic:
refine' le_trans _ (mk_bounded_set_le s c)
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  refine' le_trans _ (mk_bounded_set_le s c)
  

Proof state:
α : Type u
s : Set α
c : Cardinal.{u}
⊢ #{ t // t ⊆ s ∧ #↑t ≤ c } ≤ #{ t // #↑t ≤ c }

Next tactic:
refine' ⟨Embedding.codRestrict _ _ _⟩
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  refine' le_trans _ (mk_bounded_set_le s c)
  refine' ⟨Embedding.codRestrict _ _ _⟩
  

Proof state:
case refine'_1
α : Type u
s : Set α
c : Cardinal.{u}
⊢ { t // t ⊆ s ∧ #↑t ≤ c } ↪ Set ↑s
case refine'_2
α : Type u
s : Set α
c : Cardinal.{u}
⊢ ∀ (a : { t // t ⊆ s ∧ #↑t ≤ c }),
    ?refine'_1 a ∈ fun t =>
      Quot.lift ((fun α β => Nonempty (α ↪ β)) ↑t) (_ : ∀ (a b : Type u), a ≈ b → Nonempty (↑t ↪ a) = Nonempty (↑t ↪ b))
        c

Next tactic:
use fun t => (↑) ⁻¹' t.1
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  refine' le_trans _ (mk_bounded_set_le s c)
  refine' ⟨Embedding.codRestrict _ _ _⟩
  use fun t => (↑) ⁻¹' t.1
  · 

Proof state:
case inj'
α : Type u
s : Set α
c : Cardinal.{u}
⊢ Injective fun t => Subtype.val ⁻¹' ↑t

Next tactic:
rintro ⟨t, ht1, ht2⟩ ⟨t', h1t', h2t'⟩ h
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  refine' le_trans _ (mk_bounded_set_le s c)
  refine' ⟨Embedding.codRestrict _ _ _⟩
  use fun t => (↑) ⁻¹' t.1
  · rintro ⟨t, ht1, ht2⟩ ⟨t', h1t', h2t'⟩ h
    

Proof state:
case inj'.mk.intro.mk.intro
α : Type u
s : Set α
c : Cardinal.{u}
t : Set α
ht1 : t ⊆ s
ht2 : #↑t ≤ c
t' : Set α
h1t' : t' ⊆ s
h2t' : #↑t' ≤ c
h :
  (fun t => Subtype.val ⁻¹' ↑t) { val := t, property := (_ : t ⊆ s ∧ #↑t ≤ c) } =
    (fun t => Subtype.val ⁻¹' ↑t) { val := t', property := (_ : t' ⊆ s ∧ #↑t' ≤ c) }
⊢ { val := t, property := (_ : t ⊆ s ∧ #↑t ≤ c) } = { val := t', property := (_ : t' ⊆ s ∧ #↑t' ≤ c) }

Next tactic:
apply Subtype.eq
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  refine' le_trans _ (mk_bounded_set_le s c)
  refine' ⟨Embedding.codRestrict _ _ _⟩
  use fun t => (↑) ⁻¹' t.1
  · rintro ⟨t, ht1, ht2⟩ ⟨t', h1t', h2t'⟩ h
    apply Subtype.eq
    

Proof state:
case inj'.mk.intro.mk.intro.a
α : Type u
s : Set α
c : Cardinal.{u}
t : Set α
ht1 : t ⊆ s
ht2 : #↑t ≤ c
t' : Set α
h1t' : t' ⊆ s
h2t' : #↑t' ≤ c
h :
  (fun t => Subtype.val ⁻¹' ↑t) { val := t, property := (_ : t ⊆ s ∧ #↑t ≤ c) } =
    (fun t => Subtype.val ⁻¹' ↑t) { val := t', property := (_ : t' ⊆ s ∧ #↑t' ≤ c) }
⊢ ↑{ val := t, property := (_ : t ⊆ s ∧ #↑t ≤ c) } = ↑{ val := t', property := (_ : t' ⊆ s ∧ #↑t' ≤ c) }

Next tactic:
dsimp only at h ⊢
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  refine' le_trans _ (mk_bounded_set_le s c)
  refine' ⟨Embedding.codRestrict _ _ _⟩
  use fun t => (↑) ⁻¹' t.1
  · rintro ⟨t, ht1, ht2⟩ ⟨t', h1t', h2t'⟩ h
    apply Subtype.eq
    dsimp only at h ⊢
    

Proof state:
case inj'.mk.intro.mk.intro.a
α : Type u
s : Set α
c : Cardinal.{u}
t : Set α
ht1 : t ⊆ s
ht2 : #↑t ≤ c
t' : Set α
h1t' : t' ⊆ s
h2t' : #↑t' ≤ c
h : Subtype.val ⁻¹' t = Subtype.val ⁻¹' t'
⊢ t = t'

Next tactic:
refine' (preimage_eq_preimage' _ _).1 h
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  refine' le_trans _ (mk_bounded_set_le s c)
  refine' ⟨Embedding.codRestrict _ _ _⟩
  use fun t => (↑) ⁻¹' t.1
  · rintro ⟨t, ht1, ht2⟩ ⟨t', h1t', h2t'⟩ h
    apply Subtype.eq
    dsimp only at h ⊢
    refine' (preimage_eq_preimage' _ _).1 h <;> 

Proof state:
case inj'.mk.intro.mk.intro.a.refine'_1
α : Type u
s : Set α
c : Cardinal.{u}
t : Set α
ht1 : t ⊆ s
ht2 : #↑t ≤ c
t' : Set α
h1t' : t' ⊆ s
h2t' : #↑t' ≤ c
h : Subtype.val ⁻¹' t = Subtype.val ⁻¹' t'
⊢ t ⊆ range Subtype.val

Next tactic:
rw [Subtype.range_coe]
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  refine' le_trans _ (mk_bounded_set_le s c)
  refine' ⟨Embedding.codRestrict _ _ _⟩
  use fun t => (↑) ⁻¹' t.1
  · rintro ⟨t, ht1, ht2⟩ ⟨t', h1t', h2t'⟩ h
    apply Subtype.eq
    dsimp only at h ⊢
    refine' (preimage_eq_preimage' _ _).1 h <;> 

Proof state:
case inj'.mk.intro.mk.intro.a.refine'_2
α : Type u
s : Set α
c : Cardinal.{u}
t : Set α
ht1 : t ⊆ s
ht2 : #↑t ≤ c
t' : Set α
h1t' : t' ⊆ s
h2t' : #↑t' ≤ c
h : Subtype.val ⁻¹' t = Subtype.val ⁻¹' t'
⊢ t' ⊆ range Subtype.val

Next tactic:
rw [Subtype.range_coe]
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  refine' le_trans _ (mk_bounded_set_le s c)
  refine' ⟨Embedding.codRestrict _ _ _⟩
  use fun t => (↑) ⁻¹' t.1
  · rintro ⟨t, ht1, ht2⟩ ⟨t', h1t', h2t'⟩ h
    apply Subtype.eq
    dsimp only at h ⊢
    refine' (preimage_eq_preimage' _ _).1 h <;> rw [Subtype.range_coe] <;> 

Proof state:
case inj'.mk.intro.mk.intro.a.refine'_1
α : Type u
s : Set α
c : Cardinal.{u}
t : Set α
ht1 : t ⊆ s
ht2 : #↑t ≤ c
t' : Set α
h1t' : t' ⊆ s
h2t' : #↑t' ≤ c
h : Subtype.val ⁻¹' t = Subtype.val ⁻¹' t'
⊢ t ⊆ s

Next tactic:
assumption
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  refine' le_trans _ (mk_bounded_set_le s c)
  refine' ⟨Embedding.codRestrict _ _ _⟩
  use fun t => (↑) ⁻¹' t.1
  · rintro ⟨t, ht1, ht2⟩ ⟨t', h1t', h2t'⟩ h
    apply Subtype.eq
    dsimp only at h ⊢
    refine' (preimage_eq_preimage' _ _).1 h <;> rw [Subtype.range_coe] <;> 

Proof state:
case inj'.mk.intro.mk.intro.a.refine'_2
α : Type u
s : Set α
c : Cardinal.{u}
t : Set α
ht1 : t ⊆ s
ht2 : #↑t ≤ c
t' : Set α
h1t' : t' ⊆ s
h2t' : #↑t' ≤ c
h : Subtype.val ⁻¹' t = Subtype.val ⁻¹' t'
⊢ t' ⊆ s

Next tactic:
assumption
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  refine' le_trans _ (mk_bounded_set_le s c)
  refine' ⟨Embedding.codRestrict _ _ _⟩
  use fun t => (↑) ⁻¹' t.1
  · rintro ⟨t, ht1, ht2⟩ ⟨t', h1t', h2t'⟩ h
    apply Subtype.eq
    dsimp only at h ⊢
    refine' (preimage_eq_preimage' _ _).1 h <;> rw [Subtype.range_coe] <;> assumption
  

Proof state:
case refine'_2
α : Type u
s : Set α
c : Cardinal.{u}
⊢ ∀ (a : { t // t ⊆ s ∧ #↑t ≤ c }),
    { toFun := fun t => Subtype.val ⁻¹' ↑t,
          inj' :=
            (_ :
              ∀ ⦃a₁ a₂ : { t // t ⊆ s ∧ #↑t ≤ c }⦄,
                (fun t => Subtype.val ⁻¹' ↑t) a₁ = (fun t => Subtype.val ⁻¹' ↑t) a₂ → a₁ = a₂) }
        a ∈
      fun t =>
      Quot.lift ((fun α β => Nonempty (α ↪ β)) ↑t) (_ : ∀ (a b : Type u), a ≈ b → Nonempty (↑t ↪ a) = Nonempty (↑t ↪ b))
        c

Next tactic:
rintro ⟨t, _, h2t⟩
theorem mk_bounded_subset_le {α : Type u} (s : Set α) (c : Cardinal.{u}) :
    #{ t : Set α // t ⊆ s ∧ #t ≤ c } ≤ max #s ℵ₀ ^ c := by
  refine' le_trans _ (mk_bounded_set_le s c)
  refine' ⟨Embedding.codRestrict _ _ _⟩
  use fun t => (↑) ⁻¹' t.1
  · rintro ⟨t, ht1, ht2⟩ ⟨t', h1t', h2t'⟩ h
    apply Subtype.eq
    dsimp only at h ⊢
    refine' (preimage_eq_preimage' _ _).1 h <;> rw [Subtype.range_coe] <;> assumption
  rintro ⟨t, _, h2t⟩; 

Proof state:
case refine'_2.mk.intro
α : Type u
s : Set α
c : Cardinal.{u}
t : Set α
left✝ : t ⊆ s
h2t : #↑t ≤ c
⊢ { toFun := fun t => Subtype.val ⁻¹' ↑t,
        inj' :=
          (_ :
            ∀ ⦃a₁ a₂ : { t // t ⊆ s ∧ #↑t ≤ c }⦄,
              (fun t => Subtype.val ⁻¹' ↑t) a₁ = (fun t => Subtype.val ⁻¹' ↑t) a₂ → a₁ = a₂) }
      { val := t, property := (_ : t ⊆ s ∧ #↑t ≤ c) } ∈
    fun t =>
    Quot.lift ((fun α β => Nonempty (α ↪ β)) ↑t) (_ : ∀ (a b : Type u), a ≈ b → Nonempty (↑t ↪ a) = Nonempty (↑t ↪ b)) c

Next tactic:
exact (mk_preimage_of_injective _ _ Subtype.val_injective).trans h2t
theorem mk_compl_of_infinite {α : Type*} [Infinite α] (s : Set α) (h2 : #s < #α) :
    #(sᶜ : Set α) = #α := by
  

Proof state:
α : Type u_1
inst✝ : Infinite α
s : Set α
h2 : #↑s < #α
⊢ #↑sᶜ = #α

Next tactic:
refine' eq_of_add_eq_of_aleph0_le _ h2 (aleph0_le_mk α)
theorem mk_compl_of_infinite {α : Type*} [Infinite α] (s : Set α) (h2 : #s < #α) :
    #(sᶜ : Set α) = #α := by
  refine' eq_of_add_eq_of_aleph0_le _ h2 (aleph0_le_mk α)
  

Proof state:
α : Type u_1
inst✝ : Infinite α
s : Set α
h2 : #↑s < #α
⊢ #↑s + #↑sᶜ = #α

Next tactic:
exact mk_sum_compl s
theorem mk_compl_finset_of_infinite {α : Type*} [Infinite α] (s : Finset α) :
    #((↑s)ᶜ : Set α) = #α := by
  

Proof state:
α : Type u_1
inst✝ : Infinite α
s : Finset α
⊢ #↑(↑s)ᶜ = #α

Next tactic:
apply mk_compl_of_infinite
theorem mk_compl_finset_of_infinite {α : Type*} [Infinite α] (s : Finset α) :
    #((↑s)ᶜ : Set α) = #α := by
  apply mk_compl_of_infinite
  

Proof state:
case h2
α : Type u_1
inst✝ : Infinite α
s : Finset α
⊢ #↑↑s < #α

Next tactic:
exact (finset_card_lt_aleph0 s).trans_le (aleph0_le_mk α)
theorem mk_compl_eq_mk_compl_infinite {α : Type*} [Infinite α] {s t : Set α} (hs : #s < #α)
    (ht : #t < #α) : #(sᶜ : Set α) = #(tᶜ : Set α) := by
  

Proof state:
α : Type u_1
inst✝ : Infinite α
s t : Set α
hs : #↑s < #α
ht : #↑t < #α
⊢ #↑sᶜ = #↑tᶜ

Next tactic:
rw [mk_compl_of_infinite s hs, mk_compl_of_infinite t ht]
theorem mk_compl_eq_mk_compl_finite_lift {α : Type u} {β : Type v} [Finite α] {s : Set α}
    {t : Set β} (h1 : (lift.{max v w, u} #α) = (lift.{max u w, v} #β))
    (h2 : lift.{max v w, u} #s = lift.{max u w, v} #t) :
    lift.{max v w} #(sᶜ : Set α) = lift.{max u w} #(tᶜ : Set β) := by
  

Proof state:
α : Type u
β : Type v
inst✝ : Finite α
s : Set α
t : Set β
h1 : lift.{max v w, u} #α = lift.{max u w, v} #β
h2 : lift.{max v w, u} #↑s = lift.{max u w, v} #↑t
⊢ lift.{max v w, u} #↑sᶜ = lift.{max u w, v} #↑tᶜ

Next tactic:
cases nonempty_fintype α
theorem mk_compl_eq_mk_compl_finite_lift {α : Type u} {β : Type v} [Finite α] {s : Set α}
    {t : Set β} (h1 : (lift.{max v w, u} #α) = (lift.{max u w, v} #β))
    (h2 : lift.{max v w, u} #s = lift.{max u w, v} #t) :
    lift.{max v w} #(sᶜ : Set α) = lift.{max u w} #(tᶜ : Set β) := by
  cases nonempty_fintype α
  

Proof state:
case intro
α : Type u
β : Type v
inst✝ : Finite α
s : Set α
t : Set β
h1 : lift.{max v w, u} #α = lift.{max u w, v} #β
h2 : lift.{max v w, u} #↑s = lift.{max u w, v} #↑t
val✝ : Fintype α
⊢ lift.{max v w, u} #↑sᶜ = lift.{max u w, v} #↑tᶜ

Next tactic:
rcases lift_mk_eq.{u, v, w}.1 h1 with ⟨e⟩
theorem mk_compl_eq_mk_compl_finite_lift {α : Type u} {β : Type v} [Finite α] {s : Set α}
    {t : Set β} (h1 : (lift.{max v w, u} #α) = (lift.{max u w, v} #β))
    (h2 : lift.{max v w, u} #s = lift.{max u w, v} #t) :
    lift.{max v w} #(sᶜ : Set α) = lift.{max u w} #(tᶜ : Set β) := by
  cases nonempty_fintype α
  rcases lift_mk_eq.{u, v, w}.1 h1 with ⟨e⟩; 

Proof state:
case intro.intro
α : Type u
β : Type v
inst✝ : Finite α
s : Set α
t : Set β
h1 : lift.{max v w, u} #α = lift.{max u w, v} #β
h2 : lift.{max v w, u} #↑s = lift.{max u w, v} #↑t
val✝ : Fintype α
e : α ≃ β
⊢ lift.{max v w, u} #↑sᶜ = lift.{max u w, v} #↑tᶜ

Next tactic:
letI : Fintype β := Fintype.ofEquiv α e
theorem mk_compl_eq_mk_compl_finite_lift {α : Type u} {β : Type v} [Finite α] {s : Set α}
    {t : Set β} (h1 : (lift.{max v w, u} #α) = (lift.{max u w, v} #β))
    (h2 : lift.{max v w, u} #s = lift.{max u w, v} #t) :
    lift.{max v w} #(sᶜ : Set α) = lift.{max u w} #(tᶜ : Set β) := by
  cases nonempty_fintype α
  rcases lift_mk_eq.{u, v, w}.1 h1 with ⟨e⟩; letI : Fintype β := Fintype.ofEquiv α e
  

Proof state:
case intro.intro
α : Type u
β : Type v
inst✝ : Finite α
s : Set α
t : Set β
h1 : lift.{max v w, u} #α = lift.{max u w, v} #β
h2 : lift.{max v w, u} #↑s = lift.{max u w, v} #↑t
val✝ : Fintype α
e : α ≃ β
this : Fintype β := Fintype.ofEquiv α e
⊢ lift.{max v w, u} #↑sᶜ = lift.{max u w, v} #↑tᶜ

Next tactic:
replace h1 : Fintype.card α = Fintype.card β := (Fintype.ofEquiv_card _).symm
theorem mk_compl_eq_mk_compl_finite_lift {α : Type u} {β : Type v} [Finite α] {s : Set α}
    {t : Set β} (h1 : (lift.{max v w, u} #α) = (lift.{max u w, v} #β))
    (h2 : lift.{max v w, u} #s = lift.{max u w, v} #t) :
    lift.{max v w} #(sᶜ : Set α) = lift.{max u w} #(tᶜ : Set β) := by
  cases nonempty_fintype α
  rcases lift_mk_eq.{u, v, w}.1 h1 with ⟨e⟩; letI : Fintype β := Fintype.ofEquiv α e
  replace h1 : Fintype.card α = Fintype.card β := (Fintype.ofEquiv_card _).symm
  

Proof state:
case intro.intro
α : Type u
β : Type v
inst✝ : Finite α
s : Set α
t : Set β
h2 : lift.{max v w, u} #↑s = lift.{max u w, v} #↑t
val✝ : Fintype α
e : α ≃ β
this : Fintype β := Fintype.ofEquiv α e
h1 : Fintype.card α = Fintype.card β
⊢ lift.{max v w, u} #↑sᶜ = lift.{max u w, v} #↑tᶜ

Next tactic:
classical
    lift s to Finset α using s.toFinite
    lift t to Finset β using t.toFinite
    simp only [Finset.coe_sort_coe, mk_fintype, Fintype.card_coe, lift_natCast, Nat.cast_inj] at h2
    simp only [← Finset.coe_compl, Finset.coe_sort_coe, mk_coe_finset, Finset.card_compl,
      lift_natCast, Nat.cast_inj, h1, h2]
theorem mk_compl_eq_mk_compl_finite_lift {α : Type u} {β : Type v} [Finite α] {s : Set α}
    {t : Set β} (h1 : (lift.{max v w, u} #α) = (lift.{max u w, v} #β))
    (h2 : lift.{max v w, u} #s = lift.{max u w, v} #t) :
    lift.{max v w} #(sᶜ : Set α) = lift.{max u w} #(tᶜ : Set β) := by
  cases nonempty_fintype α
  rcases lift_mk_eq.{u, v, w}.1 h1 with ⟨e⟩; letI : Fintype β := Fintype.ofEquiv α e
  replace h1 : Fintype.card α = Fintype.card β := (Fintype.ofEquiv_card _).symm
  classical
    

Proof state:
case intro.intro
α : Type u
β : Type v
inst✝ : Finite α
s : Set α
t : Set β
h2 : lift.{max v w, u} #↑s = lift.{max u w, v} #↑t
val✝ : Fintype α
e : α ≃ β
this : Fintype β := Fintype.ofEquiv α e
h1 : Fintype.card α = Fintype.card β
⊢ lift.{max v w, u} #↑sᶜ = lift.{max u w, v} #↑tᶜ

Next tactic:
lift s to Finset α using s.toFinite
theorem mk_compl_eq_mk_compl_finite_lift {α : Type u} {β : Type v} [Finite α] {s : Set α}
    {t : Set β} (h1 : (lift.{max v w, u} #α) = (lift.{max u w, v} #β))
    (h2 : lift.{max v w, u} #s = lift.{max u w, v} #t) :
    lift.{max v w} #(sᶜ : Set α) = lift.{max u w} #(tᶜ : Set β) := by
  cases nonempty_fintype α
  rcases lift_mk_eq.{u, v, w}.1 h1 with ⟨e⟩; letI : Fintype β := Fintype.ofEquiv α e
  replace h1 : Fintype.card α = Fintype.card β := (Fintype.ofEquiv_card _).symm
  classical
    lift s to Finset α using s.toFinite
    

Proof state:
case intro.intro.intro
α : Type u
β : Type v
inst✝ : Finite α
t : Set β
val✝ : Fintype α
e : α ≃ β
this : Fintype β := Fintype.ofEquiv α e
h1 : Fintype.card α = Fintype.card β
s : Finset α
h2 : lift.{max v w, u} #↑↑s = lift.{max u w, v} #↑t
⊢ lift.{max v w, u} #↑(↑s)ᶜ = lift.{max u w, v} #↑tᶜ

Next tactic:
lift t to Finset β using t.toFinite
theorem mk_compl_eq_mk_compl_finite_lift {α : Type u} {β : Type v} [Finite α] {s : Set α}
    {t : Set β} (h1 : (lift.{max v w, u} #α) = (lift.{max u w, v} #β))
    (h2 : lift.{max v w, u} #s = lift.{max u w, v} #t) :
    lift.{max v w} #(sᶜ : Set α) = lift.{max u w} #(tᶜ : Set β) := by
  cases nonempty_fintype α
  rcases lift_mk_eq.{u, v, w}.1 h1 with ⟨e⟩; letI : Fintype β := Fintype.ofEquiv α e
  replace h1 : Fintype.card α = Fintype.card β := (Fintype.ofEquiv_card _).symm
  classical
    lift s to Finset α using s.toFinite
    lift t to Finset β using t.toFinite
    

Proof state:
case intro.intro.intro.intro
α : Type u
β : Type v
inst✝ : Finite α
val✝ : Fintype α
e : α ≃ β
this : Fintype β := Fintype.ofEquiv α e
h1 : Fintype.card α = Fintype.card β
s : Finset α
t : Finset β
h2 : lift.{max v w, u} #↑↑s = lift.{max u w, v} #↑↑t
⊢ lift.{max v w, u} #↑(↑s)ᶜ = lift.{max u w, v} #↑(↑t)ᶜ

Next tactic:
simp only [Finset.coe_sort_coe, mk_fintype, Fintype.card_coe, lift_natCast, Nat.cast_inj] at h2
theorem mk_compl_eq_mk_compl_finite_lift {α : Type u} {β : Type v} [Finite α] {s : Set α}
    {t : Set β} (h1 : (lift.{max v w, u} #α) = (lift.{max u w, v} #β))
    (h2 : lift.{max v w, u} #s = lift.{max u w, v} #t) :
    lift.{max v w} #(sᶜ : Set α) = lift.{max u w} #(tᶜ : Set β) := by
  cases nonempty_fintype α
  rcases lift_mk_eq.{u, v, w}.1 h1 with ⟨e⟩; letI : Fintype β := Fintype.ofEquiv α e
  replace h1 : Fintype.card α = Fintype.card β := (Fintype.ofEquiv_card _).symm
  classical
    lift s to Finset α using s.toFinite
    lift t to Finset β using t.toFinite
    simp only [Finset.coe_sort_coe, mk_fintype, Fintype.card_coe, lift_natCast, Nat.cast_inj] at h2
    

Proof state:
case intro.intro.intro.intro
α : Type u
β : Type v
inst✝ : Finite α
val✝ : Fintype α
e : α ≃ β
this : Fintype β := Fintype.ofEquiv α e
h1 : Fintype.card α = Fintype.card β
s : Finset α
t : Finset β
h2 : Finset.card s = Finset.card t
⊢ lift.{max v w, u} #↑(↑s)ᶜ = lift.{max u w, v} #↑(↑t)ᶜ

Next tactic:
simp only [← Finset.coe_compl, Finset.coe_sort_coe, mk_coe_finset, Finset.card_compl,
      lift_natCast, Nat.cast_inj, h1, h2]
theorem mk_compl_eq_mk_compl_finite {α β : Type u} [Finite α] {s : Set α} {t : Set β}
    (h1 : #α = #β) (h : #s = #t) : #(sᶜ : Set α) = #(tᶜ : Set β) := by
  

Proof state:
α β : Type u
inst✝ : Finite α
s : Set α
t : Set β
h1 : #α = #β
h : #↑s = #↑t
⊢ #↑sᶜ = #↑tᶜ

Next tactic:
rw [← lift_inj.{u, max u v}]
theorem mk_compl_eq_mk_compl_finite {α β : Type u} [Finite α] {s : Set α} {t : Set β}
    (h1 : #α = #β) (h : #s = #t) : #(sᶜ : Set α) = #(tᶜ : Set β) := by
  rw [← lift_inj.{u, max u v}]
  

Proof state:
α β : Type u
inst✝ : Finite α
s : Set α
t : Set β
h1 : #α = #β
h : #↑s = #↑t
⊢ lift.{max u v, u} #↑sᶜ = lift.{max u v, u} #↑tᶜ

Next tactic:
apply mk_compl_eq_mk_compl_finite_lift.{u, u, max u v}
theorem mk_compl_eq_mk_compl_finite {α β : Type u} [Finite α] {s : Set α} {t : Set β}
    (h1 : #α = #β) (h : #s = #t) : #(sᶜ : Set α) = #(tᶜ : Set β) := by
  rw [← lift_inj.{u, max u v}]
  apply mk_compl_eq_mk_compl_finite_lift.{u, u, max u v}
  <;> 

Proof state:
case h1
α β : Type u
inst✝ : Finite α
s : Set α
t : Set β
h1 : #α = #β
h : #↑s = #↑t
⊢ lift.{max u v, u} #α = lift.{max u v, u} #β

Next tactic:
rwa [lift_inj]
theorem mk_compl_eq_mk_compl_finite {α β : Type u} [Finite α] {s : Set α} {t : Set β}
    (h1 : #α = #β) (h : #s = #t) : #(sᶜ : Set α) = #(tᶜ : Set β) := by
  rw [← lift_inj.{u, max u v}]
  apply mk_compl_eq_mk_compl_finite_lift.{u, u, max u v}
  <;> 

Proof state:
case h2
α β : Type u
inst✝ : Finite α
s : Set α
t : Set β
h1 : #α = #β
h : #↑s = #↑t
⊢ lift.{max u v, u} #↑s = lift.{max u v, u} #↑t

Next tactic:
rwa [lift_inj]
theorem extend_function {α β : Type*} {s : Set α} (f : s ↪ β)
    (h : Nonempty ((sᶜ : Set α) ≃ ((range f)ᶜ : Set β))) : ∃ g : α ≃ β, ∀ x : s, g x = f x := by
  

Proof state:
α : Type u_1
β : Type u_2
s : Set α
f : ↑s ↪ β
h : Nonempty (↑sᶜ ≃ ↑(range ⇑f)ᶜ)
⊢ ∃ g, ∀ (x : ↑s), g ↑x = f x

Next tactic:
intros
theorem extend_function {α β : Type*} {s : Set α} (f : s ↪ β)
    (h : Nonempty ((sᶜ : Set α) ≃ ((range f)ᶜ : Set β))) : ∃ g : α ≃ β, ∀ x : s, g x = f x := by
  intros; 

Proof state:
α : Type u_1
β : Type u_2
s : Set α
f : ↑s ↪ β
h : Nonempty (↑sᶜ ≃ ↑(range ⇑f)ᶜ)
⊢ ∃ g, ∀ (x : ↑s), g ↑x = f x

Next tactic:
have := h
theorem extend_function {α β : Type*} {s : Set α} (f : s ↪ β)
    (h : Nonempty ((sᶜ : Set α) ≃ ((range f)ᶜ : Set β))) : ∃ g : α ≃ β, ∀ x : s, g x = f x := by
  intros; have := h; 

Proof state:
α : Type u_1
β : Type u_2
s : Set α
f : ↑s ↪ β
h this : Nonempty (↑sᶜ ≃ ↑(range ⇑f)ᶜ)
⊢ ∃ g, ∀ (x : ↑s), g ↑x = f x

Next tactic:
cases' this with g
theorem extend_function {α β : Type*} {s : Set α} (f : s ↪ β)
    (h : Nonempty ((sᶜ : Set α) ≃ ((range f)ᶜ : Set β))) : ∃ g : α ≃ β, ∀ x : s, g x = f x := by
  intros; have := h; cases' this with g
  

Proof state:
case intro
α : Type u_1
β : Type u_2
s : Set α
f : ↑s ↪ β
h : Nonempty (↑sᶜ ≃ ↑(range ⇑f)ᶜ)
g : ↑sᶜ ≃ ↑(range ⇑f)ᶜ
⊢ ∃ g, ∀ (x : ↑s), g ↑x = f x

Next tactic:
let h : α ≃ β :=
    (Set.sumCompl (s : Set α)).symm.trans
      ((sumCongr (Equiv.ofInjective f f.2) g).trans (Set.sumCompl (range f)))
theorem extend_function {α β : Type*} {s : Set α} (f : s ↪ β)
    (h : Nonempty ((sᶜ : Set α) ≃ ((range f)ᶜ : Set β))) : ∃ g : α ≃ β, ∀ x : s, g x = f x := by
  intros; have := h; cases' this with g
  let h : α ≃ β :=
    (Set.sumCompl (s : Set α)).symm.trans
      ((sumCongr (Equiv.ofInjective f f.2) g).trans (Set.sumCompl (range f)))
  

Proof state:
case intro
α : Type u_1
β : Type u_2
s : Set α
f : ↑s ↪ β
h✝ : Nonempty (↑sᶜ ≃ ↑(range ⇑f)ᶜ)
g : ↑sᶜ ≃ ↑(range ⇑f)ᶜ
h : α ≃ β :=
  (Set.sumCompl s).symm.trans ((sumCongr (ofInjective ⇑f (_ : Injective f.toFun)) g).trans (Set.sumCompl (range ⇑f)))
⊢ ∃ g, ∀ (x : ↑s), g ↑x = f x

Next tactic:
refine' ⟨h, _⟩
theorem extend_function {α β : Type*} {s : Set α} (f : s ↪ β)
    (h : Nonempty ((sᶜ : Set α) ≃ ((range f)ᶜ : Set β))) : ∃ g : α ≃ β, ∀ x : s, g x = f x := by
  intros; have := h; cases' this with g
  let h : α ≃ β :=
    (Set.sumCompl (s : Set α)).symm.trans
      ((sumCongr (Equiv.ofInjective f f.2) g).trans (Set.sumCompl (range f)))
  refine' ⟨h, _⟩; 

Proof state:
case intro
α : Type u_1
β : Type u_2
s : Set α
f : ↑s ↪ β
h✝ : Nonempty (↑sᶜ ≃ ↑(range ⇑f)ᶜ)
g : ↑sᶜ ≃ ↑(range ⇑f)ᶜ
h : α ≃ β :=
  (Set.sumCompl s).symm.trans ((sumCongr (ofInjective ⇑f (_ : Injective f.toFun)) g).trans (Set.sumCompl (range ⇑f)))
⊢ ∀ (x : ↑s), h ↑x = f x

Next tactic:
rintro ⟨x, hx⟩
theorem extend_function {α β : Type*} {s : Set α} (f : s ↪ β)
    (h : Nonempty ((sᶜ : Set α) ≃ ((range f)ᶜ : Set β))) : ∃ g : α ≃ β, ∀ x : s, g x = f x := by
  intros; have := h; cases' this with g
  let h : α ≃ β :=
    (Set.sumCompl (s : Set α)).symm.trans
      ((sumCongr (Equiv.ofInjective f f.2) g).trans (Set.sumCompl (range f)))
  refine' ⟨h, _⟩; rintro ⟨x, hx⟩; 

Proof state:
case intro.mk
α : Type u_1
β : Type u_2
s : Set α
f : ↑s ↪ β
h✝ : Nonempty (↑sᶜ ≃ ↑(range ⇑f)ᶜ)
g : ↑sᶜ ≃ ↑(range ⇑f)ᶜ
h : α ≃ β :=
  (Set.sumCompl s).symm.trans ((sumCongr (ofInjective ⇑f (_ : Injective f.toFun)) g).trans (Set.sumCompl (range ⇑f)))
x : α
hx : x ∈ s
⊢ h ↑{ val := x, property := hx } = f { val := x, property := hx }

Next tactic:
simp [Set.sumCompl_symm_apply_of_mem, hx]
theorem extend_function_finite {α : Type u} {β : Type v} [Finite α] {s : Set α} (f : s ↪ β)
    (h : Nonempty (α ≃ β)) : ∃ g : α ≃ β, ∀ x : s, g x = f x := by
  

Proof state:
α : Type u
β : Type v
inst✝ : Finite α
s : Set α
f : ↑s ↪ β
h : Nonempty (α ≃ β)
⊢ ∃ g, ∀ (x : ↑s), g ↑x = f x

Next tactic:
apply extend_function.{v, u} f
theorem extend_function_finite {α : Type u} {β : Type v} [Finite α] {s : Set α} (f : s ↪ β)
    (h : Nonempty (α ≃ β)) : ∃ g : α ≃ β, ∀ x : s, g x = f x := by
  apply extend_function.{v, u} f
  

Proof state:
α : Type u
β : Type v
inst✝ : Finite α
s : Set α
f : ↑s ↪ β
h : Nonempty (α ≃ β)
⊢ Nonempty (↑sᶜ ≃ ↑(range ⇑f)ᶜ)

Next tactic:
cases' id h with g
theorem extend_function_finite {α : Type u} {β : Type v} [Finite α] {s : Set α} (f : s ↪ β)
    (h : Nonempty (α ≃ β)) : ∃ g : α ≃ β, ∀ x : s, g x = f x := by
  apply extend_function.{v, u} f
  cases' id h with g
  

Proof state:
case intro
α : Type u
β : Type v
inst✝ : Finite α
s : Set α
f : ↑s ↪ β
h : Nonempty (α ≃ β)
g : α ≃ β
⊢ Nonempty (↑sᶜ ≃ ↑(range ⇑f)ᶜ)

Next tactic:
rw [← lift_mk_eq.{u, v, max u v}] at h
theorem extend_function_finite {α : Type u} {β : Type v} [Finite α] {s : Set α} (f : s ↪ β)
    (h : Nonempty (α ≃ β)) : ∃ g : α ≃ β, ∀ x : s, g x = f x := by
  apply extend_function.{v, u} f
  cases' id h with g
  rw [← lift_mk_eq.{u, v, max u v}] at h
  

Proof state:
case intro
α : Type u
β : Type v
inst✝ : Finite α
s : Set α
f : ↑s ↪ β
h : lift.{max u v, u} #α = lift.{max u v, v} #β
g : α ≃ β
⊢ Nonempty (↑sᶜ ≃ ↑(range ⇑f)ᶜ)

Next tactic:
rw [← lift_mk_eq.{u, v, max u v}, mk_compl_eq_mk_compl_finite_lift.{u, v, max u v} h]