16 #ifndef PAAL_STEINER_NETWORK_HPP
17 #define PAAL_STEINER_NETWORK_HPP
26 #include <boost/graph/kruskal_min_spanning_tree.hpp>
27 #include <boost/graph/named_function_params.hpp>
28 #include <boost/range/as_array.hpp>
34 struct steiner_network_compare_traits {
35 static const double EPSILON;
38 const double steiner_network_compare_traits::EPSILON = 1e-10;
52 template <
typename Graph,
typename Restrictions,
typename CostMap,
53 typename VertexIndex,
typename ResultNetworkOutputIterator,
56 using edge =
typename boost::graph_traits<Graph>::edge_descriptor;
57 using vertex =
typename boost::graph_traits<Graph>::vertex_descriptor;
58 using vertex_idx = decltype(
get(std::declval<VertexIndex>(),
59 std::declval<VertexIndex>()));
61 using edge_map = std::unordered_map<lp::col_id, edge>;
62 using edge_list = std::vector<edge>;
64 using error_message = boost::optional<std::string>;
68 const Restrictions &m_restrictions;
71 ResultNetworkOutputIterator m_result_network;
72 RestrictionsVector m_restrictions_vec;
76 edge_list m_result_list;
85 CostMap cost_map, VertexIndex vertex_index,
86 ResultNetworkOutputIterator result_network,
87 Oracle oracle = Oracle{}) :
88 m_g(g), m_restrictions(restrictions),
89 m_cost_map(cost_map), m_index(vertex_index), m_result_network(result_network),
91 m_oracle(oracle), m_compare(steiner_network_compare_traits::EPSILON) {}
99 return error_message{
"A Steiner network satisfying the "
100 "restrictions does not exist." };
102 return error_message{};
114 template <
typename LP>
116 using candidate = steiner_network_violation_checker::Candidate;
118 [&](candidate c){
return m_violation_checker.
check_violation(c, *
this);},
135 const VertexIndex &
get_index()
const {
return m_index; }
142 -> decltype(std::declval<Restrictions>()(0, 0))
144 return std::max(m_restrictions(u, v), m_restrictions(v, u));
152 return m_restrictions_vec;
159 auto get_cost(edge e) -> decltype(
get(std::declval<CostMap>(), e))
161 return get(m_cost_map, e);
168 m_edge_map.insert(
typename edge_map::value_type(col, e));
175 auto ret = m_edge_map.erase(col_id);
183 auto e = col_to_edge(col_id);
184 *m_result_network = e;
186 m_result_list.push_back(e);
202 auto i = m_edge_map.find(col);
203 assert(i != m_edge_map.end());
227 template <
typename Oracle = lp::random_violated_separation_oracle,
228 typename Graph,
typename Restrictions,
typename CostMap,
229 typename VertexIndex,
typename ResultNetworkOutputIterator>
230 steiner_network<Graph, Restrictions, CostMap, VertexIndex, ResultNetworkOutputIterator, Oracle>
232 CostMap cost_map, VertexIndex vertex_index,
233 ResultNetworkOutputIterator result_network,
234 Oracle oracle = Oracle{}) {
236 ResultNetworkOutputIterator, Oracle>(
237 g, restrictions, cost_map, vertex_index, result_network, oracle);
262 template <
typename Oracle = lp::random_violated_separation_oracle,
263 typename Graph,
typename Restrictions,
typename ResultNetworkOutputIterator,
264 typename P,
typename T,
typename R>
267 const boost::bgl_named_params<P, T, R>&
params,
268 ResultNetworkOutputIterator result_network,
269 Oracle oracle = Oracle()) ->
271 decltype(choose_const_pmap(get_param(params, boost::edge_weight), g, boost::edge_weight)),
272 decltype(choose_const_pmap(get_param(params, boost::vertex_index), g, boost::vertex_index)),
273 ResultNetworkOutputIterator, Oracle> {
275 choose_const_pmap(get_param(params, boost::edge_weight), g, boost::edge_weight),
276 choose_const_pmap(get_param(params, boost::vertex_index), g, boost::vertex_index),
277 result_network, oracle);
298 typename Graph,
typename Restrictions,
typename ResultNetworkOutputIterator>
301 ResultNetworkOutputIterator result_network, Oracle oracle = Oracle()) ->
302 decltype(
make_steiner_network(g, restrictions, boost::no_named_parameters(), result_network, oracle)) {
303 return make_steiner_network(g, restrictions, boost::no_named_parameters(), result_network, oracle);
313 template <
typename Problem,
typename LP>
316 lp.set_optimization_type(lp::MINIMIZE);
317 add_variables(problem, lp);
322 template <
typename Problem,
typename LP>
323 void add_variables(Problem &problem,
LP &lp) {
324 for (
auto e : boost::as_array(edges(problem.get_graph()))) {
326 problem.bind_edge_to_col(e, col);
339 steiner_network_compare_traits::EPSILON)
340 : m_round_half(epsilon), m_round_zero(epsilon) {}
352 template <
typename Problem,
typename LP>
354 auto ret = m_round_zero(problem, lp, col_id);
357 problem.remove_column(col_id);
360 ret = m_round_half(problem, lp, col_id);
362 problem.add_column_to_solution(col_id);
363 problem.remove_column(col_id);
382 steiner_network_compare_traits::EPSILON)
383 : m_compare(epsilon) {}
389 template <
typename Problem,
typename GetSolution>
390 void operator()(Problem &problem,
const GetSolution &solution) {
391 for (
auto edge_and_col : problem.get_edge_map()) {
392 if (m_compare.
e(solution(edge_and_col.first), 1)) {
393 problem.add_column_to_solution(edge_and_col.first);
402 template <
typename Init = steiner_network_init,
403 typename RoundCondition = steiner_network_round_condition,
405 typename SetSolution = steiner_network_set_solution,
406 typename SolveLPToExtremePoint = row_generation_solve_lp<>,
407 typename ResolveLPToExtremePoint = row_generation_solve_lp<>>
408 using steiner_network_ir_components =
409 IRcomponents<Init, RoundCondition, RelaxContition, SetSolution,
410 SolveLPToExtremePoint, ResolveLPToExtremePoint>;
437 typename Restrictions,
typename CostMap,
typename VertexIndex,
438 typename ResultNetworkOutputIterator,
439 typename IRcomponents = steiner_network_ir_components<>,
440 typename Visitor = trivial_visitor>
443 const Restrictions & restrictions,
445 VertexIndex vertex_index,
446 ResultNetworkOutputIterator result,
448 Oracle oracle = Oracle(),
449 Visitor visitor = Visitor()) {
479 typename Restrictions,
typename ResultNetworkOutputIterator,
480 typename IRcomponents = steiner_network_ir_components<>,
481 typename Visitor = trivial_visitor,
typename P,
typename T,
484 const Graph &g,
const Restrictions &restrictions,
485 const boost::bgl_named_params<P, T, R> ¶ms,
486 ResultNetworkOutputIterator result,
488 Visitor visitor = Visitor()) {
491 choose_const_pmap(get_param(params, boost::edge_weight), g,
493 choose_const_pmap(get_param(params, boost::vertex_index), g,
494 boost::vertex_index),
495 std::move(result), std::move(
components), std::move(oracle),
519 typename Restrictions,
typename ResultNetworkOutputIterator,
520 typename IRcomponents = steiner_network_ir_components<>,
521 typename Visitor = trivial_visitor>
523 const Restrictions &restrictions,
524 ResultNetworkOutputIterator result,
527 Oracle oracle = Oracle(),
528 Visitor visitor = Visitor()) {
530 g, restrictions, boost::no_named_parameters(), std::move(result),
531 std::move(
components), std::move(oracle), std::move(visitor));
536 #endif // PAAL_STEINER_NETWORK_HPP
void operator()(Problem &problem, const GetSolution &solution)
const edge_list & get_edges_in_solution() const
void add_column_to_solution(lp::col_id col_id)
The common LP solvers base class. Responsible for:
col_id add_column(double cost_coef=0, double lb=0., double ub=lp_traits::PLUS_INF, const std::string &name="")
void add_violated_constraint(Candidate violation, const Problem &problem, LP &lp)
Violations checker for the separation oracle in the steiner network problem.
void remove_column(lp::col_id col_id)
void bind_edge_to_col(edge e, lp::col_id col)
IRResult steiner_network_iterative_rounding(const Graph &g, const Restrictions &restrictions, const boost::bgl_named_params< P, T, R > ¶ms, ResultNetworkOutputIterator result, IRcomponents components=IRcomponents(), Oracle oracle=Oracle(), Visitor visitor=Visitor())
Solves the Steiner Network problem using Iterative Rounding. Named version.
error_message check_input_validity()
const VertexIndex & get_index() const
steiner_network_set_solution(double epsilon=steiner_network_compare_traits::EPSILON)
void set_lp_name(const std::string problem_name)
The class for solving the Steiner Network problem using Iterative Rounding.
auto get_max_restriction(vertex_idx u, vertex_idx v) const -> decltype(std::declval< Restrictions >()(0, 0))
steiner_network(const Graph &g, const Restrictions &restrictions, CostMap cost_map, VertexIndex vertex_index, ResultNetworkOutputIterator result_network, Oracle oracle=Oracle{})
void operator()(Problem &problem, LP &lp)
Violation check_violation(Candidate candidate, const Problem &problem)
steiner_network< Graph, Restrictions, CostMap, VertexIndex, ResultNetworkOutputIterator, Oracle > make_steiner_network(const Graph &g, const Restrictions &restrictions, CostMap cost_map, VertexIndex vertex_index, ResultNetworkOutputIterator result_network, Oracle oracle=Oracle{})
Creates a steiner_network object. Non-named version.
RestrictionsVector prune_restrictions_to_tree(Restrictions res, int N)
Returns a list of restrictions, made of the edges of a maximum spanning tree in a clique with edge we...
Column rounding component. A variable is rounded up to 1, if it has value at least half in the soluti...
const RestrictionsVector & get_restrictions_vec() const
typename components::type< Args...> IRcomponents
Iterative rounding components.
steiner_network_round_condition(double epsilon=steiner_network_compare_traits::EPSILON)
auto get_cost(edge e) -> decltype(get(std::declval< CostMap >(), e))
const Graph & get_graph() const
std::pair< lp::problem_type, IRSolutionCost > IRResult
IRResult solve_iterative_rounding(Problem &problem, IRcomponents components, Visitor visitor=Visitor())
Solves an Iterative Rounding problem.
bool e(T a, T b) const
equals
boost::optional< double > operator()(Problem &problem, const LP &lp, lp::col_id col_id)
IRResult steiner_network_iterative_rounding(const Graph &g, const Restrictions &restrictions, CostMap cost, VertexIndex vertex_index, ResultNetworkOutputIterator result, IRcomponents components=IRcomponents(), Oracle oracle=Oracle(), Visitor visitor=Visitor())
Solves the Steiner Network problem using Iterative Rounding. Non-named version.
auto get_find_violation(LP &lp)
bool check_if_solution_exists(Problem &problem)
const edge_map & get_edge_map() const
auto get_violation_candidates(const Problem &problem, const LP &lp) -> decltype(problem.get_restrictions_vec())
auto make_steiner_network(const Graph &g, const Restrictions &restrictions, const boost::bgl_named_params< P, T, R > ¶ms, ResultNetworkOutputIterator result_network, Oracle oracle=Oracle()) -> steiner_network< Graph, Restrictions, decltype(choose_const_pmap(get_param(params, boost::edge_weight), g, boost::edge_weight)), decltype(choose_const_pmap(get_param(params, boost::vertex_index), g, boost::vertex_index)), ResultNetworkOutputIterator, Oracle >
compare get_compare() const