graph

package
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ComputeCouplingMetrics

func ComputeCouplingMetrics(g DirectedGraph, config CouplingConfig) (map[string]*CouplingMetrics, error)

ComputeCouplingMetrics computes Robert Martin's coupling metrics for all nodes in the directed graph.

func StronglyConnectedComponents added in v0.2.2

func StronglyConnectedComponents(g DirectedGraph) [][]string

StronglyConnectedComponents returns every strongly connected component of g, including single-node components, using Tarjan's algorithm. Components are returned in reverse topological order: a component appears before any component it depends on.

Types

type ChainFinder added in v0.2.2

type ChainFinder struct {
	// contains filtered or unexported fields
}

ChainFinder answers longest-dependency-chain queries over a directed graph.

Finding the longest simple path in a graph that may contain cycles is NP-hard, so a ChainFinder walks the condensation instead: strongly connected components are collapsed to single vertices and the heaviest path through the resulting DAG is memoized in one linear pass, weighting each component by how many nodes it holds. Each query then expands that component path into a concrete route through the members of every component it crosses, so every chain returned is a real simple path in the graph.

The chain is maximal in dependency layers: no other simple path crosses more strongly connected components. Within a component the route is not guaranteed maximal — the final component is walked greedily through as many members as it can reach, while components the chain passes through are crossed by the shortest route between the edges that enter and leave them. Recovering the longest route through a cycle is the NP-hard problem again.

Ties are resolved by traversal order, which is derived from the graph's node ordering, so repeated queries over the same graph return the same chain.

func NewChainFinder added in v0.2.2

func NewChainFinder(g DirectedGraph) *ChainFinder

NewChainFinder builds the condensation of g and memoizes the longest chain reachable from every component. Construction is linear in the graph size; each subsequent query is linear in the length of the chain it returns.

func (*ChainFinder) LongestChain added in v0.2.2

func (f *ChainFinder) LongestChain() []string

LongestChain returns the longest chain anywhere in the graph.

func (*ChainFinder) LongestChainFrom added in v0.2.2

func (f *ChainFinder) LongestChainFrom(nodeID string) []string

LongestChainFrom returns the longest chain that starts at nodeID, or nil if the node is not in the graph.

type CouplingConfig

type CouplingConfig struct {
	// AbstractnessFunc computes the abstractness (0.0–1.0) for a given node.
	// pyscn: ratio of public names matching abstract patterns.
	// jscan: export ratio.
	// If nil, Abstractness defaults to 0.0 for all nodes.
	AbstractnessFunc func(nodeID string) (float64, error)
}

CouplingConfig configures coupling metric computation.

type CouplingMetrics

type CouplingMetrics struct {
	NodeID       string
	Ca           int     // Afferent coupling (incoming edges)
	Ce           int     // Efferent coupling (outgoing edges)
	Instability  float64 // Ce / (Ca + Ce), 0 = maximally stable
	Abstractness float64 // Provided by language-specific callback
	Distance     float64 // |Abstractness + Instability - 1|
}

CouplingMetrics holds Robert Martin's package coupling metrics for a node.

type CycleDetector

type CycleDetector struct {
	// contains filtered or unexported fields
}

CycleDetector finds strongly connected components using Tarjan's algorithm.

func NewCycleDetector

func NewCycleDetector() *CycleDetector

NewCycleDetector creates a new CycleDetector.

func (*CycleDetector) DetectCycles

func (d *CycleDetector) DetectCycles(g DirectedGraph) *CycleResult

DetectCycles finds all cycles (SCCs with size > 1) in the directed graph.

type CycleResult

type CycleResult struct {
	// Cycles contains all strongly connected components with more than one node.
	Cycles [][]string
	// HasCycles is true if any cycle was found.
	HasCycles bool
	// AffectedNodes contains all nodes that participate in at least one cycle.
	AffectedNodes map[string]bool
}

CycleResult holds the result of cycle detection via Tarjan's SCC algorithm.

type DirectedGraph

type DirectedGraph interface {
	// NodeIDs returns all node identifiers in the graph.
	NodeIDs() []string
	// Successors returns the IDs of nodes that this node has edges to.
	Successors(nodeID string) []string
	// Predecessors returns the IDs of nodes that have edges to this node.
	Predecessors(nodeID string) []string
	// NodeCount returns the number of nodes in the graph.
	NodeCount() int
	// HasNode returns true if the node exists in the graph.
	HasNode(nodeID string) bool
}

DirectedGraph provides read-only access to a directed graph. pyscn's DependencyGraph (map[string]*ModuleNode) and jscan's domain.DependencyGraph (method-based) can both implement this.

type MapGraph

type MapGraph struct {
	// contains filtered or unexported fields
}

MapGraph is a simple directed graph implementation backed by maps. Useful for testing and as a default implementation.

func NewMapGraph

func NewMapGraph() *MapGraph

NewMapGraph creates a new empty MapGraph.

func (*MapGraph) AddEdge

func (g *MapGraph) AddEdge(from, to string)

AddEdge adds a directed edge from → to. Both nodes are created if absent.

func (*MapGraph) AddNode

func (g *MapGraph) AddNode(id string)

AddNode adds a node to the graph. No-op if already present.

func (*MapGraph) HasNode

func (g *MapGraph) HasNode(nodeID string) bool

HasNode returns true if the node exists.

func (*MapGraph) NodeCount

func (g *MapGraph) NodeCount() int

NodeCount returns the number of nodes.

func (*MapGraph) NodeIDs

func (g *MapGraph) NodeIDs() []string

NodeIDs returns all node identifiers sorted lexicographically.

func (*MapGraph) Predecessors

func (g *MapGraph) Predecessors(nodeID string) []string

Predecessors returns the IDs of nodes that have an edge to nodeID.

func (*MapGraph) Successors

func (g *MapGraph) Successors(nodeID string) []string

Successors returns the IDs of nodes reachable by one edge from nodeID.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL