Commit 21a6c023 authored by Gauthier Quesnel's avatar Gauthier Quesnel
Browse files

solver: add debug mode for all solvers

parent fa1ff55d
Pipeline #5270 passed with stage
in 3 minutes and 22 seconds
......@@ -34,12 +34,16 @@
#include <algorithm>
#include <chrono>
#include <fstream>
#include <iterator>
#include <numeric>
#include <random>
#include <thread>
#include <tuple>
#include <vector>
#include <fmt/ostream.h>
namespace baryonyx {
namespace itm {
......@@ -421,9 +425,6 @@ class solver_initializer
cycle_automaton cycle{ cycle_automaton::pessimistic_solve };
init_automaton init{ init_automaton::random };
// Fully fill the solution vector X with a mix of values from the bastert
// policy and from random value.
void init_bastert(Solver& slv, bit_array& x) noexcept
{
const int value_if_cost_0 = 1;
......@@ -434,53 +435,16 @@ class solver_initializer
x.set(i);
else
x.unset(i);
} else {
if (toss_up(slv.rng))
x.set(i);
else
x.unset(i);
}
}
}
void reinit_bastert(Solver& slv,
bit_array& x,
const solution& best) noexcept
{
const int value_if_cost_0 = 1;
for (int i = 0; i != slv.n; ++i)
if (dist(slv.rng)) {
if (init_x<Mode>(slv.c(i, x), value_if_cost_0))
x.set(i);
else
x.unset(i);
} else {
if (best.variables[i])
x.set(i);
else
x.unset(i);
}
}
void reinit_bastert(Solver& slv, bit_array& x) noexcept
{
const int value_if_cost_0 = 1;
for (int i = 0; i != slv.n; ++i)
if (dist(slv.rng)) {
if (init_x<Mode>(slv.c(i, x), value_if_cost_0))
x.set(i);
else
x.unset(i);
}
}
void do_init_pessimistic_solve(Solver& slv, bit_array& x) noexcept
void init_pessimistic_solve(Solver& slv, bit_array& x) noexcept
{
for (int k = 0; k != slv.m; ++k) {
if (!dist(slv.rng))
continue;
auto [begin, end] = slv.ap.row(k);
int r_size = 0;
......@@ -526,38 +490,7 @@ class solver_initializer
}
}
void init_pessimistic_solve(Solver& slv, bit_array& x) noexcept
{
for (int i = 0; i != slv.n; ++i)
if (toss_up(slv.rng))
x.set(i);
else
x.unset(i);
do_init_pessimistic_solve(slv, x);
}
void reinit_pessimistic_solve(Solver& slv, bit_array& x) noexcept
{
do_init_pessimistic_solve(slv, x);
}
void reinit_pessimistic_solve(Solver& slv,
bit_array& x,
const solution& best) noexcept
{
for (int i = 0; i != slv.n; ++i)
if (best.variables[i])
x.set(i);
else
x.unset(i);
do_init_pessimistic_solve(slv, x);
}
/////
void do_init_optimistic_solve(Solver& slv, bit_array& x) noexcept
void init_optimistic_solve(Solver& slv, bit_array& x) noexcept
{
for (int k = 0; k != slv.m; ++k) {
if (!dist(slv.rng))
......@@ -610,35 +543,6 @@ class solver_initializer
}
}
void init_optimistic_solve(Solver& slv, bit_array& x) noexcept
{
for (int i = 0; i != slv.n; ++i)
if (toss_up(slv.rng))
x.set(i);
else
x.unset(i);
do_init_optimistic_solve(slv, x);
}
void reinit_optimistic_solve(Solver& slv, bit_array& x) noexcept
{
do_init_optimistic_solve(slv, x);
}
void reinit_optimistic_solve(Solver& slv,
bit_array& x,
const solution& best) noexcept
{
for (int i = 0; i != slv.n; ++i)
if (best.variables[i])
x.set(i);
else
x.unset(i);
do_init_optimistic_solve(slv, x);
}
public:
solver_initializer(Solver& slv,
solver_parameters::init_policy_type policy,
......@@ -734,13 +638,13 @@ public:
case single_automaton::improve_x_3:
switch (cycle) {
case cycle_automaton::bastert:
reinit_bastert(slv, x);
init_bastert(slv, x);
break;
case cycle_automaton::pessimistic_solve:
reinit_pessimistic_solve(slv, x);
init_pessimistic_solve(slv, x);
break;
case cycle_automaton::optimistic_solve:
reinit_optimistic_solve(slv, x);
init_optimistic_solve(slv, x);
break;
}
break;
......@@ -808,13 +712,13 @@ public:
case single_automaton::improve_x_3:
switch (cycle) {
case cycle_automaton::bastert:
reinit_bastert(slv, x);
init_bastert(slv, x);
break;
case cycle_automaton::pessimistic_solve:
reinit_pessimistic_solve(slv, x);
init_pessimistic_solve(slv, x);
break;
case cycle_automaton::optimistic_solve:
reinit_optimistic_solve(slv, x);
init_optimistic_solve(slv, x);
break;
}
break;
......@@ -1882,6 +1786,58 @@ template<int o>
using mode_sel =
typename std::conditional<o == 0, maximize_tag, minimize_tag>::type;
template<bool debug>
struct debug_logger
{
std::FILE* ofs;
debug_logger([[maybe_unused]] const std::string_view name) noexcept
{
if constexpr (debug) {
char buffer[512] = { '\0' };
auto written = fmt::format_to_n(
buffer,
511,
"{}-{}.log",
name,
std::hash<std::thread::id>{}(std::this_thread::get_id()));
buffer[written.size] = '\0';
ofs = std::fopen(buffer, "w");
}
}
~debug_logger() noexcept
{
if constexpr (debug) {
if (ofs)
std::fclose(ofs);
}
}
template<typename... Args>
void log([[maybe_unused]] const std::string_view fmt,
[[maybe_unused]] const Args&... args) const noexcept
{
if constexpr (debug) {
fmt::print(ofs, fmt, args...);
}
}
template<typename... Args>
void log([[maybe_unused]] unsigned indent,
[[maybe_unused]] const std::string_view fmt,
[[maybe_unused]] const Args&... args) const noexcept
{
if constexpr (debug) {
fmt::print(ofs, "{:{}}", "", indent);
fmt::print(ofs, fmt, args...);
}
}
};
} // namespace itm
} // namespace baryonyx
......
......@@ -27,9 +27,10 @@
namespace baryonyx {
namespace itm {
template<typename Float, typename Mode, typename Cost>
struct solver_equalities_01coeff
template<typename Float, typename Mode, typename Cost, bool debug>
struct solver_equalities_01coeff : debug_logger<debug>
{
using logger = debug_logger<debug>;
using mode_type = Mode;
using float_type = Float;
using cost_type = Cost;
......@@ -69,7 +70,8 @@ struct solver_equalities_01coeff
int n_,
const cost_type& c_,
const std::vector<merged_constraint>& csts)
: rng(rng_)
: logger("solver_equalities_01coeff")
, rng(rng_)
, ap(csts, m_, n_)
, P(std::make_unique<Float[]>(ap.size()))
, R(std::make_unique<rc_data[]>(compute_reduced_costs_vector_size(csts)))
......@@ -190,6 +192,8 @@ struct solver_equalities_01coeff
{
auto at_least_one_pi_changed{ false };
logger::log("push-update-row {} {} {}\n", kappa, delta, theta);
for (; first != last; ++first) {
auto k = constraint(first);
......@@ -209,6 +213,13 @@ struct solver_equalities_01coeff
calculator_sort<Mode>(R.get(), R.get() + r_size, rng);
int selected = select_variables(r_size, b[k]);
logger::log("constraints {}: {} = ", k, b[k]);
for (int i = 0; i < r_size; ++i)
logger::log("{} ({}) ", R[i].value, R[i].id);
logger::log(" => Selected: {}\n", selected);
auto pi_change = affect(
*this, x, std::get<0>(it), k, selected, r_size, kappa, delta);
......@@ -228,6 +239,8 @@ struct solver_equalities_01coeff
{
auto at_least_one_pi_changed{ false };
logger::log("update-row {} {} {}\n", kappa, delta, theta);
for (; first != last; ++first) {
auto k = constraint(first);
......@@ -240,6 +253,13 @@ struct solver_equalities_01coeff
calculator_sort<Mode>(R.get(), R.get() + r_size, rng);
int selected = select_variables(r_size, b[k]);
logger::log("constraints {}: {} = ", k, b[k]);
for (int i = 0; i < r_size; ++i)
logger::log("{} ({}) ", R[i].value, R[i].id);
logger::log(" => Selected: {}\n", selected);
auto pi_change = affect(
*this, x, std::get<0>(it), k, selected, r_size, kappa, delta);
......@@ -250,19 +270,25 @@ struct solver_equalities_01coeff
}
};
template<typename Float,
typename Mode,
typename Cost>
template<typename Float, typename Mode, typename Cost>
static result
solve_or_optimize(const context_ptr& ctx,
const problem& pb,
bool is_optimization)
{
using Solver = solver_equalities_01coeff<Float, Mode, Cost>;
return is_optimization
? optimize_problem<Solver, Float, Mode, Cost>(ctx, pb)
: solve_problem<Solver, Float, Mode, Cost>(ctx, pb);
if (ctx->parameters.debug) {
using Solver = solver_equalities_01coeff<Float, Mode, Cost, true>;
return is_optimization
? optimize_problem<Solver, Float, Mode, Cost>(ctx, pb)
: solve_problem<Solver, Float, Mode, Cost>(ctx, pb);
} else {
using Solver = solver_equalities_01coeff<Float, Mode, Cost, false>;
return is_optimization
? optimize_problem<Solver, Float, Mode, Cost>(ctx, pb)
: solve_problem<Solver, Float, Mode, Cost>(ctx, pb);
}
}
template<typename Float, typename Mode>
......@@ -271,12 +297,12 @@ select_cost(const context_ptr& ctx, const problem& pb, bool is_optimization)
{
return pb.objective.qelements.empty()
? solve_or_optimize<Float,
Mode,
baryonyx::itm::default_cost_type<Float>>(
Mode,
baryonyx::itm::default_cost_type<Float>>(
ctx, pb, is_optimization)
: solve_or_optimize<Float,
Mode,
baryonyx::itm::quadratic_cost_type<Float>>(
Mode,
baryonyx::itm::quadratic_cost_type<Float>>(
ctx, pb, is_optimization);
}
......
......@@ -27,9 +27,10 @@
namespace baryonyx {
namespace itm {
template<typename Float, typename Mode, typename Cost>
struct solver_equalities_101coeff
template<typename Float, typename Mode, typename Cost, bool debug>
struct solver_equalities_101coeff : debug_logger<debug>
{
using logger = debug_logger<debug>;
using mode_type = Mode;
using float_type = Float;
using cost_type = Cost;
......@@ -81,7 +82,8 @@ struct solver_equalities_101coeff
int n_,
const cost_type& c_,
const std::vector<merged_constraint>& csts)
: rng(rng_)
: logger("solver_equalities_101coeff")
, rng(rng_)
, ap(csts, m_, n_)
, P(std::make_unique<Float[]>(ap.size()))
, A(std::make_unique<int[]>(ap.size()))
......@@ -214,6 +216,8 @@ struct solver_equalities_101coeff
{
auto at_least_one_pi_changed{ false };
logger::log("push-update-row {} {} {}\n", kappa, delta, theta);
for (; first != last; ++first) {
auto k = constraint(first);
......@@ -234,6 +238,13 @@ struct solver_equalities_101coeff
calculator_sort<Mode>(R.get(), R.get() + sizes.r_size, rng);
int selected = select_variables(sizes, b[k].value);
logger::log("constraints {}: {} = ", k, b[k].value);
for (int i = 0; i < sizes.r_size; ++i)
logger::log("{} ({}) ", R[i].value, R[i].id);
logger::log(" => Selected: {}\n", selected);
auto pi_change = affect(*this,
x,
std::get<0>(it),
......@@ -258,6 +269,8 @@ struct solver_equalities_101coeff
{
auto at_least_one_pi_changed{ false };
logger::log("update-row {} {} {}\n", kappa, delta, theta);
for (; first != last; ++first) {
auto k = constraint(first);
......@@ -272,6 +285,13 @@ struct solver_equalities_101coeff
calculator_sort<Mode>(R.get(), R.get() + sizes.r_size, rng);
int selected = select_variables(sizes, b[k].value);
logger::log("constraints {}: {} = ", k, b[k].value);
for (int i = 0; i < sizes.r_size; ++i)
logger::log("{} ({}) ", R[i].value, R[i].id);
logger::log(" => Selected: {}\n", selected);
auto pi_change = affect(*this,
x,
std::get<0>(it),
......@@ -287,34 +307,39 @@ struct solver_equalities_101coeff
}
};
template<typename Float,
typename Mode,
typename Cost>
template<typename Float, typename Mode, typename Cost>
static result
solve_or_optimize(const context_ptr& ctx,
const problem& pb,
bool is_optimization)
{
using Solver = solver_equalities_101coeff<Float, Mode, Cost>;
return is_optimization
? optimize_problem<Solver, Float, Mode, Cost>(ctx, pb)
: solve_problem<Solver, Float, Mode, Cost>(ctx, pb);
if (ctx->parameters.debug) {
using Solver = solver_equalities_101coeff<Float, Mode, Cost, true>;
return is_optimization
? optimize_problem<Solver, Float, Mode, Cost>(ctx, pb)
: solve_problem<Solver, Float, Mode, Cost>(ctx, pb);
} else {
using Solver = solver_equalities_101coeff<Float, Mode, Cost, false>;
return is_optimization
? optimize_problem<Solver, Float, Mode, Cost>(ctx, pb)
: solve_problem<Solver, Float, Mode, Cost>(ctx, pb);
}
}
template<typename Float, typename Mode>
static result
select_cost(const context_ptr& ctx, const problem& pb, bool is_optimization)
{
return pb.objective.qelements.empty()
? solve_or_optimize<Float,
Mode,
baryonyx::itm::default_cost_type<Float>>(
Mode,
baryonyx::itm::default_cost_type<Float>>(
ctx, pb, is_optimization)
: solve_or_optimize<Float,
Mode,
baryonyx::itm::quadratic_cost_type<Float>>(
Mode,
baryonyx::itm::quadratic_cost_type<Float>>(
ctx, pb, is_optimization);
}
......
......@@ -27,9 +27,10 @@
namespace baryonyx {
namespace itm {
template<typename Float, typename Mode, typename Cost>
struct solver_inequalities_01coeff
template<typename Float, typename Mode, typename Cost, bool debug>
struct solver_inequalities_01coeff : debug_logger<debug>
{
using logger = debug_logger<debug>;
using mode_type = Mode;
using float_type = Float;
using cost_type = Cost;
......@@ -73,7 +74,8 @@ struct solver_inequalities_01coeff
int n_,
const cost_type& c_,
const std::vector<merged_constraint>& csts)
: rng(rng_)
: logger("solver_inequalities_01coeff")
, rng(rng_)
, ap(csts, m_, n_)
, P(std::make_unique<Float[]>(ap.size()))
, R(std::make_unique<rc_data[]>(compute_reduced_costs_vector_size(csts)))
......@@ -214,6 +216,8 @@ struct solver_inequalities_01coeff
{
auto at_least_one_pi_changed{ false };
logger::log("push-update-row {} {} {}\n", kappa, delta, theta);
for (; first != last; ++first) {
auto k = constraint(first);
......@@ -235,6 +239,13 @@ struct solver_inequalities_01coeff
calculator_sort<Mode>(R.get(), R.get() + r_size, rng);
int selected = select_variables(r_size, b[k].min, b[k].max);
logger::log("constraints {}: {} <= ", k, b[k].min);
for (int i = 0; i < r_size; ++i)
logger::log("({} {}) ", R[i].value, R[i].id);
logger::log("<= {} => Selected: {}\n", b[k].max, selected);
auto pi_change = affect(
*this, x, std::get<0>(it), k, selected, r_size, kappa, delta);
......@@ -254,6 +265,8 @@ struct solver_inequalities_01coeff
{
auto at_least_one_pi_changed{ false };
logger::log("update-row {} {} {}\n", kappa, delta, theta);
for (; first != last; ++first) {
auto k = constraint(first);
......@@ -266,6 +279,13 @@ struct solver_inequalities_01coeff
calculator_sort<Mode>(R.get(), R.get() + r_size, rng);
int selected = select_variables(r_size, b[k].min, b[k].max);
logger::log("constraints {}: {} <= ", k, b[k].min);
for (int i = 0; i < r_size; ++i)
logger::log("({} {}) ", R[i].value, R[i].id);
logger::log("<= {} => Selected: {}\n", b[k].max, selected);
auto pi_change = affect(
*this, x, std::get<0>(it), k, selected, r_size, kappa, delta);
......@@ -276,19 +296,25 @@ struct solver_inequalities_01coeff
}
};
template<typename Float,
typename Mode,
typename Cost>
template<typename Float, typename Mode, typename Cost>
static result
solve_or_optimize(const context_ptr& ctx,
const problem& pb,
bool is_optimization)
{
using Solver = solver_inequalities_01coeff<Float, Mode, Cost>;
return is_optimization
? optimize_problem<Solver, Float, Mode, Cost>(ctx, pb)
: solve_problem<Solver, Float, Mode, Cost>(ctx, pb);
if (ctx->parameters.debug) {
using Solver = solver_inequalities_01coeff<Float, Mode, Cost, true>;
return is_optimization
? optimize_problem<Solver, Float, Mode, Cost>(ctx, pb)
: solve_problem<Solver, Float, Mode, Cost>(ctx, pb);
} else {
using Solver = solver_inequalities_01coeff<Float, Mode, Cost, false>;
return is_optimization
? optimize_problem<Solver, Float, Mode, Cost>(ctx, pb)
: solve_problem<Solver, Float, Mode, Cost>(ctx, pb);
}
}
template<typename Float, typename Mode>
......@@ -297,12 +323,12 @@ select_cost(const context_ptr& ctx, const problem& pb, bool is_optimization)
{
return pb.objective.qelements.empty()
? solve_or_optimize<Float,
Mode,
baryonyx::itm::default_cost_type<Float>>(
Mode,
baryonyx::itm::default_cost_type<Float>>(
ctx, pb, is_optimization)
: solve_or_optimize<Float,
Mode,
baryonyx::itm::quadratic_cost_type<Float>>(
Mode,
baryonyx::itm::quadratic_cost_type<Float>>(
ctx, pb, is_optimization);
}
......