l3lab/ntp-mathlib huggingface dataset:
/-- Equivalence between embeddings of `Option α` and a sigma type over the embeddings of `α`. -/
@[simps]
def optionEmbeddingEquiv (α β) : (Option α ↪ β) ≃ Σ f : α ↪ β, ↥(Set.range f)ᶜ where
  toFun f := ⟨coeWithTop.trans f, f none, fun ⟨x, hx⟩ ↦ Option.some_ne_none x <| f.injective hx⟩
  invFun f := f.1.optionElim f.2 f.2.2
  left_inv f := ext <| by 

Proof state:
α : Type ?u.1294
β : Type ?u.1295
f : Option α ↪ β
⊢ ∀ (x : Option α),
    ((fun f => optionElim f.fst ↑f.snd (_ : ↑f.snd ∈ (Set.range ⇑f.fst)ᶜ))
          ((fun f =>
              { fst := Embedding.trans coeWithTop f,
                snd :=
                  { val := f none, property := (_ : f none ∈ Set.range ⇑(Embedding.trans coeWithTop f) → False) } })
            f))
        x =
      f x

Next tactic:
rintro (_ | _)
/-- Equivalence between embeddings of `Option α` and a sigma type over the embeddings of `α`. -/
@[simps]
def optionEmbeddingEquiv (α β) : (Option α ↪ β) ≃ Σ f : α ↪ β, ↥(Set.range f)ᶜ where
  toFun f := ⟨coeWithTop.trans f, f none, fun ⟨x, hx⟩ ↦ Option.some_ne_none x <| f.injective hx⟩
  invFun f := f.1.optionElim f.2 f.2.2
  left_inv f := ext <| by rintro (_ | _) <;> 

Proof state:
case none
α : Type ?u.1294
β : Type ?u.1295
f : Option α ↪ β
⊢ ((fun f => optionElim f.fst ↑f.snd (_ : ↑f.snd ∈ (Set.range ⇑f.fst)ᶜ))
        ((fun f =>
            { fst := Embedding.trans coeWithTop f,
              snd := { val := f none, property := (_ : f none ∈ Set.range ⇑(Embedding.trans coeWithTop f) → False) } })
          f))
      none =
    f none

Next tactic:
simp [Option.coe_def]
/-- Equivalence between embeddings of `Option α` and a sigma type over the embeddings of `α`. -/
@[simps]
def optionEmbeddingEquiv (α β) : (Option α ↪ β) ≃ Σ f : α ↪ β, ↥(Set.range f)ᶜ where
  toFun f := ⟨coeWithTop.trans f, f none, fun ⟨x, hx⟩ ↦ Option.some_ne_none x <| f.injective hx⟩
  invFun f := f.1.optionElim f.2 f.2.2
  left_inv f := ext <| by rintro (_ | _) <;> 

Proof state:
case some
α : Type ?u.1294
β : Type ?u.1295
f : Option α ↪ β
val✝ : α
⊢ ((fun f => optionElim f.fst ↑f.snd (_ : ↑f.snd ∈ (Set.range ⇑f.fst)ᶜ))
        ((fun f =>
            { fst := Embedding.trans coeWithTop f,
              snd := { val := f none, property := (_ : f none ∈ Set.range ⇑(Embedding.trans coeWithTop f) → False) } })
          f))
      (some val✝) =
    f (some val✝)

Next tactic:
simp [Option.coe_def]
/-- Equivalence between embeddings of `Option α` and a sigma type over the embeddings of `α`. -/
@[simps]
def optionEmbeddingEquiv (α β) : (Option α ↪ β) ≃ Σ f : α ↪ β, ↥(Set.range f)ᶜ where
  toFun f := ⟨coeWithTop.trans f, f none, fun ⟨x, hx⟩ ↦ Option.some_ne_none x <| f.injective hx⟩
  invFun f := f.1.optionElim f.2 f.2.2
  left_inv f := ext <| by rintro (_ | _) <;> simp [Option.coe_def]; 

Proof state:
case some
α : Type ?u.1294
β : Type ?u.1295
f : Option α ↪ β
val✝ : α
⊢ f ↑val✝ = f (some val✝)

