l3lab/ntp-mathlib huggingface dataset:
/-- Given `AddCommMonoid M` and `e : α ≃ β`, `domCongr e` is the corresponding `Equiv` between
`α →₀ M` and `β →₀ M`.

This is `Finsupp.equivCongrLeft` as an `AddEquiv`. -/
@[simps apply]
protected def domCongr [AddCommMonoid M] (e : α ≃ β) : (α →₀ M) ≃+ (β →₀ M)
    where
  toFun := equivMapDomain e
  invFun := equivMapDomain e.symm
  left_inv v := by
    simp only [← equivMapDomain_trans, Equiv.self_trans_symm]
    exact equivMapDomain_refl _
  right_inv := by
    intro v
    simp only [← equivMapDomain_trans, Equiv.symm_trans_self]
    exact equivMapDomain_refl _
  map_add' a b := by simp only [equivMapDomain_eq_mapDomain]; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
inst✝ : AddCommMonoid M
e : α ≃ β
a b : α →₀ M
⊢ mapDomain (⇑e) (a + b) = mapDomain (⇑e) a + mapDomain (⇑e) b

Next tactic:
exact mapDomain_add
theorem split_apply (i : ι) (x : αs i) : split l i x = l ⟨i, x⟩ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝ : Zero M
l : (i : ι) × αs i →₀ M
i : ι
x : αs i
⊢ (split l i) x = l { fst := i, snd := x }

Next tactic:
dsimp only [split]
theorem split_apply (i : ι) (x : αs i) : split l i x = l ⟨i, x⟩ := by
  dsimp only [split]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝ : Zero M
