@@ -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+
262352template <typename i_t , typename f_t >
263353void 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 ();
0 commit comments