/-
Copyright (c) 2017 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro
-/
import data.fintype.basic
import algebra.big_operators.ring

/-!
Results about "big operations" over a `fintype`, and consequent
results about cardinalities of certain types.

## Implementation note
This content had previously been in `data.fintype.basic`, but was moved here to avoid
requiring `algebra.big_operators` (and hence many other imports) as a
dependency of `fintype`.

However many of the results here really belong in `algebra.big_operators.basic`
and should be moved at some point.
-/

universes u v

variables {α : Type*} {β : Type*} {γ : Type*}

open_locale big_operators

namespace fintype

@[to_additive]
lemma prod_bool [comm_monoid α] (f : bool → α) : ∏ b, f b = f tt * f ff := by simp

lemma card_eq_sum_ones {α} [fintype α] : fintype.card α = ∑ a : α, 1 :=
finset.card_eq_sum_ones _

section
open finset

variables {ι : Type*} [decidable_eq ι] [fintype ι]

@[to_additive]
lemma prod_extend_by_one [comm_monoid α] (s : finset ι) (f : ι → α) :
  ∏ i, (if i ∈ s then f i else 1) = ∏ i in s, f i :=
by rw [← prod_filter, filter_mem_eq_inter, univ_inter]

end

section
variables {M : Type*} [fintype α] [comm_monoid M]

@[to_additive]
lemma prod_eq_one (f : α → M) (h : ∀ a, f a = 1) :
  (∏ a, f a) = 1 :=
finset.prod_eq_one $ λ a ha, h a

@[to_additive]
lemma prod_congr (f g : α → M) (h : ∀ a, f a = g a) :
  (∏ a, f a) = ∏ a, g a :=
finset.prod_congr rfl $ λ a ha, h a

@[to_additive]
lemma prod_eq_single {f : α → M} (a : α) (h : ∀ x ≠ a, f x = 1) :
  (∏ x, f x) = f a :=
finset.prod_eq_single a (λ x _ hx, h x hx) $ λ ha, (ha (finset.mem_univ a)).elim

@[to_additive]
lemma prod_eq_mul {f : α → M} (a b : α) (h₁ : a ≠ b) (h₂ : ∀ x, x ≠ a ∧ x ≠ b → f x = 1) :
  (∏ x, f x) = (f a) * (f b) :=
begin
  apply finset.prod_eq_mul a b h₁ (λ x _ hx, h₂ x hx);
  exact λ hc, (hc (finset.mem_univ _)).elim
end

@[to_additive]
lemma prod_unique [unique β] (f : β → M) :
  (∏ x, f x) = f (default β) :=
by simp only [finset.prod_singleton, univ_unique]

