Skip to content

Commit f99b3c3

Browse files
committed
Norm and bound scaling
1 parent e070929 commit f99b3c3

File tree

3 files changed

+37
-26
lines changed

3 files changed

+37
-26
lines changed

highs/ipm/hipo/ipm/Model.cpp

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace hipo {
99
Int Model::init(const Int num_var, const Int num_con, const double* obj,
1010
const double* rhs, const double* lower, const double* upper,
1111
const Int* A_ptr, const Int* A_rows, const double* A_vals,
12-
const char* constraints, double offset) {
12+
const char* constraints, double offset, OptionScaling opt) {
1313
// copy the input into the model
1414

1515
if (checkData(num_var, num_con, obj, rhs, lower, upper, A_ptr, A_rows, A_vals,
@@ -45,7 +45,7 @@ Int Model::init(const Int num_var, const Int num_con, const double* obj,
4545
constraints_ = std::vector<char>(constraints, constraints + m_);
4646

4747
preprocess();
48-
scale();
48+
scale(opt);
4949
reformulate();
5050
denseColumns();
5151
computeNorms();
@@ -317,17 +317,14 @@ void Model::print(const LogHighs& log) const {
317317
}
318318
if (std::isinf(bmin)) bmin = 0.0;
319319

320-
// compute max and min for bounds
320+
// compute max and min inerval for bounds
321321
double boundmin = kHighsInf;
322322
double boundmax = 0.0;
323323
for (Int i = 0; i < n_; ++i) {
324-
if (lower_[i] != 0.0 && std::isfinite(lower_[i])) {
325-
boundmin = std::min(boundmin, std::abs(lower_[i]));
326-
boundmax = std::max(boundmax, std::abs(lower_[i]));
327-
}
328-
if (upper_[i] != 0.0 && std::isfinite(upper_[i])) {
329-
boundmin = std::min(boundmin, std::abs(upper_[i]));
330-
boundmax = std::max(boundmax, std::abs(upper_[i]));
324+
if (std::isfinite(lower_[i]) && std::isfinite(upper_[i])) {
325+
const double interval = std::abs(upper_[i] - lower_[i]);
326+
boundmin = std::min(boundmin, interval);
327+
boundmax = std::max(boundmax, interval);
331328
}
332329
}
333330
if (std::isinf(boundmin)) boundmin = 0.0;
@@ -405,7 +402,7 @@ static double roundToPowerOf2(double d) {
405402
return std::ldexp(1.0, exp);
406403
}
407404

408-
void Model::scale() {
405+
void Model::scale(OptionScaling opt) {
409406
// Compute scaling:
410407
// A -> R * A * C
411408
// b -> R * b
@@ -420,7 +417,16 @@ void Model::scale() {
420417
colscale_.resize(n_, 1.0);
421418
rowscale_.resize(m_, 1.0);
422419

423-
CRscaling();
420+
if (opt == kOptionCRscaling) {
421+
CRscaling();
422+
} else if (opt == kOptionNormScaling) {
423+
const Int num_passes = 2;
424+
for (Int pass = 0; pass < num_passes; ++pass) {
425+
onePassNormScaling();
426+
boundScaling();
427+
}
428+
}
429+
424430
applyScaling();
425431
}
426432

@@ -434,15 +440,15 @@ bool Model::needScaling() {
434440
}
435441
}
436442

437-
return false;
438-
439443
// check bounds
440444
for (Int i = 0; i < n_; ++i) {
441445
if (std::isfinite(lower_[i]) && std::isfinite(upper_[i])) {
442446
const double diff = std::abs(lower_[i] - upper_[i]);
443447
if (diff < kSmallBoundDiff || diff > kLargeBoundDiff) return true;
444448
}
445449
}
450+
451+
return false;
446452
}
447453

448454
void Model::CRscaling() {
@@ -483,8 +489,8 @@ void Model::applyScaling() {
483489
}
484490

485491
void Model::onePassNormScaling() {
486-
// Compute a single pass of infinity-norm row scaling and a single pass of
487-
// infinity-norm col scaling.
492+
// Compute a single pass of infinity-norm geo-mean row scaling and col
493+
// scaling.
488494

489495
// infinity norm of rows
490496
std::vector<double> norm_rows(m_);
@@ -500,7 +506,7 @@ void Model::onePassNormScaling() {
500506

501507
// apply row scaling
502508
for (Int i = 0; i < m_; ++i)
503-
rowscale_[i] *= roundToPowerOf2(1.0 / norm_rows[i]);
509+
rowscale_[i] *= roundToPowerOf2(1.0 / std::sqrt(norm_rows[i]));
504510

505511
// infinity norm of columns
506512
std::vector<double> norm_cols(n_);
@@ -516,20 +522,24 @@ void Model::onePassNormScaling() {
516522

517523
// apply col scaling
518524
for (Int i = 0; i < n_; ++i)
519-
colscale_[i] *= roundToPowerOf2(1.0 / norm_cols[i]);
525+
colscale_[i] *= roundToPowerOf2(1.0 / std::sqrt(norm_cols[i]));
520526
}
521527

522528
void Model::boundScaling() {
529+
// Compute scaling so that bound intervals (upper-lower) are not too small or
530+
// too large.
531+
523532
for (Int i = 0; i < n_; ++i) {
524533
if (std::isfinite(lower_[i]) && std::isfinite(upper_[i])) {
525-
const double l = lower_[i] * colscale_[i];
526-
const double u = upper_[i] * colscale_[i];
534+
const double l = lower_[i] / colscale_[i];
535+
const double u = upper_[i] / colscale_[i];
527536
const double diff = std::abs(u - l);
528537

529538
if (diff < kSmallBoundDiff)
530-
colscale_[i] *= roundToPowerOf2(kSmallBoundDiff / diff);
531-
else if (diff > kLargeBoundDiff)
532-
colscale_[i] *= roundToPowerOf2(kLargeBoundDiff / diff);
539+
colscale_[i] *= roundToPowerOf2(diff / kSmallBoundDiff);
540+
else if (diff > kLargeBoundDiff) {
541+
colscale_[i] *= roundToPowerOf2(diff / kLargeBoundDiff);
542+
}
533543
}
534544
}
535545
}

highs/ipm/hipo/ipm/Model.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "CurtisReidScaling.h"
99
#include "LogHighs.h"
10+
#include "Options.h"
1011
#include "ipm/hipo/auxiliary/IntConfig.h"
1112
#include "ipm/ipx/lp_solver.h"
1213
#include "util/HighsSparseMatrix.h"
@@ -80,7 +81,7 @@ class Model {
8081
const char* constraints) const;
8182
void computeNorms();
8283

83-
void scale();
84+
void scale(OptionScaling opt);
8485
bool needScaling();
8586
void applyScaling();
8687
void CRscaling();
@@ -92,7 +93,7 @@ class Model {
9293
Int init(const Int num_var, const Int num_con, const double* obj,
9394
const double* rhs, const double* lower, const double* upper,
9495
const Int* A_ptr, const Int* A_rows, const double* A_vals,
95-
const char* constraints, double offset);
96+
const char* constraints, double offset, OptionScaling opt);
9697

9798
// Print information of model
9899
void print(const LogHighs& log) const;

highs/ipm/hipo/ipm/Solver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Int Solver::load(const Int num_var, const Int num_con, const double* obj,
1414
const Int* A_ptr, const Int* A_rows, const double* A_vals,
1515
const char* constraints, double offset) {
1616
if (model_.init(num_var, num_con, obj, rhs, lower, upper, A_ptr, A_rows,
17-
A_vals, constraints, offset))
17+
A_vals, constraints, offset, options_.scaling))
1818
return kStatusBadModel;
1919

2020
m_ = model_.m();

0 commit comments

Comments
 (0)