Next tactic:
rfl
/-- Equivalence between embeddings of `Option α` and a sigma type over the embeddings of `α`. -/
@[simps]
def optionEmbeddingEquiv (α β) : (Option α ↪ β) ≃ Σ f : α ↪ β, ↥(Set.range f)ᶜ where
  toFun f := ⟨coeWithTop.trans f, f none, fun ⟨x, hx⟩ ↦ Option.some_ne_none x <| f.injective hx⟩
  invFun f := f.1.optionElim f.2 f.2.2
  left_inv f := ext <| by rintro (_ | _) <;> simp [Option.coe_def]; rfl
  right_inv := fun ⟨f, y, hy⟩ ↦ by 

Proof state:
α : Type ?u.1294
β : Type ?u.1295
x✝ : (f : α ↪ β) × ↑(Set.range ⇑f)ᶜ
f : α ↪ β
y : β
hy : y ∈ (Set.range ⇑f)ᶜ
⊢ (fun f =>
        { fst := Embedding.trans coeWithTop f,
          snd := { val := f none, property := (_ : f none ∈ Set.range ⇑(Embedding.trans coeWithTop f) → False) } })
      ((fun f => optionElim f.fst ↑f.snd (_ : ↑f.snd ∈ (Set.range ⇑f.fst)ᶜ))
        { fst := f, snd := { val := y, property := hy } }) =
    { fst := f, snd := { val := y, property := hy } }

Next tactic:
ext
/-- Equivalence between embeddings of `Option α` and a sigma type over the embeddings of `α`. -/
@[simps]
def optionEmbeddingEquiv (α β) : (Option α ↪ β) ≃ Σ f : α ↪ β, ↥(Set.range f)ᶜ where
  toFun f := ⟨coeWithTop.trans f, f none, fun ⟨x, hx⟩ ↦ Option.some_ne_none x <| f.injective hx⟩
  invFun f := f.1.optionElim f.2 f.2.2
  left_inv f := ext <| by rintro (_ | _) <;> simp [Option.coe_def]; rfl
  right_inv := fun ⟨f, y, hy⟩ ↦ by ext <;> 

Proof state:
case a.h
α : Type ?u.1294
β : Type ?u.1295
x✝¹ : (f : α ↪ β) × ↑(Set.range ⇑f)ᶜ
f : α ↪ β
y : β
hy : y ∈ (Set.range ⇑f)ᶜ
x✝ : α
⊢ ((fun f =>
            { fst := Embedding.trans coeWithTop f,
              snd := { val := f none, property := (_ : f none ∈ Set.range ⇑(Embedding.trans coeWithTop f) → False) } })
          ((fun f => optionElim f.fst ↑f.snd (_ : ↑f.snd ∈ (Set.range ⇑f.fst)ᶜ))
            { fst := f, snd := { val := y, property := hy } })).fst
      x✝ =
    { fst := f, snd := { val := y, property := hy } }.fst x✝

Next tactic:
simp [Option.coe_def]
/-- Equivalence between embeddings of `Option α` and a sigma type over the embeddings of `α`. -/
@[simps]
def optionEmbeddingEquiv (α β) : (Option α ↪ β) ≃ Σ f : α ↪ β, ↥(Set.range f)ᶜ where
  toFun f := ⟨coeWithTop.trans f, f none, fun ⟨x, hx⟩ ↦ Option.some_ne_none x <| f.injective hx⟩
  invFun f := f.1.optionElim f.2 f.2.2
  left_inv f := ext <| by rintro (_ | _) <;> simp [Option.coe_def]; rfl
  right_inv := fun ⟨f, y, hy⟩ ↦ by ext <;> 

Proof state:
case a
α : Type ?u.1294
β : Type ?u.1295
x✝ : (f : α ↪ β) × ↑(Set.range ⇑f)ᶜ
f : α ↪ β
y : β
hy : y ∈ (Set.range ⇑f)ᶜ
⊢ ↑((fun f =>
            { fst := Embedding.trans coeWithTop f,
              snd := { val := f none, property := (_ : f none ∈ Set.range ⇑(Embedding.trans coeWithTop f) → False) } })
          ((fun f => optionElim f.fst ↑f.snd (_ : ↑f.snd ∈ (Set.range ⇑f.fst)ᶜ))
            { fst := f, snd := { val := y, property := hy } })).snd =
    ↑{ fst := f, snd := { val := y, property := hy } }.snd

