diff --git a/doc/bibliography.html b/doc/bibliography.html
index 7b5bca55..24aac759 100644
--- a/doc/bibliography.html
+++ b/doc/bibliography.html
@@ -438,6 +438,36 @@
Generating random spanning trees more quickly than the cover time.
ACM Symposium on the Theory of Computing, pp. 296-303, 1996.
+
+
++template <class Graph, class BranchingProcessor, class P, class T, class R> +void +rank_spanning_branchings(Graph& g, BranchingProcessor bp, + const bgl_named_params<P, T, R>& params = all defaults); ++ +
+The rank_spanning_branchings() function finds, in order by branching +weight, the spanning branchings in a directed graph with weighted edges. +If the order of a directed graph is N, a spanning branching is an +acyclic subgraph of +that graph with N-1 edges such that no vertex has indegree larger than +one. The weight of the branching is the sum of the weights of the edges +in the branching. +This function uses the Camerini et al. algorithm +[74] +to compute the +branchings in order by branching weight. Once the routine finds a branching, +the routine calls a user-supplied +BranchingProcessor +to process the branching and then +moves on to find the next branching. The +user-supplied +BranchingProcessor +must take as input +a filtered view of the parent graph +that gives the branching. +
++The Camerini et al. algorithm starts with a directed graph that has +a single root vertex (that is, a vertex that has indegree equal to zero +and outdegree not equal to zero). The procedure RANK +finds from the procedure BEST the spanning +branching A with the largest +branching weight, denoted d(A). +The +BranchingProcessor +is invoked on A, and if it returns true, the procedure continues. +The procedure NEXT is then invoked to find +the edge e such that when e is removed from G, +BEST will find the next largest branching. +NEXT also returns δ +such that d(A)-δ is the weight of the next largest branching. +
+ ++RANK keeps a priority queue of tuples with elements (weight, edge, +branching, Y, Z). The element +branching is a set of edges giving a branching. Y is a set of +edges that must be included in a branching. +Z is a set of edges that must be excluded from a branching. After +each evaluation of NEXT, +the appropriate tuple is inserted into Q. +The priority queue ranks tuples by the weight entry. +Once the maximum weight branching is found, RANK finds subsequent +branchings by popping a tuple off the top of Q and running +BEST. Possible descendants are then evaluated with NEXT. +
+ ++RANK(G, BranchingProcessor()) + A := BEST(G, Ø, Ø) + if (!BranchingProcessor(A)) return + (e,δ) := NEXT(G, A, Ø, Ø) + INSERT( Q, (d(A) - δ, e, A, Ø, Ø) ) + while (Q != Ø) + (w, e, A, Y, Z) := POP(Q) + Y' := Y U e + Z' := Z U e + A' := BEST(G, Y, Z') + if (!BranchingProcessor(A')) return + (e',δ) := NEXT(G, A, Y', Z) + INSERT( Q, (d(A) - δ, e', A, Y', Z)) + (e',δ) := NEXT(G, A', Y, Z') + INSERT( Q, (w - δ, e', A', Y, Z')) + end while + return ++ +
+The procedure BEST is the Chu-Liu/Edmond's algorithm +[75, +76] +in the form adopted by +Tarjan [77] and +Camerini et al. +[78]. +The procedure begins by +constructing a subgraph H of G. To construct H, +the procedure loops over each edge in Y and removes from the graph +every other edge with the same target. This ensures that the edges in +Y will be part of the branching found in this invocation of +BEST. The procedure then removes the edges in Z from the +graph; thus, the edges in Z will not be part of the branching. +BEST finds the largest edge into each vertex. When a cycle forms, +the cycle is condensed to a new vertex (such that the graph becomes +HC) and the weight of +edges into the cycle (that is, into the new vertex) +are modified. The modification is such that, if v is a vertex +in the cycle and is the invertex for edge e whose source is outside +the cycle, the weight of e is modified +by adding the weight of the least costly edge within the cycle and +subtracting the weight of the cycle edge into v. +This proceeds until all +vertices have been examined. The condensed graph is then expanded to give the +best branching given the constraints Y and Z. +
+ +
+BEST(G, Y, Z)
+ H := GYZ
+ B := Ø
+ Γ := (V,Ø)
+ while there exists an exposed vertex v ≠ root in H with respect to B
+ let wH be the weighting function of H
+ let Q be a priority queue of in edges of v ordered by wH
+ b := TOP(Q)
+ B := B U b
+ β(v) := b
+ if B contains a cycle C of H then
+ H := HC
+ let u be the vertex of HC corresponding to C
+ add u to Γ
+ for each vertex v' in C
+ make v' a child of u in Γ
+ end for
+ B := B - C
+ end if
+ end while
+ while Γ contains non-isolated vertices
+ find path in Γ with vertices v1, v2, ... vk such that v1 is any non-isolated root of Γ and vk = t(β(v1))
+ for h = 1, k - 1
+ β(vh+1) := β(vh)
+ remove from Γ vertex vh and all edges directed out of vh
+ end for
+ end while
+ A := {β(v):v ≠ root is a vertex of G}
+ return A
+
+
++The procedure NEXT constructs the constrained graph H as +in BEST. It examines each edge in the branching to determine +whether swapping an edge not in the input branching for an edge in the +branching results in a smaller +weight difference. Only those alternative +edges for which the target of the +branching edge (to be replaced) is not an ancestor of the source of the +alternative edge in the branching are allowed as possible +swapped edges (as determined by procedure SEEK). The implementation +of rank_spanning_branchings() does not in fact use a separate +SEEK routine but rather simply an ordered iteration over the +priority queue containing in edges to the vertex under +examination. Cycles are handled as in BEST. NEXT +returns the edge e that when removed from the input graph to +BEST will +give the next best branching and the weight difference between the current +best branching and the next best descendent. +
+ ++NEXT(G, A, Y, Z) + H := GYZ + B := Ø + δ := ∞ + while there exists an exposed vertex v ≠ root in H with respect to B + let wH be the weighting function of H + let Q be a priority queue of in edges of v ordered by wH + b := TOP(Q) (ties among edges must be solved in favor of edges in A) + B := B U b + if b ∈ A - Y + w' := SEEK(b, Q, A, H) + if wH(b) - w' < δ + e := b + δ := wH(b) - w' + end if + end if + if B contains a cycle C of H + H := HC + B := B - C + end if + end while + return (e, δ) ++ +
+SEEK(b, Q, A, H ) + for f in Q (ordered iteration by wH) + if f != b and target of b is not an ancestor of source of f in A + return wH(f) + end if + end for + return -∞ ++ +
+boost/graph/rank_spanning_branchings.hpp + +
+ +
+BranchingProcessor is used in the rank_spanning_branchings() +function to process the current branching. It is a functor that is called with +a filtered view of the parent graph. +The processor must return a boolean. If the return value is +true, rank_spanning_branchings() +continues and seeks the next branching. +If the return value is false, rank_spanning_branchings() stops. +
+ ++The following functor is an example +BranchingProcessor that prints out the edges in a branching. +
+struct print_branching
+{
+
+ print_branching() {}
+
+ template<class BranchingGraph>
+ bool operator()( const BranchingGraph& bg )
+ {
+ std::cout << "Branching:";
+ BGL_FORALL_EDGES_T( e, bg, BranchingGraph )
+ {
+ std::cout << " (" << source( e, bg ) << "," << target( e, bg ) << ")";
+ }
+ std::cout << std::endl;
+ return true;
+ }
+};
+
+It returns true, so rank_spanning_branchings() would always continue
+on to find the next branching.
+
+
++This example +BranchingProcessor could be called on a Graph g as +
+rank_spanning_branchings( g, print_branching() ); ++This would print out all spanning branchings in the graph in descending order +by branching weight. + + +
+ A directed graph. The graph type must be a model of + VertexAndEdgeListGraph. + The graph should + have a single root vertex, that is, a single vertex that has indegree + equal to zero and an edge directed to at least one other vertex. + No other vertex should have indegree equal to zero. + A graph with at least one spanning branching + can always be constructed from a general + directed graph by adding a vertex (the root vertex) and then adding edges + with weight zero directed from the root vertex to every other vertex.+ + + IN: BranchingProcessor bp +
+
+ A functor that models BranchingProcessor to process the edges in a branching.+ +
+
+The weight or ``length'' of + each edge in the graph. + The WeightMap type must be a model + of Readable + Property Map. If no edge weight comparison function is supplied, + its value type must be Less Than + Comparable. The key type of this map needs to be the graph's + edge descriptor type.+ +IN: vertex_index_map(VertexIndexMap i_map) +
+ Default: get(edge_weight, g)
+
+ This maps each vertex to an integer in the range [0, + num_vertices(g)). + The type VertexIndexMap + must be a model of Readable Property + Map. The value type of the map must be an integer type. The + vertex descriptor type of the graph needs to be usable as the key + type of the map.+ +IN: distance_compare(CompareFunction cmp) +
+ Default: get(vertex_index, g) + Note: if you use this default, make sure your graph has + an internal vertex_index property. For example, + adjacenty_list with VertexList=listS does + not have an internal vertex_index property. +
+
+ This function is used to compare edge weights to determine which + edges to include + in the next best branching. It is also used to compare the weights of + branchings. The weight of a branching is the sum of weights of its edges. + The CompareFunction type must be a model of Binary + Predicate and have argument types that match the value type of + the WeightMap property map.+ +
+ + Default: + std::less<W> with W=typename + property_traits<WeightMap>::value_type
+
+The time complexity is O(kE log V), where k is the number +of spanning branchings found. + +
+The files example/rank-branching1.cpp +and +example/rank-branching2.cpp +contain examples of using the Camerini et al. algorithm. + +
+The development of rank_spanning_branchings() was inspired by +the C++ implementation of +Edmond's algorithm by Ali Tofigh and Erik Sjölund. +
+ +| Copyright © 2015 | +Clemson University, Bradley S. Meyer (mbradle@clemson.edu) + |
& params
+ )
+ {
+
+ detail::rank_spanning_branchings_dispatch2(
+ g,
+ bp,
+ choose_param(
+ get_param( params, vertex_index_t()), get( vertex_index, g )
+ ),
+ choose_param(
+ get_param( params, edge_weight_t()), get( edge_weight, g )
+ ),
+ compare
+ );
+
+ }
+
+ template & params
+ )
+ {
+
+ typedef
+ typename
+ property_traits<
+ typename property_map & params
+ )
+ {
+
+ detail::rank_spanning_branchings_dispatch1(
+ g,
+ bp,
+ get_param( params, distance_compare_t() ),
+ params
+ );
+
+ }
+
+ template