Zulip Chat Archive

Stream: new members

Topic: Force extra condition with `choice`?


Jacob Weightman (Feb 18 2025 at 23:36):

Currently studying a deterministic string rewriting system, and I want to prove that a rewriting system either halts, loops, or produces ever increasingly long strings. I have a "completed" proof, except for a small hole. The idea is that if the system doesn't diverge on a string, there must be a string that repeats since the length of strings is bounded. The problem is that the way I'm applying the axiom of choice and pigeonhole principle doesn't give me a way to prove that j i₁ ≠ j i₂. I wonder if there's a way to make a "better" choice without loss of generality, or maybe there's a way to use a different PHP theorem like Finite.exists_infinite_fiber to obtain the stronger condition I need. Perhaps one of the kind Lean experts here could point me in the right direction to fix my proof?

def ShortList (α : Type u) (n : ) :=
  { l : List α // l.length  n }

instance ShortList.finite {α : Type u}{n : } [Finite α] : Finite (ShortList α n) :=
  List.finite_length_le α n

theorem not_diverges'_halts_or_loops (A : List α)
    : ¬T.diverges' A  T.halts A  T.loops A := by
  -- `T.diverges A := ∀n : ℕ, ∃i : ℕ, ∀j > i, (T.next^[j] A).length > n`
  -- so `¬T.diverges A ↔ ∃n : ℕ, ∀i : ℕ, ∃j > i, (T.next^[j] A).length ≤ n`
  intro h
  simp [diverges'] at h

  have h₁ : i₁ i₂, i₁  i₂  T.next^[i₁] A = T.next^[i₂] A := by
    -- `h` says that there's some string length `n` such that after any number of steps `i`, we can
    -- find another number of steps `j > i` such that the length of the resulting string is less
    -- than `n`. Use the axiom of choice to obtain `j : ℕ → ℕ`, which gives the index of a
    -- subsequent short string from a previous one.
    choose n j h using h

    -- With this function j, we have an infinite sequence of indices of strings shorter than `n`, of
    -- which there are finitely many. By the pigeonhole principle, some string must repeat.
    let f :   ShortList α n := fun (i : ) 
      let l := T.next^[j i] A
      have π : l.length  n := (h i).right
      l, π
    let h3 := Finite.exists_ne_map_eq_of_infinite f
    let A', h3' := Finite.exists_infinite_fiber f

    -- Let `i₁ i₂ : ℕ` such that `j i₁` and `j i₂` are indices which produce a repeated string.
    choose i₁ i₂ h3 using h3
    let h4, h5 := h3; clear h3
    have h6 : T.next^[j i₁] A = T.next^[j i₂] A := by
      simp [f] at h5
      rw [ Subtype.val_inj] at h5
      assumption

    -- TODO: we have that i₁ ≠ i₂, but the current use of axiom of choice and pigeonhole principle
    -- doesn't guarantee j i₁ ≠ j i₂. It should be possible to force such a choice, but I'm not sure
    -- how to do this in Lean...
    have h7 : j i₁  j i₂ := by sorry

    exists j i₁
    exists j i₂

  clear h
  choose i₁ i₂ h₁ h₂ using h₁
  wlog h₃ : i₁ < i₂
  · simp at h₃; rw [ne_comm] at h₁; rw [eq_comm] at h₂
    apply this A i₂ i₁ h₁ h₂ (Nat.lt_of_le_of_ne h₃ h₁)

  -- At this point, we must have either halted or found a loop. We can tell these cases apart easily
  -- by checking if the length of the string is less than `T.v`.
  cases Nat.lt_or_ge (T.next^[i₁] A).length T.v with
  | inl h₄ => left; exists i₁
  | inr h₄ =>
      right
      exists i₁
      exists i₂ - i₁
      constructor
      · simp; assumption
      · have h₁' : i₁  i₂ := Nat.le_of_lt h₃
        constructor
        · simp; exact h₃
        · rw [ Function.iterate_add_apply, Nat.sub_add_cancel h₁', h₂]

Matt Diamond (Feb 18 2025 at 23:49):

Could you include the definition of T and any imports? It's easier for people to help when it's a #mwe

Aaron Liu (Feb 18 2025 at 23:53):

Could you use Finite.exists_ne_map_eq_of_infinite (f ∘ j) instead and then use that j is strictly monotone (therefore injective) to get that j i₁ ≠ j i₂?

Aaron Liu (Feb 19 2025 at 00:03):

You have a docs#Filter.extraction_of_frequently_atTop' statement. Extract a function that indexes your short strings, instead of having a function that finds the next one. This will make it easier to prove stuff, because the new function is injective.

Jacob Weightman (Feb 20 2025 at 05:04):

Thank you so much @Aaron Liu , docs#Filter.extraction_of_frequently_atTop' did exactly what I needed it to do!


Last updated: May 02 2025 at 03:31 UTC