00001
00002
00003
00004 #if defined(_MSC_VER)
00005
00006 # pragma warning(disable:4786)
00007 #endif
00008
00009 #include <numeric>
00010 #include <cassert>
00011 #include <cmath>
00012
00013 #include "CoinHelperFunctions.hpp"
00014 #include "CoinWarmStartDual.hpp"
00015
00016 #include "OsiVolSolverInterface.hpp"
00017 #include "OsiRowCut.hpp"
00018 #include "OsiColCut.hpp"
00019
00020
00021
00022
00023
00024 void
00025 OsiVolSolverInterface::updateRowMatrix_() const
00026 {
00027 if (! rowMatrixCurrent_) {
00028 rowMatrix_.reverseOrderedCopyOf(colMatrix_);
00029 rowMatrixCurrent_ = true;
00030 }
00031 }
00032
00033 void
00034 OsiVolSolverInterface::updateColMatrix_() const
00035 {
00036 if (! colMatrixCurrent_) {
00037 colMatrix_.reverseOrderedCopyOf(rowMatrix_);
00038 colMatrixCurrent_ = true;
00039 }
00040 }
00041
00042
00043
00044 void
00045 OsiVolSolverInterface::checkData_() const throw(CoinError)
00046 {
00047 int i;
00048 for (i = getNumRows() - 1; i >= 0; --i) {
00049 if (rowlower_[i] > -1.0e20 &&
00050 rowupper_[i] < 1.0e20 &&
00051 rowlower_[i] != rowupper_[i])
00052 throw CoinError("Volume algorithm is unable to handle ranged rows",
00053 "checkData_", "OsiVolSolverInterface");
00054 }
00055
00056 for (i = getNumCols() - 1; i >= 0; --i) {
00057 if (collower_[i] < -1.0e20 || colupper_[i] > 1.0e20)
00058 throw CoinError("Volume algorithm is unable to handle infinite bounds",
00059 "checkData_", "OsiVolSolverInterface");
00060 }
00061 }
00062
00063
00064
00065 void
00066 OsiVolSolverInterface::compute_rc_(const double* u, double* rc) const
00067 {
00068 if (isZeroOneMinusOne_) {
00069 rowMatrixOneMinusOne_->timesMajor(u, rc);
00070 } else {
00071 rowMatrix_.transposeTimes(u, rc);
00072 }
00073
00074 const int psize = getNumCols();
00075 std::transform(rc, rc+psize, objcoeffs_, rc, std::minus<double>());
00076 std::transform(rc, rc+psize, rc, std::negate<double>());
00077 }
00078
00079
00080
00081 bool
00082 OsiVolSolverInterface::test_zero_one_minusone_(const CoinPackedMatrix& m) const
00083 {
00084 const int vecnum = m.getMajorDim();
00085 const double* elem = m.getElements();
00086 const int* start = m.getVectorStarts();
00087 const int* length = m.getVectorLengths();
00088 int i, j;
00089 for (i = 0; i < vecnum; ++i) {
00090 for (j = start[i] + length[i] - 1; j >= start[i]; --j) {
00091 const double val = elem[j];
00092 if (val != 1.0 && val != 0.0 && val != -1.0) {
00093 return false;
00094 }
00095 }
00096 }
00097 return true;
00098 }
00099
00100
00101
00102 OsiVolSolverInterface::OsiVolMatrixOneMinusOne_::
00103 OsiVolMatrixOneMinusOne_(const CoinPackedMatrix& m) {
00104 const int major = m.getMajorDim();
00105 const double* elem = m.getElements();
00106 const int* ind = m.getIndices();
00107 const int* start = m.getVectorStarts();
00108 const int* length = m.getVectorLengths();
00109
00110 majorDim_ = major;
00111 minorDim_ = m.getMinorDim();
00112
00113 plusSize_ = 0;
00114 minusSize_ = 0;
00115 int i, j;
00116 for (i = 0; i < major; ++i) {
00117 for (j = start[i] + length[i] - 1; j >= start[i]; --j) {
00118 const double val = elem[j];
00119 if (val == 1.0) {
00120 ++plusSize_;
00121 } else if (val == -1.0) {
00122 ++minusSize_;
00123 }
00124 }
00125 }
00126 if (plusSize_ > 0) {
00127 plusInd_ = new int[plusSize_];
00128 }
00129 if (minusSize_ > 0) {
00130 minusInd_ = new int[minusSize_];
00131 }
00132 plusStart_ = new int[major];
00133 plusLength_ = new int[major];
00134 minusStart_ = new int[major];
00135 minusLength_ = new int[major];
00136
00137 plusSize_ = 0;
00138 minusSize_ = 0;
00139 for (i = 0; i < major; ++i) {
00140 plusStart_[i] = plusSize_;
00141 minusStart_[i] = minusSize_;
00142 const int last = start[i] + length[i];
00143 for (j = start[i]; j < last; ++j) {
00144 const double val = elem[j];
00145 if (val == 1.0) {
00146 plusInd_[plusSize_++] = ind[j];
00147 } else if (val == -1.0) {
00148 minusInd_[minusSize_++] = ind[j];
00149 }
00150 }
00151 plusLength_[i] = plusSize_ - plusStart_[i];
00152 minusLength_[i] = minusSize_ - minusStart_[i];
00153 }
00154 if (plusSize_ == 0) {
00155 delete[] plusStart_; plusStart_ = NULL;
00156 delete[] plusLength_; plusLength_ = NULL;
00157 }
00158 if (minusSize_ == 0) {
00159 delete[] minusStart_; minusStart_ = NULL;
00160 delete[] minusLength_; minusLength_ = NULL;
00161 }
00162 }
00163
00164
00165
00166 OsiVolSolverInterface::OsiVolMatrixOneMinusOne_::
00167 ~OsiVolMatrixOneMinusOne_() {
00168 if (plusSize_ > 0) {
00169 delete[] plusInd_; plusInd_ = NULL;
00170 delete[] plusStart_; plusStart_ = NULL;
00171 delete[] plusLength_; plusLength_ = NULL;
00172 }
00173 if (minusSize_ > 0) {
00174 delete[] minusInd_; minusInd_ = NULL;
00175 delete[] minusStart_; minusStart_ = NULL;
00176 delete[] minusLength_; minusLength_ = NULL;
00177 }
00178 }
00179
00180
00181
00182 void OsiVolSolverInterface::OsiVolMatrixOneMinusOne_::
00183 timesMajor(const double* x, double* y) const
00184 {
00185 memset(y, 0, minorDim_ * sizeof(double));
00186 int i;
00187
00188 if (plusSize_ > 0 && minusSize_ > 0) {
00189 for (i = majorDim_ - 1; i >= 0; --i) {
00190 const double x_i = x[i];
00191 if (x_i != 0.0) {
00192 const int* vecInd = plusInd_ + plusStart_[i];
00193 int j;
00194 for ( j = plusLength_[i] - 1; j >= 0; --j)
00195 y[vecInd[j]] += x_i;
00196 vecInd = minusInd_ + minusStart_[i];
00197 for ( j = minusLength_[i] - 1; j >= 0; --j)
00198 y[vecInd[j]] -= x_i;
00199 }
00200 }
00201 return;
00202 }
00203 if (plusSize_ > 0) {
00204 for (i = majorDim_ - 1; i >= 0; --i) {
00205 const double x_i = x[i];
00206 if (x_i != 0.0) {
00207 const int* vecInd = plusInd_ + plusStart_[i];
00208 for (int j = plusLength_[i] - 1; j >= 0; --j)
00209 y[vecInd[j]] += x_i;
00210 }
00211 }
00212 return;
00213 }
00214 if (minusSize_ > 0) {
00215 for (i = majorDim_ - 1; i >= 0; --i) {
00216 const double x_i = x[i];
00217 if (x_i != 0.0) {
00218 const int* vecInd = minusInd_ + minusStart_[i];
00219 for (int j = minusLength_[i] - 1; j >= 0; --j)
00220 y[vecInd[j]] -= x_i;
00221 }
00222 }
00223 return;
00224 }
00225 }
00226
00227
00228
00229 void
00230 OsiVolSolverInterface::gutsOfDestructor_()
00231 {
00232 rowMatrix_.clear();
00233 colMatrix_.clear();
00234 rowMatrixCurrent_ = true;
00235 colMatrixCurrent_ = true;
00236
00237 delete[] colupper_; colupper_ = 0;
00238 delete[] collower_; collower_ = 0;
00239 delete[] continuous_; continuous_ = 0;
00240 delete[] rowupper_; rowupper_ = 0;
00241 delete[] rowlower_; rowlower_ = 0;
00242 delete[] rowsense_; rowsense_ = 0;
00243 delete[] rhs_; rhs_ = 0;
00244 delete[] rowrange_; rowrange_ = 0;
00245 delete[] objcoeffs_; objcoeffs_ = 0;
00246
00247 delete[] colsol_; colsol_ = 0;
00248 delete[] rowprice_; rowprice_ = 0;
00249 delete[] rowpriceHotStart_; rowpriceHotStart_ = 0;
00250 delete[] rc_; rc_ = 0;
00251 delete[] lhs_; lhs_ = 0;
00252
00253 lagrangeanCost_ = 0.0;
00254
00255 maxNumrows_ = 0;
00256 maxNumcols_ = 0;
00257 }
00258
00259
00260
00261 void
00262 OsiVolSolverInterface::rowRimAllocator_()
00263 {
00264 rowupper_ = new double[maxNumrows_];
00265 rowlower_ = new double[maxNumrows_];
00266 rowsense_ = new char[maxNumrows_];
00267 rhs_ = new double[maxNumrows_];
00268 rowrange_ = new double[maxNumrows_];
00269 rowprice_ = new double[maxNumrows_];
00270 lhs_ = new double[maxNumrows_];
00271 }
00272
00273
00274
00275 void
00276 OsiVolSolverInterface::colRimAllocator_()
00277 {
00278 colupper_ = new double[maxNumcols_];
00279 collower_ = new double[maxNumcols_];
00280 continuous_ = new bool[maxNumcols_];
00281 objcoeffs_ = new double[maxNumcols_];
00282 colsol_ = new double[maxNumcols_];
00283 rc_ = new double[maxNumcols_];
00284 }
00285
00286
00287
00288 void
00289 OsiVolSolverInterface::rowRimResize_(const int newSize)
00290 {
00291 if (newSize > maxNumrows_) {
00292 double* rub = rowupper_;
00293 double* rlb = rowlower_;
00294 char* sense = rowsense_;
00295 double* right = rhs_;
00296 double* range = rowrange_;
00297 double* dual = rowprice_;
00298 double* left = lhs_;
00299 maxNumrows_ = CoinMax(1000, (newSize * 5) / 4);
00300 rowRimAllocator_();
00301 const int rownum = getNumRows();
00302 CoinDisjointCopyN(rub , rownum, rowupper_);
00303 CoinDisjointCopyN(rlb , rownum, rowlower_);
00304 CoinDisjointCopyN(sense, rownum, rowsense_);
00305 CoinDisjointCopyN(right, rownum, rhs_);
00306 CoinDisjointCopyN(range, rownum, rowrange_);
00307 CoinDisjointCopyN(dual , rownum, rowprice_);
00308 CoinDisjointCopyN(left , rownum, lhs_);
00309 delete[] rub;
00310 delete[] rlb;
00311 delete[] sense;
00312 delete[] right;
00313 delete[] range;
00314 delete[] dual;
00315 delete[] left;
00316 }
00317 }
00318
00319
00320
00321 void
00322 OsiVolSolverInterface::colRimResize_(const int newSize)
00323 {
00324 if (newSize > maxNumcols_) {
00325 double* cub = colupper_;
00326 double* clb = collower_;
00327 bool* cont = continuous_;
00328 double* obj = objcoeffs_;
00329 double* sol = colsol_;
00330 double* rc = rc_;
00331 maxNumcols_ = CoinMax(1000, (maxNumcols_ * 5) / 4);
00332 colRimAllocator_();
00333 const int colnum = getNumCols();
00334 CoinDisjointCopyN(cub , colnum, colupper_);
00335 CoinDisjointCopyN(clb , colnum, collower_);
00336 CoinDisjointCopyN(cont, colnum, continuous_);
00337 CoinDisjointCopyN(obj , colnum, objcoeffs_);
00338 CoinDisjointCopyN(sol , colnum, colsol_);
00339 CoinDisjointCopyN(rc , colnum, rc_);
00340 delete[] cub;
00341 delete[] clb;
00342 delete[] cont;
00343 delete[] obj;
00344 delete[] sol;
00345 delete[] rc;
00346 }
00347 }
00348
00349
00350
00351 void
00352 OsiVolSolverInterface::convertBoundsToSenses_()
00353 {
00354 for (int i = getNumRows() - 1; i >= 0; --i ) {
00355 convertBoundToSense(rowlower_[i], rowupper_[i],
00356 rowsense_[i], rhs_[i], rowrange_[i]);
00357 }
00358 }
00359
00360
00361
00362 void
00363 OsiVolSolverInterface::convertSensesToBounds_()
00364 {
00365 for (int i = getNumRows() - 1; i >= 0; --i) {
00366 convertSenseToBound(rowsense_[i], rhs_[i], rowrange_[i],
00367 rowlower_[i], rowupper_[i]);
00368 }
00369 }
00370
00371
00372
00373
00374
00375
00376 int
00377 OsiVolSolverInterface::compute_rc(const VOL_dvector& u, VOL_dvector& rc)
00378 {
00379 compute_rc_(u.v, rc.v);
00380 return 0;
00381 }
00382
00383
00384
00385 int
00386 OsiVolSolverInterface::solve_subproblem(const VOL_dvector& dual,
00387 const VOL_dvector& rc,
00388 double& lcost,
00389 VOL_dvector& x, VOL_dvector& v,
00390 double& pcost)
00391 {
00392 int i;
00393
00394 const int psize = x.size();
00395 for (i = 0; i < psize; ++i) {
00396 x[i] = (rc[i] >= 0.0) ? collower_[i] : colupper_[i];
00397 }
00398
00399 const int dsize = v.size();
00400 lcost = (std::inner_product(rhs_, rhs_ + dsize, dual.v, 0.0) +
00401 std::inner_product(x.v, x.v + psize, rc.v, 0.0) );
00402
00403 if (isZeroOneMinusOne_) {
00404 colMatrixOneMinusOne_->timesMajor(x.v, v.v);
00405 } else {
00406 colMatrix_.times(x.v, v.v);
00407 }
00408
00409 std::transform(v.v, v.v+dsize, rhs_, v.v, std::minus<double>());
00410 std::transform(v.v, v.v+dsize, v.v, std::negate<double>());
00411
00412 pcost = std::inner_product(x.v, x.v + psize, objcoeffs_, 0.0);
00413
00414 return 0;
00415 }
00416
00417
00418
00419
00420
00421 void
00422 OsiVolSolverInterface::initialSolve()
00423 {
00424
00425 CoinFillN(rowprice_, getNumRows(), 0.0);
00426 resolve();
00427 }
00428
00429
00430
00431 void
00432 OsiVolSolverInterface::resolve()
00433 {
00434 int i;
00435
00436 checkData_();
00437
00438
00439 updateRowMatrix_();
00440 updateColMatrix_();
00441
00442 const int dsize = getNumRows();
00443 const int psize = getNumCols();
00444
00445
00446 if (objsense_ < 0) {
00447 std::transform(objcoeffs_, objcoeffs_+psize, objcoeffs_,
00448 std::negate<double>());
00449 }
00450
00451
00452 volprob_.dual_lb.allocate(dsize);
00453 volprob_.dual_ub.allocate(dsize);
00454 double * dlb = volprob_.dual_lb.v;
00455 double * dub = volprob_.dual_ub.v;
00456 for (i = 0; i < dsize; ++i) {
00457 dlb[i] = rowupper_[i] < OsiVolInfinity ? -1.0e31 : 0.0;
00458 dub[i] = rowlower_[i] > -OsiVolInfinity ? 1.0e31 : 0.0;
00459 }
00460 volprob_.dsize = dsize;
00461 volprob_.psize = psize;
00462
00463
00464 VOL_dvector& dsol = volprob_.dsol;
00465 dsol.allocate(dsize);
00466 std::transform(rowprice_, rowprice_+dsize, dsol.v,
00467 std::bind2nd(std::multiplies<double>(), objsense_));
00468
00469
00470 double * dv = dsol.v;
00471 for (i = 0; i < dsize; ++i) {
00472 if (dv[i] < dlb[i]) {
00473 dv[i] = dlb[i];
00474 } else if (dv[i] > dub[i]) {
00475 dv[i] = dub[i];
00476 }
00477 }
00478
00479
00480 #if 0
00481 isZeroOneMinusOne_ = false;
00482 #else
00483 isZeroOneMinusOne_ = test_zero_one_minusone_(colMatrix_);
00484 if (isZeroOneMinusOne_) {
00485 colMatrixOneMinusOne_ = new OsiVolMatrixOneMinusOne_(colMatrix_);
00486 rowMatrixOneMinusOne_ = new OsiVolMatrixOneMinusOne_(rowMatrix_);
00487 }
00488 #endif
00489
00490 volprob_.solve(*this, true);
00491
00492
00493
00494
00495 lagrangeanCost_ = objsense_ * volprob_.value;
00496
00497 CoinDisjointCopyN(volprob_.psol.v, psize, colsol_);
00498
00499
00500 if (objsense_ < 0) {
00501 std::transform(objcoeffs_, objcoeffs_ + psize, objcoeffs_,
00502 std::negate<double>());
00503
00504 std::transform(volprob_.dsol.v, volprob_.dsol.v+dsize, rowprice_,
00505 std::negate<double>());
00506 } else {
00507
00508 CoinDisjointCopyN(volprob_.dsol.v, dsize, rowprice_);
00509 }
00510
00511
00512 compute_rc_(rowprice_, rc_);
00513
00514
00515 if (isZeroOneMinusOne_) {
00516 colMatrixOneMinusOne_->timesMajor(colsol_, lhs_);
00517 } else {
00518 colMatrix_.times(colsol_, lhs_);
00519 }
00520
00521 if (isZeroOneMinusOne_) {
00522 delete colMatrixOneMinusOne_;
00523 colMatrixOneMinusOne_ = NULL;
00524 delete rowMatrixOneMinusOne_;
00525 rowMatrixOneMinusOne_ = NULL;
00526 }
00527 }
00528
00529
00530
00531
00532
00533 bool
00534 OsiVolSolverInterface::setIntParam(OsiIntParam key, int value)
00535 {
00536 switch (key) {
00537 case OsiMaxNumIteration:
00538 if (value < 0)
00539 return false;
00540 volprob_.parm.maxsgriters = value;
00541 break;
00542 case OsiMaxNumIterationHotStart:
00543 if (value < 0)
00544 return false;
00545 OsiSolverInterface::setIntParam(key, value);
00546 break;
00547 case OsiLastIntParam:
00548 return false;
00549 }
00550 return true;
00551 }
00552
00553
00554
00555 bool
00556 OsiVolSolverInterface::setDblParam(OsiDblParam key, double value)
00557 {
00558 switch (key) {
00559 case OsiDualObjectiveLimit:
00560 volprob_.parm.ubinit = value;
00561 break;
00562 case OsiPrimalObjectiveLimit:
00563 return false;
00564 case OsiDualTolerance:
00565 return (value == 1e-50);
00566 case OsiPrimalTolerance:
00567 if (value < 1e-04 || value > 1e-1)
00568 return false;
00569 volprob_.parm.primal_abs_precision = value;
00570 break;
00571 case OsiObjOffset:
00572 return OsiSolverInterface::setDblParam(key, value);
00573 case OsiLastDblParam:
00574 return false;
00575 }
00576 return true;
00577 }
00578
00579
00580
00581
00582 bool
00583 OsiVolSolverInterface::setStrParam(OsiStrParam key, const std::string & value)
00584 {
00585 bool retval=false;
00586 switch (key) {
00587 case OsiSolverName:
00588 return false;
00589
00590 case OsiProbName:
00591 OsiSolverInterface::setStrParam(key,value);
00592 return retval = true;
00593
00594 case OsiLastStrParam:
00595 return false;
00596 }
00597 return false;
00598 }
00599
00600
00601
00602 bool
00603 OsiVolSolverInterface::getIntParam(OsiIntParam key, int& value) const
00604 {
00605 switch (key) {
00606 case OsiMaxNumIteration:
00607 value = volprob_.parm.maxsgriters;
00608 break;
00609 case OsiMaxNumIterationHotStart:
00610 OsiSolverInterface::getIntParam(key, value);
00611 break;
00612 case OsiLastIntParam:
00613 return false;
00614 }
00615 return true;
00616 }
00617
00618
00619
00620 bool
00621 OsiVolSolverInterface::getDblParam(OsiDblParam key, double& value) const
00622 {
00623 switch (key) {
00624 case OsiDualObjectiveLimit:
00625 value = volprob_.parm.ubinit;
00626 break;
00627 case OsiPrimalObjectiveLimit:
00628 return false;
00629 case OsiDualTolerance:
00630 value = 1e-50;
00631 break;
00632 case OsiPrimalTolerance:
00633 value = volprob_.parm.primal_abs_precision;
00634 break;
00635 case OsiObjOffset:
00636 OsiSolverInterface::getDblParam(key, value);
00637 break;
00638 case OsiLastDblParam:
00639 return false;
00640 }
00641 return true;
00642 }
00643
00644
00645
00646
00647 bool
00648 OsiVolSolverInterface::getStrParam(OsiStrParam key, std::string & value) const
00649 {
00650 switch (key) {
00651 case OsiProbName:
00652 OsiSolverInterface::getStrParam(key, value);
00653 return true;
00654 case OsiSolverName:
00655 value = "vol";
00656 return true;
00657 case OsiLastStrParam:
00658 return false;
00659 }
00660 return false;
00661 }
00662
00663
00664
00665
00666 bool
00667 OsiVolSolverInterface::isAbandoned() const
00668 {
00669
00670 return false;
00671 }
00672
00673 bool
00674 OsiVolSolverInterface::isProvenOptimal() const
00675 {
00676
00677
00678
00679
00680 return (! isDualObjectiveLimitReached() &&
00681 volprob_.iter() < volprob_.parm.maxsgriters);
00682 }
00683
00684 bool
00685 OsiVolSolverInterface::isProvenPrimalInfeasible() const
00686 {
00687
00688
00689 return false;
00690 }
00691
00692 bool
00693 OsiVolSolverInterface::isProvenDualInfeasible() const
00694 {
00695
00696 return false;
00697 }
00698
00699 bool
00700 OsiVolSolverInterface::isPrimalObjectiveLimitReached() const
00701 {
00702
00703
00704 return false;
00705 }
00706
00707 bool
00708 OsiVolSolverInterface::isDualObjectiveLimitReached() const
00709 {
00710 return volprob_.parm.ubinit - volprob_.value < volprob_.parm.granularity;
00711 }
00712
00713 bool
00714 OsiVolSolverInterface::isIterationLimitReached() const
00715 {
00716 return volprob_.iter() >= volprob_.parm.maxsgriters;
00717 }
00718
00719
00720
00721
00722
00723 CoinWarmStart*
00724 OsiVolSolverInterface::getEmptyWarmStart () const
00725 { return (dynamic_cast<CoinWarmStart *>(new CoinWarmStartDual())) ; }
00726
00727 CoinWarmStart*
00728 OsiVolSolverInterface::getWarmStart() const
00729 {
00730 return new CoinWarmStartDual(getNumRows(), rowprice_);
00731 }
00732
00733
00734
00735 bool
00736 OsiVolSolverInterface::setWarmStart(const CoinWarmStart* warmstart)
00737 {
00738 const CoinWarmStartDual* ws =
00739 dynamic_cast<const CoinWarmStartDual*>(warmstart);
00740
00741 if (! ws)
00742 return false;
00743
00744 const int ws_size = ws->size();
00745 if (ws_size != getNumRows() && ws_size != 0) {
00746 throw CoinError("wrong dual warmstart size", "setWarmStart",
00747 "OsiVolSolverInterface");
00748 }
00749
00750 CoinDisjointCopyN(ws->dual(), ws_size, rowprice_);
00751 return true;
00752 }
00753
00754
00755
00756
00757
00758 void
00759 OsiVolSolverInterface::markHotStart()
00760 {
00761 delete[] rowpriceHotStart_;
00762 rowpriceHotStart_ = new double[getNumRows()];
00763 CoinDisjointCopyN(rowprice_, getNumRows(), rowpriceHotStart_);
00764 }
00765
00766 void
00767 OsiVolSolverInterface::solveFromHotStart()
00768 {
00769 int itlimOrig = volprob_.parm.maxsgriters;
00770 getIntParam(OsiMaxNumIterationHotStart, volprob_.parm.maxsgriters);
00771 CoinDisjointCopyN(rowpriceHotStart_, getNumRows(), rowprice_);
00772 resolve();
00773 volprob_.parm.maxsgriters = itlimOrig;
00774 }
00775
00776 void
00777 OsiVolSolverInterface::unmarkHotStart()
00778 {
00779 delete[] rowpriceHotStart_;
00780 rowpriceHotStart_ = NULL;
00781 }
00782
00783
00784
00785
00786
00787 bool
00788 OsiVolSolverInterface::isContinuous(int colNumber) const
00789 {
00790 assert( continuous_!=NULL );
00791 if ( continuous_[colNumber] ) return true;
00792 return false;
00793 }
00794
00795
00796
00797 const CoinPackedMatrix *
00798 OsiVolSolverInterface::getMatrixByRow() const {
00799 updateRowMatrix_();
00800 return &rowMatrix_;
00801 }
00802
00803
00804
00805 const CoinPackedMatrix *
00806 OsiVolSolverInterface::getMatrixByCol() const {
00807 updateColMatrix_();
00808 return &colMatrix_;
00809 }
00810
00811
00812
00813
00814
00815 std::vector<double*> OsiVolSolverInterface::getDualRays(int maxNumRays) const
00816 {
00817
00818 throw CoinError("method is not yet written", "getDualRays",
00819 "OsiVolSolverInterface");
00820 return std::vector<double*>();
00821 }
00822
00823 std::vector<double*> OsiVolSolverInterface::getPrimalRays(int maxNumRays) const
00824 {
00825
00826 throw CoinError("method is not yet written", "getPrimalRays",
00827 "OsiVolSolverInterface");
00828 return std::vector<double*>();
00829 }
00830
00831
00832
00833
00834
00835
00836 void OsiVolSolverInterface::setColSetBounds(const int* indexFirst,
00837 const int* indexLast,
00838 const double* boundList)
00839 {
00840 while (indexFirst < indexLast) {
00841 const int ind = *indexFirst;
00842 collower_[ind] = boundList[0];
00843 colupper_[ind] = boundList[1];
00844 ++indexFirst;
00845 boundList += 2;
00846 }
00847 }
00848
00849
00850 void OsiVolSolverInterface::setRowSetBounds(const int* indexFirst,
00851 const int* indexLast,
00852 const double* boundList)
00853 {
00854 if (indexLast - indexFirst < getNumRows() / 3) {
00855 while (indexFirst < indexLast) {
00856 setRowBounds(*indexFirst, boundList[0], boundList[1]);
00857 ++indexFirst;
00858 boundList += 2;
00859 }
00860 } else {
00861
00862 while (indexFirst < indexLast) {
00863 const int ind = *indexFirst;
00864 rowlower_[ind] = boundList[0];
00865 rowupper_[ind] = boundList[1];
00866 ++indexFirst;
00867 boundList += 2;
00868 }
00869 convertBoundsToSenses_();
00870 }
00871 }
00872
00873
00874 void OsiVolSolverInterface::setRowSetTypes(const int* indexFirst,
00875 const int* indexLast,
00876 const char* senseList,
00877 const double* rhsList,
00878 const double* rangeList)
00879 {
00880 if (indexLast - indexFirst < getNumRows() / 3) {
00881 while (indexFirst < indexLast) {
00882 setRowType(*indexFirst++, *senseList++, *rhsList++, *rangeList++);
00883 }
00884 } else {
00885
00886 while (indexFirst < indexLast) {
00887 const int ind = *indexFirst++;
00888 rowsense_[ind] = *senseList++;
00889 rhs_[ind] = *rhsList++;
00890 rowrange_[ind] = *rangeList++;
00891 }
00892 convertSensesToBounds_();
00893 }
00894 }
00895
00896
00897
00898 void
00899 OsiVolSolverInterface::setContinuous(int index)
00900 {
00901 assert(continuous_ != NULL);
00902 if (index < 0 || index > getNumCols()) {
00903 throw CoinError("Index out of bound.", "setContinuous",
00904 "OsiVolSolverInterface");
00905 }
00906 continuous_[index] = true;
00907 }
00908
00909
00910
00911 void
00912 OsiVolSolverInterface::setInteger(int index)
00913 {
00914 assert(continuous_ != NULL);
00915 if (index < 0 || index > getNumCols()) {
00916 throw CoinError("Index out of bound.", "setContinuous",
00917 "OsiVolSolverInterface");
00918 }
00919 continuous_[index] = false;
00920 }
00921
00922
00923
00924 void
00925 OsiVolSolverInterface::setContinuous(const int* indices, int len)
00926 {
00927 assert(continuous_ != NULL);
00928 const int colnum = getNumCols();
00929 int i;
00930
00931 for (i = len - 1; i >= 0; --i) {
00932 if (indices[i] < 0 || indices[i] > colnum) {
00933 throw CoinError("Index out of bound.", "setContinuous",
00934 "OsiVolSolverInterface");
00935 }
00936 }
00937
00938 for (i = len - 1; i >= 0; --i) {
00939 continuous_[indices[i]] = true;
00940 }
00941 }
00942
00943
00944
00945 void
00946 OsiVolSolverInterface::setInteger(const int* indices, int len)
00947 {
00948 assert(continuous_ != NULL);
00949 const int colnum = getNumCols();
00950 int i;
00951
00952 for (i = len - 1; i >= 0; --i) {
00953 if (indices[i] < 0 || indices[i] > colnum) {
00954 throw CoinError("Index out of bound.", "setContinuous",
00955 "OsiVolSolverInterface");
00956 }
00957 }
00958
00959 for (i = len - 1; i >= 0; --i) {
00960 continuous_[indices[i]] = false;
00961 }
00962 }
00963
00964
00965
00966 void
00967 OsiVolSolverInterface::setColSolution(const double *colsol)
00968 {
00969 CoinDisjointCopyN(colsol, getNumCols(), colsol_);
00970 }
00971
00972
00973
00974 void
00975 OsiVolSolverInterface::setRowPrice(const double *rowprice)
00976 {
00977 CoinDisjointCopyN(rowprice, getNumRows(), rowprice_);
00978 }
00979
00980
00981
00982
00983
00984 void
00985 OsiVolSolverInterface::addCol(const CoinPackedVectorBase& vec,
00986 const double collb, const double colub,
00987 const double obj)
00988 {
00989 const int colnum = getNumCols();
00990 colRimResize_(colnum + 1);
00991 collower_[colnum] = collb;
00992 colupper_[colnum] = colub;
00993 objcoeffs_[colnum] = obj;
00994 continuous_[colnum] = true;
00995 colsol_[colnum] = fabs(collb)<fabs(colub) ? collb : colub;
00996 rc_[colnum] = 0.0;
00997
00998 updateColMatrix_();
00999 colMatrix_.appendCol(vec);
01000 rowMatrixCurrent_ = false;
01001 }
01002
01003
01004
01005 void
01006 OsiVolSolverInterface::addCols(const int numcols,
01007 const CoinPackedVectorBase * const * cols,
01008 const double* collb, const double* colub,
01009 const double* obj)
01010 {
01011 if (numcols > 0) {
01012 const int colnum = getNumCols();
01013 colRimResize_(colnum + numcols);
01014 CoinDisjointCopyN(collb, numcols, collower_ + colnum);
01015 CoinDisjointCopyN(colub, numcols, colupper_ + colnum);
01016 CoinDisjointCopyN(obj, numcols, objcoeffs_ + colnum);
01017 CoinFillN(continuous_ + colnum, numcols, true);
01018 int c;
01019 for ( c=0; c<numcols; c++ ) {
01020 if ( fabs(collb[c]) < fabs(colub[c]) ) {
01021 colsol_[colnum+c] = collb[c];
01022 }
01023 else {
01024 colsol_[colnum+c] = colub[c];
01025 }
01026 }
01027
01028 CoinFillN(rc_ + colnum, numcols, 0.0);
01029
01030 updateColMatrix_();
01031 colMatrix_.appendCols(numcols, cols);
01032 rowMatrixCurrent_ = false;
01033 }
01034 }
01035
01036
01037
01038 void
01039 OsiVolSolverInterface::deleteCols(const int num, const int * columnIndices)
01040 {
01041 if (num > 0) {
01042 int * delPos = new int[num];
01043 CoinDisjointCopyN(columnIndices, num, delPos);
01044 std::sort(delPos, delPos + num);
01045 const int delNum = std::unique(delPos, delPos + num) - delPos;
01046
01047 const int colnum = getNumCols();
01048 CoinDeleteEntriesFromArray(collower_, collower_ + colnum,
01049 delPos, delPos + delNum);
01050 CoinDeleteEntriesFromArray(colupper_, colupper_ + colnum,
01051 delPos, delPos + delNum);
01052 CoinDeleteEntriesFromArray(objcoeffs_, objcoeffs_ + colnum,
01053 delPos, delPos + delNum);
01054 CoinDeleteEntriesFromArray(continuous_, continuous_ + colnum,
01055 delPos, delPos + delNum);
01056 CoinDeleteEntriesFromArray(colsol_, colsol_ + colnum,
01057 delPos, delPos + delNum);
01058 CoinDeleteEntriesFromArray(rc_, rc_ + colnum,
01059 delPos, delPos + delNum);
01060
01061 updateColMatrix_();
01062 colMatrix_.deleteCols(delNum, delPos);
01063 rowMatrixCurrent_ = false;
01064 }
01065 }
01066
01067
01068
01069
01070 void
01071 OsiVolSolverInterface::addRow(const CoinPackedVectorBase& vec,
01072 const double rowlb, const double rowub)
01073 {
01074 const int rownum = getNumRows();
01075 rowRimResize_(rownum + 1);
01076 rowlower_[rownum] = rowlb;
01077 rowupper_[rownum] = rowub;
01078 convertBoundToSense(rowlb, rowub,
01079 rowsense_[rownum], rhs_[rownum], rowrange_[rownum]);
01080 rowprice_[rownum] = 0.0;
01081 lhs_[rownum] = 0.0;
01082
01083 updateRowMatrix_();
01084 rowMatrix_.appendRow(vec);
01085 colMatrixCurrent_ = false;
01086 }
01087
01088
01089
01090 void
01091 OsiVolSolverInterface::addRow(const CoinPackedVectorBase& vec,
01092 const char rowsen, const double rowrhs,
01093 const double rowrng)
01094 {
01095 const int rownum = getNumRows();
01096 rowRimResize_(rownum + 1);
01097 rowsense_[rownum] = rowsen;
01098 rhs_[rownum] = rowrhs;
01099 rowrange_[rownum] = rowrng;
01100 convertSenseToBound(rowsen, rowrhs, rowrng,
01101 rowlower_[rownum], rowupper_[rownum]);
01102 rowprice_[rownum] = 0.0;
01103 lhs_[rownum] = 0.0;
01104
01105 updateRowMatrix_();
01106 rowMatrix_.appendRow(vec);
01107 colMatrixCurrent_ = false;
01108 }
01109
01110
01111
01112 void
01113 OsiVolSolverInterface::addRows(const int numrows,
01114 const CoinPackedVectorBase * const * rows,
01115 const double* rowlb, const double* rowub)
01116 {
01117 if (numrows > 0) {
01118 const int rownum = getNumRows();
01119 rowRimResize_(rownum + numrows);
01120 CoinDisjointCopyN(rowlb, numrows, rowlower_ + rownum);
01121 CoinDisjointCopyN(rowub, numrows, rowupper_ + rownum);
01122 for (int i = rownum + numrows - 1; i >= rownum; --i) {
01123 convertBoundToSense(rowlower_[i], rowupper_[i],
01124 rowsense_[i], rhs_[i], rowrange_[i]);
01125 }
01126 CoinFillN(rowprice_ + rownum, numrows, 0.0);
01127 CoinFillN(lhs_ + rownum, numrows, 0.0);
01128
01129 updateRowMatrix_();
01130 rowMatrix_.appendRows(numrows, rows);
01131 colMatrixCurrent_ = false;
01132 }
01133 }
01134
01135
01136
01137 void
01138 OsiVolSolverInterface::addRows(const int numrows,
01139 const CoinPackedVectorBase * const * rows,
01140 const char* rowsen, const double* rowrhs,
01141 const double* rowrng)
01142 {
01143 if (numrows > 0) {
01144 const int rownum = getNumRows();
01145 rowRimResize_(rownum + numrows);
01146 CoinDisjointCopyN(rowsen, numrows, rowsense_ + rownum);
01147 CoinDisjointCopyN(rowrhs, numrows, rhs_ + rownum);
01148 CoinDisjointCopyN(rowrng, numrows, rowrange_ + rownum);
01149 for (int i = rownum + numrows - 1; i >= rownum; --i) {
01150 convertSenseToBound(rowsense_[i], rhs_[i], rowrange_[i],
01151 rowlower_[i], rowupper_[i]);
01152 }
01153 CoinFillN(rowprice_ + rownum, numrows, 0.0);
01154 CoinFillN(lhs_ + rownum, numrows, 0.0);
01155
01156 updateRowMatrix_();
01157 rowMatrix_.appendRows(numrows, rows);
01158 colMatrixCurrent_ = false;
01159 }
01160 }
01161
01162
01163
01164 void
01165 OsiVolSolverInterface::deleteRows(const int num, const int * rowIndices)
01166 {
01167 if (num > 0) {
01168 int * delPos = new int[num];
01169 CoinDisjointCopyN(rowIndices, num, delPos);
01170 std::sort(delPos, delPos + num);
01171 const int delNum = std::unique(delPos, delPos + num) - delPos;
01172
01173 const int rownum = getNumRows();
01174 CoinDeleteEntriesFromArray(rowlower_, rowlower_ + rownum,
01175 delPos, delPos + delNum);
01176 CoinDeleteEntriesFromArray(rowupper_, rowupper_ + rownum,
01177 delPos, delPos + delNum);
01178 CoinDeleteEntriesFromArray(rowsense_, rowsense_ + rownum,
01179 delPos, delPos + delNum);
01180 CoinDeleteEntriesFromArray(rowrange_, rowrange_ + rownum,
01181 delPos, delPos + delNum);
01182 CoinDeleteEntriesFromArray(rhs_, rhs_ + rownum,
01183 delPos, delPos + delNum);
01184 CoinDeleteEntriesFromArray(rowprice_, rowprice_ + rownum,
01185 delPos, delPos + delNum);
01186 CoinDeleteEntriesFromArray(lhs_, lhs_ + rownum,
01187 delPos, delPos + delNum);
01188
01189 updateRowMatrix_();
01190 rowMatrix_.deleteRows(delNum, delPos);
01191 colMatrixCurrent_ = false;
01192
01193 delete[] delPos;
01194 }
01195 }
01196
01197
01198
01199
01200
01201 OsiVolSolverInterface::OsiVolSolverInterface () :
01202 rowMatrixCurrent_(true),
01203 rowMatrix_(),
01204 colMatrixCurrent_(true),
01205 colMatrix_(),
01206
01207 colupper_(0),
01208 collower_(0),
01209 continuous_(0),
01210 rowupper_(0),
01211 rowlower_(0),
01212 rowsense_(0),
01213 rhs_(0),
01214 rowrange_(0),
01215
01216 objcoeffs_(0),
01217 objsense_(1.0),
01218
01219 colsol_(0),
01220 rowprice_(0),
01221 rc_(0),
01222 lhs_(0),
01223 lagrangeanCost_(0.0),
01224
01225 rowpriceHotStart_(0),
01226
01227 maxNumrows_(0),
01228 maxNumcols_(0),
01229
01230 volprob_()
01231 {
01232 volprob_.parm.granularity = 0.0;
01233 }
01234
01235
01236
01237 OsiSolverInterface *
01238 OsiVolSolverInterface::clone(bool copyData) const {
01239 return copyData ?
01240 new OsiVolSolverInterface(*this) :
01241 new OsiVolSolverInterface();
01242 }
01243
01244
01245
01246 OsiVolSolverInterface::OsiVolSolverInterface(const OsiVolSolverInterface& x) :
01247 rowMatrixCurrent_(true),
01248 rowMatrix_(),
01249 colMatrixCurrent_(true),
01250 colMatrix_(),
01251
01252 colupper_(0),
01253 collower_(0),
01254 continuous_(0),
01255 rowupper_(0),
01256 rowlower_(0),
01257 rowsense_(0),
01258 rhs_(0),
01259 rowrange_(0),
01260
01261 objcoeffs_(0),
01262 objsense_(1.0),
01263
01264 colsol_(0),
01265 rowprice_(0),
01266 rc_(0),
01267 lhs_(0),
01268 lagrangeanCost_(0.0),
01269
01270 rowpriceHotStart_(0),
01271
01272 maxNumrows_(0),
01273 maxNumcols_(0),
01274
01275 volprob_()
01276 {
01277 operator=(x);
01278 volprob_.parm.granularity = 0.0;
01279 }
01280
01281
01282
01283 OsiVolSolverInterface&
01284 OsiVolSolverInterface::operator=(const OsiVolSolverInterface& rhs)
01285 {
01286 if (&rhs == this)
01287 return *this;
01288
01289 OsiSolverInterface::operator=(rhs);
01290 gutsOfDestructor_();
01291
01292 rowMatrixCurrent_ = rhs.rowMatrixCurrent_;
01293 if (rowMatrixCurrent_)
01294 rowMatrix_ = rhs.rowMatrix_;
01295 colMatrixCurrent_ = rhs.colMatrixCurrent_;
01296 if (colMatrixCurrent_)
01297 colMatrix_ = rhs.colMatrix_;
01298
01299 if (rhs.maxNumrows_) {
01300 maxNumrows_ = rhs.maxNumrows_;
01301 rowRimAllocator_();
01302 const int rownum = getNumRows();
01303 CoinDisjointCopyN(rhs.rowupper_, rownum, rowupper_);
01304 CoinDisjointCopyN(rhs.rowlower_, rownum, rowlower_);
01305 CoinDisjointCopyN(rhs.rowsense_, rownum, rowsense_);
01306 CoinDisjointCopyN(rhs.rhs_, rownum, rhs_);
01307 CoinDisjointCopyN(rhs.rowrange_, rownum, rowrange_);
01308 CoinDisjointCopyN(rhs.rowprice_, rownum, rowprice_);
01309 CoinDisjointCopyN(rhs.lhs_, rownum, lhs_);
01310 }
01311 if (rhs.maxNumcols_) {
01312 maxNumcols_ = rhs.maxNumcols_;
01313 colRimAllocator_();
01314 const int colnum = getNumCols();
01315 CoinDisjointCopyN(rhs.colupper_, colnum, colupper_);
01316 CoinDisjointCopyN(rhs.collower_, colnum, collower_);
01317 CoinDisjointCopyN(rhs.continuous_, colnum, continuous_);
01318 CoinDisjointCopyN(rhs.objcoeffs_, colnum, objcoeffs_);
01319 CoinDisjointCopyN(rhs.colsol_, colnum, colsol_);
01320 CoinDisjointCopyN(rhs.rc_, colnum, rc_);
01321 }
01322 volprob_.parm.granularity = 0.0;
01323 return *this;
01324 }
01325
01326
01327
01328 OsiVolSolverInterface::~OsiVolSolverInterface ()
01329 {
01330 gutsOfDestructor_();
01331 }
01332
01333
01334
01335
01336
01337 void
01338 OsiVolSolverInterface::applyRowCut(const OsiRowCut& rc)
01339 {
01340 const int rownum = getNumRows();
01341 const double lb = rc.lb();
01342 const double ub = rc.ub();
01343 rowRimResize_(rownum + 1);
01344 rowprice_[rownum] = 0.0;
01345 rowlower_[rownum] = lb;
01346 rowupper_[rownum] = ub;
01347 convertBoundToSense(lb, ub,
01348 rowsense_[rownum], rhs_[rownum], rowrange_[rownum]);
01349
01350 updateRowMatrix_();
01351 rowMatrix_.appendRow(rc.row());
01352 colMatrixCurrent_ = false;
01353 }
01354
01355
01356
01357 void
01358 OsiVolSolverInterface::applyColCut(const OsiColCut& cc)
01359 {
01360 int i;
01361
01362 const double* lb_elem = cc.lbs().getElements();
01363 const int* lb_ind = cc.lbs().getIndices();
01364 for (i = cc.lbs().getNumElements() - 1; i >= 0; --i) {
01365 collower_[lb_ind[i]] = CoinMax(collower_[lb_ind[i]], lb_elem[i]);
01366 }
01367
01368 const double* ub_elem = cc.ubs().getElements();
01369 const int* ub_ind = cc.ubs().getIndices();
01370 for (i = cc.ubs().getNumElements() - 1; i >= 0; --i) {
01371 colupper_[ub_ind[i]] = CoinMin(colupper_[ub_ind[i]], ub_elem[i]);
01372 }
01373 }
01374
01375