act/vendor/github.com/soniakeys/graph/undir.go

818 lines
23 KiB
Go
Raw Normal View History

// 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 (
"fmt"
"github.com/soniakeys/bits"
)
// 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.
//
// If you know or can compute the final graph order however, consider
// preallocating to avoid any overhead of expanding the graph.
// See second example, "More".
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)
}
}
// RemoveEdge removes a single edge between nodes n1 and n2.
//
// It removes reciprocal arcs in the case of distinct n1 and n2 or removes
// a single arc loop in the case of n1 == n2.
//
// Returns true if the specified edge is found and successfully removed,
// false if the edge does not exist.
func (g Undirected) RemoveEdge(n1, n2 NI) (ok bool) {
ok, x1, x2 := g.HasEdge(n1, n2)
if !ok {
return
}
a := g.AdjacencyList
to := a[n1]
last := len(to) - 1
to[x1] = to[last]
a[n1] = to[:last]
if n1 == n2 {
return
}
to = a[n2]
last = len(to) - 1
to[x2] = to[last]
a[n2] = to[:last]
return
}
// ArcDensity returns density for a simple directed graph.
//
// Parameter n is order, or number of nodes of a simple directed graph.
// Parameter a is the arc size, or number of directed arcs.
//
// Returned density is the fraction `a` over the total possible number of arcs
// or a / (n * (n-1)).
//
// See also Density for density of a simple undirected graph.
//
// See also the corresponding methods AdjacencyList.ArcDensity and
// LabeledAdjacencyList.ArcDensity.
func ArcDensity(n, a int) float64 {
return float64(a) / (float64(n) * float64(n-1))
}
// Density returns density for a simple undirected graph.
//
// Parameter n is order, or number of nodes of a simple undirected graph.
// Parameter m is the size, or number of undirected edges.
//
// Returned density is the fraction m over the total possible number of edges
// or m / ((n * (n-1))/2).
//
// See also ArcDensity for simple directed graphs.
//
// See also the corresponding methods AdjacencyList.Density and
// LabeledAdjacencyList.Density.
func Density(n, m int) float64 {
return float64(m) * 2 / (float64(n) * float64(n-1))
}
// An EdgeVisitor is an argument to some traversal methods.
//
// Traversal methods call the visitor function for each edge visited.
// Argument e is the edge being visited.
type EdgeVisitor func(e Edge)
// Edges iterates over the edges of an undirected graph.
//
// Edge visitor v is called for each edge of the graph. That is, it is called
// once for each reciprocal arc pair and once for each loop.
//
// See also LabeledUndirected.Edges for a labeled version.
// See also Undirected.SimpleEdges for a version that emits only the simple
// subgraph.
func (g Undirected) Edges(v EdgeVisitor) {
a := g.AdjacencyList
unpaired := make(AdjacencyList, len(a))
for fr, to := range a {
arc: // for each arc in a
for _, to := range to {
if to == NI(fr) {
v(Edge{NI(fr), to}) // output loop
continue
}
// search unpaired arcs
ut := unpaired[to]
for i, u := range ut {
if u == NI(fr) { // found reciprocal
v(Edge{u, to}) // output edge
last := len(ut) - 1
ut[i] = ut[last]
unpaired[to] = ut[:last]
continue arc
}
}
// reciprocal not found
unpaired[fr] = append(unpaired[fr], to)
}
}
// undefined behavior is that unpaired arcs are silently ignored.
}
// FromList builds a forest with a tree spanning each connected component.
//
// For each component a root is chosen and spanning is done with the method
// Undirected.SpanTree, and so is breadth-first. Returned is a FromList with
// all spanned trees, a list of roots chosen, and a bool indicating if the
// receiver graph g was found to be a simple graph connected as a forest.
// Any cycles, loops, or parallel edges in any component will cause
// simpleForest to be false, but FromList f will still be populated with
// a valid and complete spanning forest.
func (g Undirected) FromList() (f FromList, roots []NI, simpleForest bool) {
p := make([]PathEnd, g.Order())
for i := range p {
p[i].From = -1
}
f.Paths = p
simpleForest = true
ts := 0
for n := range g.AdjacencyList {
if p[n].From >= 0 {
continue
}
roots = append(roots, NI(n))
ns, st := g.SpanTree(NI(n), &f)
if !st {
simpleForest = false
}
ts += ns
if ts == len(p) {
break
}
}
return
}
// HasEdge returns true if g has any edge between nodes n1 and n2.
//
// Also returned are indexes x1 and x2 such that g[n1][x1] == n2
// and g[n2][x2] == n1. If no edge between n1 and n2 is present HasArc
// returns `has` == false.
//
// See also HasArc. If you are interested only in the boolean result and
// g is a well formed (passes IsUndirected) then HasArc is an adequate test.
func (g Undirected) HasEdge(n1, n2 NI) (has bool, x1, x2 int) {
if has, x1 = g.HasArc(n1, n2); !has {
return has, x1, x1
}
has, x2 = g.HasArc(n2, n1)
return
}
// SimpleEdges iterates over the edges of the simple subgraph of an undirected
// graph.
//
// Edge visitor v is called for each pair of distinct nodes that is connected
// with an edge. That is, loops are ignored and parallel edges are reduced to
// a single edge.
//
// See also Undirected.Edges for a version that emits all edges.
func (g Undirected) SimpleEdges(v EdgeVisitor) {
for fr, to := range g.AdjacencyList {
e := bits.New(len(g.AdjacencyList))
for _, to := range to {
if to > NI(fr) && e.Bit(int(to)) == 0 {
e.SetBit(int(to), 1)
v(Edge{NI(fr), to})
}
}
}
// undefined behavior is that unpaired arcs may or may not be emitted.
}
// SpanTree builds a tree spanning a connected component.
//
// The component is spanned by breadth-first search from the given root.
// The resulting spanning tree in stored a FromList.
//
// If FromList.Paths is not the same length as g, it is allocated and
// initialized. This allows a zero value FromList to be passed as f.
// If FromList.Paths is the same length as g, it is used as is and is not
// reinitialized. This allows multiple trees to be spanned in the same
// FromList with successive calls.
//
// For nodes spanned, the Path member of the returned FromList is populated
// with both From and Len values. The MaxLen member will be updated but
// not Leaves.
//
// Returned is the number of nodes spanned, which will be the number of nodes
// in the component, and a bool indicating if the component was found to be a
// simply connected unrooted tree in the receiver graph g. Any cycles, loops,
// or parallel edges in the component will cause simpleTree to be false, but
// FromList f will still be populated with a valid and complete spanning tree.
func (g Undirected) SpanTree(root NI, f *FromList) (nSpanned int, simpleTree bool) {
a := g.AdjacencyList
p := f.Paths
if len(p) != len(a) {
p = make([]PathEnd, len(a))
for i := range p {
p[i].From = -1
}
f.Paths = p
}
simpleTree = true
p[root] = PathEnd{From: -1, Len: 1}
type arc struct {
from NI
half NI
}
var next []arc
frontier := []arc{{-1, root}}
for len(frontier) > 0 {
for _, fa := range frontier { // fa frontier arc
nSpanned++
l := p[fa.half].Len + 1
for _, to := range a[fa.half] {
if to == fa.from {
continue
}
if p[to].Len > 0 {
simpleTree = false
continue
}
p[to] = PathEnd{From: fa.half, Len: l}
if l > f.MaxLen {
f.MaxLen = l
}
next = append(next, arc{fa.half, to})
}
}
frontier, next = next, frontier[:0]
}
return
}
// 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."
a := g.AdjacencyList
number := make([]int, len(a))
lowpt := make([]int, len(a))
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 a[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 a {
if number[w] == 0 && !biconnect(NI(w), -1) {
return
}
}
}
func (g Undirected) BlockCut(block func([]Edge) bool, cut func(NI) bool, isolated func(NI) bool) {
a := g.AdjacencyList
number := make([]int, len(a))
lowpt := make([]int, len(a))
var stack []Edge
var i, rc int
var biconnect func(NI, NI) bool
biconnect = func(v, u NI) bool {
i++
number[v] = i
lowpt[v] = i
for _, w := range a[v] {
if number[w] == 0 {
if u < 0 {
rc++
}
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] {
if u >= 0 && !cut(v) {
return false
}
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 !block(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]
}
}
}
if u < 0 && rc > 1 {
return cut(v)
}
return true
}
for w := range a {
if number[w] > 0 {
continue
}
if len(a[w]) == 0 {
if !isolated(NI(w)) {
return
}
continue
}
rc = 0
if !biconnect(NI(w), -1) {
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})
}
}
// A LabeledEdgeVisitor is an argument to some traversal methods.
//
// Traversal methods call the visitor function for each edge visited.
// Argument e is the edge being visited.
type LabeledEdgeVisitor func(e LabeledEdge)
// Edges iterates over the edges of a labeled undirected graph.
//
// Edge visitor v is called for each edge of the graph. That is, it is called
// once for each reciprocal arc pair and once for each loop.
//
// See also Undirected.Edges for an unlabeled version.
// See also the more simplistic LabeledAdjacencyList.ArcsAsEdges.
func (g LabeledUndirected) Edges(v LabeledEdgeVisitor) {
// similar code in LabeledAdjacencyList.InUndirected
a := g.LabeledAdjacencyList
unpaired := make(LabeledAdjacencyList, len(a))
for fr, to := range a {
arc: // for each arc in a
for _, to := range to {
if to.To == NI(fr) {
v(LabeledEdge{Edge{NI(fr), to.To}, to.Label}) // output loop
continue
}
// search unpaired arcs
ut := unpaired[to.To]
for i, u := range ut {
if u.To == NI(fr) && u.Label == to.Label { // found reciprocal
v(LabeledEdge{Edge{NI(fr), to.To}, to.Label}) // output edge
last := len(ut) - 1
ut[i] = ut[last]
unpaired[to.To] = ut[:last]
continue arc
}
}
// reciprocal not found
unpaired[fr] = append(unpaired[fr], to)
}
}
}
// FromList builds a forest with a tree spanning each connected component in g.
//
// A root is chosen and spanning is done with the LabeledUndirected.SpanTree
// method, and so is breadth-first. Returned is a FromList with all spanned
// trees, labels corresponding to arcs in f,
// a list of roots chosen, and a bool indicating if the receiver graph g was
// found to be a simple graph connected as a forest. Any cycles, loops, or
// parallel edges in any component will cause simpleForest to be false, but
// FromList f will still be populated with a valid and complete spanning forest.
// FromList builds a forest with a tree spanning each connected component.
//
// For each component a root is chosen and spanning is done with the method
// Undirected.SpanTree, and so is breadth-first. Returned is a FromList with
// all spanned trees, labels corresponding to arcs in f, a list of roots
// chosen, and a bool indicating if the receiver graph g was found to be a
// simple graph connected as a forest. Any cycles, loops, or parallel edges
// in any component will cause simpleForest to be false, but FromList f will
// still be populated with a valid and complete spanning forest.
func (g LabeledUndirected) FromList() (f FromList, labels []LI, roots []NI, simpleForest bool) {
p := make([]PathEnd, g.Order())
for i := range p {
p[i].From = -1
}
f.Paths = p
labels = make([]LI, len(p))
simpleForest = true
ts := 0
for n := range g.LabeledAdjacencyList {
if p[n].From >= 0 {
continue
}
roots = append(roots, NI(n))
ns, st := g.SpanTree(NI(n), &f, labels)
if !st {
simpleForest = false
}
ts += ns
if ts == len(p) {
break
}
}
return
}
// SpanTree builds a tree spanning a connected component.
//
// The component is spanned by breadth-first search from the given root.
// The resulting spanning tree in stored a FromList, and arc labels optionally
// stored in a slice.
//
// If FromList.Paths is not the same length as g, it is allocated and
// initialized. This allows a zero value FromList to be passed as f.
// If FromList.Paths is the same length as g, it is used as is and is not
// reinitialized. This allows multiple trees to be spanned in the same
// FromList with successive calls.
//
// For nodes spanned, the Path member of returned FromList f is populated
// populated with both From and Len values. The MaxLen member will be
// updated but not Leaves.
//
// The labels slice will be populated only if it is same length as g.
// Nil can be passed for example if labels are not needed.
//
// Returned is the number of nodes spanned, which will be the number of nodes
// in the component, and a bool indicating if the component was found to be a
// simply connected unrooted tree in the receiver graph g. Any cycles, loops,
// or parallel edges in the component will cause simpleTree to be false, but
// FromList f will still be populated with a valid and complete spanning tree.
func (g LabeledUndirected) SpanTree(root NI, f *FromList, labels []LI) (nSpanned int, simple bool) {
a := g.LabeledAdjacencyList
p := f.Paths
if len(p) != len(a) {
p = make([]PathEnd, len(a))
for i := range p {
p[i].From = -1
}
f.Paths = p
}
simple = true
p[root].Len = 1
type arc struct {
from NI
half Half
}
var next []arc
frontier := []arc{{-1, Half{root, -1}}}
for len(frontier) > 0 {
for _, fa := range frontier { // fa frontier arc
nSpanned++
l := p[fa.half.To].Len + 1
for _, to := range a[fa.half.To] {
if to.To == fa.from && to.Label == fa.half.Label {
continue
}
if p[to.To].Len > 0 {
simple = false
continue
}
p[to.To] = PathEnd{From: fa.half.To, Len: l}
if len(labels) == len(p) {
labels[to.To] = to.Label
}
if l > f.MaxLen {
f.MaxLen = l
}
next = append(next, arc{fa.half.To, to})
}
}
frontier, next = next, frontier[:0]
}
return
}
// HasEdge returns true if g has any edge between nodes n1 and n2.
//
// Also returned are indexes x1 and x2 such that g[n1][x1] == Half{n2, l}
// and g[n2][x2] == {n1, l} for some label l. If no edge between n1 and n2
// exists, HasArc returns `has` == false.
//
// See also HasArc. If you are only interested in the boolean result then
// HasArc is an adequate test.
func (g LabeledUndirected) HasEdge(n1, n2 NI) (has bool, x1, x2 int) {
if has, x1 = g.HasArc(n1, n2); !has {
return has, x1, x1
}
has, x2 = g.HasArcLabel(n2, n1, g.LabeledAdjacencyList[n1][x1].Label)
return
}
// HasEdgeLabel returns true if g has any edge between nodes n1 and n2 with
// label l.
//
// Also returned are indexes x1 and x2 such that g[n1][x1] == Half{n2, l}
// and g[n2][x2] == Half{n1, l}. If no edge between n1 and n2 with label l
// is present HasArc returns `has` == false.
func (g LabeledUndirected) HasEdgeLabel(n1, n2 NI, l LI) (has bool, x1, x2 int) {
if has, x1 = g.HasArcLabel(n1, n2, l); !has {
return has, x1, x1
}
has, x2 = g.HasArcLabel(n2, n1, l)
return
}
// RemoveEdge removes a single edge between nodes n1 and n2.
//
// It removes reciprocal arcs in the case of distinct n1 and n2 or removes
// a single arc loop in the case of n1 == n2.
//
// If the specified edge is found and successfully removed, RemoveEdge returns
// true and the label of the edge removed. If no edge exists between n1 and n2,
// RemoveEdge returns false, 0.
func (g LabeledUndirected) RemoveEdge(n1, n2 NI) (ok bool, label LI) {
ok, x1, x2 := g.HasEdge(n1, n2)
if !ok {
return
}
a := g.LabeledAdjacencyList
to := a[n1]
label = to[x1].Label // return value
last := len(to) - 1
to[x1] = to[last]
a[n1] = to[:last]
if n1 == n2 {
return
}
to = a[n2]
last = len(to) - 1
to[x2] = to[last]
a[n2] = to[:last]
return
}
// RemoveEdgeLabel removes a single edge between nodes n1 and n2 with label l.
//
// It removes reciprocal arcs in the case of distinct n1 and n2 or removes
// a single arc loop in the case of n1 == n2.
//
// Returns true if the specified edge is found and successfully removed,
// false if the edge does not exist.
func (g LabeledUndirected) RemoveEdgeLabel(n1, n2 NI, l LI) (ok bool) {
ok, x1, x2 := g.HasEdgeLabel(n1, n2, l)
if !ok {
return
}
a := g.LabeledAdjacencyList
to := a[n1]
last := len(to) - 1
to[x1] = to[last]
a[n1] = to[:last]
if n1 == n2 {
return
}
to = a[n2]
last = len(to) - 1
to[x2] = to[last]
a[n2] = to[:last]
return
}
// 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) {
// Code nearly identical to unlabled version.
number := make([]int, g.Order())
lowpt := make([]int, g.Order())
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), -1) {
return
}
}
}
func (e *eulerian) pushUndir() error {
for u := e.top(); ; {
e.uv.SetBit(int(u), 0)
arcs := e.g[u]
if len(arcs) == 0 {
return nil
}
w := arcs[0]
e.s++
e.p[e.s] = w
e.g[u] = arcs[1:] // consume arc
// difference from directed counterpart in dir.go:
// as long as it's not a loop, consume reciprocal arc as well
if w != u {
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.
goto l
}
}
return fmt.Errorf("graph not undirected. %d -> %d reciprocal not found", u, w)
}
l:
u = w
}
}
func (e *labEulerian) pushUndir() error {
for u := e.top(); ; {
e.uv.SetBit(int(u.To), 0)
arcs := e.g[u.To]
if len(arcs) == 0 {
return nil
}
w := arcs[0]
e.s++
e.p[e.s] = w
e.g[u.To] = arcs[1:] // consume arc
// difference from directed counterpart in dir.go:
// as long as it's not a loop, consume reciprocal arc as well
if w.To != u.To {
a2 := e.g[w.To]
for x, rx := range a2 {
if rx.To == u.To && rx.Label == w.Label { // here it is
last := len(a2) - 1
a2[x] = a2[last] // someone else can have the seat
e.g[w.To] = a2[:last] // and it's gone.
goto l
}
}
return fmt.Errorf("graph not undirected. %d -> %v reciprocal not found", u.To, w)
}
l:
u = w
}
}