l3lab/ntp-mathlib huggingface dataset:
/-- If a functor `G : C ⥤ (D, K)` is fully faithful and locally dense,
then the set `{ T ∩ mor(C) | T ∈ K }` is a grothendieck topology of `C`.
-/
@[simps]
def inducedTopology : GrothendieckTopology C where
  sieves X S := K _ (S.functorPushforward G)
  top_mem' X := by
    change K _ _
    rw [Sieve.functorPushforward_top]
    exact K.top_mem _
  pullback_stable' X Y S f hS := by
    have : S.pullback f = ((S.functorPushforward G).pullback (G.map f)).functorPullback G := by
      conv_lhs => rw [← (Sieve.fullyFaithfulFunctorGaloisCoinsertion G X).u_l_eq S]
      ext
      change (S.functorPushforward G) _ ↔ (S.functorPushforward G) _
      rw [G.map_comp]
    rw [this]
    change K _ _
    apply Hld ⟨_, K.pullback_stable (G.map f) hS⟩
  transitive' X S hS S' H' := by
    apply K.transitive hS
    rintro Y _ ⟨Z, g, i, hg, rfl⟩
    rw [Sieve.pullback_comp]
    apply K.pullback_stable i
    refine' K.superset_covering _ (H' hg)
    rintro W _ ⟨Z', g', i', hg, rfl⟩
    refine' ⟨Z', g' ≫ g , i', hg, _⟩
    

