l3lab/ntp-mathlib huggingface dataset:
/-- The n-ary version of `Set.mem_mul`. -/
@[to_additive " The n-ary version of `Set.mem_add`. "]
theorem mem_finset_prod (t : Finset ι) (f : ι → Set α) (a : α) :
    (a ∈ ∏ i in t, f i) ↔ ∃ (g : ι → α) (_ : ∀ {i}, i ∈ t → g i ∈ f i), ∏ i in t, g i = a := by
  classical
    induction' t using Finset.induction_on with i is hi ih generalizing a
    · simp_rw [Finset.prod_empty, Set.mem_one]
      exact ⟨fun h ↦ ⟨fun _ ↦ a, fun hi ↦ False.elim (Finset.not_mem_empty _ hi), h.symm⟩,
        fun ⟨_, _, hf⟩ ↦ hf.symm⟩
    rw [Finset.prod_insert hi, Set.mem_mul]
    simp_rw [Finset.prod_insert hi]
    simp_rw [ih]
    constructor
    · 

Proof state:
case insert.mp
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
i : ι
is : Finset ι
hi : i ∉ is
ih : ∀ (a : α), a ∈ ∏ i in is, f i ↔ ∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = a
a : α
⊢ (∃ x y, x ∈ f i ∧ (∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = y) ∧ x * y = a) →
    ∃ g, ∃ (_ : ∀ {i_1 : ι}, i_1 ∈ insert i is → g i_1 ∈ f i_1), g i * ∏ i in is, g i = a

Next tactic:
rintro ⟨x, y, hx, ⟨g, hg, rfl⟩, rfl⟩
/-- The n-ary version of `Set.mem_mul`. -/
@[to_additive " The n-ary version of `Set.mem_add`. "]
theorem mem_finset_prod (t : Finset ι) (f : ι → Set α) (a : α) :
    (a ∈ ∏ i in t, f i) ↔ ∃ (g : ι → α) (_ : ∀ {i}, i ∈ t → g i ∈ f i), ∏ i in t, g i = a := by
  classical
    induction' t using Finset.induction_on with i is hi ih generalizing a
    · simp_rw [Finset.prod_empty, Set.mem_one]
      exact ⟨fun h ↦ ⟨fun _ ↦ a, fun hi ↦ False.elim (Finset.not_mem_empty _ hi), h.symm⟩,
        fun ⟨_, _, hf⟩ ↦ hf.symm⟩
    rw [Finset.prod_insert hi, Set.mem_mul]
    simp_rw [Finset.prod_insert hi]
    simp_rw [ih]
    constructor
    · rintro ⟨x, y, hx, ⟨g, hg, rfl⟩, rfl⟩
      

Proof state:
case insert.mp.intro.intro.intro.intro.intro.intro
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
i : ι
is : Finset ι
hi : i ∉ is
ih : ∀ (a : α), a ∈ ∏ i in is, f i ↔ ∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = a
x : α
hx : x ∈ f i
g : ι → α
hg : ∀ {i : ι}, i ∈ is → g i ∈ f i
⊢ ∃ g_1, ∃ (_ : ∀ {i_1 : ι}, i_1 ∈ insert i is → g_1 i_1 ∈ f i_1), g_1 i * ∏ i in is, g_1 i = x * ∏ i in is, g i

Next tactic:
refine ⟨Function.update g i x, ?_, ?_⟩
/-- The n-ary version of `Set.mem_mul`. -/
@[to_additive " The n-ary version of `Set.mem_add`. "]
theorem mem_finset_prod (t : Finset ι) (f : ι → Set α) (a : α) :
    (a ∈ ∏ i in t, f i) ↔ ∃ (g : ι → α) (_ : ∀ {i}, i ∈ t → g i ∈ f i), ∏ i in t, g i = a := by
  classical
    induction' t using Finset.induction_on with i is hi ih generalizing a
    · simp_rw [Finset.prod_empty, Set.mem_one]
      exact ⟨fun h ↦ ⟨fun _ ↦ a, fun hi ↦ False.elim (Finset.not_mem_empty _ hi), h.symm⟩,
        fun ⟨_, _, hf⟩ ↦ hf.symm⟩
    rw [Finset.prod_insert hi, Set.mem_mul]
    simp_rw [Finset.prod_insert hi]
    simp_rw [ih]
    constructor
    · rintro ⟨x, y, hx, ⟨g, hg, rfl⟩, rfl⟩
      refine ⟨Function.update g i x, ?_, ?_⟩
      · 

