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

Last change on this file since 2271 was 2271, checked in by forrest, 2 years ago

change some ints to CoinBigIndex?

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