source: stable/1.15/Clp/src/ClpModel.cpp @ 2045

Last change on this file since 2045 was 2045, checked in by tkr, 5 years ago

Adding ability to set maximum wallclock running time

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 169.0 KB
Line 
1/* $Id: ClpModel.cpp 2045 2014-08-13 15:05:38Z tkr $ */
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     if (maximumRows_ < 0) {
1427          rowActivity_ = deleteDouble(rowActivity_, numberRows_,
1428                                      number, which, newSize);
1429          dual_ = deleteDouble(dual_, numberRows_,
1430                               number, which, newSize);
1431          rowObjective_ = deleteDouble(rowObjective_, numberRows_,
1432                                       number, which, newSize);
1433          rowLower_ = deleteDouble(rowLower_, numberRows_,
1434                                   number, which, newSize);
1435          rowUpper_ = deleteDouble(rowUpper_, numberRows_,
1436                                   number, which, newSize);
1437          if (matrix_->getNumRows())
1438               matrix_->deleteRows(number, which);
1439          //matrix_->removeGaps();
1440          // status
1441          if (status_) {
1442               if (numberColumns_ + newSize) {
1443                    unsigned char * tempR  = reinterpret_cast<unsigned char *>
1444                                             (deleteChar(reinterpret_cast<char *>(status_) + numberColumns_,
1445                                                         numberRows_,
1446                                                         number, which, newSize, false));
1447                    unsigned char * tempC = new unsigned char [numberColumns_+newSize];
1448                    CoinMemcpyN(status_, numberColumns_, tempC);
1449                    CoinMemcpyN(tempR, newSize, tempC + numberColumns_);
1450                    delete [] tempR;
1451                    delete [] status_;
1452                    status_ = tempC;
1453               } else {
1454                    // empty model - some systems don't like new [0]
1455                    delete [] status_;
1456                    status_ = NULL;
1457               }
1458          }
1459     } else {
1460          char * deleted = new char [numberRows_];
1461          int i;
1462          int numberDeleted = 0;
1463          CoinZeroN(deleted, numberRows_);
1464          for (i = 0; i < number; i++) {
1465               int j = which[i];
1466               if (j >= 0 && j < numberRows_ && !deleted[j]) {
1467                    numberDeleted++;
1468                    deleted[j] = 1;
1469               }
1470          }
1471          assert (!rowObjective_);
1472          unsigned char * status2 = status_ + numberColumns_;
1473          for (i = 0; i < numberRows_; i++) {
1474               if (!deleted[i]) {
1475                    rowActivity_[newSize] = rowActivity_[i];
1476                    dual_[newSize] = dual_[i];
1477                    rowLower_[newSize] = rowLower_[i];
1478                    rowUpper_[newSize] = rowUpper_[i];
1479                    status2[newSize] = status2[i];
1480                    newSize++;
1481               }
1482          }
1483          if (matrix_->getNumRows())
1484               matrix_->deleteRows(number, which);
1485          //matrix_->removeGaps();
1486          delete [] deleted;
1487     }
1488#ifndef CLP_NO_STD
1489     // Now works if which out of order
1490     if (lengthNames_) {
1491          char * mark = new char [numberRows_];
1492          CoinZeroN(mark, numberRows_);
1493          int i;
1494          for (i = 0; i < number; i++)
1495               mark[which[i]] = 1;
1496          int k = 0;
1497          for ( i = 0; i < numberRows_; ++i) {
1498               if (!mark[i])
1499                    rowNames_[k++] = rowNames_[i];
1500          }
1501          rowNames_.erase(rowNames_.begin() + k, rowNames_.end());
1502          delete [] mark;
1503     }
1504#endif
1505     numberRows_ = newSize;
1506     // set state back to unknown
1507     problemStatus_ = -1;
1508     secondaryStatus_ = 0;
1509     delete [] ray_;
1510     ray_ = NULL;
1511     if (savedRowScale_ != rowScale_) {
1512          delete [] rowScale_;
1513          delete [] columnScale_;
1514     }
1515     rowScale_ = NULL;
1516     columnScale_ = NULL;
1517     delete scaledMatrix_;
1518     scaledMatrix_ = NULL;
1519}
1520// Deletes columns
1521void
1522ClpModel::deleteColumns(int number, const int * which)
1523{
1524     if (!number)
1525          return; // nothing to do
1526     assert (maximumColumns_ < 0);
1527     whatsChanged_ &= ~(1 + 2 + 4 + 8 + 64 + 128 + 256); // all except rows changed
1528     int newSize = 0;
1529     columnActivity_ = deleteDouble(columnActivity_, numberColumns_,
1530                                    number, which, newSize);
1531     reducedCost_ = deleteDouble(reducedCost_, numberColumns_,
1532                                 number, which, newSize);
1533     objective_->deleteSome(number, which);
1534     columnLower_ = deleteDouble(columnLower_, numberColumns_,
1535                                 number, which, newSize);
1536     columnUpper_ = deleteDouble(columnUpper_, numberColumns_,
1537                                 number, which, newSize);
1538     // possible matrix is not full
1539     if (matrix_->getNumCols() < numberColumns_) {
1540          int * which2 = new int [number];
1541          int n = 0;
1542          int nMatrix = matrix_->getNumCols();
1543          for (int i = 0; i < number; i++) {
1544               if (which[i] < nMatrix)
1545                    which2[n++] = which[i];
1546          }
1547          matrix_->deleteCols(n, which2);
1548          delete [] which2;
1549     } else {
1550          matrix_->deleteCols(number, which);
1551     }
1552     //matrix_->removeGaps();
1553     // status
1554     if (status_) {
1555          if (numberRows_ + newSize) {
1556               unsigned char * tempC  = reinterpret_cast<unsigned char *>
1557                                        (deleteChar(reinterpret_cast<char *>(status_),
1558                                                    numberColumns_,
1559                                                    number, which, newSize, false));
1560               unsigned char * temp = new unsigned char [numberRows_+newSize];
1561               CoinMemcpyN(tempC, newSize, temp);
1562               CoinMemcpyN(status_ + numberColumns_,    numberRows_, temp + newSize);
1563               delete [] tempC;
1564               delete [] status_;
1565               status_ = temp;
1566          } else {
1567               // empty model - some systems don't like new [0]
1568               delete [] status_;
1569               status_ = NULL;
1570          }
1571     }
1572     integerType_ = deleteChar(integerType_, numberColumns_,
1573                               number, which, newSize, true);
1574#ifndef CLP_NO_STD
1575     // Now works if which out of order
1576     if (lengthNames_) {
1577          char * mark = new char [numberColumns_];
1578          CoinZeroN(mark, numberColumns_);
1579          int i;
1580          for (i = 0; i < number; i++)
1581               mark[which[i]] = 1;
1582          int k = 0;
1583          for ( i = 0; i < numberColumns_; ++i) {
1584               if (!mark[i])
1585                    columnNames_[k++] = columnNames_[i];
1586          }
1587          columnNames_.erase(columnNames_.begin() + k, columnNames_.end());
1588          delete [] mark;
1589     }
1590#endif
1591     numberColumns_ = newSize;
1592     // set state back to unknown
1593     problemStatus_ = -1;
1594     secondaryStatus_ = 0;
1595     delete [] ray_;
1596     ray_ = NULL;
1597     setRowScale(NULL);
1598     setColumnScale(NULL);
1599}
1600// Deletes rows AND columns (does not reallocate)
1601void 
1602ClpModel::deleteRowsAndColumns(int numberRows, const int * whichRows,
1603                               int numberColumns, const int * whichColumns)
1604{
1605  if (!numberColumns) {
1606    deleteRows(numberRows,whichRows);
1607  } else if (!numberRows) {
1608    deleteColumns(numberColumns,whichColumns);
1609  } else {
1610    whatsChanged_ &= ~511; // all changed
1611    bool doStatus = status_!=NULL;
1612    int numberTotal=numberRows_+numberColumns_;
1613    int * backRows = new int [numberTotal];
1614    int * backColumns = backRows+numberRows_;
1615    memset(backRows,0,numberTotal*sizeof(int));
1616    int newNumberColumns=0;
1617    for (int i=0;i<numberColumns;i++) {
1618      int iColumn=whichColumns[i];
1619      if (iColumn>=0&&iColumn<numberColumns_)
1620        backColumns[iColumn]=-1;
1621    }
1622    assert (objective_->type()==1);
1623    double * obj = objective(); 
1624    for (int i=0;i<numberColumns_;i++) {
1625      if (!backColumns[i]) {
1626        columnActivity_[newNumberColumns] = columnActivity_[i];
1627        reducedCost_[newNumberColumns] = reducedCost_[i];
1628        obj[newNumberColumns] = obj[i];
1629        columnLower_[newNumberColumns] = columnLower_[i];
1630        columnUpper_[newNumberColumns] = columnUpper_[i];
1631        if (doStatus)
1632          status_[newNumberColumns] = status_[i];
1633        backColumns[i]=newNumberColumns++;
1634      }
1635    }
1636    integerType_ = deleteChar(integerType_, numberColumns_,
1637                              numberColumns, whichColumns, newNumberColumns, true);
1638#ifndef CLP_NO_STD
1639    // Now works if which out of order
1640    if (lengthNames_) {
1641      for (int i=0;i<numberColumns_;i++) {
1642        int iColumn=backColumns[i];
1643        if (iColumn) 
1644          columnNames_[iColumn] = columnNames_[i];
1645      }
1646      columnNames_.erase(columnNames_.begin() + newNumberColumns, columnNames_.end());
1647    }
1648#endif
1649    int newNumberRows=0;
1650    assert (!rowObjective_);
1651    unsigned char * status2 = status_ + numberColumns_;
1652    unsigned char * status2a = status_ + newNumberColumns;
1653    for (int i=0;i<numberRows;i++) {
1654      int iRow=whichRows[i];
1655      if (iRow>=0&&iRow<numberRows_)
1656        backRows[iRow]=-1;
1657    }
1658    for (int i=0;i<numberRows_;i++) {
1659      if (!backRows[i]) {
1660        rowActivity_[newNumberRows] = rowActivity_[i];
1661        dual_[newNumberRows] = dual_[i];
1662        rowLower_[newNumberRows] = rowLower_[i];
1663        rowUpper_[newNumberRows] = rowUpper_[i];
1664        if (doStatus)
1665          status2a[newNumberRows] = status2[i];
1666        backRows[i]=newNumberRows++;
1667      }
1668    }
1669#ifndef CLP_NO_STD
1670    // Now works if which out of order
1671    if (lengthNames_) {
1672      for (int i=0;i<numberRows_;i++) {
1673        int iRow=backRows[i];
1674        if (iRow) 
1675          rowNames_[iRow] = rowNames_[i];
1676      }
1677      rowNames_.erase(rowNames_.begin() + newNumberRows, rowNames_.end());
1678    }
1679#endif
1680    // possible matrix is not full
1681    ClpPackedMatrix * clpMatrix = dynamic_cast<ClpPackedMatrix *>(matrix_);
1682    CoinPackedMatrix * matrix = clpMatrix ? clpMatrix->matrix() : NULL;
1683    if (matrix_->getNumCols() < numberColumns_) {
1684      assert (matrix);
1685      CoinBigIndex nel=matrix->getNumElements();
1686      int n=matrix->getNumCols();
1687      matrix->reserve(numberColumns_,nel);
1688      CoinBigIndex * columnStart = matrix->getMutableVectorStarts();
1689      int * columnLength = matrix->getMutableVectorLengths();
1690      for (int i=n;i<numberColumns_;i++) {
1691        columnStart[i]=nel;
1692        columnLength[i]=0;
1693      }
1694    }
1695    if (matrix) {
1696      matrix->setExtraMajor(0.1);
1697      //CoinPackedMatrix temp(*matrix);
1698      matrix->setExtraGap(0.0);
1699      matrix->setExtraMajor(0.0);
1700      int * row = matrix->getMutableIndices();
1701      CoinBigIndex * columnStart = matrix->getMutableVectorStarts();
1702      int * columnLength = matrix->getMutableVectorLengths();
1703      double * element = matrix->getMutableElements();
1704      newNumberColumns=0;
1705      CoinBigIndex n=0;
1706      for (int iColumn=0;iColumn<numberColumns_;iColumn++) {
1707        if (backColumns[iColumn]>=0) {
1708          CoinBigIndex start = columnStart[iColumn];
1709          int nSave=n;
1710          columnStart[newNumberColumns]=n;
1711          for (CoinBigIndex j=start;j<start+columnLength[iColumn];j++) {
1712            int iRow=row[j];
1713            iRow = backRows[iRow];
1714            if (iRow>=0) {
1715              row[n]=iRow;
1716              element[n++]=element[j];
1717            }
1718          }
1719          columnLength[newNumberColumns++]=n-nSave;
1720        }
1721      }
1722      columnStart[newNumberColumns]=n;
1723      matrix->setNumElements(n);
1724      matrix->setMajorDim(newNumberColumns);
1725      matrix->setMinorDim(newNumberRows);
1726      clpMatrix->setNumberActiveColumns(newNumberColumns);
1727      //temp.deleteRows(numberRows, whichRows);
1728      //temp.deleteCols(numberColumns, whichColumns);
1729      //assert(matrix->isEquivalent2(temp));
1730      //*matrix=temp;
1731    } else {
1732      matrix_->deleteRows(numberRows, whichRows);
1733      matrix_->deleteCols(numberColumns, whichColumns);
1734    }
1735    numberColumns_ = newNumberColumns;
1736    numberRows_ = newNumberRows;
1737    delete [] backRows;
1738    // set state back to unknown
1739    problemStatus_ = -1;
1740    secondaryStatus_ = 0;
1741    delete [] ray_;
1742    ray_ = NULL;
1743    if (savedRowScale_ != rowScale_) {
1744      delete [] rowScale_;
1745      delete [] columnScale_;
1746    }
1747    rowScale_ = NULL;
1748    columnScale_ = NULL;
1749    delete scaledMatrix_;
1750    scaledMatrix_ = NULL;
1751    delete rowCopy_;
1752    rowCopy_ = NULL;
1753  }
1754}
1755// Add one row
1756void
1757ClpModel::addRow(int numberInRow, const int * columns,
1758                 const double * elements, double rowLower, double rowUpper)
1759{
1760     CoinBigIndex starts[2];
1761     starts[0] = 0;
1762     starts[1] = numberInRow;
1763     addRows(1, &rowLower, &rowUpper, starts, columns, elements);
1764}
1765// Add rows
1766void
1767ClpModel::addRows(int number, const double * rowLower,
1768                  const double * rowUpper,
1769                  const CoinBigIndex * rowStarts, const int * columns,
1770                  const double * elements)
1771{
1772     if (number) {
1773          whatsChanged_ &= ~(1 + 2 + 8 + 16 + 32); // all except columns changed
1774          int numberRowsNow = numberRows_;
1775          resize(numberRowsNow + number, numberColumns_);
1776          double * lower = rowLower_ + numberRowsNow;
1777          double * upper = rowUpper_ + numberRowsNow;
1778          int iRow;
1779          if (rowLower) {
1780               for (iRow = 0; iRow < number; iRow++) {
1781                    double value = rowLower[iRow];
1782                    if (value < -1.0e20)
1783                         value = -COIN_DBL_MAX;
1784                    lower[iRow] = value;
1785               }
1786          } else {
1787               for (iRow = 0; iRow < number; iRow++) {
1788                    lower[iRow] = -COIN_DBL_MAX;
1789               }
1790          }
1791          if (rowUpper) {
1792               for (iRow = 0; iRow < number; iRow++) {
1793                    double value = rowUpper[iRow];
1794                    if (value > 1.0e20)
1795                         value = COIN_DBL_MAX;
1796                    upper[iRow] = value;
1797               }
1798          } else {
1799               for (iRow = 0; iRow < number; iRow++) {
1800                    upper[iRow] = COIN_DBL_MAX;
1801               }
1802          }
1803          // Deal with matrix
1804
1805          delete rowCopy_;
1806          rowCopy_ = NULL;
1807          delete scaledMatrix_;
1808          scaledMatrix_ = NULL;
1809          if (!matrix_)
1810               createEmptyMatrix();
1811          setRowScale(NULL);
1812          setColumnScale(NULL);
1813#ifndef CLP_NO_STD
1814          if (lengthNames_) {
1815               rowNames_.resize(numberRows_);
1816          }
1817#endif
1818          if (rowStarts) {
1819               // Make sure matrix has correct number of columns
1820               matrix_->getPackedMatrix()->reserve(numberColumns_, 0, true);
1821               matrix_->appendMatrix(number, 0, rowStarts, columns, elements);
1822          }
1823     }
1824}
1825// Add rows
1826void
1827ClpModel::addRows(int number, const double * rowLower,
1828                  const double * rowUpper,
1829                  const CoinBigIndex * rowStarts,
1830                  const int * rowLengths, const int * columns,
1831                  const double * elements)
1832{
1833     if (number) {
1834          CoinBigIndex numberElements = 0;
1835          int iRow;
1836          for (iRow = 0; iRow < number; iRow++)
1837               numberElements += rowLengths[iRow];
1838          int * newStarts = new int[number+1];
1839          int * newIndex = new int[numberElements];
1840          double * newElements = new double[numberElements];
1841          numberElements = 0;
1842          newStarts[0] = 0;
1843          for (iRow = 0; iRow < number; iRow++) {
1844               int iStart = rowStarts[iRow];
1845               int length = rowLengths[iRow];
1846               CoinMemcpyN(columns + iStart, length, newIndex + numberElements);
1847               CoinMemcpyN(elements + iStart, length, newElements + numberElements);
1848               numberElements += length;
1849               newStarts[iRow+1] = numberElements;
1850          }
1851          addRows(number, rowLower, rowUpper,
1852                  newStarts, newIndex, newElements);
1853          delete [] newStarts;
1854          delete [] newIndex;
1855          delete [] newElements;
1856     }
1857}
1858#ifndef CLP_NO_VECTOR
1859void
1860ClpModel::addRows(int number, const double * rowLower,
1861                  const double * rowUpper,
1862                  const CoinPackedVectorBase * const * rows)
1863{
1864     if (!number)
1865          return;
1866     whatsChanged_ &= ~(1 + 2 + 8 + 16 + 32); // all except columns changed
1867     int numberRowsNow = numberRows_;
1868     resize(numberRowsNow + number, numberColumns_);
1869     double * lower = rowLower_ + numberRowsNow;
1870     double * upper = rowUpper_ + numberRowsNow;
1871     int iRow;
1872     if (rowLower) {
1873          for (iRow = 0; iRow < number; iRow++) {
1874               double value = rowLower[iRow];
1875               if (value < -1.0e20)
1876                    value = -COIN_DBL_MAX;
1877               lower[iRow] = value;
1878          }
1879     } else {
1880          for (iRow = 0; iRow < number; iRow++) {
1881               lower[iRow] = -COIN_DBL_MAX;
1882          }
1883     }
1884     if (rowUpper) {
1885          for (iRow = 0; iRow < number; iRow++) {
1886               double value = rowUpper[iRow];
1887               if (value > 1.0e20)
1888                    value = COIN_DBL_MAX;
1889               upper[iRow] = value;
1890          }
1891     } else {
1892          for (iRow = 0; iRow < number; iRow++) {
1893               upper[iRow] = COIN_DBL_MAX;
1894          }
1895     }
1896     // Deal with matrix
1897
1898     delete rowCopy_;
1899     rowCopy_ = NULL;
1900     delete scaledMatrix_;
1901     scaledMatrix_ = NULL;
1902     if (!matrix_)
1903          createEmptyMatrix();
1904     if (rows)
1905          matrix_->appendRows(number, rows);
1906     setRowScale(NULL);
1907     setColumnScale(NULL);
1908     if (lengthNames_) {
1909          rowNames_.resize(numberRows_);
1910     }
1911}
1912#endif
1913#ifndef SLIM_CLP
1914// Add rows from a build object
1915int
1916ClpModel::addRows(const CoinBuild & buildObject, bool tryPlusMinusOne, bool checkDuplicates)
1917{
1918     CoinAssertHint (buildObject.type() == 0, "Looks as if both addRows and addCols being used"); // check correct
1919     int number = buildObject.numberRows();
1920     int numberErrors = 0;
1921     if (number) {
1922          CoinBigIndex size = 0;
1923          int iRow;
1924          double * lower = new double [number];
1925          double * upper = new double [number];
1926          if ((!matrix_ || !matrix_->getNumElements()) && tryPlusMinusOne) {
1927               // See if can be +-1
1928               for (iRow = 0; iRow < number; iRow++) {
1929                    const int * columns;
1930                    const double * elements;
1931                    int numberElements = buildObject.row(iRow, lower[iRow],
1932                                                         upper[iRow],
1933                                                         columns, elements);
1934                    for (int i = 0; i < numberElements; i++) {
1935                         // allow for zero elements
1936                         if (elements[i]) {
1937                              if (fabs(elements[i]) == 1.0) {
1938                                   size++;
1939                              } else {
1940                                   // bad
1941                                   tryPlusMinusOne = false;
1942                              }
1943                         }
1944                    }
1945                    if (!tryPlusMinusOne)
1946                         break;
1947               }
1948          } else {
1949               // Will add to whatever sort of matrix exists
1950               tryPlusMinusOne = false;
1951          }
1952          if (!tryPlusMinusOne) {
1953               CoinBigIndex numberElements = buildObject.numberElements();
1954               CoinBigIndex * starts = new CoinBigIndex [number+1];
1955               int * column = new int[numberElements];
1956               double * element = new double[numberElements];
1957               starts[0] = 0;
1958               numberElements = 0;
1959               for (iRow = 0; iRow < number; iRow++) {
1960                    const int * columns;
1961                    const double * elements;
1962                    int numberElementsThis = buildObject.row(iRow, lower[iRow], upper[iRow],
1963                                             columns, elements);
1964                    CoinMemcpyN(columns, numberElementsThis, column + numberElements);
1965                    CoinMemcpyN(elements, numberElementsThis, element + numberElements);
1966                    numberElements += numberElementsThis;
1967                    starts[iRow+1] = numberElements;
1968               }
1969               addRows(number, lower, upper, NULL);
1970               // make sure matrix has enough columns
1971               matrix_->setDimensions(-1, numberColumns_);
1972               numberErrors = matrix_->appendMatrix(number, 0, starts, column, element,
1973                                                    checkDuplicates ? numberColumns_ : -1);
1974               delete [] starts;
1975               delete [] column;
1976               delete [] element;
1977          } else {
1978               char * which = NULL; // for duplicates
1979               if (checkDuplicates) {
1980                    which = new char[numberColumns_];
1981                    CoinZeroN(which, numberColumns_);
1982               }
1983               // build +-1 matrix
1984               // arrays already filled in
1985               addRows(number, lower, upper, NULL);
1986               CoinBigIndex * startPositive = new CoinBigIndex [numberColumns_+1];
1987               CoinBigIndex * startNegative = new CoinBigIndex [numberColumns_];
1988               int * indices = new int [size];
1989               CoinZeroN(startPositive, numberColumns_);
1990               CoinZeroN(startNegative, numberColumns_);
1991               int maxColumn = -1;
1992               // need two passes
1993               for (iRow = 0; iRow < number; iRow++) {
1994                    const int * columns;
1995                    const double * elements;
1996                    int numberElements = buildObject.row(iRow, lower[iRow],
1997                                                         upper[iRow],
1998                                                         columns, elements);
1999                    for (int i = 0; i < numberElements; i++) {
2000                         int iColumn = columns[i];
2001                         if (checkDuplicates) {
2002                              if (iColumn >= numberColumns_) {
2003                                   if(which[iColumn])
2004                                        numberErrors++;
2005                                   else
2006                                        which[iColumn] = 1;
2007                              } else {
2008                                   numberErrors++;
2009                                   // and may as well switch off
2010                                   checkDuplicates = false;
2011                              }
2012                         }
2013                         maxColumn = CoinMax(maxColumn, iColumn);
2014                         if (elements[i] == 1.0) {
2015                              startPositive[iColumn]++;
2016                         } else if (elements[i] == -1.0) {
2017                              startNegative[iColumn]++;
2018                         }
2019                    }
2020                    if (checkDuplicates) {
2021                         for (int i = 0; i < numberElements; i++) {
2022                              int iColumn = columns[i];
2023                              which[iColumn] = 0;
2024                         }
2025                    }
2026               }
2027               // check size
2028               int numberColumns = maxColumn + 1;
2029               CoinAssertHint (numberColumns <= numberColumns_,
2030                               "rows having column indices >= numberColumns_");
2031               size = 0;
2032               int iColumn;
2033               for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2034                    CoinBigIndex n = startPositive[iColumn];
2035                    startPositive[iColumn] = size;
2036                    size += n;
2037                    n = startNegative[iColumn];
2038                    startNegative[iColumn] = size;
2039                    size += n;
2040               }
2041               startPositive[numberColumns_] = size;
2042               for (iRow = 0; iRow < number; iRow++) {
2043                    const int * columns;
2044                    const double * elements;
2045                    int numberElements = buildObject.row(iRow, lower[iRow],
2046                                                         upper[iRow],
2047                                                         columns, elements);
2048                    for (int i = 0; i < numberElements; i++) {
2049                         int iColumn = columns[i];
2050                         maxColumn = CoinMax(maxColumn, iColumn);
2051                         if (elements[i] == 1.0) {
2052                              CoinBigIndex position = startPositive[iColumn];
2053                              indices[position] = iRow;
2054                              startPositive[iColumn]++;
2055                         } else if (elements[i] == -1.0) {
2056                              CoinBigIndex position = startNegative[iColumn];
2057                              indices[position] = iRow;
2058                              startNegative[iColumn]++;
2059                         }
2060                    }
2061               }
2062               // and now redo starts
2063               for (iColumn = numberColumns_ - 1; iColumn >= 0; iColumn--) {
2064                    startPositive[iColumn+1] = startNegative[iColumn];
2065                    startNegative[iColumn] = startPositive[iColumn];
2066               }
2067               startPositive[0] = 0;
2068               for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2069                    CoinBigIndex start = startPositive[iColumn];
2070                    CoinBigIndex end = startNegative[iColumn];
2071                    std::sort(indices + start, indices + end);
2072                    start = startNegative[iColumn];
2073                    end = startPositive[iColumn+1];
2074                    std::sort(indices + start, indices + end);
2075               }
2076               // Get good object
2077               delete matrix_;
2078               ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
2079               matrix->passInCopy(numberRows_, numberColumns,
2080                                  true, indices, startPositive, startNegative);
2081               matrix_ = matrix;
2082               delete [] which;
2083          }
2084          delete [] lower;
2085          delete [] upper;
2086          // make sure matrix correct size
2087          matrix_->setDimensions(numberRows_, numberColumns_);
2088     }
2089     return numberErrors;
2090}
2091#endif
2092#ifndef SLIM_NOIO
2093// Add rows from a model object
2094int
2095ClpModel::addRows( CoinModel & modelObject, bool tryPlusMinusOne, bool checkDuplicates)
2096{
2097     if (modelObject.numberElements() == 0)
2098          return 0;
2099     bool goodState = true;
2100     int numberErrors = 0;
2101     if (modelObject.columnLowerArray()) {
2102          // some column information exists
2103          int numberColumns2 = modelObject.numberColumns();
2104          const double * columnLower = modelObject.columnLowerArray();
2105          const double * columnUpper = modelObject.columnUpperArray();
2106          const double * objective = modelObject.objectiveArray();
2107          const int * integerType = modelObject.integerTypeArray();
2108          for (int i = 0; i < numberColumns2; i++) {
2109               if (columnLower[i] != 0.0)
2110                    goodState = false;
2111               if (columnUpper[i] != COIN_DBL_MAX)
2112                    goodState = false;
2113               if (objective[i] != 0.0)
2114                    goodState = false;
2115               if (integerType[i] != 0)
2116                    goodState = false;
2117          }
2118     }
2119     if (goodState) {
2120          // can do addRows
2121          // Set arrays for normal use
2122          double * rowLower = modelObject.rowLowerArray();
2123          double * rowUpper = modelObject.rowUpperArray();
2124          double * columnLower = modelObject.columnLowerArray();
2125          double * columnUpper = modelObject.columnUpperArray();
2126          double * objective = modelObject.objectiveArray();
2127          int * integerType = modelObject.integerTypeArray();
2128          double * associated = modelObject.associatedArray();
2129          // If strings then do copies
2130          if (modelObject.stringsExist()) {
2131               numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper,
2132                                                       objective, integerType, associated);
2133          }
2134          int numberRows = numberRows_; // save number of rows
2135          int numberRows2 = modelObject.numberRows();
2136          if (numberRows2 && !numberErrors) {
2137               CoinBigIndex * startPositive = NULL;
2138               CoinBigIndex * startNegative = NULL;
2139               int numberColumns = modelObject.numberColumns();
2140               if ((!matrix_ || !matrix_->getNumElements()) && !numberRows && tryPlusMinusOne) {
2141                    startPositive = new CoinBigIndex[numberColumns+1];
2142                    startNegative = new CoinBigIndex[numberColumns];
2143                    modelObject.countPlusMinusOne(startPositive, startNegative, associated);
2144                    if (startPositive[0] < 0) {
2145                         // no good
2146                         tryPlusMinusOne = false;
2147                         delete [] startPositive;
2148                         delete [] startNegative;
2149                    }
2150               } else {
2151                    // Will add to whatever sort of matrix exists
2152                    tryPlusMinusOne = false;
2153               }
2154               assert (rowLower);
2155               addRows(numberRows2, rowLower, rowUpper, NULL, NULL, NULL);
2156#ifndef SLIM_CLP
2157               if (!tryPlusMinusOne) {
2158#endif
2159                    CoinPackedMatrix matrix;
2160                    modelObject.createPackedMatrix(matrix, associated);
2161                    assert (!matrix.getExtraGap());
2162                    if (matrix_->getNumRows()) {
2163                         // matrix by rows
2164                         matrix.reverseOrdering();
2165                         assert (!matrix.getExtraGap());
2166                         const int * column = matrix.getIndices();
2167                         //const int * rowLength = matrix.getVectorLengths();
2168                         const CoinBigIndex * rowStart = matrix.getVectorStarts();
2169                         const double * element = matrix.getElements();
2170                         // make sure matrix has enough columns
2171                         matrix_->setDimensions(-1, numberColumns_);
2172                         numberErrors += matrix_->appendMatrix(numberRows2, 0, rowStart, column, element,
2173                                                               checkDuplicates ? numberColumns_ : -1);
2174                    } else {
2175                         delete matrix_;
2176                         matrix_ = new ClpPackedMatrix(matrix);
2177                    }
2178#ifndef SLIM_CLP
2179               } else {
2180                    // create +-1 matrix
2181                    CoinBigIndex size = startPositive[numberColumns];
2182                    int * indices = new int[size];
2183                    modelObject.createPlusMinusOne(startPositive, startNegative, indices,
2184                                                   associated);
2185                    // Get good object
2186                    ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
2187                    matrix->passInCopy(numberRows2, numberColumns,
2188                                       true, indices, startPositive, startNegative);
2189                    delete matrix_;
2190                    matrix_ = matrix;
2191               }
2192               // Do names if wanted
2193               if (modelObject.rowNames()->numberItems()) {
2194                    const char *const * rowNames = modelObject.rowNames()->names();
2195                    copyRowNames(rowNames, numberRows, numberRows_);
2196               }
2197#endif
2198          }
2199          if (rowLower != modelObject.rowLowerArray()) {
2200               delete [] rowLower;
2201               delete [] rowUpper;
2202               delete [] columnLower;
2203               delete [] columnUpper;
2204               delete [] objective;
2205               delete [] integerType;
2206               delete [] associated;
2207               if (numberErrors)
2208                    handler_->message(CLP_BAD_STRING_VALUES, messages_)
2209                              << numberErrors
2210                              << CoinMessageEol;
2211          }
2212          return numberErrors;
2213     } else {
2214          // not suitable for addRows
2215          handler_->message(CLP_COMPLICATED_MODEL, messages_)
2216                    << modelObject.numberRows()
2217                    << modelObject.numberColumns()
2218                    << CoinMessageEol;
2219          return -1;
2220     }
2221}
2222#endif
2223// Add one column
2224void
2225ClpModel::addColumn(int numberInColumn,
2226                    const int * rows,
2227                    const double * elements,
2228                    double columnLower,
2229                    double  columnUpper,
2230                    double  objective)
2231{
2232     CoinBigIndex starts[2];
2233     starts[0] = 0;
2234     starts[1] = numberInColumn;
2235     addColumns(1, &columnLower, &columnUpper, &objective, starts, rows, elements);
2236}
2237// Add columns
2238void
2239ClpModel::addColumns(int number, const double * columnLower,
2240                     const double * columnUpper,
2241                     const double * objIn,
2242                     const int * columnStarts, const int * rows,
2243                     const double * elements)
2244{
2245     // Create a list of CoinPackedVectors
2246     if (number) {
2247          whatsChanged_ &= ~(1 + 2 + 4 + 64 + 128 + 256); // all except rows changed
2248          int numberColumnsNow = numberColumns_;
2249          resize(numberRows_, numberColumnsNow + number);
2250          double * lower = columnLower_ + numberColumnsNow;
2251          double * upper = columnUpper_ + numberColumnsNow;
2252          double * obj = objective() + numberColumnsNow;
2253          int iColumn;
2254          if (columnLower) {
2255               for (iColumn = 0; iColumn < number; iColumn++) {
2256                    double value = columnLower[iColumn];
2257                    if (value < -1.0e20)
2258                         value = -COIN_DBL_MAX;
2259                    lower[iColumn] = value;
2260               }
2261          } else {
2262               for (iColumn = 0; iColumn < number; iColumn++) {
2263                    lower[iColumn] = 0.0;
2264               }
2265          }
2266          if (columnUpper) {
2267               for (iColumn = 0; iColumn < number; iColumn++) {
2268                    double value = columnUpper[iColumn];
2269                    if (value > 1.0e20)
2270                         value = COIN_DBL_MAX;
2271                    upper[iColumn] = value;
2272               }
2273          } else {
2274               for (iColumn = 0; iColumn < number; iColumn++) {
2275                    upper[iColumn] = COIN_DBL_MAX;
2276               }
2277          }
2278          if (objIn) {
2279               for (iColumn = 0; iColumn < number; iColumn++) {
2280                    obj[iColumn] = objIn[iColumn];
2281               }
2282          } else {
2283               for (iColumn = 0; iColumn < number; iColumn++) {
2284                    obj[iColumn] = 0.0;
2285               }
2286          }
2287          // Deal with matrix
2288
2289          delete rowCopy_;
2290          rowCopy_ = NULL;
2291          delete scaledMatrix_;
2292          scaledMatrix_ = NULL;
2293          if (!matrix_)
2294               createEmptyMatrix();
2295          setRowScale(NULL);
2296          setColumnScale(NULL);
2297#ifndef CLP_NO_STD
2298          if (lengthNames_) {
2299               columnNames_.resize(numberColumns_);
2300          }
2301#endif
2302          // Do even if elements NULL (to resize)
2303          matrix_->appendMatrix(number, 1, columnStarts, rows, elements);
2304     }
2305}
2306// Add columns
2307void
2308ClpModel::addColumns(int number, const double * columnLower,
2309                     const double * columnUpper,
2310                     const double * objIn,
2311                     const int * columnStarts,
2312                     const int * columnLengths, const int * rows,
2313                     const double * elements)
2314{
2315     if (number) {
2316          CoinBigIndex numberElements = 0;
2317          int iColumn;
2318          for (iColumn = 0; iColumn < number; iColumn++)
2319               numberElements += columnLengths[iColumn];
2320          int * newStarts = new int[number+1];
2321          int * newIndex = new int[numberElements];
2322          double * newElements = new double[numberElements];
2323          numberElements = 0;
2324          newStarts[0] = 0;
2325          for (iColumn = 0; iColumn < number; iColumn++) {
2326               int iStart = columnStarts[iColumn];
2327               int length = columnLengths[iColumn];
2328               CoinMemcpyN(rows + iStart, length, newIndex + numberElements);
2329               CoinMemcpyN(elements + iStart, length, newElements + numberElements);
2330               numberElements += length;
2331               newStarts[iColumn+1] = numberElements;
2332          }
2333          addColumns(number, columnLower, columnUpper, objIn,
2334                     newStarts, newIndex, newElements);
2335          delete [] newStarts;
2336          delete [] newIndex;
2337          delete [] newElements;
2338     }
2339}
2340#ifndef CLP_NO_VECTOR
2341void
2342ClpModel::addColumns(int number, const double * columnLower,
2343                     const double * columnUpper,
2344                     const double * objIn,
2345                     const CoinPackedVectorBase * const * columns)
2346{
2347     if (!number)
2348          return;
2349     whatsChanged_ &= ~(1 + 2 + 4 + 64 + 128 + 256); // all except rows changed
2350     int numberColumnsNow = numberColumns_;
2351     resize(numberRows_, numberColumnsNow + number);
2352     double * lower = columnLower_ + numberColumnsNow;
2353     double * upper = columnUpper_ + numberColumnsNow;
2354     double * obj = objective() + numberColumnsNow;
2355     int iColumn;
2356     if (columnLower) {
2357          for (iColumn = 0; iColumn < number; iColumn++) {
2358               double value = columnLower[iColumn];
2359               if (value < -1.0e20)
2360                    value = -COIN_DBL_MAX;
2361               lower[iColumn] = value;
2362          }
2363     } else {
2364          for (iColumn = 0; iColumn < number; iColumn++) {
2365               lower[iColumn] = 0.0;
2366          }
2367     }
2368     if (columnUpper) {
2369          for (iColumn = 0; iColumn < number; iColumn++) {
2370               double value = columnUpper[iColumn];
2371               if (value > 1.0e20)
2372                    value = COIN_DBL_MAX;
2373               upper[iColumn] = value;
2374          }
2375     } else {
2376          for (iColumn = 0; iColumn < number; iColumn++) {
2377               upper[iColumn] = COIN_DBL_MAX;
2378          }
2379     }
2380     if (objIn) {
2381          for (iColumn = 0; iColumn < number; iColumn++) {
2382               obj[iColumn] = objIn[iColumn];
2383          }
2384     } else {
2385          for (iColumn = 0; iColumn < number; iColumn++) {
2386               obj[iColumn] = 0.0;
2387          }
2388     }
2389     // Deal with matrix
2390
2391     delete rowCopy_;
2392     rowCopy_ = NULL;
2393     delete scaledMatrix_;
2394     scaledMatrix_ = NULL;
2395     if (!matrix_)
2396          createEmptyMatrix();
2397     if (columns)
2398          matrix_->appendCols(number, columns);
2399     setRowScale(NULL);
2400     setColumnScale(NULL);
2401     if (lengthNames_) {
2402          columnNames_.resize(numberColumns_);
2403     }
2404}
2405#endif
2406#ifndef SLIM_CLP
2407// Add columns from a build object
2408int
2409ClpModel::addColumns(const CoinBuild & buildObject, bool tryPlusMinusOne, bool checkDuplicates)
2410{
2411     CoinAssertHint (buildObject.type() == 1, "Looks as if both addRows and addCols being used"); // check correct
2412     int number = buildObject.numberColumns();
2413     int numberErrors = 0;
2414     if (number) {
2415          CoinBigIndex size = 0;
2416          int maximumLength = 0;
2417          double * lower = new double [number];
2418          double * upper = new double [number];
2419          int iColumn;
2420          double * objective = new double [number];
2421          if ((!matrix_ || !matrix_->getNumElements()) && tryPlusMinusOne) {
2422               // See if can be +-1
2423               for (iColumn = 0; iColumn < number; iColumn++) {
2424                    const int * rows;
2425                    const double * elements;
2426                    int numberElements = buildObject.column(iColumn, lower[iColumn],
2427                                                            upper[iColumn], objective[iColumn],
2428                                                            rows, elements);
2429                    maximumLength = CoinMax(maximumLength, numberElements);
2430                    for (int i = 0; i < numberElements; i++) {
2431                         // allow for zero elements
2432                         if (elements[i]) {
2433                              if (fabs(elements[i]) == 1.0) {
2434                                   size++;
2435                              } else {
2436                                   // bad
2437                                   tryPlusMinusOne = false;
2438                              }
2439                         }
2440                    }
2441                    if (!tryPlusMinusOne)
2442                         break;
2443               }
2444          } else {
2445               // Will add to whatever sort of matrix exists
2446               tryPlusMinusOne = false;
2447          }
2448          if (!tryPlusMinusOne) {
2449               CoinBigIndex numberElements = buildObject.numberElements();
2450               CoinBigIndex * starts = new CoinBigIndex [number+1];
2451               int * row = new int[numberElements];
2452               double * element = new double[numberElements];
2453               starts[0] = 0;
2454               numberElements = 0;
2455               for (iColumn = 0; iColumn < number; iColumn++) {
2456                    const int * rows;
2457                    const double * elements;
2458                    int numberElementsThis = buildObject.column(iColumn, lower[iColumn], upper[iColumn],
2459                                             objective[iColumn], rows, elements);
2460                    CoinMemcpyN(rows, numberElementsThis, row + numberElements);
2461                    CoinMemcpyN(elements, numberElementsThis, element + numberElements);
2462                    numberElements += numberElementsThis;
2463                    starts[iColumn+1] = numberElements;
2464               }
2465               addColumns(number, lower, upper, objective, NULL);
2466               // make sure matrix has enough rows
2467               matrix_->setDimensions(numberRows_, -1);
2468               numberErrors = matrix_->appendMatrix(number, 1, starts, row, element,
2469                                                    checkDuplicates ? numberRows_ : -1);
2470               delete [] starts;
2471               delete [] row;
2472               delete [] element;
2473          } else {
2474               // arrays already filled in
2475               addColumns(number, lower, upper, objective, NULL);
2476               char * which = NULL; // for duplicates
2477               if (checkDuplicates) {
2478                    which = new char[numberRows_];
2479                    CoinZeroN(which, numberRows_);
2480               }
2481               // build +-1 matrix
2482               CoinBigIndex * startPositive = new CoinBigIndex [number+1];
2483               CoinBigIndex * startNegative = new CoinBigIndex [number];
2484               int * indices = new int [size];
2485               int * neg = new int[maximumLength];
2486               startPositive[0] = 0;
2487               size = 0;
2488               int maxRow = -1;
2489               for (iColumn = 0; iColumn < number; iColumn++) {
2490                    const int * rows;
2491                    const double * elements;
2492                    int numberElements = buildObject.column(iColumn, lower[iColumn],
2493                                                            upper[iColumn], objective[iColumn],
2494                                                            rows, elements);
2495                    int nNeg = 0;
2496                    CoinBigIndex start = size;
2497                    for (int i = 0; i < numberElements; i++) {
2498                         int iRow = rows[i];
2499                         if (checkDuplicates) {
2500                              if (iRow >= numberRows_) {
2501                                   if(which[iRow])
2502                                        numberErrors++;
2503                                   else
2504                                        which[iRow] = 1;
2505                              } else {
2506                                   numberErrors++;
2507                                   // and may as well switch off
2508                                   checkDuplicates = false;
2509                              }
2510                         }
2511                         maxRow = CoinMax(maxRow, iRow);
2512                         if (elements[i] == 1.0) {
2513                              indices[size++] = iRow;
2514                         } else if (elements[i] == -1.0) {
2515                              neg[nNeg++] = iRow;
2516                         }
2517                    }
2518                    std::sort(indices + start, indices + size);
2519                    std::sort(neg, neg + nNeg);
2520                    startNegative[iColumn] = size;
2521                    CoinMemcpyN(neg, nNeg, indices + size);
2522                    size += nNeg;
2523                    startPositive[iColumn+1] = size;
2524               }
2525               delete [] neg;
2526               // check size
2527               assert (maxRow + 1 <= numberRows_);
2528               // Get good object
2529               delete matrix_;
2530               ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
2531               matrix->passInCopy(numberRows_, number, true, indices, startPositive, startNegative);
2532               matrix_ = matrix;
2533               delete [] which;
2534          }
2535          delete [] objective;
2536          delete [] lower;
2537          delete [] upper;
2538     }
2539     return 0;
2540}
2541#endif
2542#ifndef SLIM_NOIO
2543// Add columns from a model object
2544int
2545ClpModel::addColumns( CoinModel & modelObject, bool tryPlusMinusOne, bool checkDuplicates)
2546{
2547     if (modelObject.numberElements() == 0)
2548          return 0;
2549     bool goodState = true;
2550     if (modelObject.rowLowerArray()) {
2551          // some row information exists
2552          int numberRows2 = modelObject.numberRows();
2553          const double * rowLower = modelObject.rowLowerArray();
2554          const double * rowUpper = modelObject.rowUpperArray();
2555          for (int i = 0; i < numberRows2; i++) {
2556               if (rowLower[i] != -COIN_DBL_MAX)
2557                    goodState = false;
2558               if (rowUpper[i] != COIN_DBL_MAX)
2559                    goodState = false;
2560          }
2561     }
2562     if (goodState) {
2563          // can do addColumns
2564          int numberErrors = 0;
2565          // Set arrays for normal use
2566          double * rowLower = modelObject.rowLowerArray();
2567          double * rowUpper = modelObject.rowUpperArray();
2568          double * columnLower = modelObject.columnLowerArray();
2569          double * columnUpper = modelObject.columnUpperArray();
2570          double * objective = modelObject.objectiveArray();
2571          int * integerType = modelObject.integerTypeArray();
2572          double * associated = modelObject.associatedArray();
2573          // If strings then do copies
2574          if (modelObject.stringsExist()) {
2575               numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper,
2576                                                       objective, integerType, associated);
2577          }
2578          int numberColumns = numberColumns_; // save number of columns
2579          int numberColumns2 = modelObject.numberColumns();
2580          if (numberColumns2 && !numberErrors) {
2581               CoinBigIndex * startPositive = NULL;
2582               CoinBigIndex * startNegative = NULL;
2583               if ((!matrix_ || !matrix_->getNumElements()) && !numberColumns && tryPlusMinusOne) {
2584                    startPositive = new CoinBigIndex[numberColumns2+1];
2585                    startNegative = new CoinBigIndex[numberColumns2];
2586                    modelObject.countPlusMinusOne(startPositive, startNegative, associated);
2587                    if (startPositive[0] < 0) {
2588                         // no good
2589                         tryPlusMinusOne = false;
2590                         delete [] startPositive;
2591                         delete [] startNegative;
2592                    }
2593               } else {
2594                    // Will add to whatever sort of matrix exists
2595                    tryPlusMinusOne = false;
2596               }
2597               assert (columnLower);
2598               addColumns(numberColumns2, columnLower, columnUpper, objective, NULL, NULL, NULL);
2599#ifndef SLIM_CLP
2600               if (!tryPlusMinusOne) {
2601#endif
2602                    /* addColumns just above extended matrix - to keep
2603                       things clean - take off again.  I know it is a bit
2604                       clumsy but won't break anything */
2605                    {
2606                      int * which = new int [numberColumns2];
2607                      for (int i=0;i<numberColumns2;i++)
2608                        which[i]=i+numberColumns;
2609                      matrix_->deleteCols(numberColumns2,which);
2610                      delete [] which;
2611                    }
2612                    CoinPackedMatrix matrix;
2613                    modelObject.createPackedMatrix(matrix, associated);
2614                    assert (!matrix.getExtraGap());
2615                    if (matrix_->getNumCols()) {
2616                         const int * row = matrix.getIndices();
2617                         //const int * columnLength = matrix.getVectorLengths();
2618                         const CoinBigIndex * columnStart = matrix.getVectorStarts();
2619                         const double * element = matrix.getElements();
2620                         // make sure matrix has enough rows
2621                         matrix_->setDimensions(numberRows_, -1);
2622                         numberErrors += matrix_->appendMatrix(numberColumns2, 1, columnStart, row, element,
2623                                                               checkDuplicates ? numberRows_ : -1);
2624                    } else {
2625                         delete matrix_;
2626                         matrix_ = new ClpPackedMatrix(matrix);
2627                    }
2628#ifndef SLIM_CLP
2629               } else {
2630                    // create +-1 matrix
2631                    CoinBigIndex size = startPositive[numberColumns2];
2632                    int * indices = new int[size];
2633                    modelObject.createPlusMinusOne(startPositive, startNegative, indices,
2634                                                   associated);
2635                    // Get good object
2636                    ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
2637                    matrix->passInCopy(numberRows_, numberColumns2,
2638                                       true, indices, startPositive, startNegative);
2639                    delete matrix_;
2640                    matrix_ = matrix;
2641               }
2642#endif
2643#ifndef CLP_NO_STD
2644               // Do names if wanted
2645               if (modelObject.columnNames()->numberItems()) {
2646                    const char *const * columnNames = modelObject.columnNames()->names();
2647                    copyColumnNames(columnNames, numberColumns, numberColumns_);
2648               }
2649#endif
2650               // Do integers if wanted
2651               assert(integerType);
2652               for (int iColumn = 0; iColumn < numberColumns2; iColumn++) {
2653                    if (integerType[iColumn])
2654                         setInteger(iColumn + numberColumns);
2655               }
2656          }
2657          if (columnLower != modelObject.columnLowerArray()) {
2658               delete [] rowLower;
2659               delete [] rowUpper;
2660               delete [] columnLower;
2661               delete [] columnUpper;
2662               delete [] objective;
2663               delete [] integerType;
2664               delete [] associated;
2665               if (numberErrors)
2666                    handler_->message(CLP_BAD_STRING_VALUES, messages_)
2667                              << numberErrors
2668                              << CoinMessageEol;
2669          }
2670          return numberErrors;
2671     } else {
2672          // not suitable for addColumns
2673          handler_->message(CLP_COMPLICATED_MODEL, messages_)
2674                    << modelObject.numberRows()
2675                    << modelObject.numberColumns()
2676                    << CoinMessageEol;
2677          return -1;
2678     }
2679}
2680#endif
2681// chgRowLower
2682void
2683ClpModel::chgRowLower(const double * rowLower)
2684{
2685     int numberRows = numberRows_;
2686     int iRow;
2687     whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2688     if (rowLower) {
2689          for (iRow = 0; iRow < numberRows; iRow++) {
2690               double value = rowLower[iRow];
2691               if (value < -1.0e20)
2692                    value = -COIN_DBL_MAX;
2693               rowLower_[iRow] = value;
2694          }
2695     } else {
2696          for (iRow = 0; iRow < numberRows; iRow++) {
2697               rowLower_[iRow] = -COIN_DBL_MAX;
2698          }
2699     }
2700}
2701// chgRowUpper
2702void
2703ClpModel::chgRowUpper(const double * rowUpper)
2704{
2705     whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2706     int numberRows = numberRows_;
2707     int iRow;
2708     if (rowUpper) {
2709          for (iRow = 0; iRow < numberRows; iRow++) {
2710               double value = rowUpper[iRow];
2711               if (value > 1.0e20)
2712                    value = COIN_DBL_MAX;
2713               rowUpper_[iRow] = value;
2714          }
2715     } else {
2716          for (iRow = 0; iRow < numberRows; iRow++) {
2717               rowUpper_[iRow] = COIN_DBL_MAX;;
2718          }
2719     }
2720}
2721// chgColumnLower
2722void
2723ClpModel::chgColumnLower(const double * columnLower)
2724{
2725     whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2726     int numberColumns = numberColumns_;
2727     int iColumn;
2728     if (columnLower) {
2729          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2730               double value = columnLower[iColumn];
2731               if (value < -1.0e20)
2732                    value = -COIN_DBL_MAX;
2733               columnLower_[iColumn] = value;
2734          }
2735     } else {
2736          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2737               columnLower_[iColumn] = 0.0;
2738          }
2739     }
2740}
2741// chgColumnUpper
2742void
2743ClpModel::chgColumnUpper(const double * columnUpper)
2744{
2745     whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2746     int numberColumns = numberColumns_;
2747     int iColumn;
2748     if (columnUpper) {
2749          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2750               double value = columnUpper[iColumn];
2751               if (value > 1.0e20)
2752                    value = COIN_DBL_MAX;
2753               columnUpper_[iColumn] = value;
2754          }
2755     } else {
2756          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2757               columnUpper_[iColumn] = COIN_DBL_MAX;;
2758          }
2759     }
2760}
2761// chgObjCoefficients
2762void
2763ClpModel::chgObjCoefficients(const double * objIn)
2764{
2765     whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2766     double * obj = objective();
2767     int numberColumns = numberColumns_;
2768     int iColumn;
2769     if (objIn) {
2770          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2771               obj[iColumn] = objIn[iColumn];
2772          }
2773     } else {
2774          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2775               obj[iColumn] = 0.0;
2776          }
2777     }
2778}
2779// Infeasibility/unbounded ray (NULL returned if none/wrong)
2780double *
2781ClpModel::infeasibilityRay(bool fullRay) const
2782{
2783     double * array = NULL;
2784     if (problemStatus_ == 1 && ray_) {
2785       if (!fullRay) {
2786         array = ClpCopyOfArray(ray_, numberRows_);
2787       } else {
2788         array = new double [numberRows_+numberColumns_];
2789         memcpy(array,ray_,numberRows_*sizeof(double));
2790         memset(array+numberRows_,0,numberColumns_*sizeof(double));
2791         transposeTimes(-1.0,array,array+numberRows_);
2792       }
2793     }
2794     return array;
2795}
2796double *
2797ClpModel::unboundedRay() const
2798{
2799     double * array = NULL;
2800     if (problemStatus_ == 2)
2801          array = ClpCopyOfArray(ray_, numberColumns_);
2802     return array;
2803}
2804void
2805ClpModel::setMaximumIterations(int value)
2806{
2807     if(value >= 0)
2808          intParam_[ClpMaxNumIteration] = value;
2809}
2810void
2811ClpModel::setMaximumSeconds(double value)
2812{
2813     if(value >= 0)
2814          dblParam_[ClpMaxSeconds] = value + CoinCpuTime();
2815     else
2816          dblParam_[ClpMaxSeconds] = -1.0;
2817}
2818void
2819ClpModel::setMaximumWallSeconds(double value)
2820{
2821     if(value >= 0)
2822          dblParam_[ClpMaxWallSeconds] = value + CoinWallclockTime();
2823     else
2824          dblParam_[ClpMaxWallSeconds] = -1.0;
2825}
2826// Returns true if hit maximum iterations (or time)
2827bool
2828ClpModel::hitMaximumIterations() const
2829{
2830     // replaced - compiler error? bool hitMax= (numberIterations_>=maximumIterations());
2831     bool hitMax = (numberIterations_ >= intParam_[ClpMaxNumIteration]);
2832     if (dblParam_[ClpMaxSeconds] >= 0.0 && !hitMax) {
2833          hitMax = (CoinCpuTime() >= dblParam_[ClpMaxSeconds]);
2834     }
2835     if (dblParam_[ClpMaxWallSeconds] >= 0.0 && !hitMax) {
2836          hitMax = (CoinWallclockTime() >= dblParam_[ClpMaxWallSeconds]);
2837     }
2838     return hitMax;
2839}
2840// On stopped - sets secondary status
2841void
2842ClpModel::onStopped()
2843{
2844     if (problemStatus_ == 3) {
2845          secondaryStatus_ = 0;
2846          if ((CoinCpuTime() >= dblParam_[ClpMaxSeconds] && dblParam_[ClpMaxSeconds] >= 0.0) ||
2847              (CoinWallclockTime() >= dblParam_[ClpMaxWallSeconds] && dblParam_[ClpMaxWallSeconds] >= 0.0))
2848               secondaryStatus_ = 9;
2849     }
2850}
2851// Pass in Message handler (not deleted at end)
2852void
2853ClpModel::passInMessageHandler(CoinMessageHandler * handler)
2854{
2855     if (defaultHandler_)
2856          delete handler_;
2857     defaultHandler_ = false;
2858     handler_ = handler;
2859}
2860// Pass in Message handler (not deleted at end) and return current
2861CoinMessageHandler *
2862ClpModel::pushMessageHandler(CoinMessageHandler * handler,
2863                             bool & oldDefault)
2864{
2865     CoinMessageHandler * returnValue = handler_;
2866     oldDefault = defaultHandler_;
2867     defaultHandler_ = false;
2868     handler_ = handler;
2869     return returnValue;
2870}
2871// back to previous message handler
2872void
2873ClpModel::popMessageHandler(CoinMessageHandler * oldHandler, bool oldDefault)
2874{
2875     if (defaultHandler_)
2876          delete handler_;
2877     defaultHandler_ = oldDefault;
2878     handler_ = oldHandler;
2879}
2880// Overrides message handler with a default one
2881void 
2882ClpModel::setDefaultMessageHandler()
2883{
2884     int logLevel = handler_->logLevel();
2885     if (defaultHandler_)
2886          delete handler_;
2887     defaultHandler_ = true;
2888     handler_ = new CoinMessageHandler();
2889     handler_->setLogLevel(logLevel);
2890}
2891// Set language
2892void
2893ClpModel::newLanguage(CoinMessages::Language language)
2894{
2895     messages_ = ClpMessage(language);
2896}
2897#ifndef SLIM_NOIO
2898// Read an mps file from the given filename
2899int
2900ClpModel::readMps(const char *fileName,
2901                  bool keepNames,
2902                  bool ignoreErrors)
2903{
2904     if (!strcmp(fileName, "-") || !strcmp(fileName, "stdin")) {
2905          // stdin
2906     } else {
2907          std::string name = fileName;
2908          bool readable = fileCoinReadable(name);
2909          if (!readable) {
2910               handler_->message(CLP_UNABLE_OPEN, messages_)
2911                         << fileName << CoinMessageEol;
2912               return -1;
2913          }
2914     }
2915     CoinMpsIO m;
2916     m.passInMessageHandler(handler_);
2917     *m.messagesPointer() = coinMessages();
2918     bool savePrefix = m.messageHandler()->prefix();
2919     m.messageHandler()->setPrefix(handler_->prefix());
2920     m.setSmallElementValue(CoinMax(smallElement_, m.getSmallElementValue()));
2921     double time1 = CoinCpuTime(), time2;
2922     int status = 0;
2923     try {
2924          status = m.readMps(fileName, "");
2925     } catch (CoinError e) {
2926          e.print();
2927          status = -1;
2928     }
2929     m.messageHandler()->setPrefix(savePrefix);
2930     if (!status || (ignoreErrors && (status > 0 && status < 100000))) {
2931          loadProblem(*m.getMatrixByCol(),
2932                      m.getColLower(), m.getColUpper(),
2933                      m.getObjCoefficients(),
2934                      m.getRowLower(), m.getRowUpper());
2935          if (m.integerColumns()) {
2936               integerType_ = new char[numberColumns_];
2937               CoinMemcpyN(m.integerColumns(), numberColumns_, integerType_);
2938          } else {
2939               integerType_ = NULL;
2940          }
2941#ifndef SLIM_CLP
2942          // get quadratic part
2943          if (m.reader()->whichSection (  ) == COIN_QUAD_SECTION ) {
2944               int * start = NULL;
2945               int * column = NULL;
2946               double * element = NULL;
2947               status = m.readQuadraticMps(NULL, start, column, element, 2);
2948               if (!status || ignoreErrors)
2949                    loadQuadraticObjective(numberColumns_, start, column, element);
2950               delete [] start;
2951               delete [] column;
2952               delete [] element;
2953          }
2954#endif
2955#ifndef CLP_NO_STD
2956          // set problem name
2957          setStrParam(ClpProbName, m.getProblemName());
2958          // do names
2959          if (keepNames) {
2960               unsigned int maxLength = 0;
2961               int iRow;
2962               rowNames_ = std::vector<std::string> ();
2963               columnNames_ = std::vector<std::string> ();
2964               rowNames_.reserve(numberRows_);
2965               for (iRow = 0; iRow < numberRows_; iRow++) {
2966                    const char * name = m.rowName(iRow);
2967                    maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
2968                    rowNames_.push_back(name);
2969               }
2970
2971               int iColumn;
2972               columnNames_.reserve(numberColumns_);
2973               for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2974                    const char * name = m.columnName(iColumn);
2975                    maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
2976                    columnNames_.push_back(name);
2977               }
2978               lengthNames_ = static_cast<int> (maxLength);
2979          } else {
2980               lengthNames_ = 0;
2981          }
2982#endif
2983          setDblParam(ClpObjOffset, m.objectiveOffset());
2984          time2 = CoinCpuTime();
2985          handler_->message(CLP_IMPORT_RESULT, messages_)
2986                    << fileName
2987                    << time2 - time1 << CoinMessageEol;
2988     } else {
2989          // errors
2990          handler_->message(CLP_IMPORT_ERRORS, messages_)
2991                    << status << fileName << CoinMessageEol;
2992     }
2993
2994     return status;
2995}
2996// Read GMPL files from the given filenames
2997int
2998ClpModel::readGMPL(const char *fileName, const char * dataName,
2999                   bool keepNames)
3000{
3001     FILE *fp = fopen(fileName, "r");
3002     if (fp) {
3003          // can open - lets go for it
3004          fclose(fp);
3005          if (dataName) {
3006               fp = fopen(dataName, "r");
3007               if (fp) {
3008                    fclose(fp);
3009               } else {
3010                    handler_->message(CLP_UNABLE_OPEN, messages_)
3011                              << dataName << CoinMessageEol;
3012                    return -1;
3013               }
3014          }
3015     } else {
3016          handler_->message(CLP_UNABLE_OPEN, messages_)
3017                    << fileName << CoinMessageEol;
3018          return -1;
3019     }
3020     CoinMpsIO m;
3021     m.passInMessageHandler(handler_);
3022     *m.messagesPointer() = coinMessages();
3023     bool savePrefix = m.messageHandler()->prefix();
3024     m.messageHandler()->setPrefix(handler_->prefix());
3025     double time1 = CoinCpuTime(), time2;
3026     int status = m.readGMPL(fileName, dataName, keepNames);
3027     m.messageHandler()->setPrefix(savePrefix);
3028     if (!status) {
3029          loadProblem(*m.getMatrixByCol(),
3030                      m.getColLower(), m.getColUpper(),
3031                      m.getObjCoefficients(),
3032                      m.getRowLower(), m.getRowUpper());
3033          if (m.integerColumns()) {
3034               integerType_ = new char[numberColumns_];
3035               CoinMemcpyN(m.integerColumns(), numberColumns_, integerType_);
3036          } else {
3037               integerType_ = NULL;
3038          }
3039#ifndef CLP_NO_STD
3040          // set problem name
3041          setStrParam(ClpProbName, m.getProblemName());
3042          // do names
3043          if (keepNames) {
3044               unsigned int maxLength = 0;
3045               int iRow;
3046               rowNames_ = std::vector<std::string> ();
3047               columnNames_ = std::vector<std::string> ();
3048               rowNames_.reserve(numberRows_);
3049               for (iRow = 0; iRow < numberRows_; iRow++) {
3050                    const char * name = m.rowName(iRow);
3051                    maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
3052                    rowNames_.push_back(name);
3053               }
3054
3055               int iColumn;
3056               columnNames_.reserve(numberColumns_);
3057               for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
3058                    const char * name = m.columnName(iColumn);
3059                    maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
3060                    columnNames_.push_back(name);
3061               }
3062               lengthNames_ = static_cast<int> (maxLength);
3063          } else {
3064               lengthNames_ = 0;
3065          }
3066#endif
3067          setDblParam(ClpObjOffset, m.objectiveOffset());
3068          time2 = CoinCpuTime();
3069          handler_->message(CLP_IMPORT_RESULT, messages_)
3070                    << fileName
3071                    << time2 - time1 << CoinMessageEol;
3072     } else {
3073          // errors
3074          handler_->message(CLP_IMPORT_ERRORS, messages_)
3075                    << status << fileName << CoinMessageEol;
3076     }
3077     return status;
3078}
3079#endif
3080bool ClpModel::isPrimalObjectiveLimitReached() const
3081{
3082     double limit = 0.0;
3083     getDblParam(ClpPrimalObjectiveLimit, limit);
3084     if (limit > 1e30) {
3085          // was not ever set
3086          return false;
3087     }
3088
3089     const double obj = objectiveValue();
3090     const double maxmin = optimizationDirection();
3091
3092     if (problemStatus_ == 0) // optimal
3093          return maxmin > 0 ? (obj < limit) /*minim*/ : (-obj < limit) /*maxim*/;
3094     else if (problemStatus_ == 2)
3095          return true;
3096     else
3097          return false;
3098}
3099
3100bool ClpModel::isDualObjectiveLimitReached() const
3101{
3102
3103     double limit = 0.0;
3104     getDblParam(ClpDualObjectiveLimit, limit);
3105     if (limit > 1e30) {
3106          // was not ever set
3107          return false;
3108     }
3109
3110     const double obj = objectiveValue();
3111     const double maxmin = optimizationDirection();
3112
3113     if (problemStatus_ == 0) // optimal
3114          return maxmin > 0 ? (obj > limit) /*minim*/ : (-obj > limit) /*maxim*/;
3115     else if (problemStatus_ == 1)
3116          return true;
3117     else
3118          return false;
3119
3120}
3121void
3122ClpModel::copyInIntegerInformation(const char * information)
3123{
3124     delete [] integerType_;
3125     if (information) {
3126          integerType_ = new char[numberColumns_];
3127          CoinMemcpyN(information, numberColumns_, integerType_);
3128     } else {
3129          integerType_ = NULL;
3130     }
3131}
3132void
3133ClpModel::setContinuous(int index)
3134{
3135
3136     if (integerType_) {
3137#ifndef NDEBUG
3138          if (index < 0 || index >= numberColumns_) {
3139               indexError(index, "setContinuous");
3140          }
3141#endif
3142          integerType_[index] = 0;
3143     }
3144}
3145//-----------------------------------------------------------------------------
3146void
3147ClpModel::setInteger(int index)
3148{
3149     if (!integerType_) {
3150          integerType_ = new char[numberColumns_];
3151          CoinZeroN ( integerType_, numberColumns_);
3152     }
3153#ifndef NDEBUG
3154     if (index < 0 || index >= numberColumns_) {
3155          indexError(index, "setInteger");
3156     }
3157#endif
3158     integerType_[index] = 1;
3159}
3160/* Return true if the index-th variable is an integer variable */
3161bool
3162ClpModel::isInteger(int index) const
3163{
3164     if (!integerType_) {
3165          return false;
3166     } else {
3167#ifndef NDEBUG
3168          if (index < 0 || index >= numberColumns_) {
3169               indexError(index, "isInteger");
3170          }
3171#endif
3172          return (integerType_[index] != 0);
3173     }
3174}
3175#ifndef CLP_NO_STD
3176// Drops names - makes lengthnames 0 and names empty
3177void
3178ClpModel::dropNames()
3179{
3180     lengthNames_ = 0;
3181     rowNames_ = std::vector<std::string> ();
3182     columnNames_ = std::vector<std::string> ();
3183}
3184#endif
3185// Drop integer informations
3186void
3187ClpModel::deleteIntegerInformation()
3188{
3189     delete [] integerType_;
3190     integerType_ = NULL;
3191}
3192/* Return copy of status array (char[numberRows+numberColumns]),
3193   use delete [] */
3194unsigned char *
3195ClpModel::statusCopy() const
3196{
3197     return ClpCopyOfArray(status_, numberRows_ + numberColumns_);
3198}
3199// Copy in status vector
3200void
3201ClpModel::copyinStatus(const unsigned char * statusArray)
3202{
3203     delete [] status_;
3204     if (statusArray) {
3205          status_ = new unsigned char [numberRows_+numberColumns_];
3206          CoinMemcpyN(statusArray, (numberRows_ + numberColumns_), status_);
3207     } else {
3208          status_ = NULL;
3209     }
3210}
3211#ifndef SLIM_CLP
3212// Load up quadratic objective
3213void
3214ClpModel::loadQuadraticObjective(const int numberColumns, const CoinBigIndex * start,
3215                                 const int * column, const double * element)
3216{
3217     whatsChanged_ = 0; // Use ClpSimplex stuff to keep
3218     CoinAssert (numberColumns == numberColumns_);
3219     assert ((dynamic_cast< ClpLinearObjective*>(objective_)));
3220     double offset;
3221     ClpObjective * obj = new ClpQuadraticObjective(objective_->gradient(NULL, NULL, offset, false),
3222               numberColumns,
3223               start, column, element);
3224     delete objective_;
3225     objective_ = obj;
3226
3227}
3228void
3229ClpModel::loadQuadraticObjective (  const CoinPackedMatrix& matrix)
3230{
3231     whatsChanged_ = 0; // Use ClpSimplex stuff to keep
3232     CoinAssert (matrix.getNumCols() == numberColumns_);
3233     assert ((dynamic_cast< ClpLinearObjective*>(objective_)));
3234     double offset;
3235     ClpQuadraticObjective * obj =
3236          new ClpQuadraticObjective(objective_->gradient(NULL, NULL, offset, false),
3237                                    numberColumns_,
3238                                    NULL, NULL, NULL);
3239     delete objective_;
3240     objective_ = obj;
3241     obj->loadQuadraticObjective(matrix);
3242}
3243// Get rid of quadratic objective
3244void
3245ClpModel::deleteQuadraticObjective()
3246{
3247     whatsChanged_ = 0; // Use ClpSimplex stuff to keep
3248     ClpQuadraticObjective * obj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
3249     if (obj)
3250          obj->deleteQuadraticObjective();
3251}
3252#endif
3253void
3254ClpModel::setObjective(ClpObjective * objective)
3255{
3256     whatsChanged_ = 0; // Use ClpSimplex stuff to keep
3257     delete objective_;
3258     objective_ = objective->clone();
3259}
3260// Returns resized array and updates size
3261double * whichDouble(double * array , int number, const int * which)
3262{
3263     double * newArray = NULL;
3264     if (array && number) {
3265          int i ;
3266          newArray = new double[number];
3267          for (i = 0; i < number; i++)
3268               newArray[i] = array[which[i]];
3269     }
3270     return newArray;
3271}
3272char * whichChar(char * array , int number, const int * which)
3273{
3274     char * newArray = NULL;
3275     if (array && number) {
3276          int i ;
3277          newArray = new char[number];
3278          for (i = 0; i < number; i++)
3279               newArray[i] = array[which[i]];
3280     }
3281     return newArray;
3282}
3283unsigned char * whichUnsignedChar(unsigned char * array ,
3284                                  int number, const int * which)
3285{
3286     unsigned char * newArray = NULL;
3287     if (array && number) {
3288          int i ;
3289          newArray = new unsigned char[number];
3290          for (i = 0; i < number; i++)
3291               newArray[i] = array[which[i]];
3292     }
3293     return newArray;
3294}
3295// Replace Clp Matrix (current is not deleted)
3296void
3297ClpModel::replaceMatrix( ClpMatrixBase * matrix, bool deleteCurrent)
3298{
3299     if (deleteCurrent)
3300          delete matrix_;
3301     matrix_ = matrix;
3302     whatsChanged_ = 0; // Too big a change
3303}
3304// Subproblem constructor
3305ClpModel::ClpModel ( const ClpModel * rhs,
3306                     int numberRows, const int * whichRow,
3307                     int numberColumns, const int * whichColumn,
3308                     bool dropNames, bool dropIntegers)
3309     :  specialOptions_(rhs->specialOptions_),
3310        maximumColumns_(-1),
3311        maximumRows_(-1),
3312        maximumInternalColumns_(-1),
3313        maximumInternalRows_(-1),
3314        savedRowScale_(NULL),
3315        savedColumnScale_(NULL)
3316{
3317     defaultHandler_ = rhs->defaultHandler_;
3318     if (defaultHandler_)
3319          handler_ = new CoinMessageHandler(*rhs->handler_);
3320     else
3321          handler_ = rhs->handler_;
3322     eventHandler_ = rhs->eventHandler_->clone();
3323     randomNumberGenerator_ = rhs->randomNumberGenerator_;
3324     messages_ = rhs->messages_;
3325     coinMessages_ = rhs->coinMessages_;
3326     maximumColumns_ = -1;
3327     maximumRows_ = -1;
3328     maximumInternalColumns_ = -1;
3329     maximumInternalRows_ = -1;
3330     savedRowScale_ = NULL;
3331     savedColumnScale_ = NULL;
3332     intParam_[ClpMaxNumIteration] = rhs->intParam_[ClpMaxNumIteration];
3333     intParam_[ClpMaxNumIterationHotStart] =
3334          rhs->intParam_[ClpMaxNumIterationHotStart];
3335     intParam_[ClpNameDiscipline] = rhs->intParam_[ClpNameDiscipline] ;
3336
3337     dblParam_[ClpDualObjectiveLimit] = rhs->dblParam_[ClpDualObjectiveLimit];
3338     dblParam_[ClpPrimalObjectiveLimit] = rhs->dblParam_[ClpPrimalObjectiveLimit];
3339     dblParam_[ClpDualTolerance] = rhs->dblParam_[ClpDualTolerance];
3340     dblParam_[ClpPrimalTolerance] = rhs->dblParam_[ClpPrimalTolerance];
3341     dblParam_[ClpObjOffset] = rhs->dblParam_[ClpObjOffset];
3342     dblParam_[ClpMaxSeconds] = rhs->dblParam_[ClpMaxSeconds];
3343     dblParam_[ClpMaxWallSeconds] = rhs->dblParam_[ClpMaxWallSeconds];
3344     dblParam_[ClpPresolveTolerance] = rhs->dblParam_[ClpPresolveTolerance];
3345#ifndef CLP_NO_STD
3346     strParam_[ClpProbName] = rhs->strParam_[ClpProbName];
3347#endif
3348     specialOptions_ = rhs->specialOptions_;
3349     optimizationDirection_ = rhs->optimizationDirection_;
3350     objectiveValue_ = rhs->objectiveValue_;
3351     smallElement_ = rhs->smallElement_;
3352     objectiveScale_ = rhs->objectiveScale_;
3353     rhsScale_ = rhs->rhsScale_;
3354     numberIterations_ = rhs->numberIterations_;
3355     solveType_ = rhs->solveType_;
3356     whatsChanged_ = 0; // Too big a change
3357     problemStatus_ = rhs->problemStatus_;
3358     secondaryStatus_ = rhs->secondaryStatus_;
3359     // check valid lists
3360     int numberBad = 0;
3361     int i;
3362     for (i = 0; i < numberRows; i++)
3363          if (whichRow[i] < 0 || whichRow[i] >= rhs->numberRows_)
3364               numberBad++;
3365     CoinAssertHint(!numberBad, "Bad row list for subproblem constructor");
3366     numberBad = 0;
3367     for (i = 0; i < numberColumns; i++)
3368          if (whichColumn[i] < 0 || whichColumn[i] >= rhs->numberColumns_)
3369               numberBad++;
3370     CoinAssertHint(!numberBad, "Bad Column list for subproblem constructor");
3371     numberRows_ = numberRows;
3372     numberColumns_ = numberColumns;
3373     userPointer_ = rhs->userPointer_;
3374     trustedUserPointer_ = rhs->trustedUserPointer_;
3375     numberThreads_ = 0;
3376#ifndef CLP_NO_STD
3377     if (!dropNames) {
3378          unsigned int maxLength = 0;
3379          int iRow;
3380          rowNames_ = std::vector<std::string> ();
3381          columnNames_ = std::vector<std::string> ();
3382          rowNames_.reserve(numberRows_);
3383          for (iRow = 0; iRow < numberRows_; iRow++) {
3384               rowNames_.push_back(rhs->rowNames_[whichRow[iRow]]);
3385               maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(rowNames_[iRow].c_str())));
3386          }
3387          int iColumn;
3388          columnNames_.reserve(numberColumns_);
3389          for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
3390               columnNames_.push_back(rhs->columnNames_[whichColumn[iColumn]]);
3391               maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(columnNames_[iColumn].c_str())));
3392          }
3393          lengthNames_ = static_cast<int> (maxLength);
3394     } else {
3395          lengthNames_ = 0;
3396          rowNames_ = std::vector<std::string> ();
3397          columnNames_ = std::vector<std::string> ();
3398     }
3399#endif
3400     if (rhs->integerType_ && !dropIntegers) {
3401          integerType_ = whichChar(rhs->integerType_, numberColumns, whichColumn);
3402     } else {
3403          integerType_ = NULL;
3404     }
3405     if (rhs->rowActivity_) {
3406          rowActivity_ = whichDouble(rhs->rowActivity_, numberRows, whichRow);
3407          dual_ = whichDouble(rhs->dual_, numberRows, whichRow);
3408          columnActivity_ = whichDouble(rhs->columnActivity_, numberColumns,
3409                                        whichColumn);
3410          reducedCost_ = whichDouble(rhs->reducedCost_, numberColumns,
3411                                     whichColumn);
3412     } else {
3413          rowActivity_ = NULL;
3414          columnActivity_ = NULL;
3415          dual_ = NULL;
3416          reducedCost_ = NULL;
3417     }
3418     rowLower_ = whichDouble(rhs->rowLower_, numberRows, whichRow);
3419     rowUpper_ = whichDouble(rhs->rowUpper_, numberRows, whichRow);
3420     columnLower_ = whichDouble(rhs->columnLower_, numberColumns, whichColumn);
3421     columnUpper_ = whichDouble(rhs->columnUpper_, numberColumns, whichColumn);
3422     if (rhs->objective_)
3423          objective_  = rhs->objective_->subsetClone(numberColumns, whichColumn);
3424     else
3425          objective_ = NULL;
3426     rowObjective_ = whichDouble(rhs->rowObjective_, numberRows, whichRow);
3427     // status has to be done in two stages
3428     if (rhs->status_) {
3429       status_ = new unsigned char[numberColumns_+numberRows_];
3430       unsigned char * rowStatus = whichUnsignedChar(rhs->status_ + rhs->numberColumns_,
3431                                                     numberRows_, whichRow);
3432       unsigned char * columnStatus = whichUnsignedChar(rhs->status_,
3433                                                        numberColumns_, whichColumn);
3434       CoinMemcpyN(rowStatus, numberRows_, status_ + numberColumns_);
3435       delete [] rowStatus;
3436       CoinMemcpyN(columnStatus, numberColumns_, status_);
3437       delete [] columnStatus;
3438     } else {
3439       status_=NULL;
3440     }
3441     ray_ = NULL;
3442     if (problemStatus_ == 1)
3443          ray_ = whichDouble (rhs->ray_, numberRows, whichRow);
3444     else if (problemStatus_ == 2)
3445          ray_ = whichDouble (rhs->ray_, numberColumns, whichColumn);
3446     rowScale_ = NULL;
3447     columnScale_ = NULL;
3448     inverseRowScale_ = NULL;
3449     inverseColumnScale_ = NULL;
3450     scalingFlag_ = rhs->scalingFlag_;
3451     rowCopy_ = NULL;
3452     scaledMatrix_ = NULL;
3453     matrix_ = NULL;
3454     if (rhs->matrix_) {
3455          matrix_ = rhs->matrix_->subsetClone(numberRows, whichRow,
3456                                              numberColumns, whichColumn);
3457     }
3458     randomNumberGenerator_ = rhs->randomNumberGenerator_;
3459}
3460#ifndef CLP_NO_STD
3461// Copies in names
3462void
3463ClpModel::copyNames(const std::vector<std::string> & rowNames,
3464                    const std::vector<std::string> & columnNames)
3465{
3466     unsigned int maxLength = 0;
3467     int iRow;
3468     rowNames_ = std::vector<std::string> ();
3469     columnNames_ = std::vector<std::string> ();
3470     rowNames_.reserve(numberRows_);
3471     for (iRow = 0; iRow < numberRows_; iRow++) {
3472          rowNames_.push_back(rowNames[iRow]);
3473          maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(rowNames_[iRow].c_str())));
3474     }
3475     int iColumn;
3476     columnNames_.reserve(numberColumns_);
3477     for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
3478          columnNames_.push_back(columnNames[iColumn]);
3479          maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(columnNames_[iColumn].c_str())));
3480     }
3481     lengthNames_ = static_cast<int> (maxLength);
3482}
3483// Return name or Rnnnnnnn
3484std::string
3485ClpModel::getRowName(int iRow) const
3486{
3487#ifndef NDEBUG
3488     if (iRow < 0 || iRow >= numberRows_) {
3489          indexError(iRow, "getRowName");
3490     }
3491#endif
3492     int size = static_cast<int>(rowNames_.size());
3493     if (size > iRow) {
3494          return rowNames_[iRow];
3495     } else {
3496          char name[9];
3497          sprintf(name, "R%7.7d", iRow);
3498          std::string rowName(name);
3499          return rowName;
3500     }
3501}
3502// Set row name
3503void
3504ClpModel::setRowName(int iRow, std::string &name)
3505{
3506#ifndef NDEBUG
3507     if (iRow < 0 || iRow >= numberRows_) {
3508          indexError(iRow, "setRowName");
3509     }
3510#endif
3511     unsigned int maxLength = lengthNames_;
3512     int size = static_cast<int>(rowNames_.size());
3513     if (size <= iRow)
3514          rowNames_.resize(iRow + 1);
3515     rowNames_[iRow] = name;
3516     maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name.c_str())));
3517     // May be too big - but we would have to check both rows and columns to be exact
3518     lengthNames_ = static_cast<int> (maxLength);
3519}
3520// Return name or Cnnnnnnn
3521std::string
3522ClpModel::getColumnName(int iColumn) const
3523{
3524#ifndef NDEBUG
3525     if (iColumn < 0 || iColumn >= numberColumns_) {
3526          indexError(iColumn, "getColumnName");
3527     }
3528#endif
3529     int size = static_cast<int>(columnNames_.size());
3530     if (size > iColumn) {
3531          return columnNames_[iColumn];
3532     } else {
3533          char name[9];
3534          sprintf(name, "C%7.7d", iColumn);
3535          std::string columnName(name);
3536          return columnName;
3537     }
3538}
3539// Set column name
3540void
3541ClpModel::setColumnName(int iColumn, std::string &name)
3542{
3543#ifndef NDEBUG
3544     if (iColumn < 0 || iColumn >= numberColumns_) {
3545          indexError(iColumn, "setColumnName");
3546     }
3547#endif
3548     unsigned int maxLength = lengthNames_;
3549     int size = static_cast<int>(columnNames_.size());
3550     if (size <= iColumn)
3551          columnNames_.resize(iColumn + 1);
3552     columnNames_[iColumn] = name;
3553     maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name.c_str())));
3554     // May be too big - but we would have to check both columns and columns to be exact
3555     lengthNames_ = static_cast<int> (maxLength);
3556}
3557// Copies in Row names - modifies names first .. last-1
3558void
3559ClpModel::copyRowNames(const std::vector<std::string> & rowNames, int first, int last)
3560{
3561     // Do column names if necessary
3562     if (!lengthNames_&&numberColumns_) {
3563       lengthNames_=8;
3564       copyColumnNames(NULL,0,numberColumns_);
3565     }
3566     unsigned int maxLength = lengthNames_;
3567     int size = static_cast<int>(rowNames_.size());
3568     if (size != numberRows_)
3569          rowNames_.resize(numberRows_);
3570     int iRow;
3571     for (iRow = first; iRow < last; iRow++) {
3572          rowNames_[iRow] = rowNames[iRow-first];
3573          maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(rowNames_[iRow-first].c_str())));
3574     }
3575     // May be too big - but we would have to check both rows and columns to be exact
3576     lengthNames_ = static_cast<int> (maxLength);
3577}
3578// Copies in Column names - modifies names first .. last-1
3579void
3580ClpModel::copyColumnNames(const std::vector<std::string> & columnNames, int first, int last)
3581{
3582     // Do row names if necessary
3583     if (!lengthNames_&&numberRows_) {
3584       lengthNames_=8;
3585       copyRowNames(NULL,0,numberRows_);
3586     }
3587     unsigned int maxLength = lengthNames_;
3588     int size = static_cast<int>(columnNames_.size());
3589     if (size != numberColumns_)
3590          columnNames_.resize(numberColumns_);
3591     int iColumn;
3592     for (iColumn = first; iColumn < last; iColumn++) {
3593          columnNames_[iColumn] = columnNames[iColumn-first];
3594          maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(columnNames_[iColumn-first].c_str())));
3595     }
3596     // May be too big - but we would have to check both rows and columns to be exact
3597     lengthNames_ = static_cast<int> (maxLength);
3598}
3599// Copies in Row names - modifies names first .. last-1
3600void
3601ClpModel::copyRowNames(const char * const * rowNames, int first, int last)
3602{
3603     // Do column names if necessary
3604     if (!lengthNames_&&numberColumns_) {
3605       lengthNames_=8;
3606       copyColumnNames(NULL,0,numberColumns_);
3607     }
3608     unsigned int maxLength = lengthNames_;
3609     int size = static_cast<int>(rowNames_.size());
3610     if (size != numberRows_)
3611          rowNames_.resize(numberRows_);
3612     int iRow;
3613     for (iRow = first; iRow < last; iRow++) {
3614          if (rowNames && rowNames[iRow-first] && strlen(rowNames[iRow-first])) {
3615               rowNames_[iRow] = rowNames[iRow-first];
3616               maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(rowNames[iRow-first])));
3617          } else {
3618               maxLength = CoinMax(maxLength, static_cast<unsigned int> (8));
3619               char name[9];
3620               sprintf(name, "R%7.7d", iRow);
3621               rowNames_[iRow] = name;
3622          }
3623     }
3624     // May be too big - but we would have to check both rows and columns to be exact
3625     lengthNames_ = static_cast<int> (maxLength);
3626}
3627// Copies in Column names - modifies names first .. last-1
3628void
3629ClpModel::copyColumnNames(const char * const * columnNames, int first, int last)
3630{
3631     // Do row names if necessary
3632     if (!lengthNames_&&numberRows_) {
3633       lengthNames_=8;
3634       copyRowNames(NULL,0,numberRows_);
3635     }
3636     unsigned int maxLength = lengthNames_;
3637     int size = static_cast<int>(columnNames_.size());
3638     if (size != numberColumns_)
3639          columnNames_.resize(numberColumns_);
3640     int iColumn;
3641     for (iColumn = first; iColumn < last; iColumn++) {
3642          if (columnNames && columnNames[iColumn-first] && strlen(columnNames[iColumn-first])) {
3643               columnNames_[iColumn] = columnNames[iColumn-first];
3644               maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(columnNames[iColumn-first])));
3645          } else {
3646               maxLength = CoinMax(maxLength, static_cast<unsigned int> (8));
3647               char name[9];
3648               sprintf(name, "C%7.7d", iColumn);
3649               columnNames_[iColumn] = name;
3650          }
3651     }
3652     // May be too big - but we would have to check both rows and columns to be exact
3653     lengthNames_ = static_cast<int> (maxLength);
3654}
3655#endif
3656// Primal objective limit
3657void
3658ClpModel::setPrimalObjectiveLimit(double value)
3659{
3660     dblParam_[ClpPrimalObjectiveLimit] = value;
3661}
3662// Dual objective limit
3663void
3664ClpModel::setDualObjectiveLimit(double value)
3665{
3666     dblParam_[ClpDualObjectiveLimit] = value;
3667}
3668// Objective offset
3669void
3670ClpModel::setObjectiveOffset(double value)
3671{
3672     dblParam_[ClpObjOffset] = value;
3673}
3674// Solve a problem with no elements - return status
3675int ClpModel::emptyProblem(int * infeasNumber, double * infeasSum, bool printMessage)
3676{
3677     secondaryStatus_ = 6; // so user can see something odd
3678     if (printMessage)
3679          handler_->message(CLP_EMPTY_PROBLEM, messages_)
3680                    << numberRows_
3681                    << numberColumns_
3682                    << 0
3683                    << CoinMessageEol;
3684     int returnCode = 0;
3685     if (numberRows_ || numberColumns_) {
3686          if (!status_) {
3687               status_ = new unsigned char[numberRows_+numberColumns_];
3688               CoinZeroN(status_, numberRows_ + numberColumns_);
3689          }
3690     }
3691     // status is set directly (as can be used by Interior methods)
3692     // check feasible
3693     int numberPrimalInfeasibilities = 0;
3694     double sumPrimalInfeasibilities = 0.0;
3695     int numberDualInfeasibilities = 0;
3696     double sumDualInfeasibilities = 0.0;
3697     if (numberRows_) {
3698          for (int i = 0; i < numberRows_; i++) {
3699               dual_[i] = 0.0;
3700               if (rowLower_[i] <= rowUpper_[i]) {
3701                    if (rowLower_[i] > -1.0e30 || rowUpper_[i] < 1.0e30) {
3702                         if (rowLower_[i] <= 0.0 && rowUpper_[i] >= 0.0) {
3703                              if (fabs(rowLower_[i]) < fabs(rowUpper_[i]))
3704                                   rowActivity_[i] = rowLower_[i];
3705                              else
3706                                   rowActivity_[i] = rowUpper_[i];
3707                         } else {
3708                              rowActivity_[i] = 0.0;
3709                              numberPrimalInfeasibilities++;
3710                              sumPrimalInfeasibilities += CoinMin(rowLower_[i], -rowUpper_[i]);
3711                              returnCode = 1;
3712                         }
3713                    } else {
3714                         rowActivity_[i] = 0.0;
3715                    }
3716               } else {
3717                    rowActivity_[i] = 0.0;
3718                    numberPrimalInfeasibilities++;
3719                    sumPrimalInfeasibilities += rowLower_[i] - rowUpper_[i];
3720                    returnCode = 1;
3721               }
3722               status_[i+numberColumns_] = 1;
3723          }
3724     }
3725     objectiveValue_ = 0.0;
3726     if (numberColumns_) {
3727          const double * cost = objective();
3728          for (int i = 0; i < numberColumns_; i++) {
3729               reducedCost_[i] = cost[i];
3730               double objValue = cost[i] * optimizationDirection_;
3731               if (columnLower_[i] <= columnUpper_[i]) {
3732                    if (columnLower_[i] > -1.0e30 || columnUpper_[i] < 1.0e30) {
3733                         if (!objValue) {
3734                              if (fabs(columnLower_[i]) < fabs(columnUpper_[i])) {
3735                                   columnActivity_[i] = columnLower_[i];
3736                                   status_[i] = 3;
3737                              } else {
3738                                   columnActivity_[i] = columnUpper_[i];
3739                                   status_[i] = 2;
3740                              }
3741                         } else if (objValue > 0.0) {
3742                              if (columnLower_[i] > -1.0e30) {
3743                                   columnActivity_[i] = columnLower_[i];
3744                                   status_[i] = 3;
3745                              } else {
3746                                   columnActivity_[i] = columnUpper_[i];
3747                                   status_[i] = 2;
3748                                   numberDualInfeasibilities++;;
3749                                   sumDualInfeasibilities += fabs(objValue);
3750                                   returnCode |= 2;
3751                              }
3752                              objectiveValue_ += columnActivity_[i] * objValue;
3753                         } else {
3754                              if (columnUpper_[i] < 1.0e30) {
3755                                   columnActivity_[i] = columnUpper_[i];
3756                                   status_[i] = 2;
3757                              } else {
3758                                   columnActivity_[i] = columnLower_[i];
3759                                   status_[i] = 3;
3760                                   numberDualInfeasibilities++;;
3761                                   sumDualInfeasibilities += fabs(objValue);
3762                                   returnCode |= 2;
3763                              }
3764                              objectiveValue_ += columnActivity_[i] * objValue;
3765                         }
3766                    } else {
3767                         columnActivity_[i] = 0.0;
3768                         if (objValue) {
3769                              numberDualInfeasibilities++;;
3770                              sumDualInfeasibilities += fabs(objValue);
3771                              returnCode |= 2;
3772                         }
3773                         status_[i] = 0;
3774                    }
3775               } else {
3776                    if (fabs(columnLower_[i]) < fabs(columnUpper_[i])) {
3777                         columnActivity_[i] = columnLower_[i];
3778                         status_[i] = 3;
3779                    } else {
3780                         columnActivity_[i] = columnUpper_[i];
3781                         status_[i] = 2;
3782                    }
3783                    numberPrimalInfeasibilities++;
3784                    sumPrimalInfeasibilities += columnLower_[i] - columnUpper_[i];
3785                    returnCode |= 1;
3786               }
3787          }
3788     }
3789     objectiveValue_ /= (objectiveScale_ * rhsScale_);
3790     if (infeasNumber) {
3791          infeasNumber[0] = numberDualInfeasibilities;
3792          infeasSum[0] = sumDualInfeasibilities;
3793          infeasNumber[1] = numberPrimalInfeasibilities;
3794          infeasSum[1] = sumPrimalInfeasibilities;
3795     }
3796     if (returnCode == 3)
3797          returnCode = 4;
3798     return returnCode;
3799}
3800#ifndef SLIM_NOIO
3801/* Write the problem in MPS format to the specified file.
3802
3803Row and column names may be null.
3804formatType is
3805<ul>
3806<li> 0 - normal
3807<li> 1 - extra accuracy
3808<li> 2 - IEEE hex (later)
3809</ul>
3810
3811Returns non-zero on I/O error
3812*/
3813int
3814ClpModel::writeMps(const char *filename,
3815                   int formatType, int numberAcross,
3816                   double objSense) const
3817{
3818     matrix_->setDimensions(numberRows_, numberColumns_);
3819
3820     // Get multiplier for objective function - default 1.0
3821     double * objective = new double[numberColumns_];
3822     CoinMemcpyN(getObjCoefficients(), numberColumns_, objective);
3823     if (objSense * getObjSense() < 0.0) {
3824          for (int i = 0; i < numberColumns_; ++i)
3825               objective [i] = - objective[i];
3826     }
3827     // get names
3828     const char * const * const rowNames = rowNamesAsChar();
3829     const char * const * const columnNames = columnNamesAsChar();
3830     CoinMpsIO writer;
3831     writer.passInMessageHandler(handler_);
3832     *writer.messagesPointer() = coinMessages();
3833     writer.setMpsData(*(matrix_->getPackedMatrix()), COIN_DBL_MAX,
3834                       getColLower(), getColUpper(),
3835                       objective,
3836                       reinterpret_cast<const char*> (NULL) /*integrality*/,
3837                       getRowLower(), getRowUpper(),
3838                       columnNames, rowNames);
3839     // Pass in array saying if each variable integer
3840     writer.copyInIntegerInformation(integerInformation());
3841     writer.setObjectiveOffset(objectiveOffset());
3842     delete [] objective;
3843     CoinPackedMatrix * quadratic = NULL;
3844#ifndef SLIM_CLP
3845     // allow for quadratic objective
3846#ifndef NO_RTTI
3847     ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
3848#else
3849     ClpQuadraticObjective * quadraticObj = NULL;
3850     if (objective_->type() == 2)
3851          quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_));
3852#endif
3853     if (quadraticObj)
3854          quadratic = quadraticObj->quadraticObjective();
3855#endif
3856     int returnCode = writer.writeMps(filename, 0 /* do not gzip it*/, formatType, numberAcross,
3857                                      quadratic);
3858     if (rowNames) {
3859          deleteNamesAsChar(rowNames, numberRows_ + 1);
3860          deleteNamesAsChar(columnNames, numberColumns_);
3861     }
3862     return returnCode;
3863}
3864#ifndef CLP_NO_STD
3865// Create row names as char **
3866const char * const *
3867ClpModel::rowNamesAsChar() const
3868{
3869     char ** rowNames = NULL;
3870     if (lengthNames()) {
3871          rowNames = new char * [numberRows_+1];
3872          int numberNames = static_cast<int>(rowNames_.size());
3873          numberNames = CoinMin(numberRows_, numberNames);
3874          int iRow;
3875          for (iRow = 0; iRow < numberNames; iRow++) {
3876               if (rowName(iRow) != "") {
3877                    rowNames[iRow] =
3878                         CoinStrdup(rowName(iRow).c_str());
3879               } else {
3880                    char name[9];
3881                    sprintf(name, "R%7.7d", iRow);
3882                    rowNames[iRow] = CoinStrdup(name);
3883               }
3884#ifdef STRIPBLANKS
3885               char * xx = rowNames[iRow];
3886               int i;
3887               int length = strlen(xx);
3888               int n = 0;
3889               for (i = 0; i < length; i++) {
3890                    if (xx[i] != ' ')
3891                         xx[n++] = xx[i];
3892               }
3893               xx[n] = '\0';
3894#endif
3895          }
3896          char name[9];
3897          for ( ; iRow < numberRows_; iRow++) {
3898               sprintf(name, "R%7.7d", iRow);
3899               rowNames[iRow] = CoinStrdup(name);
3900          }
3901          rowNames[numberRows_] = CoinStrdup("OBJROW");
3902     }
3903     return reinterpret_cast<const char * const *>(rowNames);
3904}
3905// Create column names as char **
3906const char * const *
3907ClpModel::columnNamesAsChar() const
3908{
3909     char ** columnNames = NULL;
3910     if (lengthNames()) {
3911          columnNames = new char * [numberColumns_];
3912          int numberNames = static_cast<int>(columnNames_.size());
3913          numberNames = CoinMin(numberColumns_, numberNames);
3914          int iColumn;
3915          for (iColumn = 0; iColumn < numberNames; iColumn++) {
3916               if (columnName(iColumn) != "") {
3917                    columnNames[iColumn] =
3918                         CoinStrdup(columnName(iColumn).c_str());
3919               } else {
3920                    char name[9];
3921                    sprintf(name, "C%7.7d", iColumn);
3922                    columnNames[iColumn] = CoinStrdup(name);
3923               }
3924#ifdef STRIPBLANKS
3925               char * xx = columnNames[iColumn];
3926               int i;
3927               int length = strlen(xx);
3928               int n = 0;
3929               for (i = 0; i < length; i++) {
3930                    if (xx[i] != ' ')
3931                         xx[n++] = xx[i];
3932               }
3933               xx[n] = '\0';
3934#endif
3935          }
3936          char name[9];
3937          for ( ; iColumn < numberColumns_; iColumn++) {
3938               sprintf(name, "C%7.7d", iColumn);
3939               columnNames[iColumn] = CoinStrdup(name);
3940          }
3941     }
3942     return /*reinterpret_cast<const char * const *>*/(columnNames);
3943}
3944// Delete char * version of names
3945void
3946ClpModel::deleteNamesAsChar(const char * const * names, int number) const
3947{
3948     for (int i = 0; i < number; i++) {
3949          free(const_cast<char *>(names[i]));
3950     }
3951     delete [] const_cast<char **>(names);
3952}
3953#endif
3954#endif
3955// Pass in Event handler (cloned and deleted at end)
3956void
3957ClpModel::passInEventHandler(const ClpEventHandler * eventHandler)
3958{
3959     delete eventHandler_;
3960     eventHandler_ = eventHandler->clone();
3961}
3962// Sets or unsets scaling, 0 -off, 1 on, 2 dynamic(later)
3963void
3964ClpModel::scaling(int mode)
3965{
3966     // If mode changes then we treat as new matrix (need new row copy)
3967     if (mode != scalingFlag_) {
3968          whatsChanged_ &= ~(2 + 4 + 8);
3969          // Get rid of scaled matrix
3970          setClpScaledMatrix(NULL);
3971     }
3972     if (mode > 0 && mode < 6) {
3973          scalingFlag_ = mode;
3974     } else if (!mode) {
3975          scalingFlag_ = 0;
3976          setRowScale(NULL);
3977          setColumnScale(NULL);
3978     }
3979}
3980void
3981ClpModel::times(double scalar,
3982                const double * x, double * y) const
3983{
3984     if (!scaledMatrix_ || !rowScale_) {
3985          if (rowScale_)
3986               matrix_->times(scalar, x, y, rowScale_, columnScale_);
3987          else
3988               matrix_->times(scalar, x, y);
3989     } else {
3990          scaledMatrix_->times(scalar, x, y);
3991     }
3992}
3993void
3994ClpModel::transposeTimes(double scalar,
3995                         const double * x, double * y) const
3996{
3997     if (!scaledMatrix_ || !rowScale_) {
3998          if (rowScale_)
3999               matrix_->transposeTimes(scalar, x, y, rowScale_, columnScale_, NULL);
4000          else
4001               matrix_->transposeTimes(scalar, x, y);
4002     } else {
4003          scaledMatrix_->transposeTimes(scalar, x, y);
4004     }
4005}
4006// Does much of scaling
4007void
4008ClpModel::gutsOfScaling()
4009{
4010     int i;
4011     if (rowObjective_) {
4012          for (i = 0; i < numberRows_; i++)
4013               rowObjective_[i] /= rowScale_[i];
4014     }
4015     for (i = 0; i < numberRows_; i++) {
4016          double multiplier = rowScale_[i];
4017          double inverseMultiplier = 1.0 / multiplier;
4018          rowActivity_[i] *= multiplier;
4019          dual_[i] *= inverseMultiplier;
4020          if (rowLower_[i] > -1.0e30)
4021               rowLower_[i] *= multiplier;
4022          else
4023               rowLower_[i] = -COIN_DBL_MAX;
4024          if (rowUpper_[i] < 1.0e30)
4025               rowUpper_[i] *= multiplier;
4026          else
4027               rowUpper_[i] = COIN_DBL_MAX;
4028     }
4029     for (i = 0; i < numberColumns_; i++) {
4030          double multiplier = 1.0 * inverseColumnScale_[i];
4031          columnActivity_[i] *= multiplier;
4032          reducedCost_[i] *= columnScale_[i];
4033          if (columnLower_[i] > -1.0e30)
4034               columnLower_[i] *= multiplier;
4035          else
4036               columnLower_[i] = -COIN_DBL_MAX;
4037          if (columnUpper_[i] < 1.0e30)
4038               columnUpper_[i] *= multiplier;
4039          else
4040               columnUpper_[i] = COIN_DBL_MAX;
4041
4042     }
4043     //now replace matrix
4044     //and objective
4045     matrix_->reallyScale(rowScale_, columnScale_);
4046     objective_->reallyScale(columnScale_);
4047}
4048/* If we constructed a "really" scaled model then this reverses the operation.
4049      Quantities may not be exactly as they were before due to rounding errors */
4050void
4051ClpModel::unscale()
4052{
4053     if (rowScale_) {
4054          int i;
4055          // reverse scaling
4056          for (i = 0; i < numberRows_; i++)
4057               rowScale_[i] = 1.0 * inverseRowScale_[i];
4058          for (i = 0; i < numberColumns_; i++)
4059               columnScale_[i] = 1.0 * inverseColumnScale_[i];
4060          gutsOfScaling();
4061     }
4062
4063     scalingFlag_ = 0;
4064     setRowScale(NULL);
4065     setColumnScale(NULL);
4066}
4067void
4068ClpModel::setSpecialOptions(unsigned int value)
4069{
4070     specialOptions_ = value;
4071}
4072/* This creates a coinModel object
4073 */
4074CoinModel *
4075ClpModel::createCoinModel() const
4076{
4077     CoinModel * coinModel = new CoinModel();
4078     CoinPackedMatrix matrixByRow;
4079     matrixByRow.setExtraGap(0.0);
4080     matrixByRow.setExtraMajor(0.0);
4081     matrixByRow.reverseOrderedCopyOf(*matrix());
4082     coinModel->setObjectiveOffset(objectiveOffset());
4083     coinModel->setProblemName(problemName().c_str());
4084
4085     // Build by row from scratch
4086     const double * element = matrixByRow.getElements();
4087     const int * column = matrixByRow.getIndices();
4088     const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
4089     const int * rowLength = matrixByRow.getVectorLengths();
4090     int i;
4091     for (i = 0; i < numberRows_; i++) {
4092          coinModel->addRow(rowLength[i], column + rowStart[i],
4093                            element + rowStart[i], rowLower_[i], rowUpper_[i]);
4094     }
4095     // Now do column part
4096     const double * objective = this->objective();
4097     for (i = 0; i < numberColumns_; i++) {
4098          coinModel->setColumnBounds(i, columnLower_[i], columnUpper_[i]);
4099          coinModel->setColumnObjective(i, objective[i]);
4100     }
4101     for ( i = 0; i < numberColumns_; i++) {
4102          if (isInteger(i))
4103               coinModel->setColumnIsInteger(i, true);
4104     }
4105     // do names - clear out
4106     coinModel->zapRowNames();
4107     coinModel->zapColumnNames();
4108     for (i = 0; i < numberRows_; i++) {
4109          char temp[30];
4110          strcpy(temp, rowName(i).c_str());
4111          size_t length = strlen(temp);
4112          for (size_t j = 0; j < length; j++) {
4113               if (temp[j] == '-')
4114                    temp[j] = '_';
4115          }
4116          coinModel->setRowName(i, temp);
4117     }
4118     for (i = 0; i < numberColumns_; i++) {
4119          char temp[30];
4120          strcpy(temp, columnName(i).c_str());
4121          size_t length = strlen(temp);
4122          for (size_t j = 0; j < length; j++) {
4123               if (temp[j] == '-')
4124                    temp[j] = '_';
4125          }
4126          coinModel->setColumnName(i, temp);
4127     }
4128     ClpQuadraticObjective * obj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
4129     if (obj) {
4130          const CoinPackedMatrix * quadObj = obj->quadraticObjective();
4131          // add in quadratic
4132          const double * element = quadObj->getElements();
4133          const int * row = quadObj->getIndices();
4134          const CoinBigIndex * columnStart = quadObj->getVectorStarts();
4135          const int * columnLength = quadObj->getVectorLengths();
4136          for (i = 0; i < numberColumns_; i++) {
4137               int nels = columnLength[i];
4138               if (nels) {
4139                    CoinBigIndex start = columnStart[i];
4140                    double constant = coinModel->getColumnObjective(i);
4141                    char temp[100000];
4142                    char temp2[30];
4143                    sprintf(temp, "%g", constant);
4144                    for (CoinBigIndex k = start; k < start + nels; k++) {
4145                         int kColumn = row[k];
4146                         double value = element[k];
4147#if 1
4148                         // ampl gives twice with assumed 0.5
4149                         if (kColumn < i)
4150                              continue;
4151                         else if (kColumn == i)
4152                              value *= 0.5;
4153#endif
4154                         if (value == 1.0)
4155                              sprintf(temp2, "+%s", coinModel->getColumnName(kColumn));
4156                         else if (value == -1.0)
4157                              sprintf(temp2, "-%s", coinModel->getColumnName(kColumn));
4158                         else if (value > 0.0)
4159                              sprintf(temp2, "+%g*%s", value, coinModel->getColumnName(kColumn));
4160                         else
4161                              sprintf(temp2, "%g*%s", value, coinModel->getColumnName(kColumn));
4162                         strcat(temp, temp2);
4163                         assert (strlen(temp) < 100000);
4164                    }
4165                    coinModel->setObjective(i, temp);
4166                    if (logLevel() > 2)
4167                         printf("el for objective column %s is %s\n", coinModel->getColumnName(i), temp);
4168               }
4169          }
4170     }
4171     return coinModel;
4172}
4173// Start or reset using maximumRows_ and Columns_
4174void
4175ClpModel::startPermanentArrays()
4176{
4177     COIN_DETAIL_PRINT(printf("startperm a %d rows, %d maximum rows\n",
4178                              numberRows_, maximumRows_));
4179     if ((specialOptions_ & 65536) != 0) {
4180          if (numberRows_ > maximumRows_ || numberColumns_ > maximumColumns_) {
4181               if (numberRows_ > maximumRows_) {
4182                    if (maximumRows_ > 0)
4183                         maximumRows_ = numberRows_ + 10 + numberRows_ / 100;
4184                    else
4185                         maximumRows_ = numberRows_;
4186               }
4187               if (numberColumns_ > maximumColumns_) {
4188                    if (maximumColumns_ > 0)
4189                         maximumColumns_ = numberColumns_ + 10 + numberColumns_ / 100;
4190                    else
4191                         maximumColumns_ = numberColumns_;
4192               }
4193               // need to make sure numberRows_ OK and size of matrices
4194               resize(maximumRows_, maximumColumns_);
4195               COIN_DETAIL_PRINT(printf("startperm b %d rows, %d maximum rows\n",
4196                                        numberRows_, maximumRows_));
4197          } else {
4198               return;
4199          }
4200     } else {
4201          specialOptions_ |= 65536;
4202          maximumRows_ = numberRows_;
4203          maximumColumns_ = numberColumns_;
4204          baseMatrix_ = *matrix();
4205          baseMatrix_.cleanMatrix();
4206          baseRowCopy_.setExtraGap(0.0);
4207          baseRowCopy_.setExtraMajor(0.0);
4208          baseRowCopy_.reverseOrderedCopyOf(baseMatrix_);
4209          COIN_DETAIL_PRINT(printf("startperm c %d rows, %d maximum rows\n",
4210                                   numberRows_, maximumRows_));
4211     }
4212}
4213// Stop using maximumRows_ and Columns_
4214void
4215ClpModel::stopPermanentArrays()
4216{
4217     specialOptions_ &= ~65536;
4218     maximumRows_ = -1;
4219     maximumColumns_ = -1;
4220     if (rowScale_ != savedRowScale_) {
4221          delete [] savedRowScale_;
4222          delete [] savedColumnScale_;
4223     }
4224     savedRowScale_ = NULL;
4225     savedColumnScale_ = NULL;
4226}
4227// Set new row matrix
4228void
4229ClpModel::setNewRowCopy(ClpMatrixBase * newCopy)
4230{
4231     delete rowCopy_;
4232     rowCopy_ = newCopy;
4233}
4234/* Find a network subset.
4235   rotate array should be numberRows.  On output
4236   -1 not in network
4237   0 in network as is
4238   1 in network with signs swapped
4239  Returns number of network rows (positive if exact network, negative if needs extra row)
4240  From Gulpinar, Gutin, Maros and Mitra
4241*/
4242int
4243ClpModel::findNetwork(char * rotate, double fractionNeeded)
4244{
4245     int * mapping = new int [numberRows_];
4246     // Get column copy
4247     CoinPackedMatrix * columnCopy = matrix();
4248     // Get a row copy in standard format
4249     CoinPackedMatrix * copy = new CoinPackedMatrix();
4250     copy->setExtraGap(0.0);
4251     copy->setExtraMajor(0.0);
4252     copy->reverseOrderedCopyOf(*columnCopy);
4253     // make sure ordered and no gaps
4254     copy->cleanMatrix();
4255     // get matrix data pointers
4256     const int * columnIn = copy->getIndices();
4257     const CoinBigIndex * rowStartIn = copy->getVectorStarts();
4258     const int * rowLength = copy->getVectorLengths();
4259     const double * elementByRowIn = copy->getElements();
4260     int iRow, iColumn;
4261     int numberEligible = 0;
4262     int numberIn = 0;
4263     int numberElements = 0;
4264     for (iRow = 0; iRow < numberRows_; iRow++) {
4265          bool possible = true;
4266          mapping[iRow] = -1;
4267          rotate[iRow] = -1;
4268          for (CoinBigIndex j = rowStartIn[iRow]; j < rowStartIn[iRow] + rowLength[iRow]; j++) {
4269               //int iColumn = column[j];
4270               double value = elementByRowIn[j];
4271               if (fabs(value) != 1.0) {
4272                    possible = false;
4273                    break;
4274               }
4275          }
4276          if (rowLength[iRow] && possible) {
4277               mapping[iRow] = numberEligible;
4278               numberEligible++;
4279               numberElements += rowLength[iRow];
4280          }
4281     }
4282     if (numberEligible < fractionNeeded * numberRows_) {
4283          delete [] mapping;
4284          delete copy;
4285          return 0;
4286     }
4287     // create arrays
4288     int * eligible = new int [numberRows_];
4289     int * column = new int [numberElements];
4290     CoinBigIndex * rowStart = new CoinBigIndex [numberEligible+1];
4291     char * elementByRow = new char [numberElements];
4292     numberEligible = 0;
4293     numberElements = 0;
4294     rowStart[0] = 0;
4295     for (iRow = 0; iRow < numberRows_; iRow++) {
4296          if (mapping[iRow] < 0)
4297               continue;
4298          assert (numberEligible == mapping[iRow]);
4299          rotate[numberEligible] = 0;
4300          for (CoinBigIndex j = rowStartIn[iRow]; j < rowStartIn[iRow] + rowLength[iRow]; j++) {
4301               column[numberElements] = columnIn[j];
4302               double value = elementByRowIn[j];
4303               if (value == 1.0)
4304                    elementByRow[numberElements++] = 1;
4305               else
4306                    elementByRow[numberElements++] = -1;
4307          }
4308          numberEligible++;
4309          rowStart[numberEligible] = numberElements;
4310     }
4311     // get rid of copy to save space
4312     delete copy;
4313     const int * rowIn = columnCopy->getIndices();
4314     const CoinBigIndex * columnStartIn = columnCopy->getVectorStarts();
4315     const int * columnLengthIn = columnCopy->getVectorLengths();
4316     const double * elementByColumnIn = columnCopy->getElements();
4317     int * columnLength = new int [numberColumns_];
4318     // May just be that is a network - worth checking
4319     bool isNetworkAlready = true;
4320     bool trueNetwork = true;
4321     for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
4322          double product = 1.0;
4323          int n = 0;
4324          for (CoinBigIndex j = columnStartIn[iColumn]; j < columnStartIn[iColumn] + columnLengthIn[iColumn]; j++) {
4325               iRow = mapping[rowIn[j]];
4326               if (iRow >= 0) {
4327                    n++;
4328                    product *= elementByColumnIn[j];
4329               }
4330          }
4331          if (n >= 2) {
4332               if (product != -1.0 || n > 2)
4333                    isNetworkAlready = false;
4334          } else if (n == 1) {
4335               trueNetwork = false;
4336          }
4337          columnLength[iColumn] = n;
4338     }
4339     if (!isNetworkAlready) {
4340          // For sorting
4341          double * count = new double [numberRows_];
4342          int * which = new int [numberRows_];
4343          int numberLast = -1;
4344          // Count for columns
4345          char * columnCount = new char[numberColumns_];
4346          memset(columnCount, 0, numberColumns_);
4347          char * currentColumnCount = new char[numberColumns_];
4348          // Now do main loop
4349          while (numberIn > numberLast) {
4350               numberLast = numberIn;
4351               int numberLeft = 0;
4352               for (iRow = 0; iRow < numberEligible; iRow++) {
4353                    if (rotate[iRow] == 0 && rowStart[iRow+1] > rowStart[iRow]) {
4354                         which[numberLeft] = iRow;
4355                         int merit = 0;
4356                         bool OK = true;
4357                         bool reflectionOK = true;
4358                         for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow+1]; j++) {
4359                              iColumn = column[j];
4360                              int iCount = columnCount[iColumn];
4361                              int absCount = CoinAbs(iCount);
4362                              if (absCount < 2) {
4363                                   merit = CoinMax(columnLength[iColumn] - absCount - 1, merit);
4364                                   if (elementByRow[j] == iCount)
4365                                        OK = false;
4366                                   else if (elementByRow[j] == -iCount)
4367                                        reflectionOK = false;
4368                              } else {
4369                                   merit = -2;
4370                                   break;
4371                              }
4372                         }
4373                         if (merit > -2 && (OK || reflectionOK) &&
4374                                   (!OK || !reflectionOK || !numberIn)) {
4375                              //if (!numberLast) merit=1;
4376                              count[numberLeft++] = (rowStart[iRow+1] - rowStart[iRow] - 1) *
4377                                                    (static_cast<double>(merit));
4378                              if (OK)
4379                                   rotate[iRow] = 0;
4380                              else
4381                                   rotate[iRow] = 1;
4382                         } else {
4383                              // no good
4384                              rotate[iRow] = -1;
4385                         }
4386                    }
4387               }
4388               CoinSort_2(count, count + numberLeft, which);
4389               // Get G
4390               memset(currentColumnCount, 0, numberColumns_);
4391               for (iRow = 0; iRow < numberLeft; iRow++) {
4392                    int jRow = which[iRow];
4393                    bool possible = true;
4394                    for (int i = 0; i < numberIn; i++) {
4395                         for (CoinBigIndex j = rowStart[jRow]; j < rowStart[jRow+1]; j++) {
4396                              if (currentColumnCount[column[j]]) {
4397                                   possible = false;
4398                                   break;
4399                              }
4400                         }
4401                    }
4402                    if (possible) {
4403                         rotate[jRow] = static_cast<char>(rotate[jRow] + 2);
4404                         eligible[numberIn++] = jRow;
4405                         char multiplier = static_cast<char>((rotate[jRow] == 2) ? 1 : -1);
4406                         for (CoinBigIndex j = rowStart[jRow]; j < rowStart[jRow+1]; j++) {
4407                              iColumn = column[j];
4408                              currentColumnCount[iColumn]++;
4409                              int iCount = columnCount[iColumn];
4410                              int absCount = CoinAbs(iCount);
4411                              if (!absCount) {
4412                                   columnCount[iColumn] = static_cast<char>(elementByRow[j] * multiplier);
4413                              } else {
4414                                   columnCount[iColumn] = 2;
4415                              }
4416                         }
4417                    }
4418               }
4419          }
4420#ifndef NDEBUG
4421          for (iRow = 0; iRow < numberIn; iRow++) {
4422               int kRow = eligible[iRow];
4423               assert (rotate[kRow] >= 2);
4424          }
4425#endif
4426          trueNetwork = true;
4427          for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
4428               if (CoinAbs(static_cast<int>(columnCount[iColumn])) == 1) {
4429                    trueNetwork = false;
4430                    break;
4431               }
4432          }
4433          delete [] currentColumnCount;
4434          delete [] columnCount;
4435          delete [] which;
4436          delete [] count;
4437     } else {
4438          numberIn = numberEligible;
4439          for (iRow = 0; iRow < numberRows_; iRow++) {
4440               int kRow = mapping[iRow];
4441               if (kRow >= 0) {
4442                    rotate[kRow] = 2;
4443               }
4444          }
4445     }
4446     if (!trueNetwork)
4447          numberIn = - numberIn;
4448     delete [] column;
4449     delete [] rowStart;
4450     delete [] elementByRow;
4451     delete [] columnLength;
4452     // redo rotate
4453     char * rotate2 = CoinCopyOfArray(rotate, numberEligible);
4454     for (iRow = 0; iRow < numberRows_; iRow++) {
4455          int kRow = mapping[iRow];
4456          if (kRow >= 0) {
4457               int iState = rotate2[kRow];
4458               if (iState > 1)
4459                    iState -= 2;
4460               else
4461                    iState = -1;
4462               rotate[iRow] = static_cast<char>(iState);
4463          } else {
4464               rotate[iRow] = -1;
4465          }
4466     }
4467     delete [] rotate2;
4468     delete [] eligible;
4469     delete [] mapping;
4470     return numberIn;
4471}
4472//#############################################################################
4473// Constructors / Destructor / Assignment
4474//#############################################################################
4475
4476//-------------------------------------------------------------------
4477// Default Constructor
4478//-------------------------------------------------------------------
4479ClpDataSave::ClpDataSave ()
4480{
4481     dualBound_ = 0.0;
4482     infeasibilityCost_ = 0.0;
4483     sparseThreshold_ = 0;
4484     pivotTolerance_ = 0.0;
4485     zeroFactorizationTolerance_ = 1.0e13;
4486     zeroSimplexTolerance_ = 1.0e-13;
4487     acceptablePivot_ = 0.0;
4488     objectiveScale_ = 1.0;
4489     perturbation_ = 0;
4490     forceFactorization_ = -1;
4491     scalingFlag_ = 0;
4492     specialOptions_ = 0;
4493}
4494
4495//-------------------------------------------------------------------
4496// Copy constructor
4497//-------------------------------------------------------------------
4498ClpDataSave::ClpDataSave (const ClpDataSave & rhs)
4499{
4500     dualBound_ = rhs.dualBound_;
4501     infeasibilityCost_ = rhs.infeasibilityCost_;
4502     pivotTolerance_ = rhs.pivotTolerance_;
4503     zeroFactorizationTolerance_ = rhs.zeroFactorizationTolerance_;
4504     zeroSimplexTolerance_ = rhs.zeroSimplexTolerance_;
4505     acceptablePivot_ = rhs.acceptablePivot_;
4506     objectiveScale_ = rhs.objectiveScale_;
4507     sparseThreshold_ = rhs.sparseThreshold_;
4508     perturbation_ = rhs.perturbation_;
4509     forceFactorization_ = rhs.forceFactorization_;
4510     scalingFlag_ = rhs.scalingFlag_;
4511     specialOptions_ = rhs.specialOptions_;
4512}
4513
4514//-------------------------------------------------------------------
4515// Destructor
4516//-------------------------------------------------------------------
4517ClpDataSave::~ClpDataSave ()
4518{
4519}
4520
4521//----------------------------------------------------------------
4522// Assignment operator
4523//-------------------------------------------------------------------
4524ClpDataSave &
4525ClpDataSave::operator=(const ClpDataSave& rhs)
4526{
4527     if (this != &rhs) {
4528          dualBound_ = rhs.dualBound_;
4529          infeasibilityCost_ = rhs.infeasibilityCost_;
4530          pivotTolerance_ = rhs.pivotTolerance_;
4531          zeroFactorizationTolerance_ = rhs.zeroFactorizationTolerance_;
4532          zeroSimplexTolerance_ = rhs.zeroSimplexTolerance_;
4533          acceptablePivot_ = rhs.acceptablePivot_;
4534          objectiveScale_ = rhs.objectiveScale_;
4535          sparseThreshold_ = rhs.sparseThreshold_;
4536          perturbation_ = rhs.perturbation_;
4537          forceFactorization_ = rhs.forceFactorization_;
4538          scalingFlag_ = rhs.scalingFlag_;
4539          specialOptions_ = rhs.specialOptions_;
4540     }
4541     return *this;
4542}
4543// Create C++ lines to get to current state
4544void
4545ClpModel::generateCpp( FILE * fp)
4546{
4547     // Stuff that can't be done easily
4548     if (!lengthNames_) {
4549          // no names
4550          fprintf(fp, "  clpModel->dropNames();\n");
4551     }
4552     ClpModel defaultModel;
4553     ClpModel * other = &defaultModel;
4554     int iValue1, iValue2;
4555     double dValue1, dValue2;
4556     iValue1 = this->maximumIterations();
4557     iValue2 = other->maximumIterations();
4558     fprintf(fp, "%d  int save_maximumIterations = clpModel->maximumIterations();\n", iValue1 == iValue2 ? 2 : 1);
4559     fprintf(fp, "%d  clpModel->setMaximumIterations(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
4560     fprintf(fp, "%d  clpModel->setMaximumIterations(save_maximumIterations);\n", iValue1 == iValue2 ? 7 : 6);
4561     dValue1 = this->primalTolerance();
4562     dValue2 = other->primalTolerance();
4563     fprintf(fp, "%d  double save_primalTolerance = clpModel->primalTolerance();\n", dValue1 == dValue2 ? 2 : 1);
4564     fprintf(fp, "%d  clpModel->setPrimalTolerance(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4565     fprintf(fp, "%d  clpModel->setPrimalTolerance(save_primalTolerance);\n", dValue1 == dValue2 ? 7 : 6);
4566     dValue1 = this->dualTolerance();
4567     dValue2 = other->dualTolerance();
4568     fprintf(fp, "%d  double save_dualTolerance = clpModel->dualTolerance();\n", dValue1 == dValue2 ? 2 : 1);
4569     fprintf(fp, "%d  clpModel->setDualTolerance(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4570     fprintf(fp, "%d  clpModel->setDualTolerance(save_dualTolerance);\n", dValue1 == dValue2 ? 7 : 6);
4571     iValue1 = this->numberIterations();
4572     iValue2 = other->numberIterations();
4573     fprintf(fp, "%d  int save_numberIterations = clpModel->numberIterations();\n", iValue1 == iValue2 ? 2 : 1);
4574     fprintf(fp, "%d  clpModel->setNumberIterations(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
4575     fprintf(fp, "%d  clpModel->setNumberIterations(save_numberIterations);\n", iValue1 == iValue2 ? 7 : 6);
4576     dValue1 = this->maximumSeconds();
4577     dValue2 = other->maximumSeconds();
4578     fprintf(fp, "%d  double save_maximumSeconds = clpModel->maximumSeconds();\n", dValue1 == dValue2 ? 2 : 1);
4579     fprintf(fp, "%d  clpModel->setMaximumSeconds(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4580     fprintf(fp, "%d  clpModel->setMaximumSeconds(save_maximumSeconds);\n", dValue1 == dValue2 ? 7 : 6);
4581     dValue1 = this->optimizationDirection();
4582     dValue2 = other->optimizationDirection();
4583     fprintf(fp, "%d  double save_optimizationDirection = clpModel->optimizationDirection();\n", dValue1 == dValue2 ? 2 : 1);
4584     fprintf(fp, "%d  clpModel->setOptimizationDirection(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4585     fprintf(fp, "%d  clpModel->setOptimizationDirection(save_optimizationDirection);\n", dValue1 == dValue2 ? 7 : 6);
4586     dValue1 = this->objectiveScale();
4587     dValue2 = other->objectiveScale();
4588     fprintf(fp, "%d  double save_objectiveScale = clpModel->objectiveScale();\n", dValue1 == dValue2 ? 2 : 1);
4589     fprintf(fp, "%d  clpModel->setObjectiveScale(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4590     fprintf(fp, "%d  clpModel->setObjectiveScale(save_objectiveScale);\n", dValue1 == dValue2 ? 7 : 6);
4591     dValue1 = this->rhsScale();
4592     dValue2 = other->rhsScale();
4593     fprintf(fp, "%d  double save_rhsScale = clpModel->rhsScale();\n", dValue1 == dValue2 ? 2 : 1);
4594     fprintf(fp, "%d  clpModel->setRhsScale(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4595     fprintf(fp, "%d  clpModel->setRhsScale(save_rhsScale);\n", dValue1 == dValue2 ? 7 : 6);
4596     iValue1 = this->scalingFlag();
4597     iValue2 = other->scalingFlag();
4598     fprintf(fp, "%d  int save_scalingFlag = clpModel->scalingFlag();\n", iValue1 == iValue2 ? 2 : 1);
4599     fprintf(fp, "%d  clpModel->scaling(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
4600     fprintf(fp, "%d  clpModel->scaling(save_scalingFlag);\n", iValue1 == iValue2 ? 7 : 6);
4601     dValue1 = this->getSmallElementValue();
4602     dValue2 = other->getSmallElementValue();
4603     fprintf(fp, "%d  double save_getSmallElementValue = clpModel->getSmallElementValue();\n", dValue1 == dValue2 ? 2 : 1);
4604     fprintf(fp, "%d  clpModel->setSmallElementValue(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4605     fprintf(fp, "%d  clpModel->setSmallElementValue(save_getSmallElementValue);\n", dValue1 == dValue2 ? 7 : 6);
4606     iValue1 = this->logLevel();
4607     iValue2 = other->logLevel();
4608     fprintf(fp, "%d  int save_logLevel = clpModel->logLevel();\n", iValue1 == iValue2 ? 2 : 1);
4609     fprintf(fp, "%d  clpModel->setLogLevel(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
4610     fprintf(fp, "%d  clpModel->setLogLevel(save_logLevel);\n", iValue1 == iValue2 ? 7 : 6);
4611}
Note: See TracBrowser for help on using the repository browser.