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

Last change on this file since 1665 was 1665, checked in by lou, 9 years ago

Add EPL license notice in src.

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