source: trunk/ClpModel.cpp @ 706

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

for names

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