@@ -341,8 +341,12 @@ HighsStatus solveUnconstrainedLp(const HighsOptions& options, const HighsLp& lp,
341341 return HighsStatus::kOk ;
342342}
343343
344- void assessExcessiveBoundCost (const HighsOptions options,
345- const HighsModel& model) {
344+ // Assuming that any user scaling in user_scale_data has been applied,
345+ // determine the model coefficient ranges, assess it for excessive
346+ // values, and give scaling recommendations, when appropriate
347+ void assessExcessiveBoundCost (const HighsLogOptions log_options,
348+ const HighsModel& model,
349+ const HighsUserScaleData& user_scale_data) {
346350 auto assessFiniteNonzero = [&](const double value, double & min_value,
347351 double & max_value) {
348352 double abs_value = std::abs (value);
@@ -352,203 +356,212 @@ void assessExcessiveBoundCost(const HighsOptions options,
352356 }
353357 };
354358 const HighsLp& lp = model.lp_ ;
355- const HighsLogOptions& log_options = options.log_options ;
356- double min_finite_col_cost = kHighsInf ;
357- double max_finite_col_cost = -kHighsInf ;
358- double min_finite_col_bound = kHighsInf ;
359- double max_finite_col_bound = -kHighsInf ;
360- double min_matrix_value = kHighsInf ;
361- double max_matrix_value = -kHighsInf ;
359+ double min_continuous_col_cost = kHighsInf ;
360+ double min_noncontinuous_col_cost = kHighsInf ;
361+ double max_continuous_col_cost = -kHighsInf ;
362+ double max_noncontinuous_col_cost = -kHighsInf ;
363+ double min_continuous_col_bound = kHighsInf ;
364+ double min_noncontinuous_col_bound = kHighsInf ;
365+ double max_continuous_col_bound = -kHighsInf ;
366+ double max_noncontinuous_col_bound = -kHighsInf ;
367+ double min_continuous_matrix_value = kHighsInf ;
368+ double min_noncontinuous_matrix_value = kHighsInf ;
369+ double max_continuous_matrix_value = -kHighsInf ;
370+ double max_noncontinuous_matrix_value = -kHighsInf ;
371+ const bool is_mip = lp.integrality_ .size ();
362372 for (HighsInt iCol = 0 ; iCol < lp.num_col_ ; iCol++) {
363- assessFiniteNonzero (lp.col_cost_ [iCol], min_finite_col_cost,
364- max_finite_col_cost);
365- assessFiniteNonzero (lp.col_lower_ [iCol], min_finite_col_bound,
366- max_finite_col_bound);
367- assessFiniteNonzero (lp.col_upper_ [iCol], min_finite_col_bound,
368- max_finite_col_bound);
373+ if (is_mip && lp.integrality_ [iCol] != HighsVarType::kContinuous ) {
374+ assessFiniteNonzero (lp.col_cost_ [iCol], min_noncontinuous_col_cost,
375+ max_noncontinuous_col_cost);
376+ assessFiniteNonzero (lp.col_lower_ [iCol], min_noncontinuous_col_bound,
377+ max_noncontinuous_col_bound);
378+ assessFiniteNonzero (lp.col_upper_ [iCol], min_noncontinuous_col_bound,
379+ max_noncontinuous_col_bound);
380+ } else {
381+ assessFiniteNonzero (lp.col_cost_ [iCol], min_continuous_col_cost,
382+ max_continuous_col_cost);
383+ assessFiniteNonzero (lp.col_lower_ [iCol], min_continuous_col_bound,
384+ max_continuous_col_bound);
385+ assessFiniteNonzero (lp.col_upper_ [iCol], min_continuous_col_bound,
386+ max_continuous_col_bound);
387+ }
369388 }
370- /*
371- double min_finite_col_cost = kHighsInf;
372- double max_finite_col_cost = -kHighsInf;
373- double min_finite_col_bound = kHighsInf;
374- double max_finite_col_bound = -kHighsInf;
389+ double min_col_cost =
390+ std::min (min_continuous_col_cost, min_noncontinuous_col_cost);
391+ double max_col_cost =
392+ std::max (max_continuous_col_cost, max_noncontinuous_col_cost);
393+ double min_col_bound =
394+ std::min (min_continuous_col_bound, min_noncontinuous_col_bound);
395+ 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+
375402 double min_matrix_value = kHighsInf ;
376403 double max_matrix_value = -kHighsInf ;
377- */
378- if (min_finite_col_cost == kHighsInf ) min_finite_col_cost = 0 ;
379- if (max_finite_col_cost == -kHighsInf ) max_finite_col_cost = 0 ;
380- if (min_finite_col_bound == kHighsInf ) min_finite_col_bound = 0 ;
381- if (max_finite_col_bound == -kHighsInf ) max_finite_col_bound = 0 ;
382- HighsInt num_nz = lp.a_matrix_ .numNz ();
404+ const HighsInt num_nz = lp.a_matrix_ .numNz ();
383405 for (HighsInt iEl = 0 ; iEl < num_nz; iEl++)
384406 assessFiniteNonzero (lp.a_matrix_ .value_ [iEl], min_matrix_value,
385407 max_matrix_value);
386408
387- double min_finite_row_bound = kHighsInf ;
388- double max_finite_row_bound = -kHighsInf ;
409+ double min_row_bound = kHighsInf ;
410+ double max_row_bound = -kHighsInf ;
389411 for (HighsInt iRow = 0 ; iRow < lp.num_row_ ; iRow++) {
390- assessFiniteNonzero (lp.row_lower_ [iRow], min_finite_row_bound,
391- max_finite_row_bound);
392- assessFiniteNonzero (lp.row_upper_ [iRow], min_finite_row_bound,
393- max_finite_row_bound);
412+ assessFiniteNonzero (lp.row_lower_ [iRow], min_row_bound, max_row_bound);
413+ assessFiniteNonzero (lp.row_upper_ [iRow], min_row_bound, max_row_bound);
394414 }
395- if (min_finite_row_bound == kHighsInf ) min_finite_row_bound = 0 ;
396- if (max_finite_row_bound == -kHighsInf ) max_finite_row_bound = 0 ;
415+ if (min_row_bound == kHighsInf ) min_row_bound = 0 ;
416+ if (max_row_bound == -kHighsInf ) max_row_bound = 0 ;
397417
418+ // Report on the coefficient ranges
398419 highsLogUser (log_options, HighsLogType::kInfo , " Coefficient ranges:\n " );
399420 if (num_nz)
400421 highsLogUser (log_options, HighsLogType::kInfo , " Matrix [%5.0e, %5.0e]\n " ,
401422 min_matrix_value, max_matrix_value);
402423 if (lp.num_col_ ) {
403424 highsLogUser (log_options, HighsLogType::kInfo , " Cost [%5.0e, %5.0e]\n " ,
404- min_finite_col_cost, max_finite_col_cost );
425+ min_col_cost, max_col_cost );
405426 highsLogUser (log_options, HighsLogType::kInfo , " Bound [%5.0e, %5.0e]\n " ,
406- min_finite_col_bound, max_finite_col_bound );
427+ min_col_bound, max_col_bound );
407428 }
408429 if (lp.num_row_ )
409430 highsLogUser (log_options, HighsLogType::kInfo , " RHS [%5.0e, %5.0e]\n " ,
410- min_finite_row_bound, max_finite_row_bound );
431+ min_row_bound, max_row_bound );
411432
433+ const double user_cost_scale_value =
434+ std::pow (2 , user_scale_data.user_cost_scale );
435+ const double user_bound_scale_value =
436+ std::pow (2 , user_scale_data.user_bound_scale );
437+ const std::string problem =
438+ (user_scale_data.user_cost_scale || user_scale_data.user_bound_scale )
439+ ? " User-scaled problem"
440+ : " Problem" ;
412441 // LPs with no columns or no finite nonzero costs will have
413- // max_finite_col_cost = 0
414- assert (max_finite_col_cost >= 0 );
415- if (max_finite_col_cost > kExcessivelyLargeCostValue ) {
416- double user_cost_scale_value = std::pow (2 , options.user_cost_scale );
442+ // max_col_cost = 0
443+ assert (max_col_cost >= 0 );
444+ // LPs with no columns or no finite nonzero bounds will have
445+ // max_col_bound = 0
446+ assert (max_col_bound >= 0 );
447+ // LPs with no rows or no finite nonzero bounds will have
448+ // max_row_bound = 0
449+ assert (max_row_bound >= 0 );
450+
451+ if (max_col_cost > kExcessivelyLargeCostValue ) {
417452 // Warn that costs are excessively large, and suggest scaling
418- double ratio = kExcessivelyLargeCostValue /
419- (max_finite_col_cost / user_cost_scale_value);
453+ double ratio =
454+ kExcessivelyLargeCostValue / (max_col_cost / user_cost_scale_value);
420455 HighsInt suggested_user_cost_scale_setting = std::floor (std::log2 (ratio));
421456 HighsInt suggested_cost_scale_exponent = std::floor (std::log10 (ratio));
422457 highsLogUser (
423458 log_options, HighsLogType::kWarning ,
424459 " %s has excessively large costs: consider scaling the costs "
425460 " by 1e%+1d or less, or setting option user_cost_scale to %d or less\n " ,
426- options.user_cost_scale ? " User-scaled problem" : " Problem" ,
427- int (-suggested_cost_scale_exponent),
461+ problem.c_str (), int (-suggested_cost_scale_exponent),
428462 int (suggested_user_cost_scale_setting));
429463 }
430- // LPs with no columns or no finite nonzero bounds will have
431- // max_finite_col_bound = 0
432- assert (max_finite_col_bound >= 0 );
433- if (max_finite_col_bound > kExcessivelyLargeBoundValue ) {
434- double user_bound_scale_value = std::pow (2 , options.user_bound_scale );
464+ if (max_col_bound > kExcessivelyLargeBoundValue ) {
435465 // Warn that bounds are excessively large, and suggest scaling
436- double ratio = kExcessivelyLargeBoundValue /
437- (max_finite_col_bound / user_bound_scale_value);
466+ double ratio =
467+ kExcessivelyLargeBoundValue / (max_col_bound / user_bound_scale_value);
438468 HighsInt suggested_user_bound_scale = std::floor (std::log2 (ratio));
439469 HighsInt suggested_bound_scale_exponent = std::floor (std::log10 (ratio));
440470 if (lp.isMip ()) {
441471 highsLogUser (
442472 log_options, HighsLogType::kWarning ,
443473 " %s has excessively large bounds: consider scaling the bounds "
444474 " by 1e%+1d or less\n " ,
445- options.user_bound_scale ? " User-scaled problem" : " Problem" ,
446- int (-suggested_bound_scale_exponent));
475+ problem.c_str (), int (-suggested_bound_scale_exponent));
447476 } else {
448477 highsLogUser (
449478 log_options, HighsLogType::kWarning ,
450479 " %s has excessively large bounds: consider scaling the bounds "
451480 " by 1e%+1d or less, "
452481 " or setting option user_bound_scale to %d or less\n " ,
453- options.user_bound_scale ? " User-scaled problem" : " Problem" ,
454- int (-suggested_bound_scale_exponent),
482+ problem.c_str (), int (-suggested_bound_scale_exponent),
455483 int (suggested_user_bound_scale));
456484 }
457485 }
458- // LPs with no rows or no finite nonzero bounds will have
459- // max_finite_row_bound = 0
460- assert (max_finite_row_bound >= 0 );
461- if (max_finite_row_bound > kExcessivelyLargeBoundValue ) {
462- double user_bound_scale_value = std::pow (2 , options.user_bound_scale );
486+ if (max_row_bound > kExcessivelyLargeBoundValue ) {
463487 // Warn that bounds are excessively large, and suggest scaling
464- double ratio = kExcessivelyLargeBoundValue /
465- (max_finite_row_bound / user_bound_scale_value);
488+ double ratio =
489+ kExcessivelyLargeBoundValue / (max_row_bound / user_bound_scale_value);
466490 HighsInt suggested_user_bound_scale = std::floor (std::log2 (ratio));
467491 HighsInt suggested_bound_scale_exponent = std::floor (std::log10 (ratio));
468492 if (lp.isMip ()) {
469493 highsLogUser (
470494 log_options, HighsLogType::kWarning ,
471495 " %s has excessively large bounds: consider scaling the bounds "
472496 " by 1e%+1d or less\n " ,
473- options.user_bound_scale ? " User-scaled problem" : " Problem" ,
474- int (-suggested_bound_scale_exponent));
497+ problem.c_str (), int (-suggested_bound_scale_exponent));
475498 } else {
476499 highsLogUser (
477500 log_options, HighsLogType::kWarning ,
478501 " %s has excessively large bounds: consider scaling the bounds "
479502 " by 1e%+1d or less, "
480503 " or setting option user_bound_scale to %d or less\n " ,
481- options.user_bound_scale ? " User-scaled problem" : " Problem" ,
482- int (-suggested_bound_scale_exponent),
504+ problem.c_str (), int (-suggested_bound_scale_exponent),
483505 int (suggested_user_bound_scale));
484506 }
485507 }
486508 // Now consider warning relating to small maximum costs and bounds
487- if (max_finite_col_cost > 0 &&
488- max_finite_col_cost < kExcessivelySmallCostValue ) {
489- double user_cost_scale_value = std::pow (2 , options.user_cost_scale );
509+ if (max_col_cost > 0 && max_col_cost < kExcessivelySmallCostValue ) {
490510 // Warn that costs are excessively small, and suggest scaling
491- double ratio = kExcessivelySmallCostValue /
492- (max_finite_col_cost / user_cost_scale_value);
511+ double ratio =
512+ kExcessivelySmallCostValue / (max_col_cost / user_cost_scale_value);
493513 HighsInt suggested_user_cost_scale_setting = std::ceil (std::log2 (ratio));
494514 HighsInt suggested_cost_scale_exponent = std::ceil (std::log10 (ratio));
495515 highsLogUser (
496516 log_options, HighsLogType::kWarning ,
497517 " %s has excessively small costs: consider scaling the costs up "
498518 " by 1e%+1d or more, "
499519 " or setting option user_cost_scale to %d or more\n " ,
500- options.user_cost_scale ? " User-scaled problem" : " Problem" ,
501- int (suggested_cost_scale_exponent),
520+ problem.c_str (), int (suggested_cost_scale_exponent),
502521 int (suggested_user_cost_scale_setting));
503522 }
504- if (max_finite_col_bound > 0 &&
505- max_finite_col_bound < kExcessivelySmallBoundValue ) {
506- double user_bound_scale_value = std::pow (2 , options.user_bound_scale );
523+ if (max_col_bound > 0 && max_col_bound < kExcessivelySmallBoundValue ) {
507524 // Warn that bounds are excessively small, and suggest scaling
508- double ratio = kExcessivelySmallBoundValue /
509- (max_finite_col_bound / user_bound_scale_value);
525+ double ratio =
526+ kExcessivelySmallBoundValue / (max_col_bound / user_bound_scale_value);
510527 HighsInt suggested_user_bound_scale = std::ceil (std::log2 (ratio));
511528 HighsInt suggested_bound_scale_exponent = std::ceil (std::log10 (ratio));
512529 if (lp.isMip ()) {
513530 highsLogUser (
514531 log_options, HighsLogType::kWarning ,
515532 " %s has excessively small bounds: consider scaling the bounds "
516533 " by 1e%+1d or more\n " ,
517- options.user_bound_scale ? " User-scaled problem" : " Problem" ,
518- int (suggested_bound_scale_exponent));
534+ problem.c_str (), int (suggested_bound_scale_exponent));
519535 } else {
520536 highsLogUser (
521537 log_options, HighsLogType::kWarning ,
522538 " %s has excessively small bounds: consider scaling the bounds "
523539 " by 1e%+1d or more, "
524540 " or setting option user_bound_scale to %d or more\n " ,
525- options. user_bound_scale ? " User-scaled problem " : " Problem " ,
526- int (suggested_bound_scale_exponent), int ( suggested_user_bound_scale));
541+ problem. c_str (), int (suggested_bound_scale_exponent) ,
542+ int (suggested_user_bound_scale));
527543 }
528544 }
529- if (max_finite_row_bound > 0 &&
530- max_finite_row_bound < kExcessivelySmallBoundValue ) {
531- double user_bound_scale_value = std::pow (2 , options.user_bound_scale );
545+ if (max_row_bound > 0 && max_row_bound < kExcessivelySmallBoundValue ) {
532546 // Warn that bounds are excessively small, and suggest scaling
533- double ratio = kExcessivelySmallBoundValue /
534- (max_finite_row_bound / user_bound_scale_value);
547+ double ratio =
548+ kExcessivelySmallBoundValue / (max_row_bound / user_bound_scale_value);
535549 HighsInt suggested_user_bound_scale = std::ceil (std::log2 (ratio));
536550 HighsInt suggested_bound_scale_exponent = std::ceil (std::log10 (ratio));
537551 if (lp.isMip ()) {
538552 highsLogUser (
539553 log_options, HighsLogType::kWarning ,
540554 " %s has excessively small bounds: consider scaling the bounds "
541555 " by 1e%+1d or more\n " ,
542- options.user_bound_scale ? " User-scaled problem" : " Problem" ,
543- int (suggested_bound_scale_exponent));
556+ problem.c_str (), int (suggested_bound_scale_exponent));
544557 } else {
545558 highsLogUser (
546559 log_options, HighsLogType::kWarning ,
547560 " %s has excessively small bounds: consider scaling the bounds "
548561 " by 1e%+1d or more, "
549562 " or setting option user_bound_scale to %d or more\n " ,
550- options. user_bound_scale ? " User-scaled problem " : " Problem " ,
551- int (suggested_bound_scale_exponent), int ( suggested_user_bound_scale));
563+ problem. c_str (), int (suggested_bound_scale_exponent) ,
564+ int (suggested_user_bound_scale));
552565 }
553566 }
554567}
0 commit comments