/-- If a product of a `finset` of a subsingleton type has a given
value, so do the terms in that product. -/
@[to_additive "If a sum of a `finset` of a subsingleton type has a given
value, so do the terms in that sum."]
lemma eq_of_subsingleton_of_prod_eq {ι : Type*} [subsingleton ι] {s : finset ι}
    {f : ι → M} {b : M} (h : ∏ i in s, f i = b) : ∀ i ∈ s, f i = b :=
finset.eq_of_card_le_one_of_prod_eq (finset.card_le_one_of_subsingleton s) h

end

end fintype

open finset

section

variables {M : Type*} [fintype α] [comm_monoid M]

@[simp, to_additive]
lemma fintype.prod_option (f : option α → M) : ∏ i, f i = f none * ∏ i, f (some i) :=
show ((finset.insert_none _).1.map f).prod = _,
by simp only [finset.prod, finset.insert_none, multiset.map_cons, multiset.prod_cons,
  multiset.map_map]

end

@[to_additive]
theorem fin.prod_univ_def [comm_monoid β] {n : ℕ} (f : fin n → β) :
  ∏ i, f i = ((list.fin_range n).map f).prod :=
by simp [fin.univ_def, finset.fin_range]

@[to_additive]
theorem finset.prod_range [comm_monoid β] {n : ℕ} (f : ℕ → β) :
  ∏ i in finset.range n, f i = ∏ i : fin n, f i :=
begin
  fapply @finset.prod_bij' _ _ _ _ _ _,
  exact λ k w, ⟨k, (by simpa using w)⟩,
  swap 3,
  exact λ a m, a,
  swap 3,
  exact λ a m, by simpa using a.2,
  all_goals { tidy, },
end

@[to_additive]
theorem fin.prod_of_fn [comm_monoid β] {n : ℕ} (f : fin n → β) :
  (list.of_fn f).prod = ∏ i, f i :=
by rw [list.of_fn_eq_map, fin.prod_univ_def]

/-- A product of a function `f : fin 0 → β` is `1` because `fin 0` is empty -/
@[simp, to_additive "A sum of a function `f : fin 0 → β` is `0` because `fin 0` is empty"]
theorem fin.prod_univ_zero [comm_monoid β] (f : fin 0 → β) : ∏ i, f i = 1 := rfl

/-- A product of a function `f : fin (n + 1) → β` over all `fin (n + 1)`
is the product of `f x`, for some `x : fin (n + 1)` times the remaining product -/
theorem fin.prod_univ_succ_above [comm_monoid β] {n : ℕ} (f : fin (n + 1) → β) (x : fin (n + 1)) :
  ∏ i, f i = f x * ∏ i : fin n, f (x.succ_above i) :=
begin
  rw [fin.univ_succ_above, finset.prod_insert, finset.prod_image],
  { intros x _ y _ hxy, exact fin.succ_above_right_inj.mp hxy },
  { simp [fin.succ_above_ne] }
end

/-- A sum of a function `f : fin (n + 1) → β` over all `fin (n + 1)`
is the sum of `f x`, for some `x : fin (n + 1)` plus the remaining product -/
theorem fin.sum_univ_succ_above [add_comm_monoid β] {n : ℕ} (f : fin (n + 1) → β)
  (x : fin (n + 1)) :
  ∑ i, f i = f x + ∑ i : fin n, f (x.succ_above i) :=
by apply @fin.prod_univ_succ_above (multiplicative β)

attribute [to_additive] fin.prod_univ_succ_above

/-- A product of a function `f : fin (n + 1) → β` over all `fin (n + 1)`
is the product of `f 0` plus the remaining product -/
theorem fin.prod_univ_succ [comm_monoid β] {n : ℕ} (f : fin (n + 1) → β) :
  ∏ i, f i = f 0 * ∏ i : fin n, f i.succ :=
fin.prod_univ_succ_above f 0

/-- A sum of a function `f : fin (n + 1) → β` over all `fin (n + 1)`
is the sum of `f 0` plus the remaining product -/
theorem fin.sum_univ_succ [add_comm_monoid β] {n : ℕ} (f : fin (n + 1) → β) :
  ∑ i, f i = f 0 + ∑ i : fin n, f i.succ :=
fin.sum_univ_succ_above f 0

attribute [to_additive] fin.prod_univ_succ

/-- A product of a function `f : fin (n + 1) → β` over all `fin (n + 1)`
is the product of `f (fin.last n)` plus the remaining product -/
theorem fin.prod_univ_cast_succ [comm_monoid β] {n : ℕ} (f : fin (n + 1) → β) :
  ∏ i, f i = (∏ i : fin n, f i.cast_succ) * f (fin.last n) :=
by simpa [mul_comm] using fin.prod_univ_succ_above f (fin.last n)

/-- A sum of a function `f : fin (n + 1) → β` over all `fin (n + 1)`
is the sum of `f (fin.last n)` plus the remaining sum -/
theorem fin.sum_univ_cast_succ [add_comm_monoid β] {n : ℕ} (f : fin (n + 1) → β) :
  ∑ i, f i = ∑ i : fin n, f i.cast_succ + f (fin.last n) :=
by apply @fin.prod_univ_cast_succ (multiplicative β)

attribute [to_additive] fin.prod_univ_cast_succ

open finset

@[simp] theorem fintype.card_sigma {α : Type*} (β : α → Type*)
  [fintype α] [∀ a, fintype (β a)] :
  fintype.card (sigma β) = ∑ a, fintype.card (β a) :=
card_sigma _ _

-- FIXME ouch, this should be in the main file.
@[simp] theorem fintype.card_sum (α β : Type*) [fintype α] [fintype β] :
  fintype.card (α ⊕ β) = fintype.card α + fintype.card β :=
by simp [sum.fintype, fintype.of_equiv_card]

@[simp] lemma finset.card_pi [decidable_eq α] {δ : α → Type*}
  (s : finset α) (t : Π a, finset (δ a)) :
  (s.pi t).card = ∏ a in s, card (t a) :=
multiset.card_pi _ _

@[simp] lemma fintype.card_pi_finset [decidable_eq α] [fintype α]
  {δ : α → Type*} (t : Π a, finset (δ a)) :
  (fintype.pi_finset t).card = ∏ a, card (t a) :=
by simp [fintype.pi_finset, card_map]

@[simp] lemma fintype.card_pi {β : α → Type*} [decidable_eq α] [fintype α]
  [f : Π a, fintype (β a)] : fintype.card (Π a, β a) = ∏ a, fintype.card (β a) :=
fintype.card_pi_finset _

-- FIXME ouch, this should be in the main file.
@[simp] lemma fintype.card_fun [decidable_eq α] [fintype α] [fintype β] :
  fintype.card (α → β) = fintype.card β ^ fintype.card α :=
by rw [fintype.card_pi, finset.prod_const]; refl

@[simp] lemma card_vector [fintype α] (n : ℕ) :
  fintype.card (vector α n) = fintype.card α ^ n :=
by rw fintype.of_equiv_card; simp

@[simp, to_additive]
lemma finset.prod_attach_univ [fintype α] [comm_monoid β] (f : {a : α // a ∈ @univ α _} → β) :
  ∏ x in univ.attach, f x = ∏ x, f ⟨x, (mem_univ _)⟩ :=
fintype.prod_equiv (equiv.subtype_univ_equiv (λ x, mem_univ _)) _ _ (λ x, by simp)

/-- Taking a product over `univ.pi t` is the same as taking the product over `fintype.pi_finset t`.
  `univ.pi t` and `fintype.pi_finset t` are essentially the same `finset`, but differ
  in the type of their element, `univ.pi t` is a `finset (Π a ∈ univ, t a)` and
  `fintype.pi_finset t` is a `finset (Π a, t a)`. -/
@[to_additive "Taking a sum over `univ.pi t` is the same as taking the sum over
  `fintype.pi_finset t`. `univ.pi t` and `fintype.pi_finset t` are essentially the same `finset`,
  but differ in the type of their element, `univ.pi t` is a `finset (Π a ∈ univ, t a)` and
  `fintype.pi_finset t` is a `finset (Π a, t a)`."]
lemma finset.prod_univ_pi [decidable_eq α] [fintype α] [comm_monoid β]
  {δ : α → Type*} {t : Π (a : α), finset (δ a)}
  (f : (Π (a : α), a ∈ (univ : finset α) → δ a) → β) :
  ∏ x in univ.pi t, f x = ∏ x in fintype.pi_finset t, f (λ a _, x a) :=
prod_bij (λ x _ a, x a (mem_univ _))
  (by simp)
  (by simp)
  (by simp [function.funext_iff] {contextual := tt})
  (λ x hx, ⟨λ a _, x a, by simp * at *⟩)

/-- The product over `univ` of a sum can be written as a sum over the product of sets,
  `fintype.pi_finset`. `finset.prod_sum` is an alternative statement when the product is not
  over `univ` -/
lemma finset.prod_univ_sum [decidable_eq α] [fintype α] [comm_semiring β] {δ : α → Type u_1}
  [Π (a : α), decidable_eq (δ a)] {t : Π (a : α), finset (δ a)}
  {f : Π (a : α), δ a → β} :
  ∏ a, ∑ b in t a, f a b = ∑ p in fintype.pi_finset t, ∏ x, f x (p x) :=
by simp only [finset.prod_attach_univ, prod_sum, finset.sum_univ_pi]

/-- Summing `a^s.card * b^(n-s.card)` over all finite subsets `s` of a fintype of cardinality `n`
gives `(a + b)^n`. The "good" proof involves expanding along all coordinates using the fact that
`x^n` is multilinear, but multilinear maps are only available now over rings, so we give instead
a proof reducing to the usual binomial theorem to have a result over semirings. -/
lemma fintype.sum_pow_mul_eq_add_pow
  (α : Type*) [fintype α] {R : Type*} [comm_semiring R] (a b : R) :
  ∑ s : finset α, a ^ s.card * b ^ (fintype.card α - s.card) =
  (a + b) ^ (fintype.card α) :=
finset.sum_pow_mul_eq_add_pow _ _ _

lemma fin.sum_pow_mul_eq_add_pow {n : ℕ} {R : Type*} [comm_semiring R] (a b : R) :
  ∑ s : finset (fin n), a ^ s.card * b ^ (n - s.card) = (a + b) ^ n :=
by simpa using fintype.sum_pow_mul_eq_add_pow (fin n) a b

lemma fin.prod_const [comm_monoid α] (n : ℕ) (x : α) : ∏ i : fin n, x = x ^ n := by simp

lemma fin.sum_const [add_comm_monoid α] (n : ℕ) (x : α) : ∑ i : fin n, x = n • x := by simp

@[to_additive]
lemma function.bijective.prod_comp [fintype α] [fintype β] [comm_monoid γ] {f : α → β}
  (hf : function.bijective f) (g : β → γ) :
  ∏ i, g (f i) = ∏ i, g i :=
fintype.prod_bijective f hf _ _ (λ x, rfl)

@[to_additive]
lemma equiv.prod_comp [fintype α] [fintype β] [comm_monoid γ] (e : α ≃ β) (f : β → γ) :
  ∏ i, f (e i) = ∏ i, f i :=
e.bijective.prod_comp f

/-- It is equivalent to sum a function over `fin n` or `finset.range n`. -/
@[to_additive]
lemma fin.prod_univ_eq_prod_range [comm_monoid α] (f : ℕ → α) (n : ℕ) :
  ∏ i : fin n, f i = ∏ i in range n, f i :=
calc (∏ i : fin n, f i) = ∏ i : {x // x ∈ range n}, f i :
  ((equiv.fin_equiv_subtype n).trans
    (equiv.subtype_equiv_right (λ _, mem_range.symm))).prod_comp (f ∘ coe)
... = ∏ i in range n, f i : by rw [← attach_eq_univ, prod_attach]

@[to_additive]
lemma finset.prod_fin_eq_prod_range [comm_monoid β] {n : ℕ} (c : fin n → β) :
  ∏ i, c i = ∏ i in finset.range n, if h : i < n then c ⟨i, h⟩ else 1 :=
begin
  rw [← fin.prod_univ_eq_prod_range, finset.prod_congr rfl],
  rintros ⟨i, hi⟩ _,
  simp only [fin.coe_eq_val, hi, dif_pos]
end

@[to_additive]
lemma finset.prod_to_finset_eq_subtype {M : Type*} [comm_monoid M] [fintype α]
  (p : α → Prop) [decidable_pred p] (f : α → M) :
    ∏ a in {x | p x}.to_finset, f a = ∏ a : subtype p, f a :=
by { rw ← finset.prod_subtype, simp }

@[to_additive] lemma finset.prod_fiberwise [decidable_eq β] [fintype β] [comm_monoid γ]
  (s : finset α) (f : α → β) (g : α → γ) :
  ∏ b : β, ∏ a in s.filter (λ a, f a = b), g a = ∏ a in s, g a :=
finset.prod_fiberwise_of_maps_to (λ x _, mem_univ _) _

@[to_additive]
lemma fintype.prod_fiberwise [fintype α] [decidable_eq β] [fintype β] [comm_monoid γ]
  (f : α → β) (g : α → γ) :
  (∏ b : β, ∏ a : {a // f a = b}, g (a : α)) = ∏ a, g a :=
begin
  rw [← (equiv.sigma_preimage_equiv f).prod_comp, ← univ_sigma_univ, prod_sigma],
  refl
end

lemma fintype.prod_dite [fintype α] {p : α → Prop} [decidable_pred p]
  [comm_monoid β] (f : Π (a : α) (ha : p a), β) (g : Π (a : α) (ha : ¬p a), β) :
  (∏ a, dite (p a) (f a) (g a)) = (∏ a : {a // p a}, f a a.2) * (∏ a : {a // ¬p a}, g a a.2) :=
begin
  simp only [prod_dite, attach_eq_univ],
  congr' 1,
  { convert (equiv.subtype_equiv_right _).prod_comp (λ x : {x // p x}, f x x.2),
    simp },
  { convert (equiv.subtype_equiv_right _).prod_comp (λ x : {x // ¬p x}, g x x.2),
    simp }
end

section
open finset

variables {α₁ : Type*} {α₂ : Type*} {M : Type*} [fintype α₁] [fintype α₂] [comm_monoid M]

@[to_additive]
lemma fintype.prod_sum_elim (f : α₁ → M) (g : α₂ → M) :
  (∏ x, sum.elim f g x) = (∏ a₁, f a₁) * (∏ a₂, g a₂) :=
by { classical, rw [univ_sum_type, prod_sum_elim] }

@[to_additive]
lemma fintype.prod_sum_type (f : α₁ ⊕ α₂ → M) :
  (∏ x, f x) = (∏ a₁, f (sum.inl a₁)) * (∏ a₂, f (sum.inr a₂)) :=
by simp only [← fintype.prod_sum_elim, sum.elim_comp_inl_inr]

end

namespace list

lemma prod_take_of_fn [comm_monoid α] {n : ℕ} (f : fin n → α) (i : ℕ) :
  ((of_fn f).take i).prod = ∏ j in finset.univ.filter (λ (j : fin n), j.val < i), f j :=
begin
  have A : ∀ (j : fin n), ¬ ((j : ℕ) < 0) := λ j, not_lt_bot,
  induction i with i IH, { simp [A] },
  by_cases h : i < n,
  { have : i < length (of_fn f), by rwa [length_of_fn f],
    rw prod_take_succ _ _ this,
    have A : ((finset.univ : finset (fin n)).filter (λ j, j.val < i + 1))
      = ((finset.univ : finset (fin n)).filter (λ j, j.val < i)) ∪ {(⟨i, h⟩ : fin n)},
        by { ext j, simp [nat.lt_succ_iff_lt_or_eq, fin.ext_iff, - add_comm] },
    have B : _root_.disjoint (finset.filter (λ (j : fin n), j.val < i) finset.univ)
      (singleton (⟨i, h⟩ : fin n)), by simp,
    rw [A, finset.prod_union B, IH],
    simp },
  { have A : (of_fn f).take i = (of_fn f).take i.succ,
    { rw ← length_of_fn f at h,
      have : length (of_fn f) ≤ i := not_lt.mp h,
      rw [take_all_of_le this, take_all_of_le (le_trans this (nat.le_succ _))] },
    have B : ∀ (j : fin n), ((j : ℕ) < i.succ) = ((j : ℕ) < i),
    { assume j,
      have : (j : ℕ) < i := lt_of_lt_of_le j.2 (not_lt.mp h),
      simp [this, lt_trans this (nat.lt_succ_self _)] },
    simp [← A, B, IH] }
end

-- `to_additive` does not work on `prod_take_of_fn` because of `0 : ℕ` in the proof.
-- Use `multiplicative` instead.
lemma sum_take_of_fn [add_comm_monoid α] {n : ℕ} (f : fin n → α) (i : ℕ) :
  ((of_fn f).take i).sum = ∑ j in finset.univ.filter (λ (j : fin n), j.val < i), f j :=
@prod_take_of_fn (multiplicative α) _ n f i

attribute [to_additive] prod_take_of_fn

@[to_additive]
lemma prod_of_fn [comm_monoid α] {n : ℕ} {f : fin n → α} :
  (of_fn f).prod = ∏ i, f i :=
begin
  convert prod_take_of_fn f n,
  { rw [take_all_of_le (le_of_eq (length_of_fn f))] },
  { have : ∀ (j : fin n), (j : ℕ) < n := λ j, j.is_lt,
    simp [this] }
end

lemma alternating_sum_eq_finset_sum {G : Type*} [add_comm_group G] :
  ∀ (L : list G), alternating_sum L = ∑ i : fin L.length, (-1 : ℤ) ^ (i : ℕ) • L.nth_le i i.is_lt
| [] := by { rw [alternating_sum, finset.sum_eq_zero], rintro ⟨i, ⟨⟩⟩ }
| (g :: []) :=
begin
  show g = ∑ i : fin 1, (-1 : ℤ) ^ (i : ℕ) • [g].nth_le i i.2,
  rw [fin.sum_univ_succ], simp,
end
| (g :: h :: L) :=
calc g + -h + L.alternating_sum
    = g + -h + ∑ i : fin L.length, (-1 : ℤ) ^ (i : ℕ) • L.nth_le i i.2 :
      congr_arg _ (alternating_sum_eq_finset_sum _)
... = ∑ i : fin (L.length + 2), (-1 : ℤ) ^ (i : ℕ) • list.nth_le (g :: h :: L) i _ :
begin
  rw [fin.sum_univ_succ, fin.sum_univ_succ, add_assoc],
  unfold_coes,
  simp [nat.succ_eq_add_one, pow_add],
  refl,
end

@[to_additive]
lemma alternating_prod_eq_finset_prod {G : Type*} [comm_group G] :
  ∀ (L : list G), alternating_prod L = ∏ i : fin L.length, (L.nth_le i i.2) ^ ((-1 : ℤ) ^ (i : ℕ))
| [] := by { rw [alternating_prod, finset.prod_eq_one], rintro ⟨i, ⟨⟩⟩ }
| (g :: []) :=
begin
  show g = ∏ i : fin 1, [g].nth_le i i.2 ^ (-1 : ℤ) ^ (i : ℕ),
  rw [fin.prod_univ_succ], simp,
end
| (g :: h :: L) :=
calc g * h⁻¹ * L.alternating_prod
    = g * h⁻¹ * ∏ i : fin L.length, L.nth_le i i.2 ^ (-1 : ℤ) ^ (i : ℕ) :
      congr_arg _ (alternating_prod_eq_finset_prod _)
... = ∏ i : fin (L.length + 2), list.nth_le (g :: h :: L) i _ ^ (-1 : ℤ) ^ (i : ℕ) :
begin
  rw [fin.prod_univ_succ, fin.prod_univ_succ, mul_assoc],
  unfold_coes,
  simp [nat.succ_eq_add_one, pow_add],
  refl,
end

end list


/-
Copyright (c) 2022 Damiano Testa. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Damiano Testa

! This file was ported from Lean 3 source module data.finsupp.ne_locus
! leanprover-community/mathlib commit 13a5329a8625701af92e9a96ffc90fa787fff24d
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Data.Finsupp.Defs

/-!
# Locus of unequal values of finitely supported functions

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

Let `α N` be two Types, assume that `N` has a `0` and let `f g : α →₀ N` be finitely supported
functions.

## Main definition

* `finsupp.ne_locus f g : finset α`, the finite subset of `α` where `f` and `g` differ.

In the case in which `N` is an additive group, `finsupp.ne_locus f g` coincides with
`finsupp.support (f - g)`.
-/

variable {α M N P : Type _}

namespace Finsupp

variable [DecidableEq α]

section NHasZero

variable [DecidableEq N] [Zero N] (f g : α →₀ N)

#print Finsupp.neLocus /-
/-- Given two finitely supported functions `f g : α →₀ N`, `finsupp.ne_locus f g` is the `finset`
where `f` and `g` differ. This generalizes `(f - g).support` to situations without subtraction. -/
def neLocus (f g : α →₀ N) : Finset α :=
  (f.support ∪ g.support).filterₓ fun x => f x ≠ g x
#align finsupp.ne_locus Finsupp.neLocus
-/

/- warning: finsupp.mem_ne_locus -> Finsupp.mem_neLocus is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : Zero.{u2} N] {f : Finsupp.{u1, u2} α N _inst_3} {g : Finsupp.{u1, u2} α N _inst_3} {a : α}, Iff (Membership.Mem.{u1, u1} α (Finset.{u1} α) (Finset.hasMem.{u1} α) a (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f g)) (Ne.{succ u2} N (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (Finsupp.{u1, u2} α N _inst_3) (fun (_x : Finsupp.{u1, u2} α N _inst_3) => α -> N) (Finsupp.coeFun.{u1, u2} α N _inst_3) f a) (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (Finsupp.{u1, u2} α N _inst_3) (fun (_x : Finsupp.{u1, u2} α N _inst_3) => α -> N) (Finsupp.coeFun.{u1, u2} α N _inst_3) g a))
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : Zero.{u1} N] {f : Finsupp.{u2, u1} α N _inst_3} {g : Finsupp.{u2, u1} α N _inst_3} {a : α}, Iff (Membership.mem.{u2, u2} α (Finset.{u2} α) (Finset.instMembershipFinset.{u2} α) a (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f g)) (Ne.{succ u1} ((fun (x._@.Mathlib.Data.Finsupp.Defs._hyg.779 : α) => N) a) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Finsupp.{u2, u1} α N _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Data.Finsupp.Defs._hyg.779 : α) => N) _x) (Finsupp.funLike.{u2, u1} α N _inst_3) f a) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Finsupp.{u2, u1} α N _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Data.Finsupp.Defs._hyg.779 : α) => N) _x) (Finsupp.funLike.{u2, u1} α N _inst_3) g a))
Case conversion may be inaccurate. Consider using '#align finsupp.mem_ne_locus Finsupp.mem_neLocusₓ'. -/
@[simp]
theorem mem_neLocus {f g : α →₀ N} {a : α} : a ∈ f.neLocus g ↔ f a ≠ g a := by
  simpa only [ne_locus, Finset.mem_filter, Finset.mem_union, mem_support_iff,
    and_iff_right_iff_imp] using Ne.ne_or_ne _
#align finsupp.mem_ne_locus Finsupp.mem_neLocus

/- warning: finsupp.not_mem_ne_locus -> Finsupp.not_mem_neLocus is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : Zero.{u2} N] {f : Finsupp.{u1, u2} α N _inst_3} {g : Finsupp.{u1, u2} α N _inst_3} {a : α}, Iff (Not (Membership.Mem.{u1, u1} α (Finset.{u1} α) (Finset.hasMem.{u1} α) a (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f g))) (Eq.{succ u2} N (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (Finsupp.{u1, u2} α N _inst_3) (fun (_x : Finsupp.{u1, u2} α N _inst_3) => α -> N) (Finsupp.coeFun.{u1, u2} α N _inst_3) f a) (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (Finsupp.{u1, u2} α N _inst_3) (fun (_x : Finsupp.{u1, u2} α N _inst_3) => α -> N) (Finsupp.coeFun.{u1, u2} α N _inst_3) g a))
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : Zero.{u1} N] {f : Finsupp.{u2, u1} α N _inst_3} {g : Finsupp.{u2, u1} α N _inst_3} {a : α}, Iff (Not (Membership.mem.{u2, u2} α (Finset.{u2} α) (Finset.instMembershipFinset.{u2} α) a (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f g))) (Eq.{succ u1} ((fun (x._@.Mathlib.Data.Finsupp.Defs._hyg.779 : α) => N) a) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Finsupp.{u2, u1} α N _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Data.Finsupp.Defs._hyg.779 : α) => N) _x) (Finsupp.funLike.{u2, u1} α N _inst_3) f a) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Finsupp.{u2, u1} α N _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Data.Finsupp.Defs._hyg.779 : α) => N) _x) (Finsupp.funLike.{u2, u1} α N _inst_3) g a))
Case conversion may be inaccurate. Consider using '#align finsupp.not_mem_ne_locus Finsupp.not_mem_neLocusₓ'. -/
theorem not_mem_neLocus {f g : α →₀ N} {a : α} : a ∉ f.neLocus g ↔ f a = g a :=
  mem_neLocus.Not.trans not_ne_iff
