Skip to content

Commit b5eb706

Browse files
committed
Compiles!
1 parent ab2c4c8 commit b5eb706

File tree

8 files changed

+592
-362
lines changed

8 files changed

+592
-362
lines changed

highs/lp_data/HStruct.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,27 @@ struct HighsSimplexStats {
183183
void initialise(const HighsInt iteration_count_ = 0);
184184
};
185185

186+
struct HighsUserScaleData {
187+
HighsInt user_cost_scale;
188+
HighsInt user_bound_scale;
189+
double infinite_cost;
190+
double infinite_bound;
191+
double small_matrix_value;
192+
double large_matrix_value;
193+
HighsInt num_infinite_costs;
194+
HighsInt num_infinite_col_bounds;
195+
HighsInt num_infinite_row_bounds;
196+
HighsInt num_small_matrix_values;
197+
HighsInt num_large_matrix_values;
198+
void initialise(const HighsInt& user_cost_scale_,
199+
const HighsInt& user_bound_scale_,
200+
const double& infinite_cost_,
201+
const double& infinite_bound_,
202+
const double& small_matrix_value_,
203+
const double& large_matrix_value_);
204+
bool scaleError() const;
205+
bool scaleError(std::string& message) const;
206+
bool scaleWarning(std::string& message) const;
207+
};
208+
186209
#endif /* LP_DATA_HSTRUCT_H_ */

highs/lp_data/HighsInterface.cpp

