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

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

trying to make faster

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