15 #ifndef PAAL_ITERATIVE_ROUNDING_HPP
16 #define PAAL_ITERATIVE_ROUNDING_HPP
25 #include <boost/optional.hpp>
28 #include <unordered_map>
40 template <
typename Problem,
typename LP>
46 template <
typename Problem,
typename LP>
52 template <
typename Problem,
typename LP>
58 template <
typename Problem,
typename LP>
71 return m_lp.solve_simplex(lp::PRIMAL);
73 return m_lp.resolve_simplex(lp::DUAL);
79 template <
template <
class,
class>
class SolveLP = default_solve_lp_in_row_generation>
82 template <
class Problem,
class LP>
84 return row_generation(problem.get_find_violation(lp), SolveLP<Problem, LP>(problem, lp));
100 template <
typename Problem,
typename IRcomponents,
typename Visitor = trivial_visitor,
typename LP = lp::glp>
102 using RoundedCols = std::unordered_map<lp::col_id, std::pair<double, double>>;
108 auto i = m_rounded.find(col);
109 if (i == m_rounded.end()) {
112 return i->second.first;
121 Visitor vis = Visitor())
122 : m_ir_components(std::move(e)), m_visitor(std::move(vis)),
124 call<Init>(m_problem, m_lp);
133 auto prob_type = call<SolveLP>(m_problem, m_lp);
134 assert(prob_type != lp::UNDEFINED);
135 m_visitor.solve_lp(m_problem, m_lp);
145 auto prob_type = call<ResolveLP>(m_problem, m_lp);
146 assert(prob_type != lp::UNDEFINED);
147 m_visitor.solve_lp(m_problem, m_lp);
157 sol_cost += m_lp.
get_col_value(col) * m_lp.get_col_coef(col);
159 for (
auto rounded_col : m_rounded) {
160 sol_cost += rounded_col.second.first * rounded_col.second.second;
174 auto cbegin = std::begin(cols);
175 auto cend = std::end(cols);
177 while (cbegin != cend) {
179 auto do_round = call<RoundCondition>(m_problem, m_lp, col);
182 m_rounded.insert(std::make_pair(col,
183 std::make_pair(*do_round, m_lp.get_col_coef(col))));
184 m_visitor.round_col(m_problem, m_lp, col, *do_round);
185 cbegin = delete_column(cbegin, *do_round);
203 auto rbegin = std::begin(rows);
204 auto rend = std::end(rows);
206 while (rbegin != rend) {
208 if (call<RelaxCondition>(m_problem, m_lp, row)) {
210 m_visitor.relax_row(m_problem, m_lp, row);
212 if (call<RelaxationsLimit>(deleted)) {
237 call<SetSolution>(m_problem, boost::bind(&iterative_rounding::get_val,
255 template <
typename Action,
typename... Args>
256 auto call(Args &&... args)
257 ->decltype(std::declval<IRcomponents>().
template call<Action>(
258 std::forward<Args>(args)...)) {
259 return m_ir_components.template call<Action>(
260 std::forward<Args>(args)...);
265 delete_column(
typename LP::ColIter col_iter,
double value) {
266 auto column = m_lp.get_rows_in_column(*col_iter);
269 for (
auto const &c : column) {
270 boost::tie(row, coef) = c;
271 double ub = m_lp.get_row_upper_bound(row);
272 double lb = m_lp.get_row_lower_bound(row);
273 double diff = coef * value;
274 m_lp.set_row_upper_bound(row, ub - diff);
275 m_lp.set_row_lower_bound(row, lb - diff);
284 RoundedCols m_rounded;
294 using IRResult = std::pair<lp::problem_type, IRSolutionCost>;
307 template <
typename Problem,
typename IRcomponents,
typename Visitor = trivial_visitor,
typename LP = lp::glp>
312 if (prob_type != lp::OPTIMAL) {
317 bool rounded{ ir.
round() };
318 bool relaxed{ ir.
relax() };
319 assert(rounded || relaxed);
322 if (prob_type != lp::OPTIMAL) {
341 template <
typename Problem,
typename IRcomponents,
typename Visitor = trivial_visitor,
typename LP = lp::glp>
346 if (prob_type != lp::OPTIMAL) {
355 if (prob_type != lp::OPTIMAL) {
366 #endif // PAAL_ITERATIVE_ROUNDING_HPP
iterative_rounding(Problem &problem, IRcomponents e, Visitor vis=Visitor())
Constructor.
The common LP solvers base class. Responsible for:
default_solve_lp_in_row_generation(Problem &, LP &lp)
constructor
auto operator()(Problem &problem, LP &lp)
operator()
problem_type
LP problem type.
problem_type row_generation(TryAddViolated try_add_violated, SolveLp solve_lp)
void solve_lp(Problem &problem, LP &lp)
Method called after (re)solving the LP.
bool relax()
Relaxes the LP rows using the RelaxCondition component.
bool stop_condition()
Checks if the IR problem has been solved, using the StopCondition component.
void dependent_round()
Rounds the LP using the RoundCondition component.
LP & get_lp()
Returns the LP object used to solve the IR.
double get_solution_cost()
Returns the solution cost based on the LP values.
IRcomponents & get_ir_components()
Returns the IR components.
void relax_row(Problem &problem, LP &lp, lp::row_id row)
Method called after relaxing a row of the LP.
This class solves an iterative rounding problem.
void round_col(Problem &problem, LP &lp, lp::col_id col, double val)
Method called after rounding a column of the LP.
RowIter delete_row(RowIter row)
Default Iterative Rounding visitor.
void set_solution()
Sets the solution to the problem using SetSolution component.
ColIter delete_col(ColIter col)
lp::problem_type operator()()
operator()
typename components::type< Args...> IRcomponents
Iterative rounding components.
const ColSet & get_columns() const
double get_col_value(col_id col) const
lp::problem_type resolve_lp()
Finds solution to the LP.
bool round()
Rounds the LP columns (independently) using the RoundCondition component.
std::pair< lp::problem_type, IRSolutionCost > IRResult
IRResult solve_iterative_rounding(Problem &problem, IRcomponents components, Visitor visitor=Visitor())
Solves an Iterative Rounding problem.
boost::optional< double > IRSolutionCost
Iterative Rounding solution cost type. Solution cost only makes sense if the LP has been solved to op...
lp::problem_type solve_lp()
Finds solution to the LP.
const RowSet & get_rows() const
IRResult solve_dependent_iterative_rounding(Problem &problem, IRcomponents components, Visitor visitor=Visitor())
Solves an Iterative Rounding problem with dependent rounding.