Zulip Chat Archive

Stream: new members

Topic: Tutorial Exercise


Lukas (May 09 2019 at 08:30):

I am working on the Blog article on constructing the natural numbers https://xenaproject.wordpress.com/2017/10/31/building-the-non-negative-integers-from-scratch/

Now I am stuck in one proof:

theorem one_add_eq_succ (n : xnat) : one + n = succ n :=
begin
  rewrite one,
  induction n with t Ht,
  {
    rewrite add_zero,
  },
  {
    rewrite add,
    sorry,
  }
end

I think this scan be solved via succ.inj, but I do not know how to apply this here.

Mario Carneiro (May 09 2019 at 08:31):

injection is the tactic version of apply succ.inj

Mario Carneiro (May 09 2019 at 08:31):

or cases in some cases

Lukas (May 09 2019 at 08:39):

apply succ.inj turns ⊢ succ (succ zero + t) = succ (succ t) goal into ⊢ succ (succ (succ zero + t)) = succ (succ (succ t)) so it does the inverse of what I want to do.

How can I apply the injection tactic here?

Mario Carneiro (May 09 2019 at 08:42):

oh, you want congr then

Mario Carneiro (May 09 2019 at 08:43):

if you have h : succ a = succ b in the context, injection h will turn it into a = b

Mario Carneiro (May 09 2019 at 08:43):

but if succ a = succ b is the goal, then you don't need injectivity, that's just functions respecting equality which is congr

Kevin Buzzard (May 09 2019 at 08:53):

After rewrite add you can use the inductive hypothesis Ht -- just rewrite Ht.

Kevin Buzzard (May 09 2019 at 08:58):

PS any feedback welcome. Over the summer I fully intend to expand that stuff into a more coherent and far-reaching tutorial for mathematicians, covering the naturals, the complexes, and various other ideas I have lying around.

Lukas (May 09 2019 at 08:59):

That should have been obvious...

Lukas (May 09 2019 at 09:01):

The Tutorial for the natural numbers is great, but as there are no solutions to the exercise I have to ask many questions.

Johan Commelin (May 09 2019 at 09:02):

That's how all of us have learnt Lean

Johan Commelin (May 09 2019 at 09:02):

Except for some magic wizards, who read the source code

Kevin Buzzard (May 09 2019 at 09:04):

@Lukas I wrote that tutorial and I had no solutions to the exercises either ;-) Some students at Imperial College sent me solutions and I did dump them somewhere on the internet...perhaps in the Xena project github repository (a.k.a. pile of random Lean files which I and some students wrote when we were all complete beginners 18 months ago).

Lukas (May 10 2019 at 11:17):

I just came across another problem. I defined the predicate for even like this:

definition even: xnat  Prop
| zero := true
| (succ m) := ¬ (even m)

but I can not figure out a way to test this #check even one does only show the Type prop but not the value. #reduce even zero leads as expected to true, but #reduce even one leads true → false which is false, but this becomes quickly unreadable as #reduce even two is (true → false) → false.

Kevin Buzzard (May 10 2019 at 11:30):

I think I would be tempted to define beven here, a function from xnat to bool, which is defined in Lean as {ff,tt}, and use bnot instead of not. Then you can define even to mean beven n = tt

Kevin Buzzard (May 10 2019 at 11:31):

PS you might have more luck with #eval than #reduce?

Lukas (May 10 2019 at 11:45):

The definition as function from xnat to Prop is taken from the blog article. With bool, bnot the definition works. Now my implementation look like this:

definition beven: xnat  bool
| zero := tt
| (succ m) :=  bnot (beven m)

definition even (m: xnat): Prop := beven m = tt

#reduce zero no gives me tt = tt and #reduce one gives tt = ff.

I am not yet clear if this is what I should expect. And why is the version returning a Prop better than to bool version?

Kevin Buzzard (May 10 2019 at 11:46):

I guess the author of the blog article was quite incompetent at that time.

