l3lab/ntp-mathlib huggingface dataset:
/-- Given two multilinear maps `(ι₁ → N) → N₁` and `(ι₂ → N) → N₂`, this produces the map
`(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂` by taking the coproduct of the domain and the tensor product
of the codomain.

This can be thought of as combining `Equiv.sumArrowEquivProdArrow.symm` with
`TensorProduct.map`, noting that the two operations can't be separated as the intermediate result
is not a `MultilinearMap`.

While this can be generalized to work for dependent `Π i : ι₁, N'₁ i` instead of `ι₁ → N`, doing so
introduces `Sum.elim N'₁ N'₂` types in the result which are difficult to work with and not defeq
to the simple case defined here. See [this zulip thread](
https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there.20code.20for.20X.3F/topic/Instances.20on.20.60sum.2Eelim.20A.20B.20i.60/near/218484619).
-/
@[simps apply]
def domCoprod (a : MultilinearMap R (fun _ : ι₁ => N) N₁)
    (b : MultilinearMap R (fun _ : ι₂ => N) N₂) :
    MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) where
  toFun v := (a fun i => v (Sum.inl i)) ⊗ₜ b fun i => v (Sum.inr i)
  map_add' _ i p q := by
    letI := (@Sum.inl_injective ι₁ ι₂).decidableEq
    letI := (@Sum.inr_injective ι₁ ι₂).decidableEq
    cases i <;> 

Proof state:
case inr
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁷ : CommSemiring R
N₁ : Type u_6
inst✝⁶ : AddCommMonoid N₁
inst✝⁵ : Module R N₁
N₂ : Type u_7
inst✝⁴ : AddCommMonoid N₂
inst✝³ : Module R N₂
N : Type u_8
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
a : MultilinearMap R (fun x => N) N₁
b : MultilinearMap R (fun x => N) N₂
inst✝ : DecidableEq (ι₁ ⊕ ι₂)
x✝ : ι₁ ⊕ ι₂ → N
p q : N
this✝ : DecidableEq ι₁ := Function.Injective.decidableEq (_ : Function.Injective Sum.inl)
this : DecidableEq ι₂ := Function.Injective.decidableEq (_ : Function.Injective Sum.inr)
val✝ : ι₂
⊢ (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ (Sum.inr val✝) (p + q)) =
    (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ (Sum.inr val✝) p) +
      (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ (Sum.inr val✝) q)

Next tactic:
simp [TensorProduct.add_tmul, TensorProduct.tmul_add]
/-- Given two multilinear maps `(ι₁ → N) → N₁` and `(ι₂ → N) → N₂`, this produces the map
`(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂` by taking the coproduct of the domain and the tensor product
of the codomain.

This can be thought of as combining `Equiv.sumArrowEquivProdArrow.symm` with
`TensorProduct.map`, noting that the two operations can't be separated as the intermediate result
is not a `MultilinearMap`.

While this can be generalized to work for dependent `Π i : ι₁, N'₁ i` instead of `ι₁ → N`, doing so
introduces `Sum.elim N'₁ N'₂` types in the result which are difficult to work with and not defeq
to the simple case defined here. See [this zulip thread](
https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there.20code.20for.20X.3F/topic/Instances.20on.20.60sum.2Eelim.20A.20B.20i.60/near/218484619).
-/
@[simps apply]
def domCoprod (a : MultilinearMap R (fun _ : ι₁ => N) N₁)
    (b : MultilinearMap R (fun _ : ι₂ => N) N₂) :
    MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) where
  toFun v := (a fun i => v (Sum.inl i)) ⊗ₜ b fun i => v (Sum.inr i)
  map_add' _ i p q := by
    letI := (@Sum.inl_injective ι₁ ι₂).decidableEq
    letI := (@Sum.inr_injective ι₁ ι₂).decidableEq
    cases i <;> simp [TensorProduct.add_tmul, TensorProduct.tmul_add]
  map_smul' _ i c p := by
    

