replace parser with actions/workflow-parser
This commit is contained in:
417
vendor/github.com/soniakeys/graph/adj_RO.go
generated
vendored
Normal file
417
vendor/github.com/soniakeys/graph/adj_RO.go
generated
vendored
Normal file
@@ -0,0 +1,417 @@
|
||||
// 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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
"github.com/soniakeys/bits"
|
||||
)
|
||||
|
||||
// ArcDensity returns density for an simple directed graph.
|
||||
//
|
||||
// See also ArcDensity function.
|
||||
//
|
||||
// There are equivalent labeled and unlabeled versions of this method.
|
||||
func (g AdjacencyList) ArcDensity() float64 {
|
||||
return ArcDensity(len(g), g.ArcSize())
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// Traversal starts at node start and visits the nodes reachable from
|
||||
// start. The function visit is called for each node visited. Nodes
|
||||
// not reachable from start are not visited.
|
||||
//
|
||||
// There are equivalent labeled and unlabeled versions of this method.
|
||||
//
|
||||
// See also alt.BreadthFirst, a variant with more options, and
|
||||
// alt.BreadthFirst2, a direction optimizing variant.
|
||||
func (g AdjacencyList) BreadthFirst(start NI, visit func(NI)) {
|
||||
v := bits.New(len(g))
|
||||
v.SetBit(int(start), 1)
|
||||
visit(start)
|
||||
var next []NI
|
||||
for frontier := []NI{start}; len(frontier) > 0; {
|
||||
for _, n := range frontier {
|
||||
for _, nb := range g[n] {
|
||||
if v.Bit(int(nb)) == 0 {
|
||||
v.SetBit(int(nb), 1)
|
||||
visit(nb)
|
||||
next = append(next, nb)
|
||||
}
|
||||
}
|
||||
}
|
||||
frontier, next = next, frontier[:0]
|
||||
}
|
||||
}
|
||||
|
||||
// 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 directed or undirected graph in depth
|
||||
// first order.
|
||||
//
|
||||
// Traversal starts at node start and visits the nodes reachable from
|
||||
// start. The function visit is called for each node visited. Nodes
|
||||
// not reachable from start are not visited.
|
||||
//
|
||||
// There are equivalent labeled and unlabeled versions of this method.
|
||||
//
|
||||
// See also alt.DepthFirst, a variant with more options.
|
||||
func (g AdjacencyList) DepthFirst(start NI, visit func(NI)) {
|
||||
v := bits.New(len(g))
|
||||
var f func(NI)
|
||||
f = func(n NI) {
|
||||
visit(n)
|
||||
v.SetBit(int(n), 1)
|
||||
for _, to := range g[n] {
|
||||
if v.Bit(int(to)) == 0 {
|
||||
f(to)
|
||||
}
|
||||
}
|
||||
}
|
||||
f(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.
|
||||
//
|
||||
// See also the method ParallelArcs, which finds all parallel arcs from
|
||||
// `fr` to `to`.
|
||||
func (g AdjacencyList) HasArc(fr, to NI) (bool, int) {
|
||||
for x, h := range g[fr] {
|
||||
if h == to {
|
||||
return true, x
|
||||
}
|
||||
}
|
||||
return false, -1
|
||||
}
|
||||
|
||||
// AnyLoop identifies if a graph contains a loop, an arc that leads from a
|
||||
// a node back to the same node.
|
||||
//
|
||||
// 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) AnyLoop() (bool, NI) {
|
||||
for fr, to := range g {
|
||||
for _, to := range to {
|
||||
if NI(fr) == to {
|
||||
return true, to
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, -1
|
||||
}
|
||||
|
||||
// AddNode maps a node in a supergraph to a subgraph node.
|
||||
//
|
||||
// Argument p must be an NI in supergraph s.Super. AddNode panics if
|
||||
// p is not a valid node index of s.Super.
|
||||
//
|
||||
// AddNode is idempotent in that it does not add a new node to the subgraph if
|
||||
// a subgraph node already exists mapped to supergraph node p.
|
||||
//
|
||||
// The mapped subgraph NI is returned.
|
||||
func (s *Subgraph) AddNode(p NI) (b NI) {
|
||||
if int(p) < 0 || int(p) >= s.Super.Order() {
|
||||
panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph"))
|
||||
}
|
||||
if b, ok := s.SubNI[p]; ok {
|
||||
return b
|
||||
}
|
||||
a := s.AdjacencyList
|
||||
b = NI(len(a))
|
||||
s.AdjacencyList = append(a, nil)
|
||||
s.SuperNI = append(s.SuperNI, p)
|
||||
s.SubNI[p] = b
|
||||
return
|
||||
}
|
||||
|
||||
// AddArc adds an arc to a subgraph.
|
||||
//
|
||||
// Arguments fr, to must be NIs in supergraph s.Super. As with AddNode,
|
||||
// AddArc panics if fr and to are not valid node indexes of s.Super.
|
||||
//
|
||||
// The arc specfied by fr, to must exist in s.Super. Further, the number of
|
||||
// parallel arcs in the subgraph cannot exceed the number of corresponding
|
||||
// parallel arcs in the supergraph. That is, each arc already added to the
|
||||
// subgraph counts against the arcs available in the supergraph. If a matching
|
||||
// arc is not available, AddArc returns an error.
|
||||
//
|
||||
// If a matching arc is available, subgraph nodes are added as needed, the
|
||||
// subgraph arc is added, and the method returns nil.
|
||||
func (s *Subgraph) AddArc(fr NI, to NI) error {
|
||||
// verify supergraph NIs first, but without adding subgraph nodes just yet.
|
||||
if int(fr) < 0 || int(fr) >= s.Super.Order() {
|
||||
panic(fmt.Sprint("AddArc: NI ", fr, " not in supergraph"))
|
||||
}
|
||||
if int(to) < 0 || int(to) >= s.Super.Order() {
|
||||
panic(fmt.Sprint("AddArc: NI ", to, " not in supergraph"))
|
||||
}
|
||||
// count existing matching arcs in subgraph
|
||||
n := 0
|
||||
a := s.AdjacencyList
|
||||
if bf, ok := s.SubNI[fr]; ok {
|
||||
if bt, ok := s.SubNI[to]; ok {
|
||||
// both NIs already exist in subgraph, need to count arcs
|
||||
bTo := to
|
||||
bTo = bt
|
||||
for _, t := range a[bf] {
|
||||
if t == bTo {
|
||||
n++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// verify matching arcs are available in supergraph
|
||||
for _, t := range (*s.Super)[fr] {
|
||||
if t == to {
|
||||
if n > 0 {
|
||||
n-- // match existing arc
|
||||
continue
|
||||
}
|
||||
// no more existing arcs need to be matched. nodes can finally
|
||||
// be added as needed and then the arc can be added.
|
||||
bf := s.AddNode(fr)
|
||||
to = s.AddNode(to)
|
||||
s.AdjacencyList[bf] = append(s.AdjacencyList[bf], to)
|
||||
return nil // success
|
||||
}
|
||||
}
|
||||
return errors.New("arc not available in supergraph")
|
||||
}
|
||||
|
||||
func (super AdjacencyList) induceArcs(sub map[NI]NI, sup []NI) AdjacencyList {
|
||||
s := make(AdjacencyList, len(sup))
|
||||
for b, p := range sup {
|
||||
var a []NI
|
||||
for _, to := range super[p] {
|
||||
if bt, ok := sub[to]; ok {
|
||||
to = bt
|
||||
a = append(a, to)
|
||||
}
|
||||
}
|
||||
s[b] = a
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// InduceList constructs a node-induced subgraph.
|
||||
//
|
||||
// The subgraph is induced on receiver graph g. Argument l must be a list of
|
||||
// NIs in receiver graph g. Receiver g becomes the supergraph of the induced
|
||||
// subgraph.
|
||||
//
|
||||
// Duplicate NIs are allowed in list l. The duplicates are effectively removed
|
||||
// and only a single corresponding node is created in the subgraph. Subgraph
|
||||
// NIs are mapped in the order of list l, execpt for ignoring duplicates.
|
||||
// NIs in l that are not in g will panic.
|
||||
//
|
||||
// Returned is the constructed Subgraph object containing the induced subgraph
|
||||
// and the mappings to the supergraph.
|
||||
func (g *AdjacencyList) InduceList(l []NI) *Subgraph {
|
||||
sub, sup := mapList(l)
|
||||
return &Subgraph{
|
||||
Super: g,
|
||||
SubNI: sub,
|
||||
SuperNI: sup,
|
||||
|
||||
AdjacencyList: g.induceArcs(sub, sup)}
|
||||
}
|
||||
|
||||
// InduceBits constructs a node-induced subgraph.
|
||||
//
|
||||
// The subgraph is induced on receiver graph g. Argument t must be a bitmap
|
||||
// representing NIs in receiver graph g. Receiver g becomes the supergraph
|
||||
// of the induced subgraph. NIs in t that are not in g will panic.
|
||||
//
|
||||
// Returned is the constructed Subgraph object containing the induced subgraph
|
||||
// and the mappings to the supergraph.
|
||||
func (g *AdjacencyList) InduceBits(t bits.Bits) *Subgraph {
|
||||
sub, sup := mapBits(t)
|
||||
return &Subgraph{
|
||||
Super: g,
|
||||
SubNI: sub,
|
||||
SuperNI: sup,
|
||||
|
||||
AdjacencyList: g.induceArcs(sub, sup)}
|
||||
}
|
||||
|
||||
// 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 AnyLoop and AnyParallel.
|
||||
//
|
||||
// There are equivalent labeled and unlabeled versions of this method.
|
||||
func (g AdjacencyList) IsSimple() (ok bool, n NI) {
|
||||
if lp, n := g.AnyLoop(); lp {
|
||||
return false, n
|
||||
}
|
||||
if pa, n, _ := g.AnyParallel(); 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.Bits) {
|
||||
i = bits.New(len(g))
|
||||
i.SetAll()
|
||||
for fr, to := range g {
|
||||
if len(to) > 0 {
|
||||
i.SetBit(fr, 0)
|
||||
for _, to := range to {
|
||||
i.SetBit(int(to), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Order is the number of nodes in receiver g.
|
||||
//
|
||||
// It is simply a wrapper method for the Go builtin len().
|
||||
//
|
||||
// There are equivalent labeled and unlabeled versions of this method.
|
||||
func (g AdjacencyList) Order() int {
|
||||
// Why a wrapper for len()? Mostly for Directed and Undirected.
|
||||
// u.Order() is a little nicer than len(u.LabeledAdjacencyList).
|
||||
return len(g)
|
||||
}
|
||||
|
||||
// ParallelArcs identifies all arcs from node `fr` to node `to`.
|
||||
//
|
||||
// The returned slice contains an element for each arc from node `fr` to node `to`.
|
||||
// The element value is the index within the slice of arcs from node `fr`.
|
||||
//
|
||||
// There are equivalent labeled and unlabeled versions of this method.
|
||||
//
|
||||
// See also the method HasArc, which stops after finding a single arc.
|
||||
func (g AdjacencyList) ParallelArcs(fr, to NI) (p []int) {
|
||||
for x, h := range g[fr] {
|
||||
if h == to {
|
||||
p = append(p, x)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Permute permutes the node labeling of receiver g.
|
||||
//
|
||||
// Argument p must be a permutation of the node numbers of the graph,
|
||||
// 0 through len(g)-1. A permutation returned by rand.Perm(len(g)) for
|
||||
// example is acceptable.
|
||||
//
|
||||
// The graph is permuted in place. The graph keeps the same underlying
|
||||
// memory but values of the graph representation are permuted to produce
|
||||
// an isomorphic graph. The node previously labeled 0 becomes p[0] and so on.
|
||||
// See example (or the code) for clarification.
|
||||
//
|
||||
// There are equivalent labeled and unlabeled versions of this method.
|
||||
func (g AdjacencyList) Permute(p []int) {
|
||||
old := append(AdjacencyList{}, g...) // shallow copy
|
||||
for fr, arcs := range old {
|
||||
for i, to := range arcs {
|
||||
arcs[i] = NI(p[to])
|
||||
}
|
||||
g[p[fr]] = arcs
|
||||
}
|
||||
}
|
||||
|
||||
// ShuffleArcLists shuffles the arc lists of each node of receiver g.
|
||||
//
|
||||
// For example a node with arcs leading to nodes 3 and 7 might have an
|
||||
// arc list of either [3 7] or [7 3] after calling this method. The
|
||||
// connectivity of the graph is not changed. The resulting graph stays
|
||||
// equivalent but a traversal will encounter arcs in a different
|
||||
// order.
|
||||
//
|
||||
// If Rand r is nil, the rand package default shared source is used.
|
||||
//
|
||||
// There are equivalent labeled and unlabeled versions of this method.
|
||||
func (g AdjacencyList) ShuffleArcLists(r *rand.Rand) {
|
||||
ri := rand.Intn
|
||||
if r != nil {
|
||||
ri = r.Intn
|
||||
}
|
||||
// Knuth-Fisher-Yates
|
||||
for _, to := range g {
|
||||
for i := len(to); i > 1; {
|
||||
j := ri(i)
|
||||
i--
|
||||
to[i], to[j] = to[j], to[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user