Proof state:
case insert.mp.intro.intro.intro.intro.intro.intro.refine_1
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
i : ι
is : Finset ι
hi : i ∉ is
ih : ∀ (a : α), a ∈ ∏ i in is, f i ↔ ∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = a
x : α
hx : x ∈ f i
g : ι → α
hg : ∀ {i : ι}, i ∈ is → g i ∈ f i
⊢ ∀ {i_1 : ι}, i_1 ∈ insert i is → update g i x i_1 ∈ f i_1

Next tactic:
intro j hj
/-- The n-ary version of `Set.mem_mul`. -/
@[to_additive " The n-ary version of `Set.mem_add`. "]
theorem mem_finset_prod (t : Finset ι) (f : ι → Set α) (a : α) :
    (a ∈ ∏ i in t, f i) ↔ ∃ (g : ι → α) (_ : ∀ {i}, i ∈ t → g i ∈ f i), ∏ i in t, g i = a := by
  classical
    induction' t using Finset.induction_on with i is hi ih generalizing a
    · simp_rw [Finset.prod_empty, Set.mem_one]
      exact ⟨fun h ↦ ⟨fun _ ↦ a, fun hi ↦ False.elim (Finset.not_mem_empty _ hi), h.symm⟩,
        fun ⟨_, _, hf⟩ ↦ hf.symm⟩
    rw [Finset.prod_insert hi, Set.mem_mul]
    simp_rw [Finset.prod_insert hi]
    simp_rw [ih]
    constructor
    · rintro ⟨x, y, hx, ⟨g, hg, rfl⟩, rfl⟩
      refine ⟨Function.update g i x, ?_, ?_⟩
      · intro j hj
        

Proof state:
case insert.mp.intro.intro.intro.intro.intro.intro.refine_1
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
i : ι
is : Finset ι
hi : i ∉ is
ih : ∀ (a : α), a ∈ ∏ i in is, f i ↔ ∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = a
x : α
hx : x ∈ f i
g : ι → α
hg : ∀ {i : ι}, i ∈ is → g i ∈ f i
j : ι
hj : j ∈ insert i is
⊢ update g i x j ∈ f j

Next tactic:
obtain rfl | hj := Finset.mem_insert.mp hj
/-- The n-ary version of `Set.mem_mul`. -/
@[to_additive " The n-ary version of `Set.mem_add`. "]
theorem mem_finset_prod (t : Finset ι) (f : ι → Set α) (a : α) :
    (a ∈ ∏ i in t, f i) ↔ ∃ (g : ι → α) (_ : ∀ {i}, i ∈ t → g i ∈ f i), ∏ i in t, g i = a := by
  classical
    induction' t using Finset.induction_on with i is hi ih generalizing a
    · simp_rw [Finset.prod_empty, Set.mem_one]
      exact ⟨fun h ↦ ⟨fun _ ↦ a, fun hi ↦ False.elim (Finset.not_mem_empty _ hi), h.symm⟩,
        fun ⟨_, _, hf⟩ ↦ hf.symm⟩
    rw [Finset.prod_insert hi, Set.mem_mul]
    simp_rw [Finset.prod_insert hi]
    simp_rw [ih]
    constructor
    · rintro ⟨x, y, hx, ⟨g, hg, rfl⟩, rfl⟩
      refine ⟨Function.update g i x, ?_, ?_⟩
      · intro j hj
        obtain rfl | hj := Finset.mem_insert.mp hj
        · 

