Zulip Chat Archive

Stream: new members

Topic: Proofs involving negation


Noob (May 06 2020 at 14:30):

Hi all,
I'm going through "Logic and Proof" and "Theorem Proving in Lean" exercises and got stuck on the ones that make use of negation.
Could someone outline the line of reasoning ivolved in proving something like

variables A B : Prop
example (h: ¬A  ¬B) : ¬(A  B) := sorry

?
With conjunction, disjunction and implication I usually start with a corresponding introduction rule and the rest follows naturally, but can't wrap my head around how to apply the same strategy to negation.

Kevin Buzzard (May 06 2020 at 14:31):

not X is just syntax sugar for X -> false if that helps

Kevin Buzzard (May 06 2020 at 14:32):

variables A B : Prop
example (h: ¬A  ¬B) : ¬(A  B) :=
begin
  cases h with hnA hnB,
  intro hAB,
  cases hAB with hA hB,
  { contradiction},
  { contradiction},
end

Patrick Massot (May 06 2020 at 14:32):

If you don't mind using tactics then you can follow the tutorials project. It has several files about negation, starting with https://github.com/leanprover-community/tutorials/blob/master/src/exercises/07_first_negations.lean

Kevin Buzzard (May 06 2020 at 14:33):

variables A B : Prop
example (h: ¬A  ¬B) : ¬(A  B) :=
h.elim $ λ hnA hnB hAB, hAB.elim hnA hnB

Noob (May 06 2020 at 14:47):

I'm not familiar with the cases and intro syntax yet, but I suppose it's equavalent to

  example (h: ¬A  ¬B) : ¬(A  B) :=
    have hnA : ¬A, from h.left,
    have hnB : ¬B, from h.right,
    λ hAB : A  B,

Is that correct?

Noob (May 06 2020 at 14:49):

I'd prefer not use tactics at this point, but do everything manually. Want to understand what is really going on.

Marc Huisinga (May 06 2020 at 14:51):

you probably meant λ hAB : A ∨ B,, but other than that you're right.

Noob (May 06 2020 at 15:04):

Correct. So here

  example (h: ¬A  ¬B) : ¬(A  B) :=
    have hnA : ¬A, from h.left,
    have hnB : ¬B, from h.right,
    λ hAB : A  B,

we have destructured our hypothesis such that each part can be referred to individually, we introduced a new hypothesis which is a negation of what needs to be proven.
Do we need the new hypothesis so we can arrive at a contradiction? I don't see how if so.

Marc Huisinga (May 06 2020 at 15:07):

try eliminating hAB and see if you can then derive false in both cases of the elimination.

Kevin Buzzard (May 06 2020 at 15:14):

I wrote hAB.elim but this is using some cunning dot notation. You can also write or.elim hAB

Noob (May 06 2020 at 15:38):

Thanks for the hints, I managed to prove it like this:

  example (h: ¬A  ¬B) : ¬(A  B) :=
    have hnA : ¬A, from h.left,
    have hnB : ¬B, from h.right,
    λ hAB : A  B,
      or.elim hAB
        (λ hA, absurd hA hnA)
        (λ hB, absurd hB hnB)

Still can't figure out why this

  example (h: ¬A  ¬B) : ¬(A  B) :=
    have hnA : ¬A, from h.left,
    have hnB : ¬B, from h.right,
    λ hAB : A  B,
      or.elim hAB
        (λ hA : A, false.elim (hnA hA))
        (λ hB : B, false.elim (hnB hB))

doesn't work - it looks the same to me.

Marc Huisinga (May 06 2020 at 15:52):

works for me. note that you don't actually need false.elim or absurd because you're trying to prove false itself.

Noob (May 06 2020 at 16:01):

Actually, it works for me too - VS Code got me confused.
With your latest suggestion the proof looks like this:

  example (h: ¬A  ¬B) : ¬(A  B) :=
    have hnA : ¬A, from h.left,
    have hnB : ¬B, from h.right,
    λ hAB : A  B,
      or.elim hAB
        (λ hA, hnA hA)
        (λ hB, hnB hB)

Thanks a lot for the help!

Marc Huisinga (May 06 2020 at 17:20):

another small trick: after using (λ hA, hnA hA) = hnA, your proof will look pretty similar to kevin's.

Filippo A. E. Nuccio (May 14 2020 at 14:52):

I am try to prove that 1 \ne 0. I can apply simp, and lean is happy. But I wanted to do it step-by-step.
To my knowledge, this should be an axiom (if these 1 and 0 were natural numbers, at least: but I believe that Lean has been taught that 0 : \R is the same as 0 : N; and likewise for 1). At any rate, I have tried
begin intro h,
and now should deduce from h: 1=0 that false
And I am stuck, both in performing the proof and in observing that if I try simp now, Lean is no longer happy.

Patrick Massot (May 14 2020 at 14:55):

https://xenaproject.wordpress.com/2018/03/24/no-confusion-over-no_confusion/ may help

