mirror of
https://github.com/boostorg/graph.git
synced 2026-07-21 13:23:42 +00:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a649be53bd | |||
| 2862644154 | |||
| f62a1839bd | |||
| 3600dbc226 | |||
| 01020b0265 | |||
| fcfc152f85 | |||
| ea24532da5 | |||
| 944d9fc836 | |||
| 446dc15cf8 | |||
| 44632af1a9 | |||
| 5f4ce096f8 | |||
| 393c31d148 | |||
| 73149e556b | |||
| 3b6d40011b | |||
| 797530d23a | |||
| 2e4b9c461a | |||
| 3b6825958a | |||
| fa6aa57529 | |||
| 430f61f696 | |||
| 51f7f20cb6 | |||
| 71fed2fda8 | |||
| 76aed24add | |||
| bb4fbd6494 | |||
| 64aa4a822a |
+25
-23
@@ -127,34 +127,36 @@ def main(ctx):
|
||||
osx_cxx("XCode-11.7 17", "clang++", packages="", buildtype="boost", xcode_version="11.7", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '17', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-11.7 2a", "clang++", packages="", buildtype="boost", xcode_version="11.7", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '2a', }, globalenv=globalenv),
|
||||
|
||||
osx_cxx("XCode-10.2 03", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-10.2 11", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-10.2 14", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-10.2 17", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '17', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-10.2 2a", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '2a', }, globalenv=globalenv),
|
||||
# We don't support these old versions of Xcode any more, but you are welcome to take up the challenge for doing so if you need them.
|
||||
|
||||
# osx_cxx("XCode-10.2 03", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-10.2 11", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-10.2 14", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-10.2 17", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '17', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-10.2 2a", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '2a', }, globalenv=globalenv),
|
||||
|
||||
osx_cxx("XCode-9.4 03", "clang++", packages="", buildtype="boost", xcode_version="9.4", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-9.4 11", "clang++", packages="", buildtype="boost", xcode_version="9.4", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-9.4 14", "clang++", packages="", buildtype="boost", xcode_version="9.4", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-9.4 1z", "clang++", packages="", buildtype="boost", xcode_version="9.4", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-9.4 03", "clang++", packages="", buildtype="boost", xcode_version="9.4", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-9.4 11", "clang++", packages="", buildtype="boost", xcode_version="9.4", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-9.4 14", "clang++", packages="", buildtype="boost", xcode_version="9.4", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-9.4 1z", "clang++", packages="", buildtype="boost", xcode_version="9.4", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
|
||||
|
||||
osx_cxx("XCode-9.0 03", "clang++", packages="", buildtype="boost", xcode_version="9", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-9.0 11", "clang++", packages="", buildtype="boost", xcode_version="9", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-9.0 14", "clang++", packages="", buildtype="boost", xcode_version="9", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-9.0 1z", "clang++", packages="", buildtype="boost", xcode_version="9", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-9.0 03", "clang++", packages="", buildtype="boost", xcode_version="9", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-9.0 11", "clang++", packages="", buildtype="boost", xcode_version="9", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-9.0 14", "clang++", packages="", buildtype="boost", xcode_version="9", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-9.0 1z", "clang++", packages="", buildtype="boost", xcode_version="9", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
|
||||
|
||||
osx_cxx("XCode-8.3 03", "clang++", packages="", buildtype="boost", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-8.3 11", "clang++", packages="", buildtype="boost", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-8.3 14", "clang++", packages="", buildtype="boost", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-8.3 1z", "clang++", packages="", buildtype="boost", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-8.3 03", "clang++", packages="", buildtype="boost", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-8.3 11", "clang++", packages="", buildtype="boost", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-8.3 14", "clang++", packages="", buildtype="boost", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-8.3 1z", "clang++", packages="", buildtype="boost", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
|
||||
|
||||
osx_cxx("XCode-8.0 03", "clang++", packages="", buildtype="boost", xcode_version="8", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-8.0 11", "clang++", packages="", buildtype="boost", xcode_version="8", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-8.0 14", "clang++", packages="", buildtype="boost", xcode_version="8", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-8.0 1z", "clang++", packages="", buildtype="boost", xcode_version="8", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-8.0 03", "clang++", packages="", buildtype="boost", xcode_version="8", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-8.0 11", "clang++", packages="", buildtype="boost", xcode_version="8", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-8.0 14", "clang++", packages="", buildtype="boost", xcode_version="8", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-8.0 1z", "clang++", packages="", buildtype="boost", xcode_version="8", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
|
||||
|
||||
osx_cxx("XCode-7.3 03", "clang++", packages="", buildtype="boost", xcode_version="7.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-7.3 11", "clang++", packages="", buildtype="boost", xcode_version="7.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-7.3 03", "clang++", packages="", buildtype="boost", xcode_version="7.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
# osx_cxx("XCode-7.3 11", "clang++", packages="", buildtype="boost", xcode_version="7.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
]
|
||||
|
||||
# from https://github.com/boostorg/boost-ci
|
||||
|
||||
@@ -223,3 +223,44 @@ jobs:
|
||||
- name: Test
|
||||
run: ..\..\..\b2 --hash address-model=64 cxxstd=14,17,20 toolset=msvc-14.2
|
||||
working-directory: ../boost-root/libs/graph/test
|
||||
windows_msvc_14_3:
|
||||
runs-on: windows-2022
|
||||
defaults:
|
||||
run:
|
||||
shell: cmd
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
toolset: [ msvc-14.3 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
- uses: mstachniuk/ci-skip@v1
|
||||
with:
|
||||
commit-filter: '[skip ci];[ci skip];[CI SKIP];[SKIP CI];***CI SKIP***;***SKIP CI***;[apple];[Apple];[APPLE];[linux];[Linux];[LINUX]'
|
||||
commit-filter-separator: ';'
|
||||
fail-fast: true
|
||||
- name: Checkout main boost
|
||||
run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root
|
||||
- name: Update tools/boostdep
|
||||
run: git submodule update --init tools/boostdep
|
||||
working-directory: ../boost-root
|
||||
- name: Copy files
|
||||
run: xcopy /s /e /q %GITHUB_WORKSPACE% libs\graph
|
||||
working-directory: ../boost-root
|
||||
- name: Install deps
|
||||
run: python tools/boostdep/depinst/depinst.py graph
|
||||
working-directory: ../boost-root
|
||||
- name: Bootstrap
|
||||
run: bootstrap
|
||||
working-directory: ../boost-root
|
||||
- name: Generate headers
|
||||
run: b2 headers
|
||||
working-directory: ../boost-root
|
||||
- name: Config info
|
||||
run: ..\..\..\b2 print_config_info cxxstd=14,17,20 address-model=64 toolset=msvc-14.3
|
||||
working-directory: ../boost-root/libs/config/test
|
||||
- name: Test
|
||||
run: ..\..\..\b2 --hash address-model=64 cxxstd=14,17,20 toolset=msvc-14.3
|
||||
working-directory: ../boost-root/libs/graph/test
|
||||
|
||||
+2
-1
@@ -87,7 +87,8 @@ This describes the ways in which the vertices and edges of the
|
||||
graph can be visited. The choices are <TT>incidence_graph_tag</TT>,
|
||||
<TT>adjacency_graph_tag</TT>, <TT>bidirectional_graph_tag</TT>,
|
||||
<TT>vertex_list_graph_tag</TT>, <TT>edge_list_graph_tag</TT>, and
|
||||
<TT>adjacency_matrix_tag</TT>.
|
||||
<TT>adjacency_matrix_tag</TT>. You can also create your own
|
||||
tag which should inherit from one or more of the above.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@@ -200,9 +200,9 @@ The ways in which the vertices in the graph can be traversed.
|
||||
The traversal category tags are:
|
||||
<tt>incidence_graph_tag, adjacency_graph_tag,
|
||||
bidirectional_graph_tag, vertex_list_graph_tag,
|
||||
edge_list_graph_tag, vertex_and_edge_list_graph_tag,
|
||||
edge_list_graph_tag,
|
||||
adjacency_matrix_tag</tt>. You can also create your own
|
||||
tag which should inherit from one of the above.
|
||||
tag which should inherit from one or more of the above.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@@ -328,7 +328,6 @@ inline void astar_search_no_init_tree(const VertexListGraph& g,
|
||||
BOOST_THROW_EXCEPTION(negative_edge());
|
||||
bool decreased
|
||||
= relax(e, g, weight, predecessor, distance, combine, compare);
|
||||
combine(get(distance, v), e_weight);
|
||||
if (decreased)
|
||||
{
|
||||
vis.edge_relaxed(e, g);
|
||||
|
||||
@@ -1029,8 +1029,7 @@ boykov_kolmogorov_max_flow(Graph& g, CapacityEdgeMap cap,
|
||||
* named-parameter version, some given
|
||||
*/
|
||||
template < class Graph, class P, class T, class R >
|
||||
typename property_traits<
|
||||
typename property_map< Graph, edge_capacity_t >::const_type >::value_type
|
||||
typename detail::edge_capacity_value< Graph, P, T, R >::type
|
||||
boykov_kolmogorov_max_flow(Graph& g,
|
||||
typename graph_traits< Graph >::vertex_descriptor src,
|
||||
typename graph_traits< Graph >::vertex_descriptor sink,
|
||||
|
||||
@@ -204,10 +204,10 @@ private:
|
||||
// Get the parent of a given node in the heap
|
||||
static size_type parent(size_type index) { return (index - 1) / Arity; }
|
||||
|
||||
// Get the child_idx'th child of a given node; 0 <= child_idx < Arity
|
||||
static size_type child(size_type index, std::size_t child_idx)
|
||||
// Get the first child of a given node
|
||||
static size_type first_child(size_type index)
|
||||
{
|
||||
return index * Arity + child_idx + 1;
|
||||
return index * Arity + 1;
|
||||
}
|
||||
|
||||
// Swap two elements in the heap by index, updating index_in_heap
|
||||
@@ -304,7 +304,7 @@ private:
|
||||
Value* data_ptr = &data[0];
|
||||
for (;;)
|
||||
{
|
||||
size_type first_child_index = child(index, 0);
|
||||
size_type first_child_index = first_child(index);
|
||||
if (first_child_index >= heap_size)
|
||||
break; /* No children */
|
||||
Value* child_base_ptr = data_ptr + first_child_index;
|
||||
|
||||
@@ -29,94 +29,130 @@ namespace boost
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template < typename ParityMap, typename WeightMap, typename IndexMap >
|
||||
class mas_min_cut_visitor : public boost::default_mas_visitor
|
||||
/**
|
||||
* \brief Performs a phase of the Stoer-Wagner min-cut algorithm
|
||||
*
|
||||
* Performs a phase of the Stoer-Wagner min-cut algorithm.
|
||||
*
|
||||
* As described by Stoer & Wagner (1997), a phase is simply a maximum
|
||||
* adjacency search (also called a maximum cardinality search), which
|
||||
* results in the selection of two vertices \em s and \em t, and, as a side
|
||||
* product, a minimum <em>s</em>-<em>t</em> cut of the input graph. Here,
|
||||
* the input graph is basically \p g, but some vertices are virtually
|
||||
* assigned to others as a way of viewing \p g as a graph with some sets of
|
||||
* vertices merged together.
|
||||
*
|
||||
* This implementation is a translation of pseudocode by Professor Uri
|
||||
* Zwick, School of Computer Science, Tel Aviv University.
|
||||
*
|
||||
* \pre \p g is a connected, undirected graph
|
||||
* \param[in] g the input graph
|
||||
* \param[in] assignments a read/write property map from each vertex to the
|
||||
* vertex that it is assigned to
|
||||
* \param[in] assignedVertices a list of vertices that are assigned to
|
||||
* others
|
||||
* \param[in] weights a readable property map from each edge to its
|
||||
* weight (a non-negative value)
|
||||
* \param[out] pq a keyed, updatable max-priority queue
|
||||
* \returns a tuple (\em s, \em t, \em w) of the "<em>s</em>" and
|
||||
* "<em>t</em>" of the minimum <em>s</em>-<em>t</em> cut and the
|
||||
* cut weight \em w of the minimum <em>s</em>-<em>t</em> cut.
|
||||
* \see http://www.cs.tau.ac.il/~zwick/grad-algo-08/gmc.pdf
|
||||
*
|
||||
* \author Daniel Trebbien
|
||||
* \date 2010-09-11
|
||||
*/
|
||||
template < class UndirectedGraph, class VertexAssignmentMap,
|
||||
class WeightMap, class KeyedUpdatablePriorityQueue >
|
||||
boost::tuple<
|
||||
typename boost::graph_traits< UndirectedGraph >::vertex_descriptor,
|
||||
typename boost::graph_traits< UndirectedGraph >::vertex_descriptor,
|
||||
typename boost::property_traits< WeightMap >::value_type >
|
||||
stoer_wagner_phase(const UndirectedGraph& g,
|
||||
VertexAssignmentMap assignments,
|
||||
const std::set< typename boost::graph_traits<
|
||||
UndirectedGraph >::vertex_descriptor >& assignedVertices,
|
||||
WeightMap weights, KeyedUpdatablePriorityQueue& pq)
|
||||
{
|
||||
typedef one_bit_color_map< IndexMap > InternalParityMap;
|
||||
typedef
|
||||
typename boost::graph_traits< UndirectedGraph >::vertex_descriptor
|
||||
vertex_descriptor;
|
||||
typedef typename boost::property_traits< WeightMap >::value_type
|
||||
weight_type;
|
||||
|
||||
public:
|
||||
template < typename Graph >
|
||||
mas_min_cut_visitor(const Graph& g, ParityMap parity,
|
||||
weight_type& cutweight, const WeightMap& weight_map,
|
||||
IndexMap index_map)
|
||||
: m_bestParity(parity)
|
||||
, m_parity(make_one_bit_color_map(num_vertices(g), index_map))
|
||||
, m_bestWeight(cutweight)
|
||||
, m_cutweight(0)
|
||||
, m_visited(0)
|
||||
, m_weightMap(weight_map)
|
||||
BOOST_ASSERT(pq.empty());
|
||||
typename KeyedUpdatablePriorityQueue::key_map keys = pq.keys();
|
||||
|
||||
BGL_FORALL_VERTICES_T(v, g, UndirectedGraph)
|
||||
{
|
||||
// set here since the init list sets the reference
|
||||
m_bestWeight = (std::numeric_limits< weight_type >::max)();
|
||||
}
|
||||
if (v == get(assignments, v))
|
||||
{ // foreach u \in V do
|
||||
put(keys, v, weight_type(0));
|
||||
|
||||
template < typename Vertex, typename Graph >
|
||||
void initialize_vertex(Vertex u, const Graph& g)
|
||||
{
|
||||
typedef typename boost::property_traits< ParityMap >::value_type
|
||||
parity_type;
|
||||
typedef
|
||||
typename boost::property_traits< InternalParityMap >::value_type
|
||||
internal_parity_type;
|
||||
|
||||
put(m_parity, u, internal_parity_type(0));
|
||||
put(m_bestParity, u, parity_type(0));
|
||||
}
|
||||
|
||||
template < typename Edge, typename Graph >
|
||||
void examine_edge(Edge e, const Graph& g)
|
||||
{
|
||||
weight_type w = get(m_weightMap, e);
|
||||
|
||||
// if the target of e is already marked then decrease cutweight
|
||||
// otherwise, increase it
|
||||
if (get(m_parity, boost::target(e, g)))
|
||||
{
|
||||
m_cutweight -= w;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cutweight += w;
|
||||
pq.push(v);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename Vertex, typename Graph >
|
||||
void finish_vertex(Vertex u, const Graph& g)
|
||||
{
|
||||
typedef
|
||||
typename boost::property_traits< InternalParityMap >::value_type
|
||||
internal_parity_type;
|
||||
BOOST_ASSERT(pq.size() >= 2);
|
||||
|
||||
++m_visited;
|
||||
put(m_parity, u, internal_parity_type(1));
|
||||
vertex_descriptor s
|
||||
= boost::graph_traits< UndirectedGraph >::null_vertex();
|
||||
vertex_descriptor t
|
||||
= boost::graph_traits< UndirectedGraph >::null_vertex();
|
||||
weight_type w;
|
||||
while (!pq.empty())
|
||||
{ // while PQ \neq {} do
|
||||
const vertex_descriptor u = pq.top(); // u = extractmax(PQ)
|
||||
w = get(keys, u);
|
||||
pq.pop();
|
||||
|
||||
if (m_cutweight < m_bestWeight && m_visited < num_vertices(g))
|
||||
s = t;
|
||||
t = u;
|
||||
|
||||
BGL_FORALL_OUTEDGES_T(u, e, g, UndirectedGraph)
|
||||
{ // foreach (u, v) \in E do
|
||||
const vertex_descriptor v = get(assignments, target(e, g));
|
||||
|
||||
if (pq.contains(v))
|
||||
{ // if v \in PQ then
|
||||
put(keys, v,
|
||||
get(keys, v)
|
||||
+ get(weights,
|
||||
e)); // increasekey(PQ, v, wA(v) + w(u, v))
|
||||
pq.update(v);
|
||||
}
|
||||
}
|
||||
|
||||
typename std::set< vertex_descriptor >::const_iterator
|
||||
assignedVertexIt,
|
||||
assignedVertexEnd = assignedVertices.end();
|
||||
for (assignedVertexIt = assignedVertices.begin();
|
||||
assignedVertexIt != assignedVertexEnd; ++assignedVertexIt)
|
||||
{
|
||||
m_bestWeight = m_cutweight;
|
||||
BGL_FORALL_VERTICES_T(i, g, Graph)
|
||||
const vertex_descriptor uPrime = *assignedVertexIt;
|
||||
|
||||
if (get(assignments, uPrime) == u)
|
||||
{
|
||||
put(m_bestParity, i, get(m_parity, i));
|
||||
BGL_FORALL_OUTEDGES_T(uPrime, e, g, UndirectedGraph)
|
||||
{ // foreach (u, v) \in E do
|
||||
const vertex_descriptor v
|
||||
= get(assignments, target(e, g));
|
||||
|
||||
if (pq.contains(v))
|
||||
{ // if v \in PQ then
|
||||
put(keys, v,
|
||||
get(keys, v)
|
||||
+ get(weights, e)); // increasekey(PQ, v,
|
||||
// wA(v) + w(u, v))
|
||||
pq.update(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
m_bestWeight = (std::numeric_limits< weight_type >::max)();
|
||||
m_visited = 0;
|
||||
m_cutweight = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
ParityMap m_bestParity;
|
||||
InternalParityMap m_parity;
|
||||
weight_type& m_bestWeight;
|
||||
weight_type m_cutweight;
|
||||
unsigned m_visited;
|
||||
const WeightMap& m_weightMap;
|
||||
};
|
||||
return boost::make_tuple(s, t, w);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Computes a min-cut of the input graph
|
||||
@@ -156,44 +192,71 @@ namespace detail
|
||||
vertex_descriptor;
|
||||
typedef typename boost::property_traits< WeightMap >::value_type
|
||||
weight_type;
|
||||
typedef
|
||||
typename boost::graph_traits< UndirectedGraph >::vertices_size_type
|
||||
vertices_size_type;
|
||||
typedef typename boost::property_traits< ParityMap >::value_type
|
||||
parity_type;
|
||||
|
||||
typename graph_traits< UndirectedGraph >::vertex_iterator u_iter, u_end;
|
||||
vertices_size_type n = num_vertices(g);
|
||||
|
||||
weight_type bestW = (std::numeric_limits< weight_type >::max)();
|
||||
weight_type bestThisTime = (std::numeric_limits< weight_type >::max)();
|
||||
vertex_descriptor bestStart
|
||||
= boost::graph_traits< UndirectedGraph >::null_vertex();
|
||||
std::set< vertex_descriptor > assignedVertices;
|
||||
|
||||
detail::mas_min_cut_visitor< ParityMap, WeightMap, IndexMap > vis(
|
||||
g, parities, bestThisTime, weights, index_map);
|
||||
// initialize `assignments` (all vertices are initially assigned to
|
||||
// themselves)
|
||||
BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { put(assignments, v, v); }
|
||||
|
||||
// for each node in the graph,
|
||||
for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
|
||||
vertex_descriptor s, t;
|
||||
weight_type bestW;
|
||||
|
||||
boost::tie(s, t, bestW) = boost::detail::stoer_wagner_phase(
|
||||
g, assignments, assignedVertices, weights, pq);
|
||||
BOOST_ASSERT(s != t);
|
||||
BGL_FORALL_VERTICES_T(v, g, UndirectedGraph)
|
||||
{
|
||||
// run the MAS and find the min cut
|
||||
vis.clear();
|
||||
boost::maximum_adjacency_search(g,
|
||||
boost::weight_map(weights)
|
||||
.visitor(vis)
|
||||
.root_vertex(*u_iter)
|
||||
.vertex_assignment_map(assignments)
|
||||
.max_priority_queue(pq));
|
||||
if (bestThisTime < bestW)
|
||||
put(parities, v, parity_type(v == t ? 1 : 0));
|
||||
}
|
||||
put(assignments, t, s);
|
||||
assignedVertices.insert(t);
|
||||
--n;
|
||||
|
||||
for (; n >= 2; --n)
|
||||
{
|
||||
weight_type w;
|
||||
boost::tie(s, t, w) = boost::detail::stoer_wagner_phase(
|
||||
g, assignments, assignedVertices, weights, pq);
|
||||
BOOST_ASSERT(s != t);
|
||||
|
||||
if (w < bestW)
|
||||
{
|
||||
bestW = bestThisTime;
|
||||
bestStart = *u_iter;
|
||||
BGL_FORALL_VERTICES_T(v, g, UndirectedGraph)
|
||||
{
|
||||
put(parities, v,
|
||||
parity_type(get(assignments, v) == t ? 1 : 0));
|
||||
|
||||
if (get(assignments, v)
|
||||
== t) // all vertices that were assigned to t are now
|
||||
// assigned to s
|
||||
put(assignments, v, s);
|
||||
}
|
||||
|
||||
bestW = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
BGL_FORALL_VERTICES_T(v, g, UndirectedGraph)
|
||||
{
|
||||
if (get(assignments, v)
|
||||
== t) // all vertices that were assigned to t are now
|
||||
// assigned to s
|
||||
put(assignments, v, s);
|
||||
}
|
||||
}
|
||||
put(assignments, t, s);
|
||||
assignedVertices.insert(t);
|
||||
}
|
||||
|
||||
// Run one more time, starting from the best start location, to
|
||||
// ensure the visitor has the best values.
|
||||
vis.clear();
|
||||
boost::maximum_adjacency_search(g,
|
||||
boost::vertex_assignment_map(assignments)
|
||||
.weight_map(weights)
|
||||
.visitor(vis)
|
||||
.root_vertex(bestStart)
|
||||
.max_priority_queue(pq));
|
||||
BOOST_ASSERT(pq.empty());
|
||||
|
||||
return bestW;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ void transitive_closure(const Graph& g, GraphTC& tc,
|
||||
iterator_property_map< cg_vertex*, VertexIndexMap, cg_vertex, cg_vertex& >
|
||||
component_number(&component_number_vec[0], index_map);
|
||||
|
||||
int num_scc
|
||||
const cg_vertex num_scc
|
||||
= strong_components(g, component_number, vertex_index_map(index_map));
|
||||
|
||||
std::vector< std::vector< vertex > > components;
|
||||
@@ -107,12 +107,11 @@ void transitive_closure(const Graph& g, GraphTC& tc,
|
||||
}
|
||||
}
|
||||
std::sort(adj.begin(), adj.end());
|
||||
typename std::vector< cg_vertex >::iterator di
|
||||
const typename std::vector< cg_vertex >::iterator di
|
||||
= std::unique(adj.begin(), adj.end());
|
||||
if (di != adj.end())
|
||||
adj.erase(di, adj.end());
|
||||
|
||||
for (typename std::vector< cg_vertex >::const_iterator i = adj.begin();
|
||||
i != adj.end(); ++i)
|
||||
i != di; ++i)
|
||||
{
|
||||
add_edge(s, *i, CG);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ fill_random_max_flow_graph(Graph& g, CapacityMap cap, ReverseEdgeMap rev,
|
||||
// cannot use this, as we have no idea how properties are stored, right?
|
||||
typename graph_traits< Graph >::edge_iterator ei, e_end;
|
||||
for (boost::tie(ei, e_end) = edges(g); ei != e_end; ++ei)
|
||||
cap[*ei] = int_gen();
|
||||
put(cap, *ei, int_gen());
|
||||
|
||||
// get source and sink node
|
||||
vertex_descriptor s = random_vertex(g, gen);
|
||||
@@ -96,9 +96,9 @@ fill_random_max_flow_graph(Graph& g, CapacityMap cap, ReverseEdgeMap rev,
|
||||
boost::tie(new_edge, inserted)
|
||||
= add_edge(source_vertex, target_vertex, g);
|
||||
assert(inserted);
|
||||
rev[old_edge] = new_edge;
|
||||
rev[new_edge] = old_edge;
|
||||
cap[new_edge] = 0;
|
||||
put(rev, old_edge, new_edge);
|
||||
put(rev, new_edge, old_edge);
|
||||
put(cap, new_edge, 0);
|
||||
}
|
||||
return std::make_pair(s, t);
|
||||
}
|
||||
@@ -188,10 +188,24 @@ long test_bundled_properties(int n_verts, int n_edges, std::size_t seed)
|
||||
boost::tie(src, sink)
|
||||
= fill_random_max_flow_graph(g, get(&tEdge::edge_capacity, g),
|
||||
get(&tEdge::edge_reverse, g), n_verts, n_edges, seed);
|
||||
return boykov_kolmogorov_max_flow(g, get(&tEdge::edge_capacity, g),
|
||||
get(&tEdge::edge_residual_capacity, g), get(&tEdge::edge_reverse, g),
|
||||
get(&tVertex::vertex_predecessor, g), get(&tVertex::vertex_color, g),
|
||||
get(&tVertex::vertex_distance, g), get(vertex_index, g), src, sink);
|
||||
|
||||
long flow_unnamed_overload = boykov_kolmogorov_max_flow(g,
|
||||
get(&tEdge::edge_capacity, g), get(&tEdge::edge_residual_capacity, g),
|
||||
get(&tEdge::edge_reverse, g), get(&tVertex::vertex_predecessor, g),
|
||||
get(&tVertex::vertex_color, g), get(&tVertex::vertex_distance, g),
|
||||
get(vertex_index, g), src, sink);
|
||||
|
||||
long flow_named_overload = boykov_kolmogorov_max_flow(g, src, sink,
|
||||
capacity_map(get(&tEdge::edge_capacity, g))
|
||||
.residual_capacity_map(get(&tEdge::edge_residual_capacity, g))
|
||||
.reverse_edge_map(get(&tEdge::edge_reverse, g))
|
||||
.predecessor_map(get(&tVertex::vertex_predecessor, g))
|
||||
.color_map(get(&tVertex::vertex_color, g))
|
||||
.distance_map(get(&tVertex::vertex_distance, g))
|
||||
.vertex_index_map(get(vertex_index, g)));
|
||||
|
||||
BOOST_TEST(flow_unnamed_overload == flow_named_overload);
|
||||
return flow_named_overload;
|
||||
}
|
||||
|
||||
long test_overloads(int n_verts, int n_edges, std::size_t seed)
|
||||
|
||||
@@ -184,6 +184,32 @@ void test4()
|
||||
BOOST_TEST_EQ(parity2, get(parities, 7));
|
||||
}
|
||||
|
||||
// Non regression test for github.com/boostorg/graph/issues/286
|
||||
void test5()
|
||||
{
|
||||
edge_t edges[] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 },
|
||||
{ 2, 3 }, { 4, 5 }, { 4, 6 }, { 4, 7 }, { 5, 6 }, { 5, 7 }, { 6, 7 },
|
||||
{ 0, 4 } };
|
||||
weight_type ws[] = { 3, 3, 3, 2, 2, 2, 3, 3, 3, 2, 2, 2, 6 };
|
||||
undirected_graph g(edges, edges + 13, ws, 8, 13);
|
||||
|
||||
weight_map_type weights = get(boost::edge_weight, g);
|
||||
std::map< int, bool > parity;
|
||||
boost::associative_property_map< std::map< int, bool > > parities(parity);
|
||||
int w
|
||||
= boost::stoer_wagner_min_cut(g, weights, boost::parity_map(parities));
|
||||
BOOST_TEST_EQ(w, 6);
|
||||
const bool parity0 = get(parities, 0);
|
||||
BOOST_TEST_EQ(parity0, get(parities, 1));
|
||||
BOOST_TEST_EQ(parity0, get(parities, 2));
|
||||
BOOST_TEST_EQ(parity0, get(parities, 3));
|
||||
const bool parity4 = get(parities, 4);
|
||||
BOOST_TEST_NE(parity0, parity4);
|
||||
BOOST_TEST_EQ(parity4, get(parities, 5));
|
||||
BOOST_TEST_EQ(parity4, get(parities, 6));
|
||||
BOOST_TEST_EQ(parity4, get(parities, 7));
|
||||
}
|
||||
|
||||
// The input for the `test_prgen` family of tests comes from a program, named
|
||||
// `prgen`, that comes with a package of min-cut solvers by Chandra Chekuri,
|
||||
// Andrew Goldberg, David Karger, Matthew Levine, and Cliff Stein. `prgen` was
|
||||
@@ -285,13 +311,15 @@ void test_prgen_50_70_2()
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (BOOST_TEST(argc == 2)) {
|
||||
if (BOOST_TEST(argc == 2))
|
||||
{
|
||||
test_dir = argv[1];
|
||||
test0();
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test_prgen_20_70_2();
|
||||
test_prgen_50_70_2();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user