Proof state:
case insert.mp.intro.intro.intro.intro.intro.intro.refine_1.inl
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
is : Finset ι
ih : ∀ (a : α), a ∈ ∏ i in is, f i ↔ ∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = a
x : α
g : ι → α
hg : ∀ {i : ι}, i ∈ is → g i ∈ f i
j : ι
hi : j ∉ is
hx : x ∈ f j
hj : j ∈ insert j is
⊢ update g j x j ∈ f j

Next tactic:
rwa [Function.update_same]
/-- The n-ary version of `Set.mem_mul`. -/
@[to_additive " The n-ary version of `Set.mem_add`. "]
theorem mem_finset_prod (t : Finset ι) (f : ι → Set α) (a : α) :
    (a ∈ ∏ i in t, f i) ↔ ∃ (g : ι → α) (_ : ∀ {i}, i ∈ t → g i ∈ f i), ∏ i in t, g i = a := by
  classical
    induction' t using Finset.induction_on with i is hi ih generalizing a
    · simp_rw [Finset.prod_empty, Set.mem_one]
      exact ⟨fun h ↦ ⟨fun _ ↦ a, fun hi ↦ False.elim (Finset.not_mem_empty _ hi), h.symm⟩,
        fun ⟨_, _, hf⟩ ↦ hf.symm⟩
    rw [Finset.prod_insert hi, Set.mem_mul]
    simp_rw [Finset.prod_insert hi]
    simp_rw [ih]
    constructor
    · rintro ⟨x, y, hx, ⟨g, hg, rfl⟩, rfl⟩
      refine ⟨Function.update g i x, ?_, ?_⟩
      · intro j hj
        obtain rfl | hj := Finset.mem_insert.mp hj
        · rwa [Function.update_same]
        · 

Proof state:
case insert.mp.intro.intro.intro.intro.intro.intro.refine_1.inr
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
i : ι
is : Finset ι
hi : i ∉ is
ih : ∀ (a : α), a ∈ ∏ i in is, f i ↔ ∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = a
x : α
hx : x ∈ f i
g : ι → α
hg : ∀ {i : ι}, i ∈ is → g i ∈ f i
j : ι
hj✝ : j ∈ insert i is
hj : j ∈ is
⊢ update g i x j ∈ f j

Next tactic:
rw [update_noteq (ne_of_mem_of_not_mem hj hi)]
/-- The n-ary version of `Set.mem_mul`. -/
@[to_additive " The n-ary version of `Set.mem_add`. "]
theorem mem_finset_prod (t : Finset ι) (f : ι → Set α) (a : α) :
    (a ∈ ∏ i in t, f i) ↔ ∃ (g : ι → α) (_ : ∀ {i}, i ∈ t → g i ∈ f i), ∏ i in t, g i = a := by
  classical
    induction' t using Finset.induction_on with i is hi ih generalizing a
    · simp_rw [Finset.prod_empty, Set.mem_one]
      exact ⟨fun h ↦ ⟨fun _ ↦ a, fun hi ↦ False.elim (Finset.not_mem_empty _ hi), h.symm⟩,
        fun ⟨_, _, hf⟩ ↦ hf.symm⟩
    rw [Finset.prod_insert hi, Set.mem_mul]
    simp_rw [Finset.prod_insert hi]
    simp_rw [ih]
    constructor
    · rintro ⟨x, y, hx, ⟨g, hg, rfl⟩, rfl⟩
      refine ⟨Function.update g i x, ?_, ?_⟩
      · intro j hj
        obtain rfl | hj := Finset.mem_insert.mp hj
        · rwa [Function.update_same]
        · rw [update_noteq (ne_of_mem_of_not_mem hj hi)]
          

Proof state:
case insert.mp.intro.intro.intro.intro.intro.intro.refine_1.inr
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
i : ι
is : Finset ι
hi : i ∉ is
ih : ∀ (a : α), a ∈ ∏ i in is, f i ↔ ∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = a
x : α
hx : x ∈ f i
g : ι → α
hg : ∀ {i : ι}, i ∈ is → g i ∈ f i
j : ι
hj✝ : j ∈ insert i is
hj : j ∈ is
⊢ g j ∈ f j

