...
1
2
3
4
5 package simple
6
7 import (
8 "fmt"
9
10 "golang.org/x/tools/container/intsets"
11
12 "k8s.io/kubernetes/third_party/forked/gonum/graph"
13 )
14
15
16 type UndirectedGraph struct {
17 nodes map[int]graph.Node
18 edges map[int]edgeHolder
19
20 self, absent float64
21
22 freeIDs intsets.Sparse
23 usedIDs intsets.Sparse
24 }
25
26
27
28 func NewUndirectedGraph(self, absent float64) *UndirectedGraph {
29 return &UndirectedGraph{
30 nodes: make(map[int]graph.Node),
31 edges: make(map[int]edgeHolder),
32
33 self: self,
34 absent: absent,
35 }
36 }
37
38
39
40 func (g *UndirectedGraph) NewNodeID() int {
41 if len(g.nodes) == 0 {
42 return 0
43 }
44 if len(g.nodes) == maxInt {
45 panic(fmt.Sprintf("simple: cannot allocate node: no slot"))
46 }
47
48 var id int
49 if g.freeIDs.Len() != 0 && g.freeIDs.TakeMin(&id) {
50 return id
51 }
52 if id = g.usedIDs.Max(); id < maxInt {
53 return id + 1
54 }
55 for id = 0; id < maxInt; id++ {
56 if !g.usedIDs.Has(id) {
57 return id
58 }
59 }
60 panic("unreachable")
61 }
62
63
64 func (g *UndirectedGraph) AddNode(n graph.Node) {
65 if _, exists := g.nodes[n.ID()]; exists {
66 panic(fmt.Sprintf("simple: node ID collision: %d", n.ID()))
67 }
68 g.nodes[n.ID()] = n
69 g.edges[n.ID()] = &sliceEdgeHolder{self: n.ID()}
70
71 g.freeIDs.Remove(n.ID())
72 g.usedIDs.Insert(n.ID())
73 }
74
75
76
77 func (g *UndirectedGraph) RemoveNode(n graph.Node) {
78 if _, ok := g.nodes[n.ID()]; !ok {
79 return
80 }
81 delete(g.nodes, n.ID())
82
83 g.edges[n.ID()].Visit(func(neighbor int, edge graph.Edge) {
84 g.edges[neighbor] = g.edges[neighbor].Delete(n.ID())
85 })
86 delete(g.edges, n.ID())
87
88 g.freeIDs.Insert(n.ID())
89 g.usedIDs.Remove(n.ID())
90
91 }
92
93
94
95 func (g *UndirectedGraph) SetEdge(e graph.Edge) {
96 var (
97 from = e.From()
98 fid = from.ID()
99 to = e.To()
100 tid = to.ID()
101 )
102
103 if fid == tid {
104 panic("simple: adding self edge")
105 }
106
107 if !g.Has(from) {
108 g.AddNode(from)
109 }
110 if !g.Has(to) {
111 g.AddNode(to)
112 }
113
114 g.edges[fid] = g.edges[fid].Set(tid, e)
115 g.edges[tid] = g.edges[tid].Set(fid, e)
116 }
117
118
119
120 func (g *UndirectedGraph) RemoveEdge(e graph.Edge) {
121 from, to := e.From(), e.To()
122 if _, ok := g.nodes[from.ID()]; !ok {
123 return
124 }
125 if _, ok := g.nodes[to.ID()]; !ok {
126 return
127 }
128
129 g.edges[from.ID()] = g.edges[from.ID()].Delete(to.ID())
130 g.edges[to.ID()] = g.edges[to.ID()].Delete(from.ID())
131 }
132
133
134 func (g *UndirectedGraph) Node(id int) graph.Node {
135 return g.nodes[id]
136 }
137
138
139 func (g *UndirectedGraph) Has(n graph.Node) bool {
140 _, ok := g.nodes[n.ID()]
141 return ok
142 }
143
144
145 func (g *UndirectedGraph) Nodes() []graph.Node {
146 nodes := make([]graph.Node, len(g.nodes))
147 i := 0
148 for _, n := range g.nodes {
149 nodes[i] = n
150 i++
151 }
152
153 return nodes
154 }
155
156
157 func (g *UndirectedGraph) Edges() []graph.Edge {
158 var edges []graph.Edge
159
160 seen := make(map[[2]int]struct{})
161 for _, u := range g.edges {
162 u.Visit(func(neighbor int, e graph.Edge) {
163 uid := e.From().ID()
164 vid := e.To().ID()
165 if _, ok := seen[[2]int{uid, vid}]; ok {
166 return
167 }
168 seen[[2]int{uid, vid}] = struct{}{}
169 seen[[2]int{vid, uid}] = struct{}{}
170 edges = append(edges, e)
171 })
172 }
173
174 return edges
175 }
176
177
178 func (g *UndirectedGraph) From(n graph.Node) []graph.Node {
179 if !g.Has(n) {
180 return nil
181 }
182
183 nodes := make([]graph.Node, g.edges[n.ID()].Len())
184 i := 0
185 g.edges[n.ID()].Visit(func(neighbor int, edge graph.Edge) {
186 nodes[i] = g.nodes[neighbor]
187 i++
188 })
189
190 return nodes
191 }
192
193
194 func (g *UndirectedGraph) HasEdgeBetween(x, y graph.Node) bool {
195 _, ok := g.edges[x.ID()].Get(y.ID())
196 return ok
197 }
198
199
200
201 func (g *UndirectedGraph) Edge(u, v graph.Node) graph.Edge {
202 return g.EdgeBetween(u, v)
203 }
204
205
206 func (g *UndirectedGraph) EdgeBetween(x, y graph.Node) graph.Edge {
207
208
209 if !g.Has(x) {
210 return nil
211 }
212
213 edge, _ := g.edges[x.ID()].Get(y.ID())
214 return edge
215 }
216
217
218
219
220
221 func (g *UndirectedGraph) Weight(x, y graph.Node) (w float64, ok bool) {
222 xid := x.ID()
223 yid := y.ID()
224 if xid == yid {
225 return g.self, true
226 }
227 if n, ok := g.edges[xid]; ok {
228 if e, ok := n.Get(yid); ok {
229 return e.Weight(), true
230 }
231 }
232 return g.absent, false
233 }
234
235
236 func (g *UndirectedGraph) Degree(n graph.Node) int {
237 if _, ok := g.nodes[n.ID()]; !ok {
238 return 0
239 }
240
241 return g.edges[n.ID()].Len()
242 }
243
View as plain text