#align finsupp.not_mem_ne_locus Finsupp.not_mem_neLocus

/- warning: finsupp.coe_ne_locus -> Finsupp.coe_neLocus is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : Zero.{u2} N] (f : Finsupp.{u1, u2} α N _inst_3) (g : Finsupp.{u1, u2} α N _inst_3), Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (Finset.{u1} α) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (Finset.{u1} α) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (Finset.{u1} α) (Set.{u1} α) (Finset.Set.hasCoeT.{u1} α))) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f g)) (setOf.{u1} α (fun (x : α) => Ne.{succ u2} N (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (Finsupp.{u1, u2} α N _inst_3) (fun (_x : Finsupp.{u1, u2} α N _inst_3) => α -> N) (Finsupp.coeFun.{u1, u2} α N _inst_3) f x) (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (Finsupp.{u1, u2} α N _inst_3) (fun (_x : Finsupp.{u1, u2} α N _inst_3) => α -> N) (Finsupp.coeFun.{u1, u2} α N _inst_3) g x)))
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : Zero.{u1} N] (f : Finsupp.{u2, u1} α N _inst_3) (g : Finsupp.{u2, u1} α N _inst_3), Eq.{succ u2} (Set.{u2} α) (Finset.toSet.{u2} α (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f g)) (setOf.{u2} α (fun (x : α) => Ne.{succ u1} ((fun (x._@.Mathlib.Data.Finsupp.Defs._hyg.779 : α) => N) x) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Finsupp.{u2, u1} α N _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Data.Finsupp.Defs._hyg.779 : α) => N) _x) (Finsupp.funLike.{u2, u1} α N _inst_3) f x) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Finsupp.{u2, u1} α N _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Data.Finsupp.Defs._hyg.779 : α) => N) _x) (Finsupp.funLike.{u2, u1} α N _inst_3) g x)))
Case conversion may be inaccurate. Consider using '#align finsupp.coe_ne_locus Finsupp.coe_neLocusₓ'. -/
@[simp]
theorem coe_neLocus : ↑(f.neLocus g) = { x | f x ≠ g x } :=
  by
  ext
  exact mem_ne_locus