Next tactic:
simp [Option.coe_def]
/-- Equivalence between embeddings of `Option α` and a sigma type over the embeddings of `α`. -/
@[simps]
def optionEmbeddingEquiv (α β) : (Option α ↪ β) ≃ Σ f : α ↪ β, ↥(Set.range f)ᶜ where
  toFun f := ⟨coeWithTop.trans f, f none, fun ⟨x, hx⟩ ↦ Option.some_ne_none x <| f.injective hx⟩
  invFun f := f.1.optionElim f.2 f.2.2
  left_inv f := ext <| by rintro (_ | _) <;> simp [Option.coe_def]; rfl
  right_inv := fun ⟨f, y, hy⟩ ↦ by ext <;> simp [Option.coe_def]; 

Proof state:
case a.h
α : Type ?u.1294
β : Type ?u.1295
x✝¹ : (f : α ↪ β) × ↑(Set.range ⇑f)ᶜ
f : α ↪ β
y : β
hy : y ∈ (Set.range ⇑f)ᶜ
x✝ : α
⊢ (optionElim f y
        (_ :
          ↑{ fst := f, snd := { val := y, property := hy } }.snd ∈
            (Set.range ⇑{ fst := f, snd := { val := y, property := hy } }.fst)ᶜ))
      ↑x✝ =
    f x✝

Next tactic:
rfl
/-- The injection map is an embedding between subsets. -/
@[simps apply]
def embeddingOfSubset {α} (s t : Set α) (h : s ⊆ t) : s ↪ t :=
  ⟨fun x ↦ ⟨x.1, h x.2⟩, fun ⟨x, hx⟩ ⟨y, hy⟩ h ↦ by
    

Proof state:
α : Type ?u.4584
s t : Set α
h✝ : s ⊆ t
x✝¹ x✝ : ↑s
x : α
hx : x ∈ s
y : α
hy : y ∈ s
h :
  (fun x => { val := ↑x, property := (_ : ↑x ∈ t) }) { val := x, property := hx } =
    (fun x => { val := ↑x, property := (_ : ↑x ∈ t) }) { val := y, property := hy }
⊢ { val := x, property := hx } = { val := y, property := hy }

Next tactic:
congr
/-- The injection map is an embedding between subsets. -/
@[simps apply]
def embeddingOfSubset {α} (s t : Set α) (h : s ⊆ t) : s ↪ t :=
  ⟨fun x ↦ ⟨x.1, h x.2⟩, fun ⟨x, hx⟩ ⟨y, hy⟩ h ↦ by
    congr
    

Proof state:
case e_val
α : Type ?u.4584
s t : Set α
h✝ : s ⊆ t
x✝¹ x✝ : ↑s
x : α
hx : x ∈ s
y : α
hy : y ∈ s
h :
  (fun x => { val := ↑x, property := (_ : ↑x ∈ t) }) { val := x, property := hx } =
    (fun x => { val := ↑x, property := (_ : ↑x ∈ t) }) { val := y, property := hy }
⊢ x = y

Next tactic:
injection h
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    

Proof state:
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // p x ∨ q x }
⊢ Sum.elim (⇑(Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)))
      (⇑(Subtype.impEmbedding (fun x => q x) (fun x => p x ∨ q x) (_ : ∀ (x : α), q x → p x ∨ q x)))
      ((subtypeOrLeftEmbedding p q) x) =
    x

Next tactic:
by_cases hx : p x
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    by_cases hx : p x
    · 

Proof state:
case pos
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // p x ∨ q x }
hx : p ↑x
⊢ Sum.elim (⇑(Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)))
      (⇑(Subtype.impEmbedding (fun x => q x) (fun x => p x ∨ q x) (_ : ∀ (x : α), q x → p x ∨ q x)))
      ((subtypeOrLeftEmbedding p q) x) =
    x

Next tactic:
rw [subtypeOrLeftEmbedding_apply_left _ hx]
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    by_cases hx : p x
    · rw [subtypeOrLeftEmbedding_apply_left _ hx]
      

Proof state:
case pos
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // p x ∨ q x }
hx : p ↑x
⊢ Sum.elim (⇑(Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)))
      (⇑(Subtype.impEmbedding (fun x => q x) (fun x => p x ∨ q x) (_ : ∀ (x : α), q x → p x ∨ q x)))
      (Sum.inl { val := ↑x, property := hx }) =
    x

Next tactic:
simp [Subtype.ext_iff]
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    by_cases hx : p x
    · rw [subtypeOrLeftEmbedding_apply_left _ hx]
      simp [Subtype.ext_iff]
    · 

