source: branches/devel/Clp/src/ClpModel.cpp @ 923

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

for lou

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