#align finsupp.coe_ne_locus Finsupp.coe_neLocus

/- warning: finsupp.ne_locus_eq_empty -> Finsupp.neLocus_eq_empty is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : Zero.{u2} N] {f : Finsupp.{u1, u2} α N _inst_3} {g : Finsupp.{u1, u2} α N _inst_3}, Iff (Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f g) (EmptyCollection.emptyCollection.{u1} (Finset.{u1} α) (Finset.hasEmptyc.{u1} α))) (Eq.{max (succ u1) (succ u2)} (Finsupp.{u1, u2} α N _inst_3) f g)
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : Zero.{u1} N] {f : Finsupp.{u2, u1} α N _inst_3} {g : Finsupp.{u2, u1} α N _inst_3}, Iff (Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f g) (EmptyCollection.emptyCollection.{u2} (Finset.{u2} α) (Finset.instEmptyCollectionFinset.{u2} α))) (Eq.{max (succ u2) (succ u1)} (Finsupp.{u2, u1} α N _inst_3) f g)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_eq_empty Finsupp.neLocus_eq_emptyₓ'. -/
@[simp]
theorem neLocus_eq_empty {f g : α →₀ N} : f.neLocus g = ∅ ↔ f = g :=
  ⟨fun h =>
    ext fun a =>
      Classical.not_not.mp (mem_neLocus.Not.mp (Finset.eq_empty_iff_forall_not_mem.mp h a)),
    fun h => h ▸ by simp only [ne_locus, Ne.def, eq_self_iff_true, not_true, Finset.filter_False]⟩
#align finsupp.ne_locus_eq_empty Finsupp.neLocus_eq_empty

