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

Last change on this file since 2025 was 2025, checked in by forrest, 5 years ago

mainly dantzig-wolfe - also Clp strong branching (rather than OsiClp?)

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