graph.go 8.0 KB

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