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

Last change on this file since 2470 was 2429, checked in by stefan, 7 months ago

change more reinterpret_cast from NULL to C-cast, see also #93

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