l3lab/ntp-mathlib huggingface dataset:
/-- Pull back a right dual along an equivalence. -/
def hasRightDualOfEquivalence [IsEquivalence F.toFunctor] (X : C) [HasRightDual (F.obj X)] :
    HasRightDual X where
  rightDual := F.toFunctor.inv.obj ((F.obj X)ᘁ)
  exact := by
    refine @exactPairingOfFullyFaithful _ _ _ _ _ _ F _ _ _ _ ?_
    refine @exactPairingCongrRight _ _ _ _ _ _ ?_ (F.toFunctor.asEquivalence.counitIso.app _)
    

Proof state:
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{?u.34458, u_1} C
inst✝⁴ : Category.{?u.34462, u_2} D
inst✝³ : MonoidalCategory C
inst✝² : MonoidalCategory D
F : MonoidalFunctor C D
inst✝¹ : IsEquivalence F.toFunctor
X : C
inst✝ : HasRightDual (F.obj X)
⊢ ExactPairing (F.obj X) ((𝟭 D).obj (F.obj X)ᘁ)

Next tactic:
dsimp
/-- Pull back a right dual along an equivalence. -/
def hasRightDualOfEquivalence [IsEquivalence F.toFunctor] (X : C) [HasRightDual (F.obj X)] :
    HasRightDual X where
  rightDual := F.toFunctor.inv.obj ((F.obj X)ᘁ)
  exact := by
    refine @exactPairingOfFullyFaithful _ _ _ _ _ _ F _ _ _ _ ?_
    refine @exactPairingCongrRight _ _ _ _ _ _ ?_ (F.toFunctor.asEquivalence.counitIso.app _)
    dsimp
    

Proof state:
C : Type u_1
D : Type u_2
inst✝⁵ : Category.{?u.34458, u_1} C
inst✝⁴ : Category.{?u.34462, u_2} D
inst✝³ : MonoidalCategory C
inst✝² : MonoidalCategory D
F : MonoidalFunctor C D
inst✝¹ : IsEquivalence F.toFunctor
X : C
inst✝ : HasRightDual (F.obj X)
⊢ ExactPairing (F.obj X) (F.obj X)ᘁ

Next tactic:
infer_instance
/-- This can be use to prove
```lean
example (P : Matrix (Fin 2) (Fin 3) α → Prop) :
  (∀ x, P x) ↔ ∀ a b c d e f, P !![a, b, c; d, e, f] :=
(forall_iff _).symm
```
-/
theorem forall_iff : ∀ {m n} (P : Matrix (Fin m) (Fin n) α → Prop), Forall P ↔ ∀ x, P x
  | 0, n, P => Iff.symm Fin.forall_fin_zero_pi
  | m + 1, n, P => by
    

Proof state:
l m✝ n✝ : ℕ
α : Type u_1
β : Type u_2
m n : ℕ
P : Matrix (Fin (m + 1)) (Fin n) α → Prop
⊢ Forall P ↔ ∀ (x : Matrix (Fin (m + 1)) (Fin n) α), P x

Next tactic:
simp only [Forall, FinVec.forall_iff, forall_iff]
/-- This can be use to prove
```lean
example (P : Matrix (Fin 2) (Fin 3) α → Prop) :
  (∀ x, P x) ↔ ∀ a b c d e f, P !![a, b, c; d, e, f] :=
(forall_iff _).symm
```
-/
theorem forall_iff : ∀ {m n} (P : Matrix (Fin m) (Fin n) α → Prop), Forall P ↔ ∀ x, P x
  | 0, n, P => Iff.symm Fin.forall_fin_zero_pi
  | m + 1, n, P => by
    simp only [Forall, FinVec.forall_iff, forall_iff]
    

Proof state:
l m✝ n✝ : ℕ
α : Type u_1
β : Type u_2
m n : ℕ
P : Matrix (Fin (m + 1)) (Fin n) α → Prop
⊢ (∀ (x : Fin n → α) (x_1 : Matrix (Fin (Nat.add m 0)) (Fin n) α), P (of (vecCons x x_1))) ↔
    ∀ (x : Matrix (Fin (m + 1)) (Fin n) α), P x

