Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Old code now throwing up build error, and more clang format frigging #2003

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions check/TestLpSolvers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ TEST_CASE("LP-solver", "[highs_lp_solver]") {
const HighsInfo& info = highs.getInfo();
REQUIRE(info.num_dual_infeasibilities == 0);

REQUIRE(info.simplex_iteration_count == 472); // 476); // 444);
REQUIRE(info.simplex_iteration_count == 472);

HighsModelStatus model_status = highs.getModelStatus();
REQUIRE(model_status == HighsModelStatus::kOptimal);
Expand All @@ -296,7 +296,7 @@ TEST_CASE("LP-solver", "[highs_lp_solver]") {
return_status = highs.run();
REQUIRE(return_status == HighsStatus::kOk);

REQUIRE(info.simplex_iteration_count == 592); // 621); // 584); //
REQUIRE(info.simplex_iteration_count == 592);
}

TEST_CASE("mip-with-lp-solver", "[highs_lp_solver]") {
Expand Down Expand Up @@ -470,3 +470,64 @@ TEST_CASE("blending-lp-ipm", "[highs_lp_solver]") {
printf("Sum dual infeasibilities = %g\n", info.sum_dual_infeasibilities);
}
}

TEST_CASE("standard-form-lp", "[highs_lp_solver]") {
std::string model;
std::string model_file;
Highs highs;
highs.setOptionValue("output_flag", dev_run);
model = "avgas";
model_file = std::string(HIGHS_DIR) + "/check/instances/" + model + ".mps";
highs.readModel(model_file);
highs.run();
double required_objective_function_value =
highs.getInfo().objective_function_value;
//
HighsInt num_col;
HighsInt num_row;
HighsInt num_nz;
double offset;
REQUIRE(highs.getStandardFormLp(num_col, num_row, num_nz, offset) ==
HighsStatus::kOk);

std::vector<double> cost(num_col);
std::vector<double> rhs(num_row);
std::vector<HighsInt> start(num_col + 1);
std::vector<HighsInt> index(num_nz);
std::vector<double> value(num_nz);
REQUIRE(highs.getStandardFormLp(num_col, num_row, num_nz, offset, cost.data(),
rhs.data(), start.data(), index.data(),
value.data()) == HighsStatus::kOk);

HighsLp standard_form_lp;
standard_form_lp.num_col_ = num_col;
standard_form_lp.num_row_ = num_row;
standard_form_lp.col_cost_ = cost;
standard_form_lp.col_lower_.assign(num_col, 0);
standard_form_lp.col_upper_.assign(num_col, kHighsInf);
standard_form_lp.row_lower_ = rhs;
standard_form_lp.row_upper_ = rhs;
standard_form_lp.a_matrix_.start_ = start;
standard_form_lp.a_matrix_.index_ = index;
standard_form_lp.a_matrix_.value_ = value;
REQUIRE(highs.passModel(standard_form_lp) == HighsStatus::kOk);
if (dev_run) highs.writeModel("");
REQUIRE(highs.run() == HighsStatus::kOk);
REQUIRE(highs.getModelStatus() == HighsModelStatus::kOptimal);
double objective_function_value = highs.getInfo().objective_function_value;
double objective_difference =
std::fabs(objective_function_value - required_objective_function_value) /
std::max(1.0, std::fabs(required_objective_function_value));
REQUIRE(objective_difference < 1e-10);
const bool look_at_presolved_lp = false;
if (look_at_presolved_lp) {
// Strange that presolve doesn't convert the constraints
//
// Ax-s = b; s >= 0 into Ax >= b
REQUIRE(highs.passModel(standard_form_lp) == HighsStatus::kOk);
REQUIRE(highs.presolve() == HighsStatus::kOk);
HighsLp presolved_lp = highs.getPresolvedLp();
REQUIRE(highs.passModel(presolved_lp) == HighsStatus::kOk);
highs.writeModel("");
}
}
21 changes: 21 additions & 0 deletions src/Highs.h
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,17 @@ class Highs {
* Methods for model output
*/

/**
* @brief Identify and the standard form of the HighsLp instance in
* HiGHS
*/
HighsStatus getStandardFormLp(HighsInt& num_col, HighsInt& num_row,
HighsInt& num_nz, double offset,
double* cost = nullptr, double* rhs = nullptr,
HighsInt* start = nullptr,
HighsInt* index = nullptr,
double* value = nullptr);

/**
* @brief Return a const reference to the presolved HighsLp instance in HiGHS
*/
Expand Down Expand Up @@ -1378,6 +1389,12 @@ class Highs {
HighsPresolveStatus::kNotPresolved;
HighsModelStatus model_status_ = HighsModelStatus::kNotset;

bool standard_form_valid_;
double standard_form_offset_;
std::vector<double> standard_form_cost_;
std::vector<double> standard_form_rhs_;
HighsSparseMatrix standard_form_matrix_;

HEkk ekk_instance_;

HighsPresolveLog presolve_log_;
Expand Down Expand Up @@ -1430,6 +1447,9 @@ class Highs {
// Clears the presolved model and its status
void clearPresolve();
//
// Clears the standard form LP
void clearStandardFormLp();
//
// Methods to clear solver data for users in Highs class members
// before (possibly) updating them with data from trying to solve
// the incumbent model.
Expand Down Expand Up @@ -1473,6 +1493,7 @@ class Highs {
void underDevelopmentLogMessage(const std::string& method_name);

// Interface methods
HighsStatus formStandardFormLp();
HighsStatus basisForSolution();
HighsStatus addColsInterface(
HighsInt ext_num_new_col, const double* ext_col_cost,
Expand Down
60 changes: 60 additions & 0 deletions src/lp_data/Highs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ HighsStatus Highs::clearModel() {
HighsStatus Highs::clearSolver() {
HighsStatus return_status = HighsStatus::kOk;
clearPresolve();
clearStandardFormLp();
invalidateUserSolverData();
return returnFromHighs(return_status);
}
Expand Down Expand Up @@ -1637,6 +1638,37 @@ HighsStatus Highs::run() {
return returnFromRun(return_status, undo_mods);
}

HighsStatus Highs::getStandardFormLp(HighsInt& num_col, HighsInt& num_row,
HighsInt& num_nz, double offset,
double* cost, double* rhs, HighsInt* start,
HighsInt* index, double* value) {
if (!this->standard_form_valid_) {
HighsStatus status = formStandardFormLp();
if (status != HighsStatus::kOk) return status;
}
num_col = this->standard_form_cost_.size();
num_row = this->standard_form_rhs_.size();
num_nz = this->standard_form_matrix_.start_[num_col];
offset = this->standard_form_offset_;
for (HighsInt iCol = 0; iCol < num_col; iCol++) {
if (cost) cost[iCol] = this->standard_form_cost_[iCol];
if (start) start[iCol] = this->standard_form_matrix_.start_[iCol];
if (index || value) {
for (HighsInt iEl = this->standard_form_matrix_.start_[iCol];
iEl < this->standard_form_matrix_.start_[iCol + 1]; iEl++) {
if (index) index[iEl] = this->standard_form_matrix_.index_[iEl];
if (value) value[iEl] = this->standard_form_matrix_.value_[iEl];
}
}
}
if (start) start[num_col] = this->standard_form_matrix_.start_[num_col];
if (rhs) {
for (HighsInt iRow = 0; iRow < num_row; iRow++)
rhs[iRow] = this->standard_form_rhs_[iRow];
}
return HighsStatus::kOk;
}

HighsStatus Highs::getDualRay(bool& has_dual_ray, double* dual_ray_value) {
// Can't get a ray without an INVERT, but absence is only an error
// when solving an LP #1350
Expand Down Expand Up @@ -2338,6 +2370,7 @@ HighsStatus Highs::addCols(const HighsInt num_new_col, const double* costs,
this->logHeader();
HighsStatus return_status = HighsStatus::kOk;
clearPresolve();
clearStandardFormLp();
return_status = interpretCallStatus(
options_.log_options,
addColsInterface(num_new_col, costs, lower_bounds, upper_bounds,
Expand Down Expand Up @@ -2376,6 +2409,7 @@ HighsStatus Highs::addRows(const HighsInt num_new_row,
this->logHeader();
HighsStatus return_status = HighsStatus::kOk;
clearPresolve();
clearStandardFormLp();
return_status = interpretCallStatus(
options_.log_options,
addRowsInterface(num_new_row, lower_bounds, upper_bounds, num_new_nz,
Expand All @@ -2391,6 +2425,7 @@ HighsStatus Highs::changeObjectiveSense(const ObjSense sense) {
model_.lp_.sense_ = sense;
// Nontrivial change
clearPresolve();
clearStandardFormLp();
invalidateModelStatusSolutionAndInfo();
}
return returnFromHighs(HighsStatus::kOk);
Expand Down Expand Up @@ -2520,6 +2555,7 @@ HighsStatus Highs::changeColCost(const HighsInt col, const double cost) {
HighsStatus Highs::changeColsCost(const HighsInt from_col,
const HighsInt to_col, const double* cost) {
clearPresolve();
clearStandardFormLp();
HighsIndexCollection index_collection;
const HighsInt create_error =
create(index_collection, from_col, to_col, model_.lp_.num_col_);
Expand All @@ -2546,6 +2582,7 @@ HighsStatus Highs::changeColsCost(const HighsInt num_set_entries,
if (doubleUserDataNotNull(options_.log_options, cost, "column costs"))
return HighsStatus::kError;
clearPresolve();
clearStandardFormLp();
// Ensure that the set and data are in ascending order
std::vector<double> local_cost{cost, cost + num_set_entries};
std::vector<HighsInt> local_set{set, set + num_set_entries};
Expand All @@ -2569,6 +2606,7 @@ HighsStatus Highs::changeColsCost(const HighsInt num_set_entries,

HighsStatus Highs::changeColsCost(const HighsInt* mask, const double* cost) {
clearPresolve();
clearStandardFormLp();
HighsIndexCollection index_collection;
const bool create_error = create(index_collection, mask, model_.lp_.num_col_);
assert(!create_error);
Expand All @@ -2590,6 +2628,7 @@ HighsStatus Highs::changeColsBounds(const HighsInt from_col,
const HighsInt to_col, const double* lower,
const double* upper) {
clearPresolve();
clearStandardFormLp();
HighsIndexCollection index_collection;
const HighsInt create_error =
create(index_collection, from_col, to_col, model_.lp_.num_col_);
Expand Down Expand Up @@ -2624,6 +2663,7 @@ HighsStatus Highs::changeColsBounds(const HighsInt num_set_entries,
null_data;
if (null_data) return HighsStatus::kError;
clearPresolve();
clearStandardFormLp();
// Ensure that the set and data are in ascending order
std::vector<double> local_lower{lower, lower + num_set_entries};
std::vector<double> local_upper{upper, upper + num_set_entries};
Expand All @@ -2649,6 +2689,7 @@ HighsStatus Highs::changeColsBounds(const HighsInt num_set_entries,
HighsStatus Highs::changeColsBounds(const HighsInt* mask, const double* lower,
const double* upper) {
clearPresolve();
clearStandardFormLp();
HighsIndexCollection index_collection;
const bool create_error = create(index_collection, mask, model_.lp_.num_col_);
assert(!create_error);
Expand All @@ -2671,6 +2712,7 @@ HighsStatus Highs::changeRowsBounds(const HighsInt from_row,
const HighsInt to_row, const double* lower,
const double* upper) {
clearPresolve();
clearStandardFormLp();
HighsIndexCollection index_collection;
const HighsInt create_error =
create(index_collection, from_row, to_row, model_.lp_.num_row_);
Expand Down Expand Up @@ -2705,6 +2747,7 @@ HighsStatus Highs::changeRowsBounds(const HighsInt num_set_entries,
null_data;
if (null_data) return HighsStatus::kError;
clearPresolve();
clearStandardFormLp();
// Ensure that the set and data are in ascending order
std::vector<double> local_lower{lower, lower + num_set_entries};
std::vector<double> local_upper{upper, upper + num_set_entries};
Expand All @@ -2730,6 +2773,7 @@ HighsStatus Highs::changeRowsBounds(const HighsInt num_set_entries,
HighsStatus Highs::changeRowsBounds(const HighsInt* mask, const double* lower,
const double* upper) {
clearPresolve();
clearStandardFormLp();
HighsIndexCollection index_collection;
const bool create_error = create(index_collection, mask, model_.lp_.num_row_);
assert(!create_error);
Expand Down Expand Up @@ -3028,6 +3072,7 @@ HighsStatus Highs::getCoeff(const HighsInt row, const HighsInt col,

HighsStatus Highs::deleteCols(const HighsInt from_col, const HighsInt to_col) {
clearPresolve();
clearStandardFormLp();
HighsIndexCollection index_collection;
const HighsInt create_error =
create(index_collection, from_col, to_col, model_.lp_.num_col_);
Expand All @@ -3046,6 +3091,7 @@ HighsStatus Highs::deleteCols(const HighsInt num_set_entries,
const HighsInt* set) {
if (num_set_entries == 0) return HighsStatus::kOk;
clearPresolve();
clearStandardFormLp();
HighsIndexCollection index_collection;
const HighsInt create_error =
create(index_collection, num_set_entries, set, model_.lp_.num_col_);
Expand All @@ -3059,6 +3105,7 @@ HighsStatus Highs::deleteCols(const HighsInt num_set_entries,

HighsStatus Highs::deleteCols(HighsInt* mask) {
clearPresolve();
clearStandardFormLp();
const HighsInt original_num_col = model_.lp_.num_col_;
HighsIndexCollection index_collection;
const bool create_error = create(index_collection, mask, original_num_col);
Expand All @@ -3072,6 +3119,7 @@ HighsStatus Highs::deleteCols(HighsInt* mask) {

HighsStatus Highs::deleteRows(const HighsInt from_row, const HighsInt to_row) {
clearPresolve();
clearStandardFormLp();
HighsIndexCollection index_collection;
const HighsInt create_error =
create(index_collection, from_row, to_row, model_.lp_.num_row_);
Expand All @@ -3090,6 +3138,7 @@ HighsStatus Highs::deleteRows(const HighsInt num_set_entries,
const HighsInt* set) {
if (num_set_entries == 0) return HighsStatus::kOk;
clearPresolve();
clearStandardFormLp();
HighsIndexCollection index_collection;
const HighsInt create_error =
create(index_collection, num_set_entries, set, model_.lp_.num_row_);
Expand All @@ -3103,6 +3152,7 @@ HighsStatus Highs::deleteRows(const HighsInt num_set_entries,

HighsStatus Highs::deleteRows(HighsInt* mask) {
clearPresolve();
clearStandardFormLp();
const HighsInt original_num_row = model_.lp_.num_row_;
HighsIndexCollection index_collection;
const bool create_error = create(index_collection, mask, original_num_row);
Expand All @@ -3117,6 +3167,7 @@ HighsStatus Highs::deleteRows(HighsInt* mask) {
HighsStatus Highs::scaleCol(const HighsInt col, const double scale_value) {
HighsStatus return_status = HighsStatus::kOk;
clearPresolve();
clearStandardFormLp();
HighsStatus call_status = scaleColInterface(col, scale_value);
return_status = interpretCallStatus(options_.log_options, call_status,
return_status, "scaleCol");
Expand All @@ -3127,6 +3178,7 @@ HighsStatus Highs::scaleCol(const HighsInt col, const double scale_value) {
HighsStatus Highs::scaleRow(const HighsInt row, const double scale_value) {
HighsStatus return_status = HighsStatus::kOk;
clearPresolve();
clearStandardFormLp();
HighsStatus call_status = scaleRowInterface(row, scale_value);
return_status = interpretCallStatus(options_.log_options, call_status,
return_status, "scaleRow");
Expand Down Expand Up @@ -3422,6 +3474,14 @@ void Highs::clearPresolve() {
presolve_.clear();
}

void Highs::clearStandardFormLp() {
standard_form_valid_ = false;
standard_form_offset_ = 0;
standard_form_cost_.clear();
standard_form_rhs_.clear();
standard_form_matrix_.clear();
}

void Highs::invalidateUserSolverData() {
invalidateModelStatus();
invalidateSolution();
Expand Down
2 changes: 1 addition & 1 deletion src/lp_data/HighsIis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void HighsIis::report(const std::string message, const HighsLp& lp) const {
if (num_iis_col > 10 || num_iis_row > 10) return;
printf("\nIIS %s\n===\n", message.c_str());
printf("Column: ");
for (HighsInt iCol = 0; iCol < num_iis_col; iCol++) printf("%9d ", iCol);
for (HighsInt iCol = 0; iCol < num_iis_col; iCol++) printf("%9d ", int(iCol));
printf("\nStatus: ");
for (HighsInt iCol = 0; iCol < num_iis_col; iCol++)
printf("%9s ", iisBoundStatusToString(this->col_bound_[iCol]).c_str());
Expand Down
Loading
Loading