Zulip Chat Archive

Stream: new members

Topic: Basic logic by splitting truth cases


Valentin Vinoles (Oct 29 2023 at 10:36):

Hello

I am trying to prove some basic logic results with Lean. Currently I am working on P ↔ ¬¬P. I managed to prove it coming back to the definition of the negation (i.e ¬Q is defined to be Q → False). I want to know if it is possible to prove P ↔ ¬¬P by splitting cases like this :

  • Assume PP is true. Then ¬P\neg P is false. Then ¬¬P\neg \neg P is true.
  • Assume PP is false Then ¬P\neg P is true. Then ¬¬P\neg \neg P is false.

I am interested for something like that because it would be closer to what an undergraduate student would do. More generally, I would like to know if this approach "splitting truth cases" is doable in Lean to prove some basic logic results.

Thanks !

Yaël Dillies (Oct 29 2023 at 10:38):

by_cases hp : p will do the case split you're looking for.

Valentin Vinoles (Oct 29 2023 at 11:29):

Thanks ! But I am not sure how to do it. I would start like this :

example (P : Prop) : P  ¬¬P := by
  by_cases h_P : P
  · sorry
  · sorry

In the first case, the goal is ⊢ P ↔ ¬¬P, I am not sure what I have gained here ?

Yaël Dillies (Oct 29 2023 at 11:41):

This time you have h_P : P in context

Ruben Van de Velde (Oct 29 2023 at 11:54):

Next step could be apply iff_of_true

Valentin Vinoles (Oct 29 2023 at 14:09):

Thanks to you two, I manage to do some progress !

Another question, I am now working on (P    Q)    (¬Q    ¬P)(P \implies Q) \iff (\neg Q \implies \neg P). I alreay did the direct implication part and I would like to use this direct implication to ¬Q\neg Q and ¬P\neg P to conclude:

example (P : Prop)(Q : Prop) : (P  Q)  (¬Q  ¬P) := by
  constructor
  · sorry -- proof of (P → Q) → (¬Q → ¬P) (already done)
  · intro h
   -- here I would like to apply the first case to ¬Q and ¬P

How can I reuse the first case?

Luigi Massacci (Oct 29 2023 at 14:33):

If I understood correctly you want to do something like this:

theorem contrap1 (P Q : Prop) : (P  Q)   (¬Q  ¬P) := fun pq nq p  nq (pq p)

example (P : Prop)(Q : Prop) : (P  Q)  (¬Q  ¬P) := by
  constructor
  · apply contrap1
    -- alternatively:
    -- exact contrap1 P Q
    -- or even let it instantiate the quantifiers on its own:
    -- exact contrap1 _ _
  · intro h
    have h₁ := contrap1 (¬Q) (¬P) h -- this adds the hypothesis h₁ : ¬¬P → ¬¬Q
    -- like above, you could do contrap1 _ _ h

Notification Bot (Oct 29 2023 at 18:29):

Valentin Vinoles has marked this topic as resolved.

Valentin Vinoles (Oct 29 2023 at 18:29):

thanks !

Notification Bot (Oct 29 2023 at 20:29):

Valentin Vinoles has marked this topic as unresolved.

Valentin Vinoles (Oct 29 2023 at 20:47):

Sorry for my very naive questions but I have trouble to find answers online.

During a proof involving two propositions P and Q, I have a proof h of P ∧ Q and a proof h' of ¬ P. I would like to apply h' to P but apply h' at h.left do not work, I don't understand why.

Maybe I need to declare explicitly a proof h_P of P and write apply h' at h_P but I do not know how...

Lessness (Oct 29 2023 at 20:55):