Next tactic:
exact Iff.symm Fin.forall_fin_succ_pi
/-- This can be use to prove
```lean
example (P : Matrix (Fin 2) (Fin 3) α → Prop) :
  (∃ x, P x) ↔ ∃ a b c d e f, P !![a, b, c; d, e, f] :=
(exists_iff _).symm
```
-/
theorem exists_iff : ∀ {m n} (P : Matrix (Fin m) (Fin n) α → Prop), Exists P ↔ ∃ x, P x
  | 0, n, P => Iff.symm Fin.exists_fin_zero_pi
  | m + 1, n, P => by
    

Proof state:
l m✝ n✝ : ℕ
α : Type u_1
β : Type u_2
m n : ℕ
P : Matrix (Fin (m + 1)) (Fin n) α → Prop
⊢ Exists P ↔ ∃ x, P x

Next tactic:
simp only [Exists, FinVec.exists_iff, exists_iff]
/-- This can be use to prove
```lean
example (P : Matrix (Fin 2) (Fin 3) α → Prop) :
  (∃ x, P x) ↔ ∃ a b c d e f, P !![a, b, c; d, e, f] :=
(exists_iff _).symm
```
-/
theorem exists_iff : ∀ {m n} (P : Matrix (Fin m) (Fin n) α → Prop), Exists P ↔ ∃ x, P x
  | 0, n, P => Iff.symm Fin.exists_fin_zero_pi
  | m + 1, n, P => by
    simp only [Exists, FinVec.exists_iff, exists_iff]
    

Proof state:
l m✝ n✝ : ℕ
α : Type u_1
β : Type u_2
m n : ℕ
P : Matrix (Fin (m + 1)) (Fin n) α → Prop
⊢ (∃ x A, P (of (vecCons x A))) ↔ ∃ x, P x

Next tactic:
exact Iff.symm Fin.exists_fin_succ_pi
/-- This can be used to prove
```lean
example (a b c d : α) : transpose !![a, b; c, d] = !![a, c; b, d] := (transposeᵣ_eq _).symm
```
-/
@[simp]
theorem transposeᵣ_eq : ∀ {m n} (A : Matrix (Fin m) (Fin n) α), transposeᵣ A = transpose A
  | _, 0, A => Subsingleton.elim _ _
  | m, n + 1, A =>
    Matrix.ext fun i j => by
      

Proof state:
l m✝ n✝ : ℕ
α : Type u_1
β : Type u_2
m n : ℕ
A : Matrix (Fin m) (Fin (n + 1)) α
i : Fin (n + 1)
j : Fin m
⊢ transposeᵣ A i j = Aᵀ i j

Next tactic:
simp_rw [transposeᵣ, transposeᵣ_eq]
/-- This can be used to prove
```lean
example (a b c d : α) : transpose !![a, b; c, d] = !![a, c; b, d] := (transposeᵣ_eq _).symm
```
-/
@[simp]
theorem transposeᵣ_eq : ∀ {m n} (A : Matrix (Fin m) (Fin n) α), transposeᵣ A = transpose A
  | _, 0, A => Subsingleton.elim _ _
  | m, n + 1, A =>
    Matrix.ext fun i j => by
      simp_rw [transposeᵣ, transposeᵣ_eq]
      

Proof state:
l m✝ n✝ : ℕ
α : Type u_1
β : Type u_2
m n : ℕ
A : Matrix (Fin m) (Fin (n + 1)) α
i : Fin (n + 1)
j : Fin m
⊢ of (vecCons (FinVec.map (fun v => v 0) A) (submatrix A id Fin.succ)ᵀ) i j = Aᵀ i j

Next tactic:
refine' i.cases _ fun i => _
/-- This can be used to prove
```lean
example (a b c d : α) : transpose !![a, b; c, d] = !![a, c; b, d] := (transposeᵣ_eq _).symm
```
-/
@[simp]
theorem transposeᵣ_eq : ∀ {m n} (A : Matrix (Fin m) (Fin n) α), transposeᵣ A = transpose A
  | _, 0, A => Subsingleton.elim _ _
  | m, n + 1, A =>
    Matrix.ext fun i j => by
      simp_rw [transposeᵣ, transposeᵣ_eq]
      refine' i.cases _ fun i => _
      · 

