Theorem: GroupCat.SurjectiveOfEpiAuxs.agree
File: Mathlib/Algebra/Category/GroupCat/EpiMono.lean

tactic: refine' Set.ext fun b => ⟨_, fun hb : h b = g b => by_contradiction fun r => _⟩
state_before: A B : GroupCat
f : A ⟶ B
⊢ (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier = {x | ↑h x = ↑g x}

tactic: rintro ⟨a, rfl⟩
state_before: case refine'_1
A B : GroupCat
f : A ⟶ B
b : ↑B
⊢ b ∈ (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier → b ∈ {x | ↑h x = ↑g x}

tactic: change h (f a) = g (f a)
state_before: case refine'_1.intro
A B : GroupCat
f : A ⟶ B
a : ↑A
⊢ ↑f a ∈ {x | ↑h x = ↑g x}

tactic: ext ⟨⟨_, ⟨y, rfl⟩⟩⟩
state_before: case refine'_1.intro
A B : GroupCat
f : A ⟶ B
a : ↑A
⊢ ↑h (↑f a) = ↑g (↑f a)

tactic: rw [g_apply_fromCoset]
state_before: case refine'_1.intro.H.fromCoset.mk.intro
A B : GroupCat
f : A ⟶ B
a : ↑A
y : ↑B
⊢ ↑(↑h (↑f a))
      (fromCoset
        { val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
          property :=
            (_ :
              ∃ y_1,
                Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                  Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) }) =
    ↑(↑g (↑f a))
      (fromCoset
        { val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
          property :=
            (_ :
              ∃ y_1,
                Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                  Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) })

tactic: by_cases m : y ∈ f.range
state_before: case refine'_1.intro.H.fromCoset.mk.intro
A B : GroupCat
f : A ⟶ B
a : ↑A
y : ↑B
⊢ ↑(↑h (↑f a))
      (fromCoset
        { val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
          property :=
            (_ :
              ∃ y_1,
                Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                  Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) }) =
    fromCoset
      {
        val :=
          ↑f a *l
            ↑{ val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
                property :=
                  (_ :
                    ∃ y_1,
                      Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                        Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) },
        property :=
          (_ :
            ↑f a *l
                ↑{ val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
                    property :=
                      (_ :
                        ∃ y_1,
                          Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                            Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) } ∈
              Set.range (Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier)) }

tactic: rw [h_apply_fromCoset' _ _ _ m, fromCoset_eq_of_mem_range _ m]
state_before: case pos
A B : GroupCat
f : A ⟶ B
a : ↑A
y : ↑B
m : y ∈ MonoidHom.range f
⊢ ↑(↑h (↑f a))
      (fromCoset
        { val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
          property :=
            (_ :
              ∃ y_1,
                Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                  Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) }) =
    fromCoset
      {
        val :=
          ↑f a *l
            ↑{ val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
                property :=
                  (_ :
                    ∃ y_1,
                      Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                        Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) },
        property :=
          (_ :
            ↑f a *l
                ↑{ val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
                    property :=
                      (_ :
                        ∃ y_1,
                          Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                            Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) } ∈
              Set.range (Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier)) }

tactic: change fromCoset _ = fromCoset ⟨f a *l (y *l _), _⟩
state_before: case pos
A B : GroupCat
f : A ⟶ B
a : ↑A
y : ↑B
m : y ∈ MonoidHom.range f
⊢ fromCoset
      { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) } =
    fromCoset
      {
        val :=
          ↑f a *l
            ↑{ val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
                property :=
                  (_ :
                    ∃ y_1,
                      Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                        Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) },
        property :=
          (_ :
            ↑f a *l
                ↑{ val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
                    property :=
                      (_ :
                        ∃ y_1,
                          Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                            Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) } ∈
              Set.range (Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier)) }

tactic: simp only [← fromCoset_eq_of_mem_range _ (Subgroup.mul_mem _ ⟨a, rfl⟩ m)]
state_before: case pos
A B : GroupCat
f : A ⟶ B
a : ↑A
y : ↑B
m : y ∈ MonoidHom.range f
⊢ fromCoset
      { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) } =
    fromCoset
      { val := ↑f a *l (y *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier),
        property :=
          (_ :
            ↑f a *l
                ↑{ val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
                    property :=
                      (_ :
                        ∃ y_1,
                          Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                            Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) } ∈
              Set.range (Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier)) }

tactic: congr
state_before: case pos
A B : GroupCat
f : A ⟶ B
a : ↑A
y : ↑B
m : y ∈ MonoidHom.range f
⊢ fromCoset
      { val := ↑f a * y *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y_1,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                ↑f a * y *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) } =
    fromCoset
      { val := ↑f a *l (y *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier),
        property :=
          (_ :
            ↑f a *l
                ↑{ val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
                    property :=
                      (_ :
                        ∃ y_1,
                          Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                            Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) } ∈
              Set.range (Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier)) }

tactic: rw [leftCoset_assoc _ (f a) y]
state_before: case pos.e_a.e_val
A B : GroupCat
f : A ⟶ B
a : ↑A
y : ↑B
m : y ∈ MonoidHom.range f
⊢ ↑f a * y *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier =
    ↑f a *l (y *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier)

tactic: rw [h_apply_fromCoset_nin_range f (f a) ⟨_, rfl⟩ _ m]
state_before: case neg
A B : GroupCat
f : A ⟶ B
a : ↑A
y : ↑B
m : ¬y ∈ MonoidHom.range f
⊢ ↑(↑h (↑f a))
      (fromCoset
        { val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
          property :=
            (_ :
              ∃ y_1,
                Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                  Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) }) =
    fromCoset
      {
        val :=
          ↑f a *l
            ↑{ val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
                property :=
                  (_ :
                    ∃ y_1,
                      Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                        Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) },
        property :=
          (_ :
            ↑f a *l
                ↑{ val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
                    property :=
                      (_ :
                        ∃ y_1,
                          Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                            Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) } ∈
              Set.range (Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier)) }