Kevin Buzzard (May 10 2019 at 11:47):

To a mathematician, Prop and bool are difficult to tell apart. In Lean the key difference between them is that they sit in different places in the hierarchy. bool is a type, and Prop is a universe.

Kevin Buzzard (May 10 2019 at 11:47):

So in type theory, Prop is somehow a lot bigger than bool.

Kevin Buzzard (May 10 2019 at 11:48):

In type theory, there are universes, and then types in those universe, and then terms in those types. I say "in" because that's how I think of it, I guess type theorist would say "t has type T and T has type u" or something

Kevin Buzzard (May 10 2019 at 11:48):

Because they're quite different in the type theory world, they behave quite differently.

Kevin Buzzard (May 10 2019 at 11:49):

Both both definitions "work" and "give the right answer". I guess the big question is what you want to do with the definitions.

Kevin Buzzard (May 10 2019 at 11:49):

Let's stick with the Prop version for now, if the prestigious blog writer thinks that this is a good idea.

Kevin Buzzard (May 10 2019 at 11:49):

</sarcasm>

Kevin Buzzard (May 10 2019 at 11:50):

You can still try and prove that 2 is even

Kevin Buzzard (May 10 2019 at 11:50):

You've got to prove not not true

Kevin Buzzard (May 10 2019 at 11:50):

and that should be OK, because P implies not not P

Kevin Buzzard (May 10 2019 at 11:51):

and I can prove true, because that just means constructing a term of type true and I can look at the definition of true to find out what that term is called. Just write #check true and then right click on true and peek at the definition.

Kevin Buzzard (May 10 2019 at 11:51):

eew that is a rubbish name

Kevin Buzzard (May 10 2019 at 11:51):

that is a really confusing name

Kevin Buzzard (May 10 2019 at 11:52):

I think there's a tactic which proves true, called trivial or something

Maxim Gerspach (May 11 2019 at 14:13):

(deleted)

Kevin Buzzard (May 11 2019 at 16:53):

@Lukas your interest made me go back to that blog post and think about how I would have done it nowadays. I didn't think about even/odd but I did think about inequalities. Those 4 inequalities at the bottom were terrifically difficult. I didn't really know what I was doing at the time. I just tried various versions of le and lt, and I think that actually this is the best:

def le (a b : xnat) : Prop := ∃ c, a + c = b

Using this definition of le, it is not too hard to prove le versions of all the inequalities. And conversely, this one was by far the hardest to use:

inductive le : xnat → xnat → Prop
| refl (a : xnat) : le a a
| succ (a b : xnat) : le a b → le a (succ b)

Even proving a <= b implies succ a <= succ b was horrible with this; in the end I proved that this inductive le was the same as the easier-to-use le.

Kevin Buzzard (May 11 2019 at 17:13):

Another thing I noticed was that manipulating xnat is far more tedious than manipulating nat, because you constantly want stuff which is true but which I didn't prove -- stuff like succ a = succ b -> a = b, or a + b = a -> b = 0; the proofs are all easy, but they are not there.

Kevin Buzzard (May 11 2019 at 17:14):

I distinctly remember in 2017 firmly believing that every question about le on nat should almost by definition be completely trivial, because how can there even be any content?

Chris Hughes (May 11 2019 at 21:23):

@Kevin Buzzard maybe you weren't so stupid https://github.com/leanprover/lean4/blob/master/library/init/data/nat/basic.lean#L47

Patrick Massot (May 11 2019 at 21:24):

I think this version is good for computation

Patrick Massot (May 11 2019 at 21:24):

not for proofs

Kevin Buzzard (May 11 2019 at 21:24):

One thing I learnt today was that my cool inductive predicate idea seems to be the worst of them all

Chris Hughes (May 11 2019 at 21:52):

My attempt at the proof using the inductive definition. Pretty short, but it took me a while to work it out. I also used pred

open nat
namespace xnat
inductive le (a : ) :   Prop
| refl : le a
| succ :  b, le b  le (succ b)

