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