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

Last change on this file since 1153 was 1153, checked in by forrest, 13 years ago

modify example

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