Proof state:
case neg
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // p x ∨ q x }
hx : ¬p ↑x
⊢ Sum.elim (⇑(Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)))
      (⇑(Subtype.impEmbedding (fun x => q x) (fun x => p x ∨ q x) (_ : ∀ (x : α), q x → p x ∨ q x)))
      ((subtypeOrLeftEmbedding p q) x) =
    x

Next tactic:
rw [subtypeOrLeftEmbedding_apply_right _ hx]
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    by_cases hx : p x
    · rw [subtypeOrLeftEmbedding_apply_left _ hx]
      simp [Subtype.ext_iff]
    · rw [subtypeOrLeftEmbedding_apply_right _ hx]
      

Proof state:
case neg
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // p x ∨ q x }
hx : ¬p ↑x
⊢ Sum.elim (⇑(Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)))
      (⇑(Subtype.impEmbedding (fun x => q x) (fun x => p x ∨ q x) (_ : ∀ (x : α), q x → p x ∨ q x)))
      (Sum.inr { val := ↑x, property := (_ : q ↑x) }) =
    x

Next tactic:
simp [Subtype.ext_iff]
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    by_cases hx : p x
    · rw [subtypeOrLeftEmbedding_apply_left _ hx]
      simp [Subtype.ext_iff]
    · rw [subtypeOrLeftEmbedding_apply_right _ hx]
      simp [Subtype.ext_iff]
  right_inv x := by
    

Proof state:
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // p x } ⊕ { x // q x }
⊢ (subtypeOrLeftEmbedding p q)
      (Sum.elim (⇑(Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)))
        (⇑(Subtype.impEmbedding (fun x => q x) (fun x => p x ∨ q x) (_ : ∀ (x : α), q x → p x ∨ q x))) x) =
    x

Next tactic:
cases x with
    | inl x =>
        simp only [Sum.elim_inl]
        rw [subtypeOrLeftEmbedding_apply_left]
        · simp
        · simpa using x.prop
    | inr x =>
        simp only [Sum.elim_inr]
        rw [subtypeOrLeftEmbedding_apply_right]
        · simp
        · suffices ¬p x by simpa
          intro hp
          simpa using h.le_bot x ⟨hp, x.prop⟩
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    by_cases hx : p x
    · rw [subtypeOrLeftEmbedding_apply_left _ hx]
      simp [Subtype.ext_iff]
    · rw [subtypeOrLeftEmbedding_apply_right _ hx]
      simp [Subtype.ext_iff]
  right_inv x := by
    cases x with
    

Proof state:
case inl
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // p x }
⊢ (subtypeOrLeftEmbedding p q)
      (Sum.elim (⇑(Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)))
        (⇑(Subtype.impEmbedding (fun x => q x) (fun x => p x ∨ q x) (_ : ∀ (x : α), q x → p x ∨ q x))) (Sum.inl x)) =
    Sum.inl x

Next tactic:
| inl x =>
        simp only [Sum.elim_inl]
        rw [subtypeOrLeftEmbedding_apply_left]
        · simp
        · simpa using x.prop
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    by_cases hx : p x
    · rw [subtypeOrLeftEmbedding_apply_left _ hx]
      simp [Subtype.ext_iff]
    · rw [subtypeOrLeftEmbedding_apply_right _ hx]
      simp [Subtype.ext_iff]
  right_inv x := by
    cases x with
    | inl x =>
        

Proof state:
case inl
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // p x }
⊢ (subtypeOrLeftEmbedding p q)
      (Sum.elim (⇑(Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)))
        (⇑(Subtype.impEmbedding (fun x => q x) (fun x => p x ∨ q x) (_ : ∀ (x : α), q x → p x ∨ q x))) (Sum.inl x)) =
    Sum.inl x

Next tactic:
simp only [Sum.elim_inl]
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    by_cases hx : p x
    · rw [subtypeOrLeftEmbedding_apply_left _ hx]
      simp [Subtype.ext_iff]
    · rw [subtypeOrLeftEmbedding_apply_right _ hx]
      simp [Subtype.ext_iff]
  right_inv x := by
    cases x with
    | inl x =>
        simp only [Sum.elim_inl]
        

Proof state:
case inl
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // p x }
⊢ (subtypeOrLeftEmbedding p q)
      ((Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)) x) =
    Sum.inl x