Next tactic:
exact hg hj
/-- The n-ary version of `Set.mem_mul`. -/
@[to_additive " The n-ary version of `Set.mem_add`. "]
theorem mem_finset_prod (t : Finset ι) (f : ι → Set α) (a : α) :
    (a ∈ ∏ i in t, f i) ↔ ∃ (g : ι → α) (_ : ∀ {i}, i ∈ t → g i ∈ f i), ∏ i in t, g i = a := by
  classical
    induction' t using Finset.induction_on with i is hi ih generalizing a
    · simp_rw [Finset.prod_empty, Set.mem_one]
      exact ⟨fun h ↦ ⟨fun _ ↦ a, fun hi ↦ False.elim (Finset.not_mem_empty _ hi), h.symm⟩,
        fun ⟨_, _, hf⟩ ↦ hf.symm⟩
    rw [Finset.prod_insert hi, Set.mem_mul]
    simp_rw [Finset.prod_insert hi]
    simp_rw [ih]
    constructor
    · rintro ⟨x, y, hx, ⟨g, hg, rfl⟩, rfl⟩
      refine ⟨Function.update g i x, ?_, ?_⟩
      · intro j hj
        obtain rfl | hj := Finset.mem_insert.mp hj
        · rwa [Function.update_same]
        · rw [update_noteq (ne_of_mem_of_not_mem hj hi)]
          exact hg hj
      · 

Proof state:
case insert.mp.intro.intro.intro.intro.intro.intro.refine_2
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
i : ι
is : Finset ι
hi : i ∉ is
ih : ∀ (a : α), a ∈ ∏ i in is, f i ↔ ∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = a
x : α
hx : x ∈ f i
g : ι → α
hg : ∀ {i : ι}, i ∈ is → g i ∈ f i
⊢ update g i x i * ∏ i_1 in is, update g i x i_1 = x * ∏ i in is, g i

Next tactic:
rw [Finset.prod_update_of_not_mem hi, Function.update_same]
/-- The n-ary version of `Set.mem_mul`. -/
@[to_additive " The n-ary version of `Set.mem_add`. "]
theorem mem_finset_prod (t : Finset ι) (f : ι → Set α) (a : α) :
    (a ∈ ∏ i in t, f i) ↔ ∃ (g : ι → α) (_ : ∀ {i}, i ∈ t → g i ∈ f i), ∏ i in t, g i = a := by
  classical
    induction' t using Finset.induction_on with i is hi ih generalizing a
    · simp_rw [Finset.prod_empty, Set.mem_one]
      exact ⟨fun h ↦ ⟨fun _ ↦ a, fun hi ↦ False.elim (Finset.not_mem_empty _ hi), h.symm⟩,
        fun ⟨_, _, hf⟩ ↦ hf.symm⟩
    rw [Finset.prod_insert hi, Set.mem_mul]
    simp_rw [Finset.prod_insert hi]
    simp_rw [ih]
    constructor
    · rintro ⟨x, y, hx, ⟨g, hg, rfl⟩, rfl⟩
      refine ⟨Function.update g i x, ?_, ?_⟩
      · intro j hj
        obtain rfl | hj := Finset.mem_insert.mp hj
        · rwa [Function.update_same]
        · rw [update_noteq (ne_of_mem_of_not_mem hj hi)]
          exact hg hj
      · rw [Finset.prod_update_of_not_mem hi, Function.update_same]
    · 

Proof state:
case insert.mpr
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
i : ι
is : Finset ι
hi : i ∉ is
ih : ∀ (a : α), a ∈ ∏ i in is, f i ↔ ∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = a
a : α
⊢ (∃ g, ∃ (_ : ∀ {i_1 : ι}, i_1 ∈ insert i is → g i_1 ∈ f i_1), g i * ∏ i in is, g i = a) →
    ∃ x y, x ∈ f i ∧ (∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = y) ∧ x * y = a

