diff options
Diffstat (limited to 'vendor/github.com/soniakeys/graph/dir.go')
| -rw-r--r-- | vendor/github.com/soniakeys/graph/dir.go | 538 | 
1 files changed, 0 insertions, 538 deletions
| diff --git a/vendor/github.com/soniakeys/graph/dir.go b/vendor/github.com/soniakeys/graph/dir.go deleted file mode 100644 index 508306d..0000000 --- a/vendor/github.com/soniakeys/graph/dir.go +++ /dev/null @@ -1,538 +0,0 @@ -// 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 -} | 