Filippo A. E. Nuccio (May 14 2020 at 14:58):

Seems a long read: I will try to digest the whole of it. Thanks.

Johan Commelin (May 14 2020 at 14:58):

@Filippo A. E. Nuccio That blogpost is good. But here is another approach, to figure things out yourself: you turn your first simp into squeeze_simp to see what it did. Then, you get that lemma name (probably nat.zero_ne_one) and write

#print nat.zero_ne_one

After that, you can right-click on it, and "Go to definition".

Filippo A. E. Nuccio (May 14 2020 at 14:59):

ah! the squeeze_simp is the gadget I was dreaming of! tnx

Johan Commelin (May 14 2020 at 14:59):

Then you can see how it's proven. And you'll find the no_confusion thing yourself. End result: you will ask a question here about no_confusion and still get pointed to the blogpost. :grinning_face_with_smiling_eyes:

Johan Commelin (May 14 2020 at 15:03):

@Filippo A. E. Nuccio Yup, squeeze_simp is amazing. There is also library_search, suggest, hint, and tidy? that are useful tools.

Johan Commelin (May 14 2020 at 15:04):

We should rename squeeze_simp to simp? now that we have forked lean.

Reid Barton (May 14 2020 at 15:04):

No, we should make simp? do the more useful thing

Johan Commelin (May 14 2020 at 15:04):

Which is?

Reid Barton (May 14 2020 at 15:05):

described here

Mario Carneiro (May 14 2020 at 16:34):

I disagree that this is the more useful thing. I find myself using squeeze_simp a lot more than actually trying to understand the list of rewrites. How about simp? for squeeze_simp and simp?? for simp with trace enabled?

Mario Carneiro (May 14 2020 at 16:34):

I really like the idea of a one character diff from simp to squeeze_simp

Jalex Stark (May 14 2020 at 16:35):

I would have broken my nonterminal simp habit faster if it were one character

Reid Barton (May 14 2020 at 16:59):

Does ‽ count as one character?

Reid Barton (May 14 2020 at 16:59):

I've never used squeeze_simp

Johan Commelin (May 14 2020 at 17:03):

@Reid Barton You do have sliced bread, do you?

Reid Barton (May 14 2020 at 17:07):

I guess I don't really understand what it's for

Reid Barton (May 14 2020 at 17:07):

aside from making proofs run faster, which I don't care terribly much about

Mario Carneiro (May 14 2020 at 17:22):

I care about making proofs faster even before I've finished writing them

Mario Carneiro (May 14 2020 at 17:23):

if I start off my proof with simp * then that call is going to slow down the entire interaction cycle for the rest of the proof

Reid Barton (May 14 2020 at 17:23):

I guess I also don't really use simp that much, or when I do use it experimentally I want to replace it with rw, not simp only

Johan Commelin (May 14 2020 at 17:24):

Right, I use squeeze_simp for that

Johan Commelin (May 14 2020 at 17:24):

To figure out what should go in the rw

Reid Barton (May 14 2020 at 17:24):

But then don't you still have to solve a puzzle?

Reid Barton (May 14 2020 at 17:24):

While the rewrite trace would just tell you the answer?

Johan Commelin (May 14 2020 at 17:24):

Sure, but at least I know what the pieces are

Mario Carneiro (May 14 2020 at 17:24):

I often convert squeeze_simp calls to rw as well

Reid Barton (May 14 2020 at 17:25):

I think maybe you are the one without sliced bread? :upside_down:

Mario Carneiro (May 14 2020 at 17:25):

I still want an auto-replace, not a tactic trace

Johan Commelin (May 14 2020 at 17:25):

A simp?? that outputs Try this: rw [foo, bar, bar, ← quux, foo] would be awesome.

Mario Carneiro (May 14 2020 at 17:25):

but it would be nice if the order that lemmas are printed matches the rewrite order

Mario Carneiro (May 14 2020 at 17:26):

I think simp? could print both

Johan Commelin (May 14 2020 at 17:26):

Of course simp only is more powerful than rw, so you can't always get what you want, right?

Mario Carneiro (May 14 2020 at 17:26):

also rw has to repeat lemmas and simp only doesn't, and simp only works under binders

Mario Carneiro (May 14 2020 at 17:26):

so it's not always going to work

Mario Carneiro (May 14 2020 at 17:27):

but I think even the simp only proof fails sometimes

Johan Commelin (May 14 2020 at 17:28):

Yup, although it got a lot less rare

Bryan Gin-ge Chen (May 14 2020 at 17:29):

simp? which offers both simp only and rw options would be lovely. What do we have to do to make it happen?

Scott Morrison (May 17 2020 at 04:22):

If we finish moving rewrite_search to mathlib, one possible mechanism for creating the rw suggestion would be to take the current output from squeeze_simp and pass that as the list of allowed lemmas to rewrite_search. That will automatically take care of generating the rw statement.


Last updated: Dec 20 2023 at 11:08 UTC