Skip to content

Commit e7b425b

Browse files
committed
Now geting continuous and noncontinuous data from model in assessExcessiveBoundCost
1 parent 9183f39 commit e7b425b

File tree

3 files changed

+113
-97
lines changed

3 files changed

+113
-97
lines changed

highs/lp_data/Highs.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,11 @@ HighsStatus Highs::run() {
955955
this->options_.user_cost_scale = 0;
956956
this->options_.user_bound_scale = 0;
957957
}
958+
959+
// Assess whether to warn the user about excessive bounds and costs
960+
assessExcessiveBoundCost(this->options_.log_options, this->model_,
961+
user_scale_data);
962+
958963
HighsStatus status;
959964
if (!this->multi_linear_objective_.size()) {
960965
status = this->optimizeModel();
@@ -1086,9 +1091,6 @@ HighsStatus Highs::optimizeModel() {
10861091
return HighsStatus::kError;
10871092
}
10881093

1089-
// Assess whether to warn the user about excessive bounds and costs
1090-
assessExcessiveBoundCost(this->options_, this->model_);
1091-
10921094
// HiGHS solvers require models with no infinite costs, and no semi-variables
10931095
//
10941096
// Since completeSolutionFromDiscreteAssignment() may require a call

highs/lp_data/HighsSolve.cpp

Lines changed: 105 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

highs/lp_data/HighsSolve.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ HighsStatus solveUnconstrainedLp(const HighsOptions& options, const HighsLp& lp,
1818
HighsModelStatus& model_status,
1919
HighsInfo& highs_info, HighsSolution& solution,
2020
HighsBasis& basis);
21-
void assessExcessiveBoundCost(const HighsOptions options,
22-
const HighsModel& model);
21+
void assessExcessiveBoundCost(const HighsLogOptions log_options,
22+
const HighsModel& model,
23+
const HighsUserScaleData& user_scale_data);
2324
#endif // LP_DATA_HIGHSSOLVE_H_

0 commit comments

Comments
 (0)