Proof state:
case refine'_1
l m✝ n✝ : ℕ
α : Type u_1
β : Type u_2
m n : ℕ
A : Matrix (Fin m) (Fin (n + 1)) α
i : Fin (n + 1)
j : Fin m
⊢ of (vecCons (FinVec.map (fun v => v 0) A) (submatrix A id Fin.succ)ᵀ) 0 j = Aᵀ 0 j

Next tactic:
dsimp
/-- This can be used to prove
```lean
example (a b c d : α) : transpose !![a, b; c, d] = !![a, c; b, d] := (transposeᵣ_eq _).symm
```
-/
@[simp]
theorem transposeᵣ_eq : ∀ {m n} (A : Matrix (Fin m) (Fin n) α), transposeᵣ A = transpose A
  | _, 0, A => Subsingleton.elim _ _
  | m, n + 1, A =>
    Matrix.ext fun i j => by
      simp_rw [transposeᵣ, transposeᵣ_eq]
      refine' i.cases _ fun i => _
      · dsimp
        

Proof state:
case refine'_1
l m✝ n✝ : ℕ
α : Type u_1
β : Type u_2
m n : ℕ
A : Matrix (Fin m) (Fin (n + 1)) α
i : Fin (n + 1)
j : Fin m
⊢ FinVec.map (fun v => v 0) A j = A j 0

Next tactic:
rw [FinVec.map_eq, Function.comp_apply]
/-- This can be used to prove
```lean
example (a b c d : α) : transpose !![a, b; c, d] = !![a, c; b, d] := (transposeᵣ_eq _).symm
```
-/
@[simp]
theorem transposeᵣ_eq : ∀ {m n} (A : Matrix (Fin m) (Fin n) α), transposeᵣ A = transpose A
  | _, 0, A => Subsingleton.elim _ _
  | m, n + 1, A =>
    Matrix.ext fun i j => by
      simp_rw [transposeᵣ, transposeᵣ_eq]
      refine' i.cases _ fun i => _
      · dsimp
        rw [FinVec.map_eq, Function.comp_apply]
      · 

Proof state:
case refine'_2
l m✝ n✝ : ℕ
α : Type u_1
β : Type u_2
m n : ℕ
A : Matrix (Fin m) (Fin (n + 1)) α
i✝ : Fin (n + 1)
j : Fin m
i : Fin n
⊢ of (vecCons (FinVec.map (fun v => v 0) A) (submatrix A id Fin.succ)ᵀ) (Fin.succ i) j = Aᵀ (Fin.succ i) j

Next tactic:
simp only [of_apply, Matrix.cons_val_succ]
/-- This can be used to prove
```lean
example (a b c d : α) : transpose !![a, b; c, d] = !![a, c; b, d] := (transposeᵣ_eq _).symm
```
-/
@[simp]
theorem transposeᵣ_eq : ∀ {m n} (A : Matrix (Fin m) (Fin n) α), transposeᵣ A = transpose A
  | _, 0, A => Subsingleton.elim _ _
  | m, n + 1, A =>
    Matrix.ext fun i j => by
      simp_rw [transposeᵣ, transposeᵣ_eq]
      refine' i.cases _ fun i => _
      · dsimp
        rw [FinVec.map_eq, Function.comp_apply]
      · simp only [of_apply, Matrix.cons_val_succ]
        

Proof state:
case refine'_2
l m✝ n✝ : ℕ
α : Type u_1
β : Type u_2
m n : ℕ
A : Matrix (Fin m) (Fin (n + 1)) α
i✝ : Fin (n + 1)
j : Fin m
i : Fin n
⊢ (submatrix A id Fin.succ)ᵀ i j = Aᵀ (Fin.succ i) j

Next tactic:
rfl
/-- This can be used to prove
```lean
example (a b c d : α) [Mul α] [AddCommMonoid α] :
  dot_product ![a, b] ![c, d] = a * c + b * d :=
(dot_productᵣ_eq _ _).symm
```
-/
@[simp]
theorem dotProductᵣ_eq [Mul α] [AddCommMonoid α] {m} (a b : Fin m → α) :
    dotProductᵣ a b = dotProduct a b := by
  

Proof state:
l m✝ n : ℕ
α : Type u_1
β : Type u_2
inst✝¹ : Mul α
inst✝ : AddCommMonoid α
m : ℕ
a b : Fin m → α
⊢ dotProductᵣ a b = a ⬝ᵥ b

