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

Last change on this file since 1703 was 1703, checked in by forrest, 9 years ago

add debug info and take out possible memory leak

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