Zulip Chat Archive
Stream: general
Topic: natural number hell
Patrick Massot (May 15 2018 at 07:56):
I want to use big.map
once I have the map
Patrick Massot (May 15 2018 at 07:57):
I should push something so that you can see the context
Mario Carneiro (May 15 2018 at 07:57):
and then the f
will be applied to the functions P and F... then what?
Patrick Massot (May 15 2018 at 07:58):
https://github.com/PatrickMassot/bigop/blob/master/src/bigop.lean#L343
Mario Carneiro (May 15 2018 at 07:59):
wait, so you want the function f
to be i |-> a+b-i
?
Mario Carneiro (May 15 2018 at 07:59):
then why are you mapping with something else in the lemma?
Patrick Massot (May 15 2018 at 08:01):
The problem is reverse_range'
is about your range'
, with start and length, and my goal is to have the maths range', with start and end
Mario Carneiro (May 15 2018 at 08:03):
Think of the problem in reverse. You want the theorem to say a+b-i
at the end, so you want f
to be \lam i, a+b-i
when you apply big.map
; the reverse theorem just adds a list.reverse
on the set. So you should be proving reverse (range' a b) = map (λ i, a+b-i) (range' a b)
Mario Carneiro (May 15 2018 at 08:04):
that is, without any algebraic rearrangement this is exactly what you need to fill the gap in the proof. Right?
Patrick Massot (May 15 2018 at 08:05):
Maybe I did so many detours I forgot the goal on the road
Patrick Massot (May 15 2018 at 08:08):
It seems I still need a + (b + 1 - a) - i = a + b - i
(still assuming i ∈ range' a (b + 1 - a)
)
Mario Carneiro (May 15 2018 at 08:09):
that's easy though, it is one of the add_sub
theorems
Patrick Massot (May 15 2018 at 08:09):
I think we already saw that one
Mario Carneiro (May 15 2018 at 08:10):
nat.add_sub_cancel'
, which requires a <= b + 1
Mario Carneiro (May 15 2018 at 08:11):
Note that your assumption is sufficient to prove this, but only in a circuitous fashion, do you have any more direct evidence that a <= b+1
?
Patrick Massot (May 15 2018 at 08:12):
wait
Mario Carneiro (May 15 2018 at 08:12):
wait
Mario Carneiro (May 15 2018 at 08:13):
your theorem is nonsense
Patrick Massot (May 15 2018 at 08:13):
your theorem is nonsense
Patrick Massot (May 15 2018 at 08:13):
reverse (range' a b) = map (λ i, a+b-i) (range' a b)
is not true
Patrick Massot (May 15 2018 at 08:13):
I changed all statements so many times...
Mario Carneiro (May 15 2018 at 08:14):
I'm rather confused by the dual use of range'
btw, could you give it another name? range''
maybe?
Patrick Massot (May 15 2018 at 08:14):
You mean in the name of reverse_range'
?
Mario Carneiro (May 15 2018 at 08:15):
I mean range' a b = [a, ..., b]
vs range' a b = [a, ..., a+b]
Mario Carneiro (May 15 2018 at 08:15):
pretty sure both functions are being called range'
Patrick Massot (May 15 2018 at 08:15):
I don't redefine range'
Mario Carneiro (May 15 2018 at 08:15):
What is your definition?
Patrick Massot (May 15 2018 at 08:16):
I use your range'
Mario Carneiro (May 15 2018 at 08:16):
oh I see
Patrick Massot (May 15 2018 at 08:16):
But always in range' a (b+1-a)
Mario Carneiro (May 15 2018 at 08:16):
In that case I need to state the theorem above with your bounds
Mario Carneiro (May 15 2018 at 08:16):
reverse (range' a (b+1-a)) = map (λ i, a+b-i) (range' a (b+1-a))
Patrick Massot (May 15 2018 at 08:17):
yes, this is correct
Patrick Massot (May 15 2018 at 08:17):
(not that I can prove it, but I can check it on examples)
Patrick Massot (May 15 2018 at 08:19):
But I wanted to deduce it from a version involving only range' a b
in LHS
Patrick Massot (May 15 2018 at 08:19):
hence the "arithmetic" trouble
Patrick Massot (May 15 2018 at 08:20):
But indeed this is the statement which makes big.range_anti_mph
trivial to prove from the previous results
Mario Carneiro (May 15 2018 at 08:20):
Well, there are a lot of free endpoints in the reverse theorem, maybe you need to generalize it?
Patrick Massot (May 15 2018 at 08:21):
what reverse theorem?
Mario Carneiro (May 15 2018 at 08:24):
I'm thinking:
reverse (range' a (n + 1)) = map (λ i, c-i) (range' b (n + 1))
subject to an equation relating a,b,c
Mario Carneiro (May 15 2018 at 08:25):
Actually I think we need another generalization of range'
that varies the step too
Mario Carneiro (May 15 2018 at 08:26):
that would make this easy
Patrick Massot (May 15 2018 at 08:28):
I need to go to my office, but the situation improved a lot: https://github.com/PatrickMassot/bigop/blob/master/src/bigop.lean#L335-L341 Thank you very much
Patrick Massot (May 15 2018 at 08:29):
I hope I'll be able to prove that last missing lemma later if you don't have time to do it properly
Mario Carneiro (May 15 2018 at 09:07):
I did it properly. Here are the lemmas I added:
theorem map_add_range' (a) : ∀ s n : ℕ, map ((+) a) (range' s n) = range' (a + s) n | s 0 := rfl | s (n+1) := congr_arg (cons _) (map_add_range' (s+1) n) theorem range_succ_eq_map (n : ℕ) : range (n + 1) = 0 :: map succ (range n) := by rw [range_eq_range', range_eq_range', range', add_comm, ← map_add_range']; congr; exact funext one_add theorem reverse_range' : ∀ s n : ℕ, reverse (range' s n) = map (λ i, s + n - 1 - i) (range n) | s 0 := rfl | s (n+1) := by rw [range'_concat, reverse_append, range_succ_eq_map]; simpa [show s + (n + 1) - 1 = s + n, from rfl, (∘), λ a i, show a - 1 - i = a - succ i, by rw [nat.sub_sub, add_comm]; refl] using reverse_range' s n
Patrick Massot (May 15 2018 at 09:58):
Thank you Mario! I already had the first one at https://github.com/PatrickMassot/bigop/blob/master/src/bigop.lean#L126
Patrick Massot (May 15 2018 at 09:58):
Maybe I should learn to do induction using pattern matching
Patrick Massot (May 15 2018 at 17:42):
I read too quickly, I thought you proved the lemma I needed
Patrick Massot (May 15 2018 at 17:43):
But your RHS doesn't even contains range'
Patrick Massot (May 15 2018 at 17:44):
Proving the lemma I stated from what you proved seems to be as much work as a direct proof, no?
Mario Carneiro (May 15 2018 at 20:20):
You still have some algebra before you get to the exact version you need, but you can put reverse_range'
, range_eq_range'
, map_add_range'
and map_map
together and then do some algebra
Mario Carneiro (May 15 2018 at 20:34):
theorem range'_eq_map_range (s n : ℕ) : range' s n = map ((+) s) (range n) := by rw [range_eq_range', map_add_range']; refl example (a b : ℕ) : reverse (range' a (b+1-a)) = map (λ i, a+b-i) (range' a (b+1-a)) := begin rw [reverse_range', range'_eq_map_range, map_map], apply map_congr, intros i H, simp at *, rw [nat.add_sub_add_left, nat.add_sub_cancel'], {refl}, refine (le_total _ _).resolve_left (λ h, _), rw sub_eq_zero_of_le h at H, exact not_lt_zero _ H end
Patrick Massot (May 15 2018 at 21:22):
Thank you very much Mario! I'm still not convinced this is simpler than a direct attack on this lemma, but I very much relieved to have it.
Patrick Massot (May 15 2018 at 21:22):
What is this resolve_left
thing?
Patrick Massot (May 15 2018 at 21:24):
The state at the point where you write this, a b i : ℕ,
H : i < b + 1 - a
⊢ b + 1 ≥ a
is typically something that could have led me to harm my computer.
Patrick Massot (May 15 2018 at 21:25):
I also note that you used simp at *
in the middle of a proof. Isn't this frowned upon according to mathlib's docs?
Mario Carneiro (May 15 2018 at 21:25):
That's actually a really subtle thing, it wouldn't work if it was i <= b+1-a
Patrick Massot (May 15 2018 at 21:26):
What do you mean it wouldn't work? The statement would still be true, right?
Mario Carneiro (May 15 2018 at 21:26):
no
Patrick Massot (May 15 2018 at 21:27):
This is crazy
Mario Carneiro (May 15 2018 at 21:27):
if i is zero then b+1 could be less than a
Patrick Massot (May 15 2018 at 21:28):
Did I mentioned I hate this substraction?
Mario Carneiro (May 15 2018 at 21:28):
the argument is basically that when you subtract small minus large you get 0, so since i is less than the subtraction it isn't zero so it is in the proper domain
Mario Carneiro (May 15 2018 at 21:30):
You could also have taken a <= b+1 as an assumption to the theorem if you like
Patrick Massot (May 15 2018 at 21:31):
I still don't know what resolve_left
stands for
Mario Carneiro (May 15 2018 at 21:31):
or.resolve_left
Kenny Lau (May 15 2018 at 21:32):
@Patrick Massot The type of le_total _ _
is or _ _
Kenny Lau (May 15 2018 at 21:32):
So (le_total _ _).resolve_left
means or.resolve_left (le_total _ _)
Patrick Massot (May 15 2018 at 21:32):
Thanks
Patrick Massot (May 15 2018 at 21:32):
to both of you
Patrick Massot (May 15 2018 at 21:33):
So the strategy here is some variation on a case disjunction, right?
Patrick Massot (May 15 2018 at 21:34):
Is it possible to use by_cases
instead? (I only try to understand, I don't really want to use by_cases
)
Kenny Lau (May 15 2018 at 21:34):
by_cases
uses p or not p
instead of any arbitrary p or q
Patrick Massot (May 15 2018 at 21:35):
It's true that le_total
is almost but not quite like this
Kenny Lau (May 15 2018 at 21:37):
however I don't see the difference between or.resolve_left (le_total _ _)
and le_of_not_le
Patrick Massot (May 15 2018 at 21:38):
I still don't understand why the goal after this refine
is false
Kenny Lau (May 15 2018 at 21:38):
refine (le_total _ _).resolve_left (λ h, _)
Kenny Lau (May 15 2018 at 21:39):
the expected type of (λ h, _)
is not (le _ _)
Kenny Lau (May 15 2018 at 21:39):
so h
has type le _ _
Kenny Lau (May 15 2018 at 21:39):
so _
has type false
Patrick Massot (May 15 2018 at 21:40):
Indeed the mysterious line has the same effect as apply le_of_not_le,
by_contradiction h,
Kenny Lau (May 15 2018 at 21:41):
try refine le_of_not_le (λ h, _)
Mario Carneiro (May 15 2018 at 21:41):
le_of_not_le
would also have worked
Kenny Lau (May 15 2018 at 21:41):
@Mario Carneiro entao eu ganho?
Mario Carneiro (May 15 2018 at 21:41):
vc ganhou
Kenny Lau (May 15 2018 at 21:42):
:D
Patrick Massot (May 15 2018 at 21:43):
The proof of le_of_not_le
is exactly this or.resolve_left le_total
Patrick Massot (May 15 2018 at 21:44):
But indeed Kenny's solution will probably be easier to remember for me
Patrick Massot (May 15 2018 at 21:47):
So, what should we do with all those lemmas we discussed in the last few days. Do you want me to prepare a PR? Are you doing it yourself?
Mario Carneiro (May 15 2018 at 21:49):
I've got a pot brewing, you can hold onto them locally until then
Patrick Massot (May 15 2018 at 21:49):
No problem
Patrick Massot (May 15 2018 at 21:56):
I extracted everything from my bigop file. It's now all in https://github.com/PatrickMassot/bigop/blob/master/src/pending_lemmas.lean if you want to make sure you have everything that was discussed here
Patrick Massot (May 15 2018 at 21:57):
It's bedtime now. Thank you very much again!
Patrick Massot (May 16 2018 at 09:05):
I have three substractions now :fearful: H : N ≥ 1, hyp : 0 ≤ i ∧ i < N ⊢ N - (N - 1 - i) = i + 1
Patrick Massot (May 16 2018 at 09:06):
Isn't it a way to first prove that we would get the same result in Z, because each substraction comes with its relevant inequality, and then ring
?
Mario Carneiro (May 16 2018 at 09:12):
yes, of course
Mario Carneiro (May 16 2018 at 09:13):
just use int.cast_sub
Patrick Massot (May 16 2018 at 09:14):
how does that work?
Mario Carneiro (May 16 2018 at 09:14):
that is, use int.cast_inj
to convert the natural number equality to a Z equality, and then use int.cast_add
, int.cast_sub
etc lemmas to move the arrows down to the bottom
Patrick Massot (May 16 2018 at 09:14):
Looking at the statement is pretty puzzling
Mario Carneiro (May 16 2018 at 09:15):
simp will do the latter part
Chris Hughes (May 16 2018 at 09:15):
example {i N : ℕ} (H : N ≥ 1) (hyp : 0 ≤ i ∧ i < N) : N - (N - 1 - i) = i + 1 := have 1 + i ≤ N, by rw add_comm; exact hyp.2, by rw [nat.sub_sub, nat.sub_sub_self this, add_comm]
Kenny Lau (May 16 2018 at 09:15):
and the winner is...
Mario Carneiro (May 16 2018 at 09:15):
^ or just prove it directly
Patrick Massot (May 16 2018 at 09:16):
Thanks Chris, but I'm really tired of those direct proofs
Patrick Massot (May 16 2018 at 09:16):
I want a systematic method
Mario Carneiro (May 16 2018 at 09:17):
example {i N : ℕ} (H : N ≥ 1) (hyp : 0 ≤ i ∧ i < N) : N - (N - 1 - i) = i + 1 := by rw [nat.sub_sub, add_comm, nat.sub_sub_self hyp.2]
Kenny Lau (May 16 2018 at 09:17):
and the winner is...
Chris Hughes (May 16 2018 at 09:17):
Is it poor form to use exact hyp.2
instead of exact nat.succ_le_of_lt hyp.2
?
Mario Carneiro (May 16 2018 at 09:17):
meh
Kenny Lau (May 16 2018 at 09:17):
maybe you should replace exact hyp.2
with cc
Kenny Lau (May 16 2018 at 09:18):
I mean, it isn't like you can't prove H
from hyp
...
Mario Carneiro (May 16 2018 at 09:18):
in general you should minimize your implicit definitional unfolding, but some things are too foundational to change at this point and I assume it will stay that way
Patrick Massot (May 16 2018 at 09:19):
I don't know how to use int.cast_inj
Mario Carneiro (May 16 2018 at 09:20):
oops, I mean int.coe_nat_inj'
Mario Carneiro (May 16 2018 at 09:23):
example {i N : ℕ} (H : N ≥ 1) (hyp : 0 ≤ i ∧ i < N) : N - (N - 1 - i) = i + 1 := by rw [← int.coe_nat_inj', int.coe_nat_sub, int.coe_nat_sub, int.coe_nat_sub]
produces a bunch of side conditions about less equal stuff
Mario Carneiro (May 16 2018 at 09:24):
actually it's a bit messy since the side conditions themselves involve natural number subtraction, so you need to rewrite them too or else prove them directly
Mario Carneiro (May 16 2018 at 09:26):
If you want to take this route I would suggest not writing natural number subtraction at all when you can help it, so that you don't need to deal with nested subtractions and the like
Mario Carneiro (May 16 2018 at 09:27):
that is, just use integer subtraction and convert back to natural numbers at the end with int.to_nat
if necessary
Patrick Massot (May 16 2018 at 09:29):
"not writing natural number subtraction at all" is my greatest Lean dream
Mario Carneiro (May 16 2018 at 09:30):
A simple way to actually do that is to replace m - n
everywhere with int.to_nat (m - n)
(where the subtraction there is actually integer subtraction now)
Patrick Massot (May 16 2018 at 09:30):
I need to go, I'll try tonight. Thanks you!
Mario Carneiro (May 16 2018 at 09:30):
That way the funky zero saturation operator is explicit
Kevin Buzzard (May 16 2018 at 12:48):
I want a systematic method
How about this: replace every occurrence of X <= Y
with Y = X + c
and replace every occurrence of X < Y
with Y = X + c + 1
, and then just use add_sub_cancel
or whatever it's called -- a + b - b = a
. It would not surprise me if this algorithm worked every time.
Kevin Buzzard (May 16 2018 at 12:50):
Example: you know i < N
and you want to prove N - (N - 1 - i) = i + 1
, well, write N = i + 1 + j
and -- oh -- you also need X - (Y + Z) = X- Y - Z
-- you get N - (j + 1 + i - (1 + i))
which is N - j
which is i + 1 + j - j
which is i + 1
Kevin Buzzard (May 16 2018 at 12:51):
I am assuming that your mathematician's goals never actually rely on the fact that a - b = 0 if b>a
Kevin Buzzard (May 16 2018 at 12:56):
This should reduce everything to nat.sub_sub
(if memory serves -- is it called that?) and add_sub_cancel
or whatever it's called (not in front of Lean right now).
Kevin Buzzard (May 16 2018 at 12:56):
oh and associativity and commutativity of course
Kevin Buzzard (May 16 2018 at 12:56):
Make them simp lemmas and see if simp can do it after you make the substitutions
Kevin Buzzard (May 16 2018 at 12:57):
(if they're not simp lemmas already)
Kevin Buzzard (May 16 2018 at 12:57):
Might not be the optimal approach but it looks pretty systematic to me
Chris Hughes (May 16 2018 at 12:59):
replace every occurrence of
X <= Y
with `Y = X + c
This bit sounds hard to do with simp
, since it involves casing on exists.
Kevin Buzzard (May 16 2018 at 12:59):
you just introduce another variable
Kevin Buzzard (May 16 2018 at 12:59):
you do all that before you start the simp
Last updated: Dec 20 2023 at 11:08 UTC