Skip to content

Commit e2b3aea

Browse files
committed
test scaling configs
1 parent 6b2a631 commit e2b3aea

4 files changed

Lines changed: 296 additions & 57 deletions

File tree

cpp/src/mip_heuristics/diversity/diversity_manager.cu

Lines changed: 124 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
#include <utilities/scope_guard.hpp>
1919

20+
#include <array>
21+
2022
constexpr bool fj_only_run = false;
2123

2224
namespace cuopt::linear_programming::detail {
@@ -33,11 +35,123 @@ size_t sub_mip_recombiner_config_t::max_n_of_vars_from_other =
3335
template <typename i_t, typename f_t>
3436
std::vector<recombiner_enum_t> recombiner_t<i_t, f_t>::enabled_recombiners;
3537

38+
namespace {
39+
const char* mip_scaling_call_order_to_string(mip_scaling_call_order_t call_order)
40+
{
41+
switch (call_order) {
42+
case mip_scaling_call_order_t::BEFORE_BOUNDS_UPDATE: return "before_bounds_update";
43+
case mip_scaling_call_order_t::AFTER_TRIVIAL_PRESOLVE: return "after_trivial_presolve";
44+
}
45+
return "unknown";
46+
}
47+
} // namespace
48+
49+
template <typename i_t, typename f_t>
50+
std::vector<mip_scaling_benchmark_config_t<f_t>>
51+
diversity_manager_t<i_t, f_t>::get_mip_scaling_config_matrix()
52+
{
53+
std::vector<mip_scaling_benchmark_config_t<f_t>> configs;
54+
configs.reserve(16);
55+
56+
const std::array<mip_scaling_call_order_t, 2> call_orders = {
57+
mip_scaling_call_order_t::BEFORE_BOUNDS_UPDATE,
58+
mip_scaling_call_order_t::AFTER_TRIVIAL_PRESOLVE};
59+
const std::array<int, 2> iteration_counts = {1, 3};
60+
61+
for (auto call_order : call_orders) {
62+
for (auto iteration_count : iteration_counts) {
63+
for (bool use_big_m_skip_rows : {false, true}) {
64+
for (bool use_power_of_two_scaling : {true, false}) {
65+
mip_scaling_benchmark_config_t<f_t> config{};
66+
config.call_order = call_order;
67+
config.row_scaling_num_iterations = iteration_count;
68+
config.row_scaling_k_min = -20;
69+
config.row_scaling_k_max = 20;
70+
config.use_big_m_skip_rows = use_big_m_skip_rows;
71+
config.use_power_of_two_scaling = use_power_of_two_scaling;
72+
config.minimum_scaled_magnitude = static_cast<f_t>(1.0e-5);
73+
configs.push_back(config);
74+
}
75+
}
76+
}
77+
}
78+
return configs;
79+
}
80+
81+
template <typename i_t, typename f_t>
82+
void diversity_manager_t<i_t, f_t>::configure_mip_scaling_from_config_id()
83+
{
84+
auto configs = get_mip_scaling_config_matrix();
85+
if (configs.empty()) { return; }
86+
87+
int max_config = static_cast<int>(configs.size());
88+
const char* env_max_config = std::getenv("CUOPT_MAX_CONFIG");
89+
if (env_max_config != nullptr) {
90+
try {
91+
const int parsed_max_config = std::stoi(env_max_config);
92+
if (parsed_max_config > 0) {
93+
max_config = std::min(parsed_max_config, max_config);
94+
} else {
95+
CUOPT_LOG_WARN("CUOPT_MAX_CONFIG must be > 0. Falling back to default matrix size.");
96+
}
97+
} catch (const std::exception& e) {
98+
CUOPT_LOG_WARN("Failed to parse CUOPT_MAX_CONFIG environment variable: %s", e.what());
99+
}
100+
}
101+
102+
int config_id = 0;
103+
const char* env_config_id = std::getenv("CUOPT_CONFIG_ID");
104+
if (env_config_id != nullptr) {
105+
try {
106+
config_id = std::stoi(env_config_id);
107+
} catch (const std::exception& e) {
108+
CUOPT_LOG_WARN("Failed to parse CUOPT_CONFIG_ID environment variable: %s", e.what());
109+
config_id = 0;
110+
}
111+
}
112+
113+
const int selected_config_id =
114+
((config_id % max_config) + max_config) % max_config; // keep it in [0, max_config)
115+
if (selected_config_id != config_id) {
116+
CUOPT_LOG_WARN("Config ID %d out of range [0, %d). Using wrapped config ID %d.",
117+
config_id,
118+
max_config,
119+
selected_config_id);
120+
}
121+
mip_scaling_config = configs[selected_config_id];
122+
CUOPT_LOG_INFO(
123+
"MIP scaling config selected: id=%d/%d order=%s iters=%d k=[%d,%d] "
124+
"big_m=%d pow2=%d min_scaled_val=%e",
125+
selected_config_id,
126+
max_config,
127+
mip_scaling_call_order_to_string(mip_scaling_config.call_order),
128+
mip_scaling_config.row_scaling_num_iterations,
129+
mip_scaling_config.row_scaling_k_min,
130+
mip_scaling_config.row_scaling_k_max,
131+
mip_scaling_config.use_big_m_skip_rows,
132+
mip_scaling_config.use_power_of_two_scaling,
133+
static_cast<double>(mip_scaling_config.minimum_scaled_magnitude));
134+
}
135+
136+
template <typename i_t, typename f_t>
137+
void diversity_manager_t<i_t, f_t>::apply_mip_scaling_config()
138+
{
139+
auto scaling_config = context.scaling.get_config();
140+
scaling_config.row_scaling_num_iterations = mip_scaling_config.row_scaling_num_iterations;
141+
scaling_config.row_scaling_k_min = mip_scaling_config.row_scaling_k_min;
142+
scaling_config.row_scaling_k_max = mip_scaling_config.row_scaling_k_max;
143+
scaling_config.use_big_m_skip_rows = mip_scaling_config.use_big_m_skip_rows;
144+
scaling_config.use_power_of_two_scaling = mip_scaling_config.use_power_of_two_scaling;
145+
scaling_config.minimum_scaled_magnitude = mip_scaling_config.minimum_scaled_magnitude;
146+
context.scaling.set_config(scaling_config);
147+
}
148+
36149
template <typename i_t, typename f_t>
37150
diversity_manager_t<i_t, f_t>::diversity_manager_t(mip_solver_context_t<i_t, f_t>& context_)
38151
: context(context_),
39152
branch_and_bound_ptr(nullptr),
40153
problem_ptr(context.problem_ptr),
154+
mip_scaling_config(),
41155
diversity_config(),
42156
population("population",
43157
context,
@@ -75,30 +189,8 @@ diversity_manager_t<i_t, f_t>::diversity_manager_t(mip_solver_context_t<i_t, f_t
75189
mab_ls(mab_ls_config_t<i_t, f_t>::n_of_arms, cuopt::seed_generator::get_seed(), ls_alpha, "ls"),
76190
ls_hash_map(*context.problem_ptr)
77191
{
78-
// Read configuration ID from environment variable
79-
int max_config = -1;
80-
// Read max configuration value from environment variable
81-
const char* env_max_config = std::getenv("CUOPT_MAX_CONFIG");
82-
if (env_max_config != nullptr) {
83-
try {
84-
max_config = std::stoi(env_max_config);
85-
CUOPT_LOG_INFO("Using maximum configuration value from environment: %d", max_config);
86-
} catch (const std::exception& e) {
87-
CUOPT_LOG_WARN("Failed to parse CUOPT_MAX_CONFIG environment variable: %s", e.what());
88-
}
89-
}
90-
if (max_config > 1) {
91-
[[maybe_unused]] int config_id = -1; // Default value
92-
const char* env_config_id = std::getenv("CUOPT_CONFIG_ID");
93-
if (env_config_id != nullptr) {
94-
try {
95-
config_id = std::stoi(env_config_id);
96-
CUOPT_LOG_INFO("Using configuration ID from environment: %d", config_id);
97-
} catch (const std::exception& e) {
98-
CUOPT_LOG_WARN("Failed to parse CUOPT_CONFIG_ID environment variable: %s", e.what());
99-
}
100-
}
101-
}
192+
configure_mip_scaling_from_config_id();
193+
apply_mip_scaling_config();
102194
}
103195

104196
// this function is to specialize the local search with config from diversity manager
@@ -177,7 +269,13 @@ bool diversity_manager_t<i_t, f_t>::run_presolve(f_t time_limit)
177269
raft::common::nvtx::range fun_scope("run_presolve");
178270
CUOPT_LOG_INFO("Running presolve!");
179271
timer_t presolve_timer(time_limit);
180-
if (context.settings.mip_scaling) { context.scaling.scale_problem(); }
272+
auto run_scaling_if = [this](mip_scaling_call_order_t expected_order) {
273+
if (context.settings.mip_scaling && mip_scaling_config.call_order == expected_order) {
274+
context.scaling.scale_problem();
275+
}
276+
};
277+
278+
run_scaling_if(mip_scaling_call_order_t::BEFORE_BOUNDS_UPDATE);
181279
auto term_crit = ls.constraint_prop.bounds_update.solve(*problem_ptr);
182280
if (ls.constraint_prop.bounds_update.infeas_constraints_count > 0) {
183281
stats.presolve_time = timer.elapsed_time();
@@ -217,6 +315,7 @@ bool diversity_manager_t<i_t, f_t>::run_presolve(f_t time_limit)
217315
if (!check_bounds_sanity(*problem_ptr)) { return false; }
218316
}
219317
}
318+
run_scaling_if(mip_scaling_call_order_t::AFTER_TRIVIAL_PRESOLVE);
220319
}
221320
stats.presolve_time = presolve_timer.elapsed_time();
222321
lp_optimal_solution.resize(problem_ptr->n_variables, problem_ptr->handle_ptr->get_stream());

cpp/src/mip_heuristics/diversity/diversity_manager.cuh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@
2929

3030
namespace cuopt::linear_programming::detail {
3131

32+
enum class mip_scaling_call_order_t : int { BEFORE_BOUNDS_UPDATE = 0, AFTER_TRIVIAL_PRESOLVE };
33+
34+
template <typename f_t>
35+
struct mip_scaling_benchmark_config_t {
36+
mip_scaling_call_order_t call_order = mip_scaling_call_order_t::BEFORE_BOUNDS_UPDATE;
37+
int row_scaling_num_iterations = 3;
38+
int row_scaling_k_min = -20;
39+
int row_scaling_k_max = 20;
40+
bool use_big_m_skip_rows = false;
41+
bool use_power_of_two_scaling = true;
42+
f_t minimum_scaled_magnitude = static_cast<f_t>(1.0e-5);
43+
};
44+
3245
template <typename i_t, typename f_t>
3346
class diversity_manager_t {
3447
public:
@@ -69,10 +82,14 @@ class diversity_manager_t {
6982
void set_simplex_solution(const std::vector<f_t>& solution,
7083
const std::vector<f_t>& dual_solution,
7184
f_t objective);
85+
void configure_mip_scaling_from_config_id();
86+
void apply_mip_scaling_config();
87+
static std::vector<mip_scaling_benchmark_config_t<f_t>> get_mip_scaling_config_matrix();
7288

7389
mip_solver_context_t<i_t, f_t>& context;
7490
dual_simplex::branch_and_bound_t<i_t, f_t>* branch_and_bound_ptr;
7591
problem_t<i_t, f_t>* problem_ptr;
92+
mip_scaling_benchmark_config_t<f_t> mip_scaling_config;
7693
diversity_config_t diversity_config;
7794
population_t<i_t, f_t> population;
7895
rmm::device_uvector<f_t> lp_optimal_solution;

0 commit comments

Comments
 (0)