Skip to content
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
80 changes: 39 additions & 41 deletions highs/ipm/IpxWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,29 +571,20 @@ HighsStatus solveLpHipo(const HighsOptions& options, HighsTimer& timer,
hipo.setTimer(timer);
hipo.setCallback(callback);

// Transform problem to correct formulation
hipo::Int num_col, num_row;
std::vector<double> obj, rhs, lower, upper, Aval;
std::vector<hipo::Int> Aptr, Aind;
std::vector<char> constraints;
double offset;
fillInIpxData(lp, num_col, num_row, offset, obj, lower, upper, Aptr, Aind,
Aval, rhs, constraints);
highsLogUser(options.log_options, HighsLogType::kInfo,
"HiPO model has %" HIGHSINT_FORMAT " rows, %" HIGHSINT_FORMAT
" columns and %" HIGHSINT_FORMAT " nonzeros\n",
num_row, num_col, Aptr[num_col]);

// Load the problem
hipo::Int load_status = hipo.load(
num_col, num_row, obj.data(), rhs.data(), lower.data(), upper.data(),
Aptr.data(), Aind.data(), Aval.data(), constraints.data(), offset);

hipo::Int load_status = hipo.load(lp);
if (load_status) {
model_status = HighsModelStatus::kSolveError;
return HighsStatus::kError;
}

// This information about the problem loaded into HiPO is needed for later
HighsInt num_row, num_col;
hipo.getOriginalDims(num_row, num_col);
std::vector<double> rhs;
std::vector<char> constraints;
fillInRhsAndConstraints(lp, rhs, constraints);

hipo.solve();

// const bool report_solve_data =
Expand Down Expand Up @@ -797,29 +788,7 @@ void fillInIpxData(const HighsLp& lp, ipx::Int& num_col, ipx::Int& num_row,

const HighsInt num_slack = general_bounded_rows.size();

// For each row except free rows add entry to char array and set up rhs
// vector
rhs.reserve(num_row);
constraint_type.reserve(num_row);

for (int row = 0; row < num_row; row++) {
if (lp.row_lower_[row] > -kHighsInf && lp.row_upper_[row] >= kHighsInf) {
rhs.push_back(lp.row_lower_[row]);
constraint_type.push_back('>');
} else if (lp.row_lower_[row] <= -kHighsInf &&
lp.row_upper_[row] < kHighsInf) {
rhs.push_back(lp.row_upper_[row]);
constraint_type.push_back('<');
} else if (lp.row_lower_[row] == lp.row_upper_[row]) {
rhs.push_back(lp.row_upper_[row]);
constraint_type.push_back('=');
} else if (lp.row_lower_[row] > -kHighsInf &&
lp.row_upper_[row] < kHighsInf) {
// general bounded
rhs.push_back(0);
constraint_type.push_back('=');
}
}
fillInRhsAndConstraints(lp, rhs, constraint_type);

std::vector<HighsInt> reduced_rowmap(lp.num_row_, -1);
if (free_rows.size() > 0) {
Expand Down Expand Up @@ -901,7 +870,36 @@ void fillInIpxData(const HighsLp& lp, ipx::Int& num_col, ipx::Int& num_row,
for (HighsInt col = 0; col < lp.num_col_; col++) {
obj[col] = (HighsInt)lp.sense_ * lp.col_cost_[col];
}
obj.insert(obj.end(), num_slack, 0);
}

void fillInRhsAndConstraints(const HighsLp& lp, std::vector<double>& rhs,
std::vector<char>& constraint_type) {
// For each row except free rows add entry to char array and set up rhs
// vector

const HighsInt num_row = lp.num_row_;

rhs.reserve(num_row);
constraint_type.reserve(num_row);

for (int row = 0; row < num_row; row++) {
if (lp.row_lower_[row] > -kHighsInf && lp.row_upper_[row] >= kHighsInf) {
rhs.push_back(lp.row_lower_[row]);
constraint_type.push_back('>');
} else if (lp.row_lower_[row] <= -kHighsInf &&
lp.row_upper_[row] < kHighsInf) {
rhs.push_back(lp.row_upper_[row]);
constraint_type.push_back('<');
} else if (lp.row_lower_[row] == lp.row_upper_[row]) {
rhs.push_back(lp.row_upper_[row]);
constraint_type.push_back('=');
} else if (lp.row_lower_[row] > -kHighsInf &&
lp.row_upper_[row] < kHighsInf) {
// general bounded
rhs.push_back(0);
constraint_type.push_back('=');
}
}
}

HighsStatus reportIpxSolveStatus(const HighsOptions& options,
Expand Down
3 changes: 3 additions & 0 deletions highs/ipm/IpxWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ void fillInIpxData(const HighsLp& lp, ipx::Int& num_col, ipx::Int& num_row,
std::vector<double>& Ax, std::vector<double>& rhs,
std::vector<char>& constraint_type);

void fillInRhsAndConstraints(const HighsLp& lp, std::vector<double>& rhs,
std::vector<char>& constraint_type);

HighsStatus reportIpxSolveStatus(const HighsOptions& options,
const ipx::Int solve_status,
const ipx::Int error_flag);
Expand Down
81 changes: 38 additions & 43 deletions highs/ipm/hipo/ipm/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,25 @@

#include "Parameters.h"
#include "Status.h"
#include "ipm/IpxWrapper.h"
#include "ipm/hipo/auxiliary/Log.h"

namespace hipo {

Int Model::init(const Int num_var, const Int num_con, const double* obj,
const double* rhs, const double* lower, const double* upper,
const Int* A_ptr, const Int* A_rows, const double* A_vals,
const char* constraints, double offset) {
// copy the input into the model
Int Model::init(const HighsLp& lp) {
fillInIpxData(lp, n_orig_, m_orig_, offset_, c_, lower_, upper_, A_.start_,
A_.index_, A_.value_, b_, constraints_);

if (checkData(num_var, num_con, obj, rhs, lower, upper, A_ptr, A_rows, A_vals,
constraints))
if (checkData(n_orig_, m_orig_, c_, b_, lower_, upper_, A_.start_, A_.index_,
A_.value_, constraints_))
return kStatusBadModel;

n_orig_ = num_var;
m_orig_ = num_con;
c_orig_ = obj;
b_orig_ = rhs;
lower_orig_ = lower;
upper_orig_ = upper;
A_ptr_orig_ = A_ptr;
A_rows_orig_ = A_rows;
A_vals_orig_ = A_vals;
constraints_orig_ = constraints;
offset_ = offset;

n_ = num_var;
m_ = num_con;
c_ = std::vector<double>(obj, obj + n_);
b_ = std::vector<double>(rhs, rhs + m_);
lower_ = std::vector<double>(lower, lower + n_);
upper_ = std::vector<double>(upper, upper + n_);

Int Annz = A_ptr[n_];
lp_orig_ = &lp;

n_ = n_orig_;
m_ = m_orig_;
A_.num_col_ = n_;
A_.num_row_ = m_;
A_.start_ = std::vector<Int>(A_ptr, A_ptr + n_ + 1);
A_.index_ = std::vector<Int>(A_rows, A_rows + Annz);
A_.value_ = std::vector<double>(A_vals, A_vals + Annz);

constraints_ = std::vector<char>(constraints, constraints + m_);

preprocess();
scale();
Expand All @@ -59,21 +37,25 @@ Int Model::init(const Int num_var, const Int num_con, const double* obj,
return 0;
}

Int Model::checkData(const Int num_var, const Int num_con, const double* obj,
const double* rhs, const double* lower,
const double* upper, const Int* A_ptr, const Int* A_rows,
const double* A_vals, const char* constraints) const {
Int Model::checkData(
const Int num_var, const Int num_con, const std::vector<double>& obj,
const std::vector<double>& rhs, const std::vector<double>& lower,
const std::vector<double>& upper, const std::vector<Int>& A_ptr,
const std::vector<Int>& A_rows, const std::vector<double>& A_vals,
const std::vector<char>& constraints) const {
// Check if model provided by the user is ok.
// Return kStatusBadModel if something is wrong.

// Pointers are valid
if (!obj || !rhs || !lower || !upper || !A_ptr || !A_rows || !A_vals ||
!constraints)
return kStatusBadModel;

// Dimensions are valid
if (num_var <= 0 || num_con < 0) return kStatusBadModel;

// Vectors are of correct size
if (obj.size() != num_var || rhs.size() != num_con ||
lower.size() != num_var || upper.size() != num_var ||
constraints.size() != num_con || A_ptr.size() != num_var + 1 ||
A_rows.size() != A_ptr.back() || A_vals.size() != A_ptr.back())
return kStatusBadModel;

// Vectors are valid
for (Int i = 0; i < num_var; ++i)
if (!std::isfinite(obj[i])) return kStatusBadModel;
Expand Down Expand Up @@ -530,9 +512,22 @@ void Model::denseColumns() {
}

Int Model::loadIntoIpx(ipx::LpSolver& lps) const {
Int ipx_m, ipx_n;
std::vector<double> ipx_b, ipx_c, ipx_lower, ipx_upper, ipx_A_vals;
std::vector<Int> ipx_A_ptr, ipx_A_rows;
std::vector<char> ipx_constraints;
double ipx_offset;

if (!lp_orig_) return kStatusError;

fillInIpxData(*lp_orig_, ipx_n, ipx_m, ipx_offset, ipx_c, ipx_lower,
ipx_upper, ipx_A_ptr, ipx_A_rows, ipx_A_vals, ipx_b,
ipx_constraints);

Int load_status = lps.LoadModel(
n_orig_, offset_, c_orig_, lower_orig_, upper_orig_, m_orig_, A_ptr_orig_,
A_rows_orig_, A_vals_orig_, b_orig_, constraints_orig_);
ipx_n, ipx_offset, ipx_c.data(), ipx_lower.data(), ipx_upper.data(),
ipx_m, ipx_A_ptr.data(), ipx_A_rows.data(), ipx_A_vals.data(),
ipx_b.data(), ipx_constraints.data());

return load_status;
}
Expand Down
27 changes: 11 additions & 16 deletions highs/ipm/hipo/ipm/Model.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "LogHighs.h"
#include "ipm/hipo/auxiliary/IntConfig.h"
#include "ipm/ipx/lp_solver.h"
#include "lp_data/HighsLp.h"
#include "util/HighsSparseMatrix.h"

namespace hipo {
Expand All @@ -31,14 +32,7 @@ class Model {
// data of original problem
Int n_orig_{};
Int m_orig_{};
const double* c_orig_;
const double* b_orig_;
const double* lower_orig_;
const double* upper_orig_;
const Int* A_ptr_orig_;
const Int* A_rows_orig_;
const double* A_vals_orig_;
const char* constraints_orig_;
const HighsLp* lp_orig_ = nullptr;
double offset_;

// data of reformulated problem
Expand Down Expand Up @@ -75,18 +69,18 @@ class Model {
void scale();
void preprocess();
void denseColumns();
Int checkData(const Int num_var, const Int num_con, const double* obj,
const double* rhs, const double* lower, const double* upper,
const Int* A_ptr, const Int* A_rows, const double* A_vals,
const char* constraints) const;
Int checkData(const Int num_var, const Int num_con,
const std::vector<double>& obj, const std::vector<double>& rhs,
const std::vector<double>& lower,
const std::vector<double>& upper, const std::vector<Int>& A_ptr,
const std::vector<Int>& A_rows,
const std::vector<double>& A_vals,
const std::vector<char>& constraints) const;
void computeNorms();

public:
// Initialise the model
Int init(const Int num_var, const Int num_con, const double* obj,
const double* rhs, const double* lower, const double* upper,
const Int* A_ptr, const Int* A_rows, const double* A_vals,
const char* constraints, double offset);
Int init(const HighsLp& lp);

// Print information of model
void print(const LogHighs& log) const;
Expand Down Expand Up @@ -117,6 +111,7 @@ class Model {
Int m() const { return m_; }
Int n() const { return n_; }
Int n_orig() const { return n_orig_; }
Int m_orig() const { return m_orig_; }
const HighsSparseMatrix& A() const { return A_; }
const std::vector<double>& b() const { return b_; }
const std::vector<double>& c() const { return c_; }
Expand Down
63 changes: 33 additions & 30 deletions highs/ipm/hipo/ipm/Solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,19 @@

namespace hipo {

Int Solver::load(const Int num_var, const Int num_con, const double* obj,
const double* rhs, const double* lower, const double* upper,
const Int* A_ptr, const Int* A_rows, const double* A_vals,
const char* constraints, double offset) {
if (model_.init(num_var, num_con, obj, rhs, lower, upper, A_ptr, A_rows,
A_vals, constraints, offset))
return kStatusBadModel;
Int Solver::load(const HighsLp& lp) {
if (model_.init(lp)) return kStatusBadModel;

m_ = model_.m();
n_ = model_.n();

info_.ipx_used = false;
info_.m_solver = m_;
info_.n_solver = n_;
info_.m_original = num_con;
info_.n_original = num_var;
info_.m_original = model_.m_orig();
info_.n_original = model_.n_orig();

return 0;
return kStatusOk;
}

void Solver::setOptions(const Options& options) {
Expand Down Expand Up @@ -188,6 +183,7 @@ bool Solver::prepareIpx() {
ipx_param.ipm_optimality_tol = options_.optimality_tol;
ipx_param.start_crossover_tol = options_.crossover_tol;
ipx_param.time_limit = options_.time_limit;
ipx_param.timeless_log = options_.timeless_log;
ipx_param.ipm_maxiter = options_.max_iter - iter_;
ipx_lps_.SetParameters(ipx_param);

Expand Down Expand Up @@ -1198,34 +1194,41 @@ void Solver::printSummary() const {

if (logH_.debug(1)) {
log_stream << textline("Correctors:") << integer(info_.correctors) << '\n';
log_stream << textline("Analyse AS time:")
<< fix(info_.analyse_AS_time, 0, 2) << '\n';
log_stream << textline("Analyse NE time:")
<< fix(info_.analyse_NE_time, 0, 2) << '\n';
log_stream << textline("Matrix time:") << fix(info_.matrix_time, 0, 2)
<< '\n';
log_stream << textline("Matrix structure time:")
<< fix(info_.matrix_structure_time, 0, 2) << '\n';
log_stream << textline("Factorisation time:")
<< fix(info_.factor_time, 0, 2) << '\n';
log_stream << textline("Solve time:") << fix(info_.solve_time, 0, 2)
<< '\n';
log_stream << textline("Residual time:") << fix(info_.residual_time, 0, 2)
<< '\n';
log_stream << textline("Omega time:") << fix(info_.omega_time, 0, 2)
<< '\n';
log_stream << textline("Factorisations:") << integer(info_.factor_number)
<< '\n';
log_stream << textline("Solves:") << integer(info_.solve_number) << '\n';
log_stream << textline("Avg time per factorisation:")
<< sci(info_.factor_time / info_.factor_number, 0, 2) << '\n';
log_stream << textline("Avg time per solve:")
<< sci(info_.solve_time / info_.solve_number, 0, 2) << '\n';

if (!options_.timeless_log) {
log_stream << textline("Analyse AS time:")
<< fix(info_.analyse_AS_time, 0, 2) << '\n';
log_stream << textline("Analyse NE time:")
<< fix(info_.analyse_NE_time, 0, 2) << '\n';
log_stream << textline("Matrix time:") << fix(info_.matrix_time, 0, 2)
<< '\n';
log_stream << textline("Matrix structure time:")
<< fix(info_.matrix_structure_time, 0, 2) << '\n';
log_stream << textline("Factorisation time:")
<< fix(info_.factor_time, 0, 2) << '\n';
log_stream << textline("Solve time:") << fix(info_.solve_time, 0, 2)
<< '\n';
log_stream << textline("Residual time:") << fix(info_.residual_time, 0, 2)
<< '\n';
log_stream << textline("Omega time:") << fix(info_.omega_time, 0, 2)
<< '\n';
log_stream << textline("Avg time per factorisation:")
<< sci(info_.factor_time / info_.factor_number, 0, 2) << '\n';
log_stream << textline("Avg time per solve:")
<< sci(info_.solve_time / info_.solve_number, 0, 2) << '\n';
}
}

logH_.print(log_stream);
}

void Solver::getOriginalDims(Int& num_row, Int& num_col) const {
num_row = model_.m_orig();
num_col = model_.n_orig();
}
const Info& Solver::getInfo() const { return info_; }
void Solver::getInteriorSolution(
std::vector<double>& x, std::vector<double>& xl, std::vector<double>& xu,
Expand Down
Loading
Loading