Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,41 @@
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/bron_kerbosch_all_cliques.hpp>
#include <algorithm>
#include <functional>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

// Undirected graph with no properties
using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>;
using Vertex = boost::graph_traits<Graph>::vertex_descriptor;

// Custom visitor that prints each maximal clique found.
// Custom visitor that records each maximal clique found.
// The clique is passed as a deque of vertex descriptors.
struct PrintCliquesVisitor
struct RecordCliquesVisitor
{
std::vector<std::string> cliques;

template <typename Clique, typename G>
void clique(const Clique& c, const G& /*g*/)
{
// Copy to a vector and sort so output is deterministic
std::vector<Vertex> sorted(c.begin(), c.end());
std::sort(sorted.begin(), sorted.end());

std::cout << "Clique: {";
std::ostringstream out;
out << "Clique: {";
for (std::size_t i = 0; i < sorted.size(); ++i)
{
if (i > 0)
{
std::cout << ", ";
out << ", ";
}
std::cout << sorted[i];
out << sorted[i];
}
std::cout << "}" << std::endl;
out << "}";
cliques.push_back(out.str());
}
};

Expand All @@ -58,8 +65,16 @@ int main()
boost::add_edge(1, 3, g);
boost::add_edge(2, 3, g);

RecordCliquesVisitor visitor;

// std::ref lets the visitor keep its state across the copy the algorithm makes
boost::bron_kerbosch_all_cliques(g, std::ref(visitor));

std::cout << "Finding all maximal cliques:" << std::endl;
boost::bron_kerbosch_all_cliques(g, PrintCliquesVisitor{});
for (const std::string& clique : visitor.cliques)
{
std::cout << clique << std::endl;
}

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,37 @@

#include <boost/graph/directed_graph.hpp>
#include <boost/graph/tiernan_all_cycles.hpp>
#include <functional>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

// Directed graph with no bundled properties
using Graph = boost::directed_graph<>;
using Vertex = boost::graph_traits<Graph>::vertex_descriptor;

// Custom visitor that prints each cycle found.
// Custom visitor that records each cycle found.
// The cycle is passed as a const vector of vertex descriptors.
struct PrintCyclesVisitor
struct RecordCyclesVisitor
{
std::vector<std::string> cycles;

template <typename Path, typename G>
void cycle(const Path& p, const G& g)
{
std::cout << "Cycle: ";
std::ostringstream out;
out << "Cycle: ";
for (std::size_t i = 0; i < p.size(); ++i)
{
if (i > 0)
{
std::cout << " -> ";
out << " -> ";
}
std::cout << boost::get(boost::vertex_index, g, p[i]);
out << boost::get(boost::vertex_index, g, p[i]);
}
std::cout << " -> " << boost::get(boost::vertex_index, g, p.front())
<< std::endl;
out << " -> " << boost::get(boost::vertex_index, g, p.front());
cycles.push_back(out.str());
}
};

Expand Down Expand Up @@ -61,8 +67,16 @@ int main()
g.add_edge(v1, v3);
g.add_edge(v3, v1);

RecordCyclesVisitor visitor;

// std::ref lets the visitor keep its state across the copy the algorithm makes
boost::tiernan_all_cycles(g, std::ref(visitor));

std::cout << "Finding all elementary cycles:" << std::endl;
boost::tiernan_all_cycles(g, PrintCyclesVisitor{});
for (const std::string& cycle : visitor.cycles)
{
std::cout << cycle << std::endl;
}

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ void bron_kerbosch_all_cliques(const Graph& g, Visitor vis);
| `Visitor vis`
| Called with `vis.clique(clique, g)` for each maximal clique found.
`clique` is a `std::deque<vertex_descriptor>`.
The visitor is taken by value, so the algorithm works on a copy. To keep
state, give the visitor ordinary data members and pass it with `std::ref`.
The algorithm then operates on the referenced object and its state survives
the call.

