Zulip Chat Archive

Stream: new members

Topic: David Philipps


David Philipps (May 06 2025 at 16:37):

Hi there, my Name is David and I am thinking about starting to use Lean in my mathematical work. I wrote paper in Structural Graph Theory (https://arxiv.org/abs/2502.15396), featuring versions of the Cops and Robbers game and some monotonicity results, that I would like to formalize. My goal is to learn Theorem Proving in the process and I have some questions from the start:

  1. Is Lean the right tool? Should I look into alternatives like Coq before starting?
  2. How much combinatorical game theory etc. is already formalized that would be useful?
  3. Is that a realistic undertaking?
  4. How to start?

I hope someone can give me some insight in this community to help me get going! Thanks in advance!

Kind regards,
David Philipps

Luigi Massacci (May 06 2025 at 20:08):

Taking a look at #general > Combinatorial game theory repository and related conversations in that channel should be a good start on question 2, as for graph theory itself, there's plenty in mathlib.

Luigi Massacci (May 06 2025 at 20:10):

For question 4, see the community page for learning lean

David Philipps (May 16 2025 at 12:34):

I started my journey but now I am stuck on a thing: I have this definition for degeneracy

noncomputable def degeneracy {V : Type*} [Fintype V] (G : SimpleGraph V) [G.LocallyFinite] : Nat :=
  sInf {n :  |  L : Layout V, isValidDegeneracy G L n}

, but i also saw Nat.find and seems to be more useful? How can I rewrite this with Nat.find? All my approaches fail :/

Kevin Buzzard (May 16 2025 at 13:13):

Can you edit your post to make it into a #mwe using #backticks ? It's not completely essential for understanding in this case but it's good practice so we gently encourage it :-)

David Philipps (May 16 2025 at 13:32):

Edit: here my full code and where I am going with it:

import Mathlib.Combinatorics.SimpleGraph.Basic
import Mathlib.Combinatorics.SimpleGraph.Finite
import Mathlib.Order.Defs.LinearOrder
import Mathlib.Data.Nat.Lattice
import Mathlib.Data.Fin.Basic
import Mathlib.Order.Basic
import Mathlib.Data.Set.Basic
import Mathlib.Data.Finset.Basic

namespace SimpleGraph

def Layout (V : Type*) := LinearOrder V

def countAdjPred {V : Type*} (G : SimpleGraph V) [G.LocallyFinite] (L : Layout V) (v : V) : Nat :=
  Finset.card { w  G.neighborFinset v | L.lt w v }

def isValidDegeneracy {V : Type*} (G : SimpleGraph V) [G.LocallyFinite] (L : Layout V) (k : Nat) : Prop :=
   v : V, countAdjPred G L v  k

noncomputable def degeneracy {V : Type*} [Fintype V] (G : SimpleGraph V) [G.LocallyFinite] : Nat :=
  sInf {n :  |  L : Layout V, isValidDegeneracy G L n}

theorem clique_has_deg_n (n : ) : degeneracy (completeGraph (Fin (n+1)))  n := by
  unfold degeneracy
  apply LE.le.ge
  apply le_sInf

the last line does not work, but I dont understand the error and how to resolve it. Transitioning to Nat.find is one apporach that I am trying out.

Luigi Massacci (May 16 2025 at 14:20):

Ahhh, I feel like this is a part of mathlib where it's easy to get papercuts. Do you know what a complete lattice is? le_sInf doesn't apply because the natural numbers don't form one. You should use le_csInf instead

David Philipps (May 16 2025 at 14:37):

Works like a charm :))

David Philipps (May 16 2025 at 18:51):

Okay I now have 99% of the proof through trial and error but the last thing confuses me.

import Mathlib.Combinatorics.SimpleGraph.Basic
import Mathlib.Combinatorics.SimpleGraph.Finite
import Mathlib.Order.Defs.LinearOrder
import Mathlib.Data.Nat.Lattice
import Mathlib.Data.Fin.Basic
import Mathlib.Order.Basic
import Mathlib.Data.Set.Basic
import Mathlib.Data.Finset.Basic
import Mathlib.Data.Fin.Basic

namespace SimpleGraph

/-- A layout is represented as a linear ordering of vertices -/
def Layout (V : Type*) := LinearOrder V


/-- Count of adjacent predecessors for a vertex v in a given layout -/
def countAdjPred {V : Type*} (G : SimpleGraph V) [G.LocallyFinite] (L : Layout V) (v : V) : Nat :=
  Finset.card { w  G.neighborFinset v | L.lt w v }

/-- Verifies if a number k satisfies the degeneracy condition for a given layout -/
def isValidDegeneracy {V : Type*} (G : SimpleGraph V) [G.LocallyFinite] (L : Layout V) (k : Nat) : Prop :=
   v : V, countAdjPred G L v  k

/-- The degeneracy (δ*) of a graph is the minimal k over all possible layouts such that
    for each vertex v, there are at most k vertices w ≺ v that are adjacent to v -/


noncomputable def degeneracy {V : Type*} [Fintype V] (G : SimpleGraph V) [G.LocallyFinite] : Nat :=
  sInf {n :  |  L : Layout V, isValidDegeneracy G L n}


