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

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

changes for miqp, parameters and presolve

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