Problem: cycle_detection

Your task is to implement an algorithm to detect if a directed graph (unweighted) contains a cycle and verify its functional correctness in Lean using Mathlib. You need to implement the function has_cycle, which returns true if the graph contains at least one cycle, and false if it is a Directed Acyclic Graph (DAG). The graph is represented as an Array of Array Nat (adjacency list). There are several verification challenges: (1) Soundness (Cycle Existence): Proving that if the function returns true, there indeed exists a path $p$ starting and ending at the same node with length $>1$. (2) Completeness (Acyclicity): Proving that if the function returns false, no such cycle exists in the entire graph. (3) Termination: Since the goal is to find a cycle, you must prove the algorithm terminates even when cycles are present, typically by tracking a set of visited nodes.


import Mathlib

structure CycleGraph where
  adj : Array (Array Nat)

def CycleGraph.well_formed (g : CycleGraph) : Prop :=
  ∀ u, u < g.adj.size →
    ∀ v, v ∈ g.adj.getD u #[] → v < g.adj.size

def CycleGraph.size (g : CycleGraph) : Nat :=
  g.adj.size

def CycleGraph.has_edge (g : CycleGraph) (u v : Nat) : Prop :=
  u < g.adj.size ∧
  v ∈ g.adj.getD u #[]

def CycleGraph.is_path (g : CycleGraph) (p : List Nat) : Prop :=
  p.length > 0 ∧
  ∀ i, i + 1 < p.length →
    g.has_edge (p.getD i 0) (p.getD (i + 1) 0)

def CycleGraph.is_cycle (g : CycleGraph) (p : List Nat) : Prop :=
  g.is_path p ∧ p.length > 1 ∧ p.head? = p.getLast?

def CycleGraph.graph_has_cycle (g : CycleGraph) : Prop :=
  ∃ p, g.is_cycle p

-- Precondition definitions
@[reducible, simp]
def has_cycle_precond (graph : CycleGraph) : Prop :=
  -- !benchmark @start precond
  graph.well_formed
  -- !benchmark @end precond

-- !benchmark @start auxcode
-- !benchmark @end auxcode

-- Main function definition
def has_cycle (graph : CycleGraph)
    (h_precond : has_cycle_precond graph) : Bool :=
  -- !benchmark @start code
  sorry
  -- !benchmark @end code

-- Postcondition definitions
@[reducible, simp]
def has_cycle_postcond (graph : CycleGraph) (result : Bool)
    (_ : has_cycle_precond graph) : Prop :=
  -- !benchmark @start postcond
  result = graph.graph_has_cycle
  -- !benchmark @end postcond

-- !benchmark @start lemma
-- !benchmark @end lemma

-- Proof content
theorem has_cycle_postcond_satisfied (graph : CycleGraph)
    (h_precond : has_cycle_precond graph) :
    has_cycle_postcond graph (has_cycle graph h_precond) h_precond := by
  -- !benchmark @start proof
  sorry
  -- !benchmark @end proof