source: trunk/Clp/src/ClpModel.cpp @ 2063

Last change on this file since 2063 was 2063, checked in by forrest, 5 years ago

fix typo and add some stability fixes

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