1. update clientset, deepcopy using code-generator
2. add a dummy file tools.go to force "go mod vendor" to see code-generator as dependencies 3. add a script to update CRD 4. add a README to document CRD updating steps run go mod tidy update README
This commit is contained in:
1
vendor/gonum.org/v1/gonum/graph/.gitignore
generated
vendored
Normal file
1
vendor/gonum.org/v1/gonum/graph/.gitignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
test.out
|
3
vendor/gonum.org/v1/gonum/graph/README.md
generated
vendored
Normal file
3
vendor/gonum.org/v1/gonum/graph/README.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Gonum graph [](https://godoc.org/gonum.org/v1/gonum/graph)
|
||||
|
||||
This is a generalized graph package for the Go language.
|
9
vendor/gonum.org/v1/gonum/graph/doc.go
generated
vendored
Normal file
9
vendor/gonum.org/v1/gonum/graph/doc.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package graph defines graph interfaces.
|
||||
//
|
||||
// Routines to test contract compliance by user implemented graph types
|
||||
// are available in gonum.org/v1/gonum/graph/testgraph.
|
||||
package graph // import "gonum.org/v1/gonum/graph"
|
282
vendor/gonum.org/v1/gonum/graph/graph.go
generated
vendored
Normal file
282
vendor/gonum.org/v1/gonum/graph/graph.go
generated
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package graph
|
||||
|
||||
// Node is a graph node. It returns a graph-unique integer ID.
|
||||
type Node interface {
|
||||
ID() int64
|
||||
}
|
||||
|
||||
// Edge is a graph edge. In directed graphs, the direction of the
|
||||
// edge is given from -> to, otherwise the edge is semantically
|
||||
// unordered.
|
||||
type Edge interface {
|
||||
// From returns the from node of the edge.
|
||||
From() Node
|
||||
|
||||
// To returns the to node of the edge.
|
||||
To() Node
|
||||
|
||||
// ReversedEdge returns an edge that has
|
||||
// the end points of the receiver swapped.
|
||||
ReversedEdge() Edge
|
||||
}
|
||||
|
||||
// WeightedEdge is a weighted graph edge. In directed graphs, the direction
|
||||
// of the edge is given from -> to, otherwise the edge is semantically
|
||||
// unordered.
|
||||
type WeightedEdge interface {
|
||||
Edge
|
||||
Weight() float64
|
||||
}
|
||||
|
||||
// Graph is a generalized graph.
|
||||
type Graph interface {
|
||||
// Node returns the node with the given ID if it exists
|
||||
// in the graph, and nil otherwise.
|
||||
Node(id int64) Node
|
||||
|
||||
// Nodes returns all the nodes in the graph.
|
||||
//
|
||||
// Nodes must not return nil.
|
||||
Nodes() Nodes
|
||||
|
||||
// From returns all nodes that can be reached directly
|
||||
// from the node with the given ID.
|
||||
//
|
||||
// From must not return nil.
|
||||
From(id int64) Nodes
|
||||
|
||||
// HasEdgeBetween returns whether an edge exists between
|
||||
// nodes with IDs xid and yid without considering direction.
|
||||
HasEdgeBetween(xid, yid int64) bool
|
||||
|
||||
// Edge returns the edge from u to v, with IDs uid and vid,
|
||||
// if such an edge exists and nil otherwise. The node v
|
||||
// must be directly reachable from u as defined by the
|
||||
// From method.
|
||||
Edge(uid, vid int64) Edge
|
||||
}
|
||||
|
||||
// Weighted is a weighted graph.
|
||||
type Weighted interface {
|
||||
Graph
|
||||
|
||||
// WeightedEdge returns the weighted edge from u to v
|
||||
// with IDs uid and vid if such an edge exists and
|
||||
// nil otherwise. The node v must be directly
|
||||
// reachable from u as defined by the From method.
|
||||
WeightedEdge(uid, vid int64) WeightedEdge
|
||||
|
||||
// Weight returns the weight for the edge between
|
||||
// x and y with IDs xid and yid if Edge(xid, yid)
|
||||
// returns a non-nil Edge.
|
||||
// If x and y are the same node or there is no
|
||||
// joining edge between the two nodes the weight
|
||||
// value returned is implementation dependent.
|
||||
// Weight returns true if an edge exists between
|
||||
// x and y or if x and y have the same ID, false
|
||||
// otherwise.
|
||||
Weight(xid, yid int64) (w float64, ok bool)
|
||||
}
|
||||
|
||||
// Undirected is an undirected graph.
|
||||
type Undirected interface {
|
||||
Graph
|
||||
|
||||
// EdgeBetween returns the edge between nodes x and y
|
||||
// with IDs xid and yid.
|
||||
EdgeBetween(xid, yid int64) Edge
|
||||
}
|
||||
|
||||
// WeightedUndirected is a weighted undirected graph.
|
||||
type WeightedUndirected interface {
|
||||
Weighted
|
||||
|
||||
// WeightedEdgeBetween returns the edge between nodes
|
||||
// x and y with IDs xid and yid.
|
||||
WeightedEdgeBetween(xid, yid int64) WeightedEdge
|
||||
}
|
||||
|
||||
// Directed is a directed graph.
|
||||
type Directed interface {
|
||||
Graph
|
||||
|
||||
// HasEdgeFromTo returns whether an edge exists
|
||||
// in the graph from u to v with IDs uid and vid.
|
||||
HasEdgeFromTo(uid, vid int64) bool
|
||||
|
||||
// To returns all nodes that can reach directly
|
||||
// to the node with the given ID.
|
||||
//
|
||||
// To must not return nil.
|
||||
To(id int64) Nodes
|
||||
}
|
||||
|
||||
// WeightedDirected is a weighted directed graph.
|
||||
type WeightedDirected interface {
|
||||
Weighted
|
||||
|
||||
// HasEdgeFromTo returns whether an edge exists
|
||||
// in the graph from u to v with the IDs uid and
|
||||
// vid.
|
||||
HasEdgeFromTo(uid, vid int64) bool
|
||||
|
||||
// To returns all nodes that can reach directly
|
||||
// to the node with the given ID.
|
||||
//
|
||||
// To must not return nil.
|
||||
To(id int64) Nodes
|
||||
}
|
||||
|
||||
// NodeAdder is an interface for adding arbitrary nodes to a graph.
|
||||
type NodeAdder interface {
|
||||
// NewNode returns a new Node with a unique
|
||||
// arbitrary ID.
|
||||
NewNode() Node
|
||||
|
||||
// AddNode adds a node to the graph. AddNode panics if
|
||||
// the added node ID matches an existing node ID.
|
||||
AddNode(Node)
|
||||
}
|
||||
|
||||
// NodeRemover is an interface for removing nodes from a graph.
|
||||
type NodeRemover interface {
|
||||
// RemoveNode removes the node with the given ID
|
||||
// from the graph, as well as any edges attached
|
||||
// to it. If the node is not in the graph it is
|
||||
// a no-op.
|
||||
RemoveNode(id int64)
|
||||
}
|
||||
|
||||
// EdgeAdder is an interface for adding edges to a graph.
|
||||
type EdgeAdder interface {
|
||||
// NewEdge returns a new Edge from the source to the destination node.
|
||||
NewEdge(from, to Node) Edge
|
||||
|
||||
// SetEdge adds an edge from one node to another.
|
||||
// If the graph supports node addition the nodes
|
||||
// will be added if they do not exist, otherwise
|
||||
// SetEdge will panic.
|
||||
// The behavior of an EdgeAdder when the IDs
|
||||
// returned by e.From() and e.To() are equal is
|
||||
// implementation-dependent.
|
||||
// Whether e, e.From() and e.To() are stored
|
||||
// within the graph is implementation dependent.
|
||||
SetEdge(e Edge)
|
||||
}
|
||||
|
||||
// WeightedEdgeAdder is an interface for adding edges to a graph.
|
||||
type WeightedEdgeAdder interface {
|
||||
// NewWeightedEdge returns a new WeightedEdge from
|
||||
// the source to the destination node.
|
||||
NewWeightedEdge(from, to Node, weight float64) WeightedEdge
|
||||
|
||||
// SetWeightedEdge adds an edge from one node to
|
||||
// another. If the graph supports node addition
|
||||
// the nodes will be added if they do not exist,
|
||||
// otherwise SetWeightedEdge will panic.
|
||||
// The behavior of a WeightedEdgeAdder when the IDs
|
||||
// returned by e.From() and e.To() are equal is
|
||||
// implementation-dependent.
|
||||
// Whether e, e.From() and e.To() are stored
|
||||
// within the graph is implementation dependent.
|
||||
SetWeightedEdge(e WeightedEdge)
|
||||
}
|
||||
|
||||
// EdgeRemover is an interface for removing nodes from a graph.
|
||||
type EdgeRemover interface {
|
||||
// RemoveEdge removes the edge with the given end
|
||||
// IDs, leaving the terminal nodes. If the edge
|
||||
// does not exist it is a no-op.
|
||||
RemoveEdge(fid, tid int64)
|
||||
}
|
||||
|
||||
// Builder is a graph that can have nodes and edges added.
|
||||
type Builder interface {
|
||||
NodeAdder
|
||||
EdgeAdder
|
||||
}
|
||||
|
||||
// WeightedBuilder is a graph that can have nodes and weighted edges added.
|
||||
type WeightedBuilder interface {
|
||||
NodeAdder
|
||||
WeightedEdgeAdder
|
||||
}
|
||||
|
||||
// UndirectedBuilder is an undirected graph builder.
|
||||
type UndirectedBuilder interface {
|
||||
Undirected
|
||||
Builder
|
||||
}
|
||||
|
||||
// UndirectedWeightedBuilder is an undirected weighted graph builder.
|
||||
type UndirectedWeightedBuilder interface {
|
||||
Undirected
|
||||
WeightedBuilder
|
||||
}
|
||||
|
||||
// DirectedBuilder is a directed graph builder.
|
||||
type DirectedBuilder interface {
|
||||
Directed
|
||||
Builder
|
||||
}
|
||||
|
||||
// DirectedWeightedBuilder is a directed weighted graph builder.
|
||||
type DirectedWeightedBuilder interface {
|
||||
Directed
|
||||
WeightedBuilder
|
||||
}
|
||||
|
||||
// Copy copies nodes and edges as undirected edges from the source to the destination
|
||||
// without first clearing the destination. Copy will panic if a node ID in the source
|
||||
// graph matches a node ID in the destination.
|
||||
//
|
||||
// If the source is undirected and the destination is directed both directions will
|
||||
// be present in the destination after the copy is complete.
|
||||
func Copy(dst Builder, src Graph) {
|
||||
nodes := src.Nodes()
|
||||
for nodes.Next() {
|
||||
dst.AddNode(nodes.Node())
|
||||
}
|
||||
nodes.Reset()
|
||||
for nodes.Next() {
|
||||
u := nodes.Node()
|
||||
uid := u.ID()
|
||||
to := src.From(uid)
|
||||
for to.Next() {
|
||||
v := to.Node()
|
||||
dst.SetEdge(src.Edge(uid, v.ID()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CopyWeighted copies nodes and edges as undirected edges from the source to the destination
|
||||
// without first clearing the destination. Copy will panic if a node ID in the source
|
||||
// graph matches a node ID in the destination.
|
||||
//
|
||||
// If the source is undirected and the destination is directed both directions will
|
||||
// be present in the destination after the copy is complete.
|
||||
//
|
||||
// If the source is a directed graph, the destination is undirected, and a fundamental
|
||||
// cycle exists with two nodes where the edge weights differ, the resulting destination
|
||||
// graph's edge weight between those nodes is undefined. If there is a defined function
|
||||
// to resolve such conflicts, an UndirectWeighted may be used to do this.
|
||||
func CopyWeighted(dst WeightedBuilder, src Weighted) {
|
||||
nodes := src.Nodes()
|
||||
for nodes.Next() {
|
||||
dst.AddNode(nodes.Node())
|
||||
}
|
||||
nodes.Reset()
|
||||
for nodes.Next() {
|
||||
u := nodes.Node()
|
||||
uid := u.ID()
|
||||
to := src.From(uid)
|
||||
for to.Next() {
|
||||
v := to.Node()
|
||||
dst.SetWeightedEdge(src.WeightedEdge(uid, v.ID()))
|
||||
}
|
||||
}
|
||||
}
|
6
vendor/gonum.org/v1/gonum/graph/internal/linear/doc.go
generated
vendored
Normal file
6
vendor/gonum.org/v1/gonum/graph/internal/linear/doc.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright ©2017 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package linear provides common linear data structures.
|
||||
package linear // import "gonum.org/v1/gonum/graph/internal/linear"
|
73
vendor/gonum.org/v1/gonum/graph/internal/linear/linear.go
generated
vendored
Normal file
73
vendor/gonum.org/v1/gonum/graph/internal/linear/linear.go
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright ©2015 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package linear
|
||||
|
||||
import (
|
||||
"gonum.org/v1/gonum/graph"
|
||||
)
|
||||
|
||||
// NodeStack implements a LIFO stack of graph.Node.
|
||||
type NodeStack []graph.Node
|
||||
|
||||
// Len returns the number of graph.Nodes on the stack.
|
||||
func (s *NodeStack) Len() int { return len(*s) }
|
||||
|
||||
// Pop returns the last graph.Node on the stack and removes it
|
||||
// from the stack.
|
||||
func (s *NodeStack) Pop() graph.Node {
|
||||
v := *s
|
||||
v, n := v[:len(v)-1], v[len(v)-1]
|
||||
*s = v
|
||||
return n
|
||||
}
|
||||
|
||||
// Push adds the node n to the stack at the last position.
|
||||
func (s *NodeStack) Push(n graph.Node) { *s = append(*s, n) }
|
||||
|
||||
// NodeQueue implements a FIFO queue.
|
||||
type NodeQueue struct {
|
||||
head int
|
||||
data []graph.Node
|
||||
}
|
||||
|
||||
// Len returns the number of graph.Nodes in the queue.
|
||||
func (q *NodeQueue) Len() int { return len(q.data) - q.head }
|
||||
|
||||
// Enqueue adds the node n to the back of the queue.
|
||||
func (q *NodeQueue) Enqueue(n graph.Node) {
|
||||
if len(q.data) == cap(q.data) && q.head > 0 {
|
||||
l := q.Len()
|
||||
copy(q.data, q.data[q.head:])
|
||||
q.head = 0
|
||||
q.data = append(q.data[:l], n)
|
||||
} else {
|
||||
q.data = append(q.data, n)
|
||||
}
|
||||
}
|
||||
|
||||
// Dequeue returns the graph.Node at the front of the queue and
|
||||
// removes it from the queue.
|
||||
func (q *NodeQueue) Dequeue() graph.Node {
|
||||
if q.Len() == 0 {
|
||||
panic("queue: empty queue")
|
||||
}
|
||||
|
||||
var n graph.Node
|
||||
n, q.data[q.head] = q.data[q.head], nil
|
||||
q.head++
|
||||
|
||||
if q.Len() == 0 {
|
||||
q.head = 0
|
||||
q.data = q.data[:0]
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
// Reset clears the queue for reuse.
|
||||
func (q *NodeQueue) Reset() {
|
||||
q.head = 0
|
||||
q.data = q.data[:0]
|
||||
}
|
6
vendor/gonum.org/v1/gonum/graph/internal/ordered/doc.go
generated
vendored
Normal file
6
vendor/gonum.org/v1/gonum/graph/internal/ordered/doc.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright ©2017 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package ordered provides common sort ordering types.
|
||||
package ordered // import "gonum.org/v1/gonum/graph/internal/ordered"
|
93
vendor/gonum.org/v1/gonum/graph/internal/ordered/sort.go
generated
vendored
Normal file
93
vendor/gonum.org/v1/gonum/graph/internal/ordered/sort.go
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright ©2015 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ordered
|
||||
|
||||
import "gonum.org/v1/gonum/graph"
|
||||
|
||||
// ByID implements the sort.Interface sorting a slice of graph.Node
|
||||
// by ID.
|
||||
type ByID []graph.Node
|
||||
|
||||
func (n ByID) Len() int { return len(n) }
|
||||
func (n ByID) Less(i, j int) bool { return n[i].ID() < n[j].ID() }
|
||||
func (n ByID) Swap(i, j int) { n[i], n[j] = n[j], n[i] }
|
||||
|
||||
// BySliceValues implements the sort.Interface sorting a slice of
|
||||
// []int64 lexically by the values of the []int64.
|
||||
type BySliceValues [][]int64
|
||||
|
||||
func (c BySliceValues) Len() int { return len(c) }
|
||||
func (c BySliceValues) Less(i, j int) bool {
|
||||
a, b := c[i], c[j]
|
||||
l := len(a)
|
||||
if len(b) < l {
|
||||
l = len(b)
|
||||
}
|
||||
for k, v := range a[:l] {
|
||||
if v < b[k] {
|
||||
return true
|
||||
}
|
||||
if v > b[k] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return len(a) < len(b)
|
||||
}
|
||||
func (c BySliceValues) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
||||
|
||||
// BySliceIDs implements the sort.Interface sorting a slice of
|
||||
// []graph.Node lexically by the IDs of the []graph.Node.
|
||||
type BySliceIDs [][]graph.Node
|
||||
|
||||
func (c BySliceIDs) Len() int { return len(c) }
|
||||
func (c BySliceIDs) Less(i, j int) bool {
|
||||
a, b := c[i], c[j]
|
||||
l := len(a)
|
||||
if len(b) < l {
|
||||
l = len(b)
|
||||
}
|
||||
for k, v := range a[:l] {
|
||||
if v.ID() < b[k].ID() {
|
||||
return true
|
||||
}
|
||||
if v.ID() > b[k].ID() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return len(a) < len(b)
|
||||
}
|
||||
func (c BySliceIDs) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
||||
|
||||
// Int64s implements the sort.Interface sorting a slice of
|
||||
// int64.
|
||||
type Int64s []int64
|
||||
|
||||
func (s Int64s) Len() int { return len(s) }
|
||||
func (s Int64s) Less(i, j int) bool { return s[i] < s[j] }
|
||||
func (s Int64s) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// Reverse reverses the order of nodes.
|
||||
func Reverse(nodes []graph.Node) {
|
||||
for i, j := 0, len(nodes)-1; i < j; i, j = i+1, j-1 {
|
||||
nodes[i], nodes[j] = nodes[j], nodes[i]
|
||||
}
|
||||
}
|
||||
|
||||
// LinesByIDs implements the sort.Interface sorting a slice of graph.LinesByIDs
|
||||
// lexically by the From IDs, then by the To IDs, finally by the Line IDs.
|
||||
type LinesByIDs []graph.Line
|
||||
|
||||
func (n LinesByIDs) Len() int { return len(n) }
|
||||
func (n LinesByIDs) Less(i, j int) bool {
|
||||
a, b := n[i], n[j]
|
||||
if a.From().ID() != b.From().ID() {
|
||||
return a.From().ID() < b.From().ID()
|
||||
}
|
||||
if a.To().ID() != b.To().ID() {
|
||||
return a.To().ID() < b.To().ID()
|
||||
}
|
||||
return n[i].ID() < n[j].ID()
|
||||
}
|
||||
func (n LinesByIDs) Swap(i, j int) { n[i], n[j] = n[j], n[i] }
|
6
vendor/gonum.org/v1/gonum/graph/internal/set/doc.go
generated
vendored
Normal file
6
vendor/gonum.org/v1/gonum/graph/internal/set/doc.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright ©2017 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package set provides integer and graph.Node sets.
|
||||
package set // import "gonum.org/v1/gonum/graph/internal/set"
|
36
vendor/gonum.org/v1/gonum/graph/internal/set/same.go
generated
vendored
Normal file
36
vendor/gonum.org/v1/gonum/graph/internal/set/same.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !appengine,!safe
|
||||
|
||||
package set
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// same 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 same(a, b Nodes) bool {
|
||||
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))
|
||||
}
|
||||
|
||||
// int64sSame 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 int64sSame(a, b Int64s) bool {
|
||||
return *(*uintptr)(unsafe.Pointer(&a)) == *(*uintptr)(unsafe.Pointer(&b))
|
||||
}
|
36
vendor/gonum.org/v1/gonum/graph/internal/set/same_appengine.go
generated
vendored
Normal file
36
vendor/gonum.org/v1/gonum/graph/internal/set/same_appengine.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build appengine safe
|
||||
|
||||
package set
|
||||
|
||||
import "reflect"
|
||||
|
||||
// same 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 same(a, b Nodes) bool {
|
||||
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()
|
||||
}
|
||||
|
||||
// int64sSame 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 int64sSame(a, b Int64s) bool {
|
||||
return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer()
|
||||
}
|
228
vendor/gonum.org/v1/gonum/graph/internal/set/set.go
generated
vendored
Normal file
228
vendor/gonum.org/v1/gonum/graph/internal/set/set.go
generated
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package set
|
||||
|
||||
import "gonum.org/v1/gonum/graph"
|
||||
|
||||
// Ints is a set of int identifiers.
|
||||
type Ints map[int]struct{}
|
||||
|
||||
// The simple accessor methods for Ints are provided to allow ease of
|
||||
// implementation change should the need arise.
|
||||
|
||||
// Add inserts an element into the set.
|
||||
func (s Ints) Add(e int) {
|
||||
s[e] = struct{}{}
|
||||
}
|
||||
|
||||
// Has reports the existence of the element in the set.
|
||||
func (s Ints) Has(e int) bool {
|
||||
_, ok := s[e]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Remove deletes the specified element from the set.
|
||||
func (s Ints) Remove(e int) {
|
||||
delete(s, e)
|
||||
}
|
||||
|
||||
// Count reports the number of elements stored in the set.
|
||||
func (s Ints) Count() int {
|
||||
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
|
||||
}
|
||||
|
||||
// Int64s is a set of int64 identifiers.
|
||||
type Int64s map[int64]struct{}
|
||||
|
||||
// The simple accessor methods for Ints are provided to allow ease of
|
||||
// implementation change should the need arise.
|
||||
|
||||
// Add inserts an element into the set.
|
||||
func (s Int64s) Add(e int64) {
|
||||
s[e] = struct{}{}
|
||||
}
|
||||
|
||||
// Has reports the existence of the element in the set.
|
||||
func (s Int64s) Has(e int64) bool {
|
||||
_, ok := s[e]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Remove deletes the specified element from the set.
|
||||
func (s Int64s) Remove(e int64) {
|
||||
delete(s, e)
|
||||
}
|
||||
|
||||
// Count reports the number of elements stored in the set.
|
||||
func (s Int64s) Count() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
// Int64sEqual reports set equality between the parameters. Sets are equal if
|
||||
// and only if they have the same elements.
|
||||
func Int64sEqual(a, b Int64s) bool {
|
||||
if int64sSame(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.
|
||||
type Nodes map[int64]graph.Node
|
||||
|
||||
// NewNodes returns a new Nodes.
|
||||
func NewNodes() Nodes {
|
||||
return make(Nodes)
|
||||
}
|
||||
|
||||
// NewNodes returns a new Nodes with the given size hint, n.
|
||||
func NewNodesSize(n int) Nodes {
|
||||
return make(Nodes, n)
|
||||
}
|
||||
|
||||
// The simple accessor methods for Nodes are provided to allow ease of
|
||||
// implementation change should the need arise.
|
||||
|
||||
// Add inserts an element into the set.
|
||||
func (s Nodes) Add(n graph.Node) {
|
||||
s[n.ID()] = n
|
||||
}
|
||||
|
||||
// Remove deletes the specified element from the set.
|
||||
func (s Nodes) Remove(e graph.Node) {
|
||||
delete(s, e.ID())
|
||||
}
|
||||
|
||||
// Count returns the number of element in the set.
|
||||
func (s Nodes) Count() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
// Has reports the existence of the elements in the set.
|
||||
func (s Nodes) Has(n graph.Node) bool {
|
||||
_, ok := s[n.ID()]
|
||||
return ok
|
||||
}
|
||||
|
||||
// CloneNodes returns a clone of src.
|
||||
func CloneNodes(src Nodes) Nodes {
|
||||
dst := make(Nodes, len(src))
|
||||
for e, n := range src {
|
||||
dst[e] = n
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Equal reports set equality between the parameters. Sets are equal if
|
||||
// and only if they have the same elements.
|
||||
func Equal(a, b Nodes) bool {
|
||||
if same(a, b) {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
|
||||
for e := range a {
|
||||
if _, ok := b[e]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// UnionOfNodes returns the union of a and b.
|
||||
//
|
||||
// The union of two sets, a and b, is the set containing all the
|
||||
// elements of each, for instance:
|
||||
//
|
||||
// {a,b,c} UNION {d,e,f} = {a,b,c,d,e,f}
|
||||
//
|
||||
// Since sets may not have repetition, unions of two sets that overlap
|
||||
// do not contain repeat elements, that is:
|
||||
//
|
||||
// {a,b,c} UNION {b,c,d} = {a,b,c,d}
|
||||
//
|
||||
func UnionOfNodes(a, b Nodes) Nodes {
|
||||
if same(a, b) {
|
||||
return CloneNodes(a)
|
||||
}
|
||||
|
||||
dst := make(Nodes)
|
||||
for e, n := range a {
|
||||
dst[e] = n
|
||||
}
|
||||
for e, n := range b {
|
||||
dst[e] = n
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntersectionOfNodes returns the intersection of a and b.
|
||||
//
|
||||
// The intersection of two sets, a and b, is the set containing all
|
||||
// the elements shared between the two sets, for instance:
|
||||
//
|
||||
// {a,b,c} INTERSECT {b,c,d} = {b,c}
|
||||
//
|
||||
// The intersection between a set and itself is itself, and thus
|
||||
// effectively a copy operation:
|
||||
//
|
||||
// {a,b,c} INTERSECT {a,b,c} = {a,b,c}
|
||||
//
|
||||
// The intersection between two sets that share no elements is the empty
|
||||
// set:
|
||||
//
|
||||
// {a,b,c} INTERSECT {d,e,f} = {}
|
||||
//
|
||||
func IntersectionOfNodes(a, b Nodes) Nodes {
|
||||
if same(a, b) {
|
||||
return CloneNodes(a)
|
||||
}
|
||||
dst := make(Nodes)
|
||||
if len(a) > len(b) {
|
||||
a, b = b, a
|
||||
}
|
||||
for e, n := range a {
|
||||
if _, ok := b[e]; ok {
|
||||
dst[e] = n
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
54
vendor/gonum.org/v1/gonum/graph/internal/uid/uid.go
generated
vendored
Normal file
54
vendor/gonum.org/v1/gonum/graph/internal/uid/uid.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package uid implements unique ID provision for graphs.
|
||||
package uid
|
||||
|
||||
import "gonum.org/v1/gonum/graph/internal/set"
|
||||
|
||||
// Max is the maximum value of int64.
|
||||
const Max = int64(^uint64(0) >> 1)
|
||||
|
||||
// Set implements available ID storage.
|
||||
type Set struct {
|
||||
maxID int64
|
||||
used, free set.Int64s
|
||||
}
|
||||
|
||||
// NewSet returns a new Set. The returned value should not be passed except by pointer.
|
||||
func NewSet() Set {
|
||||
return Set{maxID: -1, used: make(set.Int64s), free: make(set.Int64s)}
|
||||
}
|
||||
|
||||
// NewID returns a new unique ID. The ID returned is not considered used
|
||||
// until passed in a call to use.
|
||||
func (s *Set) NewID() int64 {
|
||||
for id := range s.free {
|
||||
return id
|
||||
}
|
||||
if s.maxID != Max {
|
||||
return s.maxID + 1
|
||||
}
|
||||
for id := int64(0); id <= s.maxID+1; id++ {
|
||||
if !s.used.Has(id) {
|
||||
return id
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// Use adds the id to the used IDs in the Set.
|
||||
func (s *Set) Use(id int64) {
|
||||
s.used.Add(id)
|
||||
s.free.Remove(id)
|
||||
if id > s.maxID {
|
||||
s.maxID = id
|
||||
}
|
||||
}
|
||||
|
||||
// Release frees the id for reuse.
|
||||
func (s *Set) Release(id int64) {
|
||||
s.free.Add(id)
|
||||
s.used.Remove(id)
|
||||
}
|
9
vendor/gonum.org/v1/gonum/graph/iterator/doc.go
generated
vendored
Normal file
9
vendor/gonum.org/v1/gonum/graph/iterator/doc.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright ©2018 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package iterator provides node, edge and line iterators.
|
||||
//
|
||||
// The iterators provided satisfy the graph.Nodes, graph.Edges and
|
||||
// graph.Lines interfaces.
|
||||
package iterator
|
131
vendor/gonum.org/v1/gonum/graph/iterator/edges.go
generated
vendored
Normal file
131
vendor/gonum.org/v1/gonum/graph/iterator/edges.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright ©2018 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package iterator
|
||||
|
||||
import "gonum.org/v1/gonum/graph"
|
||||
|
||||
// OrderedEdges implements the graph.Edges and graph.EdgeSlicer interfaces.
|
||||
// The iteration order of OrderedEdges is the order of edges passed to
|
||||
// NewEdgeIterator.
|
||||
type OrderedEdges struct {
|
||||
idx int
|
||||
edges []graph.Edge
|
||||
}
|
||||
|
||||
// NewOrderedEdges returns an OrderedEdges initialized with the provided edges.
|
||||
func NewOrderedEdges(edges []graph.Edge) *OrderedEdges {
|
||||
return &OrderedEdges{idx: -1, edges: edges}
|
||||
}
|
||||
|
||||
// Len returns the remaining number of edges to be iterated over.
|
||||
func (e *OrderedEdges) Len() int {
|
||||
if e.idx >= len(e.edges) {
|
||||
return 0
|
||||
}
|
||||
if e.idx <= 0 {
|
||||
return len(e.edges)
|
||||
}
|
||||
return len(e.edges[e.idx:])
|
||||
}
|
||||
|
||||
// Next returns whether the next call of Edge will return a valid edge.
|
||||
func (e *OrderedEdges) Next() bool {
|
||||
if uint(e.idx)+1 < uint(len(e.edges)) {
|
||||
e.idx++
|
||||
return true
|
||||
}
|
||||
e.idx = len(e.edges)
|
||||
return false
|
||||
}
|
||||
|
||||
// Edge returns the current edge of the iterator. Next must have been
|
||||
// called prior to a call to Edge.
|
||||
func (e *OrderedEdges) Edge() graph.Edge {
|
||||
if e.idx >= len(e.edges) || e.idx < 0 {
|
||||
return nil
|
||||
}
|
||||
return e.edges[e.idx]
|
||||
}
|
||||
|
||||
// EdgeSlice returns all the remaining edges in the iterator and advances
|
||||
// the iterator.
|
||||
func (e *OrderedEdges) EdgeSlice() []graph.Edge {
|
||||
if e.idx >= len(e.edges) {
|
||||
return nil
|
||||
}
|
||||
idx := e.idx
|
||||
if idx == -1 {
|
||||
idx = 0
|
||||
}
|
||||
e.idx = len(e.edges)
|
||||
return e.edges[idx:]
|
||||
}
|
||||
|
||||
// Reset returns the iterator to its initial state.
|
||||
func (e *OrderedEdges) Reset() {
|
||||
e.idx = -1
|
||||
}
|
||||
|
||||
// OrderedWeightedEdges implements the graph.Edges and graph.EdgeSlicer interfaces.
|
||||
// The iteration order of OrderedWeightedEdges is the order of edges passed to
|
||||
// NewEdgeIterator.
|
||||
type OrderedWeightedEdges struct {
|
||||
idx int
|
||||
edges []graph.WeightedEdge
|
||||
}
|
||||
|
||||
// NewOrderedWeightedEdges returns an OrderedWeightedEdges initialized with the provided edges.
|
||||
func NewOrderedWeightedEdges(edges []graph.WeightedEdge) *OrderedWeightedEdges {
|
||||
return &OrderedWeightedEdges{idx: -1, edges: edges}
|
||||
}
|
||||
|
||||
// Len returns the remaining number of edges to be iterated over.
|
||||
func (e *OrderedWeightedEdges) Len() int {
|
||||
if e.idx >= len(e.edges) {
|
||||
return 0
|
||||
}
|
||||
if e.idx <= 0 {
|
||||
return len(e.edges)
|
||||
}
|
||||
return len(e.edges[e.idx:])
|
||||
}
|
||||
|
||||
// Next returns whether the next call of WeightedEdge will return a valid edge.
|
||||
func (e *OrderedWeightedEdges) Next() bool {
|
||||
if uint(e.idx)+1 < uint(len(e.edges)) {
|
||||
e.idx++
|
||||
return true
|
||||
}
|
||||
e.idx = len(e.edges)
|
||||
return false
|
||||
}
|
||||
|
||||
// WeightedEdge returns the current edge of the iterator. Next must have been
|
||||
// called prior to a call to WeightedEdge.
|
||||
func (e *OrderedWeightedEdges) WeightedEdge() graph.WeightedEdge {
|
||||
if e.idx >= len(e.edges) || e.idx < 0 {
|
||||
return nil
|
||||
}
|
||||
return e.edges[e.idx]
|
||||
}
|
||||
|
||||
// WeightedEdgeSlice returns all the remaining edges in the iterator and advances
|
||||
// the iterator.
|
||||
func (e *OrderedWeightedEdges) WeightedEdgeSlice() []graph.WeightedEdge {
|
||||
if e.idx >= len(e.edges) {
|
||||
return nil
|
||||
}
|
||||
idx := e.idx
|
||||
if idx == -1 {
|
||||
idx = 0
|
||||
}
|
||||
e.idx = len(e.edges)
|
||||
return e.edges[idx:]
|
||||
}
|
||||
|
||||
// Reset returns the iterator to its initial state.
|
||||
func (e *OrderedWeightedEdges) Reset() {
|
||||
e.idx = -1
|
||||
}
|
131
vendor/gonum.org/v1/gonum/graph/iterator/lines.go
generated
vendored
Normal file
131
vendor/gonum.org/v1/gonum/graph/iterator/lines.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright ©2018 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package iterator
|
||||
|
||||
import "gonum.org/v1/gonum/graph"
|
||||
|
||||
// OrderedLines implements the graph.Lines and graph.LineSlicer interfaces.
|
||||
// The iteration order of OrderedLines is the order of lines passed to
|
||||
// NewLineIterator.
|
||||
type OrderedLines struct {
|
||||
idx int
|
||||
lines []graph.Line
|
||||
}
|
||||
|
||||
// NewOrderedLines returns an OrderedLines initialized with the provided lines.
|
||||
func NewOrderedLines(lines []graph.Line) *OrderedLines {
|
||||
return &OrderedLines{idx: -1, lines: lines}
|
||||
}
|
||||
|
||||
// Len returns the remaining number of lines to be iterated over.
|
||||
func (e *OrderedLines) Len() int {
|
||||
if e.idx >= len(e.lines) {
|
||||
return 0
|
||||
}
|
||||
if e.idx <= 0 {
|
||||
return len(e.lines)
|
||||
}
|
||||
return len(e.lines[e.idx:])
|
||||
}
|
||||
|
||||
// Next returns whether the next call of Line will return a valid line.
|
||||
func (e *OrderedLines) Next() bool {
|
||||
if uint(e.idx)+1 < uint(len(e.lines)) {
|
||||
e.idx++
|
||||
return true
|
||||
}
|
||||
e.idx = len(e.lines)
|
||||
return false
|
||||
}
|
||||
|
||||
// Line returns the current line of the iterator. Next must have been
|
||||
// called prior to a call to Line.
|
||||
func (e *OrderedLines) Line() graph.Line {
|
||||
if e.idx >= len(e.lines) || e.idx < 0 {
|
||||
return nil
|
||||
}
|
||||
return e.lines[e.idx]
|
||||
}
|
||||
|
||||
// LineSlice returns all the remaining lines in the iterator and advances
|
||||
// the iterator.
|
||||
func (e *OrderedLines) LineSlice() []graph.Line {
|
||||
if e.idx >= len(e.lines) {
|
||||
return nil
|
||||
}
|
||||
idx := e.idx
|
||||
if idx == -1 {
|
||||
idx = 0
|
||||
}
|
||||
e.idx = len(e.lines)
|
||||
return e.lines[idx:]
|
||||
}
|
||||
|
||||
// Reset returns the iterator to its initial state.
|
||||
func (e *OrderedLines) Reset() {
|
||||
e.idx = -1
|
||||
}
|
||||
|
||||
// OrderedWeightedLines implements the graph.Lines and graph.LineSlicer interfaces.
|
||||
// The iteration order of OrderedWeightedLines is the order of lines passed to
|
||||
// NewLineIterator.
|
||||
type OrderedWeightedLines struct {
|
||||
idx int
|
||||
lines []graph.WeightedLine
|
||||
}
|
||||
|
||||
// NewWeightedLineIterator returns an OrderedWeightedLines initialized with the provided lines.
|
||||
func NewOrderedWeightedLines(lines []graph.WeightedLine) *OrderedWeightedLines {
|
||||
return &OrderedWeightedLines{idx: -1, lines: lines}
|
||||
}
|
||||
|
||||
// Len returns the remaining number of lines to be iterated over.
|
||||
func (e *OrderedWeightedLines) Len() int {
|
||||
if e.idx >= len(e.lines) {
|
||||
return 0
|
||||
}
|
||||
if e.idx <= 0 {
|
||||
return len(e.lines)
|
||||
}
|
||||
return len(e.lines[e.idx:])
|
||||
}
|
||||
|
||||
// Next returns whether the next call of WeightedLine will return a valid line.
|
||||
func (e *OrderedWeightedLines) Next() bool {
|
||||
if uint(e.idx)+1 < uint(len(e.lines)) {
|
||||
e.idx++
|
||||
return true
|
||||
}
|
||||
e.idx = len(e.lines)
|
||||
return false
|
||||
}
|
||||
|
||||
// WeightedLine returns the current line of the iterator. Next must have been
|
||||
// called prior to a call to WeightedLine.
|
||||
func (e *OrderedWeightedLines) WeightedLine() graph.WeightedLine {
|
||||
if e.idx >= len(e.lines) || e.idx < 0 {
|
||||
return nil
|
||||
}
|
||||
return e.lines[e.idx]
|
||||
}
|
||||
|
||||
// WeightedLineSlice returns all the remaining lines in the iterator and advances
|
||||
// the iterator.
|
||||
func (e *OrderedWeightedLines) WeightedLineSlice() []graph.WeightedLine {
|
||||
if e.idx >= len(e.lines) {
|
||||
return nil
|
||||
}
|
||||
idx := e.idx
|
||||
if idx == -1 {
|
||||
idx = 0
|
||||
}
|
||||
e.idx = len(e.lines)
|
||||
return e.lines[idx:]
|
||||
}
|
||||
|
||||
// Reset returns the iterator to its initial state.
|
||||
func (e *OrderedWeightedLines) Reset() {
|
||||
e.idx = -1
|
||||
}
|
125
vendor/gonum.org/v1/gonum/graph/iterator/nodes.go
generated
vendored
Normal file
125
vendor/gonum.org/v1/gonum/graph/iterator/nodes.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright ©2018 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package iterator
|
||||
|
||||
import "gonum.org/v1/gonum/graph"
|
||||
|
||||
// OrderedNodes implements the graph.Nodes and graph.NodeSlicer interfaces.
|
||||
// The iteration order of OrderedNodes is the order of nodes passed to
|
||||
// NewNodeIterator.
|
||||
type OrderedNodes struct {
|
||||
idx int
|
||||
nodes []graph.Node
|
||||
}
|
||||
|
||||
// NewOrderedNodes returns a OrderedNodes initialized with the provided nodes.
|
||||
func NewOrderedNodes(nodes []graph.Node) *OrderedNodes {
|
||||
return &OrderedNodes{idx: -1, nodes: nodes}
|
||||
}
|
||||
|
||||
// Len returns the remaining number of nodes to be iterated over.
|
||||
func (n *OrderedNodes) Len() int {
|
||||
if n.idx >= len(n.nodes) {
|
||||
return 0
|
||||
}
|
||||
if n.idx <= 0 {
|
||||
return len(n.nodes)
|
||||
}
|
||||
return len(n.nodes[n.idx:])
|
||||
}
|
||||
|
||||
// Next returns whether the next call of Node will return a valid node.
|
||||
func (n *OrderedNodes) Next() bool {
|
||||
if uint(n.idx)+1 < uint(len(n.nodes)) {
|
||||
n.idx++
|
||||
return true
|
||||
}
|
||||
n.idx = len(n.nodes)
|
||||
return false
|
||||
}
|
||||
|
||||
// Node returns the current node of the iterator. Next must have been
|
||||
// called prior to a call to Node.
|
||||
func (n *OrderedNodes) Node() graph.Node {
|
||||
if n.idx >= len(n.nodes) || n.idx < 0 {
|
||||
return nil
|
||||
}
|
||||
return n.nodes[n.idx]
|
||||
}
|
||||
|
||||
// NodeSlice returns all the remaining nodes in the iterator and advances
|
||||
// the iterator.
|
||||
func (n *OrderedNodes) NodeSlice() []graph.Node {
|
||||
if n.idx >= len(n.nodes) {
|
||||
return nil
|
||||
}
|
||||
idx := n.idx
|
||||
if idx == -1 {
|
||||
idx = 0
|
||||
}
|
||||
n.idx = len(n.nodes)
|
||||
return n.nodes[idx:]
|
||||
}
|
||||
|
||||
// Reset returns the iterator to its initial state.
|
||||
func (n *OrderedNodes) Reset() {
|
||||
n.idx = -1
|
||||
}
|
||||
|
||||
// ImplicitNodes implements the graph.Nodes interface for a set of nodes over
|
||||
// a contiguous ID range.
|
||||
type ImplicitNodes struct {
|
||||
beg, end int
|
||||
curr int
|
||||
newNode func(id int) graph.Node
|
||||
}
|
||||
|
||||
// NewImplicitNodes returns a new implicit node iterator spanning nodes in [beg,end).
|
||||
// The provided new func maps the id to a graph.Node. NewImplicitNodes will panic
|
||||
// if beg is greater than end.
|
||||
func NewImplicitNodes(beg, end int, new func(id int) graph.Node) *ImplicitNodes {
|
||||
if beg > end {
|
||||
panic("iterator: invalid range")
|
||||
}
|
||||
return &ImplicitNodes{beg: beg, end: end, curr: beg - 1, newNode: new}
|
||||
}
|
||||
|
||||
// Len returns the remaining number of nodes to be iterated over.
|
||||
func (n *ImplicitNodes) Len() int {
|
||||
return n.end - n.curr - 1
|
||||
}
|
||||
|
||||
// Next returns whether the next call of Node will return a valid node.
|
||||
func (n *ImplicitNodes) Next() bool {
|
||||
if n.curr == n.end {
|
||||
return false
|
||||
}
|
||||
n.curr++
|
||||
return n.curr < n.end
|
||||
}
|
||||
|
||||
// Node returns the current node of the iterator. Next must have been
|
||||
// called prior to a call to Node.
|
||||
func (n *ImplicitNodes) Node() graph.Node {
|
||||
if n.Len() == -1 || n.curr < n.beg {
|
||||
return nil
|
||||
}
|
||||
return n.newNode(n.curr)
|
||||
}
|
||||
|
||||
// Reset returns the iterator to its initial state.
|
||||
func (n *ImplicitNodes) Reset() {
|
||||
n.curr = n.beg - 1
|
||||
}
|
||||
|
||||
// NodeSlice returns all the remaining nodes in the iterator and advances
|
||||
// the iterator.
|
||||
func (n *ImplicitNodes) NodeSlice() []graph.Node {
|
||||
nodes := make([]graph.Node, 0, n.Len())
|
||||
for n.curr++; n.curr < n.end; n.curr++ {
|
||||
nodes = append(nodes, n.newNode(n.curr))
|
||||
}
|
||||
return nodes
|
||||
}
|
198
vendor/gonum.org/v1/gonum/graph/multigraph.go
generated
vendored
Normal file
198
vendor/gonum.org/v1/gonum/graph/multigraph.go
generated
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package graph
|
||||
|
||||
// Line is an edge in a multigraph. A Line returns an ID that must
|
||||
// distinguish Lines sharing Node end points.
|
||||
type Line interface {
|
||||
// From returns the from node of the edge.
|
||||
From() Node
|
||||
|
||||
// To returns the to node of the edge.
|
||||
To() Node
|
||||
|
||||
// ReversedLine returns a line that has the
|
||||
// end points of the receiver swapped.
|
||||
ReversedLine() Line
|
||||
|
||||
// ID returns the unique ID for the Line.
|
||||
ID() int64
|
||||
}
|
||||
|
||||
// WeightedLine is a weighted multigraph edge.
|
||||
type WeightedLine interface {
|
||||
Line
|
||||
Weight() float64
|
||||
}
|
||||
|
||||
// Multigraph is a generalized multigraph.
|
||||
type Multigraph interface {
|
||||
// Node returns the node with the given ID if it exists
|
||||
// in the multigraph, and nil otherwise.
|
||||
Node(id int64) Node
|
||||
|
||||
// Nodes returns all the nodes in the multigraph.
|
||||
//
|
||||
// Nodes must not return nil.
|
||||
Nodes() Nodes
|
||||
|
||||
// From returns all nodes that can be reached directly
|
||||
// from the node with the given ID.
|
||||
//
|
||||
// From must not return nil.
|
||||
From(id int64) Nodes
|
||||
|
||||
// HasEdgeBetween returns whether an edge exists between
|
||||
// nodes with IDs xid and yid without considering direction.
|
||||
HasEdgeBetween(xid, yid int64) bool
|
||||
|
||||
// Lines returns the lines from u to v, with IDs uid and
|
||||
// vid, if any such lines exist and nil otherwise. The
|
||||
// node v must be directly reachable from u as defined by
|
||||
// the From method.
|
||||
//
|
||||
// Lines must not return nil.
|
||||
Lines(uid, vid int64) Lines
|
||||
}
|
||||
|
||||
// WeightedMultigraph is a weighted multigraph.
|
||||
type WeightedMultigraph interface {
|
||||
Multigraph
|
||||
|
||||
// WeightedLines returns the weighted lines from u to v
|
||||
// with IDs uid and vid if any such lines exist and nil
|
||||
// otherwise. The node v must be directly reachable
|
||||
// from u as defined by the From method.
|
||||
//
|
||||
// WeightedLines must not return nil.
|
||||
WeightedLines(uid, vid int64) WeightedLines
|
||||
}
|
||||
|
||||
// UndirectedMultigraph is an undirected multigraph.
|
||||
type UndirectedMultigraph interface {
|
||||
Multigraph
|
||||
|
||||
// LinesBetween returns the lines between nodes x and y
|
||||
// with IDs xid and yid.
|
||||
//
|
||||
// LinesBetween must not return nil.
|
||||
LinesBetween(xid, yid int64) Lines
|
||||
}
|
||||
|
||||
// WeightedUndirectedMultigraph is a weighted undirected multigraph.
|
||||
type WeightedUndirectedMultigraph interface {
|
||||
WeightedMultigraph
|
||||
|
||||
// WeightedLinesBetween returns the lines between nodes
|
||||
// x and y with IDs xid and yid.
|
||||
//
|
||||
// WeightedLinesBetween must not return nil.
|
||||
WeightedLinesBetween(xid, yid int64) WeightedLines
|
||||
}
|
||||
|
||||
// DirectedMultigraph is a directed multigraph.
|
||||
type DirectedMultigraph interface {
|
||||
Multigraph
|
||||
|
||||
// HasEdgeFromTo returns whether an edge exists
|
||||
// in the multigraph from u to v with IDs uid
|
||||
// and vid.
|
||||
HasEdgeFromTo(uid, vid int64) bool
|
||||
|
||||
// To returns all nodes that can reach directly
|
||||
// to the node with the given ID.
|
||||
//
|
||||
// To must not return nil.
|
||||
To(id int64) Nodes
|
||||
}
|
||||
|
||||
// WeightedDirectedMultigraph is a weighted directed multigraph.
|
||||
type WeightedDirectedMultigraph interface {
|
||||
WeightedMultigraph
|
||||
|
||||
// HasEdgeFromTo returns whether an edge exists
|
||||
// in the multigraph from u to v with IDs uid
|
||||
// and vid.
|
||||
HasEdgeFromTo(uid, vid int64) bool
|
||||
|
||||
// To returns all nodes that can reach directly
|
||||
// to the node with the given ID.
|
||||
//
|
||||
// To must not return nil.
|
||||
To(id int64) Nodes
|
||||
}
|
||||
|
||||
// LineAdder is an interface for adding lines to a multigraph.
|
||||
type LineAdder interface {
|
||||
// NewLine returns a new Line from the source to the destination node.
|
||||
NewLine(from, to Node) Line
|
||||
|
||||
// SetLine adds a Line from one node to another.
|
||||
// If the multigraph supports node addition the nodes
|
||||
// will be added if they do not exist, otherwise
|
||||
// SetLine will panic.
|
||||
// Whether l, l.From() and l.To() are stored
|
||||
// within the graph is implementation dependent.
|
||||
SetLine(l Line)
|
||||
}
|
||||
|
||||
// WeightedLineAdder is an interface for adding lines to a multigraph.
|
||||
type WeightedLineAdder interface {
|
||||
// NewWeightedLine returns a new WeightedLine from
|
||||
// the source to the destination node.
|
||||
NewWeightedLine(from, to Node, weight float64) WeightedLine
|
||||
|
||||
// SetWeightedLine adds a weighted line from one node
|
||||
// to another. If the multigraph supports node addition
|
||||
// the nodes will be added if they do not exist,
|
||||
// otherwise SetWeightedLine will panic.
|
||||
// Whether l, l.From() and l.To() are stored
|
||||
// within the graph is implementation dependent.
|
||||
SetWeightedLine(l WeightedLine)
|
||||
}
|
||||
|
||||
// LineRemover is an interface for removing lines from a multigraph.
|
||||
type LineRemover interface {
|
||||
// RemoveLine removes the line with the given end
|
||||
// and line IDs, leaving the terminal nodes. If
|
||||
// the line does not exist it is a no-op.
|
||||
RemoveLine(fid, tid, id int64)
|
||||
}
|
||||
|
||||
// MultigraphBuilder is a multigraph that can have nodes and lines added.
|
||||
type MultigraphBuilder interface {
|
||||
NodeAdder
|
||||
LineAdder
|
||||
}
|
||||
|
||||
// WeightedMultigraphBuilder is a multigraph that can have nodes and weighted lines added.
|
||||
type WeightedMultigraphBuilder interface {
|
||||
NodeAdder
|
||||
WeightedLineAdder
|
||||
}
|
||||
|
||||
// UndirectedMultgraphBuilder is an undirected multigraph builder.
|
||||
type UndirectedMultigraphBuilder interface {
|
||||
UndirectedMultigraph
|
||||
MultigraphBuilder
|
||||
}
|
||||
|
||||
// UndirectedWeightedMultigraphBuilder is an undirected weighted multigraph builder.
|
||||
type UndirectedWeightedMultigraphBuilder interface {
|
||||
UndirectedMultigraph
|
||||
WeightedMultigraphBuilder
|
||||
}
|
||||
|
||||
// DirectedMultigraphBuilder is a directed multigraph builder.
|
||||
type DirectedMultigraphBuilder interface {
|
||||
DirectedMultigraph
|
||||
MultigraphBuilder
|
||||
}
|
||||
|
||||
// DirectedWeightedMultigraphBuilder is a directed weighted multigraph builder.
|
||||
type DirectedWeightedMultigraphBuilder interface {
|
||||
DirectedMultigraph
|
||||
WeightedMultigraphBuilder
|
||||
}
|
300
vendor/gonum.org/v1/gonum/graph/nodes_edges.go
generated
vendored
Normal file
300
vendor/gonum.org/v1/gonum/graph/nodes_edges.go
generated
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
// Copyright ©2018 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package graph
|
||||
|
||||
// Iterator is an item iterator.
|
||||
type Iterator interface {
|
||||
// Next advances the iterator and returns whether
|
||||
// the next call to the item method will return a
|
||||
// non-nil item.
|
||||
//
|
||||
// Next should be called prior to any call to the
|
||||
// iterator's item retrieval method after the
|
||||
// iterator has been obtained or reset.
|
||||
//
|
||||
// The order of iteration is implementation
|
||||
// dependent.
|
||||
Next() bool
|
||||
|
||||
// Len returns the number of items remaining in the
|
||||
// iterator.
|
||||
//
|
||||
// If the number of items in the iterator is unknown,
|
||||
// too large to materialize or too costly to calculate
|
||||
// then Len may return a negative value.
|
||||
// In this case the consuming function must be able
|
||||
// to operate on the items of the iterator directly
|
||||
// without materializing the items into a slice.
|
||||
// The magnitude of a negative length has
|
||||
// implementation-dependent semantics.
|
||||
Len() int
|
||||
|
||||
// Reset returns the iterator to its start position.
|
||||
Reset()
|
||||
}
|
||||
|
||||
// Nodes is a Node iterator.
|
||||
type Nodes interface {
|
||||
Iterator
|
||||
|
||||
// Node returns the current Node from the iterator.
|
||||
Node() Node
|
||||
}
|
||||
|
||||
// NodeSlicer wraps the NodeSlice method.
|
||||
type NodeSlicer interface {
|
||||
// NodeSlice returns the set of nodes remaining
|
||||
// to be iterated by a Nodes iterator.
|
||||
// The holder of the iterator may arbitrarily
|
||||
// change elements in the returned slice, but
|
||||
// those changes may be reflected to other
|
||||
// iterators.
|
||||
NodeSlice() []Node
|
||||
}
|
||||
|
||||
// NodesOf returns it.Len() nodes from it. If it is a NodeSlicer, the NodeSlice method
|
||||
// is used to obtain the nodes. It is safe to pass a nil Nodes to NodesOf.
|
||||
//
|
||||
// If the Nodes has an indeterminate length, NodesOf will panic.
|
||||
func NodesOf(it Nodes) []Node {
|
||||
if it == nil {
|
||||
return nil
|
||||
}
|
||||
len := it.Len()
|
||||
switch {
|
||||
case len == 0:
|
||||
return nil
|
||||
case len < 0:
|
||||
panic("graph: called NodesOf on indeterminate iterator")
|
||||
}
|
||||
switch it := it.(type) {
|
||||
case NodeSlicer:
|
||||
return it.NodeSlice()
|
||||
}
|
||||
n := make([]Node, 0, len)
|
||||
for it.Next() {
|
||||
n = append(n, it.Node())
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Edges is an Edge iterator.
|
||||
type Edges interface {
|
||||
Iterator
|
||||
|
||||
// Edge returns the current Edge from the iterator.
|
||||
Edge() Edge
|
||||
}
|
||||
|
||||
// EdgeSlicer wraps the EdgeSlice method.
|
||||
type EdgeSlicer interface {
|
||||
// EdgeSlice returns the set of edges remaining
|
||||
// to be iterated by an Edges iterator.
|
||||
// The holder of the iterator may arbitrarily
|
||||
// change elements in the returned slice, but
|
||||
// those changes may be reflected to other
|
||||
// iterators.
|
||||
EdgeSlice() []Edge
|
||||
}
|
||||
|
||||
// EdgesOf returns it.Len() nodes from it. If it is an EdgeSlicer, the EdgeSlice method is used
|
||||
// to obtain the edges. It is safe to pass a nil Edges to EdgesOf.
|
||||
//
|
||||
// If the Edges has an indeterminate length, EdgesOf will panic.
|
||||
func EdgesOf(it Edges) []Edge {
|
||||
if it == nil {
|
||||
return nil
|
||||
}
|
||||
len := it.Len()
|
||||
switch {
|
||||
case len == 0:
|
||||
return nil
|
||||
case len < 0:
|
||||
panic("graph: called EdgesOf on indeterminate iterator")
|
||||
}
|
||||
switch it := it.(type) {
|
||||
case EdgeSlicer:
|
||||
return it.EdgeSlice()
|
||||
}
|
||||
e := make([]Edge, 0, len)
|
||||
for it.Next() {
|
||||
e = append(e, it.Edge())
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// WeightedEdges is a WeightedEdge iterator.
|
||||
type WeightedEdges interface {
|
||||
Iterator
|
||||
|
||||
// Edge returns the current Edge from the iterator.
|
||||
WeightedEdge() WeightedEdge
|
||||
}
|
||||
|
||||
// WeightedEdgeSlicer wraps the WeightedEdgeSlice method.
|
||||
type WeightedEdgeSlicer interface {
|
||||
// EdgeSlice returns the set of edges remaining
|
||||
// to be iterated by an Edges iterator.
|
||||
// The holder of the iterator may arbitrarily
|
||||
// change elements in the returned slice, but
|
||||
// those changes may be reflected to other
|
||||
// iterators.
|
||||
WeightedEdgeSlice() []WeightedEdge
|
||||
}
|
||||
|
||||
// WeightedEdgesOf returns it.Len() weighted edge from it. If it is a WeightedEdgeSlicer, the
|
||||
// WeightedEdgeSlice method is used to obtain the edges. It is safe to pass a nil WeightedEdges
|
||||
// to WeightedEdgesOf.
|
||||
//
|
||||
// If the WeightedEdges has an indeterminate length, WeightedEdgesOf will panic.
|
||||
func WeightedEdgesOf(it WeightedEdges) []WeightedEdge {
|
||||
if it == nil {
|
||||
return nil
|
||||
}
|
||||
len := it.Len()
|
||||
switch {
|
||||
case len == 0:
|
||||
return nil
|
||||
case len < 0:
|
||||
panic("graph: called WeightedEdgesOf on indeterminate iterator")
|
||||
}
|
||||
switch it := it.(type) {
|
||||
case WeightedEdgeSlicer:
|
||||
return it.WeightedEdgeSlice()
|
||||
}
|
||||
e := make([]WeightedEdge, 0, len)
|
||||
for it.Next() {
|
||||
e = append(e, it.WeightedEdge())
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// Lines is a Line iterator.
|
||||
type Lines interface {
|
||||
Iterator
|
||||
|
||||
// Line returns the current Line from the iterator.
|
||||
Line() Line
|
||||
}
|
||||
|
||||
// LineSlicer wraps the LineSlice method.
|
||||
type LineSlicer interface {
|
||||
// LineSlice returns the set of lines remaining
|
||||
// to be iterated by an Lines iterator.
|
||||
// The holder of the iterator may arbitrarily
|
||||
// change elements in the returned slice, but
|
||||
// those changes may be reflected to other
|
||||
// iterators.
|
||||
LineSlice() []Line
|
||||
}
|
||||
|
||||
// LinesOf returns it.Len() nodes from it. If it is a LineSlicer, the LineSlice method is used
|
||||
// to obtain the lines. It is safe to pass a nil Lines to LinesOf.
|
||||
//
|
||||
// If the Lines has an indeterminate length, LinesOf will panic.
|
||||
func LinesOf(it Lines) []Line {
|
||||
if it == nil {
|
||||
return nil
|
||||
}
|
||||
len := it.Len()
|
||||
switch {
|
||||
case len == 0:
|
||||
return nil
|
||||
case len < 0:
|
||||
panic("graph: called LinesOf on indeterminate iterator")
|
||||
}
|
||||
switch it := it.(type) {
|
||||
case LineSlicer:
|
||||
return it.LineSlice()
|
||||
}
|
||||
l := make([]Line, 0, len)
|
||||
for it.Next() {
|
||||
l = append(l, it.Line())
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// WeightedLines is a WeightedLine iterator.
|
||||
type WeightedLines interface {
|
||||
Iterator
|
||||
|
||||
// Line returns the current Line from the iterator.
|
||||
WeightedLine() WeightedLine
|
||||
}
|
||||
|
||||
// WeightedLineSlicer wraps the WeightedLineSlice method.
|
||||
type WeightedLineSlicer interface {
|
||||
// LineSlice returns the set of lines remaining
|
||||
// to be iterated by an Lines iterator.
|
||||
// The holder of the iterator may arbitrarily
|
||||
// change elements in the returned slice, but
|
||||
// those changes may be reflected to other
|
||||
// iterators.
|
||||
WeightedLineSlice() []WeightedLine
|
||||
}
|
||||
|
||||
// WeightedLinesOf returns it.Len() weighted line from it. If it is a WeightedLineSlicer, the
|
||||
// WeightedLineSlice method is used to obtain the lines. It is safe to pass a nil WeightedLines
|
||||
// to WeightedLinesOf.
|
||||
//
|
||||
// If the WeightedLines has an indeterminate length, WeightedLinesOf will panic.
|
||||
func WeightedLinesOf(it WeightedLines) []WeightedLine {
|
||||
if it == nil {
|
||||
return nil
|
||||
}
|
||||
len := it.Len()
|
||||
switch {
|
||||
case len == 0:
|
||||
return nil
|
||||
case len < 0:
|
||||
panic("graph: called WeightedLinesOf on indeterminate iterator")
|
||||
}
|
||||
switch it := it.(type) {
|
||||
case WeightedLineSlicer:
|
||||
return it.WeightedLineSlice()
|
||||
}
|
||||
l := make([]WeightedLine, 0, len)
|
||||
for it.Next() {
|
||||
l = append(l, it.WeightedLine())
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// Empty is an empty set of nodes, edges or lines. It should be used when
|
||||
// a graph returns a zero-length Iterator. Empty implements the slicer
|
||||
// interfaces for nodes, edges and lines, returning nil for each of these.
|
||||
const Empty = nothing
|
||||
|
||||
var (
|
||||
_ Iterator = Empty
|
||||
_ Nodes = Empty
|
||||
_ NodeSlicer = Empty
|
||||
_ Edges = Empty
|
||||
_ EdgeSlicer = Empty
|
||||
_ WeightedEdges = Empty
|
||||
_ WeightedEdgeSlicer = Empty
|
||||
_ Lines = Empty
|
||||
_ LineSlicer = Empty
|
||||
_ WeightedLines = Empty
|
||||
_ WeightedLineSlicer = Empty
|
||||
)
|
||||
|
||||
const nothing = empty(true)
|
||||
|
||||
type empty bool
|
||||
|
||||
func (empty) Next() bool { return false }
|
||||
func (empty) Len() int { return 0 }
|
||||
func (empty) Reset() {}
|
||||
func (empty) Node() Node { return nil }
|
||||
func (empty) NodeSlice() []Node { return nil }
|
||||
func (empty) Edge() Edge { return nil }
|
||||
func (empty) EdgeSlice() []Edge { return nil }
|
||||
func (empty) WeightedEdge() WeightedEdge { return nil }
|
||||
func (empty) WeightedEdgeSlice() []WeightedEdge { return nil }
|
||||
func (empty) Line() Line { return nil }
|
||||
func (empty) LineSlice() []Line { return nil }
|
||||
func (empty) WeightedLine() WeightedLine { return nil }
|
||||
func (empty) WeightedLineSlice() []WeightedLine { return nil }
|
301
vendor/gonum.org/v1/gonum/graph/simple/dense_directed_matrix.go
generated
vendored
Normal file
301
vendor/gonum.org/v1/gonum/graph/simple/dense_directed_matrix.go
generated
vendored
Normal file
@@ -0,0 +1,301 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simple
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/internal/ordered"
|
||||
"gonum.org/v1/gonum/graph/iterator"
|
||||
"gonum.org/v1/gonum/mat"
|
||||
)
|
||||
|
||||
var (
|
||||
dm *DirectedMatrix
|
||||
|
||||
_ graph.Graph = dm
|
||||
_ graph.Directed = dm
|
||||
_ edgeSetter = dm
|
||||
_ weightedEdgeSetter = dm
|
||||
)
|
||||
|
||||
// DirectedMatrix represents a directed graph using an adjacency
|
||||
// matrix such that all IDs are in a contiguous block from 0 to n-1.
|
||||
// Edges are stored implicitly as an edge weight, so edges stored in
|
||||
// the graph are not recoverable.
|
||||
type DirectedMatrix struct {
|
||||
mat *mat.Dense
|
||||
nodes []graph.Node
|
||||
|
||||
self float64
|
||||
absent float64
|
||||
}
|
||||
|
||||
// NewDirectedMatrix creates a directed dense graph with n nodes.
|
||||
// All edges are initialized with the weight given by init. The self parameter
|
||||
// specifies the cost of self connection, and absent specifies the weight
|
||||
// returned for absent edges.
|
||||
func NewDirectedMatrix(n int, init, self, absent float64) *DirectedMatrix {
|
||||
matrix := make([]float64, n*n)
|
||||
if init != 0 {
|
||||
for i := range matrix {
|
||||
matrix[i] = init
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(matrix); i += n + 1 {
|
||||
matrix[i] = self
|
||||
}
|
||||
return &DirectedMatrix{
|
||||
mat: mat.NewDense(n, n, matrix),
|
||||
self: self,
|
||||
absent: absent,
|
||||
}
|
||||
}
|
||||
|
||||
// NewDirectedMatrixFrom creates a directed dense graph with the given nodes.
|
||||
// The IDs of the nodes must be contiguous from 0 to len(nodes)-1, but may
|
||||
// be in any order. If IDs are not contiguous NewDirectedMatrixFrom will panic.
|
||||
// All edges are initialized with the weight given by init. The self parameter
|
||||
// specifies the cost of self connection, and absent specifies the weight
|
||||
// returned for absent edges.
|
||||
func NewDirectedMatrixFrom(nodes []graph.Node, init, self, absent float64) *DirectedMatrix {
|
||||
sort.Sort(ordered.ByID(nodes))
|
||||
for i, n := range nodes {
|
||||
if int64(i) != n.ID() {
|
||||
panic("simple: non-contiguous node IDs")
|
||||
}
|
||||
}
|
||||
g := NewDirectedMatrix(len(nodes), init, self, absent)
|
||||
g.nodes = nodes
|
||||
return g
|
||||
}
|
||||
|
||||
// Edge returns the edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
func (g *DirectedMatrix) Edge(uid, vid int64) graph.Edge {
|
||||
return g.WeightedEdge(uid, vid)
|
||||
}
|
||||
|
||||
// Edges returns all the edges in the graph.
|
||||
func (g *DirectedMatrix) Edges() graph.Edges {
|
||||
var edges []graph.Edge
|
||||
r, _ := g.mat.Dims()
|
||||
for i := 0; i < r; i++ {
|
||||
for j := 0; j < r; j++ {
|
||||
if i == j {
|
||||
continue
|
||||
}
|
||||
if w := g.mat.At(i, j); !isSame(w, g.absent) {
|
||||
edges = append(edges, WeightedEdge{F: g.Node(int64(i)), T: g.Node(int64(j)), W: w})
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(edges) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedEdges(edges)
|
||||
}
|
||||
|
||||
// From returns all nodes in g that can be reached directly from n.
|
||||
func (g *DirectedMatrix) From(id int64) graph.Nodes {
|
||||
if !g.has(id) {
|
||||
return graph.Empty
|
||||
}
|
||||
var nodes []graph.Node
|
||||
_, c := g.mat.Dims()
|
||||
for j := 0; j < c; j++ {
|
||||
if int64(j) == id {
|
||||
continue
|
||||
}
|
||||
// id is not greater than maximum int by this point.
|
||||
if !isSame(g.mat.At(int(id), j), g.absent) {
|
||||
nodes = append(nodes, g.Node(int64(j)))
|
||||
}
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedNodes(nodes)
|
||||
}
|
||||
|
||||
// HasEdgeBetween returns whether an edge exists between nodes x and y without
|
||||
// considering direction.
|
||||
func (g *DirectedMatrix) HasEdgeBetween(xid, yid int64) bool {
|
||||
if !g.has(xid) {
|
||||
return false
|
||||
}
|
||||
if !g.has(yid) {
|
||||
return false
|
||||
}
|
||||
// xid and yid are not greater than maximum int by this point.
|
||||
return xid != yid && (!isSame(g.mat.At(int(xid), int(yid)), g.absent) || !isSame(g.mat.At(int(yid), int(xid)), g.absent))
|
||||
}
|
||||
|
||||
// HasEdgeFromTo returns whether an edge exists in the graph from u to v.
|
||||
func (g *DirectedMatrix) HasEdgeFromTo(uid, vid int64) bool {
|
||||
if !g.has(uid) {
|
||||
return false
|
||||
}
|
||||
if !g.has(vid) {
|
||||
return false
|
||||
}
|
||||
// uid and vid are not greater than maximum int by this point.
|
||||
return uid != vid && !isSame(g.mat.At(int(uid), int(vid)), g.absent)
|
||||
}
|
||||
|
||||
// Matrix returns the mat.Matrix representation of the graph. The orientation
|
||||
// of the matrix is such that the matrix entry at G_{ij} is the weight of the edge
|
||||
// from node i to node j.
|
||||
func (g *DirectedMatrix) Matrix() mat.Matrix {
|
||||
// Prevent alteration of dimensions of the returned matrix.
|
||||
m := *g.mat
|
||||
return &m
|
||||
}
|
||||
|
||||
// Node returns the node with the given ID if it exists in the graph,
|
||||
// and nil otherwise.
|
||||
func (g *DirectedMatrix) Node(id int64) graph.Node {
|
||||
if !g.has(id) {
|
||||
return nil
|
||||
}
|
||||
if g.nodes == nil {
|
||||
return Node(id)
|
||||
}
|
||||
return g.nodes[id]
|
||||
}
|
||||
|
||||
// Nodes returns all the nodes in the graph.
|
||||
func (g *DirectedMatrix) Nodes() graph.Nodes {
|
||||
if g.nodes != nil {
|
||||
nodes := make([]graph.Node, len(g.nodes))
|
||||
copy(nodes, g.nodes)
|
||||
return iterator.NewOrderedNodes(nodes)
|
||||
}
|
||||
r, _ := g.mat.Dims()
|
||||
// Matrix graphs must have at least one node.
|
||||
return iterator.NewImplicitNodes(0, r, newSimpleNode)
|
||||
}
|
||||
|
||||
// RemoveEdge removes the edge with the given end point nodes from the graph, leaving the terminal
|
||||
// nodes. If the edge does not exist it is a no-op.
|
||||
func (g *DirectedMatrix) RemoveEdge(fid, tid int64) {
|
||||
if !g.has(fid) {
|
||||
return
|
||||
}
|
||||
if !g.has(tid) {
|
||||
return
|
||||
}
|
||||
// fid and tid are not greater than maximum int by this point.
|
||||
g.mat.Set(int(fid), int(tid), g.absent)
|
||||
}
|
||||
|
||||
// SetEdge sets e, an edge from one node to another with unit weight. If the ends of the edge
|
||||
// are not in g or the edge is a self loop, SetEdge panics. SetEdge will store the nodes of
|
||||
// e in the graph if it was initialized with NewDirectedMatrixFrom.
|
||||
func (g *DirectedMatrix) SetEdge(e graph.Edge) {
|
||||
g.setWeightedEdge(e, 1)
|
||||
}
|
||||
|
||||
// SetWeightedEdge sets e, an edge from one node to another. If the ends of the edge are not in g
|
||||
// or the edge is a self loop, SetWeightedEdge panics. SetWeightedEdge will store the nodes of
|
||||
// e in the graph if it was initialized with NewDirectedMatrixFrom.
|
||||
func (g *DirectedMatrix) SetWeightedEdge(e graph.WeightedEdge) {
|
||||
g.setWeightedEdge(e, e.Weight())
|
||||
}
|
||||
|
||||
func (g *DirectedMatrix) setWeightedEdge(e graph.Edge, weight float64) {
|
||||
from := e.From()
|
||||
fid := from.ID()
|
||||
to := e.To()
|
||||
tid := to.ID()
|
||||
if fid == tid {
|
||||
panic("simple: set illegal edge")
|
||||
}
|
||||
if int64(int(fid)) != fid {
|
||||
panic("simple: unavailable from node ID for dense graph")
|
||||
}
|
||||
if int64(int(tid)) != tid {
|
||||
panic("simple: unavailable to node ID for dense graph")
|
||||
}
|
||||
if g.nodes != nil {
|
||||
g.nodes[fid] = from
|
||||
g.nodes[tid] = to
|
||||
}
|
||||
// fid and tid are not greater than maximum int by this point.
|
||||
g.mat.Set(int(fid), int(tid), weight)
|
||||
}
|
||||
|
||||
// To returns all nodes in g that can reach directly to n.
|
||||
func (g *DirectedMatrix) To(id int64) graph.Nodes {
|
||||
if !g.has(id) {
|
||||
return graph.Empty
|
||||
}
|
||||
var nodes []graph.Node
|
||||
r, _ := g.mat.Dims()
|
||||
for i := 0; i < r; i++ {
|
||||
if int64(i) == id {
|
||||
continue
|
||||
}
|
||||
// id is not greater than maximum int by this point.
|
||||
if !isSame(g.mat.At(i, int(id)), g.absent) {
|
||||
nodes = append(nodes, g.Node(int64(i)))
|
||||
}
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedNodes(nodes)
|
||||
}
|
||||
|
||||
// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge.
|
||||
// If x and y are the same node or there is no joining edge between the two nodes the weight
|
||||
// value returned is either the graph's absent or self value. Weight returns true if an edge
|
||||
// exists between x and y or if x and y have the same ID, false otherwise.
|
||||
func (g *DirectedMatrix) Weight(xid, yid int64) (w float64, ok bool) {
|
||||
if xid == yid {
|
||||
return g.self, true
|
||||
}
|
||||
if g.HasEdgeFromTo(xid, yid) {
|
||||
// xid and yid are not greater than maximum int by this point.
|
||||
return g.mat.At(int(xid), int(yid)), true
|
||||
}
|
||||
return g.absent, false
|
||||
}
|
||||
|
||||
// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
func (g *DirectedMatrix) WeightedEdge(uid, vid int64) graph.WeightedEdge {
|
||||
if g.HasEdgeFromTo(uid, vid) {
|
||||
// xid and yid are not greater than maximum int by this point.
|
||||
return WeightedEdge{F: g.Node(uid), T: g.Node(vid), W: g.mat.At(int(uid), int(vid))}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WeightedEdges returns all the edges in the graph.
|
||||
func (g *DirectedMatrix) WeightedEdges() graph.WeightedEdges {
|
||||
var edges []graph.WeightedEdge
|
||||
r, _ := g.mat.Dims()
|
||||
for i := 0; i < r; i++ {
|
||||
for j := 0; j < r; j++ {
|
||||
if i == j {
|
||||
continue
|
||||
}
|
||||
if w := g.mat.At(i, j); !isSame(w, g.absent) {
|
||||
edges = append(edges, WeightedEdge{F: g.Node(int64(i)), T: g.Node(int64(j)), W: w})
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(edges) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedWeightedEdges(edges)
|
||||
}
|
||||
|
||||
func (g *DirectedMatrix) has(id int64) bool {
|
||||
r, _ := g.mat.Dims()
|
||||
return 0 <= id && id < int64(r)
|
||||
}
|
268
vendor/gonum.org/v1/gonum/graph/simple/dense_undirected_matrix.go
generated
vendored
Normal file
268
vendor/gonum.org/v1/gonum/graph/simple/dense_undirected_matrix.go
generated
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simple
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/internal/ordered"
|
||||
"gonum.org/v1/gonum/graph/iterator"
|
||||
"gonum.org/v1/gonum/mat"
|
||||
)
|
||||
|
||||
var (
|
||||
um *UndirectedMatrix
|
||||
|
||||
_ graph.Graph = um
|
||||
_ graph.Undirected = um
|
||||
_ edgeSetter = um
|
||||
_ weightedEdgeSetter = um
|
||||
)
|
||||
|
||||
// UndirectedMatrix represents an undirected graph using an adjacency
|
||||
// matrix such that all IDs are in a contiguous block from 0 to n-1.
|
||||
// Edges are stored implicitly as an edge weight, so edges stored in
|
||||
// the graph are not recoverable.
|
||||
type UndirectedMatrix struct {
|
||||
mat *mat.SymDense
|
||||
nodes []graph.Node
|
||||
|
||||
self float64
|
||||
absent float64
|
||||
}
|
||||
|
||||
// NewUndirectedMatrix creates an undirected dense graph with n nodes.
|
||||
// All edges are initialized with the weight given by init. The self parameter
|
||||
// specifies the cost of self connection, and absent specifies the weight
|
||||
// returned for absent edges.
|
||||
func NewUndirectedMatrix(n int, init, self, absent float64) *UndirectedMatrix {
|
||||
matrix := make([]float64, n*n)
|
||||
if init != 0 {
|
||||
for i := range matrix {
|
||||
matrix[i] = init
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(matrix); i += n + 1 {
|
||||
matrix[i] = self
|
||||
}
|
||||
return &UndirectedMatrix{
|
||||
mat: mat.NewSymDense(n, matrix),
|
||||
self: self,
|
||||
absent: absent,
|
||||
}
|
||||
}
|
||||
|
||||
// NewUndirectedMatrixFrom creates an undirected dense graph with the given nodes.
|
||||
// The IDs of the nodes must be contiguous from 0 to len(nodes)-1, but may
|
||||
// be in any order. If IDs are not contiguous NewUndirectedMatrixFrom will panic.
|
||||
// All edges are initialized with the weight given by init. The self parameter
|
||||
// specifies the cost of self connection, and absent specifies the weight
|
||||
// returned for absent edges.
|
||||
func NewUndirectedMatrixFrom(nodes []graph.Node, init, self, absent float64) *UndirectedMatrix {
|
||||
sort.Sort(ordered.ByID(nodes))
|
||||
for i, n := range nodes {
|
||||
if int64(i) != n.ID() {
|
||||
panic("simple: non-contiguous node IDs")
|
||||
}
|
||||
}
|
||||
g := NewUndirectedMatrix(len(nodes), init, self, absent)
|
||||
g.nodes = nodes
|
||||
return g
|
||||
}
|
||||
|
||||
// Edge returns the edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
func (g *UndirectedMatrix) Edge(uid, vid int64) graph.Edge {
|
||||
return g.WeightedEdgeBetween(uid, vid)
|
||||
}
|
||||
|
||||
// EdgeBetween returns the edge between nodes x and y.
|
||||
func (g *UndirectedMatrix) EdgeBetween(uid, vid int64) graph.Edge {
|
||||
return g.WeightedEdgeBetween(uid, vid)
|
||||
}
|
||||
|
||||
// Edges returns all the edges in the graph.
|
||||
func (g *UndirectedMatrix) Edges() graph.Edges {
|
||||
var edges []graph.Edge
|
||||
r, _ := g.mat.Dims()
|
||||
for i := 0; i < r; i++ {
|
||||
for j := i + 1; j < r; j++ {
|
||||
if w := g.mat.At(i, j); !isSame(w, g.absent) {
|
||||
edges = append(edges, WeightedEdge{F: g.Node(int64(i)), T: g.Node(int64(j)), W: w})
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(edges) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedEdges(edges)
|
||||
}
|
||||
|
||||
// From returns all nodes in g that can be reached directly from n.
|
||||
func (g *UndirectedMatrix) From(id int64) graph.Nodes {
|
||||
if !g.has(id) {
|
||||
return graph.Empty
|
||||
}
|
||||
var nodes []graph.Node
|
||||
r := g.mat.Symmetric()
|
||||
for i := 0; i < r; i++ {
|
||||
if int64(i) == id {
|
||||
continue
|
||||
}
|
||||
// id is not greater than maximum int by this point.
|
||||
if !isSame(g.mat.At(int(id), i), g.absent) {
|
||||
nodes = append(nodes, g.Node(int64(i)))
|
||||
}
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedNodes(nodes)
|
||||
}
|
||||
|
||||
// HasEdgeBetween returns whether an edge exists between nodes x and y.
|
||||
func (g *UndirectedMatrix) HasEdgeBetween(uid, vid int64) bool {
|
||||
if !g.has(uid) {
|
||||
return false
|
||||
}
|
||||
if !g.has(vid) {
|
||||
return false
|
||||
}
|
||||
// uid and vid are not greater than maximum int by this point.
|
||||
return uid != vid && !isSame(g.mat.At(int(uid), int(vid)), g.absent)
|
||||
}
|
||||
|
||||
// Matrix returns the mat.Matrix representation of the graph.
|
||||
func (g *UndirectedMatrix) Matrix() mat.Matrix {
|
||||
// Prevent alteration of dimensions of the returned matrix.
|
||||
m := *g.mat
|
||||
return &m
|
||||
}
|
||||
|
||||
// Node returns the node with the given ID if it exists in the graph,
|
||||
// and nil otherwise.
|
||||
func (g *UndirectedMatrix) Node(id int64) graph.Node {
|
||||
if !g.has(id) {
|
||||
return nil
|
||||
}
|
||||
if g.nodes == nil {
|
||||
return Node(id)
|
||||
}
|
||||
return g.nodes[id]
|
||||
}
|
||||
|
||||
// Nodes returns all the nodes in the graph.
|
||||
func (g *UndirectedMatrix) Nodes() graph.Nodes {
|
||||
if g.nodes != nil {
|
||||
nodes := make([]graph.Node, len(g.nodes))
|
||||
copy(nodes, g.nodes)
|
||||
return iterator.NewOrderedNodes(nodes)
|
||||
}
|
||||
r := g.mat.Symmetric()
|
||||
// Matrix graphs must have at least one node.
|
||||
return iterator.NewImplicitNodes(0, r, newSimpleNode)
|
||||
}
|
||||
|
||||
// RemoveEdge removes the edge with the given end point IDs from the graph, leaving the terminal
|
||||
// nodes. If the edge does not exist it is a no-op.
|
||||
func (g *UndirectedMatrix) RemoveEdge(fid, tid int64) {
|
||||
if !g.has(fid) {
|
||||
return
|
||||
}
|
||||
if !g.has(tid) {
|
||||
return
|
||||
}
|
||||
// fid and tid are not greater than maximum int by this point.
|
||||
g.mat.SetSym(int(fid), int(tid), g.absent)
|
||||
}
|
||||
|
||||
// SetEdge sets e, an edge from one node to another with unit weight. If the ends of the edge are
|
||||
// not in g or the edge is a self loop, SetEdge panics. SetEdge will store the nodes of
|
||||
// e in the graph if it was initialized with NewUndirectedMatrixFrom.
|
||||
func (g *UndirectedMatrix) SetEdge(e graph.Edge) {
|
||||
g.setWeightedEdge(e, 1)
|
||||
}
|
||||
|
||||
// SetWeightedEdge sets e, an edge from one node to another. If the ends of the edge are not in g
|
||||
// or the edge is a self loop, SetWeightedEdge panics. SetWeightedEdge will store the nodes of
|
||||
// e in the graph if it was initialized with NewUndirectedMatrixFrom.
|
||||
func (g *UndirectedMatrix) SetWeightedEdge(e graph.WeightedEdge) {
|
||||
g.setWeightedEdge(e, e.Weight())
|
||||
}
|
||||
|
||||
func (g *UndirectedMatrix) setWeightedEdge(e graph.Edge, weight float64) {
|
||||
from := e.From()
|
||||
fid := from.ID()
|
||||
to := e.To()
|
||||
tid := to.ID()
|
||||
if fid == tid {
|
||||
panic("simple: set illegal edge")
|
||||
}
|
||||
if int64(int(fid)) != fid {
|
||||
panic("simple: unavailable from node ID for dense graph")
|
||||
}
|
||||
if int64(int(tid)) != tid {
|
||||
panic("simple: unavailable to node ID for dense graph")
|
||||
}
|
||||
if g.nodes != nil {
|
||||
g.nodes[fid] = from
|
||||
g.nodes[tid] = to
|
||||
}
|
||||
// fid and tid are not greater than maximum int by this point.
|
||||
g.mat.SetSym(int(fid), int(tid), weight)
|
||||
}
|
||||
|
||||
// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge.
|
||||
// If x and y are the same node or there is no joining edge between the two nodes the weight
|
||||
// value returned is either the graph's absent or self value. Weight returns true if an edge
|
||||
// exists between x and y or if x and y have the same ID, false otherwise.
|
||||
func (g *UndirectedMatrix) Weight(xid, yid int64) (w float64, ok bool) {
|
||||
if xid == yid {
|
||||
return g.self, true
|
||||
}
|
||||
if g.HasEdgeBetween(xid, yid) {
|
||||
// xid and yid are not greater than maximum int by this point.
|
||||
return g.mat.At(int(xid), int(yid)), true
|
||||
}
|
||||
return g.absent, false
|
||||
}
|
||||
|
||||
// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
func (g *UndirectedMatrix) WeightedEdge(uid, vid int64) graph.WeightedEdge {
|
||||
return g.WeightedEdgeBetween(uid, vid)
|
||||
}
|
||||
|
||||
// WeightedEdgeBetween returns the weighted edge between nodes x and y.
|
||||
func (g *UndirectedMatrix) WeightedEdgeBetween(uid, vid int64) graph.WeightedEdge {
|
||||
if g.HasEdgeBetween(uid, vid) {
|
||||
// uid and vid are not greater than maximum int by this point.
|
||||
return WeightedEdge{F: g.Node(uid), T: g.Node(vid), W: g.mat.At(int(uid), int(vid))}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WeightedEdges returns all the edges in the graph.
|
||||
func (g *UndirectedMatrix) WeightedEdges() graph.WeightedEdges {
|
||||
var edges []graph.WeightedEdge
|
||||
r, _ := g.mat.Dims()
|
||||
for i := 0; i < r; i++ {
|
||||
for j := i + 1; j < r; j++ {
|
||||
if w := g.mat.At(i, j); !isSame(w, g.absent) {
|
||||
edges = append(edges, WeightedEdge{F: g.Node(int64(i)), T: g.Node(int64(j)), W: w})
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(edges) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedWeightedEdges(edges)
|
||||
}
|
||||
|
||||
func (g *UndirectedMatrix) has(id int64) bool {
|
||||
r := g.mat.Symmetric()
|
||||
return 0 <= id && id < int64(r)
|
||||
}
|
235
vendor/gonum.org/v1/gonum/graph/simple/directed.go
generated
vendored
Normal file
235
vendor/gonum.org/v1/gonum/graph/simple/directed.go
generated
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simple
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/internal/uid"
|
||||
"gonum.org/v1/gonum/graph/iterator"
|
||||
)
|
||||
|
||||
var (
|
||||
dg *DirectedGraph
|
||||
|
||||
_ graph.Graph = dg
|
||||
_ graph.Directed = dg
|
||||
_ graph.NodeAdder = dg
|
||||
_ graph.NodeRemover = dg
|
||||
_ graph.EdgeAdder = dg
|
||||
_ graph.EdgeRemover = dg
|
||||
)
|
||||
|
||||
// DirectedGraph implements a generalized directed graph.
|
||||
type DirectedGraph struct {
|
||||
nodes map[int64]graph.Node
|
||||
from map[int64]map[int64]graph.Edge
|
||||
to map[int64]map[int64]graph.Edge
|
||||
|
||||
nodeIDs uid.Set
|
||||
}
|
||||
|
||||
// NewDirectedGraph returns a DirectedGraph.
|
||||
func NewDirectedGraph() *DirectedGraph {
|
||||
return &DirectedGraph{
|
||||
nodes: make(map[int64]graph.Node),
|
||||
from: make(map[int64]map[int64]graph.Edge),
|
||||
to: make(map[int64]map[int64]graph.Edge),
|
||||
|
||||
nodeIDs: uid.NewSet(),
|
||||
}
|
||||
}
|
||||
|
||||
// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID.
|
||||
func (g *DirectedGraph) AddNode(n graph.Node) {
|
||||
if _, exists := g.nodes[n.ID()]; exists {
|
||||
panic(fmt.Sprintf("simple: node ID collision: %d", n.ID()))
|
||||
}
|
||||
g.nodes[n.ID()] = n
|
||||
g.from[n.ID()] = make(map[int64]graph.Edge)
|
||||
g.to[n.ID()] = make(map[int64]graph.Edge)
|
||||
g.nodeIDs.Use(n.ID())
|
||||
}
|
||||
|
||||
// Edge returns the edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
func (g *DirectedGraph) Edge(uid, vid int64) graph.Edge {
|
||||
edge, ok := g.from[uid][vid]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return edge
|
||||
}
|
||||
|
||||
// Edges returns all the edges in the graph.
|
||||
func (g *DirectedGraph) Edges() graph.Edges {
|
||||
var edges []graph.Edge
|
||||
for _, u := range g.nodes {
|
||||
for _, e := range g.from[u.ID()] {
|
||||
edges = append(edges, e)
|
||||
}
|
||||
}
|
||||
if len(edges) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedEdges(edges)
|
||||
}
|
||||
|
||||
// From returns all nodes in g that can be reached directly from n.
|
||||
func (g *DirectedGraph) From(id int64) graph.Nodes {
|
||||
if _, ok := g.from[id]; !ok {
|
||||
return graph.Empty
|
||||
}
|
||||
|
||||
from := make([]graph.Node, len(g.from[id]))
|
||||
i := 0
|
||||
for vid := range g.from[id] {
|
||||
from[i] = g.nodes[vid]
|
||||
i++
|
||||
}
|
||||
if len(from) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedNodes(from)
|
||||
}
|
||||
|
||||
// HasEdgeBetween returns whether an edge exists between nodes x and y without
|
||||
// considering direction.
|
||||
func (g *DirectedGraph) HasEdgeBetween(xid, yid int64) bool {
|
||||
if _, ok := g.from[xid][yid]; ok {
|
||||
return true
|
||||
}
|
||||
_, ok := g.from[yid][xid]
|
||||
return ok
|
||||
}
|
||||
|
||||
// HasEdgeFromTo returns whether an edge exists in the graph from u to v.
|
||||
func (g *DirectedGraph) HasEdgeFromTo(uid, vid int64) bool {
|
||||
if _, ok := g.from[uid][vid]; !ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// NewEdge returns a new Edge from the source to the destination node.
|
||||
func (g *DirectedGraph) NewEdge(from, to graph.Node) graph.Edge {
|
||||
return &Edge{F: from, T: to}
|
||||
}
|
||||
|
||||
// NewNode returns a new unique Node to be added to g. The Node's ID does
|
||||
// not become valid in g until the Node is added to g.
|
||||
func (g *DirectedGraph) NewNode() graph.Node {
|
||||
if len(g.nodes) == 0 {
|
||||
return Node(0)
|
||||
}
|
||||
if int64(len(g.nodes)) == uid.Max {
|
||||
panic("simple: cannot allocate node: no slot")
|
||||
}
|
||||
return Node(g.nodeIDs.NewID())
|
||||
}
|
||||
|
||||
// Node returns the node with the given ID if it exists in the graph,
|
||||
// and nil otherwise.
|
||||
func (g *DirectedGraph) Node(id int64) graph.Node {
|
||||
return g.nodes[id]
|
||||
}
|
||||
|
||||
// Nodes returns all the nodes in the graph.
|
||||
func (g *DirectedGraph) Nodes() graph.Nodes {
|
||||
if len(g.nodes) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
nodes := make([]graph.Node, len(g.nodes))
|
||||
i := 0
|
||||
for _, n := range g.nodes {
|
||||
nodes[i] = n
|
||||
i++
|
||||
}
|
||||
return iterator.NewOrderedNodes(nodes)
|
||||
}
|
||||
|
||||
// RemoveEdge removes the edge with the given end point IDs from the graph, leaving the terminal
|
||||
// nodes. If the edge does not exist it is a no-op.
|
||||
func (g *DirectedGraph) RemoveEdge(fid, tid int64) {
|
||||
if _, ok := g.nodes[fid]; !ok {
|
||||
return
|
||||
}
|
||||
if _, ok := g.nodes[tid]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
delete(g.from[fid], tid)
|
||||
delete(g.to[tid], fid)
|
||||
}
|
||||
|
||||
// RemoveNode removes the node with the given ID from the graph, as well as any edges attached
|
||||
// to it. If the node is not in the graph it is a no-op.
|
||||
func (g *DirectedGraph) RemoveNode(id int64) {
|
||||
if _, ok := g.nodes[id]; !ok {
|
||||
return
|
||||
}
|
||||
delete(g.nodes, id)
|
||||
|
||||
for from := range g.from[id] {
|
||||
delete(g.to[from], id)
|
||||
}
|
||||
delete(g.from, id)
|
||||
|
||||
for to := range g.to[id] {
|
||||
delete(g.from[to], id)
|
||||
}
|
||||
delete(g.to, id)
|
||||
|
||||
g.nodeIDs.Release(id)
|
||||
}
|
||||
|
||||
// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added
|
||||
// and are set to the nodes of the edge otherwise.
|
||||
// It will panic if the IDs of the e.From and e.To are equal.
|
||||
func (g *DirectedGraph) SetEdge(e graph.Edge) {
|
||||
var (
|
||||
from = e.From()
|
||||
fid = from.ID()
|
||||
to = e.To()
|
||||
tid = to.ID()
|
||||
)
|
||||
|
||||
if fid == tid {
|
||||
panic("simple: adding self edge")
|
||||
}
|
||||
|
||||
if _, ok := g.nodes[fid]; !ok {
|
||||
g.AddNode(from)
|
||||
} else {
|
||||
g.nodes[fid] = from
|
||||
}
|
||||
if _, ok := g.nodes[tid]; !ok {
|
||||
g.AddNode(to)
|
||||
} else {
|
||||
g.nodes[tid] = to
|
||||
}
|
||||
|
||||
g.from[fid][tid] = e
|
||||
g.to[tid][fid] = e
|
||||
}
|
||||
|
||||
// To returns all nodes in g that can reach directly to n.
|
||||
func (g *DirectedGraph) To(id int64) graph.Nodes {
|
||||
if _, ok := g.from[id]; !ok {
|
||||
return graph.Empty
|
||||
}
|
||||
|
||||
to := make([]graph.Node, len(g.to[id]))
|
||||
i := 0
|
||||
for uid := range g.to[id] {
|
||||
to[i] = g.nodes[uid]
|
||||
i++
|
||||
}
|
||||
if len(to) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedNodes(to)
|
||||
}
|
9
vendor/gonum.org/v1/gonum/graph/simple/doc.go
generated
vendored
Normal file
9
vendor/gonum.org/v1/gonum/graph/simple/doc.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright ©2017 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package simple provides a suite of simple graph implementations satisfying
|
||||
// the gonum/graph interfaces.
|
||||
//
|
||||
// All types in simple return the graph.Empty value for empty iterators.
|
||||
package simple // import "gonum.org/v1/gonum/graph/simple"
|
72
vendor/gonum.org/v1/gonum/graph/simple/simple.go
generated
vendored
Normal file
72
vendor/gonum.org/v1/gonum/graph/simple/simple.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simple
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"gonum.org/v1/gonum/graph"
|
||||
)
|
||||
|
||||
// Node is a simple graph node.
|
||||
type Node int64
|
||||
|
||||
// ID returns the ID number of the node.
|
||||
func (n Node) ID() int64 {
|
||||
return int64(n)
|
||||
}
|
||||
|
||||
func newSimpleNode(id int) graph.Node {
|
||||
return Node(id)
|
||||
}
|
||||
|
||||
// Edge is a simple graph edge.
|
||||
type Edge struct {
|
||||
F, T graph.Node
|
||||
}
|
||||
|
||||
// From returns the from-node of the edge.
|
||||
func (e Edge) From() graph.Node { return e.F }
|
||||
|
||||
// To returns the to-node of the edge.
|
||||
func (e Edge) To() graph.Node { return e.T }
|
||||
|
||||
// ReversedLine returns a new Edge with the F and T fields
|
||||
// swapped.
|
||||
func (e Edge) ReversedEdge() graph.Edge { return Edge{F: e.T, T: e.F} }
|
||||
|
||||
// WeightedEdge is a simple weighted graph edge.
|
||||
type WeightedEdge struct {
|
||||
F, T graph.Node
|
||||
W float64
|
||||
}
|
||||
|
||||
// From returns the from-node of the edge.
|
||||
func (e WeightedEdge) From() graph.Node { return e.F }
|
||||
|
||||
// To returns the to-node of the edge.
|
||||
func (e WeightedEdge) To() graph.Node { return e.T }
|
||||
|
||||
// ReversedLine returns a new Edge with the F and T fields
|
||||
// swapped. The weight of the new Edge is the same as
|
||||
// the weight of the receiver.
|
||||
func (e WeightedEdge) ReversedEdge() graph.Edge { return WeightedEdge{F: e.T, T: e.F, W: e.W} }
|
||||
|
||||
// Weight returns the weight of the edge.
|
||||
func (e WeightedEdge) Weight() float64 { return e.W }
|
||||
|
||||
// isSame returns whether two float64 values are the same where NaN values
|
||||
// are equalable.
|
||||
func isSame(a, b float64) bool {
|
||||
return a == b || (math.IsNaN(a) && math.IsNaN(b))
|
||||
}
|
||||
|
||||
type edgeSetter interface {
|
||||
SetEdge(e graph.Edge)
|
||||
}
|
||||
|
||||
type weightedEdgeSetter interface {
|
||||
SetWeightedEdge(e graph.WeightedEdge)
|
||||
}
|
216
vendor/gonum.org/v1/gonum/graph/simple/undirected.go
generated
vendored
Normal file
216
vendor/gonum.org/v1/gonum/graph/simple/undirected.go
generated
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simple
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/internal/uid"
|
||||
"gonum.org/v1/gonum/graph/iterator"
|
||||
)
|
||||
|
||||
var (
|
||||
ug *UndirectedGraph
|
||||
|
||||
_ graph.Graph = ug
|
||||
_ graph.Undirected = ug
|
||||
_ graph.NodeAdder = ug
|
||||
_ graph.NodeRemover = ug
|
||||
_ graph.EdgeAdder = ug
|
||||
_ graph.EdgeRemover = ug
|
||||
)
|
||||
|
||||
// UndirectedGraph implements a generalized undirected graph.
|
||||
type UndirectedGraph struct {
|
||||
nodes map[int64]graph.Node
|
||||
edges map[int64]map[int64]graph.Edge
|
||||
|
||||
nodeIDs uid.Set
|
||||
}
|
||||
|
||||
// NewUndirectedGraph returns an UndirectedGraph.
|
||||
func NewUndirectedGraph() *UndirectedGraph {
|
||||
return &UndirectedGraph{
|
||||
nodes: make(map[int64]graph.Node),
|
||||
edges: make(map[int64]map[int64]graph.Edge),
|
||||
|
||||
nodeIDs: uid.NewSet(),
|
||||
}
|
||||
}
|
||||
|
||||
// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID.
|
||||
func (g *UndirectedGraph) AddNode(n graph.Node) {
|
||||
if _, exists := g.nodes[n.ID()]; exists {
|
||||
panic(fmt.Sprintf("simple: node ID collision: %d", n.ID()))
|
||||
}
|
||||
g.nodes[n.ID()] = n
|
||||
g.edges[n.ID()] = make(map[int64]graph.Edge)
|
||||
g.nodeIDs.Use(n.ID())
|
||||
}
|
||||
|
||||
// Edge returns the edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
func (g *UndirectedGraph) Edge(uid, vid int64) graph.Edge {
|
||||
return g.EdgeBetween(uid, vid)
|
||||
}
|
||||
|
||||
// EdgeBetween returns the edge between nodes x and y.
|
||||
func (g *UndirectedGraph) EdgeBetween(xid, yid int64) graph.Edge {
|
||||
edge, ok := g.edges[xid][yid]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if edge.From().ID() == xid {
|
||||
return edge
|
||||
}
|
||||
return edge.ReversedEdge()
|
||||
}
|
||||
|
||||
// Edges returns all the edges in the graph.
|
||||
func (g *UndirectedGraph) Edges() graph.Edges {
|
||||
if len(g.edges) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
var edges []graph.Edge
|
||||
seen := make(map[[2]int64]struct{})
|
||||
for _, u := range g.edges {
|
||||
for _, e := range u {
|
||||
uid := e.From().ID()
|
||||
vid := e.To().ID()
|
||||
if _, ok := seen[[2]int64{uid, vid}]; ok {
|
||||
continue
|
||||
}
|
||||
seen[[2]int64{uid, vid}] = struct{}{}
|
||||
seen[[2]int64{vid, uid}] = struct{}{}
|
||||
edges = append(edges, e)
|
||||
}
|
||||
}
|
||||
if len(edges) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedEdges(edges)
|
||||
}
|
||||
|
||||
// From returns all nodes in g that can be reached directly from n.
|
||||
func (g *UndirectedGraph) From(id int64) graph.Nodes {
|
||||
if _, ok := g.nodes[id]; !ok {
|
||||
return graph.Empty
|
||||
}
|
||||
|
||||
nodes := make([]graph.Node, len(g.edges[id]))
|
||||
i := 0
|
||||
for from := range g.edges[id] {
|
||||
nodes[i] = g.nodes[from]
|
||||
i++
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedNodes(nodes)
|
||||
}
|
||||
|
||||
// HasEdgeBetween returns whether an edge exists between nodes x and y.
|
||||
func (g *UndirectedGraph) HasEdgeBetween(xid, yid int64) bool {
|
||||
_, ok := g.edges[xid][yid]
|
||||
return ok
|
||||
}
|
||||
|
||||
// NewEdge returns a new Edge from the source to the destination node.
|
||||
func (g *UndirectedGraph) NewEdge(from, to graph.Node) graph.Edge {
|
||||
return &Edge{F: from, T: to}
|
||||
}
|
||||
|
||||
// NewNode returns a new unique Node to be added to g. The Node's ID does
|
||||
// not become valid in g until the Node is added to g.
|
||||
func (g *UndirectedGraph) NewNode() graph.Node {
|
||||
if len(g.nodes) == 0 {
|
||||
return Node(0)
|
||||
}
|
||||
if int64(len(g.nodes)) == uid.Max {
|
||||
panic("simple: cannot allocate node: no slot")
|
||||
}
|
||||
return Node(g.nodeIDs.NewID())
|
||||
}
|
||||
|
||||
// Node returns the node with the given ID if it exists in the graph,
|
||||
// and nil otherwise.
|
||||
func (g *UndirectedGraph) Node(id int64) graph.Node {
|
||||
return g.nodes[id]
|
||||
}
|
||||
|
||||
// Nodes returns all the nodes in the graph.
|
||||
func (g *UndirectedGraph) Nodes() graph.Nodes {
|
||||
if len(g.nodes) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
nodes := make([]graph.Node, len(g.nodes))
|
||||
i := 0
|
||||
for _, n := range g.nodes {
|
||||
nodes[i] = n
|
||||
i++
|
||||
}
|
||||
return iterator.NewOrderedNodes(nodes)
|
||||
}
|
||||
|
||||
// RemoveEdge removes the edge with the given end IDs from the graph, leaving the terminal nodes.
|
||||
// If the edge does not exist it is a no-op.
|
||||
func (g *UndirectedGraph) RemoveEdge(fid, tid int64) {
|
||||
if _, ok := g.nodes[fid]; !ok {
|
||||
return
|
||||
}
|
||||
if _, ok := g.nodes[tid]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
delete(g.edges[fid], tid)
|
||||
delete(g.edges[tid], fid)
|
||||
}
|
||||
|
||||
// RemoveNode removes the node with the given ID from the graph, as well as any edges attached
|
||||
// to it. If the node is not in the graph it is a no-op.
|
||||
func (g *UndirectedGraph) RemoveNode(id int64) {
|
||||
if _, ok := g.nodes[id]; !ok {
|
||||
return
|
||||
}
|
||||
delete(g.nodes, id)
|
||||
|
||||
for from := range g.edges[id] {
|
||||
delete(g.edges[from], id)
|
||||
}
|
||||
delete(g.edges, id)
|
||||
|
||||
g.nodeIDs.Release(id)
|
||||
}
|
||||
|
||||
// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added
|
||||
// and are set to the nodes of the edge otherwise.
|
||||
// It will panic if the IDs of the e.From and e.To are equal.
|
||||
func (g *UndirectedGraph) SetEdge(e graph.Edge) {
|
||||
var (
|
||||
from = e.From()
|
||||
fid = from.ID()
|
||||
to = e.To()
|
||||
tid = to.ID()
|
||||
)
|
||||
|
||||
if fid == tid {
|
||||
panic("simple: adding self edge")
|
||||
}
|
||||
|
||||
if _, ok := g.nodes[fid]; !ok {
|
||||
g.AddNode(from)
|
||||
} else {
|
||||
g.nodes[fid] = from
|
||||
}
|
||||
if _, ok := g.nodes[tid]; !ok {
|
||||
g.AddNode(to)
|
||||
} else {
|
||||
g.nodes[tid] = to
|
||||
}
|
||||
|
||||
g.edges[fid][tid] = e
|
||||
g.edges[tid][fid] = e
|
||||
}
|
279
vendor/gonum.org/v1/gonum/graph/simple/weighted_directed.go
generated
vendored
Normal file
279
vendor/gonum.org/v1/gonum/graph/simple/weighted_directed.go
generated
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simple
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/internal/uid"
|
||||
"gonum.org/v1/gonum/graph/iterator"
|
||||
)
|
||||
|
||||
var (
|
||||
wdg *WeightedDirectedGraph
|
||||
|
||||
_ graph.Graph = wdg
|
||||
_ graph.Weighted = wdg
|
||||
_ graph.Directed = wdg
|
||||
_ graph.WeightedDirected = wdg
|
||||
_ graph.NodeAdder = wdg
|
||||
_ graph.NodeRemover = wdg
|
||||
_ graph.WeightedEdgeAdder = wdg
|
||||
_ graph.EdgeRemover = wdg
|
||||
)
|
||||
|
||||
// WeightedDirectedGraph implements a generalized weighted directed graph.
|
||||
type WeightedDirectedGraph struct {
|
||||
nodes map[int64]graph.Node
|
||||
from map[int64]map[int64]graph.WeightedEdge
|
||||
to map[int64]map[int64]graph.WeightedEdge
|
||||
|
||||
self, absent float64
|
||||
|
||||
nodeIDs uid.Set
|
||||
}
|
||||
|
||||
// NewWeightedDirectedGraph returns a WeightedDirectedGraph with the specified self and absent
|
||||
// edge weight values.
|
||||
func NewWeightedDirectedGraph(self, absent float64) *WeightedDirectedGraph {
|
||||
return &WeightedDirectedGraph{
|
||||
nodes: make(map[int64]graph.Node),
|
||||
from: make(map[int64]map[int64]graph.WeightedEdge),
|
||||
to: make(map[int64]map[int64]graph.WeightedEdge),
|
||||
|
||||
self: self,
|
||||
absent: absent,
|
||||
|
||||
nodeIDs: uid.NewSet(),
|
||||
}
|
||||
}
|
||||
|
||||
// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID.
|
||||
func (g *WeightedDirectedGraph) AddNode(n graph.Node) {
|
||||
if _, exists := g.nodes[n.ID()]; exists {
|
||||
panic(fmt.Sprintf("simple: node ID collision: %d", n.ID()))
|
||||
}
|
||||
g.nodes[n.ID()] = n
|
||||
g.from[n.ID()] = make(map[int64]graph.WeightedEdge)
|
||||
g.to[n.ID()] = make(map[int64]graph.WeightedEdge)
|
||||
g.nodeIDs.Use(n.ID())
|
||||
}
|
||||
|
||||
// Edge returns the edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
func (g *WeightedDirectedGraph) Edge(uid, vid int64) graph.Edge {
|
||||
return g.WeightedEdge(uid, vid)
|
||||
}
|
||||
|
||||
// Edges returns all the edges in the graph.
|
||||
func (g *WeightedDirectedGraph) Edges() graph.Edges {
|
||||
var edges []graph.Edge
|
||||
for _, u := range g.nodes {
|
||||
for _, e := range g.from[u.ID()] {
|
||||
edges = append(edges, e)
|
||||
}
|
||||
}
|
||||
if len(edges) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedEdges(edges)
|
||||
}
|
||||
|
||||
// From returns all nodes in g that can be reached directly from n.
|
||||
func (g *WeightedDirectedGraph) From(id int64) graph.Nodes {
|
||||
if _, ok := g.from[id]; !ok {
|
||||
return graph.Empty
|
||||
}
|
||||
|
||||
from := make([]graph.Node, len(g.from[id]))
|
||||
i := 0
|
||||
for vid := range g.from[id] {
|
||||
from[i] = g.nodes[vid]
|
||||
i++
|
||||
}
|
||||
if len(from) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedNodes(from)
|
||||
}
|
||||
|
||||
// HasEdgeBetween returns whether an edge exists between nodes x and y without
|
||||
// considering direction.
|
||||
func (g *WeightedDirectedGraph) HasEdgeBetween(xid, yid int64) bool {
|
||||
if _, ok := g.from[xid][yid]; ok {
|
||||
return true
|
||||
}
|
||||
_, ok := g.from[yid][xid]
|
||||
return ok
|
||||
}
|
||||
|
||||
// HasEdgeFromTo returns whether an edge exists in the graph from u to v.
|
||||
func (g *WeightedDirectedGraph) HasEdgeFromTo(uid, vid int64) bool {
|
||||
if _, ok := g.from[uid][vid]; !ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// NewNode returns a new unique Node to be added to g. The Node's ID does
|
||||
// not become valid in g until the Node is added to g.
|
||||
func (g *WeightedDirectedGraph) NewNode() graph.Node {
|
||||
if len(g.nodes) == 0 {
|
||||
return Node(0)
|
||||
}
|
||||
if int64(len(g.nodes)) == uid.Max {
|
||||
panic("simple: cannot allocate node: no slot")
|
||||
}
|
||||
return Node(g.nodeIDs.NewID())
|
||||
}
|
||||
|
||||
// NewWeightedEdge returns a new weighted edge from the source to the destination node.
|
||||
func (g *WeightedDirectedGraph) NewWeightedEdge(from, to graph.Node, weight float64) graph.WeightedEdge {
|
||||
return &WeightedEdge{F: from, T: to, W: weight}
|
||||
}
|
||||
|
||||
// Node returns the node with the given ID if it exists in the graph,
|
||||
// and nil otherwise.
|
||||
func (g *WeightedDirectedGraph) Node(id int64) graph.Node {
|
||||
return g.nodes[id]
|
||||
}
|
||||
|
||||
// Nodes returns all the nodes in the graph.
|
||||
func (g *WeightedDirectedGraph) Nodes() graph.Nodes {
|
||||
if len(g.from) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
nodes := make([]graph.Node, len(g.nodes))
|
||||
i := 0
|
||||
for _, n := range g.nodes {
|
||||
nodes[i] = n
|
||||
i++
|
||||
}
|
||||
return iterator.NewOrderedNodes(nodes)
|
||||
}
|
||||
|
||||
// RemoveEdge removes the edge with the given end point IDs from the graph, leaving the terminal
|
||||
// nodes. If the edge does not exist it is a no-op.
|
||||
func (g *WeightedDirectedGraph) RemoveEdge(fid, tid int64) {
|
||||
if _, ok := g.nodes[fid]; !ok {
|
||||
return
|
||||
}
|
||||
if _, ok := g.nodes[tid]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
delete(g.from[fid], tid)
|
||||
delete(g.to[tid], fid)
|
||||
}
|
||||
|
||||
// RemoveNode removes the node with the given ID from the graph, as well as any edges attached
|
||||
// to it. If the node is not in the graph it is a no-op.
|
||||
func (g *WeightedDirectedGraph) RemoveNode(id int64) {
|
||||
if _, ok := g.nodes[id]; !ok {
|
||||
return
|
||||
}
|
||||
delete(g.nodes, id)
|
||||
|
||||
for from := range g.from[id] {
|
||||
delete(g.to[from], id)
|
||||
}
|
||||
delete(g.from, id)
|
||||
|
||||
for to := range g.to[id] {
|
||||
delete(g.from[to], id)
|
||||
}
|
||||
delete(g.to, id)
|
||||
|
||||
g.nodeIDs.Release(id)
|
||||
}
|
||||
|
||||
// SetWeightedEdge adds a weighted edge from one node to another. If the nodes do not exist, they are added
|
||||
// and are set to the nodes of the edge otherwise.
|
||||
// It will panic if the IDs of the e.From and e.To are equal.
|
||||
func (g *WeightedDirectedGraph) SetWeightedEdge(e graph.WeightedEdge) {
|
||||
var (
|
||||
from = e.From()
|
||||
fid = from.ID()
|
||||
to = e.To()
|
||||
tid = to.ID()
|
||||
)
|
||||
|
||||
if fid == tid {
|
||||
panic("simple: adding self edge")
|
||||
}
|
||||
|
||||
if _, ok := g.nodes[fid]; !ok {
|
||||
g.AddNode(from)
|
||||
} else {
|
||||
g.nodes[fid] = from
|
||||
}
|
||||
if _, ok := g.nodes[tid]; !ok {
|
||||
g.AddNode(to)
|
||||
} else {
|
||||
g.nodes[tid] = to
|
||||
}
|
||||
|
||||
g.from[fid][tid] = e
|
||||
g.to[tid][fid] = e
|
||||
}
|
||||
|
||||
// To returns all nodes in g that can reach directly to n.
|
||||
func (g *WeightedDirectedGraph) To(id int64) graph.Nodes {
|
||||
if _, ok := g.from[id]; !ok {
|
||||
return graph.Empty
|
||||
}
|
||||
|
||||
to := make([]graph.Node, len(g.to[id]))
|
||||
i := 0
|
||||
for uid := range g.to[id] {
|
||||
to[i] = g.nodes[uid]
|
||||
i++
|
||||
}
|
||||
if len(to) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedNodes(to)
|
||||
}
|
||||
|
||||
// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge.
|
||||
// If x and y are the same node or there is no joining edge between the two nodes the weight
|
||||
// value returned is either the graph's absent or self value. Weight returns true if an edge
|
||||
// exists between x and y or if x and y have the same ID, false otherwise.
|
||||
func (g *WeightedDirectedGraph) Weight(xid, yid int64) (w float64, ok bool) {
|
||||
if xid == yid {
|
||||
return g.self, true
|
||||
}
|
||||
if to, ok := g.from[xid]; ok {
|
||||
if e, ok := to[yid]; ok {
|
||||
return e.Weight(), true
|
||||
}
|
||||
}
|
||||
return g.absent, false
|
||||
}
|
||||
|
||||
// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
func (g *WeightedDirectedGraph) WeightedEdge(uid, vid int64) graph.WeightedEdge {
|
||||
edge, ok := g.from[uid][vid]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return edge
|
||||
}
|
||||
|
||||
// WeightedEdges returns all the weighted edges in the graph.
|
||||
func (g *WeightedDirectedGraph) WeightedEdges() graph.WeightedEdges {
|
||||
var edges []graph.WeightedEdge
|
||||
for _, u := range g.nodes {
|
||||
for _, e := range g.from[u.ID()] {
|
||||
edges = append(edges, e)
|
||||
}
|
||||
}
|
||||
if len(edges) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedWeightedEdges(edges)
|
||||
}
|
273
vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected.go
generated
vendored
Normal file
273
vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected.go
generated
vendored
Normal file
@@ -0,0 +1,273 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simple
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/internal/uid"
|
||||
"gonum.org/v1/gonum/graph/iterator"
|
||||
)
|
||||
|
||||
var (
|
||||
wug *WeightedUndirectedGraph
|
||||
|
||||
_ graph.Graph = wug
|
||||
_ graph.Weighted = wug
|
||||
_ graph.Undirected = wug
|
||||
_ graph.WeightedUndirected = wug
|
||||
_ graph.NodeAdder = wug
|
||||
_ graph.NodeRemover = wug
|
||||
_ graph.WeightedEdgeAdder = wug
|
||||
_ graph.EdgeRemover = wug
|
||||
)
|
||||
|
||||
// WeightedUndirectedGraph implements a generalized weighted undirected graph.
|
||||
type WeightedUndirectedGraph struct {
|
||||
nodes map[int64]graph.Node
|
||||
edges map[int64]map[int64]graph.WeightedEdge
|
||||
|
||||
self, absent float64
|
||||
|
||||
nodeIDs uid.Set
|
||||
}
|
||||
|
||||
// NewWeightedUndirectedGraph returns an WeightedUndirectedGraph with the specified self and absent
|
||||
// edge weight values.
|
||||
func NewWeightedUndirectedGraph(self, absent float64) *WeightedUndirectedGraph {
|
||||
return &WeightedUndirectedGraph{
|
||||
nodes: make(map[int64]graph.Node),
|
||||
edges: make(map[int64]map[int64]graph.WeightedEdge),
|
||||
|
||||
self: self,
|
||||
absent: absent,
|
||||
|
||||
nodeIDs: uid.NewSet(),
|
||||
}
|
||||
}
|
||||
|
||||
// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID.
|
||||
func (g *WeightedUndirectedGraph) AddNode(n graph.Node) {
|
||||
if _, exists := g.nodes[n.ID()]; exists {
|
||||
panic(fmt.Sprintf("simple: node ID collision: %d", n.ID()))
|
||||
}
|
||||
g.nodes[n.ID()] = n
|
||||
g.edges[n.ID()] = make(map[int64]graph.WeightedEdge)
|
||||
g.nodeIDs.Use(n.ID())
|
||||
}
|
||||
|
||||
// Edge returns the edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
func (g *WeightedUndirectedGraph) Edge(uid, vid int64) graph.Edge {
|
||||
return g.WeightedEdgeBetween(uid, vid)
|
||||
}
|
||||
|
||||
// EdgeBetween returns the edge between nodes x and y.
|
||||
func (g *WeightedUndirectedGraph) EdgeBetween(xid, yid int64) graph.Edge {
|
||||
return g.WeightedEdgeBetween(xid, yid)
|
||||
}
|
||||
|
||||
// Edges returns all the edges in the graph.
|
||||
func (g *WeightedUndirectedGraph) Edges() graph.Edges {
|
||||
if len(g.edges) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
var edges []graph.Edge
|
||||
seen := make(map[[2]int64]struct{})
|
||||
for _, u := range g.edges {
|
||||
for _, e := range u {
|
||||
uid := e.From().ID()
|
||||
vid := e.To().ID()
|
||||
if _, ok := seen[[2]int64{uid, vid}]; ok {
|
||||
continue
|
||||
}
|
||||
seen[[2]int64{uid, vid}] = struct{}{}
|
||||
seen[[2]int64{vid, uid}] = struct{}{}
|
||||
edges = append(edges, e)
|
||||
}
|
||||
}
|
||||
if len(edges) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedEdges(edges)
|
||||
}
|
||||
|
||||
// From returns all nodes in g that can be reached directly from n.
|
||||
func (g *WeightedUndirectedGraph) From(id int64) graph.Nodes {
|
||||
if _, ok := g.nodes[id]; !ok {
|
||||
return graph.Empty
|
||||
}
|
||||
|
||||
nodes := make([]graph.Node, len(g.edges[id]))
|
||||
i := 0
|
||||
for from := range g.edges[id] {
|
||||
nodes[i] = g.nodes[from]
|
||||
i++
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedNodes(nodes)
|
||||
}
|
||||
|
||||
// HasEdgeBetween returns whether an edge exists between nodes x and y.
|
||||
func (g *WeightedUndirectedGraph) HasEdgeBetween(xid, yid int64) bool {
|
||||
_, ok := g.edges[xid][yid]
|
||||
return ok
|
||||
}
|
||||
|
||||
// NewNode returns a new unique Node to be added to g. The Node's ID does
|
||||
// not become valid in g until the Node is added to g.
|
||||
func (g *WeightedUndirectedGraph) NewNode() graph.Node {
|
||||
if len(g.nodes) == 0 {
|
||||
return Node(0)
|
||||
}
|
||||
if int64(len(g.nodes)) == uid.Max {
|
||||
panic("simple: cannot allocate node: no slot")
|
||||
}
|
||||
return Node(g.nodeIDs.NewID())
|
||||
}
|
||||
|
||||
// NewWeightedEdge returns a new weighted edge from the source to the destination node.
|
||||
func (g *WeightedUndirectedGraph) NewWeightedEdge(from, to graph.Node, weight float64) graph.WeightedEdge {
|
||||
return &WeightedEdge{F: from, T: to, W: weight}
|
||||
}
|
||||
|
||||
// Node returns the node with the given ID if it exists in the graph,
|
||||
// and nil otherwise.
|
||||
func (g *WeightedUndirectedGraph) Node(id int64) graph.Node {
|
||||
return g.nodes[id]
|
||||
}
|
||||
|
||||
// Nodes returns all the nodes in the graph.
|
||||
func (g *WeightedUndirectedGraph) Nodes() graph.Nodes {
|
||||
if len(g.nodes) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
nodes := make([]graph.Node, len(g.nodes))
|
||||
i := 0
|
||||
for _, n := range g.nodes {
|
||||
nodes[i] = n
|
||||
i++
|
||||
}
|
||||
return iterator.NewOrderedNodes(nodes)
|
||||
}
|
||||
|
||||
// RemoveEdge removes the edge with the given end point IDs from the graph, leaving the terminal
|
||||
// nodes. If the edge does not exist it is a no-op.
|
||||
func (g *WeightedUndirectedGraph) RemoveEdge(fid, tid int64) {
|
||||
if _, ok := g.nodes[fid]; !ok {
|
||||
return
|
||||
}
|
||||
if _, ok := g.nodes[tid]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
delete(g.edges[fid], tid)
|
||||
delete(g.edges[tid], fid)
|
||||
}
|
||||
|
||||
// RemoveNode removes the node with the given ID from the graph, as well as any edges attached
|
||||
// to it. If the node is not in the graph it is a no-op.
|
||||
func (g *WeightedUndirectedGraph) RemoveNode(id int64) {
|
||||
if _, ok := g.nodes[id]; !ok {
|
||||
return
|
||||
}
|
||||
delete(g.nodes, id)
|
||||
|
||||
for from := range g.edges[id] {
|
||||
delete(g.edges[from], id)
|
||||
}
|
||||
delete(g.edges, id)
|
||||
|
||||
g.nodeIDs.Release(id)
|
||||
}
|
||||
|
||||
// SetWeightedEdge adds a weighted edge from one node to another. If the nodes do not exist, they are added
|
||||
// and are set to the nodes of the edge otherwise.
|
||||
// It will panic if the IDs of the e.From and e.To are equal.
|
||||
func (g *WeightedUndirectedGraph) SetWeightedEdge(e graph.WeightedEdge) {
|
||||
var (
|
||||
from = e.From()
|
||||
fid = from.ID()
|
||||
to = e.To()
|
||||
tid = to.ID()
|
||||
)
|
||||
|
||||
if fid == tid {
|
||||
panic("simple: adding self edge")
|
||||
}
|
||||
|
||||
if _, ok := g.nodes[fid]; !ok {
|
||||
g.AddNode(from)
|
||||
} else {
|
||||
g.nodes[fid] = from
|
||||
}
|
||||
if _, ok := g.nodes[tid]; !ok {
|
||||
g.AddNode(to)
|
||||
} else {
|
||||
g.nodes[tid] = to
|
||||
}
|
||||
|
||||
g.edges[fid][tid] = e
|
||||
g.edges[tid][fid] = e
|
||||
}
|
||||
|
||||
// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge.
|
||||
// If x and y are the same node or there is no joining edge between the two nodes the weight
|
||||
// value returned is either the graph's absent or self value. Weight returns true if an edge
|
||||
// exists between x and y or if x and y have the same ID, false otherwise.
|
||||
func (g *WeightedUndirectedGraph) Weight(xid, yid int64) (w float64, ok bool) {
|
||||
if xid == yid {
|
||||
return g.self, true
|
||||
}
|
||||
if n, ok := g.edges[xid]; ok {
|
||||
if e, ok := n[yid]; ok {
|
||||
return e.Weight(), true
|
||||
}
|
||||
}
|
||||
return g.absent, false
|
||||
}
|
||||
|
||||
// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
func (g *WeightedUndirectedGraph) WeightedEdge(uid, vid int64) graph.WeightedEdge {
|
||||
return g.WeightedEdgeBetween(uid, vid)
|
||||
}
|
||||
|
||||
// WeightedEdgeBetween returns the weighted edge between nodes x and y.
|
||||
func (g *WeightedUndirectedGraph) WeightedEdgeBetween(xid, yid int64) graph.WeightedEdge {
|
||||
edge, ok := g.edges[xid][yid]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if edge.From().ID() == xid {
|
||||
return edge
|
||||
}
|
||||
return edge.ReversedEdge().(graph.WeightedEdge)
|
||||
}
|
||||
|
||||
// WeightedEdges returns all the weighted edges in the graph.
|
||||
func (g *WeightedUndirectedGraph) WeightedEdges() graph.WeightedEdges {
|
||||
var edges []graph.WeightedEdge
|
||||
seen := make(map[[2]int64]struct{})
|
||||
for _, u := range g.edges {
|
||||
for _, e := range u {
|
||||
uid := e.From().ID()
|
||||
vid := e.To().ID()
|
||||
if _, ok := seen[[2]int64{uid, vid}]; ok {
|
||||
continue
|
||||
}
|
||||
seen[[2]int64{uid, vid}] = struct{}{}
|
||||
seen[[2]int64{vid, uid}] = struct{}{}
|
||||
edges = append(edges, e)
|
||||
}
|
||||
}
|
||||
if len(edges) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
return iterator.NewOrderedWeightedEdges(edges)
|
||||
}
|
250
vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch.go
generated
vendored
Normal file
250
vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch.go
generated
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
// Copyright ©2015 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package topo
|
||||
|
||||
import (
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/internal/ordered"
|
||||
"gonum.org/v1/gonum/graph/internal/set"
|
||||
)
|
||||
|
||||
// DegeneracyOrdering returns the degeneracy ordering and the k-cores of
|
||||
// the undirected graph g.
|
||||
func DegeneracyOrdering(g graph.Undirected) (order []graph.Node, cores [][]graph.Node) {
|
||||
order, offsets := degeneracyOrdering(g)
|
||||
|
||||
ordered.Reverse(order)
|
||||
cores = make([][]graph.Node, len(offsets))
|
||||
offset := len(order)
|
||||
for i, n := range offsets {
|
||||
cores[i] = order[offset-n : offset]
|
||||
offset -= n
|
||||
}
|
||||
return order, cores
|
||||
}
|
||||
|
||||
// KCore returns the k-core of the undirected graph g with nodes in an
|
||||
// optimal ordering for the coloring number.
|
||||
func KCore(k int, g graph.Undirected) []graph.Node {
|
||||
order, offsets := degeneracyOrdering(g)
|
||||
|
||||
var offset int
|
||||
for _, n := range offsets[:k] {
|
||||
offset += n
|
||||
}
|
||||
core := make([]graph.Node, len(order)-offset)
|
||||
copy(core, order[offset:])
|
||||
return core
|
||||
}
|
||||
|
||||
// degeneracyOrdering is the common code for DegeneracyOrdering and KCore. It
|
||||
// returns l, the nodes of g in optimal ordering for coloring number and
|
||||
// s, a set of relative offsets into l for each k-core, where k is an index
|
||||
// into s.
|
||||
func degeneracyOrdering(g graph.Undirected) (l []graph.Node, s []int) {
|
||||
nodes := graph.NodesOf(g.Nodes())
|
||||
|
||||
// The algorithm used here is essentially as described at
|
||||
// http://en.wikipedia.org/w/index.php?title=Degeneracy_%28graph_theory%29&oldid=640308710
|
||||
|
||||
// Initialize an output list L in return parameters.
|
||||
|
||||
// Compute a number d_v for each vertex v in G,
|
||||
// the number of neighbors of v that are not already in L.
|
||||
// Initially, these numbers are just the degrees of the vertices.
|
||||
dv := make(map[int64]int, len(nodes))
|
||||
var (
|
||||
maxDegree int
|
||||
neighbours = make(map[int64][]graph.Node)
|
||||
)
|
||||
for _, n := range nodes {
|
||||
id := n.ID()
|
||||
adj := graph.NodesOf(g.From(id))
|
||||
neighbours[id] = adj
|
||||
dv[id] = len(adj)
|
||||
if len(adj) > maxDegree {
|
||||
maxDegree = len(adj)
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize an array D such that D[i] contains a list of the
|
||||
// vertices v that are not already in L for which d_v = i.
|
||||
d := make([][]graph.Node, maxDegree+1)
|
||||
for _, n := range nodes {
|
||||
deg := dv[n.ID()]
|
||||
d[deg] = append(d[deg], n)
|
||||
}
|
||||
|
||||
// Initialize k to 0.
|
||||
k := 0
|
||||
// Repeat n times:
|
||||
s = []int{0}
|
||||
for range nodes {
|
||||
// Scan the array cells D[0], D[1], ... until
|
||||
// finding an i for which D[i] is nonempty.
|
||||
var (
|
||||
i int
|
||||
di []graph.Node
|
||||
)
|
||||
for i, di = range d {
|
||||
if len(di) != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Set k to max(k,i).
|
||||
if i > k {
|
||||
k = i
|
||||
s = append(s, make([]int, k-len(s)+1)...)
|
||||
}
|
||||
|
||||
// Select a vertex v from D[i]. Add v to the
|
||||
// beginning of L and remove it from D[i].
|
||||
var v graph.Node
|
||||
v, d[i] = di[len(di)-1], di[:len(di)-1]
|
||||
l = append(l, v)
|
||||
s[k]++
|
||||
delete(dv, v.ID())
|
||||
|
||||
// For each neighbor w of v not already in L,
|
||||
// subtract one from d_w and move w to the
|
||||
// cell of D corresponding to the new value of d_w.
|
||||
for _, w := range neighbours[v.ID()] {
|
||||
dw, ok := dv[w.ID()]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for i, n := range d[dw] {
|
||||
if n.ID() == w.ID() {
|
||||
d[dw][i], d[dw] = d[dw][len(d[dw])-1], d[dw][:len(d[dw])-1]
|
||||
dw--
|
||||
d[dw] = append(d[dw], w)
|
||||
break
|
||||
}
|
||||
}
|
||||
dv[w.ID()] = dw
|
||||
}
|
||||
}
|
||||
|
||||
return l, s
|
||||
}
|
||||
|
||||
// BronKerbosch returns the set of maximal cliques of the undirected graph g.
|
||||
func BronKerbosch(g graph.Undirected) [][]graph.Node {
|
||||
nodes := graph.NodesOf(g.Nodes())
|
||||
|
||||
// The algorithm used here is essentially BronKerbosch3 as described at
|
||||
// http://en.wikipedia.org/w/index.php?title=Bron%E2%80%93Kerbosch_algorithm&oldid=656805858
|
||||
|
||||
p := set.NewNodesSize(len(nodes))
|
||||
for _, n := range nodes {
|
||||
p.Add(n)
|
||||
}
|
||||
x := set.NewNodes()
|
||||
var bk bronKerbosch
|
||||
order, _ := degeneracyOrdering(g)
|
||||
ordered.Reverse(order)
|
||||
for _, v := range order {
|
||||
neighbours := graph.NodesOf(g.From(v.ID()))
|
||||
nv := set.NewNodesSize(len(neighbours))
|
||||
for _, n := range neighbours {
|
||||
nv.Add(n)
|
||||
}
|
||||
bk.maximalCliquePivot(g, []graph.Node{v}, set.IntersectionOfNodes(p, nv), set.IntersectionOfNodes(x, nv))
|
||||
p.Remove(v)
|
||||
x.Add(v)
|
||||
}
|
||||
return bk
|
||||
}
|
||||
|
||||
type bronKerbosch [][]graph.Node
|
||||
|
||||
func (bk *bronKerbosch) maximalCliquePivot(g graph.Undirected, r []graph.Node, p, x set.Nodes) {
|
||||
if len(p) == 0 && len(x) == 0 {
|
||||
*bk = append(*bk, r)
|
||||
return
|
||||
}
|
||||
|
||||
neighbours := bk.choosePivotFrom(g, p, x)
|
||||
nu := set.NewNodesSize(len(neighbours))
|
||||
for _, n := range neighbours {
|
||||
nu.Add(n)
|
||||
}
|
||||
for _, v := range p {
|
||||
if nu.Has(v) {
|
||||
continue
|
||||
}
|
||||
vid := v.ID()
|
||||
neighbours := graph.NodesOf(g.From(vid))
|
||||
nv := set.NewNodesSize(len(neighbours))
|
||||
for _, n := range neighbours {
|
||||
nv.Add(n)
|
||||
}
|
||||
|
||||
var found bool
|
||||
for _, n := range r {
|
||||
if n.ID() == vid {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
var sr []graph.Node
|
||||
if !found {
|
||||
sr = append(r[:len(r):len(r)], v)
|
||||
}
|
||||
|
||||
bk.maximalCliquePivot(g, sr, set.IntersectionOfNodes(p, nv), set.IntersectionOfNodes(x, nv))
|
||||
p.Remove(v)
|
||||
x.Add(v)
|
||||
}
|
||||
}
|
||||
|
||||
func (*bronKerbosch) choosePivotFrom(g graph.Undirected, p, x set.Nodes) (neighbors []graph.Node) {
|
||||
// TODO(kortschak): Investigate the impact of pivot choice that maximises
|
||||
// |p ⋂ neighbours(u)| as a function of input size. Until then, leave as
|
||||
// compile time option.
|
||||
if !tomitaTanakaTakahashi {
|
||||
for _, n := range p {
|
||||
return graph.NodesOf(g.From(n.ID()))
|
||||
}
|
||||
for _, n := range x {
|
||||
return graph.NodesOf(g.From(n.ID()))
|
||||
}
|
||||
panic("bronKerbosch: empty set")
|
||||
}
|
||||
|
||||
var (
|
||||
max = -1
|
||||
pivot graph.Node
|
||||
)
|
||||
maxNeighbors := func(s set.Nodes) {
|
||||
outer:
|
||||
for _, u := range s {
|
||||
nb := graph.NodesOf(g.From(u.ID()))
|
||||
c := len(nb)
|
||||
if c <= max {
|
||||
continue
|
||||
}
|
||||
for n := range nb {
|
||||
if _, ok := p[int64(n)]; ok {
|
||||
continue
|
||||
}
|
||||
c--
|
||||
if c <= max {
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
max = c
|
||||
pivot = u
|
||||
neighbors = nb
|
||||
}
|
||||
}
|
||||
maxNeighbors(p)
|
||||
maxNeighbors(x)
|
||||
if pivot == nil {
|
||||
panic("bronKerbosch: empty set")
|
||||
}
|
||||
return neighbors
|
||||
}
|
111
vendor/gonum.org/v1/gonum/graph/topo/clique_graph.go
generated
vendored
Normal file
111
vendor/gonum.org/v1/gonum/graph/topo/clique_graph.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright ©2017 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package topo
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/internal/ordered"
|
||||
"gonum.org/v1/gonum/graph/internal/set"
|
||||
)
|
||||
|
||||
// Builder is a pure topological graph construction type.
|
||||
type Builder interface {
|
||||
AddNode(graph.Node)
|
||||
SetEdge(graph.Edge)
|
||||
}
|
||||
|
||||
// CliqueGraph builds the clique graph of g in dst using Clique and CliqueGraphEdge
|
||||
// nodes and edges. The nodes returned by calls to Nodes on the nodes and edges of
|
||||
// the constructed graph are the cliques and the common nodes between cliques
|
||||
// respectively. The dst graph is not cleared.
|
||||
func CliqueGraph(dst Builder, g graph.Undirected) {
|
||||
cliques := BronKerbosch(g)
|
||||
|
||||
// Construct a consistent view of cliques in g. Sorting costs
|
||||
// us a little, but not as much as the cliques themselves.
|
||||
for _, c := range cliques {
|
||||
sort.Sort(ordered.ByID(c))
|
||||
}
|
||||
sort.Sort(ordered.BySliceIDs(cliques))
|
||||
|
||||
cliqueNodes := make(cliqueNodeSets, len(cliques))
|
||||
for id, c := range cliques {
|
||||
s := set.NewNodesSize(len(c))
|
||||
for _, n := range c {
|
||||
s.Add(n)
|
||||
}
|
||||
ns := &nodeSet{Clique: Clique{id: int64(id), nodes: c}, nodes: s}
|
||||
dst.AddNode(ns.Clique)
|
||||
for _, n := range c {
|
||||
nid := n.ID()
|
||||
cliqueNodes[nid] = append(cliqueNodes[nid], ns)
|
||||
}
|
||||
}
|
||||
|
||||
for _, cliques := range cliqueNodes {
|
||||
for i, uc := range cliques {
|
||||
for _, vc := range cliques[i+1:] {
|
||||
// Retain the nodes that contribute to the
|
||||
// edge between the cliques.
|
||||
var edgeNodes []graph.Node
|
||||
switch 1 {
|
||||
case len(uc.Clique.nodes):
|
||||
edgeNodes = []graph.Node{uc.Clique.nodes[0]}
|
||||
case len(vc.Clique.nodes):
|
||||
edgeNodes = []graph.Node{vc.Clique.nodes[0]}
|
||||
default:
|
||||
for _, n := range set.IntersectionOfNodes(uc.nodes, vc.nodes) {
|
||||
edgeNodes = append(edgeNodes, n)
|
||||
}
|
||||
sort.Sort(ordered.ByID(edgeNodes))
|
||||
}
|
||||
|
||||
dst.SetEdge(CliqueGraphEdge{from: uc.Clique, to: vc.Clique, nodes: edgeNodes})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type cliqueNodeSets map[int64][]*nodeSet
|
||||
|
||||
type nodeSet struct {
|
||||
Clique
|
||||
nodes set.Nodes
|
||||
}
|
||||
|
||||
// Clique is a node in a clique graph.
|
||||
type Clique struct {
|
||||
id int64
|
||||
nodes []graph.Node
|
||||
}
|
||||
|
||||
// ID returns the node ID.
|
||||
func (n Clique) ID() int64 { return n.id }
|
||||
|
||||
// Nodes returns the nodes in the clique.
|
||||
func (n Clique) Nodes() []graph.Node { return n.nodes }
|
||||
|
||||
// CliqueGraphEdge is an edge in a clique graph.
|
||||
type CliqueGraphEdge struct {
|
||||
from, to Clique
|
||||
nodes []graph.Node
|
||||
}
|
||||
|
||||
// From returns the from node of the edge.
|
||||
func (e CliqueGraphEdge) From() graph.Node { return e.from }
|
||||
|
||||
// To returns the to node of the edge.
|
||||
func (e CliqueGraphEdge) To() graph.Node { return e.to }
|
||||
|
||||
// ReversedEdge returns a new CliqueGraphEdge with
|
||||
// the edge end points swapped. The nodes of the
|
||||
// new edge are shared with the receiver.
|
||||
func (e CliqueGraphEdge) ReversedEdge() graph.Edge { e.from, e.to = e.to, e.from; return e }
|
||||
|
||||
// Nodes returns the common nodes in the cliques of the underlying graph
|
||||
// corresponding to the from and to nodes in the clique graph.
|
||||
func (e CliqueGraphEdge) Nodes() []graph.Node { return e.nodes }
|
6
vendor/gonum.org/v1/gonum/graph/topo/doc.go
generated
vendored
Normal file
6
vendor/gonum.org/v1/gonum/graph/topo/doc.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright ©2017 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package topo provides graph topology analysis functions.
|
||||
package topo // import "gonum.org/v1/gonum/graph/topo"
|
285
vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles.go
generated
vendored
Normal file
285
vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles.go
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
// Copyright ©2015 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package topo
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/internal/ordered"
|
||||
"gonum.org/v1/gonum/graph/internal/set"
|
||||
"gonum.org/v1/gonum/graph/iterator"
|
||||
)
|
||||
|
||||
// johnson implements Johnson's "Finding all the elementary
|
||||
// circuits of a directed graph" algorithm. SIAM J. Comput. 4(1):1975.
|
||||
//
|
||||
// Comments in the johnson methods are kept in sync with the comments
|
||||
// and labels from the paper.
|
||||
type johnson struct {
|
||||
adjacent johnsonGraph // SCC adjacency list.
|
||||
b []set.Ints // Johnson's "B-list".
|
||||
blocked []bool
|
||||
s int
|
||||
|
||||
stack []graph.Node
|
||||
|
||||
result [][]graph.Node
|
||||
}
|
||||
|
||||
// DirectedCyclesIn returns the set of elementary cycles in the graph g.
|
||||
func DirectedCyclesIn(g graph.Directed) [][]graph.Node {
|
||||
jg := johnsonGraphFrom(g)
|
||||
j := johnson{
|
||||
adjacent: jg,
|
||||
b: make([]set.Ints, len(jg.orig)),
|
||||
blocked: make([]bool, len(jg.orig)),
|
||||
}
|
||||
|
||||
// len(j.nodes) is the order of g.
|
||||
for j.s < len(j.adjacent.orig)-1 {
|
||||
// We use the previous SCC adjacency to reduce the work needed.
|
||||
sccs := TarjanSCC(j.adjacent.subgraph(j.s))
|
||||
// A_k = adjacency structure of strong component K with least
|
||||
// vertex in subgraph of G induced by {s, s+1, ... ,n}.
|
||||
j.adjacent = j.adjacent.sccSubGraph(sccs, 2) // Only allow SCCs with >= 2 vertices.
|
||||
if j.adjacent.order() == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
// s = least vertex in V_k
|
||||
if s := j.adjacent.leastVertexIndex(); s < j.s {
|
||||
j.s = s
|
||||
}
|
||||
for i, v := range j.adjacent.orig {
|
||||
if !j.adjacent.nodes.Has(v.ID()) {
|
||||
continue
|
||||
}
|
||||
if len(j.adjacent.succ[v.ID()]) > 0 {
|
||||
j.blocked[i] = false
|
||||
j.b[i] = make(set.Ints)
|
||||
}
|
||||
}
|
||||
//L3:
|
||||
_ = j.circuit(j.s)
|
||||
j.s++
|
||||
}
|
||||
|
||||
return j.result
|
||||
}
|
||||
|
||||
// circuit is the CIRCUIT sub-procedure in the paper.
|
||||
func (j *johnson) circuit(v int) bool {
|
||||
f := false
|
||||
n := j.adjacent.orig[v]
|
||||
j.stack = append(j.stack, n)
|
||||
j.blocked[v] = true
|
||||
|
||||
//L1:
|
||||
for w := range j.adjacent.succ[n.ID()] {
|
||||
w := j.adjacent.indexOf(w)
|
||||
if w == j.s {
|
||||
// Output circuit composed of stack followed by s.
|
||||
r := make([]graph.Node, len(j.stack)+1)
|
||||
copy(r, j.stack)
|
||||
r[len(r)-1] = j.adjacent.orig[j.s]
|
||||
j.result = append(j.result, r)
|
||||
f = true
|
||||
} else if !j.blocked[w] {
|
||||
if j.circuit(w) {
|
||||
f = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//L2:
|
||||
if f {
|
||||
j.unblock(v)
|
||||
} else {
|
||||
for w := range j.adjacent.succ[n.ID()] {
|
||||
j.b[j.adjacent.indexOf(w)].Add(v)
|
||||
}
|
||||
}
|
||||
j.stack = j.stack[:len(j.stack)-1]
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
// unblock is the UNBLOCK sub-procedure in the paper.
|
||||
func (j *johnson) unblock(u int) {
|
||||
j.blocked[u] = false
|
||||
for w := range j.b[u] {
|
||||
j.b[u].Remove(w)
|
||||
if j.blocked[w] {
|
||||
j.unblock(w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// johnsonGraph is an edge list representation of a graph with helpers
|
||||
// necessary for Johnson's algorithm
|
||||
type johnsonGraph struct {
|
||||
// Keep the original graph nodes and a
|
||||
// look-up to into the non-sparse
|
||||
// collection of potentially sparse IDs.
|
||||
orig []graph.Node
|
||||
index map[int64]int
|
||||
|
||||
nodes set.Int64s
|
||||
succ map[int64]set.Int64s
|
||||
}
|
||||
|
||||
// johnsonGraphFrom returns a deep copy of the graph g.
|
||||
func johnsonGraphFrom(g graph.Directed) johnsonGraph {
|
||||
nodes := graph.NodesOf(g.Nodes())
|
||||
sort.Sort(ordered.ByID(nodes))
|
||||
c := johnsonGraph{
|
||||
orig: nodes,
|
||||
index: make(map[int64]int, len(nodes)),
|
||||
|
||||
nodes: make(set.Int64s, len(nodes)),
|
||||
succ: make(map[int64]set.Int64s),
|
||||
}
|
||||
for i, u := range nodes {
|
||||
uid := u.ID()
|
||||
c.index[uid] = i
|
||||
for _, v := range graph.NodesOf(g.From(uid)) {
|
||||
if c.succ[uid] == nil {
|
||||
c.succ[uid] = make(set.Int64s)
|
||||
c.nodes.Add(uid)
|
||||
}
|
||||
c.nodes.Add(v.ID())
|
||||
c.succ[uid].Add(v.ID())
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// order returns the order of the graph.
|
||||
func (g johnsonGraph) order() int { return g.nodes.Count() }
|
||||
|
||||
// indexOf returns the index of the retained node for the given node ID.
|
||||
func (g johnsonGraph) indexOf(id int64) int {
|
||||
return g.index[id]
|
||||
}
|
||||
|
||||
// leastVertexIndex returns the index into orig of the least vertex.
|
||||
func (g johnsonGraph) leastVertexIndex() int {
|
||||
for _, v := range g.orig {
|
||||
if g.nodes.Has(v.ID()) {
|
||||
return g.indexOf(v.ID())
|
||||
}
|
||||
}
|
||||
panic("johnsonCycles: empty set")
|
||||
}
|
||||
|
||||
// subgraph returns a subgraph of g induced by {s, s+1, ... , n}. The
|
||||
// subgraph is destructively generated in g.
|
||||
func (g johnsonGraph) subgraph(s int) johnsonGraph {
|
||||
sn := g.orig[s].ID()
|
||||
for u, e := range g.succ {
|
||||
if u < sn {
|
||||
g.nodes.Remove(u)
|
||||
delete(g.succ, u)
|
||||
continue
|
||||
}
|
||||
for v := range e {
|
||||
if v < sn {
|
||||
g.succ[u].Remove(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
// sccSubGraph returns the graph of the tarjan's strongly connected
|
||||
// components with each SCC containing at least min vertices.
|
||||
// sccSubGraph returns nil if there is no SCC with at least min
|
||||
// members.
|
||||
func (g johnsonGraph) sccSubGraph(sccs [][]graph.Node, min int) johnsonGraph {
|
||||
if len(g.nodes) == 0 {
|
||||
g.nodes = nil
|
||||
g.succ = nil
|
||||
return g
|
||||
}
|
||||
sub := johnsonGraph{
|
||||
orig: g.orig,
|
||||
index: g.index,
|
||||
nodes: make(set.Int64s),
|
||||
succ: make(map[int64]set.Int64s),
|
||||
}
|
||||
|
||||
var n int
|
||||
for _, scc := range sccs {
|
||||
if len(scc) < min {
|
||||
continue
|
||||
}
|
||||
n++
|
||||
for _, u := range scc {
|
||||
for _, v := range scc {
|
||||
if _, ok := g.succ[u.ID()][v.ID()]; ok {
|
||||
if sub.succ[u.ID()] == nil {
|
||||
sub.succ[u.ID()] = make(set.Int64s)
|
||||
sub.nodes.Add(u.ID())
|
||||
}
|
||||
sub.nodes.Add(v.ID())
|
||||
sub.succ[u.ID()].Add(v.ID())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if n == 0 {
|
||||
g.nodes = nil
|
||||
g.succ = nil
|
||||
return g
|
||||
}
|
||||
|
||||
return sub
|
||||
}
|
||||
|
||||
// Nodes is required to satisfy Tarjan.
|
||||
func (g johnsonGraph) Nodes() graph.Nodes {
|
||||
n := make([]graph.Node, 0, len(g.nodes))
|
||||
for id := range g.nodes {
|
||||
n = append(n, johnsonGraphNode(id))
|
||||
}
|
||||
return iterator.NewOrderedNodes(n)
|
||||
}
|
||||
|
||||
// Successors is required to satisfy Tarjan.
|
||||
func (g johnsonGraph) From(id int64) graph.Nodes {
|
||||
adj := g.succ[id]
|
||||
if len(adj) == 0 {
|
||||
return graph.Empty
|
||||
}
|
||||
succ := make([]graph.Node, 0, len(adj))
|
||||
for id := range adj {
|
||||
succ = append(succ, johnsonGraphNode(id))
|
||||
}
|
||||
return iterator.NewOrderedNodes(succ)
|
||||
}
|
||||
|
||||
func (johnsonGraph) Has(int64) bool {
|
||||
panic("topo: unintended use of johnsonGraph")
|
||||
}
|
||||
func (johnsonGraph) Node(int64) graph.Node {
|
||||
panic("topo: unintended use of johnsonGraph")
|
||||
}
|
||||
func (johnsonGraph) HasEdgeBetween(_, _ int64) bool {
|
||||
panic("topo: unintended use of johnsonGraph")
|
||||
}
|
||||
func (johnsonGraph) Edge(_, _ int64) graph.Edge {
|
||||
panic("topo: unintended use of johnsonGraph")
|
||||
}
|
||||
func (johnsonGraph) HasEdgeFromTo(_, _ int64) bool {
|
||||
panic("topo: unintended use of johnsonGraph")
|
||||
}
|
||||
func (johnsonGraph) To(int64) graph.Nodes {
|
||||
panic("topo: unintended use of johnsonGraph")
|
||||
}
|
||||
|
||||
type johnsonGraphNode int64
|
||||
|
||||
func (n johnsonGraphNode) ID() int64 { return int64(n) }
|
9
vendor/gonum.org/v1/gonum/graph/topo/non_tomita_choice.go
generated
vendored
Normal file
9
vendor/gonum.org/v1/gonum/graph/topo/non_tomita_choice.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright ©2015 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !tomita
|
||||
|
||||
package topo
|
||||
|
||||
const tomitaTanakaTakahashi = false
|
83
vendor/gonum.org/v1/gonum/graph/topo/paton_cycles.go
generated
vendored
Normal file
83
vendor/gonum.org/v1/gonum/graph/topo/paton_cycles.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright ©2017 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package topo
|
||||
|
||||
import (
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/internal/linear"
|
||||
"gonum.org/v1/gonum/graph/internal/set"
|
||||
)
|
||||
|
||||
// UndirectedCyclesIn returns a set of cycles that forms a cycle basis in the graph g.
|
||||
// Any cycle in g can be constructed as a symmetric difference of its elements.
|
||||
func UndirectedCyclesIn(g graph.Undirected) [][]graph.Node {
|
||||
// From "An algorithm for finding a fundamental set of cycles of a graph"
|
||||
// https://doi.org/10.1145/363219.363232
|
||||
|
||||
var cycles [][]graph.Node
|
||||
done := make(set.Int64s)
|
||||
var tree linear.NodeStack
|
||||
nodes := g.Nodes()
|
||||
for nodes.Next() {
|
||||
n := nodes.Node()
|
||||
id := n.ID()
|
||||
if done.Has(id) {
|
||||
continue
|
||||
}
|
||||
done.Add(id)
|
||||
|
||||
tree = tree[:0]
|
||||
tree.Push(n)
|
||||
from := sets{id: set.Int64s{}}
|
||||
to := map[int64]graph.Node{id: n}
|
||||
|
||||
for tree.Len() != 0 {
|
||||
u := tree.Pop()
|
||||
uid := u.ID()
|
||||
adj := from[uid]
|
||||
for _, v := range graph.NodesOf(g.From(uid)) {
|
||||
vid := v.ID()
|
||||
switch {
|
||||
case uid == vid:
|
||||
cycles = append(cycles, []graph.Node{u})
|
||||
case !from.has(vid):
|
||||
done.Add(vid)
|
||||
to[vid] = u
|
||||
tree.Push(v)
|
||||
from.add(uid, vid)
|
||||
case !adj.Has(vid):
|
||||
c := []graph.Node{v, u}
|
||||
adj := from[vid]
|
||||
p := to[uid]
|
||||
for !adj.Has(p.ID()) {
|
||||
c = append(c, p)
|
||||
p = to[p.ID()]
|
||||
}
|
||||
c = append(c, p, c[0])
|
||||
cycles = append(cycles, c)
|
||||
adj.Add(uid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cycles
|
||||
}
|
||||
|
||||
type sets map[int64]set.Int64s
|
||||
|
||||
func (s sets) add(uid, vid int64) {
|
||||
e, ok := s[vid]
|
||||
if !ok {
|
||||
e = make(set.Int64s)
|
||||
s[vid] = e
|
||||
}
|
||||
e.Add(uid)
|
||||
}
|
||||
|
||||
func (s sets) has(uid int64) bool {
|
||||
_, ok := s[uid]
|
||||
return ok
|
||||
}
|
199
vendor/gonum.org/v1/gonum/graph/topo/tarjan.go
generated
vendored
Normal file
199
vendor/gonum.org/v1/gonum/graph/topo/tarjan.go
generated
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
// Copyright ©2015 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package topo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/internal/ordered"
|
||||
"gonum.org/v1/gonum/graph/internal/set"
|
||||
)
|
||||
|
||||
// Unorderable is an error containing sets of unorderable graph.Nodes.
|
||||
type Unorderable [][]graph.Node
|
||||
|
||||
// Error satisfies the error interface.
|
||||
func (e Unorderable) Error() string {
|
||||
const maxNodes = 10
|
||||
var n int
|
||||
for _, c := range e {
|
||||
n += len(c)
|
||||
}
|
||||
if n > maxNodes {
|
||||
// Don't return errors that are too long.
|
||||
return fmt.Sprintf("topo: no topological ordering: %d nodes in %d cyclic components", n, len(e))
|
||||
}
|
||||
return fmt.Sprintf("topo: no topological ordering: cyclic components: %v", [][]graph.Node(e))
|
||||
}
|
||||
|
||||
func lexical(nodes []graph.Node) { sort.Sort(ordered.ByID(nodes)) }
|
||||
|
||||
// Sort performs a topological sort of the directed graph g returning the 'from' to 'to'
|
||||
// sort order. If a topological ordering is not possible, an Unorderable error is returned
|
||||
// listing cyclic components in g with each cyclic component's members sorted by ID. When
|
||||
// an Unorderable error is returned, each cyclic component's topological position within
|
||||
// the sorted nodes is marked with a nil graph.Node.
|
||||
func Sort(g graph.Directed) (sorted []graph.Node, err error) {
|
||||
sccs := TarjanSCC(g)
|
||||
return sortedFrom(sccs, lexical)
|
||||
}
|
||||
|
||||
// SortStabilized performs a topological sort of the directed graph g returning the 'from'
|
||||
// to 'to' sort order, or the order defined by the in place order sort function where there
|
||||
// is no unambiguous topological ordering. If a topological ordering is not possible, an
|
||||
// Unorderable error is returned listing cyclic components in g with each cyclic component's
|
||||
// members sorted by the provided order function. If order is nil, nodes are ordered lexically
|
||||
// by node ID. When an Unorderable error is returned, each cyclic component's topological
|
||||
// position within the sorted nodes is marked with a nil graph.Node.
|
||||
func SortStabilized(g graph.Directed, order func([]graph.Node)) (sorted []graph.Node, err error) {
|
||||
if order == nil {
|
||||
order = lexical
|
||||
}
|
||||
sccs := tarjanSCCstabilized(g, order)
|
||||
return sortedFrom(sccs, order)
|
||||
}
|
||||
|
||||
func sortedFrom(sccs [][]graph.Node, order func([]graph.Node)) ([]graph.Node, error) {
|
||||
sorted := make([]graph.Node, 0, len(sccs))
|
||||
var sc Unorderable
|
||||
for _, s := range sccs {
|
||||
if len(s) != 1 {
|
||||
order(s)
|
||||
sc = append(sc, s)
|
||||
sorted = append(sorted, nil)
|
||||
continue
|
||||
}
|
||||
sorted = append(sorted, s[0])
|
||||
}
|
||||
var err error
|
||||
if sc != nil {
|
||||
for i, j := 0, len(sc)-1; i < j; i, j = i+1, j-1 {
|
||||
sc[i], sc[j] = sc[j], sc[i]
|
||||
}
|
||||
err = sc
|
||||
}
|
||||
ordered.Reverse(sorted)
|
||||
return sorted, err
|
||||
}
|
||||
|
||||
// TarjanSCC returns the strongly connected components of the graph g using Tarjan's algorithm.
|
||||
//
|
||||
// A strongly connected component of a graph is a set of vertices where it's possible to reach any
|
||||
// vertex in the set from any other (meaning there's a cycle between them.)
|
||||
//
|
||||
// Generally speaking, a directed graph where the number of strongly connected components is equal
|
||||
// to the number of nodes is acyclic, unless you count reflexive edges as a cycle (which requires
|
||||
// only a little extra testing.)
|
||||
//
|
||||
func TarjanSCC(g graph.Directed) [][]graph.Node {
|
||||
return tarjanSCCstabilized(g, nil)
|
||||
}
|
||||
|
||||
func tarjanSCCstabilized(g graph.Directed, order func([]graph.Node)) [][]graph.Node {
|
||||
nodes := graph.NodesOf(g.Nodes())
|
||||
var succ func(id int64) []graph.Node
|
||||
if order == nil {
|
||||
succ = func(id int64) []graph.Node {
|
||||
return graph.NodesOf(g.From(id))
|
||||
}
|
||||
} else {
|
||||
order(nodes)
|
||||
ordered.Reverse(nodes)
|
||||
|
||||
succ = func(id int64) []graph.Node {
|
||||
to := graph.NodesOf(g.From(id))
|
||||
order(to)
|
||||
ordered.Reverse(to)
|
||||
return to
|
||||
}
|
||||
}
|
||||
|
||||
t := tarjan{
|
||||
succ: succ,
|
||||
|
||||
indexTable: make(map[int64]int, len(nodes)),
|
||||
lowLink: make(map[int64]int, len(nodes)),
|
||||
onStack: make(set.Int64s),
|
||||
}
|
||||
for _, v := range nodes {
|
||||
if t.indexTable[v.ID()] == 0 {
|
||||
t.strongconnect(v)
|
||||
}
|
||||
}
|
||||
return t.sccs
|
||||
}
|
||||
|
||||
// tarjan implements Tarjan's strongly connected component finding
|
||||
// algorithm. The implementation is from the pseudocode at
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm?oldid=642744644
|
||||
//
|
||||
type tarjan struct {
|
||||
succ func(id int64) []graph.Node
|
||||
|
||||
index int
|
||||
indexTable map[int64]int
|
||||
lowLink map[int64]int
|
||||
onStack set.Int64s
|
||||
|
||||
stack []graph.Node
|
||||
|
||||
sccs [][]graph.Node
|
||||
}
|
||||
|
||||
// strongconnect is the strongconnect function described in the
|
||||
// wikipedia article.
|
||||
func (t *tarjan) strongconnect(v graph.Node) {
|
||||
vID := v.ID()
|
||||
|
||||
// Set the depth index for v to the smallest unused index.
|
||||
t.index++
|
||||
t.indexTable[vID] = t.index
|
||||
t.lowLink[vID] = t.index
|
||||
t.stack = append(t.stack, v)
|
||||
t.onStack.Add(vID)
|
||||
|
||||
// Consider successors of v.
|
||||
for _, w := range t.succ(vID) {
|
||||
wID := w.ID()
|
||||
if t.indexTable[wID] == 0 {
|
||||
// Successor w has not yet been visited; recur on it.
|
||||
t.strongconnect(w)
|
||||
t.lowLink[vID] = min(t.lowLink[vID], t.lowLink[wID])
|
||||
} else if t.onStack.Has(wID) {
|
||||
// Successor w is in stack s and hence in the current SCC.
|
||||
t.lowLink[vID] = min(t.lowLink[vID], t.indexTable[wID])
|
||||
}
|
||||
}
|
||||
|
||||
// If v is a root node, pop the stack and generate an SCC.
|
||||
if t.lowLink[vID] == t.indexTable[vID] {
|
||||
// Start a new strongly connected component.
|
||||
var (
|
||||
scc []graph.Node
|
||||
w graph.Node
|
||||
)
|
||||
for {
|
||||
w, t.stack = t.stack[len(t.stack)-1], t.stack[:len(t.stack)-1]
|
||||
t.onStack.Remove(w.ID())
|
||||
// Add w to current strongly connected component.
|
||||
scc = append(scc, w)
|
||||
if w.ID() == vID {
|
||||
break
|
||||
}
|
||||
}
|
||||
// Output the current strongly connected component.
|
||||
t.sccs = append(t.sccs, scc)
|
||||
}
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
9
vendor/gonum.org/v1/gonum/graph/topo/tomita_choice.go
generated
vendored
Normal file
9
vendor/gonum.org/v1/gonum/graph/topo/tomita_choice.go
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright ©2015 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build tomita
|
||||
|
||||
package topo
|
||||
|
||||
const tomitaTanakaTakahashi = true
|
68
vendor/gonum.org/v1/gonum/graph/topo/topo.go
generated
vendored
Normal file
68
vendor/gonum.org/v1/gonum/graph/topo/topo.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package topo
|
||||
|
||||
import (
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/traverse"
|
||||
)
|
||||
|
||||
// IsPathIn returns whether path is a path in g.
|
||||
//
|
||||
// As special cases, IsPathIn returns true for a zero length path or for
|
||||
// a path of length 1 when the node in path exists in the graph.
|
||||
func IsPathIn(g graph.Graph, path []graph.Node) bool {
|
||||
switch len(path) {
|
||||
case 0:
|
||||
return true
|
||||
case 1:
|
||||
return g.Node(path[0].ID()) != nil
|
||||
default:
|
||||
var canReach func(uid, vid int64) bool
|
||||
switch g := g.(type) {
|
||||
case graph.Directed:
|
||||
canReach = g.HasEdgeFromTo
|
||||
default:
|
||||
canReach = g.HasEdgeBetween
|
||||
}
|
||||
|
||||
for i, u := range path[:len(path)-1] {
|
||||
if !canReach(u.ID(), path[i+1].ID()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// PathExistsIn returns whether there is a path in g starting at from extending
|
||||
// to to.
|
||||
//
|
||||
// PathExistsIn exists as a helper function. If many tests for path existence
|
||||
// are being performed, other approaches will be more efficient.
|
||||
func PathExistsIn(g graph.Graph, from, to graph.Node) bool {
|
||||
var t traverse.BreadthFirst
|
||||
return t.Walk(g, from, func(n graph.Node, _ int) bool { return n.ID() == to.ID() }) != nil
|
||||
}
|
||||
|
||||
// ConnectedComponents returns the connected components of the undirected graph g.
|
||||
func ConnectedComponents(g graph.Undirected) [][]graph.Node {
|
||||
var (
|
||||
w traverse.DepthFirst
|
||||
c []graph.Node
|
||||
cc [][]graph.Node
|
||||
)
|
||||
during := func(n graph.Node) {
|
||||
c = append(c, n)
|
||||
}
|
||||
after := func() {
|
||||
cc = append(cc, []graph.Node(nil))
|
||||
cc[len(cc)-1] = append(cc[len(cc)-1], c...)
|
||||
c = c[:0]
|
||||
}
|
||||
w.WalkAll(g, nil, after, during)
|
||||
|
||||
return cc
|
||||
}
|
6
vendor/gonum.org/v1/gonum/graph/traverse/doc.go
generated
vendored
Normal file
6
vendor/gonum.org/v1/gonum/graph/traverse/doc.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright ©2017 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package traverse provides basic graph traversal primitives.
|
||||
package traverse // import "gonum.org/v1/gonum/graph/traverse"
|
231
vendor/gonum.org/v1/gonum/graph/traverse/traverse.go
generated
vendored
Normal file
231
vendor/gonum.org/v1/gonum/graph/traverse/traverse.go
generated
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
// Copyright ©2015 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package traverse
|
||||
|
||||
import (
|
||||
"gonum.org/v1/gonum/graph"
|
||||
"gonum.org/v1/gonum/graph/internal/linear"
|
||||
"gonum.org/v1/gonum/graph/internal/set"
|
||||
)
|
||||
|
||||
var _ Graph = graph.Graph(nil)
|
||||
|
||||
// Graph is the subset of graph.Graph necessary for graph traversal.
|
||||
type Graph interface {
|
||||
// From returns all nodes that can be reached directly
|
||||
// from the node with the given ID.
|
||||
From(id int64) graph.Nodes
|
||||
|
||||
// Edge returns the edge from u to v, with IDs uid and vid,
|
||||
// if such an edge exists and nil otherwise. The node v
|
||||
// must be directly reachable from u as defined by
|
||||
// the From method.
|
||||
Edge(uid, vid int64) graph.Edge
|
||||
}
|
||||
|
||||
// BreadthFirst implements stateful breadth-first graph traversal.
|
||||
type BreadthFirst struct {
|
||||
// Visit is called on all nodes on their first visit.
|
||||
Visit func(graph.Node)
|
||||
|
||||
// Traverse is called on all edges that may be traversed
|
||||
// during the walk. This includes edges that would hop to
|
||||
// an already visited node.
|
||||
//
|
||||
// The value returned by Traverse determines whether
|
||||
// an edge can be traversed during the walk.
|
||||
Traverse func(graph.Edge) bool
|
||||
|
||||
queue linear.NodeQueue
|
||||
visited set.Int64s
|
||||
}
|
||||
|
||||
// Walk performs a breadth-first traversal of the graph g starting from the given node,
|
||||
// depending on the Traverse field and the until parameter if they are non-nil.
|
||||
// The traversal follows edges for which Traverse(edge) is true and returns the first node
|
||||
// for which until(node, depth) is true. During the traversal, if the Visit field is
|
||||
// non-nil, it is called with each node the first time it is visited.
|
||||
func (b *BreadthFirst) Walk(g Graph, from graph.Node, until func(n graph.Node, d int) bool) graph.Node {
|
||||
if b.visited == nil {
|
||||
b.visited = make(set.Int64s)
|
||||
}
|
||||
b.queue.Enqueue(from)
|
||||
if b.Visit != nil && !b.visited.Has(from.ID()) {
|
||||
b.Visit(from)
|
||||
}
|
||||
b.visited.Add(from.ID())
|
||||
|
||||
var (
|
||||
depth int
|
||||
children int
|
||||
untilNext = 1
|
||||
)
|
||||
for b.queue.Len() > 0 {
|
||||
t := b.queue.Dequeue()
|
||||
if until != nil && until(t, depth) {
|
||||
return t
|
||||
}
|
||||
tid := t.ID()
|
||||
to := g.From(tid)
|
||||
for to.Next() {
|
||||
n := to.Node()
|
||||
nid := n.ID()
|
||||
if b.Traverse != nil && !b.Traverse(g.Edge(tid, nid)) {
|
||||
continue
|
||||
}
|
||||
if b.visited.Has(nid) {
|
||||
continue
|
||||
}
|
||||
if b.Visit != nil {
|
||||
b.Visit(n)
|
||||
}
|
||||
b.visited.Add(nid)
|
||||
children++
|
||||
b.queue.Enqueue(n)
|
||||
}
|
||||
if untilNext--; untilNext == 0 {
|
||||
depth++
|
||||
untilNext = children
|
||||
children = 0
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WalkAll calls Walk for each unvisited node of the graph g using edges independent
|
||||
// of their direction. The functions before and after are called prior to commencing
|
||||
// and after completing each walk if they are non-nil respectively. The function
|
||||
// during is called on each node as it is traversed.
|
||||
func (b *BreadthFirst) WalkAll(g graph.Undirected, before, after func(), during func(graph.Node)) {
|
||||
b.Reset()
|
||||
nodes := g.Nodes()
|
||||
for nodes.Next() {
|
||||
from := nodes.Node()
|
||||
if b.Visited(from) {
|
||||
continue
|
||||
}
|
||||
if before != nil {
|
||||
before()
|
||||
}
|
||||
b.Walk(g, from, func(n graph.Node, _ int) bool {
|
||||
if during != nil {
|
||||
during(n)
|
||||
}
|
||||
return false
|
||||
})
|
||||
if after != nil {
|
||||
after()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Visited returned whether the node n was visited during a traverse.
|
||||
func (b *BreadthFirst) Visited(n graph.Node) bool {
|
||||
return b.visited.Has(n.ID())
|
||||
}
|
||||
|
||||
// Reset resets the state of the traverser for reuse.
|
||||
func (b *BreadthFirst) Reset() {
|
||||
b.queue.Reset()
|
||||
b.visited = nil
|
||||
}
|
||||
|
||||
// DepthFirst implements stateful depth-first graph traversal.
|
||||
type DepthFirst struct {
|
||||
// Visit is called on all nodes on their first visit.
|
||||
Visit func(graph.Node)
|
||||
|
||||
// Traverse is called on all edges that may be traversed
|
||||
// during the walk. This includes edges that would hop to
|
||||
// an already visited node.
|
||||
//
|
||||
// The value returned by Traverse determines whether an
|
||||
// edge can be traversed during the walk.
|
||||
Traverse func(graph.Edge) bool
|
||||
|
||||
stack linear.NodeStack
|
||||
visited set.Int64s
|
||||
}
|
||||
|
||||
// Walk performs a depth-first traversal of the graph g starting from the given node,
|
||||
// depending on the Traverse field and the until parameter if they are non-nil.
|
||||
// The traversal follows edges for which Traverse(edge) is true and returns the first node
|
||||
// for which until(node) is true. During the traversal, if the Visit field is non-nil, it
|
||||
// is called with each node the first time it is visited.
|
||||
func (d *DepthFirst) Walk(g Graph, from graph.Node, until func(graph.Node) bool) graph.Node {
|
||||
if d.visited == nil {
|
||||
d.visited = make(set.Int64s)
|
||||
}
|
||||
d.stack.Push(from)
|
||||
if d.Visit != nil && !d.visited.Has(from.ID()) {
|
||||
d.Visit(from)
|
||||
}
|
||||
d.visited.Add(from.ID())
|
||||
|
||||
for d.stack.Len() > 0 {
|
||||
t := d.stack.Pop()
|
||||
if until != nil && until(t) {
|
||||
return t
|
||||
}
|
||||
tid := t.ID()
|
||||
to := g.From(tid)
|
||||
for to.Next() {
|
||||
n := to.Node()
|
||||
nid := n.ID()
|
||||
if d.Traverse != nil && !d.Traverse(g.Edge(tid, nid)) {
|
||||
continue
|
||||
}
|
||||
if d.visited.Has(nid) {
|
||||
continue
|
||||
}
|
||||
if d.Visit != nil {
|
||||
d.Visit(n)
|
||||
}
|
||||
d.visited.Add(nid)
|
||||
d.stack.Push(n)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WalkAll calls Walk for each unvisited node of the graph g using edges independent
|
||||
// of their direction. The functions before and after are called prior to commencing
|
||||
// and after completing each walk if they are non-nil respectively. The function
|
||||
// during is called on each node as it is traversed.
|
||||
func (d *DepthFirst) WalkAll(g graph.Undirected, before, after func(), during func(graph.Node)) {
|
||||
d.Reset()
|
||||
nodes := g.Nodes()
|
||||
for nodes.Next() {
|
||||
from := nodes.Node()
|
||||
if d.Visited(from) {
|
||||
continue
|
||||
}
|
||||
if before != nil {
|
||||
before()
|
||||
}
|
||||
d.Walk(g, from, func(n graph.Node) bool {
|
||||
if during != nil {
|
||||
during(n)
|
||||
}
|
||||
return false
|
||||
})
|
||||
if after != nil {
|
||||
after()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Visited returned whether the node n was visited during a traverse.
|
||||
func (d *DepthFirst) Visited(n graph.Node) bool {
|
||||
return d.visited.Has(n.ID())
|
||||
}
|
||||
|
||||
// Reset resets the state of the traverser for reuse.
|
||||
func (d *DepthFirst) Reset() {
|
||||
d.stack = d.stack[:0]
|
||||
d.visited = nil
|
||||
}
|
270
vendor/gonum.org/v1/gonum/graph/undirect.go
generated
vendored
Normal file
270
vendor/gonum.org/v1/gonum/graph/undirect.go
generated
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
// Copyright ©2015 The Gonum Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package graph
|
||||
|
||||
// Undirect converts a directed graph to an undirected graph.
|
||||
type Undirect struct {
|
||||
G Directed
|
||||
}
|
||||
|
||||
var _ Undirected = Undirect{}
|
||||
|
||||
// Node returns the node with the given ID if it exists in the graph,
|
||||
// and nil otherwise.
|
||||
func (g Undirect) Node(id int64) Node { return g.G.Node(id) }
|
||||
|
||||
// Nodes returns all the nodes in the graph.
|
||||
func (g Undirect) Nodes() Nodes { return g.G.Nodes() }
|
||||
|
||||
// From returns all nodes in g that can be reached directly from u.
|
||||
func (g Undirect) From(uid int64) Nodes {
|
||||
return newNodeFilterIterator(g.G.From(uid), g.G.To(uid))
|
||||
}
|
||||
|
||||
// HasEdgeBetween returns whether an edge exists between nodes x and y.
|
||||
func (g Undirect) HasEdgeBetween(xid, yid int64) bool { return g.G.HasEdgeBetween(xid, yid) }
|
||||
|
||||
// Edge returns the edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
// If an edge exists, the Edge returned is an EdgePair. The weight of
|
||||
// the edge is determined by applying the Merge func to the weights of the
|
||||
// edges between u and v.
|
||||
func (g Undirect) Edge(uid, vid int64) Edge { return g.EdgeBetween(uid, vid) }
|
||||
|
||||
// EdgeBetween returns the edge between nodes x and y. If an edge exists, the
|
||||
// Edge returned is an EdgePair. The weight of the edge is determined by
|
||||
// applying the Merge func to the weights of edges between x and y.
|
||||
func (g Undirect) EdgeBetween(xid, yid int64) Edge {
|
||||
fe := g.G.Edge(xid, yid)
|
||||
re := g.G.Edge(yid, xid)
|
||||
if fe == nil && re == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return EdgePair{fe, re}
|
||||
}
|
||||
|
||||
// UndirectWeighted converts a directed weighted graph to an undirected weighted graph,
|
||||
// resolving edge weight conflicts.
|
||||
type UndirectWeighted struct {
|
||||
G WeightedDirected
|
||||
|
||||
// Absent is the value used to
|
||||
// represent absent edge weights
|
||||
// passed to Merge if the reverse
|
||||
// edge is present.
|
||||
Absent float64
|
||||
|
||||
// Merge defines how discordant edge
|
||||
// weights in G are resolved. A merge
|
||||
// is performed if at least one edge
|
||||
// exists between the nodes being
|
||||
// considered. The edges corresponding
|
||||
// to the two weights are also passed,
|
||||
// in the same order.
|
||||
// The order of weight parameters
|
||||
// passed to Merge is not defined, so
|
||||
// the function should be commutative.
|
||||
// If Merge is nil, the arithmetic
|
||||
// mean is used to merge weights.
|
||||
Merge func(x, y float64, xe, ye Edge) float64
|
||||
}
|
||||
|
||||
var (
|
||||
_ Undirected = UndirectWeighted{}
|
||||
_ WeightedUndirected = UndirectWeighted{}
|
||||
)
|
||||
|
||||
// Node returns the node with the given ID if it exists in the graph,
|
||||
// and nil otherwise.
|
||||
func (g UndirectWeighted) Node(id int64) Node { return g.G.Node(id) }
|
||||
|
||||
// Nodes returns all the nodes in the graph.
|
||||
func (g UndirectWeighted) Nodes() Nodes { return g.G.Nodes() }
|
||||
|
||||
// From returns all nodes in g that can be reached directly from u.
|
||||
func (g UndirectWeighted) From(uid int64) Nodes {
|
||||
return newNodeFilterIterator(g.G.From(uid), g.G.To(uid))
|
||||
}
|
||||
|
||||
// HasEdgeBetween returns whether an edge exists between nodes x and y.
|
||||
func (g UndirectWeighted) HasEdgeBetween(xid, yid int64) bool { return g.G.HasEdgeBetween(xid, yid) }
|
||||
|
||||
// Edge returns the edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
// If an edge exists, the Edge returned is an EdgePair. The weight of
|
||||
// the edge is determined by applying the Merge func to the weights of the
|
||||
// edges between u and v.
|
||||
func (g UndirectWeighted) Edge(uid, vid int64) Edge { return g.WeightedEdgeBetween(uid, vid) }
|
||||
|
||||
// WeightedEdge returns the weighted edge from u to v if such an edge exists and nil otherwise.
|
||||
// The node v must be directly reachable from u as defined by the From method.
|
||||
// If an edge exists, the Edge returned is an EdgePair. The weight of
|
||||
// the edge is determined by applying the Merge func to the weights of the
|
||||
// edges between u and v.
|
||||
func (g UndirectWeighted) WeightedEdge(uid, vid int64) WeightedEdge {
|
||||
return g.WeightedEdgeBetween(uid, vid)
|
||||
}
|
||||
|
||||
// EdgeBetween returns the edge between nodes x and y. If an edge exists, the
|
||||
// Edge returned is an EdgePair. The weight of the edge is determined by
|
||||
// applying the Merge func to the weights of edges between x and y.
|
||||
func (g UndirectWeighted) EdgeBetween(xid, yid int64) Edge {
|
||||
return g.WeightedEdgeBetween(xid, yid)
|
||||
}
|
||||
|
||||
// WeightedEdgeBetween returns the weighted edge between nodes x and y. If an edge exists, the
|
||||
// Edge returned is an EdgePair. The weight of the edge is determined by
|
||||
// applying the Merge func to the weights of edges between x and y.
|
||||
func (g UndirectWeighted) WeightedEdgeBetween(xid, yid int64) WeightedEdge {
|
||||
fe := g.G.Edge(xid, yid)
|
||||
re := g.G.Edge(yid, xid)
|
||||
if fe == nil && re == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
f, ok := g.G.Weight(xid, yid)
|
||||
if !ok {
|
||||
f = g.Absent
|
||||
}
|
||||
r, ok := g.G.Weight(yid, xid)
|
||||
if !ok {
|
||||
r = g.Absent
|
||||
}
|
||||
|
||||
var w float64
|
||||
if g.Merge == nil {
|
||||
w = (f + r) / 2
|
||||
} else {
|
||||
w = g.Merge(f, r, fe, re)
|
||||
}
|
||||
return WeightedEdgePair{EdgePair: [2]Edge{fe, re}, W: w}
|
||||
}
|
||||
|
||||
// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge.
|
||||
// If x and y are the same node the internal node weight is returned. If there is no joining
|
||||
// edge between the two nodes the weight value returned is zero. Weight returns true if an edge
|
||||
// exists between x and y or if x and y have the same ID, false otherwise.
|
||||
func (g UndirectWeighted) Weight(xid, yid int64) (w float64, ok bool) {
|
||||
fe := g.G.Edge(xid, yid)
|
||||
re := g.G.Edge(yid, xid)
|
||||
|
||||
f, fOk := g.G.Weight(xid, yid)
|
||||
if !fOk {
|
||||
f = g.Absent
|
||||
}
|
||||
r, rOK := g.G.Weight(yid, xid)
|
||||
if !rOK {
|
||||
r = g.Absent
|
||||
}
|
||||
ok = fOk || rOK
|
||||
|
||||
if g.Merge == nil {
|
||||
return (f + r) / 2, ok
|
||||
}
|
||||
return g.Merge(f, r, fe, re), ok
|
||||
}
|
||||
|
||||
// EdgePair is an opposed pair of directed edges.
|
||||
type EdgePair [2]Edge
|
||||
|
||||
// From returns the from node of the first non-nil edge, or nil.
|
||||
func (e EdgePair) From() Node {
|
||||
if e[0] != nil {
|
||||
return e[0].From()
|
||||
} else if e[1] != nil {
|
||||
return e[1].From()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// To returns the to node of the first non-nil edge, or nil.
|
||||
func (e EdgePair) To() Node {
|
||||
if e[0] != nil {
|
||||
return e[0].To()
|
||||
} else if e[1] != nil {
|
||||
return e[1].To()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReversedEdge returns a new Edge with the end point of the
|
||||
// edges in the pair swapped.
|
||||
func (e EdgePair) ReversedEdge() Edge {
|
||||
if e[0] != nil {
|
||||
e[0] = e[0].ReversedEdge()
|
||||
}
|
||||
if e[1] != nil {
|
||||
e[1] = e[1].ReversedEdge()
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// WeightedEdgePair is an opposed pair of directed edges.
|
||||
type WeightedEdgePair struct {
|
||||
EdgePair
|
||||
W float64
|
||||
}
|
||||
|
||||
// ReversedEdge returns a new Edge with the end point of the
|
||||
// edges in the pair swapped.
|
||||
func (e WeightedEdgePair) ReversedEdge() Edge {
|
||||
e.EdgePair = e.EdgePair.ReversedEdge().(EdgePair)
|
||||
return e
|
||||
}
|
||||
|
||||
// Weight returns the merged edge weights of the two edges.
|
||||
func (e WeightedEdgePair) Weight() float64 { return e.W }
|
||||
|
||||
// nodeFilterIterator combines two Nodes to produce a single stream of
|
||||
// unique nodes.
|
||||
type nodeFilterIterator struct {
|
||||
a, b Nodes
|
||||
|
||||
// unique indicates the node in b with the key ID is unique.
|
||||
unique map[int64]bool
|
||||
}
|
||||
|
||||
func newNodeFilterIterator(a, b Nodes) *nodeFilterIterator {
|
||||
n := nodeFilterIterator{a: a, b: b, unique: make(map[int64]bool)}
|
||||
for n.b.Next() {
|
||||
n.unique[n.b.Node().ID()] = true
|
||||
}
|
||||
n.b.Reset()
|
||||
for n.a.Next() {
|
||||
n.unique[n.a.Node().ID()] = false
|
||||
}
|
||||
n.a.Reset()
|
||||
return &n
|
||||
}
|
||||
|
||||
func (n *nodeFilterIterator) Len() int {
|
||||
return len(n.unique)
|
||||
}
|
||||
|
||||
func (n *nodeFilterIterator) Next() bool {
|
||||
n.Len()
|
||||
if n.a.Next() {
|
||||
return true
|
||||
}
|
||||
for n.b.Next() {
|
||||
if n.unique[n.b.Node().ID()] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *nodeFilterIterator) Node() Node {
|
||||
if n.a.Len() != 0 {
|
||||
return n.a.Node()
|
||||
}
|
||||
return n.b.Node()
|
||||
}
|
||||
|
||||
func (n *nodeFilterIterator) Reset() {
|
||||
n.a.Reset()
|
||||
n.b.Reset()
|
||||
}
|
Reference in New Issue
Block a user