Proof state:
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁷ : CommSemiring R
N₁ : Type u_6
inst✝⁶ : AddCommMonoid N₁
inst✝⁵ : Module R N₁
N₂ : Type u_7
inst✝⁴ : AddCommMonoid N₂
inst✝³ : Module R N₂
N : Type u_8
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
a : MultilinearMap R (fun x => N) N₁
b : MultilinearMap R (fun x => N) N₂
inst✝ : DecidableEq (ι₁ ⊕ ι₂)
x✝ : ι₁ ⊕ ι₂ → N
i : ι₁ ⊕ ι₂
c : R
p : N
⊢ (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ i (c • p)) =
    c • (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ i p)

Next tactic:
letI := (@Sum.inl_injective ι₁ ι₂).decidableEq
/-- Given two multilinear maps `(ι₁ → N) → N₁` and `(ι₂ → N) → N₂`, this produces the map
`(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂` by taking the coproduct of the domain and the tensor product
of the codomain.

This can be thought of as combining `Equiv.sumArrowEquivProdArrow.symm` with
`TensorProduct.map`, noting that the two operations can't be separated as the intermediate result
is not a `MultilinearMap`.

While this can be generalized to work for dependent `Π i : ι₁, N'₁ i` instead of `ι₁ → N`, doing so
introduces `Sum.elim N'₁ N'₂` types in the result which are difficult to work with and not defeq
to the simple case defined here. See [this zulip thread](
https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there.20code.20for.20X.3F/topic/Instances.20on.20.60sum.2Eelim.20A.20B.20i.60/near/218484619).
-/
@[simps apply]
def domCoprod (a : MultilinearMap R (fun _ : ι₁ => N) N₁)
    (b : MultilinearMap R (fun _ : ι₂ => N) N₂) :
    MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) where
  toFun v := (a fun i => v (Sum.inl i)) ⊗ₜ b fun i => v (Sum.inr i)
  map_add' _ i p q := by
    letI := (@Sum.inl_injective ι₁ ι₂).decidableEq
    letI := (@Sum.inr_injective ι₁ ι₂).decidableEq
    cases i <;> simp [TensorProduct.add_tmul, TensorProduct.tmul_add]
  map_smul' _ i c p := by
    letI := (@Sum.inl_injective ι₁ ι₂).decidableEq
    

Proof state:
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁷ : CommSemiring R
N₁ : Type u_6
inst✝⁶ : AddCommMonoid N₁
inst✝⁵ : Module R N₁
N₂ : Type u_7
inst✝⁴ : AddCommMonoid N₂
inst✝³ : Module R N₂
N : Type u_8
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
a : MultilinearMap R (fun x => N) N₁
b : MultilinearMap R (fun x => N) N₂
inst✝ : DecidableEq (ι₁ ⊕ ι₂)
x✝ : ι₁ ⊕ ι₂ → N
i : ι₁ ⊕ ι₂
c : R
p : N
this : DecidableEq ι₁ := Function.Injective.decidableEq (_ : Function.Injective Sum.inl)
⊢ (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ i (c • p)) =
    c • (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ i p)

Next tactic:
letI := (@Sum.inr_injective ι₁ ι₂).decidableEq
/-- Given two multilinear maps `(ι₁ → N) → N₁` and `(ι₂ → N) → N₂`, this produces the map
`(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂` by taking the coproduct of the domain and the tensor product
of the codomain.

This can be thought of as combining `Equiv.sumArrowEquivProdArrow.symm` with
`TensorProduct.map`, noting that the two operations can't be separated as the intermediate result
is not a `MultilinearMap`.

While this can be generalized to work for dependent `Π i : ι₁, N'₁ i` instead of `ι₁ → N`, doing so
introduces `Sum.elim N'₁ N'₂` types in the result which are difficult to work with and not defeq
to the simple case defined here. See [this zulip thread](
https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there.20code.20for.20X.3F/topic/Instances.20on.20.60sum.2Eelim.20A.20B.20i.60/near/218484619).
-/
@[simps apply]
def domCoprod (a : MultilinearMap R (fun _ : ι₁ => N) N₁)
    (b : MultilinearMap R (fun _ : ι₂ => N) N₂) :
    MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) where
  toFun v := (a fun i => v (Sum.inl i)) ⊗ₜ b fun i => v (Sum.inr i)
  map_add' _ i p q := by
    letI := (@Sum.inl_injective ι₁ ι₂).decidableEq
    letI := (@Sum.inr_injective ι₁ ι₂).decidableEq
    cases i <;> simp [TensorProduct.add_tmul, TensorProduct.tmul_add]
  map_smul' _ i c p := by
    letI := (@Sum.inl_injective ι₁ ι₂).decidableEq
    letI := (@Sum.inr_injective ι₁ ι₂).decidableEq
    

