l3lab/ntp-mathlib huggingface dataset:
/-- The **Fortuin-Kastelyn-Ginibre Inequality**. -/
lemma fkg (hμ₀ : 0 ≤ μ) (hf₀ : 0 ≤ f) (hg₀ : 0 ≤ g) (hf : Monotone f) (hg : Monotone g)
    (hμ : ∀ a b, μ a * μ b ≤ μ (a ⊓ b) * μ (a ⊔ b)) :
    (∑ a, μ a * f a) * ∑ a, μ a * g a ≤ (∑ a, μ a) * ∑ a, μ a * (f a * g a) := by
  refine' four_functions_theorem_univ (μ * f) (μ * g) μ _ (mul_nonneg hμ₀ hf₀) (mul_nonneg hμ₀ hg₀)
    hμ₀ (mul_nonneg hμ₀ $ mul_nonneg hf₀ hg₀) (fun a b ↦ _)
  dsimp
  rw [mul_mul_mul_comm, ← mul_assoc (μ (a ⊓ b))]
  

Proof state:
α : Type u_1
β : Type u_2
inst✝⁴ : DistribLattice α
inst✝³ : DecidableEq α
inst✝² : LinearOrderedCommSemiring β
inst✝¹ : ExistsAddOfLE β
f f₁ f₂ f₃ f₄ g μ : α → β
inst✝ : Fintype α
hμ₀ : 0 ≤ μ
hf₀ : 0 ≤ f
hg₀ : 0 ≤ g
hf : Monotone f
hg : Monotone g
hμ : ∀ (a b : α), μ a * μ b ≤ μ (a ⊓ b) * μ (a ⊔ b)
a b : α
⊢ μ a * μ b * (f a * g b) ≤ μ (a ⊓ b) * μ (a ⊔ b) * (f (a ⊔ b) * g (a ⊔ b))

Next tactic:
exact mul_le_mul (hμ _ _) (mul_le_mul (hf le_sup_left) (hg le_sup_right) (hg₀ _) $ hf₀ _)
    (mul_nonneg (hf₀ _) $ hg₀ _) $ mul_nonneg (hμ₀ _) $ hμ₀ _
/-- A slight generalisation of the **Marica-Schönheim Inequality**. -/
lemma Finset.le_card_diffs_mul_card_diffs (s t : Finset α) :
    s.card * t.card ≤ (s \\ t).card * (t \\ s).card := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : GeneralizedBooleanAlgebra α
s t : Finset α
⊢ card s * card t ≤ card (s \\ t) * card (t \\ s)

Next tactic:
have : ∀ s t : Finset α, (s \\ t).map ⟨_, liftLatticeHom_injective⟩ =
    s.map ⟨_, liftLatticeHom_injective⟩ \\ t.map ⟨_, liftLatticeHom_injective⟩
/-- A slight generalisation of the **Marica-Schönheim Inequality**. -/
lemma Finset.le_card_diffs_mul_card_diffs (s t : Finset α) :
    s.card * t.card ≤ (s \\ t).card * (t \\ s).card := by
  have : ∀ s t : Finset α, (s \\ t).map ⟨_, liftLatticeHom_injective⟩ =
    s.map ⟨_, liftLatticeHom_injective⟩ \\ t.map ⟨_, liftLatticeHom_injective⟩
  · 

