Skip to content

Commit b83bb81

Browse files
committed
Use options for factorisation
1 parent f9e6999 commit b83bb81

3 files changed

Lines changed: 53 additions & 37 deletions

File tree

highs/ipm/hipo/ipm/Options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ struct Options {
1414
std::string parallel = kHighsChooseString;
1515
std::string parallel_type = kHipoBothString;
1616
std::string ordering = kHighsChooseString;
17+
std::string factor = kHighsChooseString;
1718

1819
// Ipm parameters
1920
Int max_iter = kMaxIterDefault;

highs/ipm/hipo/ipm/Solver.cpp

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ void Solver::setOptions(const HighsOptions& highs_options) {
5252
options_.parallel_type = highs_options.hipo_parallel_type;
5353
options_.nla = highs_options.hipo_system;
5454
options_.ordering = highs_options.hipo_ordering;
55+
options_.factor = highs_options.hipo_factor;
5556
options_.block_size = highs_options.hipo_block_size;
5657

5758
options_orig_ = options_;
@@ -156,22 +157,7 @@ bool Solver::initialise() {
156157
}
157158
LS_->clear();
158159

159-
// Use uplooking factorisation instead of multifrontal if
160-
// - very few operations needed or
161-
// - very few nz per column in L or
162-
// - multifrontal is dominated by assembly operations
163-
bool switch_to_uplooking =
164-
LS_->flops() < kUplookFlopsThresh ||
165-
LS_->nz() < kUplookNzPerColLower * kkt_->n() ||
166-
LS_->flops() < kUplookSpopsRatioLower * LS_->spops() ||
167-
(LS_->nz() < kUplookNzPerColUpper * kkt_->n() &&
168-
LS_->flops() < kUplookSpopsRatioUpper * LS_->spops());
169-
170-
if (switch_to_uplooking) {
171-
LS_.reset(new UpLookingSolver(*kkt_, info_, it_->data, regul_, model_));
172-
LS_->setup();
173-
LS_->clear();
174-
}
160+
chooseFactorisation();
175161

176162
it_->data.append();
177163
it_->data.back().factorisation_used = LS_->type();
@@ -356,22 +342,14 @@ bool Solver::solveNewtonSystem(NewtonDir& delta) {
356342
}
357343

358344
if (terminate) {
359-
if (LS_->type() == kUpLookingType) {
345+
if (switchToMultifrontal()) {
360346
// try FactorHighs factorisation before giving up
361-
LS_.reset(new FactorHighsSolver(*kkt_, options_, model_, regul_, info_,
362-
it_->data, logger_));
363-
if (!LS_) {
364-
info_.status = kStatusError;
365-
return true;
366-
}
367-
LS_->clear();
368347
it_->data.back().factorisation_used = LS_->type();
369-
it_->bad_iter_ = 0;
370348
logger_.printInfo("Switching to FactorHighs because of bad direction\n");
371349
resetToBestIter(iter_ - 1);
372350

373-
// Solve again. This does not create an infinite loop, as the if statement
374-
// cannot trigger in the second solve.
351+
// Solve again. This does not create an infinite loop, as
352+
// switchToMultifrontal() is false in the second solve.
375353
delta.clear();
376354
it_->data.back().omega = 0.0;
377355
terminate = solveNewtonSystem(delta);
@@ -1106,16 +1084,7 @@ bool Solver::checkBadIter() {
11061084
info_.status = kStatusPrimalInfeasible;
11071085
terminate = true;
11081086
} else if (stagnation) {
1109-
if (LS_->type() == kUpLookingType) {
1110-
// try FactorHighs factorisation before giving up
1111-
LS_.reset(new FactorHighsSolver(*kkt_, options_, model_, regul_, info_,
1112-
it_->data, logger_));
1113-
if (!LS_) {
1114-
info_.status = kStatusError;
1115-
return true;
1116-
}
1117-
LS_->clear();
1118-
it_->bad_iter_ = 0;
1087+
if (switchToMultifrontal()) {
11191088
logger_.printInfo("Switching to FactorHighs because of no progress\n");
11201089
resetToBestIter(iter_);
11211090
} else {
@@ -1222,6 +1191,49 @@ void Solver::resetToBestIter(Int iter, bool print) {
12221191
if (did_reset && print) printOutput(true);
12231192
}
12241193

1194+
void Solver::chooseFactorisation() {
1195+
// Use uplooking factorisation instead of multifrontal if
1196+
// - very few operations needed or
1197+
// - very few nz per column in L or
1198+
// - multifrontal is dominated by assembly operations
1199+
const bool should_switch_to_uplooking =
1200+
LS_->flops() < kUplookFlopsThresh ||
1201+
LS_->nz() < kUplookNzPerColLower * kkt_->n() ||
1202+
LS_->flops() < kUplookSpopsRatioLower * LS_->spops() ||
1203+
(LS_->nz() < kUplookNzPerColUpper * kkt_->n() &&
1204+
LS_->flops() < kUplookSpopsRatioUpper * LS_->spops());
1205+
1206+
bool do_switch;
1207+
if (options_.factor == kHipoFactorMultifrontal)
1208+
do_switch = false;
1209+
else if (options_.factor == kHipoFactorUplooking)
1210+
do_switch = true;
1211+
else
1212+
do_switch = should_switch_to_uplooking;
1213+
1214+
if (do_switch) {
1215+
LS_.reset(new UpLookingSolver(*kkt_, info_, it_->data, regul_, model_));
1216+
LS_->setup();
1217+
LS_->clear();
1218+
}
1219+
}
1220+
1221+
bool Solver::switchToMultifrontal() {
1222+
// return true if switch successfull
1223+
if (LS_->type() == kUpLookingType && options_.factor == kHighsChooseString) {
1224+
LS_.reset(new FactorHighsSolver(*kkt_, options_, model_, regul_, info_,
1225+
it_->data, logger_));
1226+
if (!LS_) {
1227+
info_.status = kStatusError;
1228+
return false;
1229+
}
1230+
LS_->clear();
1231+
it_->bad_iter_ = 0;
1232+
return true;
1233+
}
1234+
return false;
1235+
}
1236+
12251237
void Solver::printHeader() const {
12261238
if (iter_ % 20 == 0) {
12271239
logger_.print(

highs/ipm/hipo/ipm/Solver.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,9 @@ class Solver {
334334
void resetOptions();
335335
void reset();
336336
void resetToBestIter(Int iter, bool print = true);
337+
338+
void chooseFactorisation();
339+
bool switchToMultifrontal();
337340
};
338341

339342
} // namespace hipo

0 commit comments

Comments
 (0)