Proof state:
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁷ : CommSemiring R
N₁ : Type u_6
inst✝⁶ : AddCommMonoid N₁
inst✝⁵ : Module R N₁
N₂ : Type u_7
inst✝⁴ : AddCommMonoid N₂
inst✝³ : Module R N₂
N : Type u_8
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
a : MultilinearMap R (fun x => N) N₁
b : MultilinearMap R (fun x => N) N₂
inst✝ : DecidableEq (ι₁ ⊕ ι₂)
x✝ : ι₁ ⊕ ι₂ → N
i : ι₁ ⊕ ι₂
c : R
p : N
this✝ : DecidableEq ι₁ := Function.Injective.decidableEq (_ : Function.Injective Sum.inl)
this : DecidableEq ι₂ := Function.Injective.decidableEq (_ : Function.Injective Sum.inr)
⊢ (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ i (c • p)) =
    c • (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ i p)

Next tactic:
cases i
/-- Given two multilinear maps `(ι₁ → N) → N₁` and `(ι₂ → N) → N₂`, this produces the map
`(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂` by taking the coproduct of the domain and the tensor product
of the codomain.

This can be thought of as combining `Equiv.sumArrowEquivProdArrow.symm` with
`TensorProduct.map`, noting that the two operations can't be separated as the intermediate result
is not a `MultilinearMap`.

While this can be generalized to work for dependent `Π i : ι₁, N'₁ i` instead of `ι₁ → N`, doing so
introduces `Sum.elim N'₁ N'₂` types in the result which are difficult to work with and not defeq
to the simple case defined here. See [this zulip thread](
https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there.20code.20for.20X.3F/topic/Instances.20on.20.60sum.2Eelim.20A.20B.20i.60/near/218484619).
-/
@[simps apply]
def domCoprod (a : MultilinearMap R (fun _ : ι₁ => N) N₁)
    (b : MultilinearMap R (fun _ : ι₂ => N) N₂) :
    MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) where
  toFun v := (a fun i => v (Sum.inl i)) ⊗ₜ b fun i => v (Sum.inr i)
  map_add' _ i p q := by
    letI := (@Sum.inl_injective ι₁ ι₂).decidableEq
    letI := (@Sum.inr_injective ι₁ ι₂).decidableEq
    cases i <;> simp [TensorProduct.add_tmul, TensorProduct.tmul_add]
  map_smul' _ i c p := by
    letI := (@Sum.inl_injective ι₁ ι₂).decidableEq
    letI := (@Sum.inr_injective ι₁ ι₂).decidableEq
    cases i <;> 

Proof state:
case inl
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁷ : CommSemiring R
N₁ : Type u_6
inst✝⁶ : AddCommMonoid N₁
inst✝⁵ : Module R N₁
N₂ : Type u_7
inst✝⁴ : AddCommMonoid N₂
inst✝³ : Module R N₂
N : Type u_8
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
a : MultilinearMap R (fun x => N) N₁
b : MultilinearMap R (fun x => N) N₂
inst✝ : DecidableEq (ι₁ ⊕ ι₂)
x✝ : ι₁ ⊕ ι₂ → N
c : R
p : N
this✝ : DecidableEq ι₁ := Function.Injective.decidableEq (_ : Function.Injective Sum.inl)
this : DecidableEq ι₂ := Function.Injective.decidableEq (_ : Function.Injective Sum.inr)
val✝ : ι₁
⊢ (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ (Sum.inl val✝) (c • p)) =
    c • (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ (Sum.inl val✝) p)

