diff options
Diffstat (limited to 'vendor/github.com/soniakeys/graph/adj.go')
| -rw-r--r-- | vendor/github.com/soniakeys/graph/adj.go | 325 |
1 files changed, 0 insertions, 325 deletions
diff --git a/vendor/github.com/soniakeys/graph/adj.go b/vendor/github.com/soniakeys/graph/adj.go deleted file mode 100644 index 165f365..0000000 --- a/vendor/github.com/soniakeys/graph/adj.go +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright 2014 Sonia Keys -// License MIT: https://opensource.org/licenses/MIT - -package graph - -// adj.go contains methods on AdjacencyList and LabeledAdjacencyList. -// -// AdjacencyList methods are placed first and are alphabetized. -// LabeledAdjacencyList methods follow, also alphabetized. -// Only exported methods need be alphabetized; non-exported methods can -// be left near their use. - -import ( - "math" - "sort" -) - -// HasParallelSort identifies if a graph contains parallel arcs, multiple arcs -// that lead from a node to the same node. -// -// If the graph has parallel arcs, the results fr and to represent an example -// where there are parallel arcs from node fr to node to. -// -// If there are no parallel arcs, the method returns false -1 -1. -// -// Multiple loops on a node count as parallel arcs. -// -// "Sort" in the method name indicates that sorting is used to detect parallel -// arcs. Compared to method HasParallelMap, this may give better performance -// for small or sparse graphs but will have asymtotically worse performance for -// large dense graphs. -func (g AdjacencyList) HasParallelSort() (has bool, fr, to NI) { - var t NodeList - for n, to := range g { - if len(to) == 0 { - continue - } - // different code in the labeled version, so no code gen. - t = append(t[:0], to...) - sort.Sort(t) - t0 := t[0] - for _, to := range t[1:] { - if to == t0 { - return true, NI(n), t0 - } - t0 = to - } - } - return false, -1, -1 -} - -// IsUndirected returns true if g represents an undirected graph. -// -// Returns true when all non-loop arcs are paired in reciprocal pairs. -// Otherwise returns false and an example unpaired arc. -func (g AdjacencyList) IsUndirected() (u bool, from, to NI) { - // similar code in dot/writeUndirected - unpaired := make(AdjacencyList, len(g)) - for fr, to := range g { - arc: // for each arc in g - for _, to := range to { - if to == NI(fr) { - continue // loop - } - // search unpaired arcs - ut := unpaired[to] - for i, u := range ut { - if u == NI(fr) { // found reciprocal - last := len(ut) - 1 - ut[i] = ut[last] - unpaired[to] = ut[:last] - continue arc - } - } - // reciprocal not found - unpaired[fr] = append(unpaired[fr], to) - } - } - for fr, to := range unpaired { - if len(to) > 0 { - return false, NI(fr), to[0] - } - } - return true, -1, -1 -} - -// Edgelist constructs the edge list rerpresentation of a graph. -// -// An edge is returned for each arc of the graph. For undirected graphs -// this includes reciprocal edges. -// -// See also WeightedEdgeList method. -func (g LabeledAdjacencyList) EdgeList() (el []LabeledEdge) { - for fr, to := range g { - for _, to := range to { - el = append(el, LabeledEdge{Edge{NI(fr), to.To}, to.Label}) - } - } - return -} - -// FloydWarshall finds all pairs shortest distances for a simple weighted -// graph without negative cycles. -// -// In result array d, d[i][j] will be the shortest distance from node i -// to node j. Any diagonal element < 0 indicates a negative cycle exists. -// -// If g is an undirected graph with no negative edge weights, the result -// array will be a distance matrix, for example as used by package -// github.com/soniakeys/cluster. -func (g LabeledAdjacencyList) FloydWarshall(w WeightFunc) (d [][]float64) { - d = newFWd(len(g)) - for fr, to := range g { - for _, to := range to { - d[fr][to.To] = w(to.Label) - } - } - solveFW(d) - return -} - -// little helper function, makes a blank matrix for FloydWarshall. -func newFWd(n int) [][]float64 { - d := make([][]float64, n) - for i := range d { - di := make([]float64, n) - for j := range di { - if j != i { - di[j] = math.Inf(1) - } - } - d[i] = di - } - return d -} - -// Floyd Warshall solver, once the matrix d is initialized by arc weights. -func solveFW(d [][]float64) { - for k, dk := range d { - for _, di := range d { - dik := di[k] - for j := range d { - if d2 := dik + dk[j]; d2 < di[j] { - di[j] = d2 - } - } - } - } -} - -// HasArcLabel returns true if g has any arc from node fr to node to -// with label l. -// -// Also returned is the index within the slice of arcs from node fr. -// If no arc from fr to to is present, HasArcLabel returns false, -1. -func (g LabeledAdjacencyList) HasArcLabel(fr, to NI, l LI) (bool, int) { - t := Half{to, l} - for x, h := range g[fr] { - if h == t { - return true, x - } - } - return false, -1 -} - -// HasParallelSort identifies if a graph contains parallel arcs, multiple arcs -// that lead from a node to the same node. -// -// If the graph has parallel arcs, the results fr and to represent an example -// where there are parallel arcs from node fr to node to. -// -// If there are no parallel arcs, the method returns -1 -1. -// -// Multiple loops on a node count as parallel arcs. -// -// "Sort" in the method name indicates that sorting is used to detect parallel -// arcs. Compared to method HasParallelMap, this may give better performance -// for small or sparse graphs but will have asymtotically worse performance for -// large dense graphs. -func (g LabeledAdjacencyList) HasParallelSort() (has bool, fr, to NI) { - var t NodeList - for n, to := range g { - if len(to) == 0 { - continue - } - // slightly different code needed here compared to AdjacencyList - t = t[:0] - for _, to := range to { - t = append(t, to.To) - } - sort.Sort(t) - t0 := t[0] - for _, to := range t[1:] { - if to == t0 { - return true, NI(n), t0 - } - t0 = to - } - } - return false, -1, -1 -} - -// IsUndirected returns true if g represents an undirected graph. -// -// Returns true when all non-loop arcs are paired in reciprocal pairs with -// matching labels. Otherwise returns false and an example unpaired arc. -// -// Note the requirement that reciprocal pairs have matching labels is -// an additional test not present in the otherwise equivalent unlabeled version -// of IsUndirected. -func (g LabeledAdjacencyList) IsUndirected() (u bool, from NI, to Half) { - unpaired := make(LabeledAdjacencyList, len(g)) - for fr, to := range g { - arc: // for each arc in g - for _, to := range to { - if to.To == NI(fr) { - continue // loop - } - // search unpaired arcs - ut := unpaired[to.To] - for i, u := range ut { - if u.To == NI(fr) && u.Label == to.Label { // found reciprocal - last := len(ut) - 1 - ut[i] = ut[last] - unpaired[to.To] = ut[:last] - continue arc - } - } - // reciprocal not found - unpaired[fr] = append(unpaired[fr], to) - } - } - for fr, to := range unpaired { - if len(to) > 0 { - return false, NI(fr), to[0] - } - } - return true, -1, to -} - -// NegativeArc returns true if the receiver graph contains a negative arc. -func (g LabeledAdjacencyList) NegativeArc(w WeightFunc) bool { - for _, nbs := range g { - for _, nb := range nbs { - if w(nb.Label) < 0 { - return true - } - } - } - return false -} - -// Unlabeled constructs the unlabeled graph corresponding to g. -func (g LabeledAdjacencyList) Unlabeled() AdjacencyList { - a := make(AdjacencyList, len(g)) - for n, nbs := range g { - to := make([]NI, len(nbs)) - for i, nb := range nbs { - to[i] = nb.To - } - a[n] = to - } - return a -} - -// WeightedEdgeList constructs a WeightedEdgeList object from a -// LabeledAdjacencyList. -// -// Internally it calls g.EdgeList() to obtain the Edges member. -// See LabeledAdjacencyList.EdgeList(). -func (g LabeledAdjacencyList) WeightedEdgeList(w WeightFunc) *WeightedEdgeList { - return &WeightedEdgeList{ - Order: len(g), - WeightFunc: w, - Edges: g.EdgeList(), - } -} - -// WeightedInDegree computes the weighted in-degree of each node in g -// for a given weight function w. -// -// The weighted in-degree of a node is the sum of weights of arcs going to -// the node. -// -// A weighted degree of a node is often termed the "strength" of a node. -// -// See note for undirected graphs at LabeledAdjacencyList.WeightedOutDegree. -func (g LabeledAdjacencyList) WeightedInDegree(w WeightFunc) []float64 { - ind := make([]float64, len(g)) - for _, to := range g { - for _, to := range to { - ind[to.To] += w(to.Label) - } - } - return ind -} - -// WeightedOutDegree computes the weighted out-degree of the specified node -// for a given weight function w. -// -// The weighted out-degree of a node is the sum of weights of arcs going from -// the node. -// -// A weighted degree of a node is often termed the "strength" of a node. -// -// Note for undirected graphs, the WeightedOutDegree result for a node will -// equal the WeightedInDegree for the node. You can use WeightedInDegree if -// you have need for the weighted degrees of all nodes or use WeightedOutDegree -// to compute the weighted degrees of individual nodes. In either case loops -// are counted just once, unlike the (unweighted) UndirectedDegree methods. -func (g LabeledAdjacencyList) WeightedOutDegree(n NI, w WeightFunc) (d float64) { - for _, to := range g[n] { - d += w(to.Label) - } - return -} - -// More about loops and strength: I didn't see consensus on this especially -// in the case of undirected graphs. Some sources said to add in-degree and -// out-degree, which would seemingly double both loops and non-loops. -// Some said to double loops. Some said sum the edge weights and had no -// comment on loops. R of course makes everything an option. The meaning -// of "strength" where loops exist is unclear. So while I could write an -// UndirectedWeighted degree function that doubles loops but not edges, -// I'm going to just leave this for now. |
