From e4dad62bfa5d6f5f9f5a570b2404f1f3f873ea3d Mon Sep 17 00:00:00 2001 From: JAJHall Date: Sat, 12 Oct 2024 10:07:50 +0100 Subject: [PATCH 1/4] Verified that direction to read a sparse solution file is possible from the command line --- check/TestCheckSolution.cpp | 14 +++++++++++++- check/TestNames.cpp | 3 +-- src/lp_data/HighsOptions.h | 2 +- src/lp_data/HighsSolve.cpp | 2 +- src/pdlp/CupdlpWrapper.cpp | 14 ++++++-------- src/util/HFactor.h | 2 +- 6 files changed, 23 insertions(+), 14 deletions(-) diff --git a/check/TestCheckSolution.cpp b/check/TestCheckSolution.cpp index d0f2309b1c..8e02f0d023 100644 --- a/check/TestCheckSolution.cpp +++ b/check/TestCheckSolution.cpp @@ -402,6 +402,7 @@ void runWriteReadCheckSolution(Highs& highs, const std::string model, HighsStatus return_status; std::string solution_file; HighsModelStatus status = HighsModelStatus::kNotset; + if (dev_run) printf("\nSolving model %s from scratch\n", model.c_str()); run_status = highs.run(); REQUIRE(run_status == HighsStatus::kOk); @@ -409,6 +410,9 @@ void runWriteReadCheckSolution(Highs& highs, const std::string model, REQUIRE(status == require_model_status); solution_file = model + ".sol"; + if (dev_run) + printf("Writing solution in style %d to %s\n", int(write_solution_style), + solution_file.c_str()); if (dev_run) return_status = highs.writeSolution("", write_solution_style); return_status = highs.writeSolution(solution_file, write_solution_style); REQUIRE(return_status == HighsStatus::kOk); @@ -418,6 +422,7 @@ void runWriteReadCheckSolution(Highs& highs, const std::string model, // primalDualInfeasible1Lp has no values in the solution file so, // after it's read, HiGHS::solution.value_valid is false + if (dev_run) printf("Reading solution from %s\n", solution_file.c_str()); return_status = highs.readSolution(solution_file); if (value_valid) { REQUIRE(return_status == HighsStatus::kOk); @@ -431,7 +436,14 @@ void runWriteReadCheckSolution(Highs& highs, const std::string model, } else { REQUIRE(return_status == HighsStatus::kError); } - std::remove(solution_file.c_str()); + if (dev_run) printf("Solving model from solution read from file\n"); + run_status = highs.run(); + REQUIRE(run_status == HighsStatus::kOk); + + status = highs.getModelStatus(); + REQUIRE(status == require_model_status); + + // std::remove(solution_file.c_str()); } void runSetLpSolution(const std::string model) { diff --git a/check/TestNames.cpp b/check/TestNames.cpp index f0d11fc4a8..4aceee0ca6 100644 --- a/check/TestNames.cpp +++ b/check/TestNames.cpp @@ -120,13 +120,12 @@ TEST_CASE("highs-names", "[highs_names]") { } TEST_CASE("highs-model-name", "[model_names]") { - Highs highs; const HighsLp& lp = highs.getLp(); std::string name = lp.model_name_; REQUIRE(name == ""); - + highs.passModelName("new_name"); name = lp.model_name_; REQUIRE(name == "new_name"); diff --git a/src/lp_data/HighsOptions.h b/src/lp_data/HighsOptions.h index 208bcd1802..df45d4de87 100644 --- a/src/lp_data/HighsOptions.h +++ b/src/lp_data/HighsOptions.h @@ -555,7 +555,7 @@ struct HighsOptionsStruct { #endif mip_improving_solution_save(false), mip_improving_solution_report_sparse(false), - mip_improving_solution_file("") {}; + mip_improving_solution_file(""){}; }; // For now, but later change so HiGHS properties are string based so that new diff --git a/src/lp_data/HighsSolve.cpp b/src/lp_data/HighsSolve.cpp index c03837ac01..233b16adcd 100644 --- a/src/lp_data/HighsSolve.cpp +++ b/src/lp_data/HighsSolve.cpp @@ -127,7 +127,7 @@ HighsStatus solveLp(HighsLpSolverObject& solver_object, const string message) { return HighsStatus::kError; } } // options.run_crossover == kHighsOnString - } // unwelcome_ipx_status + } // unwelcome_ipx_status } else { // PDLP has been used, so check whether claim of optimality // satisfies the HiGHS criteria diff --git a/src/pdlp/CupdlpWrapper.cpp b/src/pdlp/CupdlpWrapper.cpp index d41f14e595..31fa31e1e8 100644 --- a/src/pdlp/CupdlpWrapper.cpp +++ b/src/pdlp/CupdlpWrapper.cpp @@ -207,7 +207,7 @@ HighsStatus solveLpCupdlp(const HighsOptions& options, HighsTimer& timer, #if CUPDLP_DEBUG analysePdlpSolution(options, lp, highs_solution); #endif - + free(cost); free(lower); free(upper); @@ -225,7 +225,7 @@ HighsStatus solveLpCupdlp(const HighsOptions& options, HighsTimer& timer, free(prob->lower); free(prob->upper); free(prob->rhs); - + free(prob->hasLower); free(prob->hasUpper); @@ -233,7 +233,7 @@ HighsStatus solveLpCupdlp(const HighsOptions& options, HighsTimer& timer, free(prob->data->csr_matrix->rowMatIdx); free(prob->data->csr_matrix->rowMatElem); free(prob->data->csr_matrix); - + free(prob->data->csc_matrix->colMatBeg); free(prob->data->csc_matrix->colMatIdx); free(prob->data->csc_matrix->colMatElem); @@ -246,13 +246,11 @@ HighsStatus solveLpCupdlp(const HighsOptions& options, HighsTimer& timer, free(csc_cpu->colMatBeg); free(csc_cpu->colMatIdx); free(csc_cpu->colMatElem); - + free(csc_cpu); - if (scaling->rowScale != nullptr) - free(scaling->rowScale); - if (scaling->colScale != nullptr) - free(scaling->colScale); + if (scaling->rowScale != nullptr) free(scaling->rowScale); + if (scaling->colScale != nullptr) free(scaling->colScale); free(scaling); return HighsStatus::kOk; diff --git a/src/util/HFactor.h b/src/util/HFactor.h index 03cb8d8b1d..2f75260d8a 100644 --- a/src/util/HFactor.h +++ b/src/util/HFactor.h @@ -132,7 +132,7 @@ class HFactor { build_timer_(nullptr), nwork(0), u_merit_x(0), - u_total_x(0) {}; + u_total_x(0){}; /** * @brief Copy problem size and pointers of constraint matrix, and set From cfeaa46105b1ec54e728895eb8a1c7f66e0c8c0b Mon Sep 17 00:00:00 2001 From: JAJHall Date: Sat, 12 Oct 2024 12:19:31 +0100 Subject: [PATCH 2/4] Better testing; formatted --- check/TestCheckSolution.cpp | 37 ++++++++++++++++++++++++++++++++---- src/lp_data/HighsLpUtils.cpp | 1 + 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/check/TestCheckSolution.cpp b/check/TestCheckSolution.cpp index 8e02f0d023..ff17e1bac6 100644 --- a/check/TestCheckSolution.cpp +++ b/check/TestCheckSolution.cpp @@ -443,7 +443,7 @@ void runWriteReadCheckSolution(Highs& highs, const std::string model, status = highs.getModelStatus(); REQUIRE(status == require_model_status); - // std::remove(solution_file.c_str()); + std::remove(solution_file.c_str()); } void runSetLpSolution(const std::string model) { @@ -452,7 +452,7 @@ void runSetLpSolution(const std::string model) { std::string model_file = std::string(HIGHS_DIR) + "/check/instances/" + model + ".mps"; const HighsInfo& info = highs.getInfo(); - if (dev_run) printf("\nSolving from scratch\n"); + if (dev_run) printf("\nSolving %s from scratch\n", model.c_str()); highs.setOptionValue("output_flag", dev_run); if (dev_run) highs.setOptionValue("log_dev_level", 1); @@ -472,8 +472,8 @@ void runSetLpSolution(const std::string model) { REQUIRE(return_status == HighsStatus::kOk); highs.run(); - // Use a reduction in iteration count as a anity check that starting - // from the optimal solution has worked + // Use a reduction in iteration count as a sanity check that + // starting from the optimal solution has worked HighsInt simplex_iteration_count1 = info.simplex_iteration_count; if (dev_run) printf( @@ -482,4 +482,33 @@ void runSetLpSolution(const std::string model) { model.c_str(), (int)simplex_iteration_count0, (int)simplex_iteration_count1); REQUIRE(simplex_iteration_count1 < simplex_iteration_count0); + + // Now write a sparse solution, and read it in to hot start + HighsInt write_solution_style = kSolutionStyleSparse; + std::string solution_file = model + ".sol"; + if (dev_run) printf("Writing sparse solution to %s\n", solution_file.c_str()); + if (dev_run) return_status = highs.writeSolution(""); + return_status = highs.writeSolution(solution_file, write_solution_style); + REQUIRE(return_status == HighsStatus::kOk); + + highs.clear(); + highs.setOptionValue("output_flag", dev_run); + if (dev_run) highs.setOptionValue("log_dev_level", 1); + + highs.readModel(model_file); + if (dev_run) + printf("Reading sparse solution from %s\n", solution_file.c_str()); + return_status = highs.readSolution(solution_file); + REQUIRE(return_status == HighsStatus::kOk); + + if (dev_run) printf("Solving model from sparse solution read from file\n"); + HighsStatus run_status = highs.run(); + REQUIRE(run_status == HighsStatus::kOk); + + HighsModelStatus status = highs.getModelStatus(); + REQUIRE(status == HighsModelStatus::kOptimal); + + highs.clear(); + + std::remove(solution_file.c_str()); } diff --git a/src/lp_data/HighsLpUtils.cpp b/src/lp_data/HighsLpUtils.cpp index 465ee64aab..7fccd0ca61 100644 --- a/src/lp_data/HighsLpUtils.cpp +++ b/src/lp_data/HighsLpUtils.cpp @@ -2095,6 +2095,7 @@ HighsStatus readSolutionFile(const std::string filename, if (style == kSolutionStyleSparse) assert(sparse); if (sparse) { num_col = -num_col; + assert(num_col <= lp_num_col); } else { if (num_col != lp_num_col) { highsLogUser(log_options, HighsLogType::kError, From ef1549d18fc9975a319d83875166715f5680b33c Mon Sep 17 00:00:00 2001 From: JAJHall Date: Wed, 16 Oct 2024 08:16:20 +0100 Subject: [PATCH 3/4] Frigged formatting --- src/lp_data/HighsOptions.h | 2 +- src/util/HFactor.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lp_data/HighsOptions.h b/src/lp_data/HighsOptions.h index df45d4de87..208bcd1802 100644 --- a/src/lp_data/HighsOptions.h +++ b/src/lp_data/HighsOptions.h @@ -555,7 +555,7 @@ struct HighsOptionsStruct { #endif mip_improving_solution_save(false), mip_improving_solution_report_sparse(false), - mip_improving_solution_file(""){}; + mip_improving_solution_file("") {}; }; // For now, but later change so HiGHS properties are string based so that new diff --git a/src/util/HFactor.h b/src/util/HFactor.h index 2f75260d8a..03cb8d8b1d 100644 --- a/src/util/HFactor.h +++ b/src/util/HFactor.h @@ -132,7 +132,7 @@ class HFactor { build_timer_(nullptr), nwork(0), u_merit_x(0), - u_total_x(0){}; + u_total_x(0) {}; /** * @brief Copy problem size and pointers of constraint matrix, and set From 66aaa97e1e7a4cebcdfa671a922621fc1231c498 Mon Sep 17 00:00:00 2001 From: JAJHall Date: Wed, 16 Oct 2024 08:24:18 +0100 Subject: [PATCH 4/4] Frig format again --- src/lp_data/HighsSolve.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lp_data/HighsSolve.cpp b/src/lp_data/HighsSolve.cpp index 233b16adcd..c03837ac01 100644 --- a/src/lp_data/HighsSolve.cpp +++ b/src/lp_data/HighsSolve.cpp @@ -127,7 +127,7 @@ HighsStatus solveLp(HighsLpSolverObject& solver_object, const string message) { return HighsStatus::kError; } } // options.run_crossover == kHighsOnString - } // unwelcome_ipx_status + } // unwelcome_ipx_status } else { // PDLP has been used, so check whether claim of optimality // satisfies the HiGHS criteria