| IN
| `std::size_t min`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ void tiernan_all_cycles(const Graph& g, Visitor vis,
| `Visitor vis`
| Called with `vis.cycle(path, g)` for each cycle found.
`path` is a `const std::vector<vertex_descriptor>&`.
The visitor is taken by value, so the algorithm works on a copy. To keep
state, give the visitor ordinary data members and pass it with `std::ref`.
The algorithm then operates on the referenced object and its state survives
the call.

| IN
| `std::size_t minlen`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ The visitor type used internally. Model of `CoreNumbersVisitorConcept`. Derives

| IN
| `CoreNumVisitor vis`
| Model of `CoreNumbersVisitorConcept`. Typically constructed via `make_core_numbers_visitor`.
| Model of `CoreNumbersVisitorConcept`. Typically constructed via `make_core_numbers_visitor`. The visitor is taken by value, so the algorithm works on a copy. To keep state, give the visitor ordinary data members and pass it with `std::ref`. The algorithm then operates on the referenced object and its state survives the call.
|===

The function returns the largest core number assigned.
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ A type modelling the DominanceFunction concept must return `true` if and only if
[#ResourceConstrainedShortestPathsVisitor]
== ResourceConstrainedShortestPathsVisitor

This concept defines the visitor interface for `r_c_shortest_paths`. A user can define a type with this interface and pass an object of this type to `r_c_shortest_paths` to perform user-defined actions at the event points of the algorithm. Note that the object is passed by value.
This concept defines the visitor interface for `r_c_shortest_paths`. A user can define a type with this interface and pass an object of this type to `r_c_shortest_paths` to perform user-defined actions at the event points of the algorithm. The visitor is taken by value, so the algorithm works on a copy. To keep state, give the visitor ordinary data members and pass it with `std::ref`. The algorithm then operates on the referenced object and its state survives the call.

*Refinement of* +
http://www.boost.org/sgi/stl/DefaultConstructible.html[DefaultConstructible],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,6 @@ The overloads that do not accept a `start` vertex use `*vertices(g).first` as th

== Notes

[#1]#[1]# Since the visitor parameter is passed by value, if your visitor contains state then any changes to the state during the algorithm will be made to a copy of the visitor object, not the visitor object passed in. Therefore you may want the visitor to hold this state by pointer or reference.
[#1]#[1]# The visitor is taken by value, so the algorithm works on a copy. To keep state, give the visitor ordinary data members and pass it with `std::ref`. The algorithm then operates on the referenced object and its state survives the call.

[#2]#[2]# Passing an `adjacency_list` with a vertex _not_ set selected by `vecS` will result in _O(n^2^)_ performance.
11 changes: 8 additions & 3 deletions include/boost/graph/bron_kerbosch_all_cliques.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include <boost/concept/assert.hpp>

#include <boost/graph/detail/visitor_wrapper.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/lookup_edge.hpp>

Expand Down Expand Up @@ -168,9 +169,12 @@ namespace detail
Container& nots, Visitor vis, std::size_t min)
{
BOOST_CONCEPT_ASSERT((GraphConcept< Graph >));
BOOST_CONCEPT_ASSERT((CliqueVisitorConcept< Visitor, Clique, Graph >));
using visitor_type = ::boost::graph::detail::unwrap_visitor_t< Visitor >;
BOOST_CONCEPT_ASSERT((CliqueVisitorConcept< visitor_type, Clique, Graph >));
typedef typename graph_traits< Graph >::vertex_descriptor Vertex;

auto& vis_ref = ::boost::graph::detail::deref_visitor(vis);

// Is there vertex in nots that is connected to all vertices
// in the candidate set? If so, no clique can ever be found.
// This could be broken out into a separate function.
Expand Down Expand Up @@ -248,7 +252,7 @@ namespace detail
// the clique is below our radar, then we won't visit it.
if (clique.size() >= min)
{
vis.clique(clique, g);
vis_ref.clique(clique, g);
}
}
else
Expand Down Expand Up @@ -277,7 +281,8 @@ inline void bron_kerbosch_all_cliques(
typedef typename graph_traits< Graph >::vertex_iterator VertexIterator;
typedef std::vector< Vertex > VertexSet;
typedef std::deque< Vertex > Clique;
BOOST_CONCEPT_ASSERT((CliqueVisitorConcept< Visitor, Clique, Graph >));
using visitor_type = ::boost::graph::detail::unwrap_visitor_t< Visitor >;
BOOST_CONCEPT_ASSERT((CliqueVisitorConcept< visitor_type, Clique, Graph >));

// NOTE: We're using a deque to implement the clique, because it provides
// constant inserts and removals at the end and also a constant size.
Expand Down
17 changes: 11 additions & 6 deletions include/boost/graph/core_numbers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define BOOST_GRAPH_CORE_NUMBERS_HPP

#include <boost/graph/detail/d_ary_heap.hpp>
#include <boost/graph/detail/visitor_wrapper.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/concept/assert.hpp>
Expand Down Expand Up @@ -149,20 +150,22 @@ namespace detail
typename property_traits< CoreMap >::value_type core_numbers_impl(
Graph& g, CoreMap c, EdgeWeightMap wm, MutableQueue& Q, Visitor vis)
{
auto& vis_ref = ::boost::graph::detail::deref_visitor(vis);

typename property_traits< CoreMap >::value_type v_cn = 0;
typedef typename graph_traits< Graph >::vertex_descriptor vertex;
while (!Q.empty())
{
// remove v from the Q, and then decrease the core numbers
// of its successors
vertex v = Q.top();
vis.examine_vertex(v, g);
vis_ref.examine_vertex(v, g);
Q.pop();
v_cn = get(c, v);
typename graph_traits< Graph >::out_edge_iterator oi, oi_end;
for (boost::tie(oi, oi_end) = out_edges(v, g); oi != oi_end; ++oi)
{
vis.examine_edge(*oi, g);
vis_ref.examine_edge(*oi, g);
vertex u = target(*oi, g);
// if c[u] > c[v], then u is still in the graph,
if (get(c, u) > v_cn)
Expand All @@ -173,7 +176,7 @@ namespace detail
Q.update(u);
}
}
vis.finish_vertex(v, g);
vis_ref.finish_vertex(v, g);
}
return (v_cn);
}
Expand Down Expand Up @@ -213,6 +216,8 @@ namespace detail
typename property_traits< CoreMap >::value_type core_numbers_impl(
Graph& g, CoreMap c, PositionMap pos, Visitor vis)
{
auto& vis_ref = ::boost::graph::detail::deref_visitor(vis);

typedef typename graph_traits< Graph >::vertices_size_type size_type;
typedef typename graph_traits< Graph >::degree_size_type degree_type;
typedef typename graph_traits< Graph >::vertex_descriptor vertex;
Expand Down Expand Up @@ -268,12 +273,12 @@ namespace detail
for (size_type i = 0; i < num_vertices(g); ++i)
{
vertex v = vert[i];
vis.examine_vertex(v, g);
vis_ref.examine_vertex(v, g);
v_cn = get(c, v);
typename graph_traits< Graph >::out_edge_iterator oi, oi_end;
for (boost::tie(oi, oi_end) = out_edges(v, g); oi != oi_end; ++oi)
{
vis.examine_edge(*oi, g);
vis_ref.examine_edge(*oi, g);
vertex u = target(*oi, g);
// if c[u] > c[v], then u is still in the graph,
if (get(c, u) > v_cn)
Expand Down Expand Up @@ -303,7 +308,7 @@ namespace detail
put(c, u, get(c, u) - 1);
}
}
vis.finish_vertex(v, g);
vis_ref.finish_vertex(v, g);
}
return v_cn;
}
Expand Down
13 changes: 2 additions & 11 deletions include/boost/graph/hawick_circuits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <algorithm>
#include <boost/assert.hpp>
#include <boost/graph/detail/visitor_wrapper.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/one_bit_color_map.hpp>
#include <boost/graph/properties.hpp>
Expand Down Expand Up @@ -89,16 +90,6 @@ namespace hawick_circuits_detail
return std::find(boost::begin(c), boost::end(c), v) != boost::end(c);
}

template < typename T >
struct unwrap_reference_wrapper {
typedef T type;
};

template < typename T >
struct unwrap_reference_wrapper<std::reference_wrapper<T> > {
typedef T& type;
};

/*!
* @internal
* Algorithm finding all the cycles starting from a given vertex.
Expand Down Expand Up @@ -324,7 +315,7 @@ namespace hawick_circuits_detail

typedef std::vector< Vertex > Stack;
typedef std::vector< std::vector< Vertex > > ClosedMatrix;
typedef typename unwrap_reference_wrapper<Visitor>::type VisitorNoRef;
using VisitorNoRef = ::boost::graph::detail::unwrap_visitor_t< Visitor >;

typedef hawick_circuits_from< Graph, VisitorNoRef, VertexIndexMap, Stack,
ClosedMatrix, GetAdjacentVertices >
Expand Down
10 changes: 7 additions & 3 deletions include/boost/graph/metric_tsp_approx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <vector>

#include <boost/concept_check.hpp>
#include <boost/graph/detail/visitor_wrapper.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_as_tree.hpp>
#include <boost/graph/adjacency_list.hpp>
Expand Down Expand Up @@ -158,8 +159,11 @@ void metric_tsp_approx_from_vertex(const VertexListGraph& g,
using namespace std;

BOOST_CONCEPT_ASSERT((VertexListGraphConcept< VertexListGraph >));
using visitor_type = ::boost::graph::detail::unwrap_visitor_t< TSPVertexVisitor >;
BOOST_CONCEPT_ASSERT(
(TSPVertexVisitorConcept< TSPVertexVisitor, VertexListGraph >));
(TSPVertexVisitorConcept< visitor_type, VertexListGraph >));

auto& vis_ref = ::boost::graph::detail::deref_visitor(vis);

// Types related to the input graph (GVertex is a template parameter).
typedef typename graph_traits< VertexListGraph >::vertex_descriptor GVertex;
Expand Down Expand Up @@ -220,11 +224,11 @@ void metric_tsp_approx_from_vertex(const VertexListGraph& g,
{
// TODO: This is will be O(n^2) if vertex storage of g != vecS.
GVertex v = *next(g_verts.first, get(vertex_index, mst)[*curr]);
vis.visit_vertex(v, g);
vis_ref.visit_vertex(v, g);
}

// Connect back to the start of the tour
vis.visit_vertex(start, g);
vis_ref.visit_vertex(start, g);
}

// Default tsp tour visitor that puts the tour in an OutputIterator
Expand Down
Loading
Loading