"Fossies" - the Fresh Open Source Software Archive

Member "gdrive-2.1.1/vendor/github.com/soniakeys/graph/fromlist.go" (28 May 2021, 11916 Bytes) of package /linux/misc/gdrive-2.1.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Copyright 2014 Sonia Keys
    2 // License MIT: http://opensource.org/licenses/MIT
    3 
    4 package graph
    5 
    6 // FromList represents a rooted tree (or forest) where each node is associated
    7 // with a half arc identifying an arc "from" another node.
    8 //
    9 // Other terms for this data structure include "parent list",
   10 // "predecessor list", "in-tree", "inverse arborescence", and
   11 // "spaghetti stack."
   12 //
   13 // The Paths member represents the tree structure.  Leaves and MaxLen are
   14 // not always needed.  Where Leaves is used it serves as a bitmap where
   15 // Leaves.Bit(n) == 1 for each leaf n of the tree.  Where MaxLen is used it is
   16 // provided primarily as a convenience for functions that might want to
   17 // anticipate the maximum path length that would be encountered traversing
   18 // the tree.
   19 //
   20 // Various graph search methods use a FromList to returns search results.
   21 // For a start node of a search, From will be -1 and Len will be 1. For other
   22 // nodes reached by the search, From represents a half arc in a path back to
   23 // start and Len represents the number of nodes in the path.  For nodes not
   24 // reached by the search, From will be -1 and Len will be 0.
   25 //
   26 // A single FromList can also represent a forest.  In this case paths from
   27 // all leaves do not return to a single root node, but multiple root nodes.
   28 //
   29 // While a FromList generally encodes a tree or forest, it is technically
   30 // possible to encode a cyclic graph.  A number of FromList methods require
   31 // the receiver to be acyclic.  Graph methods documented to return a tree or
   32 // forest will never return a cyclic FromList.  In other cases however,
   33 // where a FromList is not known to by cyclic, the Cyclic method can be
   34 // useful to validate the acyclic property.
   35 type FromList struct {
   36     Paths  []PathEnd // tree representation
   37     Leaves Bits      // leaves of tree
   38     MaxLen int       // length of longest path, max of all PathEnd.Len values
   39 }
   40 
   41 // PathEnd associates a half arc and a path length.
   42 //
   43 // A PathEnd list is an element type of FromList.
   44 type PathEnd struct {
   45     From NI  // a "from" half arc, the node the arc comes from
   46     Len  int // number of nodes in path from start
   47 }
   48 
   49 // NewFromList creates a FromList object of given order.
   50 //
   51 // The Paths member is allocated to length n but there is no other
   52 // initialization.
   53 func NewFromList(n int) FromList {
   54     return FromList{Paths: make([]PathEnd, n)}
   55 }
   56 
   57 // BoundsOk validates the "from" values in the list.
   58 //
   59 // Negative values are allowed as they indicate root nodes.
   60 //
   61 // BoundsOk returns true when all from values are less than len(t).
   62 // Otherwise it returns false and a node with a from value >= len(t).
   63 func (f FromList) BoundsOk() (ok bool, n NI) {
   64     for n, e := range f.Paths {
   65         if int(e.From) >= len(f.Paths) {
   66             return false, NI(n)
   67         }
   68     }
   69     return true, -1
   70 }
   71 
   72 // CommonStart returns the common start node of minimal paths to a and b.
   73 //
   74 // It returns -1 if a and b cannot be traced back to a common node.
   75 //
   76 // The method relies on populated PathEnd.Len members.  Use RecalcLen if
   77 // the Len members are not known to be present and correct.
   78 func (f FromList) CommonStart(a, b NI) NI {
   79     p := f.Paths
   80     if p[a].Len < p[b].Len {
   81         a, b = b, a
   82     }
   83     for bl := p[b].Len; p[a].Len > bl; {
   84         a = p[a].From
   85         if a < 0 {
   86             return -1
   87         }
   88     }
   89     for a != b {
   90         a = p[a].From
   91         if a < 0 {
   92             return -1
   93         }
   94         b = p[b].From
   95     }
   96     return a
   97 }
   98 
   99 // Cyclic determines if f contains a cycle, a non-empty path from a node
  100 // back to itself.
  101 //
  102 // Cyclic returns true if g contains at least one cycle.  It also returns
  103 // an example of a node involved in a cycle.
  104 //
  105 // Cyclic returns (false, -1) in the normal case where f is acyclic.
  106 // Note that the bool is not an "ok" return.  A cyclic FromList is usually
  107 // not okay.
  108 func (f FromList) Cyclic() (cyclic bool, n NI) {
  109     var vis Bits
  110     p := f.Paths
  111     for i := range p {
  112         var path Bits
  113         for n := NI(i); vis.Bit(n) == 0; {
  114             vis.SetBit(n, 1)
  115             path.SetBit(n, 1)
  116             if n = p[n].From; n < 0 {
  117                 break
  118             }
  119             if path.Bit(n) == 1 {
  120                 return true, n
  121             }
  122         }
  123     }
  124     return false, -1
  125 }
  126 
  127 // IsolatedNodeBits returns a bitmap of isolated nodes in receiver graph f.
  128 //
  129 // An isolated node is one with no arcs going to or from it.
  130 func (f FromList) IsolatedNodes() (iso Bits) {
  131     p := f.Paths
  132     iso.SetAll(len(p))
  133     for n, e := range p {
  134         if e.From >= 0 {
  135             iso.SetBit(NI(n), 0)
  136             iso.SetBit(e.From, 0)
  137         }
  138     }
  139     return
  140 }
  141 
  142 // PathTo decodes a FromList, recovering a single path.
  143 //
  144 // The path is returned as a list of nodes where the first element will be
  145 // a root node and the last element will be the specified end node.
  146 //
  147 // Only the Paths member of the receiver is used.  Other members of the
  148 // FromList do not need to be valid, however the MaxLen member can be useful
  149 // for allocating argument p.
  150 //
  151 // Argument p can provide the result slice.  If p has capacity for the result
  152 // it will be used, otherwise a new slice is created for the result.
  153 //
  154 // See also function PathTo.
  155 func (f FromList) PathTo(end NI, p []NI) []NI {
  156     return PathTo(f.Paths, end, p)
  157 }
  158 
  159 // PathTo decodes a single path from a PathEnd list.
  160 //
  161 // A PathEnd list is the main data representation in a FromList.  See FromList.
  162 //
  163 // PathTo returns a list of nodes where the first element will be
  164 // a root node and the last element will be the specified end node.
  165 //
  166 // Argument p can provide the result slice.  If p has capacity for the result
  167 // it will be used, otherwise a new slice is created for the result.
  168 //
  169 // See also method FromList.PathTo.
  170 func PathTo(paths []PathEnd, end NI, p []NI) []NI {
  171     n := paths[end].Len
  172     if n == 0 {
  173         return nil
  174     }
  175     if cap(p) >= n {
  176         p = p[:n]
  177     } else {
  178         p = make([]NI, n)
  179     }
  180     for {
  181         n--
  182         p[n] = end
  183         if n == 0 {
  184             return p
  185         }
  186         end = paths[end].From
  187     }
  188 }
  189 
  190 // Preorder traverses f calling Visitor v in preorder.
  191 //
  192 // Nodes are visited in order such that for any node n with from node fr,
  193 // fr is visited before n.  Where f represents a tree, the visit ordering
  194 // corresponds to a preordering, or depth first traversal of the tree.
  195 // Where f represents a forest, the preorderings of the trees can be
  196 // intermingled.
  197 //
  198 // Leaves must be set correctly first.  Use RecalcLeaves if leaves are not
  199 // known to be set correctly.  FromList f cannot be cyclic.
  200 //
  201 // Traversal continues while v returns true.  It terminates if v returns false.
  202 // Preorder returns true if it completes without v returning false.  Preorder
  203 // returns false if traversal is terminated by v returning false.
  204 func (f FromList) Preorder(v OkNodeVisitor) bool {
  205     p := f.Paths
  206     var done Bits
  207     var df func(NI) bool
  208     df = func(n NI) bool {
  209         done.SetBit(n, 1)
  210         if fr := p[n].From; fr >= 0 && done.Bit(fr) == 0 {
  211             df(fr)
  212         }
  213         return v(n)
  214     }
  215     for n := range f.Paths {
  216         p[n].Len = 0
  217     }
  218     return f.Leaves.Iterate(func(n NI) bool {
  219         return df(n)
  220     })
  221 }
  222 
  223 // RecalcLeaves recomputes the Leaves member of f.
  224 func (f *FromList) RecalcLeaves() {
  225     p := f.Paths
  226     lv := &f.Leaves
  227     lv.SetAll(len(p))
  228     for n := range f.Paths {
  229         if fr := p[n].From; fr >= 0 {
  230             lv.SetBit(fr, 0)
  231         }
  232     }
  233 }
  234 
  235 // RecalcLen recomputes Len for each path end, and recomputes MaxLen.
  236 //
  237 // RecalcLen relies on the Leaves member being valid.  If it is not known
  238 // to be valid, call RecalcLeaves before calling RecalcLen.
  239 func (f *FromList) RecalcLen() {
  240     p := f.Paths
  241     var setLen func(NI) int
  242     setLen = func(n NI) int {
  243         switch {
  244         case p[n].Len > 0:
  245             return p[n].Len
  246         case p[n].From < 0:
  247             p[n].Len = 1
  248             return 1
  249         }
  250         l := 1 + setLen(p[n].From)
  251         p[n].Len = l
  252         return l
  253     }
  254     for n := range f.Paths {
  255         p[n].Len = 0
  256     }
  257     f.MaxLen = 0
  258     f.Leaves.Iterate(func(n NI) bool {
  259         if l := setLen(NI(n)); l > f.MaxLen {
  260             f.MaxLen = l
  261         }
  262         return true
  263     })
  264 }
  265 
  266 // ReRoot reorients the tree containing n to make n the root node.
  267 //
  268 // It keeps the tree connected by "reversing" the path from n to the old root.
  269 //
  270 // After ReRoot, the Leaves and Len members are invalid.
  271 // Call RecalcLeaves or RecalcLen as needed.
  272 func (f *FromList) ReRoot(n NI) {
  273     p := f.Paths
  274     fr := p[n].From
  275     if fr < 0 {
  276         return
  277     }
  278     p[n].From = -1
  279     for {
  280         ff := p[fr].From
  281         p[fr].From = n
  282         if ff < 0 {
  283             return
  284         }
  285         n = fr
  286         fr = ff
  287     }
  288 }
  289 
  290 // Root finds the root of a node in a FromList.
  291 func (f FromList) Root(n NI) NI {
  292     for p := f.Paths; ; {
  293         fr := p[n].From
  294         if fr < 0 {
  295             return n
  296         }
  297         n = fr
  298     }
  299 }
  300 
  301 // Transpose constructs the directed graph corresponding to FromList f
  302 // but with arcs in the opposite direction.  That is, from roots toward leaves.
  303 //
  304 // The method relies only on the From member of f.Paths.  Other members of
  305 // the FromList are not used.
  306 //
  307 // See FromList.TransposeRoots for a version that also accumulates and returns
  308 // information about the roots.
  309 func (f FromList) Transpose() Directed {
  310     g := make(AdjacencyList, len(f.Paths))
  311     for n, p := range f.Paths {
  312         if p.From == -1 {
  313             continue
  314         }
  315         g[p.From] = append(g[p.From], NI(n))
  316     }
  317     return Directed{g}
  318 }
  319 
  320 // TransposeLabeled constructs the directed labeled graph corresponding
  321 // to FromList f but with arcs in the opposite direction.  That is, from
  322 // roots toward leaves.
  323 //
  324 // The argument labels can be nil.  In this case labels are generated matching
  325 // the path indexes.  This corresponds to the "to", or child node.
  326 //
  327 // If labels is non-nil, it must be the same length as f.Paths and is used
  328 // to look up label numbers by the path index.
  329 //
  330 // The method relies only on the From member of f.Paths.  Other members of
  331 // the FromList are not used.
  332 //
  333 // See FromList.TransposeLabeledRoots for a version that also accumulates
  334 // and returns information about the roots.
  335 func (f FromList) TransposeLabeled(labels []LI) LabeledDirected {
  336     g := make(LabeledAdjacencyList, len(f.Paths))
  337     for n, p := range f.Paths {
  338         if p.From == -1 {
  339             continue
  340         }
  341         l := LI(n)
  342         if labels != nil {
  343             l = labels[n]
  344         }
  345         g[p.From] = append(g[p.From], Half{NI(n), l})
  346     }
  347     return LabeledDirected{g}
  348 }
  349 
  350 // TransposeLabeledRoots constructs the labeled directed graph corresponding
  351 // to FromList f but with arcs in the opposite direction.  That is, from
  352 // roots toward leaves.
  353 //
  354 // TransposeLabeledRoots also returns a count of roots of the resulting forest
  355 // and a bitmap of the roots.
  356 //
  357 // The argument labels can be nil.  In this case labels are generated matching
  358 // the path indexes.  This corresponds to the "to", or child node.
  359 //
  360 // If labels is non-nil, it must be the same length as t.Paths and is used
  361 // to look up label numbers by the path index.
  362 //
  363 // The method relies only on the From member of f.Paths.  Other members of
  364 // the FromList are not used.
  365 //
  366 // See FromList.TransposeLabeled for a simpler verstion that returns the
  367 // forest only.
  368 func (f FromList) TransposeLabeledRoots(labels []LI) (forest LabeledDirected, nRoots int, roots Bits) {
  369     p := f.Paths
  370     nRoots = len(p)
  371     roots.SetAll(len(p))
  372     g := make(LabeledAdjacencyList, len(p))
  373     for i, p := range f.Paths {
  374         if p.From == -1 {
  375             continue
  376         }
  377         l := LI(i)
  378         if labels != nil {
  379             l = labels[i]
  380         }
  381         n := NI(i)
  382         g[p.From] = append(g[p.From], Half{n, l})
  383         if roots.Bit(n) == 1 {
  384             roots.SetBit(n, 0)
  385             nRoots--
  386         }
  387     }
  388     return LabeledDirected{g}, nRoots, roots
  389 }
  390 
  391 // TransposeRoots constructs the directed graph corresponding to FromList f
  392 // but with arcs in the opposite direction.  That is, from roots toward leaves.
  393 //
  394 // TransposeRoots also returns a count of roots of the resulting forest and
  395 // a bitmap of the roots.
  396 //
  397 // The method relies only on the From member of f.Paths.  Other members of
  398 // the FromList are not used.
  399 //
  400 // See FromList.Transpose for a simpler verstion that returns the forest only.
  401 func (f FromList) TransposeRoots() (forest Directed, nRoots int, roots Bits) {
  402     p := f.Paths
  403     nRoots = len(p)
  404     roots.SetAll(len(p))
  405     g := make(AdjacencyList, len(p))
  406     for i, e := range p {
  407         if e.From == -1 {
  408             continue
  409         }
  410         n := NI(i)
  411         g[e.From] = append(g[e.From], n)
  412         if roots.Bit(n) == 1 {
  413             roots.SetBit(n, 0)
  414             nRoots--
  415         }
  416     }
  417     return Directed{g}, nRoots, roots
  418 }