Proof state:
case this
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : GeneralizedBooleanAlgebra α
s t : Finset α
⊢ ∀ (s t : Finset α),
    map { toFun := ⇑liftLatticeHom, inj' := (_ : Function.Injective ⇑liftLatticeHom) } (s \\ t) =
      map { toFun := ⇑liftLatticeHom, inj' := (_ : Function.Injective ⇑liftLatticeHom) } s \\
        map { toFun := ⇑liftLatticeHom, inj' := (_ : Function.Injective ⇑liftLatticeHom) } t

Next tactic:
rintro s t
/-- A slight generalisation of the **Marica-Schönheim Inequality**. -/
lemma Finset.le_card_diffs_mul_card_diffs (s t : Finset α) :
    s.card * t.card ≤ (s \\ t).card * (t \\ s).card := by
  have : ∀ s t : Finset α, (s \\ t).map ⟨_, liftLatticeHom_injective⟩ =
    s.map ⟨_, liftLatticeHom_injective⟩ \\ t.map ⟨_, liftLatticeHom_injective⟩
  · rintro s t
    

Proof state:
case this
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : GeneralizedBooleanAlgebra α
s✝ t✝ s t : Finset α
⊢ map { toFun := ⇑liftLatticeHom, inj' := (_ : Function.Injective ⇑liftLatticeHom) } (s \\ t) =
    map { toFun := ⇑liftLatticeHom, inj' := (_ : Function.Injective ⇑liftLatticeHom) } s \\
      map { toFun := ⇑liftLatticeHom, inj' := (_ : Function.Injective ⇑liftLatticeHom) } t

Next tactic:
simp_rw [map_eq_image]
/-- A slight generalisation of the **Marica-Schönheim Inequality**. -/
lemma Finset.le_card_diffs_mul_card_diffs (s t : Finset α) :
    s.card * t.card ≤ (s \\ t).card * (t \\ s).card := by
  have : ∀ s t : Finset α, (s \\ t).map ⟨_, liftLatticeHom_injective⟩ =
    s.map ⟨_, liftLatticeHom_injective⟩ \\ t.map ⟨_, liftLatticeHom_injective⟩
  · rintro s t
    simp_rw [map_eq_image]
    

Proof state:
case this
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : GeneralizedBooleanAlgebra α
s✝ t✝ s t : Finset α
⊢ image (⇑{ toFun := ⇑liftLatticeHom, inj' := (_ : Function.Injective ⇑liftLatticeHom) }) (s \\ t) =
    image (⇑{ toFun := ⇑liftLatticeHom, inj' := (_ : Function.Injective ⇑liftLatticeHom) }) s \\
      image (⇑{ toFun := ⇑liftLatticeHom, inj' := (_ : Function.Injective ⇑liftLatticeHom) }) t

Next tactic:
exact image_image₂_distrib fun a b ↦ rfl
/-- A slight generalisation of the **Marica-Schönheim Inequality**. -/
lemma Finset.le_card_diffs_mul_card_diffs (s t : Finset α) :
    s.card * t.card ≤ (s \\ t).card * (t \\ s).card := by
  have : ∀ s t : Finset α, (s \\ t).map ⟨_, liftLatticeHom_injective⟩ =
    s.map ⟨_, liftLatticeHom_injective⟩ \\ t.map ⟨_, liftLatticeHom_injective⟩
  · rintro s t
    simp_rw [map_eq_image]
    exact image_image₂_distrib fun a b ↦ rfl
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : GeneralizedBooleanAlgebra α
s t : Finset α
this :
  ∀ (s t : Finset α),
    map { toFun := ⇑liftLatticeHom, inj' := (_ : Function.Injective ⇑liftLatticeHom) } (s \\ t) =
      map { toFun := ⇑liftLatticeHom, inj' := (_ : Function.Injective ⇑liftLatticeHom) } s \\
        map { toFun := ⇑liftLatticeHom, inj' := (_ : Function.Injective ⇑liftLatticeHom) } t
⊢ card s * card t ≤ card (s \\ t) * card (t \\ s)

Next tactic:
simpa [← card_compls (_ ⊻ _), ← map_sup, ← map_inf, ← this] using
    (s.map ⟨_, liftLatticeHom_injective⟩).le_card_infs_mul_card_sups
      (t.map ⟨_, liftLatticeHom_injective⟩)ᶜˢ
/-- The **Marica-Schönheim Inequality**. -/
lemma Finset.card_le_card_diffs (s : Finset α) : s.card ≤ (s \\ s).card :=
  le_of_pow_le_pow_left two_ne_zero (zero_le _) $ by
    

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : DecidableEq α
inst✝ : GeneralizedBooleanAlgebra α
s : Finset α
⊢ card s ^ 2 ≤ card (s \\ s) ^ 2

Next tactic:
simpa [← sq] using s.le_card_diffs_mul_card_diffs s
@[simp]
theorem hom_eq_iff {X Y : StructuredArrow S T} (f g : X ⟶ Y) : f = g ↔ f.right = g.right :=
  ⟨fun h ↦ by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
X Y : StructuredArrow S T
f g : X ⟶ Y
h : f = g
⊢ f.right = g.right

Next tactic:
rw [h]
@[reassoc (attr := simp)]
theorem w {A B : StructuredArrow S T} (f : A ⟶ B) : A.hom ≫ T.map f.right = B.hom := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A B : StructuredArrow S T
f : A ⟶ B
⊢ A.hom ≫ T.map f.right = B.hom

Next tactic:
have := f.w
@[reassoc (attr := simp)]
theorem w {A B : StructuredArrow S T} (f : A ⟶ B) : A.hom ≫ T.map f.right = B.hom := by
  have := f.w; 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
A B : StructuredArrow S T
f : A ⟶ B
this : (Functor.fromPUnit S).map f.left ≫ B.hom = A.hom ≫ T.map f.right
⊢ A.hom ≫ T.map f.right = B.hom

Next tactic:
aesop_cat
@[simp]
theorem eqToHom_right {X Y : StructuredArrow S T} (h : X = Y) :
    (eqToHom h).right = eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
X Y : StructuredArrow S T
h : X = Y
⊢ X.right = Y.right

Next tactic:
rw [h]
@[simp]
theorem eqToHom_right {X Y : StructuredArrow S T} (h : X = Y) :
    (eqToHom h).right = eqToHom (by rw [h]) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
X Y : StructuredArrow S T
h : X = Y
⊢ (eqToHom h).right = eqToHom (_ : X.right = Y.right)

Next tactic:
subst h
@[simp]
theorem eqToHom_right {X Y : StructuredArrow S T} (h : X = Y) :
    (eqToHom h).right = eqToHom (by rw [h]) := by
  subst h
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
X : StructuredArrow S T
⊢ (eqToHom (_ : X = X)).right = eqToHom (_ : X.right = X.right)

Next tactic:
simp only [eqToHom_refl, id_right]
/-- To construct a morphism of structured arrows,
we need a morphism of the objects underlying the target,
and to check that the triangle commutes.
-/
@[simps]
def homMk {f f' : StructuredArrow S T} (g : f.right ⟶ f'.right)
    (w : f.hom ≫ T.map g = f'.hom := by aesop_cat) : f ⟶ f' where
  left := eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f f' : StructuredArrow S T
g : f.right ⟶ f'.right
w : autoParam (f.hom ≫ T.map g = f'.hom) _auto✝
⊢ f.left = f'.left

Next tactic:
ext
/-- To construct a morphism of structured arrows,
we need a morphism of the objects underlying the target,
and to check that the triangle commutes.
-/
@[simps]
def homMk {f f' : StructuredArrow S T} (g : f.right ⟶ f'.right)
    (w : f.hom ≫ T.map g = f'.hom := by aesop_cat) : f ⟶ f' where
  left := eqToHom (by ext)
  right := g
  w := by
    

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f f' : StructuredArrow S T
g : f.right ⟶ f'.right
w : autoParam (f.hom ≫ T.map g = f'.hom) _auto✝
⊢ (Functor.fromPUnit S).map (eqToHom (_ : f.left = f'.left)) ≫ f'.hom = f.hom ≫ T.map g

Next tactic:
dsimp
/-- To construct a morphism of structured arrows,
we need a morphism of the objects underlying the target,
and to check that the triangle commutes.
-/
@[simps]
def homMk {f f' : StructuredArrow S T} (g : f.right ⟶ f'.right)
    (w : f.hom ≫ T.map g = f'.hom := by aesop_cat) : f ⟶ f' where
  left := eqToHom (by ext)
  right := g
  w := by
    dsimp
    

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f f' : StructuredArrow S T
g : f.right ⟶ f'.right
w : autoParam (f.hom ≫ T.map g = f'.hom) _auto✝
⊢ 𝟙 S ≫ f'.hom = f.hom ≫ T.map g

Next tactic:
simpa using w.symm
/-- Given a structured arrow `X ⟶ T(Y)`, and an arrow `Y ⟶ Y'`, we can construct a morphism of
    structured arrows given by `(X ⟶ T(Y)) ⟶ (X ⟶ T(Y) ⟶ T(Y'))`.  -/
@[simps]
def homMk' (f : StructuredArrow S T) (g : f.right ⟶ Y') : f ⟶ mk (f.hom ≫ T.map g) where
  left := eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : StructuredArrow S T
g : f.right ⟶ Y'
⊢ f.left = (mk (f.hom ≫ T.map g)).left

Next tactic:
ext
lemma homMk'_id (f : StructuredArrow S T) : homMk' f (𝟙 f.right) = eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : StructuredArrow S T
⊢ f = mk (f.hom ≫ T.map (𝟙 f.right))

Next tactic:
aesop_cat
lemma homMk'_id (f : StructuredArrow S T) : homMk' f (𝟙 f.right) = eqToHom (by aesop_cat) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : StructuredArrow S T
⊢ homMk' f (𝟙 f.right) = eqToHom (_ : f = mk (f.hom ≫ T.map (𝟙 f.right)))

Next tactic:
ext
lemma homMk'_id (f : StructuredArrow S T) : homMk' f (𝟙 f.right) = eqToHom (by aesop_cat) := by
  ext
  

Proof state:
case h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : StructuredArrow S T
⊢ (homMk' f (𝟙 f.right)).right = (eqToHom (_ : f = mk (f.hom ≫ T.map (𝟙 f.right)))).right

Next tactic:
simp [eqToHom_right]
lemma homMk'_mk_id (f : S ⟶ T.obj Y) : homMk' (mk f) (𝟙 Y) = eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : S ⟶ T.obj Y
⊢ mk f = mk ((mk f).hom ≫ T.map (𝟙 Y))

Next tactic:
aesop_cat
lemma homMk'_comp (f : StructuredArrow S T) (g : f.right ⟶ Y') (g' : Y' ⟶ Y'') :
    homMk' f (g ≫ g') = homMk' f g ≫ homMk' (mk (f.hom ≫ T.map g)) g' ≫ eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : StructuredArrow S T
g : f.right ⟶ Y'
g' : Y' ⟶ Y''
⊢ mk ((mk (f.hom ≫ T.map g)).hom ≫ T.map g') = mk (f.hom ≫ T.map (g ≫ g'))

Next tactic:
simp
lemma homMk'_comp (f : StructuredArrow S T) (g : f.right ⟶ Y') (g' : Y' ⟶ Y'') :
    homMk' f (g ≫ g') = homMk' f g ≫ homMk' (mk (f.hom ≫ T.map g)) g' ≫ eqToHom (by simp) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : StructuredArrow S T
g : f.right ⟶ Y'
g' : Y' ⟶ Y''
⊢ homMk' f (g ≫ g') =
    homMk' f g ≫
      homMk' (mk (f.hom ≫ T.map g)) g' ≫ eqToHom (_ : mk ((f.hom ≫ T.map g) ≫ T.map g') = mk (f.hom ≫ T.map (g ≫ g')))

Next tactic:
ext
lemma homMk'_comp (f : StructuredArrow S T) (g : f.right ⟶ Y') (g' : Y' ⟶ Y'') :
    homMk' f (g ≫ g') = homMk' f g ≫ homMk' (mk (f.hom ≫ T.map g)) g' ≫ eqToHom (by simp) := by
  ext
  

Proof state:
case h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : StructuredArrow S T
g : f.right ⟶ Y'
g' : Y' ⟶ Y''
⊢ (homMk' f (g ≫ g')).right =
    (homMk' f g ≫
        homMk' (mk (f.hom ≫ T.map g)) g' ≫
          eqToHom (_ : mk ((f.hom ≫ T.map g) ≫ T.map g') = mk (f.hom ≫ T.map (g ≫ g')))).right

Next tactic:
simp [eqToHom_right]
lemma homMk'_mk_comp (f : S ⟶ T.obj Y) (g : Y ⟶ Y') (g' : Y' ⟶ Y'') :
    homMk' (mk f) (g ≫ g') = homMk' (mk f) g ≫ homMk' (mk (f ≫ T.map g)) g' ≫ eqToHom (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : S ⟶ T.obj Y
g : Y ⟶ Y'
g' : Y' ⟶ Y''
⊢ mk ((mk (f ≫ T.map g)).hom ≫ T.map g') = mk ((mk f).hom ≫ T.map (g ≫ g'))

Next tactic:
simp
/-- To construct an isomorphism of structured arrows,
we need an isomorphism of the objects underlying the target,
and to check that the triangle commutes.
-/
@[simps!]
def isoMk {f f' : StructuredArrow S T} (g : f.right ≅ f'.right)
    (w : f.hom ≫ T.map g.hom = f'.hom := by aesop_cat) :
    f ≅ f' :=
  Comma.isoMk (eqToIso (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f f' : StructuredArrow S T
g : f.right ≅ f'.right
w : autoParam (f.hom ≫ T.map g.hom = f'.hom) _auto✝
⊢ f.left = f'.left

Next tactic:
ext
/-- To construct an isomorphism of structured arrows,
we need an isomorphism of the objects underlying the target,
and to check that the triangle commutes.
-/
@[simps!]
def isoMk {f f' : StructuredArrow S T} (g : f.right ≅ f'.right)
    (w : f.hom ≫ T.map g.hom = f'.hom := by aesop_cat) :
    f ≅ f' :=
  Comma.isoMk (eqToIso (by ext)) g (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f f' : StructuredArrow S T
g : f.right ≅ f'.right
w : autoParam (f.hom ≫ T.map g.hom = f'.hom) _auto✝
⊢ (Functor.fromPUnit S).map (eqToIso (_ : f.left = f'.left)).hom ≫ f'.hom = f.hom ≫ T.map g.hom

Next tactic:
simpa [eqToHom_map] using w.symm
@[simp]
theorem map_id {f : StructuredArrow S T} : (map (𝟙 S)).obj f = f := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : StructuredArrow S T
⊢ (map (𝟙 S)).obj f = f

Next tactic:
rw [eq_mk f]
@[simp]
theorem map_id {f : StructuredArrow S T} : (map (𝟙 S)).obj f = f := by
  rw [eq_mk f]
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : StructuredArrow S T
⊢ (map (𝟙 S)).obj (mk f.hom) = mk f.hom

Next tactic:
simp
@[simp]
theorem map_comp {f : S ⟶ S'} {f' : S' ⟶ S''} {h : StructuredArrow S'' T} :
    (map (f ≫ f')).obj h = (map f).obj ((map f').obj h) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : S ⟶ S'
f' : S' ⟶ S''
h : StructuredArrow S'' T
⊢ (map (f ≫ f')).obj h = (map f).obj ((map f').obj h)

Next tactic:
rw [eq_mk h]
@[simp]
theorem map_comp {f : S ⟶ S'} {f' : S' ⟶ S''} {h : StructuredArrow S'' T} :
    (map (f ≫ f')).obj h = (map f).obj ((map f').obj h) := by
  rw [eq_mk h]
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
f : S ⟶ S'
f' : S' ⟶ S''
h : StructuredArrow S'' T
⊢ (map (f ≫ f')).obj (mk h.hom) = (map f).obj ((map f').obj (mk h.hom))

Next tactic:
simp
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨StructuredArrow.homMk
        (inv ((proj S T).map f))
        (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
Y Z : StructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ Z.hom ≫ T.map (inv ((proj S T).map f)) = Y.hom

Next tactic:
rw [Functor.map_inv, IsIso.comp_inv_eq]
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨StructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.comp_inv_eq]; 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
Y Z : StructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ Z.hom = Y.hom ≫ T.map ((proj S T).map f)

Next tactic:
simp
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨StructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.comp_inv_eq]; simp),
      by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
Y Z : StructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ f ≫ homMk (inv ((proj S T).map f)) = 𝟙 Y ∧ homMk (inv ((proj S T).map f)) ≫ f = 𝟙 Z

Next tactic:
constructor
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨StructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.comp_inv_eq]; simp),
      by constructor <;> 

Proof state:
case left
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
Y Z : StructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ f ≫ homMk (inv ((proj S T).map f)) = 𝟙 Y

Next tactic:
apply CommaMorphism.ext
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨StructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.comp_inv_eq]; simp),
      by constructor <;> 

Proof state:
case right
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
Y Z : StructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ homMk (inv ((proj S T).map f)) ≫ f = 𝟙 Z

Next tactic:
apply CommaMorphism.ext
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨StructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.comp_inv_eq]; simp),
      by constructor <;> apply CommaMorphism.ext <;> 

Proof state:
case left.left
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
Y Z : StructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ (f ≫ homMk (inv ((proj S T).map f))).left = (𝟙 Y).left

Next tactic:
dsimp at t ⊢
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨StructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.comp_inv_eq]; simp),
      by constructor <;> apply CommaMorphism.ext <;> 

Proof state:
case left.right
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
Y Z : StructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ (f ≫ homMk (inv ((proj S T).map f))).right = (𝟙 Y).right

Next tactic:
dsimp at t ⊢
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨StructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.comp_inv_eq]; simp),
      by constructor <;> apply CommaMorphism.ext <;> 

Proof state:
case right.left
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
Y Z : StructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ (homMk (inv ((proj S T).map f)) ≫ f).left = (𝟙 Z).left

Next tactic:
dsimp at t ⊢
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨StructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.comp_inv_eq]; simp),
      by constructor <;> apply CommaMorphism.ext <;> 

Proof state:
case right.right
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
Y Z : StructuredArrow S T
f : Y ⟶ Z
t : IsIso ((proj S T).map f)
⊢ (homMk (inv ((proj S T).map f)) ≫ f).right = (𝟙 Z).right

Next tactic:
dsimp at t ⊢
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨StructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.comp_inv_eq]; simp),
      by constructor <;> apply CommaMorphism.ext <;> dsimp at t ⊢ <;> 

Proof state:
case left.right
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
Y Z : StructuredArrow S T
f : Y ⟶ Z
t : IsIso f.right
⊢ f.right ≫ inv f.right = 𝟙 Y.right

Next tactic:
simp
instance proj_reflectsIsomorphisms : ReflectsIsomorphisms (proj S T) where
  reflects {Y Z} f t :=
    ⟨⟨StructuredArrow.homMk
        (inv ((proj S T).map f))
        (by rw [Functor.map_inv, IsIso.comp_inv_eq]; simp),
      by constructor <;> apply CommaMorphism.ext <;> dsimp at t ⊢ <;> 

Proof state:
case right.right
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
S S' S'' : D
Y✝ Y' Y'' : C
T T' : C ⥤ D
Y Z : StructuredArrow S T
f : Y ⟶ Z
t : IsIso f.right
⊢ inv f.right ≫ f.right = 𝟙 Z.right

Next tactic:
simp
/-- The identity structured arrow is initial. -/
def mkIdInitial [Full T] [Faithful T] : IsInitial (mk (𝟙 (T.obj Y))) where
  desc c := homMk (T.preimage c.pt.hom)
  uniq c m _ := by
    

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
inst✝¹ : Full T
inst✝ : Faithful T
c : Cocone (Functor.empty (StructuredArrow (T.obj Y) T))
m : (asEmptyCocone (mk (𝟙 (T.obj Y)))).pt ⟶ c.pt
x✝ : ∀ (j : Discrete PEmpty.{1}), (asEmptyCocone (mk (𝟙 (T.obj Y)))).ι.app j ≫ m = c.ι.app j
⊢ m = (fun c => homMk (T.preimage c.pt.hom)) c

Next tactic:
apply CommaMorphism.ext
/-- The identity structured arrow is initial. -/
def mkIdInitial [Full T] [Faithful T] : IsInitial (mk (𝟙 (T.obj Y))) where
  desc c := homMk (T.preimage c.pt.hom)
  uniq c m _ := by
    apply CommaMorphism.ext
    · 

Proof state:
case left
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
inst✝¹ : Full T
inst✝ : Faithful T
c : Cocone (Functor.empty (StructuredArrow (T.obj Y) T))
m : (asEmptyCocone (mk (𝟙 (T.obj Y)))).pt ⟶ c.pt
x✝ : ∀ (j : Discrete PEmpty.{1}), (asEmptyCocone (mk (𝟙 (T.obj Y)))).ι.app j ≫ m = c.ι.app j
⊢ m.left = ((fun c => homMk (T.preimage c.pt.hom)) c).left

Next tactic:
aesop_cat
/-- The identity structured arrow is initial. -/
def mkIdInitial [Full T] [Faithful T] : IsInitial (mk (𝟙 (T.obj Y))) where
  desc c := homMk (T.preimage c.pt.hom)
  uniq c m _ := by
    apply CommaMorphism.ext
    · aesop_cat
    · 

Proof state:
case right
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
S S' S'' : D
Y Y' Y'' : C
T T' : C ⥤ D
inst✝¹ : Full T
inst✝ : Faithful T
c : Cocone (Functor.empty (StructuredArrow (T.obj Y) T))
m : (asEmptyCocone (mk (𝟙 (T.obj Y)))).pt ⟶ c.pt
x✝ : ∀ (j : Discrete PEmpty.{1}), (asEmptyCocone (mk (𝟙 (T.obj Y)))).ι.app j ≫ m = c.ι.app j
⊢ m.right = ((fun c => homMk (T.preimage c.pt.hom)) c).right

Next tactic:
apply T.map_injective