Next tactic:
simp_rw [dotProductᵣ, dotProduct, FinVec.sum_eq, FinVec.seq_eq, FinVec.map_eq,
      Function.comp_apply]
/-- This can be used to prove
```lean
example [AddCommMonoid α] [Mul α] (a₁₁ a₁₂ a₂₁ a₂₂ b₁₁ b₁₂ b₂₁ b₂₂ : α) :
  !![a₁₁, a₁₂;
     a₂₁, a₂₂] * !![b₁₁, b₁₂;
                    b₂₁, b₂₂] =
  !![a₁₁*b₁₁ + a₁₂*b₂₁, a₁₁*b₁₂ + a₁₂*b₂₂;
     a₂₁*b₁₁ + a₂₂*b₂₁, a₂₁*b₁₂ + a₂₂*b₂₂] :=
(mulᵣ_eq _ _).symm
```
-/
@[simp]
theorem mulᵣ_eq [Mul α] [AddCommMonoid α] (A : Matrix (Fin l) (Fin m) α)
    (B : Matrix (Fin m) (Fin n) α) : mulᵣ A B = A * B := by
  

Proof state:
l m n : ℕ
α : Type u_1
β : Type u_2
inst✝¹ : Mul α
inst✝ : AddCommMonoid α
A : Matrix (Fin l) (Fin m) α
B : Matrix (Fin m) (Fin n) α
⊢ mulᵣ A B = A * B

Next tactic:
simp [mulᵣ, Function.comp, Matrix.transpose]
/-- This can be used to prove
```lean
example [AddCommMonoid α] [Mul α] (a₁₁ a₁₂ a₂₁ a₂₂ b₁₁ b₁₂ b₂₁ b₂₂ : α) :
  !![a₁₁, a₁₂;
     a₂₁, a₂₂] * !![b₁₁, b₁₂;
                    b₂₁, b₂₂] =
  !![a₁₁*b₁₁ + a₁₂*b₂₁, a₁₁*b₁₂ + a₁₂*b₂₂;
     a₂₁*b₁₁ + a₂₂*b₂₁, a₂₁*b₁₂ + a₂₂*b₂₂] :=
(mulᵣ_eq _ _).symm
```
-/
@[simp]
theorem mulᵣ_eq [Mul α] [AddCommMonoid α] (A : Matrix (Fin l) (Fin m) α)
    (B : Matrix (Fin m) (Fin n) α) : mulᵣ A B = A * B := by
  simp [mulᵣ, Function.comp, Matrix.transpose]
  

Proof state:
l m n : ℕ
α : Type u_1
β : Type u_2
inst✝¹ : Mul α
inst✝ : AddCommMonoid α
A : Matrix (Fin l) (Fin m) α
B : Matrix (Fin m) (Fin n) α
⊢ (of fun x x_1 => A x ⬝ᵥ of (fun x y => B y x) x_1) = A * B

Next tactic:
rfl
/-- This can be used to prove
```lean
example [NonUnitalNonAssocSemiring α] (a₁₁ a₁₂ a₂₁ a₂₂ b₁ b₂ : α) :
  !![a₁₁, a₁₂;
     a₂₁, a₂₂].mulVec ![b₁, b₂] = ![a₁₁*b₁ + a₁₂*b₂, a₂₁*b₁ + a₂₂*b₂] :=
(mulVecᵣ_eq _ _).symm
```
-/
@[simp]
theorem mulVecᵣ_eq [NonUnitalNonAssocSemiring α] (A : Matrix (Fin l) (Fin m) α) (v : Fin m → α) :
    mulVecᵣ A v = A.mulVec v := by
  

Proof state:
l m n : ℕ
α : Type u_1
β : Type u_2
inst✝ : NonUnitalNonAssocSemiring α
A : Matrix (Fin l) (Fin m) α
v : Fin m → α
⊢ mulVecᵣ A v = mulVec A v

