Skip to content

Commit 68b73ef

Browse files
committed
feat(tactic/tauto): handle or in goal
1 parent 7d6df1b commit 68b73ef

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

tactic/interactive.lean

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,46 @@ meta structure by_elim_opt :=
280280
meta def solve_by_elim (opt : by_elim_opt := { }) : tactic unit :=
281281
solve_by_elim_aux opt.discharger opt.restr_hyp_set opt.max_rep
282282

283+
theorem or_iff_not_imp_left {a b} [decidable a] : a ∨ b ↔ (¬ a → b) :=
284+
⟨or.resolve_left, λ h, dite _ or.inl (or.inr ∘ h)⟩
285+
286+
theorem or_iff_not_imp_right {a b} [decidable b] : a ∨ b ↔ (¬ b → a) :=
287+
or.comm.trans or_iff_not_imp_left
288+
289+
@[trans]
290+
lemma iff.trans {a b c} (h₁ : a ↔ b) (h₂ : b ↔ c) : a ↔ c :=
291+
iff.intro
292+
(assume ha, iff.mp h₂ (iff.mp h₁ ha))
293+
(assume hc, iff.mpr h₁ (iff.mpr h₂ hc))
294+
295+
theorem imp.swap {a b c : Prop} : (a → b → c) ↔ (b → a → c) :=
296+
⟨function.swap, function.swap⟩
297+
298+
theorem imp_not_comm {a b} : (a → ¬b) ↔ (b → ¬a) :=
299+
imp.swap
300+
301+
theorem not_and_of_not_or_not {a b} (h : ¬ a ∨ ¬ b) : ¬ (a ∧ b)
302+
| ⟨ha, hb⟩ := or.elim h (absurd ha) (absurd hb)
303+
304+
theorem not_and_distrib {a b} [decidable a] : ¬ (a ∧ b) ↔ ¬a ∨ ¬b :=
305+
⟨λ h, if ha : a then or.inr (λ hb, h ⟨ha, hb⟩) else or.inl ha, not_and_of_not_or_not⟩
306+
307+
theorem not_and_distrib' {a b} [decidable b] : ¬ (a ∧ b) ↔ ¬a ∨ ¬b :=
308+
⟨λ h, if hb : b then or.inl (λ ha, h ⟨ha, hb⟩) else or.inr hb, not_and_of_not_or_not⟩
309+
310+
theorem not_or_distrib {a b} : ¬ (a ∨ b) ↔ ¬ a ∧ ¬ b :=
311+
⟨λ h, ⟨λ ha, h (or.inl ha), λ hb, h (or.inr hb)⟩,
312+
λ ⟨h₁, h₂⟩ h, or.elim h h₁ h₂⟩
313+
314+
315+
meta def de_morgan_hyps : tactic unit :=
316+
do hs ← local_context,
317+
hs.for_each $ λ h,
318+
replace (some h.local_pp_name) none ``(not_and_distrib'.mp %%h) <|>
319+
replace (some h.local_pp_name) none ``(not_and_distrib.mp %%h) <|>
320+
replace (some h.local_pp_name) none ``(not_or_distrib.mp %%h) <|>
321+
skip
322+
283323
/--
284324
`tautology` breaks down assumptions of the form `_ ∧ _`, `_ ∨ _`, `_ ↔ _` and `∃ _, _`
285325
and splits a goal of the form `_ ∧ _`, `_ ↔ _` or `∃ _, _` until it can be discharged
@@ -289,12 +329,16 @@ meta def tautology : tactic unit :=
289329
repeat (do
290330
gs ← get_goals,
291331
() <$ tactic.intros;
332+
de_morgan_hyps,
292333
casesm (some ()) [``(_ ∧ _),``(_ ∨ _),``(Exists _),``(false)];
293334
constructor_matching (some ()) [``(_ ∧ _),``(_ ↔ _),``(true)],
335+
try (refine ``( or_iff_not_imp_left.mpr _)),
336+
try (refine ``( or_iff_not_imp_right.mpr _)),
294337
gs' ← get_goals,
295338
guard (gs ≠ gs') ) ;
296339
repeat
297-
(reflexivity <|> solve_by_elim <|> constructor_matching none [``(_ ∧ _),``(_ ↔ _),``(Exists _)]) ;
340+
(reflexivity <|> solve_by_elim <|>
341+
constructor_matching none [``(_ ∧ _),``(_ ↔ _),``(Exists _)] ) ;
298342
done
299343

300344
/-- Shorter name for the tactic `tautology`. -/

tests/examples.lean

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,7 @@ end
9797

9898
example (p : Prop) : p ∧ true ↔ p := by tauto
9999

100-
example (p : Prop) : p ∨ false → p := by tauto
100+
example (p : Prop) : p ∨ false ↔ p := by tauto
101+
-- local attribute [instance] classical.prop_decidable
102+
example (p q r : Prop) [decidable p] [decidable r] : p ∨ (q ∧ r) ↔ (p ∨ q) ∧ (r ∨ p ∨ r) := by tauto
103+
example (p q r : Prop) [decidable q] [decidable r] : p ∨ (q ∧ r) ↔ (p ∨ q) ∧ (r ∨ p ∨ r) := by tauto

0 commit comments

Comments
 (0)