Next tactic:
rintro ⟨g, hg, rfl⟩
/-- The n-ary version of `Set.mem_mul`. -/
@[to_additive " The n-ary version of `Set.mem_add`. "]
theorem mem_finset_prod (t : Finset ι) (f : ι → Set α) (a : α) :
    (a ∈ ∏ i in t, f i) ↔ ∃ (g : ι → α) (_ : ∀ {i}, i ∈ t → g i ∈ f i), ∏ i in t, g i = a := by
  classical
    induction' t using Finset.induction_on with i is hi ih generalizing a
    · simp_rw [Finset.prod_empty, Set.mem_one]
      exact ⟨fun h ↦ ⟨fun _ ↦ a, fun hi ↦ False.elim (Finset.not_mem_empty _ hi), h.symm⟩,
        fun ⟨_, _, hf⟩ ↦ hf.symm⟩
    rw [Finset.prod_insert hi, Set.mem_mul]
    simp_rw [Finset.prod_insert hi]
    simp_rw [ih]
    constructor
    · rintro ⟨x, y, hx, ⟨g, hg, rfl⟩, rfl⟩
      refine ⟨Function.update g i x, ?_, ?_⟩
      · intro j hj
        obtain rfl | hj := Finset.mem_insert.mp hj
        · rwa [Function.update_same]
        · rw [update_noteq (ne_of_mem_of_not_mem hj hi)]
          exact hg hj
      · rw [Finset.prod_update_of_not_mem hi, Function.update_same]
    · rintro ⟨g, hg, rfl⟩
      

Proof state:
case insert.mpr.intro.intro
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
i : ι
is : Finset ι
hi : i ∉ is
ih : ∀ (a : α), a ∈ ∏ i in is, f i ↔ ∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = a
g : ι → α
hg : ∀ {i_1 : ι}, i_1 ∈ insert i is → g i_1 ∈ f i_1
⊢ ∃ x y, x ∈ f i ∧ (∃ g, ∃ (_ : ∀ {i : ι}, i ∈ is → g i ∈ f i), ∏ i in is, g i = y) ∧ x * y = g i * ∏ i in is, g i

Next tactic:
exact ⟨g i, is.prod g, hg (is.mem_insert_self _),
        ⟨⟨g, fun hi ↦ hg (Finset.mem_insert_of_mem hi), rfl⟩, rfl⟩⟩
/-- A version of `Set.mem_finset_prod` with a simpler RHS for products over a Fintype. -/
@[to_additive " A version of `Set.mem_finset_sum` with a simpler RHS for sums over a Fintype. "]
theorem mem_fintype_prod [Fintype ι] (f : ι → Set α) (a : α) :
    (a ∈ ∏ i, f i) ↔ ∃ (g : ι → α) (_ : ∀ i, g i ∈ f i), ∏ i, g i = a := by
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝³ : CommMonoid α
inst✝² : CommMonoid β
inst✝¹ : MonoidHomClass F α β
inst✝ : Fintype ι
f : ι → Set α
a : α
⊢ a ∈ ∏ i : ι, f i ↔ ∃ g, ∃ (_ : ∀ (i : ι), g i ∈ f i), ∏ i : ι, g i = a

Next tactic:
rw [mem_finset_prod]
/-- A version of `Set.mem_finset_prod` with a simpler RHS for products over a Fintype. -/
@[to_additive " A version of `Set.mem_finset_sum` with a simpler RHS for sums over a Fintype. "]
theorem mem_fintype_prod [Fintype ι] (f : ι → Set α) (a : α) :
    (a ∈ ∏ i, f i) ↔ ∃ (g : ι → α) (_ : ∀ i, g i ∈ f i), ∏ i, g i = a := by
  rw [mem_finset_prod]
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝³ : CommMonoid α
inst✝² : CommMonoid β
inst✝¹ : MonoidHomClass F α β
inst✝ : Fintype ι
f : ι → Set α
a : α
⊢ (∃ g, ∃ (_ : ∀ {i : ι}, i ∈ Finset.univ → g i ∈ f i), ∏ i : ι, g i = a) ↔
    ∃ g, ∃ (_ : ∀ (i : ι), g i ∈ f i), ∏ i : ι, g i = a

