source: trunk/ClpModel.cpp @ 560

Last change on this file since 560 was 560, checked in by forrest, 15 years ago

CoinAssert? and check column numbers

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