Skip to content

Commit 06309ae

Browse files
committed
Removed probing local time-out, cleaned up code following @fwesselm's comments; updated FEATURES.md
1 parent 1c2cb33 commit 06309ae

File tree

2 files changed

+57
-49
lines changed

2 files changed

+57
-49
lines changed

FEATURES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,9 @@ HiPO is now capable of solving convex QP problems. Option
2525
solver="qpasm" selects the previous active-set QP solver, while
2626
solver="hipo" or solver="ipm" selects the HiPO solver.
2727

28+
Following PR [#2865](https://github.com/ERGO-Code/HiGHS/pull/2865),
29+
HiGHS performs logging during probing in MIP presolve and checks for
30+
time-out
31+
2832
## Build changes
2933

highs/presolve/HPresolve.cpp

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,70 +1683,74 @@ HPresolve::Result HPresolve::runProbing(HighsPostsolveStack& postsolve_stack) {
16831683
};
16841684
}
16851685

1686-
assert(mipsolver);
1687-
// Don't log probing for presolve before restart
1686+
// Set up logging for probing
16881687
const bool silent = silentLog();
16891688
HighsInt iBin = -1;
16901689
HighsInt iBin_probed = -1;
16911690
HighsInt num_binary = binaries.size();
1692-
double log_tt_interval = 5.0;
1693-
double tt0 = this->timer->read();
1691+
double tt = this->timer->read();
1692+
double tt0 = tt;
16941693
double log_tt = tt0;
16951694
HighsInt log_iBin_probed = iBin_probed;
1696-
double time_remaining = options->time_limit - tt0;
1697-
double probing_time_limit = 0.1 * time_remaining;
1698-
bool logged_probing_time_limit = false;
1695+
auto probingLog = [&]() {
1696+
if (silent || options->timeless_log) return;
1697+
// Ensure that enough time has elapsed, and at least on binary
1698+
// has been probed
1699+
const double log_tt_interval = 5.0;
1700+
if (tt > log_tt + log_tt_interval && iBin_probed > log_iBin_probed) {
1701+
// Get the average rate from the start of probing
1702+
assert(iBin_probed > 0);
1703+
double rate0 = (tt - tt0) / double(iBin_probed);
1704+
// Get the average rate since last logging
1705+
HighsInt dl_iBin_probed = iBin_probed - log_iBin_probed;
1706+
assert(dl_iBin_probed > 0);
1707+
double rate1 = (tt - log_tt) / double(dl_iBin_probed);
1708+
// Assess the time for probing based on the greater rate
1709+
double rate = std::max(rate0, rate1);
1710+
std::string rate_str =
1711+
" (rate " + highsTimeToString(1e3 * rate) + "/ms";
1712+
double expected_probing_finish_time =
1713+
tt + rate * (num_binary - iBin_probed);
1714+
std::string expected_probing_finish_time_str =
1715+
" => expected probing finish time " +
1716+
highsTimeSecondToString(expected_probing_finish_time) + ")";
1717+
std::string time_str = highsTimeSecondToString(tt);
1718+
highsLogUser(options->log_options, HighsLogType::kInfo,
1719+
" Considered %d / %d binaries; %d probed %s%s %s\n",
1720+
int(iBin), int(num_binary), int(iBin_probed),
1721+
rate_str.c_str(), expected_probing_finish_time_str.c_str(),
1722+
time_str.c_str());
1723+
log_tt = tt;
1724+
log_iBin_probed = iBin_probed;
1725+
}
1726+
};
1727+
16991728
for (const auto& binvar : binaries) {
1729+
// Count the binaries considered
17001730
iBin++;
1701-
HighsInt i = std::get<3>(binvar);
17021731

1732+
HighsInt i = std::get<3>(binvar);
17031733
if (cliquetable.getSubstitution(i) != nullptr || !domain.isBinary(i))
17041734
continue;
17051735

1736+
// Count the binaries probed
17061737
iBin_probed++;
1707-
double tt = this->timer->read();
1708-
if (tt > log_tt + log_tt_interval && iBin_probed > log_iBin_probed) {
1709-
if (!silent && !logged_probing_time_limit &&
1710-
probing_time_limit < kHighsInf && !options->timeless_log) {
1711-
highsLogUser(options->log_options, HighsLogType::kInfo,
1712-
" Probing %d binaries with a time limit of %s\n",
1713-
int(num_binary),
1714-
highsTimeSecondToString(probing_time_limit).c_str());
1715-
logged_probing_time_limit = true;
1716-
}
1717-
if (tt > probing_time_limit) {
1718-
if (!silent)
1719-
highsLogUser(
1720-
options->log_options, HighsLogType::kWarning,
1721-
" Probing time limit reached: solver behaviour may be "
1722-
"non-deterministic\n");
1723-
return Result::kStopped;
1724-
}
1725-
if (!silent && !options->timeless_log) {
1726-
assert(iBin_probed > 0);
1727-
HighsInt dl_iBin_probed = iBin_probed - log_iBin_probed;
1728-
assert(dl_iBin_probed > 0);
1729-
double rate0 = (tt - tt0) / double(iBin_probed);
1730-
double rate1 = (tt - log_tt) / double(dl_iBin_probed);
1731-
double rate = std::max(rate0, rate1);
1732-
std::string rate_str =
1733-
" (rate " + highsTimeToString(1e3 * rate) + "/ms";
1734-
double expected_probing_finish_time =
1735-
tt + rate * (num_binary - iBin_probed);
1736-
std::string expected_probing_finish_time_str =
1737-
" => expected probing finish time " +
1738-
highsTimeSecondToString(expected_probing_finish_time) + ")";
1739-
std::string time_str = highsTimeSecondToString(tt);
1740-
highsLogUser(
1741-
options->log_options, HighsLogType::kInfo,
1742-
" Considered %d / %d binaries; %d probed %s%s %s\n", int(iBin),
1743-
int(num_binary), int(iBin_probed), rate_str.c_str(),
1744-
expected_probing_finish_time_str.c_str(), time_str.c_str());
1745-
log_tt = tt;
1746-
log_iBin_probed = iBin_probed;
1747-
}
1738+
1739+
// Check for timeout
1740+
tt = this->timer->read();
1741+
if (tt > options->time_limit) {
1742+
highsLogUser(options->log_options, HighsLogType::kInfo,
1743+
"Time limit reached in probing: "
1744+
"consider not using probing by setting option "
1745+
"presolve_rule_off to 2^%-d = %d\n",
1746+
int(kPresolveRuleProbing),
1747+
int(std::pow(int(2), int(kPresolveRuleProbing))));
1748+
return Result::kStopped;
17481749
}
17491750

1751+
// Possibly log probing
1752+
probingLog();
1753+
17501754
bool tightenLimits = (numProbed - oldNumProbed) >= 2500;
17511755

17521756
// when a large percentage of columns have been deleted, stop this round

0 commit comments

Comments
 (0)