1 /* $Id: ClpModel.cpp 1787 2011-09-03 13:06:58Z stefan $ */
2 // copyright (C) 2002, International Business Machines
3 // Corporation and others.  All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5 
6 #include <cstdlib>
7 #include <cmath>
8 #include <cassert>
9 #include <cfloat>
10 #include <string>
11 #include <cstdio>
12 #include <iostream>
13 
14 /*
15   CLP_NO_VECTOR
16 
17   There's no hint of the motivation for this, so here's a bit of speculation.
18   CLP_NO_VECTOR excises CoinPackedVector from the code. Looking over
19   affected code here, and the much more numerous occurrences of affected
20   code in CoinUtils, it looks to be an efficiency issue.
21 
22   One good example is CoinPackedMatrix.isEquivalent. The default version
23   tests equivalence of major dimension vectors by retrieving them as
24   CPVs and invoking CPV.isEquivalent. As pointed out in the documention,
25   CPV.isEquivalent implicitly sorts the nonzeros of each vector (insertion in
26   a map) prior to comparison. As a one-off, this is arguably more efficient
27   than allocating and clearing a full vector, then dropping in the nonzeros,
28   then checking against the second vector (in fact, this is the algorithm
29   for testing a packed vector against a full vector).
30 
31   In CPM.isEquivalent, we have a whole sequence of vectors to compare. Better
32   to allocate a full vector sized to match, clear it (one time cost), then
33   edit nonzeros in and out while doing comparisons. The cost of allocating
34   and clearing the full vector is amortised over all columns.
35 */
36 
37 
38 #include "CoinPragma.hpp"
39 
40 #include "CoinHelperFunctions.hpp"
41 #include "CoinTime.hpp"
42 #include "ClpModel.hpp"
43 #include "ClpEventHandler.hpp"
44 #include "ClpPackedMatrix.hpp"
45 #ifndef SLIM_CLP
46 #include "ClpPlusMinusOneMatrix.hpp"
47 #endif
48 #ifndef CLP_NO_VECTOR
49 #include "CoinPackedVector.hpp"
50 #endif
51 #include "CoinIndexedVector.hpp"
52 #if SLIM_CLP==2
53 #define SLIM_NOIO
54 #endif
55 #ifndef SLIM_NOIO
56 #include "CoinMpsIO.hpp"
57 #include "CoinFileIO.hpp"
58 #include "CoinModel.hpp"
59 #endif
60 #include "ClpMessage.hpp"
61 #include "CoinMessage.hpp"
62 #include "ClpLinearObjective.hpp"
63 #ifndef SLIM_CLP
64 #include "ClpQuadraticObjective.hpp"
65 #include "CoinBuild.hpp"
66 #endif
67 
68 //#############################################################################
ClpModel(bool emptyMessages)69 ClpModel::ClpModel (bool emptyMessages) :
70 
71      optimizationDirection_(1),
72      objectiveValue_(0.0),
73      smallElement_(1.0e-20),
74      objectiveScale_(1.0),
75      rhsScale_(1.0),
76      numberRows_(0),
77      numberColumns_(0),
78      rowActivity_(NULL),
79      columnActivity_(NULL),
80      dual_(NULL),
81      reducedCost_(NULL),
82      rowLower_(NULL),
83      rowUpper_(NULL),
84      objective_(NULL),
85      rowObjective_(NULL),
86      columnLower_(NULL),
87      columnUpper_(NULL),
88      matrix_(NULL),
89      rowCopy_(NULL),
90      scaledMatrix_(NULL),
91      ray_(NULL),
92      rowScale_(NULL),
93      columnScale_(NULL),
94      inverseRowScale_(NULL),
95      inverseColumnScale_(NULL),
96      scalingFlag_(3),
97      status_(NULL),
98      integerType_(NULL),
99      userPointer_(NULL),
100      trustedUserPointer_(NULL),
101      numberIterations_(0),
102      solveType_(0),
103      whatsChanged_(0),
104      problemStatus_(-1),
105      secondaryStatus_(0),
106      lengthNames_(0),
107      numberThreads_(0),
108      specialOptions_(0),
109 #ifndef CLP_NO_STD
110      defaultHandler_(true),
111      rowNames_(),
112      columnNames_(),
113 #else
114      defaultHandler_(true),
115 #endif
116      maximumColumns_(-1),
117      maximumRows_(-1),
118      maximumInternalColumns_(-1),
119      maximumInternalRows_(-1),
120      savedRowScale_(NULL),
121      savedColumnScale_(NULL)
122 {
123      intParam_[ClpMaxNumIteration] = 2147483647;
124      intParam_[ClpMaxNumIterationHotStart] = 9999999;
125      intParam_[ClpNameDiscipline] = 0;
126 
127      dblParam_[ClpDualObjectiveLimit] = COIN_DBL_MAX;
128      dblParam_[ClpPrimalObjectiveLimit] = COIN_DBL_MAX;
129      dblParam_[ClpDualTolerance] = 1e-7;
130      dblParam_[ClpPrimalTolerance] = 1e-7;
131      dblParam_[ClpObjOffset] = 0.0;
132      dblParam_[ClpMaxSeconds] = -1.0;
133      dblParam_[ClpPresolveTolerance] = 1.0e-8;
134 
135 #ifndef CLP_NO_STD
136      strParam_[ClpProbName] = "ClpDefaultName";
137 #endif
138      handler_ = new CoinMessageHandler();
139      handler_->setLogLevel(1);
140      eventHandler_ = new ClpEventHandler();
141      if (!emptyMessages) {
142           messages_ = ClpMessage();
143           coinMessages_ = CoinMessage();
144      }
145      randomNumberGenerator_.setSeed(1234567);
146 }
147 
148 //-----------------------------------------------------------------------------
149 
~ClpModel()150 ClpModel::~ClpModel ()
151 {
152      if (defaultHandler_) {
153           delete handler_;
154           handler_ = NULL;
155      }
156      gutsOfDelete(0);
157 }
158 // Does most of deletion (0 = all, 1 = most)
159 void
gutsOfDelete(int type)160 ClpModel::gutsOfDelete(int type)
161 {
162      if (!type || !permanentArrays()) {
163           maximumRows_ = -1;
164           maximumColumns_ = -1;
165           delete [] rowActivity_;
166           rowActivity_ = NULL;
167           delete [] columnActivity_;
168           columnActivity_ = NULL;
169           delete [] dual_;
170           dual_ = NULL;
171           delete [] reducedCost_;
172           reducedCost_ = NULL;
173           delete [] rowLower_;
174           delete [] rowUpper_;
175           delete [] rowObjective_;
176           rowLower_ = NULL;
177           rowUpper_ = NULL;
178           rowObjective_ = NULL;
179           delete [] columnLower_;
180           delete [] columnUpper_;
181           delete objective_;
182           columnLower_ = NULL;
183           columnUpper_ = NULL;
184           objective_ = NULL;
185           delete [] savedRowScale_;
186           if (rowScale_ == savedRowScale_)
187                rowScale_ = NULL;
188           savedRowScale_ = NULL;
189           delete [] savedColumnScale_;
190           if (columnScale_ == savedColumnScale_)
191                columnScale_ = NULL;
192           savedColumnScale_ = NULL;
193           delete [] rowScale_;
194           rowScale_ = NULL;
195           delete [] columnScale_;
196           columnScale_ = NULL;
197           delete [] integerType_;
198           integerType_ = NULL;
199           delete [] status_;
200           status_ = NULL;
201           delete eventHandler_;
202           eventHandler_ = NULL;
203      }
204      whatsChanged_ = 0;
205      delete matrix_;
206      matrix_ = NULL;
207      delete rowCopy_;
208      rowCopy_ = NULL;
209      delete scaledMatrix_;
210      scaledMatrix_ = NULL,
211      delete [] ray_;
212      ray_ = NULL;
213      specialOptions_ = 0;
214 }
215 void
setRowScale(double * scale)216 ClpModel::setRowScale(double * scale)
217 {
218      if (!savedRowScale_) {
219           delete [] reinterpret_cast<double *> (rowScale_);
220           rowScale_ = scale;
221      } else {
222           assert (!scale);
223           rowScale_ = NULL;
224      }
225 }
226 void
setColumnScale(double * scale)227 ClpModel::setColumnScale(double * scale)
228 {
229      if (!savedColumnScale_) {
230           delete [] reinterpret_cast<double *> (columnScale_);
231           columnScale_ = scale;
232      } else {
233           assert (!scale);
234           columnScale_ = NULL;
235      }
236 }
237 //#############################################################################
setPrimalTolerance(double value)238 void ClpModel::setPrimalTolerance( double value)
239 {
240      if (value > 0.0 && value < 1.0e10)
241           dblParam_[ClpPrimalTolerance] = value;
242 }
setDualTolerance(double value)243 void ClpModel::setDualTolerance( double value)
244 {
245      if (value > 0.0 && value < 1.0e10)
246           dblParam_[ClpDualTolerance] = value;
247 }
setOptimizationDirection(double value)248 void ClpModel::setOptimizationDirection( double value)
249 {
250      optimizationDirection_ = value;
251 }
252 void
gutsOfLoadModel(int numberRows,int numberColumns,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub,const double * rowObjective)253 ClpModel::gutsOfLoadModel (int numberRows, int numberColumns,
254                            const double* collb, const double* colub,
255                            const double* obj,
256                            const double* rowlb, const double* rowub,
257                            const double * rowObjective)
258 {
259      // save event handler in case already set
260      ClpEventHandler * handler = eventHandler_->clone();
261      // Save specialOptions
262      int saveOptions = specialOptions_;
263      gutsOfDelete(0);
264      specialOptions_ = saveOptions;
265      eventHandler_ = handler;
266      numberRows_ = numberRows;
267      numberColumns_ = numberColumns;
268      rowActivity_ = new double[numberRows_];
269      columnActivity_ = new double[numberColumns_];
270      dual_ = new double[numberRows_];
271      reducedCost_ = new double[numberColumns_];
272 
273      CoinZeroN(dual_, numberRows_);
274      CoinZeroN(reducedCost_, numberColumns_);
275      int iRow, iColumn;
276 
277      rowLower_ = ClpCopyOfArray(rowlb, numberRows_, -COIN_DBL_MAX);
278      rowUpper_ = ClpCopyOfArray(rowub, numberRows_, COIN_DBL_MAX);
279      double * objective = ClpCopyOfArray(obj, numberColumns_, 0.0);
280      objective_ = new ClpLinearObjective(objective, numberColumns_);
281      delete [] objective;
282      rowObjective_ = ClpCopyOfArray(rowObjective, numberRows_);
283      columnLower_ = ClpCopyOfArray(collb, numberColumns_, 0.0);
284      columnUpper_ = ClpCopyOfArray(colub, numberColumns_, COIN_DBL_MAX);
285      // set default solution and clean bounds
286      for (iRow = 0; iRow < numberRows_; iRow++) {
287           if (rowLower_[iRow] > 0.0) {
288                rowActivity_[iRow] = rowLower_[iRow];
289           } else if (rowUpper_[iRow] < 0.0) {
290                rowActivity_[iRow] = rowUpper_[iRow];
291           } else {
292                rowActivity_[iRow] = 0.0;
293           }
294           if (rowLower_[iRow] < -1.0e27)
295                rowLower_[iRow] = -COIN_DBL_MAX;
296           if (rowUpper_[iRow] > 1.0e27)
297                rowUpper_[iRow] = COIN_DBL_MAX;
298      }
299      for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
300           if (columnLower_[iColumn] > 0.0) {
301                columnActivity_[iColumn] = columnLower_[iColumn];
302           } else if (columnUpper_[iColumn] < 0.0) {
303                columnActivity_[iColumn] = columnUpper_[iColumn];
304           } else {
305                columnActivity_[iColumn] = 0.0;
306           }
307           if (columnLower_[iColumn] < -1.0e27)
308                columnLower_[iColumn] = -COIN_DBL_MAX;
309           if (columnUpper_[iColumn] > 1.0e27)
310                columnUpper_[iColumn] = COIN_DBL_MAX;
311      }
312 }
313 // This just loads up a row objective
setRowObjective(const double * rowObjective)314 void ClpModel::setRowObjective(const double * rowObjective)
315 {
316      delete [] rowObjective_;
317      rowObjective_ = ClpCopyOfArray(rowObjective, numberRows_);
318      whatsChanged_ = 0;
319 }
320 void
loadProblem(const ClpMatrixBase & matrix,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub,const double * rowObjective)321 ClpModel::loadProblem (  const ClpMatrixBase& matrix,
322                          const double* collb, const double* colub,
323                          const double* obj,
324                          const double* rowlb, const double* rowub,
325                          const double * rowObjective)
326 {
327      gutsOfLoadModel(matrix.getNumRows(), matrix.getNumCols(),
328                      collb, colub, obj, rowlb, rowub, rowObjective);
329      if (matrix.isColOrdered()) {
330           matrix_ = matrix.clone();
331      } else {
332           // later may want to keep as unknown class
333           CoinPackedMatrix matrix2;
334           matrix2.setExtraGap(0.0);
335           matrix2.setExtraMajor(0.0);
336           matrix2.reverseOrderedCopyOf(*matrix.getPackedMatrix());
337           matrix.releasePackedMatrix();
338           matrix_ = new ClpPackedMatrix(matrix2);
339      }
340      matrix_->setDimensions(numberRows_, numberColumns_);
341 }
342 void
loadProblem(const CoinPackedMatrix & matrix,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub,const double * rowObjective)343 ClpModel::loadProblem (  const CoinPackedMatrix& matrix,
344                          const double* collb, const double* colub,
345                          const double* obj,
346                          const double* rowlb, const double* rowub,
347                          const double * rowObjective)
348 {
349      ClpPackedMatrix* clpMatrix =
350           dynamic_cast< ClpPackedMatrix*>(matrix_);
351      bool special = (clpMatrix) ? clpMatrix->wantsSpecialColumnCopy() : false;
352      gutsOfLoadModel(matrix.getNumRows(), matrix.getNumCols(),
353                      collb, colub, obj, rowlb, rowub, rowObjective);
354      if (matrix.isColOrdered()) {
355           matrix_ = new ClpPackedMatrix(matrix);
356           if (special) {
357                clpMatrix = static_cast< ClpPackedMatrix*>(matrix_);
358                clpMatrix->makeSpecialColumnCopy();
359           }
360      } else {
361           CoinPackedMatrix matrix2;
362           matrix2.setExtraGap(0.0);
363           matrix2.setExtraMajor(0.0);
364           matrix2.reverseOrderedCopyOf(matrix);
365           matrix_ = new ClpPackedMatrix(matrix2);
366      }
367      matrix_->setDimensions(numberRows_, numberColumns_);
368 }
369 void
loadProblem(const int numcols,const int numrows,const CoinBigIndex * start,const int * index,const double * value,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub,const double * rowObjective)370 ClpModel::loadProblem (
371      const int numcols, const int numrows,
372      const CoinBigIndex* start, const int* index,
373      const double* value,
374      const double* collb, const double* colub,
375      const double* obj,
376      const double* rowlb, const double* rowub,
377      const double * rowObjective)
378 {
379      gutsOfLoadModel(numrows, numcols,
380                      collb, colub, obj, rowlb, rowub, rowObjective);
381      int numberElements = start ? start[numcols] : 0;
382      CoinPackedMatrix matrix(true, numrows, numrows ? numcols : 0, numberElements,
383                              value, index, start, NULL);
384      matrix_ = new ClpPackedMatrix(matrix);
385      matrix_->setDimensions(numberRows_, numberColumns_);
386 }
387 void
loadProblem(const int numcols,const int numrows,const CoinBigIndex * start,const int * index,const double * value,const int * length,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub,const double * rowObjective)388 ClpModel::loadProblem (
389      const int numcols, const int numrows,
390      const CoinBigIndex* start, const int* index,
391      const double* value, const int* length,
392      const double* collb, const double* colub,
393      const double* obj,
394      const double* rowlb, const double* rowub,
395      const double * rowObjective)
396 {
397      gutsOfLoadModel(numrows, numcols,
398                      collb, colub, obj, rowlb, rowub, rowObjective);
399      // Compute number of elements
400      int numberElements = 0;
401      int i;
402      for (i = 0; i < numcols; i++)
403           numberElements += length[i];
404      CoinPackedMatrix matrix(true, numrows, numcols, numberElements,
405                              value, index, start, length);
406      matrix_ = new ClpPackedMatrix(matrix);
407 }
408 #ifndef SLIM_NOIO
409 // This loads a model from a coinModel object - returns number of errors
410 int
loadProblem(CoinModel & modelObject,bool tryPlusMinusOne)411 ClpModel::loadProblem (  CoinModel & modelObject, bool tryPlusMinusOne)
412 {
413      if (modelObject.numberColumns() == 0 && modelObject.numberRows() == 0)
414           return 0;
415      int numberErrors = 0;
416      // Set arrays for normal use
417      double * rowLower = modelObject.rowLowerArray();
418      double * rowUpper = modelObject.rowUpperArray();
419      double * columnLower = modelObject.columnLowerArray();
420      double * columnUpper = modelObject.columnUpperArray();
421      double * objective = modelObject.objectiveArray();
422      int * integerType = modelObject.integerTypeArray();
423      double * associated = modelObject.associatedArray();
424      // If strings then do copies
425      if (modelObject.stringsExist()) {
426           numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper,
427                                                   objective, integerType, associated);
428      }
429      int numberRows = modelObject.numberRows();
430      int numberColumns = modelObject.numberColumns();
431      gutsOfLoadModel(numberRows, numberColumns,
432                      columnLower, columnUpper, objective, rowLower, rowUpper, NULL);
433      setObjectiveOffset(modelObject.objectiveOffset());
434      CoinBigIndex * startPositive = NULL;
435      CoinBigIndex * startNegative = NULL;
436      delete matrix_;
437      if (tryPlusMinusOne) {
438           startPositive = new CoinBigIndex[numberColumns+1];
439           startNegative = new CoinBigIndex[numberColumns];
440           modelObject.countPlusMinusOne(startPositive, startNegative, associated);
441           if (startPositive[0] < 0) {
442                // no good
443                tryPlusMinusOne = false;
444                delete [] startPositive;
445                delete [] startNegative;
446           }
447      }
448 #ifndef SLIM_CLP
449      if (!tryPlusMinusOne) {
450 #endif
451           CoinPackedMatrix matrix;
452           modelObject.createPackedMatrix(matrix, associated);
453           matrix_ = new ClpPackedMatrix(matrix);
454 #ifndef SLIM_CLP
455      } else {
456           // create +-1 matrix
457           CoinBigIndex size = startPositive[numberColumns];
458           int * indices = new int[size];
459           modelObject.createPlusMinusOne(startPositive, startNegative, indices,
460                                          associated);
461           // Get good object
462           ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
463           matrix->passInCopy(numberRows, numberColumns,
464                              true, indices, startPositive, startNegative);
465           matrix_ = matrix;
466      }
467 #endif
468 #ifndef CLP_NO_STD
469      // Do names if wanted
470      int numberItems;
471      numberItems = modelObject.rowNames()->numberItems();
472      if (numberItems) {
473           const char *const * rowNames = modelObject.rowNames()->names();
474           copyRowNames(rowNames, 0, numberItems);
475      }
476      numberItems = modelObject.columnNames()->numberItems();
477      if (numberItems) {
478           const char *const * columnNames = modelObject.columnNames()->names();
479           copyColumnNames(columnNames, 0, numberItems);
480      }
481 #endif
482      // Do integers if wanted
483      assert(integerType);
484      for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
485           if (integerType[iColumn])
486                setInteger(iColumn);
487      }
488      if (rowLower != modelObject.rowLowerArray() ||
489                columnLower != modelObject.columnLowerArray()) {
490           delete [] rowLower;
491           delete [] rowUpper;
492           delete [] columnLower;
493           delete [] columnUpper;
494           delete [] objective;
495           delete [] integerType;
496           delete [] associated;
497           if (numberErrors)
498                handler_->message(CLP_BAD_STRING_VALUES, messages_)
499                          << numberErrors
500                          << CoinMessageEol;
501      }
502      matrix_->setDimensions(numberRows_, numberColumns_);
503      return numberErrors;
504 }
505 #endif
506 void
getRowBound(int iRow,double & lower,double & upper) const507 ClpModel::getRowBound(int iRow, double& lower, double& upper) const
508 {
509      lower = -COIN_DBL_MAX;
510      upper = COIN_DBL_MAX;
511      if (rowUpper_)
512           upper = rowUpper_[iRow];
513      if (rowLower_)
514           lower = rowLower_[iRow];
515 }
516 //------------------------------------------------------------------
517 #ifndef NDEBUG
518 // For errors to make sure print to screen
519 // only called in debug mode
indexError(int index,std::string methodName)520 static void indexError(int index,
521                        std::string methodName)
522 {
523      std::cerr << "Illegal index " << index << " in ClpModel::" << methodName << std::endl;
524      throw CoinError("Illegal index", methodName, "ClpModel");
525 }
526 #endif
527 /* Set an objective function coefficient */
528 void
setObjectiveCoefficient(int elementIndex,double elementValue)529 ClpModel::setObjectiveCoefficient( int elementIndex, double elementValue )
530 {
531 #ifndef NDEBUG
532      if (elementIndex < 0 || elementIndex >= numberColumns_) {
533           indexError(elementIndex, "setObjectiveCoefficient");
534      }
535 #endif
536      objective()[elementIndex] = elementValue;
537      whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
538 }
539 /* Set a single row lower bound<br>
540    Use -DBL_MAX for -infinity. */
541 void
setRowLower(int elementIndex,double elementValue)542 ClpModel::setRowLower( int elementIndex, double elementValue )
543 {
544      if (elementValue < -1.0e27)
545           elementValue = -COIN_DBL_MAX;
546      rowLower_[elementIndex] = elementValue;
547      whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
548 }
549 
550 /* Set a single row upper bound<br>
551    Use DBL_MAX for infinity. */
552 void
setRowUpper(int elementIndex,double elementValue)553 ClpModel::setRowUpper( int elementIndex, double elementValue )
554 {
555      if (elementValue > 1.0e27)
556           elementValue = COIN_DBL_MAX;
557      rowUpper_[elementIndex] = elementValue;
558      whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
559 }
560 
561 /* Set a single row lower and upper bound */
562 void
setRowBounds(int elementIndex,double lower,double upper)563 ClpModel::setRowBounds( int elementIndex,
564                         double lower, double upper )
565 {
566      if (lower < -1.0e27)
567           lower = -COIN_DBL_MAX;
568      if (upper > 1.0e27)
569           upper = COIN_DBL_MAX;
570      CoinAssert (upper >= lower);
571      rowLower_[elementIndex] = lower;
572      rowUpper_[elementIndex] = upper;
573      whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
574 }
setRowSetBounds(const int * indexFirst,const int * indexLast,const double * boundList)575 void ClpModel::setRowSetBounds(const int* indexFirst,
576                                const int* indexLast,
577                                const double* boundList)
578 {
579 #ifndef NDEBUG
580      int n = numberRows_;
581 #endif
582      double * lower = rowLower_;
583      double * upper = rowUpper_;
584      whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
585      while (indexFirst != indexLast) {
586           const int iRow = *indexFirst++;
587 #ifndef NDEBUG
588           if (iRow < 0 || iRow >= n) {
589                indexError(iRow, "setRowSetBounds");
590           }
591 #endif
592           lower[iRow] = *boundList++;
593           upper[iRow] = *boundList++;
594           if (lower[iRow] < -1.0e27)
595                lower[iRow] = -COIN_DBL_MAX;
596           if (upper[iRow] > 1.0e27)
597                upper[iRow] = COIN_DBL_MAX;
598           CoinAssert (upper[iRow] >= lower[iRow]);
599      }
600 }
601 //-----------------------------------------------------------------------------
602 /* Set a single column lower bound<br>
603    Use -DBL_MAX for -infinity. */
604 void
setColumnLower(int elementIndex,double elementValue)605 ClpModel::setColumnLower( int elementIndex, double elementValue )
606 {
607 #ifndef NDEBUG
608      int n = numberColumns_;
609      if (elementIndex < 0 || elementIndex >= n) {
610           indexError(elementIndex, "setColumnLower");
611      }
612 #endif
613      if (elementValue < -1.0e27)
614           elementValue = -COIN_DBL_MAX;
615      columnLower_[elementIndex] = elementValue;
616      whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
617 }
618 
619 /* Set a single column upper bound<br>
620    Use DBL_MAX for infinity. */
621 void
setColumnUpper(int elementIndex,double elementValue)622 ClpModel::setColumnUpper( int elementIndex, double elementValue )
623 {
624 #ifndef NDEBUG
625      int n = numberColumns_;
626      if (elementIndex < 0 || elementIndex >= n) {
627           indexError(elementIndex, "setColumnUpper");
628      }
629 #endif
630      if (elementValue > 1.0e27)
631           elementValue = COIN_DBL_MAX;
632      columnUpper_[elementIndex] = elementValue;
633      whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
634 }
635 
636 /* Set a single column lower and upper bound */
637 void
setColumnBounds(int elementIndex,double lower,double upper)638 ClpModel::setColumnBounds( int elementIndex,
639                            double lower, double upper )
640 {
641 #ifndef NDEBUG
642      int n = numberColumns_;
643      if (elementIndex < 0 || elementIndex >= n) {
644           indexError(elementIndex, "setColumnBounds");
645      }
646 #endif
647      if (lower < -1.0e27)
648           lower = -COIN_DBL_MAX;
649      if (upper > 1.0e27)
650           upper = COIN_DBL_MAX;
651      columnLower_[elementIndex] = lower;
652      columnUpper_[elementIndex] = upper;
653      CoinAssert (upper >= lower);
654      whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
655 }
setColumnSetBounds(const int * indexFirst,const int * indexLast,const double * boundList)656 void ClpModel::setColumnSetBounds(const int* indexFirst,
657                                   const int* indexLast,
658                                   const double* boundList)
659 {
660      double * lower = columnLower_;
661      double * upper = columnUpper_;
662      whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
663 #ifndef NDEBUG
664      int n = numberColumns_;
665 #endif
666      while (indexFirst != indexLast) {
667           const int iColumn = *indexFirst++;
668 #ifndef NDEBUG
669           if (iColumn < 0 || iColumn >= n) {
670                indexError(iColumn, "setColumnSetBounds");
671           }
672 #endif
673           lower[iColumn] = *boundList++;
674           upper[iColumn] = *boundList++;
675           CoinAssert (upper[iColumn] >= lower[iColumn]);
676           if (lower[iColumn] < -1.0e27)
677                lower[iColumn] = -COIN_DBL_MAX;
678           if (upper[iColumn] > 1.0e27)
679                upper[iColumn] = COIN_DBL_MAX;
680      }
681 }
682 //-----------------------------------------------------------------------------
683 //#############################################################################
684 // Copy constructor.
ClpModel(const ClpModel & rhs,int scalingMode)685 ClpModel::ClpModel(const ClpModel &rhs, int scalingMode) :
686      optimizationDirection_(rhs.optimizationDirection_),
687      numberRows_(rhs.numberRows_),
688      numberColumns_(rhs.numberColumns_),
689      specialOptions_(rhs.specialOptions_),
690      maximumColumns_(-1),
691      maximumRows_(-1),
692      maximumInternalColumns_(-1),
693      maximumInternalRows_(-1),
694      savedRowScale_(NULL),
695      savedColumnScale_(NULL)
696 {
697      gutsOfCopy(rhs);
698      if (scalingMode >= 0 && matrix_ &&
699                matrix_->allElementsInRange(this, smallElement_, 1.0e20)) {
700           // really do scaling
701           scalingFlag_ = scalingMode;
702           setRowScale(NULL);
703           setColumnScale(NULL);
704           delete rowCopy_; // in case odd
705           rowCopy_ = NULL;
706           delete scaledMatrix_;
707           scaledMatrix_ = NULL;
708           if (scalingMode && !matrix_->scale(this)) {
709                // scaling worked - now apply
710                inverseRowScale_ = rowScale_ + numberRows_;
711                inverseColumnScale_ = columnScale_ + numberColumns_;
712                gutsOfScaling();
713                // pretend not scaled
714                scalingFlag_ = -scalingFlag_;
715           } else {
716                // not scaled
717                scalingFlag_ = 0;
718           }
719      }
720      randomNumberGenerator_.setSeed(1234567);
721 }
722 // Assignment operator. This copies the data
723 ClpModel &
operator =(const ClpModel & rhs)724 ClpModel::operator=(const ClpModel & rhs)
725 {
726      if (this != &rhs) {
727           if (defaultHandler_) {
728                //delete handler_;
729                //handler_ = NULL;
730           }
731           gutsOfDelete(1);
732           optimizationDirection_ = rhs.optimizationDirection_;
733           numberRows_ = rhs.numberRows_;
734           numberColumns_ = rhs.numberColumns_;
735           gutsOfCopy(rhs, -1);
736      }
737      return *this;
738 }
739 /* Does most of copying
740    If trueCopy 0 then just points to arrays
741    If -1 leaves as much as possible */
742 void
gutsOfCopy(const ClpModel & rhs,int trueCopy)743 ClpModel::gutsOfCopy(const ClpModel & rhs, int trueCopy)
744 {
745      defaultHandler_ = rhs.defaultHandler_;
746      if (trueCopy >= 0) {
747           if (defaultHandler_)
748                handler_ = new CoinMessageHandler(*rhs.handler_);
749           else
750                handler_ = rhs.handler_;
751           eventHandler_ = rhs.eventHandler_->clone();
752           randomNumberGenerator_ = rhs.randomNumberGenerator_;
753           messages_ = rhs.messages_;
754           coinMessages_ = rhs.coinMessages_;
755      } else {
756           if (!eventHandler_ && rhs.eventHandler_)
757                eventHandler_ = rhs.eventHandler_->clone();
758      }
759      intParam_[ClpMaxNumIteration] = rhs.intParam_[ClpMaxNumIteration];
760      intParam_[ClpMaxNumIterationHotStart] =
761           rhs.intParam_[ClpMaxNumIterationHotStart];
762      intParam_[ClpNameDiscipline] = rhs.intParam_[ClpNameDiscipline] ;
763 
764      dblParam_[ClpDualObjectiveLimit] = rhs.dblParam_[ClpDualObjectiveLimit];
765      dblParam_[ClpPrimalObjectiveLimit] = rhs.dblParam_[ClpPrimalObjectiveLimit];
766      dblParam_[ClpDualTolerance] = rhs.dblParam_[ClpDualTolerance];
767      dblParam_[ClpPrimalTolerance] = rhs.dblParam_[ClpPrimalTolerance];
768      dblParam_[ClpObjOffset] = rhs.dblParam_[ClpObjOffset];
769      dblParam_[ClpMaxSeconds] = rhs.dblParam_[ClpMaxSeconds];
770      dblParam_[ClpPresolveTolerance] = rhs.dblParam_[ClpPresolveTolerance];
771 #ifndef CLP_NO_STD
772 
773      strParam_[ClpProbName] = rhs.strParam_[ClpProbName];
774 #endif
775 
776      optimizationDirection_ = rhs.optimizationDirection_;
777      objectiveValue_ = rhs.objectiveValue_;
778      smallElement_ = rhs.smallElement_;
779      objectiveScale_ = rhs.objectiveScale_;
780      rhsScale_ = rhs.rhsScale_;
781      numberIterations_ = rhs.numberIterations_;
782      solveType_ = rhs.solveType_;
783      whatsChanged_ = rhs.whatsChanged_;
784      problemStatus_ = rhs.problemStatus_;
785      secondaryStatus_ = rhs.secondaryStatus_;
786      numberRows_ = rhs.numberRows_;
787      numberColumns_ = rhs.numberColumns_;
788      userPointer_ = rhs.userPointer_;
789      trustedUserPointer_ = rhs.trustedUserPointer_;
790      scalingFlag_ = rhs.scalingFlag_;
791      specialOptions_ = rhs.specialOptions_;
792      if (trueCopy) {
793 #ifndef CLP_NO_STD
794           lengthNames_ = rhs.lengthNames_;
795           if (lengthNames_) {
796                rowNames_ = rhs.rowNames_;
797                columnNames_ = rhs.columnNames_;
798           }
799 #endif
800           numberThreads_ = rhs.numberThreads_;
801           if (maximumRows_ < 0) {
802                specialOptions_ &= ~65536;
803                savedRowScale_ = NULL;
804                savedColumnScale_ = NULL;
805                integerType_ = CoinCopyOfArray(rhs.integerType_, numberColumns_);
806                rowActivity_ = ClpCopyOfArray(rhs.rowActivity_, numberRows_);
807                columnActivity_ = ClpCopyOfArray(rhs.columnActivity_, numberColumns_);
808                dual_ = ClpCopyOfArray(rhs.dual_, numberRows_);
809                reducedCost_ = ClpCopyOfArray(rhs.reducedCost_, numberColumns_);
810                rowLower_ = ClpCopyOfArray ( rhs.rowLower_, numberRows_ );
811                rowUpper_ = ClpCopyOfArray ( rhs.rowUpper_, numberRows_ );
812                columnLower_ = ClpCopyOfArray ( rhs.columnLower_, numberColumns_ );
813                columnUpper_ = ClpCopyOfArray ( rhs.columnUpper_, numberColumns_ );
814                rowScale_ = ClpCopyOfArray(rhs.rowScale_, numberRows_ * 2);
815                columnScale_ = ClpCopyOfArray(rhs.columnScale_, numberColumns_ * 2);
816                if (rhs.objective_)
817                     objective_  = rhs.objective_->clone();
818                else
819                     objective_ = NULL;
820                rowObjective_ = ClpCopyOfArray ( rhs.rowObjective_, numberRows_ );
821                status_ = ClpCopyOfArray( rhs.status_, numberColumns_ + numberRows_);
822                ray_ = NULL;
823                if (problemStatus_ == 1)
824                     ray_ = ClpCopyOfArray (rhs.ray_, numberRows_);
825                else if (problemStatus_ == 2)
826                     ray_ = ClpCopyOfArray (rhs.ray_, numberColumns_);
827                if (rhs.rowCopy_) {
828                     rowCopy_ = rhs.rowCopy_->clone();
829                } else {
830                     rowCopy_ = NULL;
831                }
832                if (rhs.scaledMatrix_) {
833                     scaledMatrix_ = new ClpPackedMatrix(*rhs.scaledMatrix_);
834                } else {
835                     scaledMatrix_ = NULL;
836                }
837                matrix_ = NULL;
838                if (rhs.matrix_) {
839                     matrix_ = rhs.matrix_->clone();
840                }
841           } else {
842                // This already has arrays - just copy
843                savedRowScale_ = NULL;
844                savedColumnScale_ = NULL;
845                startPermanentArrays();
846                if (rhs.integerType_) {
847                     assert (integerType_);
848                     ClpDisjointCopyN(rhs.integerType_, numberColumns_, integerType_);
849                } else {
850                     integerType_ = NULL;
851                }
852                if (rhs.rowActivity_) {
853                     ClpDisjointCopyN ( rhs.rowActivity_, numberRows_ ,
854                                        rowActivity_);
855                     ClpDisjointCopyN ( rhs.columnActivity_, numberColumns_ ,
856                                        columnActivity_);
857                     ClpDisjointCopyN ( rhs.dual_, numberRows_ ,
858                                        dual_);
859                     ClpDisjointCopyN ( rhs.reducedCost_, numberColumns_ ,
860                                        reducedCost_);
861                } else {
862                     rowActivity_ = NULL;
863                     columnActivity_ = NULL;
864                     dual_ = NULL;
865                     reducedCost_ = NULL;
866                }
867                ClpDisjointCopyN ( rhs.rowLower_, numberRows_, rowLower_ );
868                ClpDisjointCopyN ( rhs.rowUpper_, numberRows_, rowUpper_ );
869                ClpDisjointCopyN ( rhs.columnLower_, numberColumns_, columnLower_ );
870                assert ((specialOptions_ & 131072) == 0);
871                abort();
872                ClpDisjointCopyN ( rhs.columnUpper_, numberColumns_, columnUpper_ );
873                if (rhs.objective_) {
874                     abort(); //check if same
875                     objective_  = rhs.objective_->clone();
876                } else {
877                     objective_ = NULL;
878                }
879                assert (!rhs.rowObjective_);
880                ClpDisjointCopyN( rhs.status_, numberColumns_ + numberRows_, status_);
881                ray_ = NULL;
882                if (problemStatus_ == 1)
883                     ray_ = ClpCopyOfArray (rhs.ray_, numberRows_);
884                else if (problemStatus_ == 2)
885                     ray_ = ClpCopyOfArray (rhs.ray_, numberColumns_);
886                assert (!ray_);
887                delete rowCopy_;
888                if (rhs.rowCopy_) {
889                     rowCopy_ = rhs.rowCopy_->clone();
890                } else {
891                     rowCopy_ = NULL;
892                }
893                delete scaledMatrix_;
894                if (rhs.scaledMatrix_) {
895                     scaledMatrix_ = new ClpPackedMatrix(*rhs.scaledMatrix_);
896                } else {
897                     scaledMatrix_ = NULL;
898                }
899                delete matrix_;
900                matrix_ = NULL;
901                if (rhs.matrix_) {
902                     matrix_ = rhs.matrix_->clone();
903                }
904                if (rhs.savedRowScale_) {
905                     assert (savedRowScale_);
906                     assert (!rowScale_);
907                     ClpDisjointCopyN(rhs.savedRowScale_, 4 * maximumInternalRows_, savedRowScale_);
908                     ClpDisjointCopyN(rhs.savedColumnScale_, 4 * maximumInternalColumns_, savedColumnScale_);
909                } else {
910                     assert (!savedRowScale_);
911                     if (rowScale_) {
912                          ClpDisjointCopyN(rhs.rowScale_, numberRows_, rowScale_);
913                          ClpDisjointCopyN(rhs.columnScale_, numberColumns_, columnScale_);
914                     } else {
915                          rowScale_ = NULL;
916                          columnScale_ = NULL;
917                     }
918                }
919                abort(); // look at resizeDouble and resize
920           }
921      } else {
922           savedRowScale_ = rhs.savedRowScale_;
923           assert (!savedRowScale_);
924           savedColumnScale_ = rhs.savedColumnScale_;
925           rowActivity_ = rhs.rowActivity_;
926           columnActivity_ = rhs.columnActivity_;
927           dual_ = rhs.dual_;
928           reducedCost_ = rhs.reducedCost_;
929           rowLower_ = rhs.rowLower_;
930           rowUpper_ = rhs.rowUpper_;
931           objective_ = rhs.objective_;
932           rowObjective_ = rhs.rowObjective_;
933           columnLower_ = rhs.columnLower_;
934           columnUpper_ = rhs.columnUpper_;
935           matrix_ = rhs.matrix_;
936           rowCopy_ = NULL;
937           scaledMatrix_ = NULL;
938           ray_ = rhs.ray_;
939           //rowScale_ = rhs.rowScale_;
940           //columnScale_ = rhs.columnScale_;
941           lengthNames_ = 0;
942           numberThreads_ = rhs.numberThreads_;
943 #ifndef CLP_NO_STD
944           rowNames_ = std::vector<std::string> ();
945           columnNames_ = std::vector<std::string> ();
946 #endif
947           integerType_ = NULL;
948           status_ = rhs.status_;
949      }
950      inverseRowScale_ = NULL;
951      inverseColumnScale_ = NULL;
952 }
953 // Copy contents - resizing if necessary - otherwise re-use memory
954 void
copy(const ClpMatrixBase * from,ClpMatrixBase * & to)955 ClpModel::copy(const ClpMatrixBase * from, ClpMatrixBase * & to)
956 {
957      assert (from);
958      const ClpPackedMatrix * matrixFrom = (dynamic_cast<const ClpPackedMatrix*>(from));
959      ClpPackedMatrix * matrixTo = (dynamic_cast< ClpPackedMatrix*>(to));
960      if (matrixFrom && matrixTo) {
961           matrixTo->copy(matrixFrom);
962      } else {
963           delete to;
964           to =  from->clone();
965      }
966 #if 0
967      delete modelPtr_->matrix_;
968      if (continuousModel_->matrix_) {
969           modelPtr_->matrix_ = continuousModel_->matrix_->clone();
970      } else {
971           modelPtr_->matrix_ = NULL;
972      }
973 #endif
974 }
975 /* Borrow model.  This is so we dont have to copy large amounts
976    of data around.  It assumes a derived class wants to overwrite
977    an empty model with a real one - while it does an algorithm */
978 void
borrowModel(ClpModel & rhs)979 ClpModel::borrowModel(ClpModel & rhs)
980 {
981      if (defaultHandler_) {
982           delete handler_;
983           handler_ = NULL;
984      }
985      gutsOfDelete(1);
986      optimizationDirection_ = rhs.optimizationDirection_;
987      numberRows_ = rhs.numberRows_;
988      numberColumns_ = rhs.numberColumns_;
989      delete [] rhs.ray_;
990      rhs.ray_ = NULL;
991      // make sure scaled matrix not copied
992      ClpPackedMatrix * save = rhs.scaledMatrix_;
993      rhs.scaledMatrix_ = NULL;
994      delete scaledMatrix_;
995      scaledMatrix_ = NULL;
996      gutsOfCopy(rhs, 0);
997      rhs.scaledMatrix_ = save;
998      specialOptions_ = rhs.specialOptions_ & ~65536;
999      savedRowScale_ = NULL;
1000      savedColumnScale_ = NULL;
1001      inverseRowScale_ = NULL;
1002      inverseColumnScale_ = NULL;
1003 }
1004 // Return model - nulls all arrays so can be deleted safely
1005 void
returnModel(ClpModel & otherModel)1006 ClpModel::returnModel(ClpModel & otherModel)
1007 {
1008      otherModel.objectiveValue_ = objectiveValue_;
1009      otherModel.numberIterations_ = numberIterations_;
1010      otherModel.problemStatus_ = problemStatus_;
1011      otherModel.secondaryStatus_ = secondaryStatus_;
1012      rowActivity_ = NULL;
1013      columnActivity_ = NULL;
1014      dual_ = NULL;
1015      reducedCost_ = NULL;
1016      rowLower_ = NULL;
1017      rowUpper_ = NULL;
1018      objective_ = NULL;
1019      rowObjective_ = NULL;
1020      columnLower_ = NULL;
1021      columnUpper_ = NULL;
1022      matrix_ = NULL;
1023      if (rowCopy_ != otherModel.rowCopy_)
1024        delete rowCopy_;
1025      rowCopy_ = NULL;
1026      delete scaledMatrix_;
1027      scaledMatrix_ = NULL;
1028      delete [] otherModel.ray_;
1029      otherModel.ray_ = ray_;
1030      ray_ = NULL;
1031      if (rowScale_ && otherModel.rowScale_ != rowScale_) {
1032           delete [] rowScale_;
1033           delete [] columnScale_;
1034      }
1035      rowScale_ = NULL;
1036      columnScale_ = NULL;
1037      //rowScale_=NULL;
1038      //columnScale_=NULL;
1039      // do status
1040      if (otherModel.status_ != status_) {
1041           delete [] otherModel.status_;
1042           otherModel.status_ = status_;
1043      }
1044      status_ = NULL;
1045      if (defaultHandler_) {
1046           delete handler_;
1047           handler_ = NULL;
1048      }
1049      inverseRowScale_ = NULL;
1050      inverseColumnScale_ = NULL;
1051 }
1052 //#############################################################################
1053 // Parameter related methods
1054 //#############################################################################
1055 
1056 bool
setIntParam(ClpIntParam key,int value)1057 ClpModel::setIntParam(ClpIntParam key, int value)
1058 {
1059      switch (key) {
1060      case ClpMaxNumIteration:
1061           if (value < 0)
1062                return false;
1063           break;
1064      case ClpMaxNumIterationHotStart:
1065           if (value < 0)
1066                return false;
1067           break;
1068      case ClpNameDiscipline:
1069           if (value < 0)
1070                return false;
1071           break;
1072      default:
1073           return false;
1074      }
1075      intParam_[key] = value;
1076      return true;
1077 }
1078 
1079 //-----------------------------------------------------------------------------
1080 
1081 bool
setDblParam(ClpDblParam key,double value)1082 ClpModel::setDblParam(ClpDblParam key, double value)
1083 {
1084 
1085      switch (key) {
1086      case ClpDualObjectiveLimit:
1087           break;
1088 
1089      case ClpPrimalObjectiveLimit:
1090           break;
1091 
1092      case ClpDualTolerance:
1093           if (value <= 0.0 || value > 1.0e10)
1094                return false;
1095           break;
1096 
1097      case ClpPrimalTolerance:
1098           if (value <= 0.0 || value > 1.0e10)
1099                return false;
1100           break;
1101 
1102      case ClpObjOffset:
1103           break;
1104 
1105      case ClpMaxSeconds:
1106           if(value >= 0)
1107                value += CoinCpuTime();
1108           else
1109                value = -1.0;
1110           break;
1111 
1112      case ClpPresolveTolerance:
1113           if (value <= 0.0 || value > 1.0e10)
1114                return false;
1115           break;
1116 
1117      default:
1118           return false;
1119      }
1120      dblParam_[key] = value;
1121      return true;
1122 }
1123 
1124 //-----------------------------------------------------------------------------
1125 #ifndef CLP_NO_STD
1126 
1127 bool
setStrParam(ClpStrParam key,const std::string & value)1128 ClpModel::setStrParam(ClpStrParam key, const std::string & value)
1129 {
1130 
1131      switch (key) {
1132      case ClpProbName:
1133           break;
1134 
1135      default:
1136           return false;
1137      }
1138      strParam_[key] = value;
1139      return true;
1140 }
1141 #endif
1142 // Useful routines
1143 // Returns resized array and deletes incoming
resizeDouble(double * array,int size,int newSize,double fill,bool createArray)1144 double * resizeDouble(double * array , int size, int newSize, double fill,
1145                       bool createArray)
1146 {
1147      if ((array || createArray) && size < newSize) {
1148           int i;
1149           double * newArray = new double[newSize];
1150           if (array)
1151                CoinMemcpyN(array, CoinMin(newSize, size), newArray);
1152           delete [] array;
1153           array = newArray;
1154           for (i = size; i < newSize; i++)
1155                array[i] = fill;
1156      }
1157      return array;
1158 }
1159 // Returns resized array and updates size
deleteDouble(double * array,int size,int number,const int * which,int & newSize)1160 double * deleteDouble(double * array , int size,
1161                       int number, const int * which, int & newSize)
1162 {
1163      if (array) {
1164           int i ;
1165           char * deleted = new char[size];
1166           int numberDeleted = 0;
1167           CoinZeroN(deleted, size);
1168           for (i = 0; i < number; i++) {
1169                int j = which[i];
1170                if (j >= 0 && j < size && !deleted[j]) {
1171                     numberDeleted++;
1172                     deleted[j] = 1;
1173                }
1174           }
1175           newSize = size - numberDeleted;
1176           double * newArray = new double[newSize];
1177           int put = 0;
1178           for (i = 0; i < size; i++) {
1179                if (!deleted[i]) {
1180                     newArray[put++] = array[i];
1181                }
1182           }
1183           delete [] array;
1184           array = newArray;
1185           delete [] deleted;
1186      }
1187      return array;
1188 }
deleteChar(char * array,int size,int number,const int * which,int & newSize,bool ifDelete)1189 char * deleteChar(char * array , int size,
1190                   int number, const int * which, int & newSize,
1191                   bool ifDelete)
1192 {
1193      if (array) {
1194           int i ;
1195           char * deleted = new char[size];
1196           int numberDeleted = 0;
1197           CoinZeroN(deleted, size);
1198           for (i = 0; i < number; i++) {
1199                int j = which[i];
1200                if (j >= 0 && j < size && !deleted[j]) {
1201                     numberDeleted++;
1202                     deleted[j] = 1;
1203                }
1204           }
1205           newSize = size - numberDeleted;
1206           char * newArray = new char[newSize];
1207           int put = 0;
1208           for (i = 0; i < size; i++) {
1209                if (!deleted[i]) {
1210                     newArray[put++] = array[i];
1211                }
1212           }
1213           if (ifDelete)
1214                delete [] array;
1215           array = newArray;
1216           delete [] deleted;
1217      }
1218      return array;
1219 }
1220 // Create empty ClpPackedMatrix
1221 void
createEmptyMatrix()1222 ClpModel::createEmptyMatrix()
1223 {
1224      delete matrix_;
1225      whatsChanged_ = 0;
1226      CoinPackedMatrix matrix2;
1227      matrix_ = new ClpPackedMatrix(matrix2);
1228 }
1229 /* Really clean up matrix.
1230    a) eliminate all duplicate AND small elements in matrix
1231    b) remove all gaps and set extraGap_ and extraMajor_ to 0.0
1232    c) reallocate arrays and make max lengths equal to lengths
1233    d) orders elements
1234    returns number of elements eliminated or -1 if not ClpMatrix
1235 */
1236 int
cleanMatrix(double threshold)1237 ClpModel::cleanMatrix(double threshold)
1238 {
1239      ClpPackedMatrix * matrix = (dynamic_cast< ClpPackedMatrix*>(matrix_));
1240      if (matrix) {
1241           return matrix->getPackedMatrix()->cleanMatrix(threshold);
1242      } else {
1243           return -1;
1244      }
1245 }
1246 // Resizes
1247 void
resize(int newNumberRows,int newNumberColumns)1248 ClpModel::resize (int newNumberRows, int newNumberColumns)
1249 {
1250      if (newNumberRows == numberRows_ &&
1251                newNumberColumns == numberColumns_)
1252           return; // nothing to do
1253      whatsChanged_ = 0;
1254      int numberRows2 = newNumberRows;
1255      int numberColumns2 = newNumberColumns;
1256      if (numberRows2 < maximumRows_)
1257           numberRows2 = maximumRows_;
1258      if (numberColumns2 < maximumColumns_)
1259           numberColumns2 = maximumColumns_;
1260      if (numberRows2 > maximumRows_) {
1261           rowActivity_ = resizeDouble(rowActivity_, numberRows_,
1262                                       newNumberRows, 0.0, true);
1263           dual_ = resizeDouble(dual_, numberRows_,
1264                                newNumberRows, 0.0, true);
1265           rowObjective_ = resizeDouble(rowObjective_, numberRows_,
1266                                        newNumberRows, 0.0, false);
1267           rowLower_ = resizeDouble(rowLower_, numberRows_,
1268                                    newNumberRows, -COIN_DBL_MAX, true);
1269           rowUpper_ = resizeDouble(rowUpper_, numberRows_,
1270                                    newNumberRows, COIN_DBL_MAX, true);
1271      }
1272      if (numberColumns2 > maximumColumns_) {
1273           columnActivity_ = resizeDouble(columnActivity_, numberColumns_,
1274                                          newNumberColumns, 0.0, true);
1275           reducedCost_ = resizeDouble(reducedCost_, numberColumns_,
1276                                       newNumberColumns, 0.0, true);
1277      }
1278      if (savedRowScale_ && numberRows2 > maximumInternalRows_) {
1279           double * temp;
1280           temp = new double [4*newNumberRows];
1281           CoinFillN(temp, 4 * newNumberRows, 1.0);
1282           CoinMemcpyN(savedRowScale_, numberRows_, temp);
1283           CoinMemcpyN(savedRowScale_ + maximumInternalRows_, numberRows_, temp + newNumberRows);
1284           CoinMemcpyN(savedRowScale_ + 2 * maximumInternalRows_, numberRows_, temp + 2 * newNumberRows);
1285           CoinMemcpyN(savedRowScale_ + 3 * maximumInternalRows_, numberRows_, temp + 3 * newNumberRows);
1286           delete [] savedRowScale_;
1287           savedRowScale_ = temp;
1288      }
1289      if (savedColumnScale_ && numberColumns2 > maximumInternalColumns_) {
1290           double * temp;
1291           temp = new double [4*newNumberColumns];
1292           CoinFillN(temp, 4 * newNumberColumns, 1.0);
1293           CoinMemcpyN(savedColumnScale_, numberColumns_, temp);
1294           CoinMemcpyN(savedColumnScale_ + maximumInternalColumns_, numberColumns_, temp + newNumberColumns);
1295           CoinMemcpyN(savedColumnScale_ + 2 * maximumInternalColumns_, numberColumns_, temp + 2 * newNumberColumns);
1296           CoinMemcpyN(savedColumnScale_ + 3 * maximumInternalColumns_, numberColumns_, temp + 3 * newNumberColumns);
1297           delete [] savedColumnScale_;
1298           savedColumnScale_ = temp;
1299      }
1300      if (objective_ && numberColumns2 > maximumColumns_)
1301           objective_->resize(newNumberColumns);
1302      else if (!objective_)
1303           objective_ = new ClpLinearObjective(NULL, newNumberColumns);
1304      if (numberColumns2 > maximumColumns_) {
1305           columnLower_ = resizeDouble(columnLower_, numberColumns_,
1306                                       newNumberColumns, 0.0, true);
1307           columnUpper_ = resizeDouble(columnUpper_, numberColumns_,
1308                                       newNumberColumns, COIN_DBL_MAX, true);
1309      }
1310      if (newNumberRows < numberRows_) {
1311           int * which = new int[numberRows_-newNumberRows];
1312           int i;
1313           for (i = newNumberRows; i < numberRows_; i++)
1314                which[i-newNumberRows] = i;
1315           matrix_->deleteRows(numberRows_ - newNumberRows, which);
1316           delete [] which;
1317      }
1318      if (numberRows_ != newNumberRows || numberColumns_ != newNumberColumns) {
1319           // set state back to unknown
1320           problemStatus_ = -1;
1321           secondaryStatus_ = 0;
1322           delete [] ray_;
1323           ray_ = NULL;
1324      }
1325      setRowScale(NULL);
1326      setColumnScale(NULL);
1327      if (status_) {
1328           if (newNumberColumns + newNumberRows) {
1329                if (newNumberColumns + newNumberRows > maximumRows_ + maximumColumns_) {
1330                     unsigned char * tempC = new unsigned char [newNumberColumns+newNumberRows];
1331                     unsigned char * tempR = tempC + newNumberColumns;
1332                     memset(tempC, 3, newNumberColumns * sizeof(unsigned char));
1333                     memset(tempR, 1, newNumberRows * sizeof(unsigned char));
1334                     CoinMemcpyN(status_, CoinMin(newNumberColumns, numberColumns_), tempC);
1335                     CoinMemcpyN(status_ + numberColumns_, CoinMin(newNumberRows, numberRows_), tempR);
1336                     delete [] status_;
1337                     status_ = tempC;
1338                } else if (newNumberColumns < numberColumns_) {
1339                     memmove(status_ + newNumberColumns, status_ + numberColumns_,
1340                             newNumberRows);
1341                } else if (newNumberColumns > numberColumns_) {
1342                     memset(status_ + numberColumns_, 3, newNumberColumns - numberColumns_);
1343                     memmove(status_ + newNumberColumns, status_ + numberColumns_,
1344                             newNumberRows);
1345                }
1346           } else {
1347                // empty model - some systems don't like new [0]
1348                delete [] status_;
1349                status_ = NULL;
1350           }
1351      }
1352 #ifndef CLP_NO_STD
1353      if (lengthNames_) {
1354           // redo row and column names
1355           if (numberRows_ < newNumberRows) {
1356                rowNames_.resize(newNumberRows);
1357                lengthNames_ = CoinMax(lengthNames_, 8);
1358                char name[9];
1359                for (int iRow = numberRows_; iRow < newNumberRows; iRow++) {
1360                     sprintf(name, "R%7.7d", iRow);
1361                     rowNames_[iRow] = name;
1362                }
1363           }
1364           if (numberColumns_ < newNumberColumns) {
1365                columnNames_.resize(newNumberColumns);
1366                lengthNames_ = CoinMax(lengthNames_, 8);
1367                char name[9];
1368                for (int iColumn = numberColumns_; iColumn < newNumberColumns; iColumn++) {
1369                     sprintf(name, "C%7.7d", iColumn);
1370                     columnNames_[iColumn] = name;
1371                }
1372           }
1373      }
1374 #endif
1375      numberRows_ = newNumberRows;
1376      if (newNumberColumns < numberColumns_ && matrix_->getNumCols()) {
1377           int * which = new int[numberColumns_-newNumberColumns];
1378           int i;
1379           for (i = newNumberColumns; i < numberColumns_; i++)
1380                which[i-newNumberColumns] = i;
1381           matrix_->deleteCols(numberColumns_ - newNumberColumns, which);
1382           delete [] which;
1383      }
1384      if (integerType_ && numberColumns2 > maximumColumns_) {
1385           char * temp = new char [newNumberColumns];
1386           CoinZeroN(temp, newNumberColumns);
1387           CoinMemcpyN(integerType_,
1388                       CoinMin(newNumberColumns, numberColumns_), temp);
1389           delete [] integerType_;
1390           integerType_ = temp;
1391      }
1392      numberColumns_ = newNumberColumns;
1393      if ((specialOptions_ & 65536) != 0) {
1394           // leave until next create rim to up numbers
1395      }
1396      if (maximumRows_ >= 0) {
1397           if (numberRows_ > maximumRows_)
1398                COIN_DETAIL_PRINT(printf("resize %d rows, %d old maximum rows\n",
1399 					numberRows_, maximumRows_));
1400           maximumRows_ = CoinMax(maximumRows_, numberRows_);
1401           maximumColumns_ = CoinMax(maximumColumns_, numberColumns_);
1402      }
1403 }
1404 // Deletes rows
1405 void
deleteRows(int number,const int * which)1406 ClpModel::deleteRows(int number, const int * which)
1407 {
1408      if (!number)
1409           return; // nothing to do
1410      whatsChanged_ &= ~(1 + 2 + 4 + 8 + 16 + 32); // all except columns changed
1411      int newSize = 0;
1412      if (maximumRows_ < 0) {
1413           rowActivity_ = deleteDouble(rowActivity_, numberRows_,
1414                                       number, which, newSize);
1415           dual_ = deleteDouble(dual_, numberRows_,
1416                                number, which, newSize);
1417           rowObjective_ = deleteDouble(rowObjective_, numberRows_,
1418                                        number, which, newSize);
1419           rowLower_ = deleteDouble(rowLower_, numberRows_,
1420                                    number, which, newSize);
1421           rowUpper_ = deleteDouble(rowUpper_, numberRows_,
1422                                    number, which, newSize);
1423           if (matrix_->getNumRows())
1424                matrix_->deleteRows(number, which);
1425           //matrix_->removeGaps();
1426           // status
1427           if (status_) {
1428                if (numberColumns_ + newSize) {
1429                     unsigned char * tempR  = reinterpret_cast<unsigned char *>
1430                                              (deleteChar(reinterpret_cast<char *>(status_) + numberColumns_,
1431                                                          numberRows_,
1432                                                          number, which, newSize, false));
1433                     unsigned char * tempC = new unsigned char [numberColumns_+newSize];
1434                     CoinMemcpyN(status_, numberColumns_, tempC);
1435                     CoinMemcpyN(tempR, newSize, tempC + numberColumns_);
1436                     delete [] tempR;
1437                     delete [] status_;
1438                     status_ = tempC;
1439                } else {
1440                     // empty model - some systems don't like new [0]
1441                     delete [] status_;
1442                     status_ = NULL;
1443                }
1444           }
1445      } else {
1446           char * deleted = new char [numberRows_];
1447           int i;
1448           int numberDeleted = 0;
1449           CoinZeroN(deleted, numberRows_);
1450           for (i = 0; i < number; i++) {
1451                int j = which[i];
1452                if (j >= 0 && j < numberRows_ && !deleted[j]) {
1453                     numberDeleted++;
1454                     deleted[j] = 1;
1455                }
1456           }
1457           assert (!rowObjective_);
1458           unsigned char * status2 = status_ + numberColumns_;
1459           for (i = 0; i < numberRows_; i++) {
1460                if (!deleted[i]) {
1461                     rowActivity_[newSize] = rowActivity_[i];
1462                     dual_[newSize] = dual_[i];
1463                     rowLower_[newSize] = rowLower_[i];
1464                     rowUpper_[newSize] = rowUpper_[i];
1465                     status2[newSize] = status2[i];
1466                     newSize++;
1467                }
1468           }
1469           if (matrix_->getNumRows())
1470                matrix_->deleteRows(number, which);
1471           //matrix_->removeGaps();
1472           delete [] deleted;
1473      }
1474 #ifndef CLP_NO_STD
1475      // Now works if which out of order
1476      if (lengthNames_) {
1477           char * mark = new char [numberRows_];
1478           CoinZeroN(mark, numberRows_);
1479           int i;
1480           for (i = 0; i < number; i++)
1481                mark[which[i]] = 1;
1482           int k = 0;
1483           for ( i = 0; i < numberRows_; ++i) {
1484                if (!mark[i])
1485                     rowNames_[k++] = rowNames_[i];
1486           }
1487           rowNames_.erase(rowNames_.begin() + k, rowNames_.end());
1488           delete [] mark;
1489      }
1490 #endif
1491      numberRows_ = newSize;
1492      // set state back to unknown
1493      problemStatus_ = -1;
1494      secondaryStatus_ = 0;
1495      delete [] ray_;
1496      ray_ = NULL;
1497      if (savedRowScale_ != rowScale_) {
1498           delete [] rowScale_;
1499           delete [] columnScale_;
1500      }
1501      rowScale_ = NULL;
1502      columnScale_ = NULL;
1503      delete scaledMatrix_;
1504      scaledMatrix_ = NULL;
1505 }
1506 // Deletes columns
1507 void
deleteColumns(int number,const int * which)1508 ClpModel::deleteColumns(int number, const int * which)
1509 {
1510      if (!number)
1511           return; // nothing to do
1512      assert (maximumColumns_ < 0);
1513      whatsChanged_ &= ~(1 + 2 + 4 + 8 + 64 + 128 + 256); // all except rows changed
1514      int newSize = 0;
1515      columnActivity_ = deleteDouble(columnActivity_, numberColumns_,
1516                                     number, which, newSize);
1517      reducedCost_ = deleteDouble(reducedCost_, numberColumns_,
1518                                  number, which, newSize);
1519      objective_->deleteSome(number, which);
1520      columnLower_ = deleteDouble(columnLower_, numberColumns_,
1521                                  number, which, newSize);
1522      columnUpper_ = deleteDouble(columnUpper_, numberColumns_,
1523                                  number, which, newSize);
1524      // possible matrix is not full
1525      if (matrix_->getNumCols() < numberColumns_) {
1526           int * which2 = new int [number];
1527           int n = 0;
1528           int nMatrix = matrix_->getNumCols();
1529           for (int i = 0; i < number; i++) {
1530                if (which[i] < nMatrix)
1531                     which2[n++] = which[i];
1532           }
1533           matrix_->deleteCols(n, which2);
1534           delete [] which2;
1535      } else {
1536           matrix_->deleteCols(number, which);
1537      }
1538      //matrix_->removeGaps();
1539      // status
1540      if (status_) {
1541           if (numberRows_ + newSize) {
1542                unsigned char * tempC  = reinterpret_cast<unsigned char *>
1543                                         (deleteChar(reinterpret_cast<char *>(status_),
1544                                                     numberColumns_,
1545                                                     number, which, newSize, false));
1546                unsigned char * temp = new unsigned char [numberRows_+newSize];
1547                CoinMemcpyN(tempC, newSize, temp);
1548                CoinMemcpyN(status_ + numberColumns_,	numberRows_, temp + newSize);
1549                delete [] tempC;
1550                delete [] status_;
1551                status_ = temp;
1552           } else {
1553                // empty model - some systems don't like new [0]
1554                delete [] status_;
1555                status_ = NULL;
1556           }
1557      }
1558      integerType_ = deleteChar(integerType_, numberColumns_,
1559                                number, which, newSize, true);
1560 #ifndef CLP_NO_STD
1561      // Now works if which out of order
1562      if (lengthNames_) {
1563           char * mark = new char [numberColumns_];
1564           CoinZeroN(mark, numberColumns_);
1565           int i;
1566           for (i = 0; i < number; i++)
1567                mark[which[i]] = 1;
1568           int k = 0;
1569           for ( i = 0; i < numberColumns_; ++i) {
1570                if (!mark[i])
1571                     columnNames_[k++] = columnNames_[i];
1572           }
1573           columnNames_.erase(columnNames_.begin() + k, columnNames_.end());
1574           delete [] mark;
1575      }
1576 #endif
1577      numberColumns_ = newSize;
1578      // set state back to unknown
1579      problemStatus_ = -1;
1580      secondaryStatus_ = 0;
1581      delete [] ray_;
1582      ray_ = NULL;
1583      setRowScale(NULL);
1584      setColumnScale(NULL);
1585 }
1586 // Add one row
1587 void
addRow(int numberInRow,const int * columns,const double * elements,double rowLower,double rowUpper)1588 ClpModel::addRow(int numberInRow, const int * columns,
1589                  const double * elements, double rowLower, double rowUpper)
1590 {
1591      CoinBigIndex starts[2];
1592      starts[0] = 0;
1593      starts[1] = numberInRow;
1594      addRows(1, &rowLower, &rowUpper, starts, columns, elements);
1595 }
1596 // Add rows
1597 void
addRows(int number,const double * rowLower,const double * rowUpper,const CoinBigIndex * rowStarts,const int * columns,const double * elements)1598 ClpModel::addRows(int number, const double * rowLower,
1599                   const double * rowUpper,
1600                   const CoinBigIndex * rowStarts, const int * columns,
1601                   const double * elements)
1602 {
1603      if (number) {
1604           whatsChanged_ &= ~(1 + 2 + 8 + 16 + 32); // all except columns changed
1605           int numberRowsNow = numberRows_;
1606           resize(numberRowsNow + number, numberColumns_);
1607           double * lower = rowLower_ + numberRowsNow;
1608           double * upper = rowUpper_ + numberRowsNow;
1609           int iRow;
1610           if (rowLower) {
1611                for (iRow = 0; iRow < number; iRow++) {
1612                     double value = rowLower[iRow];
1613                     if (value < -1.0e20)
1614                          value = -COIN_DBL_MAX;
1615                     lower[iRow] = value;
1616                }
1617           } else {
1618                for (iRow = 0; iRow < number; iRow++) {
1619                     lower[iRow] = -COIN_DBL_MAX;
1620                }
1621           }
1622           if (rowUpper) {
1623                for (iRow = 0; iRow < number; iRow++) {
1624                     double value = rowUpper[iRow];
1625                     if (value > 1.0e20)
1626                          value = COIN_DBL_MAX;
1627                     upper[iRow] = value;
1628                }
1629           } else {
1630                for (iRow = 0; iRow < number; iRow++) {
1631                     upper[iRow] = COIN_DBL_MAX;
1632                }
1633           }
1634           // Deal with matrix
1635 
1636           delete rowCopy_;
1637           rowCopy_ = NULL;
1638           delete scaledMatrix_;
1639           scaledMatrix_ = NULL;
1640           if (!matrix_)
1641                createEmptyMatrix();
1642           setRowScale(NULL);
1643           setColumnScale(NULL);
1644 #ifndef CLP_NO_STD
1645           if (lengthNames_) {
1646                rowNames_.resize(numberRows_);
1647           }
1648 #endif
1649           if (rowStarts) {
1650                // Make sure matrix has correct number of columns
1651                matrix_->getPackedMatrix()->reserve(numberColumns_, 0, true);
1652                matrix_->appendMatrix(number, 0, rowStarts, columns, elements);
1653           }
1654      }
1655 }
1656 // Add rows
1657 void
addRows(int number,const double * rowLower,const double * rowUpper,const CoinBigIndex * rowStarts,const int * rowLengths,const int * columns,const double * elements)1658 ClpModel::addRows(int number, const double * rowLower,
1659                   const double * rowUpper,
1660                   const CoinBigIndex * rowStarts,
1661                   const int * rowLengths, const int * columns,
1662                   const double * elements)
1663 {
1664      if (number) {
1665           CoinBigIndex numberElements = 0;
1666           int iRow;
1667           for (iRow = 0; iRow < number; iRow++)
1668                numberElements += rowLengths[iRow];
1669           int * newStarts = new int[number+1];
1670           int * newIndex = new int[numberElements];
1671           double * newElements = new double[numberElements];
1672           numberElements = 0;
1673           newStarts[0] = 0;
1674           for (iRow = 0; iRow < number; iRow++) {
1675                int iStart = rowStarts[iRow];
1676                int length = rowLengths[iRow];
1677                CoinMemcpyN(columns + iStart, length, newIndex + numberElements);
1678                CoinMemcpyN(elements + iStart, length, newElements + numberElements);
1679                numberElements += length;
1680                newStarts[iRow+1] = numberElements;
1681           }
1682           addRows(number, rowLower, rowUpper,
1683                   newStarts, newIndex, newElements);
1684           delete [] newStarts;
1685           delete [] newIndex;
1686           delete [] newElements;
1687      }
1688 }
1689 #ifndef CLP_NO_VECTOR
1690 void
addRows(int number,const double * rowLower,const double * rowUpper,const CoinPackedVectorBase * const * rows)1691 ClpModel::addRows(int number, const double * rowLower,
1692                   const double * rowUpper,
1693                   const CoinPackedVectorBase * const * rows)
1694 {
1695      if (!number)
1696           return;
1697      whatsChanged_ &= ~(1 + 2 + 8 + 16 + 32); // all except columns changed
1698      int numberRowsNow = numberRows_;
1699      resize(numberRowsNow + number, numberColumns_);
1700      double * lower = rowLower_ + numberRowsNow;
1701      double * upper = rowUpper_ + numberRowsNow;
1702      int iRow;
1703      if (rowLower) {
1704           for (iRow = 0; iRow < number; iRow++) {
1705                double value = rowLower[iRow];
1706                if (value < -1.0e20)
1707                     value = -COIN_DBL_MAX;
1708                lower[iRow] = value;
1709           }
1710      } else {
1711           for (iRow = 0; iRow < number; iRow++) {
1712                lower[iRow] = -COIN_DBL_MAX;
1713           }
1714      }
1715      if (rowUpper) {
1716           for (iRow = 0; iRow < number; iRow++) {
1717                double value = rowUpper[iRow];
1718                if (value > 1.0e20)
1719                     value = COIN_DBL_MAX;
1720                upper[iRow] = value;
1721           }
1722      } else {
1723           for (iRow = 0; iRow < number; iRow++) {
1724                upper[iRow] = COIN_DBL_MAX;
1725           }
1726      }
1727      // Deal with matrix
1728 
1729      delete rowCopy_;
1730      rowCopy_ = NULL;
1731      delete scaledMatrix_;
1732      scaledMatrix_ = NULL;
1733      if (!matrix_)
1734           createEmptyMatrix();
1735      if (rows)
1736           matrix_->appendRows(number, rows);
1737      setRowScale(NULL);
1738      setColumnScale(NULL);
1739      if (lengthNames_) {
1740           rowNames_.resize(numberRows_);
1741      }
1742 }
1743 #endif
1744 #ifndef SLIM_CLP
1745 // Add rows from a build object
1746 int
addRows(const CoinBuild & buildObject,bool tryPlusMinusOne,bool checkDuplicates)1747 ClpModel::addRows(const CoinBuild & buildObject, bool tryPlusMinusOne, bool checkDuplicates)
1748 {
1749      CoinAssertHint (buildObject.type() == 0, "Looks as if both addRows and addCols being used"); // check correct
1750      int number = buildObject.numberRows();
1751      int numberErrors = 0;
1752      if (number) {
1753           CoinBigIndex size = 0;
1754           int iRow;
1755           double * lower = new double [number];
1756           double * upper = new double [number];
1757           if ((!matrix_ || !matrix_->getNumElements()) && tryPlusMinusOne) {
1758                // See if can be +-1
1759                for (iRow = 0; iRow < number; iRow++) {
1760                     const int * columns;
1761                     const double * elements;
1762                     int numberElements = buildObject.row(iRow, lower[iRow],
1763                                                          upper[iRow],
1764                                                          columns, elements);
1765                     for (int i = 0; i < numberElements; i++) {
1766                          // allow for zero elements
1767                          if (elements[i]) {
1768                               if (fabs(elements[i]) == 1.0) {
1769                                    size++;
1770                               } else {
1771                                    // bad
1772                                    tryPlusMinusOne = false;
1773                               }
1774                          }
1775                     }
1776                     if (!tryPlusMinusOne)
1777                          break;
1778                }
1779           } else {
1780                // Will add to whatever sort of matrix exists
1781                tryPlusMinusOne = false;
1782           }
1783           if (!tryPlusMinusOne) {
1784                CoinBigIndex numberElements = buildObject.numberElements();
1785                CoinBigIndex * starts = new CoinBigIndex [number+1];
1786                int * column = new int[numberElements];
1787                double * element = new double[numberElements];
1788                starts[0] = 0;
1789                numberElements = 0;
1790                for (iRow = 0; iRow < number; iRow++) {
1791                     const int * columns;
1792                     const double * elements;
1793                     int numberElementsThis = buildObject.row(iRow, lower[iRow], upper[iRow],
1794                                              columns, elements);
1795                     CoinMemcpyN(columns, numberElementsThis, column + numberElements);
1796                     CoinMemcpyN(elements, numberElementsThis, element + numberElements);
1797                     numberElements += numberElementsThis;
1798                     starts[iRow+1] = numberElements;
1799                }
1800                addRows(number, lower, upper, NULL);
1801                // make sure matrix has enough columns
1802                matrix_->setDimensions(-1, numberColumns_);
1803                numberErrors = matrix_->appendMatrix(number, 0, starts, column, element,
1804                                                     checkDuplicates ? numberColumns_ : -1);
1805                delete [] starts;
1806                delete [] column;
1807                delete [] element;
1808           } else {
1809                char * which = NULL; // for duplicates
1810                if (checkDuplicates) {
1811                     which = new char[numberColumns_];
1812                     CoinZeroN(which, numberColumns_);
1813                }
1814                // build +-1 matrix
1815                // arrays already filled in
1816                addRows(number, lower, upper, NULL);
1817                CoinBigIndex * startPositive = new CoinBigIndex [numberColumns_+1];
1818                CoinBigIndex * startNegative = new CoinBigIndex [numberColumns_];
1819                int * indices = new int [size];
1820                CoinZeroN(startPositive, numberColumns_);
1821                CoinZeroN(startNegative, numberColumns_);
1822                int maxColumn = -1;
1823                // need two passes
1824                for (iRow = 0; iRow < number; iRow++) {
1825                     const int * columns;
1826                     const double * elements;
1827                     int numberElements = buildObject.row(iRow, lower[iRow],
1828                                                          upper[iRow],
1829                                                          columns, elements);
1830                     for (int i = 0; i < numberElements; i++) {
1831                          int iColumn = columns[i];
1832                          if (checkDuplicates) {
1833                               if (iColumn >= numberColumns_) {
1834                                    if(which[iColumn])
1835                                         numberErrors++;
1836                                    else
1837                                         which[iColumn] = 1;
1838                               } else {
1839                                    numberErrors++;
1840                                    // and may as well switch off
1841                                    checkDuplicates = false;
1842                               }
1843                          }
1844                          maxColumn = CoinMax(maxColumn, iColumn);
1845                          if (elements[i] == 1.0) {
1846                               startPositive[iColumn]++;
1847                          } else if (elements[i] == -1.0) {
1848                               startNegative[iColumn]++;
1849                          }
1850                     }
1851                     if (checkDuplicates) {
1852                          for (int i = 0; i < numberElements; i++) {
1853                               int iColumn = columns[i];
1854                               which[iColumn] = 0;
1855                          }
1856                     }
1857                }
1858                // check size
1859                int numberColumns = maxColumn + 1;
1860                CoinAssertHint (numberColumns <= numberColumns_,
1861                                "rows having column indices >= numberColumns_");
1862                size = 0;
1863                int iColumn;
1864                for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1865                     CoinBigIndex n = startPositive[iColumn];
1866                     startPositive[iColumn] = size;
1867                     size += n;
1868                     n = startNegative[iColumn];
1869                     startNegative[iColumn] = size;
1870                     size += n;
1871                }
1872                startPositive[numberColumns_] = size;
1873                for (iRow = 0; iRow < number; iRow++) {
1874                     const int * columns;
1875                     const double * elements;
1876                     int numberElements = buildObject.row(iRow, lower[iRow],
1877                                                          upper[iRow],
1878                                                          columns, elements);
1879                     for (int i = 0; i < numberElements; i++) {
1880                          int iColumn = columns[i];
1881                          maxColumn = CoinMax(maxColumn, iColumn);
1882                          if (elements[i] == 1.0) {
1883                               CoinBigIndex position = startPositive[iColumn];
1884                               indices[position] = iRow;
1885                               startPositive[iColumn]++;
1886                          } else if (elements[i] == -1.0) {
1887                               CoinBigIndex position = startNegative[iColumn];
1888                               indices[position] = iRow;
1889                               startNegative[iColumn]++;
1890                          }
1891                     }
1892                }
1893                // and now redo starts
1894                for (iColumn = numberColumns_ - 1; iColumn >= 0; iColumn--) {
1895                     startPositive[iColumn+1] = startNegative[iColumn];
1896                     startNegative[iColumn] = startPositive[iColumn];
1897                }
1898                startPositive[0] = 0;
1899                for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1900                     CoinBigIndex start = startPositive[iColumn];
1901                     CoinBigIndex end = startNegative[iColumn];
1902                     std::sort(indices + start, indices + end);
1903                     start = startNegative[iColumn];
1904                     end = startPositive[iColumn+1];
1905                     std::sort(indices + start, indices + end);
1906                }
1907                // Get good object
1908                delete matrix_;
1909                ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
1910                matrix->passInCopy(numberRows_, numberColumns,
1911                                   true, indices, startPositive, startNegative);
1912                matrix_ = matrix;
1913                delete [] which;
1914           }
1915           delete [] lower;
1916           delete [] upper;
1917           // make sure matrix correct size
1918           matrix_->setDimensions(numberRows_, numberColumns_);
1919      }
1920      return numberErrors;
1921 }
1922 #endif
1923 #ifndef SLIM_NOIO
1924 // Add rows from a model object
1925 int
addRows(CoinModel & modelObject,bool tryPlusMinusOne,bool checkDuplicates)1926 ClpModel::addRows( CoinModel & modelObject, bool tryPlusMinusOne, bool checkDuplicates)
1927 {
1928      if (modelObject.numberElements() == 0)
1929           return 0;
1930      bool goodState = true;
1931      int numberErrors = 0;
1932      if (modelObject.columnLowerArray()) {
1933           // some column information exists
1934           int numberColumns2 = modelObject.numberColumns();
1935           const double * columnLower = modelObject.columnLowerArray();
1936           const double * columnUpper = modelObject.columnUpperArray();
1937           const double * objective = modelObject.objectiveArray();
1938           const int * integerType = modelObject.integerTypeArray();
1939           for (int i = 0; i < numberColumns2; i++) {
1940                if (columnLower[i] != 0.0)
1941                     goodState = false;
1942                if (columnUpper[i] != COIN_DBL_MAX)
1943                     goodState = false;
1944                if (objective[i] != 0.0)
1945                     goodState = false;
1946                if (integerType[i] != 0)
1947                     goodState = false;
1948           }
1949      }
1950      if (goodState) {
1951           // can do addRows
1952           // Set arrays for normal use
1953           double * rowLower = modelObject.rowLowerArray();
1954           double * rowUpper = modelObject.rowUpperArray();
1955           double * columnLower = modelObject.columnLowerArray();
1956           double * columnUpper = modelObject.columnUpperArray();
1957           double * objective = modelObject.objectiveArray();
1958           int * integerType = modelObject.integerTypeArray();
1959           double * associated = modelObject.associatedArray();
1960           // If strings then do copies
1961           if (modelObject.stringsExist()) {
1962                numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper,
1963                                                        objective, integerType, associated);
1964           }
1965           int numberRows = numberRows_; // save number of rows
1966           int numberRows2 = modelObject.numberRows();
1967           if (numberRows2 && !numberErrors) {
1968                CoinBigIndex * startPositive = NULL;
1969                CoinBigIndex * startNegative = NULL;
1970                int numberColumns = modelObject.numberColumns();
1971                if ((!matrix_ || !matrix_->getNumElements()) && !numberRows && tryPlusMinusOne) {
1972                     startPositive = new CoinBigIndex[numberColumns+1];
1973                     startNegative = new CoinBigIndex[numberColumns];
1974                     modelObject.countPlusMinusOne(startPositive, startNegative, associated);
1975                     if (startPositive[0] < 0) {
1976                          // no good
1977                          tryPlusMinusOne = false;
1978                          delete [] startPositive;
1979                          delete [] startNegative;
1980                     }
1981                } else {
1982                     // Will add to whatever sort of matrix exists
1983                     tryPlusMinusOne = false;
1984                }
1985                assert (rowLower);
1986                addRows(numberRows2, rowLower, rowUpper, NULL, NULL, NULL);
1987 #ifndef SLIM_CLP
1988                if (!tryPlusMinusOne) {
1989 #endif
1990                     CoinPackedMatrix matrix;
1991                     modelObject.createPackedMatrix(matrix, associated);
1992                     assert (!matrix.getExtraGap());
1993                     if (matrix_->getNumRows()) {
1994                          // matrix by rows
1995                          matrix.reverseOrdering();
1996                          assert (!matrix.getExtraGap());
1997                          const int * column = matrix.getIndices();
1998                          //const int * rowLength = matrix.getVectorLengths();
1999                          const CoinBigIndex * rowStart = matrix.getVectorStarts();
2000                          const double * element = matrix.getElements();
2001                          // make sure matrix has enough columns
2002                          matrix_->setDimensions(-1, numberColumns_);
2003                          numberErrors += matrix_->appendMatrix(numberRows2, 0, rowStart, column, element,
2004                                                                checkDuplicates ? numberColumns_ : -1);
2005                     } else {
2006                          delete matrix_;
2007                          matrix_ = new ClpPackedMatrix(matrix);
2008                     }
2009 #ifndef SLIM_CLP
2010                } else {
2011                     // create +-1 matrix
2012                     CoinBigIndex size = startPositive[numberColumns];
2013                     int * indices = new int[size];
2014                     modelObject.createPlusMinusOne(startPositive, startNegative, indices,
2015                                                    associated);
2016                     // Get good object
2017                     ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
2018                     matrix->passInCopy(numberRows2, numberColumns,
2019                                        true, indices, startPositive, startNegative);
2020                     delete matrix_;
2021                     matrix_ = matrix;
2022                }
2023                // Do names if wanted
2024                if (modelObject.rowNames()->numberItems()) {
2025                     const char *const * rowNames = modelObject.rowNames()->names();
2026                     copyRowNames(rowNames, numberRows, numberRows_);
2027                }
2028 #endif
2029           }
2030           if (rowLower != modelObject.rowLowerArray()) {
2031                delete [] rowLower;
2032                delete [] rowUpper;
2033                delete [] columnLower;
2034                delete [] columnUpper;
2035                delete [] objective;
2036                delete [] integerType;
2037                delete [] associated;
2038                if (numberErrors)
2039                     handler_->message(CLP_BAD_STRING_VALUES, messages_)
2040                               << numberErrors
2041                               << CoinMessageEol;
2042           }
2043           return numberErrors;
2044      } else {
2045           // not suitable for addRows
2046           handler_->message(CLP_COMPLICATED_MODEL, messages_)
2047                     << modelObject.numberRows()
2048                     << modelObject.numberColumns()
2049                     << CoinMessageEol;
2050           return -1;
2051      }
2052 }
2053 #endif
2054 // Add one column
2055 void
addColumn(int numberInColumn,const int * rows,const double * elements,double columnLower,double columnUpper,double objective)2056 ClpModel::addColumn(int numberInColumn,
2057                     const int * rows,
2058                     const double * elements,
2059                     double columnLower,
2060                     double  columnUpper,
2061                     double  objective)
2062 {
2063      CoinBigIndex starts[2];
2064      starts[0] = 0;
2065      starts[1] = numberInColumn;
2066      addColumns(1, &columnLower, &columnUpper, &objective, starts, rows, elements);
2067 }
2068 // Add columns
2069 void
addColumns(int number,const double * columnLower,const double * columnUpper,const double * objIn,const int * columnStarts,const int * rows,const double * elements)2070 ClpModel::addColumns(int number, const double * columnLower,
2071                      const double * columnUpper,
2072                      const double * objIn,
2073                      const int * columnStarts, const int * rows,
2074                      const double * elements)
2075 {
2076      // Create a list of CoinPackedVectors
2077      if (number) {
2078           whatsChanged_ &= ~(1 + 2 + 4 + 64 + 128 + 256); // all except rows changed
2079           int numberColumnsNow = numberColumns_;
2080           resize(numberRows_, numberColumnsNow + number);
2081           double * lower = columnLower_ + numberColumnsNow;
2082           double * upper = columnUpper_ + numberColumnsNow;
2083           double * obj = objective() + numberColumnsNow;
2084           int iColumn;
2085           if (columnLower) {
2086                for (iColumn = 0; iColumn < number; iColumn++) {
2087                     double value = columnLower[iColumn];
2088                     if (value < -1.0e20)
2089                          value = -COIN_DBL_MAX;
2090                     lower[iColumn] = value;
2091                }
2092           } else {
2093                for (iColumn = 0; iColumn < number; iColumn++) {
2094                     lower[iColumn] = 0.0;
2095                }
2096           }
2097           if (columnUpper) {
2098                for (iColumn = 0; iColumn < number; iColumn++) {
2099                     double value = columnUpper[iColumn];
2100                     if (value > 1.0e20)
2101                          value = COIN_DBL_MAX;
2102                     upper[iColumn] = value;
2103                }
2104           } else {
2105                for (iColumn = 0; iColumn < number; iColumn++) {
2106                     upper[iColumn] = COIN_DBL_MAX;
2107                }
2108           }
2109           if (objIn) {
2110                for (iColumn = 0; iColumn < number; iColumn++) {
2111                     obj[iColumn] = objIn[iColumn];
2112                }
2113           } else {
2114                for (iColumn = 0; iColumn < number; iColumn++) {
2115                     obj[iColumn] = 0.0;
2116                }
2117           }
2118           // Deal with matrix
2119 
2120           delete rowCopy_;
2121           rowCopy_ = NULL;
2122           delete scaledMatrix_;
2123           scaledMatrix_ = NULL;
2124           if (!matrix_)
2125                createEmptyMatrix();
2126           setRowScale(NULL);
2127           setColumnScale(NULL);
2128 #ifndef CLP_NO_STD
2129           if (lengthNames_) {
2130                columnNames_.resize(numberColumns_);
2131           }
2132 #endif
2133           //if (elements)
2134           matrix_->appendMatrix(number, 1, columnStarts, rows, elements);
2135      }
2136 }
2137 // Add columns
2138 void
addColumns(int number,const double * columnLower,const double * columnUpper,const double * objIn,const int * columnStarts,const int * columnLengths,const int * rows,const double * elements)2139 ClpModel::addColumns(int number, const double * columnLower,
2140                      const double * columnUpper,
2141                      const double * objIn,
2142                      const int * columnStarts,
2143                      const int * columnLengths, const int * rows,
2144                      const double * elements)
2145 {
2146      if (number) {
2147           CoinBigIndex numberElements = 0;
2148           int iColumn;
2149           for (iColumn = 0; iColumn < number; iColumn++)
2150                numberElements += columnLengths[iColumn];
2151           int * newStarts = new int[number+1];
2152           int * newIndex = new int[numberElements];
2153           double * newElements = new double[numberElements];
2154           numberElements = 0;
2155           newStarts[0] = 0;
2156           for (iColumn = 0; iColumn < number; iColumn++) {
2157                int iStart = columnStarts[iColumn];
2158                int length = columnLengths[iColumn];
2159                CoinMemcpyN(rows + iStart, length, newIndex + numberElements);
2160                CoinMemcpyN(elements + iStart, length, newElements + numberElements);
2161                numberElements += length;
2162                newStarts[iColumn+1] = numberElements;
2163           }
2164           addColumns(number, columnLower, columnUpper, objIn,
2165                      newStarts, newIndex, newElements);
2166           delete [] newStarts;
2167           delete [] newIndex;
2168           delete [] newElements;
2169      }
2170 }
2171 #ifndef CLP_NO_VECTOR
2172 void
addColumns(int number,const double * columnLower,const double * columnUpper,const double * objIn,const CoinPackedVectorBase * const * columns)2173 ClpModel::addColumns(int number, const double * columnLower,
2174                      const double * columnUpper,
2175                      const double * objIn,
2176                      const CoinPackedVectorBase * const * columns)
2177 {
2178      if (!number)
2179           return;
2180      whatsChanged_ &= ~(1 + 2 + 4 + 64 + 128 + 256); // all except rows changed
2181      int numberColumnsNow = numberColumns_;
2182      resize(numberRows_, numberColumnsNow + number);
2183      double * lower = columnLower_ + numberColumnsNow;
2184      double * upper = columnUpper_ + numberColumnsNow;
2185      double * obj = objective() + numberColumnsNow;
2186      int iColumn;
2187      if (columnLower) {
2188           for (iColumn = 0; iColumn < number; iColumn++) {
2189                double value = columnLower[iColumn];
2190                if (value < -1.0e20)
2191                     value = -COIN_DBL_MAX;
2192                lower[iColumn] = value;
2193           }
2194      } else {
2195           for (iColumn = 0; iColumn < number; iColumn++) {
2196                lower[iColumn] = 0.0;
2197           }
2198      }
2199      if (columnUpper) {
2200           for (iColumn = 0; iColumn < number; iColumn++) {
2201                double value = columnUpper[iColumn];
2202                if (value > 1.0e20)
2203                     value = COIN_DBL_MAX;
2204                upper[iColumn] = value;
2205           }
2206      } else {
2207           for (iColumn = 0; iColumn < number; iColumn++) {
2208                upper[iColumn] = COIN_DBL_MAX;
2209           }
2210      }
2211      if (objIn) {
2212           for (iColumn = 0; iColumn < number; iColumn++) {
2213                obj[iColumn] = objIn[iColumn];
2214           }
2215      } else {
2216           for (iColumn = 0; iColumn < number; iColumn++) {
2217                obj[iColumn] = 0.0;
2218           }
2219      }
2220      // Deal with matrix
2221 
2222      delete rowCopy_;
2223      rowCopy_ = NULL;
2224      delete scaledMatrix_;
2225      scaledMatrix_ = NULL;
2226      if (!matrix_)
2227           createEmptyMatrix();
2228      if (columns)
2229           matrix_->appendCols(number, columns);
2230      setRowScale(NULL);
2231      setColumnScale(NULL);
2232      if (lengthNames_) {
2233           columnNames_.resize(numberColumns_);
2234      }
2235 }
2236 #endif
2237 #ifndef SLIM_CLP
2238 // Add columns from a build object
2239 int
addColumns(const CoinBuild & buildObject,bool tryPlusMinusOne,bool checkDuplicates)2240 ClpModel::addColumns(const CoinBuild & buildObject, bool tryPlusMinusOne, bool checkDuplicates)
2241 {
2242      CoinAssertHint (buildObject.type() == 1, "Looks as if both addRows and addCols being used"); // check correct
2243      int number = buildObject.numberColumns();
2244      int numberErrors = 0;
2245      if (number) {
2246           CoinBigIndex size = 0;
2247           int maximumLength = 0;
2248           double * lower = new double [number];
2249           double * upper = new double [number];
2250           int iColumn;
2251           double * objective = new double [number];
2252           if ((!matrix_ || !matrix_->getNumElements()) && tryPlusMinusOne) {
2253                // See if can be +-1
2254                for (iColumn = 0; iColumn < number; iColumn++) {
2255                     const int * rows;
2256                     const double * elements;
2257                     int numberElements = buildObject.column(iColumn, lower[iColumn],
2258                                                             upper[iColumn], objective[iColumn],
2259                                                             rows, elements);
2260                     maximumLength = CoinMax(maximumLength, numberElements);
2261                     for (int i = 0; i < numberElements; i++) {
2262                          // allow for zero elements
2263                          if (elements[i]) {
2264                               if (fabs(elements[i]) == 1.0) {
2265                                    size++;
2266                               } else {
2267                                    // bad
2268                                    tryPlusMinusOne = false;
2269                               }
2270                          }
2271                     }
2272                     if (!tryPlusMinusOne)
2273                          break;
2274                }
2275           } else {
2276                // Will add to whatever sort of matrix exists
2277                tryPlusMinusOne = false;
2278           }
2279           if (!tryPlusMinusOne) {
2280                CoinBigIndex numberElements = buildObject.numberElements();
2281                CoinBigIndex * starts = new CoinBigIndex [number+1];
2282                int * row = new int[numberElements];
2283                double * element = new double[numberElements];
2284                starts[0] = 0;
2285                numberElements = 0;
2286                for (iColumn = 0; iColumn < number; iColumn++) {
2287                     const int * rows;
2288                     const double * elements;
2289                     int numberElementsThis = buildObject.column(iColumn, lower[iColumn], upper[iColumn],
2290                                              objective[iColumn], rows, elements);
2291                     CoinMemcpyN(rows, numberElementsThis, row + numberElements);
2292                     CoinMemcpyN(elements, numberElementsThis, element + numberElements);
2293                     numberElements += numberElementsThis;
2294                     starts[iColumn+1] = numberElements;
2295                }
2296                addColumns(number, lower, upper, objective, NULL);
2297                // make sure matrix has enough rows
2298                matrix_->setDimensions(numberRows_, -1);
2299                numberErrors = matrix_->appendMatrix(number, 1, starts, row, element,
2300                                                     checkDuplicates ? numberRows_ : -1);
2301                delete [] starts;
2302                delete [] row;
2303                delete [] element;
2304           } else {
2305                // arrays already filled in
2306                addColumns(number, lower, upper, objective, NULL);
2307                char * which = NULL; // for duplicates
2308                if (checkDuplicates) {
2309                     which = new char[numberRows_];
2310                     CoinZeroN(which, numberRows_);
2311                }
2312                // build +-1 matrix
2313                CoinBigIndex * startPositive = new CoinBigIndex [number+1];
2314                CoinBigIndex * startNegative = new CoinBigIndex [number];
2315                int * indices = new int [size];
2316                int * neg = new int[maximumLength];
2317                startPositive[0] = 0;
2318                size = 0;
2319                int maxRow = -1;
2320                for (iColumn = 0; iColumn < number; iColumn++) {
2321                     const int * rows;
2322                     const double * elements;
2323                     int numberElements = buildObject.column(iColumn, lower[iColumn],
2324                                                             upper[iColumn], objective[iColumn],
2325                                                             rows, elements);
2326                     int nNeg = 0;
2327                     CoinBigIndex start = size;
2328                     for (int i = 0; i < numberElements; i++) {
2329                          int iRow = rows[i];
2330                          if (checkDuplicates) {
2331                               if (iRow >= numberRows_) {
2332                                    if(which[iRow])
2333                                         numberErrors++;
2334                                    else
2335                                         which[iRow] = 1;
2336                               } else {
2337                                    numberErrors++;
2338                                    // and may as well switch off
2339                                    checkDuplicates = false;
2340                               }
2341                          }
2342                          maxRow = CoinMax(maxRow, iRow);
2343                          if (elements[i] == 1.0) {
2344                               indices[size++] = iRow;
2345                          } else if (elements[i] == -1.0) {
2346                               neg[nNeg++] = iRow;
2347                          }
2348                     }
2349                     std::sort(indices + start, indices + size);
2350                     std::sort(neg, neg + nNeg);
2351                     startNegative[iColumn] = size;
2352                     CoinMemcpyN(neg, nNeg, indices + size);
2353                     size += nNeg;
2354                     startPositive[iColumn+1] = size;
2355                }
2356                delete [] neg;
2357                // check size
2358                assert (maxRow + 1 <= numberRows_);
2359                // Get good object
2360                delete matrix_;
2361                ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
2362                matrix->passInCopy(numberRows_, number, true, indices, startPositive, startNegative);
2363                matrix_ = matrix;
2364                delete [] which;
2365           }
2366           delete [] objective;
2367           delete [] lower;
2368           delete [] upper;
2369      }
2370      return 0;
2371 }
2372 #endif
2373 #ifndef SLIM_NOIO
2374 // Add columns from a model object
2375 int
addColumns(CoinModel & modelObject,bool tryPlusMinusOne,bool checkDuplicates)2376 ClpModel::addColumns( CoinModel & modelObject, bool tryPlusMinusOne, bool checkDuplicates)
2377 {
2378      if (modelObject.numberElements() == 0)
2379           return 0;
2380      bool goodState = true;
2381      if (modelObject.rowLowerArray()) {
2382           // some row information exists
2383           int numberRows2 = modelObject.numberRows();
2384           const double * rowLower = modelObject.rowLowerArray();
2385           const double * rowUpper = modelObject.rowUpperArray();
2386           for (int i = 0; i < numberRows2; i++) {
2387                if (rowLower[i] != -COIN_DBL_MAX)
2388                     goodState = false;
2389                if (rowUpper[i] != COIN_DBL_MAX)
2390                     goodState = false;
2391           }
2392      }
2393      if (goodState) {
2394           // can do addColumns
2395           int numberErrors = 0;
2396           // Set arrays for normal use
2397           double * rowLower = modelObject.rowLowerArray();
2398           double * rowUpper = modelObject.rowUpperArray();
2399           double * columnLower = modelObject.columnLowerArray();
2400           double * columnUpper = modelObject.columnUpperArray();
2401           double * objective = modelObject.objectiveArray();
2402           int * integerType = modelObject.integerTypeArray();
2403           double * associated = modelObject.associatedArray();
2404           // If strings then do copies
2405           if (modelObject.stringsExist()) {
2406                numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper,
2407                                                        objective, integerType, associated);
2408           }
2409           int numberColumns = numberColumns_; // save number of columns
2410           int numberColumns2 = modelObject.numberColumns();
2411           if (numberColumns2 && !numberErrors) {
2412                CoinBigIndex * startPositive = NULL;
2413                CoinBigIndex * startNegative = NULL;
2414                if ((!matrix_ || !matrix_->getNumElements()) && !numberColumns && tryPlusMinusOne) {
2415                     startPositive = new CoinBigIndex[numberColumns2+1];
2416                     startNegative = new CoinBigIndex[numberColumns2];
2417                     modelObject.countPlusMinusOne(startPositive, startNegative, associated);
2418                     if (startPositive[0] < 0) {
2419                          // no good
2420                          tryPlusMinusOne = false;
2421                          delete [] startPositive;
2422                          delete [] startNegative;
2423                     }
2424                } else {
2425                     // Will add to whatever sort of matrix exists
2426                     tryPlusMinusOne = false;
2427                }
2428                assert (columnLower);
2429                addColumns(numberColumns2, columnLower, columnUpper, objective, NULL, NULL, NULL);
2430 #ifndef SLIM_CLP
2431                if (!tryPlusMinusOne) {
2432 #endif
2433                     CoinPackedMatrix matrix;
2434                     modelObject.createPackedMatrix(matrix, associated);
2435                     assert (!matrix.getExtraGap());
2436                     if (matrix_->getNumCols()) {
2437                          const int * row = matrix.getIndices();
2438                          //const int * columnLength = matrix.getVectorLengths();
2439                          const CoinBigIndex * columnStart = matrix.getVectorStarts();
2440                          const double * element = matrix.getElements();
2441                          // make sure matrix has enough rows
2442                          matrix_->setDimensions(numberRows_, -1);
2443                          numberErrors += matrix_->appendMatrix(numberColumns2, 1, columnStart, row, element,
2444                                                                checkDuplicates ? numberRows_ : -1);
2445                     } else {
2446                          delete matrix_;
2447                          matrix_ = new ClpPackedMatrix(matrix);
2448                     }
2449 #ifndef SLIM_CLP
2450                } else {
2451                     // create +-1 matrix
2452                     CoinBigIndex size = startPositive[numberColumns2];
2453                     int * indices = new int[size];
2454                     modelObject.createPlusMinusOne(startPositive, startNegative, indices,
2455                                                    associated);
2456                     // Get good object
2457                     ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
2458                     matrix->passInCopy(numberRows_, numberColumns2,
2459                                        true, indices, startPositive, startNegative);
2460                     delete matrix_;
2461                     matrix_ = matrix;
2462                }
2463 #endif
2464 #ifndef CLP_NO_STD
2465                // Do names if wanted
2466                if (modelObject.columnNames()->numberItems()) {
2467                     const char *const * columnNames = modelObject.columnNames()->names();
2468                     copyColumnNames(columnNames, numberColumns, numberColumns_);
2469                }
2470 #endif
2471                // Do integers if wanted
2472                assert(integerType);
2473                for (int iColumn = 0; iColumn < numberColumns2; iColumn++) {
2474                     if (integerType[iColumn])
2475                          setInteger(iColumn + numberColumns);
2476                }
2477           }
2478           if (columnLower != modelObject.columnLowerArray()) {
2479                delete [] rowLower;
2480                delete [] rowUpper;
2481                delete [] columnLower;
2482                delete [] columnUpper;
2483                delete [] objective;
2484                delete [] integerType;
2485                delete [] associated;
2486                if (numberErrors)
2487                     handler_->message(CLP_BAD_STRING_VALUES, messages_)
2488                               << numberErrors
2489                               << CoinMessageEol;
2490           }
2491           return numberErrors;
2492      } else {
2493           // not suitable for addColumns
2494           handler_->message(CLP_COMPLICATED_MODEL, messages_)
2495                     << modelObject.numberRows()
2496                     << modelObject.numberColumns()
2497                     << CoinMessageEol;
2498           return -1;
2499      }
2500 }
2501 #endif
2502 // chgRowLower
2503 void
chgRowLower(const double * rowLower)2504 ClpModel::chgRowLower(const double * rowLower)
2505 {
2506      int numberRows = numberRows_;
2507      int iRow;
2508      whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2509      if (rowLower) {
2510           for (iRow = 0; iRow < numberRows; iRow++) {
2511                double value = rowLower[iRow];
2512                if (value < -1.0e20)
2513                     value = -COIN_DBL_MAX;
2514                rowLower_[iRow] = value;
2515           }
2516      } else {
2517           for (iRow = 0; iRow < numberRows; iRow++) {
2518                rowLower_[iRow] = -COIN_DBL_MAX;
2519           }
2520      }
2521 }
2522 // chgRowUpper
2523 void
chgRowUpper(const double * rowUpper)2524 ClpModel::chgRowUpper(const double * rowUpper)
2525 {
2526      whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2527      int numberRows = numberRows_;
2528      int iRow;
2529      if (rowUpper) {
2530           for (iRow = 0; iRow < numberRows; iRow++) {
2531                double value = rowUpper[iRow];
2532                if (value > 1.0e20)
2533                     value = COIN_DBL_MAX;
2534                rowUpper_[iRow] = value;
2535           }
2536      } else {
2537           for (iRow = 0; iRow < numberRows; iRow++) {
2538                rowUpper_[iRow] = COIN_DBL_MAX;
2539           }
2540      }
2541 }
2542 // chgColumnLower
2543 void
chgColumnLower(const double * columnLower)2544 ClpModel::chgColumnLower(const double * columnLower)
2545 {
2546      whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2547      int numberColumns = numberColumns_;
2548      int iColumn;
2549      if (columnLower) {
2550           for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2551                double value = columnLower[iColumn];
2552                if (value < -1.0e20)
2553                     value = -COIN_DBL_MAX;
2554                columnLower_[iColumn] = value;
2555           }
2556      } else {
2557           for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2558                columnLower_[iColumn] = 0.0;
2559           }
2560      }
2561 }
2562 // chgColumnUpper
2563 void
chgColumnUpper(const double * columnUpper)2564 ClpModel::chgColumnUpper(const double * columnUpper)
2565 {
2566      whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2567      int numberColumns = numberColumns_;
2568      int iColumn;
2569      if (columnUpper) {
2570           for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2571                double value = columnUpper[iColumn];
2572                if (value > 1.0e20)
2573                     value = COIN_DBL_MAX;
2574                columnUpper_[iColumn] = value;
2575           }
2576      } else {
2577           for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2578                columnUpper_[iColumn] = COIN_DBL_MAX;
2579           }
2580      }
2581 }
2582 // chgObjCoefficients
2583 void
chgObjCoefficients(const double * objIn)2584 ClpModel::chgObjCoefficients(const double * objIn)
2585 {
2586      whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2587      double * obj = objective();
2588      int numberColumns = numberColumns_;
2589      int iColumn;
2590      if (objIn) {
2591           for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2592                obj[iColumn] = objIn[iColumn];
2593           }
2594      } else {
2595           for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2596                obj[iColumn] = 0.0;
2597           }
2598      }
2599 }
2600 // Infeasibility/unbounded ray (NULL returned if none/wrong)
2601 double *
infeasibilityRay() const2602 ClpModel::infeasibilityRay() const
2603 {
2604      double * array = NULL;
2605      if (problemStatus_ == 1 && ray_) {
2606           array = ClpCopyOfArray(ray_, numberRows_);
2607 #ifndef CLP_NO_SWAP_SIGN
2608           // swap signs to be consistent with norm
2609           for (int i = 0; i < numberRows_; i++)
2610                array[i] = -array[i];
2611 #endif
2612 #if 0
2613           // clean up
2614           double largest = 1.0e-30;
2615           double smallest = COIN_DBL_MAX;
2616           int i;
2617           for (i = 0; i < numberRows_; i++) {
2618                double value = fabs(array[i]);
2619                smallest = CoinMin(smallest, value);
2620                largest = CoinMax(largest, value);
2621           }
2622 #endif
2623      }
2624      return array;
2625 }
2626 double *
unboundedRay() const2627 ClpModel::unboundedRay() const
2628 {
2629      double * array = NULL;
2630      if (problemStatus_ == 2)
2631           array = ClpCopyOfArray(ray_, numberColumns_);
2632      return array;
2633 }
2634 void
setMaximumIterations(int value)2635 ClpModel::setMaximumIterations(int value)
2636 {
2637      if(value >= 0)
2638           intParam_[ClpMaxNumIteration] = value;
2639 }
2640 void
setMaximumSeconds(double value)2641 ClpModel::setMaximumSeconds(double value)
2642 {
2643      if(value >= 0)
2644           dblParam_[ClpMaxSeconds] = value + CoinCpuTime();
2645      else
2646           dblParam_[ClpMaxSeconds] = -1.0;
2647 }
2648 // Returns true if hit maximum iterations (or time)
2649 bool
hitMaximumIterations() const2650 ClpModel::hitMaximumIterations() const
2651 {
2652      // replaced - compiler error? bool hitMax= (numberIterations_>=maximumIterations());
2653      bool hitMax = (numberIterations_ >= intParam_[ClpMaxNumIteration]);
2654      if (dblParam_[ClpMaxSeconds] >= 0.0 && !hitMax) {
2655           hitMax = (CoinCpuTime() >= dblParam_[ClpMaxSeconds]);
2656      }
2657      return hitMax;
2658 }
2659 // On stopped - sets secondary status
2660 void
onStopped()2661 ClpModel::onStopped()
2662 {
2663      if (problemStatus_ == 3) {
2664           secondaryStatus_ = 0;
2665           if (CoinCpuTime() >= dblParam_[ClpMaxSeconds] && dblParam_[ClpMaxSeconds] >= 0.0)
2666                secondaryStatus_ = 9;
2667      }
2668 }
2669 // Pass in Message handler (not deleted at end)
2670 void
passInMessageHandler(CoinMessageHandler * handler)2671 ClpModel::passInMessageHandler(CoinMessageHandler * handler)
2672 {
2673      if (defaultHandler_)
2674           delete handler_;
2675      defaultHandler_ = false;
2676      handler_ = handler;
2677 }
2678 // Pass in Message handler (not deleted at end) and return current
2679 CoinMessageHandler *
pushMessageHandler(CoinMessageHandler * handler,bool & oldDefault)2680 ClpModel::pushMessageHandler(CoinMessageHandler * handler,
2681                              bool & oldDefault)
2682 {
2683      CoinMessageHandler * returnValue = handler_;
2684      oldDefault = defaultHandler_;
2685      defaultHandler_ = false;
2686      handler_ = handler;
2687      return returnValue;
2688 }
2689 // back to previous message handler
2690 void
popMessageHandler(CoinMessageHandler * oldHandler,bool oldDefault)2691 ClpModel::popMessageHandler(CoinMessageHandler * oldHandler, bool oldDefault)
2692 {
2693      if (defaultHandler_)
2694           delete handler_;
2695      defaultHandler_ = oldDefault;
2696      handler_ = oldHandler;
2697 }
2698 // Set language
2699 void
newLanguage(CoinMessages::Language language)2700 ClpModel::newLanguage(CoinMessages::Language language)
2701 {
2702      messages_ = ClpMessage(language);
2703 }
2704 #ifndef SLIM_NOIO
2705 // Read an mps file from the given filename
2706 int
readMps(const char * fileName,bool keepNames,bool ignoreErrors)2707 ClpModel::readMps(const char *fileName,
2708                   bool keepNames,
2709                   bool ignoreErrors)
2710 {
2711      if (!strcmp(fileName, "-") || !strcmp(fileName, "stdin")) {
2712           // stdin
2713      } else {
2714           std::string name = fileName;
2715           bool readable = fileCoinReadable(name);
2716           if (!readable) {
2717                handler_->message(CLP_UNABLE_OPEN, messages_)
2718                          << fileName << CoinMessageEol;
2719                return -1;
2720           }
2721      }
2722      CoinMpsIO m;
2723      m.passInMessageHandler(handler_);
2724      *m.messagesPointer() = coinMessages();
2725      bool savePrefix = m.messageHandler()->prefix();
2726      m.messageHandler()->setPrefix(handler_->prefix());
2727      m.setSmallElementValue(CoinMax(smallElement_, m.getSmallElementValue()));
2728      double time1 = CoinCpuTime(), time2;
2729      int status = 0;
2730      try {
2731           status = m.readMps(fileName, "");
2732      } catch (CoinError e) {
2733           e.print();
2734           status = -1;
2735      }
2736      m.messageHandler()->setPrefix(savePrefix);
2737      if (!status || (ignoreErrors && (status > 0 && status < 100000))) {
2738           loadProblem(*m.getMatrixByCol(),
2739                       m.getColLower(), m.getColUpper(),
2740                       m.getObjCoefficients(),
2741                       m.getRowLower(), m.getRowUpper());
2742           if (m.integerColumns()) {
2743                integerType_ = new char[numberColumns_];
2744                CoinMemcpyN(m.integerColumns(), numberColumns_, integerType_);
2745           } else {
2746                integerType_ = NULL;
2747           }
2748 #ifndef SLIM_CLP
2749           // get quadratic part
2750           if (m.reader()->whichSection (  ) == COIN_QUAD_SECTION ) {
2751                int * start = NULL;
2752                int * column = NULL;
2753                double * element = NULL;
2754                status = m.readQuadraticMps(NULL, start, column, element, 2);
2755                if (!status || ignoreErrors)
2756                     loadQuadraticObjective(numberColumns_, start, column, element);
2757                delete [] start;
2758                delete [] column;
2759                delete [] element;
2760           }
2761 #endif
2762 #ifndef CLP_NO_STD
2763           // set problem name
2764           setStrParam(ClpProbName, m.getProblemName());
2765           // do names
2766           if (keepNames) {
2767                unsigned int maxLength = 0;
2768                int iRow;
2769                rowNames_ = std::vector<std::string> ();
2770                columnNames_ = std::vector<std::string> ();
2771                rowNames_.reserve(numberRows_);
2772                for (iRow = 0; iRow < numberRows_; iRow++) {
2773                     const char * name = m.rowName(iRow);
2774                     maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
2775                     rowNames_.push_back(name);
2776                }
2777 
2778                int iColumn;
2779                columnNames_.reserve(numberColumns_);
2780                for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2781                     const char * name = m.columnName(iColumn);
2782                     maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
2783                     columnNames_.push_back(name);
2784                }
2785                lengthNames_ = static_cast<int> (maxLength);
2786           } else {
2787                lengthNames_ = 0;
2788           }
2789 #endif
2790           setDblParam(ClpObjOffset, m.objectiveOffset());
2791           time2 = CoinCpuTime();
2792           handler_->message(CLP_IMPORT_RESULT, messages_)
2793                     << fileName
2794                     << time2 - time1 << CoinMessageEol;
2795      } else {
2796           // errors
2797           handler_->message(CLP_IMPORT_ERRORS, messages_)
2798                     << status << fileName << CoinMessageEol;
2799      }
2800 
2801      return status;
2802 }
2803 // Read GMPL files from the given filenames
2804 int
readGMPL(const char * fileName,const char * dataName,bool keepNames)2805 ClpModel::readGMPL(const char *fileName, const char * dataName,
2806                    bool keepNames)
2807 {
2808      FILE *fp = fopen(fileName, "r");
2809      if (fp) {
2810           // can open - lets go for it
2811           fclose(fp);
2812           if (dataName) {
2813                fp = fopen(dataName, "r");
2814                if (fp) {
2815                     fclose(fp);
2816                } else {
2817                     handler_->message(CLP_UNABLE_OPEN, messages_)
2818                               << dataName << CoinMessageEol;
2819                     return -1;
2820                }
2821           }
2822      } else {
2823           handler_->message(CLP_UNABLE_OPEN, messages_)
2824                     << fileName << CoinMessageEol;
2825           return -1;
2826      }
2827      CoinMpsIO m;
2828      m.passInMessageHandler(handler_);
2829      *m.messagesPointer() = coinMessages();
2830      bool savePrefix = m.messageHandler()->prefix();
2831      m.messageHandler()->setPrefix(handler_->prefix());
2832      double time1 = CoinCpuTime(), time2;
2833      int status = m.readGMPL(fileName, dataName, keepNames);
2834      m.messageHandler()->setPrefix(savePrefix);
2835      if (!status) {
2836           loadProblem(*m.getMatrixByCol(),
2837                       m.getColLower(), m.getColUpper(),
2838                       m.getObjCoefficients(),
2839                       m.getRowLower(), m.getRowUpper());
2840           if (m.integerColumns()) {
2841                integerType_ = new char[numberColumns_];
2842                CoinMemcpyN(m.integerColumns(), numberColumns_, integerType_);
2843           } else {
2844                integerType_ = NULL;
2845           }
2846 #ifndef CLP_NO_STD
2847           // set problem name
2848           setStrParam(ClpProbName, m.getProblemName());
2849           // do names
2850           if (keepNames) {
2851                unsigned int maxLength = 0;
2852                int iRow;
2853                rowNames_ = std::vector<std::string> ();
2854                columnNames_ = std::vector<std::string> ();
2855                rowNames_.reserve(numberRows_);
2856                for (iRow = 0; iRow < numberRows_; iRow++) {
2857                     const char * name = m.rowName(iRow);
2858                     maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
2859                     rowNames_.push_back(name);
2860                }
2861 
2862                int iColumn;
2863                columnNames_.reserve(numberColumns_);
2864                for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2865                     const char * name = m.columnName(iColumn);
2866                     maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
2867                     columnNames_.push_back(name);
2868                }
2869                lengthNames_ = static_cast<int> (maxLength);
2870           } else {
2871                lengthNames_ = 0;
2872           }
2873 #endif
2874           setDblParam(ClpObjOffset, m.objectiveOffset());
2875           time2 = CoinCpuTime();
2876           handler_->message(CLP_IMPORT_RESULT, messages_)
2877                     << fileName
2878                     << time2 - time1 << CoinMessageEol;
2879      } else {
2880           // errors
2881           handler_->message(CLP_IMPORT_ERRORS, messages_)
2882                     << status << fileName << CoinMessageEol;
2883      }
2884      return status;
2885 }
2886 #endif
isPrimalObjectiveLimitReached() const2887 bool ClpModel::isPrimalObjectiveLimitReached() const
2888 {
2889      double limit = 0.0;
2890      getDblParam(ClpPrimalObjectiveLimit, limit);
2891      if (limit > 1e30) {
2892           // was not ever set
2893           return false;
2894      }
2895 
2896      const double obj = objectiveValue();
2897      const double maxmin = optimizationDirection();
2898 
2899      if (problemStatus_ == 0) // optimal
2900           return maxmin > 0 ? (obj < limit) /*minim*/ : (-obj < limit) /*maxim*/;
2901      else if (problemStatus_ == 2)
2902           return true;
2903      else
2904           return false;
2905 }
2906 
isDualObjectiveLimitReached() const2907 bool ClpModel::isDualObjectiveLimitReached() const
2908 {
2909 
2910      double limit = 0.0;
2911      getDblParam(ClpDualObjectiveLimit, limit);
2912      if (limit > 1e30) {
2913           // was not ever set
2914           return false;
2915      }
2916 
2917      const double obj = objectiveValue();
2918      const double maxmin = optimizationDirection();
2919 
2920      if (problemStatus_ == 0) // optimal
2921           return maxmin > 0 ? (obj > limit) /*minim*/ : (-obj > limit) /*maxim*/;
2922      else if (problemStatus_ == 1)
2923           return true;
2924      else
2925           return false;
2926 
2927 }
2928 void
copyInIntegerInformation(const char * information)2929 ClpModel::copyInIntegerInformation(const char * information)
2930 {
2931      delete [] integerType_;
2932      if (information) {
2933           integerType_ = new char[numberColumns_];
2934           CoinMemcpyN(information, numberColumns_, integerType_);
2935      } else {
2936           integerType_ = NULL;
2937      }
2938 }
2939 void
setContinuous(int index)2940 ClpModel::setContinuous(int index)
2941 {
2942 
2943      if (integerType_) {
2944 #ifndef NDEBUG
2945           if (index < 0 || index >= numberColumns_) {
2946                indexError(index, "setContinuous");
2947           }
2948 #endif
2949           integerType_[index] = 0;
2950      }
2951 }
2952 //-----------------------------------------------------------------------------
2953 void
setInteger(int index)2954 ClpModel::setInteger(int index)
2955 {
2956      if (!integerType_) {
2957           integerType_ = new char[numberColumns_];
2958           CoinZeroN ( integerType_, numberColumns_);
2959      }
2960 #ifndef NDEBUG
2961      if (index < 0 || index >= numberColumns_) {
2962           indexError(index, "setInteger");
2963      }
2964 #endif
2965      integerType_[index] = 1;
2966 }
2967 /* Return true if the index-th variable is an integer variable */
2968 bool
isInteger(int index) const2969 ClpModel::isInteger(int index) const
2970 {
2971      if (!integerType_) {
2972           return false;
2973      } else {
2974 #ifndef NDEBUG
2975           if (index < 0 || index >= numberColumns_) {
2976                indexError(index, "isInteger");
2977           }
2978 #endif
2979           return (integerType_[index] != 0);
2980      }
2981 }
2982 #ifndef CLP_NO_STD
2983 // Drops names - makes lengthnames 0 and names empty
2984 void
dropNames()2985 ClpModel::dropNames()
2986 {
2987      lengthNames_ = 0;
2988      rowNames_ = std::vector<std::string> ();
2989      columnNames_ = std::vector<std::string> ();
2990 }
2991 #endif
2992 // Drop integer informations
2993 void
deleteIntegerInformation()2994 ClpModel::deleteIntegerInformation()
2995 {
2996      delete [] integerType_;
2997      integerType_ = NULL;
2998 }
2999 /* Return copy of status array (char[numberRows+numberColumns]),
3000    use delete [] */
3001 unsigned char *
statusCopy() const3002 ClpModel::statusCopy() const
3003 {
3004      return ClpCopyOfArray(status_, numberRows_ + numberColumns_);
3005 }
3006 // Copy in status vector
3007 void
copyinStatus(const unsigned char * statusArray)3008 ClpModel::copyinStatus(const unsigned char * statusArray)
3009 {
3010      delete [] status_;
3011      if (statusArray) {
3012           status_ = new unsigned char [numberRows_+numberColumns_];
3013           CoinMemcpyN(statusArray, (numberRows_ + numberColumns_), status_);
3014      } else {
3015           status_ = NULL;
3016      }
3017 }
3018 #ifndef SLIM_CLP
3019 // Load up quadratic objective
3020 void
loadQuadraticObjective(const int numberColumns,const CoinBigIndex * start,const int * column,const double * element)3021 ClpModel::loadQuadraticObjective(const int numberColumns, const CoinBigIndex * start,
3022                                  const int * column, const double * element)
3023 {
3024      whatsChanged_ = 0; // Use ClpSimplex stuff to keep
3025      CoinAssert (numberColumns == numberColumns_);
3026      assert ((dynamic_cast< ClpLinearObjective*>(objective_)));
3027      double offset;
3028      ClpObjective * obj = new ClpQuadraticObjective(objective_->gradient(NULL, NULL, offset, false),
3029                numberColumns,
3030                start, column, element);
3031      delete objective_;
3032      objective_ = obj;
3033 
3034 }
3035 void
loadQuadraticObjective(const CoinPackedMatrix & matrix)3036 ClpModel::loadQuadraticObjective (  const CoinPackedMatrix& matrix)
3037 {
3038      whatsChanged_ = 0; // Use ClpSimplex stuff to keep
3039      CoinAssert (matrix.getNumCols() == numberColumns_);
3040      assert ((dynamic_cast< ClpLinearObjective*>(objective_)));
3041      double offset;
3042      ClpQuadraticObjective * obj =
3043           new ClpQuadraticObjective(objective_->gradient(NULL, NULL, offset, false),
3044                                     numberColumns_,
3045                                     NULL, NULL, NULL);
3046      delete objective_;
3047      objective_ = obj;
3048      obj->loadQuadraticObjective(matrix);
3049 }
3050 // Get rid of quadratic objective
3051 void
deleteQuadraticObjective()3052 ClpModel::deleteQuadraticObjective()
3053 {
3054      whatsChanged_ = 0; // Use ClpSimplex stuff to keep
3055      ClpQuadraticObjective * obj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
3056      if (obj)
3057           obj->deleteQuadraticObjective();
3058 }
3059 #endif
3060 void
setObjective(ClpObjective * objective)3061 ClpModel::setObjective(ClpObjective * objective)
3062 {
3063      whatsChanged_ = 0; // Use ClpSimplex stuff to keep
3064      delete objective_;
3065      objective_ = objective->clone();
3066 }
3067 // Returns resized array and updates size
whichDouble(double * array,int number,const int * which)3068 double * whichDouble(double * array , int number, const int * which)
3069 {
3070      double * newArray = NULL;
3071      if (array && number) {
3072           int i ;
3073           newArray = new double[number];
3074           for (i = 0; i < number; i++)
3075                newArray[i] = array[which[i]];
3076      }
3077      return newArray;
3078 }
whichChar(char * array,int number,const int * which)3079 char * whichChar(char * array , int number, const int * which)
3080 {
3081      char * newArray = NULL;
3082      if (array && number) {
3083           int i ;
3084           newArray = new char[number];
3085           for (i = 0; i < number; i++)
3086                newArray[i] = array[which[i]];
3087      }
3088      return newArray;
3089 }
whichUnsignedChar(unsigned char * array,int number,const int * which)3090 unsigned char * whichUnsignedChar(unsigned char * array ,
3091                                   int number, const int * which)
3092 {
3093      unsigned char * newArray = NULL;
3094      if (array && number) {
3095           int i ;
3096           newArray = new unsigned char[number];
3097           for (i = 0; i < number; i++)
3098                newArray[i] = array[which[i]];
3099      }
3100      return newArray;
3101 }
3102 // Replace Clp Matrix (current is not deleted)
3103 void
replaceMatrix(ClpMatrixBase * matrix,bool deleteCurrent)3104 ClpModel::replaceMatrix( ClpMatrixBase * matrix, bool deleteCurrent)
3105 {
3106      if (deleteCurrent)
3107           delete matrix_;
3108      matrix_ = matrix;
3109      whatsChanged_ = 0; // Too big a change
3110 }
3111 // Subproblem constructor
ClpModel(const ClpModel * rhs,int numberRows,const int * whichRow,int numberColumns,const int * whichColumn,bool dropNames,bool dropIntegers)3112 ClpModel::ClpModel ( const ClpModel * rhs,
3113                      int numberRows, const int * whichRow,
3114                      int numberColumns, const int * whichColumn,
3115                      bool dropNames, bool dropIntegers)
3116      :  specialOptions_(rhs->specialOptions_),
3117         maximumColumns_(-1),
3118         maximumRows_(-1),
3119         maximumInternalColumns_(-1),
3120         maximumInternalRows_(-1),
3121         savedRowScale_(NULL),
3122         savedColumnScale_(NULL)
3123 {
3124      defaultHandler_ = rhs->defaultHandler_;
3125      if (defaultHandler_)
3126           handler_ = new CoinMessageHandler(*rhs->handler_);
3127      else
3128           handler_ = rhs->handler_;
3129      eventHandler_ = rhs->eventHandler_->clone();
3130      randomNumberGenerator_ = rhs->randomNumberGenerator_;
3131      messages_ = rhs->messages_;
3132      coinMessages_ = rhs->coinMessages_;
3133      maximumColumns_ = -1;
3134      maximumRows_ = -1;
3135      maximumInternalColumns_ = -1;
3136      maximumInternalRows_ = -1;
3137      savedRowScale_ = NULL;
3138      savedColumnScale_ = NULL;
3139      intParam_[ClpMaxNumIteration] = rhs->intParam_[ClpMaxNumIteration];
3140      intParam_[ClpMaxNumIterationHotStart] =
3141           rhs->intParam_[ClpMaxNumIterationHotStart];
3142      intParam_[ClpNameDiscipline] = rhs->intParam_[ClpNameDiscipline] ;
3143 
3144      dblParam_[ClpDualObjectiveLimit] = rhs->dblParam_[ClpDualObjectiveLimit];
3145      dblParam_[ClpPrimalObjectiveLimit] = rhs->dblParam_[ClpPrimalObjectiveLimit];
3146      dblParam_[ClpDualTolerance] = rhs->dblParam_[ClpDualTolerance];
3147      dblParam_[ClpPrimalTolerance] = rhs->dblParam_[ClpPrimalTolerance];
3148      dblParam_[ClpObjOffset] = rhs->dblParam_[ClpObjOffset];
3149      dblParam_[ClpMaxSeconds] = rhs->dblParam_[ClpMaxSeconds];
3150      dblParam_[ClpPresolveTolerance] = rhs->dblParam_[ClpPresolveTolerance];
3151 #ifndef CLP_NO_STD
3152      strParam_[ClpProbName] = rhs->strParam_[ClpProbName];
3153 #endif
3154      specialOptions_ = rhs->specialOptions_;
3155      optimizationDirection_ = rhs->optimizationDirection_;
3156      objectiveValue_ = rhs->objectiveValue_;
3157      smallElement_ = rhs->smallElement_;
3158      objectiveScale_ = rhs->objectiveScale_;
3159      rhsScale_ = rhs->rhsScale_;
3160      numberIterations_ = rhs->numberIterations_;
3161      solveType_ = rhs->solveType_;
3162      whatsChanged_ = 0; // Too big a change
3163      problemStatus_ = rhs->problemStatus_;
3164      secondaryStatus_ = rhs->secondaryStatus_;
3165      // check valid lists
3166      int numberBad = 0;
3167      int i;
3168      for (i = 0; i < numberRows; i++)
3169           if (whichRow[i] < 0 || whichRow[i] >= rhs->numberRows_)
3170                numberBad++;
3171      CoinAssertHint(!numberBad, "Bad row list for subproblem constructor");
3172      numberBad = 0;
3173      for (i = 0; i < numberColumns; i++)
3174           if (whichColumn[i] < 0 || whichColumn[i] >= rhs->numberColumns_)
3175                numberBad++;
3176      CoinAssertHint(!numberBad, "Bad Column list for subproblem constructor");
3177      numberRows_ = numberRows;
3178      numberColumns_ = numberColumns;
3179      userPointer_ = rhs->userPointer_;
3180      trustedUserPointer_ = rhs->trustedUserPointer_;
3181      numberThreads_ = 0;
3182 #ifndef CLP_NO_STD
3183      if (!dropNames) {
3184           unsigned int maxLength = 0;
3185           int iRow;
3186           rowNames_ = std::vector<std::string> ();
3187           columnNames_ = std::vector<std::string> ();
3188           rowNames_.reserve(numberRows_);
3189           for (iRow = 0; iRow < numberRows_; iRow++) {
3190                rowNames_.push_back(rhs->rowNames_[whichRow[iRow]]);
3191                maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(rowNames_[iRow].c_str())));
3192           }
3193           int iColumn;
3194           columnNames_.reserve(numberColumns_);
3195           for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
3196                columnNames_.push_back(rhs->columnNames_[whichColumn[iColumn]]);
3197                maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(columnNames_[iColumn].c_str())));
3198           }
3199           lengthNames_ = static_cast<int> (maxLength);
3200      } else {
3201           lengthNames_ = 0;
3202           rowNames_ = std::vector<std::string> ();
3203           columnNames_ = std::vector<std::string> ();
3204      }
3205 #endif
3206      if (rhs->integerType_ && !dropIntegers) {
3207           integerType_ = whichChar(rhs->integerType_, numberColumns, whichColumn);
3208      } else {
3209           integerType_ = NULL;
3210      }
3211      if (rhs->rowActivity_) {
3212           rowActivity_ = whichDouble(rhs->rowActivity_, numberRows, whichRow);
3213           dual_ = whichDouble(rhs->dual_, numberRows, whichRow);
3214           columnActivity_ = whichDouble(rhs->columnActivity_, numberColumns,
3215                                         whichColumn);
3216           reducedCost_ = whichDouble(rhs->reducedCost_, numberColumns,
3217                                      whichColumn);
3218      } else {
3219           rowActivity_ = NULL;
3220           columnActivity_ = NULL;
3221           dual_ = NULL;
3222           reducedCost_ = NULL;
3223      }
3224      rowLower_ = whichDouble(rhs->rowLower_, numberRows, whichRow);
3225      rowUpper_ = whichDouble(rhs->rowUpper_, numberRows, whichRow);
3226      columnLower_ = whichDouble(rhs->columnLower_, numberColumns, whichColumn);
3227      columnUpper_ = whichDouble(rhs->columnUpper_, numberColumns, whichColumn);
3228      if (rhs->objective_)
3229           objective_  = rhs->objective_->subsetClone(numberColumns, whichColumn);
3230      else
3231           objective_ = NULL;
3232      rowObjective_ = whichDouble(rhs->rowObjective_, numberRows, whichRow);
3233      // status has to be done in two stages
3234      if (rhs->status_) {
3235        status_ = new unsigned char[numberColumns_+numberRows_];
3236        unsigned char * rowStatus = whichUnsignedChar(rhs->status_ + rhs->numberColumns_,
3237 						     numberRows_, whichRow);
3238        unsigned char * columnStatus = whichUnsignedChar(rhs->status_,
3239 							numberColumns_, whichColumn);
3240        CoinMemcpyN(rowStatus, numberRows_, status_ + numberColumns_);
3241        delete [] rowStatus;
3242        CoinMemcpyN(columnStatus, numberColumns_, status_);
3243        delete [] columnStatus;
3244      } else {
3245        status_=NULL;
3246      }
3247      ray_ = NULL;
3248      if (problemStatus_ == 1)
3249           ray_ = whichDouble (rhs->ray_, numberRows, whichRow);
3250      else if (problemStatus_ == 2)
3251           ray_ = whichDouble (rhs->ray_, numberColumns, whichColumn);
3252      rowScale_ = NULL;
3253      columnScale_ = NULL;
3254      inverseRowScale_ = NULL;
3255      inverseColumnScale_ = NULL;
3256      scalingFlag_ = rhs->scalingFlag_;
3257      rowCopy_ = NULL;
3258      scaledMatrix_ = NULL;
3259      matrix_ = NULL;
3260      if (rhs->matrix_) {
3261           matrix_ = rhs->matrix_->subsetClone(numberRows, whichRow,
3262                                               numberColumns, whichColumn);
3263      }
3264      randomNumberGenerator_.setSeed(1234567);
3265 }
3266 #ifndef CLP_NO_STD
3267 // Copies in names
3268 void
copyNames(std::vector<std::string> & rowNames,std::vector<std::string> & columnNames)3269 ClpModel::copyNames(std::vector<std::string> & rowNames,
3270                     std::vector<std::string> & columnNames)
3271 {
3272      unsigned int maxLength = 0;
3273      int iRow;
3274      rowNames_ = std::vector<std::string> ();
3275      columnNames_ = std::vector<std::string> ();
3276      rowNames_.reserve(numberRows_);
3277      for (iRow = 0; iRow < numberRows_; iRow++) {
3278           rowNames_.push_back(rowNames[iRow]);
3279           maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(rowNames_[iRow].c_str())));
3280      }
3281      int iColumn;
3282      columnNames_.reserve(numberColumns_);
3283      for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
3284           columnNames_.push_back(columnNames[iColumn]);
3285           maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(columnNames_[iColumn].c_str())));
3286      }
3287      lengthNames_ = static_cast<int> (maxLength);
3288 }
3289 // Return name or Rnnnnnnn
3290 std::string
getRowName(int iRow) const3291 ClpModel::getRowName(int iRow) const
3292 {
3293 #ifndef NDEBUG
3294      if (iRow < 0 || iRow >= numberRows_) {
3295           indexError(iRow, "getRowName");
3296      }
3297 #endif
3298      int size = static_cast<int>(rowNames_.size());
3299      if (size > iRow) {
3300           return rowNames_[iRow];
3301      } else {
3302           char name[9];
3303           sprintf(name, "R%7.7d", iRow);
3304           std::string rowName(name);
3305           return rowName;
3306      }
3307 }
3308 // Set row name
3309 void
setRowName(int iRow,std::string & name)3310 ClpModel::setRowName(int iRow, std::string &name)
3311 {
3312 #ifndef NDEBUG
3313      if (iRow < 0 || iRow >= numberRows_) {
3314           indexError(iRow, "setRowName");
3315      }
3316 #endif
3317      unsigned int maxLength = lengthNames_;
3318      int size = static_cast<int>(rowNames_.size());
3319      if (size <= iRow)
3320           rowNames_.resize(iRow + 1);
3321      rowNames_[iRow] = name;
3322      maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name.c_str())));
3323      // May be too big - but we would have to check both rows and columns to be exact
3324      lengthNames_ = static_cast<int> (maxLength);
3325 }
3326 // Return name or Cnnnnnnn
3327 std::string
getColumnName(int iColumn) const3328 ClpModel::getColumnName(int iColumn) const
3329 {
3330 #ifndef NDEBUG
3331      if (iColumn < 0 || iColumn >= numberColumns_) {
3332           indexError(iColumn, "getColumnName");
3333      }
3334 #endif
3335      int size = static_cast<int>(columnNames_.size());
3336      if (size > iColumn) {
3337           return columnNames_[iColumn];
3338      } else {
3339           char name[9];
3340           sprintf(name, "C%7.7d", iColumn);
3341           std::string columnName(name);
3342           return columnName;
3343      }
3344 }
3345 // Set column name
3346 void
setColumnName(int iColumn,std::string & name)3347 ClpModel::setColumnName(int iColumn, std::string &name)
3348 {
3349 #ifndef NDEBUG
3350      if (iColumn < 0 || iColumn >= numberColumns_) {
3351           indexError(iColumn, "setColumnName");
3352      }
3353 #endif
3354      unsigned int maxLength = lengthNames_;
3355      int size = static_cast<int>(columnNames_.size());
3356      if (size <= iColumn)
3357           columnNames_.resize(iColumn + 1);
3358      columnNames_[iColumn] = name;
3359      maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name.c_str())));
3360      // May be too big - but we would have to check both columns and columns to be exact
3361      lengthNames_ = static_cast<int> (maxLength);
3362 }
3363 // Copies in Row names - modifies names first .. last-1
3364 void
copyRowNames(const std::vector<std::string> & rowNames,int first,int last)3365 ClpModel::copyRowNames(const std::vector<std::string> & rowNames, int first, int last)
3366 {
3367      unsigned int maxLength = lengthNames_;
3368      int size = static_cast<int>(rowNames_.size());
3369      if (size != numberRows_)
3370           rowNames_.resize(numberRows_);
3371      int iRow;
3372      for (iRow = first; iRow < last; iRow++) {
3373           rowNames_[iRow] = rowNames[iRow-first];
3374           maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(rowNames_[iRow-first].c_str())));
3375      }
3376      // May be too big - but we would have to check both rows and columns to be exact
3377      lengthNames_ = static_cast<int> (maxLength);
3378 }
3379 // Copies in Column names - modifies names first .. last-1
3380 void
copyColumnNames(const std::vector<std::string> & columnNames,int first,int last)3381 ClpModel::copyColumnNames(const std::vector<std::string> & columnNames, int first, int last)
3382 {
3383      unsigned int maxLength = lengthNames_;
3384      int size = static_cast<int>(columnNames_.size());
3385      if (size != numberColumns_)
3386           columnNames_.resize(numberColumns_);
3387      int iColumn;
3388      for (iColumn = first; iColumn < last; iColumn++) {
3389           columnNames_[iColumn] = columnNames[iColumn-first];
3390           maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(columnNames_[iColumn-first].c_str())));
3391      }
3392      // May be too big - but we would have to check both rows and columns to be exact
3393      lengthNames_ = static_cast<int> (maxLength);
3394 }
3395 // Copies in Row names - modifies names first .. last-1
3396 void
copyRowNames(const char * const * rowNames,int first,int last)3397 ClpModel::copyRowNames(const char * const * rowNames, int first, int last)
3398 {
3399      unsigned int maxLength = lengthNames_;
3400      int size = static_cast<int>(rowNames_.size());
3401      if (size != numberRows_)
3402           rowNames_.resize(numberRows_);
3403      int iRow;
3404      for (iRow = first; iRow < last; iRow++) {
3405           if (rowNames[iRow-first] && strlen(rowNames[iRow-first])) {
3406                rowNames_[iRow] = rowNames[iRow-first];
3407                maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(rowNames[iRow-first])));
3408           } else {
3409                maxLength = CoinMax(maxLength, static_cast<unsigned int> (8));
3410                char name[9];
3411                sprintf(name, "R%7.7d", iRow);
3412                rowNames_[iRow] = name;
3413           }
3414      }
3415      // May be too big - but we would have to check both rows and columns to be exact
3416      lengthNames_ = static_cast<int> (maxLength);
3417 }
3418 // Copies in Column names - modifies names first .. last-1
3419 void
copyColumnNames(const char * const * columnNames,int first,int last)3420 ClpModel::copyColumnNames(const char * const * columnNames, int first, int last)
3421 {
3422      unsigned int maxLength = lengthNames_;
3423      int size = static_cast<int>(columnNames_.size());
3424      if (size != numberColumns_)
3425           columnNames_.resize(numberColumns_);
3426      int iColumn;
3427      for (iColumn = first; iColumn < last; iColumn++) {
3428           if (columnNames[iColumn-first] && strlen(columnNames[iColumn-first])) {
3429                columnNames_[iColumn] = columnNames[iColumn-first];
3430                maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(columnNames[iColumn-first])));
3431           } else {
3432                maxLength = CoinMax(maxLength, static_cast<unsigned int> (8));
3433                char name[9];
3434                sprintf(name, "C%7.7d", iColumn);
3435                columnNames_[iColumn] = name;
3436           }
3437      }
3438      // May be too big - but we would have to check both rows and columns to be exact
3439      lengthNames_ = static_cast<int> (maxLength);
3440 }
3441 #endif
3442 // Primal objective limit
3443 void
setPrimalObjectiveLimit(double value)3444 ClpModel::setPrimalObjectiveLimit(double value)
3445 {
3446      dblParam_[ClpPrimalObjectiveLimit] = value;
3447 }
3448 // Dual objective limit
3449 void
setDualObjectiveLimit(double value)3450 ClpModel::setDualObjectiveLimit(double value)
3451 {
3452      dblParam_[ClpDualObjectiveLimit] = value;
3453 }
3454 // Objective offset
3455 void
setObjectiveOffset(double value)3456 ClpModel::setObjectiveOffset(double value)
3457 {
3458      dblParam_[ClpObjOffset] = value;
3459 }
3460 // Solve a problem with no elements - return status
emptyProblem(int * infeasNumber,double * infeasSum,bool printMessage)3461 int ClpModel::emptyProblem(int * infeasNumber, double * infeasSum, bool printMessage)
3462 {
3463      secondaryStatus_ = 6; // so user can see something odd
3464      if (printMessage)
3465           handler_->message(CLP_EMPTY_PROBLEM, messages_)
3466                     << numberRows_
3467                     << numberColumns_
3468                     << 0
3469                     << CoinMessageEol;
3470      int returnCode = 0;
3471      if (numberRows_ || numberColumns_) {
3472           if (!status_) {
3473                status_ = new unsigned char[numberRows_+numberColumns_];
3474                CoinZeroN(status_, numberRows_ + numberColumns_);
3475           }
3476      }
3477      // status is set directly (as can be used by Interior methods)
3478      // check feasible
3479      int numberPrimalInfeasibilities = 0;
3480      double sumPrimalInfeasibilities = 0.0;
3481      int numberDualInfeasibilities = 0;
3482      double sumDualInfeasibilities = 0.0;
3483      if (numberRows_) {
3484           for (int i = 0; i < numberRows_; i++) {
3485                dual_[i] = 0.0;
3486                if (rowLower_[i] <= rowUpper_[i]) {
3487                     if (rowLower_[i] > -1.0e30 || rowUpper_[i] < 1.0e30) {
3488                          if (rowLower_[i] <= 0.0 && rowUpper_[i] >= 0.0) {
3489                               if (fabs(rowLower_[i]) < fabs(rowUpper_[i]))
3490                                    rowActivity_[i] = rowLower_[i];
3491                               else
3492                                    rowActivity_[i] = rowUpper_[i];
3493                          } else {
3494                               rowActivity_[i] = 0.0;
3495                               numberPrimalInfeasibilities++;
3496                               sumPrimalInfeasibilities += CoinMin(rowLower_[i], -rowUpper_[i]);
3497                               returnCode = 1;
3498                          }
3499                     } else {
3500                          rowActivity_[i] = 0.0;
3501                     }
3502                } else {
3503                     rowActivity_[i] = 0.0;
3504                     numberPrimalInfeasibilities++;
3505                     sumPrimalInfeasibilities += rowLower_[i] - rowUpper_[i];
3506                     returnCode = 1;
3507                }
3508                status_[i+numberColumns_] = 1;
3509           }
3510      }
3511      objectiveValue_ = 0.0;
3512      if (numberColumns_) {
3513           const double * cost = objective();
3514           for (int i = 0; i < numberColumns_; i++) {
3515                reducedCost_[i] = cost[i];
3516                double objValue = cost[i] * optimizationDirection_;
3517                if (columnLower_[i] <= columnUpper_[i]) {
3518                     if (columnLower_[i] > -1.0e30 || columnUpper_[i] < 1.0e30) {
3519                          if (!objValue) {
3520                               if (fabs(columnLower_[i]) < fabs(columnUpper_[i])) {
3521                                    columnActivity_[i] = columnLower_[i];
3522                                    status_[i] = 3;
3523                               } else {
3524                                    columnActivity_[i] = columnUpper_[i];
3525                                    status_[i] = 2;
3526                               }
3527                          } else if (objValue > 0.0) {
3528                               if (columnLower_[i] > -1.0e30) {
3529                                    columnActivity_[i] = columnLower_[i];
3530                                    status_[i] = 3;
3531                               } else {
3532                                    columnActivity_[i] = columnUpper_[i];
3533                                    status_[i] = 2;
3534                                    numberDualInfeasibilities++;
3535                                    sumDualInfeasibilities += fabs(objValue);
3536                                    returnCode |= 2;
3537                               }
3538                               objectiveValue_ += columnActivity_[i] * objValue;
3539                          } else {
3540                               if (columnUpper_[i] < 1.0e30) {
3541                                    columnActivity_[i] = columnUpper_[i];
3542                                    status_[i] = 2;
3543                               } else {
3544                                    columnActivity_[i] = columnLower_[i];
3545                                    status_[i] = 3;
3546                                    numberDualInfeasibilities++;
3547                                    sumDualInfeasibilities += fabs(objValue);
3548                                    returnCode |= 2;
3549                               }
3550                               objectiveValue_ += columnActivity_[i] * objValue;
3551                          }
3552                     } else {
3553                          columnActivity_[i] = 0.0;
3554                          if (objValue) {
3555                               numberDualInfeasibilities++;
3556                               sumDualInfeasibilities += fabs(objValue);
3557                               returnCode |= 2;
3558                          }
3559                          status_[i] = 0;
3560                     }
3561                } else {
3562                     if (fabs(columnLower_[i]) < fabs(columnUpper_[i])) {
3563                          columnActivity_[i] = columnLower_[i];
3564                          status_[i] = 3;
3565                     } else {
3566                          columnActivity_[i] = columnUpper_[i];
3567                          status_[i] = 2;
3568                     }
3569                     numberPrimalInfeasibilities++;
3570                     sumPrimalInfeasibilities += columnLower_[i] - columnUpper_[i];
3571                     returnCode |= 1;
3572                }
3573           }
3574      }
3575      objectiveValue_ /= (objectiveScale_ * rhsScale_);
3576      if (infeasNumber) {
3577           infeasNumber[0] = numberDualInfeasibilities;
3578           infeasSum[0] = sumDualInfeasibilities;
3579           infeasNumber[1] = numberPrimalInfeasibilities;
3580           infeasSum[1] = sumPrimalInfeasibilities;
3581      }
3582      if (returnCode == 3)
3583           returnCode = 4;
3584      return returnCode;
3585 }
3586 #ifndef SLIM_NOIO
3587 /* Write the problem in MPS format to the specified file.
3588 
3589 Row and column names may be null.
3590 formatType is
3591 <ul>
3592 <li> 0 - normal
3593 <li> 1 - extra accuracy
3594 <li> 2 - IEEE hex (later)
3595 </ul>
3596 
3597 Returns non-zero on I/O error
3598 */
3599 int
writeMps(const char * filename,int formatType,int numberAcross,double objSense) const3600 ClpModel::writeMps(const char *filename,
3601                    int formatType, int numberAcross,
3602                    double objSense) const
3603 {
3604      matrix_->setDimensions(numberRows_, numberColumns_);
3605 
3606      // Get multiplier for objective function - default 1.0
3607      double * objective = new double[numberColumns_];
3608      CoinMemcpyN(getObjCoefficients(), numberColumns_, objective);
3609      if (objSense * getObjSense() < 0.0) {
3610           for (int i = 0; i < numberColumns_; ++i)
3611                objective [i] = - objective[i];
3612      }
3613      // get names
3614      const char * const * const rowNames = rowNamesAsChar();
3615      const char * const * const columnNames = columnNamesAsChar();
3616      CoinMpsIO writer;
3617      writer.passInMessageHandler(handler_);
3618      *writer.messagesPointer() = coinMessages();
3619      writer.setMpsData(*(matrix_->getPackedMatrix()), COIN_DBL_MAX,
3620                        getColLower(), getColUpper(),
3621                        objective,
3622                        static_cast<const char*> (NULL) /*integrality*/,
3623                        getRowLower(), getRowUpper(),
3624                        columnNames, rowNames);
3625      // Pass in array saying if each variable integer
3626      writer.copyInIntegerInformation(integerInformation());
3627      writer.setObjectiveOffset(objectiveOffset());
3628      delete [] objective;
3629      CoinPackedMatrix * quadratic = NULL;
3630 #ifndef SLIM_CLP
3631      // allow for quadratic objective
3632 #ifndef NO_RTTI
3633      ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
3634 #else
3635      ClpQuadraticObjective * quadraticObj = NULL;
3636      if (objective_->type() == 2)
3637           quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_));
3638 #endif
3639      if (quadraticObj)
3640           quadratic = quadraticObj->quadraticObjective();
3641 #endif
3642      int returnCode = writer.writeMps(filename, 0 /* do not gzip it*/, formatType, numberAcross,
3643                                       quadratic);
3644      if (rowNames) {
3645           deleteNamesAsChar(rowNames, numberRows_ + 1);
3646           deleteNamesAsChar(columnNames, numberColumns_);
3647      }
3648      return returnCode;
3649 }
3650 #ifndef CLP_NO_STD
3651 // Create row names as char **
3652 const char * const *
rowNamesAsChar() const3653 ClpModel::rowNamesAsChar() const
3654 {
3655      char ** rowNames = NULL;
3656      if (lengthNames()) {
3657           rowNames = new char * [numberRows_+1];
3658           int numberNames = static_cast<int>(rowNames_.size());
3659           numberNames = CoinMin(numberRows_, numberNames);
3660           int iRow;
3661           for (iRow = 0; iRow < numberNames; iRow++) {
3662                if (rowName(iRow) != "") {
3663                     rowNames[iRow] =
3664                          CoinStrdup(rowName(iRow).c_str());
3665                } else {
3666                     char name[9];
3667                     sprintf(name, "R%7.7d", iRow);
3668                     rowNames[iRow] = CoinStrdup(name);
3669                }
3670 #ifdef STRIPBLANKS
3671                char * xx = rowNames[iRow];
3672                int i;
3673                int length = strlen(xx);
3674                int n = 0;
3675                for (i = 0; i < length; i++) {
3676                     if (xx[i] != ' ')
3677                          xx[n++] = xx[i];
3678                }
3679                xx[n] = '\0';
3680 #endif
3681           }
3682           char name[9];
3683           for ( ; iRow < numberRows_; iRow++) {
3684                sprintf(name, "R%7.7d", iRow);
3685                rowNames[iRow] = CoinStrdup(name);
3686           }
3687           rowNames[numberRows_] = CoinStrdup("OBJROW");
3688      }
3689      return reinterpret_cast<const char * const *>(rowNames);
3690 }
3691 // Create column names as char **
3692 const char * const *
columnNamesAsChar() const3693 ClpModel::columnNamesAsChar() const
3694 {
3695      char ** columnNames = NULL;
3696      if (lengthNames()) {
3697           columnNames = new char * [numberColumns_];
3698           int numberNames = static_cast<int>(columnNames_.size());
3699           numberNames = CoinMin(numberColumns_, numberNames);
3700           int iColumn;
3701           for (iColumn = 0; iColumn < numberNames; iColumn++) {
3702                if (columnName(iColumn) != "") {
3703                     columnNames[iColumn] =
3704                          CoinStrdup(columnName(iColumn).c_str());
3705                } else {
3706                     char name[9];
3707                     sprintf(name, "C%7.7d", iColumn);
3708                     columnNames[iColumn] = CoinStrdup(name);
3709                }
3710 #ifdef STRIPBLANKS
3711                char * xx = columnNames[iColumn];
3712                int i;
3713                int length = strlen(xx);
3714                int n = 0;
3715                for (i = 0; i < length; i++) {
3716                     if (xx[i] != ' ')
3717                          xx[n++] = xx[i];
3718                }
3719                xx[n] = '\0';
3720 #endif
3721           }
3722           char name[9];
3723           for ( ; iColumn < numberColumns_; iColumn++) {
3724                sprintf(name, "C%7.7d", iColumn);
3725                columnNames[iColumn] = CoinStrdup(name);
3726           }
3727      }
3728      return /*reinterpret_cast<const char * const *>*/(columnNames);
3729 }
3730 // Delete char * version of names
3731 void
deleteNamesAsChar(const char * const * names,int number) const3732 ClpModel::deleteNamesAsChar(const char * const * names, int number) const
3733 {
3734      for (int i = 0; i < number; i++) {
3735           free(const_cast<char *>(names[i]));
3736      }
3737      delete [] const_cast<char **>(names);
3738 }
3739 #endif
3740 #endif
3741 // Pass in Event handler (cloned and deleted at end)
3742 void
passInEventHandler(const ClpEventHandler * eventHandler)3743 ClpModel::passInEventHandler(const ClpEventHandler * eventHandler)
3744 {
3745      delete eventHandler_;
3746      eventHandler_ = eventHandler->clone();
3747 }
3748 // Sets or unsets scaling, 0 -off, 1 on, 2 dynamic(later)
3749 void
scaling(int mode)3750 ClpModel::scaling(int mode)
3751 {
3752      // If mode changes then we treat as new matrix (need new row copy)
3753      if (mode != scalingFlag_) {
3754           whatsChanged_ &= ~(2 + 4 + 8);
3755 	  // Get rid of scaled matrix
3756 	  setClpScaledMatrix(NULL);
3757      }
3758      if (mode > 0 && mode < 6) {
3759           scalingFlag_ = mode;
3760      } else if (!mode) {
3761           scalingFlag_ = 0;
3762           setRowScale(NULL);
3763           setColumnScale(NULL);
3764      }
3765 }
3766 void
times(double scalar,const double * x,double * y) const3767 ClpModel::times(double scalar,
3768                 const double * x, double * y) const
3769 {
3770      if (!scaledMatrix_ || !rowScale_) {
3771           if (rowScale_)
3772                matrix_->times(scalar, x, y, rowScale_, columnScale_);
3773           else
3774                matrix_->times(scalar, x, y);
3775      } else {
3776           scaledMatrix_->times(scalar, x, y);
3777      }
3778 }
3779 void
transposeTimes(double scalar,const double * x,double * y) const3780 ClpModel::transposeTimes(double scalar,
3781                          const double * x, double * y) const
3782 {
3783      if (!scaledMatrix_ || !rowScale_) {
3784           if (rowScale_)
3785                matrix_->transposeTimes(scalar, x, y, rowScale_, columnScale_, NULL);
3786           else
3787                matrix_->transposeTimes(scalar, x, y);
3788      } else {
3789           scaledMatrix_->transposeTimes(scalar, x, y);
3790      }
3791 }
3792 // Does much of scaling
3793 void
gutsOfScaling()3794 ClpModel::gutsOfScaling()
3795 {
3796      int i;
3797      if (rowObjective_) {
3798           for (i = 0; i < numberRows_; i++)
3799                rowObjective_[i] /= rowScale_[i];
3800      }
3801      for (i = 0; i < numberRows_; i++) {
3802           double multiplier = rowScale_[i];
3803           double inverseMultiplier = 1.0 / multiplier;
3804           rowActivity_[i] *= multiplier;
3805           dual_[i] *= inverseMultiplier;
3806           if (rowLower_[i] > -1.0e30)
3807                rowLower_[i] *= multiplier;
3808           else
3809                rowLower_[i] = -COIN_DBL_MAX;
3810           if (rowUpper_[i] < 1.0e30)
3811                rowUpper_[i] *= multiplier;
3812           else
3813                rowUpper_[i] = COIN_DBL_MAX;
3814      }
3815      for (i = 0; i < numberColumns_; i++) {
3816           double multiplier = 1.0 * inverseColumnScale_[i];
3817           columnActivity_[i] *= multiplier;
3818           reducedCost_[i] *= columnScale_[i];
3819           if (columnLower_[i] > -1.0e30)
3820                columnLower_[i] *= multiplier;
3821           else
3822                columnLower_[i] = -COIN_DBL_MAX;
3823           if (columnUpper_[i] < 1.0e30)
3824                columnUpper_[i] *= multiplier;
3825           else
3826                columnUpper_[i] = COIN_DBL_MAX;
3827 
3828      }
3829      //now replace matrix
3830      //and objective
3831      matrix_->reallyScale(rowScale_, columnScale_);
3832      objective_->reallyScale(columnScale_);
3833 }
3834 /* If we constructed a "really" scaled model then this reverses the operation.
3835       Quantities may not be exactly as they were before due to rounding errors */
3836 void
unscale()3837 ClpModel::unscale()
3838 {
3839      if (rowScale_) {
3840           int i;
3841           // reverse scaling
3842           for (i = 0; i < numberRows_; i++)
3843                rowScale_[i] = 1.0 * inverseRowScale_[i];
3844           for (i = 0; i < numberColumns_; i++)
3845                columnScale_[i] = 1.0 * inverseColumnScale_[i];
3846           gutsOfScaling();
3847      }
3848 
3849      scalingFlag_ = 0;
3850      setRowScale(NULL);
3851      setColumnScale(NULL);
3852 }
3853 void
setSpecialOptions(unsigned int value)3854 ClpModel::setSpecialOptions(unsigned int value)
3855 {
3856      specialOptions_ = value;
3857 }
3858 /* This creates a coinModel object
3859  */
3860 CoinModel *
createCoinModel() const3861 ClpModel::createCoinModel() const
3862 {
3863      CoinModel * coinModel = new CoinModel();
3864      CoinPackedMatrix matrixByRow;
3865      matrixByRow.setExtraGap(0.0);
3866      matrixByRow.setExtraMajor(0.0);
3867      matrixByRow.reverseOrderedCopyOf(*matrix());
3868      coinModel->setObjectiveOffset(objectiveOffset());
3869      coinModel->setProblemName(problemName().c_str());
3870 
3871      // Build by row from scratch
3872      const double * element = matrixByRow.getElements();
3873      const int * column = matrixByRow.getIndices();
3874      const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
3875      const int * rowLength = matrixByRow.getVectorLengths();
3876      int i;
3877      for (i = 0; i < numberRows_; i++) {
3878           coinModel->addRow(rowLength[i], column + rowStart[i],
3879                             element + rowStart[i], rowLower_[i], rowUpper_[i]);
3880      }
3881      // Now do column part
3882      const double * objective = this->objective();
3883      for (i = 0; i < numberColumns_; i++) {
3884           coinModel->setColumnBounds(i, columnLower_[i], columnUpper_[i]);
3885           coinModel->setColumnObjective(i, objective[i]);
3886      }
3887      for ( i = 0; i < numberColumns_; i++) {
3888           if (isInteger(i))
3889                coinModel->setColumnIsInteger(i, true);
3890      }
3891      // do names
3892      for (i = 0; i < numberRows_; i++) {
3893           char temp[30];
3894           strcpy(temp, rowName(i).c_str());
3895           size_t length = strlen(temp);
3896           for (size_t j = 0; j < length; j++) {
3897                if (temp[j] == '-')
3898                     temp[j] = '_';
3899           }
3900           coinModel->setRowName(i, temp);
3901      }
3902      for (i = 0; i < numberColumns_; i++) {
3903           char temp[30];
3904           strcpy(temp, columnName(i).c_str());
3905           size_t length = strlen(temp);
3906           for (size_t j = 0; j < length; j++) {
3907                if (temp[j] == '-')
3908                     temp[j] = '_';
3909           }
3910           coinModel->setColumnName(i, temp);
3911      }
3912      ClpQuadraticObjective * obj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
3913      if (obj) {
3914           const CoinPackedMatrix * quadObj = obj->quadraticObjective();
3915           // add in quadratic
3916           const double * element = quadObj->getElements();
3917           const int * row = quadObj->getIndices();
3918           const CoinBigIndex * columnStart = quadObj->getVectorStarts();
3919           const int * columnLength = quadObj->getVectorLengths();
3920           for (i = 0; i < numberColumns_; i++) {
3921                int nels = columnLength[i];
3922                if (nels) {
3923                     CoinBigIndex start = columnStart[i];
3924                     double constant = coinModel->getColumnObjective(i);
3925                     char temp[100000];
3926                     char temp2[30];
3927                     sprintf(temp, "%g", constant);
3928                     for (CoinBigIndex k = start; k < start + nels; k++) {
3929                          int kColumn = row[k];
3930                          double value = element[k];
3931 #if 1
3932                          // ampl gives twice with assumed 0.5
3933                          if (kColumn < i)
3934                               continue;
3935                          else if (kColumn == i)
3936                               value *= 0.5;
3937 #endif
3938                          if (value == 1.0)
3939                               sprintf(temp2, "+%s", coinModel->getColumnName(kColumn));
3940                          else if (value == -1.0)
3941                               sprintf(temp2, "-%s", coinModel->getColumnName(kColumn));
3942                          else if (value > 0.0)
3943                               sprintf(temp2, "+%g*%s", value, coinModel->getColumnName(kColumn));
3944                          else
3945                               sprintf(temp2, "%g*%s", value, coinModel->getColumnName(kColumn));
3946                          strcat(temp, temp2);
3947                          assert (strlen(temp) < 100000);
3948                     }
3949                     coinModel->setObjective(i, temp);
3950                     if (logLevel() > 2)
3951                          printf("el for objective column %s is %s\n", coinModel->getColumnName(i), temp);
3952                }
3953           }
3954      }
3955      return coinModel;
3956 }
3957 // Start or reset using maximumRows_ and Columns_
3958 void
startPermanentArrays()3959 ClpModel::startPermanentArrays()
3960 {
3961      COIN_DETAIL_PRINT(printf("startperm a %d rows, %d maximum rows\n",
3962 			      numberRows_, maximumRows_));
3963      if ((specialOptions_ & 65536) != 0) {
3964           if (numberRows_ > maximumRows_ || numberColumns_ > maximumColumns_) {
3965                if (numberRows_ > maximumRows_) {
3966                     if (maximumRows_ > 0)
3967                          maximumRows_ = numberRows_ + 10 + numberRows_ / 100;
3968                     else
3969                          maximumRows_ = numberRows_;
3970                }
3971                if (numberColumns_ > maximumColumns_) {
3972                     if (maximumColumns_ > 0)
3973                          maximumColumns_ = numberColumns_ + 10 + numberColumns_ / 100;
3974                     else
3975                          maximumColumns_ = numberColumns_;
3976                }
3977                // need to make sure numberRows_ OK and size of matrices
3978                resize(maximumRows_, maximumColumns_);
3979                COIN_DETAIL_PRINT(printf("startperm b %d rows, %d maximum rows\n",
3980 					numberRows_, maximumRows_));
3981           } else {
3982                return;
3983           }
3984      } else {
3985           specialOptions_ |= 65536;
3986           maximumRows_ = numberRows_;
3987           maximumColumns_ = numberColumns_;
3988           baseMatrix_ = *matrix();
3989           baseMatrix_.cleanMatrix();
3990           baseRowCopy_.setExtraGap(0.0);
3991           baseRowCopy_.setExtraMajor(0.0);
3992           baseRowCopy_.reverseOrderedCopyOf(baseMatrix_);
3993           COIN_DETAIL_PRINT(printf("startperm c %d rows, %d maximum rows\n",
3994 				   numberRows_, maximumRows_));
3995      }
3996 }
3997 // Stop using maximumRows_ and Columns_
3998 void
stopPermanentArrays()3999 ClpModel::stopPermanentArrays()
4000 {
4001      specialOptions_ &= ~65536;
4002      maximumRows_ = -1;
4003      maximumColumns_ = -1;
4004      if (rowScale_ != savedRowScale_) {
4005           delete [] savedRowScale_;
4006           delete [] savedColumnScale_;
4007      }
4008      savedRowScale_ = NULL;
4009      savedColumnScale_ = NULL;
4010 }
4011 // Set new row matrix
4012 void
setNewRowCopy(ClpMatrixBase * newCopy)4013 ClpModel::setNewRowCopy(ClpMatrixBase * newCopy)
4014 {
4015      delete rowCopy_;
4016      rowCopy_ = newCopy;
4017 }
4018 /* Find a network subset.
4019    rotate array should be numberRows.  On output
4020    -1 not in network
4021    0 in network as is
4022    1 in network with signs swapped
4023   Returns number of network rows (positive if exact network, negative if needs extra row)
4024   From Gulpinar, Gutin, Maros and Mitra
4025 */
4026 int
findNetwork(char * rotate,double fractionNeeded)4027 ClpModel::findNetwork(char * rotate, double fractionNeeded)
4028 {
4029      int * mapping = new int [numberRows_];
4030      // Get column copy
4031      CoinPackedMatrix * columnCopy = matrix();
4032      // Get a row copy in standard format
4033      CoinPackedMatrix * copy = new CoinPackedMatrix();
4034      copy->setExtraGap(0.0);
4035      copy->setExtraMajor(0.0);
4036      copy->reverseOrderedCopyOf(*columnCopy);
4037      // make sure ordered and no gaps
4038      copy->cleanMatrix();
4039      // get matrix data pointers
4040      const int * columnIn = copy->getIndices();
4041      const CoinBigIndex * rowStartIn = copy->getVectorStarts();
4042      const int * rowLength = copy->getVectorLengths();
4043      const double * elementByRowIn = copy->getElements();
4044      int iRow, iColumn;
4045      int numberEligible = 0;
4046      int numberIn = 0;
4047      int numberElements = 0;
4048      for (iRow = 0; iRow < numberRows_; iRow++) {
4049           bool possible = true;
4050           mapping[iRow] = -1;
4051           rotate[iRow] = -1;
4052           for (CoinBigIndex j = rowStartIn[iRow]; j < rowStartIn[iRow] + rowLength[iRow]; j++) {
4053                //int iColumn = column[j];
4054                double value = elementByRowIn[j];
4055                if (fabs(value) != 1.0) {
4056                     possible = false;
4057                     break;
4058                }
4059           }
4060           if (rowLength[iRow] && possible) {
4061                mapping[iRow] = numberEligible;
4062                numberEligible++;
4063                numberElements += rowLength[iRow];
4064           }
4065      }
4066      if (numberEligible < fractionNeeded * numberRows_) {
4067           delete [] mapping;
4068           delete copy;
4069           return 0;
4070      }
4071      // create arrays
4072      int * eligible = new int [numberRows_];
4073      int * column = new int [numberElements];
4074      CoinBigIndex * rowStart = new CoinBigIndex [numberEligible+1];
4075      char * elementByRow = new char [numberElements];
4076      numberEligible = 0;
4077      numberElements = 0;
4078      rowStart[0] = 0;
4079      for (iRow = 0; iRow < numberRows_; iRow++) {
4080           if (mapping[iRow] < 0)
4081                continue;
4082           assert (numberEligible == mapping[iRow]);
4083           rotate[numberEligible] = 0;
4084           for (CoinBigIndex j = rowStartIn[iRow]; j < rowStartIn[iRow] + rowLength[iRow]; j++) {
4085                column[numberElements] = columnIn[j];
4086                double value = elementByRowIn[j];
4087                if (value == 1.0)
4088                     elementByRow[numberElements++] = 1;
4089                else
4090                     elementByRow[numberElements++] = -1;
4091           }
4092           numberEligible++;
4093           rowStart[numberEligible] = numberElements;
4094      }
4095      // get rid of copy to save space
4096      delete copy;
4097      const int * rowIn = columnCopy->getIndices();
4098      const CoinBigIndex * columnStartIn = columnCopy->getVectorStarts();
4099      const int * columnLengthIn = columnCopy->getVectorLengths();
4100      const double * elementByColumnIn = columnCopy->getElements();
4101      int * columnLength = new int [numberColumns_];
4102      // May just be that is a network - worth checking
4103      bool isNetworkAlready = true;
4104      bool trueNetwork = true;
4105      for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
4106           double product = 1.0;
4107           int n = 0;
4108           for (CoinBigIndex j = columnStartIn[iColumn]; j < columnStartIn[iColumn] + columnLengthIn[iColumn]; j++) {
4109                iRow = mapping[rowIn[j]];
4110                if (iRow >= 0) {
4111                     n++;
4112                     product *= elementByColumnIn[j];
4113                }
4114           }
4115           if (n >= 2) {
4116                if (product != -1.0 || n > 2)
4117                     isNetworkAlready = false;
4118           } else if (n == 1) {
4119                trueNetwork = false;
4120           }
4121           columnLength[iColumn] = n;
4122      }
4123      if (!isNetworkAlready) {
4124           // For sorting
4125           double * count = new double [numberRows_];
4126           int * which = new int [numberRows_];
4127           int numberLast = -1;
4128           // Count for columns
4129           char * columnCount = new char[numberColumns_];
4130           memset(columnCount, 0, numberColumns_);
4131           char * currentColumnCount = new char[numberColumns_];
4132           // Now do main loop
4133           while (numberIn > numberLast) {
4134                numberLast = numberIn;
4135                int numberLeft = 0;
4136                for (iRow = 0; iRow < numberEligible; iRow++) {
4137                     if (rotate[iRow] == 0 && rowStart[iRow+1] > rowStart[iRow]) {
4138                          which[numberLeft] = iRow;
4139                          int merit = 0;
4140                          bool OK = true;
4141                          bool reflectionOK = true;
4142                          for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow+1]; j++) {
4143                               iColumn = column[j];
4144                               int iCount = columnCount[iColumn];
4145                               int absCount = CoinAbs(iCount);
4146                               if (absCount < 2) {
4147                                    merit = CoinMax(columnLength[iColumn] - absCount - 1, merit);
4148                                    if (elementByRow[j] == iCount)
4149                                         OK = false;
4150                                    else if (elementByRow[j] == -iCount)
4151                                         reflectionOK = false;
4152                               } else {
4153                                    merit = -2;
4154                                    break;
4155                               }
4156                          }
4157                          if (merit > -2 && (OK || reflectionOK) &&
4158                                    (!OK || !reflectionOK || !numberIn)) {
4159                               //if (!numberLast) merit=1;
4160                               count[numberLeft++] = (rowStart[iRow+1] - rowStart[iRow] - 1) *
4161                                                     (static_cast<double>(merit));
4162                               if (OK)
4163                                    rotate[iRow] = 0;
4164                               else
4165                                    rotate[iRow] = 1;
4166                          } else {
4167                               // no good
4168                               rotate[iRow] = -1;
4169                          }
4170                     }
4171                }
4172                CoinSort_2(count, count + numberLeft, which);
4173                // Get G
4174                memset(currentColumnCount, 0, numberColumns_);
4175                for (iRow = 0; iRow < numberLeft; iRow++) {
4176                     int jRow = which[iRow];
4177                     bool possible = true;
4178                     for (int i = 0; i < numberIn; i++) {
4179                          for (CoinBigIndex j = rowStart[jRow]; j < rowStart[jRow+1]; j++) {
4180                               if (currentColumnCount[column[j]]) {
4181                                    possible = false;
4182                                    break;
4183                               }
4184                          }
4185                     }
4186                     if (possible) {
4187                          rotate[jRow] = static_cast<char>(rotate[jRow] + 2);
4188                          eligible[numberIn++] = jRow;
4189                          char multiplier = static_cast<char>((rotate[jRow] == 2) ? 1 : -1);
4190                          for (CoinBigIndex j = rowStart[jRow]; j < rowStart[jRow+1]; j++) {
4191                               iColumn = column[j];
4192                               currentColumnCount[iColumn]++;
4193                               int iCount = columnCount[iColumn];
4194                               int absCount = CoinAbs(iCount);
4195                               if (!absCount) {
4196                                    columnCount[iColumn] = static_cast<char>(elementByRow[j] * multiplier);
4197                               } else {
4198                                    columnCount[iColumn] = 2;
4199                               }
4200                          }
4201                     }
4202                }
4203           }
4204 #ifndef NDEBUG
4205           for (iRow = 0; iRow < numberIn; iRow++) {
4206                int kRow = eligible[iRow];
4207                assert (rotate[kRow] >= 2);
4208           }
4209 #endif
4210           trueNetwork = true;
4211           for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
4212                if (CoinAbs(static_cast<int>(columnCount[iColumn])) == 1) {
4213                     trueNetwork = false;
4214                     break;
4215                }
4216           }
4217           delete [] currentColumnCount;
4218           delete [] columnCount;
4219           delete [] which;
4220           delete [] count;
4221      } else {
4222           numberIn = numberEligible;
4223           for (iRow = 0; iRow < numberRows_; iRow++) {
4224                int kRow = mapping[iRow];
4225                if (kRow >= 0) {
4226                     rotate[kRow] = 2;
4227                }
4228           }
4229      }
4230      if (!trueNetwork)
4231           numberIn = - numberIn;
4232      delete [] column;
4233      delete [] rowStart;
4234      delete [] elementByRow;
4235      delete [] columnLength;
4236      // redo rotate
4237      char * rotate2 = CoinCopyOfArray(rotate, numberEligible);
4238      for (iRow = 0; iRow < numberRows_; iRow++) {
4239           int kRow = mapping[iRow];
4240           if (kRow >= 0) {
4241                int iState = rotate2[kRow];
4242                if (iState > 1)
4243                     iState -= 2;
4244                else
4245                     iState = -1;
4246                rotate[iRow] = static_cast<char>(iState);
4247           } else {
4248                rotate[iRow] = -1;
4249           }
4250      }
4251      delete [] rotate2;
4252      delete [] eligible;
4253      delete [] mapping;
4254      return numberIn;
4255 }
4256 //#############################################################################
4257 // Constructors / Destructor / Assignment
4258 //#############################################################################
4259 
4260 //-------------------------------------------------------------------
4261 // Default Constructor
4262 //-------------------------------------------------------------------
ClpDataSave()4263 ClpDataSave::ClpDataSave ()
4264 {
4265      dualBound_ = 0.0;
4266      infeasibilityCost_ = 0.0;
4267      sparseThreshold_ = 0;
4268      pivotTolerance_ = 0.0;
4269      zeroFactorizationTolerance_ = 1.0e13;
4270      zeroSimplexTolerance_ = 1.0e-13;
4271      acceptablePivot_ = 0.0;
4272      objectiveScale_ = 1.0;
4273      perturbation_ = 0;
4274      forceFactorization_ = -1;
4275      scalingFlag_ = 0;
4276      specialOptions_ = 0;
4277 }
4278 
4279 //-------------------------------------------------------------------
4280 // Copy constructor
4281 //-------------------------------------------------------------------
ClpDataSave(const ClpDataSave & rhs)4282 ClpDataSave::ClpDataSave (const ClpDataSave & rhs)
4283 {
4284      dualBound_ = rhs.dualBound_;
4285      infeasibilityCost_ = rhs.infeasibilityCost_;
4286      pivotTolerance_ = rhs.pivotTolerance_;
4287      zeroFactorizationTolerance_ = rhs.zeroFactorizationTolerance_;
4288      zeroSimplexTolerance_ = rhs.zeroSimplexTolerance_;
4289      acceptablePivot_ = rhs.acceptablePivot_;
4290      objectiveScale_ = rhs.objectiveScale_;
4291      sparseThreshold_ = rhs.sparseThreshold_;
4292      perturbation_ = rhs.perturbation_;
4293      forceFactorization_ = rhs.forceFactorization_;
4294      scalingFlag_ = rhs.scalingFlag_;
4295      specialOptions_ = rhs.specialOptions_;
4296 }
4297 
4298 //-------------------------------------------------------------------
4299 // Destructor
4300 //-------------------------------------------------------------------
~ClpDataSave()4301 ClpDataSave::~ClpDataSave ()
4302 {
4303 }
4304 
4305 //----------------------------------------------------------------
4306 // Assignment operator
4307 //-------------------------------------------------------------------
4308 ClpDataSave &
operator =(const ClpDataSave & rhs)4309 ClpDataSave::operator=(const ClpDataSave& rhs)
4310 {
4311      if (this != &rhs) {
4312           dualBound_ = rhs.dualBound_;
4313           infeasibilityCost_ = rhs.infeasibilityCost_;
4314           pivotTolerance_ = rhs.pivotTolerance_;
4315           zeroFactorizationTolerance_ = rhs.zeroFactorizationTolerance_;
4316           zeroSimplexTolerance_ = rhs.zeroSimplexTolerance_;
4317           acceptablePivot_ = rhs.acceptablePivot_;
4318           objectiveScale_ = rhs.objectiveScale_;
4319           sparseThreshold_ = rhs.sparseThreshold_;
4320           perturbation_ = rhs.perturbation_;
4321           forceFactorization_ = rhs.forceFactorization_;
4322           scalingFlag_ = rhs.scalingFlag_;
4323           specialOptions_ = rhs.specialOptions_;
4324      }
4325      return *this;
4326 }
4327 // Create C++ lines to get to current state
4328 void
generateCpp(FILE * fp)4329 ClpModel::generateCpp( FILE * fp)
4330 {
4331      // Stuff that can't be done easily
4332      if (!lengthNames_) {
4333           // no names
4334           fprintf(fp, "  clpModel->dropNames();\n");
4335      }
4336      ClpModel defaultModel;
4337      ClpModel * other = &defaultModel;
4338      int iValue1, iValue2;
4339      double dValue1, dValue2;
4340      iValue1 = this->maximumIterations();
4341      iValue2 = other->maximumIterations();
4342      fprintf(fp, "%d  int save_maximumIterations = clpModel->maximumIterations();\n", iValue1 == iValue2 ? 2 : 1);
4343      fprintf(fp, "%d  clpModel->setMaximumIterations(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
4344      fprintf(fp, "%d  clpModel->setMaximumIterations(save_maximumIterations);\n", iValue1 == iValue2 ? 7 : 6);
4345      dValue1 = this->primalTolerance();
4346      dValue2 = other->primalTolerance();
4347      fprintf(fp, "%d  double save_primalTolerance = clpModel->primalTolerance();\n", dValue1 == dValue2 ? 2 : 1);
4348      fprintf(fp, "%d  clpModel->setPrimalTolerance(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4349      fprintf(fp, "%d  clpModel->setPrimalTolerance(save_primalTolerance);\n", dValue1 == dValue2 ? 7 : 6);
4350      dValue1 = this->dualTolerance();
4351      dValue2 = other->dualTolerance();
4352      fprintf(fp, "%d  double save_dualTolerance = clpModel->dualTolerance();\n", dValue1 == dValue2 ? 2 : 1);
4353      fprintf(fp, "%d  clpModel->setDualTolerance(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4354      fprintf(fp, "%d  clpModel->setDualTolerance(save_dualTolerance);\n", dValue1 == dValue2 ? 7 : 6);
4355      iValue1 = this->numberIterations();
4356      iValue2 = other->numberIterations();
4357      fprintf(fp, "%d  int save_numberIterations = clpModel->numberIterations();\n", iValue1 == iValue2 ? 2 : 1);
4358      fprintf(fp, "%d  clpModel->setNumberIterations(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
4359      fprintf(fp, "%d  clpModel->setNumberIterations(save_numberIterations);\n", iValue1 == iValue2 ? 7 : 6);
4360      dValue1 = this->maximumSeconds();
4361      dValue2 = other->maximumSeconds();
4362      fprintf(fp, "%d  double save_maximumSeconds = clpModel->maximumSeconds();\n", dValue1 == dValue2 ? 2 : 1);
4363      fprintf(fp, "%d  clpModel->setMaximumSeconds(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4364      fprintf(fp, "%d  clpModel->setMaximumSeconds(save_maximumSeconds);\n", dValue1 == dValue2 ? 7 : 6);
4365      dValue1 = this->optimizationDirection();
4366      dValue2 = other->optimizationDirection();
4367      fprintf(fp, "%d  double save_optimizationDirection = clpModel->optimizationDirection();\n", dValue1 == dValue2 ? 2 : 1);
4368      fprintf(fp, "%d  clpModel->setOptimizationDirection(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4369      fprintf(fp, "%d  clpModel->setOptimizationDirection(save_optimizationDirection);\n", dValue1 == dValue2 ? 7 : 6);
4370      dValue1 = this->objectiveScale();
4371      dValue2 = other->objectiveScale();
4372      fprintf(fp, "%d  double save_objectiveScale = clpModel->objectiveScale();\n", dValue1 == dValue2 ? 2 : 1);
4373      fprintf(fp, "%d  clpModel->setObjectiveScale(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4374      fprintf(fp, "%d  clpModel->setObjectiveScale(save_objectiveScale);\n", dValue1 == dValue2 ? 7 : 6);
4375      dValue1 = this->rhsScale();
4376      dValue2 = other->rhsScale();
4377      fprintf(fp, "%d  double save_rhsScale = clpModel->rhsScale();\n", dValue1 == dValue2 ? 2 : 1);
4378      fprintf(fp, "%d  clpModel->setRhsScale(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4379      fprintf(fp, "%d  clpModel->setRhsScale(save_rhsScale);\n", dValue1 == dValue2 ? 7 : 6);
4380      iValue1 = this->scalingFlag();
4381      iValue2 = other->scalingFlag();
4382      fprintf(fp, "%d  int save_scalingFlag = clpModel->scalingFlag();\n", iValue1 == iValue2 ? 2 : 1);
4383      fprintf(fp, "%d  clpModel->scaling(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
4384      fprintf(fp, "%d  clpModel->scaling(save_scalingFlag);\n", iValue1 == iValue2 ? 7 : 6);
4385      dValue1 = this->getSmallElementValue();
4386      dValue2 = other->getSmallElementValue();
4387      fprintf(fp, "%d  double save_getSmallElementValue = clpModel->getSmallElementValue();\n", dValue1 == dValue2 ? 2 : 1);
4388      fprintf(fp, "%d  clpModel->setSmallElementValue(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4389      fprintf(fp, "%d  clpModel->setSmallElementValue(save_getSmallElementValue);\n", dValue1 == dValue2 ? 7 : 6);
4390      iValue1 = this->logLevel();
4391      iValue2 = other->logLevel();
4392      fprintf(fp, "%d  int save_logLevel = clpModel->logLevel();\n", iValue1 == iValue2 ? 2 : 1);
4393      fprintf(fp, "%d  clpModel->setLogLevel(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
4394      fprintf(fp, "%d  clpModel->setLogLevel(save_logLevel);\n", iValue1 == iValue2 ? 7 : 6);
4395 }
4396