15 #ifndef PAAL_STEINER_TREE_ORACLE_HPP
16 #define PAAL_STEINER_TREE_ORACLE_HPP
21 #include <boost/optional.hpp>
23 #include <unordered_map>
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>;
41 using Candidate = AuxVertex;
47 template <
typename Problem,
typename LP>
49 ->decltype(
irange(problem.get_terminals().size())) {
51 int graph_size = problem.get_terminals().size();
52 if (graph_size != m_current_graph_size) {
54 m_current_graph_size = graph_size;
55 m_root = select_root(problem.get_terminals());
56 create_auxiliary_digraph(problem, lp);
58 update_auxiliary_digraph(problem, lp);
61 return irange(problem.get_terminals().size());
68 template <
typename Problem>
70 if (candidate == m_root) {
74 double violation = find_violation(candidate);
75 if (problem.get_compare().g(violation, 0)) {
87 template <
typename Problem,
typename LP>
89 const Problem &problem,
LP &lp) {
90 if (std::make_pair(violating_terminal, m_root) !=
92 find_violation(violating_terminal);
95 auto const &
components = problem.get_components();
98 auto u = m_artif_vertices[i];
100 auto v = m_terminals_to_aux[problem.get_terminal_idx(
components.find(i).get_sink(ver))];
103 expr += problem.find_column_lp(i);
106 lp.
add_row(std::move(expr) >= 1);
118 template <
typename Problem,
typename LP>
119 void create_auxiliary_digraph(Problem &problem,
const LP &lp) {
121 m_artif_vertices.clear();
122 m_terminals_to_aux.clear();
123 for (
auto term :
irange(problem.get_terminals().size())) {
126 auto const &components = problem.get_components();
128 for (
int i = 0; i < components.size(); ++i) {
130 m_artif_vertices[i] = new_v;
131 int ver = components.find_version(i);
132 auto sink = components.find(i).get_sink(ver);
133 for (
auto w : boost::make_iterator_range(components.find(i)
136 double INF = std::numeric_limits<double>::max();
137 m_min_cut.
add_edge_to_graph(m_terminals_to_aux[problem.get_terminal_idx(w)], new_v,
140 lp::col_id x = problem.find_column_lp(i);
143 m_terminals_to_aux[problem.get_terminal_idx(sink)],
154 template <
typename Problem,
typename LP>
155 void update_auxiliary_digraph(Problem &problem,
const LP &lp) {
156 auto const &components = problem.get_components();
157 for (
int i = 0; i < components.size(); ++i) {
158 auto component_v = m_artif_vertices[i];
159 int ver = components.find_version(i);
160 auto sink = components.find(i).get_sink(ver);
161 double col_val = lp.
get_col_value(problem.find_column_lp(i));
163 m_terminals_to_aux[problem.get_terminal_idx(sink)], col_val);
171 template <
typename Terminals>
172 AuxVertex select_root(
const Terminals &terminals) {
181 double find_violation(AuxVertex src) {
183 m_terminals_to_aux[src], m_terminals_to_aux[m_root]);
184 return 1 - min_cut_weight;
188 int m_current_graph_size;
191 std::unordered_map<int, AuxVertex> m_artif_vertices;
194 std::unordered_map<AuxVertex, AuxVertex> m_terminals_to_aux;
196 min_cut_finder m_min_cut;
201 #endif // PAAL_STEINER_TREE_ORACLE_HPP
std::pair< Edge, Edge > add_edge_to_graph(Vertex src, Vertex trg, double cap, double rev_cap=0.)
bool is_in_source_set(Vertex v) const
void set_capacity(Edge e, double cap)
Violation check_violation(Candidate candidate, const Problem &problem)
The common LP solvers base class. Responsible for:
auto get_violation_candidates(const Problem &problem, const LP &lp) -> decltype(irange(problem.get_terminals().size()))
auto irange(T begin, T end)
irange
Violations checker for the separation oracle in the steiner tree problem.
double find_min_cut(Vertex src, Vertex trg)
Terminals
enum indicates if given color represents terminal or NONTERMINAL.
double get_col_value(col_id col) const
row_id add_row(const double_bounded_expression &constraint=double_bounded_expression{}, const std::string &name="")
void add_violated_constraint(Candidate violating_terminal, const Problem &problem, LP &lp)
Vertex add_vertex_to_graph()
void init(int vertices_num)
std::pair< Vertex, Vertex > get_last_cut() const