/- warning: finsupp.nonempty_ne_locus_iff -> Finsupp.nonempty_neLocus_iff is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : Zero.{u2} N] {f : Finsupp.{u1, u2} α N _inst_3} {g : Finsupp.{u1, u2} α N _inst_3}, Iff (Finset.Nonempty.{u1} α (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f g)) (Ne.{max (succ u1) (succ u2)} (Finsupp.{u1, u2} α N _inst_3) f g)
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : Zero.{u1} N] {f : Finsupp.{u2, u1} α N _inst_3} {g : Finsupp.{u2, u1} α N _inst_3}, Iff (Finset.Nonempty.{u2} α (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f g)) (Ne.{max (succ u2) (succ u1)} (Finsupp.{u2, u1} α N _inst_3) f g)
Case conversion may be inaccurate. Consider using '#align finsupp.nonempty_ne_locus_iff Finsupp.nonempty_neLocus_iffₓ'. -/
@[simp]
theorem nonempty_neLocus_iff {f g : α →₀ N} : (f.neLocus g).Nonempty ↔ f ≠ g :=
  Finset.nonempty_iff_ne_empty.trans neLocus_eq_empty.Not
#align finsupp.nonempty_ne_locus_iff Finsupp.nonempty_neLocus_iff

/- warning: finsupp.ne_locus_comm -> Finsupp.neLocus_comm is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : Zero.{u2} N] (f : Finsupp.{u1, u2} α N _inst_3) (g : Finsupp.{u1, u2} α N _inst_3), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f g) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 g f)
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : Zero.{u1} N] (f : Finsupp.{u2, u1} α N _inst_3) (g : Finsupp.{u2, u1} α N _inst_3), Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f g) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 g f)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_comm Finsupp.neLocus_commₓ'. -/
theorem neLocus_comm : f.neLocus g = g.neLocus f := by
  simp_rw [ne_locus, Finset.union_comm, ne_comm]
#align finsupp.ne_locus_comm Finsupp.neLocus_comm

/- warning: finsupp.ne_locus_zero_right -> Finsupp.neLocus_zero_right is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : Zero.{u2} N] (f : Finsupp.{u1, u2} α N _inst_3), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f (OfNat.ofNat.{max u1 u2} (Finsupp.{u1, u2} α N _inst_3) 0 (OfNat.mk.{max u1 u2} (Finsupp.{u1, u2} α N _inst_3) 0 (Zero.zero.{max u1 u2} (Finsupp.{u1, u2} α N _inst_3) (Finsupp.zero.{u1, u2} α N _inst_3))))) (Finsupp.support.{u1, u2} α N _inst_3 f)
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : Zero.{u1} N] (f : Finsupp.{u2, u1} α N _inst_3), Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 f (OfNat.ofNat.{max u2 u1} (Finsupp.{u2, u1} α N _inst_3) 0 (Zero.toOfNat0.{max u2 u1} (Finsupp.{u2, u1} α N _inst_3) (Finsupp.zero.{u2, u1} α N _inst_3)))) (Finsupp.support.{u2, u1} α N _inst_3 f)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_zero_right Finsupp.neLocus_zero_rightₓ'. -/
@[simp]
theorem neLocus_zero_right : f.neLocus 0 = f.support :=
  by
  ext
  rw [mem_ne_locus, mem_support_iff, coe_zero, Pi.zero_apply]
#align finsupp.ne_locus_zero_right Finsupp.neLocus_zero_right

/- warning: finsupp.ne_locus_zero_left -> Finsupp.neLocus_zero_left is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : Zero.{u2} N] (f : Finsupp.{u1, u2} α N _inst_3), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 (OfNat.ofNat.{max u1 u2} (Finsupp.{u1, u2} α N _inst_3) 0 (OfNat.mk.{max u1 u2} (Finsupp.{u1, u2} α N _inst_3) 0 (Zero.zero.{max u1 u2} (Finsupp.{u1, u2} α N _inst_3) (Finsupp.zero.{u1, u2} α N _inst_3)))) f) (Finsupp.support.{u1, u2} α N _inst_3 f)
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : Zero.{u1} N] (f : Finsupp.{u2, u1} α N _inst_3), Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_3 (OfNat.ofNat.{max u2 u1} (Finsupp.{u2, u1} α N _inst_3) 0 (Zero.toOfNat0.{max u2 u1} (Finsupp.{u2, u1} α N _inst_3) (Finsupp.zero.{u2, u1} α N _inst_3))) f) (Finsupp.support.{u2, u1} α N _inst_3 f)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_zero_left Finsupp.neLocus_zero_leftₓ'. -/
@[simp]
theorem neLocus_zero_left : (0 : α →₀ N).neLocus f = f.support :=
  (neLocus_comm _ _).trans (neLocus_zero_right _)
#align finsupp.ne_locus_zero_left Finsupp.neLocus_zero_left

end NHasZero

section NeLocusAndMaps

#print Finsupp.subset_mapRange_neLocus /-
theorem subset_mapRange_neLocus [DecidableEq N] [Zero N] [DecidableEq M] [Zero M] (f g : α →₀ N)
    {F : N → M} (F0 : F 0 = 0) : (f.mapRange F F0).neLocus (g.mapRange F F0) ⊆ f.neLocus g :=
  fun x => by simpa only [mem_ne_locus, map_range_apply, not_imp_not] using congr_arg F
#align finsupp.subset_map_range_ne_locus Finsupp.subset_mapRange_neLocus
-/

/- warning: finsupp.zip_with_ne_locus_eq_left -> Finsupp.zipWith_neLocus_eq_left is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {M : Type.{u2}} {N : Type.{u3}} {P : Type.{u4}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u3} N] [_inst_3 : Zero.{u2} M] [_inst_4 : DecidableEq.{succ u4} P] [_inst_5 : Zero.{u4} P] [_inst_6 : Zero.{u3} N] {F : M -> N -> P} (F0 : Eq.{succ u4} P (F (OfNat.ofNat.{u2} M 0 (OfNat.mk.{u2} M 0 (Zero.zero.{u2} M _inst_3))) (OfNat.ofNat.{u3} N 0 (OfNat.mk.{u3} N 0 (Zero.zero.{u3} N _inst_6)))) (OfNat.ofNat.{u4} P 0 (OfNat.mk.{u4} P 0 (Zero.zero.{u4} P _inst_5)))) (f : Finsupp.{u1, u2} α M _inst_3) (g₁ : Finsupp.{u1, u3} α N _inst_6) (g₂ : Finsupp.{u1, u3} α N _inst_6), (forall (f : M), Function.Injective.{succ u3, succ u4} N P (fun (g : N) => F f g)) -> (Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u4} α P (fun (a : α) (b : α) => _inst_1 a b) (fun (a : P) (b : P) => _inst_4 a b) _inst_5 (Finsupp.zipWith.{u1, u2, u3, u4} α M N P _inst_3 _inst_6 _inst_5 F F0 f g₁) (Finsupp.zipWith.{u1, u2, u3, u4} α M N P _inst_3 _inst_6 _inst_5 F F0 f g₂)) (Finsupp.neLocus.{u1, u3} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_6 g₁ g₂))
but is expected to have type
  forall {α : Type.{u1}} {M : Type.{u3}} {N : Type.{u4}} {P : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u4} N] [_inst_3 : Zero.{u3} M] [_inst_4 : DecidableEq.{succ u2} P] [_inst_5 : Zero.{u2} P] [_inst_6 : Zero.{u4} N] {F : M -> N -> P} (F0 : Eq.{succ u2} P (F (OfNat.ofNat.{u3} M 0 (Zero.toOfNat0.{u3} M _inst_3)) (OfNat.ofNat.{u4} N 0 (Zero.toOfNat0.{u4} N _inst_6))) (OfNat.ofNat.{u2} P 0 (Zero.toOfNat0.{u2} P _inst_5))) (f : Finsupp.{u1, u3} α M _inst_3) (g₁ : Finsupp.{u1, u4} α N _inst_6) (g₂ : Finsupp.{u1, u4} α N _inst_6), (forall (f : M), Function.Injective.{succ u4, succ u2} N P (fun (g : N) => F f g)) -> (Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α P (fun (a : α) (b : α) => _inst_1 a b) (fun (a : P) (b : P) => _inst_4 a b) _inst_5 (Finsupp.zipWith.{u1, u3, u4, u2} α M N P _inst_3 _inst_6 _inst_5 F F0 f g₁) (Finsupp.zipWith.{u1, u3, u4, u2} α M N P _inst_3 _inst_6 _inst_5 F F0 f g₂)) (Finsupp.neLocus.{u1, u4} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) _inst_6 g₁ g₂))
