undirected.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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 simple
  5. import (
  6. "fmt"
  7. "gonum.org/v1/gonum/graph"
  8. "gonum.org/v1/gonum/graph/internal/uid"
  9. "gonum.org/v1/gonum/graph/iterator"
  10. )
  11. var (
  12. ug *UndirectedGraph
  13. _ graph.Graph = ug
  14. _ graph.Undirected = ug
  15. _ graph.NodeAdder = ug
  16. _ graph.NodeRemover = ug
  17. _ graph.EdgeAdder = ug
  18. _ graph.EdgeRemover = ug
  19. )
  20. // UndirectedGraph implements a generalized undirected graph.
  21. type UndirectedGraph struct {
  22. nodes map[int64]graph.Node
  23. edges map[int64]map[int64]graph.Edge
  24. nodeIDs uid.Set
  25. }
  26. // NewUndirectedGraph returns an UndirectedGraph.
  27. func NewUndirectedGraph() *UndirectedGraph {
  28. return &UndirectedGraph{
  29. nodes: make(map[int64]graph.Node),
  30. edges: make(map[int64]map[int64]graph.Edge),
  31. nodeIDs: uid.NewSet(),
  32. }
  33. }
  34. // AddNode adds n to the graph. It panics if the added node ID matches an existing node ID.
  35. func (g *UndirectedGraph) AddNode(n graph.Node) {
  36. if _, exists := g.nodes[n.ID()]; exists {
  37. panic(fmt.Sprintf("simple: node ID collision: %d", n.ID()))
  38. }
  39. g.nodes[n.ID()] = n
  40. g.nodeIDs.Use(n.ID())
  41. }
  42. // Edge returns the edge from u to v if such an edge exists and nil otherwise.
  43. // The node v must be directly reachable from u as defined by the From method.
  44. func (g *UndirectedGraph) Edge(uid, vid int64) graph.Edge {
  45. return g.EdgeBetween(uid, vid)
  46. }
  47. // EdgeBetween returns the edge between nodes x and y.
  48. func (g *UndirectedGraph) EdgeBetween(xid, yid int64) graph.Edge {
  49. edge, ok := g.edges[xid][yid]
  50. if !ok {
  51. return nil
  52. }
  53. if edge.From().ID() == xid {
  54. return edge
  55. }
  56. return edge.ReversedEdge()
  57. }
  58. // Edges returns all the edges in the graph.
  59. func (g *UndirectedGraph) Edges() graph.Edges {
  60. if len(g.edges) == 0 {
  61. return graph.Empty
  62. }
  63. var edges []graph.Edge
  64. seen := make(map[[2]int64]struct{})
  65. for _, u := range g.edges {
  66. for _, e := range u {
  67. uid := e.From().ID()
  68. vid := e.To().ID()
  69. if _, ok := seen[[2]int64{uid, vid}]; ok {
  70. continue
  71. }
  72. seen[[2]int64{uid, vid}] = struct{}{}
  73. seen[[2]int64{vid, uid}] = struct{}{}
  74. edges = append(edges, e)
  75. }
  76. }
  77. if len(edges) == 0 {
  78. return graph.Empty
  79. }
  80. return iterator.NewOrderedEdges(edges)
  81. }
  82. // From returns all nodes in g that can be reached directly from n.
  83. func (g *UndirectedGraph) From(id int64) graph.Nodes {
  84. if _, ok := g.nodes[id]; !ok {
  85. return graph.Empty
  86. }
  87. nodes := make([]graph.Node, len(g.edges[id]))
  88. i := 0
  89. for from := range g.edges[id] {
  90. nodes[i] = g.nodes[from]
  91. i++
  92. }
  93. if len(nodes) == 0 {
  94. return graph.Empty
  95. }
  96. return iterator.NewOrderedNodes(nodes)
  97. }
  98. // HasEdgeBetween returns whether an edge exists between nodes x and y.
  99. func (g *UndirectedGraph) HasEdgeBetween(xid, yid int64) bool {
  100. _, ok := g.edges[xid][yid]
  101. return ok
  102. }
  103. // NewEdge returns a new Edge from the source to the destination node.
  104. func (g *UndirectedGraph) NewEdge(from, to graph.Node) graph.Edge {
  105. return &Edge{F: from, T: to}
  106. }
  107. // NewNode returns a new unique Node to be added to g. The Node's ID does
  108. // not become valid in g until the Node is added to g.
  109. func (g *UndirectedGraph) NewNode() graph.Node {
  110. if len(g.nodes) == 0 {
  111. return Node(0)
  112. }
  113. if int64(len(g.nodes)) == uid.Max {
  114. panic("simple: cannot allocate node: no slot")
  115. }
  116. return Node(g.nodeIDs.NewID())
  117. }
  118. // Node returns the node with the given ID if it exists in the graph,
  119. // and nil otherwise.
  120. func (g *UndirectedGraph) Node(id int64) graph.Node {
  121. return g.nodes[id]
  122. }
  123. // Nodes returns all the nodes in the graph.
  124. func (g *UndirectedGraph) Nodes() graph.Nodes {
  125. if len(g.nodes) == 0 {
  126. return graph.Empty
  127. }
  128. nodes := make([]graph.Node, len(g.nodes))
  129. i := 0
  130. for _, n := range g.nodes {
  131. nodes[i] = n
  132. i++
  133. }
  134. return iterator.NewOrderedNodes(nodes)
  135. }
  136. // RemoveEdge removes the edge with the given end IDs from the graph, leaving the terminal nodes.
  137. // If the edge does not exist it is a no-op.
  138. func (g *UndirectedGraph) RemoveEdge(fid, tid int64) {
  139. if _, ok := g.nodes[fid]; !ok {
  140. return
  141. }
  142. if _, ok := g.nodes[tid]; !ok {
  143. return
  144. }
  145. delete(g.edges[fid], tid)
  146. delete(g.edges[tid], fid)
  147. }
  148. // RemoveNode removes the node with the given ID from the graph, as well as any edges attached
  149. // to it. If the node is not in the graph it is a no-op.
  150. func (g *UndirectedGraph) RemoveNode(id int64) {
  151. if _, ok := g.nodes[id]; !ok {
  152. return
  153. }
  154. delete(g.nodes, id)
  155. for from := range g.edges[id] {
  156. delete(g.edges[from], id)
  157. }
  158. delete(g.edges, id)
  159. g.nodeIDs.Release(id)
  160. }
  161. // SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added
  162. // and are set to the nodes of the edge otherwise.
  163. // It will panic if the IDs of the e.From and e.To are equal.
  164. func (g *UndirectedGraph) SetEdge(e graph.Edge) {
  165. var (
  166. from = e.From()
  167. fid = from.ID()
  168. to = e.To()
  169. tid = to.ID()
  170. )
  171. if fid == tid {
  172. panic("simple: adding self edge")
  173. }
  174. if _, ok := g.nodes[fid]; !ok {
  175. g.AddNode(from)
  176. } else {
  177. g.nodes[fid] = from
  178. }
  179. if _, ok := g.nodes[tid]; !ok {
  180. g.AddNode(to)
  181. } else {
  182. g.nodes[tid] = to
  183. }
  184. if fm, ok := g.edges[fid]; ok {
  185. fm[tid] = e
  186. } else {
  187. g.edges[fid] = map[int64]graph.Edge{tid: e}
  188. }
  189. if tm, ok := g.edges[tid]; ok {
  190. tm[fid] = e
  191. } else {
  192. g.edges[tid] = map[int64]graph.Edge{fid: e}
  193. }
  194. }