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

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

fixes for various things

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