Zulip Chat Archive

Stream: mathlib4

Topic: Dealing with multiple goals


Gareth Ma (Oct 26 2023 at 18:12):

Hi, is there any way to make this less tedious:

example {P : Nat  Prop} {f : Nat  Nat}
    (h1 : 1  n) (h2 : n  2)
    (p1 : P 7) (p2 : P 9)
    (f1 : f 1 = 7) (f2 : f 2 = 9):
     (s : Finset Nat), n  s  s.card = n  P (f n) := by
  interval_cases n
  · use {1}    ; constructor ; trivial ; constructor ; trivial ; rwa [f1]
  · use {1, 2} ; constructor ; trivial ; constructor ; trivial ; rwa [f2]

You can see there is a lot of repetition in the middle (constructor ; trivial ; constructor ; trivial), but they are also surrounded by other commands so I can't use <;> at the start.

Gareth Ma (Oct 26 2023 at 18:14):

I came up with something like this:

example {P : Nat  Prop} {f : Nat  Nat}
    (h1 : 1  n) (h2 : n  2)
    (p1 : P 7) (p2 : P 9)
    (f1 : f 1 = 7) (f2 : f 2 = 9):
     (s : Finset Nat), n  s  s.card = n  P (f n) := by
  interval_cases n
  use {1}
  rotate_left
  use {1, 2}
  all_goals
    constructor
    trivial
    constructor
    trivial
    simp only [*]

But the rotate_left still feels a bit annoying to use.

Gareth Ma (Oct 26 2023 at 18:14):

(Sorry if I sound like I am just complaining, I don't mean it that way :D)

Kyle Miller (Oct 26 2023 at 18:18):

How about this?

import Mathlib.Tactic.IntervalCases
import Mathlib.Data.Finset.Card

set_option autoImplicit true

example {P : Nat  Prop} {f : Nat  Nat}
    (h1 : 1  n) (h2 : n  2)
    (p1 : P 7) (p2 : P 9)
    (f1 : f 1 = 7) (f2 : f 2 = 9):
     (s : Finset Nat), n  s  s.card = n  P (f n) := by
  interval_cases n <;> simp only [f1, f2, p1, p2, and_true]
  · use {1}; simp
  · use {1, 2}; simp

Gareth Ma (Oct 26 2023 at 18:19):

Ahh that works for this case, but not for my actual use case (I simplified too much :joy:) Let me simplify and share mine real quick

Kyle Miller (Oct 26 2023 at 18:19):

This is sort of silly, but just to mention this feature you can also use the discharger for use

example {P : Nat  Prop} {f : Nat  Nat}
    (h1 : 1  n) (h2 : n  2)
    (p1 : P 7) (p2 : P 9)
    (f1 : f 1 = 7) (f2 : f 2 = 9):
     (s : Finset Nat), n  s  s.card = n  P (f n) := by
  interval_cases n
  · use (discharger := simp [*]) {1}
  · use (discharger := simp [*]) {1, 2}

The use (discharger := simp [*]) {1} is roughly the same as use {1} <;> simp [*]

Gareth Ma (Oct 26 2023 at 18:20):

Gareth Ma said:

Ahh that works for this case, but not for my actual use case (I simplified too much :joy:) Let me simplify and share mine real quick

Actually, maybe a better idea is for me to finish my proof in the tedious way, then ask for golfing :)

Gareth Ma (Oct 26 2023 at 19:00):

It's here. This is quite long, but making it shorter kinda risk losing the idea.
I am trying to prove A11, which asks to construct a BXB \subseteq X such that some condition holds.
My construction depends on hm1 and hm2 on line 26, but it's always either BB or $$B \union \{m\}$$, both of which is always a subset of XX. As annotated with (1) and (3), there's a lot of repetition in the proof, and I was wondering if that's necessary

Gareth Ma (Oct 26 2023 at 19:01):

If you don't have time for it, it's fine and not urgent, I just copy and paste a few times for now :D

Gareth Ma (Oct 26 2023 at 19:03):

Screenshot-2023-10-26-at-20.02.12.png
Here's the proof being formalised, specifically the part with "For each element xXx \in X, ..., this procedure will not change the divisibility condition of xx".

Kyle Miller (Oct 26 2023 at 19:14):

A very small thing: if you want to save a constructor here and there, you can do use B' ∪ {m}, ?_, ?_ for example.

Kyle Miller (Oct 26 2023 at 19:22):

Here's a bit of deduplication:

code

Kyle Miller (Oct 26 2023 at 19:26):

I'd say don't worry about duplication of tactic scripts, since they mean different things each time. I wouldn't recommend doing this since it makes the proof unreadable, but just to mention it you could use all_goals and first, assuming that sorry really will be the same script between the two cases:

theorem A11 (hX : 0  X) (hA : A  X) :  B, B  X  Pred B X = A := by
  induction' X using ind_min with m X hm hind generalizing A
  · use  ; simp [Pred, subset_empty.mp hA]
  · set A' := A.filter (fun x  x  m) with hA'
    let B', hB'₁, hB'₂⟩⟩ := hind A' (by sorry) (by sorry)
    /- We construct B as B' or B' ∪ {m} -/
    rw [Pred] at hB'₂
    have hB' := subset_trans hB'₁ $ subset_cons $ min_not_mem hm
    by_cases hm₁ : m  A <;> by_cases hm₂ : (PredElement B' m)
    all_goals
      first
      | · use B', hB'
          simp only [Pred, filter_cons, hm₂, ite_true, hB'₂, disjUnion_eq_union]
          nth_rewrite 2 [filter_union_filter_neg_eq (fun x => x = m) A]
          congr
          simp only [filter_eq', hm₁, ite_true]
      | · use B'  {m}, ?_, ?_
          · apply union_subset hB'
            rw [singleton_subset_iff]
            apply mem_cons_self
          · sorry

Gareth Ma (Oct 26 2023 at 19:29):

Ah, your point about code readability is also true. I will worry less about it then! I will study your code. Thanks!

Gareth Ma (Oct 26 2023 at 20:35):

I got the final proof, it's pretty terrible :P


Last updated: Dec 20 2023 at 11:08 UTC