mirror of
https://github.com/gonum/gonum.git
synced 2025-10-06 07:37:03 +08:00
graph,graph/{encoding/dot,internal/set,topo,traverse}: remove intsets imports
This commit is contained in:
@@ -7,11 +7,10 @@ package dot
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"golang.org/x/tools/container/intsets"
|
|
||||||
|
|
||||||
"gonum.org/v1/gonum/graph"
|
"gonum.org/v1/gonum/graph"
|
||||||
"gonum.org/v1/gonum/graph/formats/dot"
|
"gonum.org/v1/gonum/graph/formats/dot"
|
||||||
"gonum.org/v1/gonum/graph/formats/dot/ast"
|
"gonum.org/v1/gonum/graph/formats/dot/ast"
|
||||||
|
"gonum.org/v1/gonum/graph/internal/set"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Builder is a graph that can have user-defined nodes and edges added.
|
// Builder is a graph that can have user-defined nodes and edges added.
|
||||||
@@ -267,14 +266,14 @@ func (gen *generator) popSubgraph() []graph.Node {
|
|||||||
// unique returns the set of unique nodes contained within ns.
|
// unique returns the set of unique nodes contained within ns.
|
||||||
func unique(ns []graph.Node) []graph.Node {
|
func unique(ns []graph.Node) []graph.Node {
|
||||||
var nodes []graph.Node
|
var nodes []graph.Node
|
||||||
var set intsets.Sparse
|
seen := make(set.Ints)
|
||||||
for _, n := range ns {
|
for _, n := range ns {
|
||||||
id := n.ID()
|
id := n.ID()
|
||||||
if set.Has(id) {
|
if seen.Has(id) {
|
||||||
// skip duplicate node
|
// skip duplicate node
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
set.Insert(id)
|
seen.Add(id)
|
||||||
nodes = append(nodes, n)
|
nodes = append(nodes, n)
|
||||||
}
|
}
|
||||||
return nodes
|
return nodes
|
||||||
|
@@ -12,14 +12,14 @@ import (
|
|||||||
"gonum.org/v1/gonum/graph/simple"
|
"gonum.org/v1/gonum/graph/simple"
|
||||||
)
|
)
|
||||||
|
|
||||||
// set is an integer set.
|
// intset is an integer set.
|
||||||
type set map[int]struct{}
|
type intset map[int]struct{}
|
||||||
|
|
||||||
func linksTo(i ...int) set {
|
func linksTo(i ...int) intset {
|
||||||
if len(i) == 0 {
|
if len(i) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
s := make(set)
|
s := make(intset)
|
||||||
for _, v := range i {
|
for _, v := range i {
|
||||||
s[v] = struct{}{}
|
s[v] = struct{}{}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ func linksTo(i ...int) set {
|
|||||||
var (
|
var (
|
||||||
// Example graph from http://en.wikipedia.org/wiki/File:PageRanks-Example.svg 16:17, 8 July 2009
|
// Example graph from http://en.wikipedia.org/wiki/File:PageRanks-Example.svg 16:17, 8 July 2009
|
||||||
// Node identities are rewritten here to use integers from 0 to match with the DOT output.
|
// Node identities are rewritten here to use integers from 0 to match with the DOT output.
|
||||||
pageRankGraph = []set{
|
pageRankGraph = []intset{
|
||||||
0: nil,
|
0: nil,
|
||||||
1: linksTo(2),
|
1: linksTo(2),
|
||||||
2: linksTo(1),
|
2: linksTo(1),
|
||||||
@@ -44,7 +44,7 @@ var (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Example graph from http://en.wikipedia.org/w/index.php?title=PageRank&oldid=659286279#Power_Method
|
// Example graph from http://en.wikipedia.org/w/index.php?title=PageRank&oldid=659286279#Power_Method
|
||||||
powerMethodGraph = []set{
|
powerMethodGraph = []intset{
|
||||||
0: linksTo(1, 2),
|
0: linksTo(1, 2),
|
||||||
1: linksTo(3),
|
1: linksTo(3),
|
||||||
2: linksTo(3, 4),
|
2: linksTo(3, 4),
|
||||||
@@ -53,7 +53,7 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func directedGraphFrom(g []set) graph.Directed {
|
func directedGraphFrom(g []intset) graph.Directed {
|
||||||
dg := simple.NewDirectedGraph(0, math.Inf(1))
|
dg := simple.NewDirectedGraph(0, math.Inf(1))
|
||||||
for u, e := range g {
|
for u, e := range g {
|
||||||
for v := range e {
|
for v := range e {
|
||||||
@@ -63,7 +63,7 @@ func directedGraphFrom(g []set) graph.Directed {
|
|||||||
return dg
|
return dg
|
||||||
}
|
}
|
||||||
|
|
||||||
func undirectedGraphFrom(g []set) graph.Graph {
|
func undirectedGraphFrom(g []intset) graph.Graph {
|
||||||
dg := simple.NewUndirectedGraph(0, math.Inf(1))
|
dg := simple.NewUndirectedGraph(0, math.Inf(1))
|
||||||
for u, e := range g {
|
for u, e := range g {
|
||||||
for v := range e {
|
for v := range e {
|
||||||
@@ -83,7 +83,7 @@ type namedNode struct {
|
|||||||
func (n namedNode) ID() int { return n.id }
|
func (n namedNode) ID() int { return n.id }
|
||||||
func (n namedNode) DOTID() string { return n.name }
|
func (n namedNode) DOTID() string { return n.name }
|
||||||
|
|
||||||
func directedNamedIDGraphFrom(g []set) graph.Directed {
|
func directedNamedIDGraphFrom(g []intset) graph.Directed {
|
||||||
dg := simple.NewDirectedGraph(0, math.Inf(1))
|
dg := simple.NewDirectedGraph(0, math.Inf(1))
|
||||||
for u, e := range g {
|
for u, e := range g {
|
||||||
nu := namedNode{id: u, name: alpha[u : u+1]}
|
nu := namedNode{id: u, name: alpha[u : u+1]}
|
||||||
@@ -95,7 +95,7 @@ func directedNamedIDGraphFrom(g []set) graph.Directed {
|
|||||||
return dg
|
return dg
|
||||||
}
|
}
|
||||||
|
|
||||||
func undirectedNamedIDGraphFrom(g []set) graph.Graph {
|
func undirectedNamedIDGraphFrom(g []intset) graph.Graph {
|
||||||
dg := simple.NewUndirectedGraph(0, math.Inf(1))
|
dg := simple.NewUndirectedGraph(0, math.Inf(1))
|
||||||
for u, e := range g {
|
for u, e := range g {
|
||||||
nu := namedNode{id: u, name: alpha[u : u+1]}
|
nu := namedNode{id: u, name: alpha[u : u+1]}
|
||||||
@@ -116,7 +116,7 @@ type attrNode struct {
|
|||||||
func (n attrNode) ID() int { return n.id }
|
func (n attrNode) ID() int { return n.id }
|
||||||
func (n attrNode) DOTAttributes() []Attribute { return n.attr }
|
func (n attrNode) DOTAttributes() []Attribute { return n.attr }
|
||||||
|
|
||||||
func directedNodeAttrGraphFrom(g []set, attr [][]Attribute) graph.Directed {
|
func directedNodeAttrGraphFrom(g []intset, attr [][]Attribute) graph.Directed {
|
||||||
dg := simple.NewDirectedGraph(0, math.Inf(1))
|
dg := simple.NewDirectedGraph(0, math.Inf(1))
|
||||||
for u, e := range g {
|
for u, e := range g {
|
||||||
var at []Attribute
|
var at []Attribute
|
||||||
@@ -135,7 +135,7 @@ func directedNodeAttrGraphFrom(g []set, attr [][]Attribute) graph.Directed {
|
|||||||
return dg
|
return dg
|
||||||
}
|
}
|
||||||
|
|
||||||
func undirectedNodeAttrGraphFrom(g []set, attr [][]Attribute) graph.Graph {
|
func undirectedNodeAttrGraphFrom(g []intset, attr [][]Attribute) graph.Graph {
|
||||||
dg := simple.NewUndirectedGraph(0, math.Inf(1))
|
dg := simple.NewUndirectedGraph(0, math.Inf(1))
|
||||||
for u, e := range g {
|
for u, e := range g {
|
||||||
var at []Attribute
|
var at []Attribute
|
||||||
@@ -164,7 +164,7 @@ func (n namedAttrNode) ID() int { return n.id }
|
|||||||
func (n namedAttrNode) DOTID() string { return n.name }
|
func (n namedAttrNode) DOTID() string { return n.name }
|
||||||
func (n namedAttrNode) DOTAttributes() []Attribute { return n.attr }
|
func (n namedAttrNode) DOTAttributes() []Attribute { return n.attr }
|
||||||
|
|
||||||
func directedNamedIDNodeAttrGraphFrom(g []set, attr [][]Attribute) graph.Directed {
|
func directedNamedIDNodeAttrGraphFrom(g []intset, attr [][]Attribute) graph.Directed {
|
||||||
dg := simple.NewDirectedGraph(0, math.Inf(1))
|
dg := simple.NewDirectedGraph(0, math.Inf(1))
|
||||||
for u, e := range g {
|
for u, e := range g {
|
||||||
var at []Attribute
|
var at []Attribute
|
||||||
@@ -183,7 +183,7 @@ func directedNamedIDNodeAttrGraphFrom(g []set, attr [][]Attribute) graph.Directe
|
|||||||
return dg
|
return dg
|
||||||
}
|
}
|
||||||
|
|
||||||
func undirectedNamedIDNodeAttrGraphFrom(g []set, attr [][]Attribute) graph.Graph {
|
func undirectedNamedIDNodeAttrGraphFrom(g []intset, attr [][]Attribute) graph.Graph {
|
||||||
dg := simple.NewUndirectedGraph(0, math.Inf(1))
|
dg := simple.NewUndirectedGraph(0, math.Inf(1))
|
||||||
for u, e := range g {
|
for u, e := range g {
|
||||||
var at []Attribute
|
var at []Attribute
|
||||||
@@ -213,7 +213,7 @@ func (e attrEdge) To() graph.Node { return e.to }
|
|||||||
func (e attrEdge) Weight() float64 { return 0 }
|
func (e attrEdge) Weight() float64 { return 0 }
|
||||||
func (e attrEdge) DOTAttributes() []Attribute { return e.attr }
|
func (e attrEdge) DOTAttributes() []Attribute { return e.attr }
|
||||||
|
|
||||||
func directedEdgeAttrGraphFrom(g []set, attr map[edge][]Attribute) graph.Directed {
|
func directedEdgeAttrGraphFrom(g []intset, attr map[edge][]Attribute) graph.Directed {
|
||||||
dg := simple.NewDirectedGraph(0, math.Inf(1))
|
dg := simple.NewDirectedGraph(0, math.Inf(1))
|
||||||
for u, e := range g {
|
for u, e := range g {
|
||||||
for v := range e {
|
for v := range e {
|
||||||
@@ -223,7 +223,7 @@ func directedEdgeAttrGraphFrom(g []set, attr map[edge][]Attribute) graph.Directe
|
|||||||
return dg
|
return dg
|
||||||
}
|
}
|
||||||
|
|
||||||
func undirectedEdgeAttrGraphFrom(g []set, attr map[edge][]Attribute) graph.Graph {
|
func undirectedEdgeAttrGraphFrom(g []intset, attr map[edge][]Attribute) graph.Graph {
|
||||||
dg := simple.NewUndirectedGraph(0, math.Inf(1))
|
dg := simple.NewUndirectedGraph(0, math.Inf(1))
|
||||||
for u, e := range g {
|
for u, e := range g {
|
||||||
for v := range e {
|
for v := range e {
|
||||||
@@ -263,7 +263,7 @@ func (e portedEdge) ToPort() (port, compass string) {
|
|||||||
return e.toPort, e.toCompass
|
return e.toPort, e.toCompass
|
||||||
}
|
}
|
||||||
|
|
||||||
func directedPortedAttrGraphFrom(g []set, attr [][]Attribute, ports map[edge]portedEdge) graph.Directed {
|
func directedPortedAttrGraphFrom(g []intset, attr [][]Attribute, ports map[edge]portedEdge) graph.Directed {
|
||||||
dg := simple.NewDirectedGraph(0, math.Inf(1))
|
dg := simple.NewDirectedGraph(0, math.Inf(1))
|
||||||
for u, e := range g {
|
for u, e := range g {
|
||||||
var at []Attribute
|
var at []Attribute
|
||||||
@@ -284,7 +284,7 @@ func directedPortedAttrGraphFrom(g []set, attr [][]Attribute, ports map[edge]por
|
|||||||
return dg
|
return dg
|
||||||
}
|
}
|
||||||
|
|
||||||
func undirectedPortedAttrGraphFrom(g []set, attr [][]Attribute, ports map[edge]portedEdge) graph.Graph {
|
func undirectedPortedAttrGraphFrom(g []intset, attr [][]Attribute, ports map[edge]portedEdge) graph.Graph {
|
||||||
dg := simple.NewUndirectedGraph(0, math.Inf(1))
|
dg := simple.NewUndirectedGraph(0, math.Inf(1))
|
||||||
for u, e := range g {
|
for u, e := range g {
|
||||||
var at []Attribute
|
var at []Attribute
|
||||||
@@ -325,7 +325,7 @@ type structuredGraph struct {
|
|||||||
sub []Graph
|
sub []Graph
|
||||||
}
|
}
|
||||||
|
|
||||||
func undirectedStructuredGraphFrom(c []edge, g ...[]set) graph.Graph {
|
func undirectedStructuredGraphFrom(c []edge, g ...[]intset) graph.Graph {
|
||||||
s := &structuredGraph{UndirectedGraph: simple.NewUndirectedGraph(0, math.Inf(1))}
|
s := &structuredGraph{UndirectedGraph: simple.NewUndirectedGraph(0, math.Inf(1))}
|
||||||
var base int
|
var base int
|
||||||
for i, sg := range g {
|
for i, sg := range g {
|
||||||
@@ -366,7 +366,7 @@ func (g subGraph) Subgraph() graph.Graph {
|
|||||||
return namedGraph{id: g.id, Graph: g.Graph}
|
return namedGraph{id: g.id, Graph: g.Graph}
|
||||||
}
|
}
|
||||||
|
|
||||||
func undirectedSubGraphFrom(g []set, s map[int][]set) graph.Graph {
|
func undirectedSubGraphFrom(g []intset, s map[int][]intset) graph.Graph {
|
||||||
var base int
|
var base int
|
||||||
subs := make(map[int]subGraph)
|
subs := make(map[int]subGraph)
|
||||||
for i, sg := range s {
|
for i, sg := range s {
|
||||||
@@ -1264,7 +1264,7 @@ var encodeTests = []struct {
|
|||||||
|
|
||||||
// Handling subgraphs.
|
// Handling subgraphs.
|
||||||
{
|
{
|
||||||
g: undirectedSubGraphFrom(pageRankGraph, map[int][]set{2: powerMethodGraph}),
|
g: undirectedSubGraphFrom(pageRankGraph, map[int][]intset{2: powerMethodGraph}),
|
||||||
|
|
||||||
want: `graph {
|
want: `graph {
|
||||||
// Node definitions.
|
// Node definitions.
|
||||||
@@ -1315,7 +1315,7 @@ var encodeTests = []struct {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "H",
|
name: "H",
|
||||||
g: undirectedSubGraphFrom(pageRankGraph, map[int][]set{1: powerMethodGraph}),
|
g: undirectedSubGraphFrom(pageRankGraph, map[int][]intset{1: powerMethodGraph}),
|
||||||
strict: true,
|
strict: true,
|
||||||
|
|
||||||
want: `strict graph H {
|
want: `strict graph H {
|
||||||
|
@@ -16,3 +16,12 @@ import "unsafe"
|
|||||||
func same(a, b Nodes) bool {
|
func same(a, b Nodes) bool {
|
||||||
return *(*uintptr)(unsafe.Pointer(&a)) == *(*uintptr)(unsafe.Pointer(&b))
|
return *(*uintptr)(unsafe.Pointer(&a)) == *(*uintptr)(unsafe.Pointer(&b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// intsSame determines whether two sets are backed by the same store. In the
|
||||||
|
// current implementation using hash maps it makes use of the fact that
|
||||||
|
// hash maps are passed as a pointer to a runtime Hmap struct. A map is
|
||||||
|
// not seen by the runtime as a pointer though, so we use unsafe to get
|
||||||
|
// the maps' pointer values to compare.
|
||||||
|
func intsSame(a, b Ints) bool {
|
||||||
|
return *(*uintptr)(unsafe.Pointer(&a)) == *(*uintptr)(unsafe.Pointer(&b))
|
||||||
|
}
|
||||||
|
@@ -16,3 +16,12 @@ import "reflect"
|
|||||||
func same(a, b Nodes) bool {
|
func same(a, b Nodes) bool {
|
||||||
return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer()
|
return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// intsSame determines whether two sets are backed by the same store. In the
|
||||||
|
// current implementation using hash maps it makes use of the fact that
|
||||||
|
// hash maps are passed as a pointer to a runtime Hmap struct. A map is
|
||||||
|
// not seen by the runtime as a pointer though, so we use reflect to get
|
||||||
|
// the maps' pointer values to compare.
|
||||||
|
func intsSame(a, b Ints) bool {
|
||||||
|
return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer()
|
||||||
|
}
|
||||||
|
@@ -34,6 +34,26 @@ func (s Ints) Count() int {
|
|||||||
return len(s)
|
return len(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IntsEqual reports set equality between the parameters. Sets are equal if
|
||||||
|
// and only if they have the same elements.
|
||||||
|
func IntsEqual(a, b Ints) bool {
|
||||||
|
if intsSame(a, b) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for e := range a {
|
||||||
|
if _, ok := b[e]; !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Nodes is a set of nodes keyed in their integer identifiers.
|
// Nodes is a set of nodes keyed in their integer identifiers.
|
||||||
type Nodes map[int]graph.Node
|
type Nodes map[int]graph.Node
|
||||||
|
|
||||||
|
@@ -8,10 +8,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"golang.org/x/tools/container/intsets"
|
|
||||||
|
|
||||||
"gonum.org/v1/gonum/graph"
|
"gonum.org/v1/gonum/graph"
|
||||||
"gonum.org/v1/gonum/graph/internal/ordered"
|
"gonum.org/v1/gonum/graph/internal/ordered"
|
||||||
|
"gonum.org/v1/gonum/graph/internal/set"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Unorderable is an error containing sets of unorderable graph.Nodes.
|
// Unorderable is an error containing sets of unorderable graph.Nodes.
|
||||||
@@ -122,7 +121,7 @@ func tarjanSCCstabilized(g graph.Directed, order func([]graph.Node)) [][]graph.N
|
|||||||
|
|
||||||
indexTable: make(map[int]int, len(nodes)),
|
indexTable: make(map[int]int, len(nodes)),
|
||||||
lowLink: make(map[int]int, len(nodes)),
|
lowLink: make(map[int]int, len(nodes)),
|
||||||
onStack: &intsets.Sparse{},
|
onStack: make(set.Ints),
|
||||||
}
|
}
|
||||||
for _, v := range nodes {
|
for _, v := range nodes {
|
||||||
if t.indexTable[v.ID()] == 0 {
|
if t.indexTable[v.ID()] == 0 {
|
||||||
@@ -143,7 +142,7 @@ type tarjan struct {
|
|||||||
index int
|
index int
|
||||||
indexTable map[int]int
|
indexTable map[int]int
|
||||||
lowLink map[int]int
|
lowLink map[int]int
|
||||||
onStack *intsets.Sparse
|
onStack set.Ints
|
||||||
|
|
||||||
stack []graph.Node
|
stack []graph.Node
|
||||||
|
|
||||||
@@ -160,7 +159,7 @@ func (t *tarjan) strongconnect(v graph.Node) {
|
|||||||
t.indexTable[vID] = t.index
|
t.indexTable[vID] = t.index
|
||||||
t.lowLink[vID] = t.index
|
t.lowLink[vID] = t.index
|
||||||
t.stack = append(t.stack, v)
|
t.stack = append(t.stack, v)
|
||||||
t.onStack.Insert(vID)
|
t.onStack.Add(vID)
|
||||||
|
|
||||||
// Consider successors of v.
|
// Consider successors of v.
|
||||||
for _, w := range t.succ(v) {
|
for _, w := range t.succ(v) {
|
||||||
|
@@ -6,10 +6,9 @@
|
|||||||
package traverse // import "gonum.org/v1/gonum/graph/traverse"
|
package traverse // import "gonum.org/v1/gonum/graph/traverse"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"golang.org/x/tools/container/intsets"
|
|
||||||
|
|
||||||
"gonum.org/v1/gonum/graph"
|
"gonum.org/v1/gonum/graph"
|
||||||
"gonum.org/v1/gonum/graph/internal/linear"
|
"gonum.org/v1/gonum/graph/internal/linear"
|
||||||
|
"gonum.org/v1/gonum/graph/internal/set"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BreadthFirst implements stateful breadth-first graph traversal.
|
// BreadthFirst implements stateful breadth-first graph traversal.
|
||||||
@@ -17,7 +16,7 @@ type BreadthFirst struct {
|
|||||||
EdgeFilter func(graph.Edge) bool
|
EdgeFilter func(graph.Edge) bool
|
||||||
Visit func(u, v graph.Node)
|
Visit func(u, v graph.Node)
|
||||||
queue linear.NodeQueue
|
queue linear.NodeQueue
|
||||||
visited *intsets.Sparse
|
visited set.Ints
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk performs a breadth-first traversal of the graph g starting from the given node,
|
// Walk performs a breadth-first traversal of the graph g starting from the given node,
|
||||||
@@ -27,10 +26,10 @@ type BreadthFirst struct {
|
|||||||
// non-nil, it is called with the nodes joined by each followed edge.
|
// non-nil, it is called with the nodes joined by each followed edge.
|
||||||
func (b *BreadthFirst) Walk(g graph.Graph, from graph.Node, until func(n graph.Node, d int) bool) graph.Node {
|
func (b *BreadthFirst) Walk(g graph.Graph, from graph.Node, until func(n graph.Node, d int) bool) graph.Node {
|
||||||
if b.visited == nil {
|
if b.visited == nil {
|
||||||
b.visited = &intsets.Sparse{}
|
b.visited = make(set.Ints)
|
||||||
}
|
}
|
||||||
b.queue.Enqueue(from)
|
b.queue.Enqueue(from)
|
||||||
b.visited.Insert(from.ID())
|
b.visited.Add(from.ID())
|
||||||
|
|
||||||
var (
|
var (
|
||||||
depth int
|
depth int
|
||||||
@@ -52,7 +51,7 @@ func (b *BreadthFirst) Walk(g graph.Graph, from graph.Node, until func(n graph.N
|
|||||||
if b.Visit != nil {
|
if b.Visit != nil {
|
||||||
b.Visit(t, n)
|
b.Visit(t, n)
|
||||||
}
|
}
|
||||||
b.visited.Insert(n.ID())
|
b.visited.Add(n.ID())
|
||||||
children++
|
children++
|
||||||
b.queue.Enqueue(n)
|
b.queue.Enqueue(n)
|
||||||
}
|
}
|
||||||
@@ -93,15 +92,13 @@ func (b *BreadthFirst) WalkAll(g graph.Undirected, before, after func(), during
|
|||||||
|
|
||||||
// Visited returned whether the node n was visited during a traverse.
|
// Visited returned whether the node n was visited during a traverse.
|
||||||
func (b *BreadthFirst) Visited(n graph.Node) bool {
|
func (b *BreadthFirst) Visited(n graph.Node) bool {
|
||||||
return b.visited != nil && b.visited.Has(n.ID())
|
return b.visited.Has(n.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset resets the state of the traverser for reuse.
|
// Reset resets the state of the traverser for reuse.
|
||||||
func (b *BreadthFirst) Reset() {
|
func (b *BreadthFirst) Reset() {
|
||||||
b.queue.Reset()
|
b.queue.Reset()
|
||||||
if b.visited != nil {
|
b.visited = nil
|
||||||
b.visited.Clear()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DepthFirst implements stateful depth-first graph traversal.
|
// DepthFirst implements stateful depth-first graph traversal.
|
||||||
@@ -109,7 +106,7 @@ type DepthFirst struct {
|
|||||||
EdgeFilter func(graph.Edge) bool
|
EdgeFilter func(graph.Edge) bool
|
||||||
Visit func(u, v graph.Node)
|
Visit func(u, v graph.Node)
|
||||||
stack linear.NodeStack
|
stack linear.NodeStack
|
||||||
visited *intsets.Sparse
|
visited set.Ints
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk performs a depth-first traversal of the graph g starting from the given node,
|
// Walk performs a depth-first traversal of the graph g starting from the given node,
|
||||||
@@ -119,10 +116,10 @@ type DepthFirst struct {
|
|||||||
// is called with the nodes joined by each followed edge.
|
// is called with the nodes joined by each followed edge.
|
||||||
func (d *DepthFirst) Walk(g graph.Graph, from graph.Node, until func(graph.Node) bool) graph.Node {
|
func (d *DepthFirst) Walk(g graph.Graph, from graph.Node, until func(graph.Node) bool) graph.Node {
|
||||||
if d.visited == nil {
|
if d.visited == nil {
|
||||||
d.visited = &intsets.Sparse{}
|
d.visited = make(set.Ints)
|
||||||
}
|
}
|
||||||
d.stack.Push(from)
|
d.stack.Push(from)
|
||||||
d.visited.Insert(from.ID())
|
d.visited.Add(from.ID())
|
||||||
|
|
||||||
for d.stack.Len() > 0 {
|
for d.stack.Len() > 0 {
|
||||||
t := d.stack.Pop()
|
t := d.stack.Pop()
|
||||||
@@ -139,7 +136,7 @@ func (d *DepthFirst) Walk(g graph.Graph, from graph.Node, until func(graph.Node)
|
|||||||
if d.Visit != nil {
|
if d.Visit != nil {
|
||||||
d.Visit(t, n)
|
d.Visit(t, n)
|
||||||
}
|
}
|
||||||
d.visited.Insert(n.ID())
|
d.visited.Add(n.ID())
|
||||||
d.stack.Push(n)
|
d.stack.Push(n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,13 +171,11 @@ func (d *DepthFirst) WalkAll(g graph.Undirected, before, after func(), during fu
|
|||||||
|
|
||||||
// Visited returned whether the node n was visited during a traverse.
|
// Visited returned whether the node n was visited during a traverse.
|
||||||
func (d *DepthFirst) Visited(n graph.Node) bool {
|
func (d *DepthFirst) Visited(n graph.Node) bool {
|
||||||
return d.visited != nil && d.visited.Has(n.ID())
|
return d.visited.Has(n.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset resets the state of the traverser for reuse.
|
// Reset resets the state of the traverser for reuse.
|
||||||
func (d *DepthFirst) Reset() {
|
func (d *DepthFirst) Reset() {
|
||||||
d.stack = d.stack[:0]
|
d.stack = d.stack[:0]
|
||||||
if d.visited != nil {
|
d.visited = nil
|
||||||
d.visited.Clear()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
// batageljZaversnikGraph is the example graph from
|
// batageljZaversnikGraph is the example graph from
|
||||||
// figure 1 of http://arxiv.org/abs/cs/0310049v1
|
// figure 1 of http://arxiv.org/abs/cs/0310049v1
|
||||||
batageljZaversnikGraph = []set{
|
batageljZaversnikGraph = []intset{
|
||||||
0: nil,
|
0: nil,
|
||||||
|
|
||||||
1: linksTo(2, 3),
|
1: linksTo(2, 3),
|
||||||
@@ -48,7 +48,7 @@ var (
|
|||||||
|
|
||||||
// wpBronKerboschGraph is the example given in the Bron-Kerbosch article on wikipedia (renumbered).
|
// wpBronKerboschGraph is the example given in the Bron-Kerbosch article on wikipedia (renumbered).
|
||||||
// http://en.wikipedia.org/w/index.php?title=Bron%E2%80%93Kerbosch_algorithm&oldid=656805858
|
// http://en.wikipedia.org/w/index.php?title=Bron%E2%80%93Kerbosch_algorithm&oldid=656805858
|
||||||
wpBronKerboschGraph = []set{
|
wpBronKerboschGraph = []intset{
|
||||||
0: linksTo(1, 4),
|
0: linksTo(1, 4),
|
||||||
1: linksTo(2, 4),
|
1: linksTo(2, 4),
|
||||||
2: linksTo(3),
|
2: linksTo(3),
|
||||||
@@ -59,7 +59,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var breadthFirstTests = []struct {
|
var breadthFirstTests = []struct {
|
||||||
g []set
|
g []intset
|
||||||
from graph.Node
|
from graph.Node
|
||||||
edge func(graph.Edge) bool
|
edge func(graph.Edge) bool
|
||||||
until func(graph.Node, int) bool
|
until func(graph.Node, int) bool
|
||||||
@@ -171,7 +171,7 @@ func TestBreadthFirst(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var depthFirstTests = []struct {
|
var depthFirstTests = []struct {
|
||||||
g []set
|
g []intset
|
||||||
from graph.Node
|
from graph.Node
|
||||||
edge func(graph.Edge) bool
|
edge func(graph.Edge) bool
|
||||||
until func(graph.Node) bool
|
until func(graph.Node) bool
|
||||||
@@ -254,7 +254,7 @@ func TestDepthFirst(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var walkAllTests = []struct {
|
var walkAllTests = []struct {
|
||||||
g []set
|
g []intset
|
||||||
edge func(graph.Edge) bool
|
edge func(graph.Edge) bool
|
||||||
want [][]int
|
want [][]int
|
||||||
}{
|
}{
|
||||||
@@ -342,14 +342,14 @@ func TestWalkAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set is an integer set.
|
// intset is an integer set.
|
||||||
type set map[int]struct{}
|
type intset map[int]struct{}
|
||||||
|
|
||||||
func linksTo(i ...int) set {
|
func linksTo(i ...int) intset {
|
||||||
if len(i) == 0 {
|
if len(i) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
s := make(set)
|
s := make(intset)
|
||||||
for _, v := range i {
|
for _, v := range i {
|
||||||
s[v] = struct{}{}
|
s[v] = struct{}{}
|
||||||
}
|
}
|
||||||
@@ -378,8 +378,8 @@ func benchmarkWalkAllBreadthFirst(b *testing.B, g graph.Undirected) {
|
|||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
bft.WalkAll(g, nil, nil, nil)
|
bft.WalkAll(g, nil, nil, nil)
|
||||||
}
|
}
|
||||||
if bft.visited.Len() != n {
|
if len(bft.visited) != n {
|
||||||
b.Fatalf("unexpected number of nodes visited: want: %d got %d", n, bft.visited.Len())
|
b.Fatalf("unexpected number of nodes visited: want: %d got %d", n, len(bft.visited))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,8 +409,8 @@ func benchmarkWalkAllDepthFirst(b *testing.B, g graph.Undirected) {
|
|||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
dft.WalkAll(g, nil, nil, nil)
|
dft.WalkAll(g, nil, nil, nil)
|
||||||
}
|
}
|
||||||
if dft.visited.Len() != n {
|
if len(dft.visited) != n {
|
||||||
b.Fatalf("unexpected number of nodes visited: want: %d got %d", n, dft.visited.Len())
|
b.Fatalf("unexpected number of nodes visited: want: %d got %d", n, len(dft.visited))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,10 +4,6 @@
|
|||||||
|
|
||||||
package graph
|
package graph
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/tools/container/intsets"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Undirect converts a directed graph to an undirected graph, resolving
|
// Undirect converts a directed graph to an undirected graph, resolving
|
||||||
// edge weight conflicts.
|
// edge weight conflicts.
|
||||||
type Undirect struct {
|
type Undirect struct {
|
||||||
@@ -47,20 +43,18 @@ func (g Undirect) Nodes() []Node { return g.G.Nodes() }
|
|||||||
|
|
||||||
// From returns all nodes in g that can be reached directly from u.
|
// From returns all nodes in g that can be reached directly from u.
|
||||||
func (g Undirect) From(u Node) []Node {
|
func (g Undirect) From(u Node) []Node {
|
||||||
var (
|
var nodes []Node
|
||||||
nodes []Node
|
seen := make(map[int]struct{})
|
||||||
seen intsets.Sparse
|
|
||||||
)
|
|
||||||
for _, n := range g.G.From(u) {
|
for _, n := range g.G.From(u) {
|
||||||
seen.Insert(n.ID())
|
seen[n.ID()] = struct{}{}
|
||||||
nodes = append(nodes, n)
|
nodes = append(nodes, n)
|
||||||
}
|
}
|
||||||
for _, n := range g.G.To(u) {
|
for _, n := range g.G.To(u) {
|
||||||
id := n.ID()
|
id := n.ID()
|
||||||
if seen.Has(id) {
|
if _, ok := seen[id]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
seen.Insert(id)
|
seen[n.ID()] = struct{}{}
|
||||||
nodes = append(nodes, n)
|
nodes = append(nodes, n)
|
||||||
}
|
}
|
||||||
return nodes
|
return nodes
|
||||||
|
Reference in New Issue
Block a user