l3lab/ntp-mathlib huggingface dataset:
/-- `A →*[n] β` is a `CommMonoid`. -/
@[to_additive "`α →+[n] β` is an `AddCommMonoid`."]
instance commMonoid : CommMonoid (A →*[n] β) where
  mul_assoc a b c := by
    ext
    apply mul_assoc
  one_mul a := by
    ext
    

Proof state:
case h
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁵ : FunLike F α fun x => β
inst✝⁴ : CommMonoid α
inst✝³ : CommMonoid β
inst✝² : CommMonoid γ
inst✝¹ : CommMonoid δ
inst✝ : CommGroup G
A : Set α
B : Set β
C : Set γ
n : ℕ
a✝ b c d : α
a : A →*[n] β
x✝ : α
⊢ (1 * a) x✝ = a x✝

Next tactic:
apply one_mul
/-- `A →*[n] β` is a `CommMonoid`. -/
@[to_additive "`α →+[n] β` is an `AddCommMonoid`."]
instance commMonoid : CommMonoid (A →*[n] β) where
  mul_assoc a b c := by
    ext
    apply mul_assoc
  one_mul a := by
    ext
    apply one_mul
  mul_one a := by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁵ : FunLike F α fun x => β
inst✝⁴ : CommMonoid α
inst✝³ : CommMonoid β
inst✝² : CommMonoid γ
inst✝¹ : CommMonoid δ
inst✝ : CommGroup G
A : Set α
B : Set β
C : Set γ
n : ℕ
a✝ b c d : α
a : A →*[n] β
⊢ a * 1 = a

Next tactic:
ext
/-- `A →*[n] β` is a `CommMonoid`. -/
@[to_additive "`α →+[n] β` is an `AddCommMonoid`."]
instance commMonoid : CommMonoid (A →*[n] β) where
  mul_assoc a b c := by
    ext
    apply mul_assoc
  one_mul a := by
    ext
    apply one_mul
  mul_one a := by
    ext
    

Proof state:
case h
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁵ : FunLike F α fun x => β
inst✝⁴ : CommMonoid α
inst✝³ : CommMonoid β
inst✝² : CommMonoid γ
inst✝¹ : CommMonoid δ
inst✝ : CommGroup G
A : Set α
B : Set β
C : Set γ
n : ℕ
a✝ b c d : α
a : A →*[n] β
x✝ : α
⊢ (a * 1) x✝ = a x✝

Next tactic:
apply mul_one
/-- `A →*[n] β` is a `CommMonoid`. -/
@[to_additive "`α →+[n] β` is an `AddCommMonoid`."]
instance commMonoid : CommMonoid (A →*[n] β) where
  mul_assoc a b c := by
    ext
    apply mul_assoc
  one_mul a := by
    ext
    apply one_mul
  mul_one a := by
    ext
    apply mul_one
  mul_comm a b := by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁵ : FunLike F α fun x => β
inst✝⁴ : CommMonoid α
inst✝³ : CommMonoid β
inst✝² : CommMonoid γ
inst✝¹ : CommMonoid δ
inst✝ : CommGroup G
A : Set α
B : Set β
C : Set γ
n : ℕ
a✝ b✝ c d : α
a b : A →*[n] β
⊢ a * b = b * a

Next tactic:
ext
/-- `A →*[n] β` is a `CommMonoid`. -/
@[to_additive "`α →+[n] β` is an `AddCommMonoid`."]
instance commMonoid : CommMonoid (A →*[n] β) where
  mul_assoc a b c := by
    ext
    apply mul_assoc
  one_mul a := by
    ext
    apply one_mul
  mul_one a := by
    ext
    apply mul_one
  mul_comm a b := by
    ext
    

Proof state:
case h
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁵ : FunLike F α fun x => β
inst✝⁴ : CommMonoid α
inst✝³ : CommMonoid β
inst✝² : CommMonoid γ
inst✝¹ : CommMonoid δ
inst✝ : CommGroup G
A : Set α
B : Set β
C : Set γ
n : ℕ
a✝ b✝ c d : α
a b : A →*[n] β
x✝ : α
⊢ (a * b) x✝ = (b * a) x✝