theorem clique_has_deg_n (n : ) : degeneracy (completeGraph (Fin (n+1))) = n := by
  unfold degeneracy
  have nonEmpty : n  {n_1 |  L, (completeGraph (Fin (n + 1))).isValidDegeneracy L n_1} := by
    simp
    let L : LinearOrder (Fin (n+1)) :=  inferInstance
    use L
    unfold isValidDegeneracy
    intro v
    refine le_trans ?_ (Nat.le_pred_of_lt v.prop)
    unfold countAdjPred

    trans {w | w < v}.toFinset.card
    · apply Finset.card_le_card
      intro w hw
      simp only [Finset.mem_filter] at hw
      exact Set.mem_toFinset.mpr hw.2
    · calc
      -- There are at most v elements less than v
      _ = ({w | w < v}.toFinset.map Fin.val, Fin.val_injective).card :=
        (Finset.card_map _).symm
      _ = ({w :  | w < v.val }).toFinset.card := by
        congr 1
        simp
        ext w
        simp
        constructor <;> intro h
        · obtain a, ha, rfl := h
          exact_mod_cast ha
        · use w, ?_⟩, ?_
          · apply h.trans v.prop
          · exact_mod_cast h
      _ = (Finset.range v.val).card := by
        congr
        exact Set.toFinset_ofFinset (Finset.range v) (Set.fintypeLTNat._proof_34 v)
      _  _ := by
        apply le_of_eq
        exact Finset.card_range v

  apply le_antisymm
  · -- Show degeneracy ≤ n-1
    apply Nat.sInf_le
    exact nonEmpty

  · apply le_csInf
    · exact Set.nonempty_of_mem nonEmpty
    · simp only [Set.mem_setOf_eq]
      simp only [forall_exists_index]
      intro n' L
      intro hvalid
      unfold isValidDegeneracy at hvalid
      specialize hvalid n
      unfold countAdjPred at hvalid
      unfold neighborFinset at hvalid
      unfold neighborSet at hvalid
      unfold Adj at hvalid
      apply le_trans _ hvalid
      apply le_of_eq
      symm
      simp only [completeGraph_eq_top, top_adj, ne_eq, Set.toFinset_setOf]
      rw [Finset.filter_filter]

The final goal is

{a | ¬↑n = a  a < n}.card = n

How can i translate between sets and types like Fin n?

Aaron Liu (May 16 2025 at 19:22):

Are you sure this is true? Can you provide an informal proof?

Kevin Buzzard (May 16 2025 at 19:42):

Informally it looks good to me: we have a : Fin (n + 1) and both of the criteria defining the finset say that it's not n, so you have 0,1,...,n-1 left. What am I missing?

Aaron Liu (May 16 2025 at 19:50):

The < is not the normal Fin <

Kevin Buzzard (May 16 2025 at 19:54):

Lol what the heck?

Kevin Buzzard (May 16 2025 at 19:54):

How can let L : LinearOrder (Fin (n+1)) := inferInstance give a < which is not the normal one?

Kevin Buzzard (May 16 2025 at 19:55):

Adding

theorem extracted (n : ) : (Finset.filter
  (fun a : Fin (n + 1)  ¬(n : Fin (n + 1)) = a  a < (n : Fin (n + 1)))
  Finset.univ).card = n := sorry

(I don't know what notation for Finset.filter is) then indeed exact extracted n fails and convert extracted n gives

 Preorder.toLT = instLTFin

Aaron Liu (May 16 2025 at 19:56):

Kevin Buzzard said:

How can let L : LinearOrder (Fin (n+1)) := inferInstance give a < which is not the normal one?

That's not where the L comes from, that's a different L in a different context

Aaron Liu (May 16 2025 at 19:57):

The L that is not the normal linear order comes from intro n' L

Aaron Liu (May 16 2025 at 20:00):

And specialize hvalid n made the goal unprovable

David Philipps (May 16 2025 at 21:04):

Ahh I see, so I need to access the maximal element according to L. Currently trying to figure our how one does that, open for tipps

Kevin Buzzard (May 16 2025 at 21:14):

There's Finset.max' which you could apply to Finset.univ and there's also \top if the instances are there (a finite linear order is a complete lattice).

Aaron Liu (May 16 2025 at 21:15):

I'm guessing the instance is not there because you would be synthesizing data

David Philipps (May 16 2025 at 21:18):

What does synthesizing data mean? I read it multiple times in errors, but what is it about?

Kevin Buzzard (May 16 2025 at 21:23):

Typeclass inference (the square bracket system) works best when there's at most one instance of everything. You might have run into this already in your argument because you've been putting more than one < on Fin (n + 1). The problem with typeclass inference creating data is that then you might end up with two different instances pointing at the same thing. And by "different" I include the case where actually the objects are the same but the proof that they're the same isn't rfl. So if you choose a total order on Fin n then there's a danger if you get typeclass inference to start making a top element in the sense that even though there's only one top element, there's more than one way to make it, and this might confuse the system.


Last updated: Dec 20 2025 at 21:32 UTC