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

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

changes to abc

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