Zulip Chat Archive

Stream: mathlib4

Topic: Depth-first search on quivers, with proof


Anand Rao Tadipatri (Feb 13 2023 at 15:12):

I am considering implementing the depth-first search algorithm for finite quivers and proving a few related properties. This may be useful in graph theory or geometric group theory, where one may want to produce a spanning tree of a connected graph or decide whether two vertices of a graph are connected by a (directed) path. Ideally the implementation should run reasonably fast on small graphs to allow testing of examples, while also being transparent enough to allow proofs.

I am thinking of implementing something along the lines of the code snippet below (perhaps rewritten to avoid loops and mutable variables if that makes the proofs easier). I would like to know whether this kind of algorithm with proofs is suitable for Mathlib. I would also appreciate feedback on whether and in what form definitions and constructions such as Listable, Quiver.neighbourhood and the union of WideSubquivers should be integrated into Mathlib.

import Mathlib.Combinatorics.Quiver.Subquiver
import Mathlib.Data.Fintype.Basic

/-- A version of `Fintype α` which not only expresses the
  fact that the type is finite but also gives a way of enumerating the elements. -/
class Listable (α : Sort _) where
  elems : List α
  complete :  x : α, x  elems
  -- may be unnecessary
  nodup : elems.Nodup

notation "[" α "]ₗ" => (Listable.elems : List α)

instance {α : Sort _} [Listable α] : Fintype α :=
  ⟨⟨.mk' [α], Listable.nodup⟩, Listable.complete

instance {α : Sort _} [Fintype α] [Ord α] : Listable α := sorry

instance {α : Sort _} {β : α  Sort _}
  [Listable α] [ a : α, Listable (β a)] : Listable (Sigma β) :=
  { elems := .join <| [α]ₗ.map <| fun a => [β a]ₗ.map (Sigma.mk a),
    complete := sorry, nodup := sorry }

instance {α : Sort _} [Listable α] {P : α  Prop} [DecidablePred P] : Listable {a : α // P a} :=
  { elems := [α]ₗ.filterMap <| fun a =>
    if h : P a then some a, h else none
  , complete := sorry, nodup := sorry }


def Quiver.star [Q : Quiver V] (v : V) := Σ w : V, v  w

instance {V : Sort _} [Q : Quiver V] [Listable V] (v : V) [ w : V, Listable (v  w)] :
  Listable (Quiver.star(Q := Q) v) :=
  inferInstanceAs <| Listable <| Sigma _

namespace WideSubquiver

instance [Quiver V] : Union (WideSubquiver V) :=
  fun Q Q' v w => Q v w  Q' v w

def ofEdge [Quiver V] {v w : V} (e : v  w) : WideSubquiver V :=
  Quiver.wideSubquiverEquivSetTotal.invFun {⟨v, w, e⟩}

end WideSubquiver

variable {V : Type _} [Q : Quiver V] [Listable V] [ v w : V, Listable (v  w)] [DecidableEq V]

def depthFirstTraversal (root : V) (visited : List V) : List V × (WideSubquiver V) := Id.run do
  let mut discovered := root :: visited
  let mut Q : WideSubquiver V := 
  for w, e in [Quiver.star root] do
    if w  discovered then
      have : [V]ₗ.length - discovered.length < [V]ₗ.length - visited.length := sorry
      let (discovered', Q') := depthFirstTraversal w discovered
      Q := Q  (WideSubquiver.ofEdge e)  Q'
  return (discovered, Q)
termination_by _ => [V]ₗ.length - visited.length

theorem visited_of_edge {u v w : V} (e : v  w) : v  (depthFirstTraversal u []).fst  w  (depthFirstTraversal u []).fst := by
  unfold depthFirstTraversal
  sorry

Rémi Bottinelli (Feb 13 2023 at 15:22):

Not very important, but in PR 17828 we call your Neighborhood Star.

Anand Rao Tadipatri (Feb 13 2023 at 15:36):

Thanks, I think star sounds better. I've updated my code snippet.

Shreyas Srinivas (Feb 13 2023 at 15:40):

This is nice. May I ask why you would like to remove mutable variables? There is much to be gained from being able to reason about mutable variables in the algorithms world, at least complexity-theory-wise.

Rémi Bottinelli (Feb 13 2023 at 15:42):

How do you even reason about those (mutables) in lean? Is it translated to some monad?

Shreyas Srinivas (Feb 13 2023 at 15:55):

Rémi Bottinelli said:

How do you even reason about those (mutables) in lean? Is it translated to some monad?

I don't know yet. My idea was to use restricted mutations. But this is a slightly different context.

Anand Rao Tadipatri (Feb 13 2023 at 16:03):

Thanks. I believe the code in the Id monad is compiled down to fold and map internally. I prefer the mutable variable and loop syntax too, but I am not sure how easy it will be to analyse in a proof.

I am not having very good results trying to prove this test lemma about the depthFirstTraversal function:

theorem visited_of_edge {u v w : V} (e : v  w) : v  (depthFirstTraversal u []).fst  w  (depthFirstTraversal u []).fst := by
  unfold depthFirstTraversal
  sorry

Shreyas Srinivas (Feb 13 2023 at 16:05):

Am I correct to assume that you are not using this to make complexity claims? We will probably be doing something similar for complexity and algorithms. I am checking to avoid duplication of effort and names of defs

Yuyang Zhao (Feb 13 2023 at 16:09):

We recently found docs#fin_enum / docs4#FinEnum and no file import it, I think we should choose one between it and Listable to keep in mathlib (of course, maybe make some small changes).

Anand Rao Tadipatri (Feb 13 2023 at 16:24):

Yes, you're right - I am mainly concerned with using this implementation to perform small-scale computations with graphs and using it with proofs to automatically decide properties like connectedness and reachability. However I'd be happy to coordinate and work on implementing it in a way that's useful to both complexity analysis and decision procedures/proofs.

Anand Rao Tadipatri (Feb 13 2023 at 16:30):

Yuyang Zhao said:

We recently found docs#fin_enum / docs4#FinEnum and no file import it, I think we should choose one between it and Listable to keep in mathlib (of course, maybe make some small changes).

Thanks. FinEnum seems to already have a large number of useful lemmas and constructions associated with it. One thing that seems to be missing, but may be useful while trying out computations, is the for ... in notation through the ForIn typeclass.

Yuyang Zhao (Feb 13 2023 at 16:33):

(As an experienced competitive programmer I can't wait to use lean to write some algorithms (with correctness proofs), but I'm still trying to convince some Online Judge owners to add lean4 to their OJ :innocent: )

Anand Rao Tadipatri (Feb 13 2023 at 16:38):

(Indeed - with the Std4 library, competitive programming in Lean4 seems very much a possibility.)


Last updated: Dec 20 2023 at 11:08 UTC