From e134a0f44b079ad6b9bf679e6f0f0009de340fe4 Mon Sep 17 00:00:00 2001 From: jajhall Date: Fri, 20 Sep 2024 14:26:13 +0100 Subject: [PATCH 1/3] Only check for timeout if time_limit is finite, and don't consider timed logging if output_flag is false; formatted --- docs/src/solvers.md | 4 ++-- src/lp_data/Highs.cpp | 1 - src/lp_data/HighsOptions.h | 2 +- src/mip/HighsMipSolverData.cpp | 5 +++-- src/presolve/HPresolve.cpp | 12 +++++++----- src/qpsolver/feasibility_highs.hpp | 7 +++++-- src/simplex/HEkk.cpp | 3 ++- src/simplex/HEkkDual.cpp | 2 +- src/simplex/HEkkPrimal.cpp | 2 +- src/simplex/HighsSimplexAnalysis.cpp | 2 ++ src/util/HFactor.h | 2 +- 11 files changed, 25 insertions(+), 17 deletions(-) diff --git a/docs/src/solvers.md b/docs/src/solvers.md index 0b881c14c0..6734ec694a 100644 --- a/docs/src/solvers.md +++ b/docs/src/solvers.md @@ -21,8 +21,8 @@ J. A. J. Hall, Mathematical Programming Computation, 10 (1), 119-142, * Setting the option [__solver__](@ref option-solver) to "simplex" forces the simplex solver to be used * The option [__simplex\_strategy__](@ref option-simplex_strategy) -determines whether the primal solver or one of the parallel solvers is -to be used. + determines whether the primal solver or one of the parallel solvers is + to be used. #### Interior point diff --git a/src/lp_data/Highs.cpp b/src/lp_data/Highs.cpp index 43cd3094c6..5521036121 100644 --- a/src/lp_data/Highs.cpp +++ b/src/lp_data/Highs.cpp @@ -4336,7 +4336,6 @@ HighsStatus Highs::returnFromRun(const HighsStatus run_return_status, const bool solved_as_mip = !options_.solver.compare(kHighsChooseString) && model_.isMip() && !options_.solve_relaxation; if (!solved_as_mip) reportSolvedLpQpStats(); - return returnFromHighs(return_status); } 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/mip/HighsMipSolverData.cpp b/src/mip/HighsMipSolverData.cpp index 884f7a4713..cb72d1f6e7 100644 --- a/src/mip/HighsMipSolverData.cpp +++ b/src/mip/HighsMipSolverData.cpp @@ -1872,8 +1872,9 @@ bool HighsMipSolverData::checkLimits(int64_t nodeOffset) const { // const double time = mipsolver.timer_.read(mipsolver.timer_.solve_clock); // printf("checkLimits: time = %g\n", time); - if (mipsolver.timer_.read(mipsolver.timer_.solve_clock) >= - options.time_limit) { + if (options.time_limit < kHighsInf && + mipsolver.timer_.read(mipsolver.timer_.solve_clock) >= + options.time_limit) { if (mipsolver.modelstatus_ == HighsModelStatus::kNotset) { highsLogDev(options.log_options, HighsLogType::kInfo, "Reached time limit\n"); diff --git a/src/presolve/HPresolve.cpp b/src/presolve/HPresolve.cpp index 10e17ab95f..475f43d60f 100644 --- a/src/presolve/HPresolve.cpp +++ b/src/presolve/HPresolve.cpp @@ -4254,12 +4254,13 @@ HPresolve::Result HPresolve::presolve(HighsPostsolveStack& postsolve_stack) { HighsInt numCol = model->num_col_ - numDeletedCols; HighsInt numRow = model->num_row_ - numDeletedRows; HighsInt numNonz = Avalue.size() - freeslots.size(); + // Only read the run time if it's to be printed + const double run_time = + options->output_flag ? this->timer->read(run_clock) : 0; #ifndef NDEBUG - std::string time_str = - " " + std::to_string(this->timer->read(run_clock)) + "s"; + std::string time_str = " " + std::to_string(run_time) + "s"; #else - std::string time_str = - " " + std::to_string(int(this->timer->read(run_clock))) + "s"; + std::string time_str = " " + std::to_string(int(run_time)) + "s"; #endif highsLogUser(options->log_options, HighsLogType::kInfo, "%" HIGHSINT_FORMAT " rows, %" HIGHSINT_FORMAT @@ -4487,7 +4488,8 @@ HPresolve::Result HPresolve::checkLimits(HighsPostsolveStack& postsolve_stack) { if ((numreductions & 1023u) == 0) { assert(timer); assert(run_clock >= 0); - if (timer->read(run_clock) >= options->time_limit) { + if (options->time_limit < kHighsInf && + timer->read(run_clock) >= options->time_limit) { return Result::kStopped; } } diff --git a/src/qpsolver/feasibility_highs.hpp b/src/qpsolver/feasibility_highs.hpp index 7f8daf3da4..8594be00df 100644 --- a/src/qpsolver/feasibility_highs.hpp +++ b/src/qpsolver/feasibility_highs.hpp @@ -61,8 +61,11 @@ static void computeStartingPointHighs(Instance& instance, highs.setOptionValue("presolve", "on"); - highs.setOptionValue("time_limit", settings.time_limit - - timer.readRunHighsClock()); + const double use_time_limit = settings.time_limit < kHighsInf ? + settings.time_limit - timer.readRunHighsClock() : + kHighsInf; + + highs.setOptionValue("time_limit", use_time_limit); HighsLp lp; lp.a_matrix_.index_ = instance.A.mat.index; diff --git a/src/simplex/HEkk.cpp b/src/simplex/HEkk.cpp index 32fc0b40e3..e244f55e12 100644 --- a/src/simplex/HEkk.cpp +++ b/src/simplex/HEkk.cpp @@ -3458,7 +3458,8 @@ bool HEkk::bailout() { model_status_ == HighsModelStatus::kIterationLimit || model_status_ == HighsModelStatus::kObjectiveBound || model_status_ == HighsModelStatus::kObjectiveTarget); - } else if (timer_->readRunHighsClock() > options_->time_limit) { + } else if (options_->time_limit < kHighsInf && + timer_->readRunHighsClock() > options_->time_limit) { solve_bailout_ = true; model_status_ = HighsModelStatus::kTimeLimit; } else if (iteration_count_ >= options_->simplex_iteration_limit) { diff --git a/src/simplex/HEkkDual.cpp b/src/simplex/HEkkDual.cpp index 5e2e49755f..a9f53ce0ee 100644 --- a/src/simplex/HEkkDual.cpp +++ b/src/simplex/HEkkDual.cpp @@ -1403,7 +1403,7 @@ void HEkkDual::reportRebuild(const HighsInt reason_for_rebuild) { analysis->rebuild_reason = reason_for_rebuild; analysis->rebuild_reason_string = ekk_instance_.rebuildReason(reason_for_rebuild); - analysis->invertReport(); + if (ekk_instance_.options_->output_flag) analysis->invertReport(); analysis->simplexTimerStop(ReportRebuildClock); } diff --git a/src/simplex/HEkkPrimal.cpp b/src/simplex/HEkkPrimal.cpp index c440fb0f07..51d9c8abee 100644 --- a/src/simplex/HEkkPrimal.cpp +++ b/src/simplex/HEkkPrimal.cpp @@ -2676,7 +2676,7 @@ void HEkkPrimal::reportRebuild(const HighsInt reason_for_rebuild) { analysis->rebuild_reason = reason_for_rebuild; analysis->rebuild_reason_string = ekk_instance_.rebuildReason(reason_for_rebuild); - analysis->invertReport(); + if (ekk_instance_.options_->output_flag) analysis->invertReport(); analysis->simplexTimerStop(ReportRebuildClock); } diff --git a/src/simplex/HighsSimplexAnalysis.cpp b/src/simplex/HighsSimplexAnalysis.cpp index 13522088e8..05aed5a3f1 100644 --- a/src/simplex/HighsSimplexAnalysis.cpp +++ b/src/simplex/HighsSimplexAnalysis.cpp @@ -333,6 +333,7 @@ void HighsSimplexAnalysis::iterationReport() { iterationReport(false); } +// Called externally - from HEkkPrimal/Dual::reportRebuild void HighsSimplexAnalysis::invertReport() { if (*log_options.log_dev_level) { const bool header = (num_invert_report_since_last_header < 0) || @@ -373,6 +374,7 @@ void HighsSimplexAnalysis::invertReport(const bool header) { if (!header) num_invert_report_since_last_header++; } +// Called externally - from HEkk::returnFromSolve void HighsSimplexAnalysis::userInvertReport(const bool force) { if (last_user_log_time < 0) { const bool header = true; 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 86e533fec2dbb0d76f9eb51c0466f30afbd26e15 Mon Sep 17 00:00:00 2001 From: jajhall Date: Mon, 23 Sep 2024 14:24:18 +0100 Subject: [PATCH 2/3] Added const bool kNoClockCalls to switch off/on most clocks; formatted --- src/io/HMpsFF.cpp | 10 ++++++++-- src/util/HighsTimer.h | 11 ++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/io/HMpsFF.cpp b/src/io/HMpsFF.cpp index 414e1fcbbb..cd52109526 100644 --- a/src/io/HMpsFF.cpp +++ b/src/io/HMpsFF.cpp @@ -19,6 +19,8 @@ namespace free_format_parser { +const bool kNoClockCalls = false; + FreeFormatParserReturnCode HMpsFF::loadProblem( const HighsLogOptions& log_options, const std::string filename, HighsModel& model) { @@ -514,8 +516,12 @@ HMpsFF::Parsekey HMpsFF::parseDefault(const HighsLogOptions& log_options, double getWallTime() { using namespace std::chrono; - return duration_cast >(wall_clock::now().time_since_epoch()) - .count(); + const double wall_time = kNoClockCalls + ? 0 + : duration_cast >( + wall_clock::now().time_since_epoch()) + .count(); + return wall_time; } HMpsFF::Parsekey HMpsFF::parseObjsense(const HighsLogOptions& log_options, diff --git a/src/util/HighsTimer.h b/src/util/HighsTimer.h index 13b1617eff..6371b47312 100644 --- a/src/util/HighsTimer.h +++ b/src/util/HighsTimer.h @@ -24,6 +24,8 @@ #include "util/HighsInt.h" +const bool kNoClockCalls = false; + /** * @brief Clock record structure */ @@ -311,9 +313,12 @@ class HighsTimer { */ double getWallTime() { using namespace std::chrono; - return duration_cast >( - wall_clock::now().time_since_epoch()) - .count(); + const double wall_time = kNoClockCalls + ? 0 + : duration_cast >( + wall_clock::now().time_since_epoch()) + .count(); + return wall_time; } virtual ~HighsTimer() = default; From 70fdc014ac39843b9003ab69ef6505e03f546062 Mon Sep 17 00:00:00 2001 From: jajhall Date: Tue, 8 Oct 2024 16:06:34 +0100 Subject: [PATCH 3/3] Clang format 18 frig --- 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