Case conversion may be inaccurate. Consider using '#align finsupp.zip_with_ne_locus_eq_left Finsupp.zipWith_neLocus_eq_leftₓ'. -/
theorem zipWith_neLocus_eq_left [DecidableEq N] [Zero M] [DecidableEq P] [Zero P] [Zero N]
    {F : M → N → P} (F0 : F 0 0 = 0) (f : α →₀ M) (g₁ g₂ : α →₀ N)
    (hF : ∀ f, Function.Injective fun g => F f g) :
    (zipWith F F0 f g₁).neLocus (zipWith F F0 f g₂) = g₁.neLocus g₂ :=
  by
  ext
  simpa only [mem_ne_locus] using (hF _).ne_iff
#align finsupp.zip_with_ne_locus_eq_left Finsupp.zipWith_neLocus_eq_left

/- warning: finsupp.zip_with_ne_locus_eq_right -> Finsupp.zipWith_neLocus_eq_right is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {M : Type.{u2}} {N : Type.{u3}} {P : Type.{u4}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} M] [_inst_3 : Zero.{u2} M] [_inst_4 : DecidableEq.{succ u4} P] [_inst_5 : Zero.{u4} P] [_inst_6 : Zero.{u3} N] {F : M -> N -> P} (F0 : Eq.{succ u4} P (F (OfNat.ofNat.{u2} M 0 (OfNat.mk.{u2} M 0 (Zero.zero.{u2} M _inst_3))) (OfNat.ofNat.{u3} N 0 (OfNat.mk.{u3} N 0 (Zero.zero.{u3} N _inst_6)))) (OfNat.ofNat.{u4} P 0 (OfNat.mk.{u4} P 0 (Zero.zero.{u4} P _inst_5)))) (f₁ : Finsupp.{u1, u2} α M _inst_3) (f₂ : Finsupp.{u1, u2} α M _inst_3) (g : Finsupp.{u1, u3} α N _inst_6), (forall (g : N), Function.Injective.{succ u2, succ u4} M P (fun (f : M) => F f g)) -> (Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u4} α P (fun (a : α) (b : α) => _inst_1 a b) (fun (a : P) (b : P) => _inst_4 a b) _inst_5 (Finsupp.zipWith.{u1, u2, u3, u4} α M N P _inst_3 _inst_6 _inst_5 F F0 f₁ g) (Finsupp.zipWith.{u1, u2, u3, u4} α M N P _inst_3 _inst_6 _inst_5 F F0 f₂ g)) (Finsupp.neLocus.{u1, u2} α M (fun (a : α) (b : α) => _inst_1 a b) (fun (a : M) (b : M) => _inst_2 a b) _inst_3 f₁ f₂))
but is expected to have type
  forall {α : Type.{u1}} {M : Type.{u4}} {N : Type.{u2}} {P : Type.{u3}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u4} M] [_inst_3 : Zero.{u4} M] [_inst_4 : DecidableEq.{succ u3} P] [_inst_5 : Zero.{u3} P] [_inst_6 : Zero.{u2} N] {F : M -> N -> P} (F0 : Eq.{succ u3} P (F (OfNat.ofNat.{u4} M 0 (Zero.toOfNat0.{u4} M _inst_3)) (OfNat.ofNat.{u2} N 0 (Zero.toOfNat0.{u2} N _inst_6))) (OfNat.ofNat.{u3} P 0 (Zero.toOfNat0.{u3} P _inst_5))) (f₁ : Finsupp.{u1, u4} α M _inst_3) (f₂ : Finsupp.{u1, u4} α M _inst_3) (g : Finsupp.{u1, u2} α N _inst_6), (forall (g : N), Function.Injective.{succ u4, succ u3} M P (fun (f : M) => F f g)) -> (Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u3} α P (fun (a : α) (b : α) => _inst_1 a b) (fun (a : P) (b : P) => _inst_4 a b) _inst_5 (Finsupp.zipWith.{u1, u4, u2, u3} α M N P _inst_3 _inst_6 _inst_5 F F0 f₁ g) (Finsupp.zipWith.{u1, u4, u2, u3} α M N P _inst_3 _inst_6 _inst_5 F F0 f₂ g)) (Finsupp.neLocus.{u1, u4} α M (fun (a : α) (b : α) => _inst_1 a b) (fun (a : M) (b : M) => _inst_2 a b) _inst_3 f₁ f₂))
Case conversion may be inaccurate. Consider using '#align finsupp.zip_with_ne_locus_eq_right Finsupp.zipWith_neLocus_eq_rightₓ'. -/
theorem zipWith_neLocus_eq_right [DecidableEq M] [Zero M] [DecidableEq P] [Zero P] [Zero N]
    {F : M → N → P} (F0 : F 0 0 = 0) (f₁ f₂ : α →₀ M) (g : α →₀ N)
    (hF : ∀ g, Function.Injective fun f => F f g) :
    (zipWith F F0 f₁ g).neLocus (zipWith F F0 f₂ g) = f₁.neLocus f₂ :=
  by
  ext
  simpa only [mem_ne_locus] using (hF _).ne_iff
#align finsupp.zip_with_ne_locus_eq_right Finsupp.zipWith_neLocus_eq_right

#print Finsupp.mapRange_neLocus_eq /-
theorem mapRange_neLocus_eq [DecidableEq N] [DecidableEq M] [Zero M] [Zero N] (f g : α →₀ N)
    {F : N → M} (F0 : F 0 = 0) (hF : Function.Injective F) :
    (f.mapRange F F0).neLocus (g.mapRange F F0) = f.neLocus g :=
  by
  ext
  simpa only [mem_ne_locus] using hF.ne_iff
#align finsupp.map_range_ne_locus_eq Finsupp.mapRange_neLocus_eq
-/

end NeLocusAndMaps

variable [DecidableEq N]

/- warning: finsupp.ne_locus_add_left -> Finsupp.neLocus_add_left is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddLeftCancelMonoid.{u2} N] (f : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (g : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (h : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3))) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (instHAdd.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (Finsupp.add.{u1, u2} α N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) f g) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (instHAdd.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (Finsupp.add.{u1, u2} α N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) f h)) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3))) g h)
but is expected to have type
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddLeftCancelMonoid.{u2} N] (f : Finsupp.{u1, u2} α N (AddLeftCancelMonoid.toZero.{u2} N _inst_3)) (g : Finsupp.{u1, u2} α N (AddLeftCancelMonoid.toZero.{u2} N _inst_3)) (h : Finsupp.{u1, u2} α N (AddLeftCancelMonoid.toZero.{u2} N _inst_3)), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddLeftCancelMonoid.toZero.{u2} N _inst_3) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddLeftCancelMonoid.toZero.{u2} N _inst_3)) (Finsupp.{u1, u2} α N (AddLeftCancelMonoid.toZero.{u2} N _inst_3)) (Finsupp.{u1, u2} α N (AddLeftCancelMonoid.toZero.{u2} N _inst_3)) (instHAdd.{max u1 u2} (Finsupp.{u1, u2} α N (AddLeftCancelMonoid.toZero.{u2} N _inst_3)) (Finsupp.add.{u1, u2} α N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) f g) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddLeftCancelMonoid.toZero.{u2} N _inst_3)) (Finsupp.{u1, u2} α N (AddLeftCancelMonoid.toZero.{u2} N _inst_3)) (Finsupp.{u1, u2} α N (AddLeftCancelMonoid.toZero.{u2} N _inst_3)) (instHAdd.{max u1 u2} (Finsupp.{u1, u2} α N (AddLeftCancelMonoid.toZero.{u2} N _inst_3)) (Finsupp.add.{u1, u2} α N (AddMonoid.toAddZeroClass.{u2} N (AddLeftCancelMonoid.toAddMonoid.{u2} N _inst_3)))) f h)) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddLeftCancelMonoid.toZero.{u2} N _inst_3) g h)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_add_left Finsupp.neLocus_add_leftₓ'. -/
@[simp]
theorem neLocus_add_left [AddLeftCancelMonoid N] (f g h : α →₀ N) :
    (f + g).neLocus (f + h) = g.neLocus h :=
  zipWith_neLocus_eq_left _ _ _ _ add_right_injective
