bounded_degree_mst_oracle.hpp
Go to the documentation of this file.
1 //=======================================================================
3 //
5 // accompanying file LICENSE_1_0.txt or copy at
7 //=======================================================================
15 #ifndef PAAL_BOUNDED_DEGREE_MST_ORACLE_HPP
16 #define PAAL_BOUNDED_DEGREE_MST_ORACLE_HPP
17
19 #include "paal/lp/lp_base.hpp"
20
21 #include <boost/optional.hpp>
22 #include <boost/range/as_array.hpp>
23
24 #include <vector>
25
26 namespace paal {
27 namespace ir {
28
35  using AuxEdge = min_cut_finder::Edge;
36  using AuxVertex = min_cut_finder::Vertex;
37  using AuxEdgeList = std::vector<AuxEdge>;
38  using Violation = boost::optional<double>;
39
40  public:
41  using Candidate = std::pair<AuxVertex, AuxVertex>;
42  using CandidateList = std::vector<Candidate>;
43
47  template <typename Problem, typename LP>
48  const CandidateList &get_violation_candidates(const Problem &problem,
49  const LP &lp) {
50  fill_auxiliary_digraph(problem, lp);
51  initialize_candidates(problem);
52  return m_candidate_list;
53  }
54
59  template <typename Problem>
60  Violation check_violation(Candidate candidate, const Problem &problem) {
61  double violation = find_violation(candidate.first, candidate.second);
62  if (problem.get_compare().g(violation, 0)) {
63  return violation;
64  } else {
65  return Violation{};
66  }
67  }
68
72  template <typename Problem, typename LP>
74  const Problem &problem, LP &lp) {
75  if (violating_pair != m_min_cut.get_last_cut()) {
76  find_violation(violating_pair.first, violating_pair.second);
77  }
78
79  auto const &g = problem.get_graph();
80  auto const &index = problem.get_index();
81
83  for (auto const &e : problem.get_edge_map().right) {
84  auto u = get(index, source(e.second, g));
85  auto v = get(index, target(e.second, g));
86  if (m_min_cut.is_in_source_set(u) &&
87  m_min_cut.is_in_source_set(v)) {
88  expr += e.first;
89  }
90  }
91  lp.add_row(std::move(expr) <= m_min_cut.source_set_size() - 2);
92  }
93
94  private:
95
99  template <typename Problem, typename LP>
100  void fill_auxiliary_digraph(const Problem &problem, const LP &lp) {
101  auto const &g = problem.get_graph();
102  auto const &index = problem.get_index();
103  m_vertices_num = num_vertices(g);
104  m_min_cut.init(m_vertices_num);
105  m_src_to_v.resize(m_vertices_num);
106  m_v_to_trg.resize(m_vertices_num);
107
108  for (auto const &e : problem.get_edge_map().right) {
109  lp::col_id col_idx = e.first;
110  double col_val = lp.get_col_value(col_idx) / 2;
111
112  if (!problem.get_compare().e(col_val, 0)) {
113  auto u = get(index, source(e.second, g));
114  auto v = get(index, target(e.second, g));
116  }
117  }
118
121
122  for (auto v : boost::as_array(vertices(g))) {
123  auto aux_v = get(index, v);
124  m_src_to_v[aux_v] = m_min_cut
125  .add_edge_to_graph(m_src, aux_v, degree_of(problem, v, lp) / 2)
126  .first;
127  m_v_to_trg[aux_v] =
129  }
130  }
131
135  template <typename Problem>
136  void initialize_candidates(const Problem &problem) {
137  auto const &g = problem.get_graph();
138  auto const &index = problem.get_index();
139  auto src = *(std::next(vertices(g).first, rand() % m_vertices_num));
140  auto aux_src = get(index, src);
141  m_candidate_list.clear();
142  for (auto v : boost::as_array(vertices(g))) {
143  if (v != src) {
144  auto aux_v = get(index, v);
145  m_candidate_list.push_back(std::make_pair(aux_src, aux_v));
146  m_candidate_list.push_back(std::make_pair(aux_v, aux_src));
147  }
148  }
149  }
150
155  template <typename Problem, typename LP, typename Vertex>
156  double degree_of(const Problem &problem, const Vertex &v, const LP &lp) {
157  double res = 0;
158
159  for (auto e : boost::as_array(out_edges(v, problem.get_graph()))) {
160  auto col_id = problem.edge_to_col(e);
161  if (col_id) {
162  res += lp.get_col_value(*col_id);
163  }
164  }
165  return res;
166  }
167
175  double find_violation(AuxVertex src, AuxVertex trg) {
176  double orig_cap = m_min_cut.get_capacity(m_src_to_v[src]);
177
178  m_min_cut.set_capacity(m_src_to_v[src], m_vertices_num);
179  // capacity of m_src_to_v[trg] does not change
180  m_min_cut.set_capacity(m_v_to_trg[src], 0);
181  m_min_cut.set_capacity(m_v_to_trg[trg], m_vertices_num);
182
183  double min_cut_weight = m_min_cut.find_min_cut(m_src, m_trg);
184  double violation = m_vertices_num - 1 - min_cut_weight;
185
186  // reset the original values for the capacities
187  m_min_cut.set_capacity(m_src_to_v[src], orig_cap);
188  // capacity of m_src_to_v[trg] does not change
189  m_min_cut.set_capacity(m_v_to_trg[src], 1);
190  m_min_cut.set_capacity(m_v_to_trg[trg], 1);
191
192  return violation;
193  }
194
195  int m_vertices_num;
196
197  AuxVertex m_src;
198  AuxVertex m_trg;
199
200  AuxEdgeList m_src_to_v;
201  AuxEdgeList m_v_to_trg;
202
203  CandidateList m_candidate_list;
204
205  min_cut_finder m_min_cut;
206 };
207
208 }
209 }
210 #endif // PAAL_BOUNDED_DEGREE_MST_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
const CandidateList & get_violation_candidates(const Problem &problem, const LP &lp)
void set_capacity(Edge e, double cap)
Definition: min_cut.hpp:138
The common LP solvers base class. Responsible for:
Definition: lp_base.hpp:55
Violations checker for the separation oracle in the bounded degree minimum spanning tree problem...
double find_min_cut(Vertex src, Vertex trg)
Definition: min_cut.hpp:95
double get_capacity(Edge e) const
Definition: min_cut.hpp:133
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 add_violated_constraint(Candidate violating_pair, const Problem &problem, LP &lp)