@@ -387,34 +387,44 @@ void assessExcessiveBoundCost(const HighsLogOptions log_options,
387387 }
388388 }
389389 double min_col_cost =
390- std::min (min_continuous_col_cost, min_noncontinuous_col_cost);
390+ std::min (min_continuous_col_cost, min_noncontinuous_col_cost);
391391 double max_col_cost =
392- std::max (max_continuous_col_cost, max_noncontinuous_col_cost);
392+ std::max (max_continuous_col_cost, max_noncontinuous_col_cost);
393393 double min_col_bound =
394- std::min (min_continuous_col_bound, min_noncontinuous_col_bound);
394+ std::min (min_continuous_col_bound, min_noncontinuous_col_bound);
395395 double max_col_bound =
396- std::max (max_continuous_col_bound, max_noncontinuous_col_bound);
397- if (min_col_cost == kHighsInf ) min_col_cost = 0 ;
398- if (max_col_cost == -kHighsInf ) max_col_cost = 0 ;
399- if (min_col_bound == kHighsInf ) min_col_bound = 0 ;
400- if (max_col_bound == -kHighsInf ) max_col_bound = 0 ;
401-
396+ std::max (max_continuous_col_bound, max_noncontinuous_col_bound);
397+
402398 double min_matrix_value = kHighsInf ;
403399 double max_matrix_value = -kHighsInf ;
404400 const HighsInt num_nz = lp.a_matrix_ .numNz ();
405401 for (HighsInt iEl = 0 ; iEl < num_nz; iEl++)
406402 assessFiniteNonzero (lp.a_matrix_ .value_ [iEl], min_matrix_value,
407403 max_matrix_value);
408-
404+
409405 double min_row_bound = kHighsInf ;
410406 double max_row_bound = -kHighsInf ;
411407 for (HighsInt iRow = 0 ; iRow < lp.num_row_ ; iRow++) {
412408 assessFiniteNonzero (lp.row_lower_ [iRow], min_row_bound, max_row_bound);
413409 assessFiniteNonzero (lp.row_upper_ [iRow], min_row_bound, max_row_bound);
414410 }
411+
412+ // Determine the minimum and maximum overall bounds that can be
413+ // scaled with user_bound_scale before zeroing extrema due to
414+ // absence of finite nonzero bounds
415+
416+ double min_scalable_bound = std::min (min_continuous_col_bound, min_row_bound);
417+ double max_scalable_bound = std::max (max_continuous_col_bound, max_row_bound);
418+ if (min_scalable_bound == kHighsInf ) min_scalable_bound = 0 ;
419+ if (max_scalable_bound == -kHighsInf ) max_scalable_bound = 0 ;
420+
421+ if (min_col_cost == kHighsInf ) min_col_cost = 0 ;
422+ if (max_col_cost == -kHighsInf ) max_col_cost = 0 ;
423+ if (min_col_bound == kHighsInf ) min_col_bound = 0 ;
424+ if (max_col_bound == -kHighsInf ) max_col_bound = 0 ;
415425 if (min_row_bound == kHighsInf ) min_row_bound = 0 ;
416426 if (max_row_bound == -kHighsInf ) max_row_bound = 0 ;
417-
427+
418428 // Report on the coefficient ranges
419429 highsLogUser (log_options, HighsLogType::kInfo , " Coefficient ranges:\n " );
420430 if (num_nz)
@@ -429,15 +439,43 @@ void assessExcessiveBoundCost(const HighsLogOptions log_options,
429439 if (lp.num_row_ )
430440 highsLogUser (log_options, HighsLogType::kInfo , " RHS [%5.0e, %5.0e]\n " ,
431441 min_row_bound, max_row_bound);
432-
442+
443+ // Determine recommended user scaling values
444+ HighsInt recommend_user_bound_scale_setting = 0 ;
445+ HighsInt recommend_user_cost_scale_setting = 0 ;
446+ double ratio = 1 ;
447+ if (min_scalable_bound > kExcessivelyLargeBoundValue ) {
448+ // All scalable bounds are excessively large, so obviously suggest
449+ // scaling them down
450+ ratio = kExcessivelyLargeBoundValue / min_scalable_bound;
451+ } else if (0 < max_scalable_bound && max_scalable_bound < kExcessivelySmallBoundValue ) {
452+ // All scalable bounds are excessively small, so obviously suggest
453+ // scaling them up
454+ ratio = kExcessivelySmallBoundValue / min_scalable_bound;
455+ } else {
456+ if (max_scalable_bound > kExcessivelyLargeBoundValue ) {
457+ // Max bound is excessively large, so look to scale it down
458+ ratio = kExcessivelyLargeBoundValue / max_scalable_bound;
459+ if (0 < min_scalable_bound && min_scalable_bound < kExcessivelySmallBoundValue ) {
460+ // Min nonzero bound is excessively small: look for balance
461+
462+ } else {
463+ // Ensure that scaling down large bounds doesn't lead to min
464+ // bound being too small
465+ }
466+ } else if (0 < min_scalable_bound && min_scalable_bound < kExcessivelySmallBoundValue ) {
467+ // Min bound is excessively small, so look to scale it up,
468+ // ensuring that it doesn't lead to max bounds being too large
469+ }
470+ }
433471 const double user_cost_scale_value =
434- std::pow (2 , user_scale_data.user_cost_scale );
472+ std::pow (2 , user_scale_data.user_cost_scale );
435473 const double user_bound_scale_value =
436- std::pow (2 , user_scale_data.user_bound_scale );
474+ std::pow (2 , user_scale_data.user_bound_scale );
437475 const std::string problem =
438- (user_scale_data.user_cost_scale || user_scale_data.user_bound_scale )
439- ? " User-scaled problem"
440- : " Problem" ;
476+ (user_scale_data.user_cost_scale || user_scale_data.user_bound_scale )
477+ ? " User-scaled problem"
478+ : " Problem" ;
441479 // LPs with no columns or no finite nonzero costs will have
442480 // max_col_cost = 0
443481 assert (max_col_cost >= 0 );
@@ -447,121 +485,121 @@ void assessExcessiveBoundCost(const HighsLogOptions log_options,
447485 // LPs with no rows or no finite nonzero bounds will have
448486 // max_row_bound = 0
449487 assert (max_row_bound >= 0 );
450-
488+
451489 if (max_col_cost > kExcessivelyLargeCostValue ) {
452490 // Warn that costs are excessively large, and suggest scaling
453491 double ratio =
454- kExcessivelyLargeCostValue / (max_col_cost / user_cost_scale_value);
492+ kExcessivelyLargeCostValue / (max_col_cost / user_cost_scale_value);
455493 HighsInt suggested_user_cost_scale_setting = std::floor (std::log2 (ratio));
456494 HighsInt suggested_cost_scale_exponent = std::floor (std::log10 (ratio));
457495 highsLogUser (
458- log_options, HighsLogType::kWarning ,
459- " %s has excessively large costs: consider scaling the costs "
460- " by 1e%+1d or less, or setting option user_cost_scale to %d or less\n " ,
461- problem.c_str (), int (-suggested_cost_scale_exponent),
462- int (suggested_user_cost_scale_setting));
496+ log_options, HighsLogType::kWarning ,
497+ " %s has excessively large costs: consider scaling the costs "
498+ " by 1e%+1d or less, or setting option user_cost_scale to %d or less\n " ,
499+ problem.c_str (), int (-suggested_cost_scale_exponent),
500+ int (suggested_user_cost_scale_setting));
463501 }
464502 if (max_col_bound > kExcessivelyLargeBoundValue ) {
465503 // Warn that bounds are excessively large, and suggest scaling
466504 double ratio =
467- kExcessivelyLargeBoundValue / (max_col_bound / user_bound_scale_value);
505+ kExcessivelyLargeBoundValue / (max_col_bound / user_bound_scale_value);
468506 HighsInt suggested_user_bound_scale = std::floor (std::log2 (ratio));
469507 HighsInt suggested_bound_scale_exponent = std::floor (std::log10 (ratio));
470508 if (lp.isMip ()) {
471509 highsLogUser (
472- log_options, HighsLogType::kWarning ,
473- " %s has excessively large bounds: consider scaling the bounds "
474- " by 1e%+1d or less\n " ,
475- problem.c_str (), int (-suggested_bound_scale_exponent));
510+ log_options, HighsLogType::kWarning ,
511+ " %s has excessively large bounds: consider scaling the bounds "
512+ " by 1e%+1d or less\n " ,
513+ problem.c_str (), int (-suggested_bound_scale_exponent));
476514 } else {
477515 highsLogUser (
478- log_options, HighsLogType::kWarning ,
479- " %s has excessively large bounds: consider scaling the bounds "
480- " by 1e%+1d or less, "
481- " or setting option user_bound_scale to %d or less\n " ,
482- problem.c_str (), int (-suggested_bound_scale_exponent),
483- int (suggested_user_bound_scale));
516+ log_options, HighsLogType::kWarning ,
517+ " %s has excessively large bounds: consider scaling the bounds "
518+ " by 1e%+1d or less, "
519+ " or setting option user_bound_scale to %d or less\n " ,
520+ problem.c_str (), int (-suggested_bound_scale_exponent),
521+ int (suggested_user_bound_scale));
484522 }
485523 }
486524 if (max_row_bound > kExcessivelyLargeBoundValue ) {
487525 // Warn that bounds are excessively large, and suggest scaling
488526 double ratio =
489- kExcessivelyLargeBoundValue / (max_row_bound / user_bound_scale_value);
527+ kExcessivelyLargeBoundValue / (max_row_bound / user_bound_scale_value);
490528 HighsInt suggested_user_bound_scale = std::floor (std::log2 (ratio));
491529 HighsInt suggested_bound_scale_exponent = std::floor (std::log10 (ratio));
492530 if (lp.isMip ()) {
493531 highsLogUser (
494- log_options, HighsLogType::kWarning ,
495- " %s has excessively large bounds: consider scaling the bounds "
496- " by 1e%+1d or less\n " ,
497- problem.c_str (), int (-suggested_bound_scale_exponent));
532+ log_options, HighsLogType::kWarning ,
533+ " %s has excessively large bounds: consider scaling the bounds "
534+ " by 1e%+1d or less\n " ,
535+ problem.c_str (), int (-suggested_bound_scale_exponent));
498536 } else {
499537 highsLogUser (
500- log_options, HighsLogType::kWarning ,
501- " %s has excessively large bounds: consider scaling the bounds "
502- " by 1e%+1d or less, "
503- " or setting option user_bound_scale to %d or less\n " ,
504- problem.c_str (), int (-suggested_bound_scale_exponent),
505- int (suggested_user_bound_scale));
538+ log_options, HighsLogType::kWarning ,
539+ " %s has excessively large bounds: consider scaling the bounds "
540+ " by 1e%+1d or less, "
541+ " or setting option user_bound_scale to %d or less\n " ,
542+ problem.c_str (), int (-suggested_bound_scale_exponent),
543+ int (suggested_user_bound_scale));
506544 }
507545 }
508546 // Now consider warning relating to small maximum costs and bounds
509547 if (max_col_cost > 0 && max_col_cost < kExcessivelySmallCostValue ) {
510548 // Warn that costs are excessively small, and suggest scaling
511549 double ratio =
512- kExcessivelySmallCostValue / (max_col_cost / user_cost_scale_value);
550+ kExcessivelySmallCostValue / (max_col_cost / user_cost_scale_value);
513551 HighsInt suggested_user_cost_scale_setting = std::ceil (std::log2 (ratio));
514552 HighsInt suggested_cost_scale_exponent = std::ceil (std::log10 (ratio));
515553 highsLogUser (
516- log_options, HighsLogType::kWarning ,
517- " %s has excessively small costs: consider scaling the costs up "
518- " by 1e%+1d or more, "
519- " or setting option user_cost_scale to %d or more\n " ,
520- problem.c_str (), int (suggested_cost_scale_exponent),
521- int (suggested_user_cost_scale_setting));
554+ log_options, HighsLogType::kWarning ,
555+ " %s has excessively small costs: consider scaling the costs up "
556+ " by 1e%+1d or more, "
557+ " or setting option user_cost_scale to %d or more\n " ,
558+ problem.c_str (), int (suggested_cost_scale_exponent),
559+ int (suggested_user_cost_scale_setting));
522560 }
523561 if (max_col_bound > 0 && max_col_bound < kExcessivelySmallBoundValue ) {
524562 // Warn that bounds are excessively small, and suggest scaling
525563 double ratio =
526- kExcessivelySmallBoundValue / (max_col_bound / user_bound_scale_value);
564+ kExcessivelySmallBoundValue / (max_col_bound / user_bound_scale_value);
527565 HighsInt suggested_user_bound_scale = std::ceil (std::log2 (ratio));
528566 HighsInt suggested_bound_scale_exponent = std::ceil (std::log10 (ratio));
529567 if (lp.isMip ()) {
530568 highsLogUser (
531- log_options, HighsLogType::kWarning ,
532- " %s has excessively small bounds: consider scaling the bounds "
533- " by 1e%+1d or more\n " ,
534- problem.c_str (), int (suggested_bound_scale_exponent));
569+ log_options, HighsLogType::kWarning ,
570+ " %s has excessively small bounds: consider scaling the bounds "
571+ " by 1e%+1d or more\n " ,
572+ problem.c_str (), int (suggested_bound_scale_exponent));
535573 } else {
536574 highsLogUser (
537- log_options, HighsLogType::kWarning ,
538- " %s has excessively small bounds: consider scaling the bounds "
539- " by 1e%+1d or more, "
540- " or setting option user_bound_scale to %d or more\n " ,
541- problem.c_str (), int (suggested_bound_scale_exponent),
542- int (suggested_user_bound_scale));
575+ log_options, HighsLogType::kWarning ,
576+ " %s has excessively small bounds: consider scaling the bounds "
577+ " by 1e%+1d or more, "
578+ " or setting option user_bound_scale to %d or more\n " ,
579+ problem.c_str (), int (suggested_bound_scale_exponent),
580+ int (suggested_user_bound_scale));
543581 }
544582 }
545583 if (max_row_bound > 0 && max_row_bound < kExcessivelySmallBoundValue ) {
546584 // Warn that bounds are excessively small, and suggest scaling
547585 double ratio =
548- kExcessivelySmallBoundValue / (max_row_bound / user_bound_scale_value);
586+ kExcessivelySmallBoundValue / (max_row_bound / user_bound_scale_value);
549587 HighsInt suggested_user_bound_scale = std::ceil (std::log2 (ratio));
550588 HighsInt suggested_bound_scale_exponent = std::ceil (std::log10 (ratio));
551589 if (lp.isMip ()) {
552590 highsLogUser (
553- log_options, HighsLogType::kWarning ,
554- " %s has excessively small bounds: consider scaling the bounds "
555- " by 1e%+1d or more\n " ,
556- problem.c_str (), int (suggested_bound_scale_exponent));
591+ log_options, HighsLogType::kWarning ,
592+ " %s has excessively small bounds: consider scaling the bounds "
593+ " by 1e%+1d or more\n " ,
594+ problem.c_str (), int (suggested_bound_scale_exponent));
557595 } else {
558596 highsLogUser (
559- log_options, HighsLogType::kWarning ,
560- " %s has excessively small bounds: consider scaling the bounds "
561- " by 1e%+1d or more, "
562- " or setting option user_bound_scale to %d or more\n " ,
563- problem.c_str (), int (suggested_bound_scale_exponent),
564- int (suggested_user_bound_scale));
597+ log_options, HighsLogType::kWarning ,
598+ " %s has excessively small bounds: consider scaling the bounds "
599+ " by 1e%+1d or more, "
600+ " or setting option user_bound_scale to %d or more\n " ,
601+ problem.c_str (), int (suggested_bound_scale_exponent),
602+ int (suggested_user_bound_scale));
565603 }
566604 }
567605}
0 commit comments