Next tactic:
simp [TensorProduct.smul_tmul', TensorProduct.tmul_smul]
/-- Given two multilinear maps `(ι₁ → N) → N₁` and `(ι₂ → N) → N₂`, this produces the map
`(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂` by taking the coproduct of the domain and the tensor product
of the codomain.

This can be thought of as combining `Equiv.sumArrowEquivProdArrow.symm` with
`TensorProduct.map`, noting that the two operations can't be separated as the intermediate result
is not a `MultilinearMap`.

While this can be generalized to work for dependent `Π i : ι₁, N'₁ i` instead of `ι₁ → N`, doing so
introduces `Sum.elim N'₁ N'₂` types in the result which are difficult to work with and not defeq
to the simple case defined here. See [this zulip thread](
https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there.20code.20for.20X.3F/topic/Instances.20on.20.60sum.2Eelim.20A.20B.20i.60/near/218484619).
-/
@[simps apply]
def domCoprod (a : MultilinearMap R (fun _ : ι₁ => N) N₁)
    (b : MultilinearMap R (fun _ : ι₂ => N) N₂) :
    MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) where
  toFun v := (a fun i => v (Sum.inl i)) ⊗ₜ b fun i => v (Sum.inr i)
  map_add' _ i p q := by
    letI := (@Sum.inl_injective ι₁ ι₂).decidableEq
    letI := (@Sum.inr_injective ι₁ ι₂).decidableEq
    cases i <;> simp [TensorProduct.add_tmul, TensorProduct.tmul_add]
  map_smul' _ i c p := by
    letI := (@Sum.inl_injective ι₁ ι₂).decidableEq
    letI := (@Sum.inr_injective ι₁ ι₂).decidableEq
    cases i <;> 

Proof state:
case inr
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁷ : CommSemiring R
N₁ : Type u_6
inst✝⁶ : AddCommMonoid N₁
inst✝⁵ : Module R N₁
N₂ : Type u_7
inst✝⁴ : AddCommMonoid N₂
inst✝³ : Module R N₂
N : Type u_8
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
a : MultilinearMap R (fun x => N) N₁
b : MultilinearMap R (fun x => N) N₂
inst✝ : DecidableEq (ι₁ ⊕ ι₂)
x✝ : ι₁ ⊕ ι₂ → N
c : R
p : N
this✝ : DecidableEq ι₁ := Function.Injective.decidableEq (_ : Function.Injective Sum.inl)
this : DecidableEq ι₂ := Function.Injective.decidableEq (_ : Function.Injective Sum.inr)
val✝ : ι₂
⊢ (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ (Sum.inr val✝) (c • p)) =
    c • (fun v => (a fun i => v (Sum.inl i)) ⊗ₜ[R] b fun i => v (Sum.inr i)) (Function.update x✝ (Sum.inr val✝) p)

