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

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

changes to try and make faster

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