diff options
| author | Petter Rasmussen | 2016-04-17 13:11:19 +0200 |
|---|---|---|
| committer | Petter Rasmussen | 2016-04-17 13:11:19 +0200 |
| commit | 97981f7fd205353907135eacfc0e0ade24b88269 (patch) | |
| tree | 1fdb61a7138642a1612bb201434e8ebda141cc8a /vendor/github.com | |
| parent | 8de8e05c483c6b5f23b14742315f1860211dcef7 (diff) | |
| parent | b5eb2866cfceb69b0d4dd4948273d679a884fbb2 (diff) | |
| download | gdrive-97981f7fd205353907135eacfc0e0ade24b88269.tar.bz2 | |
Merge pull request #140 from paulz/godep
add Go dependencies by godep
Diffstat (limited to 'vendor/github.com')
28 files changed, 6876 insertions, 0 deletions
diff --git a/vendor/github.com/sabhiram/go-git-ignore/.gitignore b/vendor/github.com/sabhiram/go-git-ignore/.gitignore new file mode 100644 index 0000000..0e919af --- /dev/null +++ b/vendor/github.com/sabhiram/go-git-ignore/.gitignore @@ -0,0 +1,28 @@ +# Package test fixtures +test_fixtures + +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + diff --git a/vendor/github.com/sabhiram/go-git-ignore/.travis.yml b/vendor/github.com/sabhiram/go-git-ignore/.travis.yml new file mode 100644 index 0000000..24ddadf --- /dev/null +++ b/vendor/github.com/sabhiram/go-git-ignore/.travis.yml @@ -0,0 +1,18 @@ +language: go + +go: + - 1.3 + - tip + +env: + - "PATH=$HOME/gopath/bin:$PATH" + +before_install: + - go get github.com/stretchr/testify/assert + - go get github.com/axw/gocov/gocov + - go get github.com/mattn/goveralls + - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi + +script: + - go test -v -covermode=count -coverprofile=coverage.out + - goveralls -coverprofile=coverage.out -service travis-ci -repotoken $COVERALLS_TOKEN diff --git a/vendor/github.com/sabhiram/go-git-ignore/LICENSE b/vendor/github.com/sabhiram/go-git-ignore/LICENSE new file mode 100644 index 0000000..c606f49 --- /dev/null +++ b/vendor/github.com/sabhiram/go-git-ignore/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Shaba Abhiram + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/github.com/sabhiram/go-git-ignore/README.md b/vendor/github.com/sabhiram/go-git-ignore/README.md new file mode 100644 index 0000000..fbbb376 --- /dev/null +++ b/vendor/github.com/sabhiram/go-git-ignore/README.md @@ -0,0 +1,17 @@ +# go-git-ignore + +[](https://travis-ci.org/sabhiram/go-git-ignore) [](https://coveralls.io/r/sabhiram/go-git-ignore?branch=master) + +A gitignore parser for `Go` + +## Install + +```shell +go get github.com/sabhiram/go-git-ignore +``` + +## Usage + +```shell +TODO +``` diff --git a/vendor/github.com/sabhiram/go-git-ignore/ignore.go b/vendor/github.com/sabhiram/go-git-ignore/ignore.go new file mode 100644 index 0000000..e3241b2 --- /dev/null +++ b/vendor/github.com/sabhiram/go-git-ignore/ignore.go @@ -0,0 +1,200 @@ +/* +ignore is a library which returns a new ignorer object which can +test against various paths. This is particularly useful when trying +to filter files based on a .gitignore document + +The rules for parsing the input file are the same as the ones listed +in the Git docs here: http://git-scm.com/docs/gitignore + +The summarized version of the same has been copied here: + + 1. A blank line matches no files, so it can serve as a separator + for readability. + 2. A line starting with # serves as a comment. Put a backslash ("\") + in front of the first hash for patterns that begin with a hash. + 3. Trailing spaces are ignored unless they are quoted with backslash ("\"). + 4. An optional prefix "!" which negates the pattern; any matching file + excluded by a previous pattern will become included again. It is not + possible to re-include a file if a parent directory of that file is + excluded. Git doesn’t list excluded directories for performance reasons, + so any patterns on contained files have no effect, no matter where they + are defined. Put a backslash ("\") in front of the first "!" for + patterns that begin with a literal "!", for example, "\!important!.txt". + 5. If the pattern ends with a slash, it is removed for the purpose of the + following description, but it would only find a match with a directory. + In other words, foo/ will match a directory foo and paths underneath it, + but will not match a regular file or a symbolic link foo (this is + consistent with the way how pathspec works in general in Git). + 6. If the pattern does not contain a slash /, Git treats it as a shell glob + pattern and checks for a match against the pathname relative to the + location of the .gitignore file (relative to the toplevel of the work + tree if not from a .gitignore file). + 7. Otherwise, Git treats the pattern as a shell glob suitable for + consumption by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the + pattern will not match a / in the pathname. For example, + "Documentation/*.html" matches "Documentation/git.html" but not + "Documentation/ppc/ppc.html" or "tools/perf/Documentation/perf.html". + 8. A leading slash matches the beginning of the pathname. For example, + "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c". + 9. Two consecutive asterisks ("**") in patterns matched against full + pathname may have special meaning: + i. A leading "**" followed by a slash means match in all directories. + For example, "** /foo" matches file or directory "foo" anywhere, + the same as pattern "foo". "** /foo/bar" matches file or directory + "bar" anywhere that is directly under directory "foo". + ii. A trailing "/**" matches everything inside. For example, "abc/**" + matches all files inside directory "abc", relative to the location + of the .gitignore file, with infinite depth. + iii. A slash followed by two consecutive asterisks then a slash matches + zero or more directories. For example, "a/** /b" matches "a/b", + "a/x/b", "a/x/y/b" and so on. + iv. Other consecutive asterisks are considered invalid. */ +package ignore + +import ( + "io/ioutil" + "os" + "regexp" + "strings" +) + +// An IgnoreParser is an interface which exposes two methods: +// MatchesPath() - Returns true if the path is targeted by the patterns compiled in the GitIgnore structure +type IgnoreParser interface { + IncludesPath(f string) bool + IgnoresPath(f string) bool + MatchesPath(f string) bool +} + +// GitIgnore is a struct which contains a slice of regexp.Regexp +// patterns +type GitIgnore struct { + patterns []*regexp.Regexp // List of regexp patterns which this ignore file applies + negate []bool // List of booleans which determine if the pattern is negated +} + +// This function pretty much attempts to mimic the parsing rules +// listed above at the start of this file +func getPatternFromLine(line string) (*regexp.Regexp, bool) { + // Trim OS-specific carriage returns. + line = strings.TrimRight(line, "\r") + + // Strip comments [Rule 2] + if strings.HasPrefix(line, `#`) { + return nil, false + } + + // Trim string [Rule 3] + // TODO: Handle [Rule 3], when the " " is escaped with a \ + line = strings.Trim(line, " ") + + // Exit for no-ops and return nil which will prevent us from + // appending a pattern against this line + if line == "" { + return nil, false + } + + // TODO: Handle [Rule 4] which negates the match for patterns leading with "!" + negatePattern := false + if line[0] == '!' { + negatePattern = true + line = line[1:] + } + + // Handle [Rule 2, 4], when # or ! is escaped with a \ + // Handle [Rule 4] once we tag negatePattern, strip the leading ! char + if regexp.MustCompile(`^(\#|\!)`).MatchString(line) { + line = line[1:] + } + + // If we encounter a foo/*.blah in a folder, prepend the / char + if regexp.MustCompile(`([^\/+])/.*\*\.`).MatchString(line) && line[0] != '/' { + line = "/" + line + } + + // Handle escaping the "." char + line = regexp.MustCompile(`\.`).ReplaceAllString(line, `\.`) + + magicStar := "#$~" + + // Handle "/**/" usage + if strings.HasPrefix(line, "/**/") { + line = line[1:] + } + line = regexp.MustCompile(`/\*\*/`).ReplaceAllString(line, `(/|/.+/)`) + line = regexp.MustCompile(`\*\*/`).ReplaceAllString(line, `(|.`+magicStar+`/)`) + line = regexp.MustCompile(`/\*\*`).ReplaceAllString(line, `(|/.`+magicStar+`)`) + + // Handle escaping the "*" char + line = regexp.MustCompile(`\\\*`).ReplaceAllString(line, `\`+magicStar) + line = regexp.MustCompile(`\*`).ReplaceAllString(line, `([^/]*)`) + + // Handle escaping the "?" char + line = strings.Replace(line, "?", `\?`, -1) + + line = strings.Replace(line, magicStar, "*", -1) + + // Temporary regex + var expr = "" + if strings.HasSuffix(line, "/") { + expr = line + "(|.*)$" + } else { + expr = line + "(|/.*)$" + } + if strings.HasPrefix(expr, "/") { + expr = "^(|/)" + expr[1:] + } else { + expr = "^(|.*/)" + expr + } + pattern, _ := regexp.Compile(expr) + + return pattern, negatePattern +} + +// Accepts a variadic set of strings, and returns a GitIgnore object which +// converts and appends the lines in the input to regexp.Regexp patterns +// held within the GitIgnore objects "patterns" field +func CompileIgnoreLines(lines ...string) (*GitIgnore, error) { + g := new(GitIgnore) + for _, line := range lines { + pattern, negatePattern := getPatternFromLine(line) + if pattern != nil { + g.patterns = append(g.patterns, pattern) + g.negate = append(g.negate, negatePattern) + } + } + return g, nil +} + +// Accepts a ignore file as the input, parses the lines out of the file +// and invokes the CompileIgnoreLines method +func CompileIgnoreFile(fpath string) (*GitIgnore, error) { + buffer, error := ioutil.ReadFile(fpath) + if error == nil { + s := strings.Split(string(buffer), "\n") + return CompileIgnoreLines(s...) + } + return nil, error +} + +// MatchesPath is an interface function for the IgnoreParser interface. +// It returns true if the given GitIgnore structure would target a given +// path string "f" +func (g GitIgnore) MatchesPath(f string) bool { + // Replace OS-specific path separator. + f = strings.Replace(f, string(os.PathSeparator), "/", -1) + + matchesPath := false + for idx, pattern := range g.patterns { + if pattern.MatchString(f) { + // If this is a regular target (not negated with a gitignore exclude "!" etc) + if !g.negate[idx] { + matchesPath = true + // Negated pattern, and matchesPath is already set + } else if matchesPath { + matchesPath = false + } + } + } + return matchesPath +} diff --git a/vendor/github.com/soniakeys/graph/.gitignore b/vendor/github.com/soniakeys/graph/.gitignore new file mode 100644 index 0000000..3be6158 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/.gitignore @@ -0,0 +1,2 @@ +*.dot + diff --git a/vendor/github.com/soniakeys/graph/.travis.yml b/vendor/github.com/soniakeys/graph/.travis.yml new file mode 100644 index 0000000..bcc4f9f --- /dev/null +++ b/vendor/github.com/soniakeys/graph/.travis.yml @@ -0,0 +1,8 @@ +sudo: false +language: go +# update travis.sh when changing version number here +go: + - 1.2.1 + - 1.6 +install: go get -t ./... +script: ./travis.sh diff --git a/vendor/github.com/soniakeys/graph/adj.go b/vendor/github.com/soniakeys/graph/adj.go new file mode 100644 index 0000000..165f365 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/adj.go @@ -0,0 +1,325 @@ +// 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. diff --git a/vendor/github.com/soniakeys/graph/adj_RO.go b/vendor/github.com/soniakeys/graph/adj_RO.go new file mode 100644 index 0000000..1d37d14 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/adj_RO.go @@ -0,0 +1,387 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// adj_RO.go is code generated from adj_cg.go by directives in graph.go. +// Editing adj_cg.go is okay. +// DO NOT EDIT adj_RO.go. The RO is for Read Only. + +import ( + "math/rand" + "time" +) + +// ArcSize returns the number of arcs in g. +// +// Note that for an undirected graph without loops, the number of undirected +// edges -- the traditional meaning of graph size -- will be ArcSize()/2. +// On the other hand, if g is an undirected graph that has or may have loops, +// g.ArcSize()/2 is not a meaningful quantity. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) ArcSize() int { + m := 0 + for _, to := range g { + m += len(to) + } + return m +} + +// BoundsOk validates that all arcs in g stay within the slice bounds of g. +// +// BoundsOk returns true when no arcs point outside the bounds of g. +// Otherwise it returns false and an example arc that points outside of g. +// +// Most methods of this package assume the BoundsOk condition and may +// panic when they encounter an arc pointing outside of the graph. This +// function can be used to validate a graph when the BoundsOk condition +// is unknown. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) BoundsOk() (ok bool, fr NI, to NI) { + for fr, to := range g { + for _, to := range to { + if to < 0 || to >= NI(len(g)) { + return false, NI(fr), to + } + } + } + return true, -1, to +} + +// BreadthFirst traverses a directed or undirected graph in breadth first order. +// +// Argument start is the start node for the traversal. If r is nil, nodes are +// visited in deterministic order. If a random number generator is supplied, +// nodes at each level are visited in random order. +// +// Argument f can be nil if you have no interest in the FromList path result. +// If FromList f is non-nil, the method populates f.Paths and sets f.MaxLen. +// It does not set f.Leaves. For convenience argument f can be a zero value +// FromList. If f.Paths is nil, the FromList is initialized first. If f.Paths +// is non-nil however, the FromList is used as is. The method uses a value of +// PathEnd.Len == 0 to indentify unvisited nodes. Existing non-zero values +// will limit the traversal. +// +// Traversal calls the visitor function v for each node starting with node +// start. If v returns true, traversal continues. If v returns false, the +// traversal terminates immediately. PathEnd Len and From values are updated +// before calling the visitor function. +// +// On return f.Paths and f.MaxLen are set but not f.Leaves. +// +// Returned is the number of nodes visited and ok = true if the traversal +// ran to completion or ok = false if it was terminated by the visitor +// function returning false. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) BreadthFirst(start NI, r *rand.Rand, f *FromList, v OkNodeVisitor) (visited int, ok bool) { + switch { + case f == nil: + e := NewFromList(len(g)) + f = &e + case f.Paths == nil: + *f = NewFromList(len(g)) + } + rp := f.Paths + // the frontier consists of nodes all at the same level + frontier := []NI{start} + level := 1 + // assign path when node is put on frontier, + rp[start] = PathEnd{Len: level, From: -1} + for { + f.MaxLen = level + level++ + var next []NI + if r == nil { + for _, n := range frontier { + visited++ + if !v(n) { // visit nodes as they come off frontier + return + } + for _, nb := range g[n] { + if rp[nb].Len == 0 { + next = append(next, nb) + rp[nb] = PathEnd{From: n, Len: level} + } + } + } + } else { // take nodes off frontier at random + for _, i := range r.Perm(len(frontier)) { + n := frontier[i] + // remainder of block same as above + visited++ + if !v(n) { + return + } + for _, nb := range g[n] { + if rp[nb].Len == 0 { + next = append(next, nb) + rp[nb] = PathEnd{From: n, Len: level} + } + } + } + } + if len(next) == 0 { + break + } + frontier = next + } + return visited, true +} + +// BreadthFirstPath finds a single path from start to end with a minimum +// number of nodes. +// +// Returned is the path as list of nodes. +// The result is nil if no path was found. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) BreadthFirstPath(start, end NI) []NI { + var f FromList + g.BreadthFirst(start, nil, &f, func(n NI) bool { return n != end }) + return f.PathTo(end, nil) +} + +// Copy makes a deep copy of g. +// Copy also computes the arc size ma, the number of arcs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) Copy() (c AdjacencyList, ma int) { + c = make(AdjacencyList, len(g)) + for n, to := range g { + c[n] = append([]NI{}, to...) + ma += len(to) + } + return +} + +// DepthFirst traverses a graph depth first. +// +// As it traverses it calls visitor function v for each node. If v returns +// false at any point, the traversal is terminated immediately and DepthFirst +// returns false. Otherwise DepthFirst returns true. +// +// DepthFirst uses argument bm is used as a bitmap to guide the traversal. +// For a complete traversal, bm should be 0 initially. During the +// traversal, bits are set corresponding to each node visited. +// The bit is set before calling the visitor function. +// +// Argument bm can be nil if you have no need for it. +// In this case a bitmap is created internally for one-time use. +// +// Alternatively v can be nil. In this case traversal still proceeds and +// updates the bitmap, which can be a useful result. +// DepthFirst always returns true in this case. +// +// It makes no sense for both bm and v to be nil. In this case DepthFirst +// returns false immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) DepthFirst(start NI, bm *Bits, v OkNodeVisitor) (ok bool) { + if bm == nil { + if v == nil { + return false + } + bm = &Bits{} + } + var df func(n NI) bool + df = func(n NI) bool { + if bm.Bit(n) == 1 { + return true + } + bm.SetBit(n, 1) + if v != nil && !v(n) { + return false + } + for _, nb := range g[n] { + if !df(nb) { + return false + } + } + return true + } + return df(start) +} + +// DepthFirstRandom traverses a graph depth first, but following arcs in +// random order among arcs from a single node. +// +// If Rand r is nil, the method creates a new source and generator for +// one-time use. +// +// Usage is otherwise like the DepthFirst method. See DepthFirst. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) DepthFirstRandom(start NI, bm *Bits, v OkNodeVisitor, r *rand.Rand) (ok bool) { + if bm == nil { + if v == nil { + return false + } + bm = &Bits{} + } + if r == nil { + r = rand.New(rand.NewSource(time.Now().UnixNano())) + } + var df func(n NI) bool + df = func(n NI) bool { + if bm.Bit(n) == 1 { + return true + } + bm.SetBit(n, 1) + if v != nil && !v(n) { + return false + } + to := g[n] + for _, i := range r.Perm(len(to)) { + if !df(to[i]) { + return false + } + } + return true + } + return df(start) +} + +// HasArc returns true if g has any arc from node fr to node to. +// +// Also returned is the index within the slice of arcs from node fr. +// If no arc from fr to to is present, HasArc returns false, -1. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) HasArc(fr, to NI) (bool, int) { + for x, h := range g[fr] { + if h == to { + return true, x + } + } + return false, -1 +} + +// HasLoop identifies if a graph contains a loop, an arc that leads from a +// a node back to the same node. +// +// If the graph has a loop, the result is an example node that has a loop. +// +// If g contains a loop, the method returns true and an example of a node +// with a loop. If there are no loops in g, the method returns false, -1. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) HasLoop() (bool, NI) { + for fr, to := range g { + for _, to := range to { + if NI(fr) == to { + return true, to + } + } + } + return false, -1 +} + +// HasParallelMap 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 method returns true and +// 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. +// +// "Map" in the method name indicates that a Go map is used to detect parallel +// arcs. Compared to method HasParallelSort, this gives better asymtotic +// performance for large dense graphs but may have increased overhead for +// small or sparse graphs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) HasParallelMap() (has bool, fr, to NI) { + for n, to := range g { + if len(to) == 0 { + continue + } + m := map[NI]struct{}{} + for _, to := range to { + if _, ok := m[to]; ok { + return true, NI(n), to + } + m[to] = struct{}{} + } + } + return false, -1, -1 +} + +// IsSimple checks for loops and parallel arcs. +// +// A graph is "simple" if it has no loops or parallel arcs. +// +// IsSimple returns true, -1 for simple graphs. If a loop or parallel arc is +// found, simple returns false and a node that represents a counterexample +// to the graph being simple. +// +// See also separate methods HasLoop and HasParallel. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) IsSimple() (ok bool, n NI) { + if lp, n := g.HasLoop(); lp { + return false, n + } + if pa, n, _ := g.HasParallelSort(); pa { + return false, n + } + return true, -1 +} + +// IsolatedNodes returns a bitmap of isolated nodes in receiver graph g. +// +// An isolated node is one with no arcs going to or from it. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) IsolatedNodes() (i Bits) { + i.SetAll(len(g)) + for fr, to := range g { + if len(to) > 0 { + i.SetBit(NI(fr), 0) + for _, to := range to { + i.SetBit(to, 0) + } + } + } + return +} + +/* +MaxmimalClique finds a maximal clique containing the node n. + +Not sure this is good for anything. It produces a single maximal clique +but there can be multiple maximal cliques containing a given node. +This algorithm just returns one of them, not even necessarily the +largest one. + +func (g LabeledAdjacencyList) MaximalClique(n int) []int { + c := []int{n} + var m bitset.BitSet + m.Set(uint(n)) + for fr, to := range g { + if fr == n { + continue + } + if len(to) < len(c) { + continue + } + f := 0 + for _, to := range to { + if m.Test(uint(to.To)) { + f++ + if f == len(c) { + c = append(c, to.To) + m.Set(uint(to.To)) + break + } + } + } + } + return c +} +*/ diff --git a/vendor/github.com/soniakeys/graph/adj_cg.go b/vendor/github.com/soniakeys/graph/adj_cg.go new file mode 100644 index 0000000..a484ee0 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/adj_cg.go @@ -0,0 +1,387 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// adj_RO.go is code generated from adj_cg.go by directives in graph.go. +// Editing adj_cg.go is okay. +// DO NOT EDIT adj_RO.go. The RO is for Read Only. + +import ( + "math/rand" + "time" +) + +// ArcSize returns the number of arcs in g. +// +// Note that for an undirected graph without loops, the number of undirected +// edges -- the traditional meaning of graph size -- will be ArcSize()/2. +// On the other hand, if g is an undirected graph that has or may have loops, +// g.ArcSize()/2 is not a meaningful quantity. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) ArcSize() int { + m := 0 + for _, to := range g { + m += len(to) + } + return m +} + +// BoundsOk validates that all arcs in g stay within the slice bounds of g. +// +// BoundsOk returns true when no arcs point outside the bounds of g. +// Otherwise it returns false and an example arc that points outside of g. +// +// Most methods of this package assume the BoundsOk condition and may +// panic when they encounter an arc pointing outside of the graph. This +// function can be used to validate a graph when the BoundsOk condition +// is unknown. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) BoundsOk() (ok bool, fr NI, to Half) { + for fr, to := range g { + for _, to := range to { + if to.To < 0 || to.To >= NI(len(g)) { + return false, NI(fr), to + } + } + } + return true, -1, to +} + +// BreadthFirst traverses a directed or undirected graph in breadth first order. +// +// Argument start is the start node for the traversal. If r is nil, nodes are +// visited in deterministic order. If a random number generator is supplied, +// nodes at each level are visited in random order. +// +// Argument f can be nil if you have no interest in the FromList path result. +// If FromList f is non-nil, the method populates f.Paths and sets f.MaxLen. +// It does not set f.Leaves. For convenience argument f can be a zero value +// FromList. If f.Paths is nil, the FromList is initialized first. If f.Paths +// is non-nil however, the FromList is used as is. The method uses a value of +// PathEnd.Len == 0 to indentify unvisited nodes. Existing non-zero values +// will limit the traversal. +// +// Traversal calls the visitor function v for each node starting with node +// start. If v returns true, traversal continues. If v returns false, the +// traversal terminates immediately. PathEnd Len and From values are updated +// before calling the visitor function. +// +// On return f.Paths and f.MaxLen are set but not f.Leaves. +// +// Returned is the number of nodes visited and ok = true if the traversal +// ran to completion or ok = false if it was terminated by the visitor +// function returning false. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) BreadthFirst(start NI, r *rand.Rand, f *FromList, v OkNodeVisitor) (visited int, ok bool) { + switch { + case f == nil: + e := NewFromList(len(g)) + f = &e + case f.Paths == nil: + *f = NewFromList(len(g)) + } + rp := f.Paths + // the frontier consists of nodes all at the same level + frontier := []NI{start} + level := 1 + // assign path when node is put on frontier, + rp[start] = PathEnd{Len: level, From: -1} + for { + f.MaxLen = level + level++ + var next []NI + if r == nil { + for _, n := range frontier { + visited++ + if !v(n) { // visit nodes as they come off frontier + return + } + for _, nb := range g[n] { + if rp[nb.To].Len == 0 { + next = append(next, nb.To) + rp[nb.To] = PathEnd{From: n, Len: level} + } + } + } + } else { // take nodes off frontier at random + for _, i := range r.Perm(len(frontier)) { + n := frontier[i] + // remainder of block same as above + visited++ + if !v(n) { + return + } + for _, nb := range g[n] { + if rp[nb.To].Len == 0 { + next = append(next, nb.To) + rp[nb.To] = PathEnd{From: n, Len: level} + } + } + } + } + if len(next) == 0 { + break + } + frontier = next + } + return visited, true +} + +// BreadthFirstPath finds a single path from start to end with a minimum +// number of nodes. +// +// Returned is the path as list of nodes. +// The result is nil if no path was found. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) BreadthFirstPath(start, end NI) []NI { + var f FromList + g.BreadthFirst(start, nil, &f, func(n NI) bool { return n != end }) + return f.PathTo(end, nil) +} + +// Copy makes a deep copy of g. +// Copy also computes the arc size ma, the number of arcs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) Copy() (c LabeledAdjacencyList, ma int) { + c = make(LabeledAdjacencyList, len(g)) + for n, to := range g { + c[n] = append([]Half{}, to...) + ma += len(to) + } + return +} + +// DepthFirst traverses a graph depth first. +// +// As it traverses it calls visitor function v for each node. If v returns +// false at any point, the traversal is terminated immediately and DepthFirst +// returns false. Otherwise DepthFirst returns true. +// +// DepthFirst uses argument bm is used as a bitmap to guide the traversal. +// For a complete traversal, bm should be 0 initially. During the +// traversal, bits are set corresponding to each node visited. +// The bit is set before calling the visitor function. +// +// Argument bm can be nil if you have no need for it. +// In this case a bitmap is created internally for one-time use. +// +// Alternatively v can be nil. In this case traversal still proceeds and +// updates the bitmap, which can be a useful result. +// DepthFirst always returns true in this case. +// +// It makes no sense for both bm and v to be nil. In this case DepthFirst +// returns false immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) DepthFirst(start NI, bm *Bits, v OkNodeVisitor) (ok bool) { + if bm == nil { + if v == nil { + return false + } + bm = &Bits{} + } + var df func(n NI) bool + df = func(n NI) bool { + if bm.Bit(n) == 1 { + return true + } + bm.SetBit(n, 1) + if v != nil && !v(n) { + return false + } + for _, nb := range g[n] { + if !df(nb.To) { + return false + } + } + return true + } + return df(start) +} + +// DepthFirstRandom traverses a graph depth first, but following arcs in +// random order among arcs from a single node. +// +// If Rand r is nil, the method creates a new source and generator for +// one-time use. +// +// Usage is otherwise like the DepthFirst method. See DepthFirst. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) DepthFirstRandom(start NI, bm *Bits, v OkNodeVisitor, r *rand.Rand) (ok bool) { + if bm == nil { + if v == nil { + return false + } + bm = &Bits{} + } + if r == nil { + r = rand.New(rand.NewSource(time.Now().UnixNano())) + } + var df func(n NI) bool + df = func(n NI) bool { + if bm.Bit(n) == 1 { + return true + } + bm.SetBit(n, 1) + if v != nil && !v(n) { + return false + } + to := g[n] + for _, i := range r.Perm(len(to)) { + if !df(to[i].To) { + return false + } + } + return true + } + return df(start) +} + +// HasArc returns true if g has any arc from node fr to node to. +// +// Also returned is the index within the slice of arcs from node fr. +// If no arc from fr to to is present, HasArc returns false, -1. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) HasArc(fr, to NI) (bool, int) { + for x, h := range g[fr] { + if h.To == to { + return true, x + } + } + return false, -1 +} + +// HasLoop identifies if a graph contains a loop, an arc that leads from a +// a node back to the same node. +// +// If the graph has a loop, the result is an example node that has a loop. +// +// If g contains a loop, the method returns true and an example of a node +// with a loop. If there are no loops in g, the method returns false, -1. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) HasLoop() (bool, NI) { + for fr, to := range g { + for _, to := range to { + if NI(fr) == to.To { + return true, to.To + } + } + } + return false, -1 +} + +// HasParallelMap 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 method returns true and +// 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. +// +// "Map" in the method name indicates that a Go map is used to detect parallel +// arcs. Compared to method HasParallelSort, this gives better asymtotic +// performance for large dense graphs but may have increased overhead for +// small or sparse graphs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) HasParallelMap() (has bool, fr, to NI) { + for n, to := range g { + if len(to) == 0 { + continue + } + m := map[NI]struct{}{} + for _, to := range to { + if _, ok := m[to.To]; ok { + return true, NI(n), to.To + } + m[to.To] = struct{}{} + } + } + return false, -1, -1 +} + +// IsSimple checks for loops and parallel arcs. +// +// A graph is "simple" if it has no loops or parallel arcs. +// +// IsSimple returns true, -1 for simple graphs. If a loop or parallel arc is +// found, simple returns false and a node that represents a counterexample +// to the graph being simple. +// +// See also separate methods HasLoop and HasParallel. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) IsSimple() (ok bool, n NI) { + if lp, n := g.HasLoop(); lp { + return false, n + } + if pa, n, _ := g.HasParallelSort(); pa { + return false, n + } + return true, -1 +} + +// IsolatedNodes returns a bitmap of isolated nodes in receiver graph g. +// +// An isolated node is one with no arcs going to or from it. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) IsolatedNodes() (i Bits) { + i.SetAll(len(g)) + for fr, to := range g { + if len(to) > 0 { + i.SetBit(NI(fr), 0) + for _, to := range to { + i.SetBit(to.To, 0) + } + } + } + return +} + +/* +MaxmimalClique finds a maximal clique containing the node n. + +Not sure this is good for anything. It produces a single maximal clique +but there can be multiple maximal cliques containing a given node. +This algorithm just returns one of them, not even necessarily the +largest one. + +func (g LabeledAdjacencyList) MaximalClique(n int) []int { + c := []int{n} + var m bitset.BitSet + m.Set(uint(n)) + for fr, to := range g { + if fr == n { + continue + } + if len(to) < len(c) { + continue + } + f := 0 + for _, to := range to { + if m.Test(uint(to.To)) { + f++ + if f == len(c) { + c = append(c, to.To) + m.Set(uint(to.To)) + break + } + } + } + } + return c +} +*/ diff --git a/vendor/github.com/soniakeys/graph/bits.go b/vendor/github.com/soniakeys/graph/bits.go new file mode 100644 index 0000000..b86703c --- /dev/null +++ b/vendor/github.com/soniakeys/graph/bits.go @@ -0,0 +1,207 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +import ( + "fmt" + "math/big" +) + +// Bits is bitmap, or bitset, intended to store a single bit of information +// per node of a graph. +// +// The current implementation is backed by a big.Int and so is a reference +// type in the same way a big.Int is. +type Bits struct { + i big.Int +} + +// NewBits constructs a Bits value with the bits ns set to 1. +func NewBits(ns ...NI) (b Bits) { + for _, n := range ns { + b.SetBit(n, 1) + } + return +} + +// AllNot sets n bits of z to the complement of x. +// +// It is a convenience method for SetAll followed by AndNot. +func (z *Bits) AllNot(n int, x Bits) { + var y Bits + y.SetAll(n) + z.AndNot(y, x) +} + +// And sets z = x & y. +func (z *Bits) And(x, y Bits) { + z.i.And(&x.i, &y.i) +} + +// AndNot sets z = x &^ y. +func (z *Bits) AndNot(x, y Bits) { + z.i.AndNot(&x.i, &y.i) +} + +// Bit returns the value of the n'th bit of x. +func (b Bits) Bit(n NI) uint { + return b.i.Bit(int(n)) +} + +// Clear sets all bits to 0. +func (z *Bits) Clear() { + *z = Bits{} +} + +// Format satisfies fmt.Formatter for fmt.Printf and related methods. +// +// graph.Bits format exactly like big.Ints. +func (b Bits) Format(s fmt.State, ch rune) { + b.i.Format(s, ch) +} + +// From returns the position of the first 1 bit at or after (from) position n. +// +// It returns -1 if there is no one bit at or after position n. +// +// This provides one way to iterate over one bits. +// To iterate over the one bits, call with n = 0 to get the the first +// one bit, then call with the result + 1 to get successive one bits. +// Unlike the Iterate method, this technique is stateless and so allows +// bits to be changed between successive calls. +// +// See also Iterate. +// +// (From is just a short word that means "at or after" here; +// it has nothing to do with arc direction.) +func (b Bits) From(n NI) NI { + words := b.i.Bits() + i := int(n) + x := i >> wordExp // x now index of word containing bit i. + if x >= len(words) { + return -1 + } + // test for 1 in this word at or after n + if wx := words[x] >> (uint(i) & (wordSize - 1)); wx != 0 { + return n + NI(trailingZeros(wx)) + } + x++ + for y, wy := range words[x:] { + if wy != 0 { + return NI((x+y)<<wordExp | trailingZeros(wy)) + } + } + return -1 +} + +// Iterate calls Visitor v for each bit with a value of 1, in order +// from lowest bit to highest bit. +// +// Iteration continues to the highest bit as long as v returns true. +// It stops if v returns false. +// +// Iterate returns true normally. It returns false if v returns false. +// +// Bit values should not be modified during iteration, by the visitor function +// for example. See From for an iteration method that allows modification. +func (b Bits) Iterate(v OkNodeVisitor) bool { + for x, w := range b.i.Bits() { + if w != 0 { + t := trailingZeros(w) + i := t // index in w of next 1 bit + for { + if !v(NI(x<<wordExp | i)) { + return false + } + w >>= uint(t + 1) + if w == 0 { + break + } + t = trailingZeros(w) + i += 1 + t + } + } + } + return true +} + +// Or sets z = x | y. +func (z *Bits) Or(x, y Bits) { + z.i.Or(&x.i, &y.i) +} + +// PopCount returns the number of 1 bits. +func (b Bits) PopCount() (c int) { + // algorithm selected to be efficient for sparse bit sets. + for _, w := range b.i.Bits() { + for w != 0 { + w &= w - 1 + c++ + } + } + return +} + +// Set sets the bits of z to the bits of x. +func (z *Bits) Set(x Bits) { + z.i.Set(&x.i) +} + +var one = big.NewInt(1) + +// SetAll sets z to have n 1 bits. +// +// It's useful for initializing z to have a 1 for each node of a graph. +func (z *Bits) SetAll(n int) { + z.i.Sub(z.i.Lsh(one, uint(n)), one) +} + +// SetBit sets the n'th bit to b, where be is a 0 or 1. +func (z *Bits) SetBit(n NI, b uint) { + z.i.SetBit(&z.i, int(n), b) +} + +// Single returns true if b has exactly one 1 bit. +func (b Bits) Single() bool { + // like PopCount, but stop as soon as two are found + c := 0 + for _, w := range b.i.Bits() { + for w != 0 { + w &= w - 1 + c++ + if c == 2 { + return false + } + } + } + return c == 1 +} + +// Slice returns a slice with the positions of each 1 bit. +func (b Bits) Slice() (s []NI) { + // (alternative implementation might use Popcount and make to get the + // exact cap slice up front. unclear if that would be better.) + b.Iterate(func(n NI) bool { + s = append(s, n) + return true + }) + return +} + +// Xor sets z = x ^ y. +func (z *Bits) Xor(x, y Bits) { + z.i.Xor(&x.i, &y.i) +} + +// Zero returns true if there are no 1 bits. +func (b Bits) Zero() bool { + return len(b.i.Bits()) == 0 +} + +// trailingZeros returns the number of trailing 0 bits in v. +// +// If v is 0, it returns 0. +func trailingZeros(v big.Word) int { + return deBruijnBits[v&-v*deBruijnMultiple>>deBruijnShift] +} diff --git a/vendor/github.com/soniakeys/graph/bits32.go b/vendor/github.com/soniakeys/graph/bits32.go new file mode 100644 index 0000000..18e07f9 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/bits32.go @@ -0,0 +1,23 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +// +build 386 arm + +package graph + +// "word" here is math/big.Word +const ( + wordSize = 32 + wordExp = 5 // 2^5 = 32 +) + +// deBruijn magic numbers used in trailingZeros() +// +// reference: http://graphics.stanford.edu/~seander/bithacks.html +const deBruijnMultiple = 0x077CB531 +const deBruijnShift = 27 + +var deBruijnBits = []int{ + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9, +} diff --git a/vendor/github.com/soniakeys/graph/bits64.go b/vendor/github.com/soniakeys/graph/bits64.go new file mode 100644 index 0000000..ab601dd --- /dev/null +++ b/vendor/github.com/soniakeys/graph/bits64.go @@ -0,0 +1,22 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +// +build !386,!arm + +package graph + +const ( + wordSize = 64 + wordExp = 6 // 2^6 = 64 +) + +// reference: http://graphics.stanford.edu/~seander/bithacks.html +const deBruijnMultiple = 0x03f79d71b4ca8b09 +const deBruijnShift = 58 + +var deBruijnBits = []int{ + 0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4, + 62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5, + 63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11, + 54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6, +} diff --git a/vendor/github.com/soniakeys/graph/dir.go b/vendor/github.com/soniakeys/graph/dir.go new file mode 100644 index 0000000..508306d --- /dev/null +++ b/vendor/github.com/soniakeys/graph/dir.go @@ -0,0 +1,538 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// dir.go has methods specific to directed graphs, types Directed and +// LabeledDirected. +// +// Methods on Directed are first, with exported methods alphabetized. + +import "errors" + +// DAGMaxLenPath finds a maximum length path in a directed acyclic graph. +// +// Argument ordering must be a topological ordering of g. +func (g Directed) DAGMaxLenPath(ordering []NI) (path []NI) { + // dynamic programming. visit nodes in reverse order. for each, compute + // longest path as one plus longest of 'to' nodes. + // Visits each arc once. O(m). + // + // Similar code in label.go + var n NI + mlp := make([][]NI, len(g.AdjacencyList)) // index by node number + for i := len(ordering) - 1; i >= 0; i-- { + fr := ordering[i] // node number + to := g.AdjacencyList[fr] + if len(to) == 0 { + continue + } + mt := to[0] + for _, to := range to[1:] { + if len(mlp[to]) > len(mlp[mt]) { + mt = to + } + } + p := append([]NI{mt}, mlp[mt]...) + mlp[fr] = p + if len(p) > len(path) { + n = fr + path = p + } + } + return append([]NI{n}, path...) +} + +// EulerianCycle finds an Eulerian cycle in a directed multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The cycle result is a list of nodes, where the first and last +// nodes are the same. +// +// * Otherwise, result is nil, error +// +// Internally, EulerianCycle copies the entire graph g. +// See EulerianCycleD for a more space efficient version. +func (g Directed) EulerianCycle() ([]NI, error) { + c, m := g.Copy() + return c.EulerianCycleD(m) +} + +// EulerianCycleD finds an Eulerian cycle in a directed multigraph. +// +// EulerianCycleD is destructive on its receiver g. See EulerianCycle for +// a non-destructive version. +// +// Argument ma must be the correct arc size, or number of arcs in g. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The cycle result is a list of nodes, where the first and last +// nodes are the same. +// +// * Otherwise, result is nil, error +func (g Directed) EulerianCycleD(ma int) ([]NI, error) { + if len(g.AdjacencyList) == 0 { + return nil, nil + } + e := newEulerian(g.AdjacencyList, ma) + for e.s >= 0 { + v := e.top() // v is node that starts cycle + e.push() + // if Eulerian, we'll always come back to starting node + if e.top() != v { + return nil, errors.New("not balanced") + } + e.keep() + } + if !e.uv.Zero() { + return nil, errors.New("not strongly connected") + } + return e.p, nil +} + +// EulerianPath finds an Eulerian path in a directed multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path, result is an Eulerian path with err = nil. +// The path result is a list of nodes, where the first node is start. +// +// * Otherwise, result is nil, error +// +// Internally, EulerianPath copies the entire graph g. +// See EulerianPathD for a more space efficient version. +func (g Directed) EulerianPath() ([]NI, error) { + ind := g.InDegree() + var start NI + for n, to := range g.AdjacencyList { + if len(to) > ind[n] { + start = NI(n) + break + } + } + c, m := g.Copy() + return c.EulerianPathD(m, start) +} + +// EulerianPathD finds an Eulerian path in a directed multigraph. +// +// EulerianPathD is destructive on its receiver g. See EulerianPath for +// a non-destructive version. +// +// Argument ma must be the correct arc size, or number of arcs in g. +// Argument start must be a valid start node for the path. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path, result is an Eulerian path with err = nil. +// The path result is a list of nodes, where the first node is start. +// +// * Otherwise, result is nil, error +func (g Directed) EulerianPathD(ma int, start NI) ([]NI, error) { + if len(g.AdjacencyList) == 0 { + return nil, nil + } + e := newEulerian(g.AdjacencyList, ma) + e.p[0] = start + // unlike EulerianCycle, the first path doesn't have be a cycle. + e.push() + e.keep() + for e.s >= 0 { + start = e.top() + e.push() + // paths after the first must be cycles though + // (as long as there are nodes on the stack) + if e.top() != start { + return nil, errors.New("no Eulerian path") + } + e.keep() + } + if !e.uv.Zero() { + return nil, errors.New("no Eulerian path") + } + return e.p, nil +} + +// starting at the node on the top of the stack, follow arcs until stuck. +// mark nodes visited, push nodes on stack, remove arcs from g. +func (e *eulerian) push() { + for u := e.top(); ; { + e.uv.SetBit(u, 0) // reset unvisited bit + arcs := e.g[u] + if len(arcs) == 0 { + return // stuck + } + w := arcs[0] // follow first arc + e.s++ // push followed node on stack + e.p[e.s] = w + e.g[u] = arcs[1:] // consume arc + u = w + } +} + +// like push, but for for undirected graphs. +func (e *eulerian) pushUndir() { + for u := e.top(); ; { + e.uv.SetBit(u, 0) + arcs := e.g[u] + if len(arcs) == 0 { + return + } + w := arcs[0] + e.s++ + e.p[e.s] = w + e.g[u] = arcs[1:] // consume arc + // here is the only difference, consume reciprocal arc as well: + a2 := e.g[w] + for x, rx := range a2 { + if rx == u { // here it is + last := len(a2) - 1 + a2[x] = a2[last] // someone else gets the seat + e.g[w] = a2[:last] // and it's gone. + break + } + } + u = w + } +} + +// starting with the node on top of the stack, move nodes with no arcs. +func (e *eulerian) keep() { + for e.s >= 0 { + n := e.top() + if len(e.g[n]) > 0 { + break + } + e.p[e.m] = n + e.s-- + e.m-- + } +} + +type eulerian struct { + g AdjacencyList // working copy of graph, it gets consumed + m int // number of arcs in g, updated as g is consumed + uv Bits // unvisited + // low end of p is stack of unfinished nodes + // high end is finished path + p []NI // stack + path + s int // stack pointer +} + +func (e *eulerian) top() NI { + return e.p[e.s] +} + +func newEulerian(g AdjacencyList, m int) *eulerian { + e := &eulerian{ + g: g, + m: m, + p: make([]NI, m+1), + } + e.uv.SetAll(len(g)) + return e +} + +// MaximalNonBranchingPaths finds all paths in a directed graph that are +// "maximal" and "non-branching". +// +// A non-branching path is one where path nodes other than the first and last +// have exactly one arc leading to the node and one arc leading from the node, +// thus there is no possibility to branch away to a different path. +// +// A maximal non-branching path cannot be extended to a longer non-branching +// path by including another node at either end. +// +// In the case of a cyclic non-branching path, the first and last elements +// of the path will be the same node, indicating an isolated cycle. +// +// The method calls the emit argument for each path or isolated cycle in g, +// as long as emit returns true. If emit returns false, +// MaximalNonBranchingPaths returns immediately. +func (g Directed) MaximalNonBranchingPaths(emit func([]NI) bool) { + ind := g.InDegree() + var uv Bits + uv.SetAll(len(g.AdjacencyList)) + for v, vTo := range g.AdjacencyList { + if !(ind[v] == 1 && len(vTo) == 1) { + for _, w := range vTo { + n := []NI{NI(v), w} + uv.SetBit(NI(v), 0) + uv.SetBit(w, 0) + wTo := g.AdjacencyList[w] + for ind[w] == 1 && len(wTo) == 1 { + u := wTo[0] + n = append(n, u) + uv.SetBit(u, 0) + w = u + wTo = g.AdjacencyList[w] + } + if !emit(n) { // n is a path + return + } + } + } + } + // use uv.From rather than uv.Iterate. + // Iterate doesn't work here because we're modifying uv + for b := uv.From(0); b >= 0; b = uv.From(b + 1) { + v := NI(b) + n := []NI{v} + for w := v; ; { + w = g.AdjacencyList[w][0] + uv.SetBit(w, 0) + n = append(n, w) + if w == v { + break + } + } + if !emit(n) { // n is an isolated cycle + return + } + } +} + +// Undirected returns copy of g augmented as needed to make it undirected. +func (g Directed) Undirected() Undirected { + c, _ := g.AdjacencyList.Copy() // start with a copy + rw := make(AdjacencyList, len(g.AdjacencyList)) // "reciprocals wanted" + for fr, to := range g.AdjacencyList { + arc: // for each arc in g + for _, to := range to { + if to == NI(fr) { + continue // loop + } + // search wanted arcs + wf := rw[fr] + for i, w := range wf { + if w == to { // found, remove + last := len(wf) - 1 + wf[i] = wf[last] + rw[fr] = wf[:last] + continue arc + } + } + // arc not found, add to reciprocal to wanted list + rw[to] = append(rw[to], NI(fr)) + } + } + // add missing reciprocals + for fr, to := range rw { + c[fr] = append(c[fr], to...) + } + return Undirected{c} +} + +// StronglyConnectedComponents identifies strongly connected components +// in a directed graph. +// +// Algorithm by David J. Pearce, from "An Improved Algorithm for Finding the +// Strongly Connected Components of a Directed Graph". It is algorithm 3, +// PEA_FIND_SCC2 in +// http://homepages.mcs.vuw.ac.nz/~djp/files/P05.pdf, accessed 22 Feb 2015. +// +// Returned is a list of components, each component is a list of nodes. +/* +func (g Directed) StronglyConnectedComponents() []int { + rindex := make([]int, len(g)) + S := []int{} + index := 1 + c := len(g) - 1 + visit := func(v int) { + root := true + rindex[v] = index + index++ + for _, w := range g[v] { + if rindex[w] == 0 { + visit(w) + } + if rindex[w] < rindex[v] { + rindex[v] = rindex[w] + root = false + } + } + if root { + index-- + for top := len(S) - 1; top >= 0 && rindex[v] <= rindex[top]; top-- { + w = rindex[top] + S = S[:top] + rindex[w] = c + index-- + } + rindex[v] = c + c-- + } else { + S = append(S, v) + } + } + for v := range g { + if rindex[v] == 0 { + visit(v) + } + } + return rindex +} +*/ + +// Transpose constructs a new adjacency list with all arcs reversed. +// +// For every arc from->to of g, the result will have an arc to->from. +// Transpose also counts arcs as it traverses and returns ma the number of arcs +// in g (equal to the number of arcs in the result.) +func (g Directed) Transpose() (t Directed, ma int) { + ta := make(AdjacencyList, len(g.AdjacencyList)) + for n, nbs := range g.AdjacencyList { + for _, nb := range nbs { + ta[nb] = append(ta[nb], NI(n)) + ma++ + } + } + return Directed{ta}, ma +} + +// DAGMaxLenPath finds a maximum length path in a directed acyclic graph. +// +// Length here means number of nodes or arcs, not a sum of arc weights. +// +// Argument ordering must be a topological ordering of g. +// +// Returned is a node beginning a maximum length path, and a path of arcs +// starting from that node. +func (g LabeledDirected) DAGMaxLenPath(ordering []NI) (n NI, path []Half) { + // dynamic programming. visit nodes in reverse order. for each, compute + // longest path as one plus longest of 'to' nodes. + // Visits each arc once. Time complexity O(m). + // + // Similar code in dir.go. + mlp := make([][]Half, len(g.LabeledAdjacencyList)) // index by node number + for i := len(ordering) - 1; i >= 0; i-- { + fr := ordering[i] // node number + to := g.LabeledAdjacencyList[fr] + if len(to) == 0 { + continue + } + mt := to[0] + for _, to := range to[1:] { + if len(mlp[to.To]) > len(mlp[mt.To]) { + mt = to + } + } + p := append([]Half{mt}, mlp[mt.To]...) + mlp[fr] = p + if len(p) > len(path) { + n = fr + path = p + } + } + return +} + +// FromListLabels transposes a labeled graph into a FromList and associated +// list of labels. +// +// Receiver g should be connected as a tree or forest. Specifically no node +// can have multiple incoming arcs. If any node n in g has multiple incoming +// arcs, the method returns (nil, nil, n) where n is a node with multiple +// incoming arcs. +// +// Otherwise (normally) the method populates the From members in a +// FromList.Path, populates a slice of labels, and returns the FromList, +// labels, and -1. +// +// Other members of the FromList are left as zero values. +// Use FromList.RecalcLen and FromList.RecalcLeaves as needed. +func (g LabeledDirected) FromListLabels() (*FromList, []LI, NI) { + labels := make([]LI, len(g.LabeledAdjacencyList)) + paths := make([]PathEnd, len(g.LabeledAdjacencyList)) + for i := range paths { + paths[i].From = -1 + } + for fr, to := range g.LabeledAdjacencyList { + for _, to := range to { + if paths[to.To].From >= 0 { + return nil, nil, to.To + } + paths[to.To].From = NI(fr) + labels[to.To] = to.Label + } + } + return &FromList{Paths: paths}, labels, -1 +} + +// Transpose constructs a new adjacency list that is the transpose of g. +// +// For every arc from->to of g, the result will have an arc to->from. +// Transpose also counts arcs as it traverses and returns ma the number of +// arcs in g (equal to the number of arcs in the result.) +func (g LabeledDirected) Transpose() (t LabeledDirected, ma int) { + ta := make(LabeledAdjacencyList, len(g.LabeledAdjacencyList)) + for n, nbs := range g.LabeledAdjacencyList { + for _, nb := range nbs { + ta[nb.To] = append(ta[nb.To], Half{To: NI(n), Label: nb.Label}) + ma++ + } + } + return LabeledDirected{ta}, ma +} + +// Undirected returns a new undirected graph derived from g, augmented as +// needed to make it undirected, with reciprocal arcs having matching labels. +func (g LabeledDirected) Undirected() LabeledUndirected { + c, _ := g.LabeledAdjacencyList.Copy() // start with a copy + // "reciprocals wanted" + rw := make(LabeledAdjacencyList, len(g.LabeledAdjacencyList)) + for fr, to := range g.LabeledAdjacencyList { + arc: // for each arc in g + for _, to := range to { + if to.To == NI(fr) { + continue // arc is a loop + } + // search wanted arcs + wf := rw[fr] + for i, w := range wf { + if w == to { // found, remove + last := len(wf) - 1 + wf[i] = wf[last] + rw[fr] = wf[:last] + continue arc + } + } + // arc not found, add to reciprocal to wanted list + rw[to.To] = append(rw[to.To], Half{To: NI(fr), Label: to.Label}) + } + } + // add missing reciprocals + for fr, to := range rw { + c[fr] = append(c[fr], to...) + } + return LabeledUndirected{c} +} + +// Unlabeled constructs the unlabeled directed graph corresponding to g. +func (g LabeledDirected) Unlabeled() Directed { + return Directed{g.LabeledAdjacencyList.Unlabeled()} +} + +// UnlabeledTranspose constructs a new adjacency list that is the unlabeled +// transpose of g. +// +// For every arc from->to of g, the result will have an arc to->from. +// Transpose also counts arcs as it traverses and returns ma, the number of +// arcs in g (equal to the number of arcs in the result.) +// +// It is equivalent to g.Unlabeled().Transpose() but constructs the result +// directly. +func (g LabeledDirected) UnlabeledTranspose() (t Directed, ma int) { + ta := make(AdjacencyList, len(g.LabeledAdjacencyList)) + for n, nbs := range g.LabeledAdjacencyList { + for _, nb := range nbs { + ta[nb.To] = append(ta[nb.To], NI(n)) + ma++ + } + } + return Directed{ta}, ma +} diff --git a/vendor/github.com/soniakeys/graph/dir_RO.go b/vendor/github.com/soniakeys/graph/dir_RO.go new file mode 100644 index 0000000..77558a9 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/dir_RO.go @@ -0,0 +1,395 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// dir_RO.go is code generated from dir_cg.go by directives in graph.go. +// Editing dir_cg.go is okay. It is the code generation source. +// DO NOT EDIT dir_RO.go. +// The RO means read only and it is upper case RO to slow you down a bit +// in case you start to edit the file. + +// Balanced returns true if for every node in g, in-degree equals out-degree. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) Balanced() bool { + for n, in := range g.InDegree() { + if in != len(g.AdjacencyList[n]) { + return false + } + } + return true +} + +// Copy makes a deep copy of g. +// Copy also computes the arc size ma, the number of arcs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) Copy() (c Directed, ma int) { + l, s := g.AdjacencyList.Copy() + return Directed{l}, s +} + +// Cyclic determines if g contains a cycle, a non-empty path from a node +// back to itself. +// +// Cyclic returns true if g contains at least one cycle. It also returns +// an example of an arc involved in a cycle. +// Cyclic returns false if g is acyclic. +// +// Also see Topological, which detects cycles. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) Cyclic() (cyclic bool, fr NI, to NI) { + a := g.AdjacencyList + fr, to = -1, -1 + var temp, perm Bits + var df func(NI) + df = func(n NI) { + switch { + case temp.Bit(n) == 1: + cyclic = true + return + case perm.Bit(n) == 1: + return + } + temp.SetBit(n, 1) + for _, nb := range a[n] { + df(nb) + if cyclic { + if fr < 0 { + fr, to = n, nb + } + return + } + } + temp.SetBit(n, 0) + perm.SetBit(n, 1) + } + for n := range a { + if perm.Bit(NI(n)) == 1 { + continue + } + if df(NI(n)); cyclic { // short circuit as soon as a cycle is found + break + } + } + return +} + +// FromList transposes a labeled graph into a FromList. +// +// Receiver g should be connected as a tree or forest. Specifically no node +// can have multiple incoming arcs. If any node n in g has multiple incoming +// arcs, the method returns (nil, n) where n is a node with multiple +// incoming arcs. +// +// Otherwise (normally) the method populates the From members in a +// FromList.Path and returns the FromList and -1. +// +// Other members of the FromList are left as zero values. +// Use FromList.RecalcLen and FromList.RecalcLeaves as needed. +// +// Unusual cases are parallel arcs and loops. A parallel arc represents +// a case of multiple arcs going to some node and so will lead to a (nil, n) +// return, even though a graph might be considered a multigraph tree. +// A single loop on a node that would otherwise be a root node, though, +// is not a case of multiple incoming arcs and so does not force a (nil, n) +// result. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) FromList() (*FromList, NI) { + paths := make([]PathEnd, len(g.AdjacencyList)) + for i := range paths { + paths[i].From = -1 + } + for fr, to := range g.AdjacencyList { + for _, to := range to { + if paths[to].From >= 0 { + return nil, to + } + paths[to].From = NI(fr) + } + } + return &FromList{Paths: paths}, -1 +} + +// InDegree computes the in-degree of each node in g +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) InDegree() []int { + ind := make([]int, len(g.AdjacencyList)) + for _, nbs := range g.AdjacencyList { + for _, nb := range nbs { + ind[nb]++ + } + } + return ind +} + +// IsTree identifies trees in directed graphs. +// +// Return value isTree is true if the subgraph reachable from root is a tree. +// Further, return value allTree is true if the entire graph g is reachable +// from root. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) IsTree(root NI) (isTree, allTree bool) { + a := g.AdjacencyList + var v Bits + v.SetAll(len(a)) + var df func(NI) bool + df = func(n NI) bool { + if v.Bit(n) == 0 { + return false + } + v.SetBit(n, 0) + for _, to := range a[n] { + if !df(to) { + return false + } + } + return true + } + isTree = df(root) + return isTree, isTree && v.Zero() +} + +// Tarjan identifies strongly connected components in a directed graph using +// Tarjan's algorithm. +// +// The method calls the emit argument for each component identified. Each +// component is a list of nodes. A property of the algorithm is that +// components are emitted in reverse topological order of the condensation. +// (See https://en.wikipedia.org/wiki/Strongly_connected_component#Definitions +// for description of condensation.) +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also TarjanForward and TarjanCondensation. +func (g Directed) Tarjan(emit func([]NI) bool) { + // See "Depth-first search and linear graph algorithms", Robert Tarjan, + // SIAM J. Comput. Vol. 1, No. 2, June 1972. + // + // Implementation here from Wikipedia pseudocode, + // http://en.wikipedia.org/w/index.php?title=Tarjan%27s_strongly_connected_components_algorithm&direction=prev&oldid=647184742 + var indexed, stacked Bits + a := g.AdjacencyList + index := make([]int, len(a)) + lowlink := make([]int, len(a)) + x := 0 + var S []NI + var sc func(NI) bool + sc = func(n NI) bool { + index[n] = x + indexed.SetBit(n, 1) + lowlink[n] = x + x++ + S = append(S, n) + stacked.SetBit(n, 1) + for _, nb := range a[n] { + if indexed.Bit(nb) == 0 { + if !sc(nb) { + return false + } + if lowlink[nb] < lowlink[n] { + lowlink[n] = lowlink[nb] + } + } else if stacked.Bit(nb) == 1 { + if index[nb] < lowlink[n] { + lowlink[n] = index[nb] + } + } + } + if lowlink[n] == index[n] { + var c []NI + for { + last := len(S) - 1 + w := S[last] + S = S[:last] + stacked.SetBit(w, 0) + c = append(c, w) + if w == n { + if !emit(c) { + return false + } + break + } + } + } + return true + } + for n := range a { + if indexed.Bit(NI(n)) == 0 && !sc(NI(n)) { + return + } + } +} + +// TarjanForward returns strongly connected components. +// +// It returns components in the reverse order of Tarjan, for situations +// where a forward topological ordering is easier. +func (g Directed) TarjanForward() [][]NI { + var r [][]NI + g.Tarjan(func(c []NI) bool { + r = append(r, c) + return true + }) + scc := make([][]NI, len(r)) + last := len(r) - 1 + for i, ci := range r { + scc[last-i] = ci + } + return scc +} + +// TarjanCondensation returns strongly connected components and their +// condensation graph. +// +// Components are ordered in a forward topological ordering. +func (g Directed) TarjanCondensation() (scc [][]NI, cd AdjacencyList) { + scc = g.TarjanForward() + cd = make(AdjacencyList, len(scc)) // return value + cond := make([]NI, len(g.AdjacencyList)) // mapping from g node to cd node + for cn := NI(len(scc) - 1); cn >= 0; cn-- { + c := scc[cn] + for _, n := range c { + cond[n] = NI(cn) // map g node to cd node + } + var tos []NI // list of 'to' nodes + var m Bits // tos map + m.SetBit(cn, 1) + for _, n := range c { + for _, to := range g.AdjacencyList[n] { + if ct := cond[to]; m.Bit(ct) == 0 { + m.SetBit(ct, 1) + tos = append(tos, ct) + } + } + } + cd[cn] = tos + } + return +} + +// Topological computes a topological ordering of a directed acyclic graph. +// +// For an acyclic graph, return value ordering is a permutation of node numbers +// in topologically sorted order and cycle will be nil. If the graph is found +// to be cyclic, ordering will be nil and cycle will be the path of a found +// cycle. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) Topological() (ordering, cycle []NI) { + a := g.AdjacencyList + ordering = make([]NI, len(a)) + i := len(ordering) + var temp, perm Bits + var cycleFound bool + var cycleStart NI + var df func(NI) + df = func(n NI) { + switch { + case temp.Bit(n) == 1: + cycleFound = true + cycleStart = n + return + case perm.Bit(n) == 1: + return + } + temp.SetBit(n, 1) + for _, nb := range a[n] { + df(nb) + if cycleFound { + if cycleStart >= 0 { + // a little hack: orderng won't be needed so repurpose the + // slice as cycle. this is read out in reverse order + // as the recursion unwinds. + x := len(ordering) - 1 - len(cycle) + ordering[x] = n + cycle = ordering[x:] + if n == cycleStart { + cycleStart = -1 + } + } + return + } + } + temp.SetBit(n, 0) + perm.SetBit(n, 1) + i-- + ordering[i] = n + } + for n := range a { + if perm.Bit(NI(n)) == 1 { + continue + } + df(NI(n)) + if cycleFound { + return nil, cycle + } + } + return ordering, nil +} + +// TopologicalKahn computes a topological ordering of a directed acyclic graph. +// +// For an acyclic graph, return value ordering is a permutation of node numbers +// in topologically sorted order and cycle will be nil. If the graph is found +// to be cyclic, ordering will be nil and cycle will be the path of a found +// cycle. +// +// This function is based on the algorithm by Arthur Kahn and requires the +// transpose of g be passed as the argument. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) TopologicalKahn(tr Directed) (ordering, cycle []NI) { + // code follows Wikipedia pseudocode. + var L, S []NI + // rem for "remaining edges," this function makes a local copy of the + // in-degrees and consumes that instead of consuming an input. + rem := make([]int, len(g.AdjacencyList)) + for n, fr := range tr.AdjacencyList { + if len(fr) == 0 { + // accumulate "set of all nodes with no incoming edges" + S = append(S, NI(n)) + } else { + // initialize rem from in-degree + rem[n] = len(fr) + } + } + for len(S) > 0 { + last := len(S) - 1 // "remove a node n from S" + n := S[last] + S = S[:last] + L = append(L, n) // "add n to tail of L" + for _, m := range g.AdjacencyList[n] { + // WP pseudo code reads "for each node m..." but it means for each + // node m *remaining in the graph.* We consume rem rather than + // the graph, so "remaining in the graph" for us means rem[m] > 0. + if rem[m] > 0 { + rem[m]-- // "remove edge from the graph" + if rem[m] == 0 { // if "m has no other incoming edges" + S = append(S, m) // "insert m into S" + } + } + } + } + // "If graph has edges," for us means a value in rem is > 0. + for c, in := range rem { + if in > 0 { + // recover cyclic nodes + for _, nb := range g.AdjacencyList[c] { + if rem[nb] > 0 { + cycle = append(cycle, NI(c)) + break + } + } + } + } + if len(cycle) > 0 { + return nil, cycle + } + return L, nil +} diff --git a/vendor/github.com/soniakeys/graph/dir_cg.go b/vendor/github.com/soniakeys/graph/dir_cg.go new file mode 100644 index 0000000..2b82f4f --- /dev/null +++ b/vendor/github.com/soniakeys/graph/dir_cg.go @@ -0,0 +1,395 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// dir_RO.go is code generated from dir_cg.go by directives in graph.go. +// Editing dir_cg.go is okay. It is the code generation source. +// DO NOT EDIT dir_RO.go. +// The RO means read only and it is upper case RO to slow you down a bit +// in case you start to edit the file. + +// Balanced returns true if for every node in g, in-degree equals out-degree. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) Balanced() bool { + for n, in := range g.InDegree() { + if in != len(g.LabeledAdjacencyList[n]) { + return false + } + } + return true +} + +// Copy makes a deep copy of g. +// Copy also computes the arc size ma, the number of arcs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) Copy() (c LabeledDirected, ma int) { + l, s := g.LabeledAdjacencyList.Copy() + return LabeledDirected{l}, s +} + +// Cyclic determines if g contains a cycle, a non-empty path from a node +// back to itself. +// +// Cyclic returns true if g contains at least one cycle. It also returns +// an example of an arc involved in a cycle. +// Cyclic returns false if g is acyclic. +// +// Also see Topological, which detects cycles. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) Cyclic() (cyclic bool, fr NI, to Half) { + a := g.LabeledAdjacencyList + fr, to.To = -1, -1 + var temp, perm Bits + var df func(NI) + df = func(n NI) { + switch { + case temp.Bit(n) == 1: + cyclic = true + return + case perm.Bit(n) == 1: + return + } + temp.SetBit(n, 1) + for _, nb := range a[n] { + df(nb.To) + if cyclic { + if fr < 0 { + fr, to = n, nb + } + return + } + } + temp.SetBit(n, 0) + perm.SetBit(n, 1) + } + for n := range a { + if perm.Bit(NI(n)) == 1 { + continue + } + if df(NI(n)); cyclic { // short circuit as soon as a cycle is found + break + } + } + return +} + +// FromList transposes a labeled graph into a FromList. +// +// Receiver g should be connected as a tree or forest. Specifically no node +// can have multiple incoming arcs. If any node n in g has multiple incoming +// arcs, the method returns (nil, n) where n is a node with multiple +// incoming arcs. +// +// Otherwise (normally) the method populates the From members in a +// FromList.Path and returns the FromList and -1. +// +// Other members of the FromList are left as zero values. +// Use FromList.RecalcLen and FromList.RecalcLeaves as needed. +// +// Unusual cases are parallel arcs and loops. A parallel arc represents +// a case of multiple arcs going to some node and so will lead to a (nil, n) +// return, even though a graph might be considered a multigraph tree. +// A single loop on a node that would otherwise be a root node, though, +// is not a case of multiple incoming arcs and so does not force a (nil, n) +// result. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) FromList() (*FromList, NI) { + paths := make([]PathEnd, len(g.LabeledAdjacencyList)) + for i := range paths { + paths[i].From = -1 + } + for fr, to := range g.LabeledAdjacencyList { + for _, to := range to { + if paths[to.To].From >= 0 { + return nil, to.To + } + paths[to.To].From = NI(fr) + } + } + return &FromList{Paths: paths}, -1 +} + +// InDegree computes the in-degree of each node in g +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) InDegree() []int { + ind := make([]int, len(g.LabeledAdjacencyList)) + for _, nbs := range g.LabeledAdjacencyList { + for _, nb := range nbs { + ind[nb.To]++ + } + } + return ind +} + +// IsTree identifies trees in directed graphs. +// +// Return value isTree is true if the subgraph reachable from root is a tree. +// Further, return value allTree is true if the entire graph g is reachable +// from root. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) IsTree(root NI) (isTree, allTree bool) { + a := g.LabeledAdjacencyList + var v Bits + v.SetAll(len(a)) + var df func(NI) bool + df = func(n NI) bool { + if v.Bit(n) == 0 { + return false + } + v.SetBit(n, 0) + for _, to := range a[n] { + if !df(to.To) { + return false + } + } + return true + } + isTree = df(root) + return isTree, isTree && v.Zero() +} + +// Tarjan identifies strongly connected components in a directed graph using +// Tarjan's algorithm. +// +// The method calls the emit argument for each component identified. Each +// component is a list of nodes. A property of the algorithm is that +// components are emitted in reverse topological order of the condensation. +// (See https://en.wikipedia.org/wiki/Strongly_connected_component#Definitions +// for description of condensation.) +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also TarjanForward and TarjanCondensation. +func (g LabeledDirected) Tarjan(emit func([]NI) bool) { + // See "Depth-first search and linear graph algorithms", Robert Tarjan, + // SIAM J. Comput. Vol. 1, No. 2, June 1972. + // + // Implementation here from Wikipedia pseudocode, + // http://en.wikipedia.org/w/index.php?title=Tarjan%27s_strongly_connected_components_algorithm&direction=prev&oldid=647184742 + var indexed, stacked Bits + a := g.LabeledAdjacencyList + index := make([]int, len(a)) + lowlink := make([]int, len(a)) + x := 0 + var S []NI + var sc func(NI) bool + sc = func(n NI) bool { + index[n] = x + indexed.SetBit(n, 1) + lowlink[n] = x + x++ + S = append(S, n) + stacked.SetBit(n, 1) + for _, nb := range a[n] { + if indexed.Bit(nb.To) == 0 { + if !sc(nb.To) { + return false + } + if lowlink[nb.To] < lowlink[n] { + lowlink[n] = lowlink[nb.To] + } + } else if stacked.Bit(nb.To) == 1 { + if index[nb.To] < lowlink[n] { + lowlink[n] = index[nb.To] + } + } + } + if lowlink[n] == index[n] { + var c []NI + for { + last := len(S) - 1 + w := S[last] + S = S[:last] + stacked.SetBit(w, 0) + c = append(c, w) + if w == n { + if !emit(c) { + return false + } + break + } + } + } + return true + } + for n := range a { + if indexed.Bit(NI(n)) == 0 && !sc(NI(n)) { + return + } + } +} + +// TarjanForward returns strongly connected components. +// +// It returns components in the reverse order of Tarjan, for situations +// where a forward topological ordering is easier. +func (g LabeledDirected) TarjanForward() [][]NI { + var r [][]NI + g.Tarjan(func(c []NI) bool { + r = append(r, c) + return true + }) + scc := make([][]NI, len(r)) + last := len(r) - 1 + for i, ci := range r { + scc[last-i] = ci + } + return scc +} + +// TarjanCondensation returns strongly connected components and their +// condensation graph. +// +// Components are ordered in a forward topological ordering. +func (g LabeledDirected) TarjanCondensation() (scc [][]NI, cd AdjacencyList) { + scc = g.TarjanForward() + cd = make(AdjacencyList, len(scc)) // return value + cond := make([]NI, len(g.LabeledAdjacencyList)) // mapping from g node to cd node + for cn := NI(len(scc) - 1); cn >= 0; cn-- { + c := scc[cn] + for _, n := range c { + cond[n] = NI(cn) // map g node to cd node + } + var tos []NI // list of 'to' nodes + var m Bits // tos map + m.SetBit(cn, 1) + for _, n := range c { + for _, to := range g.LabeledAdjacencyList[n] { + if ct := cond[to.To]; m.Bit(ct) == 0 { + m.SetBit(ct, 1) + tos = append(tos, ct) + } + } + } + cd[cn] = tos + } + return +} + +// Topological computes a topological ordering of a directed acyclic graph. +// +// For an acyclic graph, return value ordering is a permutation of node numbers +// in topologically sorted order and cycle will be nil. If the graph is found +// to be cyclic, ordering will be nil and cycle will be the path of a found +// cycle. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) Topological() (ordering, cycle []NI) { + a := g.LabeledAdjacencyList + ordering = make([]NI, len(a)) + i := len(ordering) + var temp, perm Bits + var cycleFound bool + var cycleStart NI + var df func(NI) + df = func(n NI) { + switch { + case temp.Bit(n) == 1: + cycleFound = true + cycleStart = n + return + case perm.Bit(n) == 1: + return + } + temp.SetBit(n, 1) + for _, nb := range a[n] { + df(nb.To) + if cycleFound { + if cycleStart >= 0 { + // a little hack: orderng won't be needed so repurpose the + // slice as cycle. this is read out in reverse order + // as the recursion unwinds. + x := len(ordering) - 1 - len(cycle) + ordering[x] = n + cycle = ordering[x:] + if n == cycleStart { + cycleStart = -1 + } + } + return + } + } + temp.SetBit(n, 0) + perm.SetBit(n, 1) + i-- + ordering[i] = n + } + for n := range a { + if perm.Bit(NI(n)) == 1 { + continue + } + df(NI(n)) + if cycleFound { + return nil, cycle + } + } + return ordering, nil +} + +// TopologicalKahn computes a topological ordering of a directed acyclic graph. +// +// For an acyclic graph, return value ordering is a permutation of node numbers +// in topologically sorted order and cycle will be nil. If the graph is found +// to be cyclic, ordering will be nil and cycle will be the path of a found +// cycle. +// +// This function is based on the algorithm by Arthur Kahn and requires the +// transpose of g be passed as the argument. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) TopologicalKahn(tr Directed) (ordering, cycle []NI) { + // code follows Wikipedia pseudocode. + var L, S []NI + // rem for "remaining edges," this function makes a local copy of the + // in-degrees and consumes that instead of consuming an input. + rem := make([]int, len(g.LabeledAdjacencyList)) + for n, fr := range tr.AdjacencyList { + if len(fr) == 0 { + // accumulate "set of all nodes with no incoming edges" + S = append(S, NI(n)) + } else { + // initialize rem from in-degree + rem[n] = len(fr) + } + } + for len(S) > 0 { + last := len(S) - 1 // "remove a node n from S" + n := S[last] + S = S[:last] + L = append(L, n) // "add n to tail of L" + for _, m := range g.LabeledAdjacencyList[n] { + // WP pseudo code reads "for each node m..." but it means for each + // node m *remaining in the graph.* We consume rem rather than + // the graph, so "remaining in the graph" for us means rem[m] > 0. + if rem[m.To] > 0 { + rem[m.To]-- // "remove edge from the graph" + if rem[m.To] == 0 { // if "m has no other incoming edges" + S = append(S, m.To) // "insert m into S" + } + } + } + } + // "If graph has edges," for us means a value in rem is > 0. + for c, in := range rem { + if in > 0 { + // recover cyclic nodes + for _, nb := range g.LabeledAdjacencyList[c] { + if rem[nb.To] > 0 { + cycle = append(cycle, NI(c)) + break + } + } + } + } + if len(cycle) > 0 { + return nil, cycle + } + return L, nil +} diff --git a/vendor/github.com/soniakeys/graph/doc.go b/vendor/github.com/soniakeys/graph/doc.go new file mode 100644 index 0000000..6d07278 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/doc.go @@ -0,0 +1,128 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +// Graph algorithms: Dijkstra, A*, Bellman Ford, Floyd Warshall; +// Kruskal and Prim minimal spanning tree; topological sort and DAG longest +// and shortest paths; Eulerian cycle and path; degeneracy and k-cores; +// Bron Kerbosch clique finding; connected components; and others. +// +// This is a graph library of integer indexes. To use it with application +// data, you associate data with integer indexes, perform searches or other +// operations with the library, and then use the integer index results to refer +// back to your application data. +// +// Thus it does not store application data, pointers to application data, +// or require you to implement an interface on your application data. +// The idea is to keep the library methods fast and lean. +// +// Representation overview +// +// The package defines a type for a node index (NI) which is just an integer +// type. It defines types for a number of number graph representations using +// NI. The fundamental graph type is AdjacencyList, which is the +// common "list of lists" graph representation. It is a list as a slice +// with one element for each node of the graph. Each element is a list +// itself, a list of neighbor nodes, implemented as an NI slice. Methods +// on an AdjacencyList generally work on any representable graph, including +// directed or undirected graphs, simple graphs or multigraphs. +// +// The type Undirected embeds an AdjacencyList adding methods specific to +// undirected graphs. Similarly the type Directed adds methods meaningful +// for directed graphs. +// +// Similar to NI, the type LI is a "label index" which labels a +// node-to-neighbor "arc" or edge. Just as an NI can index arbitrary node +// data, an LI can index arbitrary arc or edge data. A number of algorithms +// use a "weight" associated with an arc. This package does not represent +// weighted arcs explicitly, but instead uses the LI as a more general +// mechanism allowing not only weights but arbitrary data to be associated +// with arcs. While AdjacencyList represents an arc with simply an NI, +// the type LabeledAdjacencyList uses a type that pairs an NI with an LI. +// This type is named Half, for half-arc. (A full arc would represent +// both ends.) Types LabeledDirected and LabeledUndirected embed a +// LabeledAdjacencyList. +// +// In contrast to Half, the type Edge represents both ends of an edge (but +// no label.) The type LabeledEdge adds the label. The type WeightedEdgeList +// bundles a list of LabeledEdges with a WeightFunc. WeightedEdgeList is +// currently only used by Kruskal methods. +// +// FromList is a compact rooted tree (or forest) respresentation. Like +// AdjacencyList and LabeledAdjacencyList, it is a list with one element for +// each node of the graph. Each element contains only a single neighbor +// however, its parent in the tree, the "from" node. +// +// Code generation +// +// A number of methods on AdjacencyList, Directed, and Undirected are +// applicable to LabeledAdjacencyList, LabeledDirected, and LabeledUndirected +// simply by ignoring the label. In these cases code generation provides +// methods on both types from a single source implementation. These methods +// are documented with the sentence "There are equivalent labeled and unlabeled +// versions of this method" and examples are provided only for the unlabeled +// version. +// +// Terminology +// +// This package uses the term "node" rather than "vertex." It uses "arc" +// to mean a directed edge, and uses "from" and "to" to refer to the ends +// of an arc. It uses "start" and "end" to refer to endpoints of a search +// or traversal. +// +// The usage of "to" and "from" is perhaps most strange. In common speech +// they are prepositions, but throughout this package they are used as +// adjectives, for example to refer to the "from node" of an arc or the +// "to node". The type "FromList" is named to indicate it stores a list of +// "from" values. +// +// A "half arc" refers to just one end of an arc, either the to or from end. +// +// Two arcs are "reciprocal" if they connect two distinct nodes n1 and n2, +// one arc leading from n1 to n2 and the other arc leading from n2 to n1. +// Undirected graphs are represented with reciprocal arcs. +// +// A node with an arc to itself represents a "loop." Duplicate arcs, where +// a node has multiple arcs to another node, are termed "parallel arcs." +// A graph with no loops or parallel arcs is "simple." A graph that allows +// parallel arcs is a "multigraph" +// +// The "size" of a graph traditionally means the number of undirected edges. +// This package uses "arc size" to mean the number of arcs in a graph. For an +// undirected graph without loops, arc size is 2 * size. +// +// The "order" of a graph is the number of nodes. An "ordering" though means +// an ordered list of nodes. +// +// A number of graph search algorithms use a concept of arc "weights." +// The sum of arc weights along a path is a "distance." In contrast, the +// number of nodes in a path, including start and end nodes, is the path's +// "length." (Yes, mixing weights and lengths would be nonsense physically, +// but the terms used here are just distinct terms for abstract values. +// The actual meaning to an application is likely to be something else +// entirely and is not relevant within this package.) +// +// Finally, this package documentation takes back the word "object" in some +// places to refer to a Go value, especially a value of a type with methods. +// +// Shortest path searches +// +// This package implements a number of shortest path searches. Most work +// with weighted graphs that are directed or undirected, and with graphs +// that may have loops or parallel arcs. For weighted graphs, "shortest" +// is defined as the path distance (sum of arc weights) with path length +// (number of nodes) breaking ties. If multiple paths have the same minimum +// distance with the same minimum length, search methods are free to return +// any of them. +// +// Type name Description, methods +// BreadthFirst Unweigted arcs, traversal, single path search or all paths. +// BreadthFirst2 Direction-optimizing variant of BreadthFirst. +// Dijkstra Non-negative arc weights, single or all paths. +// AStar Non-negative arc weights, heuristic guided, single path. +// BellmanFord Negative arc weights allowed, no negative cycles, all paths. +// DAGPath O(n) algorithm for DAGs, arc weights of any sign. +// FloydWarshall all pairs distances, no negative cycles. +// +// These searches typically have one method that is full-featured and +// then a convenience method with a simpler API targeting a simpler use case. +package graph diff --git a/vendor/github.com/soniakeys/graph/fromlist.go b/vendor/github.com/soniakeys/graph/fromlist.go new file mode 100644 index 0000000..31d41fa --- /dev/null +++ b/vendor/github.com/soniakeys/graph/fromlist.go @@ -0,0 +1,418 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// FromList represents a rooted tree (or forest) where each node is associated +// with a half arc identifying an arc "from" another node. +// +// Other terms for this data structure include "parent list", +// "predecessor list", "in-tree", "inverse arborescence", and +// "spaghetti stack." +// +// The Paths member represents the tree structure. Leaves and MaxLen are +// not always needed. Where Leaves is used it serves as a bitmap where +// Leaves.Bit(n) == 1 for each leaf n of the tree. Where MaxLen is used it is +// provided primarily as a convenience for functions that might want to +// anticipate the maximum path length that would be encountered traversing +// the tree. +// +// Various graph search methods use a FromList to returns search results. +// For a start node of a search, From will be -1 and Len will be 1. For other +// nodes reached by the search, From represents a half arc in a path back to +// start and Len represents the number of nodes in the path. For nodes not +// reached by the search, From will be -1 and Len will be 0. +// +// A single FromList can also represent a forest. In this case paths from +// all leaves do not return to a single root node, but multiple root nodes. +// +// While a FromList generally encodes a tree or forest, it is technically +// possible to encode a cyclic graph. A number of FromList methods require +// the receiver to be acyclic. Graph methods documented to return a tree or +// forest will never return a cyclic FromList. In other cases however, +// where a FromList is not known to by cyclic, the Cyclic method can be +// useful to validate the acyclic property. +type FromList struct { + Paths []PathEnd // tree representation + Leaves Bits // leaves of tree + MaxLen int // length of longest path, max of all PathEnd.Len values +} + +// PathEnd associates a half arc and a path length. +// +// A PathEnd list is an element type of FromList. +type PathEnd struct { + From NI // a "from" half arc, the node the arc comes from + Len int // number of nodes in path from start +} + +// NewFromList creates a FromList object of given order. +// +// The Paths member is allocated to length n but there is no other +// initialization. +func NewFromList(n int) FromList { + return FromList{Paths: make([]PathEnd, n)} +} + +// BoundsOk validates the "from" values in the list. +// +// Negative values are allowed as they indicate root nodes. +// +// BoundsOk returns true when all from values are less than len(t). +// Otherwise it returns false and a node with a from value >= len(t). +func (f FromList) BoundsOk() (ok bool, n NI) { + for n, e := range f.Paths { + if int(e.From) >= len(f.Paths) { + return false, NI(n) + } + } + return true, -1 +} + +// CommonStart returns the common start node of minimal paths to a and b. +// +// It returns -1 if a and b cannot be traced back to a common node. +// +// The method relies on populated PathEnd.Len members. Use RecalcLen if +// the Len members are not known to be present and correct. +func (f FromList) CommonStart(a, b NI) NI { + p := f.Paths + if p[a].Len < p[b].Len { + a, b = b, a + } + for bl := p[b].Len; p[a].Len > bl; { + a = p[a].From + if a < 0 { + return -1 + } + } + for a != b { + a = p[a].From + if a < 0 { + return -1 + } + b = p[b].From + } + return a +} + +// Cyclic determines if f contains a cycle, a non-empty path from a node +// back to itself. +// +// Cyclic returns true if g contains at least one cycle. It also returns +// an example of a node involved in a cycle. +// +// Cyclic returns (false, -1) in the normal case where f is acyclic. +// Note that the bool is not an "ok" return. A cyclic FromList is usually +// not okay. +func (f FromList) Cyclic() (cyclic bool, n NI) { + var vis Bits + p := f.Paths + for i := range p { + var path Bits + for n := NI(i); vis.Bit(n) == 0; { + vis.SetBit(n, 1) + path.SetBit(n, 1) + if n = p[n].From; n < 0 { + break + } + if path.Bit(n) == 1 { + return true, n + } + } + } + return false, -1 +} + +// IsolatedNodeBits returns a bitmap of isolated nodes in receiver graph f. +// +// An isolated node is one with no arcs going to or from it. +func (f FromList) IsolatedNodes() (iso Bits) { + p := f.Paths + iso.SetAll(len(p)) + for n, e := range p { + if e.From >= 0 { + iso.SetBit(NI(n), 0) + iso.SetBit(e.From, 0) + } + } + return +} + +// PathTo decodes a FromList, recovering a single path. +// +// The path is returned as a list of nodes where the first element will be +// a root node and the last element will be the specified end node. +// +// Only the Paths member of the receiver is used. Other members of the +// FromList do not need to be valid, however the MaxLen member can be useful +// for allocating argument p. +// +// Argument p can provide the result slice. If p has capacity for the result +// it will be used, otherwise a new slice is created for the result. +// +// See also function PathTo. +func (f FromList) PathTo(end NI, p []NI) []NI { + return PathTo(f.Paths, end, p) +} + +// PathTo decodes a single path from a PathEnd list. +// +// A PathEnd list is the main data representation in a FromList. See FromList. +// +// PathTo returns a list of nodes where the first element will be +// a root node and the last element will be the specified end node. +// +// Argument p can provide the result slice. If p has capacity for the result +// it will be used, otherwise a new slice is created for the result. +// +// See also method FromList.PathTo. +func PathTo(paths []PathEnd, end NI, p []NI) []NI { + n := paths[end].Len + if n == 0 { + return nil + } + if cap(p) >= n { + p = p[:n] + } else { + p = make([]NI, n) + } + for { + n-- + p[n] = end + if n == 0 { + return p + } + end = paths[end].From + } +} + +// Preorder traverses f calling Visitor v in preorder. +// +// Nodes are visited in order such that for any node n with from node fr, +// fr is visited before n. Where f represents a tree, the visit ordering +// corresponds to a preordering, or depth first traversal of the tree. +// Where f represents a forest, the preorderings of the trees can be +// intermingled. +// +// Leaves must be set correctly first. Use RecalcLeaves if leaves are not +// known to be set correctly. FromList f cannot be cyclic. +// +// Traversal continues while v returns true. It terminates if v returns false. +// Preorder returns true if it completes without v returning false. Preorder +// returns false if traversal is terminated by v returning false. +func (f FromList) Preorder(v OkNodeVisitor) bool { + p := f.Paths + var done Bits + var df func(NI) bool + df = func(n NI) bool { + done.SetBit(n, 1) + if fr := p[n].From; fr >= 0 && done.Bit(fr) == 0 { + df(fr) + } + return v(n) + } + for n := range f.Paths { + p[n].Len = 0 + } + return f.Leaves.Iterate(func(n NI) bool { + return df(n) + }) +} + +// RecalcLeaves recomputes the Leaves member of f. +func (f *FromList) RecalcLeaves() { + p := f.Paths + lv := &f.Leaves + lv.SetAll(len(p)) + for n := range f.Paths { + if fr := p[n].From; fr >= 0 { + lv.SetBit(fr, 0) + } + } +} + +// RecalcLen recomputes Len for each path end, and recomputes MaxLen. +// +// RecalcLen relies on the Leaves member being valid. If it is not known +// to be valid, call RecalcLeaves before calling RecalcLen. +func (f *FromList) RecalcLen() { + p := f.Paths + var setLen func(NI) int + setLen = func(n NI) int { + switch { + case p[n].Len > 0: + return p[n].Len + case p[n].From < 0: + p[n].Len = 1 + return 1 + } + l := 1 + setLen(p[n].From) + p[n].Len = l + return l + } + for n := range f.Paths { + p[n].Len = 0 + } + f.MaxLen = 0 + f.Leaves.Iterate(func(n NI) bool { + if l := setLen(NI(n)); l > f.MaxLen { + f.MaxLen = l + } + return true + }) +} + +// ReRoot reorients the tree containing n to make n the root node. +// +// It keeps the tree connected by "reversing" the path from n to the old root. +// +// After ReRoot, the Leaves and Len members are invalid. +// Call RecalcLeaves or RecalcLen as needed. +func (f *FromList) ReRoot(n NI) { + p := f.Paths + fr := p[n].From + if fr < 0 { + return + } + p[n].From = -1 + for { + ff := p[fr].From + p[fr].From = n + if ff < 0 { + return + } + n = fr + fr = ff + } +} + +// Root finds the root of a node in a FromList. +func (f FromList) Root(n NI) NI { + for p := f.Paths; ; { + fr := p[n].From + if fr < 0 { + return n + } + n = fr + } +} + +// Transpose constructs the directed graph corresponding to FromList f +// but with arcs in the opposite direction. That is, from roots toward leaves. +// +// The method relies only on the From member of f.Paths. Other members of +// the FromList are not used. +// +// See FromList.TransposeRoots for a version that also accumulates and returns +// information about the roots. +func (f FromList) Transpose() Directed { + g := make(AdjacencyList, len(f.Paths)) + for n, p := range f.Paths { + if p.From == -1 { + continue + } + g[p.From] = append(g[p.From], NI(n)) + } + return Directed{g} +} + +// TransposeLabeled constructs the directed labeled graph corresponding +// to FromList f but with arcs in the opposite direction. That is, from +// roots toward leaves. +// +// The argument labels can be nil. In this case labels are generated matching +// the path indexes. This corresponds to the "to", or child node. +// +// If labels is non-nil, it must be the same length as f.Paths and is used +// to look up label numbers by the path index. +// +// The method relies only on the From member of f.Paths. Other members of +// the FromList are not used. +// +// See FromList.TransposeLabeledRoots for a version that also accumulates +// and returns information about the roots. +func (f FromList) TransposeLabeled(labels []LI) LabeledDirected { + g := make(LabeledAdjacencyList, len(f.Paths)) + for n, p := range f.Paths { + if p.From == -1 { + continue + } + l := LI(n) + if labels != nil { + l = labels[n] + } + g[p.From] = append(g[p.From], Half{NI(n), l}) + } + return LabeledDirected{g} +} + +// TransposeLabeledRoots constructs the labeled directed graph corresponding +// to FromList f but with arcs in the opposite direction. That is, from +// roots toward leaves. +// +// TransposeLabeledRoots also returns a count of roots of the resulting forest +// and a bitmap of the roots. +// +// The argument labels can be nil. In this case labels are generated matching +// the path indexes. This corresponds to the "to", or child node. +// +// If labels is non-nil, it must be the same length as t.Paths and is used +// to look up label numbers by the path index. +// +// The method relies only on the From member of f.Paths. Other members of +// the FromList are not used. +// +// See FromList.TransposeLabeled for a simpler verstion that returns the +// forest only. +func (f FromList) TransposeLabeledRoots(labels []LI) (forest LabeledDirected, nRoots int, roots Bits) { + p := f.Paths + nRoots = len(p) + roots.SetAll(len(p)) + g := make(LabeledAdjacencyList, len(p)) + for i, p := range f.Paths { + if p.From == -1 { + continue + } + l := LI(i) + if labels != nil { + l = labels[i] + } + n := NI(i) + g[p.From] = append(g[p.From], Half{n, l}) + if roots.Bit(n) == 1 { + roots.SetBit(n, 0) + nRoots-- + } + } + return LabeledDirected{g}, nRoots, roots +} + +// TransposeRoots constructs the directed graph corresponding to FromList f +// but with arcs in the opposite direction. That is, from roots toward leaves. +// +// TransposeRoots also returns a count of roots of the resulting forest and +// a bitmap of the roots. +// +// The method relies only on the From member of f.Paths. Other members of +// the FromList are not used. +// +// See FromList.Transpose for a simpler verstion that returns the forest only. +func (f FromList) TransposeRoots() (forest Directed, nRoots int, roots Bits) { + p := f.Paths + nRoots = len(p) + roots.SetAll(len(p)) + g := make(AdjacencyList, len(p)) + for i, e := range p { + if e.From == -1 { + continue + } + n := NI(i) + g[e.From] = append(g[e.From], n) + if roots.Bit(n) == 1 { + roots.SetBit(n, 0) + nRoots-- + } + } + return Directed{g}, nRoots, roots +} diff --git a/vendor/github.com/soniakeys/graph/graph.go b/vendor/github.com/soniakeys/graph/graph.go new file mode 100644 index 0000000..a2044e9 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/graph.go @@ -0,0 +1,181 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// graph.go contains type definitions for all graph types and components. +// Also, go generate directives for source transformations. +// +// For readability, the types are defined in a dependency order: +// +// NI +// NodeList +// AdjacencyList +// Directed +// Undirected +// LI +// Half +// LabeledAdjacencyList +// LabeledDirected +// LabeledUndirected +// Edge +// LabeledEdge +// WeightFunc +// WeightedEdgeList + +//go:generate cp adj_cg.go adj_RO.go +//go:generate gofmt -r "LabeledAdjacencyList -> AdjacencyList" -w adj_RO.go +//go:generate gofmt -r "n.To -> n" -w adj_RO.go +//go:generate gofmt -r "Half -> NI" -w adj_RO.go + +//go:generate cp dir_cg.go dir_RO.go +//go:generate gofmt -r "LabeledDirected -> Directed" -w dir_RO.go +//go:generate gofmt -r "LabeledAdjacencyList -> AdjacencyList" -w dir_RO.go +//go:generate gofmt -r "n.To -> n" -w dir_RO.go +//go:generate gofmt -r "Half -> NI" -w dir_RO.go + +//go:generate cp undir_cg.go undir_RO.go +//go:generate gofmt -r "LabeledUndirected -> Undirected" -w undir_RO.go +//go:generate gofmt -r "LabeledAdjacencyList -> AdjacencyList" -w undir_RO.go +//go:generate gofmt -r "n.To -> n" -w undir_RO.go +//go:generate gofmt -r "Half -> NI" -w undir_RO.go + +// NI is a "node int" +// +// It is a node number or node ID. NIs are used extensively as slice indexes. +// NIs typically account for a significant fraction of the memory footprint of +// a graph. +type NI int32 + +// NodeList satisfies sort.Interface. +type NodeList []NI + +func (l NodeList) Len() int { return len(l) } +func (l NodeList) Less(i, j int) bool { return l[i] < l[j] } +func (l NodeList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } + +// An AdjacencyList represents a graph as a list of neighbors for each node. +// The "node ID" of a node is simply it's slice index in the AdjacencyList. +// For an AdjacencyList g, g[n] represents arcs going from node n to nodes +// g[n]. +// +// Adjacency lists are inherently directed but can be used to represent +// directed or undirected graphs. See types Directed and Undirected. +type AdjacencyList [][]NI + +// Directed represents a directed graph. +// +// Directed methods generally rely on the graph being directed, specifically +// that arcs do not have reciprocals. +type Directed struct { + AdjacencyList // embedded to include AdjacencyList methods +} + +// Undirected represents an undirected graph. +// +// In an undirected graph, for each arc between distinct nodes there is also +// a reciprocal arc, an arc in the opposite direction. Loops do not have +// reciprocals. +// +// Undirected methods generally rely on the graph being undirected, +// specifically that every arc between distinct nodes has a reciprocal. +type Undirected struct { + AdjacencyList // embedded to include AdjacencyList methods +} + +// LI is a label integer, used for associating labels with arcs. +type LI int32 + +// Half is a half arc, representing a labeled arc and the "neighbor" node +// that the arc leads to. +// +// Halfs can be composed to form a labeled adjacency list. +type Half struct { + To NI // node ID, usable as a slice index + Label LI // half-arc ID for application data, often a weight +} + +// A LabeledAdjacencyList represents a graph as a list of neighbors for each +// node, connected by labeled arcs. +// +// Arc labels are not necessarily unique arc IDs. Different arcs can have +// the same label. +// +// Arc labels are commonly used to assocate a weight with an arc. Arc labels +// are general purpose however and can be used to associate arbitrary +// information with an arc. +// +// Methods implementing weighted graph algorithms will commonly take a +// weight function that turns a label int into a float64 weight. +// +// If only a small amount of information -- such as an integer weight or +// a single printable character -- needs to be associated, it can sometimes +// be possible to encode the information directly into the label int. For +// more generality, some lookup scheme will be needed. +// +// In an undirected labeled graph, reciprocal arcs must have identical labels. +// Note this does not preclude parallel arcs with different labels. +type LabeledAdjacencyList [][]Half + +// LabeledDirected represents a directed labeled graph. +// +// This is the labeled version of Directed. See types LabeledAdjacencyList +// and Directed. +type LabeledDirected struct { + LabeledAdjacencyList // embedded to include LabeledAdjacencyList methods +} + +// LabeledUndirected represents an undirected labeled graph. +// +// This is the labeled version of Undirected. See types LabeledAdjacencyList +// and Undirected. +type LabeledUndirected struct { + LabeledAdjacencyList // embedded to include LabeledAdjacencyList methods +} + +// Edge is an undirected edge between nodes N1 and N2. +type Edge struct{ N1, N2 NI } + +// LabeledEdge is an undirected edge with an associated label. +type LabeledEdge struct { + Edge + LI +} + +// WeightFunc returns a weight for a given label. +// +// WeightFunc is a parameter type for various search functions. The intent +// is to return a weight corresponding to an arc label. The name "weight" +// is an abstract term. An arc "weight" will typically have some application +// specific meaning other than physical weight. +type WeightFunc func(label LI) (weight float64) + +// WeightedEdgeList is a graph representation. +// +// It is a labeled edge list, with an associated weight function to return +// a weight given an edge label. +// +// Also associated is the order, or number of nodes of the graph. +// All nodes occurring in the edge list must be strictly less than Order. +// +// WeigtedEdgeList sorts by weight, obtained by calling the weight function. +// If weight computation is expensive, consider supplying a cached or +// memoized version. +type WeightedEdgeList struct { + Order int + WeightFunc + Edges []LabeledEdge +} + +// Len implements sort.Interface. +func (l WeightedEdgeList) Len() int { return len(l.Edges) } + +// Less implements sort.Interface. +func (l WeightedEdgeList) Less(i, j int) bool { + return l.WeightFunc(l.Edges[i].LI) < l.WeightFunc(l.Edges[j].LI) +} + +// Swap implements sort.Interface. +func (l WeightedEdgeList) Swap(i, j int) { + l.Edges[i], l.Edges[j] = l.Edges[j], l.Edges[i] +} diff --git a/vendor/github.com/soniakeys/graph/hacking.md b/vendor/github.com/soniakeys/graph/hacking.md new file mode 100644 index 0000000..30d2d7c --- /dev/null +++ b/vendor/github.com/soniakeys/graph/hacking.md @@ -0,0 +1,37 @@ +#Hacking + +Basic use of the package is just go get, or git clone; go install. There are +no dependencies outside the standard library. + +The primary to-do list is the issue tracker on Github. I maintained a +journal on google drive for a while but at some point filed issues for all +remaining ideas in that document that still seemed relevant. So currently +there is no other roadmap or planning document. + +CI is currently on travis-ci.org. The .travis.yml builds for go 1.2.1 +following https://github.com/soniakeys/graph/issues/49, and it currently builds +for go 1.6 as well. The travis script calls a shell script right away because +I didn’t see a way to get it to do different steps for the different go +versions. For 1.2.1, I just wanted the basic tests. For a current go version +such as 1.6, there’s a growing list of checks. + +The GOARCH=386 test is for https://github.com/soniakeys/graph/issues/41. +The problem is the architecture specific code in bits32.go and bits64.go. +Yes, there are architecture independent algorithms. There is also assembly +to access machine instructions. Anyway, it’s the way it is for now. + +Im not big on making go vet happy just for a badge but I really like the +example check that I believe appeared with go 1.6. (I think it will be a +standard check with 1.7, so the test script will have to change then.) + +https://github.com/client9/misspell has been valuable. + +Also I wrote https://github.com/soniakeys/vetc to validate that each source +file has copyright/license statement. + +Then, it’s not in the ci script, but I wrote https://github.com/soniakeys/rcv +to put coverage stats in the readme. Maybe it could be commit hook or +something but for now I’ll try just running it manually now and then. + +Go fmt is not in the ci script, but I have at least one editor set up to run +it on save, so code should stay formatted pretty well. diff --git a/vendor/github.com/soniakeys/graph/mst.go b/vendor/github.com/soniakeys/graph/mst.go new file mode 100644 index 0000000..028e680 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/mst.go @@ -0,0 +1,244 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +import ( + "container/heap" + "sort" +) + +type dsElement struct { + from NI + rank int +} + +type disjointSet struct { + set []dsElement +} + +func newDisjointSet(n int) disjointSet { + set := make([]dsElement, n) + for i := range set { + set[i].from = -1 + } + return disjointSet{set} +} + +// return true if disjoint trees were combined. +// false if x and y were already in the same tree. +func (ds disjointSet) union(x, y NI) bool { + xr := ds.find(x) + yr := ds.find(y) + if xr == yr { + return false + } + switch xe, ye := &ds.set[xr], &ds.set[yr]; { + case xe.rank < ye.rank: + xe.from = yr + case xe.rank == ye.rank: + xe.rank++ + fallthrough + default: + ye.from = xr + } + return true +} + +func (ds disjointSet) find(n NI) NI { + // fast paths for n == root or from root. + // no updates need in these cases. + s := ds.set + fr := s[n].from + if fr < 0 { // n is root + return n + } + n, fr = fr, s[fr].from + if fr < 0 { // n is from root + return n + } + // otherwise updates needed. + // two iterative passes (rather than recursion or stack) + // pass 1: find root + r := fr + for { + f := s[r].from + if f < 0 { + break + } + r = f + } + // pass 2: update froms + for { + s[n].from = r + if fr == r { + return r + } + n = fr + fr = s[n].from + } +} + +// Kruskal implements Kruskal's algorithm for constructing a minimum spanning +// forest on an undirected graph. +// +// While the input graph is interpreted as undirected, the receiver edge list +// does not actually need to contain reciprocal arcs. A property of the +// algorithm is that arc direction is ignored. Thus only a single arc out of +// a reciprocal pair must be present in the edge list. Reciprocal arcs (and +// parallel arcs) are allowed though, and do not affect the result. +// +// The forest is returned as an undirected graph. +// +// Also returned is a total distance for the returned forest. +// +// The edge list of the receiver is sorted as a side effect of this method. +// See KruskalSorted for a version that relies on the edge list being already +// sorted. +func (l WeightedEdgeList) Kruskal() (g LabeledUndirected, dist float64) { + sort.Sort(l) + return l.KruskalSorted() +} + +// KruskalSorted implements Kruskal's algorithm for constructing a minimum +// spanning tree on an undirected graph. +// +// While the input graph is interpreted as undirected, the receiver edge list +// does not actually need to contain reciprocal arcs. A property of the +// algorithm is that arc direction is ignored. Thus only a single arc out of +// a reciprocal pair must be present in the edge list. Reciprocal arcs (and +// parallel arcs) are allowed though, and do not affect the result. +// +// When called, the edge list of the receiver must be already sorted by weight. +// See Kruskal for a version that accepts an unsorted edge list. +// +// The forest is returned as an undirected graph. +// +// Also returned is a total distance for the returned forest. +func (l WeightedEdgeList) KruskalSorted() (g LabeledUndirected, dist float64) { + ds := newDisjointSet(l.Order) + g.LabeledAdjacencyList = make(LabeledAdjacencyList, l.Order) + for _, e := range l.Edges { + if ds.union(e.N1, e.N2) { + g.AddEdge(Edge{e.N1, e.N2}, e.LI) + dist += l.WeightFunc(e.LI) + } + } + return +} + +// Prim implements the JarnĂk-Prim-Dijkstra algorithm for constructing +// a minimum spanning tree on an undirected graph. +// +// Prim computes a minimal spanning tree on the connected component containing +// the given start node. The tree is returned in FromList f. Argument f +// cannot be a nil pointer although it can point to a zero value FromList. +// +// If the passed FromList.Paths has the len of g though, it will be reused. +// In the case of a graph with multiple connected components, this allows a +// spanning forest to be accumulated by calling Prim successively on +// representative nodes of the components. In this case if leaves for +// individual trees are of interest, pass a non-nil zero-value for the argument +// componentLeaves and it will be populated with leaves for the single tree +// spanned by the call. +// +// If argument labels is non-nil, it must have the same length as g and will +// be populated with labels corresponding to the edges of the tree. +// +// Returned are the number of nodes spanned for the single tree (which will be +// the order of the connected component) and the total spanned distance for the +// single tree. +func (g LabeledUndirected) Prim(start NI, w WeightFunc, f *FromList, labels []LI, componentLeaves *Bits) (numSpanned int, dist float64) { + al := g.LabeledAdjacencyList + if len(f.Paths) != len(al) { + *f = NewFromList(len(al)) + } + b := make([]prNode, len(al)) // "best" + for n := range b { + b[n].nx = NI(n) + b[n].fx = -1 + } + rp := f.Paths + var frontier prHeap + rp[start] = PathEnd{From: -1, Len: 1} + numSpanned = 1 + fLeaves := &f.Leaves + fLeaves.SetBit(start, 1) + if componentLeaves != nil { + componentLeaves.SetBit(start, 1) + } + for a := start; ; { + for _, nb := range al[a] { + if rp[nb.To].Len > 0 { + continue // already in MST, no action + } + switch bp := &b[nb.To]; { + case bp.fx == -1: // new node for frontier + bp.from = fromHalf{From: a, Label: nb.Label} + bp.wt = w(nb.Label) + heap.Push(&frontier, bp) + case w(nb.Label) < bp.wt: // better arc + bp.from = fromHalf{From: a, Label: nb.Label} + bp.wt = w(nb.Label) + heap.Fix(&frontier, bp.fx) + } + } + if len(frontier) == 0 { + break // done + } + bp := heap.Pop(&frontier).(*prNode) + a = bp.nx + rp[a].Len = rp[bp.from.From].Len + 1 + rp[a].From = bp.from.From + if len(labels) != 0 { + labels[a] = bp.from.Label + } + dist += bp.wt + fLeaves.SetBit(bp.from.From, 0) + fLeaves.SetBit(a, 1) + if componentLeaves != nil { + componentLeaves.SetBit(bp.from.From, 0) + componentLeaves.SetBit(a, 1) + } + numSpanned++ + } + return +} + +// fromHalf is a half arc, representing a labeled arc and the "neighbor" node +// that the arc originates from. +// +// (This used to be exported when there was a LabeledFromList. Currently +// unexported now that it seems to have much more limited use.) +type fromHalf struct { + From NI + Label LI +} + +type prNode struct { + nx NI + from fromHalf + wt float64 // p.Weight(from.Label) + fx int +} + +type prHeap []*prNode + +func (h prHeap) Len() int { return len(h) } +func (h prHeap) Less(i, j int) bool { return h[i].wt < h[j].wt } +func (h prHeap) Swap(i, j int) { + h[i], h[j] = h[j], h[i] + h[i].fx = i + h[j].fx = j +} +func (p *prHeap) Push(x interface{}) { + nd := x.(*prNode) + nd.fx = len(*p) + *p = append(*p, nd) +} +func (p *prHeap) Pop() interface{} { + r := *p + last := len(r) - 1 + *p = r[:last] + return r[last] +} diff --git a/vendor/github.com/soniakeys/graph/random.go b/vendor/github.com/soniakeys/graph/random.go new file mode 100644 index 0000000..99f0445 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/random.go @@ -0,0 +1,325 @@ +// Copyright 2016 Sonia Keys +// License MIT: https://opensource.org/licenses/MIT + +package graph + +import ( + "errors" + "math" + "math/rand" + "time" +) + +// Euclidean generates a random simple graph on the Euclidean plane. +// +// Nodes are associated with coordinates uniformly distributed on a unit +// square. Arcs are added between random nodes with a bias toward connecting +// nearer nodes. +// +// Unfortunately the function has a few "knobs". +// The returned graph will have order nNodes and arc size nArcs. The affinity +// argument controls the bias toward connecting nearer nodes. The function +// selects random pairs of nodes as a candidate arc then rejects the candidate +// if the nodes fail an affinity test. Also parallel arcs are rejected. +// As more affine or denser graphs are requested, rejections increase, +// increasing run time. The patience argument controls the number of arc +// rejections allowed before the function gives up and returns an error. +// Note that higher affinity will require more patience and that some +// combinations of nNodes and nArcs cannot be achieved with any amount of +// patience given that the returned graph must be simple. +// +// If Rand r is nil, the method creates a new source and generator for +// one-time use. +// +// Returned is a directed simple graph and associated positions indexed by +// node number. +// +// See also LabeledEuclidean. +func Euclidean(nNodes, nArcs int, affinity float64, patience int, r *rand.Rand) (g Directed, pos []struct{ X, Y float64 }, err error) { + a := make(AdjacencyList, nNodes) // graph + // generate random positions + if r == nil { + r = rand.New(rand.NewSource(time.Now().UnixNano())) + } + pos = make([]struct{ X, Y float64 }, nNodes) + for i := range pos { + pos[i].X = r.Float64() + pos[i].Y = r.Float64() + } + // arcs + var tooFar, dup int +arc: + for i := 0; i < nArcs; { + if tooFar == nArcs*patience { + err = errors.New("affinity not found") + return + } + if dup == nArcs*patience { + err = errors.New("overcrowding") + return + } + n1 := NI(r.Intn(nNodes)) + var n2 NI + for { + n2 = NI(r.Intn(nNodes)) + if n2 != n1 { // no graph loops + break + } + } + c1 := &pos[n1] + c2 := &pos[n2] + dist := math.Hypot(c2.X-c1.X, c2.Y-c1.Y) + if dist*affinity > r.ExpFloat64() { // favor near nodes + tooFar++ + continue + } + for _, nb := range a[n1] { + if nb == n2 { // no parallel arcs + dup++ + continue arc + } + } + a[n1] = append(a[n1], n2) + i++ + } + g = Directed{a} + return +} + +// LabeledEuclidean generates a random simple graph on the Euclidean plane. +// +// Arc label values in the returned graph g are indexes into the return value +// wt. Wt is the Euclidean distance between the from and to nodes of the arc. +// +// Otherwise the function arguments and return values are the same as for +// function Euclidean. See Euclidean. +func LabeledEuclidean(nNodes, nArcs int, affinity float64, patience int, r *rand.Rand) (g LabeledDirected, pos []struct{ X, Y float64 }, wt []float64, err error) { + a := make(LabeledAdjacencyList, nNodes) // graph + wt = make([]float64, nArcs) // arc weights + // generate random positions + if r == nil { + r = rand.New(rand.NewSource(time.Now().UnixNano())) + } + pos = make([]struct{ X, Y float64 }, nNodes) + for i := range pos { + pos[i].X = r.Float64() + pos[i].Y = r.Float64() + } + // arcs + var tooFar, dup int +arc: + for i := 0; i < nArcs; { + if tooFar == nArcs*patience { + err = errors.New("affinity not found") + return + } + if dup == nArcs*patience { + err = errors.New("overcrowding") + return + } + n1 := NI(r.Intn(nNodes)) + var n2 NI + for { + n2 = NI(r.Intn(nNodes)) + if n2 != n1 { // no graph loops + break + } + } + c1 := &pos[n1] + c2 := &pos[n2] + dist := math.Hypot(c2.X-c1.X, c2.Y-c1.Y) + if dist*affinity > r.ExpFloat64() { // favor near nodes + tooFar++ + continue + } + for _, nb := range a[n1] { + if nb.To == n2 { // no parallel arcs + dup++ + continue arc + } + } + wt[i] = dist + a[n1] = append(a[n1], Half{n2, LI(i)}) + i++ + } + g = LabeledDirected{a} + return +} + +// Geometric generates a random geometric graph (RGG) on the Euclidean plane. +// +// An RGG is an undirected simple graph. Nodes are associated with coordinates +// uniformly distributed on a unit square. Edges are added between all nodes +// falling within a specified distance or radius of each other. +// +// The resulting number of edges is somewhat random but asymptotically +// approaches m = Ď€r²n²/2. The method accumulates and returns the actual +// number of edges constructed. +// +// If Rand r is nil, the method creates a new source and generator for +// one-time use. +// +// See also LabeledGeometric. +func Geometric(nNodes int, radius float64, r *rand.Rand) (g Undirected, pos []struct{ X, Y float64 }, m int) { + // Expected degree is approximately nĎ€r². + a := make(AdjacencyList, nNodes) + if r == nil { + r = rand.New(rand.NewSource(time.Now().UnixNano())) + } + pos = make([]struct{ X, Y float64 }, nNodes) + for i := range pos { + pos[i].X = r.Float64() + pos[i].Y = r.Float64() + } + for u, up := range pos { + for v := u + 1; v < len(pos); v++ { + vp := pos[v] + if math.Hypot(up.X-vp.X, up.Y-vp.Y) < radius { + a[u] = append(a[u], NI(v)) + a[v] = append(a[v], NI(u)) + m++ + } + } + } + g = Undirected{a} + return +} + +// LabeledGeometric generates a random geometric graph (RGG) on the Euclidean +// plane. +// +// Edge label values in the returned graph g are indexes into the return value +// wt. Wt is the Euclidean distance between nodes of the edge. The graph +// size m is len(wt). +// +// See Geometric for additional description. +func LabeledGeometric(nNodes int, radius float64, r *rand.Rand) (g LabeledUndirected, pos []struct{ X, Y float64 }, wt []float64) { + a := make(LabeledAdjacencyList, nNodes) + if r == nil { + r = rand.New(rand.NewSource(time.Now().UnixNano())) + } + pos = make([]struct{ X, Y float64 }, nNodes) + for i := range pos { + pos[i].X = r.Float64() + pos[i].Y = r.Float64() + } + for u, up := range pos { + for v := u + 1; v < len(pos); v++ { + vp := pos[v] + if w := math.Hypot(up.X-vp.X, up.Y-vp.Y); w < radius { + a[u] = append(a[u], Half{NI(v), LI(len(wt))}) + a[v] = append(a[v], Half{NI(u), LI(len(wt))}) + wt = append(wt, w) + } + } + } + g = LabeledUndirected{a} + return +} + +// KroneckerDirected generates a Kronecker-like random directed graph. +// +// The returned graph g is simple and has no isolated nodes but is not +// necessarily fully connected. The number of of nodes will be <= 2^scale, +// and will be near 2^scale for typical values of arcFactor, >= 2. +// ArcFactor * 2^scale arcs are generated, although loops and duplicate arcs +// are rejected. +// +// If Rand r is nil, the method creates a new source and generator for +// one-time use. +// +// Return value ma is the number of arcs retained in the result graph. +func KroneckerDirected(scale uint, arcFactor float64, r *rand.Rand) (g Directed, ma int) { + a, m := kronecker(scale, arcFactor, true, r) + return Directed{a}, m +} + +// KroneckerUndirected generates a Kronecker-like random undirected graph. +// +// The returned graph g is simple and has no isolated nodes but is not +// necessarily fully connected. The number of of nodes will be <= 2^scale, +// and will be near 2^scale for typical values of edgeFactor, >= 2. +// EdgeFactor * 2^scale edges are generated, although loops and duplicate edges +// are rejected. +// +// If Rand r is nil, the method creates a new source and generator for +// one-time use. +// +// Return value m is the true number of edges--not arcs--retained in the result +// graph. +func KroneckerUndirected(scale uint, edgeFactor float64, r *rand.Rand) (g Undirected, m int) { + al, s := kronecker(scale, edgeFactor, false, r) + return Undirected{al}, s +} + +// Styled after the Graph500 example code. Not well tested currently. +// Graph500 example generates undirected only. No idea if the directed variant +// here is meaningful or not. +// +// note mma returns arc size ma for dir=true, but returns size m for dir=false +func kronecker(scale uint, edgeFactor float64, dir bool, r *rand.Rand) (g AdjacencyList, mma int) { + if r == nil { + r = rand.New(rand.NewSource(time.Now().UnixNano())) + } + N := NI(1 << scale) // node extent + M := int(edgeFactor*float64(N) + .5) // number of arcs/edges to generate + a, b, c := 0.57, 0.19, 0.19 // initiator probabilities + ab := a + b + cNorm := c / (1 - ab) + aNorm := a / ab + ij := make([][2]NI, M) + var bm Bits + var nNodes int + for k := range ij { + var i, j NI + for b := NI(1); b < N; b <<= 1 { + if r.Float64() > ab { + i |= b + if r.Float64() > cNorm { + j |= b + } + } else if r.Float64() > aNorm { + j |= b + } + } + if bm.Bit(i) == 0 { + bm.SetBit(i, 1) + nNodes++ + } + if bm.Bit(j) == 0 { + bm.SetBit(j, 1) + nNodes++ + } + r := r.Intn(k + 1) // shuffle edges as they are generated + ij[k] = ij[r] + ij[r] = [2]NI{i, j} + } + p := r.Perm(nNodes) // mapping to shuffle IDs of non-isolated nodes + px := 0 + rn := make([]NI, N) + for i := range rn { + if bm.Bit(NI(i)) == 1 { + rn[i] = NI(p[px]) // fill lookup table + px++ + } + } + g = make(AdjacencyList, nNodes) +ij: + for _, e := range ij { + if e[0] == e[1] { + continue // skip loops + } + ri, rj := rn[e[0]], rn[e[1]] + for _, nb := range g[ri] { + if nb == rj { + continue ij // skip parallel edges + } + } + g[ri] = append(g[ri], rj) + mma++ + if !dir { + g[rj] = append(g[rj], ri) + } + } + return +} diff --git a/vendor/github.com/soniakeys/graph/readme.md b/vendor/github.com/soniakeys/graph/readme.md new file mode 100644 index 0000000..539670f --- /dev/null +++ b/vendor/github.com/soniakeys/graph/readme.md @@ -0,0 +1,38 @@ +#Graph + +A graph library with goals of speed and simplicity, Graph implements +graph algorithms on graphs of zero-based integer node IDs. + +[](https://godoc.org/github.com/soniakeys/graph) [](https://gowalker.org/github.com/soniakeys/graph) [](http://go-search.org/view?id=github.com%2Fsoniakeys%2Fgraph)[](https://travis-ci.org/soniakeys/graph) + +Status, 4 Apr 2016: The repo has benefitted recently from being included +in another package. In response to users of that package, this repo now +builds for 32 bit Windows and ARM, and for Go versions back to 1.2.1. +Thank you all who have filed issues. + +###Non-source files of interest + +The directory [tutorials](tutorials) is a work in progress - there are only +a couple of tutorials there yet - but the concept is to provide some topical +walk-throughs to supplement godoc. The source-based godoc documentation +remains the primary documentation. + +* [Dijkstra's algorithm](tutorials/dijkstra.md) +* [AdjacencyList types](tutorials/adjacencylist.md) + +The directory [bench](bench) is another work in progress. The concept is +to present some plots showing benchmark performance approaching some +theoretical asymptote. + +[hacking.md](hacking.md) has some information about how the library is +developed, built, and tested. It might be of interest if for example you +plan to fork or contribute to the the repository. + +###Test coverage +8 Apr 2016 +``` +graph 95.3% +graph/df 20.7% +graph/dot 77.5% +graph/treevis 79.4% +``` diff --git a/vendor/github.com/soniakeys/graph/sssp.go b/vendor/github.com/soniakeys/graph/sssp.go new file mode 100644 index 0000000..32cc192 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/sssp.go @@ -0,0 +1,881 @@ +// Copyright 2013 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +import ( + "container/heap" + "fmt" + "math" +) + +// rNode holds data for a "reached" node +type rNode struct { + nx NI + state int8 // state constants defined below + f float64 // "g+h", path dist + heuristic estimate + fx int // heap.Fix index +} + +// for rNode.state +const ( + unreached = 0 + reached = 1 + open = 1 + closed = 2 +) + +type openHeap []*rNode + +// A Heuristic is defined on a specific end node. The function +// returns an estimate of the path distance from node argument +// "from" to the end node. Two subclasses of heuristics are "admissible" +// and "monotonic." +// +// Admissible means the value returned is guaranteed to be less than or +// equal to the actual shortest path distance from the node to end. +// +// An admissible estimate may further be monotonic. +// Monotonic means that for any neighboring nodes A and B with half arc aB +// leading from A to B, and for heuristic h defined on some end node, then +// h(A) <= aB.ArcWeight + h(B). +// +// See AStarA for additional notes on implementing heuristic functions for +// AStar search methods. +type Heuristic func(from NI) float64 + +// Admissible returns true if heuristic h is admissible on graph g relative to +// the given end node. +// +// If h is inadmissible, the string result describes a counter example. +func (h Heuristic) Admissible(g LabeledAdjacencyList, w WeightFunc, end NI) (bool, string) { + // invert graph + inv := make(LabeledAdjacencyList, len(g)) + for from, nbs := range g { + for _, nb := range nbs { + inv[nb.To] = append(inv[nb.To], + Half{To: NI(from), Label: nb.Label}) + } + } + // run dijkstra + // Dijkstra.AllPaths takes a start node but after inverting the graph + // argument end now represents the start node of the inverted graph. + f, dist, _ := inv.Dijkstra(end, -1, w) + // compare h to found shortest paths + for n := range inv { + if f.Paths[n].Len == 0 { + continue // no path, any heuristic estimate is fine. + } + if !(h(NI(n)) <= dist[n]) { + return false, fmt.Sprintf("h(%d) = %g, "+ + "required to be <= found shortest path (%g)", + n, h(NI(n)), dist[n]) + } + } + return true, "" +} + +// Monotonic returns true if heuristic h is monotonic on weighted graph g. +// +// If h is non-monotonic, the string result describes a counter example. +func (h Heuristic) Monotonic(g LabeledAdjacencyList, w WeightFunc) (bool, string) { + // precompute + hv := make([]float64, len(g)) + for n := range g { + hv[n] = h(NI(n)) + } + // iterate over all edges + for from, nbs := range g { + for _, nb := range nbs { + arcWeight := w(nb.Label) + if !(hv[from] <= arcWeight+hv[nb.To]) { + return false, fmt.Sprintf("h(%d) = %g, "+ + "required to be <= arc weight + h(%d) (= %g + %g = %g)", + from, hv[from], + nb.To, arcWeight, hv[nb.To], arcWeight+hv[nb.To]) + } + } + } + return true, "" +} + +// AStarA finds a path between two nodes. +// +// AStarA implements both algorithm A and algorithm A*. The difference in the +// two algorithms is strictly in the heuristic estimate returned by argument h. +// If h is an "admissible" heuristic estimate, then the algorithm is termed A*, +// otherwise it is algorithm A. +// +// Like Dijkstra's algorithm, AStarA with an admissible heuristic finds the +// shortest path between start and end. AStarA generally runs faster than +// Dijkstra though, by using the heuristic distance estimate. +// +// AStarA with an inadmissible heuristic becomes algorithm A. Algorithm A +// will find a path, but it is not guaranteed to be the shortest path. +// The heuristic still guides the search however, so a nearly admissible +// heuristic is likely to find a very good path, if not the best. Quality +// of the path returned degrades gracefully with the quality of the heuristic. +// +// The heuristic function h should ideally be fairly inexpensive. AStarA +// may call it more than once for the same node, especially as graph density +// increases. In some cases it may be worth the effort to memoize or +// precompute values. +// +// Argument g is the graph to be searched, with arc weights returned by w. +// As usual for AStar, arc weights must be non-negative. +// Graphs may be directed or undirected. +// +// If AStarA finds a path it returns a FromList encoding the path, the arc +// labels for path nodes, the total path distance, and ok = true. +// Otherwise it returns ok = false. +func (g LabeledAdjacencyList) AStarA(w WeightFunc, start, end NI, h Heuristic) (f FromList, labels []LI, dist float64, ok bool) { + // NOTE: AStarM is largely duplicate code. + + f = NewFromList(len(g)) + labels = make([]LI, len(g)) + d := make([]float64, len(g)) + r := make([]rNode, len(g)) + for i := range r { + r[i].nx = NI(i) + } + // start node is reached initially + cr := &r[start] + cr.state = reached + cr.f = h(start) // total path estimate is estimate from start + rp := f.Paths + rp[start] = PathEnd{Len: 1, From: -1} // path length at start is 1 node + // oh is a heap of nodes "open" for exploration. nodes go on the heap + // when they get an initial or new "g" path distance, and therefore a + // new "f" which serves as priority for exploration. + oh := openHeap{cr} + for len(oh) > 0 { + bestPath := heap.Pop(&oh).(*rNode) + bestNode := bestPath.nx + if bestNode == end { + return f, labels, d[end], true + } + bp := &rp[bestNode] + nextLen := bp.Len + 1 + for _, nb := range g[bestNode] { + alt := &r[nb.To] + ap := &rp[alt.nx] + // "g" path distance from start + g := d[bestNode] + w(nb.Label) + if alt.state == reached { + if g > d[nb.To] { + // candidate path to nb is longer than some alternate path + continue + } + if g == d[nb.To] && nextLen >= ap.Len { + // candidate path has identical length of some alternate + // path but it takes no fewer hops. + continue + } + // cool, we found a better way to get to this node. + // record new path data for this node and + // update alt with new data and make sure it's on the heap. + *ap = PathEnd{From: bestNode, Len: nextLen} + labels[nb.To] = nb.Label + d[nb.To] = g + alt.f = g + h(nb.To) + if alt.fx < 0 { + heap.Push(&oh, alt) + } else { + heap.Fix(&oh, alt.fx) + } + } else { + // bestNode being reached for the first time. + *ap = PathEnd{From: bestNode, Len: nextLen} + labels[nb.To] = nb.Label + d[nb.To] = g + alt.f = g + h(nb.To) + alt.state = reached + heap.Push(&oh, alt) // and it's now open for exploration + } + } + } + return // no path +} + +// AStarAPath finds a shortest path using the AStarA algorithm. +// +// This is a convenience method with a simpler result than the AStarA method. +// See documentation on the AStarA method. +// +// If a path is found, the non-nil node path is returned with the total path +// distance. Otherwise the returned path will be nil. +func (g LabeledAdjacencyList) AStarAPath(start, end NI, h Heuristic, w WeightFunc) ([]NI, float64) { + f, _, d, _ := g.AStarA(w, start, end, h) + return f.PathTo(end, nil), d +} + +// AStarM is AStarA optimized for monotonic heuristic estimates. +// +// Note that this function requires a monotonic heuristic. Results will +// not be meaningful if argument h is non-monotonic. +// +// See AStarA for general usage. See Heuristic for notes on monotonicity. +func (g LabeledAdjacencyList) AStarM(w WeightFunc, start, end NI, h Heuristic) (f FromList, labels []LI, dist float64, ok bool) { + // NOTE: AStarM is largely code duplicated from AStarA. + // Differences are noted in comments in this method. + + f = NewFromList(len(g)) + labels = make([]LI, len(g)) + d := make([]float64, len(g)) + r := make([]rNode, len(g)) + for i := range r { + r[i].nx = NI(i) + } + cr := &r[start] + + // difference from AStarA: + // instead of a bit to mark a reached node, there are two states, + // open and closed. open marks nodes "open" for exploration. + // nodes are marked open as they are reached, then marked + // closed as they are found to be on the best path. + cr.state = open + + cr.f = h(start) + rp := f.Paths + rp[start] = PathEnd{Len: 1, From: -1} + oh := openHeap{cr} + for len(oh) > 0 { + bestPath := heap.Pop(&oh).(*rNode) + bestNode := bestPath.nx + if bestNode == end { + return f, labels, d[end], true + } + + // difference from AStarA: + // move nodes to closed list as they are found to be best so far. + bestPath.state = closed + + bp := &rp[bestNode] + nextLen := bp.Len + 1 + for _, nb := range g[bestNode] { + alt := &r[nb.To] + + // difference from AStarA: + // Monotonicity means that f cannot be improved. + if alt.state == closed { + continue + } + + ap := &rp[alt.nx] + g := d[bestNode] + w(nb.Label) + + // difference from AStarA: + // test for open state, not just reached + if alt.state == open { + + if g > d[nb.To] { + continue + } + if g == d[nb.To] && nextLen >= ap.Len { + continue + } + *ap = PathEnd{From: bestNode, Len: nextLen} + labels[nb.To] = nb.Label + d[nb.To] = g + alt.f = g + h(nb.To) + + // difference from AStarA: + // we know alt was on the heap because we found it marked open + heap.Fix(&oh, alt.fx) + } else { + *ap = PathEnd{From: bestNode, Len: nextLen} + labels[nb.To] = nb.Label + d[nb.To] = g + alt.f = g + h(nb.To) + + // difference from AStarA: + // nodes are opened when first reached + alt.state = open + heap.Push(&oh, alt) + } + } + } + return +} + +// AStarMPath finds a shortest path using the AStarM algorithm. +// +// This is a convenience method with a simpler result than the AStarM method. +// See documentation on the AStarM and AStarA methods. +// +// If a path is found, the non-nil node path is returned with the total path +// distance. Otherwise the returned path will be nil. +func (g LabeledAdjacencyList) AStarMPath(start, end NI, h Heuristic, w WeightFunc) ([]NI, float64) { + f, _, d, _ := g.AStarM(w, start, end, h) + return f.PathTo(end, nil), d +} + +// implement container/heap +func (h openHeap) Len() int { return len(h) } +func (h openHeap) Less(i, j int) bool { return h[i].f < h[j].f } +func (h openHeap) Swap(i, j int) { + h[i], h[j] = h[j], h[i] + h[i].fx = i + h[j].fx = j +} +func (p *openHeap) Push(x interface{}) { + h := *p + fx := len(h) + h = append(h, x.(*rNode)) + h[fx].fx = fx + *p = h +} + +func (p *openHeap) Pop() interface{} { + h := *p + last := len(h) - 1 + *p = h[:last] + h[last].fx = -1 + return h[last] +} + +// BellmanFord finds shortest paths from a start node in a weighted directed +// graph using the Bellman-Ford-Moore algorithm. +// +// WeightFunc w must translate arc labels to arc weights. +// Negative arc weights are allowed but not negative cycles. +// Loops and parallel arcs are allowed. +// +// If the algorithm completes without encountering a negative cycle the method +// returns shortest paths encoded in a FromList, path distances indexed by +// node, and return value end = -1. +// +// If it encounters a negative cycle reachable from start it returns end >= 0. +// In this case the cycle can be obtained by calling f.BellmanFordCycle(end). +// +// Negative cycles are only detected when reachable from start. A negative +// cycle not reachable from start will not prevent the algorithm from finding +// shortest paths from start. +// +// See also NegativeCycle to find a cycle anywhere in the graph, and see +// HasNegativeCycle for lighter-weight negative cycle detection, +func (g LabeledDirected) BellmanFord(w WeightFunc, start NI) (f FromList, dist []float64, end NI) { + a := g.LabeledAdjacencyList + f = NewFromList(len(a)) + dist = make([]float64, len(a)) + inf := math.Inf(1) + for i := range dist { + dist[i] = inf + } + rp := f.Paths + rp[start] = PathEnd{Len: 1, From: -1} + dist[start] = 0 + for _ = range a[1:] { + imp := false + for from, nbs := range a { + fp := &rp[from] + d1 := dist[from] + for _, nb := range nbs { + d2 := d1 + w(nb.Label) + to := &rp[nb.To] + // TODO improve to break ties + if fp.Len > 0 && d2 < dist[nb.To] { + *to = PathEnd{From: NI(from), Len: fp.Len + 1} + dist[nb.To] = d2 + imp = true + } + } + } + if !imp { + break + } + } + for from, nbs := range a { + d1 := dist[from] + for _, nb := range nbs { + if d1+w(nb.Label) < dist[nb.To] { + // return nb as end of a path with negative cycle at root + return f, dist, NI(from) + } + } + } + return f, dist, -1 +} + +// BellmanFordCycle decodes a negative cycle detected by BellmanFord. +// +// Receiver f and argument end must be results returned from BellmanFord. +func (f FromList) BellmanFordCycle(end NI) (c []NI) { + p := f.Paths + var b Bits + for b.Bit(end) == 0 { + b.SetBit(end, 1) + end = p[end].From + } + for b.Bit(end) == 1 { + c = append(c, end) + b.SetBit(end, 0) + end = p[end].From + } + for i, j := 0, len(c)-1; i < j; i, j = i+1, j-1 { + c[i], c[j] = c[j], c[i] + } + return +} + +// HasNegativeCycle returns true if the graph contains any negative cycle. +// +// HasNegativeCycle uses a Bellman-Ford-like algorithm, but finds negative +// cycles anywhere in the graph. Also path information is not computed, +// reducing memory use somewhat compared to BellmanFord. +// +// See also NegativeCycle to obtain the cycle, and see BellmanFord for +// single source shortest path searches. +func (g LabeledDirected) HasNegativeCycle(w WeightFunc) bool { + a := g.LabeledAdjacencyList + dist := make([]float64, len(a)) + for _ = range a[1:] { + imp := false + for from, nbs := range a { + d1 := dist[from] + for _, nb := range nbs { + d2 := d1 + w(nb.Label) + if d2 < dist[nb.To] { + dist[nb.To] = d2 + imp = true + } + } + } + if !imp { + break + } + } + for from, nbs := range a { + d1 := dist[from] + for _, nb := range nbs { + if d1+w(nb.Label) < dist[nb.To] { + return true // negative cycle + } + } + } + return false +} + +// NegativeCycle finds a negative cycle if one exists. +// +// NegativeCycle uses a Bellman-Ford-like algorithm, but finds negative +// cycles anywhere in the graph. If a negative cycle exists, one will be +// returned. The result is nil if no negative cycle exists. +// +// See also HasNegativeCycle for lighter-weight cycle detection, and see +// BellmanFord for single source shortest paths. +func (g LabeledDirected) NegativeCycle(w WeightFunc) (c []NI) { + a := g.LabeledAdjacencyList + f := NewFromList(len(a)) + p := f.Paths + for n := range p { + p[n] = PathEnd{From: -1, Len: 1} + } + dist := make([]float64, len(a)) + for _ = range a { + imp := false + for from, nbs := range a { + fp := &p[from] + d1 := dist[from] + for _, nb := range nbs { + d2 := d1 + w(nb.Label) + to := &p[nb.To] + if fp.Len > 0 && d2 < dist[nb.To] { + *to = PathEnd{From: NI(from), Len: fp.Len + 1} + dist[nb.To] = d2 + imp = true + } + } + } + if !imp { + return nil + } + } + var vis Bits +a: + for n := range a { + end := NI(n) + var b Bits + for b.Bit(end) == 0 { + if vis.Bit(end) == 1 { + continue a + } + vis.SetBit(end, 1) + b.SetBit(end, 1) + end = p[end].From + if end < 0 { + continue a + } + } + for b.Bit(end) == 1 { + c = append(c, end) + b.SetBit(end, 0) + end = p[end].From + } + for i, j := 0, len(c)-1; i < j; i, j = i+1, j-1 { + c[i], c[j] = c[j], c[i] + } + return c + } + return nil // no negative cycle +} + +// A NodeVisitor is an argument to some graph traversal methods. +// +// Graph traversal methods call the visitor function for each node visited. +// Argument n is the node being visited. +type NodeVisitor func(n NI) + +// An OkNodeVisitor function is an argument to some graph traversal methods. +// +// Graph traversal methods call the visitor function for each node visited. +// The argument n is the node being visited. If the visitor function +// returns true, the traversal will continue. If the visitor function +// returns false, the traversal will terminate immediately. +type OkNodeVisitor func(n NI) (ok bool) + +// BreadthFirst2 traverses a graph breadth first using a direction +// optimizing algorithm. +// +// The code is experimental and currently seems no faster than the +// conventional breadth first code. +// +// Use AdjacencyList.BreadthFirst instead. +func BreadthFirst2(g, tr AdjacencyList, ma int, start NI, f *FromList, v OkNodeVisitor) int { + if tr == nil { + var d Directed + d, ma = Directed{g}.Transpose() + tr = d.AdjacencyList + } + switch { + case f == nil: + e := NewFromList(len(g)) + f = &e + case f.Paths == nil: + *f = NewFromList(len(g)) + } + if ma <= 0 { + ma = g.ArcSize() + } + rp := f.Paths + level := 1 + rp[start] = PathEnd{Len: level, From: -1} + if !v(start) { + f.MaxLen = level + return -1 + } + nReached := 1 // accumulated for a return value + // the frontier consists of nodes all at the same level + frontier := []NI{start} + mf := len(g[start]) // number of arcs leading out from frontier + ctb := ma / 10 // threshold change from top-down to bottom-up + k14 := 14 * ma / len(g) // 14 * mean degree + cbt := len(g) / k14 // threshold change from bottom-up to top-down + // var fBits, nextb big.Int + fBits := make([]bool, len(g)) + nextb := make([]bool, len(g)) + zBits := make([]bool, len(g)) + for { + // top down step + level++ + var next []NI + for _, n := range frontier { + for _, nb := range g[n] { + if rp[nb].Len == 0 { + rp[nb] = PathEnd{From: n, Len: level} + if !v(nb) { + f.MaxLen = level + return -1 + } + next = append(next, nb) + nReached++ + } + } + } + if len(next) == 0 { + break + } + frontier = next + if mf > ctb { + // switch to bottom up! + } else { + // stick with top down + continue + } + // convert frontier representation + nf := 0 // number of vertices on the frontier + for _, n := range frontier { + // fBits.SetBit(&fBits, n, 1) + fBits[n] = true + nf++ + } + bottomUpLoop: + level++ + nNext := 0 + for n := range tr { + if rp[n].Len == 0 { + for _, nb := range tr[n] { + // if fBits.Bit(nb) == 1 { + if fBits[nb] { + rp[n] = PathEnd{From: nb, Len: level} + if !v(nb) { + f.MaxLen = level + return -1 + } + // nextb.SetBit(&nextb, n, 1) + nextb[n] = true + nReached++ + nNext++ + break + } + } + } + } + if nNext == 0 { + break + } + fBits, nextb = nextb, fBits + // nextb.SetInt64(0) + copy(nextb, zBits) + nf = nNext + if nf < cbt { + // switch back to top down! + } else { + // stick with bottom up + goto bottomUpLoop + } + // convert frontier representation + mf = 0 + frontier = frontier[:0] + for n := range g { + // if fBits.Bit(n) == 1 { + if fBits[n] { + frontier = append(frontier, NI(n)) + mf += len(g[n]) + fBits[n] = false + } + } + // fBits.SetInt64(0) + } + f.MaxLen = level - 1 + return nReached +} + +// DAGMinDistPath finds a single shortest path. +// +// Shortest means minimum sum of arc weights. +// +// Returned is the path and distance as returned by FromList.PathTo. +// +// This is a convenience method. See DAGOptimalPaths for more options. +func (g LabeledDirected) DAGMinDistPath(start, end NI, w WeightFunc) ([]NI, float64, error) { + return g.dagPath(start, end, w, false) +} + +// DAGMaxDistPath finds a single longest path. +// +// Longest means maximum sum of arc weights. +// +// Returned is the path and distance as returned by FromList.PathTo. +// +// This is a convenience method. See DAGOptimalPaths for more options. +func (g LabeledDirected) DAGMaxDistPath(start, end NI, w WeightFunc) ([]NI, float64, error) { + return g.dagPath(start, end, w, true) +} + +func (g LabeledDirected) dagPath(start, end NI, w WeightFunc, longest bool) ([]NI, float64, error) { + o, _ := g.Topological() + if o == nil { + return nil, 0, fmt.Errorf("not a DAG") + } + f, dist, _ := g.DAGOptimalPaths(start, end, o, w, longest) + if f.Paths[end].Len == 0 { + return nil, 0, fmt.Errorf("no path from %d to %d", start, end) + } + return f.PathTo(end, nil), dist[end], nil +} + +// DAGOptimalPaths finds either longest or shortest distance paths in a +// directed acyclic graph. +// +// Path distance is the sum of arc weights on the path. +// Negative arc weights are allowed. +// Where multiple paths exist with the same distance, the path length +// (number of nodes) is used as a tie breaker. +// +// Receiver g must be a directed acyclic graph. Argument o must be either nil +// or a topological ordering of g. If nil, a topologcal ordering is +// computed internally. If longest is true, an optimal path is a longest +// distance path. Otherwise it is a shortest distance path. +// +// Argument start is the start node for paths, end is the end node. If end +// is a valid node number, the method returns as soon as the optimal path +// to end is found. If end is -1, all optimal paths from start are found. +// +// Paths and path distances are encoded in the returned FromList and dist +// slice. The number of nodes reached is returned as nReached. +func (g LabeledDirected) DAGOptimalPaths(start, end NI, ordering []NI, w WeightFunc, longest bool) (f FromList, dist []float64, nReached int) { + a := g.LabeledAdjacencyList + f = NewFromList(len(a)) + dist = make([]float64, len(a)) + if ordering == nil { + ordering, _ = g.Topological() + } + // search ordering for start + o := 0 + for ordering[o] != start { + o++ + } + var fBetter func(cand, ext float64) bool + var iBetter func(cand, ext int) bool + if longest { + fBetter = func(cand, ext float64) bool { return cand > ext } + iBetter = func(cand, ext int) bool { return cand > ext } + } else { + fBetter = func(cand, ext float64) bool { return cand < ext } + iBetter = func(cand, ext int) bool { return cand < ext } + } + p := f.Paths + p[start] = PathEnd{From: -1, Len: 1} + f.MaxLen = 1 + leaves := &f.Leaves + leaves.SetBit(start, 1) + nReached = 1 + for n := start; n != end; n = ordering[o] { + if p[n].Len > 0 && len(a[n]) > 0 { + nDist := dist[n] + candLen := p[n].Len + 1 // len for any candidate arc followed from n + for _, to := range a[n] { + leaves.SetBit(to.To, 1) + candDist := nDist + w(to.Label) + switch { + case p[to.To].Len == 0: // first path to node to.To + nReached++ + case fBetter(candDist, dist[to.To]): // better distance + case candDist == dist[to.To] && iBetter(candLen, p[to.To].Len): // same distance but better path length + default: + continue + } + dist[to.To] = candDist + p[to.To] = PathEnd{From: n, Len: candLen} + if candLen > f.MaxLen { + f.MaxLen = candLen + } + } + leaves.SetBit(n, 0) + } + o++ + if o == len(ordering) { + break + } + } + return +} + +// Dijkstra finds shortest paths by Dijkstra's algorithm. +// +// Shortest means shortest distance where distance is the +// sum of arc weights. Where multiple paths exist with the same distance, +// a path with the minimum number of nodes is returned. +// +// As usual for Dijkstra's algorithm, arc weights must be non-negative. +// Graphs may be directed or undirected. Loops and parallel arcs are +// allowed. +func (g LabeledAdjacencyList) Dijkstra(start, end NI, w WeightFunc) (f FromList, dist []float64, reached int) { + r := make([]tentResult, len(g)) + for i := range r { + r[i].nx = NI(i) + } + f = NewFromList(len(g)) + dist = make([]float64, len(g)) + current := start + rp := f.Paths + rp[current] = PathEnd{Len: 1, From: -1} // path length at start is 1 node + cr := &r[current] + cr.dist = 0 // distance at start is 0. + cr.done = true // mark start done. it skips the heap. + nDone := 1 // accumulated for a return value + var t tent + for current != end { + nextLen := rp[current].Len + 1 + for _, nb := range g[current] { + // d.arcVis++ + hr := &r[nb.To] + if hr.done { + continue // skip nodes already done + } + dist := cr.dist + w(nb.Label) + vl := rp[nb.To].Len + visited := vl > 0 + if visited { + if dist > hr.dist { + continue // distance is worse + } + // tie breaker is a nice touch and doesn't seem to + // impact performance much. + if dist == hr.dist && nextLen >= vl { + continue // distance same, but number of nodes is no better + } + } + // the path through current to this node is shortest so far. + // record new path data for this node and update tentative set. + hr.dist = dist + rp[nb.To].Len = nextLen + rp[nb.To].From = current + if visited { + heap.Fix(&t, hr.fx) + } else { + heap.Push(&t, hr) + } + } + //d.ndVis++ + if len(t) == 0 { + return f, dist, nDone // no more reachable nodes. AllPaths normal return + } + // new current is node with smallest tentative distance + cr = heap.Pop(&t).(*tentResult) + cr.done = true + nDone++ + current = cr.nx + dist[current] = cr.dist // store final distance + } + // normal return for single shortest path search + return f, dist, -1 +} + +// DijkstraPath finds a single shortest path. +// +// Returned is the path and distance as returned by FromList.PathTo. +func (g LabeledAdjacencyList) DijkstraPath(start, end NI, w WeightFunc) ([]NI, float64) { + f, dist, _ := g.Dijkstra(start, end, w) + return f.PathTo(end, nil), dist[end] +} + +// tent implements container/heap +func (t tent) Len() int { return len(t) } +func (t tent) Less(i, j int) bool { return t[i].dist < t[j].dist } +func (t tent) Swap(i, j int) { + t[i], t[j] = t[j], t[i] + t[i].fx = i + t[j].fx = j +} +func (s *tent) Push(x interface{}) { + nd := x.(*tentResult) + nd.fx = len(*s) + *s = append(*s, nd) +} +func (s *tent) Pop() interface{} { + t := *s + last := len(t) - 1 + *s = t[:last] + return t[last] +} + +type tentResult struct { + dist float64 // tentative distance, sum of arc weights + nx NI // slice index, "node id" + fx int // heap.Fix index + done bool +} + +type tent []*tentResult diff --git a/vendor/github.com/soniakeys/graph/travis.sh b/vendor/github.com/soniakeys/graph/travis.sh new file mode 100644 index 0000000..5a8030a --- /dev/null +++ b/vendor/github.com/soniakeys/graph/travis.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -ex +go test ./... +if [ "$TRAVIS_GO_VERSION" = "1.6" ]; then + GOARCH=386 go test ./... + go tool vet -example . + go get github.com/client9/misspell/cmd/misspell + go get github.com/soniakeys/vetc + misspell -error * */* */*/* + vetc +fi diff --git a/vendor/github.com/soniakeys/graph/undir.go b/vendor/github.com/soniakeys/graph/undir.go new file mode 100644 index 0000000..75a7f24 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/undir.go @@ -0,0 +1,321 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// undir.go has methods specific to undirected graphs, Undirected and +// LabeledUndirected. + +import "errors" + +// AddEdge adds an edge to a graph. +// +// It can be useful for constructing undirected graphs. +// +// When n1 and n2 are distinct, it adds the arc n1->n2 and the reciprocal +// n2->n1. When n1 and n2 are the same, it adds a single arc loop. +// +// The pointer receiver allows the method to expand the graph as needed +// to include the values n1 and n2. If n1 or n2 happen to be greater than +// len(*p) the method does not panic, but simply expands the graph. +func (p *Undirected) AddEdge(n1, n2 NI) { + // Similar code in LabeledAdjacencyList.AddEdge. + + // determine max of the two end points + max := n1 + if n2 > max { + max = n2 + } + // expand graph if needed, to include both + g := p.AdjacencyList + if int(max) >= len(g) { + p.AdjacencyList = make(AdjacencyList, max+1) + copy(p.AdjacencyList, g) + g = p.AdjacencyList + } + // create one half-arc, + g[n1] = append(g[n1], n2) + // and except for loops, create the reciprocal + if n1 != n2 { + g[n2] = append(g[n2], n1) + } +} + +// EulerianCycleD for undirected graphs is a bit of an experiment. +// +// It is about the same as the directed version, but modified for an undirected +// multigraph. +// +// Parameter m in this case must be the size of the undirected graph -- the +// number of edges. Use Undirected.Size if the size is unknown. +// +// It works, but contains an extra loop that I think spoils the time +// complexity. Probably still pretty fast in practice, but a different +// graph representation might be better. +func (g Undirected) EulerianCycleD(m int) ([]NI, error) { + if len(g.AdjacencyList) == 0 { + return nil, nil + } + e := newEulerian(g.AdjacencyList, m) + for e.s >= 0 { + v := e.top() + e.pushUndir() // call modified method + if e.top() != v { + return nil, errors.New("not balanced") + } + e.keep() + } + if !e.uv.Zero() { + return nil, errors.New("not strongly connected") + } + return e.p, nil +} + +// TarjanBiconnectedComponents decomposes a graph into maximal biconnected +// components, components for which if any node were removed the component +// would remain connected. +// +// The receiver g must be a simple graph. The method calls the emit argument +// for each component identified, as long as emit returns true. If emit +// returns false, TarjanBiconnectedComponents returns immediately. +// +// See also the eqivalent labeled TarjanBiconnectedComponents. +func (g Undirected) TarjanBiconnectedComponents(emit func([]Edge) bool) { + // Implemented closely to pseudocode in "Depth-first search and linear + // graph algorithms", Robert Tarjan, SIAM J. Comput. Vol. 1, No. 2, + // June 1972. + // + // Note Tarjan's "adjacency structure" is graph.AdjacencyList, + // His "adjacency list" is an element of a graph.AdjacencyList, also + // termed a "to-list", "neighbor list", or "child list." + number := make([]int, len(g.AdjacencyList)) + lowpt := make([]int, len(g.AdjacencyList)) + var stack []Edge + var i int + var biconnect func(NI, NI) bool + biconnect = func(v, u NI) bool { + i++ + number[v] = i + lowpt[v] = i + for _, w := range g.AdjacencyList[v] { + if number[w] == 0 { + stack = append(stack, Edge{v, w}) + if !biconnect(w, v) { + return false + } + if lowpt[w] < lowpt[v] { + lowpt[v] = lowpt[w] + } + if lowpt[w] >= number[v] { + var bcc []Edge + top := len(stack) - 1 + for number[stack[top].N1] >= number[w] { + bcc = append(bcc, stack[top]) + stack = stack[:top] + top-- + } + bcc = append(bcc, stack[top]) + stack = stack[:top] + top-- + if !emit(bcc) { + return false + } + } + } else if number[w] < number[v] && w != u { + stack = append(stack, Edge{v, w}) + if number[w] < lowpt[v] { + lowpt[v] = number[w] + } + } + } + return true + } + for w := range g.AdjacencyList { + if number[w] == 0 && !biconnect(NI(w), 0) { + return + } + } +} + +/* half-baked. Read the 72 paper. Maybe revisit at some point. +type BiconnectedComponents struct { + Graph AdjacencyList + Start int + Cuts big.Int // bitmap of node cuts + From []int // from-tree + Leaves []int // leaves of from-tree +} + +func NewBiconnectedComponents(g Undirected) *BiconnectedComponents { + return &BiconnectedComponents{ + Graph: g, + From: make([]int, len(g)), + } +} + +func (b *BiconnectedComponents) Find(start int) { + g := b.Graph + depth := make([]int, len(g)) + low := make([]int, len(g)) + // reset from any previous run + b.Cuts.SetInt64(0) + bf := b.From + for n := range bf { + bf[n] = -1 + } + b.Leaves = b.Leaves[:0] + d := 1 // depth. d > 0 means visited + depth[start] = d + low[start] = d + d++ + var df func(int, int) + df = func(from, n int) { + bf[n] = from + depth[n] = d + dn := d + l := d + d++ + cut := false + leaf := true + for _, nb := range g[n] { + if depth[nb] == 0 { + leaf = false + df(n, nb) + if low[nb] < l { + l = low[nb] + } + if low[nb] >= dn { + cut = true + } + } else if nb != from && depth[nb] < l { + l = depth[nb] + } + } + low[n] = l + if cut { + b.Cuts.SetBit(&b.Cuts, n, 1) + } + if leaf { + b.Leaves = append(b.Leaves, n) + } + d-- + } + nbs := g[start] + if len(nbs) == 0 { + return + } + df(start, nbs[0]) + var rc uint + for _, nb := range nbs[1:] { + if depth[nb] == 0 { + rc = 1 + df(start, nb) + } + } + b.Cuts.SetBit(&b.Cuts, start, rc) + return +} +*/ + +// AddEdge adds an edge to a labeled graph. +// +// It can be useful for constructing undirected graphs. +// +// When n1 and n2 are distinct, it adds the arc n1->n2 and the reciprocal +// n2->n1. When n1 and n2 are the same, it adds a single arc loop. +// +// If the edge already exists in *p, a parallel edge is added. +// +// The pointer receiver allows the method to expand the graph as needed +// to include the values n1 and n2. If n1 or n2 happen to be greater than +// len(*p) the method does not panic, but simply expands the graph. +func (p *LabeledUndirected) AddEdge(e Edge, l LI) { + // Similar code in AdjacencyList.AddEdge. + + // determine max of the two end points + max := e.N1 + if e.N2 > max { + max = e.N2 + } + // expand graph if needed, to include both + g := p.LabeledAdjacencyList + if max >= NI(len(g)) { + p.LabeledAdjacencyList = make(LabeledAdjacencyList, max+1) + copy(p.LabeledAdjacencyList, g) + g = p.LabeledAdjacencyList + } + // create one half-arc, + g[e.N1] = append(g[e.N1], Half{To: e.N2, Label: l}) + // and except for loops, create the reciprocal + if e.N1 != e.N2 { + g[e.N2] = append(g[e.N2], Half{To: e.N1, Label: l}) + } +} + +// TarjanBiconnectedComponents decomposes a graph into maximal biconnected +// components, components for which if any node were removed the component +// would remain connected. +// +// The receiver g must be a simple graph. The method calls the emit argument +// for each component identified, as long as emit returns true. If emit +// returns false, TarjanBiconnectedComponents returns immediately. +// +// See also the eqivalent unlabeled TarjanBiconnectedComponents. +func (g LabeledUndirected) TarjanBiconnectedComponents(emit func([]LabeledEdge) bool) { + // Implemented closely to pseudocode in "Depth-first search and linear + // graph algorithms", Robert Tarjan, SIAM J. Comput. Vol. 1, No. 2, + // June 1972. + // + // Note Tarjan's "adjacency structure" is graph.AdjacencyList, + // His "adjacency list" is an element of a graph.AdjacencyList, also + // termed a "to-list", "neighbor list", or "child list." + // + // Nearly identical code in undir.go. + number := make([]int, len(g.LabeledAdjacencyList)) + lowpt := make([]int, len(g.LabeledAdjacencyList)) + var stack []LabeledEdge + var i int + var biconnect func(NI, NI) bool + biconnect = func(v, u NI) bool { + i++ + number[v] = i + lowpt[v] = i + for _, w := range g.LabeledAdjacencyList[v] { + if number[w.To] == 0 { + stack = append(stack, LabeledEdge{Edge{v, w.To}, w.Label}) + if !biconnect(w.To, v) { + return false + } + if lowpt[w.To] < lowpt[v] { + lowpt[v] = lowpt[w.To] + } + if lowpt[w.To] >= number[v] { + var bcc []LabeledEdge + top := len(stack) - 1 + for number[stack[top].N1] >= number[w.To] { + bcc = append(bcc, stack[top]) + stack = stack[:top] + top-- + } + bcc = append(bcc, stack[top]) + stack = stack[:top] + top-- + if !emit(bcc) { + return false + } + } + } else if number[w.To] < number[v] && w.To != u { + stack = append(stack, LabeledEdge{Edge{v, w.To}, w.Label}) + if number[w.To] < lowpt[v] { + lowpt[v] = number[w.To] + } + } + } + return true + } + for w := range g.LabeledAdjacencyList { + if number[w] == 0 && !biconnect(NI(w), 0) { + return + } + } +} diff --git a/vendor/github.com/soniakeys/graph/undir_RO.go b/vendor/github.com/soniakeys/graph/undir_RO.go new file mode 100644 index 0000000..fd8e377 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/undir_RO.go @@ -0,0 +1,659 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// undir_RO.go is code generated from undir_cg.go by directives in graph.go. +// Editing undir_cg.go is okay. It is the code generation source. +// DO NOT EDIT undir_RO.go. +// The RO means read only and it is upper case RO to slow you down a bit +// in case you start to edit the file. + +// Bipartite determines if a connected component of an undirected graph +// is bipartite, a component where nodes can be partitioned into two sets +// such that every edge in the component goes from one set to the other. +// +// Argument n can be any representative node of the component. +// +// If the component is bipartite, Bipartite returns true and a two-coloring +// of the component. Each color set is returned as a bitmap. If the component +// is not bipartite, Bipartite returns false and a representative odd cycle. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) Bipartite(n NI) (b bool, c1, c2 Bits, oc []NI) { + b = true + var open bool + var df func(n NI, c1, c2 *Bits) + df = func(n NI, c1, c2 *Bits) { + c1.SetBit(n, 1) + for _, nb := range g.AdjacencyList[n] { + if c1.Bit(nb) == 1 { + b = false + oc = []NI{nb, n} + open = true + return + } + if c2.Bit(nb) == 1 { + continue + } + df(nb, c2, c1) + if b { + continue + } + switch { + case !open: + case n == oc[0]: + open = false + default: + oc = append(oc, n) + } + return + } + } + df(n, &c1, &c2) + if b { + return b, c1, c2, nil + } + return b, Bits{}, Bits{}, oc +} + +// BronKerbosch1 finds maximal cliques in an undirected graph. +// +// The graph must not contain parallel edges or loops. +// +// See https://en.wikipedia.org/wiki/Clique_(graph_theory) and +// https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm for background. +// +// This method implements the BronKerbosch1 algorithm of WP; that is, +// the original algorithm without improvements. +// +// The method calls the emit argument for each maximal clique in g, as long +// as emit returns true. If emit returns false, BronKerbosch1 returns +// immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also more sophisticated variants BronKerbosch2 and BronKerbosch3. +func (g Undirected) BronKerbosch1(emit func([]NI) bool) { + a := g.AdjacencyList + var f func(R, P, X *Bits) bool + f = func(R, P, X *Bits) bool { + switch { + case !P.Zero(): + var r2, p2, x2 Bits + pf := func(n NI) bool { + r2.Set(*R) + r2.SetBit(n, 1) + p2.Clear() + x2.Clear() + for _, to := range a[n] { + if P.Bit(to) == 1 { + p2.SetBit(to, 1) + } + if X.Bit(to) == 1 { + x2.SetBit(to, 1) + } + } + if !f(&r2, &p2, &x2) { + return false + } + P.SetBit(n, 0) + X.SetBit(n, 1) + return true + } + if !P.Iterate(pf) { + return false + } + case X.Zero(): + return emit(R.Slice()) + } + return true + } + var R, P, X Bits + P.SetAll(len(a)) + f(&R, &P, &X) +} + +// BKPivotMaxDegree is a strategy for BronKerbosch methods. +// +// To use it, take the method value (see golang.org/ref/spec#Method_values) +// and pass it as the argument to BronKerbosch2 or 3. +// +// The strategy is to pick the node from P or X with the maximum degree +// (number of edges) in g. Note this is a shortcut from evaluating degrees +// in P. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) BKPivotMaxDegree(P, X *Bits) (p NI) { + // choose pivot u as highest degree node from P or X + a := g.AdjacencyList + maxDeg := -1 + P.Iterate(func(n NI) bool { // scan P + if d := len(a[n]); d > maxDeg { + p = n + maxDeg = d + } + return true + }) + X.Iterate(func(n NI) bool { // scan X + if d := len(a[n]); d > maxDeg { + p = n + maxDeg = d + } + return true + }) + return +} + +// BKPivotMinP is a strategy for BronKerbosch methods. +// +// To use it, take the method value (see golang.org/ref/spec#Method_values) +// and pass it as the argument to BronKerbosch2 or 3. +// +// The strategy is to simply pick the first node in P. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) BKPivotMinP(P, X *Bits) NI { + return P.From(0) +} + +// BronKerbosch2 finds maximal cliques in an undirected graph. +// +// The graph must not contain parallel edges or loops. +// +// See https://en.wikipedia.org/wiki/Clique_(graph_theory) and +// https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm for background. +// +// This method implements the BronKerbosch2 algorithm of WP; that is, +// the original algorithm plus pivoting. +// +// The argument is a pivot function that must return a node of P or X. +// P is guaranteed to contain at least one node. X is not. +// For example see BKPivotMaxDegree. +// +// The method calls the emit argument for each maximal clique in g, as long +// as emit returns true. If emit returns false, BronKerbosch1 returns +// immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also simpler variant BronKerbosch1 and more sophisticated variant +// BronKerbosch3. +func (g Undirected) BronKerbosch2(pivot func(P, X *Bits) NI, emit func([]NI) bool) { + a := g.AdjacencyList + var f func(R, P, X *Bits) bool + f = func(R, P, X *Bits) bool { + switch { + case !P.Zero(): + var r2, p2, x2, pnu Bits + // compute P \ N(u). next 5 lines are only difference from BK1 + pnu.Set(*P) + for _, to := range a[pivot(P, X)] { + pnu.SetBit(to, 0) + } + // remaining code like BK1 + pf := func(n NI) bool { + r2.Set(*R) + r2.SetBit(n, 1) + p2.Clear() + x2.Clear() + for _, to := range a[n] { + if P.Bit(to) == 1 { + p2.SetBit(to, 1) + } + if X.Bit(to) == 1 { + x2.SetBit(to, 1) + } + } + if !f(&r2, &p2, &x2) { + return false + } + P.SetBit(n, 0) + X.SetBit(n, 1) + return true + } + if !pnu.Iterate(pf) { + return false + } + case X.Zero(): + return emit(R.Slice()) + } + return true + } + var R, P, X Bits + P.SetAll(len(a)) + f(&R, &P, &X) +} + +// BronKerbosch3 finds maximal cliques in an undirected graph. +// +// The graph must not contain parallel edges or loops. +// +// See https://en.wikipedia.org/wiki/Clique_(graph_theory) and +// https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm for background. +// +// This method implements the BronKerbosch3 algorithm of WP; that is, +// the original algorithm with pivoting and degeneracy ordering. +// +// The argument is a pivot function that must return a node of P or X. +// P is guaranteed to contain at least one node. X is not. +// For example see BKPivotMaxDegree. +// +// The method calls the emit argument for each maximal clique in g, as long +// as emit returns true. If emit returns false, BronKerbosch1 returns +// immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also simpler variants BronKerbosch1 and BronKerbosch2. +func (g Undirected) BronKerbosch3(pivot func(P, X *Bits) NI, emit func([]NI) bool) { + a := g.AdjacencyList + var f func(R, P, X *Bits) bool + f = func(R, P, X *Bits) bool { + switch { + case !P.Zero(): + var r2, p2, x2, pnu Bits + // compute P \ N(u). next lines are only difference from BK1 + pnu.Set(*P) + for _, to := range a[pivot(P, X)] { + pnu.SetBit(to, 0) + } + // remaining code like BK2 + pf := func(n NI) bool { + r2.Set(*R) + r2.SetBit(n, 1) + p2.Clear() + x2.Clear() + for _, to := range a[n] { + if P.Bit(to) == 1 { + p2.SetBit(to, 1) + } + if X.Bit(to) == 1 { + x2.SetBit(to, 1) + } + } + if !f(&r2, &p2, &x2) { + return false + } + P.SetBit(n, 0) + X.SetBit(n, 1) + return true + } + if !pnu.Iterate(pf) { + return false + } + case X.Zero(): + return emit(R.Slice()) + } + return true + } + var R, P, X Bits + P.SetAll(len(a)) + // code above same as BK2 + // code below new to BK3 + _, ord, _ := g.Degeneracy() + var p2, x2 Bits + for _, n := range ord { + R.SetBit(n, 1) + p2.Clear() + x2.Clear() + for _, to := range a[n] { + if P.Bit(to) == 1 { + p2.SetBit(to, 1) + } + if X.Bit(to) == 1 { + x2.SetBit(to, 1) + } + } + if !f(&R, &p2, &x2) { + return + } + R.SetBit(n, 0) + P.SetBit(n, 0) + X.SetBit(n, 1) + } +} + +// ConnectedComponentBits returns a function that iterates over connected +// components of g, returning a member bitmap for each. +// +// Each call of the returned function returns the order (number of nodes) +// and bits of a connected component. The returned function returns zeros +// after returning all connected components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentReps, which has lighter weight return values. +func (g Undirected) ConnectedComponentBits() func() (order int, bits Bits) { + a := g.AdjacencyList + var vg Bits // nodes visited in graph + var vc *Bits // nodes visited in current component + var nc int + var df func(NI) + df = func(n NI) { + vg.SetBit(n, 1) + vc.SetBit(n, 1) + nc++ + for _, nb := range a[n] { + if vg.Bit(nb) == 0 { + df(nb) + } + } + return + } + var n NI + return func() (o int, bits Bits) { + for ; n < NI(len(a)); n++ { + if vg.Bit(n) == 0 { + vc = &bits + nc = 0 + df(n) + return nc, bits + } + } + return + } +} + +// ConnectedComponentLists returns a function that iterates over connected +// components of g, returning the member list of each. +// +// Each call of the returned function returns a node list of a connected +// component. The returned function returns nil after returning all connected +// components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentReps, which has lighter weight return values. +func (g Undirected) ConnectedComponentLists() func() []NI { + a := g.AdjacencyList + var vg Bits // nodes visited in graph + var m []NI // members of current component + var df func(NI) + df = func(n NI) { + vg.SetBit(n, 1) + m = append(m, n) + for _, nb := range a[n] { + if vg.Bit(nb) == 0 { + df(nb) + } + } + return + } + var n NI + return func() []NI { + for ; n < NI(len(a)); n++ { + if vg.Bit(n) == 0 { + m = nil + df(n) + return m + } + } + return nil + } +} + +// ConnectedComponentReps returns a representative node from each connected +// component of g. +// +// Returned is a slice with a single representative node from each connected +// component and also a parallel slice with the order, or number of nodes, +// in the corresponding component. +// +// This is fairly minimal information describing connected components. +// From a representative node, other nodes in the component can be reached +// by depth first traversal for example. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentBits and ConnectedComponentLists which can +// collect component members in a single traversal, and IsConnected which +// is an even simpler boolean test. +func (g Undirected) ConnectedComponentReps() (reps []NI, orders []int) { + a := g.AdjacencyList + var c Bits + var o int + var df func(NI) + df = func(n NI) { + c.SetBit(n, 1) + o++ + for _, nb := range a[n] { + if c.Bit(nb) == 0 { + df(nb) + } + } + return + } + for n := range a { + if c.Bit(NI(n)) == 0 { + reps = append(reps, NI(n)) + o = 0 + df(NI(n)) + orders = append(orders, o) + } + } + return +} + +// Copy makes a deep copy of g. +// Copy also computes the arc size ma, the number of arcs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) Copy() (c Undirected, ma int) { + l, s := g.AdjacencyList.Copy() + return Undirected{l}, s +} + +// Degeneracy computes k-degeneracy, vertex ordering and k-cores. +// +// See Wikipedia https://en.wikipedia.org/wiki/Degeneracy_(graph_theory) +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) Degeneracy() (k int, ordering []NI, cores []int) { + a := g.AdjacencyList + // WP algorithm + ordering = make([]NI, len(a)) + var L Bits + d := make([]int, len(a)) + var D [][]NI + for v, nb := range a { + dv := len(nb) + d[v] = dv + for len(D) <= dv { + D = append(D, nil) + } + D[dv] = append(D[dv], NI(v)) + } + for ox := range a { + // find a non-empty D + i := 0 + for len(D[i]) == 0 { + i++ + } + // k is max(i, k) + if i > k { + for len(cores) <= i { + cores = append(cores, 0) + } + cores[k] = ox + k = i + } + // select from D[i] + Di := D[i] + last := len(Di) - 1 + v := Di[last] + // Add v to ordering, remove from Di + ordering[ox] = v + L.SetBit(v, 1) + D[i] = Di[:last] + // move neighbors + for _, nb := range a[v] { + if L.Bit(nb) == 1 { + continue + } + dn := d[nb] // old number of neighbors of nb + Ddn := D[dn] // nb is in this list + // remove it from the list + for wx, w := range Ddn { + if w == nb { + last := len(Ddn) - 1 + Ddn[wx], Ddn[last] = Ddn[last], Ddn[wx] + D[dn] = Ddn[:last] + } + } + dn-- // new number of neighbors + d[nb] = dn + // re--add it to it's new list + D[dn] = append(D[dn], nb) + } + } + cores[k] = len(ordering) + return +} + +// Degree for undirected graphs, returns the degree of a node. +// +// The degree of a node in an undirected graph is the number of incident +// edges, where loops count twice. +// +// If g is known to be loop-free, the result is simply equivalent to len(g[n]). +// See handshaking lemma example at AdjacencyList.ArcSize. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) Degree(n NI) int { + to := g.AdjacencyList[n] + d := len(to) // just "out" degree, + for _, to := range to { + if to == n { + d++ // except loops count twice + } + } + return d +} + +// FromList constructs a FromList representing the tree reachable from +// the given root. +// +// The connected component containing root should represent a simple graph, +// connected as a tree. +// +// For nodes connected as a tree, the Path member of the returned FromList +// will be populated with both From and Len values. The MaxLen member will be +// set but Leaves will be left a zero value. Return value cycle will be -1. +// +// If the connected component containing root is not connected as a tree, +// a cycle will be detected. The returned FromList will be a zero value and +// return value cycle will be a node involved in the cycle. +// +// Loops and parallel edges will be detected as cycles, however only in the +// connected component containing root. If g is not fully connected, nodes +// not reachable from root will have PathEnd values of {From: -1, Len: 0}. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) FromList(root NI) (f FromList, cycle NI) { + p := make([]PathEnd, len(g.AdjacencyList)) + for i := range p { + p[i].From = -1 + } + ml := 0 + var df func(NI, NI) bool + df = func(fr, n NI) bool { + l := p[n].Len + 1 + for _, to := range g.AdjacencyList[n] { + if to == fr { + continue + } + if p[to].Len > 0 { + cycle = to + return false + } + p[to] = PathEnd{From: n, Len: l} + if l > ml { + ml = l + } + if !df(n, to) { + return false + } + } + return true + } + p[root].Len = 1 + if !df(-1, root) { + return + } + return FromList{Paths: p, MaxLen: ml}, -1 +} + +// IsConnected tests if an undirected graph is a single connected component. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentReps for a method returning more information. +func (g Undirected) IsConnected() bool { + a := g.AdjacencyList + if len(a) == 0 { + return true + } + var b Bits + b.SetAll(len(a)) + var df func(NI) + df = func(n NI) { + b.SetBit(n, 0) + for _, to := range a[n] { + if b.Bit(to) == 1 { + df(to) + } + } + } + df(0) + return b.Zero() +} + +// IsTree identifies trees in undirected graphs. +// +// Return value isTree is true if the connected component reachable from root +// is a tree. Further, return value allTree is true if the entire graph g is +// connected. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) IsTree(root NI) (isTree, allTree bool) { + a := g.AdjacencyList + var v Bits + v.SetAll(len(a)) + var df func(NI, NI) bool + df = func(fr, n NI) bool { + if v.Bit(n) == 0 { + return false + } + v.SetBit(n, 0) + for _, to := range a[n] { + if to != fr && !df(n, to) { + return false + } + } + return true + } + v.SetBit(root, 0) + for _, to := range a[root] { + if !df(root, to) { + return false, false + } + } + return true, v.Zero() +} + +// Size returns the number of edges in g. +// +// See also ArcSize and HasLoop. +func (g Undirected) Size() int { + m2 := 0 + for fr, to := range g.AdjacencyList { + m2 += len(to) + for _, to := range to { + if to == NI(fr) { + m2++ + } + } + } + return m2 / 2 +} diff --git a/vendor/github.com/soniakeys/graph/undir_cg.go b/vendor/github.com/soniakeys/graph/undir_cg.go new file mode 100644 index 0000000..35b5b97 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/undir_cg.go @@ -0,0 +1,659 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// undir_RO.go is code generated from undir_cg.go by directives in graph.go. +// Editing undir_cg.go is okay. It is the code generation source. +// DO NOT EDIT undir_RO.go. +// The RO means read only and it is upper case RO to slow you down a bit +// in case you start to edit the file. + +// Bipartite determines if a connected component of an undirected graph +// is bipartite, a component where nodes can be partitioned into two sets +// such that every edge in the component goes from one set to the other. +// +// Argument n can be any representative node of the component. +// +// If the component is bipartite, Bipartite returns true and a two-coloring +// of the component. Each color set is returned as a bitmap. If the component +// is not bipartite, Bipartite returns false and a representative odd cycle. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) Bipartite(n NI) (b bool, c1, c2 Bits, oc []NI) { + b = true + var open bool + var df func(n NI, c1, c2 *Bits) + df = func(n NI, c1, c2 *Bits) { + c1.SetBit(n, 1) + for _, nb := range g.LabeledAdjacencyList[n] { + if c1.Bit(nb.To) == 1 { + b = false + oc = []NI{nb.To, n} + open = true + return + } + if c2.Bit(nb.To) == 1 { + continue + } + df(nb.To, c2, c1) + if b { + continue + } + switch { + case !open: + case n == oc[0]: + open = false + default: + oc = append(oc, n) + } + return + } + } + df(n, &c1, &c2) + if b { + return b, c1, c2, nil + } + return b, Bits{}, Bits{}, oc +} + +// BronKerbosch1 finds maximal cliques in an undirected graph. +// +// The graph must not contain parallel edges or loops. +// +// See https://en.wikipedia.org/wiki/Clique_(graph_theory) and +// https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm for background. +// +// This method implements the BronKerbosch1 algorithm of WP; that is, +// the original algorithm without improvements. +// +// The method calls the emit argument for each maximal clique in g, as long +// as emit returns true. If emit returns false, BronKerbosch1 returns +// immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also more sophisticated variants BronKerbosch2 and BronKerbosch3. +func (g LabeledUndirected) BronKerbosch1(emit func([]NI) bool) { + a := g.LabeledAdjacencyList + var f func(R, P, X *Bits) bool + f = func(R, P, X *Bits) bool { + switch { + case !P.Zero(): + var r2, p2, x2 Bits + pf := func(n NI) bool { + r2.Set(*R) + r2.SetBit(n, 1) + p2.Clear() + x2.Clear() + for _, to := range a[n] { + if P.Bit(to.To) == 1 { + p2.SetBit(to.To, 1) + } + if X.Bit(to.To) == 1 { + x2.SetBit(to.To, 1) + } + } + if !f(&r2, &p2, &x2) { + return false + } + P.SetBit(n, 0) + X.SetBit(n, 1) + return true + } + if !P.Iterate(pf) { + return false + } + case X.Zero(): + return emit(R.Slice()) + } + return true + } + var R, P, X Bits + P.SetAll(len(a)) + f(&R, &P, &X) +} + +// BKPivotMaxDegree is a strategy for BronKerbosch methods. +// +// To use it, take the method value (see golang.org/ref/spec#Method_values) +// and pass it as the argument to BronKerbosch2 or 3. +// +// The strategy is to pick the node from P or X with the maximum degree +// (number of edges) in g. Note this is a shortcut from evaluating degrees +// in P. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) BKPivotMaxDegree(P, X *Bits) (p NI) { + // choose pivot u as highest degree node from P or X + a := g.LabeledAdjacencyList + maxDeg := -1 + P.Iterate(func(n NI) bool { // scan P + if d := len(a[n]); d > maxDeg { + p = n + maxDeg = d + } + return true + }) + X.Iterate(func(n NI) bool { // scan X + if d := len(a[n]); d > maxDeg { + p = n + maxDeg = d + } + return true + }) + return +} + +// BKPivotMinP is a strategy for BronKerbosch methods. +// +// To use it, take the method value (see golang.org/ref/spec#Method_values) +// and pass it as the argument to BronKerbosch2 or 3. +// +// The strategy is to simply pick the first node in P. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) BKPivotMinP(P, X *Bits) NI { + return P.From(0) +} + +// BronKerbosch2 finds maximal cliques in an undirected graph. +// +// The graph must not contain parallel edges or loops. +// +// See https://en.wikipedia.org/wiki/Clique_(graph_theory) and +// https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm for background. +// +// This method implements the BronKerbosch2 algorithm of WP; that is, +// the original algorithm plus pivoting. +// +// The argument is a pivot function that must return a node of P or X. +// P is guaranteed to contain at least one node. X is not. +// For example see BKPivotMaxDegree. +// +// The method calls the emit argument for each maximal clique in g, as long +// as emit returns true. If emit returns false, BronKerbosch1 returns +// immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also simpler variant BronKerbosch1 and more sophisticated variant +// BronKerbosch3. +func (g LabeledUndirected) BronKerbosch2(pivot func(P, X *Bits) NI, emit func([]NI) bool) { + a := g.LabeledAdjacencyList + var f func(R, P, X *Bits) bool + f = func(R, P, X *Bits) bool { + switch { + case !P.Zero(): + var r2, p2, x2, pnu Bits + // compute P \ N(u). next 5 lines are only difference from BK1 + pnu.Set(*P) + for _, to := range a[pivot(P, X)] { + pnu.SetBit(to.To, 0) + } + // remaining code like BK1 + pf := func(n NI) bool { + r2.Set(*R) + r2.SetBit(n, 1) + p2.Clear() + x2.Clear() + for _, to := range a[n] { + if P.Bit(to.To) == 1 { + p2.SetBit(to.To, 1) + } + if X.Bit(to.To) == 1 { + x2.SetBit(to.To, 1) + } + } + if !f(&r2, &p2, &x2) { + return false + } + P.SetBit(n, 0) + X.SetBit(n, 1) + return true + } + if !pnu.Iterate(pf) { + return false + } + case X.Zero(): + return emit(R.Slice()) + } + return true + } + var R, P, X Bits + P.SetAll(len(a)) + f(&R, &P, &X) +} + +// BronKerbosch3 finds maximal cliques in an undirected graph. +// +// The graph must not contain parallel edges or loops. +// +// See https://en.wikipedia.org/wiki/Clique_(graph_theory) and +// https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm for background. +// +// This method implements the BronKerbosch3 algorithm of WP; that is, +// the original algorithm with pivoting and degeneracy ordering. +// +// The argument is a pivot function that must return a node of P or X. +// P is guaranteed to contain at least one node. X is not. +// For example see BKPivotMaxDegree. +// +// The method calls the emit argument for each maximal clique in g, as long +// as emit returns true. If emit returns false, BronKerbosch1 returns +// immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also simpler variants BronKerbosch1 and BronKerbosch2. +func (g LabeledUndirected) BronKerbosch3(pivot func(P, X *Bits) NI, emit func([]NI) bool) { + a := g.LabeledAdjacencyList + var f func(R, P, X *Bits) bool + f = func(R, P, X *Bits) bool { + switch { + case !P.Zero(): + var r2, p2, x2, pnu Bits + // compute P \ N(u). next lines are only difference from BK1 + pnu.Set(*P) + for _, to := range a[pivot(P, X)] { + pnu.SetBit(to.To, 0) + } + // remaining code like BK2 + pf := func(n NI) bool { + r2.Set(*R) + r2.SetBit(n, 1) + p2.Clear() + x2.Clear() + for _, to := range a[n] { + if P.Bit(to.To) == 1 { + p2.SetBit(to.To, 1) + } + if X.Bit(to.To) == 1 { + x2.SetBit(to.To, 1) + } + } + if !f(&r2, &p2, &x2) { + return false + } + P.SetBit(n, 0) + X.SetBit(n, 1) + return true + } + if !pnu.Iterate(pf) { + return false + } + case X.Zero(): + return emit(R.Slice()) + } + return true + } + var R, P, X Bits + P.SetAll(len(a)) + // code above same as BK2 + // code below new to BK3 + _, ord, _ := g.Degeneracy() + var p2, x2 Bits + for _, n := range ord { + R.SetBit(n, 1) + p2.Clear() + x2.Clear() + for _, to := range a[n] { + if P.Bit(to.To) == 1 { + p2.SetBit(to.To, 1) + } + if X.Bit(to.To) == 1 { + x2.SetBit(to.To, 1) + } + } + if !f(&R, &p2, &x2) { + return + } + R.SetBit(n, 0) + P.SetBit(n, 0) + X.SetBit(n, 1) + } +} + +// ConnectedComponentBits returns a function that iterates over connected +// components of g, returning a member bitmap for each. +// +// Each call of the returned function returns the order (number of nodes) +// and bits of a connected component. The returned function returns zeros +// after returning all connected components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentReps, which has lighter weight return values. +func (g LabeledUndirected) ConnectedComponentBits() func() (order int, bits Bits) { + a := g.LabeledAdjacencyList + var vg Bits // nodes visited in graph + var vc *Bits // nodes visited in current component + var nc int + var df func(NI) + df = func(n NI) { + vg.SetBit(n, 1) + vc.SetBit(n, 1) + nc++ + for _, nb := range a[n] { + if vg.Bit(nb.To) == 0 { + df(nb.To) + } + } + return + } + var n NI + return func() (o int, bits Bits) { + for ; n < NI(len(a)); n++ { + if vg.Bit(n) == 0 { + vc = &bits + nc = 0 + df(n) + return nc, bits + } + } + return + } +} + +// ConnectedComponentLists returns a function that iterates over connected +// components of g, returning the member list of each. +// +// Each call of the returned function returns a node list of a connected +// component. The returned function returns nil after returning all connected +// components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentReps, which has lighter weight return values. +func (g LabeledUndirected) ConnectedComponentLists() func() []NI { + a := g.LabeledAdjacencyList + var vg Bits // nodes visited in graph + var m []NI // members of current component + var df func(NI) + df = func(n NI) { + vg.SetBit(n, 1) + m = append(m, n) + for _, nb := range a[n] { + if vg.Bit(nb.To) == 0 { + df(nb.To) + } + } + return + } + var n NI + return func() []NI { + for ; n < NI(len(a)); n++ { + if vg.Bit(n) == 0 { + m = nil + df(n) + return m + } + } + return nil + } +} + +// ConnectedComponentReps returns a representative node from each connected +// component of g. +// +// Returned is a slice with a single representative node from each connected +// component and also a parallel slice with the order, or number of nodes, +// in the corresponding component. +// +// This is fairly minimal information describing connected components. +// From a representative node, other nodes in the component can be reached +// by depth first traversal for example. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentBits and ConnectedComponentLists which can +// collect component members in a single traversal, and IsConnected which +// is an even simpler boolean test. +func (g LabeledUndirected) ConnectedComponentReps() (reps []NI, orders []int) { + a := g.LabeledAdjacencyList + var c Bits + var o int + var df func(NI) + df = func(n NI) { + c.SetBit(n, 1) + o++ + for _, nb := range a[n] { + if c.Bit(nb.To) == 0 { + df(nb.To) + } + } + return + } + for n := range a { + if c.Bit(NI(n)) == 0 { + reps = append(reps, NI(n)) + o = 0 + df(NI(n)) + orders = append(orders, o) + } + } + return +} + +// Copy makes a deep copy of g. +// Copy also computes the arc size ma, the number of arcs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) Copy() (c LabeledUndirected, ma int) { + l, s := g.LabeledAdjacencyList.Copy() + return LabeledUndirected{l}, s +} + +// Degeneracy computes k-degeneracy, vertex ordering and k-cores. +// +// See Wikipedia https://en.wikipedia.org/wiki/Degeneracy_(graph_theory) +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) Degeneracy() (k int, ordering []NI, cores []int) { + a := g.LabeledAdjacencyList + // WP algorithm + ordering = make([]NI, len(a)) + var L Bits + d := make([]int, len(a)) + var D [][]NI + for v, nb := range a { + dv := len(nb) + d[v] = dv + for len(D) <= dv { + D = append(D, nil) + } + D[dv] = append(D[dv], NI(v)) + } + for ox := range a { + // find a non-empty D + i := 0 + for len(D[i]) == 0 { + i++ + } + // k is max(i, k) + if i > k { + for len(cores) <= i { + cores = append(cores, 0) + } + cores[k] = ox + k = i + } + // select from D[i] + Di := D[i] + last := len(Di) - 1 + v := Di[last] + // Add v to ordering, remove from Di + ordering[ox] = v + L.SetBit(v, 1) + D[i] = Di[:last] + // move neighbors + for _, nb := range a[v] { + if L.Bit(nb.To) == 1 { + continue + } + dn := d[nb.To] // old number of neighbors of nb + Ddn := D[dn] // nb is in this list + // remove it from the list + for wx, w := range Ddn { + if w == nb.To { + last := len(Ddn) - 1 + Ddn[wx], Ddn[last] = Ddn[last], Ddn[wx] + D[dn] = Ddn[:last] + } + } + dn-- // new number of neighbors + d[nb.To] = dn + // re--add it to it's new list + D[dn] = append(D[dn], nb.To) + } + } + cores[k] = len(ordering) + return +} + +// Degree for undirected graphs, returns the degree of a node. +// +// The degree of a node in an undirected graph is the number of incident +// edges, where loops count twice. +// +// If g is known to be loop-free, the result is simply equivalent to len(g[n]). +// See handshaking lemma example at AdjacencyList.ArcSize. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) Degree(n NI) int { + to := g.LabeledAdjacencyList[n] + d := len(to) // just "out" degree, + for _, to := range to { + if to.To == n { + d++ // except loops count twice + } + } + return d +} + +// FromList constructs a FromList representing the tree reachable from +// the given root. +// +// The connected component containing root should represent a simple graph, +// connected as a tree. +// +// For nodes connected as a tree, the Path member of the returned FromList +// will be populated with both From and Len values. The MaxLen member will be +// set but Leaves will be left a zero value. Return value cycle will be -1. +// +// If the connected component containing root is not connected as a tree, +// a cycle will be detected. The returned FromList will be a zero value and +// return value cycle will be a node involved in the cycle. +// +// Loops and parallel edges will be detected as cycles, however only in the +// connected component containing root. If g is not fully connected, nodes +// not reachable from root will have PathEnd values of {From: -1, Len: 0}. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) FromList(root NI) (f FromList, cycle NI) { + p := make([]PathEnd, len(g.LabeledAdjacencyList)) + for i := range p { + p[i].From = -1 + } + ml := 0 + var df func(NI, NI) bool + df = func(fr, n NI) bool { + l := p[n].Len + 1 + for _, to := range g.LabeledAdjacencyList[n] { + if to.To == fr { + continue + } + if p[to.To].Len > 0 { + cycle = to.To + return false + } + p[to.To] = PathEnd{From: n, Len: l} + if l > ml { + ml = l + } + if !df(n, to.To) { + return false + } + } + return true + } + p[root].Len = 1 + if !df(-1, root) { + return + } + return FromList{Paths: p, MaxLen: ml}, -1 +} + +// IsConnected tests if an undirected graph is a single connected component. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentReps for a method returning more information. +func (g LabeledUndirected) IsConnected() bool { + a := g.LabeledAdjacencyList + if len(a) == 0 { + return true + } + var b Bits + b.SetAll(len(a)) + var df func(NI) + df = func(n NI) { + b.SetBit(n, 0) + for _, to := range a[n] { + if b.Bit(to.To) == 1 { + df(to.To) + } + } + } + df(0) + return b.Zero() +} + +// IsTree identifies trees in undirected graphs. +// +// Return value isTree is true if the connected component reachable from root +// is a tree. Further, return value allTree is true if the entire graph g is +// connected. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) IsTree(root NI) (isTree, allTree bool) { + a := g.LabeledAdjacencyList + var v Bits + v.SetAll(len(a)) + var df func(NI, NI) bool + df = func(fr, n NI) bool { + if v.Bit(n) == 0 { + return false + } + v.SetBit(n, 0) + for _, to := range a[n] { + if to.To != fr && !df(n, to.To) { + return false + } + } + return true + } + v.SetBit(root, 0) + for _, to := range a[root] { + if !df(root, to.To) { + return false, false + } + } + return true, v.Zero() +} + +// Size returns the number of edges in g. +// +// See also ArcSize and HasLoop. +func (g LabeledUndirected) Size() int { + m2 := 0 + for fr, to := range g.LabeledAdjacencyList { + m2 += len(to) + for _, to := range to { + if to.To == NI(fr) { + m2++ + } + } + } + return m2 / 2 +} |
