Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cslib.lean
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module -- shake: keep-all --deprecated_module: ignore

public import Cslib.Algorithms.Lean.MergeSort.MergeSort
public import Cslib.Algorithms.Lean.TimeM
public import Cslib.Analysis.Dataflow.CFG
public import Cslib.Analysis.Dataflow.Kildall
public import Cslib.Computability.Automata.Acceptors.Acceptor
public import Cslib.Computability.Automata.Acceptors.OmegaAcceptor
public import Cslib.Computability.Automata.DA.Basic
Expand Down
95 changes: 95 additions & 0 deletions Cslib/Analysis/Dataflow/CFG.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/-
Copyright (c) 2026 Jacopo Moretti. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Jacopo Moretti
-/

module

public import Cslib.Init
public import Mathlib.Data.Fintype.List
public import Mathlib.Data.Fintype.Sigma
public import Mathlib.Data.Finset.Sort
public import Mathlib.Data.DFinsupp.WellFounded
public import Mathlib.Combinatorics.Quiver.Basic
public import Mathlib.Combinatorics.Quiver.Covering


/-!
# Control flow graphs

## Main definitions

- `CFG` is a structure representing Control Flow Graphs on which the dataflow
algorithm defined in `Kildall.lean` runs.
-/

@[expose] public section

/-- Abstract structure defining the necessary operations on a CFG to define a Control Flow Graph. -/
structure CFG where
/-- All of the nodes in the CFG. -/
Node : Type u
/-- A CFG contains a finite amount of nodes. -/
[fintypeNode : Fintype Node]
/-- An ordering of nodes, to make the conversion to lists computable. -/
[orderNode : LinearOrder Node]
/-- Decidable equality on nodes. -/
[dEqNode : DecidableEq Node]
/-- Quiver structure for the edges of the CFG. -/
quiver : Quiver Node
/-- A CFG contains a finite amount of edges. -/
[fintypeEdges : ∀ a b, Fintype (@Quiver.Hom Node quiver a b)]
/-- Distinguished entry node in the CFG. -/
entry : Node

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, in cslib (and mathlib), we prefer unbundled definitions. That is, we prefer that types like Node be given as a parameter to CFG, rather than being bundled in the structure. Similarly, assumptions like FinType should be made only when needed and given as parameters. You can assume [DecidableEq Node] globally.

Second, do you need to allow for the possibility of having more than one edge between two nodes? If not, then Digraph would be simpler and more appropriate than Quiver:
https://leanprover-community.github.io/mathlib4_docs/Mathlib/Combinatorics/Digraph/Basic.html#Digraph
Also, by using Quiver, you have a separate type of edges for each pair of nodes. Do you have a need for a single type Edge of edges? If so, you may want to consider using cslib's LTS:
https://api.cslib.io/docs/Cslib/Foundations/Semantics/LTS/Basic.html

Thrid, I do not understand your comment about needing a LinearOrder to make CFG computable. Do you actually use this order in Kildall's algorithm? If so, you may consider substituting Fin n for Node or assuming the existence of an Equiv:
https://leanprover-community.github.io/mathlib4_docs/Mathlib/Logic/Equiv/Defs.html#Equiv
between Node and some totally ordered finite type such as Fin n. And you can make that assumption only when needed.


namespace CFG

instance {g : CFG} : Fintype (g.Node) :=
g.fintypeNode

instance {g : CFG} : LinearOrder (g.Node) :=
g.orderNode

/-- Finite set of all of the nodes of `g` -/
def nodesOf (g : CFG) : Finset g.Node := g.fintypeNode.elems

/-- List of all of the nodes of `g`, ordered by the ordering on `g.Node` -/
def nodeList (g : CFG) : List g.Node := g.nodesOf.sort

/-- Any node of `g` is in `g.nodeList`. -/
@[simp] theorem mem_nodeList (g : CFG) (n : g.Node) : n ∈ g.nodeList := by
rw [nodeList]
apply (Finset.mem_sort (· ≤ ·)).mpr
exact @Fintype.complete _ g.fintypeNode n

/-- Convenience type for edges of `g`: `Edge src dst` represents an edge between src and dst. -/
abbrev Edge {g : CFG} (src dst : g.Node) := @Quiver.Hom g.Node g.quiver src dst
/-- Convenience type for incoming edges of `n` in `g`: `inEdge n` represents the type of edges
entering n. -/
abbrev inEdge {g : CFG} (n : g.Node) := @Quiver.Costar g.Node g.quiver n
/-- Convenience type for outgoing edges of `n` in `g`: `outEdge n` represents the type of edges
entering n. -/
abbrev outEdge {g : CFG} (n : g.Node) := @Quiver.Star g.Node g.quiver n

/-- All incoming edges of a given node, bundled with their source nodes. -/
def inEdges {g : CFG} (n : g.Node) : Finset (inEdge n) := by
letI := g.quiver
letI := g.fintypeNode
letI := g.orderNode
letI (src dst : g.Node) := g.fintypeEdges src dst
exact Finset.univ

/-- All outgoing edges of a given node, bundled with their source nodes. -/
def outEdges {g : CFG} (n : g.Node) : Finset (outEdge n) := by
letI := g.quiver
letI := g.fintypeNode
letI (src dst : g.Node) := g.fintypeEdges src dst
exact Finset.univ

/-- The set of successor nodes of node `n` in `g`. -/
def succOf {g : CFG} (n : g.Node) : Finset g.Node :=
letI := g.dEqNode
(outEdges n).image Sigma.fst

end CFG
Loading
Loading