l : (i : ι) × αs i →₀ M
i : ι
x : αs i
⊢ (comapDomain (Sigma.mk i) l
        (_ :
          ∀ x ∈ Sigma.mk i ⁻¹' ↑l.support,
            ∀ x_2 ∈ Sigma.mk i ⁻¹' ↑l.support, { fst := i, snd := x } = { fst := i, snd := x_2 } → x = x_2))
      x =
    l { fst := i, snd := x }

Next tactic:
rw [comapDomain_apply]
theorem mem_splitSupport_iff_nonzero (i : ι) : i ∈ splitSupport l ↔ split l i ≠ 0 := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝ : Zero M
l : (i : ι) × αs i →₀ M
i : ι
⊢ i ∈ splitSupport l ↔ split l i ≠ 0

Next tactic:
rw [splitSupport, @mem_image _ _ (Classical.decEq _), Ne.def, ← support_eq_empty, ← Ne.def, ←
    Finset.nonempty_iff_ne_empty, split, comapDomain, Finset.Nonempty]
theorem mem_splitSupport_iff_nonzero (i : ι) : i ∈ splitSupport l ↔ split l i ≠ 0 := by
  rw [splitSupport, @mem_image _ _ (Classical.decEq _), Ne.def, ← support_eq_empty, ← Ne.def, ←
    Finset.nonempty_iff_ne_empty, split, comapDomain, Finset.Nonempty]
  -- porting note: had to add the `Classical.decEq` instance manually
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝ : Zero M
l : (i : ι) × αs i →₀ M
i : ι
⊢ (∃ a ∈ l.support, a.fst = i) ↔
    ∃ x,
      x ∈
        {
            support :=
              preimage l.support (Sigma.mk i)
                (_ :
                  ∀ x ∈ Sigma.mk i ⁻¹' ↑l.support,
                    ∀ x_2 ∈ Sigma.mk i ⁻¹' ↑l.support, { fst := i, snd := x } = { fst := i, snd := x_2 } → x = x_2),
            toFun := fun a => l { fst := i, snd := a },
            mem_support_toFun :=
              (_ :
                ∀ (a : αs i),
                  a ∈
                      preimage l.support (Sigma.mk i)
                        (_ :
                          ∀ x ∈ Sigma.mk i ⁻¹' ↑l.support,
                            ∀ x_2 ∈ Sigma.mk i ⁻¹' ↑l.support,
                              { fst := i, snd := x } = { fst := i, snd := x_2 } → x = x_2) ↔
                    (fun a => l { fst := i, snd := a }) a ≠ 0) }.support

Next tactic:
simp only [exists_prop, Finset.mem_preimage, exists_and_right, exists_eq_right, mem_support_iff,
    Sigma.exists, Ne.def]
/-- Given `l`, a finitely supported function from the sigma type `Σ i, αs i` to `β` and
an `ι`-indexed family `g` of functions from `(αs i →₀ β)` to `γ`, `split_comp` defines a
finitely supported function from the index type `ι` to `γ` given by composing `g i` with
`split l i`. -/
def splitComp [Zero N] (g : ∀ i, (αs i →₀ M) → N) (hg : ∀ i x, x = 0 ↔ g i x = 0) : ι →₀ N
    where
  support := splitSupport l
  toFun i := g i (split l i)
  mem_support_toFun := by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝¹ : Zero M
l : (i : ι) × αs i →₀ M
inst✝ : Zero N
g : (i : ι) → (αs i →₀ M) → N
hg : ∀ (i : ι) (x : αs i →₀ M), x = 0 ↔ g i x = 0
⊢ ∀ (a : ι), a ∈ splitSupport l ↔ (fun i => g i (split l i)) a ≠ 0

Next tactic:
intro i
/-- Given `l`, a finitely supported function from the sigma type `Σ i, αs i` to `β` and
an `ι`-indexed family `g` of functions from `(αs i →₀ β)` to `γ`, `split_comp` defines a
finitely supported function from the index type `ι` to `γ` given by composing `g i` with
`split l i`. -/
def splitComp [Zero N] (g : ∀ i, (αs i →₀ M) → N) (hg : ∀ i x, x = 0 ↔ g i x = 0) : ι →₀ N
    where
  support := splitSupport l
  toFun i := g i (split l i)
  mem_support_toFun := by
    intro i
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝¹ : Zero M
l : (i : ι) × αs i →₀ M
inst✝ : Zero N
g : (i : ι) → (αs i →₀ M) → N
hg : ∀ (i : ι) (x : αs i →₀ M), x = 0 ↔ g i x = 0
i : ι
⊢ i ∈ splitSupport l ↔ (fun i => g i (split l i)) i ≠ 0

Next tactic:
rw [mem_splitSupport_iff_nonzero, not_iff_not, hg]
theorem sigma_support : l.support = l.splitSupport.sigma fun i => (l.split i).support := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝ : Zero M
l : (i : ι) × αs i →₀ M
⊢ l.support = Finset.sigma (splitSupport l) fun i => (split l i).support

Next tactic:
simp only [Finset.ext_iff, splitSupport, split, comapDomain, @mem_image _ _ (Classical.decEq _),
    mem_preimage, Sigma.forall, mem_sigma]
theorem sigma_support : l.support = l.splitSupport.sigma fun i => (l.split i).support := by
  simp only [Finset.ext_iff, splitSupport, split, comapDomain, @mem_image _ _ (Classical.decEq _),
    mem_preimage, Sigma.forall, mem_sigma]
  -- porting note: had to add the `Classical.decEq` instance manually
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝ : Zero M
l : (i : ι) × αs i →₀ M
⊢ ∀ (a : ι) (b : αs a),
    { fst := a, snd := b } ∈ l.support ↔ (∃ a_1 ∈ l.support, a_1.fst = a) ∧ { fst := a, snd := b } ∈ l.support

Next tactic:
tauto
theorem sigma_sum [AddCommMonoid N] (f : (Σi : ι, αs i) → M → N) :
    l.sum f = ∑ i in splitSupport l, (split l i).sum fun (a : αs i) b => f ⟨i, a⟩ b := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝¹ : Zero M
l : (i : ι) × αs i →₀ M
inst✝ : AddCommMonoid N
f : (i : ι) × αs i → M → N
⊢ sum l f = ∑ i in splitSupport l, sum (split l i) fun a b => f { fst := i, snd := a } b

Next tactic:
simp only [sum, sigma_support, sum_sigma, split_apply]
/-- On a `Fintype η`, `Finsupp.split` is an equivalence between `(Σ (j : η), ιs j) →₀ α`
and `Π j, (ιs j →₀ α)`.

This is the `Finsupp` version of `Equiv.Pi_curry`. -/
noncomputable def sigmaFinsuppEquivPiFinsupp : ((Σj, ιs j) →₀ α) ≃ ∀ j, ιs j →₀ α
    where
  toFun := split
  invFun f :=
    onFinset (Finset.univ.sigma fun j => (f j).support) (fun ji => f ji.1 ji.2) fun g hg =>
      Finset.mem_sigma.mpr ⟨Finset.mem_univ _, mem_support_iff.mpr hg⟩
  left_inv f := by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝² : Zero M
l : (i : ι) × αs i →₀ M
η : Type u_14
inst✝¹ : Fintype η
ιs : η → Type u_15
inst✝ : Zero α
f : (j : η) × ιs j →₀ α
⊢ (fun f =>
        onFinset (Finset.sigma univ fun j => (f j).support) (fun ji => (f ji.fst) ji.snd)
          (_ :
            ∀ (g : (j : η) × ιs j), (fun ji => (f ji.fst) ji.snd) g ≠ 0 → g ∈ Finset.sigma univ fun j => (f j).support))
      (split f) =
    f

Next tactic:
ext
/-- On a `Fintype η`, `Finsupp.split` is an equivalence between `(Σ (j : η), ιs j) →₀ α`
and `Π j, (ιs j →₀ α)`.

This is the `Finsupp` version of `Equiv.Pi_curry`. -/
noncomputable def sigmaFinsuppEquivPiFinsupp : ((Σj, ιs j) →₀ α) ≃ ∀ j, ιs j →₀ α
    where
  toFun := split
  invFun f :=
    onFinset (Finset.univ.sigma fun j => (f j).support) (fun ji => f ji.1 ji.2) fun g hg =>
      Finset.mem_sigma.mpr ⟨Finset.mem_univ _, mem_support_iff.mpr hg⟩
  left_inv f := by
    ext
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝² : Zero M
l : (i : ι) × αs i →₀ M
η : Type u_14
inst✝¹ : Fintype η
ιs : η → Type u_15
inst✝ : Zero α
f : (j : η) × ιs j →₀ α
a✝ : (j : η) × ιs j
⊢ ((fun f =>
          onFinset (Finset.sigma univ fun j => (f j).support) (fun ji => (f ji.fst) ji.snd)
            (_ :
              ∀ (g : (j : η) × ιs j),
                (fun ji => (f ji.fst) ji.snd) g ≠ 0 → g ∈ Finset.sigma univ fun j => (f j).support))
        (split f))
      a✝ =
    f a✝

Next tactic:
simp [split]
/-- On a `Fintype η`, `Finsupp.split` is an equivalence between `(Σ (j : η), ιs j) →₀ α`
and `Π j, (ιs j →₀ α)`.

This is the `Finsupp` version of `Equiv.Pi_curry`. -/
noncomputable def sigmaFinsuppEquivPiFinsupp : ((Σj, ιs j) →₀ α) ≃ ∀ j, ιs j →₀ α
    where
  toFun := split
  invFun f :=
    onFinset (Finset.univ.sigma fun j => (f j).support) (fun ji => f ji.1 ji.2) fun g hg =>
      Finset.mem_sigma.mpr ⟨Finset.mem_univ _, mem_support_iff.mpr hg⟩
  left_inv f := by
    ext
    simp [split]
  right_inv f := by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝² : Zero M
l : (i : ι) × αs i →₀ M
η : Type u_14
inst✝¹ : Fintype η
ιs : η → Type u_15
inst✝ : Zero α
f : (j : η) → ιs j →₀ α
⊢ split
      ((fun f =>
          onFinset (Finset.sigma univ fun j => (f j).support) (fun ji => (f ji.fst) ji.snd)
            (_ :
              ∀ (g : (j : η) × ιs j),
                (fun ji => (f ji.fst) ji.snd) g ≠ 0 → g ∈ Finset.sigma univ fun j => (f j).support))
        f) =
    f

Next tactic:
ext
/-- On a `Fintype η`, `Finsupp.split` is an equivalence between `(Σ (j : η), ιs j) →₀ α`
and `Π j, (ιs j →₀ α)`.

This is the `Finsupp` version of `Equiv.Pi_curry`. -/
noncomputable def sigmaFinsuppEquivPiFinsupp : ((Σj, ιs j) →₀ α) ≃ ∀ j, ιs j →₀ α
    where
  toFun := split
  invFun f :=
    onFinset (Finset.univ.sigma fun j => (f j).support) (fun ji => f ji.1 ji.2) fun g hg =>
      Finset.mem_sigma.mpr ⟨Finset.mem_univ _, mem_support_iff.mpr hg⟩
  left_inv f := by
    ext
    simp [split]
  right_inv f := by
    ext
    

Proof state:
case h.h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝² : Zero M
l : (i : ι) × αs i →₀ M
η : Type u_14
inst✝¹ : Fintype η
ιs : η → Type u_15
inst✝ : Zero α
f : (j : η) → ιs j →₀ α
x✝ : η
a✝ : ιs x✝
⊢ (split
        ((fun f =>
            onFinset (Finset.sigma univ fun j => (f j).support) (fun ji => (f ji.fst) ji.snd)
              (_ :
                ∀ (g : (j : η) × ιs j),
                  (fun ji => (f ji.fst) ji.snd) g ≠ 0 → g ∈ Finset.sigma univ fun j => (f j).support))
          f)
        x✝)
      a✝ =
    (f x✝) a✝

Next tactic:
simp [split]
/-- On a `Fintype η`, `Finsupp.split` is an additive equivalence between
`(Σ (j : η), ιs j) →₀ α` and `Π j, (ιs j →₀ α)`.

This is the `AddEquiv` version of `Finsupp.sigmaFinsuppEquivPiFinsupp`.
-/
noncomputable def sigmaFinsuppAddEquivPiFinsupp {α : Type*} {ιs : η → Type*} [AddMonoid α] :
    ((Σj, ιs j) →₀ α) ≃+ ∀ j, ιs j →₀ α :=
  { sigmaFinsuppEquivPiFinsupp with
    map_add' := fun f g => by
      

Proof state:
α✝ : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝³ : Zero M
l : (i : ι) × αs i →₀ M
η : Type u_14
inst✝² : Fintype η
ιs✝ : η → Type u_15
inst✝¹ : Zero α✝
α : Type u_16
ιs : η → Type u_17
inst✝ : AddMonoid α
src✝ : ((j : η) × ιs j →₀ α) ≃ ((j : η) → ιs j →₀ α) := sigmaFinsuppEquivPiFinsupp
f g : (j : η) × ιs j →₀ α
⊢ Equiv.toFun
      { toFun := src✝.toFun, invFun := src✝.invFun, left_inv := (_ : LeftInverse src✝.invFun src✝.toFun),
        right_inv := (_ : Function.RightInverse src✝.invFun src✝.toFun) }
      (f + g) =
    Equiv.toFun
        { toFun := src✝.toFun, invFun := src✝.invFun, left_inv := (_ : LeftInverse src✝.invFun src✝.toFun),
          right_inv := (_ : Function.RightInverse src✝.invFun src✝.toFun) }
        f +
      Equiv.toFun
        { toFun := src✝.toFun, invFun := src✝.invFun, left_inv := (_ : LeftInverse src✝.invFun src✝.toFun),
          right_inv := (_ : Function.RightInverse src✝.invFun src✝.toFun) }
        g

Next tactic:
ext
/-- On a `Fintype η`, `Finsupp.split` is an additive equivalence between
`(Σ (j : η), ιs j) →₀ α` and `Π j, (ιs j →₀ α)`.

This is the `AddEquiv` version of `Finsupp.sigmaFinsuppEquivPiFinsupp`.
-/
noncomputable def sigmaFinsuppAddEquivPiFinsupp {α : Type*} {ιs : η → Type*} [AddMonoid α] :
    ((Σj, ιs j) →₀ α) ≃+ ∀ j, ιs j →₀ α :=
  { sigmaFinsuppEquivPiFinsupp with
    map_add' := fun f g => by
      ext
      

Proof state:
case h.h
α✝ : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
M : Type u_5
M' : Type u_6
N : Type u_7
P : Type u_8
G : Type u_9
H : Type u_10
R : Type u_11
S : Type u_12
αs : ι → Type u_13
inst✝³ : Zero M
l : (i : ι) × αs i →₀ M
η : Type u_14
inst✝² : Fintype η
ιs✝ : η → Type u_15
inst✝¹ : Zero α✝
α : Type u_16
ιs : η → Type u_17
inst✝ : AddMonoid α
src✝ : ((j : η) × ιs j →₀ α) ≃ ((j : η) → ιs j →₀ α) := sigmaFinsuppEquivPiFinsupp
f g : (j : η) × ιs j →₀ α
x✝ : η
a✝ : ιs x✝
⊢ (Equiv.toFun
        { toFun := src✝.toFun, invFun := src✝.invFun, left_inv := (_ : LeftInverse src✝.invFun src✝.toFun),
          right_inv := (_ : Function.RightInverse src✝.invFun src✝.toFun) }
        (f + g) x✝)
      a✝ =
    ((Equiv.toFun
            { toFun := src✝.toFun, invFun := src✝.invFun, left_inv := (_ : LeftInverse src✝.invFun src✝.toFun),
              right_inv := (_ : Function.RightInverse src✝.invFun src✝.toFun) }
            f +
          Equiv.toFun
            { toFun := src✝.toFun, invFun := src✝.invFun, left_inv := (_ : LeftInverse src✝.invFun src✝.toFun),
              right_inv := (_ : Function.RightInverse src✝.invFun src✝.toFun) }
            g)
        x✝)
      a✝

Next tactic:
simp
theorem embeddingPiTangent_injOn : InjOn f.embeddingPiTangent s := by
  

Proof state:
ι : Type uι
E : Type uE
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type uH
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type uM
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SmoothManifoldWithCorners I M
inst✝ : T2Space M
hi : Fintype ι
s : Set M
f : SmoothBumpCovering ι I M s
⊢ InjOn (⇑(embeddingPiTangent f)) s

Next tactic:
intro x hx y _ h
theorem embeddingPiTangent_injOn : InjOn f.embeddingPiTangent s := by
  intro x hx y _ h
  

Proof state:
ι : Type uι
E : Type uE
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type uH
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type uM
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SmoothManifoldWithCorners I M
inst✝ : T2Space M
hi : Fintype ι
s : Set M
f : SmoothBumpCovering ι I M s
x : M
hx : x ∈ s
y : M
a✝ : y ∈ s
h : (embeddingPiTangent f) x = (embeddingPiTangent f) y
⊢ x = y

Next tactic:
simp only [embeddingPiTangent_coe, funext_iff] at h
theorem embeddingPiTangent_injOn : InjOn f.embeddingPiTangent s := by
  intro x hx y _ h
  simp only [embeddingPiTangent_coe, funext_iff] at h
  

Proof state:
ι : Type uι
E : Type uE
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type uH
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type uM
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SmoothManifoldWithCorners I M
inst✝ : T2Space M
hi : Fintype ι
s : Set M
f : SmoothBumpCovering ι I M s
x : M
hx : x ∈ s
y : M
a✝ : y ∈ s
h :
  ∀ (a : ι),
    (↑(toFun s f a) x • ↑(extChartAt I (c s f a)) x, ↑(toFun s f a) x) =
      (↑(toFun s f a) y • ↑(extChartAt I (c s f a)) y, ↑(toFun s f a) y)
⊢ x = y

Next tactic:
obtain ⟨h₁, h₂⟩ := Prod.mk.inj_iff.1 (h (f.ind x hx))
theorem embeddingPiTangent_injOn : InjOn f.embeddingPiTangent s := by
  intro x hx y _ h
  simp only [embeddingPiTangent_coe, funext_iff] at h
  obtain ⟨h₁, h₂⟩ := Prod.mk.inj_iff.1 (h (f.ind x hx))
  

Proof state:
case intro
ι : Type uι
E : Type uE
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type uH
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type uM
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SmoothManifoldWithCorners I M
inst✝ : T2Space M
hi : Fintype ι
s : Set M
f : SmoothBumpCovering ι I M s
x : M
hx : x ∈ s
y : M
a✝ : y ∈ s
h :
  ∀ (a : ι),
    (↑(toFun s f a) x • ↑(extChartAt I (c s f a)) x, ↑(toFun s f a) x) =
      (↑(toFun s f a) y • ↑(extChartAt I (c s f a)) y, ↑(toFun s f a) y)
h₁ :
  ↑(toFun s f (ind f x hx)) x • ↑(extChartAt I (c s f (ind f x hx))) x =
    ↑(toFun s f (ind f x hx)) y • ↑(extChartAt I (c s f (ind f x hx))) y
h₂ : ↑(toFun s f (ind f x hx)) x = ↑(toFun s f (ind f x hx)) y
⊢ x = y

Next tactic:
rw [f.apply_ind x hx] at h₂
theorem embeddingPiTangent_injOn : InjOn f.embeddingPiTangent s := by
  intro x hx y _ h
  simp only [embeddingPiTangent_coe, funext_iff] at h
  obtain ⟨h₁, h₂⟩ := Prod.mk.inj_iff.1 (h (f.ind x hx))
  rw [f.apply_ind x hx] at h₂
  

Proof state:
case intro
ι : Type uι
E : Type uE
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type uH
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type uM
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SmoothManifoldWithCorners I M
inst✝ : T2Space M
hi : Fintype ι
s : Set M
f : SmoothBumpCovering ι I M s
x : M
hx : x ∈ s
y : M
a✝ : y ∈ s
h :
  ∀ (a : ι),
    (↑(toFun s f a) x • ↑(extChartAt I (c s f a)) x, ↑(toFun s f a) x) =
      (↑(toFun s f a) y • ↑(extChartAt I (c s f a)) y, ↑(toFun s f a) y)
h₁ :
  ↑(toFun s f (ind f x hx)) x • ↑(extChartAt I (c s f (ind f x hx))) x =
    ↑(toFun s f (ind f x hx)) y • ↑(extChartAt I (c s f (ind f x hx))) y
h₂ : 1 = ↑(toFun s f (ind f x hx)) y
⊢ x = y

Next tactic:
rw [← h₂, f.apply_ind x hx, one_smul, one_smul] at h₁
theorem embeddingPiTangent_injOn : InjOn f.embeddingPiTangent s := by
  intro x hx y _ h
  simp only [embeddingPiTangent_coe, funext_iff] at h
  obtain ⟨h₁, h₂⟩ := Prod.mk.inj_iff.1 (h (f.ind x hx))
  rw [f.apply_ind x hx] at h₂
  rw [← h₂, f.apply_ind x hx, one_smul, one_smul] at h₁
  

Proof state:
case intro
ι : Type uι
E : Type uE
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type uH
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type uM
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SmoothManifoldWithCorners I M
inst✝ : T2Space M
hi : Fintype ι
s : Set M
f : SmoothBumpCovering ι I M s
x : M
hx : x ∈ s
y : M
a✝ : y ∈ s
h :
  ∀ (a : ι),
    (↑(toFun s f a) x • ↑(extChartAt I (c s f a)) x, ↑(toFun s f a) x) =
      (↑(toFun s f a) y • ↑(extChartAt I (c s f a)) y, ↑(toFun s f a) y)
h₁ : ↑(extChartAt I (c s f (ind f x hx))) x = ↑(extChartAt I (c s f (ind f x hx))) y
h₂ : 1 = ↑(toFun s f (ind f x hx)) y
⊢ x = y

Next tactic:
have := f.mem_extChartAt_source_of_eq_one h₂.symm
theorem embeddingPiTangent_injOn : InjOn f.embeddingPiTangent s := by
  intro x hx y _ h
  simp only [embeddingPiTangent_coe, funext_iff] at h
  obtain ⟨h₁, h₂⟩ := Prod.mk.inj_iff.1 (h (f.ind x hx))
  rw [f.apply_ind x hx] at h₂
  rw [← h₂, f.apply_ind x hx, one_smul, one_smul] at h₁
  have := f.mem_extChartAt_source_of_eq_one h₂.symm
  

Proof state:
case intro
ι : Type uι
E : Type uE
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type uH
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type uM
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SmoothManifoldWithCorners I M
inst✝ : T2Space M
hi : Fintype ι
s : Set M
f : SmoothBumpCovering ι I M s
x : M
hx : x ∈ s
y : M
a✝ : y ∈ s
h :
  ∀ (a : ι),
    (↑(toFun s f a) x • ↑(extChartAt I (c s f a)) x, ↑(toFun s f a) x) =
      (↑(toFun s f a) y • ↑(extChartAt I (c s f a)) y, ↑(toFun s f a) y)
h₁ : ↑(extChartAt I (c s f (ind f x hx))) x = ↑(extChartAt I (c s f (ind f x hx))) y
h₂ : 1 = ↑(toFun s f (ind f x hx)) y
this : y ∈ (extChartAt I (c s f (ind f x hx))).source
⊢ x = y

Next tactic:
exact (extChartAt I (f.c _)).injOn (f.mem_extChartAt_ind_source x hx) this h₁
theorem comp_embeddingPiTangent_mfderiv (x : M) (hx : x ∈ s) :
    ((ContinuousLinearMap.fst ℝ E ℝ).comp
            (@ContinuousLinearMap.proj ℝ _ ι (fun _ => E × ℝ) _ _ (fun _ => inferInstance)
              (f.ind x hx))).comp
        (mfderiv I 𝓘(ℝ, ι → E × ℝ) f.embeddingPiTangent x) =
      mfderiv I I (chartAt H (f.c (f.ind x hx))) x := by
  

Proof state:
ι : Type uι
E : Type uE
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type uH
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type uM
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SmoothManifoldWithCorners I M
inst✝ : T2Space M
hi : Fintype ι
s : Set M
f : SmoothBumpCovering ι I M s
x : M
hx : x ∈ s
⊢ ContinuousLinearMap.comp
      (ContinuousLinearMap.comp (ContinuousLinearMap.fst ℝ E ℝ) (ContinuousLinearMap.proj (ind f x hx)))
      (mfderiv I 𝓘(ℝ, ι → E × ℝ) (⇑(embeddingPiTangent f)) x) =
    mfderiv I I (↑(chartAt H (c s f (ind f x hx)))) x

Next tactic:
set L :=
    (ContinuousLinearMap.fst ℝ E ℝ).comp
      (@ContinuousLinearMap.proj ℝ _ ι (fun _ => E × ℝ) _ _ (fun _ => inferInstance) (f.ind x hx))
theorem comp_embeddingPiTangent_mfderiv (x : M) (hx : x ∈ s) :
    ((ContinuousLinearMap.fst ℝ E ℝ).comp
            (@ContinuousLinearMap.proj ℝ _ ι (fun _ => E × ℝ) _ _ (fun _ => inferInstance)
              (f.ind x hx))).comp
        (mfderiv I 𝓘(ℝ, ι → E × ℝ) f.embeddingPiTangent x) =
      mfderiv I I (chartAt H (f.c (f.ind x hx))) x := by
  set L :=
    (ContinuousLinearMap.fst ℝ E ℝ).comp
      (@ContinuousLinearMap.proj ℝ _ ι (fun _ => E × ℝ) _ _ (fun _ => inferInstance) (f.ind x hx))
  

Proof state:
ι : Type uι
E : Type uE
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type uH
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type uM
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SmoothManifoldWithCorners I M
inst✝ : T2Space M
hi : Fintype ι
s : Set M
f : SmoothBumpCovering ι I M s
x : M
hx : x ∈ s
L : (ι → E × ℝ) →L[ℝ] E :=
  ContinuousLinearMap.comp (ContinuousLinearMap.fst ℝ E ℝ) (ContinuousLinearMap.proj (ind f x hx))
⊢ ContinuousLinearMap.comp L (mfderiv I 𝓘(ℝ, ι → E × ℝ) (⇑(embeddingPiTangent f)) x) =
    mfderiv I I (↑(chartAt H (c s f (ind f x hx)))) x

Next tactic:
have := L.hasMFDerivAt.comp x f.embeddingPiTangent.smooth.mdifferentiableAt.hasMFDerivAt