Next tactic:
simp [mulVecᵣ, Function.comp]
/-- This can be used to prove
```lean
example [NonUnitalNonAssocSemiring α] (a₁₁ a₁₂ a₂₁ a₂₂ b₁ b₂ : α) :
  !![a₁₁, a₁₂;
     a₂₁, a₂₂].mulVec ![b₁, b₂] = ![a₁₁*b₁ + a₁₂*b₂, a₂₁*b₁ + a₂₂*b₂] :=
(mulVecᵣ_eq _ _).symm
```
-/
@[simp]
theorem mulVecᵣ_eq [NonUnitalNonAssocSemiring α] (A : Matrix (Fin l) (Fin m) α) (v : Fin m → α) :
    mulVecᵣ A v = A.mulVec v := by
  simp [mulVecᵣ, Function.comp]
  

Proof state:
l m n : ℕ
α : Type u_1
β : Type u_2
inst✝ : NonUnitalNonAssocSemiring α
A : Matrix (Fin l) (Fin m) α
v : Fin m → α
⊢ (fun x => A x ⬝ᵥ v) = mulVec A v

Next tactic:
rfl
/-- This can be used to prove
```lean
example [NonUnitalNonAssocSemiring α] (a₁₁ a₁₂ a₂₁ a₂₂ b₁ b₂ : α) :
  vecMul ![b₁, b₂] !![a₁₁, a₁₂;
                       a₂₁, a₂₂] = ![b₁*a₁₁ + b₂*a₂₁, b₁*a₁₂ + b₂*a₂₂] :=
(vecMulᵣ_eq _ _).symm
```
-/
@[simp]
theorem vecMulᵣ_eq [NonUnitalNonAssocSemiring α] (v : Fin l → α) (A : Matrix (Fin l) (Fin m) α) :
    vecMulᵣ v A = vecMul v A := by
  

Proof state:
l m n : ℕ
α : Type u_1
β : Type u_2
inst✝ : NonUnitalNonAssocSemiring α
v : Fin l → α
A : Matrix (Fin l) (Fin m) α
⊢ vecMulᵣ v A = vecMul v A

Next tactic:
simp [vecMulᵣ, Function.comp]
/-- This can be used to prove
```lean
example [NonUnitalNonAssocSemiring α] (a₁₁ a₁₂ a₂₁ a₂₂ b₁ b₂ : α) :
  vecMul ![b₁, b₂] !![a₁₁, a₁₂;
                       a₂₁, a₂₂] = ![b₁*a₁₁ + b₂*a₂₁, b₁*a₁₂ + b₂*a₂₂] :=
(vecMulᵣ_eq _ _).symm
```
-/
@[simp]
theorem vecMulᵣ_eq [NonUnitalNonAssocSemiring α] (v : Fin l → α) (A : Matrix (Fin l) (Fin m) α) :
    vecMulᵣ v A = vecMul v A := by
  simp [vecMulᵣ, Function.comp]
  

Proof state:
l m n : ℕ
α : Type u_1
β : Type u_2
inst✝ : NonUnitalNonAssocSemiring α
v : Fin l → α
A : Matrix (Fin l) (Fin m) α
⊢ (fun x => v ⬝ᵥ Aᵀ x) = vecMul v A

Next tactic:
rfl
/-- This can be used to prove
```lean
example (A : Matrix (Fin 2) (Fin 2) α) :
  A = !![A 0 0, A 0 1;
         A 1 0, A 1 1] :=
(etaExpand_eq _).symm
```
-/
theorem etaExpand_eq {m n} (A : Matrix (Fin m) (Fin n) α) : etaExpand A = A := by
  

Proof state:
l m✝ n✝ : ℕ
α : Type u_1
β : Type u_2
m n : ℕ
A : Matrix (Fin m) (Fin n) α
⊢ etaExpand A = A

Next tactic:
simp_rw [etaExpand, FinVec.etaExpand_eq, Matrix.of]
/-- This can be used to prove
```lean
example (A : Matrix (Fin 2) (Fin 2) α) :
  A = !![A 0 0, A 0 1;
         A 1 0, A 1 1] :=
(etaExpand_eq _).symm
```
-/
theorem etaExpand_eq {m n} (A : Matrix (Fin m) (Fin n) α) : etaExpand A = A := by
  simp_rw [etaExpand, FinVec.etaExpand_eq, Matrix.of]
  -- This to be in the above `simp_rw` before leanprover/lean4#2644
  

Proof state:
l m✝ n✝ : ℕ
α : Type u_1
β : Type u_2
m n : ℕ
A : Matrix (Fin m) (Fin n) α
⊢ ((Equiv.refl (Fin m → Fin n → α)) fun i j => A i j) = A

