-- Mathlib/CategoryTheory/Limits/Shapes/Types.lean
theorem coequalizer_preimage_image_eq_of_preimage_eq (π : Y ⟶ Z) (e : f ≫ π = g ≫ π)
    (h : IsColimit (Cofork.ofπ π e)) (U : Set Y) (H : f ⁻¹' U = g ⁻¹' U) : π ⁻¹' (π '' U) = U

Proof state:
case intro
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
x : X
⊢ f x ∈ U ↔ g x ∈ U

Tactic:
change x ∈ f ⁻¹' U ↔ x ∈ g ⁻¹' U

Result:
case intro
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
x : X
⊢ x ∈ f ⁻¹' U ↔ x ∈ g ⁻¹' U

Proof state:
case h.mp
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ : Y
⊢ x✝ ∈ π ⁻¹' (π '' U) → x✝ ∈ U

Tactic:
rw [←
  show _ = π from
    h.comp_coconePointUniqueUpToIso_inv (coequalizerColimit f g).2
      WalkingParallelPair.one]

Result:
case h.mp
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ : Y
⊢ x✝ ∈
      ((coequalizerColimit f g).cocone.ι.app WalkingParallelPair.one ≫
          (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv) ⁻¹'
        (((coequalizerColimit f g).cocone.ι.app WalkingParallelPair.one ≫
            (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv) ''
          U) →
    x✝ ∈ U

Proof state:
case h.mp
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ : Y
⊢ x✝ ∈
      ((coequalizerColimit f g).cocone.ι.app WalkingParallelPair.one ≫
          (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv) ⁻¹'
        (((coequalizerColimit f g).cocone.ι.app WalkingParallelPair.one ≫
            (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv) ''
          U) →
    x✝ ∈ U

Tactic:
rintro ⟨y, hy, e'⟩

Result:
case h.mp.intro.intro
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ y : Y
hy : y ∈ U
e' :
  ((coequalizerColimit f g).cocone.ι.app WalkingParallelPair.one ≫
        (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv)
      y =
    ((coequalizerColimit f g).cocone.ι.app WalkingParallelPair.one ≫
        (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv)
      x✝
⊢ x✝ ∈ U

Proof state:
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
⊢ π ⁻¹' (π '' U) = U

Tactic:
have eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U :=
  { refl := by tauto
    symm := by tauto
    trans := by tauto }

Result:
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
⊢ π ⁻¹' (π '' U) = U

Proof state:
case h
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ : Y
⊢ x✝ ∈ π ⁻¹' (π '' U) ↔ x✝ ∈ U

Tactic:
constructor

Result:
case h.mp
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ : Y
⊢ x✝ ∈ π ⁻¹' (π '' U) → x✝ ∈ U

case h.mpr
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ : Y
⊢ x✝ ∈ U → x✝ ∈ π ⁻¹' (π '' U)

Proof state:
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
⊢ ∀ {x y z : Y}, (x ∈ U ↔ y ∈ U) → (y ∈ U ↔ z ∈ U) → (x ∈ U ↔ z ∈ U)

Tactic:
tauto

Result:
no goals

Proof state:
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
⊢ ∀ (x : Y), x ∈ U ↔ x ∈ U

Tactic:
tauto

Result:
no goals

Proof state:
case h.mp.intro.intro
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ y : Y
hy : y ∈ U
e' :
  (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv (Cofork.π (coequalizerColimit f g).cocone y) =
    (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv (Cofork.π (coequalizerColimit f g).cocone x✝)
⊢ x✝ ∈ U

Tactic:
replace e' :=
  (mono_iff_injective
        (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv).mp
    inferInstance e'

Result:
case h.mp.intro.intro
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ y : Y
hy : y ∈ U
e' : Cofork.π (coequalizerColimit f g).cocone y = Cofork.π (coequalizerColimit f g).cocone x✝
⊢ x✝ ∈ U

Proof state:
case h.mp.intro.intro
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ y : Y
hy : y ∈ U
e' :
  ((coequalizerColimit f g).cocone.ι.app WalkingParallelPair.one ≫
        (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv)
      y =
    ((coequalizerColimit f g).cocone.ι.app WalkingParallelPair.one ≫
        (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv)
      x✝
⊢ x✝ ∈ U

Tactic:
dsimp at e'

Result:
case h.mp.intro.intro
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ y : Y
hy : y ∈ U
e' :
  (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv (Cofork.π (coequalizerColimit f g).cocone y) =
    (h.coconePointUniqueUpToIso (coequalizerColimit f g).isColimit).inv (Cofork.π (coequalizerColimit f g).cocone x✝)
⊢ x✝ ∈ U

Proof state:
case h.mpr
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
lem : ∀ (x y : Y), Function.Coequalizer.Rel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ : Y
⊢ x✝ ∈ U → x✝ ∈ π ⁻¹' (π '' U)

Tactic:
exact fun hx => ⟨_, hx, rfl⟩

Result:
no goals

Proof state:
case intro
X Y Z : Type u
f g : X ⟶ Y
π : Y ⟶ Z
e : f ≫ π = g ≫ π
h : IsColimit (Cofork.ofπ π e)
U : Set Y
H : f ⁻¹' U = g ⁻¹' U
x : X
⊢ x ∈ f ⁻¹' U ↔ x ∈ g ⁻¹' U

Tactic:
rw [H]

Result:
no goals