#align finsupp.ne_locus_add_left Finsupp.neLocus_add_left

/- warning: finsupp.ne_locus_add_right -> Finsupp.neLocus_add_right is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddRightCancelMonoid.{u2} N] (f : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (g : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (h : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3))) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (instHAdd.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (Finsupp.add.{u1, u2} α N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) f h) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (instHAdd.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) (Finsupp.add.{u1, u2} α N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) g h)) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3))) f g)
but is expected to have type
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddRightCancelMonoid.{u2} N] (f : Finsupp.{u1, u2} α N (AddRightCancelMonoid.toZero.{u2} N _inst_3)) (g : Finsupp.{u1, u2} α N (AddRightCancelMonoid.toZero.{u2} N _inst_3)) (h : Finsupp.{u1, u2} α N (AddRightCancelMonoid.toZero.{u2} N _inst_3)), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddRightCancelMonoid.toZero.{u2} N _inst_3) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddRightCancelMonoid.toZero.{u2} N _inst_3)) (Finsupp.{u1, u2} α N (AddRightCancelMonoid.toZero.{u2} N _inst_3)) (Finsupp.{u1, u2} α N (AddRightCancelMonoid.toZero.{u2} N _inst_3)) (instHAdd.{max u1 u2} (Finsupp.{u1, u2} α N (AddRightCancelMonoid.toZero.{u2} N _inst_3)) (Finsupp.add.{u1, u2} α N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) f h) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddRightCancelMonoid.toZero.{u2} N _inst_3)) (Finsupp.{u1, u2} α N (AddRightCancelMonoid.toZero.{u2} N _inst_3)) (Finsupp.{u1, u2} α N (AddRightCancelMonoid.toZero.{u2} N _inst_3)) (instHAdd.{max u1 u2} (Finsupp.{u1, u2} α N (AddRightCancelMonoid.toZero.{u2} N _inst_3)) (Finsupp.add.{u1, u2} α N (AddMonoid.toAddZeroClass.{u2} N (AddRightCancelMonoid.toAddMonoid.{u2} N _inst_3)))) g h)) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddRightCancelMonoid.toZero.{u2} N _inst_3) f g)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_add_right Finsupp.neLocus_add_rightₓ'. -/
@[simp]
theorem neLocus_add_right [AddRightCancelMonoid N] (f g h : α →₀ N) :
    (f + h).neLocus (g + h) = f.neLocus g :=
  zipWith_neLocus_eq_right _ _ _ _ add_left_injective
#align finsupp.ne_locus_add_right Finsupp.neLocus_add_right

section AddGroup

variable [AddGroup N] (f f₁ f₂ g g₁ g₂ : α →₀ N)

/- warning: finsupp.ne_locus_neg_neg -> Finsupp.neLocus_neg_neg is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddGroup.{u2} N] (f : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (g : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) (Neg.neg.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.neg.{u1, u2} α N (SubNegZeroMonoid.toNegZeroClass.{u2} N (SubtractionMonoid.toSubNegZeroMonoid.{u2} N (AddGroup.toSubtractionMonoid.{u2} N _inst_3)))) f) (Neg.neg.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.neg.{u1, u2} α N (SubNegZeroMonoid.toNegZeroClass.{u2} N (SubtractionMonoid.toSubNegZeroMonoid.{u2} N (AddGroup.toSubtractionMonoid.{u2} N _inst_3)))) g)) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) f g)
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : AddGroup.{u1} N] (f : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (g : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))), Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) (Neg.neg.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.neg.{u2, u1} α N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f) (Neg.neg.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.neg.{u2, u1} α N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) g)) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f g)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_neg_neg Finsupp.neLocus_neg_negₓ'. -/
@[simp]
theorem neLocus_neg_neg : neLocus (-f) (-g) = f.neLocus g :=
  mapRange_neLocus_eq _ _ neg_zero neg_injective
#align finsupp.ne_locus_neg_neg Finsupp.neLocus_neg_neg

/- warning: finsupp.ne_locus_neg -> Finsupp.neLocus_neg is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddGroup.{u2} N] (f : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (g : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) (Neg.neg.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.neg.{u1, u2} α N (SubNegZeroMonoid.toNegZeroClass.{u2} N (SubtractionMonoid.toSubNegZeroMonoid.{u2} N (AddGroup.toSubtractionMonoid.{u2} N _inst_3)))) f) g) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) f (Neg.neg.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.neg.{u1, u2} α N (SubNegZeroMonoid.toNegZeroClass.{u2} N (SubtractionMonoid.toSubNegZeroMonoid.{u2} N (AddGroup.toSubtractionMonoid.{u2} N _inst_3)))) g))
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : AddGroup.{u1} N] (f : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (g : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))), Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) (Neg.neg.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.neg.{u2, u1} α N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f) g) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f (Neg.neg.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.neg.{u2, u1} α N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) g))
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_neg Finsupp.neLocus_negₓ'. -/
theorem neLocus_neg : neLocus (-f) g = f.neLocus (-g) := by rw [← ne_locus_neg_neg, neg_neg]
#align finsupp.ne_locus_neg Finsupp.neLocus_neg

/- warning: finsupp.ne_locus_eq_support_sub -> Finsupp.neLocus_eq_support_sub is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddGroup.{u2} N] (f : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (g : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) f g) (Finsupp.support.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) (HSub.hSub.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (instHSub.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.sub.{u1, u2} α N (SubtractionMonoid.toSubNegZeroMonoid.{u2} N (AddGroup.toSubtractionMonoid.{u2} N _inst_3)))) f g))
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : AddGroup.{u1} N] (f : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (g : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))), Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f g) (Finsupp.support.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) (HSub.hSub.{max u2 u1, max u2 u1, max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (instHSub.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.sub.{u2, u1} α N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f g))
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_eq_support_sub Finsupp.neLocus_eq_support_subₓ'. -/
theorem neLocus_eq_support_sub : f.neLocus g = (f - g).support := by
  rw [← ne_locus_add_right _ _ (-g), add_right_neg, ne_locus_zero_right, sub_eq_add_neg]
#align finsupp.ne_locus_eq_support_sub Finsupp.neLocus_eq_support_sub

/- warning: finsupp.ne_locus_sub_left -> Finsupp.neLocus_sub_left is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddGroup.{u2} N] (f : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (g₁ : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (g₂ : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) (HSub.hSub.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (instHSub.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.sub.{u1, u2} α N (SubtractionMonoid.toSubNegZeroMonoid.{u2} N (AddGroup.toSubtractionMonoid.{u2} N _inst_3)))) f g₁) (HSub.hSub.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (instHSub.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.sub.{u1, u2} α N (SubtractionMonoid.toSubNegZeroMonoid.{u2} N (AddGroup.toSubtractionMonoid.{u2} N _inst_3)))) f g₂)) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) g₁ g₂)
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : AddGroup.{u1} N] (f : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (g₁ : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (g₂ : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))), Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) (HSub.hSub.{max u2 u1, max u2 u1, max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (instHSub.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.sub.{u2, u1} α N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f g₁) (HSub.hSub.{max u2 u1, max u2 u1, max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (instHSub.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.sub.{u2, u1} α N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f g₂)) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) g₁ g₂)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_sub_left Finsupp.neLocus_sub_leftₓ'. -/
@[simp]
theorem neLocus_sub_left : neLocus (f - g₁) (f - g₂) = neLocus g₁ g₂ := by
  simp only [sub_eq_add_neg, ne_locus_add_left, ne_locus_neg_neg]
#align finsupp.ne_locus_sub_left Finsupp.neLocus_sub_left

/- warning: finsupp.ne_locus_sub_right -> Finsupp.neLocus_sub_right is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddGroup.{u2} N] (f₁ : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (f₂ : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (g : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) (HSub.hSub.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (instHSub.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.sub.{u1, u2} α N (SubtractionMonoid.toSubNegZeroMonoid.{u2} N (AddGroup.toSubtractionMonoid.{u2} N _inst_3)))) f₁ g) (HSub.hSub.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (instHSub.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.sub.{u1, u2} α N (SubtractionMonoid.toSubNegZeroMonoid.{u2} N (AddGroup.toSubtractionMonoid.{u2} N _inst_3)))) f₂ g)) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) f₁ f₂)
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : AddGroup.{u1} N] (f₁ : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (f₂ : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (g : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))), Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) (HSub.hSub.{max u2 u1, max u2 u1, max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (instHSub.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.sub.{u2, u1} α N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f₁ g) (HSub.hSub.{max u2 u1, max u2 u1, max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (instHSub.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.sub.{u2, u1} α N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f₂ g)) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f₁ f₂)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_sub_right Finsupp.neLocus_sub_rightₓ'. -/
@[simp]
theorem neLocus_sub_right : neLocus (f₁ - g) (f₂ - g) = neLocus f₁ f₂ := by
  simpa only [sub_eq_add_neg] using ne_locus_add_right _ _ _
#align finsupp.ne_locus_sub_right Finsupp.neLocus_sub_right

/- warning: finsupp.ne_locus_self_add_right -> Finsupp.neLocus_self_add_right is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddGroup.{u2} N] (f : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (g : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) f (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (instHAdd.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.add.{u1, u2} α N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) f g)) (Finsupp.support.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) g)
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : AddGroup.{u1} N] (f : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (g : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))), Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f (HAdd.hAdd.{max u2 u1, max u2 u1, max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (instHAdd.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.add.{u2, u1} α N (AddMonoid.toAddZeroClass.{u1} N (SubNegMonoid.toAddMonoid.{u1} N (AddGroup.toSubNegMonoid.{u1} N _inst_3))))) f g)) (Finsupp.support.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) g)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_self_add_right Finsupp.neLocus_self_add_rightₓ'. -/
@[simp]
theorem neLocus_self_add_right : neLocus f (f + g) = g.support := by
  rw [← ne_locus_zero_left, ← ne_locus_add_left f 0 g, add_zero]
