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

Last change on this file since 1314 was 1314, checked in by forrest, 12 years ago

fix bug which has cropped up in addRows example

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