|
| 1 | +/- |
| 2 | +Copyright (c) 2020 Bhavik Mehta. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Bhavik Mehta, Alena Gusakov |
| 5 | +-/ |
| 6 | +import data.finset |
| 7 | +import data.fintype.basic |
| 8 | +import algebra.geom_sum |
| 9 | +import tactic |
| 10 | + |
| 11 | +/-! |
| 12 | +# Colex |
| 13 | +
|
| 14 | +We define the colex ordering for finite sets, and give a couple of important |
| 15 | +lemmas and properties relating to it. |
| 16 | +
|
| 17 | +The colex ordering likes to avoid large values - it can be thought of on |
| 18 | +`finset ℕ` as the "binary" ordering. That is, order A based on |
| 19 | +`∑_{i ∈ A} 2^i`. |
| 20 | +It's defined here in a slightly more general way, requiring only `has_lt α` in |
| 21 | +the definition of colex on `finset α`. In the context of the Kruskal-Katona |
| 22 | +theorem, we are interested in particular on how colex behaves for sets of a |
| 23 | +fixed size. If the size is 3, colex on ℕ starts |
| 24 | +123, 124, 134, 234, 125, 135, 235, 145, 245, 345, ... |
| 25 | +
|
| 26 | +## Main statements |
| 27 | +* `colex_hom`: strictly monotone functions preserve colex |
| 28 | +* Colex order properties - linearity, decidability and so on. |
| 29 | +* `forall_lt_of_colex_lt_of_forall_lt`: if A < B in colex, and everything |
| 30 | + in B is < t, then everything in A is < t. This confirms the idea that |
| 31 | + an enumeration under colex will exhaust all sets using elements < t before |
| 32 | + allowing t to be included. |
| 33 | +* `binary_iff`: colex for α = ℕ is the same as binary |
| 34 | + (this also proves binary expansions are unique) |
| 35 | +
|
| 36 | +## Notation |
| 37 | +We define `<` and `≤` to denote colex ordering, useful in particular when |
| 38 | +multiple orderings are available in context. |
| 39 | +
|
| 40 | +## Tags |
| 41 | +colex, colexicographic, binary |
| 42 | +
|
| 43 | +## References |
| 44 | +* https://github.com/b-mehta/maths-notes/blob/master/iii/mich/combinatorics.pdf |
| 45 | +
|
| 46 | +## Todo |
| 47 | +Show the subset ordering is a sub-relation of the colex ordering. |
| 48 | +-/ |
| 49 | + |
| 50 | +variable {α : Type*} |
| 51 | + |
| 52 | +open finset |
| 53 | + |
| 54 | +/-- |
| 55 | +We define this type synonym to refer to the colexicographic ordering on finsets |
| 56 | +rather than the natural subset ordering. |
| 57 | +-/ |
| 58 | +@[derive inhabited] |
| 59 | +def finset.colex (α) := finset α |
| 60 | + |
| 61 | +/-- |
| 62 | +A convenience constructor to turn a `finset α` into a `finset.colex α`, useful in order to |
| 63 | +use the colex ordering rather than the subset ordering. |
| 64 | +-/ |
| 65 | +def finset.to_colex {α} (s : finset α) : finset.colex α := s |
| 66 | + |
| 67 | +@[simp] |
| 68 | +lemma colex.eq_iff (A B : finset α) : |
| 69 | + A.to_colex = B.to_colex ↔ A = B := by refl |
| 70 | + |
| 71 | +/-- |
| 72 | +`A` is less than `B` in the colex ordering if the largest thing that's not in both sets is in B. |
| 73 | +In other words, max (A ▵ B) ∈ B (if the maximum exists). |
| 74 | +-/ |
| 75 | +instance [has_lt α] : has_lt (finset.colex α) := |
| 76 | +⟨λ (A B : finset α), ∃ (k : α), (∀ {x}, k < x → (x ∈ A ↔ x ∈ B)) ∧ k ∉ A ∧ k ∈ B⟩ |
| 77 | + |
| 78 | +/-- We can define (≤) in the obvious way. -/ |
| 79 | +instance [has_lt α] : has_le (finset.colex α) := |
| 80 | +⟨λ A B, A < B ∨ A = B⟩ |
| 81 | + |
| 82 | +lemma colex.lt_def [has_lt α] (A B : finset α) : |
| 83 | + A.to_colex < B.to_colex ↔ ∃ k, (∀ {x}, k < x → (x ∈ A ↔ x ∈ B)) ∧ k ∉ A ∧ k ∈ B := |
| 84 | +iff.rfl |
| 85 | +lemma colex.le_def [has_lt α] (A B : finset α) : |
| 86 | + A.to_colex ≤ B.to_colex ↔ A.to_colex < B.to_colex ∨ A = B := |
| 87 | +iff.rfl |
| 88 | + |
| 89 | +/-- If everything in A is less than k, we can bound the sum of powers. -/ |
| 90 | +lemma nat.sum_pow_two_lt {k : ℕ} {A : finset ℕ} (h₁ : ∀ {x}, x ∈ A → x < k) : |
| 91 | + A.sum (pow 2) < 2^k := |
| 92 | +begin |
| 93 | + apply lt_of_le_of_lt (sum_le_sum_of_subset (λ t, mem_range.2 ∘ h₁)), |
| 94 | + have z := geom_sum_mul_add 1 k, |
| 95 | + rw [geom_series, mul_one, one_add_one_eq_two] at z, |
| 96 | + rw ← z, |
| 97 | + apply nat.lt_succ_self, |
| 98 | +end |
| 99 | + |
| 100 | +namespace colex |
| 101 | + |
| 102 | +/-- Strictly monotone functions preserve the colex ordering. -/ |
| 103 | +lemma hom {β : Type*} [linear_order α] [decidable_eq β] [preorder β] |
| 104 | + {f : α → β} (h₁ : strict_mono f) (A B : finset α) : |
| 105 | + (A.image f).to_colex < (B.image f).to_colex ↔ A.to_colex < B.to_colex := |
| 106 | +begin |
| 107 | + simp only [colex.lt_def, not_exists, mem_image, exists_prop, not_and], |
| 108 | + split, |
| 109 | + { rintro ⟨k, z, q, k', _, rfl⟩, |
| 110 | + exact ⟨k', λ x hx, by simpa [h₁.injective] using z (h₁ hx), λ t, q _ t rfl, ‹k' ∈ B›⟩ }, |
| 111 | + rintro ⟨k, z, ka, _⟩, |
| 112 | + refine ⟨f k, λ x hx, _, _, k, ‹k ∈ B›, rfl⟩, |
| 113 | + { split, |
| 114 | + any_goals { |
| 115 | + rintro ⟨x', hx', rfl⟩, |
| 116 | + refine ⟨x', _, rfl⟩, |
| 117 | + rwa ← z _ <|> rwa z _, |
| 118 | + rwa strict_mono.lt_iff_lt h₁ at hx } }, |
| 119 | + { simp only [h₁.injective, function.injective.eq_iff], |
| 120 | + exact λ x hx, ne_of_mem_of_not_mem hx ka } |
| 121 | +end |
| 122 | + |
| 123 | +/-- A special case of `colex_hom` which is sometimes useful. -/ |
| 124 | +@[simp] lemma hom_fin {n : ℕ} (A B : finset (fin n)) : |
| 125 | + finset.to_colex (A.image (λ n, (n : ℕ))) < finset.to_colex (B.image (λ n, (n : ℕ))) |
| 126 | + ↔ finset.to_colex A < finset.to_colex B := |
| 127 | +colex.hom (λ x y k, k) _ _ |
| 128 | + |
| 129 | +instance [has_lt α] : is_irrefl (finset.colex α) (<) := |
| 130 | +⟨λ A h, exists.elim h (λ _ ⟨_,a,b⟩, a b)⟩ |
| 131 | + |
| 132 | +@[trans] |
| 133 | +lemma lt_trans [linear_order α] {a b c : finset.colex α} : |
| 134 | + a < b → b < c → a < c := |
| 135 | +begin |
| 136 | + rintros ⟨k₁, k₁z, notinA, inB⟩ ⟨k₂, k₂z, notinB, inC⟩, |
| 137 | + cases lt_or_gt_of_ne (ne_of_mem_of_not_mem inB notinB), |
| 138 | + { refine ⟨k₂, _, by rwa k₁z h, inC⟩, |
| 139 | + intros x hx, |
| 140 | + rw ← k₂z hx, |
| 141 | + apply k₁z (trans h hx) }, |
| 142 | + { refine ⟨k₁, _, notinA, by rwa ← k₂z h⟩, |
| 143 | + intros x hx, |
| 144 | + rw k₁z hx, |
| 145 | + apply k₂z (trans h hx) } |
| 146 | +end |
| 147 | + |
| 148 | +@[trans] |
| 149 | +lemma le_trans [linear_order α] (a b c : finset.colex α) : |
| 150 | + a ≤ b → b ≤ c → a ≤ c := |
| 151 | +λ AB BC, AB.elim (λ k, BC.elim (λ t, or.inl (lt_trans k t)) (λ t, t ▸ AB)) (λ k, k.symm ▸ BC) |
| 152 | + |
| 153 | +instance [linear_order α] : is_trans (finset.colex α) (<) := ⟨λ _ _ _, colex.lt_trans⟩ |
| 154 | + |
| 155 | +instance [linear_order α] : is_asymm (finset.colex α) (<) := by apply_instance |
| 156 | + |
| 157 | +instance [linear_order α] : is_strict_order (finset.colex α) (<) := {} |
| 158 | + |
| 159 | +lemma lt_trichotomy [linear_order α] (A B : finset.colex α) : |
| 160 | + A < B ∨ A = B ∨ B < A := |
| 161 | +begin |
| 162 | + by_cases h₁ : (A = B), |
| 163 | + { tauto }, |
| 164 | + rcases (exists_max_image (A \ B ∪ B \ A) id _) with ⟨k, hk, z⟩, |
| 165 | + { simp only [mem_union, mem_sdiff] at hk, |
| 166 | + cases hk, |
| 167 | + { right, |
| 168 | + right, |
| 169 | + refine ⟨k, λ t th, _, hk.2, hk.1⟩, |
| 170 | + specialize z t, |
| 171 | + by_contra h₂, |
| 172 | + simp only [mem_union, mem_sdiff, id.def] at z, |
| 173 | + rw [not_iff, iff_iff_and_or_not_and_not, not_not, and_comm] at h₂, |
| 174 | + apply not_le_of_lt th (z h₂) }, |
| 175 | + { left, |
| 176 | + refine ⟨k, λ t th, _, hk.2, hk.1⟩, |
| 177 | + specialize z t, |
| 178 | + by_contra h₃, |
| 179 | + simp only [mem_union, mem_sdiff, id.def] at z, |
| 180 | + rw [not_iff, iff_iff_and_or_not_and_not, not_not, and_comm, or_comm] at h₃, |
| 181 | + apply not_le_of_lt th (z h₃) }, }, |
| 182 | + rw nonempty_iff_ne_empty, |
| 183 | + intro a, |
| 184 | + simp only [union_eq_empty_iff, sdiff_eq_empty_iff_subset] at a, |
| 185 | + apply h₁ (subset.antisymm a.1 a.2) |
| 186 | +end |
| 187 | + |
| 188 | +instance [linear_order α] : is_trichotomous (finset.colex α) (<) := ⟨lt_trichotomy⟩ |
| 189 | + |
| 190 | +-- It should be possible to do this computably but it doesn't seem to make any difference for now. |
| 191 | +noncomputable instance [linear_order α] : linear_order (finset.colex α) := |
| 192 | +{ le_refl := λ A, or.inr rfl, |
| 193 | + le_trans := le_trans, |
| 194 | + le_antisymm := λ A B AB BA, AB.elim (λ k, BA.elim (λ t, (asymm k t).elim) (λ t, t.symm)) id, |
| 195 | + le_total := λ A B, |
| 196 | + (lt_trichotomy A B).elim3 (or.inl ∘ or.inl) (or.inl ∘ or.inr) (or.inr ∘ or.inl), |
| 197 | + decidable_le := classical.dec_rel _, |
| 198 | + ..finset.colex.has_le } |
| 199 | + |
| 200 | +instance [linear_order α] : is_incomp_trans (finset.colex α) (<) := |
| 201 | +begin |
| 202 | + constructor, |
| 203 | + rintros A B C ⟨nAB, nBA⟩ ⟨nBC, nCB⟩, |
| 204 | + have : A = B := ((lt_trichotomy A B).resolve_left nAB).resolve_right nBA, |
| 205 | + have : B = C := ((lt_trichotomy B C).resolve_left nBC).resolve_right nCB, |
| 206 | + rw [‹A = B›, ‹B = C›, and_self], |
| 207 | + apply irrefl |
| 208 | +end |
| 209 | + |
| 210 | +instance [linear_order α] : is_strict_weak_order (finset.colex α) (<) := {} |
| 211 | + |
| 212 | +instance [linear_order α] : is_strict_total_order (finset.colex α) (<) := {} |
| 213 | + |
| 214 | +/-- If {r} is less than or equal to s in the colexicographical sense, |
| 215 | + then s contains an element greater than or equal to r. -/ |
| 216 | +lemma mem_le_of_singleton_le [linear_order α] {r : α} {s : finset α}: |
| 217 | + ({r} : finset α).to_colex ≤ s.to_colex → ∃ x ∈ s, r ≤ x := |
| 218 | +begin |
| 219 | + intro h, |
| 220 | + rw colex.le_def at h, |
| 221 | + cases h with lt eq, |
| 222 | + { rw colex.lt_def at lt, |
| 223 | + rcases lt with ⟨k, hk, hi, hj⟩, |
| 224 | + by_cases hr : r ∈ s, |
| 225 | + { use r, |
| 226 | + tauto }, |
| 227 | + { contrapose! hk, |
| 228 | + simp only [mem_singleton], |
| 229 | + specialize hk k, |
| 230 | + use r, |
| 231 | + split, |
| 232 | + { apply hk, |
| 233 | + cc }, |
| 234 | + { simp, |
| 235 | + exact hr } } }, |
| 236 | + { rw ← eq, |
| 237 | + use r, |
| 238 | + simp only [true_and, eq_self_iff_true, mem_singleton] }, |
| 239 | +end |
| 240 | + |
| 241 | +/-- s.to_colex < finset.to_colex {r} iff all elements of s are less than r. -/ |
| 242 | +lemma lt_singleton_iff_mem_lt [linear_order α] {r : α} {s : finset α}: |
| 243 | + s.to_colex < finset.to_colex {r} ↔ ∀ x ∈ s, x < r := |
| 244 | +begin |
| 245 | + simp only [lt_def, mem_singleton, ← and_assoc, exists_eq_right], |
| 246 | + split, |
| 247 | + { rintro ⟨q, rs⟩ x hx, |
| 248 | + by_contra h, |
| 249 | + rw not_lt at h, |
| 250 | + cases lt_or_eq_of_le h with h₁ h₁, |
| 251 | + { rw q h₁ at hx, |
| 252 | + subst hx, |
| 253 | + apply lt_irrefl x h₁ }, |
| 254 | + { apply rs, |
| 255 | + rwa h₁ } }, |
| 256 | + { intro h, |
| 257 | + refine ⟨λ z hz, _, _⟩, |
| 258 | + { split, |
| 259 | + { intro hr, |
| 260 | + exfalso, |
| 261 | + apply lt_asymm (h _ hr) hz }, |
| 262 | + { rintro rfl, |
| 263 | + apply (lt_irrefl _ hz).elim } }, |
| 264 | + { intro rs, |
| 265 | + apply lt_irrefl _ (h _ rs) } } |
| 266 | +end |
| 267 | + |
| 268 | +/-- Colex is an extension of the base ordering on α. -/ |
| 269 | +lemma singleton_lt_iff_lt [linear_order α] {r s : α} : |
| 270 | + ({r} : finset α).to_colex < ({s} : finset α).to_colex ↔ r < s := |
| 271 | +begin |
| 272 | + rw colex.lt_def, |
| 273 | + simp only [mem_singleton, ← and_assoc, exists_eq_right], |
| 274 | + split, |
| 275 | + { rintro ⟨q, p⟩, |
| 276 | + apply lt_of_le_of_ne _ (ne.symm p), |
| 277 | + contrapose! p, |
| 278 | + rw (q p).1 rfl }, |
| 279 | + { intro a, |
| 280 | + exact ⟨λ z hz, iff_of_false (ne_of_gt (trans hz a)) (ne_of_gt hz), ne_of_gt a⟩ } |
| 281 | +end |
| 282 | + |
| 283 | +/-- |
| 284 | +If A is before B in colex, and everything in B is small, then everything in A is small. |
| 285 | +-/ |
| 286 | +lemma forall_lt_of_colex_lt_of_forall_lt [linear_order α] {A B : finset α} |
| 287 | +(t : α) (h₁ : A.to_colex < B.to_colex) (h₂ : ∀ x ∈ B, x < t) : |
| 288 | + ∀ x ∈ A, x < t := |
| 289 | +begin |
| 290 | + rw colex.lt_def at h₁, |
| 291 | + rcases h₁ with ⟨k, z, _, _⟩, |
| 292 | + intros x hx, |
| 293 | + apply lt_of_not_ge, |
| 294 | + intro a, |
| 295 | + refine not_lt_of_ge a (h₂ x _), |
| 296 | + rwa ← z, |
| 297 | + apply lt_of_lt_of_le (h₂ k ‹_›) a, |
| 298 | +end |
| 299 | + |
| 300 | +/-- Colex doesn't care if you remove the other set -/ |
| 301 | +@[simp] lemma sdiff_lt_sdiff_iff_lt [has_lt α] [decidable_eq α] (A B : finset α) : |
| 302 | + (A \ B).to_colex < (B \ A).to_colex ↔ A.to_colex < B.to_colex := |
| 303 | +begin |
| 304 | + rw [colex.lt_def, colex.lt_def], |
| 305 | + apply exists_congr, |
| 306 | + intro k, |
| 307 | + simp only [mem_sdiff, not_and, not_not], |
| 308 | + split, |
| 309 | + { rintro ⟨z, kAB, kB, kA⟩, |
| 310 | + refine ⟨_, kA, kB⟩, |
| 311 | + { intros x hx, |
| 312 | + specialize z hx, |
| 313 | + tauto } }, |
| 314 | + { rintro ⟨z, kA, kB⟩, |
| 315 | + refine ⟨_, λ _, kB, kB, kA⟩, |
| 316 | + intros x hx, |
| 317 | + rw z hx }, |
| 318 | +end |
| 319 | + |
| 320 | +/-- For subsets of ℕ, we can show that colex is equivalent to binary. -/ |
| 321 | +lemma sum_pow_two_lt_iff_lt (A B : finset ℕ) : A.sum (pow 2) < B.sum (pow 2) ↔ |
| 322 | + A.to_colex < B.to_colex := |
| 323 | +begin |
| 324 | + have z : ∀ (A B : finset ℕ), A.to_colex < B.to_colex → A.sum (pow 2) < B.sum (pow 2), |
| 325 | + { intros A B, |
| 326 | + rw [← sdiff_lt_sdiff_iff_lt, colex.lt_def], |
| 327 | + rintro ⟨k, z, kA, kB⟩, |
| 328 | + rw ← sdiff_union_inter A B, |
| 329 | + conv_rhs { rw ← sdiff_union_inter B A }, |
| 330 | + rw [sum_union (disjoint_sdiff_inter _ _), sum_union (disjoint_sdiff_inter _ _), |
| 331 | + inter_comm, add_lt_add_iff_right], |
| 332 | + apply lt_of_lt_of_le (@nat.sum_pow_two_lt k (A \ B) _), |
| 333 | + { apply single_le_sum (λ _ _, nat.zero_le _) kB }, |
| 334 | + intros x hx, |
| 335 | + apply lt_of_le_of_ne (le_of_not_lt (λ kx, _)), |
| 336 | + { apply (ne_of_mem_of_not_mem hx kA) }, |
| 337 | + specialize z kx, |
| 338 | + have := z.1 hx, |
| 339 | + rw mem_sdiff at this hx, |
| 340 | + exact hx.2 this.1 }, |
| 341 | + refine ⟨λ h, (lt_trichotomy A B).resolve_right (λ h₁, h₁.elim _ (not_lt_of_gt h ∘ z _ _)), z A B⟩, |
| 342 | + rintro rfl, |
| 343 | + apply irrefl _ h |
| 344 | +end |
| 345 | + |
| 346 | +end colex |
0 commit comments