Next tactic:
erw [Equiv.refl_apply]
lemma toSetoid_injective : Function.Injective (@toSetoid X _)
  | ⟨_, _⟩, ⟨_, _⟩, _ => by 

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
toSetoid✝¹ : Setoid X
isOpen_setOf_rel✝¹ : ∀ (x : X), IsOpen (setOf (Setoid.Rel toSetoid✝¹ x))
toSetoid✝ : Setoid X
isOpen_setOf_rel✝ : ∀ (x : X), IsOpen (setOf (Setoid.Rel toSetoid✝ x))
x✝ :
  { toSetoid := toSetoid✝¹, isOpen_setOf_rel := isOpen_setOf_rel✝¹ }.toSetoid =
    { toSetoid := toSetoid✝, isOpen_setOf_rel := isOpen_setOf_rel✝ }.toSetoid
⊢ { toSetoid := toSetoid✝¹, isOpen_setOf_rel := isOpen_setOf_rel✝¹ } =
    { toSetoid := toSetoid✝, isOpen_setOf_rel := isOpen_setOf_rel✝ }

Next tactic:
congr
/-- Construct a discrete quotient from a clopen set. -/
def ofIsClopen {A : Set X} (h : IsClopen A) : DiscreteQuotient X where
  toSetoid := ⟨fun x y => x ∈ A ↔ y ∈ A, fun _ => Iff.rfl, Iff.symm, Iff.trans⟩
  isOpen_setOf_rel x := by 

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
A : Set X
h : IsClopen A
x : X
⊢ IsOpen (setOf (Setoid.Rel { r := fun x y => x ∈ A ↔ y ∈ A, iseqv := (_ : Equivalence fun x y => x ∈ A ↔ y ∈ A) } x))

Next tactic:
by_cases hx : x ∈ A
/-- Construct a discrete quotient from a clopen set. -/
def ofIsClopen {A : Set X} (h : IsClopen A) : DiscreteQuotient X where
  toSetoid := ⟨fun x y => x ∈ A ↔ y ∈ A, fun _ => Iff.rfl, Iff.symm, Iff.trans⟩
  isOpen_setOf_rel x := by by_cases hx : x ∈ A <;> 

Proof state:
case pos
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
A : Set X
h : IsClopen A
x : X
hx : x ∈ A
⊢ IsOpen (setOf (Setoid.Rel { r := fun x y => x ∈ A ↔ y ∈ A, iseqv := (_ : Equivalence fun x y => x ∈ A ↔ y ∈ A) } x))

Next tactic:
simp [Setoid.Rel, hx, h.1, h.2, ← compl_setOf]
/-- Construct a discrete quotient from a clopen set. -/
def ofIsClopen {A : Set X} (h : IsClopen A) : DiscreteQuotient X where
  toSetoid := ⟨fun x y => x ∈ A ↔ y ∈ A, fun _ => Iff.rfl, Iff.symm, Iff.trans⟩
  isOpen_setOf_rel x := by by_cases hx : x ∈ A <;> 

Proof state:
case neg
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
A : Set X
h : IsClopen A
x : X
hx : x ∉ A
⊢ IsOpen (setOf (Setoid.Rel { r := fun x y => x ∈ A ↔ y ∈ A, iseqv := (_ : Equivalence fun x y => x ∈ A ↔ y ∈ A) } x))

Next tactic:
simp [Setoid.Rel, hx, h.1, h.2, ← compl_setOf]
instance : DiscreteTopology S :=
  singletons_open_iff_discrete.1 <| S.proj_surjective.forall.2 fun x => by
    

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
x : X
⊢ IsOpen {proj S x}

Next tactic:
rw [← S.proj_quotientMap.isOpen_preimage, fiber_eq]
instance : DiscreteTopology S :=
  singletons_open_iff_discrete.1 <| S.proj_surjective.forall.2 fun x => by
    rw [← S.proj_quotientMap.isOpen_preimage, fiber_eq]
    

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
x : X
⊢ IsOpen (setOf (Setoid.Rel S.toSetoid x))

Next tactic:
exact S.isOpen_setOf_rel _
theorem isClopen_setOf_rel (x : X) : IsClopen (setOf (S.Rel x)) := by
  

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
x : X
⊢ IsClopen (setOf (Setoid.Rel S.toSetoid x))

