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

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

moving branches/devel to trunk

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