l3lab/ntp-mathlib huggingface dataset:
@[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
    rw [mem_add] at 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 ∨ x ∈ replicate (n - m) a
⊢ x ∈ A

Next tactic:
cases' hx with hx 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
    rw [mem_add] at hx
    cases' hx with hx hx
    · 

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 α
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
⊢ x ∈ A

Next tactic:
exact hsA 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
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact hsA x hx
    · 

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
a : α
ha : a ∈ A
x : α
hx : x ∈ replicate (n - m) a
⊢ x ∈ A

Next tactic:
rwa [eq_of_mem_replicate 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
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact hsA x hx
    · rwa [eq_of_mem_replicate 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 ∈ t + 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
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact hsA x hx
    · rwa [eq_of_mem_replicate hx]
  · 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 ∈ t + replicate (n - m) a
⊢ x ∈ A

Next tactic:
rw [mem_add] at 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
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact hsA x hx
    · rwa [eq_of_mem_replicate hx]
  · intro x hx
    rw [mem_add] at 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 ∈ t ∨ x ∈ replicate (n - m) a
⊢ x ∈ A

Next tactic:
cases' hx with hx 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
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact hsA x hx
    · rwa [eq_of_mem_replicate hx]
  · intro x hx
    rw [mem_add] at hx
    cases' hx with hx hx
    · 

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 α
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 ∈ t
⊢ x ∈ A

Next tactic:
exact htA 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
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact hsA x hx
    · rwa [eq_of_mem_replicate hx]
  · intro x hx
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact htA x hx
    · 

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
a : α
ha : a ∈ A
x : α
hx : x ∈ replicate (n - m) a
⊢ x ∈ A

Next tactic:
rwa [eq_of_mem_replicate 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
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact hsA x hx
    · rwa [eq_of_mem_replicate hx]
  · intro x hx
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact htA x hx
    · rwa [eq_of_mem_replicate 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
⊢ card (s + replicate (n - m) a) = n

Next tactic:
rw [_root_.map_add, card_replicate, hs]
@[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
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact hsA x hx
    · rwa [eq_of_mem_replicate hx]
  · intro x hx
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact htA x hx
    · rwa [eq_of_mem_replicate hx]
  · rw [_root_.map_add, card_replicate, hs]; 

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
⊢ m + (n - m) = n

Next tactic:
simp [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
  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
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact hsA x hx
    · rwa [eq_of_mem_replicate hx]
  · intro x hx
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact htA x hx
    · rwa [eq_of_mem_replicate hx]
  · rw [_root_.map_add, card_replicate, hs]; simp [h]
  · 

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
⊢ card (t + replicate (n - m) a) = n

Next tactic:
rw [_root_.map_add, card_replicate, 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]
  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
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact hsA x hx
    · rwa [eq_of_mem_replicate hx]
  · intro x hx
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact htA x hx
    · rwa [eq_of_mem_replicate hx]
  · rw [_root_.map_add, card_replicate, hs]; simp [h]
  · rw [_root_.map_add, card_replicate, ht]; 

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
⊢ m + (n - m) = n

Next tactic:
simp [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
  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
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact hsA x hx
    · rwa [eq_of_mem_replicate hx]
  · intro x hx
    rw [mem_add] at hx
    cases' hx with hx hx
    · exact htA x hx
    · rwa [eq_of_mem_replicate hx]
  · rw [_root_.map_add, card_replicate, hs]; simp [h]
  · rw [_root_.map_add, card_replicate, ht]; simp [h]
  · 

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
⊢ prod (s + replicate (n - m) a) = prod (t + replicate (n - m) a)

Next tactic:
rw [prod_add, prod_add, hst]
@[to_additive AddFreimanHom.toAddFreimanHom_injective]
theorem FreimanHom.toFreimanHom_injective (h : m ≤ n) :
    Function.Injective (FreimanHom.toFreimanHom h : (A →*[n] β) → A →*[m] β) := fun f g hfg =>
  FreimanHom.ext <| 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 : ℕ
h : m ≤ n
f g : A →*[n] β
hfg : toFreimanHom h f = toFreimanHom h g
⊢ ∀ (x : α), f x = g x

Next tactic:
convert FunLike.ext_iff.1 hfg using 0
/-- If `A.det` has a constructive inverse, produce one for `A`. -/
def invertibleOfDetInvertible [Invertible A.det] : Invertible A where
  invOf := ⅟ A.det • A.adjugate
  mul_invOf_self := by
    rw [mul_smul_comm, mul_adjugate, smul_smul, invOf_mul_self, one_smul]
  invOf_mul_self := by
    

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝³ : Fintype n
inst✝² : DecidableEq n
inst✝¹ : CommRing α
A B : Matrix n n α
inst✝ : Invertible (det A)
⊢ ⅟(det A) • adjugate A * A = 1

Next tactic:
rw [smul_mul_assoc, adjugate_mul, smul_smul, invOf_mul_self, one_smul]
/-- If `A.det` has a constructive inverse, produce one for `A`. -/
def invertibleOfDetInvertible [Invertible A.det] : Invertible A where
  invOf := ⅟ A.det • A.adjugate
  mul_invOf_self := by
    

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝³ : Fintype n
inst✝² : DecidableEq n
inst✝¹ : CommRing α
A B : Matrix n n α
inst✝ : Invertible (det A)
⊢ A * ⅟(det A) • adjugate A = 1

Next tactic:
rw [mul_smul_comm, mul_adjugate, smul_smul, invOf_mul_self, one_smul]
theorem invOf_eq [Invertible A.det] [Invertible A] : ⅟ A = ⅟ A.det • A.adjugate := by
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁴ : Fintype n
inst✝³ : DecidableEq n
inst✝² : CommRing α
A B : Matrix n n α
inst✝¹ : Invertible (det A)
inst✝ : Invertible A
⊢ ⅟A = ⅟(det A) • adjugate A

Next tactic:
letI := invertibleOfDetInvertible A
theorem invOf_eq [Invertible A.det] [Invertible A] : ⅟ A = ⅟ A.det • A.adjugate := by
  letI := invertibleOfDetInvertible A
  

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝⁴ : Fintype n
inst✝³ : DecidableEq n
inst✝² : CommRing α
A B : Matrix n n α
inst✝¹ : Invertible (det A)
inst✝ : Invertible A
this : Invertible A := invertibleOfDetInvertible A
⊢ ⅟A = ⅟(det A) • adjugate A

Next tactic:
convert (rfl : ⅟ A = _)
/-- `A.det` is invertible if `A` has a left inverse. -/
def detInvertibleOfLeftInverse (h : B * A = 1) : Invertible A.det where
  invOf := B.det
  mul_invOf_self := by rw [mul_comm, ← det_mul, h, det_one]
  invOf_mul_self := by 

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : B * A = 1
⊢ det B * det A = 1

Next tactic:
rw [← det_mul, h, det_one]
/-- `A.det` is invertible if `A` has a left inverse. -/
def detInvertibleOfLeftInverse (h : B * A = 1) : Invertible A.det where
  invOf := B.det
  mul_invOf_self := by 

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : B * A = 1
⊢ det A * det B = 1

Next tactic:
rw [mul_comm, ← det_mul, h, det_one]
/-- `A.det` is invertible if `A` has a right inverse. -/
def detInvertibleOfRightInverse (h : A * B = 1) : Invertible A.det where
  invOf := B.det
  mul_invOf_self := by rw [← det_mul, h, det_one]
  invOf_mul_self := by 

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : A * B = 1
⊢ det B * det A = 1

Next tactic:
rw [mul_comm, ← det_mul, h, det_one]
/-- `A.det` is invertible if `A` has a right inverse. -/
def detInvertibleOfRightInverse (h : A * B = 1) : Invertible A.det where
  invOf := B.det
  mul_invOf_self := by 

Proof state:
l : Type u_1
m : Type u
n : Type u'
α : Type v
inst✝² : Fintype n
inst✝¹ : DecidableEq n
inst✝ : CommRing α
A B : Matrix n n α
h : A * B = 1
⊢ det A * det B = 1

Next tactic:
rw [← det_mul, h, det_one]