Lines changed: 70 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -449,35 +449,6 @@ HighsStatus Highs::addColsInterface(
449449
local_colLower, local_colUpper, options.infinite_bound),
450450
return_status, "assessBounds");
451451
if (return_status == HighsStatus::kError) return return_status;
452-
if (lp.user_bound_scale_) {
453-
// Assess and apply any user bound scaling
454-
if (!boundScaleOk(local_colLower, local_colUpper, lp.user_bound_scale_,
455-
options.infinite_bound)) {
456-
highsLogUser(options_.log_options, HighsLogType::kError,
457-
"User bound scaling yields infinite bound\n");
458-
return HighsStatus::kError;
459-
}
460-
double bound_scale_value = std::pow(2, lp.user_bound_scale_);
461-
for (HighsInt iCol = 0; iCol < ext_num_new_col; iCol++) {
462-
local_colLower[iCol] *= bound_scale_value;
463-
local_colUpper[iCol] *= bound_scale_value;
464-
}
465-
}
466-
if (lp.user_cost_scale_) {
467-
// Assess and apply any user cost scaling
468-
if (!costScaleOk(local_colCost, lp.user_cost_scale_,
469-
options.infinite_cost)) {
470-
highsLogUser(options_.log_options, HighsLogType::kError,
471-
"User cost scaling yields infinite cost\n");
472-
return HighsStatus::kError;
473-
}
474-
double cost_scale_value = std::pow(2, lp.user_cost_scale_);
475-
for (HighsInt iCol = 0; iCol < ext_num_new_col; iCol++)
476-
local_colCost[iCol] *= cost_scale_value;
477-
}
478-
// Append the columns to the LP vectors and matrix
479-
appendColsToLpVectors(lp, ext_num_new_col, local_colCost, local_colLower,
480-
local_colUpper);
481452
// Form a column-wise HighsSparseMatrix of the new matrix columns so
482453
// that is easy to handle and, if there are nonzeros, it can be
483454
// normalised
@@ -506,6 +477,20 @@ HighsStatus Highs::addColsInterface(
506477
// matrix columns
507478
local_a_matrix.start_.assign(ext_num_new_col + 1, 0);
508479
}
480+
if (lp.user_cost_scale_ || lp.user_bound_scale_) {
481+
HighsUserScaleData user_scale_data;
482+
initialiseUserScaleData(lp, options_, user_scale_data);
483+
return_status = userScaleNewCols(local_colCost,
484+
local_colLower,
485+
local_colUpper,
486+
local_a_matrix,
487+
user_scale_data,
488+
options.log_options);
489+
if (return_status == HighsStatus::kError) return HighsStatus::kError;
490+
}
491+
// Append the columns to the LP vectors and matrix
492+
appendColsToLpVectors(lp, ext_num_new_col, local_colCost, local_colLower,
493+
local_colUpper);
509494
// Append the columns to LP matrix
510495
lp.a_matrix_.addCols(local_a_matrix);
511496
if (lp_has_scaling) {
@@ -599,30 +584,11 @@ HighsStatus Highs::addRowsInterface(HighsInt ext_num_new_row,
599584
std::vector<double> local_rowUpper{ext_row_upper,
600585
ext_row_upper + ext_num_new_row};
601586

602-
return_status = interpretCallStatus(
603-
options_.log_options,
587+
return_status = interpretCallStatus(options_.log_options,
604588
assessBounds(options, "Row", lp.num_row_, index_collection,
605589
local_rowLower, local_rowUpper, options.infinite_bound),
606590
return_status, "assessBounds");
607591
if (return_status == HighsStatus::kError) return return_status;
608-
if (lp.user_bound_scale_) {
609-
// Assess and apply any user bound scaling
610-
if (!boundScaleOk(local_rowLower, local_rowUpper, lp.user_bound_scale_,
611-
options_.infinite_bound)) {
612-
highsLogUser(options_.log_options, HighsLogType::kError,
613-
"User bound scaling yields infinite bound\n");
614-
return HighsStatus::kError;
615-
}
616-
double bound_scale_value = std::pow(2, lp.user_bound_scale_);
617-
for (HighsInt iRow = 0; iRow < ext_num_new_row; iRow++) {
618-
local_rowLower[iRow] *= bound_scale_value;
619-
local_rowUpper[iRow] *= bound_scale_value;
620-
}
621-
}
622-
623-
// Append the rows to the LP vectors
624-
appendRowsToLpVectors(lp, ext_num_new_row, local_rowLower, local_rowUpper);
625-
626592
// Form a row-wise HighsSparseMatrix of the new matrix rows so that
627593
// is easy to handle and, if there are nonzeros, it can be
628594
// normalised
@@ -652,24 +618,25 @@ HighsStatus Highs::addRowsInterface(HighsInt ext_num_new_row,
652618
local_ar_matrix.start_.assign(ext_num_new_row + 1, 0);
653619
}
654620
if (lp.user_bound_scale_) {
655-
// Scale the columns corresponding to non-continuous variables,
656-
// warning the user if small or large matrix entries are created
657-
// as a result
658-
HighsInt num_small_values;
659-
HighsInt num_large_values;
660-
if (!userScaleNonContinuousMatrix(lp.integrality_,
661-
local_ar_matrix,
662-
lp.user_bound_scale_,
663-
options.small_matrix_value,
664-
options.large_matrix_value,
665-
num_small_values,
666-
num_large_values)) {
667-
return_status = HighsStatus::kWarning;
668-
highsLogUser(options_.log_options, HighsLogType::kWarning,
669-
"User bound scaling yields %d small matrix entries and %d small matrix entries\n",
670-
int(num_small_values), int(num_large_values));
671-
}
621+
HighsUserScaleData user_scale_data;
622+
initialiseUserScaleData(lp, options_, user_scale_data);
623+
const bool apply = false;
624+
userScaleNewRows(lp.integrality_,
625+
local_rowLower,
626+
local_rowUpper,
627+
local_ar_matrix,
628+
user_scale_data,
629+
apply);
630+
return_status = userScaleStatus(options.log_options, user_scale_data);
631+
if (return_status == HighsStatus::kError) return HighsStatus::kError;
632+
userScaleNewRows(lp.integrality_,
633+
local_rowLower,
634+
local_rowUpper,
635+
local_ar_matrix,
636+
user_scale_data);
672637
}
638+
// Append the rows to the LP vectors
639+
appendRowsToLpVectors(lp, ext_num_new_row, local_rowLower, local_rowUpper);
673640
// Append the rows to LP matrix
674641
lp.a_matrix_.addRows(local_ar_matrix);
675642
if (lp_has_scaling) {
@@ -981,19 +948,12 @@ HighsStatus Highs::changeCostsInterface(HighsIndexCollection& index_collection,
981948
if (return_status == HighsStatus::kError) return return_status;
982949
HighsLp& lp = model_.lp_;
983950
if (lp.user_cost_scale_) {
984-
// Assess and apply any user cost scaling
985-
if (!costScaleOk(local_colCost, lp.user_cost_scale_,
986-
options_.infinite_cost)) {
987-
highsLogUser(options_.log_options, HighsLogType::kError,
988-
"User cost scaling yields infinite cost\n");
989-
return HighsStatus::kError;
990-
}
991-
double cost_scale_value = std::pow(2, lp.user_cost_scale_);
992-
for (HighsInt iCol = 0; iCol < num_cost; iCol++)
993-
local_colCost[iCol] *= cost_scale_value;
951+
HighsUserScaleData user_scale_data;
952+
initialiseUserScaleData(lp, options_, user_scale_data);
953+
userScaleCosts(lp.integrality_, local_colCost, user_scale_data, options_.log_options);
954+
if (return_status == HighsStatus::kError) return HighsStatus::kError;
994955
}
995956
changeLpCosts(lp, index_collection, local_colCost, options_.infinite_cost);
996-
997957
// Interpret possible introduction of infinite costs
998958
lp.has_infinite_cost_ = lp.has_infinite_cost_ || local_has_infinite_cost;
999959
assert(lp.has_infinite_cost_ == lp.hasInfiniteCost(options_.infinite_cost));
@@ -1038,16 +998,11 @@ HighsStatus Highs::changeColBoundsInterface(
1038998
if (return_status == HighsStatus::kError) return return_status;
1039999
HighsLp& lp = model_.lp_;
10401000
if (lp.user_bound_scale_) {
1041-
// Assess and apply any user bound scaling
1042-
if (!boundScaleOk(local_colLower, local_colUpper, lp.user_bound_scale_,
1043-
options_.infinite_bound)) {
1044-
highsLogUser(options_.log_options, HighsLogType::kError,
1045-
"User bound scaling yields infinite bound\n");
1046-
return HighsStatus::kError;
1047-
}
1048-
userScaleContinuousColBounds(lp.integrality_, local_colLower, local_colUpper, lp.user_bound_scale_);
1001+
HighsUserScaleData user_scale_data;
1002+
initialiseUserScaleData(lp, options_, user_scale_data);
1003+
return_status = userScaleColBounds(lp.integrality_, local_colLower, local_colUpper, user_scale_data, options_.log_options);
1004+
if (return_status == HighsStatus::kError) return HighsStatus::kError;
10491005
}
1050-
10511006
changeLpColBounds(lp, index_collection, local_colLower, local_colUpper);
10521007
// Update HiGHS basis status and (any) simplex move status of
10531008
// nonbasic variables whose bounds have changed
@@ -1092,20 +1047,11 @@ HighsStatus Highs::changeRowBoundsInterface(
10921047
if (return_status == HighsStatus::kError) return return_status;
10931048
HighsLp& lp = model_.lp_;
10941049
if (lp.user_bound_scale_) {
1095-
// Assess and apply any user bound scaling
1096-
if (!boundScaleOk(local_rowLower, local_rowUpper, lp.user_bound_scale_,
1097-
options_.infinite_bound)) {
1098-
highsLogUser(options_.log_options, HighsLogType::kError,
1099-
"User bound scaling yields infinite bound\n");
1100-
return HighsStatus::kError;
1101-
}
1102-
double bound_scale_value = std::pow(2, lp.user_bound_scale_);
1103-
for (HighsInt iRow = 0; iRow < num_row_bounds; iRow++) {
1104-
local_rowLower[iRow] *= bound_scale_value;
1105-
local_rowUpper[iRow] *= bound_scale_value;
1106-
}
1050+
HighsUserScaleData user_scale_data;
1051+
initialiseUserScaleData(lp, options_, user_scale_data);
1052+
return_status = userScaleRowBounds(local_rowLower, local_rowUpper, user_scale_data, options_.log_options);
1053+
if (return_status == HighsStatus::kError) return HighsStatus::kError;
11071054
}
1108-
11091055
changeLpRowBounds(lp, index_collection, local_rowLower, local_rowUpper);
11101056
// Update HiGHS basis status and (any) simplex move status of
11111057
// nonbasic variables whose bounds have changed
@@ -3090,88 +3036,35 @@ HighsStatus Highs::optionChangeAction() {
30903036
HighsLp& lp = model.lp_;
30913037
HighsInfo& info = this->info_;
30923038
HighsOptions& options = this->options_;
3093-
const bool is_mip = lp.isMip();
3094-
HighsInt dl_user_bound_scale = 0;
30953039
HighsStatus return_status = HighsStatus::kOk;
3096-
const bool has_integrality = lp.integrality_.size() > 0;
3097-
// Ensure that user bound scaling does not yield infinite bounds or costs
3098-
if (options.user_bound_scale != lp.user_bound_scale_) {
3099-
if (!lp.userBoundScaleOk(options.user_bound_scale, options.infinite_bound)) {
3100-
options.user_bound_scale = lp.user_bound_scale_;
3101-
highsLogUser(options_.log_options, HighsLogType::kError,
3102-
"New user bound scaling yields infinite bound: reverting user "
3103-
"bound scaling to %d\n",
3104-
int(lp.user_bound_scale_));
3105-
return_status = HighsStatus::kError;
3106-
} else {
3107-
dl_user_bound_scale = options.user_bound_scale - lp.user_bound_scale_;
3108-
}
3109-
}
3110-
if (dl_user_bound_scale) {
3111-
double dl_user_bound_scale_value = std::pow(2, dl_user_bound_scale);
3112-
// Now update model status, data and solution with respect to
3113-
// non-trivial user cost scaling
3114-
this->model_status_ = HighsModelStatus::kNotset;
3115-
if (has_integrality) {
3116-
double objective_function_value = info.objective_function_value * dl_user_bound_scale_value;
3117-
info.clear();
3118-
info.objective_function_value = objective_function_value;
3119-
for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
3120-
if (lp.integrality_[iCol] == HighsVarType::kContinuous) {
3121-
this->solution_.col_value[iCol] *= dl_user_bound_scale_value;
3122-
} else {
3123-
lp.col_cost_[iCol] *= dl_user_bound_scale_value;
3124-
}
3125-
}
3126-
} else {
3127-
info.objective_function_value *= dl_user_bound_scale_value;
3128-
info.num_primal_infeasibility = kHighsIllegalInfeasibilityCount;
3129-
info.max_primal_infeasibility *= dl_user_bound_scale_value;
3130-
info.sum_primal_infeasibilities *= dl_user_bound_scale_value;
3131-
for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++)
3132-
this->solution_.col_value[iCol] *= dl_user_bound_scale_value;
3133-
}
3134-
for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++)
3135-
this->solution_.row_value[iRow] *= dl_user_bound_scale_value;
3136-
info.primal_solution_status = kSolutionStatusNone;
3137-
// Update LP with respect to non-trivial user bound scaling
3138-
lp.userBoundScale(options_.user_bound_scale);
3139-
}
3140-
// Now consider whether options.user_cost_scale has changed
3141-
HighsInt dl_user_cost_scale = 0;
3142-
if (options.user_cost_scale != lp.user_cost_scale_) {
3143-
if (!model.userCostScaleOk(options.user_cost_scale, options.small_matrix_value,
3144-
options.large_matrix_value, options.infinite_cost)) {
3040+
HighsInt dl_user_cost_scale = options.user_cost_scale - lp.user_cost_scale_;
3041+
HighsInt dl_user_bound_scale = options.user_bound_scale - lp.user_bound_scale_;
3042+
if (dl_user_cost_scale || dl_user_bound_scale) {
3043+
HighsUserScaleData user_scale_data;
3044+
initialiseUserScaleData(lp, options_, user_scale_data);
3045+
user_scale_data.user_cost_scale = dl_user_cost_scale;
3046+
user_scale_data.user_bound_scale = dl_user_bound_scale;
3047+
return_status = userScaleLp(lp.integrality_,
3048+
lp.col_cost_,
3049+
lp.col_lower_,
3050+
lp.col_upper_,
3051+
lp.row_lower_,
3052+
lp.row_upper_,
3053+
lp.a_matrix_,
3054+
user_scale_data,
3055+
options.log_options);
3056+
if (return_status == HighsStatus::kError) {
31453057
options.user_cost_scale = lp.user_cost_scale_;
3058+
options.user_bound_scale = lp.user_bound_scale_;
31463059
highsLogUser(options_.log_options, HighsLogType::kError,
3147-
"New user cost scaling yields excessive cost coefficient: "
3148-
"reverting user cost scaling to %d\n",
3149-
int(lp.user_cost_scale_));
3150-
return_status = HighsStatus::kError;
3151-
} else {
3152-
dl_user_cost_scale = options.user_cost_scale - lp.user_cost_scale_;
3060+
"New user cost/bound scaling yields excessive costs/bounds: "
3061+
"reverting user cost scaling to %d, and user bound scaling to %d\n",
3062+
int(lp.user_cost_scale_), int(lp.user_bound_scale_));
3063+
return HighsStatus::kError;
31533064
}
3065+
this->invalidateModelStatusSolutionAndInfo();
3066+
this->invalidateSolverData();
31543067
}
3155-
if (dl_user_cost_scale) {
3156-
double dl_user_cost_scale_value = std::pow(2, dl_user_cost_scale);
3157-
// Now update model status, data and solution with respect to
3158-
// non-trivial user cost scaling
3159-
this->model_status_ = HighsModelStatus::kNotset;
3160-
info.objective_function_value *= dl_user_cost_scale_value;
3161-
info.num_dual_infeasibilities = kHighsIllegalInfeasibilityCount;
3162-
info.max_dual_infeasibility *= dl_user_cost_scale_value;
3163-
info.sum_dual_infeasibilities *= dl_user_cost_scale_value;
3164-
for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++)
3165-
this->solution_.col_dual[iCol] *= dl_user_cost_scale_value;
3166-
for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++)
3167-
this->solution_.row_dual[iRow] *= dl_user_cost_scale_value;
3168-
info.dual_solution_status = kSolutionStatusNone;
3169-
// Update LP with respect to non-trivial user cost scaling
3170-
model.userCostScale(options.user_cost_scale);
3171-
}
3172-
if (!user_bound_scale_ok || !user_cost_scale_ok) return HighsStatus::kError;
3173-
if (this->iis_.valid_ && options_.iis_strategy != this->iis_.strategy_)
3174-
this->iis_.invalidate();
31753068
return HighsStatus::kOk;
31763069
}
31773070

@@ -4256,3 +4149,4 @@ void HighsLinearObjective::clear() {
42564149
this->rel_tolerance = 0.0;
42574150
this->priority = 0;
42584151
}
4152+

0 commit comments

Comments
 (0)