variable (P Q: Prop)
variable (h: P  Q)
variable (h': ¬ P)

#check (h' h.left)

Inside the proof with tactics you can write set F := h' h.left.

Lessness (Oct 29 2023 at 20:57):

I believe there's no way to applyat something that's not a goal. (I may be wrong.)

Valentin Vinoles (Oct 29 2023 at 21:17):

Thanks a lot, it works with set !

Ruben Van de Velde (Oct 29 2023 at 22:08):

There's some work on using apply with hypotheses, though I don't know if it landed yet. It would never work in this case, though

Valentin Vinoles (Oct 30 2023 at 09:08):

Another question :sweat_smile:

I am playing around with False.elim. If h : False and P : Prop, how can I deduce a proof of P. I can do the following:

example (P : Prop) : False  P := by
  intro h                                   -- h : False
  apply False.elim at h

but the issue is that h is now a proof of ?C (I am not sure what it is...). How can I change it to make a proof of P?

Damiano Testa (Oct 30 2023 at 09:13):

You can do

  change P at h

While this works, I find this way of arguing a little unusual, though!

Damiano Testa (Oct 30 2023 at 09:14):

The ?C that you see is a metavariable and with change P at h you tell Lean that you want it to unify with P.

Valentin Vinoles (Oct 30 2023 at 09:29):

Thank you it works !

I know it is unusual, it is just playing around to understand how things work. I do not plan to use it in "real" proofs.

Is there a way to do it in one line, something like apply False.elim P at h (this does not work).

Damiano Testa (Oct 30 2023 at 09:35):

After intro h, you can do exact?. Alternatively, also cases h works. Or even, the whole proof could be rintro ⟨⟩.

Valentin Vinoles (Oct 30 2023 at 09:38):

I mean a one line to merge

apply False.elim at h
change P at h

Notification Bot (Oct 30 2023 at 09:38):

A message was moved here from #new members > CompactIccSpace for unitInterval by Valentin Vinoles.

Ruben Van de Velde (Oct 30 2023 at 09:45):

Either of these would make more sense than using apply here:

example (P : Prop) : False  P := by
  intro h                                   -- h : False
  have : P := False.elim h
  exact False.elim h

You don't need to use the apply tactic in every situation where you're use the verb "apply" in mathematical English

Damiano Testa (Oct 30 2023 at 09:47):

In fact, I would say that almost always the tactic apply is translated to it suffices.

You can though do this

  apply False.elim (C := P) at h

as well.

Valentin Vinoles (Oct 30 2023 at 10:02):

Thank to you two. I already write a lof of stuffs with apply everywhere... I guess I need to rework all of these. The learning curve is quite stiff !

Valentin Vinoles (Oct 30 2023 at 10:06):

I guess this is bad ?

theorem not_not_direct (P : Prop) : P  ¬¬P := by
  intro h                  -- h : P
  apply Not.intro          -- goal becomes ¬P → False
  intro h_notP             -- h : ¬P (i.e. h : P → False)
  apply h_notP at h        -- h : False
  exact h

Luigi Massacci (Oct 30 2023 at 10:12):

I’m not an authority, but I would have written

theorem not_not_direct (P : Prop) : P  ¬¬P := by
  intro p np
  exact np p

or if you really want to use apply:

theorem not_not_direct (P : Prop) : P  ¬¬P := by
  intro p np
  apply np
  exact p

Kevin Buzzard (Oct 30 2023 at 11:54):

Ruben Van de Velde said:

There's some work on using apply with hypotheses, though I don't know if it landed yet. It would never work in this case, though

Right. I think that apply at has now landed, but you cannot apply a hypothesis to h.left and expect only h.left to change. You need to do cases on h first, extract the left component as h_1 and then apply h' to h_1.

Kevin Buzzard (Oct 30 2023 at 11:56):

Valentin Vinoles said:

I mean a one line to merge

apply False.elim at h
change P at h

import Mathlib.Tactic

example (P : Prop) : False  P := by
  rintro ⟨⟩

Kevin Buzzard (Oct 30 2023 at 11:57):

Valentin Vinoles said:

I guess this is bad ?

theorem not_not_direct (P : Prop) : P  ¬¬P := by
  intro h                  -- h : P
  apply Not.intro          -- goal becomes ¬P → False
  intro h_notP             -- h : ¬P (i.e. h : P → False)
  apply h_notP at h        -- h : False
  exact h

How about

theorem not_not_direct (P : Prop) : P  ¬¬P := fun h h1  h1 h

Last updated: Dec 20 2023 at 11:08 UTC