Goals
- Sacrifice a little RAM for O(1) operations.
- Sacrifice a little CPU for less memory churn.
- Aggressively remove API that proves useless or confusing.
- Aggressively abstract and hide complexity from the user.
- Perfect is the enemy of Good.
Types
Edge[N; E] = ref EdgeObj[N, E]
-
An edge connects two nodes.
Nodes have a user-supplied .value of type N. Edges have a user-supplied .value of type E.
Source Edit Graph[N; E; F] = ref GraphObj[N, E, F]
-
A collection of nodes and edges.
Nodes have a user-supplied .value of type N. Edges have a user-supplied .value of type E.
Source Edit GraphFlag {.size: 8.} = enum QueryResult = "the graph only makes sense in relation to another graph", UniqueNodes = "the nodes in the graph all have unique values", UniqueEdges = "the edges in the graph all have unique values", Directed = "edges have different semantics for source and target", Undirected = "edges have identical semantics for source and target", SelfLoops = "nodes may have edges that target themselves", Ultralight = "the graph is even lighter", ValueIndex = "node and edge values are indexed for speed"
- Source Edit
GraphFlags = int
- Source Edit
Node[N; E] = ref NodeObj[N, E]
-
A node in the graph.
Nodes have a user-supplied .value of type N. Edges have a user-supplied .value of type E.
Source Edit NoValueIndexGraph = concept g contains(g.flags, ValueIndex) == false
- Source Edit
ValueIndexGraph = concept g contains(g.flags, ValueIndex) == true
- Source Edit
Consts
defaultGraphFlags = {Directed, SelfLoops, ValueIndex}
- Source Edit
Procs
proc `[]`[N, E; F: static[GraphFlags]](graph: Graph[N, E, F]; key: N): Node[N, E]
- Index an immutable graph to retrieve a immutable node of value key. Source Edit
proc `[]`[N, E; F: static[GraphFlags]](graph: var Graph[N, E, F]; key: N): var Node[ N, E]
-
Index a mutable graph to retrieve a mutable node of value key.
Example:
var g = newGraph[int, string]() discard g.add 3 assert g[3].value == 3
Source Edit proc `[]`[N, E](node: Node[N, E]; key: E): Node[N, E]
-
Index a node by edge key, returning the opposite node.
Example:
var g = newGraph[int, string]() discard g.add 3 discard g.add 9 discard g.edge(g[3], "squared", g[9]) let l3 = g[3] l9 = g[3]["squared"] assert l9.value == 9
Source Edit proc `[]`[N, E](node: var Node[N, E]; key: E): var Node[N, E]
-
Index a node by edge key, returning the opposite (mutable) node.
Example:
var g = newGraph[int, string]() discard g.add 3 discard g.add 9 let squared = g.edge(g[3], "squared", g[9]) let n9 = g[3]["squared"] assert n9.value == 9
Source Edit proc clear[N, E; F: static[GraphFlags]](graph: var Graph[N, E, F])
-
Empty a graph of all nodes and edges.
Example:
var g = newGraph[int, string]() discard g.add 3 clear(g) assert len(g) == 0
Source Edit proc contains[N, E; F: static[GraphFlags]](graph: Graph[N, E, F]; edge: Edge[N, E]): bool
-
Returns true if graph contains edge. O(1).
Example:
var g = newGraph[int, string]() discard g.add 3 discard g.add 27 let e = g.edge(g[3], "cubed", g[27]) assert e in g
Source Edit proc contains[N, E; F: static[GraphFlags]](graph: Graph[N, E, F]; node: Node[N, E]): bool
-
Returns true if graph contains node. O(1).
Example:
var g = newGraph[int, string]() let n = g.add 3 assert n in g
Source Edit proc contains[N, E; F: static[GraphFlags]](graph: Graph[N, E, F]; value: N): bool
-
Returns true if graph contains a node with the given value. O(1) for ValueIndex graphs, else O(n).
Example:
var g = newGraph[int, string]() discard g.add 3 assert 3 in g
Source Edit proc contains[N, E](edge: Edge[N, E]; node: Node[N, E]): bool
-
Returns true if the edge links to node; else false. O(1).
Example:
var g = newGraph[int, string]() discard g.add 3 discard g.add 9 discard g.edge(g[3], "squared", g[9]) for source, edge, target in g.edges: assert source in edge assert target in edge
Source Edit proc contains[N, E](edge: Edge[N, E]; value: N): bool
-
Returns true if edge links to a node with the given value; else false. O(1).
Example:
var g = newGraph[int, string]() discard g.add 3 discard g.add 9 discard g.edge(g[3], "squared", g[9]) let n = g[9] for source, edge, target in g.edges: assert 9 in edge assert 3 in edge
Source Edit proc del[N, E; F: static[GraphFlags]](graph: var Graph[N, E, F]; node: Node[N, E])
-
Remove a node from the graph; O(n). Has no effect if the node is not in the graph. Not O(1) yet.
Example:
var g = newGraph[int, string]() let n = g.add 3 g.del n assert len(g) == 0
Source Edit proc del[N, E](node: var Node[N, E]; edge: Edge[N, E])
- Remove edge from node. Of course, this also removes edge from the target node on the opposite side. O(log n). Source Edit
proc del[N, E](node: var Node[N, E]; value: E)
-
Remove edge with value value from node. Of course, this also removes the edge from the target node on the opposite side. O(log n)
Example:
var g = newGraph[int, string]() discard g.add 3 discard g.add 9 discard g.edge(g[3], "squared", g[9]) var n9 = g[3]["squared"] n9.del "squared" assert not peers(g[3], n9)
Source Edit proc edge[N, E; F: static[GraphFlags]](graph: var Graph[N, E, F]; node: var Node[N, E]; value: E; target: var Node[N, E]): Edge[N, E]
-
Link node to target via a new edge of value; O(1).
Example:
var g = newGraph[int, string]() discard g.add 3 discard g.add 27 let e = g.edge(g[3], "cubed", g[27]) assert e.value == "cubed" assert g[3] in e assert g[27] in e
Source Edit proc hash[N, E, F](graph: Graph[N, E, F]): Hash
- Produce a Hash that uniquely identifies the graph based upon its contents. Source Edit
proc incl[N, E; F: static[GraphFlags]](graph: var Graph[N, E, F]; node: Node[N, E])
-
Includes a node in the graph. Has no effect if the node is already in the graph. O(1).
Example:
var g = newGraph[int, string]() let n = g.add 3 var q = newGraph[int, string]() q.incl n q.incl n assert len(q) == 1
Source Edit proc init(graph: var NoValueIndexGraph)
- Source Edit
proc init(graph: var ValueIndexGraph)
- Source Edit
proc len[N, E; F: static[GraphFlags]](graph: Graph[N, E, F]): int
-
Return the number of nodes in a graph. O(1).
Example:
var g = newGraph[int, string]() assert len(g) == 0
Source Edit proc newContainer[N, E, F](graph: Graph[N, E, F]; form: typedesc): auto
- Create a new container for nodes or edges. Source Edit
proc nodesAreUnique[N, E, F](graph: Graph[N, E, F]): bool
-
Returns true if there are no nodes in the graph with duplicate values. O(1) for ValueIndex graphs, else O(n).
Example:
var g = newGraph[int, string]() discard g.add 3 discard g.add 9 assert g.nodesAreUnique discard g.add 3 assert not g.nodesAreUnique
Source Edit
Iterators
iterator edges[N, E; F: static[GraphFlags]](graph: Graph[N, E, F]): EdgeResult[ N, E]
-
Yield source node, edge, and target node from a graph.
Example:
var g = newGraph[int, string]() discard g.add 3 discard g.add 9 discard g.edge(g[3], "squared", g[9]) for source, edge, target in edges(g): assert edge.value == "squared" assert source.value == 3 assert target.value == 9
Source Edit iterator items[N, E; F: static[GraphFlags]](graph: Graph[N, E, F]): N
-
Yield the values of nodes in the graph.
Example:
var g = newGraph[int, string]() discard g.add 3 for value in items(g): assert value == 3
Source Edit
Converters
converter toFlags(value: GraphFlags): set[GraphFlag] {....raises: [], tags: [], forbids: [].}
- Source Edit
converter toInt(flags: set[GraphFlag]): GraphFlags {....raises: [], tags: [], forbids: [].}
- Source Edit