Next tactic:
rw [← fiber_eq]
theorem isClopen_setOf_rel (x : X) : IsClopen (setOf (S.Rel x)) := by
  rw [← fiber_eq]
  

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
x : X
⊢ IsClopen (proj S ⁻¹' {proj S x})

Next tactic:
apply isClopen_preimage
instance : OrderTop (DiscreteQuotient X) where
  top := ⟨⊤, fun _ => isOpen_univ⟩
  le_top a := by 

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S a : DiscreteQuotient X
⊢ a ≤ ⊤

Next tactic:
tauto
/-- The quotient by `⊤ : DiscreteQuotient X` is a `Subsingleton`. -/
instance : Subsingleton (⊤ : DiscreteQuotient X) where
  allEq := by 

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
⊢ ∀ (a b : Quotient ⊤.toSetoid), a = b

Next tactic:
rintro ⟨_⟩ ⟨_⟩
/-- The quotient by `⊤ : DiscreteQuotient X` is a `Subsingleton`. -/
instance : Subsingleton (⊤ : DiscreteQuotient X) where
  allEq := by rintro ⟨_⟩ ⟨_⟩; 

Proof state:
case mk.mk
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
a✝² : Quotient ⊤.toSetoid
a✝¹ : X
b✝ : Quotient ⊤.toSetoid
a✝ : X
⊢ Quot.mk Setoid.r a✝¹ = Quot.mk Setoid.r a✝

Next tactic:
exact Quotient.sound trivial
@[mono]
theorem comap_mono {A B : DiscreteQuotient Y} (h : A ≤ B) : A.comap f ≤ B.comap f := by 

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
g : C(Y, Z)
f : C(X, Y)
A B : DiscreteQuotient Y
h : A ≤ B
⊢ comap f A ≤ comap f B

Next tactic:
tauto
@[simp]
theorem ofLE_refl : ofLE (le_refl A) = id := by
  

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S A B C : DiscreteQuotient X
⊢ ofLE (_ : A ≤ A) = id

Next tactic:
ext ⟨⟩
@[simp]
theorem ofLE_refl : ofLE (le_refl A) = id := by
  ext ⟨⟩
  

Proof state:
case h.mk
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S A B C : DiscreteQuotient X
x✝ : Quotient A.toSetoid
a✝ : X
⊢ ofLE (_ : A ≤ A) (Quot.mk Setoid.r a✝) = id (Quot.mk Setoid.r a✝)

Next tactic:
rfl
theorem ofLE_refl_apply (a : A) : ofLE (le_refl A) a = a := by 

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S A B C : DiscreteQuotient X
a : Quotient A.toSetoid
⊢ ofLE (_ : A ≤ A) a = a

Next tactic:
simp
@[simp]
theorem ofLE_ofLE (h₁ : A ≤ B) (h₂ : B ≤ C) (x : A) :
    ofLE h₂ (ofLE h₁ x) = ofLE (h₁.trans h₂) x := by
  

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S A B C : DiscreteQuotient X
h₁ : A ≤ B
h₂ : B ≤ C
x : Quotient A.toSetoid
⊢ ofLE h₂ (ofLE h₁ x) = ofLE (_ : A ≤ C) x

Next tactic:
rcases x with ⟨⟩
@[simp]
theorem ofLE_ofLE (h₁ : A ≤ B) (h₂ : B ≤ C) (x : A) :
    ofLE h₂ (ofLE h₁ x) = ofLE (h₁.trans h₂) x := by
  rcases x with ⟨⟩
  

Proof state:
case mk
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S A B C : DiscreteQuotient X
h₁ : A ≤ B
h₂ : B ≤ C
x : Quotient A.toSetoid
a✝ : X
⊢ ofLE h₂ (ofLE h₁ (Quot.mk Setoid.r a✝)) = ofLE (_ : A ≤ C) (Quot.mk Setoid.r a✝)

Next tactic:
rfl
/-- When `X` is a locally connected space, there is an `OrderBot` instance on
`DiscreteQuotient X`. The bottom element is given by `connectedComponentSetoid X`
-/
instance [LocallyConnectedSpace X] : OrderBot (DiscreteQuotient X) where
  bot :=
    { toSetoid := connectedComponentSetoid X
      isOpen_setOf_rel := fun x => by
        

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝³ : TopologicalSpace X
inst✝² : TopologicalSpace Y
inst✝¹ : TopologicalSpace Z
S : DiscreteQuotient X
inst✝ : LocallyConnectedSpace X
x : X
⊢ IsOpen (setOf (Setoid.Rel (connectedComponentSetoid X) x))

Next tactic:
convert isOpen_connectedComponent (x := x)
/-- When `X` is a locally connected space, there is an `OrderBot` instance on
`DiscreteQuotient X`. The bottom element is given by `connectedComponentSetoid X`
-/
instance [LocallyConnectedSpace X] : OrderBot (DiscreteQuotient X) where
  bot :=
    { toSetoid := connectedComponentSetoid X
      isOpen_setOf_rel := fun x => by
        convert isOpen_connectedComponent (x := x)
        

Proof state:
case h.e'_3
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝³ : TopologicalSpace X
inst✝² : TopologicalSpace Y
inst✝¹ : TopologicalSpace Z
S : DiscreteQuotient X
inst✝ : LocallyConnectedSpace X
x : X
⊢ setOf (Setoid.Rel (connectedComponentSetoid X) x) = connectedComponent x

Next tactic:
ext y
/-- When `X` is a locally connected space, there is an `OrderBot` instance on
`DiscreteQuotient X`. The bottom element is given by `connectedComponentSetoid X`
-/
instance [LocallyConnectedSpace X] : OrderBot (DiscreteQuotient X) where
  bot :=
    { toSetoid := connectedComponentSetoid X
      isOpen_setOf_rel := fun x => by
        convert isOpen_connectedComponent (x := x)
        ext y
        

Proof state:
case h.e'_3.h
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝³ : TopologicalSpace X
inst✝² : TopologicalSpace Y
inst✝¹ : TopologicalSpace Z
S : DiscreteQuotient X
inst✝ : LocallyConnectedSpace X
x y : X
⊢ y ∈ setOf (Setoid.Rel (connectedComponentSetoid X) x) ↔ y ∈ connectedComponent x

Next tactic:
simpa only [connectedComponentSetoid, ← connectedComponent_eq_iff_mem] using eq_comm
theorem proj_bot_inj [DiscreteTopology X] {x y : X} : proj ⊥ x = proj ⊥ y ↔ x = y := by 

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝³ : TopologicalSpace X
inst✝² : TopologicalSpace Y
inst✝¹ : TopologicalSpace Z
S : DiscreteQuotient X
inst✝ : DiscreteTopology X
x y : X
⊢ proj ⊥ x = proj ⊥ y ↔ x = y

Next tactic:
simp
theorem LEComap.comp : LEComap g B C → LEComap f A B → LEComap (g.comp f) A C := by 

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
f : C(X, Y)
A A' : DiscreteQuotient X
B B' : DiscreteQuotient Y
g : C(Y, Z)
C : DiscreteQuotient Z
⊢ LEComap g B C → LEComap f A B → LEComap (ContinuousMap.comp g f) A C

Next tactic:
tauto
@[simp]
theorem map_id : map _ (leComap_id A) = id := by 

Proof state:
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
f : C(X, Y)
A A' : DiscreteQuotient X
B B' : DiscreteQuotient Y
g : C(Y, Z)
C : DiscreteQuotient Z
⊢ map (ContinuousMap.id X) (_ : LEComap (ContinuousMap.id X) A A) = id

Next tactic:
ext ⟨⟩
@[simp]
theorem map_id : map _ (leComap_id A) = id := by ext ⟨⟩; 

Proof state:
case h.mk
α : Type u_1
X : Type u_2
Y : Type u_3
Z : Type u_4
inst✝² : TopologicalSpace X
inst✝¹ : TopologicalSpace Y
inst✝ : TopologicalSpace Z
S : DiscreteQuotient X
f : C(X, Y)
A A' : DiscreteQuotient X
B B' : DiscreteQuotient Y
g : C(Y, Z)
C : DiscreteQuotient Z
x✝ : Quotient A.toSetoid
a✝ : X
⊢ map (ContinuousMap.id X) (_ : LEComap (ContinuousMap.id X) A A) (Quot.mk Setoid.r a✝) = id (Quot.mk Setoid.r a✝)

Next tactic:
rfl