Next tactic:
rw [subtypeOrLeftEmbedding_apply_left]
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    by_cases hx : p x
    · rw [subtypeOrLeftEmbedding_apply_left _ hx]
      simp [Subtype.ext_iff]
    · rw [subtypeOrLeftEmbedding_apply_right _ hx]
      simp [Subtype.ext_iff]
  right_inv x := by
    cases x with
    | inl x =>
        simp only [Sum.elim_inl]
        rw [subtypeOrLeftEmbedding_apply_left]
        · 

Proof state:
case inl
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // p x }
⊢ Sum.inl
      { val := ↑((Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)) x),
        property := ?inl.hx } =
    Sum.inl x

Next tactic:
simp
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    by_cases hx : p x
    · rw [subtypeOrLeftEmbedding_apply_left _ hx]
      simp [Subtype.ext_iff]
    · rw [subtypeOrLeftEmbedding_apply_right _ hx]
      simp [Subtype.ext_iff]
  right_inv x := by
    cases x with
    | inl x =>
        simp only [Sum.elim_inl]
        rw [subtypeOrLeftEmbedding_apply_left]
        · simp
        · 

Proof state:
case inl.hx
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // p x }
⊢ p ↑((Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)) x)

Next tactic:
simpa using x.prop
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    by_cases hx : p x
    · rw [subtypeOrLeftEmbedding_apply_left _ hx]
      simp [Subtype.ext_iff]
    · rw [subtypeOrLeftEmbedding_apply_right _ hx]
      simp [Subtype.ext_iff]
  right_inv x := by
    cases x with
    | inl x =>
        simp only [Sum.elim_inl]
        rw [subtypeOrLeftEmbedding_apply_left]
        · simp
        · simpa using x.prop
    

Proof state:
case inr
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // q x }
⊢ (subtypeOrLeftEmbedding p q)
      (Sum.elim (⇑(Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)))
        (⇑(Subtype.impEmbedding (fun x => q x) (fun x => p x ∨ q x) (_ : ∀ (x : α), q x → p x ∨ q x))) (Sum.inr x)) =
    Sum.inr x

Next tactic:
| inr x =>
        simp only [Sum.elim_inr]
        rw [subtypeOrLeftEmbedding_apply_right]
        · simp
        · suffices ¬p x by simpa
          intro hp
          simpa using h.le_bot x ⟨hp, x.prop⟩
/-- A subtype `{x // p x ∨ q x}` over a disjunction of `p q : α → Prop` is equivalent to a sum of
subtypes `{x // p x} ⊕ {x // q x}` such that `¬ p x` is sent to the right, when
`Disjoint p q`.

See also `Equiv.sumCompl`, for when `IsCompl p q`.  -/
@[simps apply]
def subtypeOrEquiv (p q : α → Prop) [DecidablePred p] (h : Disjoint p q) :
    { x // p x ∨ q x } ≃ { x // p x } ⊕ { x // q x } where
  toFun := subtypeOrLeftEmbedding p q
  invFun :=
    Sum.elim (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inl hx : p x ∨ q x))
      (Subtype.impEmbedding _ _ fun x hx ↦ (Or.inr hx : p x ∨ q x))
  left_inv x := by
    by_cases hx : p x
    · rw [subtypeOrLeftEmbedding_apply_left _ hx]
      simp [Subtype.ext_iff]
    · rw [subtypeOrLeftEmbedding_apply_right _ hx]
      simp [Subtype.ext_iff]
  right_inv x := by
    cases x with
    | inl x =>
        simp only [Sum.elim_inl]
        rw [subtypeOrLeftEmbedding_apply_left]
        · simp
        · simpa using x.prop
    | inr x =>
        

Proof state:
case inr
α : Type u_1
p q : α → Prop
inst✝ : DecidablePred p
h : Disjoint p q
x : { x // q x }
⊢ (subtypeOrLeftEmbedding p q)
      (Sum.elim (⇑(Subtype.impEmbedding (fun x => p x) (fun x => p x ∨ q x) (_ : ∀ (x : α), p x → p x ∨ q x)))
        (⇑(Subtype.impEmbedding (fun x => q x) (fun x => p x ∨ q x) (_ : ∀ (x : α), q x → p x ∨ q x))) (Sum.inr x)) =
    Sum.inr x

Next tactic:
simp only [Sum.elim_inr]