infix ` ' `: 50 := le

lemma le_succ (a : ) : a ' succ a :=
le.succ _ (le.refl _)

lemma le_of_succ_le {a b : } (ha : succ a ' b) : a ' b :=
le.rec_on ha (le_succ _) (λ _ _, le.succ _)

lemma succ_le_succ {a b : } (h : succ a ' succ b) : a ' b :=
show a ' pred (succ b),
from le.rec_on h (le.refl _) (λ _ h _, le_of_succ_le h)

lemma le_trans {a b c : } (hab : a ' b) (hbc : b ' c) : a ' c :=
le.rec_on hbc hab (λ _ _, le.succ _)

Kevin Buzzard (May 11 2019 at 21:54):

Nice!

Chris Hughes (May 11 2019 at 21:55):

This does illustrate a difficulty with inductive predicates. They're hard to use when not applied directly to local constants.

Chris Hughes (May 11 2019 at 21:57):

When you induct you want the fact that succ b has something to do with b, but the computed motives rarely give you that.

Chris Hughes (May 11 2019 at 22:04):

If I was recursing on equality, it would be completely obvious to do something like the method I chose. Interesting how my intuition for the equality recursor is so much better than other predicates, yet they're not that different.

Chris Hughes (May 11 2019 at 22:05):

This has changed the way I think about induction.

Kevin Buzzard (May 11 2019 at 22:09):

It was my job as your M1F teacher to teach you induction, I'm glad you now understand it better than me ;-)

Kevin Buzzard (May 11 2019 at 22:10):

After my M1F induction lecture last year, someone came up to me at the end of the lecture and complained that they thought they understood induction when they came into the lecture but now they realised they were completely confused about it ;-)

Chris Hughes (May 11 2019 at 22:11):

It's so obvious now I think about it. If i had succ a = succ b, it's obviously completely useless to try and recurse on that until I have a succ b in my goal. same applies here.

Kevin Buzzard (May 11 2019 at 22:11):

What confused them was that I told them that proofs were finite in length by definition but if you think about the proof of P(100) which you get by induction, it looks like "P(0) is true, therefore P(1) is true, therefore P(2) is true...therefore P(100) is true", so maybe "forall n, P(n)" has infinite length and can't be a proof?

Chris Hughes (May 11 2019 at 22:13):

I guess it does without the axiom of infinity.

Chris Hughes (May 11 2019 at 22:15):

If you don't say induction is an axiom and instead give that as the explanation, then it is an infinite length proof.

Kevin Buzzard (May 11 2019 at 22:15):

This was in my introduction to proof lectures -- I guess you can feel like induction is obvious, and then you start thinking about it that way and then you realise that actually there's more to it than meets the eye.

Chris Hughes (May 11 2019 at 22:17):

There's a lot to it. Have you ever tried to prove eq_of_heq in term mode from axioms? It's really hard.

Kevin Buzzard (May 11 2019 at 22:18):

I have never tried doing anything with heq, mostly because I remember you going through a period several months ago where you were continually moaning about it!

matt rice (May 12 2019 at 07:41):

@Kevin Buzzard
That definition you gave

def le (a b : xnat) : Prop :=  c, a + c = b

Is the exact one used in Logic and Proof, chapter 17/18 i believe

Kevin Buzzard (May 12 2019 at 08:00):

I think that the inductive predicate is used in Lean 3 and the definition by cases is used in Lean 4

Neil Strickland (May 20 2019 at 13:21):

So it seems that Lean 4 defines the order and decidable equality on Nat via maps to Bool, but reverts to using the same kind of framework as Lean 3 for Int, list Nat and so on. Does anyone know why that is?

François G. Dorais (May 21 2019 at 21:10):

@Neil Strickland My best guess is that derived Bool equality hasn't been built into inductive types yet. It's pretty ubiquitous, so I'm pretty sure it will be built in eventually.


Last updated: Dec 20 2023 at 11:08 UTC