tactic: simp only [leftCoset_assoc]
state_before: case neg
A B : GroupCat
f : A ⟶ B
a : ↑A
y : ↑B
m : ¬y ∈ MonoidHom.range f
⊢ fromCoset
      { val := ↑f a * y *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y_1,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                ↑f a * y *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) } =
    fromCoset
      {
        val :=
          ↑f a *l
            ↑{ val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
                property :=
                  (_ :
                    ∃ y_1,
                      Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                        Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) },
        property :=
          (_ :
            ↑f a *l
                ↑{ val := Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y,
                    property :=
                      (_ :
                        ∃ y_1,
                          Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y_1 =
                            Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y) } ∈
              Set.range (Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier)) }

tactic: rw [g_apply_infinity, h_apply_infinity f (f a) ⟨_, rfl⟩]
state_before: case refine'_1.intro.H.infinity
A B : GroupCat
f : A ⟶ B
a : ↑A
⊢ ↑(↑h (↑f a)) ∞ = ↑(↑g (↑f a)) ∞

tactic: have eq1 : (h b) (fromCoset ⟨f.range.carrier, ⟨1, one_leftCoset _⟩⟩) =
    fromCoset ⟨f.range.carrier, ⟨1, one_leftCoset _⟩⟩ := by
  change ((τ).symm.trans (g b)).trans τ _ = _
  dsimp [tau]
  simp [g_apply_infinity f]
state_before: case refine'_2
A B : GroupCat
f : A ⟶ B
b : ↑B
hb : ↑h b = ↑g b
r : ¬b ∈ (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier
⊢ False

tactic: have eq2 :
  (g b) (fromCoset ⟨f.range.carrier, ⟨1, one_leftCoset _⟩⟩) =
    fromCoset ⟨b *l f.range.carrier, ⟨b, rfl⟩⟩ := rfl
state_before: case refine'_2
A B : GroupCat
f : A ⟶ B
b : ↑B
hb : ↑h b = ↑g b
r : ¬b ∈ (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier
eq1 :
  ↑(↑h b)
      (fromCoset
        { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
          property :=
            (_ :
              ∃ y,
                Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                  (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }) =
    fromCoset
      { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }
⊢ False

tactic: exact (fromCoset_ne_of_nin_range _ r).symm (by rw [← eq1, ← eq2, FunLike.congr_fun hb])
state_before: case refine'_2
A B : GroupCat
f : A ⟶ B
b : ↑B
hb : ↑h b = ↑g b
r : ¬b ∈ (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier
eq1 :
  ↑(↑h b)
      (fromCoset
        { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
          property :=
            (_ :
              ∃ y,
                Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                  (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }) =
    fromCoset
      { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }
eq2 :
  ↑(↑g b)
      (fromCoset
        { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
          property :=
            (_ :
              ∃ y,
                Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                  (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }) =
    fromCoset
      { val := b *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                b *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }
⊢ False

tactic: change ((τ).symm.trans (g b)).trans τ _ = _
state_before: A B : GroupCat
f : A ⟶ B
b : ↑B
hb : ↑h b = ↑g b
r : ¬b ∈ (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier
⊢ ↑(↑h b)
      (fromCoset
        { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
          property :=
            (_ :
              ∃ y,
                Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                  (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }) =
    fromCoset
      { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }

tactic: dsimp [tau]
state_before: A B : GroupCat
f : A ⟶ B
b : ↑B
hb : ↑h b = ↑g b
r : ¬b ∈ (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier
⊢ ↑((τ.symm.trans (↑g b)).trans τ)
      (fromCoset
        { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
          property :=
            (_ :
              ∃ y,
                Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                  (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }) =
    fromCoset
      { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }

tactic: simp [g_apply_infinity f]
state_before: A B : GroupCat
f : A ⟶ B
b : ↑B
hb : ↑h b = ↑g b
r : ¬b ∈ (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier
⊢ ↑(Equiv.swap
          (fromCoset
            { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
              property :=
                (_ :
                  ∃ y,
                    Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                      (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) })
          ∞)
      (↑(↑g b)
        (↑(Equiv.swap
              (fromCoset
                { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
                  property :=
                    (_ :
                      ∃ y,
                        Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                          (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) })
              ∞)
          (fromCoset
            { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
              property :=
                (_ :
                  ∃ y,
                    Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                      (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }))) =
    fromCoset
      { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }

tactic: rw [← eq1, ← eq2, FunLike.congr_fun hb]
state_before: A B : GroupCat
f : A ⟶ B
b : ↑B
hb : ↑h b = ↑g b
r : ¬b ∈ (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier
eq1 :
  ↑(↑h b)
      (fromCoset
        { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
          property :=
            (_ :
              ∃ y,
                Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                  (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }) =
    fromCoset
      { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }
eq2 :
  ↑(↑g b)
      (fromCoset
        { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
          property :=
            (_ :
              ∃ y,
                Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                  (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }) =
    fromCoset
      { val := b *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                b *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }
⊢ fromCoset
      { val := (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) } =
    fromCoset
      { val := b *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier,
        property :=
          (_ :
            ∃ y,
              Function.swap leftCoset (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier y =
                b *l (MonoidHom.range f).toSubmonoid.toSubsemigroup.carrier) }