Documentation
¶
Overview ¶
Package tsort is a pure-Go (CGO=0), MRI-faithful port of Ruby's TSort stdlib: topological sorting and strongly connected components over an arbitrary directed graph, using Tarjan's algorithm exactly as MRI's tsort.rb does.
A graph is described functionally by two callbacks, mirroring Ruby's tsort_each_node / tsort_each_child:
- nodes(yield) yields every node in the graph.
- children(node, yield) yields every child (out-edge target) of node.
Both use the Go range-function shape func(yield func(any)). Nodes are arbitrary any values; equality between two nodes is decided by an Identity function (mirroring Ruby's eql?/hash). When no Identity is supplied the nodes are used as Go map keys directly, which requires them to be comparable.
The traversal order, component grouping and component ordering all match MRI byte-for-byte: each SCC is emitted in reverse topological order (children before parents), and a component's internal order is its DFS discovery order.
Index ¶
- func EachStronglyConnectedComponent(nodes NodesFunc, children ChildrenFunc, yield func(component []any))
- func EachStronglyConnectedComponentFrom(start any, children ChildrenFunc, yield func(component []any))
- func EachStronglyConnectedComponentFromWith(start any, children ChildrenFunc, opts *Options, yield func(component []any))
- func EachStronglyConnectedComponentWith(nodes NodesFunc, children ChildrenFunc, opts *Options, ...)
- func StronglyConnectedComponents(nodes NodesFunc, children ChildrenFunc) [][]any
- func StronglyConnectedComponentsWith(nodes NodesFunc, children ChildrenFunc, opts *Options) [][]any
- func TSort(nodes NodesFunc, children ChildrenFunc) ([]any, error)
- func TSortWith(nodes NodesFunc, children ChildrenFunc, opts *Options) ([]any, error)
- type ChildrenFunc
- type Cyclic
- type NodesFunc
- type Options
- type Symbol
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EachStronglyConnectedComponent ¶
func EachStronglyConnectedComponent(nodes NodesFunc, children ChildrenFunc, yield func(component []any))
EachStronglyConnectedComponent invokes yield for each strongly connected component, in reverse topological order. Mirrors Ruby's TSort.each_strongly_connected_component.
func EachStronglyConnectedComponentFrom ¶
func EachStronglyConnectedComponentFrom(start any, children ChildrenFunc, yield func(component []any))
EachStronglyConnectedComponentFrom iterates over the strongly connected components in the subgraph reachable from start. It does NOT enumerate the node set (no NodesFunc), exactly like Ruby's TSort.each_strongly_connected_component_from. Mirrors that method.
func EachStronglyConnectedComponentFromWith ¶
func EachStronglyConnectedComponentFromWith(start any, children ChildrenFunc, opts *Options, yield func(component []any))
EachStronglyConnectedComponentFromWith is EachStronglyConnectedComponentFrom with explicit Options.
func EachStronglyConnectedComponentWith ¶
func EachStronglyConnectedComponentWith(nodes NodesFunc, children ChildrenFunc, opts *Options, yield func(component []any))
EachStronglyConnectedComponentWith is EachStronglyConnectedComponent with explicit Options.
func StronglyConnectedComponents ¶
func StronglyConnectedComponents(nodes NodesFunc, children ChildrenFunc) [][]any
StronglyConnectedComponents returns the strongly connected components as a slice of slices, sorted from children to parents (reverse topological order). Mirrors Ruby's TSort.strongly_connected_components.
func StronglyConnectedComponentsWith ¶
func StronglyConnectedComponentsWith(nodes NodesFunc, children ChildrenFunc, opts *Options) [][]any
StronglyConnectedComponentsWith is StronglyConnectedComponents with explicit Options.
func TSort ¶
func TSort(nodes NodesFunc, children ChildrenFunc) ([]any, error)
TSort returns a topologically sorted slice of nodes, sorted from children to parents: the first element has no child and the last has no parent. It mirrors Ruby's TSort.tsort.
If the graph contains a cycle (an SCC with more than one node) a *Cyclic error is returned. A self-loop forms a single-node SCC and therefore — exactly like MRI — does NOT raise.
Types ¶
type ChildrenFunc ¶
ChildrenFunc yields every child of node, mirroring Ruby's tsort_each_child.
type Cyclic ¶
type Cyclic struct {
// Component is the strongly connected component (length >= 2) that broke the
// sort, in the same order MRI would have yielded it.
Component []any
// contains filtered or unexported fields
}
Cyclic is raised (returned) when a topological sort encounters a strongly connected component of more than one node, i.e. a true cycle. Its Error string reproduces MRI's message exactly: "topological sort failed: [...]" where the bracketed part is the Ruby #inspect of the offending component.
type NodesFunc ¶
type NodesFunc = func(yield func(any))
NodesFunc yields every node of the graph, mirroring Ruby's tsort_each_node.
type Options ¶
type Options struct {
// Identity maps a node to a comparable key used for graph-equality (Ruby's
// eql?/hash). If nil, the node itself is used as the key, which means nodes
// must be comparable Go values.
Identity func(node any) any
// Inspect renders a node the way Ruby's #inspect would, used only to build the
// Cyclic error message. If nil, a built-in approximation is used.
Inspect func(node any) string
}
Options tunes how nodes are identified and inspected so that the MRI-faithful behaviour can be reproduced for any host node representation (e.g. rbgo's boxed Ruby objects). The zero Options work for comparable Go nodes inspected with a Go-side approximation of Ruby #inspect.
