Zulip Chat Archive
Stream: new members
Topic: How to import everything under `(mathlib)/data/nat/` ?
Michael Stoll (Mar 19 2022 at 13:18):
Since I never know beforehand which precise files I need to import (who would have guessed that nat.odd_of_mod_four_eq_three
lives in data.nat.modeq
?), I would like to imprt everything related to nat
s (say) in one go. But import data.nat
gives the error file 'data/nat' not found in the search path
(whereas import tactic
does work, even though tactic
is a folder and not a file). So how can I get around this?
Johan Commelin (Mar 19 2022 at 13:20):
@Michael Stoll If there is a file some/directory/default.lean
, then that will get imported if you write import some.directory
.
Johan Commelin (Mar 19 2022 at 13:20):
But not all directories have such a file. And default.lean
doesn't always import all other files in the directory either.
Michael Stoll (Mar 19 2022 at 13:23):
OK; this tells me why my attempt did not work. But is there a reasonable way to do it other than importing all the individual files? I guess I could write some sort of all_nat.lean
file for this and import that. Is this the way to go?
Yaël Dillies (Mar 19 2022 at 13:23):
YOu would end up importing most of the library I suspect. has a lot of properties.
Eric Rodriguez (Mar 19 2022 at 13:24):
I feel like out of all the folders, data/nat could definbitely have a default
; I thought the same as Yael but I had a hunt and there's no really egregiously large file there
Damiano Testa (Mar 19 2022 at 13:24):
In a separate thread, Kevin said this:
You can always run ./scripts/mk_all.sh
on the command line and then import all
if you want to search all of mathlib.
Michael Stoll (Mar 19 2022 at 13:24):
BTW, generating all.lean
and doing import all
tends to produce excessive memory errors
on things like suggest
or hint
...
Michael Stoll (Mar 19 2022 at 13:24):
(I was just typing this before Damiano replied...)
Eric Rodriguez (Mar 19 2022 at 13:25):
I feel like the most efficient way to search theorems in mathlib is using the regex search
Michael Stoll (Mar 19 2022 at 13:26):
The concrete motivation for my question is the following. I want to prove
example (p : ℕ) (hp : p % 4 = 3) : ∃ n : ℕ, p = 4*n + 3 := ?
believing that this should certainly be (in a suitably more general form) in mathlib, but I was unable to find it...
Eric Rodriguez (Mar 19 2022 at 13:26):
indeed, just typing % 4
finds this theorem pretty instantly
Michael Stoll (Mar 19 2022 at 13:27):
Where do I type % 4
?
Eric Rodriguez (Mar 19 2022 at 13:28):
if you're using vscode
, you can press the search thing on the left or press (ctrl/command)+shift+f
Michael Stoll (Mar 19 2022 at 13:29):
If I do that, I find lots of places where % 4
occurs in my project files, but it doesn't appear to search the library.
Eric Rodriguez (Mar 19 2022 at 13:30):
oh! you'll need to turn off the cog of doom
Eric Rodriguez (Mar 19 2022 at 13:30):
unpress that weird cog at the bottom right
Eric Rodriguez (Mar 19 2022 at 13:31):
(in this case though, you may enjoy docs#nat.div_add_mod, too)
Kevin Buzzard (Mar 19 2022 at 13:32):
Yeah, the proof is use p/4
then rw <- hp
followed by library_search
Michael Stoll (Mar 19 2022 at 13:38):
I knew that I had seen this at some point, but wasn't able to find it again...
Michael Stoll (Mar 19 2022 at 13:39):
Which is an experience I'm having more and more frequently.
Yaël Dillies (Mar 19 2022 at 13:40):
Eric Rodriguez said:
I thought the same as Yael but I had a hunt and there's no really egregiously large file there
My point is that not all the properties of are under data.nat.
.
Michael Stoll (Mar 19 2022 at 13:50):
And how do I do
example (p : ℕ) (hp : p % 4 = 3) : odd ((p-1)/2) := ?
Somehow I think that all these trivial elementary number theory lemmas should be much easier to obtain...
Michael Stoll (Mar 19 2022 at 14:03):
... than in the way I'm trying to do it.
Yaël Dillies (Mar 19 2022 at 14:05):
Maybe giving (p - 3)/4
as a witness of oddness is somewhat easy?
Michael Stoll (Mar 19 2022 at 14:13):
example (p : ℕ) (hp : p % 4 = 3) : odd ((p-1)/2) :=
begin
have h : ∃ n : ℕ, p = 4*n + 3 := by { use p/4, rw ← hp, exact (nat.div_add_mod p 4).symm, },
use (p-3)/4, rw [h],
nth_rewrite 0 (by norm_num : 4 = 2*2),
rw mul_assoc,
simp,
end
I'm sure this can be simplified...
Kevin Buzzard (Mar 19 2022 at 15:16):
You are using subtraction and division of naturals so you can expect pain. Neither of these operations are mathematically well-behaved in Lean
Michael Stoll (Mar 19 2022 at 15:39):
I'm going to use things as exponents, so I do want naturals... Also, prime numbers are naturals in mathlib.
Michael Stoll (Mar 19 2022 at 16:42):
Here is finally what I wanted to achieve. I had expected this to be part of the API in number_theory.sum_two_squares
, but there is really no API there. (One has to add the necessary imports.)
/-- A lemma from elementary number theory that should be in the library -/
lemma prime_eq_three_mod_four_not_dvd_sum_of_two_squares
(p : ℕ) [fact p.prime] (hp : p % 4 = 3) (a b : ℤ) (hab : is_coprime a b) : ¬ ↑p ∣ a^2 + b^2 :=
begin
intro h,
-- rewrite divisibility assumption as an equality in ℤ/pℤ
have h₁ : ((a^2 + b^2 : ℤ) : zmod p) = 0 := (zmod.int_coe_zmod_eq_zero_iff_dvd _ _).mpr h,
push_cast at h₁,
have h₂ : (a : zmod p)^2 = -↑b^2 := eq_neg_of_add_eq_zero h₁,
-- The idea is now to deduce from a² = -b² in ℤ/pℤ that 1 = -1
-- using Fermat's little theorem
have h₃ := nat.mul_div_cancel' (div_sub_one_of_mod_two_eq_one p (nat.odd_of_mod_four_eq_three hp)),
-- h₃ : 2*((p-1)/2) = p-1
have h₄ : ∃ n : ℕ, p = 4*n + 3 := by { use p/4, rw ← hp, exact (nat.div_add_mod p 4).symm, },
cases h₄ with n h₄,
-- we need to know that `(p-1)/2` is odd
have hodd : odd ((p-1)/2) :=
by { use (p-3)/4, rw [h₄],
nth_rewrite 0 (by norm_num : 4 = 2*2),
rw mul_assoc,
simp, },
-- raise our equality to the `(p-1)/2`th power
have h₅ : (a : zmod p)^(p-1) = -↑b^(p-1),
{ have h₂' : ((a : zmod p)^2)^((p-1)/2) = (-↑b^2)^((p-1)/2) :=
congr_fun (congr_arg pow h₂) ((p - 1) / 2),
rw [← pow_mul (↑a), neg_pow, ← pow_mul (↑b), h₃, nat.neg_one_pow_of_odd hodd, neg_one_mul] at h₂',
exact h₂', },
-- another bit of trivial knowledge that is needed
have h₆ : 0 < p - 1 := by { simp [h₄], },
-- we can apply Fermat's little theorem when `a` and `b` are nonzero in ℤ/pℤ,
-- so we have to distinguish cases here
by_cases ha : (a : zmod p) = 0,
{ simp [ha, zero_pow h₆] at h₅,
-- if `a = 0` mod `p`, then `b = 0` mod `p`, so `p` divides `a` and `b`,
-- which contradicts the coprimality assumption
have hpa := (zmod.int_coe_zmod_eq_zero_iff_dvd a p).mp ha,
have hpb := (zmod.int_coe_zmod_eq_zero_iff_dvd b p).mp (pow_eq_zero h₅),
rcases hab with ⟨u, v, hab⟩,
have hf : (p : ℤ) ∣ 1 :=
by { rw [← hab],
apply dvd_add,
apply dvd_mul_of_dvd_right hpa,
apply dvd_mul_of_dvd_right hpb, },
norm_cast at hf,
exact nat.prime.not_dvd_one _inst_1.1 hf, },
{ -- now the case that `a ≠ 0` mod `p`
rw zmod.pow_card_sub_one_eq_one ha at h₅,
-- we have to get rid of the possibility that `b = 0` mod `p`
by_cases hb : (b : zmod p) = 0,
{ simp [hb, zero_pow h₆] at h₅,
exact h₅, },
{ -- now both are nonzero mod `p` and we get that `1 = -1` mod `p`
rw zmod.pow_card_sub_one_eq_one hb at h₅,
-- it is surprisingly hard to get from this to a contradiction...
have h₇ : ↑p ∣ (2 : ℤ) :=
by { rw [(by norm_cast : (-1 : zmod p) = ↑(-1 : ℤ)), (by norm_cast : (1 : zmod p) = ↑(1 : ℤ))] at h₅,
rw [zmod.int_coe_eq_int_coe_iff, int.modeq_iff_dvd] at h₅,
norm_num at h₅,
exact h₅, },
norm_cast at h₇,
have hp2 : 2 < p :=
by { simp [h₄], apply nat.succ_lt_succ, apply nat.succ_lt_succ, exact nat.zero_lt_succ _, },
have h₈ : p ≤ 2 := nat.le_of_dvd (nat.zero_lt_succ 1) h₇,
revert hp2,
exact not_lt_of_le h₈, }, },
end
This has cost me a full day! :frown: It shouldn't be that hard...
Kevin Buzzard (Mar 19 2022 at 17:35):
I know but wasn't it satisfying!
Kevin Buzzard (Mar 19 2022 at 17:37):
It might have been cheaper to deduce that -1 is a square and then use the fact (in the library) that this is false if p=3 mod 4
Michael Stoll (Mar 19 2022 at 17:53):
Not sure that it would be much cheaper to get to -1
being a square mod p
. But feel free to suggest a more efficient proof :smile:
Johan Commelin (Mar 19 2022 at 18:12):
@Michael Stoll
import number_theory.sum_two_squares
/-- A lemma from elementary number theory that should be in the library -/
lemma prime_eq_three_mod_four_not_dvd_sum_of_two_squares
(p : ℕ) [fact p.prime] (hp : p % 4 = 3) (a b : ℤ) (hab : is_coprime a b) : ¬ ↑p ∣ a^2 + b^2 :=
begin
contrapose! hp,
rw ← zmod.exists_sq_eq_neg_one_iff_mod_four_ne_three,
simp only [← zmod.int_coe_zmod_eq_zero_iff_dvd, int.cast_add, int.cast_pow] at hp,
obtain hb|hb := eq_or_ne (b : zmod p) 0,
{ simp only [hb, zero_pow', ne.def, bit0_eq_zero, nat.one_ne_zero, not_false_iff, add_zero,
pow_eq_zero_iff, nat.succ_pos'] at hp,
rw [zmod.int_coe_zmod_eq_zero_iff_dvd, ← int.dvd_nat_abs, int.coe_nat_dvd] at hb hp,
rw int.coprime_iff_nat_coprime at hab,
have h1p : 1 < p := fact.out _,
exact (nat.not_coprime_of_dvd_of_dvd h1p hp hb hab).elim, },
refine ⟨(a / b : zmod p), _⟩,
field_simp [hb, eq_neg_iff_add_eq_zero, hp],
end
Michael Stoll (Mar 19 2022 at 18:20):
@Johan Commelin Thanks! I did not realize that nat.not_coprime_of_dvd_of_dvd
was there; this saves a few extra lines...
Johan Commelin (Mar 19 2022 at 18:22):
Also, it suffices to case on whether (b : zmod p)
is 0
.
Michael Stoll (Mar 19 2022 at 18:35):
Yes, I saw that in your code.
Michael Stoll (Mar 19 2022 at 19:35):
Is there an integers version of nat.not_coprime_of_dvd_of_dvd
?
Johan Commelin (Mar 19 2022 at 20:14):
Nope, but there should be. My proof is a bit hacky at that point.
Johan Commelin (Mar 19 2022 at 20:14):
Otoh, that would probably use p : ℤ
. So we'd still need some glue at some point.
Michael Stoll (Mar 19 2022 at 20:14):
Presumably a more general version for any commutative ring would make sense.
Johan Commelin (Mar 19 2022 at 20:15):
Agreed. I guess it makes sense in any UFD? Or gcd_domain
? I don't know precisely what's needed.
Michael Stoll (Mar 19 2022 at 20:16):
When dealing with primes, one has to convert between ℕ and ℤ anyway.
Michael Stoll (Mar 19 2022 at 20:17):
Commutative ring should be OK. The proof is the same: a | b
and a | c
implies a | u*b + v*c = 1
if b
and c
are coprime, as witnessed by u
and v
. The condition for a
is then that a
is not a unit (which is clearly a bit less nice to work with than a ≠ 1
).
Eric Rodriguez (Mar 19 2022 at 20:21):
import field_theory.abel_ruffini
lemma coprime_of_dvd_of_dvd {R} [comm_semiring R] {d x y : R} (h : ¬ is_unit d)
(hx : d ∣ x) (hy : d ∣ y) : ¬is_coprime x y :=
begin
rintro ⟨a, b, hab⟩,
apply h,
exact is_unit_of_dvd_unit (show d ∣ 1, from hab ▸ hx.linear_comb hy a b) is_unit_one,
end
Eric Rodriguez (Mar 19 2022 at 20:22):
I'll leave it to you to figure out the right imports :b
Michael Stoll (Mar 19 2022 at 20:22):
It should better be called not_coprime_...
:smile:
Last updated: Dec 20 2023 at 11:08 UTC