| // Copyright ©2014 The Gonum Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package graph |
| |
| // Node is a graph node. It returns a graph-unique integer ID. |
| type Node interface { |
| ID() int64 |
| } |
| |
| // Edge is a graph edge. In directed graphs, the direction of the |
| // edge is given from -> to, otherwise the edge is semantically |
| // unordered. |
| type Edge interface { |
| // From returns the from node of the edge. |
| From() Node |
| |
| // To returns the to node of the edge. |
| To() Node |
| |
| // ReversedEdge returns an edge that has |
| // the end points of the receiver swapped. |
| ReversedEdge() Edge |
| } |
| |
| // WeightedEdge is a weighted graph edge. In directed graphs, the direction |
| // of the edge is given from -> to, otherwise the edge is semantically |
| // unordered. |
| type WeightedEdge interface { |
| Edge |
| Weight() float64 |
| } |
| |
| // Graph is a generalized graph. |
| type Graph interface { |
| // Node returns the node with the given ID if it exists |
| // in the graph, and nil otherwise. |
| Node(id int64) Node |
| |
| // Nodes returns all the nodes in the graph. |
| // |
| // Nodes must not return nil. |
| Nodes() Nodes |
| |
| // From returns all nodes that can be reached directly |
| // from the node with the given ID. |
| // |
| // From must not return nil. |
| From(id int64) Nodes |
| |
| // HasEdgeBetween returns whether an edge exists between |
| // nodes with IDs xid and yid without considering direction. |
| HasEdgeBetween(xid, yid int64) bool |
| |
| // Edge returns the edge from u to v, with IDs uid and vid, |
| // if such an edge exists and nil otherwise. The node v |
| // must be directly reachable from u as defined by the |
| // From method. |
| Edge(uid, vid int64) Edge |
| } |
| |
| // Weighted is a weighted graph. |
| type Weighted interface { |
| Graph |
| |
| // WeightedEdge returns the weighted edge from u to v |
| // with IDs uid and vid if such an edge exists and |
| // nil otherwise. The node v must be directly |
| // reachable from u as defined by the From method. |
| WeightedEdge(uid, vid int64) WeightedEdge |
| |
| // Weight returns the weight for the edge between |
| // x and y with IDs xid and yid if Edge(xid, yid) |
| // returns a non-nil Edge. |
| // If x and y are the same node or there is no |
| // joining edge between the two nodes the weight |
| // value returned is implementation dependent. |
| // Weight returns true if an edge exists between |
| // x and y or if x and y have the same ID, false |
| // otherwise. |
| Weight(xid, yid int64) (w float64, ok bool) |
| } |
| |
| // Undirected is an undirected graph. |
| type Undirected interface { |
| Graph |
| |
| // EdgeBetween returns the edge between nodes x and y |
| // with IDs xid and yid. |
| EdgeBetween(xid, yid int64) Edge |
| } |
| |
| // WeightedUndirected is a weighted undirected graph. |
| type WeightedUndirected interface { |
| Weighted |
| |
| // WeightedEdgeBetween returns the edge between nodes |
| // x and y with IDs xid and yid. |
| WeightedEdgeBetween(xid, yid int64) WeightedEdge |
| } |
| |
| // Directed is a directed graph. |
| type Directed interface { |
| Graph |
| |
| // HasEdgeFromTo returns whether an edge exists |
| // in the graph from u to v with IDs uid and vid. |
| HasEdgeFromTo(uid, vid int64) bool |
| |
| // To returns all nodes that can reach directly |
| // to the node with the given ID. |
| // |
| // To must not return nil. |
| To(id int64) Nodes |
| } |
| |
| // WeightedDirected is a weighted directed graph. |
| type WeightedDirected interface { |
| Weighted |
| |
| // HasEdgeFromTo returns whether an edge exists |
| // in the graph from u to v with the IDs uid and |
| // vid. |
| HasEdgeFromTo(uid, vid int64) bool |
| |
| // To returns all nodes that can reach directly |
| // to the node with the given ID. |
| // |
| // To must not return nil. |
| To(id int64) Nodes |
| } |
| |
| // NodeAdder is an interface for adding arbitrary nodes to a graph. |
| type NodeAdder interface { |
| // NewNode returns a new Node with a unique |
| // arbitrary ID. |
| NewNode() Node |
| |
| // AddNode adds a node to the graph. AddNode panics if |
| // the added node ID matches an existing node ID. |
| AddNode(Node) |
| } |
| |
| // NodeRemover is an interface for removing nodes from a graph. |
| type NodeRemover interface { |
| // RemoveNode removes the node with the given ID |
| // from the graph, as well as any edges attached |
| // to it. If the node is not in the graph it is |
| // a no-op. |
| RemoveNode(id int64) |
| } |
| |
| // EdgeAdder is an interface for adding edges to a graph. |
| type EdgeAdder interface { |
| // NewEdge returns a new Edge from the source to the destination node. |
| NewEdge(from, to Node) Edge |
| |
| // SetEdge adds an edge from one node to another. |
| // If the graph supports node addition the nodes |
| // will be added if they do not exist, otherwise |
| // SetEdge will panic. |
| // The behavior of an EdgeAdder when the IDs |
| // returned by e.From() and e.To() are equal is |
| // implementation-dependent. |
| // Whether e, e.From() and e.To() are stored |
| // within the graph is implementation dependent. |
| SetEdge(e Edge) |
| } |
| |
| // WeightedEdgeAdder is an interface for adding edges to a graph. |
| type WeightedEdgeAdder interface { |
| // NewWeightedEdge returns a new WeightedEdge from |
| // the source to the destination node. |
| NewWeightedEdge(from, to Node, weight float64) WeightedEdge |
| |
| // SetWeightedEdge adds an edge from one node to |
| // another. If the graph supports node addition |
| // the nodes will be added if they do not exist, |
| // otherwise SetWeightedEdge will panic. |
| // The behavior of a WeightedEdgeAdder when the IDs |
| // returned by e.From() and e.To() are equal is |
| // implementation-dependent. |
| // Whether e, e.From() and e.To() are stored |
| // within the graph is implementation dependent. |
| SetWeightedEdge(e WeightedEdge) |
| } |
| |
| // EdgeRemover is an interface for removing nodes from a graph. |
| type EdgeRemover interface { |
| // RemoveEdge removes the edge with the given end |
| // IDs, leaving the terminal nodes. If the edge |
| // does not exist it is a no-op. |
| RemoveEdge(fid, tid int64) |
| } |
| |
| // Builder is a graph that can have nodes and edges added. |
| type Builder interface { |
| NodeAdder |
| EdgeAdder |
| } |
| |
| // WeightedBuilder is a graph that can have nodes and weighted edges added. |
| type WeightedBuilder interface { |
| NodeAdder |
| WeightedEdgeAdder |
| } |
| |
| // UndirectedBuilder is an undirected graph builder. |
| type UndirectedBuilder interface { |
| Undirected |
| Builder |
| } |
| |
| // UndirectedWeightedBuilder is an undirected weighted graph builder. |
| type UndirectedWeightedBuilder interface { |
| Undirected |
| WeightedBuilder |
| } |
| |
| // DirectedBuilder is a directed graph builder. |
| type DirectedBuilder interface { |
| Directed |
| Builder |
| } |
| |
| // DirectedWeightedBuilder is a directed weighted graph builder. |
| type DirectedWeightedBuilder interface { |
| Directed |
| WeightedBuilder |
| } |
| |
| // Copy copies nodes and edges as undirected edges from the source to the destination |
| // without first clearing the destination. Copy will panic if a node ID in the source |
| // graph matches a node ID in the destination. |
| // |
| // If the source is undirected and the destination is directed both directions will |
| // be present in the destination after the copy is complete. |
| func Copy(dst Builder, src Graph) { |
| nodes := src.Nodes() |
| for nodes.Next() { |
| dst.AddNode(nodes.Node()) |
| } |
| nodes.Reset() |
| for nodes.Next() { |
| u := nodes.Node() |
| uid := u.ID() |
| to := src.From(uid) |
| for to.Next() { |
| v := to.Node() |
| dst.SetEdge(src.Edge(uid, v.ID())) |
| } |
| } |
| } |
| |
| // CopyWeighted copies nodes and edges as undirected edges from the source to the destination |
| // without first clearing the destination. Copy will panic if a node ID in the source |
| // graph matches a node ID in the destination. |
| // |
| // If the source is undirected and the destination is directed both directions will |
| // be present in the destination after the copy is complete. |
| // |
| // If the source is a directed graph, the destination is undirected, and a fundamental |
| // cycle exists with two nodes where the edge weights differ, the resulting destination |
| // graph's edge weight between those nodes is undefined. If there is a defined function |
| // to resolve such conflicts, an UndirectWeighted may be used to do this. |
| func CopyWeighted(dst WeightedBuilder, src Weighted) { |
| nodes := src.Nodes() |
| for nodes.Next() { |
| dst.AddNode(nodes.Node()) |
| } |
| nodes.Reset() |
| for nodes.Next() { |
| u := nodes.Node() |
| uid := u.ID() |
| to := src.From(uid) |
| for to.Next() { |
| v := to.Node() |
| dst.SetWeightedEdge(src.WeightedEdge(uid, v.ID())) |
| } |
| } |
| } |