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

Last change on this file since 799 was 799, checked in by andreasw, 13 years ago

undid last commit (patches incorrectly applied)

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