mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 20:53:33 +00:00
gonum: directed acyclic graph
Implements graph.Directed capable of storing at most one edge between any two nodes. Uses the Undirected implementation for space efficiency (~30% space savings).
This commit is contained in:
parent
b1ac314046
commit
ec1d79da19
6
third_party/forked/gonum/graph/simple/BUILD
vendored
6
third_party/forked/gonum/graph/simple/BUILD
vendored
@ -10,7 +10,10 @@ load(
|
|||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
name = "go_default_test",
|
name = "go_default_test",
|
||||||
srcs = ["undirected_test.go"],
|
srcs = [
|
||||||
|
"directed_acyclic_test.go",
|
||||||
|
"undirected_test.go",
|
||||||
|
],
|
||||||
library = ":go_default_library",
|
library = ":go_default_library",
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = ["//third_party/forked/gonum/graph:go_default_library"],
|
deps = ["//third_party/forked/gonum/graph:go_default_library"],
|
||||||
@ -19,6 +22,7 @@ go_test(
|
|||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"directed_acyclic.go",
|
||||||
"simple.go",
|
"simple.go",
|
||||||
"undirected.go",
|
"undirected.go",
|
||||||
],
|
],
|
||||||
|
55
third_party/forked/gonum/graph/simple/directed_acyclic.go
vendored
Normal file
55
third_party/forked/gonum/graph/simple/directed_acyclic.go
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package simple
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/kubernetes/third_party/forked/gonum/graph"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DirectedAcyclicGraph implements graph.Directed using UndirectedGraph,
|
||||||
|
// which only stores one edge for any node pair.
|
||||||
|
type DirectedAcyclicGraph struct {
|
||||||
|
*UndirectedGraph
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDirectedAcyclicGraph(self, absent float64) *DirectedAcyclicGraph {
|
||||||
|
return &DirectedAcyclicGraph{
|
||||||
|
UndirectedGraph: NewUndirectedGraph(self, absent),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *DirectedAcyclicGraph) HasEdgeFromTo(u, v graph.Node) bool {
|
||||||
|
edge := g.UndirectedGraph.EdgeBetween(u, v)
|
||||||
|
if edge == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return (edge.From().ID() == u.ID())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *DirectedAcyclicGraph) From(n graph.Node) []graph.Node {
|
||||||
|
if !g.Has(n) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fid := n.ID()
|
||||||
|
nodes := make([]graph.Node, 0, len(g.UndirectedGraph.edges[n.ID()]))
|
||||||
|
for _, edge := range g.UndirectedGraph.edges[n.ID()] {
|
||||||
|
if edge.From().ID() == fid {
|
||||||
|
nodes = append(nodes, g.UndirectedGraph.nodes[edge.To().ID()])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *DirectedAcyclicGraph) To(n graph.Node) []graph.Node {
|
||||||
|
if !g.Has(n) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tid := n.ID()
|
||||||
|
nodes := make([]graph.Node, 0, len(g.UndirectedGraph.edges[n.ID()]))
|
||||||
|
for _, edge := range g.UndirectedGraph.edges[n.ID()] {
|
||||||
|
if edge.To().ID() == tid {
|
||||||
|
nodes = append(nodes, g.UndirectedGraph.nodes[edge.From().ID()])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes
|
||||||
|
}
|
62
third_party/forked/gonum/graph/simple/directed_acyclic_test.go
vendored
Normal file
62
third_party/forked/gonum/graph/simple/directed_acyclic_test.go
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// 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 = &DirectedAcyclicGraph{}
|
||||||
|
var _ graph.Directed = &DirectedAcyclicGraph{}
|
||||||
|
|
||||||
|
// Tests Issue #27
|
||||||
|
func TestAcyclicEdgeOvercounting(t *testing.T) {
|
||||||
|
g := generateDummyAcyclicGraph()
|
||||||
|
|
||||||
|
if neigh := g.From(Node(Node(2))); len(neigh) != 2 {
|
||||||
|
t.Errorf("Node 2 has incorrect number of neighbors got neighbors %v (count %d), expected 2 neighbors {0,1}", neigh, len(neigh))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateDummyAcyclicGraph() *DirectedAcyclicGraph {
|
||||||
|
nodes := [4]struct{ srcID, targetID int }{
|
||||||
|
{2, 1},
|
||||||
|
{1, 0},
|
||||||
|
{0, 2},
|
||||||
|
{2, 0},
|
||||||
|
}
|
||||||
|
|
||||||
|
g := NewDirectedAcyclicGraph(0, math.Inf(1))
|
||||||
|
|
||||||
|
for _, n := range nodes {
|
||||||
|
g.SetEdge(Edge{F: Node(n.srcID), T: Node(n.targetID), W: 1})
|
||||||
|
}
|
||||||
|
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for issue #123 https://github.com/gonum/graph/issues/123
|
||||||
|
func TestAcyclicIssue123DirectedGraph(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
t.Errorf("unexpected panic: %v", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
g := NewDirectedAcyclicGraph(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)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user