All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
steiner_network_oracle.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2013 Piotr Wygocki
3 // 2014 Piotr Godlewski
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //=======================================================================
16 #ifndef PAAL_STEINER_NETWORK_ORACLE_HPP
17 #define PAAL_STEINER_NETWORK_ORACLE_HPP
18 
20 
21 #include <boost/range/as_array.hpp>
22 
23 namespace paal {
24 namespace ir {
25 
32  using AuxVertex = min_cut_finder::Vertex;
33  using Violation = double;
34 
35  public:
36  using Candidate = std::pair<AuxVertex, AuxVertex>;
37 
41  template <typename Problem>
42  bool check_if_solution_exists(Problem &problem) {
43  auto const &g = problem.get_graph();
44  auto const &index = problem.get_index();
45  m_min_cut.init(num_vertices(g));
46 
47  for (auto e : boost::as_array(edges(g))) {
48  auto u = get(index, source(e, g));
49  auto v = get(index, target(e, g));
50  m_min_cut.add_edge_to_graph(u, v, 1, 1);
51  }
52 
53  for (auto res : problem.get_restrictions_vec()) {
54  if (check_violation(res, problem)) {
55  return false;
56  }
57  }
58 
59  return true;
60  }
61 
65  template <typename Problem, typename LP>
66  auto get_violation_candidates(const Problem &problem, const LP &lp)
67  ->decltype(problem.get_restrictions_vec()) {
68 
69  fill_auxiliary_digraph(problem, lp);
70  return problem.get_restrictions_vec();
71  }
72 
77  template <typename Problem>
78  Violation check_violation(Candidate candidate, const Problem &problem) {
79  double violation =
80  find_violation(candidate.first, candidate.second, problem);
81  if (problem.get_compare().g(violation, 0)) {
82  return violation;
83  } else {
84  return Violation{};
85  }
86  }
87 
91  template <typename Problem, typename LP>
92  void add_violated_constraint(Candidate violation, const Problem &problem,
93  LP &lp) {
94  if (violation != m_min_cut.get_last_cut()) {
95  find_violation(violation.first, violation.second, problem);
96  }
97 
98  auto const &g = problem.get_graph();
99  auto const &index = problem.get_index();
100  auto restriction =
101  problem.get_max_restriction(violation.first, violation.second);
102 
103  for (auto const &e : problem.get_edges_in_solution()) {
104  if (is_edge_in_violating_cut(e, g, index)) {
105  --restriction;
106  }
107  }
108 
110  for (auto const &e : problem.get_edge_map()) {
111  if (is_edge_in_violating_cut(e.second, g, index)) {
112  expr += e.first;
113  }
114  }
115 
116  lp.add_row(std::move(expr) >= restriction);
117  }
118 
119  private:
120 
125  template <typename Edge, typename Graph, typename Index>
126  bool is_edge_in_violating_cut(Edge edge, const Graph &g,
127  const Index &index) {
128  auto u = get(index, source(edge, g));
129  auto v = get(index, target(edge, g));
130  return m_min_cut.is_in_source_set(u) != m_min_cut.is_in_source_set(v);
131  }
132 
136  template <typename Problem, typename LP>
137  void fill_auxiliary_digraph(Problem &problem, const LP &lp) {
138  auto const &g = problem.get_graph();
139  auto const &index = problem.get_index();
140  m_min_cut.init(num_vertices(g));
141 
142  for (auto const &e : problem.get_edge_map()) {
143  lp::col_id col_idx = e.first;
144  double col_val = lp.get_col_value(col_idx);
145 
146  if (problem.get_compare().g(col_val, 0)) {
147  auto u = get(index, source(e.second, g));
148  auto v = get(index, target(e.second, g));
149  m_min_cut.add_edge_to_graph(u, v, col_val, col_val);
150  }
151  }
152 
153  for (auto const &e : problem.get_edges_in_solution()) {
154  auto u = get(index, source(e, g));
155  auto v = get(index, target(e, g));
156  m_min_cut.add_edge_to_graph(u, v, 1, 1);
157  }
158  }
159 
168  template <typename Problem>
169  double find_violation(AuxVertex src, AuxVertex trg,
170  const Problem &problem) {
171  double min_cut_weight = m_min_cut.find_min_cut(src, trg);
172  double restriction = problem.get_max_restriction(src, trg);
173  return restriction - min_cut_weight;
174  }
175 
176  min_cut_finder m_min_cut;
177 };
178 
179 }
180 }
181 #endif // PAAL_STEINER_NETWORK_ORACLE_HPP
std::pair< Edge, Edge > add_edge_to_graph(Vertex src, Vertex trg, double cap, double rev_cap=0.)
Definition: min_cut.hpp:70
bool is_in_source_set(Vertex v) const
Definition: min_cut.hpp:109
The common LP solvers base class. Responsible for:
Definition: lp_base.hpp:55
void add_violated_constraint(Candidate violation, const Problem &problem, LP &lp)
Violations checker for the separation oracle in the steiner network problem.
Violation check_violation(Candidate candidate, const Problem &problem)
double find_min_cut(Vertex src, Vertex trg)
Definition: min_cut.hpp:95
double get_col_value(col_id col) const
Definition: lp_base.hpp:228
row_id add_row(const double_bounded_expression &constraint=double_bounded_expression{}, const std::string &name="")
Definition: lp_base.hpp:109
void init(int vertices_num)
Definition: min_cut.hpp:46
auto get_violation_candidates(const Problem &problem, const LP &lp) -> decltype(problem.get_restrictions_vec())
std::pair< Vertex, Vertex > get_last_cut() const
Definition: min_cut.hpp:128