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

Last change on this file since 1370 was 1370, checked in by forrest, 11 years ago

add ids

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