Skip to content

Commit b3df7d7

Browse files
committed
Add option for ordering
1 parent 5d91a9b commit b3df7d7

File tree

9 files changed

+108
-36
lines changed

9 files changed

+108
-36
lines changed

docs/src/options/definitions.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,11 @@
434434
- Type: string
435435
- Default: "both"
436436

437+
## hipo\_ordering
438+
- HiPO matrix reordering: "metis", "amd", "rcm" or "choose"
439+
- Type: string
440+
- Default: "choose"
441+
437442
## hipo\_block\_size
438443
- Block size for dense linear algebra within HiPO
439444
- Type: integer

highs/ipm/IpxWrapper.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,18 @@ HighsStatus solveLpHipo(const HighsOptions& options, HighsTimer& timer,
552552
return HighsStatus::kError;
553553
}
554554

555+
// Reordering heuristic
556+
if (options.hipo_ordering != kHipoMetisString &&
557+
options.hipo_ordering != kHipoAmdString &&
558+
options.hipo_ordering != kHipoRcmString &&
559+
options.hipo_ordering != kHighsChooseString) {
560+
highsLogUser(options.log_options, HighsLogType::kError,
561+
"Unknown value of option %s\n", kHipoOrderingString.c_str());
562+
model_status = HighsModelStatus::kSolveError;
563+
return HighsStatus::kError;
564+
}
565+
hipo_options.ordering = options.hipo_ordering;
566+
555567
// block size option
556568
hipo_options.block_size = options.hipo_block_size;
557569

highs/ipm/hipo/factorhighs/Analyse.cpp

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "ReturnValues.h"
1414
#include "ipm/hipo/auxiliary/Auxiliary.h"
1515
#include "ipm/hipo/auxiliary/Log.h"
16+
#include "rcm/rcm.h"
1617

