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

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

stuff to allow more event handling

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