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 : (2+3)2=5+26(\surd2+\surd3)^2=5+2\surd6

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):

https://github.com/leanprover/mathlib/blob/bdd54acda358f535b42951b784757135213dcf52/data/real/basic.lean#L16

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 rr (with r=10r = 10 or 1616)? 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 groups and real isn't a (multiplicative) group. Maybe there should be another definition for division_rings 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 and with_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