Next tactic:
apply mul_comm
/-- If `β` is a commutative group, then `A →*[n] β` is a commutative group too. -/
@[to_additive
      "If `β` is an additive commutative group, then `A →*[n] β` is an additive commutative
      group too."]
instance commGroup {β} [CommGroup β] : CommGroup (A →*[n] β) :=
  { FreimanHom.commMonoid with
    div_eq_mul_inv := by
      

Proof state:
F : Type u_1
α : Type u_2
β✝ : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁶ : FunLike F α fun x => β✝
inst✝⁵ : CommMonoid α
inst✝⁴ : CommMonoid β✝
inst✝³ : CommMonoid γ
inst✝² : CommMonoid δ
inst✝¹ : CommGroup G
A : Set α
B : Set β✝
C : Set γ
n : ℕ
a b c d : α
β : Type ?u.66761
inst✝ : CommGroup β
src✝ : CommMonoid (A →*[n] β) := commMonoid
⊢ ∀ (a b : A →*[n] β), a / b = a * b⁻¹

Next tactic:
intros
/-- If `β` is a commutative group, then `A →*[n] β` is a commutative group too. -/
@[to_additive
      "If `β` is an additive commutative group, then `A →*[n] β` is an additive commutative
      group too."]
instance commGroup {β} [CommGroup β] : CommGroup (A →*[n] β) :=
  { FreimanHom.commMonoid with
    div_eq_mul_inv := by
      intros
      

Proof state:
F : Type u_1
α : Type u_2
β✝ : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁶ : FunLike F α fun x => β✝
inst✝⁵ : CommMonoid α
inst✝⁴ : CommMonoid β✝
inst✝³ : CommMonoid γ
inst✝² : CommMonoid δ
inst✝¹ : CommGroup G
A : Set α
B : Set β✝
C : Set γ
n : ℕ
a b c d : α
β : Type ?u.66761
inst✝ : CommGroup β
src✝ : CommMonoid (A →*[n] β) := commMonoid
a✝ b✝ : A →*[n] β
⊢ a✝ / b✝ = a✝ * b✝⁻¹

Next tactic:
ext
/-- If `β` is a commutative group, then `A →*[n] β` is a commutative group too. -/
@[to_additive
      "If `β` is an additive commutative group, then `A →*[n] β` is an additive commutative
      group too."]
instance commGroup {β} [CommGroup β] : CommGroup (A →*[n] β) :=
  { FreimanHom.commMonoid with
    div_eq_mul_inv := by
      intros
      ext
      

Proof state:
case h
F : Type u_1
α : Type u_2
β✝ : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁶ : FunLike F α fun x => β✝
inst✝⁵ : CommMonoid α
inst✝⁴ : CommMonoid β✝
inst✝³ : CommMonoid γ
inst✝² : CommMonoid δ
inst✝¹ : CommGroup G
A : Set α
B : Set β✝
C : Set γ
n : ℕ
a b c d : α
β : Type ?u.66761
inst✝ : CommGroup β
src✝ : CommMonoid (A →*[n] β) := commMonoid
a✝ b✝ : A →*[n] β
x✝ : α
⊢ (a✝ / b✝) x✝ = (a✝ * b✝⁻¹) x✝

Next tactic:
apply div_eq_mul_inv
/-- If `β` is a commutative group, then `A →*[n] β` is a commutative group too. -/
@[to_additive
      "If `β` is an additive commutative group, then `A →*[n] β` is an additive commutative
      group too."]
instance commGroup {β} [CommGroup β] : CommGroup (A →*[n] β) :=
  { FreimanHom.commMonoid with
    div_eq_mul_inv := by
      intros
      ext
      apply div_eq_mul_inv
    mul_left_inv := by
      

Proof state:
F : Type u_1
α : Type u_2
β✝ : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁶ : FunLike F α fun x => β✝
inst✝⁵ : CommMonoid α
inst✝⁴ : CommMonoid β✝
inst✝³ : CommMonoid γ
inst✝² : CommMonoid δ
inst✝¹ : CommGroup G
A : Set α
B : Set β✝
C : Set γ
n : ℕ
a b c d : α
β : Type ?u.66761
inst✝ : CommGroup β
src✝ : CommMonoid (A →*[n] β) := commMonoid
⊢ ∀ (a : A →*[n] β), a⁻¹ * a = 1

Next tactic:
intros
/-- If `β` is a commutative group, then `A →*[n] β` is a commutative group too. -/
@[to_additive
      "If `β` is an additive commutative group, then `A →*[n] β` is an additive commutative
      group too."]
instance commGroup {β} [CommGroup β] : CommGroup (A →*[n] β) :=
  { FreimanHom.commMonoid with
    div_eq_mul_inv := by
      intros
      ext
      apply div_eq_mul_inv
    mul_left_inv := by
      intros
      

Proof state:
F : Type u_1
α : Type u_2
β✝ : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁶ : FunLike F α fun x => β✝
inst✝⁵ : CommMonoid α
inst✝⁴ : CommMonoid β✝
inst✝³ : CommMonoid γ
inst✝² : CommMonoid δ
inst✝¹ : CommGroup G
A : Set α
B : Set β✝
C : Set γ
n : ℕ
a b c d : α
β : Type ?u.66761
inst✝ : CommGroup β
src✝ : CommMonoid (A →*[n] β) := commMonoid
a✝ : A →*[n] β
⊢ a✝⁻¹ * a✝ = 1

Next tactic:
ext
/-- If `β` is a commutative group, then `A →*[n] β` is a commutative group too. -/
@[to_additive
      "If `β` is an additive commutative group, then `A →*[n] β` is an additive commutative
      group too."]
instance commGroup {β} [CommGroup β] : CommGroup (A →*[n] β) :=
  { FreimanHom.commMonoid with
    div_eq_mul_inv := by
      intros
      ext
      apply div_eq_mul_inv
    mul_left_inv := by
      intros
      ext
      

Proof state:
case h
F : Type u_1
α : Type u_2
β✝ : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁶ : FunLike F α fun x => β✝
inst✝⁵ : CommMonoid α
inst✝⁴ : CommMonoid β✝
inst✝³ : CommMonoid γ
inst✝² : CommMonoid δ
inst✝¹ : CommGroup G
A : Set α
B : Set β✝
C : Set γ
n : ℕ
a b c d : α
β : Type ?u.66761
inst✝ : CommGroup β
src✝ : CommMonoid (A →*[n] β) := commMonoid
a✝ : A →*[n] β
x✝ : α
⊢ (a✝⁻¹ * a✝) x✝ = 1 x✝

Next tactic:
apply mul_left_inv
/-- A monoid homomorphism is naturally a `FreimanHom` on its entire domain.

We can't leave the domain `A : Set α` of the `FreimanHom` a free variable, since it wouldn't be
inferrable. -/
@[to_additive AddMonoidHom.addFreimanHomClass
      " An additive monoid homomorphism is naturally an `AddFreimanHom` on its entire
      domain.

      We can't leave the domain `A : Set α` of the `AddFreimanHom` a free variable, since it
      wouldn't be inferrable."]
instance MonoidHom.freimanHomClass : FreimanHomClass (α →* β) Set.univ β n where
  map_prod_eq_map_prod' f s t _ _ _ _ h := by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁵ : FunLike F α fun x => β
inst✝⁴ : CommMonoid α
inst✝³ : CommMonoid β
inst✝² : CommMonoid γ
inst✝¹ : CommMonoid δ
inst✝ : CommGroup G
A : Set α
B : Set β
C : Set γ
n : ℕ
a b c d : α
f : α →* β
s t : Multiset α
x✝³ : ∀ ⦃x : α⦄, x ∈ s → x ∈ Set.univ
x✝² : ∀ ⦃x : α⦄, x ∈ t → x ∈ Set.univ
x✝¹ : card s = n
x✝ : card t = n
h : prod s = prod t
⊢ prod (map (⇑f) s) = prod (map (⇑f) t)

Next tactic:
rw [← f.map_multiset_prod, h, f.map_multiset_prod]
@[to_additive AddMonoidHom.toAddFreimanHom_injective]
theorem MonoidHom.toFreimanHom_injective :
    Function.Injective (MonoidHom.toFreimanHom A n : (α →* β) → A →*[n] β) := fun f g h =>
   by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝⁵ : FunLike F α fun x => β
inst✝⁴ : CommMonoid α
inst✝³ : CommMonoid β
inst✝² : CommMonoid γ
inst✝¹ : CommMonoid δ
inst✝ : CommGroup G
A : Set α
B : Set β
C : Set γ
n : ℕ
a b c d : α
f g : α →* β
h : toFreimanHom A n f = toFreimanHom A n g
⊢ f = g

Next tactic:
rwa [toFreimanHom, toFreimanHom, FreimanHom.mk.injEq, FunLike.coe_fn_eq] at h
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
m n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hs : card s = m
ht : card t = m
hst : prod s = prod t
h : m ≤ n
⊢ prod (map (⇑f) s) = prod (map (⇑f) t)

Next tactic:
obtain rfl | hm := m.eq_zero_or_pos
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  obtain rfl | hm := m.eq_zero_or_pos
  · 

Proof state:
case inl
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hst : prod s = prod t
hs : card s = 0
ht : card t = 0
h : 0 ≤ n
⊢ prod (map (⇑f) s) = prod (map (⇑f) t)

Next tactic:
rw [card_eq_zero] at hs ht
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  obtain rfl | hm := m.eq_zero_or_pos
  · rw [card_eq_zero] at hs ht
    

Proof state:
case inl
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hst : prod s = prod t
hs : s = 0
ht : t = 0
h : 0 ≤ n
⊢ prod (map (⇑f) s) = prod (map (⇑f) t)

Next tactic:
rw [hs, ht]
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  obtain rfl | hm := m.eq_zero_or_pos
  · rw [card_eq_zero] at hs ht
    rw [hs, ht]
  

Proof state:
case inr
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
m n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hs : card s = m
ht : card t = m
hst : prod s = prod t
h : m ≤ n
hm : m > 0
⊢ prod (map (⇑f) s) = prod (map (⇑f) t)

Next tactic:
simp? [← hs, card_pos_iff_exists_mem] at hm says
    simp only [← hs, gt_iff_lt, card_pos_iff_exists_mem] at hm
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  obtain rfl | hm := m.eq_zero_or_pos
  · rw [card_eq_zero] at hs ht
    rw [hs, ht]
  simp? [← hs, card_pos_iff_exists_mem] at hm says
    

Proof state:
case inr
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
m n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hs : card s = m
ht : card t = m
hst : prod s = prod t
h : m ≤ n
hm : m > 0
⊢ prod (map (⇑f) s) = prod (map (⇑f) t)

Next tactic:
simp only [← hs, gt_iff_lt, card_pos_iff_exists_mem] at hm
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  obtain rfl | hm := m.eq_zero_or_pos
  · rw [card_eq_zero] at hs ht
    rw [hs, ht]
  simp? [← hs, card_pos_iff_exists_mem] at hm says
    simp only [← hs, gt_iff_lt, card_pos_iff_exists_mem] at hm
  

Proof state:
case inr
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
m n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hs : card s = m
ht : card t = m
hst : prod s = prod t
h : m ≤ n
hm : ∃ a, a ∈ s
⊢ prod (map (⇑f) s) = prod (map (⇑f) t)

Next tactic:
obtain ⟨a, ha⟩ := hm
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  obtain rfl | hm := m.eq_zero_or_pos
  · rw [card_eq_zero] at hs ht
    rw [hs, ht]
  simp? [← hs, card_pos_iff_exists_mem] at hm says
    simp only [← hs, gt_iff_lt, card_pos_iff_exists_mem] at hm
  obtain ⟨a, ha⟩ := hm
  

Proof state:
case inr.intro
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
m n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hs : card s = m
ht : card t = m
hst : prod s = prod t
h : m ≤ n
a : α
ha : a ∈ s
⊢ prod (map (⇑f) s) = prod (map (⇑f) t)

Next tactic:
suffices
    ((s + Multiset.replicate (n - m) a).map f).prod =
      ((t + Multiset.replicate (n - m) a).map f).prod by
    simp_rw [Multiset.map_add, prod_add] at this
    exact mul_right_cancel this
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  obtain rfl | hm := m.eq_zero_or_pos
  · rw [card_eq_zero] at hs ht
    rw [hs, ht]
  simp? [← hs, card_pos_iff_exists_mem] at hm says
    simp only [← hs, gt_iff_lt, card_pos_iff_exists_mem] at hm
  obtain ⟨a, ha⟩ := hm
  suffices
    ((s + Multiset.replicate (n - m) a).map f).prod =
      ((t + Multiset.replicate (n - m) a).map f).prod by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
m n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hs : card s = m
ht : card t = m
hst : prod s = prod t
h : m ≤ n
a : α
ha : a ∈ s
this : prod (map (⇑f) (s + replicate (n - m) a)) = prod (map (⇑f) (t + replicate (n - m) a))
⊢ prod (map (⇑f) s) = prod (map (⇑f) t)

Next tactic:
simp_rw [Multiset.map_add, prod_add] at this
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  obtain rfl | hm := m.eq_zero_or_pos
  · rw [card_eq_zero] at hs ht
    rw [hs, ht]
  simp? [← hs, card_pos_iff_exists_mem] at hm says
    simp only [← hs, gt_iff_lt, card_pos_iff_exists_mem] at hm
  obtain ⟨a, ha⟩ := hm
  suffices
    ((s + Multiset.replicate (n - m) a).map f).prod =
      ((t + Multiset.replicate (n - m) a).map f).prod by
    simp_rw [Multiset.map_add, prod_add] at this
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
m n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hs : card s = m
ht : card t = m
hst : prod s = prod t
h : m ≤ n
a : α
ha : a ∈ s
this :
  prod (map (⇑f) s) * prod (map (⇑f) (replicate (n - m) a)) = prod (map (⇑f) t) * prod (map (⇑f) (replicate (n - m) a))
⊢ prod (map (⇑f) s) = prod (map (⇑f) t)

Next tactic:
exact mul_right_cancel this
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  obtain rfl | hm := m.eq_zero_or_pos
  · rw [card_eq_zero] at hs ht
    rw [hs, ht]
  simp? [← hs, card_pos_iff_exists_mem] at hm says
    simp only [← hs, gt_iff_lt, card_pos_iff_exists_mem] at hm
  obtain ⟨a, ha⟩ := hm
  suffices
    ((s + Multiset.replicate (n - m) a).map f).prod =
      ((t + Multiset.replicate (n - m) a).map f).prod by
    simp_rw [Multiset.map_add, prod_add] at this
    exact mul_right_cancel this
  

Proof state:
case inr.intro
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
m n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hs : card s = m
ht : card t = m
hst : prod s = prod t
h : m ≤ n
a : α
ha : a ∈ s
⊢ prod (map (⇑f) (s + replicate (n - m) a)) = prod (map (⇑f) (t + replicate (n - m) a))

Next tactic:
replace ha := hsA _ ha
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  obtain rfl | hm := m.eq_zero_or_pos
  · rw [card_eq_zero] at hs ht
    rw [hs, ht]
  simp? [← hs, card_pos_iff_exists_mem] at hm says
    simp only [← hs, gt_iff_lt, card_pos_iff_exists_mem] at hm
  obtain ⟨a, ha⟩ := hm
  suffices
    ((s + Multiset.replicate (n - m) a).map f).prod =
      ((t + Multiset.replicate (n - m) a).map f).prod by
    simp_rw [Multiset.map_add, prod_add] at this
    exact mul_right_cancel this
  replace ha := hsA _ ha
  

Proof state:
case inr.intro
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
m n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hs : card s = m
ht : card t = m
hst : prod s = prod t
h : m ≤ n
a : α
ha : a ∈ A
⊢ prod (map (⇑f) (s + replicate (n - m) a)) = prod (map (⇑f) (t + replicate (n - m) a))

Next tactic:
apply map_prod_eq_map_prod f (A := A) (β := β) (n := n) (fun x hx => _) (fun x hx => _) _ _ _
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  obtain rfl | hm := m.eq_zero_or_pos
  · rw [card_eq_zero] at hs ht
    rw [hs, ht]
  simp? [← hs, card_pos_iff_exists_mem] at hm says
    simp only [← hs, gt_iff_lt, card_pos_iff_exists_mem] at hm
  obtain ⟨a, ha⟩ := hm
  suffices
    ((s + Multiset.replicate (n - m) a).map f).prod =
      ((t + Multiset.replicate (n - m) a).map f).prod by
    simp_rw [Multiset.map_add, prod_add] at this
    exact mul_right_cancel this
  replace ha := hsA _ ha
  apply map_prod_eq_map_prod f (A := A) (β := β) (n := n) (fun x hx => _) (fun x hx => _) _ _ _
  -- porting note: below could be golfed when wlog is available
  · 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
m n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hs : card s = m
ht : card t = m
hst : prod s = prod t
h : m ≤ n
a : α
ha : a ∈ A
⊢ ∀ x ∈ s + replicate (n - m) a, x ∈ A

Next tactic:
intro x hx
@[to_additive]
theorem map_prod_eq_map_prod_of_le [FreimanHomClass F A β n] (f : F) {s t : Multiset α}
    (hsA : ∀ x ∈ s, x ∈ A) (htA : ∀ x ∈ t, x ∈ A)
    (hs : Multiset.card s = m) (ht : Multiset.card t = m)
    (hst : s.prod = t.prod) (h : m ≤ n) : (s.map f).prod = (t.map f).prod := by
  obtain rfl | hm := m.eq_zero_or_pos
  · rw [card_eq_zero] at hs ht
    rw [hs, ht]
  simp? [← hs, card_pos_iff_exists_mem] at hm says
    simp only [← hs, gt_iff_lt, card_pos_iff_exists_mem] at hm
  obtain ⟨a, ha⟩ := hm
  suffices
    ((s + Multiset.replicate (n - m) a).map f).prod =
      ((t + Multiset.replicate (n - m) a).map f).prod by
    simp_rw [Multiset.map_add, prod_add] at this
    exact mul_right_cancel this
  replace ha := hsA _ ha
  apply map_prod_eq_map_prod f (A := A) (β := β) (n := n) (fun x hx => _) (fun x hx => _) _ _ _
  -- porting note: below could be golfed when wlog is available
  · intro x hx
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
δ : Type u_5
G : Type u_6
inst✝³ : FunLike F α fun x => β
inst✝² : CommMonoid α
inst✝¹ : CancelCommMonoid β
A : Set α
m n : ℕ
inst✝ : FreimanHomClass F A β n
f : F
s t : Multiset α
hsA : ∀ x ∈ s, x ∈ A
htA : ∀ x ∈ t, x ∈ A
hs : card s = m
ht : card t = m
hst : prod s = prod t
h : m ≤ n
a : α
ha : a ∈ A
x : α
hx : x ∈ s + replicate (n - m) a
⊢ x ∈ A

Next tactic:
rw [mem_add] at hx