Skip to content

Commit

Permalink
Added support for partial MIP starts (#203) on all supported solvers.
Browse files Browse the repository at this point in the history
  • Loading branch information
mapgccv committed Apr 26, 2023
1 parent 7f40432 commit bdec071
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 17 deletions.
30 changes: 27 additions & 3 deletions solvers/cbcmp/cbcmpbackend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1049,11 +1049,35 @@ void CbcmpBackend::SetBasis(SolutionBasis basis) {
lp()->solver_->setBasisStatus(varstt.data(), constt.data());
}

void CbcmpBackend::AddPrimalDualStart(Solution sol0_unpres) {
if (IsMIP()) return;
auto mv = GetValuePresolver().PresolveSolution(
{ sol0_unpres.primal, sol0_unpres.dual });
auto x0 = mv.GetVarValues()();
auto pi0 = mv.GetConValues()(CG_Linear);
lp()->solver_->setColSolution(x0.data());
lp()->solver_->setRowPrice(pi0.data());
}

void CbcmpBackend::AddMIPStart(ArrayRef<double> x0,
ArrayRef<int> sparsity) {
//CBCMP_CCALL(CBCMP_AddMipStart(lp(), NumVars(), NULL, const_cast<double*>(x0.data())));

void CbcmpBackend::AddMIPStart(ArrayRef<double> x0_unpres,
ArrayRef<int> sparsity_unpres) {

auto mv = GetValuePresolver().PresolveSolution({ x0_unpres });
auto ms = GetValuePresolver().PresolveGenericInt({ sparsity_unpres });
auto x0 = mv.GetVarValues()();
auto s0 = ms.GetVarValues()();
std::vector<int> idx; // Create sparse vector
idx.reserve(x0.size());
std::vector<double> val;
val.reserve(x0.size());
for (int i = 0; i < (int)x0.size(); ++i) {
if (s0[i]) {
idx.push_back(i);
val.push_back(x0[i]);
}
}
Cbc_setMIPStartI(lp(), val.size(), idx.data(), x0.data());
}


Expand Down
13 changes: 8 additions & 5 deletions solvers/cbcmp/cbcmpbackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,24 @@ class CbcmpBackend :
SolutionBasis GetBasis() override;
void SetBasis(SolutionBasis) override;


/**
* General warm start, e.g.,
* set primal/dual initial guesses for continuous case
**/
ALLOW_STD_FEATURE(WARMSTART, true)
void AddPrimalDualStart(Solution sol0) override;
/**
* MIP warm start
**/
// TODO If MIP warm start is supported, implement the function below
// to set a non-presolved starting solution
ALLOW_STD_FEATURE(MIPSTART, false)
ALLOW_STD_FEATURE(MIPSTART, true)
void AddMIPStart(ArrayRef<double> x0,
ArrayRef<int> sparsity) override;


/**
* Get MIP Gap
**/
// TODO Implement to return MIP gap
// (adds option mip:return_gap)
ALLOW_STD_FEATURE(RETURN_MIP_GAP, false)
double MIPGap() override;
double MIPGapAbs() override;
Expand Down
30 changes: 26 additions & 4 deletions solvers/copt/coptbackend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ void CoptBackend::DoWriteProblem(const std::string& name) {
}



void CoptBackend::SetInterrupter(mp::Interrupter *inter) {
inter->SetHandler(InterruptCopt, lp());
}
Expand Down Expand Up @@ -846,11 +845,34 @@ ArrayRef<double> CoptBackend::DRay() {
}


void CoptBackend::AddPrimalDualStart(Solution sol0_unpres) {
if (IsMIP())
return;
auto mv = GetValuePresolver().PresolveSolution(
{ sol0_unpres.primal, sol0_unpres.dual });
auto x0 = mv.GetVarValues()();
auto pi0 = mv.GetConValues()(CG_Linear);
COPT_CCALL(COPT_SetLpSolution(lp(), x0.data(), nullptr, pi0.data(), nullptr));

void CoptBackend::AddMIPStart(
ArrayRef<double> x0, ArrayRef<int> sparsity) {
COPT_CCALL(COPT_AddMipStart(lp(), NumVars(), NULL, const_cast<double*>(x0.data())));
}

void CoptBackend::AddMIPStart(
ArrayRef<double> x0_unpres, ArrayRef<int> sparsity_unpres) {
auto mv = GetValuePresolver().PresolveSolution({ x0_unpres });
auto ms = GetValuePresolver().PresolveGenericInt({ sparsity_unpres });
auto x0 = mv.GetVarValues()();
auto s0 = ms.GetVarValues()();
std::vector<int> idx; // Create sparse vector
idx.reserve(x0.size());
std::vector<double> val;
val.reserve(x0.size());
for (int i = 0; i < (int)x0.size(); ++i) {
if (s0[i]) {
idx.push_back(i);
val.push_back(x0[i]);
}
}
COPT_CCALL(COPT_AddMipStart(lp(), val.size(), idx.data(), const_cast<double*>(val.data())));
}


Expand Down
11 changes: 9 additions & 2 deletions solvers/copt/coptbackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,15 @@ class CoptBackend :
void SetBasis(SolutionBasis) override;

/**
* MIP warm start
**/
* General warm start, e.g.,
* set primal/dual initial guesses for continuous case
**/
ALLOW_STD_FEATURE(WARMSTART, true)
void AddPrimalDualStart(Solution sol0) override;

/**
* MIP warm start
**/
ALLOW_STD_FEATURE(MIPSTART, true)
void AddMIPStart(ArrayRef<double> x0,
ArrayRef<int> sparsity) override;
Expand Down
33 changes: 33 additions & 0 deletions solvers/cplexmp/cplexmpbackend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,39 @@ namespace mp {
VarConStatii(varstt, constt);
}

/*
void CplexBackend::AddPrimalDualStart(Solution sol0_unpres) {
if (IsMIP())
return;
auto mv = GetValuePresolver().PresolveSolution(
{ sol0_unpres.primal, sol0_unpres.dual });
auto x0 = mv.GetVarValues()();
auto pi0 = mv.GetConValues()(CG_Linear);
//COPT_CCALL(COPT_SetLpSolution(lp(), x0.data(), nullptr, pi0.data(), nullptr));
}*/

void CplexBackend::AddMIPStart(
ArrayRef<double> x0_unpres, ArrayRef<int> sparsity_unpres) {
auto mv = GetValuePresolver().PresolveSolution({ x0_unpres });
auto ms = GetValuePresolver().PresolveGenericInt({ sparsity_unpres });
auto x0 = mv.GetVarValues()();
auto s0 = ms.GetVarValues()();
std::vector<int> idx; // Create sparse vector
idx.reserve(x0.size());
std::vector<double> val;
val.reserve(x0.size());
for (int i = 0; i < (int)x0.size(); ++i) {
if (s0[i]) {
idx.push_back(i);
val.push_back(x0[i]);
}
}
int beg[2] = { 0, val.size() };
CPLEX_CALL(CPXaddmipstarts(env(), lp(), 1, val.size(), beg, idx.data(), val.data(), 0, nullptr));
}

ArrayRef<double> CplexBackend::PrimalSolution() {
int num_vars = NumVars();
std::vector<double> x(num_vars);
Expand Down
11 changes: 11 additions & 0 deletions solvers/cplexmp/cplexmpbackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ class CplexBackend :
ArrayRef<int> ConStatii();
ArrayRef<int> VarStatii();
void VarConStatii(ArrayRef<int>, ArrayRef<int>);
/**
* General warm start, e.g.,
* set primal/dual initial guesses for continuous case
**/
//ALLOW_STD_FEATURE(WARMSTART, true)
//void AddPrimalDualStart(Solution sol0) override;
/**
* Specifically, MIP warm start
**/
ALLOW_STD_FEATURE(MIPSTART, true)
void AddMIPStart(ArrayRef<double> x0, ArrayRef<int> s0) override;


ALLOW_STD_FEATURE(IIS, true)
Expand Down
17 changes: 14 additions & 3 deletions solvers/xpress/xpressbackend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2572,11 +2572,22 @@ void XpressmpBackend::AddPrimalDualStart(Solution sol0_unpres) {
}

void XpressmpBackend::AddMIPStart(
ArrayRef<double> x0_unpres, ArrayRef<int> sparsity) {
ArrayRef<double> x0_unpres, ArrayRef<int> s0_unpres) {
auto mv = GetValuePresolver().PresolveSolution({ x0_unpres });
auto ms = GetValuePresolver().PresolveGenericInt({ s0_unpres });
auto x0 = mv.GetVarValues()();
int status;
XPRSaddmipsol(lp(), NumVars(), x0.data(), nullptr, nullptr);
auto s0 = ms.GetVarValues()();
std::vector<int> idx; // Create sparse vector
idx.reserve(x0.size());
std::vector<double> val;
val.reserve(x0.size());
for (int i = 0; i < (int)x0.size(); ++i) {
if (s0[i]) {
idx.push_back(i);
val.push_back(x0[i]);
}
}
XPRSaddmipsol(lp(), x0.size(), x0.data(), idx.data(), nullptr);
}

void XpressmpBackend::xpdisplay(XPRSprob prob, void* data, const char* ch, int n, int msglvl)
Expand Down

0 comments on commit bdec071

Please sign in to comment.