#align finsupp.ne_locus_self_add_right Finsupp.neLocus_self_add_right

/- warning: finsupp.ne_locus_self_add_left -> Finsupp.neLocus_self_add_left is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddGroup.{u2} N] (f : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (g : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (instHAdd.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.add.{u1, u2} α N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) f g) f) (Finsupp.support.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) g)
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : AddGroup.{u1} N] (f : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (g : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))), Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) (HAdd.hAdd.{max u2 u1, max u2 u1, max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (instHAdd.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.add.{u2, u1} α N (AddMonoid.toAddZeroClass.{u1} N (SubNegMonoid.toAddMonoid.{u1} N (AddGroup.toSubNegMonoid.{u1} N _inst_3))))) f g) f) (Finsupp.support.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) g)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_self_add_left Finsupp.neLocus_self_add_leftₓ'. -/
@[simp]
theorem neLocus_self_add_left : neLocus (f + g) f = g.support := by
  rw [ne_locus_comm, ne_locus_self_add_right]
#align finsupp.ne_locus_self_add_left Finsupp.neLocus_self_add_left

/- warning: finsupp.ne_locus_self_sub_right -> Finsupp.neLocus_self_sub_right is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddGroup.{u2} N] (f : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (g : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) f (HSub.hSub.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (instHSub.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.sub.{u1, u2} α N (SubtractionMonoid.toSubNegZeroMonoid.{u2} N (AddGroup.toSubtractionMonoid.{u2} N _inst_3)))) f g)) (Finsupp.support.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) g)
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : AddGroup.{u1} N] (f : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (g : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))), Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f (HSub.hSub.{max u2 u1, max u2 u1, max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (instHSub.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.sub.{u2, u1} α N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f g)) (Finsupp.support.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) g)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_self_sub_right Finsupp.neLocus_self_sub_rightₓ'. -/
@[simp]
theorem neLocus_self_sub_right : neLocus f (f - g) = g.support := by
  rw [sub_eq_add_neg, ne_locus_self_add_right, support_neg]
#align finsupp.ne_locus_self_sub_right Finsupp.neLocus_self_sub_right

/- warning: finsupp.ne_locus_self_sub_left -> Finsupp.neLocus_self_sub_left is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {N : Type.{u2}} [_inst_1 : DecidableEq.{succ u1} α] [_inst_2 : DecidableEq.{succ u2} N] [_inst_3 : AddGroup.{u2} N] (f : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (g : Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))), Eq.{succ u1} (Finset.{u1} α) (Finsupp.neLocus.{u1, u2} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) (HSub.hSub.{max u1 u2, max u1 u2, max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (instHSub.{max u1 u2} (Finsupp.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3))))) (Finsupp.sub.{u1, u2} α N (SubtractionMonoid.toSubNegZeroMonoid.{u2} N (AddGroup.toSubtractionMonoid.{u2} N _inst_3)))) f g) f) (Finsupp.support.{u1, u2} α N (AddZeroClass.toHasZero.{u2} N (AddMonoid.toAddZeroClass.{u2} N (SubNegMonoid.toAddMonoid.{u2} N (AddGroup.toSubNegMonoid.{u2} N _inst_3)))) g)
but is expected to have type
  forall {α : Type.{u2}} {N : Type.{u1}} [_inst_1 : DecidableEq.{succ u2} α] [_inst_2 : DecidableEq.{succ u1} N] [_inst_3 : AddGroup.{u1} N] (f : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (g : Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))), Eq.{succ u2} (Finset.{u2} α) (Finsupp.neLocus.{u2, u1} α N (fun (a : α) (b : α) => _inst_1 a b) (fun (a : N) (b : N) => _inst_2 a b) (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) (HSub.hSub.{max u2 u1, max u2 u1, max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (instHSub.{max u2 u1} (Finsupp.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3))))) (Finsupp.sub.{u2, u1} α N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) f g) f) (Finsupp.support.{u2, u1} α N (NegZeroClass.toZero.{u1} N (SubNegZeroMonoid.toNegZeroClass.{u1} N (SubtractionMonoid.toSubNegZeroMonoid.{u1} N (AddGroup.toSubtractionMonoid.{u1} N _inst_3)))) g)
Case conversion may be inaccurate. Consider using '#align finsupp.ne_locus_self_sub_left Finsupp.neLocus_self_sub_leftₓ'. -/
@[simp]
theorem neLocus_self_sub_left : neLocus (f - g) f = g.support := by
  rw [ne_locus_comm, ne_locus_self_sub_right]
#align finsupp.ne_locus_self_sub_left Finsupp.neLocus_self_sub_left

end AddGroup

end Finsupp


import BrownCs22.Library.Tactics

/-

Wrapping up Lecture 4: here's how we can work with *implications* and *negations*.

if we know `hpq : p → q`, and our goal is to prove `q`,
then `apply hpq` will change the goal to `p`.

-/

example : p → (p → q) → q := by
  intro hp
  intro hpq
  apply hpq
  assumption

/-

Alternatively, if we know `hpq : p → q` and `hp : p`,
we can "reason forward" by writing `have hq : q := hpq hp`.
This adds a new hypothesis `hq : q` without changing the goal.
This syntax is a little clunky, but we'll use it in a more general setting later.

-/

example : p → (p → q) → q ∧ p := by
  intro hp
  intro hpq
  have hq : q := hpq hp
  split_goal
  { assumption }
  { assumption }

/-
If you *know* a negation: use it to find a contradiction.

-/

variable (p q r : Prop)

example : (¬ p ∧ (p ∨ q)) → q := by
  intro hand
  eliminate hand with hnp hpq
  eliminate hpq with hp hq
  { contradiction }
  { assumption }

/-
If you want to *prove* a negation: assume the statement is true,
and find a contradiction.
-/

example : ¬ (p ∧ ¬ p) := by
  intro hpnp
  eliminate hpnp with hp hnp
  contradiction