16 #ifndef PAAL_STEINER_TREE_GREEDY_HPP
17 #define PAAL_STEINER_TREE_GREEDY_HPP
22 #include <boost/graph/adjacency_list.hpp>
23 #include <boost/graph/dijkstra_shortest_paths.hpp>
24 #include <boost/graph/graph_concepts.hpp>
25 #include <boost/graph/graph_traits.hpp>
26 #include <boost/graph/kruskal_min_spanning_tree.hpp>
27 #include <boost/graph/named_function_params.hpp>
28 #include <boost/graph/properties.hpp>
29 #include <boost/graph/two_bit_color_map.hpp>
31 #include <boost/property_map/property_map.hpp>
33 #include <boost/range/algorithm/copy.hpp>
34 #include <boost/range/algorithm/fill.hpp>
35 #include <boost/range/algorithm/sort.hpp>
36 #include <boost/range/algorithm/unique.hpp>
37 #include <boost/range/as_array.hpp>
38 #include <boost/range/numeric.hpp>
48 BOOST_INSTALL_PROPERTY(edge, base);
59 template <
typename NearestMap,
typename LastEdgeMap,
typename Tag>
61 : boost::base_visitor<nearest_recorder<NearestMap, LastEdgeMap, Tag>> {
63 using event_filter = Tag;
65 : m_nearest_map(nearest_map), m_vpred(vpred) {};
66 template <
typename Edge,
typename Graph>
67 void operator()(Edge
const e, Graph
const &g) {
68 m_nearest_map[target(e, g)] = m_nearest_map[source(e, g)];
69 m_vpred[target(e, g)] = e;
73 NearestMap &m_nearest_map;
77 template <
typename NearestMap,
typename LastEdgeMap,
typename Tag>
79 make_nearest_recorder(NearestMap &nearest_map, LastEdgeMap &vpred, Tag) {
95 template <
typename Graph,
typename OutputIterator,
typename EdgeWeightMap,
98 EdgeWeightMap edge_weight, ColorMap color_map)
99 ->
typename std::pair<
100 typename boost::property_traits<EdgeWeightMap>::value_type,
101 typename boost::property_traits<EdgeWeightMap>::value_type> {
102 using Vertex =
typename boost::graph_traits<Graph>::vertex_descriptor;
103 using Edge =
typename boost::graph_traits<Graph>::edge_descriptor;
104 using Base =
typename boost::property<edge_base_t, Edge>;
105 using Weight =
typename boost::property_traits<EdgeWeightMap>::value_type;
106 using WeightProperty =
107 typename boost::property<boost::edge_weight_t, Weight, Base>;
108 using TerminalGraph =
109 boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
110 boost::no_property, WeightProperty>;
112 typename boost::graph_traits<TerminalGraph>::edge_descriptor;
114 auto N = num_vertices(g);
117 std::vector<Weight> distance(N);
120 std::vector<int> terminals;
122 vertices(g), 0, [=](Vertex v) {
return get(color_map, v); });
123 terminals.reserve(terminals_nr);
124 for (
auto v : boost::as_array(vertices(g))) {
125 if (
get(color_map, v) == Terminals::TERMINAL) {
126 terminals.push_back(v);
129 if (terminals.empty()) {
130 return std::make_pair(Weight{}, Weight{});
132 std::vector<Vertex> nearest_terminal(num_vertices(g));
133 auto index =
get(boost::vertex_index, g);
134 auto nearest_terminal_map = boost::make_iterator_property_map(
135 nearest_terminal.begin(),
get(boost::vertex_index, g));
136 for (
auto terminal : terminals) {
137 nearest_terminal_map[terminal] = terminal;
142 auto distance_map = make_iterator_property_map(distance.begin(), index);
143 std::vector<Edge> vpred(N);
144 auto last_edge = boost::make_iterator_property_map(
145 vpred.begin(),
get(boost::vertex_index, g));
146 boost::dijkstra_shortest_paths(
147 g, terminals.begin(), terminals.end(), boost::dummy_property_map(),
149 boost::closed_plus<Weight>(), std::numeric_limits<Weight>::max(), 0,
150 boost::make_dijkstra_visitor(detail::make_nearest_recorder(
151 nearest_terminal_map, last_edge, boost::on_edge_relaxed{})));
155 TerminalGraph terminal_graph(N);
156 for (
auto w : boost::as_array(edges(g))) {
157 auto const &nearest_to_source = nearest_terminal_map[source(w, g)];
158 auto const &nearest_to_target = nearest_terminal_map[target(w, g)];
159 if (nearest_to_source != nearest_to_target) {
160 add_edge(nearest_to_source, nearest_to_target,
161 WeightProperty(distance[source(w, g)] +
162 distance[target(w, g)] + edge_weight[w],
168 std::vector<Edge> terminal_edge;
169 boost::kruskal_minimum_spanning_tree(terminal_graph,
170 std::back_inserter(terminal_edge));
173 std::vector<Edge> tree_edges;
174 tree_edges.reserve(terminals_nr);
175 for (
auto edge : terminal_edge) {
176 auto base =
get(edge_base, terminal_graph, edge);
177 tree_edges.push_back(base);
178 for (
auto pom : { source(base, g), target(base, g) }) {
179 while (nearest_terminal_map[pom] != pom) {
180 tree_edges.push_back(vpred[pom]);
181 pom = source(vpred[pom], g);
190 boost::sort(tree_edges);
191 auto get_weight=[&](Edge edge){
return edge_weight[edge];};
193 auto unique_edges = boost::unique(tree_edges);
195 boost::copy(unique_edges, out);
196 return std::make_pair(cost_solution, lower_bound / 2.);
211 template <
typename Graph,
typename OutputIterator,
typename P,
typename T,
214 const boost::bgl_named_params<P, T, R> &
params) {
216 g, out, choose_const_pmap(get_param(params, boost::edge_weight), g,
218 choose_const_pmap(get_param(params, boost::vertex_color), g,
219 boost::vertex_color));
230 template <
typename Graph,
typename OutputIterator>
237 #endif // PAAL_STEINER_TREE_GREEDY_HPP
auto steiner_tree_greedy(const Graph &g, OutputIterator out, EdgeWeightMap edge_weight, ColorMap color_map) -> typename std::pair< typename boost::property_traits< EdgeWeightMap >::value_type, typename boost::property_traits< EdgeWeightMap >::value_type >
non-named version of steiner_tree_greedy
This file contains set of simple useful functors or functor adapters.
T accumulate_functor(const Range &rng, T init, Functor f, BinaryOperation bin_op=BinaryOperation{})
combination of boost::accumulate and boost::adaptors::transformed
Terminals
enum indicates if given color represents terminal or NONTERMINAL.
edge_base_t
enum for edge base property