Next tactic:
simp
/-- An n-ary version of `Set.mul_mem_mul`. -/
@[to_additive " An n-ary version of `Set.add_mem_add`. "]
theorem list_prod_mem_list_prod (t : List ι) (f : ι → Set α) (g : ι → α) (hg : ∀ i ∈ t, g i ∈ f i) :
    (t.map g).prod ∈ (t.map f).prod := by
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
t : List ι
f : ι → Set α
g : ι → α
hg : ∀ i ∈ t, g i ∈ f i
⊢ List.prod (List.map g t) ∈ List.prod (List.map f t)

Next tactic:
induction' t with h tl ih
/-- An n-ary version of `Set.mul_mem_mul`. -/
@[to_additive " An n-ary version of `Set.add_mem_add`. "]
theorem list_prod_mem_list_prod (t : List ι) (f : ι → Set α) (g : ι → α) (hg : ∀ i ∈ t, g i ∈ f i) :
    (t.map g).prod ∈ (t.map f).prod := by
  induction' t with h tl ih
  · 

Proof state:
case nil
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
g : ι → α
hg : ∀ i ∈ [], g i ∈ f i
⊢ List.prod (List.map g []) ∈ List.prod (List.map f [])

Next tactic:
simp_rw [List.map_nil, List.prod_nil, Set.mem_one]
/-- An n-ary version of `Set.mul_mem_mul`. -/
@[to_additive " An n-ary version of `Set.add_mem_add`. "]
theorem list_prod_mem_list_prod (t : List ι) (f : ι → Set α) (g : ι → α) (hg : ∀ i ∈ t, g i ∈ f i) :
    (t.map g).prod ∈ (t.map f).prod := by
  induction' t with h tl ih
  · simp_rw [List.map_nil, List.prod_nil, Set.mem_one]
  · 

Proof state:
case cons
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
g : ι → α
h : ι
tl : List ι
ih : (∀ i ∈ tl, g i ∈ f i) → List.prod (List.map g tl) ∈ List.prod (List.map f tl)
hg : ∀ i ∈ h :: tl, g i ∈ f i
⊢ List.prod (List.map g (h :: tl)) ∈ List.prod (List.map f (h :: tl))

Next tactic:
simp_rw [List.map_cons, List.prod_cons]
/-- An n-ary version of `Set.mul_mem_mul`. -/
@[to_additive " An n-ary version of `Set.add_mem_add`. "]
theorem list_prod_mem_list_prod (t : List ι) (f : ι → Set α) (g : ι → α) (hg : ∀ i ∈ t, g i ∈ f i) :
    (t.map g).prod ∈ (t.map f).prod := by
  induction' t with h tl ih
  · simp_rw [List.map_nil, List.prod_nil, Set.mem_one]
  · simp_rw [List.map_cons, List.prod_cons]
    

Proof state:
case cons
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
g : ι → α
h : ι
tl : List ι
ih : (∀ i ∈ tl, g i ∈ f i) → List.prod (List.map g tl) ∈ List.prod (List.map f tl)
hg : ∀ i ∈ h :: tl, g i ∈ f i
⊢ g h * List.prod (List.map g tl) ∈ f h * List.prod (List.map f tl)

Next tactic:
exact mul_mem_mul (hg h <| List.mem_cons_self _ _)
      (ih fun i hi ↦ hg i <| List.mem_cons_of_mem _ hi)
/-- An n-ary version of `Set.mul_subset_mul`. -/
@[to_additive " An n-ary version of `Set.add_subset_add`. "]
theorem list_prod_subset_list_prod (t : List ι) (f₁ f₂ : ι → Set α) (hf : ∀ i ∈ t, f₁ i ⊆ f₂ i) :
    (t.map f₁).prod ⊆ (t.map f₂).prod := by
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
t : List ι
f₁ f₂ : ι → Set α
hf : ∀ i ∈ t, f₁ i ⊆ f₂ i
⊢ List.prod (List.map f₁ t) ⊆ List.prod (List.map f₂ t)

