source: trunk/ClpModel.cpp @ 708

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

for presolve tolerance

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