github.com/gopherd/gonum@v0.0.4/graph/graph.go (about) 1 // Copyright ©2014 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package graph 6 7 // Node is a graph node. It returns a graph-unique integer ID. 8 type Node interface { 9 ID() int64 10 } 11 12 // Edge is a graph edge. In directed graphs, the direction of the 13 // edge is given from -> to, otherwise the edge is semantically 14 // unordered. 15 type Edge interface { 16 // From returns the from node of the edge. 17 From() Node 18 19 // To returns the to node of the edge. 20 To() Node 21 22 // ReversedEdge returns the edge reversal of the receiver 23 // if a reversal is valid for the data type. 24 // When a reversal is valid an edge of the same type as 25 // the receiver with nodes of the receiver swapped should 26 // be returned, otherwise the receiver should be returned 27 // unaltered. 28 ReversedEdge() Edge 29 } 30 31 // WeightedEdge is a weighted graph edge. In directed graphs, the direction 32 // of the edge is given from -> to, otherwise the edge is semantically 33 // unordered. 34 type WeightedEdge interface { 35 Edge 36 Weight() float64 37 } 38 39 // Graph is a generalized graph. 40 type Graph interface { 41 // Node returns the node with the given ID if it exists 42 // in the graph, and nil otherwise. 43 Node(id int64) Node 44 45 // Nodes returns all the nodes in the graph. 46 // 47 // Nodes must not return nil. 48 Nodes() Nodes 49 50 // From returns all nodes that can be reached directly 51 // from the node with the given ID. 52 // 53 // From must not return nil. 54 From(id int64) Nodes 55 56 // HasEdgeBetween returns whether an edge exists between 57 // nodes with IDs xid and yid without considering direction. 58 HasEdgeBetween(xid, yid int64) bool 59 60 // Edge returns the edge from u to v, with IDs uid and vid, 61 // if such an edge exists and nil otherwise. The node v 62 // must be directly reachable from u as defined by the 63 // From method. 64 Edge(uid, vid int64) Edge 65 } 66 67 // Weighted is a weighted graph. 68 type Weighted interface { 69 Graph 70 71 // WeightedEdge returns the weighted edge from u to v 72 // with IDs uid and vid if such an edge exists and 73 // nil otherwise. The node v must be directly 74 // reachable from u as defined by the From method. 75 WeightedEdge(uid, vid int64) WeightedEdge 76 77 // Weight returns the weight for the edge between 78 // x and y with IDs xid and yid if Edge(xid, yid) 79 // returns a non-nil Edge. 80 // If x and y are the same node or there is no 81 // joining edge between the two nodes the weight 82 // value returned is implementation dependent. 83 // Weight returns true if an edge exists between 84 // x and y or if x and y have the same ID, false 85 // otherwise. 86 Weight(xid, yid int64) (w float64, ok bool) 87 } 88 89 // Undirected is an undirected graph. 90 type Undirected interface { 91 Graph 92 93 // EdgeBetween returns the edge between nodes x and y 94 // with IDs xid and yid. 95 EdgeBetween(xid, yid int64) Edge 96 } 97 98 // WeightedUndirected is a weighted undirected graph. 99 type WeightedUndirected interface { 100 Weighted 101 102 // WeightedEdgeBetween returns the edge between nodes 103 // x and y with IDs xid and yid. 104 WeightedEdgeBetween(xid, yid int64) WeightedEdge 105 } 106 107 // Directed is a directed graph. 108 type Directed interface { 109 Graph 110 111 // HasEdgeFromTo returns whether an edge exists 112 // in the graph from u to v with IDs uid and vid. 113 HasEdgeFromTo(uid, vid int64) bool 114 115 // To returns all nodes that can reach directly 116 // to the node with the given ID. 117 // 118 // To must not return nil. 119 To(id int64) Nodes 120 } 121 122 // WeightedDirected is a weighted directed graph. 123 type WeightedDirected interface { 124 Weighted 125 126 // HasEdgeFromTo returns whether an edge exists 127 // in the graph from u to v with the IDs uid and 128 // vid. 129 HasEdgeFromTo(uid, vid int64) bool 130 131 // To returns all nodes that can reach directly 132 // to the node with the given ID. 133 // 134 // To must not return nil. 135 To(id int64) Nodes 136 } 137 138 // NodeAdder is an interface for adding arbitrary nodes to a graph. 139 type NodeAdder interface { 140 // NewNode returns a new Node with a unique 141 // arbitrary ID. 142 NewNode() Node 143 144 // AddNode adds a node to the graph. AddNode panics if 145 // the added node ID matches an existing node ID. 146 AddNode(Node) 147 } 148 149 // NodeWithIDer is a graph that can return potentially new nodes with 150 // a defined ID. 151 type NodeWithIDer interface { 152 // NodeWithID returns a Node with the given ID if possible. 153 // A nil Node will be returned if no Node exists or 154 // can be created. 155 // If a non-nil Node is returned that is not already in the 156 // graph NodeWithID will return true for new and the Node 157 // must be added to the graph before use. 158 NodeWithID(id int64) (n Node, new bool) 159 } 160 161 // NodeRemover is an interface for removing nodes from a graph. 162 type NodeRemover interface { 163 // RemoveNode removes the node with the given ID 164 // from the graph, as well as any edges attached 165 // to it. If the node is not in the graph it is 166 // a no-op. 167 RemoveNode(id int64) 168 } 169 170 // EdgeAdder is an interface for adding edges to a graph. 171 type EdgeAdder interface { 172 // NewEdge returns a new Edge from the source to the destination node. 173 NewEdge(from, to Node) Edge 174 175 // SetEdge adds an edge from one node to another. 176 // If the graph supports node addition the nodes 177 // will be added if they do not exist, otherwise 178 // SetEdge will panic. 179 // The behavior of an EdgeAdder when the IDs 180 // returned by e.From() and e.To() are equal is 181 // implementation-dependent. 182 // Whether e, e.From() and e.To() are stored 183 // within the graph is implementation dependent. 184 SetEdge(e Edge) 185 } 186 187 // WeightedEdgeAdder is an interface for adding edges to a graph. 188 type WeightedEdgeAdder interface { 189 // NewWeightedEdge returns a new WeightedEdge from 190 // the source to the destination node. 191 NewWeightedEdge(from, to Node, weight float64) WeightedEdge 192 193 // SetWeightedEdge adds an edge from one node to 194 // another. If the graph supports node addition 195 // the nodes will be added if they do not exist, 196 // otherwise SetWeightedEdge will panic. 197 // The behavior of a WeightedEdgeAdder when the IDs 198 // returned by e.From() and e.To() are equal is 199 // implementation-dependent. 200 // Whether e, e.From() and e.To() are stored 201 // within the graph is implementation dependent. 202 SetWeightedEdge(e WeightedEdge) 203 } 204 205 // EdgeRemover is an interface for removing nodes from a graph. 206 type EdgeRemover interface { 207 // RemoveEdge removes the edge with the given end 208 // IDs, leaving the terminal nodes. If the edge 209 // does not exist it is a no-op. 210 RemoveEdge(fid, tid int64) 211 } 212 213 // Builder is a graph that can have nodes and edges added. 214 type Builder interface { 215 NodeAdder 216 EdgeAdder 217 } 218 219 // WeightedBuilder is a graph that can have nodes and weighted edges added. 220 type WeightedBuilder interface { 221 NodeAdder 222 WeightedEdgeAdder 223 } 224 225 // UndirectedBuilder is an undirected graph builder. 226 type UndirectedBuilder interface { 227 Undirected 228 Builder 229 } 230 231 // UndirectedWeightedBuilder is an undirected weighted graph builder. 232 type UndirectedWeightedBuilder interface { 233 Undirected 234 WeightedBuilder 235 } 236 237 // DirectedBuilder is a directed graph builder. 238 type DirectedBuilder interface { 239 Directed 240 Builder 241 } 242 243 // DirectedWeightedBuilder is a directed weighted graph builder. 244 type DirectedWeightedBuilder interface { 245 Directed 246 WeightedBuilder 247 } 248 249 // Copy copies nodes and edges as undirected edges from the source to the destination 250 // without first clearing the destination. Copy will panic if a node ID in the source 251 // graph matches a node ID in the destination. 252 // 253 // If the source is undirected and the destination is directed both directions will 254 // be present in the destination after the copy is complete. 255 func Copy(dst Builder, src Graph) { 256 nodes := src.Nodes() 257 for nodes.Next() { 258 dst.AddNode(nodes.Node()) 259 } 260 nodes.Reset() 261 for nodes.Next() { 262 u := nodes.Node() 263 uid := u.ID() 264 to := src.From(uid) 265 for to.Next() { 266 v := to.Node() 267 dst.SetEdge(src.Edge(uid, v.ID())) 268 } 269 } 270 } 271 272 // CopyWeighted copies nodes and edges as undirected edges from the source to the destination 273 // without first clearing the destination. Copy will panic if a node ID in the source 274 // graph matches a node ID in the destination. 275 // 276 // If the source is undirected and the destination is directed both directions will 277 // be present in the destination after the copy is complete. 278 // 279 // If the source is a directed graph, the destination is undirected, and a fundamental 280 // cycle exists with two nodes where the edge weights differ, the resulting destination 281 // graph's edge weight between those nodes is undefined. If there is a defined function 282 // to resolve such conflicts, an UndirectWeighted may be used to do this. 283 func CopyWeighted(dst WeightedBuilder, src Weighted) { 284 nodes := src.Nodes() 285 for nodes.Next() { 286 dst.AddNode(nodes.Node()) 287 } 288 nodes.Reset() 289 for nodes.Next() { 290 u := nodes.Node() 291 uid := u.ID() 292 to := src.From(uid) 293 for to.Next() { 294 v := to.Node() 295 dst.SetWeightedEdge(src.WeightedEdge(uid, v.ID())) 296 } 297 } 298 }