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

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

to try and help with trunk branches mess

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