source: trunk/ClpModel.cpp @ 701

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

messages and preprocessing

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