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

Only check for timeout if time_limit is finite, and don't consider timed logging if output_flag is false; formatted #1941

Merged
merged 3 commits into from
Oct 9, 2024
Merged
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
4 changes: 2 additions & 2 deletions docs/src/solvers.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 8 additions & 2 deletions src/io/HMpsFF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -514,8 +516,12 @@ HMpsFF::Parsekey HMpsFF::parseDefault(const HighsLogOptions& log_options,

double getWallTime() {
using namespace std::chrono;
return duration_cast<duration<double> >(wall_clock::now().time_since_epoch())
.count();
const double wall_time = kNoClockCalls
? 0
: duration_cast<duration<double> >(
wall_clock::now().time_since_epoch())
.count();
return wall_time;
}

HMpsFF::Parsekey HMpsFF::parseObjsense(const HighsLogOptions& log_options,
Expand Down
1 change: 0 additions & 1 deletion src/lp_data/Highs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
5 changes: 3 additions & 2 deletions src/mip/HighsMipSolverData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
12 changes: 7 additions & 5 deletions src/presolve/HPresolve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/qpsolver/feasibility_highs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/simplex/HEkk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/simplex/HEkkDual.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion src/simplex/HEkkPrimal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 2 additions & 0 deletions src/simplex/HighsSimplexAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) ||
Expand Down Expand Up @@ -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;
Expand Down
11 changes: 8 additions & 3 deletions src/util/HighsTimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

#include "util/HighsInt.h"

const bool kNoClockCalls = false;

/**
* @brief Clock record structure
*/
Expand Down Expand Up @@ -311,9 +313,12 @@ class HighsTimer {
*/
double getWallTime() {
using namespace std::chrono;
return duration_cast<duration<double> >(
wall_clock::now().time_since_epoch())
.count();
const double wall_time = kNoClockCalls
? 0
: duration_cast<duration<double> >(
wall_clock::now().time_since_epoch())
.count();
return wall_time;
}

virtual ~HighsTimer() = default;
Expand Down
Loading