Skip to content

Instantly share code, notes, and snippets.

@antmd
Forked from amedama41/multiple_source_dijkstra.cpp
Last active August 29, 2015 14:23
Show Gist options
  • Save antmd/99f9c7f6f01bd569f729 to your computer and use it in GitHub Desktop.
Save antmd/99f9c7f6f01bd569f729 to your computer and use it in GitHub Desktop.
#include <fstream>
#include <iterator>
#include <limits>
#include <string>
#include <random>
#include <ctime>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/small_world_generator.hpp>
#include <boost/graph/properties.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
#include <boost/property_map/vector_property_map.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm/for_each.hpp>
namespace Canard {
template <class ParentMap, class Tag>
struct parent_recorder : boost::base_visitor<parent_recorder<ParentMap, Tag>> {
using event_filter = Tag;
explicit parent_recorder(ParentMap const parent_map)
: parent_map_(parent_map)
{}
template <class Edge, class Graph>
void operator()(Edge const e, Graph const& g) const {
auto value = get(parent_map_, source(e, g));
put(parent_map_, target(e, g), value);
}
private:
ParentMap const parent_map_;
};
template <class ParentMap, class Tag>
parent_recorder<ParentMap, Tag>
record_parent(ParentMap parent_map, Tag) {
return parent_recorder<ParentMap, Tag>{parent_map};
}
}
template <class Graph, class RootRange, class ParentMap, class IndexMap>
void multisource_dijkstra(Graph& graph, RootRange const root_range, ParentMap const parent_map, IndexMap const index_map)
{
boost::dijkstra_shortest_paths(
graph
// root vertices
, begin(root_range), end(root_range)
// predecessor map(unused)
, boost::dummy_property_map{}
// distance map
, boost::vector_property_map<std::size_t, IndexMap>{num_vertices(graph), index_map}
// edge weight map(all edge weights is 1)
, boost::make_constant_property<typename boost::graph_traits<Graph>::edge_descriptor>(1)
, index_map
, std::less<std::size_t>{}
, boost::closed_plus<std::size_t>{}
, std::numeric_limits<std::size_t>::max()
, std::size_t{0}
, boost::make_dijkstra_visitor(
Canard::record_parent(parent_map, boost::on_edge_relaxed{})));
}
int main(int argc, char* argv[])
{
using Graph = boost::adjacency_list<
boost::vecS
, boost::vecS
, boost::undirectedS
, boost::property<boost::vertex_root_t, bool>
, boost::property<boost::edge_color_t, std::string>>;
using SWIterator = boost::small_world_iterator<std::mt19937, Graph>;
auto const num_v = std::size_t(100);
auto random_gen = std::mt19937{static_cast<std::mt19937::result_type>(std::time(nullptr))};
auto graph = Graph{SWIterator{random_gen, num_v, 4, 0.15}, SWIterator{}, num_v};
auto const root_map = get(boost::vertex_root, graph);
auto const index_map = get(boost::vertex_index, graph);
using IndexMapType = decltype(index_map);
auto const parent_map
= boost::vector_property_map<std::string, IndexMapType>{num_vertices(graph), index_map};
// set parent(root) and parent color
{
auto const root_vertices = {
boost::vertex( 0, graph), boost::vertex(20, graph), boost::vertex(40, graph),
boost::vertex(60, graph), boost::vertex(80, graph),
};
std::string const colors[] = {"tomato", "green", "cyan", "yellow", "violet"};
auto color = colors;
for (auto const root : root_vertices) {
put(root_map, root, true);
put(parent_map, root, *color++);
}
}
using Vertex = boost::graph_traits<Graph>::vertex_descriptor;
using boost::adaptors::filtered;
multisource_dijkstra(
graph
, vertices(graph) | filtered([=](Vertex const v){return get(root_map, v);})
, parent_map, index_map);
// set edge color
{
using Edge = boost::graph_traits<Graph>::edge_descriptor;
auto const edge_color_map = get(boost::edge_color, graph);
boost::for_each(edges(graph), [&](Edge const e) {
put(edge_color_map, e,
get(parent_map, source(e, graph)) == get(parent_map, target(e, graph))
? get(parent_map, source(e, graph))
: "gray");
});
}
// output to dot file
{
std::ofstream ofs{"graph.dot"};
boost::dynamic_properties dp;
dp
.property("label", index_map)
.property("fillcolor", parent_map)
.property("color", get(boost::edge_color, graph))
// emphasize root
.property("peripheries", boost::make_transform_value_property_map(
[](bool const is_root){ return is_root ? 2 : 1; }
, get(boost::vertex_root, graph)));
boost::write_graphviz_dp(ofs, graph, dp, "label");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment