1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 // This file is licensed under the terms of Eclipse Public License (EPL).
4
5 // this is a copy of OsiVolSolverInterface (trunk rev. 1466) renamed to OsiTestSolverInterface
6
7 #include "CoinPragma.hpp"
8
9 #include <cstdlib>
10 #include <numeric>
11 #include <cassert>
12 #include <cmath>
13
14 #include "CoinHelperFunctions.hpp"
15 #include "CoinWarmStartDual.hpp"
16
17 #include "OsiTestSolverInterface.hpp"
18 #include "OsiRowCut.hpp"
19 #include "OsiColCut.hpp"
20
21 //#######################################################################
22 // Private helper methods
23 //#######################################################################
24
25 void
updateRowMatrix_() const26 OsiTestSolverInterface::updateRowMatrix_() const
27 {
28 if (! rowMatrixCurrent_) {
29 rowMatrix_.reverseOrderedCopyOf(colMatrix_);
30 rowMatrixCurrent_ = true;
31 }
32 }
33
34 void
updateColMatrix_() const35 OsiTestSolverInterface::updateColMatrix_() const
36 {
37 if (! colMatrixCurrent_) {
38 colMatrix_.reverseOrderedCopyOf(rowMatrix_);
39 colMatrixCurrent_ = true;
40 }
41 }
42
43 //-----------------------------------------------------------------------------
44
45 void
checkData_() const46 OsiTestSolverInterface::checkData_() const
47 {
48 int i;
49 for (i = getNumRows() - 1; i >= 0; --i) {
50 if (rowlower_[i] > -1.0e20 &&
51 rowupper_[i] < 1.0e20 &&
52 rowlower_[i] != rowupper_[i])
53 throw CoinError("Volume algorithm is unable to handle ranged rows",
54 "checkData_", "OsiTestSolverInterface");
55 }
56
57 for (i = getNumCols() - 1; i >= 0; --i) {
58 if (collower_[i] < -1.0e20 || colupper_[i] > 1.0e20)
59 throw CoinError("Volume algorithm is unable to handle infinite bounds",
60 "checkData_", "OsiTestSolverInterface");
61 }
62 }
63
64 //-----------------------------------------------------------------------------
65
66 void
compute_rc_(const double * u,double * rc) const67 OsiTestSolverInterface::compute_rc_(const double* u, double* rc) const
68 {
69 if (isZeroOneMinusOne_) {
70 rowMatrixOneMinusOne_->timesMajor(u, rc);
71 } else {
72 rowMatrix_.transposeTimes(u, rc);
73 }
74
75 const int psize = getNumCols();
76 std::transform(rc, rc+psize, objcoeffs_, rc, std::minus<double>());
77 std::transform(rc, rc+psize, rc, std::negate<double>());
78 }
79
80 //#############################################################################
81
82 bool
test_zero_one_minusone_(const CoinPackedMatrix & m) const83 OsiTestSolverInterface::test_zero_one_minusone_(const CoinPackedMatrix& m) const
84 {
85 const int vecnum = m.getMajorDim();
86 const double* elem = m.getElements();
87 const int* start = m.getVectorStarts();
88 const int* length = m.getVectorLengths();
89 int i, j;
90 for (i = 0; i < vecnum; ++i) {
91 for (j = start[i] + length[i] - 1; j >= start[i]; --j) {
92 const double val = elem[j];
93 if (val != 1.0 && val != 0.0 && val != -1.0) {
94 return false;
95 }
96 }
97 }
98 return true;
99 }
100
101 //-----------------------------------------------------------------------------
102
103 OsiTestSolverInterface::OsiVolMatrixOneMinusOne_::
OsiVolMatrixOneMinusOne_(const CoinPackedMatrix & m)104 OsiVolMatrixOneMinusOne_(const CoinPackedMatrix& m) {
105 const int major = m.getMajorDim();
106 const double* elem = m.getElements();
107 const int* ind = m.getIndices();
108 const int* start = m.getVectorStarts();
109 const int* length = m.getVectorLengths();
110
111 majorDim_ = major;
112 minorDim_ = m.getMinorDim();
113
114 plusSize_ = 0;
115 minusSize_ = 0;
116 int i, j;
117 for (i = 0; i < major; ++i) {
118 for (j = start[i] + length[i] - 1; j >= start[i]; --j) {
119 const double val = elem[j];
120 if (val == 1.0) {
121 ++plusSize_;
122 } else if (val == -1.0) {
123 ++minusSize_;
124 }
125 }
126 }
127 if (plusSize_ > 0) {
128 plusInd_ = new int[plusSize_];
129 }
130 if (minusSize_ > 0) {
131 minusInd_ = new int[minusSize_];
132 }
133 plusStart_ = new int[major];
134 plusLength_ = new int[major];
135 minusStart_ = new int[major];
136 minusLength_ = new int[major];
137
138 plusSize_ = 0;
139 minusSize_ = 0;
140 for (i = 0; i < major; ++i) {
141 plusStart_[i] = plusSize_;
142 minusStart_[i] = minusSize_;
143 const int last = start[i] + length[i];
144 for (j = start[i]; j < last; ++j) {
145 const double val = elem[j];
146 if (val == 1.0) {
147 plusInd_[plusSize_++] = ind[j];
148 } else if (val == -1.0) {
149 minusInd_[minusSize_++] = ind[j];
150 }
151 }
152 plusLength_[i] = plusSize_ - plusStart_[i];
153 minusLength_[i] = minusSize_ - minusStart_[i];
154 }
155 if (plusSize_ == 0) {
156 delete[] plusStart_; plusStart_ = NULL;
157 delete[] plusLength_; plusLength_ = NULL;
158 }
159 if (minusSize_ == 0) {
160 delete[] minusStart_; minusStart_ = NULL;
161 delete[] minusLength_; minusLength_ = NULL;
162 }
163 }
164
165 //-----------------------------------------------------------------------------
166
167 OsiTestSolverInterface::OsiVolMatrixOneMinusOne_::
~OsiVolMatrixOneMinusOne_()168 ~OsiVolMatrixOneMinusOne_() {
169 if (plusSize_ > 0) {
170 delete[] plusInd_; plusInd_ = NULL;
171 delete[] plusStart_; plusStart_ = NULL;
172 delete[] plusLength_; plusLength_ = NULL;
173 }
174 if (minusSize_ > 0) {
175 delete[] minusInd_; minusInd_ = NULL;
176 delete[] minusStart_; minusStart_ = NULL;
177 delete[] minusLength_; minusLength_ = NULL;
178 }
179 }
180
181 //-----------------------------------------------------------------------------
182
183 void OsiTestSolverInterface::OsiVolMatrixOneMinusOne_::
timesMajor(const double * x,double * y) const184 timesMajor(const double* x, double* y) const
185 {
186 memset(y, 0, minorDim_ * sizeof(double));
187 int i;
188
189 if (plusSize_ > 0 && minusSize_ > 0) {
190 for (i = majorDim_ - 1; i >= 0; --i) {
191 const double x_i = x[i];
192 if (x_i != 0.0) {
193 const int* vecInd = plusInd_ + plusStart_[i];
194 int j;
195 for ( j = plusLength_[i] - 1; j >= 0; --j)
196 y[vecInd[j]] += x_i;
197 vecInd = minusInd_ + minusStart_[i];
198 for ( j = minusLength_[i] - 1; j >= 0; --j)
199 y[vecInd[j]] -= x_i;
200 }
201 }
202 return;
203 }
204 if (plusSize_ > 0) {
205 for (i = majorDim_ - 1; i >= 0; --i) {
206 const double x_i = x[i];
207 if (x_i != 0.0) {
208 const int* vecInd = plusInd_ + plusStart_[i];
209 for (int j = plusLength_[i] - 1; j >= 0; --j)
210 y[vecInd[j]] += x_i;
211 }
212 }
213 return;
214 }
215 if (minusSize_ > 0) {
216 for (i = majorDim_ - 1; i >= 0; --i) {
217 const double x_i = x[i];
218 if (x_i != 0.0) {
219 const int* vecInd = minusInd_ + minusStart_[i];
220 for (int j = minusLength_[i] - 1; j >= 0; --j)
221 y[vecInd[j]] -= x_i;
222 }
223 }
224 return;
225 }
226 }
227
228 //#############################################################################
229
230 void
gutsOfDestructor_()231 OsiTestSolverInterface::gutsOfDestructor_()
232 {
233 rowMatrix_.clear();
234 colMatrix_.clear();
235 rowMatrixCurrent_ = true;
236 colMatrixCurrent_ = true;
237
238 delete[] colupper_; colupper_ = 0;
239 delete[] collower_; collower_ = 0;
240 delete[] continuous_; continuous_ = 0;
241 delete[] rowupper_; rowupper_ = 0;
242 delete[] rowlower_; rowlower_ = 0;
243 delete[] rowsense_; rowsense_ = 0;
244 delete[] rhs_; rhs_ = 0;
245 delete[] rowrange_; rowrange_ = 0;
246 delete[] objcoeffs_; objcoeffs_ = 0;
247
248 delete[] colsol_; colsol_ = 0;
249 delete[] rowprice_; rowprice_ = 0;
250 delete[] rowpriceHotStart_; rowpriceHotStart_ = 0;
251 delete[] rc_; rc_ = 0;
252 delete[] lhs_; lhs_ = 0;
253
254 lagrangeanCost_ = 0.0;
255
256 maxNumrows_ = 0;
257 maxNumcols_ = 0;
258 }
259
260 //#############################################################################
261
262 void
rowRimAllocator_()263 OsiTestSolverInterface::rowRimAllocator_()
264 {
265 rowupper_ = new double[maxNumrows_];
266 rowlower_ = new double[maxNumrows_];
267 rowsense_ = new char[maxNumrows_];
268 rhs_ = new double[maxNumrows_];
269 rowrange_ = new double[maxNumrows_];
270 rowprice_ = new double[maxNumrows_];
271 lhs_ = new double[maxNumrows_];
272 }
273
274 //-----------------------------------------------------------------------------
275
276 void
colRimAllocator_()277 OsiTestSolverInterface::colRimAllocator_()
278 {
279 colupper_ = new double[maxNumcols_];
280 collower_ = new double[maxNumcols_];
281 continuous_ = new bool[maxNumcols_];
282 objcoeffs_ = new double[maxNumcols_];
283 colsol_ = new double[maxNumcols_];
284 rc_ = new double[maxNumcols_];
285 }
286
287 //-----------------------------------------------------------------------------
288
289 void
rowRimResize_(const int newSize)290 OsiTestSolverInterface::rowRimResize_(const int newSize)
291 {
292 if (newSize > maxNumrows_) {
293 double* rub = rowupper_;
294 double* rlb = rowlower_;
295 char* sense = rowsense_;
296 double* right = rhs_;
297 double* range = rowrange_;
298 double* dual = rowprice_;
299 double* left = lhs_;
300 maxNumrows_ = CoinMax(1000, (newSize * 5) / 4);
301 rowRimAllocator_();
302 const int rownum = getNumRows();
303 CoinDisjointCopyN(rub , rownum, rowupper_);
304 CoinDisjointCopyN(rlb , rownum, rowlower_);
305 CoinDisjointCopyN(sense, rownum, rowsense_);
306 CoinDisjointCopyN(right, rownum, rhs_);
307 CoinDisjointCopyN(range, rownum, rowrange_);
308 CoinDisjointCopyN(dual , rownum, rowprice_);
309 CoinDisjointCopyN(left , rownum, lhs_);
310 delete[] rub;
311 delete[] rlb;
312 delete[] sense;
313 delete[] right;
314 delete[] range;
315 delete[] dual;
316 delete[] left;
317 }
318 }
319
320 //-----------------------------------------------------------------------------
321
322 void
colRimResize_(const int newSize)323 OsiTestSolverInterface::colRimResize_(const int newSize)
324 {
325 if (newSize > maxNumcols_) {
326 double* cub = colupper_;
327 double* clb = collower_;
328 bool* cont = continuous_;
329 double* obj = objcoeffs_;
330 double* sol = colsol_;
331 double* rc = rc_;
332 maxNumcols_ = CoinMax(1000, (newSize * 5) / 4);
333 colRimAllocator_();
334 const int colnum = getNumCols();
335 CoinDisjointCopyN(cub , colnum, colupper_);
336 CoinDisjointCopyN(clb , colnum, collower_);
337 CoinDisjointCopyN(cont, colnum, continuous_);
338 CoinDisjointCopyN(obj , colnum, objcoeffs_);
339 CoinDisjointCopyN(sol , colnum, colsol_);
340 CoinDisjointCopyN(rc , colnum, rc_);
341 delete[] cub;
342 delete[] clb;
343 delete[] cont;
344 delete[] obj;
345 delete[] sol;
346 delete[] rc;
347 }
348 }
349
350 //#############################################################################
351
352 void
convertBoundsToSenses_()353 OsiTestSolverInterface::convertBoundsToSenses_()
354 {
355 for (int i = getNumRows() - 1; i >= 0; --i ) {
356 convertBoundToSense(rowlower_[i], rowupper_[i],
357 rowsense_[i], rhs_[i], rowrange_[i]);
358 }
359 }
360
361 //-----------------------------------------------------------------------------
362
363 void
convertSensesToBounds_()364 OsiTestSolverInterface::convertSensesToBounds_()
365 {
366 for (int i = getNumRows() - 1; i >= 0; --i) {
367 convertSenseToBound(rowsense_[i], rhs_[i], rowrange_[i],
368 rowlower_[i], rowupper_[i]);
369 }
370 }
371
372 //#############################################################################
373 // Here are the routines implementing the virtual methods inherited from
374 // VOL_user_hooks.
375 //#############################################################################
376
377 int
compute_rc(const VOL_dvector & u,VOL_dvector & rc)378 OsiTestSolverInterface::compute_rc(const VOL_dvector& u, VOL_dvector& rc)
379 {
380 compute_rc_(u.v, rc.v);
381 return 0;
382 }
383
384 //-----------------------------------------------------------------------
385
386 int
solve_subproblem(const VOL_dvector & dual,const VOL_dvector & rc,double & lcost,VOL_dvector & x,VOL_dvector & v,double & pcost)387 OsiTestSolverInterface::solve_subproblem(const VOL_dvector& dual,
388 const VOL_dvector& rc,
389 double& lcost,
390 VOL_dvector& x, VOL_dvector& v,
391 double& pcost)
392 {
393 int i;
394
395 const int psize = x.size();
396 for (i = 0; i < psize; ++i) {
397 x[i] = (rc[i] >= 0.0) ? collower_[i] : colupper_[i];
398 }
399
400 const int dsize = v.size();
401 lcost = (std::inner_product(rhs_, rhs_ + dsize, dual.v, 0.0) +
402 std::inner_product(x.v, x.v + psize, rc.v, 0.0) );
403
404 if (isZeroOneMinusOne_) {
405 colMatrixOneMinusOne_->timesMajor(x.v, v.v);
406 } else {
407 colMatrix_.times(x.v, v.v);
408 }
409
410 std::transform(v.v, v.v+dsize, rhs_, v.v, std::minus<double>());
411 std::transform(v.v, v.v+dsize, v.v, std::negate<double>());
412
413 pcost = std::inner_product(x.v, x.v + psize, objcoeffs_, 0.0);
414
415 return 0;
416 }
417
418 //#############################################################################
419 // Solve methods
420 //#############################################################################
421
422 void
initialSolve()423 OsiTestSolverInterface::initialSolve()
424 {
425 // set every entry to 0.0 in the dual solution
426 CoinFillN(rowprice_, getNumRows(), 0.0);
427 resolve();
428 }
429
430 //-----------------------------------------------------------------------------
431
432 void
resolve()433 OsiTestSolverInterface::resolve()
434 {
435 int i;
436
437 checkData_();
438
439 // Only one of these can do any work
440 updateRowMatrix_();
441 updateColMatrix_();
442
443 const int dsize = getNumRows();
444 const int psize = getNumCols();
445
446 // Negate the objective coefficients if necessary
447 if (objsense_ < 0) {
448 std::transform(objcoeffs_, objcoeffs_+psize, objcoeffs_,
449 std::negate<double>());
450 }
451
452 // Set the lb/ub on the duals
453 volprob_.dual_lb.allocate(dsize);
454 volprob_.dual_ub.allocate(dsize);
455 double * dlb = volprob_.dual_lb.v;
456 double * dub = volprob_.dual_ub.v;
457 for (i = 0; i < dsize; ++i) {
458 dlb[i] = rowupper_[i] < getInfinity() ? -1.0e31 : 0.0;
459 dub[i] = rowlower_[i] > -getInfinity() ? 1.0e31 : 0.0;
460 }
461 volprob_.dsize = dsize;
462 volprob_.psize = psize;
463
464 // Set the dual starting point
465 VOL_dvector& dsol = volprob_.dsol;
466 dsol.allocate(dsize);
467 std::transform(rowprice_, rowprice_+dsize, dsol.v,
468 std::bind2nd(std::multiplies<double>(), objsense_));
469
470 // adjust the dual vector (if necessary) to be sure it's feasible
471 double * dv = dsol.v;
472 for (i = 0; i < dsize; ++i) {
473 if (dv[i] < dlb[i]) {
474 dv[i] = dlb[i];
475 } else if (dv[i] > dub[i]) {
476 dv[i] = dub[i];
477 }
478 }
479
480 // If requested, check whether the matrix contains anything but 0/1/-1
481 #if 0
482 isZeroOneMinusOne_ = false;
483 #else
484 isZeroOneMinusOne_ = test_zero_one_minusone_(colMatrix_);
485 if (isZeroOneMinusOne_) {
486 colMatrixOneMinusOne_ = new OsiVolMatrixOneMinusOne_(colMatrix_);
487 rowMatrixOneMinusOne_ = new OsiVolMatrixOneMinusOne_(rowMatrix_);
488 }
489 #endif
490
491 volprob_.solve(*this, true);
492
493 // extract the solution
494
495 // the lower bound on the objective value
496 lagrangeanCost_ = objsense_ * volprob_.value;
497 // the primal solution
498 CoinDisjointCopyN(volprob_.psol.v, psize, colsol_);
499
500 // Reset the objective coefficients if necessary
501 if (objsense_ < 0) {
502 std::transform(objcoeffs_, objcoeffs_ + psize, objcoeffs_,
503 std::negate<double>());
504 // also, multiply the dual solution by -1
505 std::transform(volprob_.dsol.v, volprob_.dsol.v+dsize, rowprice_,
506 std::negate<double>());
507 } else {
508 // now we just have to copy the dual
509 CoinDisjointCopyN(volprob_.dsol.v, dsize, rowprice_);
510 }
511
512 // Compute the reduced costs
513 compute_rc_(rowprice_, rc_);
514
515 // Compute the left hand side (row activity levels)
516 if (isZeroOneMinusOne_) {
517 colMatrixOneMinusOne_->timesMajor(colsol_, lhs_);
518 } else {
519 colMatrix_.times(colsol_, lhs_);
520 }
521
522 if (isZeroOneMinusOne_) {
523 delete colMatrixOneMinusOne_;
524 colMatrixOneMinusOne_ = NULL;
525 delete rowMatrixOneMinusOne_;
526 rowMatrixOneMinusOne_ = NULL;
527 }
528 }
529
530 //#############################################################################
531 // Parameter related methods
532 //#############################################################################
533
534 bool
setIntParam(OsiIntParam key,int value)535 OsiTestSolverInterface::setIntParam(OsiIntParam key, int value)
536 {
537 switch (key) {
538 case OsiMaxNumIteration:
539 if (value < 0)
540 return false;
541 volprob_.parm.maxsgriters = value;
542 break;
543 case OsiMaxNumIterationHotStart:
544 if (value < 0)
545 return false;
546 OsiSolverInterface::setIntParam(key, value);
547 break;
548 case OsiLastIntParam:
549 return false;
550 default:
551 return false;
552 }
553 return true;
554 }
555
556 //-----------------------------------------------------------------------------
557
558 bool
setDblParam(OsiDblParam key,double value)559 OsiTestSolverInterface::setDblParam(OsiDblParam key, double value)
560 {
561 switch (key) {
562 case OsiDualObjectiveLimit:
563 volprob_.parm.ubinit = value;
564 break;
565 case OsiPrimalObjectiveLimit: // not applicable
566 return false;
567 case OsiDualTolerance: // only ~0 is applicable, so accept only 1e-50 ...
568 return (value == 1e-50);
569 case OsiPrimalTolerance:
570 if (value < 1e-04 || value > 1e-1)
571 return false;
572 volprob_.parm.primal_abs_precision = value;
573 break;
574 case OsiObjOffset:
575 return OsiSolverInterface::setDblParam(key, value);
576 case OsiLastDblParam:
577 return false;
578 default:
579 return false;
580 }
581 return true;
582 }
583
584
585 //-----------------------------------------------------------------------------
586
587 bool
setStrParam(OsiStrParam key,const std::string & value)588 OsiTestSolverInterface::setStrParam(OsiStrParam key, const std::string & value)
589 {
590 bool retval=false;
591 switch (key) {
592 case OsiSolverName:
593 return false;
594
595 case OsiProbName:
596 OsiSolverInterface::setStrParam(key,value);
597 return retval = true;
598
599 case OsiLastStrParam:
600 return false;
601
602 default:
603 return false;
604 }
605 return false;
606 }
607
608 //-----------------------------------------------------------------------------
609
610 bool
getIntParam(OsiIntParam key,int & value) const611 OsiTestSolverInterface::getIntParam(OsiIntParam key, int& value) const
612 {
613 switch (key) {
614 case OsiMaxNumIteration:
615 value = volprob_.parm.maxsgriters;
616 break;
617 case OsiMaxNumIterationHotStart:
618 OsiSolverInterface::getIntParam(key, value);
619 break;
620 case OsiLastIntParam:
621 return false;
622 default:
623 return false;
624 }
625 return true;
626 }
627
628 //-----------------------------------------------------------------------------
629
630 bool
getDblParam(OsiDblParam key,double & value) const631 OsiTestSolverInterface::getDblParam(OsiDblParam key, double& value) const
632 {
633 switch (key) {
634 case OsiDualObjectiveLimit:
635 value = volprob_.parm.ubinit;
636 break;
637 case OsiPrimalObjectiveLimit: // not applicable
638 return false;
639 case OsiDualTolerance: // not applicable, but must return almost 0
640 value = 1e-50;
641 break;
642 case OsiPrimalTolerance:
643 value = volprob_.parm.primal_abs_precision;
644 break;
645 case OsiObjOffset:
646 OsiSolverInterface::getDblParam(key, value);
647 break;
648 case OsiLastDblParam:
649 return false;
650 default:
651 return false;
652 }
653 return true;
654 }
655
656
657 //-----------------------------------------------------------------------------
658
659 bool
getStrParam(OsiStrParam key,std::string & value) const660 OsiTestSolverInterface::getStrParam(OsiStrParam key, std::string & value) const
661 {
662 switch (key) {
663 case OsiProbName:
664 OsiSolverInterface::getStrParam(key, value);
665 return true;
666 case OsiSolverName:
667 value = "vol";
668 return true;
669 case OsiLastStrParam:
670 return false;
671 default:
672 return false;
673 }
674 return false;
675 }
676 //#############################################################################
677 // Methods returning info on how the solution process terminated
678 //#############################################################################
679
680 bool
isAbandoned() const681 OsiTestSolverInterface::isAbandoned() const
682 {
683 // *THINK*: see the *THINK* in isProvenOptimal()
684 return false;
685 }
686
687 bool
isProvenOptimal() const688 OsiTestSolverInterface::isProvenOptimal() const
689 {
690 // if exited before reaching the iteration limit it is declared optimal
691 // *THINK*: Granted, it can exit because the dual value is not improving.
692 // *THINK*: Should that be "abandoned"? But then it'll be abandoned way too
693 // *THINK*: frequently...
694 return (! isDualObjectiveLimitReached() &&
695 volprob_.iter() < volprob_.parm.maxsgriters);
696 }
697
698 bool
isProvenPrimalInfeasible() const699 OsiTestSolverInterface::isProvenPrimalInfeasible() const
700 {
701 // LL: *FIXME* : at the moment the volume can't detect primal infeasibility.
702 // LL: *FIXME* : The dual will go to infinity.
703 return false;
704 }
705
706 bool
isProvenDualInfeasible() const707 OsiTestSolverInterface::isProvenDualInfeasible() const
708 {
709 // LL: *FIXME* : at the moment the volume assumes dual feasibility...
710 return false;
711 }
712
713 bool
isPrimalObjectiveLimitReached() const714 OsiTestSolverInterface::isPrimalObjectiveLimitReached() const
715 {
716 // The volume algorithm doesn't know anything about the primal; only the
717 // dual is monotone
718 return false;
719 }
720
721 bool
isDualObjectiveLimitReached() const722 OsiTestSolverInterface::isDualObjectiveLimitReached() const
723 {
724 return volprob_.parm.ubinit - volprob_.value < volprob_.parm.granularity;
725 }
726
727 bool
isIterationLimitReached() const728 OsiTestSolverInterface::isIterationLimitReached() const
729 {
730 return volprob_.iter() >= volprob_.parm.maxsgriters;
731 }
732
733 //#############################################################################
734 // WarmStart related methods
735 //#############################################################################
736
737 CoinWarmStart*
getEmptyWarmStart() const738 OsiTestSolverInterface::getEmptyWarmStart () const
739 { return (dynamic_cast<CoinWarmStart *>(new CoinWarmStartDual())) ; }
740
741 CoinWarmStart*
getWarmStart() const742 OsiTestSolverInterface::getWarmStart() const
743 {
744 return new CoinWarmStartDual(getNumRows(), rowprice_);
745 }
746
747 //-----------------------------------------------------------------------------
748
749 bool
setWarmStart(const CoinWarmStart * warmstart)750 OsiTestSolverInterface::setWarmStart(const CoinWarmStart* warmstart)
751 {
752 const CoinWarmStartDual* ws =
753 dynamic_cast<const CoinWarmStartDual*>(warmstart);
754
755 if (! ws)
756 return false;
757
758 const int ws_size = ws->size();
759 if (ws_size != getNumRows() && ws_size != 0) {
760 throw CoinError("wrong dual warmstart size", "setWarmStart",
761 "OsiTestSolverInterface");
762 }
763
764 CoinDisjointCopyN(ws->dual(), ws_size, rowprice_);
765 return true;
766 }
767
768 //#############################################################################
769 // HotStart related methods
770 //#############################################################################
771
772 void
markHotStart()773 OsiTestSolverInterface::markHotStart()
774 {
775 delete[] rowpriceHotStart_;
776 rowpriceHotStart_ = new double[getNumRows()];
777 CoinDisjointCopyN(rowprice_, getNumRows(), rowpriceHotStart_);
778 }
779
780 void
solveFromHotStart()781 OsiTestSolverInterface::solveFromHotStart()
782 {
783 int itlimOrig = volprob_.parm.maxsgriters;
784 getIntParam(OsiMaxNumIterationHotStart, volprob_.parm.maxsgriters);
785 CoinDisjointCopyN(rowpriceHotStart_, getNumRows(), rowprice_);
786 resolve();
787 volprob_.parm.maxsgriters = itlimOrig;
788 }
789
790 void
unmarkHotStart()791 OsiTestSolverInterface::unmarkHotStart()
792 {
793 delete[] rowpriceHotStart_;
794 rowpriceHotStart_ = NULL;
795 }
796
797 //#############################################################################
798 // Problem information methods (original data)
799 //#############################################################################
800
801 bool
isContinuous(int colNumber) const802 OsiTestSolverInterface::isContinuous(int colNumber) const
803 {
804 assert( continuous_!=NULL );
805 if ( continuous_[colNumber] ) return true;
806 return false;
807 }
808
809 //-----------------------------------------------------------------------------
810
811 const CoinPackedMatrix *
getMatrixByRow() const812 OsiTestSolverInterface::getMatrixByRow() const {
813 updateRowMatrix_();
814 return &rowMatrix_;
815 }
816
817 //-----------------------------------------------------------------------
818
819 const CoinPackedMatrix *
getMatrixByCol() const820 OsiTestSolverInterface::getMatrixByCol() const {
821 updateColMatrix_();
822 return &colMatrix_;
823 }
824
825 //#############################################################################
826 // Problem information methods (results)
827 //#############################################################################
828
getDualRays(int,bool) const829 std::vector<double*> OsiTestSolverInterface::getDualRays(int /*maxNumRays*/,
830 bool /*fullRay*/) const
831 {
832 // *FIXME* : must write the method -LL
833 throw CoinError("method is not yet written", "getDualRays",
834 "OsiTestSolverInterface");
835 return std::vector<double*>();
836 }
837 //------------------------------------------------------------------
getPrimalRays(int) const838 std::vector<double*> OsiTestSolverInterface::getPrimalRays(int /*maxNumRays*/) const
839 {
840 // *FIXME* : must write the method -LL
841 throw CoinError("method is not yet written", "getPrimalRays",
842 "OsiTestSolverInterface");
843 return std::vector<double*>();
844 }
845
846 //#############################################################################
847 // Problem modifying methods (rim vectors)
848 //#############################################################################
849
850 //-----------------------------------------------------------------------------
setColSetBounds(const int * indexFirst,const int * indexLast,const double * boundList)851 void OsiTestSolverInterface::setColSetBounds(const int* indexFirst,
852 const int* indexLast,
853 const double* boundList)
854 {
855 while (indexFirst < indexLast) {
856 const int ind = *indexFirst;
857 collower_[ind] = boundList[0];
858 colupper_[ind] = boundList[1];
859 ++indexFirst;
860 boundList += 2;
861 }
862 }
863
864 //-----------------------------------------------------------------------------
setRowSetBounds(const int * indexFirst,const int * indexLast,const double * boundList)865 void OsiTestSolverInterface::setRowSetBounds(const int* indexFirst,
866 const int* indexLast,
867 const double* boundList)
868 {
869 if (indexLast - indexFirst < getNumRows() / 3) {
870 while (indexFirst < indexLast) {
871 setRowBounds(*indexFirst, boundList[0], boundList[1]);
872 ++indexFirst;
873 boundList += 2;
874 }
875 } else {
876 // it's better to convert everything at once
877 while (indexFirst < indexLast) {
878 const int ind = *indexFirst;
879 rowlower_[ind] = boundList[0];
880 rowupper_[ind] = boundList[1];
881 ++indexFirst;
882 boundList += 2;
883 }
884 convertBoundsToSenses_();
885 }
886 }
887
888 //-----------------------------------------------------------------------------
setRowSetTypes(const int * indexFirst,const int * indexLast,const char * senseList,const double * rhsList,const double * rangeList)889 void OsiTestSolverInterface::setRowSetTypes(const int* indexFirst,
890 const int* indexLast,
891 const char* senseList,
892 const double* rhsList,
893 const double* rangeList)
894 {
895 if (indexLast - indexFirst < getNumRows() / 3) {
896 while (indexFirst < indexLast) {
897 setRowType(*indexFirst++, *senseList++, *rhsList++, *rangeList++);
898 }
899 } else {
900 // it's better to convert everything at once
901 while (indexFirst < indexLast) {
902 const int ind = *indexFirst++;
903 rowsense_[ind] = *senseList++;
904 rhs_[ind] = *rhsList++;
905 rowrange_[ind] = *rangeList++;
906 }
907 convertSensesToBounds_();
908 }
909 }
910
911 //#############################################################################
912
913 void
setContinuous(int index)914 OsiTestSolverInterface::setContinuous(int index)
915 {
916 assert(continuous_ != NULL);
917 if (index < 0 || index > getNumCols()) {
918 throw CoinError("Index out of bound.", "setContinuous",
919 "OsiTestSolverInterface");
920 }
921 continuous_[index] = true;
922 }
923
924 //-----------------------------------------------------------------------
925
926 void
setInteger(int index)927 OsiTestSolverInterface::setInteger(int index)
928 {
929 assert(continuous_ != NULL);
930 if (index < 0 || index > getNumCols()) {
931 throw CoinError("Index out of bound.", "setContinuous",
932 "OsiTestSolverInterface");
933 }
934 continuous_[index] = false;
935 }
936
937 //-----------------------------------------------------------------------
938
939 void
setContinuous(const int * indices,int len)940 OsiTestSolverInterface::setContinuous(const int* indices, int len)
941 {
942 assert(continuous_ != NULL);
943 const int colnum = getNumCols();
944 int i;
945
946 for (i = len - 1; i >= 0; --i) {
947 if (indices[i] < 0 || indices[i] > colnum) {
948 throw CoinError("Index out of bound.", "setContinuous",
949 "OsiTestSolverInterface");
950 }
951 }
952
953 for (i = len - 1; i >= 0; --i) {
954 continuous_[indices[i]] = true;
955 }
956 }
957
958 //-----------------------------------------------------------------------
959
960 void
setInteger(const int * indices,int len)961 OsiTestSolverInterface::setInteger(const int* indices, int len)
962 {
963 assert(continuous_ != NULL);
964 const int colnum = getNumCols();
965 int i;
966
967 for (i = len - 1; i >= 0; --i) {
968 if (indices[i] < 0 || indices[i] > colnum) {
969 throw CoinError("Index out of bound.", "setContinuous",
970 "OsiTestSolverInterface");
971 }
972 }
973
974 for (i = len - 1; i >= 0; --i) {
975 continuous_[indices[i]] = false;
976 }
977 }
978
979 //#############################################################################
980
981 void
setColSolution(const double * colsol)982 OsiTestSolverInterface::setColSolution(const double *colsol)
983 {
984 CoinDisjointCopyN(colsol, getNumCols(), colsol_);
985 // Compute the left hand side (row activity levels)
986 if (isZeroOneMinusOne_) {
987 colMatrixOneMinusOne_->timesMajor(colsol_, lhs_);
988 } else {
989 colMatrix_.times(colsol_, lhs_);
990 }
991 }
992
993 //-----------------------------------------------------------------------
994
995 void
setRowPrice(const double * rowprice)996 OsiTestSolverInterface::setRowPrice(const double *rowprice)
997 {
998 CoinDisjointCopyN(rowprice, getNumRows(), rowprice_);
999 compute_rc_(rowprice_, rc_);
1000 }
1001
1002 //#############################################################################
1003 // Problem modifying methods (matrix)
1004 //#############################################################################
1005
1006 void
addCol(const CoinPackedVectorBase & vec,const double collb,const double colub,const double obj)1007 OsiTestSolverInterface::addCol(const CoinPackedVectorBase& vec,
1008 const double collb, const double colub,
1009 const double obj)
1010 {
1011 const int colnum = getNumCols();
1012 colRimResize_(colnum + 1);
1013 collower_[colnum] = collb;
1014 colupper_[colnum] = colub;
1015 objcoeffs_[colnum] = obj;
1016 continuous_[colnum] = true;
1017 colsol_[colnum] = fabs(collb)<fabs(colub) ? collb : colub;
1018 rc_[colnum] = 0.0;
1019
1020 updateColMatrix_();
1021 colMatrix_.appendCol(vec);
1022 rowMatrixCurrent_ = false;
1023 }
1024
1025 //-----------------------------------------------------------------------------
1026
1027 void
addCols(const int numcols,const CoinPackedVectorBase * const * cols,const double * collb,const double * colub,const double * obj)1028 OsiTestSolverInterface::addCols(const int numcols,
1029 const CoinPackedVectorBase * const * cols,
1030 const double* collb, const double* colub,
1031 const double* obj)
1032 {
1033 if (numcols > 0) {
1034 const int colnum = getNumCols();
1035 colRimResize_(colnum + numcols);
1036 CoinDisjointCopyN(collb, numcols, collower_ + colnum);
1037 CoinDisjointCopyN(colub, numcols, colupper_ + colnum);
1038 CoinDisjointCopyN(obj, numcols, objcoeffs_ + colnum);
1039 CoinFillN(continuous_ + colnum, numcols, true);
1040 int c;
1041 for ( c=0; c<numcols; c++ ) {
1042 if ( fabs(collb[c]) < fabs(colub[c]) ) {
1043 colsol_[colnum+c] = collb[c];
1044 }
1045 else {
1046 colsol_[colnum+c] = colub[c];
1047 }
1048 }
1049 //CoinFillN(colsol_ + colnum, numcols, 0.0);
1050 CoinFillN(rc_ + colnum, numcols, 0.0);
1051
1052 updateColMatrix_();
1053 colMatrix_.appendCols(numcols, cols);
1054 rowMatrixCurrent_ = false;
1055 }
1056 }
1057
1058 //-----------------------------------------------------------------------------
1059
1060 void
deleteCols(const int num,const int * columnIndices)1061 OsiTestSolverInterface::deleteCols(const int num, const int * columnIndices)
1062 {
1063 if (num > 0) {
1064 int * delPos = new int[num];
1065 CoinDisjointCopyN(columnIndices, num, delPos);
1066 std::sort(delPos, delPos + num);
1067 const int delNum =
1068 static_cast<int>(std::unique(delPos, delPos + num) - delPos);
1069
1070 const int colnum = getNumCols();
1071 CoinDeleteEntriesFromArray(collower_, collower_ + colnum,
1072 delPos, delPos + delNum);
1073 CoinDeleteEntriesFromArray(colupper_, colupper_ + colnum,
1074 delPos, delPos + delNum);
1075 CoinDeleteEntriesFromArray(objcoeffs_, objcoeffs_ + colnum,
1076 delPos, delPos + delNum);
1077 CoinDeleteEntriesFromArray(continuous_, continuous_ + colnum,
1078 delPos, delPos + delNum);
1079 CoinDeleteEntriesFromArray(colsol_, colsol_ + colnum,
1080 delPos, delPos + delNum);
1081 CoinDeleteEntriesFromArray(rc_, rc_ + colnum,
1082 delPos, delPos + delNum);
1083
1084 updateColMatrix_();
1085 colMatrix_.deleteCols(delNum, delPos);
1086 rowMatrixCurrent_ = false;
1087 }
1088 }
1089
1090
1091 //-----------------------------------------------------------------------------
1092
1093 void
addRow(const CoinPackedVectorBase & vec,const double rowlb,const double rowub)1094 OsiTestSolverInterface::addRow(const CoinPackedVectorBase& vec,
1095 const double rowlb, const double rowub)
1096 {
1097 const int rownum = getNumRows();
1098 rowRimResize_(rownum + 1);
1099 rowlower_[rownum] = rowlb;
1100 rowupper_[rownum] = rowub;
1101 convertBoundToSense(rowlb, rowub,
1102 rowsense_[rownum], rhs_[rownum], rowrange_[rownum]);
1103 rowprice_[rownum] = 0.0;
1104 lhs_[rownum] = 0.0;
1105
1106 updateRowMatrix_();
1107 rowMatrix_.appendRow(vec);
1108 colMatrixCurrent_ = false;
1109 }
1110
1111 //-----------------------------------------------------------------------------
1112
1113 void
addRow(const CoinPackedVectorBase & vec,const char rowsen,const double rowrhs,const double rowrng)1114 OsiTestSolverInterface::addRow(const CoinPackedVectorBase& vec,
1115 const char rowsen, const double rowrhs,
1116 const double rowrng)
1117 {
1118 const int rownum = getNumRows();
1119 rowRimResize_(rownum + 1);
1120 rowsense_[rownum] = rowsen;
1121 rhs_[rownum] = rowrhs;
1122 rowrange_[rownum] = rowrng;
1123 convertSenseToBound(rowsen, rowrhs, rowrng,
1124 rowlower_[rownum], rowupper_[rownum]);
1125 rowprice_[rownum] = 0.0;
1126 lhs_[rownum] = 0.0;
1127
1128 updateRowMatrix_();
1129 rowMatrix_.appendRow(vec);
1130 colMatrixCurrent_ = false;
1131 }
1132
1133 //-----------------------------------------------------------------------------
1134
1135 void
addRows(const int numrows,const CoinPackedVectorBase * const * rows,const double * rowlb,const double * rowub)1136 OsiTestSolverInterface::addRows(const int numrows,
1137 const CoinPackedVectorBase * const * rows,
1138 const double* rowlb, const double* rowub)
1139 {
1140 if (numrows > 0) {
1141 const int rownum = getNumRows();
1142 rowRimResize_(rownum + numrows);
1143 CoinDisjointCopyN(rowlb, numrows, rowlower_ + rownum);
1144 CoinDisjointCopyN(rowub, numrows, rowupper_ + rownum);
1145 for (int i = rownum + numrows - 1; i >= rownum; --i) {
1146 convertBoundToSense(rowlower_[i], rowupper_[i],
1147 rowsense_[i], rhs_[i], rowrange_[i]);
1148 }
1149 CoinFillN(rowprice_ + rownum, numrows, 0.0);
1150 CoinFillN(lhs_ + rownum, numrows, 0.0);
1151
1152 updateRowMatrix_();
1153 rowMatrix_.appendRows(numrows, rows);
1154 colMatrixCurrent_ = false;
1155 }
1156 }
1157
1158 //-----------------------------------------------------------------------------
1159
1160 void
addRows(const int numrows,const CoinPackedVectorBase * const * rows,const char * rowsen,const double * rowrhs,const double * rowrng)1161 OsiTestSolverInterface::addRows(const int numrows,
1162 const CoinPackedVectorBase * const * rows,
1163 const char* rowsen, const double* rowrhs,
1164 const double* rowrng)
1165 {
1166 if (numrows > 0) {
1167 const int rownum = getNumRows();
1168 rowRimResize_(rownum + numrows);
1169 CoinDisjointCopyN(rowsen, numrows, rowsense_ + rownum);
1170 CoinDisjointCopyN(rowrhs, numrows, rhs_ + rownum);
1171 CoinDisjointCopyN(rowrng, numrows, rowrange_ + rownum);
1172 for (int i = rownum + numrows - 1; i >= rownum; --i) {
1173 convertSenseToBound(rowsense_[i], rhs_[i], rowrange_[i],
1174 rowlower_[i], rowupper_[i]);
1175 }
1176 CoinFillN(rowprice_ + rownum, numrows, 0.0);
1177 CoinFillN(lhs_ + rownum, numrows, 0.0);
1178
1179 updateRowMatrix_();
1180 rowMatrix_.appendRows(numrows, rows);
1181 colMatrixCurrent_ = false;
1182 }
1183 }
1184
1185 //-----------------------------------------------------------------------------
1186
1187 void
deleteRows(const int num,const int * rowIndices)1188 OsiTestSolverInterface::deleteRows(const int num, const int * rowIndices)
1189 {
1190 if (num > 0) {
1191 int * delPos = new int[num];
1192 CoinDisjointCopyN(rowIndices, num, delPos);
1193 std::sort(delPos, delPos + num);
1194 const int delNum =
1195 static_cast<int>(std::unique(delPos, delPos + num) - delPos);
1196
1197 const int rownum = getNumRows();
1198 CoinDeleteEntriesFromArray(rowlower_, rowlower_ + rownum,
1199 delPos, delPos + delNum);
1200 CoinDeleteEntriesFromArray(rowupper_, rowupper_ + rownum,
1201 delPos, delPos + delNum);
1202 CoinDeleteEntriesFromArray(rowsense_, rowsense_ + rownum,
1203 delPos, delPos + delNum);
1204 CoinDeleteEntriesFromArray(rowrange_, rowrange_ + rownum,
1205 delPos, delPos + delNum);
1206 CoinDeleteEntriesFromArray(rhs_, rhs_ + rownum,
1207 delPos, delPos + delNum);
1208 CoinDeleteEntriesFromArray(rowprice_, rowprice_ + rownum,
1209 delPos, delPos + delNum);
1210 CoinDeleteEntriesFromArray(lhs_, lhs_ + rownum,
1211 delPos, delPos + delNum);
1212
1213 updateRowMatrix_();
1214 rowMatrix_.deleteRows(delNum, delPos);
1215 colMatrixCurrent_ = false;
1216
1217 delete[] delPos;
1218 }
1219 }
1220
1221 //#############################################################################
1222 // Constructors, destructors clone and assignment
1223 //#############################################################################
1224
OsiTestSolverInterface()1225 OsiTestSolverInterface::OsiTestSolverInterface () :
1226 rowMatrixCurrent_(true),
1227 rowMatrix_(),
1228 colMatrixCurrent_(true),
1229 colMatrix_(),
1230 isZeroOneMinusOne_(false),
1231
1232 colupper_(0),
1233 collower_(0),
1234 continuous_(0),
1235 rowupper_(0),
1236 rowlower_(0),
1237 rowsense_(0),
1238 rhs_(0),
1239 rowrange_(0),
1240
1241 objcoeffs_(0),
1242 objsense_(1.0),
1243
1244 colsol_(0),
1245 rowprice_(0),
1246 rc_(0),
1247 lhs_(0),
1248 lagrangeanCost_(0.0),
1249
1250 rowpriceHotStart_(0),
1251
1252 maxNumrows_(0),
1253 maxNumcols_(0),
1254
1255 volprob_()
1256 {
1257 volprob_.parm.granularity = 0.0;
1258 }
1259
1260 //-----------------------------------------------------------------------
1261
1262 OsiSolverInterface *
clone(bool copyData) const1263 OsiTestSolverInterface::clone(bool copyData) const {
1264 return copyData ?
1265 new OsiTestSolverInterface(*this) :
1266 new OsiTestSolverInterface();
1267 }
1268
1269 //-----------------------------------------------------------------------
1270
OsiTestSolverInterface(const OsiTestSolverInterface & x)1271 OsiTestSolverInterface::OsiTestSolverInterface(const OsiTestSolverInterface& x) :
1272 OsiSolverInterface(x),
1273 rowMatrixCurrent_(true),
1274 rowMatrix_(),
1275 colMatrixCurrent_(true),
1276 colMatrix_(),
1277 isZeroOneMinusOne_(false),
1278
1279 colupper_(0),
1280 collower_(0),
1281 continuous_(0),
1282 rowupper_(0),
1283 rowlower_(0),
1284 rowsense_(0),
1285 rhs_(0),
1286 rowrange_(0),
1287
1288 objcoeffs_(0),
1289 objsense_(1.0),
1290
1291 colsol_(0),
1292 rowprice_(0),
1293 rc_(0),
1294 lhs_(0),
1295 lagrangeanCost_(0.0),
1296
1297 rowpriceHotStart_(0),
1298
1299 maxNumrows_(0),
1300 maxNumcols_(0),
1301
1302 volprob_()
1303 {
1304 operator=(x);
1305 volprob_.parm.granularity = 0.0;
1306 }
1307
1308 //-----------------------------------------------------------------------
1309
1310 OsiTestSolverInterface&
operator =(const OsiTestSolverInterface & rhs)1311 OsiTestSolverInterface::operator=(const OsiTestSolverInterface& rhs)
1312 {
1313 if (&rhs == this)
1314 return *this;
1315
1316 OsiSolverInterface::operator=(rhs);
1317 gutsOfDestructor_();
1318
1319 rowMatrixCurrent_ = rhs.rowMatrixCurrent_;
1320 if (rowMatrixCurrent_)
1321 rowMatrix_ = rhs.rowMatrix_;
1322 colMatrixCurrent_ = rhs.colMatrixCurrent_;
1323 if (colMatrixCurrent_)
1324 colMatrix_ = rhs.colMatrix_;
1325
1326 if (rhs.maxNumrows_) {
1327 maxNumrows_ = rhs.maxNumrows_;
1328 rowRimAllocator_();
1329 const int rownum = getNumRows();
1330 CoinDisjointCopyN(rhs.rowupper_, rownum, rowupper_);
1331 CoinDisjointCopyN(rhs.rowlower_, rownum, rowlower_);
1332 CoinDisjointCopyN(rhs.rowsense_, rownum, rowsense_);
1333 CoinDisjointCopyN(rhs.rhs_, rownum, rhs_);
1334 CoinDisjointCopyN(rhs.rowrange_, rownum, rowrange_);
1335 CoinDisjointCopyN(rhs.rowprice_, rownum, rowprice_);
1336 CoinDisjointCopyN(rhs.lhs_, rownum, lhs_);
1337 }
1338 if (rhs.maxNumcols_) {
1339 maxNumcols_ = rhs.maxNumcols_;
1340 colRimAllocator_();
1341 const int colnum = getNumCols();
1342 CoinDisjointCopyN(rhs.colupper_, colnum, colupper_);
1343 CoinDisjointCopyN(rhs.collower_, colnum, collower_);
1344 CoinDisjointCopyN(rhs.continuous_, colnum, continuous_);
1345 CoinDisjointCopyN(rhs.objcoeffs_, colnum, objcoeffs_);
1346 CoinDisjointCopyN(rhs.colsol_, colnum, colsol_);
1347 CoinDisjointCopyN(rhs.rc_, colnum, rc_);
1348 }
1349 volprob_.parm.granularity = 0.0;
1350 return *this;
1351 }
1352
1353 //-----------------------------------------------------------------------
1354
~OsiTestSolverInterface()1355 OsiTestSolverInterface::~OsiTestSolverInterface ()
1356 {
1357 gutsOfDestructor_();
1358 }
1359
1360 //#############################################################################
1361 // Applying cuts
1362 //#############################################################################
1363
1364 void
applyRowCut(const OsiRowCut & rc)1365 OsiTestSolverInterface::applyRowCut(const OsiRowCut& rc)
1366 {
1367 const int rownum = getNumRows();
1368 const double lb = rc.lb();
1369 const double ub = rc.ub();
1370 rowRimResize_(rownum + 1);
1371 rowprice_[rownum] = 0.0;
1372 rowlower_[rownum] = lb;
1373 rowupper_[rownum] = ub;
1374 convertBoundToSense(lb, ub,
1375 rowsense_[rownum], rhs_[rownum], rowrange_[rownum]);
1376
1377 updateRowMatrix_();
1378 rowMatrix_.appendRow(rc.row());
1379 colMatrixCurrent_ = false;
1380 }
1381
1382 //-----------------------------------------------------------------------
1383
1384 void
applyColCut(const OsiColCut & cc)1385 OsiTestSolverInterface::applyColCut(const OsiColCut& cc)
1386 {
1387 int i;
1388
1389 const double* lb_elem = cc.lbs().getElements();
1390 const int* lb_ind = cc.lbs().getIndices();
1391 for (i = cc.lbs().getNumElements() - 1; i >= 0; --i) {
1392 collower_[lb_ind[i]] = CoinMax(collower_[lb_ind[i]], lb_elem[i]);
1393 }
1394
1395 const double* ub_elem = cc.ubs().getElements();
1396 const int* ub_ind = cc.ubs().getIndices();
1397 for (i = cc.ubs().getNumElements() - 1; i >= 0; --i) {
1398 colupper_[ub_ind[i]] = CoinMin(colupper_[ub_ind[i]], ub_elem[i]);
1399 }
1400 }
1401
1402 //#############################################################################
1403