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

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

out ambiguities

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