/* * Copyright 2025 Casper Dalgaard Nielsen * Adam Yasser Tallouzi * * Use of this source code is governed by the Apache 2.0 license * that can be found in the LICENSE.md file. */////// `PrecedenceGraph` contains a graph module which is used to compute a stratification/// of a Datalog program. The stratification is based on a topological sort/// of the strongly connected components (SCC) of the precedence graph.////// The topological sort describes is a legal stratification of the Datalog program.////// A `PseudoStratum` is a group of mutually independent, consecutive strata, each/// represented by a unique SCC in the topological order.///pubmod Fixpoint3.PrecedenceGraph {/// A vertex of the precedence graph, identified by an integer.pubtypealiasVertex = Int32////// A `PseudoStratum` is an unordered list of strata without dependencies between them.///pubtypealiasPseudoStratum = List[Set[Vertex]]////// Returns a list of the pseudostrata of `g`.////// For example, the graph given by the edges/// ```/// 1 -> 2/// 2 -> 3/// 3 -> 2/// 4 -> 3/// ```/// would produce three SCCs: `{2, 3}`, `{1}`, and `{4}`. A topological sort of the/// condensation graph gives the ordering `[{1}, {4}, {2, 3}]`. Since the components/// `{1}` and `{4}` have no dependencies between them and are adjacent in the ordering,/// they are merged into the same pseudostratum `[{1}, {4}]`. Thus, the list of/// pseudostrata is `[[{1}, {4}], {2, 3}]`.///pubdefgetPseudoStrata(g: MutGraph[r]): List[PseudoStratum] \ r = regionrc {letsorted = MutGraph.getSCCOrder(g);letpseudoStratums = MutList.empty(rc);defloop(s1, list) = matchlist {cases2 :: rest =>letmergeable = s1 |> List.forAll(Set.forAll(u -> s2 |> Set.forAll(v -> notMutGraph.hasEdge(u, v, g))) );letnext =if (mergeable)s2 :: s1else {MutList.push(s1, pseudoStratums);s2 :: Nil };loop(next, rest)case Nil => MutList.push(s1, pseudoStratums) };matchsorted {cases :: rest => loop(s :: Nil, rest)case Nil => () };MutList.toList(pseudoStratums) }}