Zulip Chat Archive

Stream: general

Topic: multiple disjunction elimination


Bernd Losert (Dec 05 2021 at 13:59):

If you have multiple hypotheses:

h : p  q
h' : p'  q'
h'' : p''  q''

how would I combine them into a disjunction of conjuncts (p ∧ p' ∧ p'') ∨ ...? And how do you eliminate such a large disjuction? I hope I won't have to resort to writing deeply nested code.

Yaël Dillies (Dec 05 2021 at 14:22):

One way to do it is to use the ; combinator:

obtain (h | h) := h; obtain (h' | h') := h'; obtain (h'' | h'') := h'',

Huỳnh Trần Khanh (Dec 05 2021 at 14:27):

another option is to use... the tauto tactic! for simple 1st order logic goals, tauto is great :smiley::+1:

Bernd Losert (Dec 05 2021 at 14:32):

Yaël Dillies said:

One way to do it is to use the ; combinator:

obtain (h | h) := h; obtain (h' | h') := h'; obtain (h'' | h'') := h'',

I don't understand that syntax. Is there a how-to or a tutorial explaining how to do this?

Eric Wieser (Dec 05 2021 at 14:36):

Another way is to use all_goals:

import tactic

lemma split_three_ors (p p' p'' q q' q'' : Prop) (h : p  q) (h' : p'  q') (h'' : p''  q'') :
  ((p  p'  p''  p  p'  q'') 
   (p  q'  p''  p  q'  q'')) 
  ((q  p'  p''  q  p'  q'') 
   (q  q'  p''  q  q'  q'')) :=
begin
  -- `tauto` probably works but is _very_ slow,
  obtain h | h := h; [left, right],
  all_goals { obtain h' | h' := h'; [left, right] },
  all_goals { obtain h'' | h'' := h''; [left, right], },
  all_goals { exact h, h', h''⟩}
end

Huỳnh Trần Khanh (Dec 05 2021 at 14:37):

Bernd Losert said:

Yaël Dillies said:

One way to do it is to use the ; combinator:

obtain (h | h) := h; obtain (h' | h') := h'; obtain (h'' | h'') := h'',

I don't understand that syntax. Is there a how-to or a tutorial explaining how to do this?

this is the ultimate guide on tactics https://leanprover-community.github.io/mathlib_docs/tactics.html. ; is a tactic combinator and you can read about tactic combinators here https://leanprover.github.io/theorem_proving_in_lean/tactics.html#tactic-combinators

Eric Wieser (Dec 05 2021 at 14:39):

The other thing to note is that | is part of the obtain syntax, which is the same as its meaning in rcases and rintro

Bernd Losert (Dec 05 2021 at 14:44):

Thanks guys. I'll grep mathlib to find examples that I can copy/paste.

Mario Carneiro (Dec 06 2021 at 06:23):

Also, obtain supports multiple destruction like so: obtain ⟨h | h, h' | h', h'' | h''⟩ := ⟨h, h', h''⟩. Thus:

lemma split_three_ors (p p' p'' q q' q'' : Prop) (h : p  q) (h' : p'  q') (h'' : p''  q'') :
  ((p  p'  p''  p  p'  q'') 
   (p  q'  p''  p  q'  q'')) 
  ((q  p'  p''  q  p'  q'') 
   (q  q'  p''  q  q'  q'')) :=
begin
  obtain h | h, h' | h', h'' | h'' := h, h', h''⟩,
  all_goals { simp [h, h', h''] }
end

Mario Carneiro (Dec 06 2021 at 06:26):

Regarding tauto being slow: I am not sure why, this is a fairly trivial problem. itauto is quite fast on this problem

Kyle Miller (Dec 06 2021 at 06:27):

tauto doesn't seem to work for me with split_three_ors, but finish does work (somewhat slowly)

Mario Carneiro (Dec 06 2021 at 06:28):

(itauto also produces exactly the proof term you would write by hand, which I like to see)

Eric Wieser (Dec 06 2021 at 08:26):

Mario, does the ⟨h, h', h''⟩ there create an and term? Or is it special notation that obtain parses directly?

Mario Carneiro (Dec 06 2021 at 10:55):

@Eric Wieser It is special notation. (That notation would never parse normally, since the expected type is not known.) rcases is mutually recursive with a variation called rcases_many which handles many patterns at once (you need this to handle the list of subpatterns once you match a given n-ary pattern), and this is the surface level syntax to call rcases_many directly.

Bhavik Mehta (Dec 06 2021 at 18:37):

You can also do cases_matching* [_ ∨ _],


Last updated: Dec 20 2023 at 11:08 UTC