Skip to content

Commit 76df73b

Browse files
feat port : Data.Finset.NatAntidiagonal (#1598)
Co-authored-by: ChrisHughes24 <chrishughes24@gmail.com>
1 parent f25f56f commit 76df73b

File tree

2 files changed

+152
-0
lines changed

2 files changed

+152
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ import Mathlib.Data.Finset.Fold
234234
import Mathlib.Data.Finset.Image
235235
import Mathlib.Data.Finset.Lattice
236236
import Mathlib.Data.Finset.NAry
237+
import Mathlib.Data.Finset.NatAntidiagonal
237238
import Mathlib.Data.Finset.Option
238239
import Mathlib.Data.Finset.Order
239240
import Mathlib.Data.Finset.Pi
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/-
2+
Copyright (c) 2019 Johan Commelin. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Johan Commelin
5+
6+
! This file was ported from Lean 3 source module data.finset.nat_antidiagonal
7+
! leanprover-community/mathlib commit 9003f28797c0664a49e4179487267c494477d853
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.Data.Finset.Card
12+
import Mathlib.Data.Multiset.NatAntidiagonal
13+
14+
/-!
15+
# Antidiagonals in ℕ × ℕ as finsets
16+
17+
This file defines the antidiagonals of ℕ × ℕ as finsets: the `n`-th antidiagonal is the finset of
18+
pairs `(i, j)` such that `i + j = n`. This is useful for polynomial multiplication and more
19+
generally for sums going from `0` to `n`.
20+
21+
## Notes
22+
23+
This refines files `Data.List.NatAntidiagonal` and `Data.Multiset.NatAntidiagonal`.
24+
-/
25+
26+
27+
namespace Finset
28+
29+
namespace Nat
30+
31+
/-- The antidiagonal of a natural number `n` is
32+
the finset of pairs `(i, j)` such that `i + j = n`. -/
33+
def antidiagonal (n : ℕ) : Finset (ℕ × ℕ) :=
34+
⟨Multiset.Nat.antidiagonal n, Multiset.Nat.nodup_antidiagonal n⟩
35+
#align finset.nat.antidiagonal Finset.Nat.antidiagonal
36+
37+
/-- A pair (i, j) is contained in the antidiagonal of `n` if and only if `i + j = n`. -/
38+
@[simp]
39+
theorem mem_antidiagonal {n : ℕ} {x : ℕ × ℕ} : x ∈ antidiagonal n ↔ x.1 + x.2 = n := by
40+
rw [antidiagonal, mem_def, Multiset.Nat.mem_antidiagonal]
41+
#align finset.nat.mem_antidiagonal Finset.Nat.mem_antidiagonal
42+
43+
/-- The cardinality of the antidiagonal of `n` is `n + 1`. -/
44+
@[simp]
45+
theorem card_antidiagonal (n : ℕ) : (antidiagonal n).card = n + 1 := by simp [antidiagonal]
46+
#align finset.nat.card_antidiagonal Finset.Nat.card_antidiagonal
47+
48+
/-- The antidiagonal of `0` is the list `[(0, 0)]` -/
49+
@[simp]
50+
theorem antidiagonal_zero : antidiagonal 0 = {(0, 0)} := rfl
51+
#align finset.nat.antidiagonal_zero Finset.Nat.antidiagonal_zero
52+
53+
theorem antidiagonal_succ (n : ℕ) :
54+
antidiagonal (n + 1) =
55+
cons (0, n + 1)
56+
((antidiagonal n).map
57+
(Function.Embedding.prodMap ⟨Nat.succ, Nat.succ_injective⟩ (Function.Embedding.refl _)))
58+
(by simp) := by
59+
apply eq_of_veq
60+
rw [cons_val, map_val]
61+
· apply Multiset.Nat.antidiagonal_succ
62+
#align finset.nat.antidiagonal_succ Finset.Nat.antidiagonal_succ
63+
64+
theorem antidiagonal_succ' (n : ℕ) :
65+
antidiagonal (n + 1) =
66+
cons (n + 1, 0)
67+
((antidiagonal n).map
68+
(Function.Embedding.prodMap (Function.Embedding.refl _) ⟨Nat.succ, Nat.succ_injective⟩))
69+
(by simp) := by
70+
apply eq_of_veq
71+
rw [cons_val, map_val]
72+
exact Multiset.Nat.antidiagonal_succ'
73+
#align finset.nat.antidiagonal_succ' Finset.Nat.antidiagonal_succ'
74+
75+
theorem antidiagonal_succ_succ' {n : ℕ} :
76+
antidiagonal (n + 2) =
77+
cons (0, n + 2)
78+
(cons (n + 2, 0)
79+
((antidiagonal n).map
80+
(Function.Embedding.prodMap ⟨Nat.succ, Nat.succ_injective⟩
81+
⟨Nat.succ, Nat.succ_injective⟩)) <|
82+
by simp)
83+
(by simp) := by
84+
simp_rw [antidiagonal_succ (n + 1), antidiagonal_succ', Finset.map_cons, map_map]
85+
rfl
86+
#align finset.nat.antidiagonal_succ_succ' Finset.Nat.antidiagonal_succ_succ'
87+
88+
theorem map_swap_antidiagonal {n : ℕ} :
89+
(antidiagonal n).map ⟨Prod.swap, Prod.swap_injective⟩ = antidiagonal n :=
90+
eq_of_veq <| by simp [antidiagonal, Multiset.Nat.map_swap_antidiagonal]
91+
#align finset.nat.map_swap_antidiagonal Finset.Nat.map_swap_antidiagonal
92+
93+
/-- A point in the antidiagonal is determined by its first co-ordinate. -/
94+
theorem antidiagonal_congr {n : ℕ} {p q : ℕ × ℕ} (hp : p ∈ antidiagonal n)
95+
(hq : q ∈ antidiagonal n) : p = q ↔ p.fst = q.fst := by
96+
refine' ⟨congr_arg Prod.fst, fun h ↦ Prod.ext h ((add_right_inj q.fst).mp _)⟩
97+
rw [mem_antidiagonal] at hp hq
98+
rw [hq, ← h, hp]
99+
#align finset.nat.antidiagonal_congr Finset.Nat.antidiagonal_congr
100+
101+
theorem antidiagonal.fst_le {n : ℕ} {kl : ℕ × ℕ} (hlk : kl ∈ antidiagonal n) : kl.1 ≤ n := by
102+
rw [le_iff_exists_add]
103+
use kl.2
104+
rwa [mem_antidiagonal, eq_comm] at hlk
105+
#align finset.nat.antidiagonal.fst_le Finset.Nat.antidiagonal.fst_le
106+
107+
theorem antidiagonal.snd_le {n : ℕ} {kl : ℕ × ℕ} (hlk : kl ∈ antidiagonal n) : kl.2 ≤ n := by
108+
rw [le_iff_exists_add]
109+
use kl.1
110+
rwa [mem_antidiagonal, eq_comm, add_comm] at hlk
111+
#align finset.nat.antidiagonal.snd_le Finset.Nat.antidiagonal.snd_le
112+
113+
theorem filter_fst_eq_antidiagonal (n m : ℕ) :
114+
filter (fun x : ℕ × ℕ ↦ x.fst = m) (antidiagonal n) = if m ≤ n then {(m, n - m)} else ∅ := by
115+
ext ⟨x, y⟩
116+
simp only [mem_filter, Nat.mem_antidiagonal]
117+
split_ifs with h
118+
· simp (config := { contextual := true }) [and_comm, eq_tsub_iff_add_eq_of_le h, add_comm]
119+
· rw [not_le] at h
120+
simp only [not_mem_empty, iff_false_iff, not_and, decide_eq_true_eq]
121+
exact fun hn => ne_of_lt (lt_of_le_of_lt (le_self_add.trans hn.le) h)
122+
#align finset.nat.filter_fst_eq_antidiagonal Finset.Nat.filter_fst_eq_antidiagonal
123+
124+
theorem filter_snd_eq_antidiagonal (n m : ℕ) :
125+
filter (fun x : ℕ × ℕ ↦ x.snd = m) (antidiagonal n) = if m ≤ n then {(n - m, m)} else ∅ := by
126+
have : (fun x : ℕ × ℕ ↦ (x.snd = m : Bool)) ∘ Prod.swap = fun x : ℕ × ℕ ↦ x.fst = m := by
127+
ext ; simp
128+
rw [← map_swap_antidiagonal]
129+
simp [filter_map, this, filter_fst_eq_antidiagonal, apply_ite (Finset.map _)]
130+
#align finset.nat.filter_snd_eq_antidiagonal Finset.Nat.filter_snd_eq_antidiagonal
131+
132+
section EquivProd
133+
134+
/-- The disjoint union of antidiagonals `Σ (n : ℕ), antidiagonal n` is equivalent to the product
135+
`ℕ × ℕ`. This is such an equivalence, obtained by mapping `(n, (k, l))` to `(k, l)`. -/
136+
@[simps]
137+
def sigmaAntidiagonalEquivProd : (Σn : ℕ, antidiagonal n) ≃ ℕ × ℕ where
138+
toFun x := x.2
139+
invFun x := ⟨x.1 + x.2, x, mem_antidiagonal.mpr rfl⟩
140+
left_inv := by
141+
rintro ⟨n, ⟨k, l⟩, h⟩
142+
rw [mem_antidiagonal] at h
143+
exact Sigma.subtype_ext h rfl
144+
right_inv x := rfl
145+
#align finset.nat.sigma_antidiagonal_equiv_prod Finset.Nat.sigmaAntidiagonalEquivProd
146+
147+
end EquivProd
148+
149+
end Nat
150+
151+
end Finset

0 commit comments

Comments
 (0)