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 Dafny. 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 a sequence of sequences (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$. If using DFS, this typically involves proving that a "back-edge" points to a node currently in the recursion stack. (2) Completeness (Acyclicity): Proving that if the function returns false, no such cycle exists in the entire graph. This requires a strong invariant, such as proving that the graph nodes can be ordered (topologically) or that the recursion finished without finding any back-edges (3) Termination: Since the goal is to find a cycle (infinite loop in a naive traversal), you must prove the algorithm terminates even when cycles are present, typically by tracking a set of visited nodes.

// Following is the block for necessary definitions
// <preamble>
datatype Graph = Graph(adj: seq<seq<int>>)

// Helper predicates/functions for the Graph datatype
ghost predicate well_formed(g: Graph) {
  forall u: int, i: int :: 
    0 <= u < |g.adj| && 0 <= i < |g.adj[u]| 
    ==> 
    0 <= g.adj[u][i] < |g.adj|
}

ghost function size(g: Graph): int {
  |g.adj|
}

// --- Basic Graph Definitions ---

ghost predicate has_edge(g: Graph, u: int, v: int) {
  exists i: int :: 
    0 <= u < |g.adj| 
    && 0 <= i < |g.adj[u]| 
    && g.adj[u][i] == v
}

ghost predicate is_path(g: Graph, p: seq<int>) {
  |p| > 0 &&
  (forall i: int :: 0 <= i < |p| - 1 
      ==> has_edge(g, p[i], p[i+1]))
}

// A cycle is a path that starts and ends at the same node.
ghost predicate is_cycle(g: Graph, p: seq<int>) {
  is_path(g, p)
  && |p| > 1
  && p[0] == p[|p| - 1]
}

ghost predicate graph_has_cycle(g: Graph) {
  exists p: seq<int> :: is_cycle(g, p)
}
// </preamble>

// <helpers>

// </helpers>

// <proofs>

// </proofs>

// <spec>
// Cycle Detection (Whole Graph)
// Functional Correctness:
// - true  <==> The graph contains at least one cycle.
// - false <==> The graph is a DAG (Directed Acyclic Graph).
method has_cycle(graph: Graph) returns (res: bool)
  requires well_formed(graph)
  ensures res == graph_has_cycle(graph)
// </spec>
// <code>
{
    // Implement and verify the has_cycle function here
}
// </code>