Class ProcessGraph
- All Implemented Interfaces:
Serializable
This class provides comprehensive graph analysis capabilities:
- Explicit DAG of equipment (nodes) and streams (edges)
- Topological sorting with cycle detection
- Strongly connected component (SCC) detection for recycle handling
- Calculation order derivation (not assumed from insertion order)
- Partitioning for parallel execution
- Graph neural network compatible representation
- AI agent compatibility for flowsheet reasoning
Why this matters: Without explicit graph representation:
- Execution order = insertion order (fragile)
- Rearranging units or adding recycles late causes wrong results
- Parallel execution risks silent convergence failures
- Execution order is derived, not assumed
- Recycles and feedback loops are explicit objects
- AI agents can reason about flowsheet structure
- Version:
- 1.0
- Author:
- NeqSim
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classResult of cycle detection analysis.static classResult of parallel execution partitioning.static classResult of strongly connected component analysis.static classResult of sensitivity analysis for tear stream selection.static classResult of tear stream selection analysis. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate ProcessGraph.CycleAnalysisResultCached cycle analysis (null if not computed or invalidated).private ProcessGraph.SCCResultCached SCC result (null if not computed or invalidated).private List<ProcessNode> Cached topological order (null if not computed or invalidated).private final List<ProcessEdge> All edges in the graph.private final Map<Object, ProcessNode> Map from equipment to its node.Equipment type to index mapping for feature vectors.private static final org.apache.logging.log4j.Loggerprivate final Map<String, ProcessNode> Map from equipment name to node.private final List<ProcessNode> All nodes in the graph, indexed by their index.private static final longprivate booleanWhether the graph structure has changed since last analysis. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionaddEdge(ProcessEquipmentInterface sourceEquipment, ProcessEquipmentInterface targetEquipment, StreamInterface stream) Adds an edge between two equipment units.addEdge(ProcessNode source, ProcessNode target, StreamInterface stream) Adds an edge between two nodes.addNode(ProcessEquipmentInterface equipment) Adds a node to the graph.Analyzes the graph for cycles using DFS.Analyzes sensitivity of potential tear streams to select optimal ones.private doublecomputeBranchingFactor(List<ProcessNode> scc, Set<ProcessNode> sccNodes) Computes the average branching factor in an SCC.private doublecomputeEdgeSensitivity(ProcessEdge edge, List<ProcessNode> scc, Set<ProcessNode> sccNodes) Computes sensitivity score for a potential tear stream.private doubleComputes average equipment type sensitivity for nodes in SCC.private intcomputePathLengthInSCC(ProcessNode source, ProcessNode target, Set<ProcessNode> sccNodes) Computes the path length from source to target within an SCC.private doublecomputeTearStreamScore(ProcessEdge edge, List<ProcessNode> scc) Computes a heuristic score for a potential tear stream.private voiddetectCyclesDFS(ProcessNode node, Deque<ProcessNode> currentPath, List<List<ProcessNode>> cycles, List<ProcessEdge> backEdges) Computes strongly connected components using Tarjan's algorithm.Gets adjacency list representation.boolean[][]Gets adjacency matrix (sparse representation).Gets calculation order - the order in which units should be executed.intdouble[][]Gets edge feature matrix for GNN.int[][]Gets edge index tensor in COO format for GNN.getEdges()getNode(int index) Gets a node by index.Gets a node by name.getNode(ProcessEquipmentInterface equipment) Gets a node by equipment.intdouble[][]Gets node feature matrix for GNN.getNodes()Gets nodes that are part of recycle loops.Gets all recycle edges.Gets a detailed report of sensitivity analysis for all SCCs.Gets all sink nodes (no outgoing edges).Gets all source nodes (no incoming edges).Generates a summary of the graph structure.Computes topological order of nodes.booleanChecks if the graph has cycles.private booleanhasCycleWithoutTears(ProcessNode node, Set<ProcessNode> visited, Set<ProcessNode> inStack, Set<ProcessEdge> tearSet) DFS helper to detect cycles ignoring specified tear streams.private voidInvalidates cached analysis results.Partitions nodes into levels for parallel execution.private voidResets all nodes' traversal state.private ProcessEdgeselectBestTearStreamForSCC(List<ProcessNode> scc, List<ProcessEdge> sccEdges) Selects the best tear stream for a single SCC using heuristics.Selects optimal tear streams to break all cycles in the flowsheet.Suggests tear streams using flow rate minimization heuristic.Selects tear streams using sensitivity analysis for each SCC.private voidtarjanDFS(ProcessNode node, int[] ids, int[] low, boolean[] onStack, Deque<ProcessNode> stack, List<List<ProcessNode>> components, int[] idCounter) private voidtopologicalSortDFS(ProcessNode node, Deque<ProcessNode> stack) toString()validate()Validates the graph structure.booleanvalidateTearStreams(List<ProcessEdge> tearStreams) Validates that selected tear streams break all cycles.
-
Field Details
-
serialVersionUID
private static final long serialVersionUID- See Also:
-
logger
private static final org.apache.logging.log4j.Logger logger -
nodes
All nodes in the graph, indexed by their index. -
edges
All edges in the graph. -
equipmentToNode
Map from equipment to its node. -
nameToNode
Map from equipment name to node. -
equipmentTypeMapping
-
cachedTopologicalOrder
Cached topological order (null if not computed or invalidated). -
cachedCycleAnalysis
Cached cycle analysis (null if not computed or invalidated). -
cachedSCCResult
Cached SCC result (null if not computed or invalidated). -
structureChanged
private transient boolean structureChangedWhether the graph structure has changed since last analysis.
-
-
Constructor Details
-
ProcessGraph
public ProcessGraph()Creates an empty process graph.
-
-
Method Details
-
addNode
Adds a node to the graph.- Parameters:
equipment- the equipment to add- Returns:
- the created node
-
addEdge
Adds an edge between two nodes.- Parameters:
source- source nodetarget- target nodestream- the stream connecting them (may be null)- Returns:
- the created edge
-
addEdge
public ProcessEdge addEdge(ProcessEquipmentInterface sourceEquipment, ProcessEquipmentInterface targetEquipment, StreamInterface stream) Adds an edge between two equipment units.- Parameters:
sourceEquipment- source equipmenttargetEquipment- target equipmentstream- the stream connecting them (may be null)- Returns:
- the created edge, or null if either equipment is not in the graph
-
getNode
Gets a node by equipment.- Parameters:
equipment- the equipment- Returns:
- the node, or null if not found
-
getNode
Gets a node by name.- Parameters:
name- the equipment name- Returns:
- the node, or null if not found
-
getNode
Gets a node by index.- Parameters:
index- the node index- Returns:
- the node
- Throws:
IndexOutOfBoundsException- if index is out of range
-
getNodes
- Returns:
- unmodifiable list of all nodes
-
getEdges
- Returns:
- unmodifiable list of all edges
-
getNodeCount
public int getNodeCount()- Returns:
- number of nodes
-
getEdgeCount
public int getEdgeCount()- Returns:
- number of edges
-
invalidateCache
private void invalidateCache()Invalidates cached analysis results. -
resetTraversalState
private void resetTraversalState()Resets all nodes' traversal state. -
analyzeCycles
Analyzes the graph for cycles using DFS.- Returns:
- cycle analysis result
-
detectCyclesDFS
private void detectCyclesDFS(ProcessNode node, Deque<ProcessNode> currentPath, List<List<ProcessNode>> cycles, List<ProcessEdge> backEdges) -
hasCycles
public boolean hasCycles()Checks if the graph has cycles.- Returns:
- true if there are cycles
-
getTopologicalOrder
Computes topological order of nodes.If the graph has cycles, back edges are ignored to produce a valid ordering for the acyclic portion. This is essential for determining correct calculation order.
- Returns:
- list of nodes in topological order
-
topologicalSortDFS
-
getCalculationOrder
Gets calculation order - the order in which units should be executed.This is the primary method for deriving execution order from topology rather than insertion order.
- Returns:
- list of equipment in calculation order
-
findStronglyConnectedComponents
Computes strongly connected components using Tarjan's algorithm.SCCs are used to identify recycle loops that need iterative solving.
- Returns:
- SCC analysis result
-
tarjanDFS
private void tarjanDFS(ProcessNode node, int[] ids, int[] low, boolean[] onStack, Deque<ProcessNode> stack, List<List<ProcessNode>> components, int[] idCounter) -
partitionForParallelExecution
Partitions nodes into levels for parallel execution.Nodes at the same level have no dependencies on each other and can be executed in parallel. This uses the longest path algorithm on the DAG (ignoring back edges).
- Returns:
- parallel partition result
-
getNodeFeatureMatrix
public double[][] getNodeFeatureMatrix()Gets node feature matrix for GNN.- Returns:
- 2D array [numNodes][numFeatures]
-
getEdgeIndexTensor
public int[][] getEdgeIndexTensor()Gets edge index tensor in COO format for GNN.- Returns:
- 2D array [[sources], [targets]]
-
getEdgeFeatureMatrix
public double[][] getEdgeFeatureMatrix()Gets edge feature matrix for GNN.- Returns:
- 2D array [numEdges][numFeatures]
-
getAdjacencyList
-
getAdjacencyMatrix
public boolean[][] getAdjacencyMatrix()Gets adjacency matrix (sparse representation).- Returns:
- adjacency matrix as boolean 2D array
-
getSourceNodes
Gets all source nodes (no incoming edges).- Returns:
- list of source nodes
-
getSinkNodes
Gets all sink nodes (no outgoing edges).- Returns:
- list of sink nodes
-
getRecycleEdges
Gets all recycle edges.- Returns:
- list of edges marked as recycles or back edges
-
getNodesInRecycleLoops
Gets nodes that are part of recycle loops.- Returns:
- set of nodes in recycle loops
-
validate
-
selectTearStreams
Selects optimal tear streams to break all cycles in the flowsheet.This method implements a heuristic approach to the Minimum Feedback Arc Set (MFAS) problem, which is NP-hard in general. The algorithm:
- Finds all strongly connected components (SCCs)
- For each non-trivial SCC (size > 1), selects the best tear stream
- Uses heuristics based on stream characteristics to select optimal tears
The heuristics prefer streams that:
- Have fewer downstream dependencies (minimizes propagation)
- Are marked as recycle streams (user intent)
- Have lower flow rates (faster convergence)
- Break the most cycles (greedy optimization)
- Returns:
- tear stream selection result
-
selectBestTearStreamForSCC
Selects the best tear stream for a single SCC using heuristics.- Parameters:
scc- the strongly connected componentsccEdges- edges within the SCC- Returns:
- the best tear stream edge
-
computeTearStreamScore
Computes a heuristic score for a potential tear stream. Higher scores indicate better tear stream candidates.- Parameters:
edge- the candidate edgescc- the SCC containing the edge- Returns:
- heuristic score
-
selectTearStreamsForFastConvergence
Suggests tear streams using flow rate minimization heuristic.This method selects tear streams that minimize the total flow rate being torn, which typically leads to faster convergence as smaller streams have less impact on the overall mass and energy balance.
Note: This requires flow rate information to be available in the stream objects. If not available, falls back to the default selection algorithm.
- Returns:
- tear stream selection result optimized for convergence speed
-
analyzeTearStreamSensitivity
Analyzes sensitivity of potential tear streams to select optimal ones.This method estimates the sensitivity of each potential tear stream by analyzing how much perturbations in the tear stream values would propagate through the SCC. Lower sensitivity means faster convergence.
The sensitivity is estimated using graph-based heuristics:
- Path length from tear to its re-entry point
- Number of equipment units in the recycle path
- Branching factor (flow splitting in the loop)
- Equipment type weights (separators have higher sensitivity than heaters)
- Parameters:
scc- the strongly connected component to analyze- Returns:
- sensitivity analysis result
-
computeEdgeSensitivity
private double computeEdgeSensitivity(ProcessEdge edge, List<ProcessNode> scc, Set<ProcessNode> sccNodes) Computes sensitivity score for a potential tear stream.Lower sensitivity indicates a better tear stream candidate.
- Parameters:
edge- the candidate tear streamscc- the SCC containing the edgesccNodes- set of nodes in the SCC for fast lookup- Returns:
- sensitivity score
-
computePathLengthInSCC
private int computePathLengthInSCC(ProcessNode source, ProcessNode target, Set<ProcessNode> sccNodes) Computes the path length from source to target within an SCC.- Parameters:
source- starting nodetarget- ending nodesccNodes- nodes in the SCC- Returns:
- path length, or -1 if no path exists
-
computeEquipmentTypeSensitivity
Computes average equipment type sensitivity for nodes in SCC.- Parameters:
scc- the SCC nodes- Returns:
- average sensitivity weight
-
computeBranchingFactor
Computes the average branching factor in an SCC.- Parameters:
scc- the SCC nodessccNodes- set of SCC nodes for lookup- Returns:
- average branching factor
-
selectTearStreamsWithSensitivity
Selects tear streams using sensitivity analysis for each SCC.This method improves upon the heuristic-based selection by computing actual sensitivity estimates that predict convergence behavior.
- Returns:
- tear stream selection result with sensitivity-optimized tears
-
getSensitivityAnalysisReport
Gets a detailed report of sensitivity analysis for all SCCs.- Returns:
- formatted string with sensitivity analysis details
-
validateTearStreams
Validates that selected tear streams break all cycles.- Parameters:
tearStreams- the tear streams to validate- Returns:
- true if all cycles are broken
-
hasCycleWithoutTears
private boolean hasCycleWithoutTears(ProcessNode node, Set<ProcessNode> visited, Set<ProcessNode> inStack, Set<ProcessEdge> tearSet) DFS helper to detect cycles ignoring specified tear streams.- Parameters:
node- the current node to checkvisited- set of already visited nodesinStack- set of nodes currently in the recursion stacktearSet- set of tear edges to ignore- Returns:
- true if a cycle is detected, false otherwise
-
getSummary
-
toString
-