Theorem: CategoryTheory.Limits.Types.coequalizer_preimage_image_eq_of_preimage_eq
File: Mathlib/CategoryTheory/Limits/Shapes/Types.lean

tactic: have lem : ∀ x y, CoequalizerRel f g x y → (x ∈ U ↔ y ∈ U) := by
  rintro _ _ ⟨x⟩
  change x ∈ f ⁻¹' U ↔ x ∈ g ⁻¹' U
  rw [H]
state_before: 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
⊢ π ⁻¹' (π '' U) = U
state_after: 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), CoequalizerRel 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 }
state_before: 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), CoequalizerRel f g x y → (x ∈ U ↔ y ∈ U)
⊢ π ⁻¹' (π '' U) = U
state_after: 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), CoequalizerRel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
⊢ π ⁻¹' (π '' U) = U

tactic: ext
state_before: 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), CoequalizerRel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
⊢ π ⁻¹' (π '' U) = U
state_after: 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), CoequalizerRel 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
state_before: 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), CoequalizerRel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ : Y
⊢ x✝ ∈ π ⁻¹' (π '' U) ↔ x✝ ∈ U
state_after: 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), CoequalizerRel 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), CoequalizerRel 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: rintro _ _ ⟨x⟩
state_before: 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 y : Y), CoequalizerRel f g x y → (x ∈ U ↔ y ∈ U)
state_after: case Rel
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
state_before: case Rel
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
state_after: case Rel
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]
state_before: case Rel
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
state_after: no goals

tactic: tauto
state_before: 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), CoequalizerRel f g x y → (x ∈ U ↔ y ∈ U)
⊢ ∀ (x : Y), x ∈ U ↔ x ∈ U
state_after: no goals

tactic: tauto
state_before: 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), CoequalizerRel f g x y → (x ∈ U ↔ y ∈ U)
⊢ ∀ {x y : Y}, (x ∈ U ↔ y ∈ U) → (y ∈ U ↔ x ∈ U)
state_after: no goals

tactic: tauto
state_before: 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), CoequalizerRel f g x y → (x ∈ U ↔ y ∈ U)
⊢ ∀ {x y z : Y}, (x ∈ U ↔ y ∈ U) → (y ∈ U ↔ z ∈ U) → (x ∈ U ↔ z ∈ U)
state_after: no goals

tactic: rw [←
  show _ = π from
    h.comp_coconePointUniqueUpToIso_inv (coequalizerColimit f g).2
      WalkingParallelPair.one]
state_before: 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), CoequalizerRel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ : Y
⊢ x✝ ∈ π ⁻¹' (π '' U) → x✝ ∈ U
state_after: 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), CoequalizerRel 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'⟩
state_before: 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), CoequalizerRel 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
state_after: 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), CoequalizerRel 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'
state_before: 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), CoequalizerRel 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
state_after: 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), CoequalizerRel 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'
state_before: 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), CoequalizerRel 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
state_after: 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), CoequalizerRel 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

tactic: exact (eqv.eqvGen_iff.mp (EqvGen.mono lem (Quot.exact _ e'))).mp hy
state_before: 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), CoequalizerRel 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
state_after: no goals

tactic: exact fun hx => ⟨_, hx, rfl⟩
state_before: 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), CoequalizerRel f g x y → (x ∈ U ↔ y ∈ U)
eqv : _root_.Equivalence fun x y => x ∈ U ↔ y ∈ U
x✝ : Y
⊢ x✝ ∈ U → x✝ ∈ π ⁻¹' (π '' U)
state_after: no goals