Next tactic:
simp [TensorProduct.smul_tmul', TensorProduct.tmul_smul]
/-- A more bundled version of `MultilinearMap.domCoprod` that maps
`((ι₁ → N) → N₁) ⊗ ((ι₂ → N) → N₂)` to `(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂`. -/
def domCoprod' :
    MultilinearMap R (fun _ : ι₁ => N) N₁ ⊗[R] MultilinearMap R (fun _ : ι₂ => N) N₂ →ₗ[R]
      MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) :=
  TensorProduct.lift <|
    LinearMap.mk₂ R domCoprod
      (fun m₁ m₂ n => by
        

Proof state:
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁶ : CommSemiring R
N₁ : Type u_6
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : Module R N₁
N₂ : Type u_7
inst✝³ : AddCommMonoid N₂
inst✝² : Module R N₂
N : Type u_8
inst✝¹ : AddCommMonoid N
inst✝ : Module R N
m₁ m₂ : MultilinearMap R (fun x => N) N₁
n : MultilinearMap R (fun x => N) N₂
⊢ domCoprod (m₁ + m₂) n = domCoprod m₁ n + domCoprod m₂ n

Next tactic:
ext
/-- A more bundled version of `MultilinearMap.domCoprod` that maps
`((ι₁ → N) → N₁) ⊗ ((ι₂ → N) → N₂)` to `(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂`. -/
def domCoprod' :
    MultilinearMap R (fun _ : ι₁ => N) N₁ ⊗[R] MultilinearMap R (fun _ : ι₂ => N) N₂ →ₗ[R]
      MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) :=
  TensorProduct.lift <|
    LinearMap.mk₂ R domCoprod
      (fun m₁ m₂ n => by
        ext
        

Proof state:
case H
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁶ : CommSemiring R
N₁ : Type u_6
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : Module R N₁
N₂ : Type u_7
inst✝³ : AddCommMonoid N₂
inst✝² : Module R N₂
N : Type u_8
inst✝¹ : AddCommMonoid N
inst✝ : Module R N
m₁ m₂ : MultilinearMap R (fun x => N) N₁
n : MultilinearMap R (fun x => N) N₂
x✝ : ι₁ ⊕ ι₂ → N
⊢ (domCoprod (m₁ + m₂) n) x✝ = (domCoprod m₁ n + domCoprod m₂ n) x✝

Next tactic:
simp only [domCoprod_apply, TensorProduct.add_tmul, add_apply]
/-- A more bundled version of `MultilinearMap.domCoprod` that maps
`((ι₁ → N) → N₁) ⊗ ((ι₂ → N) → N₂)` to `(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂`. -/
def domCoprod' :
    MultilinearMap R (fun _ : ι₁ => N) N₁ ⊗[R] MultilinearMap R (fun _ : ι₂ => N) N₂ →ₗ[R]
      MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) :=
  TensorProduct.lift <|
    LinearMap.mk₂ R domCoprod
      (fun m₁ m₂ n => by
        ext
        simp only [domCoprod_apply, TensorProduct.add_tmul, add_apply])
      (fun c m n => by
        

Proof state:
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁶ : CommSemiring R
N₁ : Type u_6
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : Module R N₁
N₂ : Type u_7
inst✝³ : AddCommMonoid N₂
inst✝² : Module R N₂
N : Type u_8
inst✝¹ : AddCommMonoid N
inst✝ : Module R N
c : R
m : MultilinearMap R (fun x => N) N₁
n : MultilinearMap R (fun x => N) N₂
⊢ domCoprod (c • m) n = c • domCoprod m n

Next tactic:
ext
/-- A more bundled version of `MultilinearMap.domCoprod` that maps
`((ι₁ → N) → N₁) ⊗ ((ι₂ → N) → N₂)` to `(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂`. -/
def domCoprod' :
    MultilinearMap R (fun _ : ι₁ => N) N₁ ⊗[R] MultilinearMap R (fun _ : ι₂ => N) N₂ →ₗ[R]
      MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) :=
  TensorProduct.lift <|
    LinearMap.mk₂ R domCoprod
      (fun m₁ m₂ n => by
        ext
        simp only [domCoprod_apply, TensorProduct.add_tmul, add_apply])
      (fun c m n => by
        ext
        

Proof state:
case H
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁶ : CommSemiring R
N₁ : Type u_6
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : Module R N₁
N₂ : Type u_7
inst✝³ : AddCommMonoid N₂
inst✝² : Module R N₂
N : Type u_8
inst✝¹ : AddCommMonoid N
inst✝ : Module R N
c : R
m : MultilinearMap R (fun x => N) N₁
n : MultilinearMap R (fun x => N) N₂
x✝ : ι₁ ⊕ ι₂ → N
⊢ (domCoprod (c • m) n) x✝ = (c • domCoprod m n) x✝

Next tactic:
simp only [domCoprod_apply, TensorProduct.smul_tmul', smul_apply]
/-- A more bundled version of `MultilinearMap.domCoprod` that maps
`((ι₁ → N) → N₁) ⊗ ((ι₂ → N) → N₂)` to `(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂`. -/
def domCoprod' :
    MultilinearMap R (fun _ : ι₁ => N) N₁ ⊗[R] MultilinearMap R (fun _ : ι₂ => N) N₂ →ₗ[R]
      MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) :=
  TensorProduct.lift <|
    LinearMap.mk₂ R domCoprod
      (fun m₁ m₂ n => by
        ext
        simp only [domCoprod_apply, TensorProduct.add_tmul, add_apply])
      (fun c m n => by
        ext
        simp only [domCoprod_apply, TensorProduct.smul_tmul', smul_apply])
      (fun m n₁ n₂ => by
        

Proof state:
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁶ : CommSemiring R
N₁ : Type u_6
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : Module R N₁
N₂ : Type u_7
inst✝³ : AddCommMonoid N₂
inst✝² : Module R N₂
N : Type u_8
inst✝¹ : AddCommMonoid N
inst✝ : Module R N
m : MultilinearMap R (fun x => N) N₁
n₁ n₂ : MultilinearMap R (fun x => N) N₂
⊢ domCoprod m (n₁ + n₂) = domCoprod m n₁ + domCoprod m n₂

Next tactic:
ext
/-- A more bundled version of `MultilinearMap.domCoprod` that maps
`((ι₁ → N) → N₁) ⊗ ((ι₂ → N) → N₂)` to `(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂`. -/
def domCoprod' :
    MultilinearMap R (fun _ : ι₁ => N) N₁ ⊗[R] MultilinearMap R (fun _ : ι₂ => N) N₂ →ₗ[R]
      MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) :=
  TensorProduct.lift <|
    LinearMap.mk₂ R domCoprod
      (fun m₁ m₂ n => by
        ext
        simp only [domCoprod_apply, TensorProduct.add_tmul, add_apply])
      (fun c m n => by
        ext
        simp only [domCoprod_apply, TensorProduct.smul_tmul', smul_apply])
      (fun m n₁ n₂ => by
        ext
        

Proof state:
case H
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁶ : CommSemiring R
N₁ : Type u_6
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : Module R N₁
N₂ : Type u_7
inst✝³ : AddCommMonoid N₂
inst✝² : Module R N₂
N : Type u_8
inst✝¹ : AddCommMonoid N
inst✝ : Module R N
m : MultilinearMap R (fun x => N) N₁
n₁ n₂ : MultilinearMap R (fun x => N) N₂
x✝ : ι₁ ⊕ ι₂ → N
⊢ (domCoprod m (n₁ + n₂)) x✝ = (domCoprod m n₁ + domCoprod m n₂) x✝

Next tactic:
simp only [domCoprod_apply, TensorProduct.tmul_add, add_apply]
/-- A more bundled version of `MultilinearMap.domCoprod` that maps
`((ι₁ → N) → N₁) ⊗ ((ι₂ → N) → N₂)` to `(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂`. -/
def domCoprod' :
    MultilinearMap R (fun _ : ι₁ => N) N₁ ⊗[R] MultilinearMap R (fun _ : ι₂ => N) N₂ →ₗ[R]
      MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) :=
  TensorProduct.lift <|
    LinearMap.mk₂ R domCoprod
      (fun m₁ m₂ n => by
        ext
        simp only [domCoprod_apply, TensorProduct.add_tmul, add_apply])
      (fun c m n => by
        ext
        simp only [domCoprod_apply, TensorProduct.smul_tmul', smul_apply])
      (fun m n₁ n₂ => by
        ext
        simp only [domCoprod_apply, TensorProduct.tmul_add, add_apply])
      fun c m n => by
      

Proof state:
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁶ : CommSemiring R
N₁ : Type u_6
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : Module R N₁
N₂ : Type u_7
inst✝³ : AddCommMonoid N₂
inst✝² : Module R N₂
N : Type u_8
inst✝¹ : AddCommMonoid N
inst✝ : Module R N
c : R
m : MultilinearMap R (fun x => N) N₁
n : MultilinearMap R (fun x => N) N₂
⊢ domCoprod m (c • n) = c • domCoprod m n

Next tactic:
ext
/-- A more bundled version of `MultilinearMap.domCoprod` that maps
`((ι₁ → N) → N₁) ⊗ ((ι₂ → N) → N₂)` to `(ι₁ ⊕ ι₂ → N) → N₁ ⊗ N₂`. -/
def domCoprod' :
    MultilinearMap R (fun _ : ι₁ => N) N₁ ⊗[R] MultilinearMap R (fun _ : ι₂ => N) N₂ →ₗ[R]
      MultilinearMap R (fun _ : Sum ι₁ ι₂ => N) (N₁ ⊗[R] N₂) :=
  TensorProduct.lift <|
    LinearMap.mk₂ R domCoprod
      (fun m₁ m₂ n => by
        ext
        simp only [domCoprod_apply, TensorProduct.add_tmul, add_apply])
      (fun c m n => by
        ext
        simp only [domCoprod_apply, TensorProduct.smul_tmul', smul_apply])
      (fun m n₁ n₂ => by
        ext
        simp only [domCoprod_apply, TensorProduct.tmul_add, add_apply])
      fun c m n => by
      ext
      

Proof state:
case H
R : Type u_1
ι₁ : Type u_2
ι₂ : Type u_3
ι₃ : Type u_4
ι₄ : Type u_5
inst✝⁶ : CommSemiring R
N₁ : Type u_6
inst✝⁵ : AddCommMonoid N₁
inst✝⁴ : Module R N₁
N₂ : Type u_7
inst✝³ : AddCommMonoid N₂
inst✝² : Module R N₂
N : Type u_8
inst✝¹ : AddCommMonoid N
inst✝ : Module R N
c : R
m : MultilinearMap R (fun x => N) N₁
n : MultilinearMap R (fun x => N) N₂
x✝ : ι₁ ⊕ ι₂ → N
⊢ (domCoprod m (c • n)) x✝ = (c • domCoprod m n) x✝

Next tactic:
simp only [domCoprod_apply, TensorProduct.tmul_smul, smul_apply]
theorem image_restrict (f : α → β) (s t : Set α) :
    s.restrict f '' (Subtype.val ⁻¹' t) = f '' (t ∩ s) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
π : α → Type u_5
f : α → β
s t : Set α
⊢ restrict s f '' (Subtype.val ⁻¹' t) = f '' (t ∩ s)

Next tactic:
rw [restrict_eq, image_comp, image_preimage_eq_inter_range, Subtype.range_coe]
theorem restrict_extend_range (f : α → β) (g : α → γ) (g' : β → γ) :
    (range f).restrict (extend f g g') = fun x => g x.coe_prop.choose := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
π : α → Type u_5
f : α → β
g : α → γ
g' : β → γ
⊢ restrict (range f) (extend f g g') = fun x => g (Exists.choose (_ : ↑x ∈ range f))

Next tactic:
classical
  exact restrict_dite _ _
theorem restrict_extend_range (f : α → β) (g : α → γ) (g' : β → γ) :
    (range f).restrict (extend f g g') = fun x => g x.coe_prop.choose := by
  classical
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
π : α → Type u_5
f : α → β
g : α → γ
g' : β → γ
⊢ restrict (range f) (extend f g g') = fun x => g (Exists.choose (_ : ↑x ∈ range f))

Next tactic:
exact restrict_dite _ _
@[simp]
theorem restrict_extend_compl_range (f : α → β) (g : α → γ) (g' : β → γ) :
    (range f)ᶜ.restrict (extend f g g') = g' ∘ Subtype.val := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
π : α → Type u_5
f : α → β
g : α → γ
g' : β → γ
⊢ restrict (range f)ᶜ (extend f g g') = g' ∘ Subtype.val

Next tactic:
classical
  exact restrict_dite_compl _ _
@[simp]
theorem restrict_extend_compl_range (f : α → β) (g : α → γ) (g' : β → γ) :
    (range f)ᶜ.restrict (extend f g g') = g' ∘ Subtype.val := by
  classical
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
π : α → Type u_5
f : α → β
g : α → γ
g' : β → γ
⊢ restrict (range f)ᶜ (extend f g g') = g' ∘ Subtype.val

Next tactic:
exact restrict_dite_compl _ _
theorem range_extend_subset (f : α → β) (g : α → γ) (g' : β → γ) :
    range (extend f g g') ⊆ range g ∪ g' '' (range f)ᶜ := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
π : α → Type u_5
f : α → β
g : α → γ
g' : β → γ
⊢ range (extend f g g') ⊆ range g ∪ g' '' (range f)ᶜ

Next tactic:
classical
  rintro _ ⟨y, rfl⟩
  rw [extend_def]
  split_ifs with h
  exacts [Or.inl (mem_range_self _), Or.inr (mem_image_of_mem _ h)]
theorem range_extend_subset (f : α → β) (g : α → γ) (g' : β → γ) :
    range (extend f g g') ⊆ range g ∪ g' '' (range f)ᶜ := by
  classical
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Sort u_4
π : α → Type u_5
f : α → β
g : α → γ
g' : β → γ
⊢ range (extend f g g') ⊆ range g ∪ g' '' (range f)ᶜ

Next tactic:
rintro _ ⟨y, rfl⟩