Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 957f64e

Browse files
committed
feat(algebra/floor): When the floor is strictly positive (#9625)
`⌊a⌋₊` and `⌊a⌋` are strictly positive iff `1 ≤ a`. We use this to slightly golf IMO 2013 P5.
1 parent bcd79a1 commit 957f64e

File tree

2 files changed

+54
-53
lines changed

2 files changed

+54
-53
lines changed

archive/imo/imo2013_q5.lean

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ import data.real.basic
1111
/-!
1212
# IMO 2013 Q5
1313
14-
Let ℚ>₀ be the set of positive rational numbers. Let f: ℚ>₀ → ℝ be a function satisfying
14+
Let `ℚ>₀` be the positive rational numbers. Let `f : ℚ>₀ → ℝ` be a function satisfying
1515
the conditions
1616
17-
(1) f(x) * f(y) ≥ f(x * y)
18-
(2) f(x + y) ≥ f(x) + f(y)
17+
1. `f(x) * f(y) ≥ f(x * y)`
18+
2. `f(x + y) ≥ f(x) + f(y)`
1919
20-
for all x,y ∈ ℚ>₀. Given that f(a) = a for some rational a > 1, prove that f(x) = x for
21-
all x ∈ ℚ>₀.
20+
for all `x, y ∈ ℚ>₀`. Given that `f(a) = a` for some rational `a > 1`, prove that `f(x) = x` for
21+
all `x ∈ ℚ>₀`.
2222
2323
# Solution
2424
@@ -98,54 +98,39 @@ lemma f_pos_of_pos {f : ℚ → ℝ} {q : ℚ} (hq : 0 < q)
9898
(H4 : ∀ n : ℕ, 0 < n → (n : ℝ) ≤ f n) :
9999
0 < f q :=
100100
begin
101-
have hfqn := calc f q.num = f (q * q.denom) : by rw ←rat.mul_denom_eq_num
102-
... ≤ f q * f q.denom : H1 q q.denom hq (nat.cast_pos.mpr q.pos),
103-
104-
-- Now we just need to show that `f q.num` and `f q.denom` are positive.
105-
-- Then nlinarith will be able to close the goal.
106-
107101
have num_pos : 0 < q.num := rat.num_pos_iff_pos.mpr hq,
108-
have hqna : (q.num.nat_abs : ℤ) = q.num := int.nat_abs_of_nonneg num_pos.le,
109-
have hqfn' :=
110-
calc (q.num : ℝ)
111-
= ((q.num.nat_abs : ℤ) : ℝ) : congr_arg coe (eq.symm hqna)
112-
... ≤ f q.num.nat_abs : H4 q.num.nat_abs
113-
(int.nat_abs_pos_of_ne_zero (ne_of_gt num_pos))
114-
... = f q.num : by exact_mod_cast congr_arg f (congr_arg coe hqna),
115-
116-
have f_num_pos := calc (0 : ℝ) < q.num : int.cast_pos.mpr num_pos
117-
... ≤ f q.num : hqfn',
118-
have f_denom_pos := calc (0 : ℝ) < q.denom : nat.cast_pos.mpr q.pos
119-
... ≤ f q.denom : H4 q.denom q.pos,
120-
nlinarith
102+
have hmul_pos :=
103+
calc (0 : ℝ) < q.num : int.cast_pos.mpr num_pos
104+
... = ((q.num.nat_abs : ℤ) : ℝ) : congr_arg coe (int.nat_abs_of_nonneg num_pos.le).symm
105+
... ≤ f q.num.nat_abs : H4 q.num.nat_abs
106+
(int.nat_abs_pos_of_ne_zero num_pos.ne')
107+
... = f q.num : by { rw ←int.nat_abs_of_nonneg num_pos.le, norm_cast }
108+
... = f (q * q.denom) : by rw ←rat.mul_denom_eq_num
109+
... ≤ f q * f q.denom : H1 q q.denom hq (nat.cast_pos.mpr q.pos),
110+
have h_f_denom_pos :=
111+
calc (0 : ℝ) < q.denom : nat.cast_pos.mpr q.pos
112+
... ≤ f q.denom : H4 q.denom q.pos,
113+
exact pos_of_mul_pos_right hmul_pos h_f_denom_pos.le,
121114
end
122115

123116
lemma fx_gt_xm1 {f : ℚ → ℝ} {x : ℚ} (hx : 1 ≤ x)
124117
(H1 : ∀ x y, 0 < x → 0 < y → f (x * y) ≤ f x * f y)
125118
(H2 : ∀ x y, 0 < x → 0 < y → f x + f y ≤ f (x + y))
126119
(H4 : ∀ n : ℕ, 0 < n → (n : ℝ) ≤ f n) :
127-
((x - 1 : ℚ) : ℝ) < f x :=
120+
(x - 1 : ℝ) < f x :=
128121
begin
129-
have hfe : (⌊x⌋.nat_abs : ℤ) = ⌊x⌋ := int.nat_abs_of_nonneg
130-
(floor_nonneg.mpr (zero_le_one.trans hx)),
131-
have hfe' : (⌊x⌋.nat_abs : ℚ) = ⌊x⌋, { exact_mod_cast hfe },
132-
have h0fx : 0 < ⌊x⌋ := int.cast_pos.mp ((sub_nonneg.mpr hx).trans_lt (sub_one_lt_floor x)),
133-
have h_nat_abs_floor_pos : 0 < ⌊x⌋.nat_abs := int.nat_abs_pos_of_ne_zero (ne_of_gt h0fx),
134-
have hx0 := calc ((x - 1 : ℚ) : ℝ)
135-
< ⌊x⌋ : by exact_mod_cast sub_one_lt_floor x
136-
... = ↑⌊x⌋.nat_abs : by exact_mod_cast hfe.symm
137-
... ≤ f ⌊x⌋.nat_abs : H4 ⌊x⌋.nat_abs h_nat_abs_floor_pos
138-
... = f ⌊x⌋ : by rw hfe',
139-
140-
obtain (h_eq : (⌊x⌋ : ℚ) = x) | (h_lt : (⌊x⌋ : ℚ) < x) := (floor_le x).eq_or_lt,
122+
have hx0 :=
123+
calc (x - 1 : ℝ)
124+
< ⌊x⌋₊ : by exact_mod_cast sub_one_lt_nat_floor x
125+
... ≤ f ⌊x⌋₊ : H4 _ (nat_floor_pos.2 hx),
126+
127+
obtain h_eq | h_lt := (nat_floor_le $ zero_le_one.trans hx).eq_or_lt,
141128
{ rwa h_eq at hx0 },
142129

143-
calc ((x - 1 : ℚ) : ℝ) < f ⌊x⌋ : hx0
144-
... < f (x - ⌊x⌋) + f ⌊x⌋ : lt_add_of_pos_left (f ↑⌊x⌋)
145-
(f_pos_of_pos (sub_pos.mpr h_lt) H1 H4)
146-
... ≤ f (x - ⌊x⌋ + ⌊x⌋) : H2 (x - ⌊x⌋) ⌊x⌋ (sub_pos.mpr h_lt)
147-
(by exact_mod_cast h0fx)
148-
... = f x : by simp only [sub_add_cancel]
130+
calc (x - 1 : ℝ) < f ⌊x⌋₊ : hx0
131+
... < f (x - ⌊x⌋₊) + f ⌊x⌋₊ : lt_add_of_pos_left _ (f_pos_of_pos (sub_pos.mpr h_lt) H1 H4)
132+
... ≤ f (x - ⌊x⌋₊ + ⌊x⌋₊) : H2 _ _ (sub_pos.mpr h_lt) (nat.cast_pos.2 (nat_floor_pos.2 hx))
133+
... = f x : by rw sub_add_cancel
149134
end
150135

151136
lemma pow_f_le_f_pow {f : ℚ → ℝ} {n : ℕ} (hn : 0 < n) {x : ℚ} (hx : 1 < x)
@@ -223,7 +208,7 @@ begin
223208
have H3 : ∀ x : ℚ, 0 < x → ∀ n : ℕ, 0 < n → ↑n * f x ≤ f (n * x),
224209
{ intros x hx n hn,
225210
cases n,
226-
{ exfalso, exact nat.lt_asymm hn hn },
211+
{ exact (lt_irrefl 0 hn).elim },
227212
induction n with pn hpn,
228213
{ simp only [one_mul, nat.cast_one] },
229214
calc (↑pn + 1 + 1) * f x
@@ -247,7 +232,7 @@ begin
247232
... = ↑a * f 1 : by rw hae },
248233

249234
calc (n : ℝ) = (n : ℝ) * 1 : (mul_one _).symm
250-
... ≤ (n : ℝ) * f 1 : (mul_le_mul_left (nat.cast_pos.mpr hn)).mpr hf1
235+
... ≤ (n : ℝ) * f 1 : mul_le_mul_of_nonneg_left hf1 (nat.cast_nonneg _)
251236
... ≤ f (n * 1) : H3 1 zero_lt_one n hn
252237
... = f n : by rw mul_one },
253238

src/algebra/floor.lean

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class floor_ring (α) [linear_ordered_ring α] :=
5555

5656
instance : floor_ring ℤ := { floor := id, le_floor := λ _ _, by rw int.cast_id; refl }
5757

58-
variables [linear_ordered_ring α] [floor_ring α]
58+
variables [linear_ordered_ring α] [floor_ring α] {z : ℤ} {a : α}
5959

6060
/-- `floor x` is the greatest integer `z` such that `z ≤ x`. It is denoted with `⌊x⌋`. -/
6161
def floor : α → ℤ := floor_ring.floor
@@ -94,6 +94,10 @@ by rw [← int.cast_one, floor_coe]
9494
@[mono] theorem floor_mono {a b : α} (h : a ≤ b) : ⌊a⌋ ≤ ⌊b⌋ :=
9595
le_floor.2 (le_trans (floor_le _) h)
9696

97+
lemma floor_pos : 0 < ⌊a⌋ ↔ 1 ≤ a :=
98+
⟨λ h, le_trans (by rwa [←int.cast_one, int.cast_le, ←zero_add (1 : ℤ), int.add_one_le_iff])
99+
(floor_le _), λ h, zero_lt_one.trans_le (le_floor.2 $ by rwa int.cast_one)⟩
100+
97101
@[simp] theorem floor_add_int (x : α) (z : ℤ) : ⌊x + z⌋ = ⌊x⌋ + z :=
98102
eq_of_forall_le_iff $ λ a, by rw [le_floor,
99103
← sub_le_iff_le_add, ← sub_le_iff_le_add, le_floor, int.cast_sub]
@@ -273,7 +277,7 @@ by { rw floor_lt, exact h.trans_le (le_ceil _) }
273277
/-! ### `nat_floor` and `nat_ceil` -/
274278

275279
section nat
276-
variables {a : α} {n : ℕ}
280+
variables {n : ℕ}
277281

278282
/-- `nat_floor x` is the greatest natural `n` that is less than `x`.
279283
It is equal to `⌊x⌋` when `x ≥ 0`, and is `0` otherwise. It is denoted with `⌊x⌋₊`.-/
@@ -287,12 +291,6 @@ begin
287291
exact_mod_cast (floor_le a).trans ha,
288292
end
289293

290-
lemma pos_of_nat_floor_pos (h : 0 < ⌊a⌋₊) : 0 < a :=
291-
begin
292-
refine (le_or_lt a 0).resolve_left (λ ha, lt_irrefl 0 _),
293-
rwa nat_floor_of_nonpos ha at h,
294-
end
295-
296294
lemma nat_floor_le (ha : 0 ≤ a) : ↑⌊a⌋₊ ≤ a :=
297295
begin
298296
refine le_trans _ (floor_le _),
@@ -310,6 +308,21 @@ end
310308
theorem le_nat_floor_iff (ha : 0 ≤ a) : n ≤ ⌊a⌋₊ ↔ ↑n ≤ a :=
311309
⟨λ h, (nat.cast_le.2 h).trans (nat_floor_le ha), le_nat_floor_of_le⟩
312310

311+
lemma nat_floor_pos : 0 < ⌊a⌋₊ ↔ 1 ≤ a :=
312+
begin
313+
cases le_total a 0,
314+
{ rw nat_floor_of_nonpos h,
315+
exact iff_of_false (lt_irrefl 0) (λ ha, zero_lt_one.not_le $ ha.trans h) },
316+
{ rw [←nat.cast_one, ←le_nat_floor_iff h],
317+
refl }
318+
end
319+
320+
lemma pos_of_nat_floor_pos (h : 0 < ⌊a⌋₊) : 0 < a :=
321+
begin
322+
refine (le_or_lt a 0).resolve_left (λ ha, lt_irrefl 0 _),
323+
rwa nat_floor_of_nonpos ha at h,
324+
end
325+
313326
lemma lt_of_lt_nat_floor (h : n < ⌊a⌋₊) : ↑n < a :=
314327
(nat.cast_lt.2 h).trans_le (nat_floor_le (pos_of_nat_floor_pos ((nat.zero_le n).trans_lt h)).le)
315328

@@ -346,6 +359,9 @@ begin
346359
exact int.le_to_nat _,
347360
end
348361

362+
lemma sub_one_lt_nat_floor (a : α) : a - 1 < ⌊a⌋₊ :=
363+
sub_lt_iff_lt_add.2 (lt_nat_floor_add_one a)
364+
349365
lemma nat_floor_eq_zero_iff : ⌊a⌋₊ = 0 ↔ a < 1 :=
350366
begin
351367
obtain ha | ha := le_total a 0,

0 commit comments

Comments
 (0)