1718
namespace hipo {
1819

@@ -21,8 +22,8 @@ const Int64 int64_limit = std::numeric_limits<int64_t>::max();
2122

2223
Analyse::Analyse(const std::vector<Int>& rows, const std::vector<Int>& ptr,
2324
const std::vector<Int>& signs, Int nb, const Log* log,
24-
DataCollector& data)
25-
: log_{log}, data_{data} {
25+
DataCollector& data, const std::string& ordering)
26+
: log_{log}, data_{data}, ordering_{ordering} {
2627
// Input the symmetric matrix to be analysed in CSC format.
2728
// rows contains the row indices.
2829
// ptr contains the starting points of each column.
@@ -116,46 +117,74 @@ Int Analyse::getPermutation(bool metis_no2hop) {
116117
}
117118
}
118119

119-
idx_t options[METIS_NOPTIONS];
120-
METIS_SetDefaultOptions(options);
121-
options[METIS_OPTION_SEED] = kMetisSeed;
120+
if (ordering_ == "metis") {
121+
// ----------------------------
122+
// ----- METIS ----------------
123+
// ----------------------------
124+
idx_t options[METIS_NOPTIONS];
125+
METIS_SetDefaultOptions(options);
126+
options[METIS_OPTION_SEED] = kMetisSeed;
122127

123-
// set logging of Metis depending on debug level
124-
options[METIS_OPTION_DBGLVL] = 0;
125-
if (log_->debug(2))
126-
options[METIS_OPTION_DBGLVL] = METIS_DBG_INFO | METIS_DBG_COARSEN;
128+
// set logging of Metis depending on debug level
129+
options[METIS_OPTION_DBGLVL] = 0;
130+
if (log_->debug(2))
131+
options[METIS_OPTION_DBGLVL] = METIS_DBG_INFO | METIS_DBG_COARSEN;
127132

128-
// set no2hop=1 if the user requested it
129-
if (metis_no2hop) options[METIS_OPTION_NO2HOP] = 1;
133+
// set no2hop=1 if the user requested it
134+
if (metis_no2hop) options[METIS_OPTION_NO2HOP] = 1;
130135

131-
if (log_) log_->printDevInfo("Running Metis\n");
136+
if (log_) log_->printDevInfo("Running Metis\n");
132137

133-
Int status = METIS_NodeND(&n_, temp_ptr.data(), temp_rows.data(), NULL,
134-
options, perm_.data(), iperm_.data());
138+
Int status = METIS_NodeND(&n_, temp_ptr.data(), temp_rows.data(), NULL,
139+
options, perm_.data(), iperm_.data());
135140

136-
if (log_) log_->printDevInfo("Metis done\n");
137-
if (status != METIS_OK) {
138-
if (log_) log_->printDevInfo("Error with Metis\n");
139-
return kRetMetisError;
141+
if (log_) log_->printDevInfo("Metis done\n");
142+
if (status != METIS_OK) {
143+
if (log_) log_->printDevInfo("Error with Metis\n");
144+
return kRetMetisError;
145+
}
146+
147+
} else if (ordering_ == "amd") {
148+
// ----------------------------
149+
// ------ AMD -----------------
150+
// ----------------------------
151+
double control[AMD_CONTROL];
152+
amd_defaults(control);
153+
double info[AMD_INFO];
154+
155+
if (log_) log_->printDevInfo("Running AMD\n");
156+
Int status = amd_order(n_, temp_ptr.data(), temp_rows.data(), perm_.data(),
157+
control, info);
158+
if (log_) log_->printDevInfo("AMD done\n");
159+
160+
if (status != AMD_OK) {
161+
if (log_) log_->printDevInfo("Error with AMD\n");
162+
return kRetMetisError;
163+
}
164+
inversePerm(perm_, iperm_);
140165
}
141166

142-
/*
143-
double control[AMD_CONTROL];
144-
amd_defaults(control);
167+
else if (ordering_ == "rcm") {
168+
// ----------------------------
169+
// ------ RCM -----------------
170+
// ----------------------------
145171

146-
double info[AMD_INFO];
172+
if (log_) log_->printDevInfo("Running RCM\n");
173+
Int status = genrcm(n_, temp_ptr.back(), temp_ptr.data(), temp_rows.data(),
174+
perm_.data());
175+
if (log_) log_->printDevInfo("RCM done\n");
147176

148-
Int status = amd_order(n_, temp_ptr.data(), temp_rows.data(), perm_.data(),
149-
control, info);
177+
if (status != 0) {
178+
if (log_) log_->printDevInfo("Error with RCM\n");
179+
return kRetMetisError;
180+
}
181+
inversePerm(perm_, iperm_);
150182

151-
if (status != AMD_OK) {
152-
if (log_) log_->printDevInfo("Error with AMD\n");
153-
return kRetMetisError;
183+
} else {
184+
if (log_) log_->printe("Invalid reordering option\n");
185+
return kRetMetisError;
154186
}
155187

156-
inversePerm(perm_, iperm_);
157-
*/
158-
159188
return kRetOk;
160189
}
161190

highs/ipm/hipo/factorhighs/Analyse.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ class Analyse {
8585
const Log* log_;
8686
DataCollector& data_;
8787

88+
const std::string& ordering_;
89+
8890
// Functions to perform analyse phase
8991
Int getPermutation(bool metis_no2hop);
9092
void permute(const std::vector<Int>& iperm);
@@ -110,7 +112,7 @@ class Analyse {
110112
// Constructor: matrix must be in lower triangular format
111113
Analyse(const std::vector<Int>& rows, const std::vector<Int>& ptr,
112114
const std::vector<Int>& signs, Int nb, const Log* log,
113-
DataCollector& data);
115+
DataCollector& data, const std::string& ordering);
114116

115117
// Run analyse phase and save the result in Symbolic object S
116118
Int run(Symbolic& S);

highs/ipm/hipo/factorhighs/FactorHiGHS.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ void FHsolver::setRegularisation(double reg_p, double reg_d) {
3636

3737
Int FHsolver::analyse(Symbolic& S, const std::vector<Int>& rows,
3838
const std::vector<Int>& ptr,
39-
const std::vector<Int>& signs) {
40-
Analyse an_obj(rows, ptr, signs, nb_, log_, data_);
39+
const std::vector<Int>& signs,
40+
const std::string& ordering) {
41+
Analyse an_obj(rows, ptr, signs, nb_, log_, data_, ordering);
4142
return an_obj.run(S);
4243
}
4344

highs/ipm/hipo/factorhighs/FactorHiGHS.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ class FHsolver {
8383
// ptr, and store symbolic factorisation in object S.
8484
// See ReturnValues.h for errors.
8585
Int analyse(Symbolic& S, const std::vector<Int>& rows,
86-
const std::vector<Int>& ptr, const std::vector<Int>& signs);
86+
const std::vector<Int>& ptr, const std::vector<Int>& signs,
87+
const std::string& ordering = "metis");
8788

8889
// Perform factorise phase of matrix given by rows, ptr, vals, and store
8990
// numerical factorisation in object N. Matrix is moved into the object, so

highs/ipm/hipo/ipm/FactorHiGHSSolver.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,11 @@ Int FactorHiGHSSolver::analyseAS(Symbolic& S) {
398398

399399
log_.printDevInfo("Performing AS analyse phase\n");
400400

401+
std::string ordering = options_.ordering;
402+
if (ordering == kHighsChooseString) ordering = kHipoMetisString;
403+
401404
clock.start();
402-
Int status = FH_.analyse(S, rowsLower, ptrLower, pivot_signs);
405+
Int status = FH_.analyse(S, rowsLower, ptrLower, pivot_signs, ordering);
403406
if (info_) info_->analyse_AS_time = clock.stop();
404407

405408
if (status && log_.debug(2)) {
@@ -437,8 +440,11 @@ Int FactorHiGHSSolver::analyseNE(Symbolic& S, Int64 nz_limit) {
437440

438441
log_.printDevInfo("Performing NE analyse phase\n");
439442

443+
std::string ordering = options_.ordering;
444+
if (ordering == kHighsChooseString) ordering = kHipoMetisString;
445+
440446
clock.start();
441-
Int status = FH_.analyse(S, rowsNE_, ptrNE_, pivot_signs);
447+
Int status = FH_.analyse(S, rowsNE_, ptrNE_, pivot_signs, ordering);
442448
if (info_) info_->analyse_NE_time = clock.stop();
443449

444450
if (status && log_.debug(2)) {

highs/ipm/hipo/ipm/Options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ struct Options {
4040
OptionNla nla = kOptionNlaDefault;
4141
OptionCrossover crossover = kOptionCrossoverDefault;
4242
OptionParallel parallel = kOptionParallelDefault;
43+
std::string ordering = kHighsChooseString;
4344

4445
// Metis options
4546
bool metis_no2hop = false;

highs/lp_data/HighsOptions.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,12 @@ const string kHipoTreeString = "tree";
307307
const string kHipoNodeString = "node";
308308
const string kHipoBothString = "both";
309309

310+
// Strings for HiPO matrix reordering
311+
const string kHipoOrderingString = "hipo_ordering";
312+
const string kHipoMetisString = "metis";
313+
const string kHipoAmdString = "amd";
314+
const string kHipoRcmString = "rcm";
315+
310316
struct HighsOptionsStruct {
311317
// Run-time options read from the command line
312318
std::string presolve;
@@ -371,6 +377,7 @@ struct HighsOptionsStruct {
371377
HighsInt ipm_iteration_limit;
372378
std::string hipo_system;
373379
std::string hipo_parallel_type;
380+
std::string hipo_ordering;
374381
HighsInt hipo_block_size;
375382
bool hipo_metis_no2hop;
376383

@@ -543,6 +550,7 @@ struct HighsOptionsStruct {
543550
ipm_iteration_limit(0),
544551
hipo_system(""),
545552
hipo_parallel_type(""),
553+
hipo_ordering(""),
546554
hipo_block_size(0),
547555
hipo_metis_no2hop(false),
548556
pdlp_scaling(false),
@@ -1262,6 +1270,13 @@ class HighsOptions : public HighsOptionsStruct {
12621270
advanced, &hipo_parallel_type, kHipoBothString);
12631271
records.push_back(record_string);
12641272

1273+
record_string =
1274+
new OptionRecordString(kHipoOrderingString,
1275+
"HiPO matrix reordering option: \"metis\", "
1276+
"\"amd\", \"rcm\" or \"choose\".",
1277+
advanced, &hipo_ordering, kHighsChooseString);
1278+
records.push_back(record_string);
1279+
12651280
record_int = new OptionRecordInt(
12661281
"hipo_block_size", "Block size for dense linear algebra within HiPO",
12671282
advanced, &hipo_block_size, 0, 128, kHighsIInf);

0 commit comments

Comments
 (0)