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

Last change on this file since 2022 was 2022, checked in by forrest, 7 years ago

fixx AddColumns? CoinModel?

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