mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 04:06:03 +00:00
bump(github.com/gonum/graph): 50b27dea7ebbfb052dfaf91681afc6fde28d8796
This commit is contained in:
parent
986cdfa6ff
commit
b1ac314046
1
third_party/BUILD
vendored
1
third_party/BUILD
vendored
@ -20,6 +20,7 @@ filegroup(
|
||||
"//third_party/forked/golang/expansion:all-srcs",
|
||||
"//third_party/forked/golang/reflect:all-srcs",
|
||||
"//third_party/forked/golang/template:all-srcs",
|
||||
"//third_party/forked/gonum/graph:all-srcs",
|
||||
"//third_party/htpasswd:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
|
32
third_party/forked/gonum/graph/BUILD
vendored
Normal file
32
third_party/forked/gonum/graph/BUILD
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["graph.go"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//third_party/forked/gonum/graph/internal/linear:all-srcs",
|
||||
"//third_party/forked/gonum/graph/simple:all-srcs",
|
||||
"//third_party/forked/gonum/graph/traverse:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
23
third_party/forked/gonum/graph/LICENSE
vendored
Normal file
23
third_party/forked/gonum/graph/LICENSE
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
Copyright ©2013 The gonum Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the gonum project nor the names of its authors and
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
1
third_party/forked/gonum/graph/README.md
vendored
Normal file
1
third_party/forked/gonum/graph/README.md
vendored
Normal file
@ -0,0 +1 @@
|
||||
Forked from gonum/graph@50b27dea7ebbfb052dfaf91681afc6fde28d8796 to support memory-use improvements to the simple graph
|
153
third_party/forked/gonum/graph/graph.go
vendored
Normal file
153
third_party/forked/gonum/graph/graph.go
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
// 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() int
|
||||
}
|
||||
|
||||
// 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() Node
|
||||
To() Node
|
||||
Weight() float64
|
||||
}
|
||||
|
||||
// Graph is a generalized graph.
|
||||
type Graph interface {
|
||||
// Has returns whether the node exists within the graph.
|
||||
Has(Node) bool
|
||||
|
||||
// Nodes returns all the nodes in the graph.
|
||||
Nodes() []Node
|
||||
|
||||
// From returns all nodes that can be reached directly
|
||||
// from the given node.
|
||||
From(Node) []Node
|
||||
|
||||
// HasEdgeBeteen returns whether an edge exists between
|
||||
// nodes x and y without considering direction.
|
||||
HasEdgeBetween(x, y Node) bool
|
||||
|
||||
// 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.
|
||||
Edge(u, v Node) Edge
|
||||
}
|
||||
|
||||
// Undirected is an undirected graph.
|
||||
type Undirected interface {
|
||||
Graph
|
||||
|
||||
// EdgeBetween returns the edge between nodes x and y.
|
||||
EdgeBetween(x, y Node) Edge
|
||||
}
|
||||
|
||||
// Directed is a directed graph.
|
||||
type Directed interface {
|
||||
Graph
|
||||
|
||||
// HasEdgeFromTo returns whether an edge exists
|
||||
// in the graph from u to v.
|
||||
HasEdgeFromTo(u, v Node) bool
|
||||
|
||||
// To returns all nodes that can reach directly
|
||||
// to the given node.
|
||||
To(Node) []Node
|
||||
}
|
||||
|
||||
// Weighter defines graphs that can report edge weights.
|
||||
type Weighter interface {
|
||||
// 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 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(x, y Node) (w float64, ok bool)
|
||||
}
|
||||
|
||||
// NodeAdder is an interface for adding arbitrary nodes to a graph.
|
||||
type NodeAdder interface {
|
||||
// NewNodeID returns a new unique arbitrary ID.
|
||||
NewNodeID() int
|
||||
|
||||
// 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 a node 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(Node)
|
||||
}
|
||||
|
||||
// EdgeSetter is an interface for adding edges to a graph.
|
||||
type EdgeSetter interface {
|
||||
// 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.
|
||||
// If the IDs returned by e.From and e.To are
|
||||
// equal, SetEdge will panic.
|
||||
SetEdge(e Edge)
|
||||
}
|
||||
|
||||
// EdgeRemover is an interface for removing nodes from a graph.
|
||||
type EdgeRemover interface {
|
||||
// RemoveEdge removes the given edge, leaving the
|
||||
// terminal nodes. If the edge does not exist it
|
||||
// is a no-op.
|
||||
RemoveEdge(Edge)
|
||||
}
|
||||
|
||||
// Builder is a graph that can have nodes and edges added.
|
||||
type Builder interface {
|
||||
NodeAdder
|
||||
EdgeSetter
|
||||
}
|
||||
|
||||
// UndirectedBuilder is an undirected graph builder.
|
||||
type UndirectedBuilder interface {
|
||||
Undirected
|
||||
Builder
|
||||
}
|
||||
|
||||
// DirectedBuilder is a directed graph builder.
|
||||
type DirectedBuilder interface {
|
||||
Directed
|
||||
Builder
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// 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 Undirect may be used to do this.
|
||||
func Copy(dst Builder, src Graph) {
|
||||
nodes := src.Nodes()
|
||||
for _, n := range nodes {
|
||||
dst.AddNode(n)
|
||||
}
|
||||
for _, u := range nodes {
|
||||
for _, v := range src.From(u) {
|
||||
dst.SetEdge(src.Edge(u, v))
|
||||
}
|
||||
}
|
||||
}
|
28
third_party/forked/gonum/graph/internal/linear/BUILD
vendored
Normal file
28
third_party/forked/gonum/graph/internal/linear/BUILD
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["linear.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = ["//third_party/forked/gonum/graph:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
74
third_party/forked/gonum/graph/internal/linear/linear.go
vendored
Normal file
74
third_party/forked/gonum/graph/internal/linear/linear.go
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
// 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 provides common linear data structures.
|
||||
package linear
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/third_party/forked/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]
|
||||
}
|
43
third_party/forked/gonum/graph/simple/BUILD
vendored
Normal file
43
third_party/forked/gonum/graph/simple/BUILD
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["undirected_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = ["//third_party/forked/gonum/graph:go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"simple.go",
|
||||
"undirected.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//third_party/forked/gonum/graph:go_default_library",
|
||||
"//vendor/golang.org/x/tools/container/intsets:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
45
third_party/forked/gonum/graph/simple/simple.go
vendored
Normal file
45
third_party/forked/gonum/graph/simple/simple.go
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
// 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 provides a suite of simple graph implementations satisfying
|
||||
// the gonum/graph interfaces.
|
||||
package simple
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"k8s.io/kubernetes/third_party/forked/gonum/graph"
|
||||
)
|
||||
|
||||
// Node is a simple graph node.
|
||||
type Node int
|
||||
|
||||
// ID returns the ID number of the node.
|
||||
func (n Node) ID() int {
|
||||
return int(n)
|
||||
}
|
||||
|
||||
// Edge is a simple graph edge.
|
||||
type Edge struct {
|
||||
F, T graph.Node
|
||||
W float64
|
||||
}
|
||||
|
||||
// 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 }
|
||||
|
||||
// Weight returns the weight of the edge.
|
||||
func (e Edge) Weight() float64 { return e.W }
|
||||
|
||||
// maxInt is the maximum value of the machine-dependent int type.
|
||||
const maxInt int = int(^uint(0) >> 1)
|
||||
|
||||
// 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))
|
||||
}
|
241
third_party/forked/gonum/graph/simple/undirected.go
vendored
Normal file
241
third_party/forked/gonum/graph/simple/undirected.go
vendored
Normal file
@ -0,0 +1,241 @@
|
||||
// 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"
|
||||
|
||||
"golang.org/x/tools/container/intsets"
|
||||
|
||||
"k8s.io/kubernetes/third_party/forked/gonum/graph"
|
||||
)
|
||||
|
||||
// UndirectedGraph implements a generalized undirected graph.
|
||||
type UndirectedGraph struct {
|
||||
nodes map[int]graph.Node
|
||||
edges map[int]map[int]graph.Edge
|
||||
|
||||
self, absent float64
|
||||
|
||||
freeIDs intsets.Sparse
|
||||
usedIDs intsets.Sparse
|
||||
}
|
||||
|
||||
// NewUndirectedGraph returns an UndirectedGraph with the specified self and absent
|
||||
// edge weight values.
|
||||
func NewUndirectedGraph(self, absent float64) *UndirectedGraph {
|
||||
return &UndirectedGraph{
|
||||
nodes: make(map[int]graph.Node),
|
||||
edges: make(map[int]map[int]graph.Edge),
|
||||
|
||||
self: self,
|
||||
absent: absent,
|
||||
}
|
||||
}
|
||||
|
||||
// NewNodeID returns a new unique ID for a node to be added to g. The returned ID does
|
||||
// not become a valid ID in g until it is added to g.
|
||||
func (g *UndirectedGraph) NewNodeID() int {
|
||||
if len(g.nodes) == 0 {
|
||||
return 0
|
||||
}
|
||||
if len(g.nodes) == maxInt {
|
||||
panic(fmt.Sprintf("simple: cannot allocate node: no slot"))
|
||||
}
|
||||
|
||||
var id int
|
||||
if g.freeIDs.Len() != 0 && g.freeIDs.TakeMin(&id) {
|
||||
return id
|
||||
}
|
||||
if id = g.usedIDs.Max(); id < maxInt {
|
||||
return id + 1
|
||||
}
|
||||
for id = 0; id < maxInt; id++ {
|
||||
if !g.usedIDs.Has(id) {
|
||||
return id
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID.
|
||||
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[int]graph.Edge)
|
||||
|
||||
g.freeIDs.Remove(n.ID())
|
||||
g.usedIDs.Insert(n.ID())
|
||||
}
|
||||
|
||||
// RemoveNode removes n from the graph, as well as any edges attached to it. If the node
|
||||
// is not in the graph it is a no-op.
|
||||
func (g *UndirectedGraph) RemoveNode(n graph.Node) {
|
||||
if _, ok := g.nodes[n.ID()]; !ok {
|
||||
return
|
||||
}
|
||||
delete(g.nodes, n.ID())
|
||||
|
||||
for from := range g.edges[n.ID()] {
|
||||
delete(g.edges[from], n.ID())
|
||||
}
|
||||
delete(g.edges, n.ID())
|
||||
|
||||
g.freeIDs.Insert(n.ID())
|
||||
g.usedIDs.Remove(n.ID())
|
||||
|
||||
}
|
||||
|
||||
// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added.
|
||||
// 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 !g.Has(from) {
|
||||
g.AddNode(from)
|
||||
}
|
||||
if !g.Has(to) {
|
||||
g.AddNode(to)
|
||||
}
|
||||
|
||||
g.edges[fid][tid] = e
|
||||
g.edges[tid][fid] = e
|
||||
}
|
||||
|
||||
// RemoveEdge removes e from the graph, leaving the terminal nodes. If the edge does not exist
|
||||
// it is a no-op.
|
||||
func (g *UndirectedGraph) RemoveEdge(e graph.Edge) {
|
||||
from, to := e.From(), e.To()
|
||||
if _, ok := g.nodes[from.ID()]; !ok {
|
||||
return
|
||||
}
|
||||
if _, ok := g.nodes[to.ID()]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
delete(g.edges[from.ID()], to.ID())
|
||||
delete(g.edges[to.ID()], from.ID())
|
||||
}
|
||||
|
||||
// Node returns the node in the graph with the given ID.
|
||||
func (g *UndirectedGraph) Node(id int) graph.Node {
|
||||
return g.nodes[id]
|
||||
}
|
||||
|
||||
// Has returns whether the node exists within the graph.
|
||||
func (g *UndirectedGraph) Has(n graph.Node) bool {
|
||||
_, ok := g.nodes[n.ID()]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Nodes returns all the nodes in the graph.
|
||||
func (g *UndirectedGraph) Nodes() []graph.Node {
|
||||
nodes := make([]graph.Node, len(g.nodes))
|
||||
i := 0
|
||||
for _, n := range g.nodes {
|
||||
nodes[i] = n
|
||||
i++
|
||||
}
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
// Edges returns all the edges in the graph.
|
||||
func (g *UndirectedGraph) Edges() []graph.Edge {
|
||||
var edges []graph.Edge
|
||||
|
||||
seen := make(map[[2]int]struct{})
|
||||
for _, u := range g.edges {
|
||||
for _, e := range u {
|
||||
uid := e.From().ID()
|
||||
vid := e.To().ID()
|
||||
if _, ok := seen[[2]int{uid, vid}]; ok {
|
||||
continue
|
||||
}
|
||||
seen[[2]int{uid, vid}] = struct{}{}
|
||||
seen[[2]int{vid, uid}] = struct{}{}
|
||||
edges = append(edges, e)
|
||||
}
|
||||
}
|
||||
|
||||
return edges
|
||||
}
|
||||
|
||||
// From returns all nodes in g that can be reached directly from n.
|
||||
func (g *UndirectedGraph) From(n graph.Node) []graph.Node {
|
||||
if !g.Has(n) {
|
||||
return nil
|
||||
}
|
||||
|
||||
nodes := make([]graph.Node, len(g.edges[n.ID()]))
|
||||
i := 0
|
||||
for from := range g.edges[n.ID()] {
|
||||
nodes[i] = g.nodes[from]
|
||||
i++
|
||||
}
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
// HasEdgeBetween returns whether an edge exists between nodes x and y.
|
||||
func (g *UndirectedGraph) HasEdgeBetween(x, y graph.Node) bool {
|
||||
_, ok := g.edges[x.ID()][y.ID()]
|
||||
return ok
|
||||
}
|
||||
|
||||
// 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(u, v graph.Node) graph.Edge {
|
||||
return g.EdgeBetween(u, v)
|
||||
}
|
||||
|
||||
// EdgeBetween returns the edge between nodes x and y.
|
||||
func (g *UndirectedGraph) EdgeBetween(x, y graph.Node) graph.Edge {
|
||||
// We don't need to check if neigh exists because
|
||||
// it's implicit in the edges access.
|
||||
if !g.Has(x) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return g.edges[x.ID()][y.ID()]
|
||||
}
|
||||
|
||||
// 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 *UndirectedGraph) Weight(x, y graph.Node) (w float64, ok bool) {
|
||||
xid := x.ID()
|
||||
yid := y.ID()
|
||||
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
|
||||
}
|
||||
|
||||
// Degree returns the degree of n in g.
|
||||
func (g *UndirectedGraph) Degree(n graph.Node) int {
|
||||
if _, ok := g.nodes[n.ID()]; !ok {
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(g.edges[n.ID()])
|
||||
}
|
63
third_party/forked/gonum/graph/simple/undirected_test.go
vendored
Normal file
63
third_party/forked/gonum/graph/simple/undirected_test.go
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
// 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"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/third_party/forked/gonum/graph"
|
||||
)
|
||||
|
||||
var _ graph.Graph = (*UndirectedGraph)(nil)
|
||||
|
||||
func TestAssertMutableNotDirected(t *testing.T) {
|
||||
var g graph.UndirectedBuilder = NewUndirectedGraph(0, math.Inf(1))
|
||||
if _, ok := g.(graph.Directed); ok {
|
||||
t.Fatal("Graph is directed, but a MutableGraph cannot safely be directed!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaxID(t *testing.T) {
|
||||
g := NewUndirectedGraph(0, math.Inf(1))
|
||||
nodes := make(map[graph.Node]struct{})
|
||||
for i := Node(0); i < 3; i++ {
|
||||
g.AddNode(i)
|
||||
nodes[i] = struct{}{}
|
||||
}
|
||||
g.RemoveNode(Node(0))
|
||||
delete(nodes, Node(0))
|
||||
g.RemoveNode(Node(2))
|
||||
delete(nodes, Node(2))
|
||||
n := Node(g.NewNodeID())
|
||||
g.AddNode(n)
|
||||
if !g.Has(n) {
|
||||
t.Error("added node does not exist in graph")
|
||||
}
|
||||
if _, exists := nodes[n]; exists {
|
||||
t.Errorf("Created already existing node id: %v", n.ID())
|
||||
}
|
||||
}
|
||||
|
||||
// Test for issue #123 https://github.com/gonum/graph/issues/123
|
||||
func TestIssue123UndirectedGraph(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Errorf("unexpected panic: %v", r)
|
||||
}
|
||||
}()
|
||||
g := NewUndirectedGraph(0, math.Inf(1))
|
||||
|
||||
n0 := Node(g.NewNodeID())
|
||||
g.AddNode(n0)
|
||||
|
||||
n1 := Node(g.NewNodeID())
|
||||
g.AddNode(n1)
|
||||
|
||||
g.RemoveNode(n0)
|
||||
|
||||
n2 := Node(g.NewNodeID())
|
||||
g.AddNode(n2)
|
||||
}
|
32
third_party/forked/gonum/graph/traverse/BUILD
vendored
Normal file
32
third_party/forked/gonum/graph/traverse/BUILD
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["traverse.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//third_party/forked/gonum/graph:go_default_library",
|
||||
"//third_party/forked/gonum/graph/internal/linear:go_default_library",
|
||||
"//vendor/golang.org/x/tools/container/intsets:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
186
third_party/forked/gonum/graph/traverse/traverse.go
vendored
Normal file
186
third_party/forked/gonum/graph/traverse/traverse.go
vendored
Normal file
@ -0,0 +1,186 @@
|
||||
// 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 provides basic graph traversal primitives.
|
||||
package traverse
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/container/intsets"
|
||||
|
||||
"k8s.io/kubernetes/third_party/forked/gonum/graph"
|
||||
"k8s.io/kubernetes/third_party/forked/gonum/graph/internal/linear"
|
||||
)
|
||||
|
||||
// BreadthFirst implements stateful breadth-first graph traversal.
|
||||
type BreadthFirst struct {
|
||||
EdgeFilter func(graph.Edge) bool
|
||||
Visit func(u, v graph.Node)
|
||||
queue linear.NodeQueue
|
||||
visited *intsets.Sparse
|
||||
}
|
||||
|
||||
// Walk performs a breadth-first traversal of the graph g starting from the given node,
|
||||
// depending on the the EdgeFilter field and the until parameter if they are non-nil. The
|
||||
// traversal follows edges for which EdgeFilter(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 the nodes joined by each followed edge.
|
||||
func (b *BreadthFirst) Walk(g graph.Graph, from graph.Node, until func(n graph.Node, d int) bool) graph.Node {
|
||||
if b.visited == nil {
|
||||
b.visited = &intsets.Sparse{}
|
||||
}
|
||||
b.queue.Enqueue(from)
|
||||
b.visited.Insert(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
|
||||
}
|
||||
for _, n := range g.From(t) {
|
||||
if b.EdgeFilter != nil && !b.EdgeFilter(g.Edge(t, n)) {
|
||||
continue
|
||||
}
|
||||
if b.visited.Has(n.ID()) {
|
||||
continue
|
||||
}
|
||||
if b.Visit != nil {
|
||||
b.Visit(t, n)
|
||||
}
|
||||
b.visited.Insert(n.ID())
|
||||
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()
|
||||
for _, from := range g.Nodes() {
|
||||
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 != nil && b.visited.Has(n.ID())
|
||||
}
|
||||
|
||||
// Reset resets the state of the traverser for reuse.
|
||||
func (b *BreadthFirst) Reset() {
|
||||
b.queue.Reset()
|
||||
if b.visited != nil {
|
||||
b.visited.Clear()
|
||||
}
|
||||
}
|
||||
|
||||
// DepthFirst implements stateful depth-first graph traversal.
|
||||
type DepthFirst struct {
|
||||
EdgeFilter func(graph.Edge) bool
|
||||
Visit func(u, v graph.Node)
|
||||
stack linear.NodeStack
|
||||
visited *intsets.Sparse
|
||||
}
|
||||
|
||||
// Walk performs a depth-first traversal of the graph g starting from the given node,
|
||||
// depending on the the EdgeFilter field and the until parameter if they are non-nil. The
|
||||
// traversal follows edges for which EdgeFilter(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 the nodes joined by each followed edge.
|
||||
func (d *DepthFirst) Walk(g graph.Graph, from graph.Node, until func(graph.Node) bool) graph.Node {
|
||||
if d.visited == nil {
|
||||
d.visited = &intsets.Sparse{}
|
||||
}
|
||||
d.stack.Push(from)
|
||||
d.visited.Insert(from.ID())
|
||||
|
||||
for d.stack.Len() > 0 {
|
||||
t := d.stack.Pop()
|
||||
if until != nil && until(t) {
|
||||
return t
|
||||
}
|
||||
for _, n := range g.From(t) {
|
||||
if d.EdgeFilter != nil && !d.EdgeFilter(g.Edge(t, n)) {
|
||||
continue
|
||||
}
|
||||
if d.visited.Has(n.ID()) {
|
||||
continue
|
||||
}
|
||||
if d.Visit != nil {
|
||||
d.Visit(t, n)
|
||||
}
|
||||
d.visited.Insert(n.ID())
|
||||
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()
|
||||
for _, from := range g.Nodes() {
|
||||
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 != nil && d.visited.Has(n.ID())
|
||||
}
|
||||
|
||||
// Reset resets the state of the traverser for reuse.
|
||||
func (d *DepthFirst) Reset() {
|
||||
d.stack = d.stack[:0]
|
||||
if d.visited != nil {
|
||||
d.visited.Clear()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user