Skip to content

Commit 7a5284e

Browse files
committed
Merge branch 'adjust-bnb-logs' into diving-heuristics
2 parents 0aa344e + fbb9966 commit 7a5284e

File tree

2 files changed

+101
-89
lines changed

2 files changed

+101
-89
lines changed

cpp/src/dual_simplex/branch_and_bound.cpp

Lines changed: 98 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,96 @@ f_t branch_and_bound_t<i_t, f_t>::get_lower_bound()
259259
return std::isfinite(lower_bound) ? lower_bound : -inf;
260260
}
261261

262+
template <typename i_t, typename f_t>
263+
void branch_and_bound_t<i_t, f_t>::report_heuristic(f_t obj)
264+
{
265+
if (solver_status_ == mip_exploration_status_t::RUNNING) {
266+
f_t user_obj = compute_user_objective(original_lp_, obj);
267+
f_t user_lower = compute_user_objective(original_lp_, get_lower_bound());
268+
std::string user_gap = user_mip_gap<f_t>(user_obj, user_lower);
269+
270+
settings_.log.printf(
271+
"H %+13.6e %+10.6e %s %9.2f\n",
272+
user_obj,
273+
user_lower,
274+
user_gap.c_str(),
275+
toc(exploration_stats_.start_time));
276+
} else {
277+
settings_.log.printf("New solution from primal heuristics. Objective %+.6e. Time %.2f\n",
278+
compute_user_objective(original_lp_, obj),
279+
toc(exploration_stats_.start_time));
280+
}
281+
}
282+
283+
template <typename i_t, typename f_t>
284+
void branch_and_bound_t<i_t, f_t>::report(std::string symbol,
285+
f_t obj,
286+
f_t lower_bound,
287+
i_t node_depth)
288+
{
289+
i_t nodes_explored = exploration_stats_.nodes_explored;
290+
i_t nodes_unexplored = exploration_stats_.nodes_unexplored;
291+
f_t user_obj = compute_user_objective(original_lp_, obj);
292+
f_t user_lower = compute_user_objective(original_lp_, lower_bound);
293+
f_t iter_node = exploration_stats_.total_lp_iters / nodes_explored;
294+
std::string user_gap = user_mip_gap<f_t>(user_obj, user_lower);
295+
settings_.log.printf("%s%10d %10lu %+13.6e %+10.6e %6d %7.1e %s %9.2f\n",
296+
symbol.c_str(),
297+
nodes_explored,
298+
nodes_unexplored,
299+
user_obj,
300+
user_lower,
301+
node_depth,
302+
iter_node,
303+
user_gap.c_str(),
304+
toc(exploration_stats_.start_time));
305+
}
306+
307+
template <typename i_t, typename f_t>
308+
void branch_and_bound_t<i_t, f_t>::report_heuristic(f_t obj)
309+
{
310+
if (solver_status_ == mip_exploration_status_t::RUNNING) {
311+
f_t user_obj = compute_user_objective(original_lp_, obj);
312+
f_t user_lower = compute_user_objective(original_lp_, get_lower_bound());
313+
std::string user_gap = user_mip_gap<f_t>(user_obj, user_lower);
314+
315+
settings_.log.printf(
316+
"H %+13.6e %+10.6e %s %9.2f\n",
317+
user_obj,
318+
user_lower,
319+
user_gap.c_str(),
320+
toc(exploration_stats_.start_time));
321+
} else {
322+
settings_.log.printf("New solution from primal heuristics. Objective %+.6e. Time %.2f\n",
323+
compute_user_objective(original_lp_, obj),
324+
toc(exploration_stats_.start_time));
325+
}
326+
}
327+
328+
template <typename i_t, typename f_t>
329+
void branch_and_bound_t<i_t, f_t>::report(std::string symbol,
330+
f_t obj,
331+
f_t lower_bound,
332+
i_t node_depth)
333+
{
334+
i_t nodes_explored = exploration_stats_.nodes_explored;
335+
i_t nodes_unexplored = exploration_stats_.nodes_unexplored;
336+
f_t user_obj = compute_user_objective(original_lp_, obj);
337+
f_t user_lower = compute_user_objective(original_lp_, lower_bound);
338+
f_t iter_node = exploration_stats_.total_lp_iters / nodes_explored;
339+
std::string user_gap = user_mip_gap<f_t>(user_obj, user_lower);
340+
settings_.log.printf("%s%10d %10lu %+13.6e %+10.6e %6d %7.1e %s %9.2f\n",
341+
symbol.c_str(),
342+
nodes_explored,
343+
nodes_unexplored,
344+
user_obj,
345+
user_lower,
346+
node_depth,
347+
iter_node,
348+
user_gap.c_str(),
349+
toc(exploration_stats_.start_time));
350+
}
351+
262352
template <typename i_t, typename f_t>
263353
void branch_and_bound_t<i_t, f_t>::set_new_solution(const std::vector<f_t>& solution)
264354
{
@@ -297,25 +387,7 @@ void branch_and_bound_t<i_t, f_t>::set_new_solution(const std::vector<f_t>& solu
297387
}
298388
mutex_upper_.unlock();
299389

300-
if (is_feasible) {
301-
if (solver_status_ == mip_exploration_status_t::RUNNING) {
302-
f_t user_obj = compute_user_objective(original_lp_, obj);
303-
f_t user_lower = compute_user_objective(original_lp_, get_lower_bound());
304-
std::string gap = user_mip_gap<f_t>(user_obj, user_lower);
305-
306-
settings_.log.printf(
307-
"H %+13.6e %+10.6e %s %9.2f\n",
308-
user_obj,
309-
user_lower,
310-
gap.c_str(),
311-
toc(exploration_stats_.start_time));
312-
} else {
313-
settings_.log.printf("New solution from primal heuristics. Objective %+.6e. Time %.2f\n",
314-
compute_user_objective(original_lp_, obj),
315-
toc(exploration_stats_.start_time));
316-
}
317-
}
318-
390+
if (is_feasible) { report_heuristic(obj); }
319391
if (attempt_repair) {
320392
mutex_repair_.lock();
321393
repair_queue_.push_back(crushed_solution);
@@ -411,17 +483,7 @@ void branch_and_bound_t<i_t, f_t>::repair_heuristic_solutions()
411483
if (repaired_obj < upper_bound_) {
412484
upper_bound_ = repaired_obj;
413485
incumbent_.set_incumbent_solution(repaired_obj, repaired_solution);
414-
415-
f_t obj = compute_user_objective(original_lp_, repaired_obj);
416-
f_t lower = compute_user_objective(original_lp_, get_lower_bound());
417-
std::string user_gap = user_mip_gap<f_t>(obj, lower);
418-
419-
settings_.log.printf(
420-
"H %+13.6e %+10.6e %s %9.2f\n",
421-
obj,
422-
lower,
423-
user_gap.c_str(),
424-
toc(exploration_stats_.start_time));
486+
report_heuristic(repaired_obj);
425487

426488
if (settings_.solution_callback != nullptr) {
427489
std::vector<f_t> original_x;
@@ -517,9 +579,7 @@ void branch_and_bound_t<i_t, f_t>::add_feasible_solution(f_t leaf_objective,
517579
i_t leaf_depth,
518580
bnb_thread_type_t thread_type)
519581
{
520-
bool send_solution = false;
521-
i_t nodes_explored = exploration_stats_.nodes_explored;
522-
i_t nodes_unexplored = exploration_stats_.nodes_unexplored;
582+
bool send_solution = false;
523583

524584
settings_.log.debug("%s found a feasible solution with obj=%.10e.\n",
525585
feasible_solution_symbol(thread_type),
@@ -528,24 +588,8 @@ void branch_and_bound_t<i_t, f_t>::add_feasible_solution(f_t leaf_objective,
528588
mutex_upper_.lock();
529589
if (leaf_objective < upper_bound_) {
530590
incumbent_.set_incumbent_solution(leaf_objective, leaf_solution);
531-
upper_bound_ = leaf_objective;
532-
f_t lower_bound = get_lower_bound();
533-
f_t obj = compute_user_objective(original_lp_, upper_bound_);
534-
f_t lower = compute_user_objective(original_lp_, lower_bound);
535-
f_t iter_node = nodes_explored > 0 ? static_cast<f_t>(exploration_stats_.total_lp_iters) /
536-
static_cast<f_t>(nodes_explored)
537-
: 0;
538-
settings_.log.printf("%s%10d %10lu %+13.6e %+10.6e %6d %7.1e %s %9.2f\n",
539-
feasible_solution_symbol(thread_type),
540-
nodes_explored,
541-
nodes_unexplored,
542-
obj,
543-
lower,
544-
leaf_depth,
545-
iter_node,
546-
user_mip_gap<f_t>(obj, lower).c_str(),
547-
toc(exploration_stats_.start_time));
548-
591+
upper_bound_ = leaf_objective;
592+
report(feasible_solution_symbol(thread_type), leaf_objective, get_lower_bound(), leaf_depth);
549593
send_solution = true;
550594
}
551595

@@ -868,25 +912,7 @@ void branch_and_bound_t<i_t, f_t>::exploration_ramp_up(mip_node_t<i_t, f_t>* nod
868912
bool should_report = should_report_.exchange(false);
869913

870914
if (should_report) {
871-
f_t obj = compute_user_objective(original_lp_, upper_bound);
872-
f_t user_lower = compute_user_objective(original_lp_, root_objective_);
873-
std::string gap_user = user_mip_gap<f_t>(obj, user_lower);
874-
i_t nodes_explored = exploration_stats_.nodes_explored;
875-
i_t nodes_unexplored = exploration_stats_.nodes_unexplored;
876-
f_t iter_node = nodes_explored > 0 ? static_cast<f_t>(exploration_stats_.total_lp_iters) /
877-
static_cast<f_t>(nodes_explored)
878-
: 0;
879-
880-
settings_.log.printf(" %10d %10lu %+13.6e %+10.6e %6d %7.1e %s %9.2f\n",
881-
nodes_explored,
882-
nodes_unexplored,
883-
obj,
884-
user_lower,
885-
node->depth,
886-
iter_node,
887-
gap_user.c_str(),
888-
now);
889-
915+
report(" ", upper_bound, root_objective_, node->depth);
890916
exploration_stats_.nodes_since_last_log = 0;
891917
exploration_stats_.last_log = tic();
892918
should_report_ = true;
@@ -1001,24 +1027,7 @@ void branch_and_bound_t<i_t, f_t>::plunge_from(i_t task_id,
10011027
abs_gap < 10 * settings_.absolute_mip_gap_tol) &&
10021028
time_since_last_log >= 1) ||
10031029
(time_since_last_log > 30) || now > settings_.time_limit) {
1004-
f_t obj = compute_user_objective(original_lp_, upper_bound);
1005-
f_t user_lower = compute_user_objective(original_lp_, get_lower_bound());
1006-
std::string gap_user = user_mip_gap<f_t>(obj, user_lower);
1007-
i_t nodes_explored = exploration_stats_.nodes_explored;
1008-
i_t nodes_unexplored = exploration_stats_.nodes_unexplored;
1009-
f_t iter_node = nodes_explored > 0 ? static_cast<f_t>(exploration_stats_.total_lp_iters) /
1010-
static_cast<f_t>(nodes_explored)
1011-
: 0;
1012-
1013-
settings_.log.printf(" %10d %10lu %+13.6e %+10.6e %6d %7.1e %s %9.2f\n",
1014-
nodes_explored,
1015-
nodes_unexplored,
1016-
obj,
1017-
user_lower,
1018-
node_ptr->depth,
1019-
iter_node,
1020-
gap_user.c_str(),
1021-
now);
1030+
report(" ", upper_bound, get_lower_bound(), node_ptr->depth);
10221031
exploration_stats_.last_log = tic();
10231032
exploration_stats_.nodes_since_last_log = 0;
10241033
}
@@ -1535,7 +1544,7 @@ mip_status_t branch_and_bound_t<i_t, f_t>::solve(mip_solution_t<i_t, f_t>& solut
15351544
" | Explored | Unexplored | Objective | Bound | Depth | Iter/Node | Gap "
15361545
"| Time |\n");
15371546

1538-
exploration_stats_.nodes_explored = 0;
1547+
exploration_stats_.nodes_explored = 1;
15391548
exploration_stats_.nodes_unexplored = 2;
15401549
exploration_stats_.nodes_since_last_log = 0;
15411550
exploration_stats_.last_log = tic();

cpp/src/dual_simplex/branch_and_bound.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ class branch_and_bound_t {
197197
// its blocks the progression of the lower bound.
198198
omp_atomic_t<f_t> lower_bound_ceiling_;
199199

200+
void report_heuristic(f_t obj);
201+
void report(std::string symbol, f_t obj, f_t lower_bound, i_t node_depth);
202+
200203
// Set the final solution.
201204
mip_status_t set_final_solution(mip_solution_t<i_t, f_t>& solution, f_t lower_bound);
202205

0 commit comments

Comments
 (0)