mirror of https://github.com/k3s-io/k3s
283 lines
8.0 KiB
Go
283 lines
8.0 KiB
Go
|
// 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()))
|
||
|
}
|
||
|
}
|
||
|
}
|