mirror of
https://github.com/gonum/gonum.git
synced 2025-10-20 21:59:25 +08:00
graph/simple: factor id handling out of graphs
This commit is contained in:
@@ -7,8 +7,6 @@ package simple
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"golang.org/x/tools/container/intsets"
|
|
||||||
|
|
||||||
"gonum.org/v1/gonum/graph"
|
"gonum.org/v1/gonum/graph"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,8 +18,7 @@ type DirectedGraph struct {
|
|||||||
|
|
||||||
self, absent float64
|
self, absent float64
|
||||||
|
|
||||||
freeIDs intsets.Sparse
|
nodeIDs idSet
|
||||||
usedIDs intsets.Sparse
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDirectedGraph returns a DirectedGraph with the specified self and absent
|
// NewDirectedGraph returns a DirectedGraph with the specified self and absent
|
||||||
@@ -44,22 +41,9 @@ func (g *DirectedGraph) NewNodeID() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if len(g.nodes) == maxInt {
|
if len(g.nodes) == maxInt {
|
||||||
panic(fmt.Sprintf("simple: cannot allocate node: no slot"))
|
panic("simple: cannot allocate node: no slot")
|
||||||
}
|
}
|
||||||
|
return g.nodeIDs.newID()
|
||||||
var id int
|
|
||||||
if g.freeIDs.Len() != 0 && g.freeIDs.TakeMin(&id) {
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
if id = g.usedIDs.Max(); id < maxInt {
|
|
||||||
return id + 1
|
|
||||||
}
|
|
||||||
for id = 0; id < maxInt; id++ {
|
|
||||||
if !g.usedIDs.Has(id) {
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID.
|
// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID.
|
||||||
@@ -70,9 +54,7 @@ func (g *DirectedGraph) AddNode(n graph.Node) {
|
|||||||
g.nodes[n.ID()] = n
|
g.nodes[n.ID()] = n
|
||||||
g.from[n.ID()] = make(map[int]graph.Edge)
|
g.from[n.ID()] = make(map[int]graph.Edge)
|
||||||
g.to[n.ID()] = make(map[int]graph.Edge)
|
g.to[n.ID()] = make(map[int]graph.Edge)
|
||||||
|
g.nodeIDs.use(n.ID())
|
||||||
g.freeIDs.Remove(n.ID())
|
|
||||||
g.usedIDs.Insert(n.ID())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveNode removes n from the graph, as well as any edges attached to it. If the node
|
// RemoveNode removes n from the graph, as well as any edges attached to it. If the node
|
||||||
@@ -93,8 +75,7 @@ func (g *DirectedGraph) RemoveNode(n graph.Node) {
|
|||||||
}
|
}
|
||||||
delete(g.to, n.ID())
|
delete(g.to, n.ID())
|
||||||
|
|
||||||
g.freeIDs.Insert(n.ID())
|
g.nodeIDs.release(n.ID())
|
||||||
g.usedIDs.Remove(n.ID())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added.
|
// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added.
|
||||||
|
@@ -9,6 +9,8 @@ package simple // import "gonum.org/v1/gonum/graph/simple"
|
|||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
|
"golang.org/x/tools/container/intsets"
|
||||||
|
|
||||||
"gonum.org/v1/gonum/graph"
|
"gonum.org/v1/gonum/graph"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -43,3 +45,37 @@ const maxInt int = int(^uint(0) >> 1)
|
|||||||
func isSame(a, b float64) bool {
|
func isSame(a, b float64) bool {
|
||||||
return a == b || (math.IsNaN(a) && math.IsNaN(b))
|
return a == b || (math.IsNaN(a) && math.IsNaN(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// idSet implements available ID storage.
|
||||||
|
type idSet struct {
|
||||||
|
used, free intsets.Sparse
|
||||||
|
}
|
||||||
|
|
||||||
|
// newID returns a new unique ID.
|
||||||
|
func (s *idSet) newID() int {
|
||||||
|
var id int
|
||||||
|
if s.free.TakeMin(&id) {
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
if id = s.used.Max(); id < maxInt {
|
||||||
|
return id + 1
|
||||||
|
}
|
||||||
|
for id = 0; id < maxInt; id++ {
|
||||||
|
if !s.used.Has(id) {
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
|
// use adds the id to the used IDs in the idSet.
|
||||||
|
func (s *idSet) use(id int) {
|
||||||
|
s.free.Remove(id)
|
||||||
|
s.used.Insert(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// free frees the id for reuse.
|
||||||
|
func (s *idSet) release(id int) {
|
||||||
|
s.free.Insert(id)
|
||||||
|
s.used.Remove(id)
|
||||||
|
}
|
||||||
|
@@ -7,8 +7,6 @@ package simple
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"golang.org/x/tools/container/intsets"
|
|
||||||
|
|
||||||
"gonum.org/v1/gonum/graph"
|
"gonum.org/v1/gonum/graph"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,8 +17,7 @@ type UndirectedGraph struct {
|
|||||||
|
|
||||||
self, absent float64
|
self, absent float64
|
||||||
|
|
||||||
freeIDs intsets.Sparse
|
nodeIDs idSet
|
||||||
usedIDs intsets.Sparse
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUndirectedGraph returns an UndirectedGraph with the specified self and absent
|
// NewUndirectedGraph returns an UndirectedGraph with the specified self and absent
|
||||||
@@ -42,22 +39,9 @@ func (g *UndirectedGraph) NewNodeID() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if len(g.nodes) == maxInt {
|
if len(g.nodes) == maxInt {
|
||||||
panic(fmt.Sprintf("simple: cannot allocate node: no slot"))
|
panic("simple: cannot allocate node: no slot")
|
||||||
}
|
}
|
||||||
|
return g.nodeIDs.newID()
|
||||||
var id int
|
|
||||||
if g.freeIDs.Len() != 0 && g.freeIDs.TakeMin(&id) {
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
if id = g.usedIDs.Max(); id < maxInt {
|
|
||||||
return id + 1
|
|
||||||
}
|
|
||||||
for id = 0; id < maxInt; id++ {
|
|
||||||
if !g.usedIDs.Has(id) {
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID.
|
// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID.
|
||||||
@@ -67,9 +51,7 @@ func (g *UndirectedGraph) AddNode(n graph.Node) {
|
|||||||
}
|
}
|
||||||
g.nodes[n.ID()] = n
|
g.nodes[n.ID()] = n
|
||||||
g.edges[n.ID()] = make(map[int]graph.Edge)
|
g.edges[n.ID()] = make(map[int]graph.Edge)
|
||||||
|
g.nodeIDs.use(n.ID())
|
||||||
g.freeIDs.Remove(n.ID())
|
|
||||||
g.usedIDs.Insert(n.ID())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveNode removes n from the graph, as well as any edges attached to it. If the node
|
// RemoveNode removes n from the graph, as well as any edges attached to it. If the node
|
||||||
@@ -85,9 +67,7 @@ func (g *UndirectedGraph) RemoveNode(n graph.Node) {
|
|||||||
}
|
}
|
||||||
delete(g.edges, n.ID())
|
delete(g.edges, n.ID())
|
||||||
|
|
||||||
g.freeIDs.Insert(n.ID())
|
g.nodeIDs.release(n.ID())
|
||||||
g.usedIDs.Remove(n.ID())
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added.
|
// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added.
|
||||||
|
Reference in New Issue
Block a user