1// Copyright (C) 2000, International Business Machines
2// Corporation and others. All Rights Reserved.
3// This code is licensed under the terms of the Eclipse Public License (EPL).
4
5#include <stddef.h>
6#include <iostream>
7
8#include "CoinPragma.hpp"
9#include "CoinHelperFunctions.hpp"
10#include "CoinMpsIO.hpp"
11#include "CoinMessage.hpp"
12#include "CoinWarmStart.hpp"
13#ifdef COIN_SNAPSHOT
14#include "CoinSnapshot.hpp"
15#endif
16
17#include "OsiSolverInterface.hpp"
18#ifdef CBC_NEXT_VERSION
19#include "OsiSolverBranch.hpp"
20#endif
21#include "OsiCuts.hpp"
22#include "OsiRowCut.hpp"
23#include "OsiColCut.hpp"
24#include "OsiRowCutDebugger.hpp"
25#include "OsiAuxInfo.hpp"
26#include "OsiBranchingObject.hpp"
27#include <cassert>
28#include "CoinFinite.hpp"
29#include "CoinBuild.hpp"
30#include "CoinModel.hpp"
31#include "CoinLpIO.hpp"
32//#############################################################################
33// Hotstart related methods (primarily used in strong branching)
34// It is assumed that only bounds (on vars/constraints) can change between
35// markHotStart() and unmarkHotStart()
36//#############################################################################
37
38void OsiSolverInterface::markHotStart()
39{
40 delete ws_;
41 ws_ = getWarmStart();
42}
43
44void OsiSolverInterface::solveFromHotStart()
45{
46 setWarmStart(ws_);
47 resolve();
48}
49
50void OsiSolverInterface::unmarkHotStart()
51{
52 delete ws_;
53 ws_ = NULL;
54}
55
56//#############################################################################
57// Get indices of solution vector which are integer variables presently at
58// fractional values
59//#############################################################################
60
61OsiVectorInt
62OsiSolverInterface::getFractionalIndices(const double etol) const
63{
64 const int colnum = getNumCols();
65 OsiVectorInt frac;
66 CoinAbsFltEq eq(etol);
67 for (int i = 0; i < colnum; ++i) {
68 if (isInteger(i)) {
69 const double ci = getColSolution()[i];
70 const double distanceFromInteger = ci - floor(ci + 0.5);
71 if (! eq(distanceFromInteger, 0.0))
72 frac.push_back(i);
73 }
74 }
75 return frac;
76}
77
78
79int OsiSolverInterface::getNumElements() const
80{
81 return getMatrixByRow()->getNumElements();
82}
83
84//#############################################################################
85// Methods for determining the type of column variable.
86// The method isContinuous() is presently implemented in the derived classes.
87// The methods below depend on isContinuous and the values
88// stored in the column bounds.
89//#############################################################################
90
91bool
92OsiSolverInterface::isBinary(int colIndex) const
93{
94 if ( isContinuous(colIndex) ) return false;
95 const double * cu = getColUpper();
96 const double * cl = getColLower();
97 if (
98 (cu[colIndex]== 1 || cu[colIndex]== 0) &&
99 (cl[colIndex]== 0 || cl[colIndex]==1)
100 ) return true;
101 else return false;
102}
103
104
105//#############################################################################
106// Method for getting a column solution that is guaranteed to be
107// between the column lower and upper bounds.
108//
109// This method is was introduced for Cgl. Osi developers can
110// improve performance for their favorite solvers by
111// overriding this method and providing an implementation that caches
112// strictColSolution_.
113//#############################################################################
114
115const double *
116OsiSolverInterface::getStrictColSolution()
117{
118 const double * colSolution = getColSolution();
119 const double * colLower = getColLower();
120 const double * colUpper = getColUpper();
121 const int numCols = getNumCols();
122
123 strictColSolution_.clear();
124 strictColSolution_.insert(strictColSolution_.end(),colSolution, colSolution+numCols);
125
126 for (int i=numCols-1; i> 0; --i){
127 if (colSolution[i] <= colUpper[i]){
128 if (colSolution[i] >= colLower[i]){
129 continue;
130 } else {
131 strictColSolution_[i] = colLower[i];
132 }
133 } else {
134 strictColSolution_[i] = colUpper[i];
135 }
136 }
137 return &strictColSolution_[0];
138}
139
140
141//-----------------------------------------------------------------------------
142bool
143OsiSolverInterface::isInteger(int colIndex) const
144{
145 return !isContinuous(colIndex);
146}
147//-----------------------------------------------------------------------------
148/*
149 Return number of integer variables. OSI implementors really should replace
150 this one, it's generally trivial from within the OSI, but this is the only
151 safe way to do it generically.
152*/
153int
154OsiSolverInterface::getNumIntegers () const
155{
156 if (numberIntegers_>=0) {
157 // we already know
158 return numberIntegers_;
159 } else {
160 // work out
161 const int numCols = getNumCols() ;
162 int numIntegers = 0 ;
163 for (int i = 0 ; i < numCols ; ++i) {
164 if (!isContinuous(i)) {
165 numIntegers++ ;
166 }
167 }
168 return (numIntegers) ;
169 }
170}
171//-----------------------------------------------------------------------------
172bool
173OsiSolverInterface::isIntegerNonBinary(int colIndex) const
174{
175 if ( isInteger(colIndex) && !isBinary(colIndex) )
176 return true;
177 else return false;
178}
179//-----------------------------------------------------------------------------
180bool
181OsiSolverInterface::isFreeBinary(int colIndex) const
182{
183 if ( isContinuous(colIndex) ) return false;
184 const double * cu = getColUpper();
185 const double * cl = getColLower();
186 if (
187 (cu[colIndex]== 1) &&
188 (cl[colIndex]== 0)
189 ) return true;
190 else return false;
191}
192/* Return array of column length
193 0 - continuous
194 1 - binary (may get fixed later)
195 2 - general integer (may get fixed later)
196*/
197const char *
198OsiSolverInterface::getColType(bool refresh) const
199{
200 if (!columnType_||refresh) {
201 const int numCols = getNumCols() ;
202 if (!columnType_)
203 columnType_ = new char [numCols];
204 const double * cu = getColUpper();
205 const double * cl = getColLower();
206 for (int i = 0 ; i < numCols ; ++i) {
207 if (!isContinuous(i)) {
208 if ((cu[i]== 1 || cu[i]== 0) &&
209 (cl[i]== 0 || cl[i]==1))
210 columnType_[i]=1;
211 else
212 columnType_[i]=2;
213 } else {
214 columnType_[i]=0;
215 }
216 }
217 }
218 return columnType_;
219}
220
221/*
222###############################################################################
223
224 Built-in methods for problem modification
225
226 Some of these can surely be reimplemented more efficiently given knowledge of
227 the derived OsiXXX data structures, but we can't make assumptions here. For
228 others, it's less clear. Given standard vector data structures in the
229 underlying OsiXXX, likely the only possible gain is avoiding a method call.
230
231###############################################################################
232*/
233
234void
235OsiSolverInterface::setObjCoeffSet(const int* indexFirst,
236 const int* indexLast,
237 const double* coeffList)
238{
239 const std::ptrdiff_t cnt = indexLast - indexFirst;
240 for (std::ptrdiff_t i = 0; i < cnt; ++i) {
241 setObjCoeff(indexFirst[i], coeffList[i]);
242 }
243}
244//-----------------------------------------------------------------------------
245void
246OsiSolverInterface::setColSetBounds(const int* indexFirst,
247 const int* indexLast,
248 const double* boundList)
249{
250 while (indexFirst != indexLast) {
251 setColBounds(*indexFirst, boundList[0], boundList[1]);
252 ++indexFirst;
253 boundList += 2;
254 }
255}
256//-----------------------------------------------------------------------------
257void
258OsiSolverInterface::setRowSetBounds(const int* indexFirst,
259 const int* indexLast,
260 const double* boundList)
261{
262 while (indexFirst != indexLast) {
263 setRowBounds(*indexFirst, boundList[0], boundList[1]);
264 ++indexFirst;
265 boundList += 2;
266 }
267}
268//-----------------------------------------------------------------------------
269void
270OsiSolverInterface::setRowSetTypes(const int* indexFirst,
271 const int* indexLast,
272 const char* senseList,
273 const double* rhsList,
274 const double* rangeList)
275{
276 while (indexFirst != indexLast) {
277 setRowType(*indexFirst++, *senseList++, *rhsList++, *rangeList++);
278 }
279}
280//-----------------------------------------------------------------------------
281void
282OsiSolverInterface::setContinuous(const int* indices, int len)
283{
284 for (int i = 0; i < len; ++i) {
285 setContinuous(indices[i]);
286 }
287}
288//-----------------------------------------------------------------------------
289void
290OsiSolverInterface::setInteger(const int* indices, int len)
291{
292 for (int i = 0; i < len; ++i) {
293 setInteger(indices[i]);
294 }
295}
296//-----------------------------------------------------------------------------
297/* Set the objective coefficients for all columns
298 array [getNumCols()] is an array of values for the objective.
299 This defaults to a series of set operations and is here for speed.
300*/
301void OsiSolverInterface::setObjective(const double * array)
302{
303 int n=getNumCols();
304 for (int i=0;i<n;i++)
305 setObjCoeff(i,array[i]);
306}
307//-----------------------------------------------------------------------------
308/* Set the lower bounds for all columns
309 array [getNumCols()] is an array of values for the objective.
310 This defaults to a series of set operations and is here for speed.
311*/
312void OsiSolverInterface::setColLower(const double * array)
313{
314 int n=getNumCols();
315 for (int i=0;i<n;i++)
316 setColLower(i,array[i]);
317}
318//-----------------------------------------------------------------------------
319/* Set the upper bounds for all columns
320 array [getNumCols()] is an array of values for the objective.
321 This defaults to a series of set operations and is here for speed.
322*/
323void OsiSolverInterface::setColUpper(const double * array)
324{
325 int n=getNumCols();
326 for (int i=0;i<n;i++)
327 setColUpper(i,array[i]);
328}
329//-----------------------------------------------------------------------------
330/*
331 Add a named column. Less than efficient, because the underlying solver almost
332 surely generates an internal name when creating the column, which is then
333 replaced.
334*/
335void OsiSolverInterface::addCol(const CoinPackedVectorBase& vec,
336 const double collb, const double colub,
337 const double obj, std::string name)
338{
339 int ndx = getNumCols() ;
340 addCol(vec,collb,colub,obj) ;
341 setColName(ndx,name) ;
342}
343
344void OsiSolverInterface::addCol(int numberElements,
345 const int* rows, const double* elements,
346 const double collb, const double colub,
347 const double obj, std::string name)
348{
349 int ndx = getNumCols() ;
350 addCol(numberElements,rows,elements,collb,colub,obj) ;
351 setColName(ndx,name) ;
352}
353
354/* Convenience alias for addCol */
355void
356OsiSolverInterface::addCol(int numberElements,
357 const int* rows, const double* elements,
358 const double collb, const double colub,
359 const double obj)
360{
361 CoinPackedVector column(numberElements, rows, elements);
362 addCol(column,collb,colub,obj);
363}
364//-----------------------------------------------------------------------------
365/* Add a set of columns (primal variables) to the problem.
366
367 Default implementation simply makes repeated calls to addCol().
368*/
369void
370OsiSolverInterface::addCols(const int numcols,
371 const CoinPackedVectorBase* const* cols,
372 const double* collb, const double* colub,
373 const double* obj)
374{
375 for (int i = 0; i < numcols; ++i) {
376 addCol(*cols[i], collb[i], colub[i], obj[i]);
377 }
378}
379
380void OsiSolverInterface::addCols(const int numcols, const int* columnStarts,
381 const int* rows, const double* elements,
382 const double* collb, const double* colub,
383 const double* obj)
384{
385 double infinity = getInfinity();
386 for (int i = 0; i < numcols; ++i) {
387 int start = columnStarts[i];
388 int number = columnStarts[i+1]-start;
389 assert (number>=0);
390 addCol(number, rows+start, elements+start, collb ? collb[i] : 0.0,
391 colub ? colub[i] : infinity,
392 obj ? obj[i] : 0.0);
393 }
394}
395//-----------------------------------------------------------------------------
396// Add columns from a build object
397void
398OsiSolverInterface::addCols(const CoinBuild & buildObject)
399{
400 assert (buildObject.type()==1); // check correct
401 int number = buildObject.numberColumns();
402 if (number) {
403 CoinPackedVectorBase ** columns=
404 new CoinPackedVectorBase * [number];
405 int iColumn;
406 double * objective = new double [number];
407 double * lower = new double [number];
408 double * upper = new double [number];
409 for (iColumn=0;iColumn<number;iColumn++) {
410 const int * rows;
411 const double * elements;
412 int numberElements = buildObject.column(iColumn,lower[iColumn],
413 upper[iColumn],objective[iColumn],
414 rows,elements);
415 columns[iColumn] =
416 new CoinPackedVector(numberElements,
417 rows,elements);
418 }
419 addCols(number, columns, lower, upper,objective);
420 for (iColumn=0;iColumn<number;iColumn++)
421 delete columns[iColumn];
422 delete [] columns;
423 delete [] objective;
424 delete [] lower;
425 delete [] upper;
426 }
427 return;
428}
429// Add columns from a model object
430int
431OsiSolverInterface::addCols( CoinModel & modelObject)
432{
433 bool goodState=true;
434 if (modelObject.rowLowerArray()) {
435 // some row information exists
436 int numberRows2 = modelObject.numberRows();
437 const double * rowLower = modelObject.rowLowerArray();
438 const double * rowUpper = modelObject.rowUpperArray();
439 for (int i=0;i<numberRows2;i++) {
440 if (rowLower[i]!=-COIN_DBL_MAX)
441 goodState=false;
442 if (rowUpper[i]!=COIN_DBL_MAX)
443 goodState=false;
444 }
445 }
446 if (goodState) {
447 // can do addColumns
448 int numberErrors = 0;
449 // Set arrays for normal use
450 double * rowLower = modelObject.rowLowerArray();
451 double * rowUpper = modelObject.rowUpperArray();
452 double * columnLower = modelObject.columnLowerArray();
453 double * columnUpper = modelObject.columnUpperArray();
454 double * objective = modelObject.objectiveArray();
455 int * integerType = modelObject.integerTypeArray();
456 double * associated = modelObject.associatedArray();
457 // If strings then do copies
458 if (modelObject.stringsExist()) {
459 numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper,
460 objective, integerType,associated);
461 }
462 CoinPackedMatrix matrix;
463 modelObject.createPackedMatrix(matrix,associated);
464 int numberColumns = getNumCols(); // save number of columns
465 int numberColumns2 = modelObject.numberColumns();
466 if (numberColumns2&&!numberErrors) {
467 // Clean up infinity
468 double infinity = getInfinity();
469 int iColumn;
470 for (iColumn=0;iColumn<numberColumns2;iColumn++) {
471 if (columnUpper[iColumn]>1.0e30)
472 columnUpper[iColumn]=infinity;
473 if (columnLower[iColumn]<-1.0e30)
474 columnLower[iColumn]=-infinity;
475 }
476 const int * row = matrix.getIndices();
477 const int * columnLength = matrix.getVectorLengths();
478 const CoinBigIndex * columnStart = matrix.getVectorStarts();
479 const double * element = matrix.getElements();
480 CoinPackedVectorBase ** columns=
481 new CoinPackedVectorBase * [numberColumns2];
482 assert (columnLower);
483 for (iColumn=0;iColumn<numberColumns2;iColumn++) {
484 int start = columnStart[iColumn];
485 columns[iColumn] =
486 new CoinPackedVector(columnLength[iColumn],
487 row+start,element+start);
488 }
489 addCols(numberColumns2, columns, columnLower, columnUpper,objective);
490 for (iColumn=0;iColumn<numberColumns2;iColumn++)
491 delete columns[iColumn];
492 delete [] columns;
493 // Do integers if wanted
494 assert(integerType);
495 for (iColumn=0;iColumn<numberColumns2;iColumn++) {
496 if (integerType[iColumn])
497 setInteger(iColumn+numberColumns);
498 }
499 }
500 if (columnLower!=modelObject.columnLowerArray()) {
501 delete [] rowLower;
502 delete [] rowUpper;
503 delete [] columnLower;
504 delete [] columnUpper;
505 delete [] objective;
506 delete [] integerType;
507 delete [] associated;
508 //if (numberErrors)
509 //handler_->message(CLP_BAD_STRING_VALUES,messages_)
510 // <<numberErrors
511 // <<CoinMessageEol;
512 }
513 return numberErrors;
514 } else {
515 // not suitable for addColumns
516 //handler_->message(CLP_COMPLICATED_MODEL,messages_)
517 //<<modelObject.numberRows()
518 //<<modelObject.numberColumns()
519 //<<CoinMessageEol;
520 return -1;
521 }
522}
523//-----------------------------------------------------------------------------
524/*
525 Add a named row. Less than efficient, because the underlying solver almost
526 surely generates an internal name when creating the row, which is then
527 replaced.
528*/
529void OsiSolverInterface::addRow(const CoinPackedVectorBase& vec,
530 const double rowlb, const double rowub,
531 std::string name)
532{
533 int ndx = getNumRows() ;
534 addRow(vec,rowlb,rowub) ;
535 setRowName(ndx,name) ;
536}
537
538void OsiSolverInterface::addRow(const CoinPackedVectorBase& vec,
539 const char rowsen, const double rowrhs,
540 const double rowrng, std::string name)
541{
542 int ndx = getNumRows() ;
543 addRow(vec,rowsen,rowrhs,rowrng) ;
544 setRowName(ndx,name) ;
545}
546
547/* Convenience alias for addRow. */
548void
549OsiSolverInterface::addRow(int numberElements,
550 const int *columns, const double *elements,
551 const double rowlb, const double rowub)
552{
553 CoinPackedVector row(numberElements,columns,elements);
554 addRow(row,rowlb,rowub);
555}
556//-----------------------------------------------------------------------------
557/* Add a set of rows (constraints) to the problem.
558
559 The default implementation simply makes repeated calls to addRow().
560*/
561void
562OsiSolverInterface::addRows(const int numrows, const int* rowStarts,
563 const int* columns, const double* elements,
564 const double* rowlb, const double* rowub)
565{
566 double infinity = getInfinity();
567 for (int i = 0; i < numrows; ++i) {
568 int start = rowStarts[i];
569 int number = rowStarts[i+1]-start;
570 assert (number>=0);
571 addRow(number, columns+start, elements+start, rowlb ? rowlb[i] : -infinity,
572 rowub ? rowub[i] : infinity);
573 }
574}
575
576void
577OsiSolverInterface::addRows(const int numrows,
578 const CoinPackedVectorBase* const* rows,
579 const double* rowlb, const double* rowub)
580{
581 for (int i = 0; i < numrows; ++i) {
582 addRow(*rows[i], rowlb[i], rowub[i]);
583 }
584}
585
586void
587OsiSolverInterface::addRows(const int numrows,
588 const CoinPackedVectorBase* const* rows,
589 const char* rowsen, const double* rowrhs,
590 const double* rowrng)
591{
592 for (int i = 0; i < numrows; ++i) {
593 addRow(*rows[i], rowsen[i], rowrhs[i], rowrng[i]);
594 }
595}
596//-----------------------------------------------------------------------------
597void
598OsiSolverInterface::addRows(const CoinBuild & buildObject)
599{
600 int number = buildObject.numberRows();
601 if (number) {
602 CoinPackedVectorBase ** rows=
603 new CoinPackedVectorBase * [number];
604 int iRow;
605 double * lower = new double [number];
606 double * upper = new double [number];
607 for (iRow=0;iRow<number;iRow++) {
608 const int * columns;
609 const double * elements;
610 int numberElements = buildObject.row(iRow,lower[iRow],upper[iRow],
611 columns,elements);
612 rows[iRow] =
613 new CoinPackedVector(numberElements,
614 columns,elements);
615 }
616 addRows(number, rows, lower, upper);
617 for (iRow=0;iRow<number;iRow++)
618 delete rows[iRow];
619 delete [] rows;
620 delete [] lower;
621 delete [] upper;
622 }
623}
624//-----------------------------------------------------------------------------
625int
626OsiSolverInterface::addRows( CoinModel & modelObject)
627{
628 bool goodState=true;
629 if (modelObject.columnLowerArray()) {
630 // some column information exists
631 int numberColumns2 = modelObject.numberColumns();
632 const double * columnLower = modelObject.columnLowerArray();
633 const double * columnUpper = modelObject.columnUpperArray();
634 const double * objective = modelObject.objectiveArray();
635 const int * integerType = modelObject.integerTypeArray();
636 for (int i=0;i<numberColumns2;i++) {
637 if (columnLower[i]!=0.0)
638 goodState=false;
639 if (columnUpper[i]!=COIN_DBL_MAX)
640 goodState=false;
641 if (objective[i]!=0.0)
642 goodState=false;
643 if (integerType[i]!=0)
644 goodState=false;
645 }
646 }
647 if (goodState) {
648 // can do addRows
649 int numberErrors = 0;
650 // Set arrays for normal use
651 double * rowLower = modelObject.rowLowerArray();
652 double * rowUpper = modelObject.rowUpperArray();
653 double * columnLower = modelObject.columnLowerArray();
654 double * columnUpper = modelObject.columnUpperArray();
655 double * objective = modelObject.objectiveArray();
656 int * integerType = modelObject.integerTypeArray();
657 double * associated = modelObject.associatedArray();
658 // If strings then do copies
659 if (modelObject.stringsExist()) {
660 numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper,
661 objective, integerType,associated);
662 }
663 CoinPackedMatrix matrix;
664 modelObject.createPackedMatrix(matrix,associated);
665 int numberRows2 = modelObject.numberRows();
666 if (numberRows2&&!numberErrors) {
667 // Clean up infinity
668 double infinity = getInfinity();
669 int iRow;
670 for (iRow=0;iRow<numberRows2;iRow++) {
671 if (rowUpper[iRow]>1.0e30)
672 rowUpper[iRow]=infinity;
673 if (rowLower[iRow]<-1.0e30)
674 rowLower[iRow]=-infinity;
675 }
676 // matrix by rows
677 matrix.reverseOrdering();
678 const int * column = matrix.getIndices();
679 const int * rowLength = matrix.getVectorLengths();
680 const CoinBigIndex * rowStart = matrix.getVectorStarts();
681 const double * element = matrix.getElements();
682 CoinPackedVectorBase ** rows=
683 new CoinPackedVectorBase * [numberRows2];
684 assert (rowLower);
685 for (iRow=0;iRow<numberRows2;iRow++) {
686 int start = rowStart[iRow];
687 rows[iRow] =
688 new CoinPackedVector(rowLength[iRow],
689 column+start,element+start);
690 }
691 addRows(numberRows2, rows, rowLower, rowUpper);
692 for (iRow=0;iRow<numberRows2;iRow++)
693 delete rows[iRow];
694 delete [] rows;
695 }
696 if (rowLower!=modelObject.rowLowerArray()) {
697 delete [] rowLower;
698 delete [] rowUpper;
699 delete [] columnLower;
700 delete [] columnUpper;
701 delete [] objective;
702 delete [] integerType;
703 delete [] associated;
704 //if (numberErrors)
705 //handler_->message(CLP_BAD_STRING_VALUES,messages_)
706 // <<numberErrors
707 // <<CoinMessageEol;
708 }
709 return numberErrors;
710 } else {
711 // not suitable for addRows
712 //handler_->message(CLP_COMPLICATED_MODEL,messages_)
713 //<<modelObject.numberRows()
714 //<<modelObject.numberColumns()
715 //<<CoinMessageEol;
716 return -1;
717 }
718}
719/* Strip off rows to get to this number of rows.
720 If solver wants it can restore a copy of "base" (continuous) model here
721*/
722void
723OsiSolverInterface::restoreBaseModel(int numberRows)
724{
725 int currentNumberCuts = getNumRows()-numberRows;
726 int *which = new int[currentNumberCuts];
727 for (int i = 0 ; i < currentNumberCuts ; i++)
728 which[i] = i+numberRows;
729 deleteRows(currentNumberCuts,which);
730 delete [] which;
731}
732
733// This loads a model from a coinModel object - returns number of errors
734int
735OsiSolverInterface::loadFromCoinModel ( CoinModel & modelObject, bool keepSolution)
736{
737 int numberErrors = 0;
738 // Set arrays for normal use
739 double * rowLower = modelObject.rowLowerArray();
740 double * rowUpper = modelObject.rowUpperArray();
741 double * columnLower = modelObject.columnLowerArray();
742 double * columnUpper = modelObject.columnUpperArray();
743 double * objective = modelObject.objectiveArray();
744 int * integerType = modelObject.integerTypeArray();
745 double * associated = modelObject.associatedArray();
746 // If strings then do copies
747 if (modelObject.stringsExist()) {
748 numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper,
749 objective, integerType,associated);
750 }
751 CoinPackedMatrix matrix;
752 modelObject.createPackedMatrix(matrix,associated);
753 int numberRows = modelObject.numberRows();
754 int numberColumns = modelObject.numberColumns();
755 // Clean up infinity
756 double infinity = getInfinity();
757 int iColumn,iRow;
758 for (iColumn=0;iColumn<numberColumns;iColumn++) {
759 if (columnUpper[iColumn]>1.0e30)
760 columnUpper[iColumn]=infinity;
761 if (columnLower[iColumn]<-1.0e30)
762 columnLower[iColumn]=-infinity;
763 }
764 for (iRow=0;iRow<numberRows;iRow++) {
765 if (rowUpper[iRow]>1.0e30)
766 rowUpper[iRow]=infinity;
767 if (rowLower[iRow]<-1.0e30)
768 rowLower[iRow]=-infinity;
769 }
770 CoinWarmStart * ws = getWarmStart();
771 bool restoreBasis = keepSolution && numberRows&&numberRows==getNumRows()&&
772 numberColumns==getNumCols();
773 loadProblem(matrix,
774 columnLower, columnUpper, objective, rowLower, rowUpper);
775 setRowColNames(modelObject) ;
776 if (restoreBasis)
777 setWarmStart(ws);
778 delete ws;
779 // Do integers if wanted
780 assert(integerType);
781 for (int iColumn=0;iColumn<numberColumns;iColumn++) {
782 if (integerType[iColumn])
783 setInteger(iColumn);
784 }
785 if (rowLower!=modelObject.rowLowerArray()||
786 columnLower!=modelObject.columnLowerArray()) {
787 delete [] rowLower;
788 delete [] rowUpper;
789 delete [] columnLower;
790 delete [] columnUpper;
791 delete [] objective;
792 delete [] integerType;
793 delete [] associated;
794 //if (numberErrors)
795 // handler_->message(CLP_BAD_STRING_VALUES,messages_)
796 // <<numberErrors
797 // <<CoinMessageEol;
798 }
799 return numberErrors;
800}
801//-----------------------------------------------------------------------------
802
803//#############################################################################
804// Implement getObjValue in a simple way that the derived solver interfaces
805// can use if the choose.
806//#############################################################################
807double OsiSolverInterface::getObjValue() const
808{
809 int nc = getNumCols();
810 const double * objCoef = getObjCoefficients();
811 const double * colSol = getColSolution();
812 double objOffset=0.0;
813 getDblParam(OsiObjOffset,objOffset);
814
815 // Compute dot product of objCoef and colSol and then adjust by offset
816 // Jean-Sebastien pointed out this is overkill - lets just do it simply
817 //double retVal = CoinPackedVector(nc,objCoef).dotProduct(colSol)-objOffset;
818 double retVal = -objOffset;
819 for ( int i=0 ; i<nc ; i++ )
820 retVal += objCoef[i]*colSol[i];
821 return retVal;
822}
823
824//#############################################################################
825// Apply Cuts
826//#############################################################################
827
828OsiSolverInterface::ApplyCutsReturnCode
829OsiSolverInterface::applyCuts( const OsiCuts & cs, double effectivenessLb )
830{
831 OsiSolverInterface::ApplyCutsReturnCode retVal;
832 int i;
833
834 // Loop once for each column cut
835 for ( i=0; i<cs.sizeColCuts(); i ++ ) {
836 if ( cs.colCut(i).effectiveness() < effectivenessLb ) {
837 retVal.incrementIneffective();
838 continue;
839 }
840 if ( !cs.colCut(i).consistent() ) {
841 retVal.incrementInternallyInconsistent();
842 continue;
843 }
844 if ( !cs.colCut(i).consistent(*this) ) {
845 retVal.incrementExternallyInconsistent();
846 continue;
847 }
848 if ( cs.colCut(i).infeasible(*this) ) {
849 retVal.incrementInfeasible();
850 continue;
851 }
852 applyColCut( cs.colCut(i) );
853 retVal.incrementApplied();
854 }
855
856 // Loop once for each row cut
857 for ( i=0; i<cs.sizeRowCuts(); i ++ ) {
858 if ( cs.rowCut(i).effectiveness() < effectivenessLb ) {
859 retVal.incrementIneffective();
860 continue;
861 }
862 if ( !cs.rowCut(i).consistent() ) {
863 retVal.incrementInternallyInconsistent();
864 continue;
865 }
866 if ( !cs.rowCut(i).consistent(*this) ) {
867 retVal.incrementExternallyInconsistent();
868 continue;
869 }
870 if ( cs.rowCut(i).infeasible(*this) ) {
871 retVal.incrementInfeasible();
872 continue;
873 }
874 applyRowCut( cs.rowCut(i) );
875 retVal.incrementApplied();
876 }
877
878 return retVal;
879}
880/* Apply a collection of row cuts which are all effective.
881 applyCuts seems to do one at a time which seems inefficient.
882 The default does slowly, but solvers can override.
883*/
884void
885OsiSolverInterface::applyRowCuts(int numberCuts, const OsiRowCut * cuts)
886{
887 int i;
888 for (i=0;i<numberCuts;i++) {
889 applyRowCut(cuts[i]);
890 }
891}
892// And alternatively
893void
894OsiSolverInterface::applyRowCuts(int numberCuts, const OsiRowCut ** cuts)
895{
896 int i;
897 for (i=0;i<numberCuts;i++) {
898 applyRowCut(*cuts[i]);
899 }
900}
901//#############################################################################
902// Set/Get Application Data
903// This is a pointer that the application can store into and retrieve
904// from the solverInterface.
905// This field is the application to optionally define and use.
906//#############################################################################
907
908void OsiSolverInterface::setApplicationData(void * appData)
909{
910 delete appDataEtc_;
911 appDataEtc_ = new OsiAuxInfo(appData);
912}
913//-----------------------------------------------------------------------------
914void * OsiSolverInterface::getApplicationData() const
915{
916 return appDataEtc_->getApplicationData();
917}
918void
919OsiSolverInterface::setAuxiliaryInfo(OsiAuxInfo * auxiliaryInfo)
920{
921 delete appDataEtc_;
922 appDataEtc_ = auxiliaryInfo->clone();
923}
924// Get pointer to auxiliary info object
925OsiAuxInfo *
926OsiSolverInterface::getAuxiliaryInfo() const
927{
928 return appDataEtc_;
929}
930
931//#############################################################################
932// Methods related to Row Cut Debuggers
933//#############################################################################
934
935//-------------------------------------------------------------------
936// Activate Row Cut Debugger<br>
937// If the model name passed is on list of known models
938// then all cuts are checked to see that they do NOT cut
939// off the known optimal solution.
940
941void OsiSolverInterface::activateRowCutDebugger (const char * modelName)
942{
943 delete rowCutDebugger_;
944 rowCutDebugger_=NULL; // so won't use in new
945 rowCutDebugger_ = new OsiRowCutDebugger(*this,modelName);
946}
947/* Activate debugger using full solution array.
948 Only integer values need to be correct.
949 Up to user to get it correct.
950*/
951void OsiSolverInterface::activateRowCutDebugger (const double * solution,
952 bool keepContinuous)
953{
954 delete rowCutDebugger_;
955 rowCutDebugger_=NULL; // so won't use in new
956 rowCutDebugger_ = new OsiRowCutDebugger(*this,solution,keepContinuous);
957}
958//-------------------------------------------------------------------
959// Get Row Cut Debugger<br>
960// If there is a row cut debugger object associated with
961// model AND if the known optimal solution is within the
962// current feasible region then a pointer to the object is
963// returned which may be used to test validity of cuts.
964// Otherwise NULL is returned
965
966const OsiRowCutDebugger * OsiSolverInterface::getRowCutDebugger() const
967{
968 if (rowCutDebugger_&&rowCutDebugger_->onOptimalPath(*this)) {
969 return rowCutDebugger_;
970 } else {
971 return NULL;
972 }
973}
974// If you want to get debugger object even if not on optimal path then use this
975OsiRowCutDebugger * OsiSolverInterface::getRowCutDebuggerAlways() const
976{
977 if (rowCutDebugger_&&rowCutDebugger_->active()) {
978 return rowCutDebugger_;
979 } else {
980 return NULL;
981 }
982}
983
984//#############################################################################
985// Constructors / Destructor / Assignment
986//#############################################################################
987
988//-------------------------------------------------------------------
989// Default Constructor
990//-------------------------------------------------------------------
991OsiSolverInterface::OsiSolverInterface () :
992 rowCutDebugger_(NULL),
993 handler_(NULL),
994 defaultHandler_(true),
995 columnType_(NULL),
996 appDataEtc_(NULL),
997 ws_(NULL)
998{
999 setInitialData();
1000}
1001// Set data for default constructor
1002void
1003OsiSolverInterface::setInitialData()
1004{
1005 delete rowCutDebugger_;
1006 rowCutDebugger_ = NULL;
1007 delete ws_;
1008 ws_ = NULL;
1009 delete appDataEtc_;
1010 appDataEtc_ = new OsiAuxInfo();
1011 if (defaultHandler_) {
1012 delete handler_;
1013 handler_ = NULL;
1014 }
1015 defaultHandler_=true;
1016 delete [] columnType_;
1017 columnType_ = NULL;
1018 intParam_[OsiMaxNumIteration] = 9999999;
1019 intParam_[OsiMaxNumIterationHotStart] = 9999999;
1020 intParam_[OsiNameDiscipline] = 0;
1021
1022 // Dual objective limit is acceptable `badness'; for minimisation, COIN_DBL_MAX
1023 dblParam_[OsiDualObjectiveLimit] = COIN_DBL_MAX;
1024 // Primal objective limit is desired `goodness'; for minimisation, -COIN_DBL_MAX
1025 dblParam_[OsiPrimalObjectiveLimit] = -COIN_DBL_MAX;
1026 dblParam_[OsiDualTolerance] = 1e-6;
1027 dblParam_[OsiPrimalTolerance] = 1e-6;
1028 dblParam_[OsiObjOffset] = 0.0;
1029
1030 strParam_[OsiProbName] = "OsiDefaultName";
1031 strParam_[OsiSolverName] = "Unknown Solver";
1032 handler_ = new CoinMessageHandler();
1033 messages_ = CoinMessage();
1034
1035 // initialize all hints
1036 int hint;
1037 for (hint=OsiDoPresolveInInitial;hint<OsiLastHintParam;hint++) {
1038 hintParam_[hint] = false;
1039 hintStrength_[hint] = OsiHintIgnore;
1040 }
1041 // objects
1042 numberObjects_=0;
1043 numberIntegers_=-1;
1044 object_=NULL;
1045
1046 // names
1047 rowNames_ = OsiNameVec(0) ;
1048 colNames_ = OsiNameVec(0) ;
1049 objName_ = "" ;
1050}
1051
1052//-------------------------------------------------------------------
1053// Copy constructor
1054//-------------------------------------------------------------------
1055OsiSolverInterface::OsiSolverInterface (const OsiSolverInterface & rhs) :
1056 rowCutDebugger_(NULL),
1057 ws_(NULL)
1058{
1059 appDataEtc_ = rhs.appDataEtc_->clone();
1060 if ( rhs.rowCutDebugger_!=NULL )
1061 rowCutDebugger_ = new OsiRowCutDebugger(*rhs.rowCutDebugger_);
1062 defaultHandler_ = rhs.defaultHandler_;
1063 if (defaultHandler_) {
1064 handler_ = new CoinMessageHandler(*rhs.handler_);
1065 } else {
1066 handler_ = rhs.handler_;
1067 }
1068 messages_ = CoinMessages(rhs.messages_);
1069 CoinDisjointCopyN(rhs.intParam_, OsiLastIntParam, intParam_);
1070 CoinDisjointCopyN(rhs.dblParam_, OsiLastDblParam, dblParam_);
1071 CoinDisjointCopyN(rhs.strParam_, OsiLastStrParam, strParam_);
1072 CoinDisjointCopyN(rhs.hintParam_, OsiLastHintParam, hintParam_);
1073 CoinDisjointCopyN(rhs.hintStrength_, OsiLastHintParam, hintStrength_);
1074 // objects
1075 numberObjects_=rhs.numberObjects_;
1076 numberIntegers_=rhs.numberIntegers_;
1077 if (numberObjects_) {
1078 object_ = new OsiObject * [numberObjects_];
1079 for (int i=0;i<numberObjects_;i++)
1080 object_[i] = rhs.object_[i]->clone();
1081 } else {
1082 object_=NULL;
1083 }
1084 // names
1085 rowNames_ = rhs.rowNames_ ;
1086 colNames_ = rhs.colNames_ ;
1087 objName_ = rhs.objName_ ;
1088 // NULL as number of columns not known
1089 columnType_ = NULL;
1090}
1091
1092//-------------------------------------------------------------------
1093// Destructor
1094//-------------------------------------------------------------------
1095OsiSolverInterface::~OsiSolverInterface ()
1096{
1097 // delete debugger - should be safe as only ever returned const
1098 delete rowCutDebugger_;
1099 rowCutDebugger_ = NULL;
1100 delete ws_;
1101 ws_ = NULL;
1102 delete appDataEtc_;
1103 if (defaultHandler_) {
1104 delete handler_;
1105 handler_ = NULL;
1106 }
1107 for (int i=0;i<numberObjects_;i++)
1108 delete object_[i];
1109 delete [] object_;
1110 delete [] columnType_;
1111}
1112
1113//----------------------------------------------------------------
1114// Assignment operator
1115//-------------------------------------------------------------------
1116OsiSolverInterface &
1117OsiSolverInterface::operator=(const OsiSolverInterface& rhs)
1118{
1119 if (this != &rhs) {
1120 delete appDataEtc_;
1121 appDataEtc_ = rhs.appDataEtc_->clone();
1122 delete rowCutDebugger_;
1123 if ( rhs.rowCutDebugger_!=NULL )
1124 rowCutDebugger_ = new OsiRowCutDebugger(*rhs.rowCutDebugger_);
1125 else
1126 rowCutDebugger_ = NULL;
1127 CoinDisjointCopyN(rhs.intParam_, OsiLastIntParam, intParam_);
1128 CoinDisjointCopyN(rhs.dblParam_, OsiLastDblParam, dblParam_);
1129 CoinDisjointCopyN(rhs.strParam_, OsiLastStrParam, strParam_);
1130 CoinDisjointCopyN(rhs.hintParam_, OsiLastHintParam, hintParam_);
1131 CoinDisjointCopyN(rhs.hintStrength_, OsiLastHintParam, hintStrength_);
1132 delete ws_;
1133 ws_ = NULL;
1134 if (defaultHandler_) {
1135 delete handler_;
1136 handler_ = NULL;
1137 }
1138 defaultHandler_ = rhs.defaultHandler_;
1139 if (defaultHandler_) {
1140 handler_ = new CoinMessageHandler(*rhs.handler_);
1141 } else {
1142 handler_ = rhs.handler_;
1143 }
1144 // objects
1145 int i;
1146 for (i=0;i<numberObjects_;i++)
1147 delete object_[i];
1148 delete [] object_;
1149 numberObjects_=rhs.numberObjects_;
1150 numberIntegers_=rhs.numberIntegers_;
1151 if (numberObjects_) {
1152 object_ = new OsiObject * [numberObjects_];
1153 for (i=0;i<numberObjects_;i++)
1154 object_[i] = rhs.object_[i]->clone();
1155 } else {
1156 object_=NULL;
1157 }
1158 // names
1159 rowNames_ = rhs.rowNames_ ;
1160 colNames_ = rhs.colNames_ ;
1161 objName_ = rhs.objName_ ;
1162 delete [] columnType_;
1163 // NULL as number of columns not known
1164 columnType_ = NULL;
1165 }
1166 return *this;
1167}
1168
1169//-----------------------------------------------------------------------------
1170// Read mps files
1171//-----------------------------------------------------------------------------
1172
1173int OsiSolverInterface::readMps(const char * filename,
1174 const char * extension)
1175{
1176 CoinMpsIO m;
1177
1178 int logLvl = handler_->logLevel() ;
1179 if (logLvl > 1)
1180 { m.messageHandler()->setLogLevel(handler_->logLevel()) ; }
1181 else
1182 { m.messageHandler()->setLogLevel(0) ; }
1183 m.setInfinity(getInfinity());
1184
1185 int numberErrors = m.readMps(filename,extension);
1186 handler_->message(COIN_SOLVER_MPS,messages_)
1187 <<m.getProblemName()<< numberErrors <<CoinMessageEol;
1188 if (!numberErrors) {
1189
1190 // set objective function offest
1191 setDblParam(OsiObjOffset,m.objectiveOffset());
1192
1193 // set problem name
1194 setStrParam(OsiProbName,m.getProblemName());
1195
1196 // no errors --- load problem, set names and integrality
1197 loadProblem(*m.getMatrixByCol(),m.getColLower(),m.getColUpper(),
1198 m.getObjCoefficients(),m.getRowSense(),m.getRightHandSide(),
1199 m.getRowRange());
1200 setRowColNames(m) ;
1201 const char * integer = m.integerColumns();
1202 if (integer) {
1203 int i,n=0;
1204 int nCols=m.getNumCols();
1205 int * index = new int [nCols];
1206 for (i=0;i<nCols;i++) {
1207 if (integer[i]) {
1208 index[n++]=i;
1209 }
1210 }
1211 setInteger(index,n);
1212 delete [] index;
1213 }
1214 }
1215 return numberErrors;
1216}
1217/* Read a problem in GMPL format from the given filenames.
1218
1219 Will only work if glpk installed
1220*/
1221int
1222OsiSolverInterface::readGMPL(const char *filename, const char * dataname)
1223{
1224 CoinMpsIO m;
1225 m.setInfinity(getInfinity());
1226 m.passInMessageHandler(handler_);
1227
1228 int numberErrors = m.readGMPL(filename,dataname,false);
1229 handler_->message(COIN_SOLVER_MPS,messages_)
1230 <<m.getProblemName()<< numberErrors <<CoinMessageEol;
1231 if (!numberErrors) {
1232
1233 // set objective function offest
1234 setDblParam(OsiObjOffset,m.objectiveOffset());
1235
1236 // set problem name
1237 setStrParam(OsiProbName,m.getProblemName());
1238
1239 // no errors --- load problem, set names and integrality
1240 loadProblem(*m.getMatrixByCol(),m.getColLower(),m.getColUpper(),
1241 m.getObjCoefficients(),m.getRowSense(),m.getRightHandSide(),
1242 m.getRowRange());
1243 setRowColNames(m) ;
1244 const char * integer = m.integerColumns();
1245 if (integer) {
1246 int i,n=0;
1247 int nCols=m.getNumCols();
1248 int * index = new int [nCols];
1249 for (i=0;i<nCols;i++) {
1250 if (integer[i]) {
1251 index[n++]=i;
1252 }
1253 }
1254 setInteger(index,n);
1255 delete [] index;
1256 }
1257 }
1258 return numberErrors;
1259}
1260 /* Read a problem in MPS format from the given full filename.
1261
1262This uses CoinMpsIO::readMps() to read
1263the MPS file and returns the number of errors encountered.
1264It also may return an array of set information
1265*/
1266int
1267OsiSolverInterface::readMps(const char *filename, const char*extension,
1268 int & numberSets, CoinSet ** & sets)
1269{
1270 CoinMpsIO m;
1271 m.setInfinity(getInfinity());
1272
1273 int numberErrors = m.readMps(filename,extension,numberSets,sets);
1274 handler_->message(COIN_SOLVER_MPS,messages_)
1275 <<m.getProblemName()<< numberErrors <<CoinMessageEol;
1276 if (!numberErrors) {
1277 // set objective function offset
1278 setDblParam(OsiObjOffset,m.objectiveOffset());
1279
1280 // set problem name
1281 setStrParam(OsiProbName,m.getProblemName());
1282
1283 // no errors --- load problem, set names and integrality
1284 loadProblem(*m.getMatrixByCol(),m.getColLower(),m.getColUpper(),
1285 m.getObjCoefficients(),m.getRowSense(),m.getRightHandSide(),
1286 m.getRowRange());
1287 setRowColNames(m) ;
1288 const char * integer = m.integerColumns();
1289 if (integer) {
1290 int i,n=0;
1291 int nCols=m.getNumCols();
1292 int * index = new int [nCols];
1293 for (i=0;i<nCols;i++) {
1294 if (integer[i]) {
1295 index[n++]=i;
1296 }
1297 }
1298 setInteger(index,n);
1299 delete [] index;
1300 }
1301 }
1302 return numberErrors;
1303}
1304
1305int
1306OsiSolverInterface::writeMpsNative(const char *filename,
1307 const char ** rowNames,
1308 const char ** columnNames,
1309 int formatType,
1310 int numberAcross,
1311 double objSense,
1312 int numberSOS,
1313 const CoinSet * setInfo ) const
1314{
1315 const int numcols = getNumCols();
1316 char* integrality = new char[numcols];
1317 bool hasInteger = false;
1318 for (int i = 0; i < numcols; ++i) {
1319 if (isInteger(i)) {
1320 integrality[i] = 1;
1321 hasInteger = true;
1322 } else {
1323 integrality[i] = 0;
1324 }
1325 }
1326
1327 // Get multiplier for objective function - default 1.0
1328 double * objective = new double[numcols];
1329 memcpy(objective,getObjCoefficients(),numcols*sizeof(double));
1330 //if (objSense*getObjSense()<0.0) {
1331 double locObjSense = (objSense == 0 ? 1 : objSense);
1332 if(getObjSense() * locObjSense < 0.0) {
1333 for (int i = 0; i < numcols; ++i)
1334 objective [i] = - objective[i];
1335 }
1336
1337 CoinMpsIO writer;
1338 writer.setInfinity(getInfinity());
1339 writer.passInMessageHandler(handler_);
1340 writer.setMpsData(*getMatrixByCol(), getInfinity(),
1341 getColLower(), getColUpper(),
1342 objective, hasInteger ? integrality : 0,
1343 getRowLower(), getRowUpper(),
1344 columnNames,rowNames);
1345 double objOffset=0.0;
1346 getDblParam(OsiObjOffset,objOffset);
1347 writer.setObjectiveOffset(objOffset);
1348 delete [] objective;
1349 delete[] integrality;
1350 return writer.writeMps(filename, 1 /*gzip it*/, formatType, numberAcross,
1351 NULL,numberSOS,setInfo);
1352}
1353/***********************************************************************/
1354void OsiSolverInterface::writeLp(const char * filename,
1355 const char * extension,
1356 double epsilon,
1357 int numberAcross,
1358 int decimals,
1359 double objSense,
1360 bool useRowNames) const
1361{
1362 std::string f(filename);
1363 std::string e(extension);
1364 std::string fullname;
1365 if (e!="") {
1366 fullname = f + "." + e;
1367 } else {
1368 // no extension so no trailing period
1369 fullname = f;
1370 }
1371
1372 char** colnames;
1373 char** rownames;
1374 int nameDiscipline;
1375 if (!getIntParam(OsiNameDiscipline,nameDiscipline))
1376 nameDiscipline = 0;
1377 if (useRowNames && nameDiscipline==2) {
1378 colnames = new char*[getNumCols()];
1379 rownames = new char*[getNumRows()+1];
1380 for (int i = 0; i < getNumCols(); ++i)
1381 colnames[i] = strdup(getColName(i).c_str());
1382 for (int i = 0; i < getNumRows(); ++i)
1383 rownames[i] = strdup(getRowName(i).c_str());
1384 rownames[getNumRows()] = strdup(getObjName().c_str());
1385 } else {
1386 colnames = NULL;
1387 rownames = NULL;
1388 }
1389
1390 // Fall back on Osi version
1391 OsiSolverInterface::writeLpNative(fullname.c_str(),
1392 rownames, colnames, epsilon, numberAcross,
1393 decimals, objSense, useRowNames);
1394
1395 if (useRowNames && nameDiscipline==2) {
1396 for (int i = 0; i < getNumCols(); ++i)
1397 free(colnames[i]);
1398 for (int i = 0; i < getNumRows()+1; ++i)
1399 free(rownames[i]);
1400 delete[] colnames;
1401 delete[] rownames;
1402 }
1403}
1404
1405/*************************************************************************/
1406void OsiSolverInterface::writeLp(FILE *fp,
1407 double epsilon,
1408 int numberAcross,
1409 int decimals,
1410 double objSense,
1411 bool useRowNames) const
1412{
1413 char** colnames;
1414 char** rownames;
1415 int nameDiscipline;
1416 getIntParam(OsiNameDiscipline,nameDiscipline) ;
1417 if (useRowNames && nameDiscipline==2) {
1418 colnames = new char*[getNumCols()];
1419 rownames = new char*[getNumRows()+1];
1420 for (int i = 0; i < getNumCols(); ++i)
1421 colnames[i] = strdup(getColName(i).c_str());
1422 for (int i = 0; i < getNumRows(); ++i)
1423 rownames[i] = strdup(getRowName(i).c_str());
1424 rownames[getNumRows()] = strdup(getObjName().c_str());
1425 } else {
1426 colnames = NULL;
1427 rownames = NULL;
1428 }
1429
1430 // Fall back on Osi version
1431 OsiSolverInterface::writeLpNative(fp,
1432 rownames, colnames, epsilon, numberAcross,
1433 decimals, objSense, useRowNames);
1434
1435 if (useRowNames && nameDiscipline==2) {
1436 for (int i = 0; i < getNumCols(); ++i)
1437 free(colnames[i]);
1438 for (int i = 0; i < getNumRows()+1; ++i)
1439 free(rownames[i]);
1440 delete[] colnames;
1441 delete[] rownames;
1442 }
1443}
1444
1445/***********************************************************************/
1446int
1447OsiSolverInterface::writeLpNative(const char *filename,
1448 char const * const * const rowNames,
1449 char const * const * const columnNames,
1450 const double epsilon,
1451 const int numberAcross,
1452 const int decimals,
1453 const double objSense,
1454 const bool useRowNames) const
1455{
1456 FILE *fp = NULL;
1457 fp = fopen(filename,"w");
1458 if (!fp) {
1459 printf("### ERROR: in OsiSolverInterface::writeLpNative(): unable to open file %s\n",
1460 filename);
1461 exit(1);
1462 }
1463 int nerr = writeLpNative(fp,rowNames, columnNames,
1464 epsilon, numberAcross, decimals,
1465 objSense, useRowNames);
1466 fclose(fp);
1467 return(nerr);
1468}
1469
1470/***********************************************************************/
1471int
1472OsiSolverInterface::writeLpNative(FILE *fp,
1473 char const * const * const rowNames,
1474 char const * const * const columnNames,
1475 const double epsilon,
1476 const int numberAcross,
1477 const int decimals,
1478 const double objSense,
1479 const bool useRowNames) const
1480{
1481 const int numcols = getNumCols();
1482 char *integrality = new char[numcols];
1483 bool hasInteger = false;
1484
1485 for (int i=0; i<numcols; i++) {
1486 if (isInteger(i)) {
1487 integrality[i] = 1;
1488 hasInteger = true;
1489 } else {
1490 integrality[i] = 0;
1491 }
1492 }
1493
1494 // Get multiplier for objective function - default 1.0
1495 double *objective = new double[numcols];
1496 const double *curr_obj = getObjCoefficients();
1497
1498 //if(getObjSense() * objSense < 0.0) {
1499 double locObjSense = (objSense == 0 ? 1 : objSense);
1500 if(getObjSense() * locObjSense < 0.0) {
1501 for (int i=0; i<numcols; i++) {
1502 objective[i] = - curr_obj[i];
1503 }
1504 }
1505 else {
1506 for (int i=0; i<numcols; i++) {
1507 objective[i] = curr_obj[i];
1508 }
1509 }
1510
1511 CoinLpIO writer;
1512 writer.setInfinity(getInfinity());
1513 writer.setEpsilon(epsilon);
1514 writer.setNumberAcross(numberAcross);
1515 writer.setDecimals(decimals);
1516
1517 writer.setLpDataWithoutRowAndColNames(*getMatrixByRow(),
1518 getColLower(), getColUpper(),
1519 objective, hasInteger ? integrality : 0,
1520 getRowLower(), getRowUpper());
1521
1522 writer.setLpDataRowAndColNames(rowNames, columnNames);
1523
1524 //writer.print();
1525 delete [] objective;
1526 delete[] integrality;
1527 return writer.writeLp(fp, epsilon, numberAcross, decimals,
1528 useRowNames);
1529
1530} /*writeLpNative */
1531
1532/*************************************************************************/
1533int OsiSolverInterface::readLp(const char * filename, const double epsilon) {
1534 FILE *fp = fopen(filename, "r");
1535
1536 if(!fp) {
1537 printf("### ERROR: OsiSolverInterface::readLp(): Unable to open file %s for reading\n",
1538 filename);
1539 return(1);
1540 }
1541
1542 int nerr = readLp(fp, epsilon);
1543 fclose(fp);
1544 return(nerr);
1545}
1546
1547/*************************************************************************/
1548int OsiSolverInterface::readLp(FILE *fp, const double epsilon) {
1549 CoinLpIO m;
1550 m.readLp(fp, epsilon);
1551
1552 // set objective function offest
1553 setDblParam(OsiObjOffset, 0);
1554
1555 // set problem name
1556 setStrParam(OsiProbName, m.getProblemName());
1557
1558 // no errors --- load problem, set names and integrality
1559 loadProblem(*m.getMatrixByRow(), m.getColLower(), m.getColUpper(),
1560 m.getObjCoefficients(), m.getRowLower(), m.getRowUpper());
1561 setRowColNames(m) ;
1562 const char *integer = m.integerColumns();
1563 if (integer) {
1564 int i, n = 0;
1565 int nCols = m.getNumCols();
1566 int *index = new int [nCols];
1567 for (i=0; i<nCols; i++) {
1568 if (integer[i]) {
1569 index[n++] = i;
1570 }
1571 }
1572 setInteger(index, n);
1573 delete [] index;
1574 }
1575 setObjSense(1);
1576 return(0);
1577} /* readLp */
1578
1579/*************************************************************************/
1580
1581// Pass in Message handler (not deleted at end)
1582void
1583OsiSolverInterface::passInMessageHandler(CoinMessageHandler * handler)
1584{
1585 if (defaultHandler_) {
1586 delete handler_;
1587 handler_ = NULL;
1588 }
1589 defaultHandler_=false;
1590 handler_=handler;
1591}
1592// Set language
1593void
1594OsiSolverInterface::newLanguage(CoinMessages::Language language)
1595{
1596 messages_ = CoinMessage(language);
1597}
1598// Is the given primal objective limit reached?
1599bool
1600OsiSolverInterface::isPrimalObjectiveLimitReached() const
1601{
1602 double primalobjlimit;
1603 if (getDblParam(OsiPrimalObjectiveLimit, primalobjlimit))
1604 return getObjSense() * getObjValue() < getObjSense() * primalobjlimit;
1605 else
1606 return false;
1607}
1608// Is the given dual objective limit reached?
1609bool
1610OsiSolverInterface::isDualObjectiveLimitReached() const
1611{
1612 double dualobjlimit;
1613 if (getDblParam(OsiDualObjectiveLimit, dualobjlimit))
1614 return getObjSense() * getObjValue() > getObjSense() * dualobjlimit;
1615 else
1616 return false;
1617}
1618// copy all parameters in this section from one solver to another
1619void
1620OsiSolverInterface::copyParameters(OsiSolverInterface & rhs)
1621{
1622 /*
1623 We should think about this block of code. appData, rowCutDebugger,
1624 and handler_ are not part of the standard parameter data. Arguably copy
1625 actions for them belong in the base Osi.clone() or as separate methods.
1626 -lh, 091021-
1627 */
1628 delete appDataEtc_;
1629 appDataEtc_ = rhs.appDataEtc_->clone();
1630 delete rowCutDebugger_;
1631 if ( rhs.rowCutDebugger_!=NULL )
1632 rowCutDebugger_ = new OsiRowCutDebugger(*rhs.rowCutDebugger_);
1633 else
1634 rowCutDebugger_ = NULL;
1635 if (defaultHandler_) {
1636 delete handler_;
1637 }
1638 /*
1639 Is this correct? Shouldn't we clone a non-default handler instead of
1640 simply assigning the pointer? -lh, 091021-
1641 */
1642 defaultHandler_ = rhs.defaultHandler_;
1643 if (defaultHandler_) {
1644 handler_ = new CoinMessageHandler(*rhs.handler_);
1645 } else {
1646 handler_ = rhs.handler_;
1647 }
1648 CoinDisjointCopyN(rhs.intParam_, OsiLastIntParam, intParam_);
1649 CoinDisjointCopyN(rhs.dblParam_, OsiLastDblParam, dblParam_);
1650 CoinDisjointCopyN(rhs.strParam_, OsiLastStrParam, strParam_);
1651 CoinDisjointCopyN(rhs.hintParam_, OsiLastHintParam, hintParam_);
1652 CoinDisjointCopyN(rhs.hintStrength_, OsiLastHintParam, hintStrength_);
1653}
1654// Resets as if default constructor
1655void
1656OsiSolverInterface::reset()
1657{
1658 // Throw an exception
1659 throw CoinError("Needs coding for this interface", "reset",
1660 "OsiSolverInterface");
1661}
1662/*Enables normal operation of subsequent functions.
1663 This method is supposed to ensure that all typical things (like
1664 reduced costs, etc.) are updated when individual pivots are executed
1665 and can be queried by other methods. says whether will be
1666 doing primal or dual
1667*/
1668void
1669OsiSolverInterface::enableSimplexInterface(bool ) {}
1670
1671//Undo whatever setting changes the above method had to make
1672void
1673OsiSolverInterface::disableSimplexInterface() {}
1674/* Returns 1 if can just do getBInv etc
1675 2 if has all OsiSimplex methods
1676 and 0 if it has none */
1677int
1678OsiSolverInterface::canDoSimplexInterface() const
1679{
1680 return 0;
1681}
1682
1683/* Tells solver that calls to getBInv etc are about to take place.
1684 Underlying code may need mutable as this may be called from
1685 CglCut:;generateCuts which is const. If that is too horrific then
1686 each solver e.g. BCP or CBC will have to do something outside
1687 main loop.
1688*/
1689void
1690OsiSolverInterface::enableFactorization() const
1691{
1692 // Throw an exception
1693 throw CoinError("Needs coding for this interface", "enableFactorization",
1694 "OsiSolverInterface");
1695}
1696// and stop
1697void
1698OsiSolverInterface::disableFactorization() const
1699{
1700 // Throw an exception
1701 throw CoinError("Needs coding for this interface", "disableFactorization",
1702 "OsiSolverInterface");
1703}
1704
1705//Returns true if a basis is available
1706bool
1707OsiSolverInterface::basisIsAvailable() const
1708{
1709 return false;
1710}
1711
1712/* (JJF ?date?) The following two methods may be replaced by the
1713 methods of OsiSolverInterface using OsiWarmStartBasis if:
1714 1. OsiWarmStartBasis resize operation is implemented
1715 more efficiently and
1716 2. It is ensured that effects on the solver are the same
1717
1718 (lh 100818)
1719 1. CoinWarmStartBasis is the relevant resize, and John's right, it needs
1720 to be reworked. The problem is that when new columns or rows are added,
1721 the new space is initialised two bits at a time. It needs to be done
1722 in bulk. There are other problems with CoinWarmStartBasis that should
1723 be addressed at the same time.
1724 2. setWarmStart followed by resolve should do it.
1725*/
1726void
1727OsiSolverInterface::getBasisStatus(int* , int* ) const
1728{
1729 // Throw an exception
1730 throw CoinError("Needs coding for this interface", "getBasisStatus",
1731 "OsiSolverInterface");
1732}
1733
1734/* Set the status of structural/artificial variables and
1735 factorize, update solution etc
1736
1737 NOTE artificials are treated as +1 elements so for <= rhs
1738 artificial will be at lower bound if constraint is tight
1739*/
1740int
1741OsiSolverInterface::setBasisStatus(const int* , const int* )
1742{
1743 // Throw an exception
1744 throw CoinError("Needs coding for this interface", "setBasisStatus",
1745 "OsiSolverInterface");
1746}
1747
1748/* Perform a pivot by substituting a colIn for colOut in the basis.
1749 The status of the leaving variable is given in statOut. Where
1750 1 is to upper bound, -1 to lower bound
1751*/
1752int
1753OsiSolverInterface::pivot(int , int , int )
1754{
1755 // Throw an exception
1756 throw CoinError("Needs coding for this interface", "pivot",
1757 "OsiSolverInterface");
1758}
1759
1760/* Obtain a result of the primal pivot
1761 Outputs: colOut -- leaving column, outStatus -- its status,
1762 t -- step size, and, if dx!=NULL, *dx -- primal ray direction.
1763 Inputs: colIn -- entering column, sign -- direction of its change (+/-1).
1764 Both for colIn and colOut, artificial variables are index by
1765 the negative of the row index minus 1.
1766 Return code (for now): 0 -- leaving variable found,
1767 -1 -- everything else?
1768 Clearly, more informative set of return values is required
1769 Primal and dual solutions are updated
1770*/
1771int
1772OsiSolverInterface::primalPivotResult(int, int ,
1773 int& , int& ,
1774 double& , CoinPackedVector* )
1775{
1776 // Throw an exception
1777 throw CoinError("Needs coding for this interface", "primalPivotResult",
1778 "OsiSolverInterface");
1779}
1780
1781/* Obtain a result of the dual pivot (similar to the previous method)
1782 Differences: entering variable and a sign of its change are now
1783 the outputs, the leaving variable and its statuts -- the inputs
1784 If dx!=NULL, then *dx contains dual ray
1785 Return code: same
1786*/
1787int
1788OsiSolverInterface::dualPivotResult(int& , int& ,
1789 int , int ,
1790 double& , CoinPackedVector* )
1791{
1792 // Throw an exception
1793 throw CoinError("Needs coding for this interface", "dualPivotResult",
1794 "OsiSolverInterface");
1795}
1796
1797//Get the reduced gradient for the cost vector c
1798void
1799OsiSolverInterface::getReducedGradient(double* ,
1800 double * ,
1801 const double * ) const
1802{
1803 // Throw an exception
1804 throw CoinError("Needs coding for this interface", "getReducedGradient",
1805 "OsiSolverInterface");
1806}
1807
1808//Get a row of the tableau (slack part in slack if not NULL)
1809void
1810OsiSolverInterface::getBInvARow(int , double* , double * ) const
1811{
1812 // Throw an exception
1813 throw CoinError("Needs coding for this interface", "getBInvARow",
1814 "OsiSolverInterface");
1815}
1816
1817//Get a row of the basis inverse
1818void OsiSolverInterface::getBInvRow(int , double* ) const
1819{
1820 // Throw an exception
1821 throw CoinError("Needs coding for this interface", "getBInvRow",
1822 "OsiSolverInterface");
1823}
1824
1825//Get a column of the tableau
1826void
1827OsiSolverInterface::getBInvACol(int , double* ) const
1828{
1829 // Throw an exception
1830 throw CoinError("Needs coding for this interface", "getBInvACol",
1831 "OsiSolverInterface");
1832}
1833
1834//Get a column of the basis inverse
1835void
1836OsiSolverInterface::getBInvCol(int , double* ) const
1837{
1838 // Throw an exception
1839 throw CoinError("Needs coding for this interface", "getBInvCol",
1840 "OsiSolverInterface");
1841}
1842/* Get warm start information.
1843 Return warm start information for the current state of the solver
1844 interface. If there is no valid warm start information, an empty warm
1845 start object wil be returned. This does not necessarily create an
1846 object - may just point to one. must Delete set true if user
1847 should delete returned object.
1848 OsiClp version always returns pointer and false.
1849*/
1850CoinWarmStart*
1851OsiSolverInterface::getPointerToWarmStart(bool & mustDelete)
1852{
1853 mustDelete = true;
1854 return getWarmStart();
1855}
1856
1857/* Get basic indices (order of indices corresponds to the
1858 order of elements in a vector retured by getBInvACol() and
1859 getBInvCol()).
1860*/
1861void
1862OsiSolverInterface::getBasics(int* ) const
1863{
1864 // Throw an exception
1865 throw CoinError("Needs coding for this interface", "getBasics",
1866 "OsiSolverInterface");
1867}
1868#ifdef COIN_SNAPSHOT
1869// Fill in a CoinSnapshot
1870CoinSnapshot *
1871OsiSolverInterface::snapshot(bool createArrays) const
1872{
1873 CoinSnapshot * snap = new CoinSnapshot();
1874 // scalars
1875 snap->setObjSense(getObjSense());
1876 snap->setInfinity(getInfinity());
1877 snap->setObjValue(getObjValue());
1878 double objOffset=0.0;
1879 getDblParam(OsiObjOffset,objOffset);
1880 snap->setObjOffset(objOffset);
1881 snap->setDualTolerance(dblParam_[OsiDualTolerance]);
1882 snap->setPrimalTolerance(dblParam_[OsiPrimalTolerance]);
1883 snap->setIntegerTolerance(getIntegerTolerance());
1884 snap->setIntegerUpperBound(dblParam_[OsiDualObjectiveLimit]);
1885 if (createArrays) {
1886 snap->loadProblem(*getMatrixByCol(),getColLower(),getColUpper(),
1887 getObjCoefficients(),getRowLower(),
1888 getRowUpper());
1889 snap->createRightHandSide();
1890 // Solution
1891 snap->setColSolution(getColSolution(),true);
1892 snap->setRowPrice(getRowPrice(),true);
1893 snap->setReducedCost(getReducedCost(),true);
1894 snap->setRowActivity(getRowActivity(),true);
1895 } else {
1896 snap->setNumCols(getNumCols());
1897 snap->setNumRows(getNumRows());
1898 snap->setNumElements(getNumElements());
1899 snap->setMatrixByCol(getMatrixByCol(),false);
1900 snap->setColLower(getColLower(),false);
1901 snap->setColUpper(getColUpper(),false);
1902 snap->setObjCoefficients(getObjCoefficients(),false);
1903 snap->setRowLower(getRowLower(),false);
1904 snap->setRowUpper(getRowUpper(),false);
1905 // Solution
1906 snap->setColSolution(getColSolution(),false);
1907 snap->setRowPrice(getRowPrice(),false);
1908 snap->setReducedCost(getReducedCost(),false);
1909 snap->setRowActivity(getRowActivity(),false);
1910 }
1911 // If integer then create array (which snapshot has to own);
1912 int numberColumns = getNumCols();
1913 char * type = new char[numberColumns];
1914 int numberIntegers=0;
1915 for (int i=0;i<numberColumns;i++) {
1916 if (isInteger(i)) {
1917 numberIntegers++;
1918 if (isBinary(i))
1919 type[i]='B';
1920 else
1921 type[i]='I';
1922 } else {
1923 type[i]='C';
1924 }
1925 }
1926 if (numberIntegers)
1927 snap->setColType(type,true);
1928 else
1929 snap->setNumIntegers(0);
1930 delete [] type;
1931 return snap;
1932}
1933#endif
1934/* Identify integer variables and create corresponding objects.
1935
1936 Record integer variables and create an OsiSimpleInteger object for each
1937 one. All existing OsiSimpleInteger objects will be destroyed.
1938 New
1939*/
1940void
1941OsiSolverInterface::findIntegers(bool justCount)
1942{
1943 numberIntegers_=0;
1944 int numberColumns = getNumCols();
1945 int iColumn;
1946 for (iColumn=0;iColumn<numberColumns;iColumn++) {
1947 if (isInteger(iColumn))
1948 numberIntegers_++;
1949 }
1950 if (justCount) {
1951 assert (!numberObjects_);
1952 assert (!object_);
1953 return;
1954 }
1955 int numberIntegers=0;
1956 int iObject;
1957 for (iObject = 0;iObject<numberObjects_;iObject++) {
1958 OsiSimpleInteger * obj =
1959 dynamic_cast <OsiSimpleInteger *>(object_[iObject]) ;
1960 if (obj)
1961 numberIntegers++;
1962 }
1963 // if same number return
1964 if (numberIntegers_==numberIntegers)
1965 return;
1966 // space for integers
1967 int * marked = new int[numberColumns];
1968 for (iColumn=0;iColumn<numberColumns;iColumn++)
1969 marked[iColumn]=-1;
1970 // mark simple integers
1971 OsiObject ** oldObject = object_;
1972 int nObjects=numberObjects_;
1973 for (iObject = 0;iObject<nObjects;iObject++) {
1974 OsiSimpleInteger * obj =
1975 dynamic_cast <OsiSimpleInteger *>(oldObject[iObject]) ;
1976 if (obj) {
1977 iColumn = obj->columnNumber();
1978 assert (iColumn>=0&&iColumn<numberColumns);
1979 marked[iColumn]=iObject;
1980 }
1981 }
1982 // make a large enough array for new objects
1983 numberObjects_ += numberIntegers_-numberIntegers;
1984 if (numberObjects_)
1985 object_ = new OsiObject * [numberObjects_];
1986 else
1987 object_=NULL;
1988 /*
1989 Walk the variables again, filling in the indices and creating objects for
1990 the integer variables. Initially, the objects hold the index and upper &
1991 lower bounds.
1992 */
1993 numberObjects_=0;
1994 for (iColumn=0;iColumn<numberColumns;iColumn++) {
1995 if(isInteger(iColumn)) {
1996 iObject=marked[iColumn];
1997 if (iObject>=0)
1998 object_[numberObjects_++] = oldObject[iObject];
1999 else
2000 object_[numberObjects_++] =
2001 new OsiSimpleInteger(this,iColumn);
2002 }
2003 }
2004 // Now append other objects
2005 for (iObject = 0;iObject<nObjects;iObject++) {
2006 OsiSimpleInteger * obj =
2007 dynamic_cast <OsiSimpleInteger *>(oldObject[iObject]) ;
2008 if (!obj)
2009 object_[numberObjects_++] = oldObject[iObject];
2010 }
2011 // Delete old array (just array)
2012 delete [] oldObject;
2013 delete [] marked;
2014}
2015/* Identify integer variables and SOS and create corresponding objects.
2016
2017 Record integer variables and create an OsiSimpleInteger object for each
2018 one. All existing OsiSimpleInteger objects will be destroyed.
2019 If the solver supports SOS then do the same for SOS.
2020
2021 If justCount then no objects created and we just store numberIntegers_
2022 Returns number of SOS
2023*/
2024int
2025OsiSolverInterface::findIntegersAndSOS(bool justCount)
2026{
2027 findIntegers(justCount);
2028 return 0;
2029}
2030// Delete all object information
2031void
2032OsiSolverInterface::deleteObjects()
2033{
2034 for (int i=0;i<numberObjects_;i++)
2035 delete object_[i];
2036 delete [] object_;
2037 object_=NULL;
2038 numberObjects_=0;
2039}
2040
2041/* Add in object information.
2042
2043 Objects are cloned; the owner can delete the originals.
2044*/
2045void
2046OsiSolverInterface::addObjects(int numberObjects, OsiObject ** objects)
2047{
2048 // Create integers if first time
2049 if (!numberObjects_)
2050 findIntegers(false);
2051 /* But if incoming objects inherit from simple integer we just want
2052 to replace */
2053 int numberColumns = getNumCols();
2054 /** mark is -1 if not integer, >=0 if using existing simple integer and
2055 >=numberColumns if using new integer */
2056 int * mark = new int[numberColumns];
2057 int i;
2058 for (i=0;i<numberColumns;i++)
2059 mark[i]=-1;
2060 int newNumberObjects = numberObjects;
2061 int newIntegers=0;
2062 for (i=0;i<numberObjects;i++) {
2063 OsiSimpleInteger * obj =
2064 dynamic_cast <OsiSimpleInteger *>(objects[i]) ;
2065 if (obj) {
2066 int iColumn = obj->columnNumber();
2067 mark[iColumn]=i+numberColumns;
2068 newIntegers++;
2069 }
2070 }
2071 // and existing
2072 for (i=0;i<numberObjects_;i++) {
2073 OsiSimpleInteger * obj =
2074 dynamic_cast <OsiSimpleInteger *>(object_[i]) ;
2075 if (obj) {
2076 int iColumn = obj->columnNumber();
2077 if (mark[iColumn]<0) {
2078 newIntegers++;
2079 newNumberObjects++;
2080 mark[iColumn]=i;
2081 } else {
2082 // But delete existing
2083 delete object_[i];
2084 object_[i]=NULL;
2085 }
2086 } else {
2087 newNumberObjects++;
2088 }
2089 }
2090 numberIntegers_ = newIntegers;
2091 OsiObject ** temp = new OsiObject * [newNumberObjects];
2092 // Put integers first
2093 newIntegers=0;
2094 numberIntegers_=0;
2095 for (i=0;i<numberColumns;i++) {
2096 int which = mark[i];
2097 if (which>=0) {
2098 if (!isInteger(i)) {
2099 newIntegers++;
2100 setInteger(i);
2101 }
2102 if (which<numberColumns) {
2103 temp[numberIntegers_]=object_[which];
2104 } else {
2105 temp[numberIntegers_]=objects[which-numberColumns]->clone();
2106 }
2107 numberIntegers_++;
2108 }
2109 }
2110 int n=numberIntegers_;
2111 // Now rest of old
2112 for (i=0;i<numberObjects_;i++) {
2113 if (object_[i]) {
2114 OsiSimpleInteger * obj =
2115 dynamic_cast <OsiSimpleInteger *>(object_[i]) ;
2116 if (!obj) {
2117 temp[n++]=object_[i];
2118 }
2119 }
2120 }
2121 // and rest of new
2122 for (i=0;i<numberObjects;i++) {
2123 OsiSimpleInteger * obj =
2124 dynamic_cast <OsiSimpleInteger *>(objects[i]) ;
2125 if (!obj) {
2126 temp[n++]=objects[i]->clone();
2127 }
2128 }
2129 delete [] mark;
2130 delete [] object_;
2131 object_ = temp;
2132 numberObjects_ = newNumberObjects;
2133}
2134// Deletes branching information before columns deleted
2135void
2136OsiSolverInterface::deleteBranchingInfo(int numberDeleted, const int * which)
2137{
2138 if (numberObjects_) {
2139 int numberColumns = getNumCols();
2140 // mark is -1 if deleted and new number if not deleted
2141 int * mark = new int[numberColumns];
2142 int i;
2143 int iColumn;
2144 for (i=0;i<numberColumns;i++)
2145 mark[i]=0;
2146 for (i=0;i<numberDeleted;i++) {
2147 iColumn = which[i];
2148 if (iColumn>=0&&iColumn<numberColumns)
2149 mark[iColumn]=-1;
2150 }
2151 iColumn = 0;
2152 for (i=0;i<numberColumns;i++) {
2153 if (mark[i]>=0) {
2154 mark[i]=iColumn;
2155 iColumn++;
2156 }
2157 }
2158 int oldNumberObjects = numberObjects_;
2159 numberIntegers_=0;
2160 numberObjects_=0;
2161 for (i=0;i<oldNumberObjects;i++) {
2162 OsiSimpleInteger * obj =
2163 dynamic_cast <OsiSimpleInteger *>(object_[i]) ;
2164 if (obj) {
2165 iColumn = obj->columnNumber();
2166 int jColumn = mark[iColumn];
2167 if (jColumn>=0) {
2168 obj->setColumnNumber(jColumn);
2169 object_[numberObjects_++]=obj;
2170 numberIntegers_++;
2171 } else {
2172 delete obj;
2173 }
2174 } else {
2175 // not integer - all I know about is SOS
2176 OsiSOS * obj =
2177 dynamic_cast <OsiSOS *>(object_[i]) ;
2178 if (obj) {
2179 int oldNumberMembers=obj->numberMembers();
2180 int numberMembers=0;
2181 double * weight = obj->mutableWeights();
2182 int * members = obj->mutableMembers();
2183 for (int k=0;k<oldNumberMembers;k++) {
2184 iColumn = members[k];
2185 int jColumn = mark[iColumn];
2186 if (jColumn>=0) {
2187 members[numberMembers]=jColumn;
2188 weight[numberMembers++]=weight[k];
2189 }
2190 }
2191 if (numberMembers) {
2192 obj->setNumberMembers(numberMembers);
2193 object_[numberObjects_++]=obj;
2194 }
2195 }
2196 }
2197 }
2198 delete [] mark;
2199 } else {
2200 findIntegers(false);
2201 }
2202}
2203/* Use current solution to set bounds so current integer feasible solution will stay feasible.
2204 Only feasible bounds will be used, even if current solution outside bounds. The amount of
2205 such violation will be returned (and if small can be ignored)
2206*/
2207double
2208OsiSolverInterface::forceFeasible()
2209{
2210 /*
2211 Run through the objects and use feasibleRegion() to set variable bounds
2212 so as to fix the variables specified in the objects at their value in this
2213 solution. Since the object list contains (at least) one object for every
2214 integer variable, this has the effect of fixing all integer variables.
2215 */
2216 int i;
2217 // Can't guarantee has matrix
2218 const OsiBranchingInformation info(this,false,false);
2219 double infeasibility=0.0;
2220 for (i=0;i<numberObjects_;i++)
2221 infeasibility += object_[i]->feasibleRegion(this,&info);
2222 return infeasibility;
2223}
2224/*
2225 For variables currently at bound, fix at bound if reduced cost >= gap
2226 Returns number fixed
2227*/
2228int
2229OsiSolverInterface::reducedCostFix(double gap, bool justInteger)
2230{
2231 double direction = getObjSense() ;
2232 double tolerance;
2233 getDblParam(OsiPrimalTolerance,tolerance) ;
2234 if (gap<=0.0)
2235 return 0;
2236
2237 const double *lower = getColLower() ;
2238 const double *upper = getColUpper() ;
2239 const double *solution = getColSolution() ;
2240 const double *reducedCost = getReducedCost() ;
2241
2242 int numberFixed = 0 ;
2243 int numberColumns = getNumCols();
2244
2245 for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) {
2246 if (isInteger(iColumn)||!justInteger) {
2247 double djValue = direction*reducedCost[iColumn] ;
2248 if (upper[iColumn]-lower[iColumn] > tolerance) {
2249 if (solution[iColumn] < lower[iColumn]+tolerance && djValue > gap) {
2250 setColUpper(iColumn,lower[iColumn]) ;
2251 numberFixed++ ;
2252 } else if (solution[iColumn] > upper[iColumn]-tolerance && -djValue > gap) {
2253 setColLower(iColumn,upper[iColumn]) ;
2254 numberFixed++ ;
2255 }
2256 }
2257 }
2258 }
2259
2260 return numberFixed;
2261}
2262#ifdef COIN_FACTORIZATION_INFO
2263// Return number of entries in L part of current factorization
2264CoinBigIndex
2265OsiSolverInterface::getSizeL() const
2266{
2267 return -1;
2268}
2269// Return number of entries in U part of current factorization
2270CoinBigIndex
2271OsiSolverInterface::getSizeU() const
2272{
2273 return -1;
2274}
2275#endif
2276#ifdef CBC_NEXT_VERSION
2277/*
2278 Solve 2**N (N==depth) problems and return solutions and bases.
2279 There are N branches each of which changes bounds on both sides
2280 as given by branch. The user should provide an array of (empty)
2281 results which will be filled in. See OsiSolveResult for more details
2282 (in OsiSolveBranch.?pp) but it will include a basis and primal solution.
2283
2284 The order of results is left to right at feasible leaf nodes so first one
2285 is down, down, .....
2286
2287 Returns number of feasible leaves. Also sets number of solves done and number
2288 of iterations.
2289
2290 This is provided so a solver can do faster.
2291
2292 If forceBranch true then branch done even if satisfied
2293*/
2294int
2295OsiSolverInterface::solveBranches(int depth,const OsiSolverBranch * branch,
2296 OsiSolverResult * result,
2297 int & numberSolves, int & numberIterations,
2298 bool forceBranch)
2299{
2300 int * stack = new int [depth];
2301 CoinWarmStart ** basis = new CoinWarmStart * [depth];
2302 int iDepth;
2303 for (iDepth=0;iDepth<depth;iDepth++) {
2304 stack[iDepth]=-1;
2305 basis[iDepth]=NULL;
2306 }
2307 //#define PRINTALL
2308#ifdef PRINTALL
2309 int seq[10];
2310 double val[10];
2311 assert (iDepth<=10);
2312 for (iDepth=0;iDepth<depth;iDepth++) {
2313 assert (branch[iDepth].starts()[4]==2);
2314 assert (branch[iDepth].which()[0]==branch[iDepth].which()[1]);
2315 assert (branch[iDepth].bounds()[0]==branch[iDepth].bounds()[1]-1.0);
2316 seq[iDepth]=branch[iDepth].which()[0];
2317 val[iDepth]=branch[iDepth].bounds()[0];
2318 printf("depth %d seq %d nominal value %g\n",iDepth,seq[iDepth],val[iDepth]+0.5);
2319 }
2320#endif
2321 int numberColumns = getNumCols();
2322 double * lowerBefore = CoinCopyOfArray(getColLower(),numberColumns);
2323 double * upperBefore = CoinCopyOfArray(getColUpper(),numberColumns);
2324 iDepth=0;
2325 int numberFeasible=0;
2326 bool finished=false;
2327 bool backTrack=false;
2328 bool iterated=false;
2329 numberIterations=0;
2330 numberSolves=0;
2331 int nFeas=0;
2332 while (!finished) {
2333 bool feasible = true;
2334 if (stack[iDepth]==-1) {
2335 delete basis[iDepth];
2336 basis[iDepth]=getWarmStart();
2337 } else {
2338 setWarmStart(basis[iDepth]);
2339 }
2340 // may be a faster way
2341 setColLower(lowerBefore);
2342 setColUpper(upperBefore);
2343 for (int i=0;i<iDepth;i++) {
2344 // skip if values feasible and not forceBranch
2345 if (stack[i])
2346 branch[i].applyBounds(*this,stack[i]);
2347 }
2348 bool doBranch = true;
2349 if (!forceBranch&&!backTrack) {
2350 // see if feasible on one side
2351 if (!branch[iDepth].feasibleOneWay(*this)) {
2352 branch[iDepth].applyBounds(*this,stack[iDepth]);
2353 } else {
2354 doBranch=false;
2355 stack[iDepth]=0;
2356 }
2357 } else {
2358 branch[iDepth].applyBounds(*this,stack[iDepth]);
2359 }
2360 if (doBranch) {
2361 resolve();
2362 numberIterations += getIterationCount();
2363 numberSolves++;
2364 iterated=true;
2365 if (!isProvenOptimal()||isDualObjectiveLimitReached()) {
2366 feasible=false;
2367#ifdef PRINTALL
2368 const double * columnLower = getColLower();
2369 const double * columnUpper = getColUpper();
2370 const double * columnSolution = getColSolution();
2371 printf("infeas depth %d ",iDepth);
2372 for (int jDepth=0;jDepth<=iDepth;jDepth++) {
2373 int iColumn=seq[jDepth];
2374 printf(" (%d %g, %g, %g (nom %g))",iColumn,columnLower[iColumn],
2375 columnSolution[iColumn],columnUpper[iColumn],val[jDepth]+0.5);
2376 }
2377 printf("\n");
2378#endif
2379 }
2380 } else {
2381 // must be feasible
2382 nFeas++;
2383#ifdef PRINTALL
2384 const double * columnLower = getColLower();
2385 const double * columnUpper = getColUpper();
2386 const double * columnSolution = getColSolution();
2387 printf("feas depth %d ",iDepth);
2388 int iColumn=seq[iDepth];
2389 printf(" (%d %g, %g, %g (nom %g))",iColumn,columnLower[iColumn],
2390 columnSolution[iColumn],columnUpper[iColumn],val[iDepth]+0.5);
2391 printf("\n");
2392#endif
2393 }
2394 backTrack=false;
2395 iDepth++;
2396 if (iDepth==depth||!feasible) {
2397 if (feasible&&iterated) {
2398 result[numberFeasible++]=OsiSolverResult(*this,lowerBefore,upperBefore);
2399#ifdef PRINTALL
2400 const double * columnLower = getColLower();
2401 const double * columnUpper = getColUpper();
2402 const double * columnSolution = getColSolution();
2403 printf("sol obj %g",getObjValue());
2404 for (int jDepth=0;jDepth<depth;jDepth++) {
2405 int iColumn=seq[jDepth];
2406 printf(" (%d %g, %g, %g (nom %g))",iColumn,columnLower[iColumn],
2407 columnSolution[iColumn],columnUpper[iColumn],val[jDepth]+0.5);
2408 }
2409 printf("\n");
2410#endif
2411 }
2412 // on to next
2413 iDepth--;
2414 iterated=false;
2415 backTrack=true;
2416 while (stack[iDepth]>=0) {
2417 if (iDepth==0) {
2418 // finished
2419 finished=true;
2420 break;
2421 }
2422 stack[iDepth]=-1;
2423 iDepth--;
2424 }
2425 if (!finished) {
2426 stack[iDepth]=1;
2427 }
2428 }
2429 }
2430 delete [] stack;
2431 for (iDepth=0;iDepth<depth;iDepth++)
2432 delete basis[iDepth];
2433 delete [] basis;
2434 // restore bounds
2435 setColLower(lowerBefore);
2436 setColUpper(upperBefore);
2437 delete [] lowerBefore;
2438 delete [] upperBefore;
2439#if 0
2440 static int xxxxxx=0;
2441 static int yyyyyy=0;
2442 static int zzzzzz=0;
2443 zzzzzz += nFeas;
2444 for (int j=0;j<(1<<depth);j++) {
2445 xxxxxx++;
2446 if ((xxxxxx%10000)==0)
2447 printf("%d implicit %d feas %d sent back\n",xxxxxx,zzzzzz,yyyyyy);
2448 }
2449 for (int j=0;j<numberFeasible;j++) {
2450 yyyyyy++;
2451 if ((yyyyyy%10000)==0)
2452 printf("%d implicit %d feas %d sent back\n",xxxxxx,zzzzzz,yyyyyy);
2453 }
2454#endif
2455 return numberFeasible;
2456}
2457#endif
2458