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

Last change on this file since 1451 was 1451, checked in by forrest, 11 years ago

fix for segfault in guts of copy

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