Proof state:
case h.intro.intro.intro.intro.intro.intro.intro.intro
C : Type u_1
inst✝⁴ : Category.{?u.3086, u_1} C
D : Type u_2
inst✝³ : Category.{?u.3093, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝² : Category.{u, v} A
inst✝¹ : Full G
inst✝ : Faithful G
Hld : LocallyCoverDense K G
X : C
S : Sieve X
hS : S ∈ (fun X S => GrothendieckTopology.sieves K (G.obj X) (Sieve.functorPushforward G S)) X
S' : Sieve X
H' :
  ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄,
    S.arrows f →
      Sieve.pullback f S' ∈ (fun X S => GrothendieckTopology.sieves K (G.obj X) (Sieve.functorPushforward G S)) Y
Y : D
Z : C
g : Z ⟶ X
i : Y ⟶ G.obj Z
hg✝ : S.arrows g
W : D
Z' : C
g' : Z' ⟶ Z
i' : W ⟶ G.obj Z'
hg : (Sieve.pullback g S').arrows g'
⊢ (i' ≫ G.map g') ≫ G.map g = i' ≫ G.map (g' ≫ g)

Next tactic:
simp
theorem Functor.locallyCoverDense_of_isCoverDense [Full G] [G.IsCoverDense K] :
    LocallyCoverDense K G := by
  

Proof state:
C : Type u_1
inst✝⁴ : Category.{u_3, u_1} C
D : Type u_2
inst✝³ : Category.{u_4, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝² : Category.{u, v} A
inst✝¹ : Full G
inst✝ : IsCoverDense G K
⊢ LocallyCoverDense K G

Next tactic:
intro X T
theorem Functor.locallyCoverDense_of_isCoverDense [Full G] [G.IsCoverDense K] :
    LocallyCoverDense K G := by
  intro X T
  

Proof state:
C : Type u_1
inst✝⁴ : Category.{u_3, u_1} C
D : Type u_2
inst✝³ : Category.{u_4, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝² : Category.{u, v} A
inst✝¹ : Full G
inst✝ : IsCoverDense G K
X : C
T : ↑(GrothendieckTopology.sieves K (G.obj X))
⊢ Sieve.functorPushforward G (Sieve.functorPullback G ↑T) ∈ GrothendieckTopology.sieves K (G.obj X)

Next tactic:
refine' K.superset_covering _ (K.bind_covering T.property
    fun Y f _ => G.is_cover_of_isCoverDense _ Y)
theorem Functor.locallyCoverDense_of_isCoverDense [Full G] [G.IsCoverDense K] :
    LocallyCoverDense K G := by
  intro X T
  refine' K.superset_covering _ (K.bind_covering T.property
    fun Y f _ => G.is_cover_of_isCoverDense _ Y)
  

Proof state:
C : Type u_1
inst✝⁴ : Category.{u_3, u_1} C
D : Type u_2
inst✝³ : Category.{u_4, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝² : Category.{u, v} A
inst✝¹ : Full G
inst✝ : IsCoverDense G K
X : C
T : ↑(GrothendieckTopology.sieves K (G.obj X))
⊢ (Sieve.bind (↑T).arrows fun Y f x => Sieve.coverByImage G Y) ≤ Sieve.functorPushforward G (Sieve.functorPullback G ↑T)

Next tactic:
rintro Y _ ⟨Z, _, f, hf, ⟨W, g, f', rfl : _ = _⟩, rfl⟩
theorem Functor.locallyCoverDense_of_isCoverDense [Full G] [G.IsCoverDense K] :
    LocallyCoverDense K G := by
  intro X T
  refine' K.superset_covering _ (K.bind_covering T.property
    fun Y f _ => G.is_cover_of_isCoverDense _ Y)
  rintro Y _ ⟨Z, _, f, hf, ⟨W, g, f', rfl : _ = _⟩, rfl⟩
  

Proof state:
case intro.intro.intro.intro.intro.intro.mk
C : Type u_1
inst✝⁴ : Category.{u_3, u_1} C
D : Type u_2
inst✝³ : Category.{u_4, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝² : Category.{u, v} A
inst✝¹ : Full G
inst✝ : IsCoverDense G K
X : C
T : ↑(GrothendieckTopology.sieves K (G.obj X))
Y Z : D
f : Z ⟶ G.obj X
hf : (↑T).arrows f
W : C
g : Y ⟶ G.obj W
f' : G.obj W ⟶ Z
⊢ (Sieve.functorPushforward G (Sieve.functorPullback G ↑T)).arrows ((g ≫ f') ≫ f)

Next tactic:
use W
theorem Functor.locallyCoverDense_of_isCoverDense [Full G] [G.IsCoverDense K] :
    LocallyCoverDense K G := by
  intro X T
  refine' K.superset_covering _ (K.bind_covering T.property
    fun Y f _ => G.is_cover_of_isCoverDense _ Y)
  rintro Y _ ⟨Z, _, f, hf, ⟨W, g, f', rfl : _ = _⟩, rfl⟩
  use W; 

Proof state:
case h
C : Type u_1
inst✝⁴ : Category.{u_3, u_1} C
D : Type u_2
inst✝³ : Category.{u_4, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝² : Category.{u, v} A
inst✝¹ : Full G
inst✝ : IsCoverDense G K
X : C
T : ↑(GrothendieckTopology.sieves K (G.obj X))
Y Z : D
f : Z ⟶ G.obj X
hf : (↑T).arrows f
W : C
g : Y ⟶ G.obj W
f' : G.obj W ⟶ Z
⊢ ∃ g_1 h, (Sieve.functorPullback G ↑T).arrows g_1 ∧ (g ≫ f') ≫ f = h ≫ G.map g_1

Next tactic:
use G.preimage (f' ≫ f)
theorem Functor.locallyCoverDense_of_isCoverDense [Full G] [G.IsCoverDense K] :
    LocallyCoverDense K G := by
  intro X T
  refine' K.superset_covering _ (K.bind_covering T.property
    fun Y f _ => G.is_cover_of_isCoverDense _ Y)
  rintro Y _ ⟨Z, _, f, hf, ⟨W, g, f', rfl : _ = _⟩, rfl⟩
  use W; use G.preimage (f' ≫ f); 

Proof state:
case h
C : Type u_1
inst✝⁴ : Category.{u_3, u_1} C
D : Type u_2
inst✝³ : Category.{u_4, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝² : Category.{u, v} A
inst✝¹ : Full G
inst✝ : IsCoverDense G K
X : C
T : ↑(GrothendieckTopology.sieves K (G.obj X))
Y Z : D
f : Z ⟶ G.obj X
hf : (↑T).arrows f
W : C
g : Y ⟶ G.obj W
f' : G.obj W ⟶ Z
⊢ ∃ h, (Sieve.functorPullback G ↑T).arrows (G.preimage (f' ≫ f)) ∧ (g ≫ f') ≫ f = h ≫ G.map (G.preimage (f' ≫ f))

Next tactic:
use g
theorem Functor.locallyCoverDense_of_isCoverDense [Full G] [G.IsCoverDense K] :
    LocallyCoverDense K G := by
  intro X T
  refine' K.superset_covering _ (K.bind_covering T.property
    fun Y f _ => G.is_cover_of_isCoverDense _ Y)
  rintro Y _ ⟨Z, _, f, hf, ⟨W, g, f', rfl : _ = _⟩, rfl⟩
  use W; use G.preimage (f' ≫ f); use g
  

Proof state:
case h
C : Type u_1
inst✝⁴ : Category.{u_3, u_1} C
D : Type u_2
inst✝³ : Category.{u_4, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝² : Category.{u, v} A
inst✝¹ : Full G
inst✝ : IsCoverDense G K
X : C
T : ↑(GrothendieckTopology.sieves K (G.obj X))
Y Z : D
f : Z ⟶ G.obj X
hf : (↑T).arrows f
W : C
g : Y ⟶ G.obj W
f' : G.obj W ⟶ Z
⊢ (Sieve.functorPullback G ↑T).arrows (G.preimage (f' ≫ f)) ∧ (g ≫ f') ≫ f = g ≫ G.map (G.preimage (f' ≫ f))

Next tactic:
constructor
theorem Functor.locallyCoverDense_of_isCoverDense [Full G] [G.IsCoverDense K] :
    LocallyCoverDense K G := by
  intro X T
  refine' K.superset_covering _ (K.bind_covering T.property
    fun Y f _ => G.is_cover_of_isCoverDense _ Y)
  rintro Y _ ⟨Z, _, f, hf, ⟨W, g, f', rfl : _ = _⟩, rfl⟩
  use W; use G.preimage (f' ≫ f); use g
  constructor
  

Proof state:
case h.left
C : Type u_1
inst✝⁴ : Category.{u_3, u_1} C
D : Type u_2
inst✝³ : Category.{u_4, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝² : Category.{u, v} A
inst✝¹ : Full G
inst✝ : IsCoverDense G K
X : C
T : ↑(GrothendieckTopology.sieves K (G.obj X))
Y Z : D
f : Z ⟶ G.obj X
hf : (↑T).arrows f
W : C
g : Y ⟶ G.obj W
f' : G.obj W ⟶ Z
⊢ (Sieve.functorPullback G ↑T).arrows (G.preimage (f' ≫ f))
case h.right
C : Type u_1
inst✝⁴ : Category.{u_3, u_1} C
D : Type u_2
inst✝³ : Category.{u_4, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝² : Category.{u, v} A
inst✝¹ : Full G
inst✝ : IsCoverDense G K
X : C
T : ↑(GrothendieckTopology.sieves K (G.obj X))
Y Z : D
f : Z ⟶ G.obj X
hf : (↑T).arrows f
W : C
g : Y ⟶ G.obj W
f' : G.obj W ⟶ Z
⊢ (g ≫ f') ≫ f = g ≫ G.map (G.preimage (f' ≫ f))

Next tactic:
simpa using T.val.downward_closed hf f'
theorem Functor.locallyCoverDense_of_isCoverDense [Full G] [G.IsCoverDense K] :
    LocallyCoverDense K G := by
  intro X T
  refine' K.superset_covering _ (K.bind_covering T.property
    fun Y f _ => G.is_cover_of_isCoverDense _ Y)
  rintro Y _ ⟨Z, _, f, hf, ⟨W, g, f', rfl : _ = _⟩, rfl⟩
  use W; use G.preimage (f' ≫ f); use g
  constructor
  simpa using T.val.downward_closed hf f'
  

Proof state:
case h.right
C : Type u_1
inst✝⁴ : Category.{u_3, u_1} C
D : Type u_2
inst✝³ : Category.{u_4, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝² : Category.{u, v} A
inst✝¹ : Full G
inst✝ : IsCoverDense G K
X : C
T : ↑(GrothendieckTopology.sieves K (G.obj X))
Y Z : D
f : Z ⟶ G.obj X
hf : (↑T).arrows f
W : C
g : Y ⟶ G.obj W
f' : G.obj W ⟶ Z
⊢ (g ≫ f') ≫ f = g ≫ G.map (G.preimage (f' ≫ f))

Next tactic:
simp
theorem over_forget_locallyCoverDense (X : C) : LocallyCoverDense J (Over.forget X) := by
  

Proof state:
C : Type u_1
inst✝² : Category.{u_3, u_1} C
D : Type u_2
inst✝¹ : Category.{?u.12664, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝ : Category.{u, v} A
X : C
⊢ LocallyCoverDense J (Over.forget X)

Next tactic:
intro Y T
theorem over_forget_locallyCoverDense (X : C) : LocallyCoverDense J (Over.forget X) := by
  intro Y T
  

Proof state:
C : Type u_1
inst✝² : Category.{u_3, u_1} C
D : Type u_2
inst✝¹ : Category.{?u.12664, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝ : Category.{u, v} A
X : C
Y : Over X
T : ↑(GrothendieckTopology.sieves J ((Over.forget X).obj Y))
⊢ Sieve.functorPushforward (Over.forget X) (Sieve.functorPullback (Over.forget X) ↑T) ∈
    GrothendieckTopology.sieves J ((Over.forget X).obj Y)

Next tactic:
convert T.property
theorem over_forget_locallyCoverDense (X : C) : LocallyCoverDense J (Over.forget X) := by
  intro Y T
  convert T.property
  

Proof state:
case h.e'_4
C : Type u_1
inst✝² : Category.{u_3, u_1} C
D : Type u_2
inst✝¹ : Category.{?u.12664, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝ : Category.{u, v} A
X : C
Y : Over X
T : ↑(GrothendieckTopology.sieves J ((Over.forget X).obj Y))
⊢ Sieve.functorPushforward (Over.forget X) (Sieve.functorPullback (Over.forget X) ↑T) = ↑T

Next tactic:
ext Z f
theorem over_forget_locallyCoverDense (X : C) : LocallyCoverDense J (Over.forget X) := by
  intro Y T
  convert T.property
  ext Z f
  

Proof state:
case h.e'_4.h
C : Type u_1
inst✝² : Category.{u_3, u_1} C
D : Type u_2
inst✝¹ : Category.{?u.12664, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝ : Category.{u, v} A
X : C
Y : Over X
T : ↑(GrothendieckTopology.sieves J ((Over.forget X).obj Y))
Z : C
f : Z ⟶ (Over.forget X).obj Y
⊢ (Sieve.functorPushforward (Over.forget X) (Sieve.functorPullback (Over.forget X) ↑T)).arrows f ↔ (↑T).arrows f

Next tactic:
constructor
theorem over_forget_locallyCoverDense (X : C) : LocallyCoverDense J (Over.forget X) := by
  intro Y T
  convert T.property
  ext Z f
  constructor
  · 

Proof state:
case h.e'_4.h.mp
C : Type u_1
inst✝² : Category.{u_3, u_1} C
D : Type u_2
inst✝¹ : Category.{?u.12664, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝ : Category.{u, v} A
X : C
Y : Over X
T : ↑(GrothendieckTopology.sieves J ((Over.forget X).obj Y))
Z : C
f : Z ⟶ (Over.forget X).obj Y
⊢ (Sieve.functorPushforward (Over.forget X) (Sieve.functorPullback (Over.forget X) ↑T)).arrows f → (↑T).arrows f

Next tactic:
rintro ⟨_, _, g', hg, rfl⟩
theorem over_forget_locallyCoverDense (X : C) : LocallyCoverDense J (Over.forget X) := by
  intro Y T
  convert T.property
  ext Z f
  constructor
  · rintro ⟨_, _, g', hg, rfl⟩
    

Proof state:
case h.e'_4.h.mp.intro.intro.intro.intro
C : Type u_1
inst✝² : Category.{u_3, u_1} C
D : Type u_2
inst✝¹ : Category.{?u.12664, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝ : Category.{u, v} A
X : C
Y : Over X
T : ↑(GrothendieckTopology.sieves J ((Over.forget X).obj Y))
Z : C
w✝¹ : Over X
w✝ : w✝¹ ⟶ Y
g' : Z ⟶ (Over.forget X).obj w✝¹
hg : (Sieve.functorPullback (Over.forget X) ↑T).arrows w✝
⊢ (↑T).arrows (g' ≫ (Over.forget X).map w✝)

Next tactic:
exact T.val.downward_closed hg g'
theorem over_forget_locallyCoverDense (X : C) : LocallyCoverDense J (Over.forget X) := by
  intro Y T
  convert T.property
  ext Z f
  constructor
  · rintro ⟨_, _, g', hg, rfl⟩
    exact T.val.downward_closed hg g'
  · 

Proof state:
case h.e'_4.h.mpr
C : Type u_1
inst✝² : Category.{u_3, u_1} C
D : Type u_2
inst✝¹ : Category.{?u.12664, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝ : Category.{u, v} A
X : C
Y : Over X
T : ↑(GrothendieckTopology.sieves J ((Over.forget X).obj Y))
Z : C
f : Z ⟶ (Over.forget X).obj Y
⊢ (↑T).arrows f → (Sieve.functorPushforward (Over.forget X) (Sieve.functorPullback (Over.forget X) ↑T)).arrows f

Next tactic:
intro hf
theorem over_forget_locallyCoverDense (X : C) : LocallyCoverDense J (Over.forget X) := by
  intro Y T
  convert T.property
  ext Z f
  constructor
  · rintro ⟨_, _, g', hg, rfl⟩
    exact T.val.downward_closed hg g'
  · intro hf
    

Proof state:
case h.e'_4.h.mpr
C : Type u_1
inst✝² : Category.{u_3, u_1} C
D : Type u_2
inst✝¹ : Category.{?u.12664, u_2} D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type v
inst✝ : Category.{u, v} A
X : C
Y : Over X
T : ↑(GrothendieckTopology.sieves J ((Over.forget X).obj Y))
Z : C
f : Z ⟶ (Over.forget X).obj Y
hf : (↑T).arrows f
⊢ (Sieve.functorPushforward (Over.forget X) (Sieve.functorPullback (Over.forget X) ↑T)).arrows f

Next tactic:
exact ⟨Over.mk (f ≫ Y.hom), Over.homMk f, 𝟙 _, hf, (Category.id_comp _).symm⟩
instance [Full G] [Faithful G] [G.IsCoverDense K]  :
    Functor.IsContinuous G (G.inducedTopologyOfIsCoverDense K) K := by
  

Proof state:
C : Type v
inst✝⁵ : SmallCategory C
D : Type v
inst✝⁴ : SmallCategory D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type u
inst✝³ : Category.{v, u} A
inst✝² : Full G
inst✝¹ : Faithful G
inst✝ : Functor.IsCoverDense G K
⊢ Functor.IsContinuous G (Functor.inducedTopologyOfIsCoverDense G K) K

Next tactic:
apply Functor.IsCoverDense.isContinuous
instance [Full G] [Faithful G] [G.IsCoverDense K]  :
    Functor.IsContinuous G (G.inducedTopologyOfIsCoverDense K) K := by
  apply Functor.IsCoverDense.isContinuous
  

Proof state:
case Hp
C : Type v
inst✝⁵ : SmallCategory C
D : Type v
inst✝⁴ : SmallCategory D
G : C ⥤ D
J : GrothendieckTopology C
K : GrothendieckTopology D
A : Type u
inst✝³ : Category.{v, u} A
inst✝² : Full G
inst✝¹ : Faithful G
inst✝ : Functor.IsCoverDense G K
⊢ CoverPreserving (Functor.inducedTopologyOfIsCoverDense G K) K G

Next tactic:
exact (G.locallyCoverDense_of_isCoverDense K).inducedTopology_coverPreserving
theorem exists_iff_exists_of_mono {P : F α → Prop} {q : F β → Prop}
    (f : α ⟹ β) (g : β ⟹ α)
    (h₀ : f ⊚ g = TypeVec.id)
    (h₁ : ∀ u : F α, P u ↔ q (f <$$> u)) :
    (∃ u : F α, P u) ↔ ∃ u : F β, q u := by
  

Proof state:
n : ℕ
α β γ : TypeVec.{u} n
F : TypeVec.{u} n → Type v
inst✝¹ : MvFunctor F
P✝ : α ⟹ TypeVec.repeat n Prop
R : α ⊗ α ⟹ TypeVec.repeat n Prop
inst✝ : LawfulMvFunctor F
P : F α → Prop
q : F β → Prop
f : α ⟹ β
g : β ⟹ α
h₀ : f ⊚ g = TypeVec.id
h₁ : ∀ (u : F α), P u ↔ q (f <$$> u)
⊢ (∃ u, P u) ↔ ∃ u, q u

Next tactic:
constructor
theorem exists_iff_exists_of_mono {P : F α → Prop} {q : F β → Prop}
    (f : α ⟹ β) (g : β ⟹ α)
    (h₀ : f ⊚ g = TypeVec.id)
    (h₁ : ∀ u : F α, P u ↔ q (f <$$> u)) :
    (∃ u : F α, P u) ↔ ∃ u : F β, q u := by
  constructor <;> 

Proof state:
case mp
n : ℕ
α β γ : TypeVec.{u} n
F : TypeVec.{u} n → Type v
inst✝¹ : MvFunctor F
P✝ : α ⟹ TypeVec.repeat n Prop
R : α ⊗ α ⟹ TypeVec.repeat n Prop
inst✝ : LawfulMvFunctor F
P : F α → Prop
q : F β → Prop
f : α ⟹ β
g : β ⟹ α
h₀ : f ⊚ g = TypeVec.id
h₁ : ∀ (u : F α), P u ↔ q (f <$$> u)
⊢ (∃ u, P u) → ∃ u, q u

Next tactic:
rintro ⟨u, h₂⟩
theorem exists_iff_exists_of_mono {P : F α → Prop} {q : F β → Prop}
    (f : α ⟹ β) (g : β ⟹ α)
    (h₀ : f ⊚ g = TypeVec.id)
    (h₁ : ∀ u : F α, P u ↔ q (f <$$> u)) :
    (∃ u : F α, P u) ↔ ∃ u : F β, q u := by
  constructor <;> 

Proof state:
case mpr
n : ℕ
α β γ : TypeVec.{u} n
F : TypeVec.{u} n → Type v
inst✝¹ : MvFunctor F
P✝ : α ⟹ TypeVec.repeat n Prop
R : α ⊗ α ⟹ TypeVec.repeat n Prop
inst✝ : LawfulMvFunctor F
P : F α → Prop
q : F β → Prop
f : α ⟹ β
g : β ⟹ α
h₀ : f ⊚ g = TypeVec.id
h₁ : ∀ (u : F α), P u ↔ q (f <$$> u)
⊢ (∃ u, q u) → ∃ u, P u

Next tactic:
rintro ⟨u, h₂⟩
theorem exists_iff_exists_of_mono {P : F α → Prop} {q : F β → Prop}
    (f : α ⟹ β) (g : β ⟹ α)
    (h₀ : f ⊚ g = TypeVec.id)
    (h₁ : ∀ u : F α, P u ↔ q (f <$$> u)) :
    (∃ u : F α, P u) ↔ ∃ u : F β, q u := by
  constructor <;> rintro ⟨u, h₂⟩
  · 

Proof state:
case mp.intro
n : ℕ
α β γ : TypeVec.{u} n
F : TypeVec.{u} n → Type v
inst✝¹ : MvFunctor F
P✝ : α ⟹ TypeVec.repeat n Prop
R : α ⊗ α ⟹ TypeVec.repeat n Prop
inst✝ : LawfulMvFunctor F
P : F α → Prop
q : F β → Prop
f : α ⟹ β
g : β ⟹ α
h₀ : f ⊚ g = TypeVec.id
h₁ : ∀ (u : F α), P u ↔ q (f <$$> u)
u : F α
h₂ : P u
⊢ ∃ u, q u

Next tactic:
refine ⟨f <$$> u, ?_⟩
theorem exists_iff_exists_of_mono {P : F α → Prop} {q : F β → Prop}
    (f : α ⟹ β) (g : β ⟹ α)
    (h₀ : f ⊚ g = TypeVec.id)
    (h₁ : ∀ u : F α, P u ↔ q (f <$$> u)) :
    (∃ u : F α, P u) ↔ ∃ u : F β, q u := by
  constructor <;> rintro ⟨u, h₂⟩
  · refine ⟨f <$$> u, ?_⟩
    

Proof state:
case mp.intro
n : ℕ
α β γ : TypeVec.{u} n
F : TypeVec.{u} n → Type v
inst✝¹ : MvFunctor F
P✝ : α ⟹ TypeVec.repeat n Prop
R : α ⊗ α ⟹ TypeVec.repeat n Prop
inst✝ : LawfulMvFunctor F
P : F α → Prop
q : F β → Prop
f : α ⟹ β
g : β ⟹ α
h₀ : f ⊚ g = TypeVec.id
h₁ : ∀ (u : F α), P u ↔ q (f <$$> u)
u : F α
h₂ : P u
⊢ q (f <$$> u)

Next tactic:
apply (h₁ u).mp h₂
theorem exists_iff_exists_of_mono {P : F α → Prop} {q : F β → Prop}
    (f : α ⟹ β) (g : β ⟹ α)
    (h₀ : f ⊚ g = TypeVec.id)
    (h₁ : ∀ u : F α, P u ↔ q (f <$$> u)) :
    (∃ u : F α, P u) ↔ ∃ u : F β, q u := by
  constructor <;> rintro ⟨u, h₂⟩
  · refine ⟨f <$$> u, ?_⟩
    apply (h₁ u).mp h₂
  · 

Proof state:
case mpr.intro
n : ℕ
α β γ : TypeVec.{u} n
F : TypeVec.{u} n → Type v
inst✝¹ : MvFunctor F
P✝ : α ⟹ TypeVec.repeat n Prop
R : α ⊗ α ⟹ TypeVec.repeat n Prop
inst✝ : LawfulMvFunctor F
P : F α → Prop
q : F β → Prop
f : α ⟹ β
g : β ⟹ α
h₀ : f ⊚ g = TypeVec.id
h₁ : ∀ (u : F α), P u ↔ q (f <$$> u)
u : F β
h₂ : q u
⊢ ∃ u, P u

Next tactic:
refine ⟨g <$$> u, ?_⟩
theorem exists_iff_exists_of_mono {P : F α → Prop} {q : F β → Prop}
    (f : α ⟹ β) (g : β ⟹ α)
    (h₀ : f ⊚ g = TypeVec.id)
    (h₁ : ∀ u : F α, P u ↔ q (f <$$> u)) :
    (∃ u : F α, P u) ↔ ∃ u : F β, q u := by
  constructor <;> rintro ⟨u, h₂⟩
  · refine ⟨f <$$> u, ?_⟩
    apply (h₁ u).mp h₂
  · refine ⟨g <$$> u, ?_⟩
    

Proof state:
case mpr.intro
n : ℕ
α β γ : TypeVec.{u} n
F : TypeVec.{u} n → Type v
inst✝¹ : MvFunctor F
P✝ : α ⟹ TypeVec.repeat n Prop
R : α ⊗ α ⟹ TypeVec.repeat n Prop
inst✝ : LawfulMvFunctor F
P : F α → Prop
q : F β → Prop
f : α ⟹ β
g : β ⟹ α
h₀ : f ⊚ g = TypeVec.id
h₁ : ∀ (u : F α), P u ↔ q (f <$$> u)
u : F β
h₂ : q u
⊢ P (g <$$> u)

Next tactic:
apply (h₁ _).mpr _
theorem exists_iff_exists_of_mono {P : F α → Prop} {q : F β → Prop}
    (f : α ⟹ β) (g : β ⟹ α)
    (h₀ : f ⊚ g = TypeVec.id)
    (h₁ : ∀ u : F α, P u ↔ q (f <$$> u)) :
    (∃ u : F α, P u) ↔ ∃ u : F β, q u := by
  constructor <;> rintro ⟨u, h₂⟩
  · refine ⟨f <$$> u, ?_⟩
    apply (h₁ u).mp h₂
  · refine ⟨g <$$> u, ?_⟩
    apply (h₁ _).mpr _
    

Proof state:
n : ℕ
α β γ : TypeVec.{u} n
F : TypeVec.{u} n → Type v
inst✝¹ : MvFunctor F
P✝ : α ⟹ TypeVec.repeat n Prop
R : α ⊗ α ⟹ TypeVec.repeat n Prop
inst✝ : LawfulMvFunctor F
P : F α → Prop
q : F β → Prop
f : α ⟹ β
g : β ⟹ α
h₀ : f ⊚ g = TypeVec.id
h₁ : ∀ (u : F α), P u ↔ q (f <$$> u)
u : F β
h₂ : q u
⊢ q (f <$$> g <$$> u)

Next tactic:
simp only [MvFunctor.map_map, h₀, LawfulMvFunctor.id_map, h₂]
theorem LiftP_def (x : F α) : LiftP' P x ↔ ∃ u : F (Subtype_ P), subtypeVal P <$$> u = x :=
  exists_iff_exists_of_mono F _ _ (toSubtype_of_subtype P) (by 

Proof state:
n : ℕ
α β γ : TypeVec.{u} n
F : TypeVec.{u} n → Type v
inst✝¹ : MvFunctor F
P : α ⟹ TypeVec.repeat n Prop
R : α ⊗ α ⟹ TypeVec.repeat n Prop
inst✝ : LawfulMvFunctor F
x : F α
⊢ ∀ (u : F fun i => Subtype ((fun i x => ofRepeat (P i x)) i)),
    (fun i => Subtype.val) <$$> u = x ↔ subtypeVal P <$$> toSubtype P <$$> u = x

Next tactic:
simp [MvFunctor.map_map]
theorem LiftR_def (x y : F α) :
    LiftR' R x y ↔
      ∃ u : F (Subtype_ R),
        (TypeVec.prod.fst ⊚ subtypeVal R) <$$> u = x ∧
          (TypeVec.prod.snd ⊚ subtypeVal R) <$$> u = y :=
  exists_iff_exists_of_mono _ _ _ (toSubtype'_of_subtype' R) (by
    

Proof state:
n : ℕ
α β γ : TypeVec.{u} n
F : TypeVec.{u} n → Type v
inst✝¹ : MvFunctor F
P : α ⟹ TypeVec.repeat n Prop
R : α ⊗ α ⟹ TypeVec.repeat n Prop
inst✝ : LawfulMvFunctor F
x y : F α
⊢ ∀ (u : F fun i => { p // (fun i x y => ofRepeat (R i (prod.mk i x y))) i p.fst p.snd }),
    (fun i t => (↑t).fst) <$$> u = x ∧ (fun i t => (↑t).snd) <$$> u = y ↔
      (prod.fst ⊚ subtypeVal R) <$$> toSubtype' R <$$> u = x ∧ (prod.snd ⊚ subtypeVal R) <$$> toSubtype' R <$$> u = y

Next tactic:
simp only [map_map, comp_assoc, subtypeVal_toSubtype']
theorem LiftR_def (x y : F α) :
    LiftR' R x y ↔
      ∃ u : F (Subtype_ R),
        (TypeVec.prod.fst ⊚ subtypeVal R) <$$> u = x ∧
          (TypeVec.prod.snd ⊚ subtypeVal R) <$$> u = y :=
  exists_iff_exists_of_mono _ _ _ (toSubtype'_of_subtype' R) (by
    simp only [map_map, comp_assoc, subtypeVal_toSubtype']
    

Proof state:
n : ℕ
α β γ : TypeVec.{u} n
F : TypeVec.{u} n → Type v
inst✝¹ : MvFunctor F
P : α ⟹ TypeVec.repeat n Prop
R : α ⊗ α ⟹ TypeVec.repeat n Prop
inst✝ : LawfulMvFunctor F
x y : F α
⊢ ∀ (u : F fun i => { p // ofRepeat (R i (prod.mk i p.fst p.snd)) }),
    (fun i t => (↑t).fst) <$$> u = x ∧ (fun i t => (↑t).snd) <$$> u = y ↔
      (prod.fst ⊚ fun i x => prod.mk i (↑x).fst (↑x).snd) <$$> u = x ∧
        (prod.snd ⊚ fun i x => prod.mk i (↑x).fst (↑x).snd) <$$> u = y

Next tactic:
simp (config := { unfoldPartialApp := true }) [comp]
private def f :
    ∀ n α,
      (fun i : Fin2 (n + 1) => { p_1 // ofRepeat (PredLast' α pp i p_1) }) ⟹ fun i : Fin2 (n + 1) =>
        { p_1 : (α ::: β) i // PredLast α pp p_1 }
  | _, α, Fin2.fs i, x =>
    ⟨x.val, cast (by 

Proof state:
n : ℕ
F : TypeVec.{u} (n + 1) → Type u_1
inst✝¹ : MvFunctor F
inst✝ : LawfulMvFunctor F
α✝ : TypeVec.{u} n
β : Type u
pp : β → Prop
x✝ : ℕ
α : TypeVec.{u} x✝
i : Fin2 x✝
x : (fun i => { p_1 // ofRepeat (PredLast' α pp i p_1) }) (Fin2.fs i)
⊢ ofRepeat (PredLast' α pp (Fin2.fs i) ↑x) = PredLast α pp ↑x

Next tactic:
simp only [PredLast]
private def f :
    ∀ n α,
      (fun i : Fin2 (n + 1) => { p_1 // ofRepeat (PredLast' α pp i p_1) }) ⟹ fun i : Fin2 (n + 1) =>
        { p_1 : (α ::: β) i // PredLast α pp p_1 }
  | _, α, Fin2.fs i, x =>
    ⟨x.val, cast (by simp only [PredLast]; 

Proof state:
n : ℕ
F : TypeVec.{u} (n + 1) → Type u_1
inst✝¹ : MvFunctor F
inst✝ : LawfulMvFunctor F
α✝ : TypeVec.{u} n
β : Type u
pp : β → Prop
x✝ : ℕ
α : TypeVec.{u} x✝
i : Fin2 x✝
x : (fun i => { p_1 // ofRepeat (PredLast' α pp i p_1) }) (Fin2.fs i)
⊢ ofRepeat (PredLast' α pp (Fin2.fs i) ↑x) = True

Next tactic:
erw [const_iff_true]
private def g :
    ∀ n α,
      (fun i : Fin2 (n + 1) => { p_1 : (α ::: β) i // PredLast α pp p_1 }) ⟹ fun i : Fin2 (n + 1) =>
        { p_1 // ofRepeat (PredLast' α pp i p_1) }
  | _, α, Fin2.fs i, x =>
    ⟨x.val, cast (by 

Proof state:
n : ℕ
F : TypeVec.{u} (n + 1) → Type u_1
inst✝¹ : MvFunctor F
inst✝ : LawfulMvFunctor F
α✝ : TypeVec.{u} n
β : Type u
pp : β → Prop
x✝ : ℕ
α : TypeVec.{u} x✝
i : Fin2 x✝
x : (fun i => { p_1 // PredLast α pp p_1 }) (Fin2.fs i)
⊢ PredLast α pp ↑x = ofRepeat (PredLast' α pp (Fin2.fs i) ↑x)

Next tactic:
simp only [PredLast]