Next tactic:
induction' t with h tl ih
/-- An n-ary version of `Set.mul_subset_mul`. -/
@[to_additive " An n-ary version of `Set.add_subset_add`. "]
theorem list_prod_subset_list_prod (t : List ι) (f₁ f₂ : ι → Set α) (hf : ∀ i ∈ t, f₁ i ⊆ f₂ i) :
    (t.map f₁).prod ⊆ (t.map f₂).prod := by
  induction' t with h tl ih
  · 

Proof state:
case nil
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f₁ f₂ : ι → Set α
hf : ∀ i ∈ [], f₁ i ⊆ f₂ i
⊢ List.prod (List.map f₁ []) ⊆ List.prod (List.map f₂ [])

Next tactic:
rfl
/-- An n-ary version of `Set.mul_subset_mul`. -/
@[to_additive " An n-ary version of `Set.add_subset_add`. "]
theorem list_prod_subset_list_prod (t : List ι) (f₁ f₂ : ι → Set α) (hf : ∀ i ∈ t, f₁ i ⊆ f₂ i) :
    (t.map f₁).prod ⊆ (t.map f₂).prod := by
  induction' t with h tl ih
  · rfl
  · 

Proof state:
case cons
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f₁ f₂ : ι → Set α
h : ι
tl : List ι
ih : (∀ i ∈ tl, f₁ i ⊆ f₂ i) → List.prod (List.map f₁ tl) ⊆ List.prod (List.map f₂ tl)
hf : ∀ i ∈ h :: tl, f₁ i ⊆ f₂ i
⊢ List.prod (List.map f₁ (h :: tl)) ⊆ List.prod (List.map f₂ (h :: tl))

Next tactic:
simp_rw [List.map_cons, List.prod_cons]
/-- An n-ary version of `Set.mul_subset_mul`. -/
@[to_additive " An n-ary version of `Set.add_subset_add`. "]
theorem list_prod_subset_list_prod (t : List ι) (f₁ f₂ : ι → Set α) (hf : ∀ i ∈ t, f₁ i ⊆ f₂ i) :
    (t.map f₁).prod ⊆ (t.map f₂).prod := by
  induction' t with h tl ih
  · rfl
  · simp_rw [List.map_cons, List.prod_cons]
    

Proof state:
case cons
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f₁ f₂ : ι → Set α
h : ι
tl : List ι
ih : (∀ i ∈ tl, f₁ i ⊆ f₂ i) → List.prod (List.map f₁ tl) ⊆ List.prod (List.map f₂ tl)
hf : ∀ i ∈ h :: tl, f₁ i ⊆ f₂ i
⊢ f₁ h * List.prod (List.map f₁ tl) ⊆ f₂ h * List.prod (List.map f₂ tl)

Next tactic:
exact mul_subset_mul (hf h <| List.mem_cons_self _ _)
      (ih fun i hi ↦ hf i <| List.mem_cons_of_mem _ hi)
/-- An n-ary version of `Set.mul_mem_mul`. -/
@[to_additive " An n-ary version of `Set.add_mem_add`. "]
theorem multiset_prod_mem_multiset_prod (t : Multiset ι) (f : ι → Set α) (g : ι → α)
    (hg : ∀ i ∈ t, g i ∈ f i) : (t.map g).prod ∈ (t.map f).prod := by
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
t : Multiset ι
f : ι → Set α
g : ι → α
hg : ∀ i ∈ t, g i ∈ f i
⊢ Multiset.prod (Multiset.map g t) ∈ Multiset.prod (Multiset.map f t)

Next tactic:
induction t using Quotient.inductionOn
/-- An n-ary version of `Set.mul_mem_mul`. -/
@[to_additive " An n-ary version of `Set.add_mem_add`. "]
theorem multiset_prod_mem_multiset_prod (t : Multiset ι) (f : ι → Set α) (g : ι → α)
    (hg : ∀ i ∈ t, g i ∈ f i) : (t.map g).prod ∈ (t.map f).prod := by
  induction t using Quotient.inductionOn
  

