Zulip Chat Archive
Stream: maths
Topic: The real numbers
Kevin Buzzard (May 30 2018 at 22:07):
How are our real numbers getting along? Do we have the definition of a differentiable function yet, and of its derivative?
Kenny Lau (May 30 2018 at 22:08):
one thing about analysis is that there are a lot of promises made
Kenny Lau (May 30 2018 at 22:08):
when we say the derivative of a function, we don't just mean the derivative of a function
Kenny Lau (May 30 2018 at 22:08):
we mean that it exists
Kevin Buzzard (May 30 2018 at 22:11):
Do we have that the reals are the unique Dedekind-complete ordered field up to unique isomorphism?
Kenny Lau (May 30 2018 at 22:12):
is R[ε] Dedekind-complete?
Kevin Buzzard (May 30 2018 at 22:12):
I was writing a chapter in my book on reals and I was trying to figure out the interface that a mathematician needed.
Kevin Buzzard (May 30 2018 at 22:13):
I figure we need the uniqueness statement above, and the intermediate value theorem and the mean value theorem
Kevin Buzzard (May 30 2018 at 22:13):
and I reckon we have then got a huge chunk of 1st year Imperial analysis
Andrew Ashworth (May 30 2018 at 22:13):
analysis is tricky, I took a long look at awhile back since I was interested in probability
Kevin Buzzard (May 30 2018 at 22:13):
I could get students working on this over the summer but I don't have a clue about the current state of things and just thought it was easiest to ask
Kenny Lau (May 30 2018 at 22:13):
I already proved the IVT ^^
Kevin Buzzard (May 30 2018 at 22:14):
Where Kenny?
Kenny Lau (May 30 2018 at 22:14):
in my own construction of the real numbers
Kenny Lau (May 30 2018 at 22:14):
https://github.com/kckennylau/Lean/blob/master/cauchy_real.lean#L1508
Andrew Ashworth (May 30 2018 at 22:15):
my plan for attacking it (which I eventually gave up on when I realized is was quite some work) was to follow the isabelle analysis theorems (many of them were written by johannes and jeremy avigad!)
Andrew Ashworth (May 30 2018 at 22:17):
well, you could just ask @Johannes Hölzl for his advice on what analysis developments to work on :)
Kevin Buzzard (May 30 2018 at 22:18):
Kenny did you prove that your real numbers were the unique complete ordered field up to unique isomorphism?
Kenny Lau (May 30 2018 at 22:18):
no
Kevin Buzzard (May 30 2018 at 22:18):
Is it in mathlib?
Kenny Lau (May 30 2018 at 22:18):
no idea
Andrew Ashworth (May 30 2018 at 22:21):
out of curiosity is there a good reference on filters around? I only know about the Cauchy sequence construction, but it seems I must know more to use the reals in mathlib...
Johannes Hölzl (May 30 2018 at 22:21):
@Andrew Ashworth most of Isabelle's analysis developed over some time. Starting from Fleuriot, over porting stuff from HOL Light by Amine Chaieb, and then generalizing it to type classes by Brian Huffman, Fabian Immler and me.
Johannes Hölzl (May 30 2018 at 22:22):
and a lot of other people
Johannes Hölzl (May 30 2018 at 22:22):
@Kevin Buzzard I don't think there is a uniqueness proof in mathlib
Kevin Buzzard (May 30 2018 at 22:24):
@Andrew Ashworth Given a point in a space, you get a "filter" of sets on the space, namely the sets containing the point.
Kevin Buzzard (May 30 2018 at 22:24):
So a filter is kind-of a generalization of a point
Kevin Buzzard (May 30 2018 at 22:24):
it's a really cool way of saying "tends to +infinity" for example
Kevin Buzzard (May 30 2018 at 22:24):
because even though infinity isn't a real number
Johannes Hölzl (May 30 2018 at 22:24):
@Andrew Ashworth do you know our filter paper http://home.in.tum.de/~hoelzl/documents/hoelzl2013typeclasses.pdf ? at least it explains how filters are used in Isabelle.
Kevin Buzzard (May 30 2018 at 22:24):
the sets of reals that contain an open interval (r,infinity) is a filter
Johannes Hölzl (May 30 2018 at 22:25):
- the sets of sets (r, infinite) over all r
Johannes Hölzl (May 30 2018 at 22:26):
the sets of all neighbourhoods around x forms a filter, all left neighbourhoods (and right neibourhoods) etc
Johannes Hölzl (May 30 2018 at 22:29):
but currently you need to do a lot of operations directly with filters, there is a lot of porcelian missing. Porcelain the sense that a lot the nice lemmas to show continuity of a function and using it are just not there yet. Many should be proved in a couple of lines but need to be written down.
Kevin Buzzard (May 30 2018 at 22:30):
Am I right in thinking that @Mario Carneiro @Johannes Hölzl and @Kenny Lau -- that all of you wrote distinct definitions of real numbers recently?
Kevin Buzzard (May 30 2018 at 22:30):
Each one of you should prove the fundamental theorem of real numbers
Kevin Buzzard (May 30 2018 at 22:30):
that you are a Dedekind complete ordered field
Kevin Buzzard (May 30 2018 at 22:31):
and the moment you do that you can access all the theorems proved about the other real numbers
Kevin Buzzard (May 30 2018 at 22:31):
Did you all do that?
Mario Carneiro (May 30 2018 at 22:32):
Uniqueness is overrated
Kevin Buzzard (May 30 2018 at 22:32):
rofl
Kevin Buzzard (May 30 2018 at 22:32):
you people
Kevin Buzzard (May 30 2018 at 22:32):
you don't understand equality
Mario Carneiro (May 30 2018 at 22:32):
It's really not needed for anything practical though
Mario Carneiro (May 30 2018 at 22:32):
in a sense it tells you you "got it right" but that's it
Kevin Buzzard (May 30 2018 at 22:32):
it's needed for clear thinking
Kevin Buzzard (May 30 2018 at 22:33):
and so we have to teach it to computers
Kevin Buzzard (May 30 2018 at 22:33):
it makes the world a simpler place
Mario Carneiro (May 30 2018 at 22:33):
when you want to apply theorems about reals, you need to have theorems on (your) reals
Mario Carneiro (May 30 2018 at 22:33):
a uniqueness statement doesn't help here
Kevin Buzzard (May 30 2018 at 22:34):
I just mean you can port theorems with the uniqueness statement
Mario Carneiro (May 30 2018 at 22:35):
yeah, that's a bad idea, avoid if you can help it
Kevin Buzzard (May 30 2018 at 22:35):
I want to do more than port theorems
Kevin Buzzard (May 30 2018 at 22:35):
I want to identify them as one
Mario Carneiro (May 30 2018 at 22:36):
Better to have a single definition and prove equivalent "views" of it
Kenny Lau (May 30 2018 at 22:36):
uniqueness theorem is a part of interface, because sometimes you would have more than one instance, because it's describing a class of objects (e.g. algebra homomorphism)
Kenny Lau (May 30 2018 at 22:36):
but in this case there is only one object that we call the real numbers
Kevin Buzzard (May 30 2018 at 22:36):
I have so much to learn about the way you guys think about things.
Kenny Lau (May 30 2018 at 22:36):
we won't be constructing other real numbers
Kenny Lau (May 30 2018 at 22:36):
so I don't see why uniqueness is important
Kevin Buzzard (May 30 2018 at 22:37):
What is the point of having three copies of the real numbers?
Kevin Buzzard (May 30 2018 at 22:37):
Is one of them "the best one" or do they all have their merits or what?
Kenny Lau (May 30 2018 at 22:37):
i just did it for myself
Mario Carneiro (May 30 2018 at 22:37):
There's only one I'm aware of, unless Kenny did something
Kenny Lau (May 30 2018 at 22:37):
i did it privately
Mario Carneiro (May 30 2018 at 22:38):
There was an old construction by Johannes and I replaced it with my own
Kevin Buzzard (May 30 2018 at 22:38):
I thought we had a filter one and a cauchy sequence one in mathlib at different times
Kevin Buzzard (May 30 2018 at 22:38):
right
Kevin Buzzard (May 30 2018 at 22:38):
and then Kenny's
Mario Carneiro (May 30 2018 at 22:38):
The filter construction is gone, although the theorems aren't
Kenny Lau (May 30 2018 at 22:38):
rip filter construction 2017-2018
Kevin Buzzard (May 30 2018 at 22:39):
OK so Mario, let's say that in Johannes' construction of real numbers with filters, he proved that the real numbers were a Dedekind complete totally ordered field (he almost certainly did prove this, I believe I remember checking once).
Kevin Buzzard (May 30 2018 at 22:39):
Then isn't that all you will ever need from the real numbers?
Mario Carneiro (May 30 2018 at 22:40):
Yes, and that theorem is still there
Kenny Lau (May 30 2018 at 22:40):
no, you need a way to construct real numbers
Kenny Lau (May 30 2018 at 22:40):
like sqrt(2)
Kenny Lau (May 30 2018 at 22:40):
and filters are hard to work with
Kevin Buzzard (May 30 2018 at 22:40):
but if Johannes had made it to that pinnacle
Kevin Buzzard (May 30 2018 at 22:40):
you would never need to think about filters any more
Kenny Lau (May 30 2018 at 22:40):
how would you make sqrt(2)?
Kevin Buzzard (May 30 2018 at 22:40):
take the sup of the set of real whose square was less than 2
Mario Carneiro (May 30 2018 at 22:41):
My construction just slots in where the old one was, all the theorems still work after porting (with filters and everything)
Kevin Buzzard (May 30 2018 at 22:41):
and then say that you're a complete field
Mario Carneiro (May 30 2018 at 22:41):
The abstract theorems like that exist, but that's still a far cry from the "algebraic" theory with say transcendental functions
Kevin Buzzard (May 30 2018 at 22:42):
Chris did exp and sin and cos
Kevin Buzzard (May 30 2018 at 22:42):
did that ever make it into mathlib?
Kevin Buzzard (May 30 2018 at 22:42):
I need that for October!
Kenny Lau (May 30 2018 at 22:42):
it's still in PR i think
Kevin Buzzard (May 30 2018 at 22:42):
If it needs work, let me know, that would be a great thing for students to work on
Kevin Buzzard (May 30 2018 at 22:43):
I need e^(i theta) = cos(theta) + i sin(theta)
Kenny Lau (May 30 2018 at 22:43):
you're on the wrong thread then
Kevin Buzzard (May 30 2018 at 22:43):
you mentioned R[e] earlier, this is R[i]
Kevin Buzzard (May 30 2018 at 22:51):
https://math.stackexchange.com/questions/269353/isomorphism-of-dedekind-complete-ordered-fields
Kevin Buzzard (May 30 2018 at 22:51):
The quote from Spivak
Kevin Buzzard (May 30 2018 at 22:51):
[not the question itself]
Kevin Buzzard (May 30 2018 at 22:51):
Is that proof, that any two complete ordered fields are isomorphic, in mathlib?
Kenny Lau (May 30 2018 at 22:52):
(removed)
Kevin Buzzard (May 30 2018 at 22:52):
up to unique isomorphism
Kevin Buzzard (May 30 2018 at 22:52):
they are _the same_
Kevin Buzzard (May 30 2018 at 22:52):
they are equal
Kevin Buzzard (May 30 2018 at 22:53):
they are maths-equivalent
Mario Carneiro (May 30 2018 at 22:56):
Having that theorem will just make you more frustrated when it isn't as powerful as you want
Reid Barton (May 30 2018 at 22:58):
Incidentally, in my limited experience, it's better not to work with any particular model of the reals directly, but just axiomatize the features that you need using type classes
Kevin Buzzard (May 30 2018 at 22:59):
Don't prove a single theorem about the reals
Kevin Buzzard (May 30 2018 at 22:59):
just prove a theorem about complete totally ordered fields?
Reid Barton (May 30 2018 at 22:59):
I got frustrated when Lean would keep running out of memory when trying to check stuff like rfl : 2 * 1 = 1 + 1
Reid Barton (May 30 2018 at 23:00):
but then when I switched to working over a general totally ordered discrete topological whatever field, my compile times went way down
Kenny Lau (May 30 2018 at 23:00):
that one is mul_one :P
Kevin Buzzard (May 30 2018 at 23:00):
norm_num ftw
Reid Barton (May 30 2018 at 23:00):
I know, but it's hard to stop Lean from trying to reduce
Kenny Lau (May 30 2018 at 23:00):
2 is defined to be bit0 1, which is defined to be 1+1
Reid Barton (May 30 2018 at 23:00):
It means every time you use simp
or something, you might fall into a memory leak
Mario Carneiro (May 30 2018 at 23:00):
but you still have to reduce (1+1)*1 = 1+1 there
Reid Barton (May 30 2018 at 23:00):
and then you have to back up and carefully walk around it
Reid Barton (May 30 2018 at 23:01):
Sure, and then norm_num
can do that for you
Kenny Lau (May 30 2018 at 23:01):
so I said it's mul_one
Andrew Ashworth (May 30 2018 at 23:01):
I have wondered whether the reals should be a typeclass too, in case somebody wants to have a really efficient computable version at some point in the future
Kevin Buzzard (May 30 2018 at 23:01):
but Kenny what about 2/3*4/5=8/30*2
Kenny Lau (May 30 2018 at 23:01):
but there is no computable version
Mario Carneiro (May 30 2018 at 23:02):
well, the current version is as computable as it gets
Kevin Buzzard (May 30 2018 at 23:02):
I see, so the issue is of course not about proving theorems, it is about doing calculations
Kevin Buzzard (May 30 2018 at 23:02):
computations
Mario Carneiro (May 30 2018 at 23:02):
i.e. stuff like 2 * 3 = 6
computes
Kenny Lau (May 30 2018 at 23:02):
everything is about computation
Kevin Buzzard (May 30 2018 at 23:02):
which are of course important when you want to prove theorems
Kevin Buzzard (May 30 2018 at 23:03):
you want your reals to be "as computable as possible"?
Mario Carneiro (May 30 2018 at 23:03):
well yes
Kevin Buzzard (May 30 2018 at 23:03):
Don't you take one look at a question involving rationals and instantly descend to the rationals?
Kenny Lau (May 30 2018 at 23:03):
then make inv
into a function that takes a proof that it is not zero
Mario Carneiro (May 30 2018 at 23:03):
I did
Andrew Ashworth (May 30 2018 at 23:03):
Kenny, there is such a thing as constructive, computable reals. You can treat it as arbitrary-precision floating point
Mario Carneiro (May 30 2018 at 23:04):
It's called divp
Kevin Buzzard (May 30 2018 at 23:04):
and does it work on an arbitrary complete totally ordered field?
Mario Carneiro (May 30 2018 at 23:04):
It works on any ring
Kenny Lau (May 30 2018 at 23:04):
you won't want to formalize computable reals
Andrew Ashworth (May 30 2018 at 23:05):
you won't want to, but yet it'll be super useful
Kenny Lau (May 30 2018 at 23:06):
are you going to set up turing machines now
Mario Carneiro (May 30 2018 at 23:07):
lol I'm actually typing out turing machines right now
Mario Carneiro (May 30 2018 at 23:07):
Actually I'm going via Wang B-machines
Kevin Buzzard (May 31 2018 at 00:04):
Lean challenge :
Kenny Lau (May 31 2018 at 00:10):
import data.real.basic tactic.norm_num prefix `√`:90 := real.sqrt example : (√2 + √3)^2 = 5 + 2*√6 := by rw [pow_two, add_mul_self_eq, mul_assoc, ← real.sqrt_mul, ← real.sqrt_mul, ← real.sqrt_mul, real.sqrt_mul_self, real.sqrt_mul_self]; norm_num; rw [← add_assoc]; refl
Kenny Lau (May 31 2018 at 00:14):
import data.real.basic tactic.norm_num prefix `√`:90 := real.sqrt example : (√2 + √3)^2 = 5 + 2*√6 := by rw [pow_two, add_mul_self_eq, mul_assoc, ← real.sqrt_mul, ← real.sqrt_mul, ← real.sqrt_mul, real.sqrt_mul_self, real.sqrt_mul_self, add_right_comm]; norm_num
Kevin Buzzard (May 31 2018 at 02:28):
Thanks Kenny.
Kevin Buzzard (May 31 2018 at 02:29):
In data/real/basic.lean
there is an import of algebra.big_operators
which doesn't seem to me to be used. Is this sort of PR welcome?
Kevin Buzzard (May 31 2018 at 03:02):
Kevin Buzzard (May 31 2018 at 03:03):
At that line, #check mk
gives that mk
is rat.mk
. And then on the next line it feels like it was redefined. Why is mk not overloaded now?
Kevin Buzzard (May 31 2018 at 03:03):
Is there some priority trick?
Mario Carneiro (May 31 2018 at 03:08):
mk
is overloaded at that point. But when one of the theorems with that name is in the current namespace (i.e. inside a namespace
block), it takes precedence over other open
namespaces.
Kevin Buzzard (May 31 2018 at 03:09):
I see. Thanks.
Kevin Buzzard (May 31 2018 at 03:09):
instance : has_add ℝ := ⟨λ x y, quotient.lift_on₂ x y (λ f g, mk (f + g)) $ λ f₁ g₁ f₂ g₂ hf hg, quotient.sound $ by simpa [(≈), setoid.r] using add_lim_zero hf hg⟩
Kevin Buzzard (May 31 2018 at 03:09):
and then
Kevin Buzzard (May 31 2018 at 03:09):
instance : has_neg ℝ := ⟨λ x, quotient.lift_on x (λ f, mk (-f)) $ λ f₁ f₂ hf, quotient.sound $ by simpa [(≈), setoid.r] using neg_lim_zero hf⟩
Kevin Buzzard (May 31 2018 at 03:09):
That's the same code again!
Mario Carneiro (May 31 2018 at 03:10):
sure is, less than 30 seconds copy paste work
Kevin Buzzard (May 31 2018 at 03:10):
That should be by math_trivial [add_lim_zero]
Kevin Buzzard (May 31 2018 at 03:10):
and then by math_trivial [neg_lim_zero]
Mario Carneiro (May 31 2018 at 03:10):
like I said, ~20 times repetition before I even consider making a tactic
Mario Carneiro (May 31 2018 at 03:11):
6 or 7 times is not enough
Kevin Buzzard (May 31 2018 at 03:11):
but if someone just came along and made that tactic and offered it to mathlib, do you think it would be useful?
Kevin Buzzard (May 31 2018 at 03:11):
I am seeing this ... idiom or whatever you call it over and over again
Kevin Buzzard (May 31 2018 at 03:11):
"we laboriously transport structure"
Mario Carneiro (May 31 2018 at 03:11):
in particular, it is often the case that all the axioms of concrete structure X are similar to each other, but not similar to structure Y
Mario Carneiro (May 31 2018 at 03:12):
having a tactic that proves axioms of X is not that helpful since there are only O(1) of them, and the tactic won't help with Y
Kevin Buzzard (May 31 2018 at 03:13):
Transport of structure is a central idea of mathematics as we see in the work of Grothendieck and Deligne
Mario Carneiro (May 31 2018 at 03:13):
Would this math_trivial
tactic apply equally to real
and pnat
?
Kevin Buzzard (May 31 2018 at 03:13):
This is just the sort of thing I want to find out
Kevin Buzzard (May 31 2018 at 03:13):
I found myself when doing schemes
Kevin Buzzard (May 31 2018 at 03:13):
wanting a tactic like this
Kevin Buzzard (May 31 2018 at 03:13):
and I know that when I start perfectoids
Kevin Buzzard (May 31 2018 at 03:13):
I'll find it again
Mario Carneiro (May 31 2018 at 03:14):
My point is that there are not that many similarities between the proof that pnat
has an add and real
does
Kevin Buzzard (May 31 2018 at 03:14):
yeah isn't that interesting
Kenny Lau (May 31 2018 at 03:14):
lol
Kenny Lau (May 31 2018 at 03:14):
Kevin
Kenny Lau (May 31 2018 at 03:14):
the sky is blue
Kevin Buzzard (May 31 2018 at 03:15):
These guys need to make a proper mathematician
Kevin Buzzard (May 31 2018 at 03:15):
with the right kind of equals
Kenny Lau (May 31 2018 at 03:16):
it's foggy
Kenny Lau (May 31 2018 at 03:16):
relative humidity 98%
Kevin Buzzard (May 31 2018 at 03:19):
/- Extra instances to short-circuit type class resolution -/ instance : semigroup ℝ := by apply_instance instance : monoid ℝ := by apply_instance instance : comm_semigroup ℝ := by apply_instance instance : comm_monoid ℝ := by apply_instance instance : add_monoid ℝ := by apply_instance instance : add_group ℝ := by apply_instance instance : add_comm_group ℝ := by apply_instance instance : ring ℝ := by apply_instance
Kevin Buzzard (May 31 2018 at 03:19):
Why do they make life better?
Kevin Buzzard (May 31 2018 at 03:19):
This is all in data/real/basic.lean
Kenny Lau (May 31 2018 at 03:19):
because beneath you is an uncomputable instance
Kevin Buzzard (May 31 2018 at 03:19):
those are the best kind IMO
Kenny Lau (May 31 2018 at 03:19):
if you don't do this, the uncomputable instance will be used
Kenny Lau (May 31 2018 at 03:20):
so your definitions would have to be noncomputable
Kenny Lau (May 31 2018 at 03:20):
and it is used because it is declared the latest
Kevin Buzzard (May 31 2018 at 03:20):
none of this makes any sense to me
Mario Carneiro (May 31 2018 at 03:20):
no, that's not related
Mario Carneiro (May 31 2018 at 03:20):
those instances
short-circuit type class resolution
Kevin Buzzard (May 31 2018 at 03:20):
so they are creating new paths in the system
Kenny Lau (May 31 2018 at 03:20):
well in my construction, if I don't do that, my things become uncomputable
Kevin Buzzard (May 31 2018 at 03:20):
which are defeq to longer paths
Mario Carneiro (May 31 2018 at 03:20):
yes
Kevin Buzzard (May 31 2018 at 03:21):
and this is perhaps making the system better for some reason
Kevin Buzzard (May 31 2018 at 03:21):
why doesn't the system run all those commands every time anyone makes anything a comm_ring?
Mario Carneiro (May 31 2018 at 03:21):
it means less time traversing the instance graph
Kevin Buzzard (May 31 2018 at 03:21):
then it would be much less time
Mario Carneiro (May 31 2018 at 03:22):
because that wouldn't save any time, it would just create lots of space
Kevin Buzzard (May 31 2018 at 03:22):
instance : has_lt ℝ := ⟨λ x y, quotient.lift_on₂ x y (<) $ λ f₁ g₁ f₂ g₂ hf hg, propext $ ⟨λ h, lt_of_eq_of_lt (setoid.symm hf) (lt_of_lt_of_eq h hg), λ h, lt_of_eq_of_lt hf (lt_of_lt_of_eq h (setoid.symm hg))⟩⟩
Kevin Buzzard (May 31 2018 at 03:22):
They're getting quite tricky for my tactic now
Mario Carneiro (May 31 2018 at 03:22):
If you do it in every case, there is no advantage over just searching the graph, since you have just precalculated all paths
Kevin Buzzard (May 31 2018 at 03:23):
ha ha
Mario Carneiro (May 31 2018 at 03:23):
the point is that I know that real
is important and people want to use it lots
Mario Carneiro (May 31 2018 at 03:23):
so I set up the system to make that easier
Kevin Buzzard (May 31 2018 at 03:24):
What else can you control within the type class inference system?
Mario Carneiro (May 31 2018 at 03:24):
so that when weirdos state ring
theorems over the reals for some reason, it's not horribly slow
Kevin Buzzard (May 31 2018 at 03:24):
I liked @Reid Barton 's comment about typeclasses.
Kevin Buzzard (May 31 2018 at 03:25):
--def real := quotient (@cau_seq.equiv ℚ _ _ _ abs _) -- orig def real := quotient (cau_seq.equiv : setoid (cau_seq ℚ abs)) -- clearer for me
Kevin Buzzard (May 31 2018 at 03:25):
You prefer yours?
Kevin Buzzard (May 31 2018 at 03:26):
@
and _
are a bit ugly maybe
Kevin Buzzard (May 31 2018 at 03:26):
but yours is shorter
Mario Carneiro (May 31 2018 at 03:28):
def real := @quotient (cau_seq ℚ abs) cau_seq.equiv
Kevin Buzzard (May 31 2018 at 03:45):
What is your preference? The mathlib one?
Mario Carneiro (May 31 2018 at 03:45):
I don't have a strong preference
Kevin Buzzard (May 31 2018 at 03:45):
In terms of Lean they're all presumably defeq
Kevin Buzzard (May 31 2018 at 03:46):
but in terms of readability some have more worth than others
Mario Carneiro (May 31 2018 at 03:46):
they are all syntactically equal
Kevin Buzzard (May 31 2018 at 03:47):
My favourite is the last one @quotient (cau_seq ℚ abs) cau_seq.equiv
because it's the most readable to mathematicians
Kevin Buzzard (May 31 2018 at 03:48):
instance : has_le ℝ := ⟨λ x y, x < y ∨ x = y⟩
Kevin Buzzard (May 31 2018 at 03:48):
You've gone the wrong way
Kevin Buzzard (May 31 2018 at 03:48):
you can do has_le
first and get has_lt
for free!
Mario Carneiro (May 31 2018 at 03:48):
I know
Kevin Buzzard (May 31 2018 at 03:49):
You did it this way for a reason, presumably?
Mario Carneiro (May 31 2018 at 03:49):
the constructively natural one is lt
Kevin Buzzard (May 31 2018 at 03:49):
I see
Kevin Buzzard (May 31 2018 at 03:49):
it's all about computing
Mario Carneiro (May 31 2018 at 03:49):
it states that there is some epsilon separating them
Mario Carneiro (May 31 2018 at 03:50):
for le, it's either the negation of that or the disjunction with equals
Patrick Massot (May 31 2018 at 07:06):
that you are a Dedekind complete ordered field
Note: as a mathematician, I use real numbers every day, and I have no idea what is a "Dedekind complete ordered field"
Patrick Massot (May 31 2018 at 07:08):
How are our real numbers getting along? Do we have the definition of a differentiable function yet, and of its derivative?
I have a definition of a function from a real normed vector space to another one which is differentiable at a point. But I don't have a normed space structure on ℝ^n because I'm swamped in type class resolution issues (https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/tc.20loop.20again). Life is really hard here.
Kevin Buzzard (May 31 2018 at 23:09):
boggle I am typing up my exam into Lean and I need the fact that the decimal expansion of the real number 0.71 contains no 8's :-)
Kevin Buzzard (May 31 2018 at 23:09):
does Lean have decimal expansions??
Kevin Buzzard (May 31 2018 at 23:10):
maybe a function from the non-negative reals to (functions from nat to nat)
Kevin Buzzard (May 31 2018 at 23:10):
with f(succ n)<=9
Kenny Lau (May 31 2018 at 23:11):
you can write that yourself
Kenny Lau (May 31 2018 at 23:11):
it's quite explicit using floor
Kevin Buzzard (May 31 2018 at 23:11):
you are right!
Kenny Lau (May 31 2018 at 23:11):
given a real number r
Kevin Buzzard (May 31 2018 at 23:11):
But I was just asking if someone had already written it
Kevin Buzzard (May 31 2018 at 23:11):
Kenny I can do it :-)
Kevin Buzzard (May 31 2018 at 23:11):
I even lecture it in M1F some years
Kevin Buzzard (May 31 2018 at 23:11):
Darn it
Kevin Buzzard (May 31 2018 at 23:11):
if I'd lectured it this year then @Chris Hughes would have done it :-)
Kevin Buzzard (May 31 2018 at 23:48):
import analysis.real -- should come with a warning noncomputable definition real.floor (x : ℝ) : ℤ := classical.some (real.exists_floor x) noncomputable definition expansion (r : ℝ) (H : r ≥ 0) : ℕ → ℕ | 0 := real.floor r | (n + 1) := 7
Kevin Buzzard (May 31 2018 at 23:48):
I made a slip: real.floor r on the last but one line is an int not a nat
Kenny Lau (May 31 2018 at 23:48):
Kevin
Kenny Lau (May 31 2018 at 23:48):
the fllor is there already
Kevin Buzzard (May 31 2018 at 23:48):
but when using reals, sllips like this bring the system to its knees. 100% CPU usage, orange bars
Kenny Lau (May 31 2018 at 23:48):
it's in archimedean
Kevin Buzzard (May 31 2018 at 23:49):
Thanks
Kevin Buzzard (May 31 2018 at 23:49):
but why does my code make Lean have a deterministic timeout?
Kevin Buzzard (May 31 2018 at 23:49):
Mario has answered this before
Kevin Buzzard (May 31 2018 at 23:50):
but this behaviour ("use the imported definitions wisely or there will be timeouts") is not the norm
Kenny Lau (May 31 2018 at 23:50):
it's just a typeclass fallout
Kevin Buzzard (May 31 2018 at 23:50):
right
Kevin Buzzard (May 31 2018 at 23:50):
but is this a design problem with Lean or something which can be fixed in mathlib or what?
Kenny Lau (May 31 2018 at 23:51):
no idea
Kevin Buzzard (May 31 2018 at 23:52):
hey that floor_ring stuff is a really cool way of doing it :-)
Kevin Buzzard (May 31 2018 at 23:56):
⌊10 / 3⌋ : ℤ
Kevin Buzzard (May 31 2018 at 23:57):
#reduce ⌊(real.sqrt 2 : ℝ)⌋
Kevin Buzzard (May 31 2018 at 23:57):
100% CPU usage!
Mario Carneiro (May 31 2018 at 23:57):
For some reason, coercing an int to a nat causes a typeclass overflow
Kevin Buzzard (May 31 2018 at 23:58):
segv :-)
Mario Carneiro (May 31 2018 at 23:58):
I've seen this many times before
Kevin Buzzard (May 31 2018 at 23:58):
but it's only with reals
Kevin Buzzard (May 31 2018 at 23:58):
Lean is really good with most structures
Kevin Buzzard (May 31 2018 at 23:58):
Oh indpt of reals?
Mario Carneiro (May 31 2018 at 23:59):
you defined an int function and applied it to get a nat
Kevin Buzzard (May 31 2018 at 23:59):
I know
Kevin Buzzard (Jun 01 2018 at 00:00):
I assumed the problem was because reals always time out
Kevin Buzzard (Jun 01 2018 at 00:00):
but maybe you fixed that
Kevin Buzzard (Jun 01 2018 at 00:00):
and this is an independent timeout
Mario Carneiro (Jun 01 2018 at 00:00):
The major source of that was fixed a while ago
Mario Carneiro (Jun 01 2018 at 00:00):
this is just Z -> N timeout
Kevin Buzzard (Jun 01 2018 at 00:00):
What do you get with
Kevin Buzzard (Jun 01 2018 at 00:00):
#reduce ⌊(real.sqrt 2 : ℝ)⌋
?
Mario Carneiro (Jun 01 2018 at 00:01):
something horrible, don't do that
Mario Carneiro (Jun 01 2018 at 00:01):
What part of noncomputable
don't you understand?
Kevin Buzzard (Jun 01 2018 at 00:01):
:-)
Kevin Buzzard (Jun 01 2018 at 00:01):
I thought there was no harm trying
Mario Carneiro (Jun 01 2018 at 00:01):
it will be some huge stuck term depending on classical.choice
Kevin Buzzard (Jun 01 2018 at 00:02):
after all, schoolkid can do it
Kevin Buzzard (Jun 01 2018 at 00:02):
it's 1 Mario
Mario Carneiro (Jun 01 2018 at 00:02):
You can do it, but not like this
Mario Carneiro (Jun 01 2018 at 00:02):
In order for reduce
to work it has to be true generally
Kevin Buzzard (Jun 01 2018 at 00:02):
this is going to be tough to explain to the mathematicians
Kevin Buzzard (Jun 01 2018 at 00:02):
I'm just being daft, I know about eval
Mario Carneiro (Jun 01 2018 at 00:02):
and there are messy terms you can give where it's impossible to decide
Mario Carneiro (Jun 01 2018 at 00:03):
#eval
won't do any better
Kevin Buzzard (Jun 01 2018 at 00:03):
no but it could
Mario Carneiro (Jun 01 2018 at 00:03):
actually it will just complain up front
Mario Carneiro (Jun 01 2018 at 00:03):
no it can't, real.floor
is necessarily noncomputable
Kevin Buzzard (Jun 01 2018 at 00:03):
the reduce gives me a segv (twice now)
Mario Carneiro (Jun 01 2018 at 00:04):
What can do better is norm_num
style tactics that prove specific instances of this in some subset of the full language of lean
Kevin Buzzard (Jun 01 2018 at 00:04):
but the floor of the square root of 2 isn't noncomputable
Mario Carneiro (Jun 01 2018 at 00:04):
That statement doesn't make sense
Mario Carneiro (Jun 01 2018 at 00:05):
noncomputability is a property of a term, not its denotation
Kenny Lau (Jun 01 2018 at 00:05):
@Kevin Buzzard local computability does not patch to give global computability
Kenny Lau (Jun 01 2018 at 00:05):
it ain't no sheaf
Kevin Buzzard (Jun 01 2018 at 00:05):
is the obstruction finite?
Mario Carneiro (Jun 01 2018 at 00:05):
?
Kenny Lau (Jun 01 2018 at 00:05):
floor is computable iff halting problem can be solved
Kenny Lau (Jun 01 2018 at 00:05):
you have an obstructio in each integer, so no it ain't finite
Kevin Buzzard (Jun 01 2018 at 00:05):
I know but you can do it on sqrt(2)
Kevin Buzzard (Jun 01 2018 at 00:05):
I can prove that 1 is floor of sqrt(2)
Mario Carneiro (Jun 01 2018 at 00:06):
So do that
Kenny Lau (Jun 01 2018 at 00:06):
that doesn't mean you can compute floor(sqrt(2))
Kevin Buzzard (Jun 01 2018 at 00:06):
so it can be computed in this case
Kevin Buzzard (Jun 01 2018 at 00:06):
Kenny -- doesn't it?
Mario Carneiro (Jun 01 2018 at 00:06):
floor (sqrt 2)
is a computable number, yes
Mario Carneiro (Jun 01 2018 at 00:06):
but floor
is not a computable function
Mario Carneiro (Jun 01 2018 at 00:07):
so you can't just plug sqrt 2
into floor
and expect an answer
Kenny Lau (Jun 01 2018 at 00:07):
you need uniform computability without creativeness
Kenny Lau (Jun 01 2018 at 00:07):
informally
Kenny Lau (Jun 01 2018 at 00:07):
you need a canonical function
Kevin Buzzard (Jun 01 2018 at 00:07):
We could get transcendental numbers into Lean if we could get Chris' sin and cos stuff
Kenny Lau (Jun 01 2018 at 00:07):
that works across everything
Kevin Buzzard (Jun 01 2018 at 00:08):
floor is daft. Give me exp any day
Kevin Buzzard (Jun 01 2018 at 00:08):
Is that computable?
Mario Carneiro (Jun 01 2018 at 00:08):
By the way, floor is computable on algebraic numbers
Kevin Buzzard (Jun 01 2018 at 00:08):
I reckon I can prove the sequence is Cauchy
Kenny Lau (Jun 01 2018 at 00:09):
everything is computable on algebraic numbers
Mario Carneiro (Jun 01 2018 at 00:09):
so you can write floor (sqrt 2)
and compute to 1
Kenny Lau (Jun 01 2018 at 00:09):
surprise
Mario Carneiro (Jun 01 2018 at 00:09):
exp
is computable
Kevin Buzzard (Jun 01 2018 at 00:09):
Kenny I'm sure there are non-recursive or whatever subsets of the natural numbers
Kenny Lau (Jun 01 2018 at 00:10):
I was uttering hyperbole
Kevin Buzzard (Jun 01 2018 at 00:10):
and so of the algebraic numbers
Mario Carneiro (Jun 01 2018 at 00:10):
I think real numbers are overrated in math
Kenny Lau (Jun 01 2018 at 00:10):
agree
Kevin Buzzard (Jun 01 2018 at 00:10):
They're just some random completion
Kenny Lau (Jun 01 2018 at 00:10):
I was about to say, let's study other local fields
Kevin Buzzard (Jun 01 2018 at 00:10):
that sometimes helps in physics
Kevin Buzzard (Jun 01 2018 at 00:10):
exactly
Mario Carneiro (Jun 01 2018 at 00:10):
you don't need full completion in 99.9% of cases
Kenny Lau (Jun 01 2018 at 00:11):
but there's a problem @Mario Carneiro
Kevin Buzzard (Jun 01 2018 at 00:11):
in number theory we need the product of all the completions :-)
Mario Carneiro (Jun 01 2018 at 00:11):
something like complete under computable sequences is more than enough
Kevin Buzzard (Jun 01 2018 at 00:12):
Mario do you think Langlands' work on cyclic base change would work with this smaller subset of the reals?
Mario Carneiro (Jun 01 2018 at 00:12):
or maybe "complete under all the operations I'm talking about today"
Kevin Buzzard (Jun 01 2018 at 00:12):
I'm sure it uses AC everywhere
Kenny Lau (Jun 01 2018 at 00:12):
I can't recall the name of the theroem
Mario Carneiro (Jun 01 2018 at 00:12):
it's not so different to doing categories in ZFC
Kenny Lau (Jun 01 2018 at 00:12):
but essentially, if you include exp, then your field is noncomputable
Kenny Lau (Jun 01 2018 at 00:12):
algebraic numbers and exp
Kenny Lau (Jun 01 2018 at 00:12):
maybe some other things
Kenny Lau (Jun 01 2018 at 00:12):
maybe you'll know the name
Mario Carneiro (Jun 01 2018 at 00:12):
you just want enough stuff for your theorem, but you assume too much for simplicity
Mario Carneiro (Jun 01 2018 at 00:15):
@Kenny Lau I guess it would be too easy to just compute to find out if e + pi is irrational
Kenny Lau (Jun 01 2018 at 00:15):
that's irrelevant
Kenny Lau (Jun 01 2018 at 00:16):
for every rational r, if you spent enough time, you can prove that e+pi is not r
Kenny Lau (Jun 01 2018 at 00:16):
you just can't prove that, for every rational r, e+pi is not r
Kenny Lau (Jun 01 2018 at 00:16):
decidable equality doesn't mean decidable pi equality
Kenny Lau (Jun 01 2018 at 00:16):
pi equality meaning forall equality
Kenny Lau (Jun 01 2018 at 00:16):
not 3.14159
Mario Carneiro (Jun 01 2018 at 00:16):
I know, but rationality is decidable on algebraic numbers
Kenny Lau (Jun 01 2018 at 00:16):
oh is it
Kenny Lau (Jun 01 2018 at 00:16):
how do you define algebraic numbers?
Mario Carneiro (Jun 01 2018 at 00:17):
yes, just compute the minimal polynomial and see if it has degree 1
Kenny Lau (Jun 01 2018 at 00:17):
do you store the minimal polynomial?
Mario Carneiro (Jun 01 2018 at 00:17):
yes
Kenny Lau (Jun 01 2018 at 00:17):
I see
Mario Carneiro (Jun 01 2018 at 00:18):
I think the most impressive thing about the algebraic numbers is that irreducibility and factoring of Q[x] polynomials is decidable
Kenny Lau (Jun 01 2018 at 00:19):
agree
Kevin Buzzard (Jun 01 2018 at 00:33):
come on norm-num
Kevin Buzzard (Jun 01 2018 at 00:33):
↑⌊0⌋ * 10 = 0
Kevin Buzzard (Jun 01 2018 at 00:33):
you can do it
Kevin Buzzard (Jun 01 2018 at 00:33):
gaargh
Kevin Buzzard (Jun 01 2018 at 00:34):
stupid floor function
Kevin Buzzard (Jun 01 2018 at 00:34):
oh there is a lemma
Kevin Buzzard (Jun 01 2018 at 00:34):
I remember now
Kevin Buzzard (Jun 01 2018 at 00:34):
floor_coe
Mario Carneiro (Jun 01 2018 at 00:35):
I guess floor_zero and floor_one should be simp lemmas
Mario Carneiro (Jun 01 2018 at 00:35):
and theorems
Kevin Buzzard (Jun 01 2018 at 00:37):
oh you're right, that's not (0 : Z)
Kevin Buzzard (Jun 01 2018 at 00:37):
that one of your other zeros
Mario Carneiro (Jun 01 2018 at 00:38):
it's defeq though, you can just apply floor_coe
Kevin Buzzard (Jun 01 2018 at 00:48):
not in a rewrite :-/
Mario Carneiro (Jun 01 2018 at 00:49):
here, use as you like:
@[simp] theorem floor_zero : ⌊(0:α)⌋ = 0 := floor_coe 0 @[simp] theorem floor_one : ⌊(1:α)⌋ = 1 := by rw [← int.cast_one, floor_coe]
Kenny Lau (Jun 01 2018 at 00:49):
that one of your other zeros
lol
Mario Carneiro (Jun 01 2018 at 00:50):
unfortunately this doesn't help with say ⌊2⌋ = 2
, that gets tricky in general
Mario Carneiro (Jun 01 2018 at 00:50):
because the two 2
's are represented differently
Kevin Buzzard (Jun 01 2018 at 00:51):
I've got interested in what needs names
Kevin Buzzard (Jun 01 2018 at 00:51):
I would vote for floor_zero
Kevin Buzzard (Jun 01 2018 at 00:52):
rofl I just tried it in my code and it didn't work
Kevin Buzzard (Jun 01 2018 at 00:52):
and then I remembered that someone writing some code on the internet doesn't mean my computer runs it
Kevin Buzzard (Jun 01 2018 at 00:52):
and you have to copy paste
Mario Carneiro (Jun 01 2018 at 00:53):
Those lines were written in archimedean.lean
, they might not work out of context
Kevin Buzzard (Jun 01 2018 at 00:55):
I know archimedean.lean so I could fix it up
Kevin Buzzard (Jun 01 2018 at 00:55):
I've been reading some of the real code recently
Kevin Buzzard (Jun 01 2018 at 00:55):
and I'd missed archimedean so I read it the moment Kenny pointed it out to me
Mario Carneiro (Jun 01 2018 at 00:56):
I already have added those lines to my local copy, they will be out with the next batch
Kevin Buzzard (Jun 01 2018 at 00:56):
I was just thinking I should do the same
Kevin Buzzard (Jun 01 2018 at 00:56):
but for me it's much harder
Kevin Buzzard (Jun 01 2018 at 00:56):
I'm doing undergrad stuff in my xena project at the minute (e.g. decimal expansions) but the library imports your mathlib
Kevin Buzzard (Jun 01 2018 at 00:57):
so I can't edit my fork of your mathlib and then run it easily in my project, unless I actually start importing my mathlib
Kevin Buzzard (Jun 01 2018 at 01:22):
ha ha, to finish Q2 of my exam all I now need to do is to prove that if s : ℝ := 71/100
then ⌊s⌋ = 7
Kevin Buzzard (Jun 01 2018 at 01:22):
the students didn't spend too much time on this bit
Kenny Lau (Jun 01 2018 at 01:23):
does that mean you finished Q1?
Mario Carneiro (Jun 01 2018 at 01:24):
I guess this isn't stated as a theorem explicitly, but the way to prove ⌊x⌋ = n
is to prove n <= x < n+1
, and norm_num will usually take care of that
Kevin Buzzard (Jun 01 2018 at 01:24):
no
Kevin Buzzard (Jun 01 2018 at 01:24):
I liked Q2 better
Kevin Buzzard (Jun 01 2018 at 01:24):
right
Mario Carneiro (Jun 01 2018 at 01:25):
also, the theorem you stated is false
Mario Carneiro (Jun 01 2018 at 01:25):
the floor of s is zero
Kevin Buzzard (Jun 01 2018 at 01:25):
:-)
Kevin Buzzard (Jun 01 2018 at 01:25):
oh too many 10s
Kevin Buzzard (Jun 01 2018 at 01:25):
sorry
Kevin Buzzard (Jun 01 2018 at 01:25):
I have to work out the full decimal expansion
Kevin Buzzard (Jun 01 2018 at 01:26):
so i need a fair few floors
Mario Carneiro (Jun 01 2018 at 01:26):
You really want to do this on rat
Mario Carneiro (Jun 01 2018 at 01:26):
then you can just compute
Mario Carneiro (Jun 01 2018 at 01:26):
just take your real number and map it to rat
Kevin Buzzard (Jun 01 2018 at 01:28):
I didn't know to what extent that mattered
Kevin Buzzard (Jun 01 2018 at 01:28):
now I need some theorem that says that the floors agree
Kevin Buzzard (Jun 01 2018 at 01:29):
noncomputable definition s : ℝ := 71/100
lemma bound1 : 0 ≤ s := by norm_num -- fails
:-(
Mario Carneiro (Jun 01 2018 at 01:29):
I am already on it
Kenny Lau (Jun 01 2018 at 01:29):
by unfold s; norm_num
Kevin Buzzard (Jun 01 2018 at 01:29):
thanks
Mario Carneiro (Jun 01 2018 at 01:53):
this should work for you:
@[simp] theorem rat.cast_floor {α} [linear_ordered_field α] [archimedean α] (x : ℚ) : by haveI := archimedean.floor_ring α; exact ⌊(x:α)⌋ = ⌊x⌋ := begin haveI := archimedean.floor_ring α, apply le_antisymm, { rw [le_floor, ← @rat.cast_le α, rat.cast_coe_int], apply floor_le }, { rw [le_floor, ← rat.cast_coe_int, rat.cast_le], apply floor_le } end
Kevin Buzzard (Jun 01 2018 at 01:57):
you have to use haveI
in the statement to make it typecheck
Mario Carneiro (Jun 01 2018 at 01:57):
I did...
Kevin Buzzard (Jun 01 2018 at 01:57):
and then again in the proof
Kevin Buzzard (Jun 01 2018 at 01:57):
The devs don't come here, this is the maths chat
Kevin Buzzard (Jun 01 2018 at 01:57):
what do you think about all this haveI stuff?
Kevin Buzzard (Jun 01 2018 at 01:58):
Aren't things worse than they used to be?
Kevin Buzzard (Jun 01 2018 at 01:58):
Or did other stuff get fixed when that change was made?
Mario Carneiro (Jun 01 2018 at 01:58):
I think I got Leo angry about it, so I'm not going to try again
Mario Carneiro (Jun 01 2018 at 01:58):
haveI is the compromise position
Mario Carneiro (Jun 01 2018 at 01:58):
...but it's not unreasonable here
Mario Carneiro (Jun 01 2018 at 01:59):
I'm injecting an instance which is not an instance normally
Kevin Buzzard (Jun 01 2018 at 02:01):
Thanks.
Kevin Buzzard (Jun 01 2018 at 02:11):
I feel like I want to apply int.succ_le_of_lt
out of decency
Kevin Buzzard (Jun 01 2018 at 02:11):
lemma int.succ_le_of_lt (a b : ℤ) : a < b → int.succ a ≤ b :=
Kevin Buzzard (Jun 01 2018 at 02:11):
but proof is id
Mario Carneiro (Jun 01 2018 at 02:11):
It's up to you
Kevin Buzzard (Jun 01 2018 at 02:12):
it looks like bad style to just know it's id
Kenny Lau (Jun 01 2018 at 02:12):
who the .... cares
Kevin Buzzard (Jun 01 2018 at 02:12):
it's the interface Kenny
Kenny Lau (Jun 01 2018 at 02:12):
proofs are irrelevant
Kevin Buzzard (Jun 01 2018 at 02:12):
id sometimes deserves a name :-)
Kevin Buzzard (Jun 01 2018 at 02:12):
proofs are irrelevant but names are important
Mario Carneiro (Jun 01 2018 at 02:13):
You are absolutely right, using defeq like this breaks the interface
Mario Carneiro (Jun 01 2018 at 02:13):
but it's not a hill I want to die on
Mario Carneiro (Jun 01 2018 at 02:13):
I would say "use in moderation"
Kevin Buzzard (Jun 01 2018 at 02:27):
lemma floor_of_bounds (r : α) (z : ℤ) : ↑z ≤ r ∧ r < (z + 1) ↔ ⌊ r ⌋ = z := begin split,swap, -- easy one { intro H,rw ←H, split,exact floor_le r, suffices : r < ↑⌊r⌋ + (1 : ℤ), simpa using this, have H' := lt_succ_floor r, rw ←int.cast_add, exact H', }, have H := λ d, @le_floor α _ d r, intro J,cases J with floor_le' lt_succ_floor', cases (le_or_gt ⌊r⌋ z) with HT HF, swap, exfalso, -- false one { have XXX := (H (z+1)).1 (int.succ_le_of_lt _ _ HF), rw int.cast_add at XXX, clear HF, have H2 := lt_of_le_of_lt XXX lt_succ_floor', revert H2,simp, }, cases lt_or_eq_of_le HT with HF HT',swap,exact HT', exfalso, have XXX := (H z).2 floor_le', apply lt_irrefl z, exact lt_of_le_of_lt XXX HF, end
Kevin Buzzard (Jun 01 2018 at 02:27):
Rubbish lean code but it's a proof
Kevin Buzzard (Jun 01 2018 at 02:27):
What tricks am I missing?
Kenny Lau (Jun 01 2018 at 02:30):
le_floor
?
Kenny Lau (Jun 01 2018 at 02:30):
given z <= r
, use le_floor
to deduce z <= floor(r)
Kevin Buzzard (Jun 01 2018 at 02:31):
here's the reals back to their old tricks
Kenny Lau (Jun 01 2018 at 02:32):
given r < z+1
, floor_lt
tells you floor(r) < z + 1
Kenny Lau (Jun 01 2018 at 02:32):
then deduce floor(r) <= z
(everything is an integer now)
Kenny Lau (Jun 01 2018 at 02:32):
and then le_antisymm
Kevin Buzzard (Jun 01 2018 at 02:33):
noncomputable definition s : ℝ := 71/100 example : floor s = 0 := begin show floor ((71/100:ℚ):ℝ) = 0, admit end
Kevin Buzzard (Jun 01 2018 at 02:33):
deterministic timeout
Kenny Lau (Jun 01 2018 at 02:33):
because 71:R / 100:R is not defeq to 71:Q / 100:Q
Kevin Buzzard (Jun 01 2018 at 02:34):
I did it by contradiction :-)
Kevin Buzzard (Jun 01 2018 at 02:34):
you always want to do things constructively
Kenny Lau (Jun 01 2018 at 02:34):
?
Kenny Lau (Jun 01 2018 at 02:34):
I see
Kenny Lau (Jun 01 2018 at 02:34):
to each their own
Kenny Lau (Jun 01 2018 at 02:34):
I have no time
Kenny Lau (Jun 01 2018 at 02:34):
I need to learn what the Weil group is
Kevin Buzzard (Jun 01 2018 at 02:34):
oh the coercion to R is done before the division
Mario Carneiro (Jun 01 2018 at 02:35):
The magic of biconditional theorems...
lemma floor_of_bounds (r : α) (z : ℤ) : ↑z ≤ r ∧ r < (z + 1) ↔ ⌊ r ⌋ = z := by rw [← le_floor, ← int.cast_one, ← int.cast_add, ← floor_lt, int.lt_add_one_iff, le_antisymm_iff, and.comm]
Kenny Lau (Jun 01 2018 at 02:35):
lol
Kenny Lau (Jun 01 2018 at 02:35):
two lines vs 100 lines
Kevin Buzzard (Jun 01 2018 at 02:35):
very nice
Kevin Buzzard (Jun 01 2018 at 02:35):
but I never got stuck
Kevin Buzzard (Jun 01 2018 at 02:35):
I just proved it and enjoyed it
Kevin Buzzard (Jun 01 2018 at 02:36):
walking around the gardens of mathematics
Mario Carneiro (Jun 01 2018 at 02:37):
oh you proved by contradiction
Mario Carneiro (Jun 01 2018 at 02:37):
that's a bit roundabout
Kevin Buzzard (Jun 01 2018 at 02:38):
it's inbuilt
Kevin Buzzard (Jun 01 2018 at 02:38):
I asked 250 students to prove sup(S) + sup(T) = sup(S+T)
Mario Carneiro (Jun 01 2018 at 02:38):
you have so many cases in this proof...
Kevin Buzzard (Jun 01 2018 at 02:38):
and about 80 did it
Kenny Lau (Jun 01 2018 at 02:38):
really
Kevin Buzzard (Jun 01 2018 at 02:38):
and 79 did it by contradiction
Kenny Lau (Jun 01 2018 at 02:39):
such a simple theorem
Kenny Lau (Jun 01 2018 at 02:39):
only 80 out of 250
Kevin Buzzard (Jun 01 2018 at 02:39):
it's about that
Kevin Buzzard (Jun 01 2018 at 02:39):
I didn't count carefully and it's all gone back to the exams office now
Kenny Lau (Jun 01 2018 at 02:39):
@Mario Carneiro and the 1 is me lol
Kevin Buzzard (Jun 01 2018 at 02:39):
maybe more
Mario Carneiro (Jun 01 2018 at 02:39):
I recall this story
Kenny Lau (Jun 01 2018 at 02:39):
like seriously
Kenny Lau (Jun 01 2018 at 02:39):
the UMPs of sup is all you need
Kevin Buzzard (Jun 01 2018 at 02:39):
contradiction is the most powerful method of proof
Kevin Buzzard (Jun 01 2018 at 02:39):
you get to assume the most stuff
Kenny Lau (Jun 01 2018 at 02:40):
but 0% of the people know about UMP and UMP of sup
Kenny Lau (Jun 01 2018 at 02:40):
rounded down to the nearest percent
Mario Carneiro (Jun 01 2018 at 02:40):
I'm not even against it on intuitionistic grounds
Kevin Buzzard (Jun 01 2018 at 02:40):
if you've never had your brain polluted by constructivism it's a very natural first step
Kenny Lau (Jun 01 2018 at 02:40):
cleansed
Mario Carneiro (Jun 01 2018 at 02:40):
it has a way of making thinking easier and proof more complicated
Kevin Buzzard (Jun 01 2018 at 02:40):
right
Kevin Buzzard (Jun 01 2018 at 02:41):
I even saw, on several occasions, and this is certainly not the first time,
Kevin Buzzard (Jun 01 2018 at 02:41):
people writing
Kenny Lau (Jun 01 2018 at 02:41):
it's not even about constructivism anymore, I'm just chaining UMPs all around
Kenny Lau (Jun 01 2018 at 02:41):
it's not about constructivism when people use UMP in category theory
Kenny Lau (Jun 01 2018 at 02:41):
because it's what it is
Kenny Lau (Jun 01 2018 at 02:41):
it's the UMP
Kevin Buzzard (Jun 01 2018 at 02:41):
"We want to prove X. Let's prove it by contradiction. So assume X is false. Now consider the following perfectly good proof of X. But X is false! Contradiction!
Kevin Buzzard (Jun 01 2018 at 02:41):
"
Kenny Lau (Jun 01 2018 at 02:42):
if you are a lazy person who only knows proof by contradiction it's a very natural first step
Mario Carneiro (Jun 01 2018 at 02:42):
For things like timed tests it's a good strategy
Kenny Lau (Jun 01 2018 at 02:42):
I find UMPs easier
Mario Carneiro (Jun 01 2018 at 02:43):
where you just write and write until you get the answer
Kenny Lau (Jun 01 2018 at 02:43):
I just use 100 UMPs until I get the answer
Kenny Lau (Jun 01 2018 at 02:43):
and I always get it
Kenny Lau (Jun 01 2018 at 02:43):
because it's universal
Mario Carneiro (Jun 01 2018 at 02:43):
Also resolution theorem proving is based on this idea
Kenny Lau (Jun 01 2018 at 02:43):
solve_by_elim ain't
Mario Carneiro (Jun 01 2018 at 02:44):
where you whittle down a counterexample until it is impossible
Mario Carneiro (Jun 01 2018 at 02:44):
but the resulting proof looks ugly I think
Kenny Lau (Jun 01 2018 at 02:45):
(whatever)
Mario Carneiro (Jun 01 2018 at 02:45):
when you want that "polished" look it's best to avoid proof by contradiction
Kevin Buzzard (Jun 01 2018 at 02:51):
My goal is has_le.le (coe 0) (has_div.div 71 100)
Kevin Buzzard (Jun 01 2018 at 02:51):
and if I try and unfold either has_le.le
or coe
I get a deterministic timeout
Kenny Lau (Jun 01 2018 at 02:52):
so don't unfold them?
Kevin Buzzard (Jun 01 2018 at 02:53):
norm_num times out too
Kenny Lau (Jun 01 2018 at 02:54):
did you use div
lemmas?
Kenny Lau (Jun 01 2018 at 02:54):
div_nonneg
Kevin Buzzard (Jun 01 2018 at 02:54):
oh I need to feed those in
Kenny Lau (Jun 01 2018 at 02:54):
you just need that one
Kenny Lau (Jun 01 2018 at 02:54):
the rest should be norm_num
Kevin Buzzard (Jun 01 2018 at 02:54):
do I put it in the context?
Kenny Lau (Jun 01 2018 at 02:55):
no, you apply it
Kevin Buzzard (Jun 01 2018 at 02:56):
you want me to actually prove it by hand??
Kevin Buzzard (Jun 01 2018 at 02:56):
what is this -- the 1980s?
Kevin Buzzard (Jun 01 2018 at 02:57):
we have norm_num!
Kenny Lau (Jun 01 2018 at 02:57):
my math teacher at high school would tell the story of people using calculators to verify that 5 x 0 = 0
Kevin Buzzard (Jun 01 2018 at 02:58):
refine div_nonneg _ _,
times out
Kevin Buzzard (Jun 01 2018 at 02:58):
everything times out
Kevin Buzzard (Jun 01 2018 at 02:58):
my goal is corrupted
Kenny Lau (Jun 01 2018 at 02:58):
code
Kevin Buzzard (Jun 01 2018 at 02:59):
noncomputable definition s : ℝ := 71/100 theorem sQ : s = ((71/100:ℚ):ℝ) := by unfold s;norm_num --set_option pp.all true example : floor s = 0 := begin rw [sQ,rat.cast_floor], apply (floor_of_bounds _ _).1, split, { have H : (100 : ℚ)> 0 := by norm_num, refine div_nonneg _ _, --unfold has_le.le, --show 0 ≤ 71 / 100, sorry}, {sorry} end
Kevin Buzzard (Jun 01 2018 at 02:59):
all this fuss about 0.71
Kevin Buzzard (Jun 01 2018 at 02:59):
I should have been in bed hours ago
Kevin Buzzard (Jun 01 2018 at 03:00):
I'm glad none of my students spent 2 hours on this bit
Kevin Buzzard (Jun 01 2018 at 03:00):
it was only a 2 hour exam
Kenny Lau (Jun 01 2018 at 03:02):
example : floor s = 0 := begin rw ← floor_of_bounds, split, { unfold s, apply div_nonneg; norm_num }, { unfold s, rw div_lt_iff; norm_num } end
Mario Carneiro (Jun 01 2018 at 03:06):
example : floor s = 0 := by rw [← floor_of_bounds, s, int.cast_zero]; norm_num
Kevin Buzzard (Jun 01 2018 at 03:08):
So using rat.cast_floor was a bad idea
Kevin Buzzard (Jun 01 2018 at 03:08):
Even though my instinct is to get out of R ASAP
Kenny Lau (Jun 01 2018 at 03:08):
there's a box
Mario Carneiro (Jun 01 2018 at 03:08):
I meant to use that if you were planning on kernel computation
Kenny Lau (Jun 01 2018 at 03:08):
think out of it
Kenny Lau (Jun 01 2018 at 03:08):
@Mario Carneiro i couldn't get the kernel to compute it
Mario Carneiro (Jun 01 2018 at 03:09):
Actually 71
might be too big for the kernel...
Kenny Lau (Jun 01 2018 at 03:09):
lol
Kenny Lau (Jun 01 2018 at 03:09):
71 is too big for the kernel
Kenny Lau (Jun 01 2018 at 03:09):
https://tio.run/##K6gsycjPM/7/v6AoM69Ew9xQS8vcUPP/fwA
Mario Carneiro (Jun 01 2018 at 03:09):
that's VM computation though
Mario Carneiro (Jun 01 2018 at 03:09):
or would be if it were lean
Mario Carneiro (Jun 01 2018 at 03:10):
python doesn't have to bother proving it is correct
Mario Carneiro (Jun 01 2018 at 03:10):
and it also doesn't use a braindead representation
Kevin Buzzard (Jun 01 2018 at 03:45):
Kenny I did it:
Kevin Buzzard (Jun 01 2018 at 03:45):
theorem no_eights (n : ℕ) : decimal.expansion s (by unfold s;norm_num) n ≠ 8 := ...
Kevin Buzzard (Jun 01 2018 at 03:45):
0.71
has no 8's in its decimal expansion
Johan Commelin (Jun 01 2018 at 06:44):
Actually
71
might be too big for the kernel...
Would it help if we compute in base (with or )? Then we could have a lookup-table of simp-lemmas. And we could implement stuff like https://en.wikipedia.org/wiki/Multiplication_algorithm#Karatsuba_multiplication
Johan Commelin (Jun 01 2018 at 06:45):
And for specific computations, of course a specific base could be used, with pre-computed lookup-tables.
Johan Commelin (Jun 01 2018 at 06:46):
Ok, to be clear: I am not suggesting that we change the implementation of nat
. But I am suggesting that we have a parallel implementation specifically for computations in base r
. And an isomorphism between the implementations.
Johan Commelin (Jun 01 2018 at 06:47):
But maybe this means that we also need a parallel implementation of int
and rat
. And then I'm not sure if I would want to go down that rabbit-hole
Mario Carneiro (Jun 01 2018 at 06:57):
Yes, it would help to work in base r. The really important part is that r should be greater than 1
Mario Carneiro (Jun 01 2018 at 06:57):
The num
type is used to address these issues, by implementing binary natural numbers instead of the default nat
which is unary
Mario Carneiro (Jun 01 2018 at 06:58):
znum
is the parallel implementation of int
; there is no qnum type (yet)
Johan Commelin (Jun 01 2018 at 07:01):
Hmm, ok. So then you would need a qnum
and afterwards an rnum
and a cnum
...
Mario Carneiro (Jun 01 2018 at 07:02):
well, those last two don't matter anyway
Mario Carneiro (Jun 01 2018 at 07:02):
or at least, they would be significantly different from the real
type you know and love
Mario Carneiro (Jun 01 2018 at 07:02):
because computable reals are not like regular reals
Johan Commelin (Jun 01 2018 at 07:02):
I am not suggesting that rnum
be computable
Johan Commelin (Jun 01 2018 at 07:03):
But maybe then it isn't useful either (-;
Mario Carneiro (Jun 01 2018 at 07:03):
That's the whole point
Mario Carneiro (Jun 01 2018 at 07:03):
The idea is to have a "programming numbers" type which is proven isomorphic to the abstract version
Johan Commelin (Jun 01 2018 at 07:03):
Right
Johan Commelin (Jun 01 2018 at 07:04):
But for a speed-up of Kevin's question, you would like to convert to num
at some point. Is that correct?
Mario Carneiro (Jun 01 2018 at 07:05):
Unfortunately, you currently have to make a decision between VM-optimized and kernel-optimized data types
Mario Carneiro (Jun 01 2018 at 07:05):
so there are valid reasons to keep both around
Mario Carneiro (Jun 01 2018 at 07:06):
nat
is actually the faster one in the VM, because lean replaces it with GMP bignums or C ints if small enough
Mario Carneiro (Jun 01 2018 at 07:06):
while num
is just a regular inductive type so it's implemented as a linked list of digits
Mario Carneiro (Jun 01 2018 at 07:08):
If you want to prove theorems by rfl
or dec_trivial
, you need to use kernel-efficient data types or else keep the numbers very small
Johan Commelin (Jun 01 2018 at 07:09):
Yes, I understand. So, are things like Karatsuba or Tom-Cook implemented for num
?
Mario Carneiro (Jun 01 2018 at 07:09):
If you are using norm_num
or simp
, you want VM-efficient data types
Mario Carneiro (Jun 01 2018 at 07:09):
No, the numbers have not got that big (yet)
Mario Carneiro (Jun 01 2018 at 07:10):
That requires significant size before it pays off
Johan Commelin (Jun 01 2018 at 07:10):
I guess another problem is that for big numbers the conversion between nat
and num
will become the bottle-neck. Right?
Mario Carneiro (Jun 01 2018 at 07:11):
You can't do anything that even mentions nat
in the kernel with big numbers
Mario Carneiro (Jun 01 2018 at 07:12):
you can't even accept nat input and convert to num because the parser produces some bit0 (bit0 ... 1)
term to pass to your function, and the kernel evaluates it before getting to your function
Johan Commelin (Jun 01 2018 at 07:12):
O.o (-;
Mario Carneiro (Jun 01 2018 at 07:12):
So this means that any conversion from nat
has to be done in the VM. The good news is that this can be done efficiently and still be verified
Johan Commelin (Jun 01 2018 at 07:13):
Ok, I don't follow this anymore... but I think it means that I can relax (-;
Mario Carneiro (Jun 01 2018 at 07:13):
You just have theorems saying bit0 \u x = \u bit0 x
where \u : nat -> num
Johan Commelin (Jun 01 2018 at 07:13):
I thought that the VM cheated... and you would lose verification
Mario Carneiro (Jun 01 2018 at 07:14):
and you have a tactic (running in the VM) that selectively chooses to apply this theorem
Mario Carneiro (Jun 01 2018 at 07:14):
by looking at the term in the goal
Mario Carneiro (Jun 01 2018 at 07:14):
with regular lean functions you can only look at the value that is given, but tactics can decompose the expr that represents the value
Mario Carneiro (Jun 01 2018 at 07:15):
so something like bit0 (bit0 ... 1)
has reasonable size as a term but not as a value
Mario Carneiro (Jun 01 2018 at 07:16):
and you can apply log(n) bit0 \u x = \u bit0 x
theorems to get it down to a theorem just about num
Mario Carneiro (Jun 01 2018 at 07:16):
and then you prove by rfl
or whatever
Mario Carneiro (Jun 01 2018 at 07:16):
and the kernel never has to evaluate big nats
Johan Commelin (Jun 01 2018 at 07:18):
Ok, I see the strategy.
Johan Commelin (Jun 01 2018 at 07:19):
I think Kevin is going to like that if at some point he wants to do some modular form stuff...
Johan Commelin (Jun 01 2018 at 07:19):
Because their coefficients explode
Mario Carneiro (Jun 01 2018 at 07:20):
So norm_num
is also working in binary, I guess
Mario Carneiro (Jun 01 2018 at 07:20):
it produces a theorem that is longer for larger numbers though
Mario Carneiro (Jun 01 2018 at 07:21):
while a kernel proof is always just rfl
Mario Carneiro (Jun 01 2018 at 07:22):
For the most part, kernel computation is discouraged because it's not particularly optimized for that
Mario Carneiro (Jun 01 2018 at 07:23):
But I think it's amusing that in dependent type theory you can write down a very short proof of almost anything
Johan Commelin (Jun 01 2018 at 07:24):
What do you mean with that last statement?
Mario Carneiro (Jun 01 2018 at 07:24):
for example, I can write a program that enumerates proofs in ZFC or whatever, and then if there is a proof of RH with fewer than 2^2^2^2^2^2^2^2^2^2^2 symbols, then I can prove it by rfl
Johan Commelin (Jun 01 2018 at 07:25):
Right, but that proof will require a lot of prerequisite work
Johan Commelin (Jun 01 2018 at 07:25):
(Which I consider part of the proof.)
Mario Carneiro (Jun 01 2018 at 07:26):
The only work that needs to be done is the setup, stating the problem
Mario Carneiro (Jun 01 2018 at 07:26):
the "hard part" is completely absent from the accounting, except in the length bound
Mario Carneiro (Jun 01 2018 at 07:27):
but I can write functions that grow ridiculously fast in DTT so that's not saying much
Johan Commelin (Jun 01 2018 at 07:27):
Ok, so we can prove that RH doesn't have a short proof.
Johan Commelin (Jun 01 2018 at 07:27):
And neither has Fermat's Last Theorem
Mario Carneiro (Jun 01 2018 at 07:28):
Okay, fermat is a good example, since we know that one is true
Johan Commelin (Jun 01 2018 at 07:28):
For otherwise they would already have been in mathlib with a rfl
proof.
Mario Carneiro (Jun 01 2018 at 07:28):
I can prove Fermat's last theorem by rfl
Johan Commelin (Jun 01 2018 at 07:28):
I would love to see that done.
Johan Commelin (Jun 01 2018 at 07:28):
The statement is already there
Johan Commelin (Jun 01 2018 at 07:28):
And that is all the setup you need.
Mario Carneiro (Jun 01 2018 at 07:29):
I just write a bool
function that checks the first bazillion proofs and returns tt
if one works, and assert by rfl
that it is tt
Johan Commelin (Jun 01 2018 at 07:30):
Right. And of course Lean will never finish running.
Mario Carneiro (Jun 01 2018 at 07:30):
that proof checks if and only if there is a short enough proof of FLT, and since we know there is, that means I have a short proof
Mario Carneiro (Jun 01 2018 at 07:31):
Of course the problem with this kind of analysis is that lean will run (almost) forever on such a proof
Mario Carneiro (Jun 01 2018 at 07:31):
But it seems to be some kind of deficiency in DTT, that the length of a proof is no longer a suitable measure of the hardness of the proof
Johan Commelin (Jun 01 2018 at 07:32):
Yes, and that's why we still dont have FLT in mathlib (-;
Johan Commelin (Jun 01 2018 at 07:32):
No, but compile-time is still a good measure
Mario Carneiro (Jun 01 2018 at 07:33):
Yes. Or number of proof steps including definitional reductions
Mario Carneiro (Jun 01 2018 at 07:33):
This doesn't come up in ZFC since there's no definitional reduction, what you see is what you get
Mario Carneiro (Jun 01 2018 at 07:35):
anyway, this "feature" of DTT should be thought of as abuse of lean, so don't be surprised if it starts to sweat
Mario Carneiro (Jun 01 2018 at 07:35):
when you try to #reduce 71 / 100
Johan Commelin (Jun 01 2018 at 07:36):
Sure, and in fact, we don't even know what the value of "bazillion" is for your bool
function. We only have a very clear suggestion that it is finite.
Mario Carneiro (Jun 01 2018 at 07:37):
I think there are some pretty reasonable upper bounds based on physical considerations
Mario Carneiro (Jun 01 2018 at 07:37):
i.e. the proof appears to fit in the universe, so it's shorter than Graham's number
Johan Commelin (Jun 01 2018 at 07:37):
ok, fair enough
Johan Commelin (Jun 01 2018 at 11:12):
It seems that real
is not an instance of has_pow
. Should I add it, or is there some computability reason for not doing that?
Kevin Buzzard (Jun 01 2018 at 12:33):
I think the definition of has_pow
is post-real so it might just be that nobody used them seriously enough since. As you can see, I've come back to the reals recently, and I am always interested in making them "undergraduate-friendly" so I would have run into this sooner or later.
Kevin Buzzard (Jun 01 2018 at 12:33):
@Mario Carneiro -- where do these definitions go? Mathlib? My own Xena library? (I'm writing a library for stuff my UG mathematicians might want or need and which is not in mathlib -- can you envisage there being good reasons for such a library?)
definition is_upper_bound (x : ℝ) (S : set ℝ) := ∀ s ∈ S, s ≤ x definition is_bounded_above (S : set ℝ) := ∃ x, is_upper_bound x S definition is_LUB (x : ℝ) (S : set ℝ) := is_upper_bound x S ∧ ∀ y : ℝ, is_upper_bound y S → x ≤ y definition has_LUB (S : set ℝ) := ∃ x, is_LUB x S
Johan Commelin (Jun 01 2018 at 12:39):
Hmm, I guess to do has_pow properly, we should define x^r
for x r : real
. And then all of a sudden you have to work.
Johan Commelin (Jun 01 2018 at 12:40):
Or can we have multiple instances, depending on whether r
has type nat
or int
or rat
or real
.
Kevin Buzzard (Jun 01 2018 at 12:42):
this is exactly the problem with pow
Johan Commelin (Jun 01 2018 at 12:43):
@Kevin Buzzard Isn't Sup
already on line 316 of data.real.basic?
Kevin Buzzard (Jun 01 2018 at 12:43):
Chris Hughes wrote exp : C -> C but it's still not in mathlib
Kevin Buzzard (Jun 01 2018 at 12:49):
That's CS sup
Kevin Buzzard (Jun 01 2018 at 12:49):
sup(S)+sup(T) = sup(S+T) is not true for that sup
Kevin Buzzard (Jun 01 2018 at 12:49):
let S have one element and let T be empty
Kevin Buzzard (Jun 01 2018 at 12:49):
(deleted)
Kevin Buzzard (Jun 01 2018 at 12:49):
it returns 37 if the set has no sup
Kevin Buzzard (Jun 01 2018 at 12:49):
This is philosophy not mathematics
Kevin Buzzard (Jun 01 2018 at 12:50):
but if you're going to define sup globally
Kevin Buzzard (Jun 01 2018 at 12:50):
then it should be taking values in -infty + R + infty
Kevin Buzzard (Jun 01 2018 at 12:50):
not just spewing out 37s when it's stuck
Kevin Buzzard (Jun 01 2018 at 12:51):
You see how my predicate solves this problem?
Kevin Buzzard (Jun 01 2018 at 12:51):
I can say "if a is the sup of S and b is the sup of T then a + b is the sup of S + T
Johan Commelin (Jun 01 2018 at 12:51):
Ok, so I read too quickly (-;
Kevin Buzzard (Jun 01 2018 at 12:51):
My question is how to formalize that statement in mathlib
Kevin Buzzard (Jun 01 2018 at 12:51):
and my predicates make it look nice and easy
Kevin Buzzard (Jun 01 2018 at 12:51):
whereas I can't quite do it with what we have
Kevin Buzzard (Jun 01 2018 at 12:52):
however I am unclear about whether "what I want as someone who wants to formulate elementary lemmas about sup"
Kevin Buzzard (Jun 01 2018 at 12:52):
has anything to do with "what should be in mathlib"
Kevin Buzzard (Jun 01 2018 at 12:52):
I am very unclear about what the boundaries of mathlib are
Kevin Buzzard (Jun 01 2018 at 12:52):
Look, watch this:
Kevin Buzzard (Jun 01 2018 at 12:52):
@Mario Carneiro -- should I put schemes in mathlib? Let me know. I don't care either way but you never answer
Kevin Buzzard (Jun 01 2018 at 12:52):
he never answers
Kevin Buzzard (Jun 01 2018 at 12:53):
I think he reads the question, thinks "hmm, I don't know offhand, I should look at the repo, oh look it's 7000 lines of sometimes poorly-written code"
Kevin Buzzard (Jun 01 2018 at 12:53):
"this will need some thought"
Kevin Buzzard (Jun 01 2018 at 12:53):
I'll try another approach
Kevin Buzzard (Jun 01 2018 at 12:55):
@Mario Carneiro I think definitions of high-level mathematical objects and statements of extremely technical theorems are extremely important things to have in Lean and I will be making quite a few of these in the future. Do you want them in mathlib or do you feel that they are beyond mathlib's remit? I hope I have conveyed in the past how I feel about this matter (namely that I think that there are many people whose interest would be sparked by a small database of complex objects built in Lean)
Kevin Buzzard (Jun 01 2018 at 12:56):
I believe @Scott Morrison thinks they should be in mathlib
Johannes Hölzl (Jun 01 2018 at 13:32):
least upper bounds etc as predicates are already there: https://github.com/leanprover/mathlib/blob/master/order/bounds.lean
Sebastien Gouezel (Jun 01 2018 at 14:07):
You can also have a look at https://github.com/leanprover/mathlib/blob/master/order/conditionally_complete_lattice.lean
Mario Carneiro (Jun 01 2018 at 15:45):
-- should I put schemes in mathlib? Let me know. I don't care either way but you never answer
RIght now? No. As Patrick has mentioned before, the scheme code is huge and requires major refactoring to go into mathlib, much like some other planned additions, e.g. Scott's category theory stuff (and he's made some progress on this last I checked). As it currently exists, it is written as a "race to the finish" which gets the job done without worrying about looking good while doing it, whereas I need "polished" code to go into mathlib. It's like the difference between research notes and a journal article or textbook. This process of bringing schemes in will take a lot of both of our time and right now I think you have bigger plans, so I would hold off on attempting this for the present.
Mario Carneiro (Jun 01 2018 at 15:46):
I think definitions of high-level mathematical objects and statements of extremely technical theorems are extremely important things to have in Lean and I will be making quite a few of these in the future. Do you want them in mathlib or do you feel that they are beyond mathlib's remit?
The "level" of the definition is not a problem, it can be as advanced as you like. But it must also be good lean code, that's my main concern.
Mario Carneiro (Jun 01 2018 at 15:51):
@Johan Commelin There is a definition of has_pow on real, because it is a field. You can use a^n
where n : nat
and a : real
Mario Carneiro (Jun 01 2018 at 15:53):
Actually a^n
where n : int
is not quite there, since the instance that exists is for group
s and real
isn't a (multiplicative) group. Maybe there should be another definition for division_ring
s that sets 0^-n = 0
?
Mario Carneiro (Jun 01 2018 at 15:56):
You could use the (tiny) library of proper division in mathlib though: units.mk0 a h
where a : real
and h : a != 0
is an element of units real
, which is a group, so you can raise it to an integer power and coerce back to real
Johan Commelin (Jun 01 2018 at 16:44):
Ok, thanks. I will take a look at those functions.
Johan Commelin (Jun 01 2018 at 16:48):
Is it now easy to have the integers \cup infty? How about int \cup -\infty
? Including the order and addition on them. (Otherwise I could just take option int
.
Mario Carneiro (Jun 01 2018 at 16:59):
Yes, with_top int
has an addition operation and an order, and is defeq to option int
Johan Commelin (Jun 01 2018 at 17:08):
Hmm, but there is no with_bot
for semigroups. I want to define a function f : nat \to (with_top int)
, and then another function nat \to real := \lam n, b^(- f(n))
, where b
is some fixed real number.
Johan Commelin (Jun 01 2018 at 17:09):
So then I need to extend -
to - : with_top int \to with_bot int
. And I need to explain to has_pow real
that b^(-infty) = 0
.
Mario Carneiro (Jun 01 2018 at 17:10):
eww
Mario Carneiro (Jun 01 2018 at 17:10):
that's a bit specialized
Johan Commelin (Jun 01 2018 at 17:10):
Ok, f(n) = infty \iff n = 0
.
Mario Carneiro (Jun 01 2018 at 17:11):
You can define -
as option.map (\lam x, -x)
, and b^o
where o : with_bot int
by cases
Johan Commelin (Jun 01 2018 at 17:11):
The other option is that I just use if-then-else everywhere... but I don't really like that either...
Mario Carneiro (Jun 01 2018 at 17:11):
no if-then
Mario Carneiro (Jun 01 2018 at 17:11):
it's an option, use cases
Johan Commelin (Jun 01 2018 at 17:12):
Right. (I meant avoiding option
and just do dite (n = 0)
in all the definitions.
Johan Commelin (Jun 01 2018 at 17:12):
(This stuff shows up everywhere in nonarchimedean valuations.)
Mario Carneiro (Jun 01 2018 at 17:12):
what n = 0
are you talking about?
Mario Carneiro (Jun 01 2018 at 17:13):
you said f
returns an option
Mario Carneiro (Jun 01 2018 at 17:13):
well, a with_top
Johan Commelin (Jun 01 2018 at 17:13):
Yes, but I could also define f
on pnat
, and g
with a dite
.
Johan Commelin (Jun 01 2018 at 17:13):
Right?
Mario Carneiro (Jun 01 2018 at 17:14):
Oh, I misunderstood your iff statement
Johan Commelin (Jun 01 2018 at 17:15):
But I like your approach. I'll try to implement it when I'm back at Lean. (And should I just clone and dualise the with_top
stuff to with_bot
for semigroups?
Mario Carneiro (Jun 01 2018 at 17:15):
It's already there
Johan Commelin (Jun 01 2018 at 17:16):
Hmm, for with_bot
I only see instances for partial orders and lattices. Not for semigroups.
Mario Carneiro (Jun 01 2018 at 17:17):
There is with_zero
also, there are lots of ways to construe the added element in all the structures
Mario Carneiro (Jun 01 2018 at 17:18):
Oh, I see, with_top
and with_bot
are actually the same as add_semigroups
Johan Commelin (Jun 01 2018 at 17:19):
Ok, so maybe you can also give a hint on how to define f
. It is the p-adic valuation (where p is a prime). So f(n)
is the maximal e : nat
such that p^e
divides n
.
Johan Commelin (Jun 01 2018 at 17:19):
Oh, I see,
with_top
andwith_bot
are actually the same as add_semigroups
Yes, but not as ordered add_semigroups.
Mario Carneiro (Jun 01 2018 at 17:19):
Yeah, I'll work on that
Reid Barton (Jun 01 2018 at 17:21):
@Johan Commelin see https://gist.github.com/rwbarton/599327954b01b2e840894189981172ea
Mario Carneiro (Jun 01 2018 at 17:21):
First, I would want a "prime count" function that takes a nat and finds the appropriate power of p. It is defined arbitrarily at zero, but for concreteness that means f 0 = 0
Reid Barton (Jun 01 2018 at 17:22):
I gave that to Kevin earlier and I think he has improved it some in the Fibonacci project
Johan Commelin (Jun 01 2018 at 17:22):
Yes, or f 0 = infty. And then you would be done.
Johan Commelin (Jun 01 2018 at 17:22):
Reid, thanks. I'll take a look.
Mario Carneiro (Jun 01 2018 at 17:22):
Then the valuation function is defined by cases on n
Mario Carneiro (Jun 01 2018 at 17:24):
actually, I just checked what I did in metamath for this and I used with_top as well. So past me seems to think that's a better idea
Mario Carneiro (Jun 01 2018 at 17:25):
I'm a bit worried about having to coerce all the time though
Kevin Buzzard (Jun 01 2018 at 17:47):
I don't think I ever got the code completely working in the Fibonacci project, there was perhaps one sorry I never got rid of
Kevin Buzzard (Jun 01 2018 at 17:48):
As it currently exists, it is written as a "race to the finish" which gets the job done without worrying about looking good while doing it, whereas I need "polished" code to go into mathlib. It's like the difference between research notes and a journal article or textbook. This process of bringing schemes in will take a lot of both of our time and right now I think you have bigger plans, so I would hold off on attempting this for the present.
Yes, this is exactly how I wrote it, and I put very little thought into how to make structures because I didn't really know how to make structures at the time. Here are my more long-term thoughts on these matters:
Kevin Buzzard (Jun 01 2018 at 17:49):
I'm going to do perfectoid spaces because I think it would be funny to do them
Kevin Buzzard (Jun 01 2018 at 17:49):
Some scheme stuff we will need e.g. sheaves
Kevin Buzzard (Jun 01 2018 at 17:49):
but I was thinking about re-doing it
Kevin Buzzard (Jun 01 2018 at 17:49):
doing it all for a second time in a perfectoid spaces directory
Kevin Buzzard (Jun 01 2018 at 17:50):
and this time doing it better and checking with people like Mario along the way as to whether the structures looked sensible
Kevin Buzzard (Jun 01 2018 at 17:50):
I understand now much better what I can do well and what I do badly
Kevin Buzzard (Jun 01 2018 at 17:50):
and especially what I do so badly that it will take a lot of time to fix
Kevin Buzzard (Jun 01 2018 at 17:50):
I make no apologies for the race to the finish with schemes -- this was simply a test to see if it could be done, and it could be done
Mario Carneiro (Jun 01 2018 at 17:51):
I thnk that's a good plan
Kevin Buzzard (Jun 01 2018 at 17:52):
In the long term with schemes, I propose doing perfectoid spaces, seeing the parts which are common to both theories, using this commonality as an argument for inclusion in mathlib, and then spending some time writing these parts of the code properly
Kevin Buzzard (Jun 01 2018 at 17:52):
so for example we will need sheaves of types at some point
Kevin Buzzard (Jun 01 2018 at 17:52):
and when we need them in the perfectoid theory I will revisit what I did for schemes
Mario Carneiro (Jun 01 2018 at 17:52):
The second time around you will have a much better appreciation for the subtleties and design questions and can do it right
Kevin Buzzard (Jun 01 2018 at 17:52):
(in fact we did these already and I even have a suggested definition from Mario somewhere in my starred messages)
Kevin Buzzard (Jun 01 2018 at 17:53):
yes -- second time round much better
Mario Carneiro (Jun 01 2018 at 17:53):
Not to mention you are a better lean programmer now than last month (and the month before that etc)
Kevin Buzzard (Jun 01 2018 at 17:53):
so second time round I think "this is important, I knocked up a definition in 10 minutes when I was doing schemes, here are the problems I had with it, let's fix those problems now and aim for mathlib"
Kevin Buzzard (Jun 01 2018 at 17:53):
"and write a proper interface while we're here"
Kevin Buzzard (Jun 01 2018 at 17:54):
so it's partly some random repo with random bits of people's papers formalised
Kevin Buzzard (Jun 01 2018 at 17:54):
and then some directory called "mathlib_someday"
Mario Carneiro (Jun 01 2018 at 17:54):
When I look at dioph.lean
I am ashamed of myself, I would write that so much better now and it's been only a year
Kevin Buzzard (Jun 01 2018 at 17:54):
where we put files where someone has actually made an effort to make the file mathlib-worthy
Kevin Buzzard (Jun 01 2018 at 17:55):
You're absolutely right that I get better every month. When I started schemes I had no idea how to use type class inference so never used it -- I would just supply all the missing proofs myself.
Scott Morrison (Jun 01 2018 at 22:15):
This all sounds like a great plan --- schemes absolutely deserve to be in mathlib (what would be the point of mathlib if we weren't aiming for it to cover the basic essentials?), and at the same time we should try to make sure code going into mathlib is good (not perfect, though).
Scott Morrison (Jun 01 2018 at 22:16):
My categories code (getting there! :-) is still abysmal, probably, and I appreciate it's going to be lots of work to get it into mathlib. :-)
Kevin Buzzard (Jun 03 2018 at 00:08):
import algebra.archimedean #check @abs_nonneg -- abs_nonneg : ∀ {α : Type u_1} -- [_inst_1 : decidable_linear_ordered_comm_group α] (a : α), -- abs a ≥ 0 theorem abs_nonneg' (α : Type) [floor_ring α] [decidable_linear_ordered_comm_group α] (r : α) : abs r ≥ 0 := abs_nonneg r -- fails
Kevin Buzzard (Jun 03 2018 at 00:08):
My understanding of something Reid said a few days ago about the reals
Kenny Lau (Jun 03 2018 at 00:08):
diamond of death?
Kevin Buzzard (Jun 03 2018 at 00:08):
was that I shouldn't be proving things about the reals
Kevin Buzzard (Jun 03 2018 at 00:09):
I should just demand I'm a complete totally ordered field and deduce everything from that
Mario Carneiro (Jun 03 2018 at 00:09):
yeah, this is a diamond problem
Kevin Buzzard (Jun 03 2018 at 00:09):
but the real problem was decidability I think
Mario Carneiro (Jun 03 2018 at 00:09):
you have two conflicting group structures on A
Kenny Lau (Jun 03 2018 at 00:09):
and order structure?
Kevin Buzzard (Jun 03 2018 at 00:10):
I want to use this abs >= 0 lemma
Kevin Buzzard (Jun 03 2018 at 00:10):
a floor_ring has an order
Mario Carneiro (Jun 03 2018 at 00:10):
Why do you have two typeclasses here? that's the question
Reid Barton (Jun 03 2018 at 00:11):
In this case I think you don't need decidable_linear_ordered_comm_group
Mario Carneiro (Jun 03 2018 at 00:11):
you do, to state abs
Mario Carneiro (Jun 03 2018 at 00:11):
but you don't need the floor_ring
Kevin Buzzard (Jun 03 2018 at 00:16):
definition abs_expansion (r : α) [decidable_linear_ordered_comm_group α]: ℕ → ℕ := expansion (abs r) (abs_nonneg r)
Kevin Buzzard (Jun 03 2018 at 00:16):
that's what the problem becomes if I remove the floor_ring
Mario Carneiro (Jun 03 2018 at 00:17):
what's expansion
Kevin Buzzard (Jun 03 2018 at 00:17):
type mismatch at application expansion (abs r) _ term abs_nonneg r has type @ge α (@preorder.to_has_le α (@partial_order.to_preorder α (@ordered_comm_group.to_partial_order α (@decidable_linear_ordered_comm_group.to_ordered_comm_group α _inst_3)))) (@abs α _inst_3 r) 0 but is expected to have type @ge α (@preorder.to_has_le α (@partial_order.to_preorder α (@ordered_comm_monoid.to_partial_order α (@ordered_cancel_comm_monoid.to_ordered_comm_monoid α (@ordered_semiring.to_ordered_cancel_comm_monoid α (@ordered_ring.to_ordered_semiring α (@linear_ordered_ring.to_ordered_ring α (@floor_ring.to_linear_ordered_ring α _inst_2)))))))) (@abs α _inst_3 r) 0
Mario Carneiro (Jun 03 2018 at 00:17):
Again, conflicting typeclasses
Kevin Buzzard (Jun 03 2018 at 00:17):
definition expansion (r : α) (H : r ≥ 0) : ℕ → ℕ | 0 := int.to_nat (floor r) | (n + 1) := int.to_nat (floor (chomp r n))
Mario Carneiro (Jun 03 2018 at 00:17):
inst_3
in one, inst_2
in the other
Kevin Buzzard (Jun 03 2018 at 00:17):
But it's just a decidability issue
Mario Carneiro (Jun 03 2018 at 00:18):
no it's a conflicting typeclasses issue
Kevin Buzzard (Jun 03 2018 at 00:18):
I just want to "switch decidability on"
Mario Carneiro (Jun 03 2018 at 00:18):
I assume you don't care about classical?
Kevin Buzzard (Jun 03 2018 at 00:18):
right
Mario Carneiro (Jun 03 2018 at 00:18):
just local instance decidable_prop
Kevin Buzzard (Jun 03 2018 at 00:18):
This is stuff for mathematicians
Mario Carneiro (Jun 03 2018 at 00:20):
Maybe you should just do this over \R
instead of A
Mario Carneiro (Jun 03 2018 at 00:20):
or else use the noncomputable floor instance for archimedean A
Kevin Buzzard (Jun 03 2018 at 00:21):
example (α : Type) [floor_ring α] : add_comm_group α := by apply_instance example (α : Type) [floor_ring α] : linear_order α := by apply_instance
Kevin Buzzard (Jun 03 2018 at 00:25):
I am a complete idiot
Kevin Buzzard (Jun 03 2018 at 00:25):
I should just be proving a junk theorem
Kevin Buzzard (Jun 03 2018 at 00:26):
I was defining decimal expansions of real numbers
Kevin Buzzard (Jun 03 2018 at 00:26):
and being fussy about issues with negative numbers
Kevin Buzzard (Jun 03 2018 at 00:27):
I should just let the function return some random result if the input is negative and then stop fussing
Kenny Lau (Jun 03 2018 at 00:28):
57
Kevin Buzzard (Jun 03 2018 at 00:28):
I can't believe I'm going to prove a junk theorem
Kevin Buzzard (Jun 03 2018 at 00:28):
I feel dirty
Kevin Buzzard (Jun 03 2018 at 00:29):
This is the problem
Kevin Buzzard (Jun 03 2018 at 00:29):
definition expansion (r : α) (H : r ≥ 0) : ℕ → ℕ | 0 := int.to_nat (floor r) | (n + 1) := int.to_nat (floor (chomp r n))
Kevin Buzzard (Jun 03 2018 at 00:29):
I just have to drop H
Mario Carneiro (Jun 03 2018 at 00:30):
It's not even used
Kevin Buzzard (Jun 03 2018 at 00:30):
and coerce a negative integer into nat
Kevin Buzzard (Jun 03 2018 at 00:30):
that's not the point Mario
Kevin Buzzard (Jun 03 2018 at 00:30):
it's all part of the mathematician's promise
Mario Carneiro (Jun 03 2018 at 00:30):
That goes in theorems, not definitions
Kevin Buzzard (Jun 03 2018 at 00:30):
we don't quite model things in the same way
Mario Carneiro (Jun 03 2018 at 00:31):
I have never seen a mathematician write a function that has an additional proof argument
Mario Carneiro (Jun 03 2018 at 00:31):
I think they would have a hard time even understanding what that means
Kevin Buzzard (Jun 03 2018 at 00:31):
It's not even used
it should be there on moral grounds
Kevin Buzzard (Jun 03 2018 at 00:32):
there should be some tactic bringing it along
Kevin Buzzard (Jun 03 2018 at 00:33):
"mathematicians promise that they will not run this programme on negative numbers"
Kenny Lau (Jun 03 2018 at 00:33):
@kevin just treat it like how you treat nat.sub
Mario Carneiro (Jun 03 2018 at 00:33):
You could use roption
for partial functions too
Kenny Lau (Jun 03 2018 at 00:33):
"subtraction with a star"
Mario Carneiro (Jun 03 2018 at 00:34):
alternatively, you could actually make sense of expansions of negative numbers
Mario Carneiro (Jun 03 2018 at 00:34):
which of course makes perfect sense and generates p-adic numbers
Mario Carneiro (Jun 03 2018 at 00:35):
or two's complement for the CS folks
Kevin Buzzard (Jun 03 2018 at 00:36):
It's not even used
It's used in int.to_nat
Mario Carneiro (Jun 03 2018 at 00:37):
Yet more alternatively, don't define it as a function, have an existence theorem
Mario Carneiro (Jun 03 2018 at 00:37):
the inverse to this is a lot easier to state
Mario Carneiro (Jun 03 2018 at 00:42):
def expansion (r : α) (n : ℕ) : ℕ := ⌊r * (10 ^ n : ℕ)⌋.nat_mod 10
Mario Carneiro (Jun 03 2018 at 00:43):
I'm not sure why n
is a nat here, there are both negative and positive exponent terms in the expansion
Kevin Buzzard (Jun 03 2018 at 01:18):
least upper bounds etc as predicates are already there: https://github.com/leanprover/mathlib/blob/master/order/bounds.lean
I see that I did mine a different way around to you. I defined is_LUB x S
and you is_lub S x
. Is there a preference for yours over mine? I chose "x S" because I would say x before S ("x is a least upper bound for S")
Mario Carneiro (Jun 03 2018 at 01:20):
yes, this allows you to view is_lub S
as a predicate by currying
Mario Carneiro (Jun 03 2018 at 01:21):
generally speaking, more "parameter" like things should come first
Kevin Buzzard (Jun 03 2018 at 01:24):
I'm far more likely to be fixing S and trying various x's than I am to be fixing an x and seeing if it bounds any S's, this seems far more unlikely to occur in practice
Mario Carneiro (Jun 03 2018 at 01:30):
that's why I said that
Mario Carneiro (Jun 03 2018 at 01:30):
S
is the parameter, x
is the variable
Mario Carneiro (Jun 03 2018 at 01:30):
so S
comes first
Kevin Buzzard (Jun 03 2018 at 13:56):
that's why I said that
I know, I was just translating you into maths
Kevin Buzzard (Jun 03 2018 at 22:53):
Hey @Kenny Lau
Kevin Buzzard (Jun 03 2018 at 22:53):
I was playing with sups
Kevin Buzzard (Jun 03 2018 at 22:54):
what do you think this is:
Kevin Buzzard (Jun 03 2018 at 22:54):
⟨λ u Hu, let ⟨s,Hs,t,Ht,Hu⟩ := Hu in by rw Hu;exact add_le_add (HSb.1 s Hs) (HTc.1 t Ht), λ d Hd,add_le_of_le_sub_right $ HSb.2 (d - c) (λ s Hs,le_sub.1 ((λ s₁ Hs₁,HTc.2 _ (λ t Ht,le_sub_left_of_add_le $ Hd _ ⟨s₁,Hs₁,t,Ht,rfl -- the proof ⟩)) s Hs))⟩
Kenny Lau (Jun 03 2018 at 22:54):
my constructive proof?
Kevin Buzzard (Jun 03 2018 at 22:54):
right
Kenny Lau (Jun 03 2018 at 22:54):
yay
Kevin Buzzard (Jun 03 2018 at 22:55):
here's an even better version
Kevin Buzzard (Jun 03 2018 at 22:55):
I wrote it twice
Kevin Buzzard (Jun 03 2018 at 22:55):
second time looked like this
Kevin Buzzard (Jun 03 2018 at 22:55):
theorem lub_add'' (S T : set ℝ) (b c : ℝ) (HSb : is_lub S b) (HTc : is_lub T c) : is_lub (S + T) (b + c) := ⟨λ u Hu, let ⟨s,Hs,t,Ht,Hu⟩ := Hu in by rw Hu;exact add_le_add (HSb.1 s Hs) (HTc.1 t Ht), λ d Hd,add_le_of_le_sub_right $ HSb.2 _ $ λ s Hs,le_sub.1 $ HTc.2 _ $ λ t Ht,le_sub_left_of_add_le $ Hd _ ⟨s,Hs,t,Ht,rfl⟩ ⟩
Kenny Lau (Jun 03 2018 at 22:55):
more dollar signs?
Kevin Buzzard (Jun 03 2018 at 22:55):
instance : has_add (set ℝ) := ⟨λ S T,{u | ∃ (s ∈ S) (t ∈ T), u = s + t}⟩
Kevin Buzzard (Jun 03 2018 at 22:56):
import order.bounds
Kevin Buzzard (Jun 03 2018 at 22:56):
and analysis.real
Kevin Buzzard (Jun 03 2018 at 22:56):
and it will run
Kevin Buzzard (Jun 03 2018 at 22:56):
I couldn't get that stupid triangle thing to work on the first line of the proof
Kevin Buzzard (Jun 03 2018 at 22:56):
the \t triangle that Patrick and I both dread
Kevin Buzzard (Jun 03 2018 at 22:57):
so I have to use rw;exact :-)
Kevin Buzzard (Jun 03 2018 at 22:57):
so that can be golfed a bit more
Kevin Buzzard (Jun 03 2018 at 22:57):
but the proof the other way I was extremely pleased with :-)
Kevin Buzzard (Jun 03 2018 at 22:57):
I formulated the theorem
Kevin Buzzard (Jun 03 2018 at 22:57):
I proved it in tactic mode
Kevin Buzzard (Jun 03 2018 at 22:58):
I then translated my tactic mode proof into term mode
Kenny Lau (Jun 03 2018 at 22:58):
nice!
Kevin Buzzard (Jun 03 2018 at 22:58):
and then I started again and proved it in term mode
Kevin Buzzard (Jun 03 2018 at 22:58):
from scratch
Kevin Buzzard (Jun 03 2018 at 22:58):
looking at my old term mode proof for hints about which arithmetic functions to use :-)
Kevin Buzzard (Jun 03 2018 at 23:01):
in that last proof line, Lean was somehow always "on the last term" -- I never had to fill in a hole with a non-zero number of characters to the right of it (other than the close bracket)
Kevin Buzzard (Jun 03 2018 at 23:01):
Kenny if you had given me that answer I would have had a hard time marking it.
Kevin Buzzard (Jun 03 2018 at 23:02):
I mean the lambda
Kevin Buzzard (Jun 03 2018 at 23:02):
it's become unreadable, right?
Kenny Lau (Jun 03 2018 at 23:02):
lol
Kenny Lau (Jun 03 2018 at 23:02):
but you can verify it
Kevin Buzzard (Jun 03 2018 at 23:03):
that is a very different thing from understanding it
Last updated: Dec 20 2023 at 11:08 UTC