l3lab/ntp-mathlib huggingface dataset:
lemma zeckendorf_sum_fib : ∀ {l}, IsZeckendorfRep l → zeckendorf (l.map fib).sum = l
  | [], _ => rfl
  | a :: l, hl => by
    have hl' := hl
    simp only [IsZeckendorfRep, cons_append, chain'_iff_pairwise, pairwise_cons, mem_append,
      mem_singleton, or_imp, forall_and, forall_eq, zero_add] at hl
    rw [← chain'_iff_pairwise] at hl
    have ha : 0 < a := hl.1.2.trans_lt' zero_lt_two
    suffices h : greatestFib (fib a + sum (map fib l)) = a
    · simp only [map, List.sum_cons, add_pos_iff, fib_pos.2 ha, true_or, zeckendorf_of_pos, h,
      add_tsub_cancel_left, zeckendorf_sum_fib hl.2]
    simp only [add_comm, add_assoc, greatestFib, findGreatest_eq_iff, ne_eq, ha.ne',
      not_false_eq_true, le_add_iff_nonneg_left, _root_.zero_le, forall_true_left, not_le, true_and]
    refine ⟨le_add_of_le_right $ le_fib_add_one _, fun n hn _ ↦ ?_⟩
    

Proof state:
case h
l✝ : List ℕ
a✝ m n✝ a : ℕ
l : List ℕ
hl' : IsZeckendorfRep (a :: l)
hl : ((∀ x ∈ l, x + 2 ≤ a) ∧ 2 ≤ a) ∧ Chain' (fun a b => b + 2 ≤ a) (l ++ [0])
ha : 0 < a
n : ℕ
hn : a < n
x✝ : n ≤ sum (map fib l) + (fib a + 1)
⊢ sum (map fib l) + fib a < fib n

Next tactic:
rw [add_comm, ← List.sum_cons, ← map_cons]
lemma zeckendorf_sum_fib : ∀ {l}, IsZeckendorfRep l → zeckendorf (l.map fib).sum = l
  | [], _ => rfl
  | a :: l, hl => by
    have hl' := hl
    simp only [IsZeckendorfRep, cons_append, chain'_iff_pairwise, pairwise_cons, mem_append,
      mem_singleton, or_imp, forall_and, forall_eq, zero_add] at hl
    rw [← chain'_iff_pairwise] at hl
    have ha : 0 < a := hl.1.2.trans_lt' zero_lt_two
    suffices h : greatestFib (fib a + sum (map fib l)) = a
    · simp only [map, List.sum_cons, add_pos_iff, fib_pos.2 ha, true_or, zeckendorf_of_pos, h,
      add_tsub_cancel_left, zeckendorf_sum_fib hl.2]
    simp only [add_comm, add_assoc, greatestFib, findGreatest_eq_iff, ne_eq, ha.ne',
      not_false_eq_true, le_add_iff_nonneg_left, _root_.zero_le, forall_true_left, not_le, true_and]
    refine ⟨le_add_of_le_right $ le_fib_add_one _, fun n hn _ ↦ ?_⟩
    rw [add_comm, ← List.sum_cons, ← map_cons]
    

Proof state:
case h
l✝ : List ℕ
a✝ m n✝ a : ℕ
l : List ℕ
hl' : IsZeckendorfRep (a :: l)
hl : ((∀ x ∈ l, x + 2 ≤ a) ∧ 2 ≤ a) ∧ Chain' (fun a b => b + 2 ≤ a) (l ++ [0])
ha : 0 < a
n : ℕ
hn : a < n
x✝ : n ≤ sum (map fib l) + (fib a + 1)
⊢ sum (map fib (a :: l)) < fib n

Next tactic:
exact hl'.sum_fib_lt (by simpa)
lemma zeckendorf_sum_fib : ∀ {l}, IsZeckendorfRep l → zeckendorf (l.map fib).sum = l
  | [], _ => rfl
  | a :: l, hl => by
    have hl' := hl
    simp only [IsZeckendorfRep, cons_append, chain'_iff_pairwise, pairwise_cons, mem_append,
      mem_singleton, or_imp, forall_and, forall_eq, zero_add] at hl
    rw [← chain'_iff_pairwise] at hl
    have ha : 0 < a := hl.1.2.trans_lt' zero_lt_two
    suffices h : greatestFib (fib a + sum (map fib l)) = a
    · simp only [map, List.sum_cons, add_pos_iff, fib_pos.2 ha, true_or, zeckendorf_of_pos, h,
      add_tsub_cancel_left, zeckendorf_sum_fib hl.2]
    simp only [add_comm, add_assoc, greatestFib, findGreatest_eq_iff, ne_eq, ha.ne',
      not_false_eq_true, le_add_iff_nonneg_left, _root_.zero_le, forall_true_left, not_le, true_and]
    refine ⟨le_add_of_le_right $ le_fib_add_one _, fun n hn _ ↦ ?_⟩
    rw [add_comm, ← List.sum_cons, ← map_cons]
    exact hl'.sum_fib_lt (by 

Proof state:
l✝ : List ℕ
a✝ m n✝ a : ℕ
l : List ℕ
hl' : IsZeckendorfRep (a :: l)
hl : ((∀ x ∈ l, x + 2 ≤ a) ∧ 2 ≤ a) ∧ Chain' (fun a b => b + 2 ≤ a) (l ++ [0])
ha : 0 < a
n : ℕ
hn : a < n
x✝ : n ≤ sum (map fib l) + (fib a + 1)
⊢ ∀ a_1 ∈ head? (a :: l ++ [0]), a_1 < n

Next tactic:
simpa
@[simp] lemma sum_zeckendorf_fib : ∀ n : ℕ, (n.zeckendorf.map fib).sum = n
  | 0 => rfl
  | n + 1 => by
    

Proof state:
l : List ℕ
a m n✝ n : ℕ
⊢ sum (map fib (zeckendorf (n + 1))) = n + 1

Next tactic:
have := zeckendorf_aux n.succ_pos
@[simp] lemma sum_zeckendorf_fib : ∀ n : ℕ, (n.zeckendorf.map fib).sum = n
  | 0 => rfl
  | n + 1 => by
    have := zeckendorf_aux n.succ_pos
    

Proof state:
l : List ℕ
a m n✝ n : ℕ
this : succ n - fib (greatestFib (succ n)) < succ n
⊢ sum (map fib (zeckendorf (n + 1))) = n + 1

Next tactic:
rw [zeckendorf_succ, map, List.sum_cons, sum_zeckendorf_fib (n + 1 - _), add_tsub_cancel_iff_le]
@[simp] lemma sum_zeckendorf_fib : ∀ n : ℕ, (n.zeckendorf.map fib).sum = n
  | 0 => rfl
  | n + 1 => by
    have := zeckendorf_aux n.succ_pos
    rw [zeckendorf_succ, map, List.sum_cons, sum_zeckendorf_fib (n + 1 - _), add_tsub_cancel_iff_le]
    

Proof state:
l : List ℕ
a m n✝ n : ℕ
this : succ n - fib (greatestFib (succ n)) < succ n
⊢ fib (greatestFib (n + 1)) ≤ n + 1

Next tactic:
exact fib_greatestFib_le _
/-- Given a nonempty Finset `s` and a function `f` from `s` to `ℕ`, if `d = s.gcd`,
then the `gcd` of `(f i) / d` is equal to `1`. -/
theorem gcd_div_eq_one {β : Type*} {f : β → ℕ} (s : Finset β) {x : β} (hx : x ∈ s)
    (hfz : f x ≠ 0) : (s.gcd fun b => f b / s.gcd f) = 1 := by
  

Proof state:
β : Type u_1
f : β → ℕ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
⊢ (gcd s fun b => f b / gcd s f) = 1

Next tactic:
obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
/-- Given a nonempty Finset `s` and a function `f` from `s` to `ℕ`, if `d = s.gcd`,
then the `gcd` of `(f i) / d` is equal to `1`. -/
theorem gcd_div_eq_one {β : Type*} {f : β → ℕ} (s : Finset β) {x : β} (hx : x ∈ s)
    (hfz : f x ≠ 0) : (s.gcd fun b => f b / s.gcd f) = 1 := by
  obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
  

Proof state:
case intro.intro
β : Type u_1
f : β → ℕ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → ℕ
he : ∀ b ∈ s, f b = gcd s f * g b
hg : gcd s g = 1
⊢ (gcd s fun b => f b / gcd s f) = 1

Next tactic:
refine' (Finset.gcd_congr rfl fun a ha => _).trans hg
/-- Given a nonempty Finset `s` and a function `f` from `s` to `ℕ`, if `d = s.gcd`,
then the `gcd` of `(f i) / d` is equal to `1`. -/
theorem gcd_div_eq_one {β : Type*} {f : β → ℕ} (s : Finset β) {x : β} (hx : x ∈ s)
    (hfz : f x ≠ 0) : (s.gcd fun b => f b / s.gcd f) = 1 := by
  obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
  refine' (Finset.gcd_congr rfl fun a ha => _).trans hg
  

Proof state:
case intro.intro
β : Type u_1
f : β → ℕ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → ℕ
he : ∀ b ∈ s, f b = gcd s f * g b
hg : gcd s g = 1
a : β
ha : a ∈ s
⊢ f a / gcd s f = g a

Next tactic:
rw [he a ha, Nat.mul_div_cancel_left]
/-- Given a nonempty Finset `s` and a function `f` from `s` to `ℕ`, if `d = s.gcd`,
then the `gcd` of `(f i) / d` is equal to `1`. -/
theorem gcd_div_eq_one {β : Type*} {f : β → ℕ} (s : Finset β) {x : β} (hx : x ∈ s)
    (hfz : f x ≠ 0) : (s.gcd fun b => f b / s.gcd f) = 1 := by
  obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
  refine' (Finset.gcd_congr rfl fun a ha => _).trans hg
  rw [he a ha, Nat.mul_div_cancel_left]
  

Proof state:
case intro.intro.H
β : Type u_1
f : β → ℕ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → ℕ
he : ∀ b ∈ s, f b = gcd s f * g b
hg : gcd s g = 1
a : β
ha : a ∈ s
⊢ 0 < gcd s f

Next tactic:
exact Nat.pos_of_ne_zero (mt Finset.gcd_eq_zero_iff.1 fun h => hfz <| h x hx)
/-- Given a nonempty Finset `s` and a function `f` from `s` to `ℤ`, if `d = s.gcd`,
then the `gcd` of `(f i) / d` is equal to `1`. -/
theorem gcd_div_eq_one {β : Type*} {f : β → ℤ} (s : Finset β) {x : β} (hx : x ∈ s)
    (hfz : f x ≠ 0) : (s.gcd fun b => f b / s.gcd f) = 1 := by
  

Proof state:
β : Type u_1
f : β → ℤ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
⊢ (gcd s fun b => f b / gcd s f) = 1

Next tactic:
obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
/-- Given a nonempty Finset `s` and a function `f` from `s` to `ℤ`, if `d = s.gcd`,
then the `gcd` of `(f i) / d` is equal to `1`. -/
theorem gcd_div_eq_one {β : Type*} {f : β → ℤ} (s : Finset β) {x : β} (hx : x ∈ s)
    (hfz : f x ≠ 0) : (s.gcd fun b => f b / s.gcd f) = 1 := by
  obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
  

Proof state:
case intro.intro
β : Type u_1
f : β → ℤ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → ℤ
he : ∀ b ∈ s, f b = gcd s f * g b
hg : gcd s g = 1
⊢ (gcd s fun b => f b / gcd s f) = 1

Next tactic:
refine' (Finset.gcd_congr rfl fun a ha => _).trans hg
/-- Given a nonempty Finset `s` and a function `f` from `s` to `ℤ`, if `d = s.gcd`,
then the `gcd` of `(f i) / d` is equal to `1`. -/
theorem gcd_div_eq_one {β : Type*} {f : β → ℤ} (s : Finset β) {x : β} (hx : x ∈ s)
    (hfz : f x ≠ 0) : (s.gcd fun b => f b / s.gcd f) = 1 := by
  obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
  refine' (Finset.gcd_congr rfl fun a ha => _).trans hg
  

Proof state:
case intro.intro
β : Type u_1
f : β → ℤ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → ℤ
he : ∀ b ∈ s, f b = gcd s f * g b
hg : gcd s g = 1
a : β
ha : a ∈ s
⊢ f a / gcd s f = g a

Next tactic:
rw [he a ha, Int.mul_ediv_cancel_left]
/-- Given a nonempty Finset `s` and a function `f` from `s` to `ℤ`, if `d = s.gcd`,
then the `gcd` of `(f i) / d` is equal to `1`. -/
theorem gcd_div_eq_one {β : Type*} {f : β → ℤ} (s : Finset β) {x : β} (hx : x ∈ s)
    (hfz : f x ≠ 0) : (s.gcd fun b => f b / s.gcd f) = 1 := by
  obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
  refine' (Finset.gcd_congr rfl fun a ha => _).trans hg
  rw [he a ha, Int.mul_ediv_cancel_left]
  

Proof state:
case intro.intro.H
β : Type u_1
f : β → ℤ
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → ℤ
he : ∀ b ∈ s, f b = gcd s f * g b
hg : gcd s g = 1
a : β
ha : a ∈ s
⊢ gcd s f ≠ 0

Next tactic:
exact mt Finset.gcd_eq_zero_iff.1 fun h => hfz <| h x hx
/-- Given a nonempty Finset `s` and a function `f` from `s` to `K[X]`, if `d = s.gcd f`,
then the `gcd` of `(f i) / d` is equal to `1`. -/
theorem gcd_div_eq_one {β : Type*} {f : β → Polynomial K} (s : Finset β) {x : β} (hx : x ∈ s)
    (hfz : f x ≠ 0) : (s.gcd fun b => f b / s.gcd f) = 1 := by
  

Proof state:
K : Type u_1
inst✝ : Field K
β : Type u_2
f : β → Polynomial K
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
⊢ (gcd s fun b => f b / gcd s f) = 1

Next tactic:
obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
/-- Given a nonempty Finset `s` and a function `f` from `s` to `K[X]`, if `d = s.gcd f`,
then the `gcd` of `(f i) / d` is equal to `1`. -/
theorem gcd_div_eq_one {β : Type*} {f : β → Polynomial K} (s : Finset β) {x : β} (hx : x ∈ s)
    (hfz : f x ≠ 0) : (s.gcd fun b => f b / s.gcd f) = 1 := by
  obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
  

Proof state:
case intro.intro
K : Type u_1
inst✝ : Field K
β : Type u_2
f : β → Polynomial K
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → Polynomial K
he : ∀ b ∈ s, f b = gcd s f * g b
hg : gcd s g = 1
⊢ (gcd s fun b => f b / gcd s f) = 1

Next tactic:
refine' (Finset.gcd_congr rfl fun a ha => _).trans hg
/-- Given a nonempty Finset `s` and a function `f` from `s` to `K[X]`, if `d = s.gcd f`,
then the `gcd` of `(f i) / d` is equal to `1`. -/
theorem gcd_div_eq_one {β : Type*} {f : β → Polynomial K} (s : Finset β) {x : β} (hx : x ∈ s)
    (hfz : f x ≠ 0) : (s.gcd fun b => f b / s.gcd f) = 1 := by
  obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
  refine' (Finset.gcd_congr rfl fun a ha => _).trans hg
  

Proof state:
case intro.intro
K : Type u_1
inst✝ : Field K
β : Type u_2
f : β → Polynomial K
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → Polynomial K
he : ∀ b ∈ s, f b = gcd s f * g b
hg : gcd s g = 1
a : β
ha : a ∈ s
⊢ f a / gcd s f = g a

Next tactic:
rw [he a ha, EuclideanDomain.mul_div_cancel_left]
/-- Given a nonempty Finset `s` and a function `f` from `s` to `K[X]`, if `d = s.gcd f`,
then the `gcd` of `(f i) / d` is equal to `1`. -/
theorem gcd_div_eq_one {β : Type*} {f : β → Polynomial K} (s : Finset β) {x : β} (hx : x ∈ s)
    (hfz : f x ≠ 0) : (s.gcd fun b => f b / s.gcd f) = 1 := by
  obtain ⟨g, he, hg⟩ := Finset.extract_gcd f ⟨x, hx⟩
  refine' (Finset.gcd_congr rfl fun a ha => _).trans hg
  rw [he a ha, EuclideanDomain.mul_div_cancel_left]
  

Proof state:
case intro.intro.a0
K : Type u_1
inst✝ : Field K
β : Type u_2
f : β → Polynomial K
s : Finset β
x : β
hx : x ∈ s
hfz : f x ≠ 0
g : β → Polynomial K
he : ∀ b ∈ s, f b = gcd s f * g b
hg : gcd s g = 1
a : β
ha : a ∈ s
⊢ gcd s f ≠ 0

Next tactic:
exact mt Finset.gcd_eq_zero_iff.1 fun h => hfz <| h x hx
theorem eq_one_iff_odd {n : ℕ} : (n : ZMod 2) = 1 ↔ Odd n := by
  

Proof state:
n : ℕ
⊢ ↑n = 1 ↔ Odd n

Next tactic:
rw [← @Nat.cast_one (ZMod 2), ZMod.eq_iff_modEq_nat, Nat.odd_iff, Nat.ModEq]
theorem eq_one_iff_odd {n : ℕ} : (n : ZMod 2) = 1 ↔ Odd n := by
  rw [← @Nat.cast_one (ZMod 2), ZMod.eq_iff_modEq_nat, Nat.odd_iff, Nat.ModEq]
  

Proof state:
n : ℕ
⊢ n % 2 = 1 % 2 ↔ n % 2 = 1

Next tactic:
norm_num
theorem ne_zero_iff_odd {n : ℕ} : (n : ZMod 2) ≠ 0 ↔ Odd n := by
  

Proof state:
n : ℕ
⊢ ↑n ≠ 0 ↔ Odd n

Next tactic:
constructor
theorem ne_zero_iff_odd {n : ℕ} : (n : ZMod 2) ≠ 0 ↔ Odd n := by
  constructor <;>
    · 

Proof state:
case mp
n : ℕ
⊢ ↑n ≠ 0 → Odd n

Next tactic:
contrapose
theorem ne_zero_iff_odd {n : ℕ} : (n : ZMod 2) ≠ 0 ↔ Odd n := by
  constructor <;>
    · contrapose
      

Proof state:
case mp
n : ℕ
⊢ ¬Odd n → ¬↑n ≠ 0

Next tactic:
simp [eq_zero_iff_even]
theorem ne_zero_iff_odd {n : ℕ} : (n : ZMod 2) ≠ 0 ↔ Odd n := by
  constructor <;>
    · 

Proof state:
case mpr
n : ℕ
⊢ Odd n → ↑n ≠ 0

Next tactic:
contrapose
theorem ne_zero_iff_odd {n : ℕ} : (n : ZMod 2) ≠ 0 ↔ Odd n := by
  constructor <;>
    · contrapose
      

Proof state:
case mpr
n : ℕ
⊢ ¬↑n ≠ 0 → ¬Odd n

Next tactic:
simp [eq_zero_iff_even]
/-- Produce an association list for the finsupp over its support using choice. -/
@[simps]
noncomputable def toAList (f : α →₀ M) : AList fun _x : α => M :=
  ⟨f.graph.toList.map Prod.toSigma,
    by
      

Proof state:
α : Type u_1
M : Type u_2
inst✝ : Zero M
f : α →₀ M
⊢ List.NodupKeys (List.map Prod.toSigma (Finset.toList (graph f)))

Next tactic:
rw [List.NodupKeys, List.keys, List.map_map, Prod.fst_comp_toSigma, List.nodup_map_iff_inj_on]
/-- Produce an association list for the finsupp over its support using choice. -/
@[simps]
noncomputable def toAList (f : α →₀ M) : AList fun _x : α => M :=
  ⟨f.graph.toList.map Prod.toSigma,
    by
      rw [List.NodupKeys, List.keys, List.map_map, Prod.fst_comp_toSigma, List.nodup_map_iff_inj_on]
      · 

Proof state:
α : Type u_1
M : Type u_2
inst✝ : Zero M
f : α →₀ M
⊢ ∀ x ∈ Finset.toList (graph f), ∀ y ∈ Finset.toList (graph f), x.1 = y.1 → x = y

Next tactic:
rintro ⟨b, m⟩ hb ⟨c, n⟩ hc (rfl : b = c)
/-- Produce an association list for the finsupp over its support using choice. -/
@[simps]
noncomputable def toAList (f : α →₀ M) : AList fun _x : α => M :=
  ⟨f.graph.toList.map Prod.toSigma,
    by
      rw [List.NodupKeys, List.keys, List.map_map, Prod.fst_comp_toSigma, List.nodup_map_iff_inj_on]
      · rintro ⟨b, m⟩ hb ⟨c, n⟩ hc (rfl : b = c)
        

Proof state:
case mk.mk
α : Type u_1
M : Type u_2
inst✝ : Zero M
f : α →₀ M
b : α
m : M
hb : (b, m) ∈ Finset.toList (graph f)
n : M
hc : (b, n) ∈ Finset.toList (graph f)
⊢ (b, m) = (b, n)

Next tactic:
rw [Finset.mem_toList, Finsupp.mem_graph_iff] at hb hc
/-- Produce an association list for the finsupp over its support using choice. -/
@[simps]
noncomputable def toAList (f : α →₀ M) : AList fun _x : α => M :=
  ⟨f.graph.toList.map Prod.toSigma,
    by
      rw [List.NodupKeys, List.keys, List.map_map, Prod.fst_comp_toSigma, List.nodup_map_iff_inj_on]
      · rintro ⟨b, m⟩ hb ⟨c, n⟩ hc (rfl : b = c)
        rw [Finset.mem_toList, Finsupp.mem_graph_iff] at hb hc
        

Proof state:
case mk.mk
α : Type u_1
M : Type u_2
inst✝ : Zero M
f : α →₀ M
b : α
m : M
hb : f (b, m).1 = (b, m).2 ∧ (b, m).2 ≠ 0
n : M
hc : f (b, n).1 = (b, n).2 ∧ (b, n).2 ≠ 0
⊢ (b, m) = (b, n)

Next tactic:
dsimp at hb hc
/-- Produce an association list for the finsupp over its support using choice. -/
@[simps]
noncomputable def toAList (f : α →₀ M) : AList fun _x : α => M :=
  ⟨f.graph.toList.map Prod.toSigma,
    by
      rw [List.NodupKeys, List.keys, List.map_map, Prod.fst_comp_toSigma, List.nodup_map_iff_inj_on]
      · rintro ⟨b, m⟩ hb ⟨c, n⟩ hc (rfl : b = c)
        rw [Finset.mem_toList, Finsupp.mem_graph_iff] at hb hc
        dsimp at hb hc
        

Proof state:
case mk.mk
α : Type u_1
M : Type u_2
inst✝ : Zero M
f : α →₀ M
b : α
m : M
hb : f b = m ∧ ¬m = 0
n : M
hc : f b = n ∧ ¬n = 0
⊢ (b, m) = (b, n)

Next tactic:
rw [← hc.1, hb.1]
/-- Produce an association list for the finsupp over its support using choice. -/
@[simps]
noncomputable def toAList (f : α →₀ M) : AList fun _x : α => M :=
  ⟨f.graph.toList.map Prod.toSigma,
    by
      rw [List.NodupKeys, List.keys, List.map_map, Prod.fst_comp_toSigma, List.nodup_map_iff_inj_on]
      · rintro ⟨b, m⟩ hb ⟨c, n⟩ hc (rfl : b = c)
        rw [Finset.mem_toList, Finsupp.mem_graph_iff] at hb hc
        dsimp at hb hc
        rw [← hc.1, hb.1]
      · 

Proof state:
α : Type u_1
M : Type u_2
inst✝ : Zero M
f : α →₀ M
⊢ List.Nodup (Finset.toList (graph f))

Next tactic:
apply Finset.nodup_toList
@[simp]
theorem toAList_keys_toFinset [DecidableEq α] (f : α →₀ M) :
    f.toAList.keys.toFinset = f.support := by
  

Proof state:
α : Type u_1
M : Type u_2
inst✝¹ : Zero M
inst✝ : DecidableEq α
f : α →₀ M
⊢ List.toFinset (AList.keys (toAList f)) = f.support

Next tactic:
ext
@[simp]
theorem toAList_keys_toFinset [DecidableEq α] (f : α →₀ M) :
    f.toAList.keys.toFinset = f.support := by
  ext
  

Proof state:
case a
α : Type u_1
M : Type u_2
inst✝¹ : Zero M
inst✝ : DecidableEq α
f : α →₀ M
a✝ : α
⊢ a✝ ∈ List.toFinset (AList.keys (toAList f)) ↔ a✝ ∈ f.support

Next tactic:
simp [toAList, AList.mem_keys, AList.keys, List.keys]
@[simp]
theorem mem_toAlist {f : α →₀ M} {x : α} : x ∈ f.toAList ↔ f x ≠ 0 := by
  

Proof state:
α : Type u_1
M : Type u_2
inst✝ : Zero M
f : α →₀ M
x : α
⊢ x ∈ toAList f ↔ f x ≠ 0

Next tactic:
classical rw [AList.mem_keys, ← List.mem_toFinset, toAList_keys_toFinset, mem_support_iff]
@[simp]
theorem mem_toAlist {f : α →₀ M} {x : α} : x ∈ f.toAList ↔ f x ≠ 0 := by
  classical 

Proof state:
α : Type u_1
M : Type u_2
inst✝ : Zero M
f : α →₀ M
x : α
⊢ x ∈ toAList f ↔ f x ≠ 0

Next tactic:
rw [AList.mem_keys, ← List.mem_toFinset, toAList_keys_toFinset, mem_support_iff]
/-- Converts an association list into a finitely supported function via `AList.lookup`, sending
absent keys to zero. -/
noncomputable def lookupFinsupp (l : AList fun _x : α => M) : α →₀ M
    where
  support := by
    

Proof state:
α : Type u_1
M : Type u_2
inst✝ : Zero M
l : AList fun _x => M
⊢ Finset α

Next tactic:
haveI := Classical.decEq α
/-- Converts an association list into a finitely supported function via `AList.lookup`, sending
absent keys to zero. -/
noncomputable def lookupFinsupp (l : AList fun _x : α => M) : α →₀ M
    where
  support := by
    haveI := Classical.decEq α; 

Proof state:
α : Type u_1
M : Type u_2
inst✝ : Zero M
l : AList fun _x => M
this : DecidableEq α
⊢ Finset α

Next tactic:
haveI := Classical.decEq M
/-- Converts an association list into a finitely supported function via `AList.lookup`, sending
absent keys to zero. -/
noncomputable def lookupFinsupp (l : AList fun _x : α => M) : α →₀ M
    where
  support := by
    haveI := Classical.decEq α; haveI := Classical.decEq M
    

Proof state:
α : Type u_1
M : Type u_2
inst✝ : Zero M
l : AList fun _x => M
this✝ : DecidableEq α
this : DecidableEq M
⊢ Finset α

Next tactic:
exact (l.1.filter fun x => Sigma.snd x ≠ 0).keys.toFinset
/-- Converts an association list into a finitely supported function via `AList.lookup`, sending
absent keys to zero. -/
noncomputable def lookupFinsupp (l : AList fun _x : α => M) : α →₀ M
    where
  support := by
    haveI := Classical.decEq α; haveI := Classical.decEq M
    exact (l.1.filter fun x => Sigma.snd x ≠ 0).keys.toFinset
  toFun a :=
    haveI := Classical.decEq α
    (l.lookup a).getD 0
  mem_support_toFun a := by
    

Proof state:
α : Type u_1
M : Type u_2
inst✝ : Zero M
l : AList fun _x => M
a : α
⊢ a ∈ toFinset (List.keys (filter (fun x => decide (x.snd ≠ 0)) l.entries)) ↔
    (fun a => Option.getD (lookup a l) 0) a ≠ 0

Next tactic:
classical
      simp_rw [@mem_toFinset _ _, List.mem_keys, List.mem_filter, ← mem_lookup_iff]
      cases lookup a l <;> simp
/-- Converts an association list into a finitely supported function via `AList.lookup`, sending
absent keys to zero. -/
noncomputable def lookupFinsupp (l : AList fun _x : α => M) : α →₀ M
    where
  support := by
    haveI := Classical.decEq α; haveI := Classical.decEq M
    exact (l.1.filter fun x => Sigma.snd x ≠ 0).keys.toFinset
  toFun a :=
    haveI := Classical.decEq α
    (l.lookup a).getD 0
  mem_support_toFun a := by
    classical
      

Proof state:
α : Type u_1
M : Type u_2
inst✝ : Zero M
l : AList fun _x => M
a : α
⊢ a ∈ toFinset (List.keys (filter (fun x => decide (x.snd ≠ 0)) l.entries)) ↔
    (fun a => Option.getD (lookup a l) 0) a ≠ 0

Next tactic:
simp_rw [@mem_toFinset _ _, List.mem_keys, List.mem_filter, ← mem_lookup_iff]
/-- Converts an association list into a finitely supported function via `AList.lookup`, sending
absent keys to zero. -/
noncomputable def lookupFinsupp (l : AList fun _x : α => M) : α →₀ M
    where
  support := by
    haveI := Classical.decEq α; haveI := Classical.decEq M
    exact (l.1.filter fun x => Sigma.snd x ≠ 0).keys.toFinset
  toFun a :=
    haveI := Classical.decEq α
    (l.lookup a).getD 0
  mem_support_toFun a := by
    classical
      simp_rw [@mem_toFinset _ _, List.mem_keys, List.mem_filter, ← mem_lookup_iff]
      

Proof state:
α : Type u_1
M : Type u_2
inst✝ : Zero M
l : AList fun _x => M
a : α
⊢ (∃ b ∈ lookup a l, decide (b ≠ 0) = true) ↔ Option.getD (lookup a l) 0 ≠ 0

Next tactic:
cases lookup a l
/-- Converts an association list into a finitely supported function via `AList.lookup`, sending
absent keys to zero. -/
noncomputable def lookupFinsupp (l : AList fun _x : α => M) : α →₀ M
    where
  support := by
    haveI := Classical.decEq α; haveI := Classical.decEq M
    exact (l.1.filter fun x => Sigma.snd x ≠ 0).keys.toFinset
  toFun a :=
    haveI := Classical.decEq α
    (l.lookup a).getD 0
  mem_support_toFun a := by
    classical
      simp_rw [@mem_toFinset _ _, List.mem_keys, List.mem_filter, ← mem_lookup_iff]
      cases lookup a l <;> 

Proof state:
case none
α : Type u_1
M : Type u_2
inst✝ : Zero M
l : AList fun _x => M
a : α
⊢ (∃ b ∈ none, decide (b ≠ 0) = true) ↔ Option.getD none 0 ≠ 0

Next tactic:
simp
/-- Converts an association list into a finitely supported function via `AList.lookup`, sending
absent keys to zero. -/
noncomputable def lookupFinsupp (l : AList fun _x : α => M) : α →₀ M
    where
  support := by
    haveI := Classical.decEq α; haveI := Classical.decEq M
    exact (l.1.filter fun x => Sigma.snd x ≠ 0).keys.toFinset
  toFun a :=
    haveI := Classical.decEq α
    (l.lookup a).getD 0
  mem_support_toFun a := by
    classical
      simp_rw [@mem_toFinset _ _, List.mem_keys, List.mem_filter, ← mem_lookup_iff]
      cases lookup a l <;> 

Proof state:
case some
α : Type u_1
M : Type u_2
inst✝ : Zero M
l : AList fun _x => M
a : α
val✝ : M
⊢ (∃ b ∈ some val✝, decide (b ≠ 0) = true) ↔ Option.getD (some val✝) 0 ≠ 0

Next tactic:
simp
@[simp]
theorem lookupFinsupp_apply [DecidableEq α] (l : AList fun _x : α => M) (a : α) :
    l.lookupFinsupp a = (l.lookup a).getD 0 := by
    

Proof state:
α : Type u_1
M : Type u_2
inst✝¹ : Zero M
inst✝ : DecidableEq α
l : AList fun _x => M
a : α
⊢ (lookupFinsupp l) a = Option.getD (lookup a l) 0

Next tactic:
convert rfl
@[simp]
theorem lookupFinsupp_apply [DecidableEq α] (l : AList fun _x : α => M) (a : α) :
    l.lookupFinsupp a = (l.lookup a).getD 0 := by
    convert rfl; 

Proof state:
case h.e'_3
α : Type u_1
M : Type u_2
inst✝¹ : Zero M
inst✝ : DecidableEq α
l : AList fun _x => M
a : α
⊢ Option.getD (lookup a l) 0 = (lookupFinsupp l) a

Next tactic:
congr
@[simp]
theorem lookupFinsupp_support [DecidableEq α] [DecidableEq M] (l : AList fun _x : α => M) :
    l.lookupFinsupp.support = (l.1.filter fun x => Sigma.snd x ≠ 0).keys.toFinset := by
  

Proof state:
α : Type u_1
M : Type u_2
inst✝² : Zero M
inst✝¹ : DecidableEq α
inst✝ : DecidableEq M
l : AList fun _x => M
⊢ (lookupFinsupp l).support = toFinset (List.keys (filter (fun x => decide (x.snd ≠ 0)) l.entries))

Next tactic:
convert rfl