Proof state:
case h
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
g : ι → α
a✝ : List ι
hg : ∀ i ∈ ⟦a✝⟧, g i ∈ f i
⊢ Multiset.prod (Multiset.map g ⟦a✝⟧) ∈ Multiset.prod (Multiset.map f ⟦a✝⟧)

Next tactic:
simp_rw [Multiset.quot_mk_to_coe, Multiset.coe_map, Multiset.coe_prod]
/-- An n-ary version of `Set.mul_mem_mul`. -/
@[to_additive " An n-ary version of `Set.add_mem_add`. "]
theorem multiset_prod_mem_multiset_prod (t : Multiset ι) (f : ι → Set α) (g : ι → α)
    (hg : ∀ i ∈ t, g i ∈ f i) : (t.map g).prod ∈ (t.map f).prod := by
  induction t using Quotient.inductionOn
  simp_rw [Multiset.quot_mk_to_coe, Multiset.coe_map, Multiset.coe_prod]
  

Proof state:
case h
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f : ι → Set α
g : ι → α
a✝ : List ι
hg : ∀ i ∈ ⟦a✝⟧, g i ∈ f i
⊢ List.prod (List.map g a✝) ∈ List.prod (List.map f a✝)

Next tactic:
exact list_prod_mem_list_prod _ _ _ hg
/-- An n-ary version of `Set.mul_subset_mul`. -/
@[to_additive " An n-ary version of `Set.add_subset_add`. "]
theorem multiset_prod_subset_multiset_prod (t : Multiset ι) (f₁ f₂ : ι → Set α)
    (hf : ∀ i ∈ t, f₁ i ⊆ f₂ i) : (t.map f₁).prod ⊆ (t.map f₂).prod := by
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
t : Multiset ι
f₁ f₂ : ι → Set α
hf : ∀ i ∈ t, f₁ i ⊆ f₂ i
⊢ Multiset.prod (Multiset.map f₁ t) ⊆ Multiset.prod (Multiset.map f₂ t)

Next tactic:
induction t using Quotient.inductionOn
/-- An n-ary version of `Set.mul_subset_mul`. -/
@[to_additive " An n-ary version of `Set.add_subset_add`. "]
theorem multiset_prod_subset_multiset_prod (t : Multiset ι) (f₁ f₂ : ι → Set α)
    (hf : ∀ i ∈ t, f₁ i ⊆ f₂ i) : (t.map f₁).prod ⊆ (t.map f₂).prod := by
  induction t using Quotient.inductionOn
  

Proof state:
case h
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f₁ f₂ : ι → Set α
a✝ : List ι
hf : ∀ i ∈ ⟦a✝⟧, f₁ i ⊆ f₂ i
⊢ Multiset.prod (Multiset.map f₁ ⟦a✝⟧) ⊆ Multiset.prod (Multiset.map f₂ ⟦a✝⟧)

Next tactic:
simp_rw [Multiset.quot_mk_to_coe, Multiset.coe_map, Multiset.coe_prod]
/-- An n-ary version of `Set.mul_subset_mul`. -/
@[to_additive " An n-ary version of `Set.add_subset_add`. "]
theorem multiset_prod_subset_multiset_prod (t : Multiset ι) (f₁ f₂ : ι → Set α)
    (hf : ∀ i ∈ t, f₁ i ⊆ f₂ i) : (t.map f₁).prod ⊆ (t.map f₂).prod := by
  induction t using Quotient.inductionOn
  simp_rw [Multiset.quot_mk_to_coe, Multiset.coe_map, Multiset.coe_prod]
  

Proof state:
case h
ι : Type u_1
α : Type u_2
β : Type u_3
F : Type u_4
inst✝² : CommMonoid α
inst✝¹ : CommMonoid β
inst✝ : MonoidHomClass F α β
f₁ f₂ : ι → Set α
a✝ : List ι
hf : ∀ i ∈ ⟦a✝⟧, f₁ i ⊆ f₂ i
⊢ List.prod (List.map f₁ a✝) ⊆ List.prod (List.map f₂ a✝)

Next tactic:
exact list_prod_subset_list_prod _ _ _ hf