1 /* $Id: CoinModel.cpp 2083 2019-01-06 19:38:09Z unxusr $ */
2 // Copyright (C) 2005, International Business Machines
3 // Corporation and others.  All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5 #include "CoinUtilsConfig.h"
6 #include "CoinHelperFunctions.hpp"
7 #include "CoinModel.hpp"
8 #include "CoinMessage.hpp"
9 #include "CoinSort.hpp"
10 #include "CoinMpsIO.hpp"
11 #include "CoinFloatEqual.hpp"
12 
13 //#############################################################################
14 // Constructors / Destructor / Assignment
15 //#############################################################################
16 
17 //-------------------------------------------------------------------
18 // Default Constructor
19 //-------------------------------------------------------------------
CoinBaseModel()20 CoinBaseModel::CoinBaseModel()
21   : numberRows_(0)
22   , numberColumns_(0)
23   , optimizationDirection_(1.0)
24   , objectiveOffset_(0.0)
25   , handler_(NULL)
26   , logLevel_(0)
27 {
28   messages_ = CoinMessage();
29   handler_ = new CoinMessageHandler();
30   problemName_ = "";
31   rowBlockName_ = "row_master";
32   columnBlockName_ = "column_master";
33 }
34 
35 //-------------------------------------------------------------------
36 // Copy constructor
37 //-------------------------------------------------------------------
CoinBaseModel(const CoinBaseModel & rhs)38 CoinBaseModel::CoinBaseModel(const CoinBaseModel &rhs)
39   : numberRows_(rhs.numberRows_)
40   , numberColumns_(rhs.numberColumns_)
41   , optimizationDirection_(rhs.optimizationDirection_)
42   , objectiveOffset_(rhs.objectiveOffset_)
43   , logLevel_(rhs.logLevel_)
44 {
45   problemName_ = rhs.problemName_;
46   rowBlockName_ = rhs.rowBlockName_;
47   columnBlockName_ = rhs.columnBlockName_;
48   handler_ = new CoinMessageHandler(*rhs.handler_);
49 }
50 
51 //-------------------------------------------------------------------
52 // Destructor
53 //-------------------------------------------------------------------
~CoinBaseModel()54 CoinBaseModel::~CoinBaseModel()
55 {
56   delete handler_;
57 }
58 
59 //----------------------------------------------------------------
60 // Assignment operator
61 //-------------------------------------------------------------------
62 CoinBaseModel &
operator =(const CoinBaseModel & rhs)63 CoinBaseModel::operator=(const CoinBaseModel &rhs)
64 {
65   if (this != &rhs) {
66     problemName_ = rhs.problemName_;
67     rowBlockName_ = rhs.rowBlockName_;
68     columnBlockName_ = rhs.columnBlockName_;
69     numberRows_ = rhs.numberRows_;
70     numberColumns_ = rhs.numberColumns_;
71     optimizationDirection_ = rhs.optimizationDirection_;
72     objectiveOffset_ = rhs.objectiveOffset_;
73     delete handler_;
74     handler_ = new CoinMessageHandler(*rhs.handler_);
75     logLevel_ = rhs.logLevel_;
76   }
77   return *this;
78 }
setLogLevel(int value)79 void CoinBaseModel::setLogLevel(int value)
80 {
81   if (value >= 0 && value < 3)
82     logLevel_ = value;
83 }
setProblemName(const char * name)84 void CoinBaseModel::setProblemName(const char *name)
85 {
86   if (name)
87     problemName_ = name;
88   else
89     problemName_ = "";
90 }
91 // Pass in message handler
setMessageHandler(CoinMessageHandler * handler)92 void CoinBaseModel::setMessageHandler(CoinMessageHandler *handler)
93 {
94   handler_ = handler;
95   if (handler)
96     logLevel_ = -1;
97   else
98     logLevel_ = CoinMax(0, logLevel_);
99 }
100 //#############################################################################
101 // Constructors / Destructor / Assignment
102 //#############################################################################
103 
104 //-------------------------------------------------------------------
105 // Default Constructor
106 //-------------------------------------------------------------------
CoinModel()107 CoinModel::CoinModel()
108   : CoinBaseModel()
109   , maximumRows_(0)
110   , maximumColumns_(0)
111   , numberElements_(0)
112   , maximumElements_(0)
113   , numberQuadraticElements_(0)
114   , maximumQuadraticElements_(0)
115   , rowLower_(NULL)
116   , rowUpper_(NULL)
117   , rowType_(NULL)
118   , objective_(NULL)
119   , columnLower_(NULL)
120   , columnUpper_(NULL)
121   , integerType_(NULL)
122   , columnType_(NULL)
123   , start_(NULL)
124   , elements_(NULL)
125   , packedMatrix_(NULL)
126   , quadraticElements_(NULL)
127   , sortIndices_(NULL)
128   , sortElements_(NULL)
129   , sortSize_(0)
130   , sizeAssociated_(0)
131   , associated_(NULL)
132   , numberSOS_(0)
133   , startSOS_(NULL)
134   , memberSOS_(NULL)
135   , typeSOS_(NULL)
136   , prioritySOS_(NULL)
137   , referenceSOS_(NULL)
138   , priority_(NULL)
139   , cut_(NULL)
140   , moreInfo_(NULL)
141   , type_(-1)
142   , noNames_(false)
143   , links_(0)
144 {
145 }
146 /* Constructor with sizes. */
CoinModel(int firstRows,int firstColumns,CoinBigIndex firstElements,bool noNames)147 CoinModel::CoinModel(int firstRows, int firstColumns,
148   CoinBigIndex firstElements, bool noNames)
149   : CoinBaseModel()
150   , maximumRows_(0)
151   , maximumColumns_(0)
152   , numberElements_(0)
153   , maximumElements_(0)
154   , numberQuadraticElements_(0)
155   , maximumQuadraticElements_(0)
156   , rowLower_(NULL)
157   , rowUpper_(NULL)
158   , rowType_(NULL)
159   , objective_(NULL)
160   , columnLower_(NULL)
161   , columnUpper_(NULL)
162   , integerType_(NULL)
163   , columnType_(NULL)
164   , start_(NULL)
165   , elements_(NULL)
166   , packedMatrix_(NULL)
167   , quadraticElements_(NULL)
168   , sortIndices_(NULL)
169   , sortElements_(NULL)
170   , sortSize_(0)
171   , sizeAssociated_(0)
172   , associated_(NULL)
173   , numberSOS_(0)
174   , startSOS_(NULL)
175   , memberSOS_(NULL)
176   , typeSOS_(NULL)
177   , prioritySOS_(NULL)
178   , referenceSOS_(NULL)
179   , priority_(NULL)
180   , cut_(NULL)
181   , moreInfo_(NULL)
182   , type_(-1)
183   , noNames_(noNames)
184   , links_(0)
185 {
186   if (!firstRows) {
187     if (firstColumns) {
188       type_ = 1;
189       resize(0, firstColumns, firstElements);
190     }
191   } else {
192     type_ = 0;
193     resize(firstRows, 0, firstElements);
194     if (firstColumns) {
195       // mixed - do linked lists for columns
196       //createList(2);
197     }
198   }
199 }
200 /* Read a problem in MPS or GAMS format from the given filename.
201  */
CoinModel(const char * fileName,int allowStrings)202 CoinModel::CoinModel(const char *fileName, int allowStrings)
203   : CoinBaseModel()
204   , maximumRows_(0)
205   , maximumColumns_(0)
206   , numberElements_(0)
207   , maximumElements_(0)
208   , numberQuadraticElements_(0)
209   , maximumQuadraticElements_(0)
210   , rowLower_(NULL)
211   , rowUpper_(NULL)
212   , rowType_(NULL)
213   , objective_(NULL)
214   , columnLower_(NULL)
215   , columnUpper_(NULL)
216   , integerType_(NULL)
217   , columnType_(NULL)
218   , start_(NULL)
219   , elements_(NULL)
220   , packedMatrix_(NULL)
221   , quadraticElements_(NULL)
222   , sortIndices_(NULL)
223   , sortElements_(NULL)
224   , sortSize_(0)
225   , sizeAssociated_(0)
226   , associated_(NULL)
227   , numberSOS_(0)
228   , startSOS_(NULL)
229   , memberSOS_(NULL)
230   , typeSOS_(NULL)
231   , prioritySOS_(NULL)
232   , referenceSOS_(NULL)
233   , priority_(NULL)
234   , cut_(NULL)
235   , moreInfo_(NULL)
236   , type_(-1)
237   , noNames_(false)
238   , links_(0)
239 {
240   rowBlockName_ = "row_master";
241   columnBlockName_ = "column_master";
242   int status = 0;
243   if (!strcmp(fileName, "-") || !strcmp(fileName, "stdin")) {
244     // stdin
245   } else {
246     std::string name = fileName;
247     bool readable = fileCoinReadable(name);
248     if (!readable) {
249       std::cerr << "Unable to open file "
250                 << fileName << std::endl;
251       status = -1;
252     }
253   }
254   CoinMpsIO m;
255   m.setAllowStringElements(allowStrings);
256   m.setConvertObjective(true);
257   if (!status) {
258     try {
259       status = m.readMps(fileName, "");
260     } catch (CoinError &e) {
261       e.print();
262       status = -1;
263     }
264   }
265   if (!status) {
266     // set problem name
267     problemName_ = m.getProblemName();
268     objectiveOffset_ = m.objectiveOffset();
269     // build model
270     int numberRows = m.getNumRows();
271     int numberColumns = m.getNumCols();
272 
273     // Build by row from scratch
274     CoinPackedMatrix matrixByRow = *m.getMatrixByRow();
275     const double *element = matrixByRow.getElements();
276     const int *column = matrixByRow.getIndices();
277     const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
278     const int *rowLength = matrixByRow.getVectorLengths();
279     const double *rowLower = m.getRowLower();
280     const double *rowUpper = m.getRowUpper();
281     const double *columnLower = m.getColLower();
282     const double *columnUpper = m.getColUpper();
283     const double *objective = m.getObjCoefficients();
284     int i;
285     for (i = 0; i < numberRows; i++) {
286       addRow(rowLength[i], column + rowStart[i],
287         element + rowStart[i], rowLower[i], rowUpper[i], m.rowName(i));
288     }
289     int numberIntegers = 0;
290     // Now do column part
291     for (i = 0; i < numberColumns; i++) {
292       setColumnBounds(i, columnLower[i], columnUpper[i]);
293       setColumnObjective(i, objective[i]);
294       if (m.isInteger(i)) {
295         setColumnIsInteger(i, true);
296         ;
297         numberIntegers++;
298       }
299     }
300     bool quadraticInteger = (numberIntegers != 0) && m.reader()->whichSection() == COIN_QUAD_SECTION;
301     // do names
302     int iRow;
303     for (iRow = 0; iRow < numberRows_; iRow++) {
304       const char *name = m.rowName(iRow);
305       setRowName(iRow, name);
306     }
307     bool ifStrings = (m.numberStringElements() != 0);
308     int nChanged = 0;
309     int iColumn;
310     for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
311       // Replace - + or * if strings
312       if (!ifStrings && !quadraticInteger) {
313         const char *name = m.columnName(iColumn);
314         setColumnName(iColumn, name);
315       } else {
316         assert(strlen(m.columnName(iColumn)) < 100);
317         char temp[100];
318         strcpy(temp, m.columnName(iColumn));
319         int n = CoinStrlenAsInt(temp);
320         bool changed = false;
321         for (int i = 0; i < n; i++) {
322           if (temp[i] == '-') {
323             temp[i] = '_';
324             changed = true;
325           } else if (temp[i] == '+') {
326             temp[i] = '$';
327             changed = true;
328           } else if (temp[i] == '*') {
329             temp[i] = '&';
330             changed = true;
331           }
332         }
333         if (changed)
334           nChanged++;
335         setColumnName(iColumn, temp);
336       }
337     }
338     if (nChanged)
339       printf("%d column names changed to eliminate - + or *\n", nChanged);
340     if (ifStrings) {
341       // add in
342       int numberElements = m.numberStringElements();
343       for (int i = 0; i < numberElements; i++) {
344         const char *line = m.stringElement(i);
345         int iRow;
346         int iColumn;
347         sscanf(line, "%d,%d,", &iRow, &iColumn);
348         assert(iRow >= 0 && iRow <= numberRows_ + 2);
349         assert(iColumn >= 0 && iColumn <= numberColumns_);
350         const char *pos = strchr(line, ',');
351         assert(pos);
352         pos = strchr(pos + 1, ',');
353         assert(pos);
354         pos++;
355         if (iRow < numberRows_ && iColumn < numberColumns_) {
356           // element
357           setElement(iRow, iColumn, pos);
358         } else {
359           fprintf(stderr, "code CoinModel strings for rim\n");
360           abort();
361         }
362       }
363     }
364     // get quadratic part
365     if (m.reader()->whichSection() == COIN_QUAD_SECTION) {
366       CoinBigIndex *start = NULL;
367       int *column = NULL;
368       double *element = NULL;
369       status = m.readQuadraticMps(NULL, start, column, element, 2);
370       if (!status) {
371         // If strings allowed 13 then just for Hans convert to constraint
372         int objRow = -1;
373         if (allowStrings == 13) {
374           int objColumn = numberColumns_;
375           objRow = numberRows_;
376           // leave linear part in objective
377           addColumn(0, NULL, NULL, -COIN_DBL_MAX, COIN_DBL_MAX, 1.0, "obj");
378           double minusOne = -1.0;
379           addRow(1, &objColumn, &minusOne, -COIN_DBL_MAX, 0.0, "objrow");
380         }
381         if (!ifStrings && !numberIntegers) {
382           // no strings - add to quadratic (not done yet)
383           for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
384             for (CoinBigIndex j = start[iColumn]; j < start[iColumn + 1]; j++) {
385               int jColumn = column[j];
386               double value = element[j];
387               // what about diagonal etc
388               if (jColumn == iColumn) {
389                 printf("diag %d %d %g\n", iColumn, jColumn, value);
390                 setQuadraticElement(iColumn, jColumn, 0.5 * value);
391               } else if (jColumn > iColumn) {
392                 printf("above diag %d %d %g\n", iColumn, jColumn, value);
393               } else if (jColumn < iColumn) {
394                 printf("below diag %d %d %g\n", iColumn, jColumn, value);
395                 setQuadraticElement(iColumn, jColumn, value);
396               }
397             }
398           }
399         } else {
400           // add in as strings
401           for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
402             char temp[20000];
403             temp[0] = '\0';
404             int put = 0;
405             int n = 0;
406             bool ifFirst = true;
407             double value = getColumnObjective(iColumn);
408             if (value && objRow < 0) {
409               sprintf(temp, "%g", value);
410               ifFirst = false;
411               /* static cast is safe, temp is at most 20000 chars */
412               put = CoinStrlenAsInt(temp);
413             }
414             for (CoinBigIndex j = start[iColumn]; j < start[iColumn + 1]; j++) {
415               int jColumn = column[j];
416               double value = element[j];
417               // what about diagonal etc
418               if (jColumn == iColumn) {
419                 //printf("diag %d %d %g\n",iColumn,jColumn,value);
420                 value *= 0.5;
421               } else if (jColumn > iColumn) {
422                 //printf("above diag %d %d %g\n",iColumn,jColumn,value);
423               } else if (jColumn < iColumn) {
424                 //printf("below diag %d %d %g\n",iColumn,jColumn,value);
425                 value = 0.0;
426               }
427               if (value) {
428                 n++;
429                 const char *name = columnName(jColumn);
430                 if (value == 1.0) {
431                   sprintf(temp + put, "%s%s", ifFirst ? "" : "+", name);
432                 } else {
433                   if (ifFirst || value < 0.0)
434                     sprintf(temp + put, "%g*%s", value, name);
435                   else
436                     sprintf(temp + put, "+%g*%s", value, name);
437                 }
438                 put += CoinStrlenAsInt(temp + put);
439                 assert(put < 20000);
440                 ifFirst = false;
441               }
442             }
443             if (n) {
444               if (objRow < 0)
445                 setObjective(iColumn, temp);
446               else
447                 setElement(objRow, iColumn, temp);
448               //printf("el for objective column c%7.7d is %s\n",iColumn,temp);
449             }
450           }
451         }
452       }
453       delete[] start;
454       delete[] column;
455       delete[] element;
456     }
457   }
458 }
459 // From arrays
CoinModel(int numberRows,int numberColumns,const CoinPackedMatrix * matrix,const double * rowLower,const double * rowUpper,const double * columnLower,const double * columnUpper,const double * objective)460 CoinModel::CoinModel(int numberRows, int numberColumns,
461   const CoinPackedMatrix *matrix,
462   const double *rowLower, const double *rowUpper,
463   const double *columnLower, const double *columnUpper,
464   const double *objective)
465   : CoinBaseModel()
466   , maximumRows_(numberRows)
467   , maximumColumns_(numberColumns)
468   , numberElements_(matrix->getNumElements())
469   , maximumElements_(matrix->getNumElements())
470   , numberQuadraticElements_(0)
471   , maximumQuadraticElements_(0)
472   , rowType_(NULL)
473   , integerType_(NULL)
474   , columnType_(NULL)
475   , start_(NULL)
476   , elements_(NULL)
477   , packedMatrix_(NULL)
478   , quadraticElements_(NULL)
479   , sortIndices_(NULL)
480   , sortElements_(NULL)
481   , sortSize_(0)
482   , sizeAssociated_(0)
483   , associated_(NULL)
484   , numberSOS_(0)
485   , startSOS_(NULL)
486   , memberSOS_(NULL)
487   , typeSOS_(NULL)
488   , prioritySOS_(NULL)
489   , referenceSOS_(NULL)
490   , priority_(NULL)
491   , cut_(NULL)
492   , moreInfo_(NULL)
493   , type_(-1)
494   , noNames_(false)
495   , links_(0)
496 {
497   numberRows_ = numberRows;
498   numberColumns_ = numberColumns;
499   assert(numberRows_ >= matrix->getNumRows());
500   assert(numberColumns_ >= matrix->getNumCols());
501   type_ = 3;
502   packedMatrix_ = new CoinPackedMatrix(*matrix);
503   rowLower_ = CoinCopyOfArray(rowLower, numberRows_);
504   rowUpper_ = CoinCopyOfArray(rowUpper, numberRows_);
505   objective_ = CoinCopyOfArray(objective, numberColumns_);
506   columnLower_ = CoinCopyOfArray(columnLower, numberColumns_);
507   columnUpper_ = CoinCopyOfArray(columnUpper, numberColumns_);
508 }
509 
510 //-------------------------------------------------------------------
511 // Copy constructor
512 //-------------------------------------------------------------------
CoinModel(const CoinModel & rhs)513 CoinModel::CoinModel(const CoinModel &rhs)
514   : CoinBaseModel(rhs)
515   , maximumRows_(rhs.maximumRows_)
516   , maximumColumns_(rhs.maximumColumns_)
517   , numberElements_(rhs.numberElements_)
518   , maximumElements_(rhs.maximumElements_)
519   , numberQuadraticElements_(rhs.numberQuadraticElements_)
520   , maximumQuadraticElements_(rhs.maximumQuadraticElements_)
521   , rowName_(rhs.rowName_)
522   , columnName_(rhs.columnName_)
523   , string_(rhs.string_)
524   , hashElements_(rhs.hashElements_)
525   , rowList_(rhs.rowList_)
526   , columnList_(rhs.columnList_)
527   , hashQuadraticElements_(rhs.hashQuadraticElements_)
528   , sortSize_(rhs.sortSize_)
529   , quadraticRowList_(rhs.quadraticRowList_)
530   , quadraticColumnList_(rhs.quadraticColumnList_)
531   , sizeAssociated_(rhs.sizeAssociated_)
532   , numberSOS_(rhs.numberSOS_)
533   , type_(rhs.type_)
534   , noNames_(rhs.noNames_)
535   , links_(rhs.links_)
536 {
537   rowLower_ = CoinCopyOfArray(rhs.rowLower_, maximumRows_);
538   rowUpper_ = CoinCopyOfArray(rhs.rowUpper_, maximumRows_);
539   rowType_ = CoinCopyOfArray(rhs.rowType_, maximumRows_);
540   objective_ = CoinCopyOfArray(rhs.objective_, maximumColumns_);
541   columnLower_ = CoinCopyOfArray(rhs.columnLower_, maximumColumns_);
542   columnUpper_ = CoinCopyOfArray(rhs.columnUpper_, maximumColumns_);
543   integerType_ = CoinCopyOfArray(rhs.integerType_, maximumColumns_);
544   columnType_ = CoinCopyOfArray(rhs.columnType_, maximumColumns_);
545   sortIndices_ = CoinCopyOfArray(rhs.sortIndices_, sortSize_);
546   sortElements_ = CoinCopyOfArray(rhs.sortElements_, sortSize_);
547   associated_ = CoinCopyOfArray(rhs.associated_, sizeAssociated_);
548   priority_ = CoinCopyOfArray(rhs.priority_, maximumColumns_);
549   cut_ = CoinCopyOfArray(rhs.cut_, maximumRows_);
550   moreInfo_ = rhs.moreInfo_;
551   if (rhs.packedMatrix_)
552     packedMatrix_ = new CoinPackedMatrix(*rhs.packedMatrix_);
553   else
554     packedMatrix_ = NULL;
555   if (numberSOS_) {
556     startSOS_ = CoinCopyOfArray(rhs.startSOS_, numberSOS_ + 1);
557     int numberMembers = startSOS_[numberSOS_];
558     memberSOS_ = CoinCopyOfArray(rhs.memberSOS_, numberMembers);
559     typeSOS_ = CoinCopyOfArray(rhs.typeSOS_, numberSOS_);
560     prioritySOS_ = CoinCopyOfArray(rhs.prioritySOS_, numberSOS_);
561     referenceSOS_ = CoinCopyOfArray(rhs.referenceSOS_, numberMembers);
562   } else {
563     startSOS_ = NULL;
564     memberSOS_ = NULL;
565     typeSOS_ = NULL;
566     prioritySOS_ = NULL;
567     referenceSOS_ = NULL;
568   }
569   if (type_ == 0) {
570     start_ = CoinCopyOfArray(rhs.start_, maximumRows_ + 1);
571   } else if (type_ == 1) {
572     start_ = CoinCopyOfArray(rhs.start_, maximumColumns_ + 1);
573   } else {
574     start_ = NULL;
575   }
576   elements_ = CoinCopyOfArray(rhs.elements_, maximumElements_);
577   quadraticElements_ = CoinCopyOfArray(rhs.quadraticElements_, maximumQuadraticElements_);
578 }
579 
580 //-------------------------------------------------------------------
581 // Destructor
582 //-------------------------------------------------------------------
~CoinModel()583 CoinModel::~CoinModel()
584 {
585   delete[] rowLower_;
586   delete[] rowUpper_;
587   delete[] rowType_;
588   delete[] objective_;
589   delete[] columnLower_;
590   delete[] columnUpper_;
591   delete[] integerType_;
592   delete[] columnType_;
593   delete[] start_;
594   delete[] elements_;
595   delete[] quadraticElements_;
596   delete[] sortIndices_;
597   delete[] sortElements_;
598   delete[] associated_;
599   delete[] startSOS_;
600   delete[] memberSOS_;
601   delete[] typeSOS_;
602   delete[] prioritySOS_;
603   delete[] referenceSOS_;
604   delete[] priority_;
605   delete[] cut_;
606   delete packedMatrix_;
607 }
608 // Clone
609 CoinBaseModel *
clone() const610 CoinModel::clone() const
611 {
612   return new CoinModel(*this);
613 }
614 
615 //----------------------------------------------------------------
616 // Assignment operator
617 //-------------------------------------------------------------------
618 CoinModel &
operator =(const CoinModel & rhs)619 CoinModel::operator=(const CoinModel &rhs)
620 {
621   if (this != &rhs) {
622     CoinBaseModel::operator=(rhs);
623     delete[] rowLower_;
624     delete[] rowUpper_;
625     delete[] rowType_;
626     delete[] objective_;
627     delete[] columnLower_;
628     delete[] columnUpper_;
629     delete[] integerType_;
630     delete[] columnType_;
631     delete[] start_;
632     delete[] elements_;
633     delete[] quadraticElements_;
634     delete[] sortIndices_;
635     delete[] sortElements_;
636     delete[] associated_;
637     delete[] startSOS_;
638     delete[] memberSOS_;
639     delete[] typeSOS_;
640     delete[] prioritySOS_;
641     delete[] referenceSOS_;
642     delete[] priority_;
643     delete[] cut_;
644     delete packedMatrix_;
645     maximumRows_ = rhs.maximumRows_;
646     maximumColumns_ = rhs.maximumColumns_;
647     numberElements_ = rhs.numberElements_;
648     maximumElements_ = rhs.maximumElements_;
649     numberQuadraticElements_ = rhs.numberQuadraticElements_;
650     maximumQuadraticElements_ = rhs.maximumQuadraticElements_;
651     sortSize_ = rhs.sortSize_;
652     rowName_ = rhs.rowName_;
653     columnName_ = rhs.columnName_;
654     string_ = rhs.string_;
655     hashElements_ = rhs.hashElements_;
656     hashQuadraticElements_ = rhs.hashQuadraticElements_;
657     rowList_ = rhs.rowList_;
658     quadraticColumnList_ = rhs.quadraticColumnList_;
659     quadraticRowList_ = rhs.quadraticRowList_;
660     columnList_ = rhs.columnList_;
661     sizeAssociated_ = rhs.sizeAssociated_;
662     numberSOS_ = rhs.numberSOS_;
663     type_ = rhs.type_;
664     noNames_ = rhs.noNames_;
665     links_ = rhs.links_;
666     rowLower_ = CoinCopyOfArray(rhs.rowLower_, maximumRows_);
667     rowUpper_ = CoinCopyOfArray(rhs.rowUpper_, maximumRows_);
668     rowType_ = CoinCopyOfArray(rhs.rowType_, maximumRows_);
669     objective_ = CoinCopyOfArray(rhs.objective_, maximumColumns_);
670     columnLower_ = CoinCopyOfArray(rhs.columnLower_, maximumColumns_);
671     columnUpper_ = CoinCopyOfArray(rhs.columnUpper_, maximumColumns_);
672     integerType_ = CoinCopyOfArray(rhs.integerType_, maximumColumns_);
673     columnType_ = CoinCopyOfArray(rhs.columnType_, maximumColumns_);
674     priority_ = CoinCopyOfArray(rhs.priority_, maximumColumns_);
675     cut_ = CoinCopyOfArray(rhs.cut_, maximumRows_);
676     moreInfo_ = rhs.moreInfo_;
677     if (rhs.packedMatrix_)
678       packedMatrix_ = new CoinPackedMatrix(*rhs.packedMatrix_);
679     else
680       packedMatrix_ = NULL;
681     if (numberSOS_) {
682       startSOS_ = CoinCopyOfArray(rhs.startSOS_, numberSOS_ + 1);
683       int numberMembers = startSOS_[numberSOS_];
684       memberSOS_ = CoinCopyOfArray(rhs.memberSOS_, numberMembers);
685       typeSOS_ = CoinCopyOfArray(rhs.typeSOS_, numberSOS_);
686       prioritySOS_ = CoinCopyOfArray(rhs.prioritySOS_, numberSOS_);
687       referenceSOS_ = CoinCopyOfArray(rhs.referenceSOS_, numberMembers);
688     } else {
689       startSOS_ = NULL;
690       memberSOS_ = NULL;
691       typeSOS_ = NULL;
692       prioritySOS_ = NULL;
693       referenceSOS_ = NULL;
694     }
695     if (type_ == 0) {
696       start_ = CoinCopyOfArray(rhs.start_, maximumRows_ + 1);
697     } else if (type_ == 1) {
698       start_ = CoinCopyOfArray(rhs.start_, maximumColumns_ + 1);
699     } else {
700       start_ = NULL;
701     }
702     elements_ = CoinCopyOfArray(rhs.elements_, maximumElements_);
703     quadraticElements_ = CoinCopyOfArray(rhs.quadraticElements_, maximumQuadraticElements_);
704     sortIndices_ = CoinCopyOfArray(rhs.sortIndices_, sortSize_);
705     sortElements_ = CoinCopyOfArray(rhs.sortElements_, sortSize_);
706     associated_ = CoinCopyOfArray(rhs.associated_, sizeAssociated_);
707   }
708   return *this;
709 }
710 /* add a row -  numberInRow may be zero */
addRow(int numberInRow,const int * columns,const double * elements,double rowLower,double rowUpper,const char * name)711 void CoinModel::addRow(int numberInRow, const int *columns,
712   const double *elements, double rowLower,
713   double rowUpper, const char *name)
714 {
715   if (type_ == -1) {
716     // initial
717     type_ = 0;
718     resize(100, 0, 1000);
719   } else if (type_ == 1) {
720     // mixed - do linked lists for rows
721     createList(1);
722   } else if (type_ == 3) {
723     badType();
724   }
725   int newColumn = -1;
726   if (numberInRow > 0) {
727     // Move and sort
728     if (numberInRow > sortSize_) {
729       delete[] sortIndices_;
730       delete[] sortElements_;
731       sortSize_ = numberInRow + 100;
732       sortIndices_ = new int[sortSize_];
733       sortElements_ = new double[sortSize_];
734     }
735     bool sorted = true;
736     int last = -1;
737     int i;
738     for (i = 0; i < numberInRow; i++) {
739       int k = columns[i];
740       if (k <= last)
741         sorted = false;
742       last = k;
743       sortIndices_[i] = k;
744       sortElements_[i] = elements[i];
745     }
746     if (!sorted) {
747       CoinSort_2(sortIndices_, sortIndices_ + numberInRow, sortElements_);
748     }
749     // check for duplicates etc
750     if (sortIndices_[0] < 0) {
751       printf("bad index %d\n", sortIndices_[0]);
752       // clean up
753       abort();
754     }
755     last = -1;
756     bool duplicate = false;
757     for (i = 0; i < numberInRow; i++) {
758       int k = sortIndices_[i];
759       if (k == last)
760         duplicate = true;
761       last = k;
762     }
763     if (duplicate) {
764       printf("duplicates - what do we want\n");
765       abort();
766     }
767     newColumn = CoinMax(newColumn, last);
768   }
769   int newRow = 0;
770   CoinBigIndex newElement = 0;
771   if (numberElements_ + numberInRow > maximumElements_) {
772     newElement = (3 * (numberElements_ + numberInRow) / 2) + 1000;
773     if (numberRows_ * 10 > maximumRows_ * 9)
774       newRow = (maximumRows_ * 3) / 2 + 100;
775   }
776   if (numberRows_ == maximumRows_)
777     newRow = (maximumRows_ * 3) / 2 + 100;
778   if (newRow || newColumn >= maximumColumns_ || newElement) {
779     if (newColumn < maximumColumns_) {
780       // columns okay
781       resize(newRow, 0, newElement);
782     } else {
783       // newColumn will be new numberColumns_
784       resize(newRow, (3 * newColumn) / 2 + 100, newElement);
785     }
786   }
787   // If rows extended - take care of that
788   fillRows(numberRows_, false, true);
789   // Do name
790   if (name) {
791     rowName_.addHash(numberRows_, name);
792   } else if (!noNames_) {
793     char name[9];
794     sprintf(name, "r%7.7d", numberRows_);
795     rowName_.addHash(numberRows_, name);
796   }
797   rowLower_[numberRows_] = rowLower;
798   rowUpper_[numberRows_] = rowUpper;
799   // If columns extended - take care of that
800   fillColumns(newColumn, false);
801   if (type_ == 0) {
802     // can do simply
803     CoinBigIndex put = start_[numberRows_];
804     assert(put == numberElements_);
805     bool doHash = hashElements_.numberItems() != 0;
806     for (int i = 0; i < numberInRow; i++) {
807       setRowAndStringInTriple(elements_[put], numberRows_, false);
808       //elements_[put].row=static_cast<unsigned int>(numberRows_);
809       //elements_[put].string=0;
810       elements_[put].column = sortIndices_[i];
811       elements_[put].value = sortElements_[i];
812       if (doHash)
813         hashElements_.addHash(put, numberRows_, sortIndices_[i], elements_);
814       put++;
815     }
816     start_[numberRows_ + 1] = put;
817     numberElements_ += numberInRow;
818   } else {
819     if (numberInRow) {
820       // must update at least one link
821       assert(links_);
822       if (links_ == 1 || links_ == 3) {
823         CoinBigIndex first = rowList_.addEasy(numberRows_, numberInRow, sortIndices_, sortElements_, elements_,
824           hashElements_);
825         if (links_ == 3)
826           columnList_.addHard(first, elements_, rowList_.firstFree(), rowList_.lastFree(),
827             rowList_.next());
828         numberElements_ = CoinMax(numberElements_, rowList_.numberElements());
829         if (links_ == 3)
830           assert(columnList_.numberElements() == rowList_.numberElements());
831       } else if (links_ == 2) {
832         columnList_.addHard(numberRows_, numberInRow, sortIndices_, sortElements_, elements_,
833           hashElements_);
834         numberElements_ = CoinMax(numberElements_, columnList_.numberElements());
835       }
836     }
837     numberElements_ = CoinMax(numberElements_, hashElements_.numberItems());
838   }
839   numberRows_++;
840 }
841 // add a column - numberInColumn may be zero */
addColumn(int numberInColumn,const int * rows,const double * elements,double columnLower,double columnUpper,double objectiveValue,const char * name,bool isInteger)842 void CoinModel::addColumn(int numberInColumn, const int *rows,
843   const double *elements,
844   double columnLower,
845   double columnUpper, double objectiveValue,
846   const char *name, bool isInteger)
847 {
848   if (type_ == -1) {
849     // initial
850     type_ = 1;
851     resize(0, 100, 1000);
852   } else if (type_ == 0) {
853     // mixed - do linked lists for columns
854     createList(2);
855   } else if (type_ == 3) {
856     badType();
857   }
858   int newRow = -1;
859   if (numberInColumn > 0) {
860     // Move and sort
861     if (numberInColumn > sortSize_) {
862       delete[] sortIndices_;
863       delete[] sortElements_;
864       sortSize_ = numberInColumn + 100;
865       sortIndices_ = new int[sortSize_];
866       sortElements_ = new double[sortSize_];
867     }
868     bool sorted = true;
869     int last = -1;
870     int i;
871     for (i = 0; i < numberInColumn; i++) {
872       int k = rows[i];
873       if (k <= last)
874         sorted = false;
875       last = k;
876       sortIndices_[i] = k;
877       sortElements_[i] = elements[i];
878     }
879     if (!sorted) {
880       CoinSort_2(sortIndices_, sortIndices_ + numberInColumn, sortElements_);
881     }
882     // check for duplicates etc
883     if (sortIndices_[0] < 0) {
884       printf("bad index %d\n", sortIndices_[0]);
885       // clean up
886       abort();
887     }
888     last = -1;
889     bool duplicate = false;
890     for (i = 0; i < numberInColumn; i++) {
891       int k = sortIndices_[i];
892       if (k == last)
893         duplicate = true;
894       last = k;
895     }
896     if (duplicate) {
897       printf("duplicates - what do we want\n");
898       abort();
899     }
900     newRow = CoinMax(newRow, last);
901   }
902   int newColumn = 0;
903   CoinBigIndex newElement = 0;
904   if (numberElements_ + numberInColumn > maximumElements_) {
905     newElement = (3 * (numberElements_ + numberInColumn) / 2) + 1000;
906     if (numberColumns_ * 10 > maximumColumns_ * 9)
907       newColumn = (maximumColumns_ * 3) / 2 + 100;
908   }
909   if (numberColumns_ == maximumColumns_)
910     newColumn = (maximumColumns_ * 3) / 2 + 100;
911   if (newColumn || newRow >= maximumRows_ || newElement) {
912     if (newRow < maximumRows_) {
913       // rows okay
914       resize(0, newColumn, newElement);
915     } else {
916       // newRow will be new numberRows_
917       resize((3 * newRow) / 2 + 100, newColumn, newElement);
918     }
919   }
920   // If columns extended - take care of that
921   fillColumns(numberColumns_, false, true);
922   // Do name
923   if (name) {
924     columnName_.addHash(numberColumns_, name);
925   } else if (!noNames_) {
926     char name[9];
927     sprintf(name, "c%7.7d", numberColumns_);
928     columnName_.addHash(numberColumns_, name);
929   }
930   columnLower_[numberColumns_] = columnLower;
931   columnUpper_[numberColumns_] = columnUpper;
932   objective_[numberColumns_] = objectiveValue;
933   if (isInteger)
934     integerType_[numberColumns_] = 1;
935   else
936     integerType_[numberColumns_] = 0;
937   // If rows extended - take care of that
938   fillRows(newRow, false);
939   if (type_ == 1) {
940     // can do simply
941     CoinBigIndex put = start_[numberColumns_];
942     assert(put == numberElements_);
943     bool doHash = hashElements_.numberItems() != 0;
944     for (int i = 0; i < numberInColumn; i++) {
945       elements_[put].column = numberColumns_;
946       setRowAndStringInTriple(elements_[put], sortIndices_[i], false);
947       //elements_[put].string=0;
948       //elements_[put].row=static_cast<unsigned int>(sortIndices_[i]);
949       elements_[put].value = sortElements_[i];
950       if (doHash)
951         hashElements_.addHash(put, sortIndices_[i], numberColumns_, elements_);
952       put++;
953     }
954     start_[numberColumns_ + 1] = put;
955     numberElements_ += numberInColumn;
956   } else {
957     if (numberInColumn) {
958       // must update at least one link
959       assert(links_);
960       if (links_ == 2 || links_ == 3) {
961         CoinBigIndex first = columnList_.addEasy(numberColumns_, numberInColumn, sortIndices_, sortElements_, elements_,
962           hashElements_);
963         if (links_ == 3)
964           rowList_.addHard(first, elements_, columnList_.firstFree(), columnList_.lastFree(),
965             columnList_.next());
966         numberElements_ = CoinMax(numberElements_, columnList_.numberElements());
967         if (links_ == 3)
968           assert(columnList_.numberElements() == rowList_.numberElements());
969       } else if (links_ == 1) {
970         rowList_.addHard(numberColumns_, numberInColumn, sortIndices_, sortElements_, elements_,
971           hashElements_);
972         numberElements_ = CoinMax(numberElements_, rowList_.numberElements());
973       }
974     }
975   }
976   numberColumns_++;
977 }
978 // Sets value for row i and column j
setElement(int i,int j,double value)979 void CoinModel::setElement(int i, int j, double value)
980 {
981   if (type_ == -1) {
982     // initial
983     type_ = 0;
984     resize(100, 100, 1000);
985     createList(2);
986   } else if (type_ == 3) {
987     badType();
988   } else if (!links_) {
989     if (type_ == 0 || type_ == 2) {
990       createList(1);
991     } else if (type_ == 1) {
992       createList(2);
993     }
994   }
995   if (!hashElements_.maximumItems()) {
996     hashElements_.resize(maximumElements_, elements_);
997   }
998   CoinBigIndex position = hashElements_.hash(i, j, elements_);
999   if (position >= 0) {
1000     elements_[position].value = value;
1001     setStringInTriple(elements_[position], false);
1002   } else {
1003     int newColumn = 0;
1004     if (j >= maximumColumns_) {
1005       newColumn = j + 1;
1006     }
1007     int newRow = 0;
1008     if (i >= maximumRows_) {
1009       newRow = i + 1;
1010     }
1011     CoinBigIndex newElement = 0;
1012     if (numberElements_ == maximumElements_) {
1013       newElement = (3 * numberElements_ / 2) + 1000;
1014     }
1015     if (newRow || newColumn || newElement) {
1016       if (newColumn)
1017         newColumn = (3 * newColumn) / 2 + 100;
1018       if (newRow)
1019         newRow = (3 * newRow) / 2 + 100;
1020       resize(newRow, newColumn, newElement);
1021     }
1022     // If columns extended - take care of that
1023     fillColumns(j, false);
1024     // If rows extended - take care of that
1025     fillRows(i, false);
1026     // treat as addRow unless only columnList_ exists
1027     if ((links_ & 1) != 0) {
1028       CoinBigIndex first = rowList_.addEasy(i, 1, &j, &value, elements_, hashElements_);
1029       if (links_ == 3)
1030         columnList_.addHard(first, elements_, rowList_.firstFree(), rowList_.lastFree(),
1031           rowList_.next());
1032       numberElements_ = CoinMax(numberElements_, rowList_.numberElements());
1033       if (links_ == 3)
1034         assert(columnList_.numberElements() == rowList_.numberElements());
1035     } else if (links_ == 2) {
1036       columnList_.addHard(i, 1, &j, &value, elements_, hashElements_);
1037       numberElements_ = CoinMax(numberElements_, columnList_.numberElements());
1038     }
1039     numberRows_ = CoinMax(numberRows_, i + 1);
1040     ;
1041     numberColumns_ = CoinMax(numberColumns_, j + 1);
1042     ;
1043   }
1044 }
1045 // Sets quadratic value for column i and j
setQuadraticElement(int,int,double)1046 void CoinModel::setQuadraticElement(int, int, double)
1047 {
1048   printf("not written yet\n");
1049   abort();
1050   return;
1051 }
1052 // Sets value for row i and column j as string
setElement(int i,int j,const char * value)1053 void CoinModel::setElement(int i, int j, const char *value)
1054 {
1055   double dummyValue = 1.0;
1056   if (type_ == -1) {
1057     // initial
1058     type_ = 0;
1059     resize(100, 100, 1000);
1060     createList(2);
1061   } else if (type_ == 3) {
1062     badType();
1063   } else if (!links_) {
1064     if (type_ == 0 || type_ == 2) {
1065       createList(1);
1066     } else if (type_ == 1) {
1067       createList(2);
1068     }
1069   }
1070   if (!hashElements_.maximumItems()) {
1071     // set up number of items
1072     hashElements_.setNumberItems(numberElements_);
1073     hashElements_.resize(maximumElements_, elements_);
1074   }
1075   CoinBigIndex position = hashElements_.hash(i, j, elements_);
1076   if (position >= 0) {
1077     int iValue = addString(value);
1078     elements_[position].value = iValue;
1079     setStringInTriple(elements_[position], true);
1080   } else {
1081     int newColumn = 0;
1082     if (j >= maximumColumns_) {
1083       newColumn = j + 1;
1084     }
1085     int newRow = 0;
1086     if (i >= maximumRows_) {
1087       newRow = i + 1;
1088     }
1089     CoinBigIndex newElement = 0;
1090     if (numberElements_ == maximumElements_) {
1091       newElement = (3 * numberElements_ / 2) + 1000;
1092     }
1093     if (newRow || newColumn || newElement) {
1094       if (newColumn)
1095         newColumn = (3 * newColumn) / 2 + 100;
1096       if (newRow)
1097         newRow = (3 * newRow) / 2 + 100;
1098       resize(newRow, newColumn, newElement);
1099     }
1100     // If columns extended - take care of that
1101     fillColumns(j, false);
1102     // If rows extended - take care of that
1103     fillRows(i, false);
1104     // treat as addRow unless only columnList_ exists
1105     if ((links_ & 1) != 0) {
1106       CoinBigIndex first = rowList_.addEasy(i, 1, &j, &dummyValue, elements_, hashElements_);
1107       if (links_ == 3)
1108         columnList_.addHard(first, elements_, rowList_.firstFree(), rowList_.lastFree(),
1109           rowList_.next());
1110       numberElements_ = CoinMax(numberElements_, rowList_.numberElements());
1111       if (links_ == 3)
1112         assert(columnList_.numberElements() == rowList_.numberElements());
1113     } else if (links_ == 2) {
1114       columnList_.addHard(i, 1, &j, &dummyValue, elements_, hashElements_);
1115       numberElements_ = CoinMax(numberElements_, columnList_.numberElements());
1116     }
1117     numberRows_ = CoinMax(numberRows_, i + 1);
1118     ;
1119     numberColumns_ = CoinMax(numberColumns_, j + 1);
1120     ;
1121     CoinBigIndex position = hashElements_.hash(i, j, elements_);
1122     assert(position >= 0);
1123     int iValue = addString(value);
1124     elements_[position].value = iValue;
1125     setStringInTriple(elements_[position], true);
1126   }
1127 }
1128 // Associates a string with a value.  Returns string id (or -1 if does not exist)
associateElement(const char * stringValue,double value)1129 int CoinModel::associateElement(const char *stringValue, double value)
1130 {
1131   int position = string_.hash(stringValue);
1132   if (position < 0) {
1133     // not there -add
1134     position = addString(stringValue);
1135     assert(position == string_.numberItems() - 1);
1136   }
1137   if (sizeAssociated_ <= position) {
1138     int newSize = (3 * position) / 2 + 100;
1139     double *temp = new double[newSize];
1140     CoinMemcpyN(associated_, sizeAssociated_, temp);
1141     CoinFillN(temp + sizeAssociated_, newSize - sizeAssociated_, unsetValue());
1142     delete[] associated_;
1143     associated_ = temp;
1144     sizeAssociated_ = newSize;
1145   }
1146   associated_[position] = value;
1147   return position;
1148 }
1149 /* Sets rowLower (if row does not exist then
1150    all rows up to this are defined with default values and no elements)
1151 */
setRowLower(int whichRow,double rowLower)1152 void CoinModel::setRowLower(int whichRow, double rowLower)
1153 {
1154   assert(whichRow >= 0);
1155   // make sure enough room and fill
1156   fillRows(whichRow, true);
1157   rowLower_[whichRow] = rowLower;
1158   rowType_[whichRow] &= ~1;
1159 }
1160 /* Sets rowUpper (if row does not exist then
1161    all rows up to this are defined with default values and no elements)
1162 */
setRowUpper(int whichRow,double rowUpper)1163 void CoinModel::setRowUpper(int whichRow, double rowUpper)
1164 {
1165   assert(whichRow >= 0);
1166   // make sure enough room and fill
1167   fillRows(whichRow, true);
1168   rowUpper_[whichRow] = rowUpper;
1169   rowType_[whichRow] &= ~2;
1170 }
1171 /* Sets rowLower and rowUpper (if row does not exist then
1172    all rows up to this are defined with default values and no elements)
1173 */
setRowBounds(int whichRow,double rowLower,double rowUpper)1174 void CoinModel::setRowBounds(int whichRow, double rowLower, double rowUpper)
1175 {
1176   assert(whichRow >= 0);
1177   // make sure enough room and fill
1178   fillRows(whichRow, true);
1179   rowLower_[whichRow] = rowLower;
1180   rowUpper_[whichRow] = rowUpper;
1181   rowType_[whichRow] &= ~3;
1182 }
1183 /* Sets name (if row does not exist then
1184    all rows up to this are defined with default values and no elements)
1185 */
setRowName(int whichRow,const char * rowName)1186 void CoinModel::setRowName(int whichRow, const char *rowName)
1187 {
1188   assert(whichRow >= 0);
1189   // make sure enough room and fill
1190   fillRows(whichRow, true);
1191   assert(!noNames_);
1192   const char *oldName = rowName_.name(whichRow);
1193   if (oldName)
1194     rowName_.deleteHash(whichRow);
1195   if (rowName)
1196     rowName_.addHash(whichRow, rowName);
1197 }
1198 /* Sets columnLower (if column does not exist then
1199    all columns up to this are defined with default values and no elements)
1200 */
setColumnLower(int whichColumn,double columnLower)1201 void CoinModel::setColumnLower(int whichColumn, double columnLower)
1202 {
1203   assert(whichColumn >= 0);
1204   // make sure enough room and fill
1205   fillColumns(whichColumn, true);
1206   columnLower_[whichColumn] = columnLower;
1207   columnType_[whichColumn] &= ~1;
1208 }
1209 /* Sets columnUpper (if column does not exist then
1210    all columns up to this are defined with default values and no elements)
1211 */
setColumnUpper(int whichColumn,double columnUpper)1212 void CoinModel::setColumnUpper(int whichColumn, double columnUpper)
1213 {
1214   assert(whichColumn >= 0);
1215   // make sure enough room and fill
1216   fillColumns(whichColumn, true);
1217   columnUpper_[whichColumn] = columnUpper;
1218   columnType_[whichColumn] &= ~2;
1219 }
1220 /* Sets columnLower and columnUpper (if column does not exist then
1221    all columns up to this are defined with default values and no elements)
1222 */
setColumnBounds(int whichColumn,double columnLower,double columnUpper)1223 void CoinModel::setColumnBounds(int whichColumn, double columnLower, double columnUpper)
1224 {
1225   assert(whichColumn >= 0);
1226   // make sure enough room and fill
1227   fillColumns(whichColumn, true);
1228   columnLower_[whichColumn] = columnLower;
1229   columnUpper_[whichColumn] = columnUpper;
1230   columnType_[whichColumn] &= ~3;
1231 }
1232 /* Sets columnObjective (if column does not exist then
1233    all columns up to this are defined with default values and no elements)
1234 */
setColumnObjective(int whichColumn,double columnObjective)1235 void CoinModel::setColumnObjective(int whichColumn, double columnObjective)
1236 {
1237   assert(whichColumn >= 0);
1238   // make sure enough room and fill
1239   fillColumns(whichColumn, true);
1240   objective_[whichColumn] = columnObjective;
1241   columnType_[whichColumn] &= ~4;
1242 }
1243 /* Sets name (if column does not exist then
1244    all columns up to this are defined with default values and no elements)
1245 */
setColumnName(int whichColumn,const char * columnName)1246 void CoinModel::setColumnName(int whichColumn, const char *columnName)
1247 {
1248   assert(whichColumn >= 0);
1249   // make sure enough room and fill
1250   fillColumns(whichColumn, true);
1251   const char *oldName = columnName_.name(whichColumn);
1252   assert(!noNames_);
1253   if (oldName)
1254     columnName_.deleteHash(whichColumn);
1255   if (columnName)
1256     columnName_.addHash(whichColumn, columnName);
1257 }
1258 /* Sets integer (if column does not exist then
1259    all columns up to this are defined with default values and no elements)
1260 */
setColumnIsInteger(int whichColumn,bool columnIsInteger)1261 void CoinModel::setColumnIsInteger(int whichColumn, bool columnIsInteger)
1262 {
1263   assert(whichColumn >= 0);
1264   // make sure enough room and fill
1265   fillColumns(whichColumn, true);
1266   integerType_[whichColumn] = (columnIsInteger) ? 1 : 0;
1267   columnType_[whichColumn] &= ~8;
1268 }
1269 // Adds one string, returns index
addString(const char * string)1270 int CoinModel::addString(const char *string)
1271 {
1272   int position = string_.hash(string);
1273   if (position < 0) {
1274     position = string_.numberItems();
1275     string_.addHash(position, string);
1276   }
1277   return position;
1278 }
1279 /* Sets rowLower (if row does not exist then
1280    all rows up to this are defined with default values and no elements)
1281 */
setRowLower(int whichRow,const char * rowLower)1282 void CoinModel::setRowLower(int whichRow, const char *rowLower)
1283 {
1284   assert(whichRow >= 0);
1285   // make sure enough room and fill
1286   fillRows(whichRow, true);
1287   if (rowLower) {
1288     int value = addString(rowLower);
1289     rowLower_[whichRow] = value;
1290     rowType_[whichRow] |= 1;
1291   } else {
1292     rowLower_[whichRow] = -COIN_DBL_MAX;
1293   }
1294 }
1295 /* Sets rowUpper (if row does not exist then
1296    all rows up to this are defined with default values and no elements)
1297 */
setRowUpper(int whichRow,const char * rowUpper)1298 void CoinModel::setRowUpper(int whichRow, const char *rowUpper)
1299 {
1300   assert(whichRow >= 0);
1301   // make sure enough room and fill
1302   fillRows(whichRow, true);
1303   if (rowUpper) {
1304     int value = addString(rowUpper);
1305     rowUpper_[whichRow] = value;
1306     rowType_[whichRow] |= 2;
1307   } else {
1308     rowUpper_[whichRow] = COIN_DBL_MAX;
1309   }
1310 }
1311 /* Sets columnLower (if column does not exist then
1312    all columns up to this are defined with default values and no elements)
1313 */
setColumnLower(int whichColumn,const char * columnLower)1314 void CoinModel::setColumnLower(int whichColumn, const char *columnLower)
1315 {
1316   assert(whichColumn >= 0);
1317   // make sure enough room and fill
1318   fillColumns(whichColumn, true);
1319   if (columnLower) {
1320     int value = addString(columnLower);
1321     columnLower_[whichColumn] = value;
1322     columnType_[whichColumn] |= 1;
1323   } else {
1324     columnLower_[whichColumn] = 0.0;
1325   }
1326 }
1327 /* Sets columnUpper (if column does not exist then
1328    all columns up to this are defined with default values and no elements)
1329 */
setColumnUpper(int whichColumn,const char * columnUpper)1330 void CoinModel::setColumnUpper(int whichColumn, const char *columnUpper)
1331 {
1332   assert(whichColumn >= 0);
1333   // make sure enough room and fill
1334   fillColumns(whichColumn, true);
1335   if (columnUpper) {
1336     int value = addString(columnUpper);
1337     columnUpper_[whichColumn] = value;
1338     columnType_[whichColumn] |= 2;
1339   } else {
1340     columnUpper_[whichColumn] = COIN_DBL_MAX;
1341   }
1342 }
1343 /* Sets columnObjective (if column does not exist then
1344    all columns up to this are defined with default values and no elements)
1345 */
setColumnObjective(int whichColumn,const char * columnObjective)1346 void CoinModel::setColumnObjective(int whichColumn, const char *columnObjective)
1347 {
1348   assert(whichColumn >= 0);
1349   // make sure enough room and fill
1350   fillColumns(whichColumn, true);
1351   if (columnObjective) {
1352     int value = addString(columnObjective);
1353     objective_[whichColumn] = value;
1354     columnType_[whichColumn] |= 4;
1355   } else {
1356     objective_[whichColumn] = 0.0;
1357   }
1358 }
1359 /* Sets integer (if column does not exist then
1360    all columns up to this are defined with default values and no elements)
1361 */
setColumnIsInteger(int whichColumn,const char * columnIsInteger)1362 void CoinModel::setColumnIsInteger(int whichColumn, const char *columnIsInteger)
1363 {
1364   assert(whichColumn >= 0);
1365   // make sure enough room and fill
1366   fillColumns(whichColumn, true);
1367   if (columnIsInteger) {
1368     int value = addString(columnIsInteger);
1369     integerType_[whichColumn] = value;
1370     columnType_[whichColumn] |= 8;
1371   } else {
1372     integerType_[whichColumn] = 0;
1373   }
1374 }
1375 //static const char * minusInfinity="-infinity";
1376 //static const char * plusInfinity="+infinity";
1377 //static const char * zero="0.0";
1378 static const char *numeric = "Numeric";
1379 /* Gets rowLower (if row does not exist then -COIN_DBL_MAX)
1380  */
1381 const char *
getRowLowerAsString(int whichRow) const1382 CoinModel::getRowLowerAsString(int whichRow) const
1383 {
1384   assert(whichRow >= 0);
1385   if (whichRow < numberRows_ && rowLower_) {
1386     if ((rowType_[whichRow] & 1) != 0) {
1387       int position = static_cast< int >(rowLower_[whichRow]);
1388       return string_.name(position);
1389     } else {
1390       return numeric;
1391     }
1392   } else {
1393     return numeric;
1394   }
1395 }
1396 /* Gets rowUpper (if row does not exist then +COIN_DBL_MAX)
1397  */
1398 const char *
getRowUpperAsString(int whichRow) const1399 CoinModel::getRowUpperAsString(int whichRow) const
1400 {
1401   assert(whichRow >= 0);
1402   if (whichRow < numberRows_ && rowUpper_) {
1403     if ((rowType_[whichRow] & 2) != 0) {
1404       int position = static_cast< int >(rowUpper_[whichRow]);
1405       return string_.name(position);
1406     } else {
1407       return numeric;
1408     }
1409   } else {
1410     return numeric;
1411   }
1412 }
1413 /* Gets columnLower (if column does not exist then 0.0)
1414  */
1415 const char *
getColumnLowerAsString(int whichColumn) const1416 CoinModel::getColumnLowerAsString(int whichColumn) const
1417 {
1418   assert(whichColumn >= 0);
1419   if (whichColumn < numberColumns_ && columnLower_) {
1420     if ((columnType_[whichColumn] & 1) != 0) {
1421       int position = static_cast< int >(columnLower_[whichColumn]);
1422       return string_.name(position);
1423     } else {
1424       return numeric;
1425     }
1426   } else {
1427     return numeric;
1428   }
1429 }
1430 /* Gets columnUpper (if column does not exist then COIN_DBL_MAX)
1431  */
1432 const char *
getColumnUpperAsString(int whichColumn) const1433 CoinModel::getColumnUpperAsString(int whichColumn) const
1434 {
1435   assert(whichColumn >= 0);
1436   if (whichColumn < numberColumns_ && columnUpper_) {
1437     if ((columnType_[whichColumn] & 2) != 0) {
1438       int position = static_cast< int >(columnUpper_[whichColumn]);
1439       return string_.name(position);
1440     } else {
1441       return numeric;
1442     }
1443   } else {
1444     return numeric;
1445   }
1446 }
1447 /* Gets columnObjective (if column does not exist then 0.0)
1448  */
1449 const char *
getColumnObjectiveAsString(int whichColumn) const1450 CoinModel::getColumnObjectiveAsString(int whichColumn) const
1451 {
1452   assert(whichColumn >= 0);
1453   if (whichColumn < numberColumns_ && objective_) {
1454     if ((columnType_[whichColumn] & 4) != 0) {
1455       int position = static_cast< int >(objective_[whichColumn]);
1456       return string_.name(position);
1457     } else {
1458       return numeric;
1459     }
1460   } else {
1461     return numeric;
1462   }
1463 }
1464 /* Gets if integer (if column does not exist then false)
1465  */
1466 const char *
getColumnIsIntegerAsString(int whichColumn) const1467 CoinModel::getColumnIsIntegerAsString(int whichColumn) const
1468 {
1469   assert(whichColumn >= 0);
1470   if (whichColumn < numberColumns_ && integerType_) {
1471     if ((columnType_[whichColumn] & 8) != 0) {
1472       int position = integerType_[whichColumn];
1473       return string_.name(position);
1474     } else {
1475       return numeric;
1476     }
1477   } else {
1478     return numeric;
1479   }
1480 }
1481 /* Deletes all entries in row and bounds.*/
deleteRow(int whichRow)1482 void CoinModel::deleteRow(int whichRow)
1483 {
1484   assert(whichRow >= 0);
1485   if (whichRow < numberRows_) {
1486     if (rowLower_) {
1487       rowLower_[whichRow] = -COIN_DBL_MAX;
1488       rowUpper_[whichRow] = COIN_DBL_MAX;
1489       rowType_[whichRow] = 0;
1490       if (!noNames_)
1491         rowName_.deleteHash(whichRow);
1492     }
1493     // need lists
1494     if (type_ == 0) {
1495       assert(start_);
1496       assert(!hashElements_.numberItems());
1497       delete[] start_;
1498       start_ = NULL;
1499     }
1500     if ((links_ & 1) == 0) {
1501       createList(1);
1502     }
1503     assert(links_);
1504     // row links guaranteed to exist
1505     rowList_.deleteSame(whichRow, elements_, hashElements_, (links_ != 3));
1506     // Just need to set first and last and take out
1507     if (links_ == 3)
1508       columnList_.updateDeleted(whichRow, elements_, rowList_);
1509   }
1510 }
1511 /* Deletes all entries in column and bounds.*/
deleteColumn(int whichColumn)1512 void CoinModel::deleteColumn(int whichColumn)
1513 {
1514   assert(whichColumn >= 0);
1515   if (whichColumn < numberColumns_) {
1516     if (columnLower_) {
1517       columnLower_[whichColumn] = 0.0;
1518       columnUpper_[whichColumn] = COIN_DBL_MAX;
1519       objective_[whichColumn] = 0.0;
1520       integerType_[whichColumn] = 0;
1521       columnType_[whichColumn] = 0;
1522       if (!noNames_)
1523         columnName_.deleteHash(whichColumn);
1524     }
1525     // need lists
1526     if (type_ == 0) {
1527       assert(start_);
1528       assert(!hashElements_.numberItems());
1529       delete[] start_;
1530       start_ = NULL;
1531     } else if (type_ == 3) {
1532       badType();
1533     }
1534     if ((links_ & 2) == 0) {
1535       createList(2);
1536     }
1537     assert(links_);
1538     // column links guaranteed to exist
1539     columnList_.deleteSame(whichColumn, elements_, hashElements_, (links_ != 3));
1540     // Just need to set first and last and take out
1541     if (links_ == 3)
1542       rowList_.updateDeleted(whichColumn, elements_, columnList_);
1543   }
1544 }
1545 // Takes element out of matrix
1546 CoinBigIndex
deleteElement(int row,int column)1547 CoinModel::deleteElement(int row, int column)
1548 {
1549   CoinBigIndex iPos = position(row, column);
1550   if (iPos >= 0)
1551     deleteThisElement(row, column, iPos);
1552   return iPos;
1553 }
1554 // Takes element out of matrix when position known
1555 void
1556 #ifndef NDEBUG
deleteThisElement(int row,int column,CoinBigIndex position)1557 CoinModel::deleteThisElement(int row, int column, CoinBigIndex position)
1558 #else
1559 CoinModel::deleteThisElement(int, int, CoinBigIndex position)
1560 #endif
1561 {
1562   assert(row < numberRows_ && column < numberColumns_);
1563   assert(row == rowInTriple(elements_[position]) && column == static_cast< int >(elements_[position].column));
1564   if ((links_ & 1) == 0) {
1565     createList(1);
1566   }
1567   assert(links_);
1568   // row links guaranteed to exist
1569   rowList_.deleteRowOne(position, elements_, hashElements_);
1570   // Just need to set first and last and take out
1571   if (links_ == 3)
1572     columnList_.updateDeletedOne(position, elements_);
1573   elements_[position].column = -1;
1574   elements_[position].value = 0.0;
1575 }
1576 /* Packs down all rows i.e. removes empty rows permanently.  Empty rows
1577    have no elements and feasible bounds. returns number of rows deleted. */
packRows()1578 int CoinModel::packRows()
1579 {
1580   if (type_ == 3)
1581     badType();
1582   int *newRow = new int[numberRows_];
1583   memset(newRow, 0, numberRows_ * sizeof(int));
1584   int iRow;
1585   int n = 0;
1586   for (iRow = 0; iRow < numberRows_; iRow++) {
1587     if (rowLower_[iRow] != -COIN_DBL_MAX)
1588       newRow[iRow]++;
1589     if (rowUpper_[iRow] != COIN_DBL_MAX)
1590       newRow[iRow]++;
1591     if (!noNames_ && rowName_.name(iRow))
1592       newRow[iRow]++;
1593   }
1594   int i;
1595   for (i = 0; i < numberElements_; i++) {
1596     if (elements_[i].column >= 0) {
1597       iRow = rowInTriple(elements_[i]);
1598       assert(iRow >= 0 && iRow < numberRows_);
1599       newRow[iRow]++;
1600     }
1601   }
1602   bool doRowNames = (rowName_.numberItems() != 0);
1603   for (iRow = 0; iRow < numberRows_; iRow++) {
1604     if (newRow[iRow]) {
1605       rowLower_[n] = rowLower_[iRow];
1606       rowUpper_[n] = rowUpper_[iRow];
1607       rowType_[n] = rowType_[iRow];
1608       if (doRowNames)
1609         rowName_.setName(n, rowName_.getName(iRow));
1610       newRow[iRow] = n++;
1611     } else {
1612       newRow[iRow] = -1;
1613     }
1614   }
1615   int numberDeleted = numberRows_ - n;
1616   if (numberDeleted) {
1617     numberRows_ = n;
1618     n = 0;
1619     for (i = 0; i < numberElements_; i++) {
1620       if (elements_[i].column >= 0) {
1621         elements_[n] = elements_[i];
1622         setRowInTriple(elements_[n], newRow[rowInTriple(elements_[i])]);
1623         n++;
1624       }
1625     }
1626     numberElements_ = n;
1627     // now redo
1628     if (doRowNames) {
1629       rowName_.setNumberItems(numberRows_);
1630       rowName_.resize(rowName_.maximumItems(), true);
1631     }
1632     if (hashElements_.numberItems()) {
1633       hashElements_.setNumberItems(numberElements_);
1634       hashElements_.resize(hashElements_.maximumItems(), elements_, true);
1635     }
1636     if (start_) {
1637       int last = -1;
1638       if (type_ == 0) {
1639         for (i = 0; i < numberElements_; i++) {
1640           int now = rowInTriple(elements_[i]);
1641           assert(now >= last);
1642           if (now > last) {
1643             start_[last + 1] = numberElements_;
1644             for (int j = last + 1; j < now; j++)
1645               start_[j + 1] = numberElements_;
1646             last = now;
1647           }
1648         }
1649         for (int j = last + 1; j < numberRows_; j++)
1650           start_[j + 1] = numberElements_;
1651       } else {
1652         assert(type_ == 1);
1653         for (i = 0; i < numberElements_; i++) {
1654           int now = elements_[i].column;
1655           assert(now >= last);
1656           if (now > last) {
1657             start_[last + 1] = numberElements_;
1658             for (int j = last + 1; j < now; j++)
1659               start_[j + 1] = numberElements_;
1660             last = now;
1661           }
1662         }
1663         for (int j = last + 1; j < numberColumns_; j++)
1664           start_[j + 1] = numberElements_;
1665       }
1666     }
1667     if ((links_ & 1) != 0) {
1668       rowList_ = CoinModelLinkedList();
1669       links_ &= ~1;
1670       createList(1);
1671     }
1672     if ((links_ & 2) != 0) {
1673       columnList_ = CoinModelLinkedList();
1674       links_ &= ~2;
1675       createList(2);
1676     }
1677   }
1678   delete[] newRow;
1679   return numberDeleted;
1680 }
1681 /* Packs down all columns i.e. removes empty columns permanently.  Empty columns
1682    have no elements and no objective. returns number of columns deleted. */
packColumns()1683 int CoinModel::packColumns()
1684 {
1685   if (type_ == 3)
1686     badType();
1687   int *newColumn = new int[numberColumns_];
1688   memset(newColumn, 0, numberColumns_ * sizeof(int));
1689   int iColumn;
1690   int n = 0;
1691   for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1692     if (columnLower_[iColumn] != 0.0)
1693       newColumn[iColumn]++;
1694     if (columnUpper_[iColumn] != COIN_DBL_MAX)
1695       newColumn[iColumn]++;
1696     if (objective_[iColumn] != 0.0)
1697       newColumn[iColumn]++;
1698     if (!noNames_ && columnName_.name(iColumn))
1699       newColumn[iColumn]++;
1700   }
1701   int i;
1702   for (i = 0; i < numberElements_; i++) {
1703     if (elements_[i].column >= 0) {
1704       iColumn = static_cast< int >(elements_[i].column);
1705       assert(iColumn >= 0 && iColumn < numberColumns_);
1706       newColumn[iColumn]++;
1707     }
1708   }
1709   bool doColumnNames = (columnName_.numberItems() != 0);
1710   for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1711     if (newColumn[iColumn]) {
1712       columnLower_[n] = columnLower_[iColumn];
1713       columnUpper_[n] = columnUpper_[iColumn];
1714       objective_[n] = objective_[iColumn];
1715       integerType_[n] = integerType_[iColumn];
1716       columnType_[n] = columnType_[iColumn];
1717       if (doColumnNames)
1718         columnName_.setName(n, columnName_.getName(iColumn));
1719       newColumn[iColumn] = n++;
1720     } else {
1721       newColumn[iColumn] = -1;
1722     }
1723   }
1724   int numberDeleted = numberColumns_ - n;
1725   if (numberDeleted) {
1726     numberColumns_ = n;
1727     n = 0;
1728     for (i = 0; i < numberElements_; i++) {
1729       if (elements_[i].column >= 0) {
1730         elements_[n] = elements_[i];
1731         elements_[n].column = newColumn[elements_[i].column];
1732         n++;
1733       }
1734     }
1735     numberElements_ = n;
1736     // now redo
1737     if (doColumnNames) {
1738       columnName_.setNumberItems(numberColumns_);
1739       columnName_.resize(columnName_.maximumItems(), true);
1740     }
1741     if (hashElements_.numberItems()) {
1742       hashElements_.setNumberItems(numberElements_);
1743       hashElements_.resize(hashElements_.maximumItems(), elements_, true);
1744     }
1745     if (start_) {
1746       int last = -1;
1747       if (type_ == 0) {
1748         for (i = 0; i < numberElements_; i++) {
1749           int now = rowInTriple(elements_[i]);
1750           assert(now >= last);
1751           if (now > last) {
1752             start_[last + 1] = numberElements_;
1753             for (int j = last + 1; j < now; j++)
1754               start_[j + 1] = numberElements_;
1755             last = now;
1756           }
1757         }
1758         for (int j = last + 1; j < numberRows_; j++)
1759           start_[j + 1] = numberElements_;
1760       } else {
1761         assert(type_ == 1);
1762         for (i = 0; i < numberElements_; i++) {
1763           int now = elements_[i].column;
1764           assert(now >= last);
1765           if (now > last) {
1766             start_[last + 1] = numberElements_;
1767             for (int j = last + 1; j < now; j++)
1768               start_[j + 1] = numberElements_;
1769             last = now;
1770           }
1771         }
1772         for (int j = last + 1; j < numberColumns_; j++)
1773           start_[j + 1] = numberElements_;
1774       }
1775     }
1776     if ((links_ & 1) != 0) {
1777       rowList_ = CoinModelLinkedList();
1778       links_ &= ~1;
1779       createList(1);
1780     }
1781     if ((links_ & 2) != 0) {
1782       columnList_ = CoinModelLinkedList();
1783       links_ &= ~2;
1784       createList(2);
1785     }
1786   }
1787   delete[] newColumn;
1788   return numberDeleted;
1789 }
1790 /* Packs down all rows and columns.  i.e. removes empty rows and columns permanently.
1791    Empty rows have no elements and feasible bounds.
1792    Empty columns have no elements and no objective.
1793    returns number of rows+columns deleted. */
pack()1794 int CoinModel::pack()
1795 {
1796   // For now do slowly (obvious overheads)
1797   return packRows() + packColumns();
1798 }
1799 // Creates a packed matrix - return sumber of errors
createPackedMatrix(CoinPackedMatrix & matrix,const double * associated)1800 int CoinModel::createPackedMatrix(CoinPackedMatrix &matrix,
1801   const double *associated)
1802 {
1803   if (type_ == 3)
1804     return 0; // badType();
1805   // Set to say all parts
1806   type_ = 2;
1807   resize(numberRows_, numberColumns_, numberElements_);
1808   // Do counts for CoinPackedMatrix
1809   int *length = new int[numberColumns_];
1810   CoinZeroN(length, numberColumns_);
1811   int i;
1812   int numberElements = 0;
1813   for (i = 0; i < numberElements_; i++) {
1814     int column = elements_[i].column;
1815     if (column >= 0) {
1816       length[column]++;
1817       numberElements++;
1818     }
1819   }
1820   int numberErrors = 0;
1821   CoinBigIndex *start = new CoinBigIndex[numberColumns_ + 1];
1822   int *row = new int[numberElements];
1823   double *element = new double[numberElements];
1824   start[0] = 0;
1825   for (i = 0; i < numberColumns_; i++) {
1826     start[i + 1] = start[i] + length[i];
1827     length[i] = 0;
1828   }
1829   numberElements = 0;
1830   for (i = 0; i < numberElements_; i++) {
1831     int column = elements_[i].column;
1832     if (column >= 0) {
1833       double value = elements_[i].value;
1834       if (stringInTriple(elements_[i])) {
1835         int position = static_cast< int >(value);
1836         assert(position < sizeAssociated_);
1837         value = associated[position];
1838         if (value == unsetValue()) {
1839           numberErrors++;
1840           value = 0.0;
1841         }
1842       }
1843       if (value) {
1844         numberElements++;
1845         CoinBigIndex put = start[column] + length[column];
1846         row[put] = rowInTriple(elements_[i]);
1847         element[put] = value;
1848         length[column]++;
1849       }
1850     }
1851   }
1852   for (i = 0; i < numberColumns_; i++) {
1853     CoinBigIndex put = start[i];
1854     CoinSort_2(row + put, row + put + length[i], element + put);
1855   }
1856   matrix = CoinPackedMatrix(true, numberRows_, numberColumns_, numberElements,
1857     element, row, start, length, 0.0, 0.0);
1858   delete[] start;
1859   delete[] length;
1860   delete[] row;
1861   delete[] element;
1862   return numberErrors;
1863 }
1864 /* Fills in startPositive and startNegative with counts for +-1 matrix.
1865    If not +-1 then startPositive[0]==-1 otherwise counts and
1866    startPositive[numberColumns]== size
1867       - return number of errors
1868 */
countPlusMinusOne(CoinBigIndex * startPositive,CoinBigIndex * startNegative,const double * associated)1869 int CoinModel::countPlusMinusOne(CoinBigIndex *startPositive, CoinBigIndex *startNegative,
1870   const double *associated)
1871 {
1872   if (type_ == 3)
1873     badType();
1874   memset(startPositive, 0, numberColumns_ * sizeof(int));
1875   memset(startNegative, 0, numberColumns_ * sizeof(int));
1876   // Set to say all parts
1877   type_ = 2;
1878   resize(numberRows_, numberColumns_, numberElements_);
1879   int numberErrors = 0;
1880   CoinBigIndex numberElements = 0;
1881   for (CoinBigIndex i = 0; i < numberElements_; i++) {
1882     int column = elements_[i].column;
1883     if (column >= 0) {
1884       double value = elements_[i].value;
1885       if (stringInTriple(elements_[i])) {
1886         int position = static_cast< int >(value);
1887         assert(position < sizeAssociated_);
1888         value = associated[position];
1889         if (value == unsetValue()) {
1890           numberErrors++;
1891           value = 0.0;
1892           startPositive[0] = -1;
1893           break;
1894         }
1895       }
1896       if (value) {
1897         numberElements++;
1898         if (value == 1.0) {
1899           startPositive[column]++;
1900         } else if (value == -1.0) {
1901           startNegative[column]++;
1902         } else {
1903           startPositive[0] = -1;
1904           break;
1905         }
1906       }
1907     }
1908   }
1909   if (startPositive[0] >= 0)
1910     startPositive[numberColumns_] = numberElements;
1911   return numberErrors;
1912 }
1913 /* Creates +-1 matrix given startPositive and startNegative counts for +-1 matrix.
1914  */
createPlusMinusOne(CoinBigIndex * startPositive,CoinBigIndex * startNegative,int * indices,const double * associated)1915 void CoinModel::createPlusMinusOne(CoinBigIndex *startPositive, CoinBigIndex *startNegative,
1916   int *indices,
1917   const double *associated)
1918 {
1919   if (type_ == 3)
1920     badType();
1921   CoinBigIndex size = 0;
1922   int iColumn;
1923   for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1924     CoinBigIndex n = startPositive[iColumn];
1925     startPositive[iColumn] = size;
1926     size += n;
1927     n = startNegative[iColumn];
1928     startNegative[iColumn] = size;
1929     size += n;
1930   }
1931   startPositive[numberColumns_] = size;
1932   for (CoinBigIndex i = 0; i < numberElements_; i++) {
1933     int column = elements_[i].column;
1934     if (column >= 0) {
1935       double value = elements_[i].value;
1936       if (stringInTriple(elements_[i])) {
1937         int position = static_cast< int >(value);
1938         assert(position < sizeAssociated_);
1939         value = associated[position];
1940       }
1941       int iRow = rowInTriple(elements_[i]);
1942       if (value == 1.0) {
1943         CoinBigIndex position = startPositive[column];
1944         indices[position] = iRow;
1945         startPositive[column]++;
1946       } else if (value == -1.0) {
1947         CoinBigIndex position = startNegative[column];
1948         indices[position] = iRow;
1949         startNegative[column]++;
1950       }
1951     }
1952   }
1953   // and now redo starts
1954   for (iColumn = numberColumns_ - 1; iColumn >= 0; iColumn--) {
1955     startPositive[iColumn + 1] = startNegative[iColumn];
1956     startNegative[iColumn] = startPositive[iColumn];
1957   }
1958   startPositive[0] = 0;
1959   for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1960     CoinBigIndex start = startPositive[iColumn];
1961     CoinBigIndex end = startNegative[iColumn];
1962     std::sort(indices + start, indices + end);
1963     start = startNegative[iColumn];
1964     end = startPositive[iColumn + 1];
1965     std::sort(indices + start, indices + end);
1966   }
1967 }
1968 // Fills in all associated - returning number of errors
computeAssociated(double * associated)1969 int CoinModel::computeAssociated(double *associated)
1970 {
1971   CoinYacc info;
1972   info.length = 0;
1973   int numberErrors = 0;
1974   for (int i = 0; i < string_.numberItems(); i++) {
1975     if (string_.name(i) && associated[i] == unsetValue()) {
1976       associated[i] = getDoubleFromString(info, string_.name(i));
1977       if (associated[i] == unsetValue())
1978         numberErrors++;
1979     }
1980   }
1981   return numberErrors;
1982 }
1983 // Creates copies of various arrays - return number of errors
createArrays(double * & rowLower,double * & rowUpper,double * & columnLower,double * & columnUpper,double * & objective,int * & integerType,double * & associated)1984 int CoinModel::createArrays(double *&rowLower, double *&rowUpper,
1985   double *&columnLower, double *&columnUpper,
1986   double *&objective, int *&integerType,
1987   double *&associated)
1988 {
1989   if (sizeAssociated_ < string_.numberItems()) {
1990     int newSize = string_.numberItems();
1991     double *temp = new double[newSize];
1992     CoinMemcpyN(associated_, sizeAssociated_, temp);
1993     CoinFillN(temp + sizeAssociated_, newSize - sizeAssociated_, unsetValue());
1994     delete[] associated_;
1995     associated_ = temp;
1996     sizeAssociated_ = newSize;
1997   }
1998   associated = CoinCopyOfArray(associated_, sizeAssociated_);
1999   int numberErrors = computeAssociated(associated);
2000   // Fill in as much as possible
2001   rowLower = CoinCopyOfArray(rowLower_, numberRows_);
2002   rowUpper = CoinCopyOfArray(rowUpper_, numberRows_);
2003   for (int iRow = 0; iRow < numberRows_; iRow++) {
2004     if ((rowType_[iRow] & 1) != 0) {
2005       int position = static_cast< int >(rowLower[iRow]);
2006       assert(position < sizeAssociated_);
2007       double value = associated[position];
2008       if (value != unsetValue()) {
2009         rowLower[iRow] = value;
2010       }
2011     }
2012     if ((rowType_[iRow] & 2) != 0) {
2013       int position = static_cast< int >(rowUpper[iRow]);
2014       assert(position < sizeAssociated_);
2015       double value = associated[position];
2016       if (value != unsetValue()) {
2017         rowUpper[iRow] = value;
2018       }
2019     }
2020   }
2021   columnLower = CoinCopyOfArray(columnLower_, numberColumns_);
2022   columnUpper = CoinCopyOfArray(columnUpper_, numberColumns_);
2023   objective = CoinCopyOfArray(objective_, numberColumns_);
2024   integerType = CoinCopyOfArray(integerType_, numberColumns_);
2025   for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
2026     if ((columnType_[iColumn] & 1) != 0) {
2027       int position = static_cast< int >(columnLower[iColumn]);
2028       assert(position < sizeAssociated_);
2029       double value = associated[position];
2030       if (value != unsetValue()) {
2031         columnLower[iColumn] = value;
2032       }
2033     }
2034     if ((columnType_[iColumn] & 2) != 0) {
2035       int position = static_cast< int >(columnUpper[iColumn]);
2036       assert(position < sizeAssociated_);
2037       double value = associated[position];
2038       if (value != unsetValue()) {
2039         columnUpper[iColumn] = value;
2040       }
2041     }
2042     if ((columnType_[iColumn] & 4) != 0) {
2043       int position = static_cast< int >(objective[iColumn]);
2044       assert(position < sizeAssociated_);
2045       double value = associated[position];
2046       if (value != unsetValue()) {
2047         objective[iColumn] = value;
2048       }
2049     }
2050     if ((columnType_[iColumn] & 8) != 0) {
2051       int position = integerType[iColumn];
2052       assert(position < sizeAssociated_);
2053       double value = associated[position];
2054       if (value != unsetValue()) {
2055         integerType[iColumn] = static_cast< int >(value);
2056       }
2057     }
2058   }
2059   return numberErrors;
2060 }
2061 
2062 /* Write the problem in MPS format to a file with the given filename.
2063  */
writeMps(const char * filename,int compression,int formatType,int numberAcross,bool keepStrings)2064 int CoinModel::writeMps(const char *filename, int compression,
2065   int formatType, int numberAcross, bool keepStrings)
2066 {
2067   int numberErrors = 0;
2068   // Set arrays for normal use
2069   double *rowLower = rowLower_;
2070   double *rowUpper = rowUpper_;
2071   double *columnLower = columnLower_;
2072   double *columnUpper = columnUpper_;
2073   double *objective = objective_;
2074   int *integerType = integerType_;
2075   double *associated = associated_;
2076   // If strings then do copies
2077   if (string_.numberItems()) {
2078     numberErrors = createArrays(rowLower, rowUpper, columnLower, columnUpper,
2079       objective, integerType, associated);
2080   }
2081   CoinPackedMatrix matrix;
2082   if (type_ != 3) {
2083     createPackedMatrix(matrix, associated);
2084   } else {
2085     matrix = *packedMatrix_;
2086   }
2087   char *integrality = new char[numberColumns_];
2088   bool hasInteger = false;
2089   for (int i = 0; i < numberColumns_; i++) {
2090     if (integerType[i]) {
2091       integrality[i] = 1;
2092       hasInteger = true;
2093     } else {
2094       integrality[i] = 0;
2095     }
2096   }
2097 
2098   CoinMpsIO writer;
2099   writer.setInfinity(COIN_DBL_MAX);
2100   const char *const *rowNames = NULL;
2101   if (rowName_.numberItems())
2102     rowNames = rowName_.names();
2103   const char *const *columnNames = NULL;
2104   if (columnName_.numberItems())
2105     columnNames = columnName_.names();
2106   writer.setMpsData(matrix, COIN_DBL_MAX,
2107     columnLower, columnUpper,
2108     objective, hasInteger ? integrality : 0,
2109     rowLower, rowUpper,
2110     columnNames, rowNames);
2111   delete[] integrality;
2112   if (rowLower != rowLower_) {
2113     delete[] rowLower;
2114     delete[] rowUpper;
2115     delete[] columnLower;
2116     delete[] columnUpper;
2117     delete[] objective;
2118     delete[] integerType;
2119     delete[] associated;
2120     if (numberErrors && logLevel_ > 0 && !keepStrings)
2121       printf("%d string elements had no values associated with them\n", numberErrors);
2122   }
2123   writer.setObjectiveOffset(objectiveOffset_);
2124   writer.setProblemName(problemName_.c_str());
2125   if (keepStrings && string_.numberItems()) {
2126     // load up strings - sorted by column and row
2127     writer.copyStringElements(this);
2128   }
2129   return writer.writeMps(filename, compression, formatType, numberAcross);
2130 }
2131 /* Check two models against each other.  Return nonzero if different.
2132    Ignore names if that set.
2133    May modify both models by cleaning up
2134 */
differentModel(CoinModel & other,bool ignoreNames)2135 int CoinModel::differentModel(CoinModel &other, bool ignoreNames)
2136 {
2137   int numberErrors = 0;
2138   int numberErrors2 = 0;
2139   int returnCode = 0;
2140   if (numberRows_ != other.numberRows_ || numberColumns_ != other.numberColumns_) {
2141     if (logLevel_ > 0)
2142       printf("** Mismatch on size, this has %d rows, %d columns - other has %d rows, %d columns\n",
2143         numberRows_, numberColumns_, other.numberRows_, other.numberColumns_);
2144     returnCode = 1000;
2145   }
2146   // Set arrays for normal use
2147   double *rowLower = rowLower_;
2148   double *rowUpper = rowUpper_;
2149   double *columnLower = columnLower_;
2150   double *columnUpper = columnUpper_;
2151   double *objective = objective_;
2152   int *integerType = integerType_;
2153   double *associated = associated_;
2154   // If strings then do copies
2155   if (string_.numberItems()) {
2156     numberErrors += createArrays(rowLower, rowUpper, columnLower, columnUpper,
2157       objective, integerType, associated);
2158   }
2159   // Set arrays for normal use
2160   double *rowLower2 = other.rowLower_;
2161   double *rowUpper2 = other.rowUpper_;
2162   double *columnLower2 = other.columnLower_;
2163   double *columnUpper2 = other.columnUpper_;
2164   double *objective2 = other.objective_;
2165   int *integerType2 = other.integerType_;
2166   double *associated2 = other.associated_;
2167   // If strings then do copies
2168   if (other.string_.numberItems()) {
2169     numberErrors2 += other.createArrays(rowLower2, rowUpper2, columnLower2, columnUpper2,
2170       objective2, integerType2, associated2);
2171   }
2172   CoinPackedMatrix matrix;
2173   createPackedMatrix(matrix, associated);
2174   CoinPackedMatrix matrix2;
2175   other.createPackedMatrix(matrix2, associated2);
2176   if (numberErrors || numberErrors2)
2177     if (logLevel_ > 0)
2178       printf("** Errors when converting strings, %d on this, %d on other\n",
2179         numberErrors, numberErrors2);
2180   CoinRelFltEq tolerance;
2181   if (numberRows_ == other.numberRows_) {
2182     bool checkNames = !ignoreNames;
2183     if (!rowName_.numberItems() || !other.rowName_.numberItems())
2184       checkNames = false;
2185     int numberDifferentL = 0;
2186     int numberDifferentU = 0;
2187     int numberDifferentN = 0;
2188     for (int i = 0; i < numberRows_; i++) {
2189       if (!tolerance(rowLower[i], rowLower2[i]))
2190         numberDifferentL++;
2191       if (!tolerance(rowUpper[i], rowUpper2[i]))
2192         numberDifferentU++;
2193       if (checkNames && rowName_.name(i) && other.rowName_.name(i)) {
2194         if (strcmp(rowName_.name(i), other.rowName_.name(i)))
2195           numberDifferentN++;
2196       }
2197     }
2198     int n = numberDifferentL + numberDifferentU + numberDifferentN;
2199     returnCode += n;
2200     if (n && logLevel_ > 0)
2201       printf("Row differences , %d lower, %d upper and %d names\n",
2202         numberDifferentL, numberDifferentU, numberDifferentN);
2203   }
2204   if (numberColumns_ == other.numberColumns_) {
2205     int numberDifferentL = 0;
2206     int numberDifferentU = 0;
2207     int numberDifferentN = 0;
2208     int numberDifferentO = 0;
2209     int numberDifferentI = 0;
2210     bool checkNames = !ignoreNames;
2211     if (!columnName_.numberItems() || !other.columnName_.numberItems())
2212       checkNames = false;
2213     for (int i = 0; i < numberColumns_; i++) {
2214       if (!tolerance(columnLower[i], columnLower2[i]))
2215         numberDifferentL++;
2216       if (!tolerance(columnUpper[i], columnUpper2[i]))
2217         numberDifferentU++;
2218       if (!tolerance(objective[i], objective2[i]))
2219         numberDifferentO++;
2220       int i1 = (integerType) ? integerType[i] : 0;
2221       int i2 = (integerType2) ? integerType2[i] : 0;
2222       if (i1 != i2)
2223         numberDifferentI++;
2224       if (checkNames && columnName_.name(i) && other.columnName_.name(i)) {
2225         if (strcmp(columnName_.name(i), other.columnName_.name(i)))
2226           numberDifferentN++;
2227       }
2228     }
2229     int n = numberDifferentL + numberDifferentU + numberDifferentN;
2230     n += numberDifferentO + numberDifferentI;
2231     returnCode += n;
2232     if (n && logLevel_ > 0)
2233       printf("Column differences , %d lower, %d upper, %d objective, %d integer and %d names\n",
2234         numberDifferentL, numberDifferentU, numberDifferentO,
2235         numberDifferentI, numberDifferentN);
2236   }
2237   if (numberRows_ == other.numberRows_ && numberColumns_ == other.numberColumns_ && numberElements_ == other.numberElements_) {
2238     if (!matrix.isEquivalent(matrix2, tolerance)) {
2239       returnCode += 100;
2240       if (returnCode && logLevel_ > 0)
2241         printf("Two matrices are not same\n");
2242     }
2243   }
2244 
2245   if (rowLower != rowLower_) {
2246     delete[] rowLower;
2247     delete[] rowUpper;
2248     delete[] columnLower;
2249     delete[] columnUpper;
2250     delete[] objective;
2251     delete[] integerType;
2252     delete[] associated;
2253   }
2254   if (rowLower2 != other.rowLower_) {
2255     delete[] rowLower2;
2256     delete[] rowUpper2;
2257     delete[] columnLower2;
2258     delete[] columnUpper2;
2259     delete[] objective2;
2260     delete[] integerType2;
2261     delete[] associated2;
2262   }
2263   return returnCode;
2264 }
2265 // Returns value for row i and column j
2266 double
getElement(int i,int j) const2267 CoinModel::getElement(int i, int j) const
2268 {
2269   if (!hashElements_.numberItems()) {
2270     hashElements_.setNumberItems(numberElements_);
2271     hashElements_.resize(maximumElements_, elements_);
2272   }
2273   CoinBigIndex position = hashElements_.hash(i, j, elements_);
2274   if (position >= 0) {
2275     return elements_[position].value;
2276   } else {
2277     return 0.0;
2278   }
2279 }
2280 // Returns value for row rowName and column columnName
2281 double
getElement(const char * rowName,const char * columnName) const2282 CoinModel::getElement(const char *rowName, const char *columnName) const
2283 {
2284   if (!hashElements_.numberItems()) {
2285     hashElements_.setNumberItems(numberElements_);
2286     hashElements_.resize(maximumElements_, elements_);
2287   }
2288   assert(!noNames_);
2289   int i = rowName_.hash(rowName);
2290   int j = columnName_.hash(columnName);
2291   CoinBigIndex position;
2292   if (i >= 0 && j >= 0)
2293     position = hashElements_.hash(i, j, elements_);
2294   else
2295     position = -1;
2296   if (position >= 0) {
2297     return elements_[position].value;
2298   } else {
2299     return 0.0;
2300   }
2301 }
2302 // Returns quadratic value for columns i and j
2303 double
getQuadraticElement(int,int) const2304 CoinModel::getQuadraticElement(int, int) const
2305 {
2306   printf("not written yet\n");
2307   abort();
2308   return 0.0;
2309 }
2310 // Returns value for row i and column j as string
2311 const char *
getElementAsString(int i,int j) const2312 CoinModel::getElementAsString(int i, int j) const
2313 {
2314   if (!hashElements_.numberItems()) {
2315     hashElements_.setNumberItems(numberElements_);
2316     hashElements_.resize(maximumElements_, elements_);
2317   }
2318   CoinBigIndex position = hashElements_.hash(i, j, elements_);
2319   if (position >= 0) {
2320     if (stringInTriple(elements_[position])) {
2321       int iString = static_cast< int >(elements_[position].value);
2322       assert(iString >= 0 && iString < string_.numberItems());
2323       return string_.name(iString);
2324     } else {
2325       return numeric;
2326     }
2327   } else {
2328     return NULL;
2329   }
2330 }
2331 /* Returns position of element for row i column j.
2332    Only valid until next modification.
2333    -1 if element does not exist */
2334 CoinBigIndex
position(int i,int j) const2335 CoinModel::position(int i, int j) const
2336 {
2337   if (!hashElements_.numberItems()) {
2338     hashElements_.setNumberItems(numberElements_);
2339     hashElements_.resize(maximumElements_, elements_, true);
2340   }
2341   return hashElements_.hash(i, j, elements_);
2342 }
2343 
2344 /* Returns pointer to element for row i column j.
2345    Only valid until next modification.
2346    NULL if element does not exist */
2347 double *
pointer(int i,int j) const2348 CoinModel::pointer(int i, int j) const
2349 {
2350   if (!hashElements_.numberItems()) {
2351     hashElements_.setNumberItems(numberElements_);
2352     hashElements_.resize(maximumElements_, elements_);
2353   }
2354   CoinBigIndex position = hashElements_.hash(i, j, elements_);
2355   if (position >= 0) {
2356     return &(elements_[position].value);
2357   } else {
2358     return NULL;
2359   }
2360 }
2361 
2362 /* Returns first element in given row - index is -1 if none.
2363    Index is given by .index and value by .value
2364 */
2365 CoinModelLink
firstInRow(int whichRow) const2366 CoinModel::firstInRow(int whichRow) const
2367 {
2368   CoinModelLink link;
2369   if (whichRow >= 0 && whichRow < numberRows_) {
2370     link.setOnRow(true);
2371     if (type_ == 0) {
2372       assert(start_);
2373       CoinBigIndex position = start_[whichRow];
2374       if (position < start_[whichRow + 1]) {
2375         link.setRow(whichRow);
2376         link.setPosition(position);
2377         link.setColumn(elements_[position].column);
2378         assert(whichRow == rowInTriple(elements_[position]));
2379         link.setValue(elements_[position].value);
2380       }
2381     } else {
2382       fillList(whichRow, rowList_, 1);
2383       CoinBigIndex position = rowList_.first(whichRow);
2384       if (position >= 0) {
2385         link.setRow(whichRow);
2386         link.setPosition(position);
2387         link.setColumn(elements_[position].column);
2388         assert(whichRow == rowInTriple(elements_[position]));
2389         link.setValue(elements_[position].value);
2390       }
2391     }
2392   }
2393   return link;
2394 }
2395 /* Returns last element in given row - index is -1 if none.
2396    Index is given by .index and value by .value
2397   */
2398 CoinModelLink
lastInRow(int whichRow) const2399 CoinModel::lastInRow(int whichRow) const
2400 {
2401   CoinModelLink link;
2402   if (whichRow >= 0 && whichRow < numberRows_) {
2403     link.setOnRow(true);
2404     if (type_ == 0) {
2405       assert(start_);
2406       CoinBigIndex position = start_[whichRow + 1] - 1;
2407       if (position >= start_[whichRow]) {
2408         link.setRow(whichRow);
2409         link.setPosition(position);
2410         link.setColumn(elements_[position].column);
2411         assert(whichRow == rowInTriple(elements_[position]));
2412         link.setValue(elements_[position].value);
2413       }
2414     } else {
2415       fillList(whichRow, rowList_, 1);
2416       CoinBigIndex position = rowList_.last(whichRow);
2417       if (position >= 0) {
2418         link.setRow(whichRow);
2419         link.setPosition(position);
2420         link.setColumn(elements_[position].column);
2421         assert(whichRow == rowInTriple(elements_[position]));
2422         link.setValue(elements_[position].value);
2423       }
2424     }
2425   }
2426   return link;
2427 }
2428 /* Returns first element in given column - index is -1 if none.
2429    Index is given by .index and value by .value
2430 */
2431 CoinModelLink
firstInColumn(int whichColumn) const2432 CoinModel::firstInColumn(int whichColumn) const
2433 {
2434   CoinModelLink link;
2435   if (whichColumn >= 0 && whichColumn < numberColumns_) {
2436     link.setOnRow(false);
2437     if (type_ == 1) {
2438       assert(start_);
2439       CoinBigIndex position = start_[whichColumn];
2440       if (position < start_[whichColumn + 1]) {
2441         link.setColumn(whichColumn);
2442         link.setPosition(position);
2443         link.setRow(rowInTriple(elements_[position]));
2444         assert(whichColumn == static_cast< int >(elements_[position].column));
2445         link.setValue(elements_[position].value);
2446       }
2447     } else {
2448       fillList(whichColumn, columnList_, 2);
2449       if ((links_ & 2) == 0) {
2450         // Create list
2451         assert(!columnList_.numberMajor());
2452         createList(2);
2453       }
2454       CoinBigIndex position = columnList_.first(whichColumn);
2455       if (position >= 0) {
2456         link.setColumn(whichColumn);
2457         link.setPosition(position);
2458         link.setRow(rowInTriple(elements_[position]));
2459         assert(whichColumn == static_cast< int >(elements_[position].column));
2460         link.setValue(elements_[position].value);
2461       }
2462     }
2463   }
2464   return link;
2465 }
2466 /* Returns last element in given column - index is -1 if none.
2467    Index is given by .index and value by .value
2468 */
2469 CoinModelLink
lastInColumn(int whichColumn) const2470 CoinModel::lastInColumn(int whichColumn) const
2471 {
2472   CoinModelLink link;
2473   if (whichColumn >= 0 && whichColumn < numberColumns_) {
2474     link.setOnRow(false);
2475     if (type_ == 1) {
2476       assert(start_);
2477       CoinBigIndex position = start_[whichColumn + 1] - 1;
2478       if (position >= start_[whichColumn]) {
2479         link.setColumn(whichColumn);
2480         link.setPosition(position);
2481         link.setRow(rowInTriple(elements_[position]));
2482         assert(whichColumn == static_cast< int >(elements_[position].column));
2483         link.setValue(elements_[position].value);
2484       }
2485     } else {
2486       fillList(whichColumn, columnList_, 2);
2487       CoinBigIndex position = columnList_.last(whichColumn);
2488       if (position >= 0) {
2489         link.setColumn(whichColumn);
2490         link.setPosition(position);
2491         link.setRow(rowInTriple(elements_[position]));
2492         assert(whichColumn == static_cast< int >(elements_[position].column));
2493         link.setValue(elements_[position].value);
2494       }
2495     }
2496   }
2497   return link;
2498 }
2499 /* Returns next element in current row or column - index is -1 if none.
2500    Index is given by .index and value by .value.
2501    User could also tell because input.next would be NULL
2502 */
2503 CoinModelLink
next(CoinModelLink & current) const2504 CoinModel::next(CoinModelLink &current) const
2505 {
2506   CoinModelLink link = current;
2507   CoinBigIndex position = current.position();
2508   if (position >= 0) {
2509     if (current.onRow()) {
2510       // Doing by row
2511       int whichRow = current.row();
2512       if (type_ == 0) {
2513         assert(start_);
2514         position++;
2515         if (position < start_[whichRow + 1]) {
2516           link.setPosition(position);
2517           link.setColumn(elements_[position].column);
2518           assert(whichRow == rowInTriple(elements_[position]));
2519           link.setValue(elements_[position].value);
2520         } else {
2521           // signal end
2522           link.setPosition(-1);
2523           link.setColumn(-1);
2524           link.setRow(-1);
2525           link.setValue(0.0);
2526         }
2527       } else {
2528         assert((links_ & 1) != 0);
2529         position = rowList_.next()[position];
2530         if (position >= 0) {
2531           link.setPosition(position);
2532           link.setColumn(elements_[position].column);
2533           assert(whichRow == rowInTriple(elements_[position]));
2534           link.setValue(elements_[position].value);
2535         } else {
2536           // signal end
2537           link.setPosition(-1);
2538           link.setColumn(-1);
2539           link.setRow(-1);
2540           link.setValue(0.0);
2541         }
2542       }
2543     } else {
2544       // Doing by column
2545       int whichColumn = current.column();
2546       if (type_ == 1) {
2547         assert(start_);
2548         position++;
2549         if (position < start_[whichColumn + 1]) {
2550           link.setPosition(position);
2551           link.setRow(rowInTriple(elements_[position]));
2552           assert(whichColumn == static_cast< int >(elements_[position].column));
2553           link.setValue(elements_[position].value);
2554         } else {
2555           // signal end
2556           link.setPosition(-1);
2557           link.setColumn(-1);
2558           link.setRow(-1);
2559           link.setValue(0.0);
2560         }
2561       } else {
2562         assert((links_ & 2) != 0);
2563         position = columnList_.next()[position];
2564         if (position >= 0) {
2565           link.setPosition(position);
2566           link.setRow(rowInTriple(elements_[position]));
2567           assert(whichColumn == static_cast< int >(elements_[position].column));
2568           link.setValue(elements_[position].value);
2569         } else {
2570           // signal end
2571           link.setPosition(-1);
2572           link.setColumn(-1);
2573           link.setRow(-1);
2574           link.setValue(0.0);
2575         }
2576       }
2577     }
2578   }
2579   return link;
2580 }
2581 /* Returns previous element in current row or column - index is -1 if none.
2582    Index is given by .index and value by .value.
2583    User could also tell because input.previous would be NULL
2584 */
2585 CoinModelLink
previous(CoinModelLink & current) const2586 CoinModel::previous(CoinModelLink &current) const
2587 {
2588   CoinModelLink link = current;
2589   CoinBigIndex position = current.position();
2590   if (position >= 0) {
2591     if (current.onRow()) {
2592       // Doing by row
2593       int whichRow = current.row();
2594       if (type_ == 0) {
2595         assert(start_);
2596         position--;
2597         if (position >= start_[whichRow]) {
2598           link.setPosition(position);
2599           link.setColumn(elements_[position].column);
2600           assert(whichRow == rowInTriple(elements_[position]));
2601           link.setValue(elements_[position].value);
2602         } else {
2603           // signal end
2604           link.setPosition(-1);
2605           link.setColumn(-1);
2606           link.setRow(-1);
2607           link.setValue(0.0);
2608         }
2609       } else {
2610         assert((links_ & 1) != 0);
2611         position = rowList_.previous()[position];
2612         if (position >= 0) {
2613           link.setPosition(position);
2614           link.setColumn(elements_[position].column);
2615           assert(whichRow == rowInTriple(elements_[position]));
2616           link.setValue(elements_[position].value);
2617         } else {
2618           // signal end
2619           link.setPosition(-1);
2620           link.setColumn(-1);
2621           link.setRow(-1);
2622           link.setValue(0.0);
2623         }
2624       }
2625     } else {
2626       // Doing by column
2627       int whichColumn = current.column();
2628       if (type_ == 1) {
2629         assert(start_);
2630         position--;
2631         if (position >= start_[whichColumn]) {
2632           link.setPosition(position);
2633           link.setRow(rowInTriple(elements_[position]));
2634           assert(whichColumn == static_cast< int >(elements_[position].column));
2635           link.setValue(elements_[position].value);
2636         } else {
2637           // signal end
2638           link.setPosition(-1);
2639           link.setColumn(-1);
2640           link.setRow(-1);
2641           link.setValue(0.0);
2642         }
2643       } else {
2644         assert((links_ & 2) != 0);
2645         position = columnList_.previous()[position];
2646         if (position >= 0) {
2647           link.setPosition(position);
2648           link.setRow(rowInTriple(elements_[position]));
2649           assert(whichColumn == static_cast< int >(elements_[position].column));
2650           link.setValue(elements_[position].value);
2651         } else {
2652           // signal end
2653           link.setPosition(-1);
2654           link.setColumn(-1);
2655           link.setRow(-1);
2656           link.setValue(0.0);
2657         }
2658       }
2659     }
2660   }
2661   return link;
2662 }
2663 /* Returns first element in given quadratic column - index is -1 if none.
2664    Index is given by .index and value by .value
2665 */
2666 CoinModelLink
firstInQuadraticColumn(int) const2667 CoinModel::firstInQuadraticColumn(int) const
2668 {
2669   printf("not written yet\n");
2670   abort();
2671   CoinModelLink x;
2672   return x;
2673 }
2674 /* Returns last element in given quadratic column - index is -1 if none.
2675    Index is given by .index and value by .value
2676 */
2677 CoinModelLink
lastInQuadraticColumn(int) const2678 CoinModel::lastInQuadraticColumn(int) const
2679 {
2680   printf("not written yet\n");
2681   abort();
2682   CoinModelLink x;
2683   return x;
2684 }
2685 /* Gets rowLower (if row does not exist then -COIN_DBL_MAX)
2686  */
2687 double
getRowLower(int whichRow) const2688 CoinModel::getRowLower(int whichRow) const
2689 {
2690   assert(whichRow >= 0);
2691   if (whichRow < numberRows_ && rowLower_)
2692     return rowLower_[whichRow];
2693   else
2694     return -COIN_DBL_MAX;
2695 }
2696 /* Gets rowUpper (if row does not exist then +COIN_DBL_MAX)
2697  */
2698 double
getRowUpper(int whichRow) const2699 CoinModel::getRowUpper(int whichRow) const
2700 {
2701   assert(whichRow >= 0);
2702   if (whichRow < numberRows_ && rowUpper_)
2703     return rowUpper_[whichRow];
2704   else
2705     return COIN_DBL_MAX;
2706 }
2707 /* Gets name (if row does not exist then NULL)
2708  */
2709 const char *
getRowName(int whichRow) const2710 CoinModel::getRowName(int whichRow) const
2711 {
2712   assert(whichRow >= 0);
2713   if (whichRow < rowName_.numberItems())
2714     return rowName_.name(whichRow);
2715   else
2716     return NULL;
2717 }
2718 /* Gets columnLower (if column does not exist then 0.0)
2719  */
2720 double
getColumnLower(int whichColumn) const2721 CoinModel::getColumnLower(int whichColumn) const
2722 {
2723   assert(whichColumn >= 0);
2724   if (whichColumn < numberColumns_ && columnLower_)
2725     return columnLower_[whichColumn];
2726   else
2727     return 0.0;
2728 }
2729 /* Gets columnUpper (if column does not exist then COIN_DBL_MAX)
2730  */
2731 double
getColumnUpper(int whichColumn) const2732 CoinModel::getColumnUpper(int whichColumn) const
2733 {
2734   assert(whichColumn >= 0);
2735   if (whichColumn < numberColumns_ && columnUpper_)
2736     return columnUpper_[whichColumn];
2737   else
2738     return COIN_DBL_MAX;
2739 }
2740 /* Gets columnObjective (if column does not exist then 0.0)
2741  */
2742 double
getColumnObjective(int whichColumn) const2743 CoinModel::getColumnObjective(int whichColumn) const
2744 {
2745   assert(whichColumn >= 0);
2746   if (whichColumn < numberColumns_ && objective_)
2747     return objective_[whichColumn];
2748   else
2749     return 0.0;
2750 }
2751 /* Gets name (if column does not exist then NULL)
2752  */
2753 const char *
getColumnName(int whichColumn) const2754 CoinModel::getColumnName(int whichColumn) const
2755 {
2756   assert(whichColumn >= 0);
2757   if (whichColumn < columnName_.numberItems())
2758     return columnName_.name(whichColumn);
2759   else
2760     return NULL;
2761 }
2762 /* Gets if integer (if column does not exist then false)
2763  */
getColumnIsInteger(int whichColumn) const2764 bool CoinModel::getColumnIsInteger(int whichColumn) const
2765 {
2766   assert(whichColumn >= 0);
2767   if (whichColumn < numberColumns_ && integerType_)
2768     return integerType_[whichColumn] != 0;
2769   else
2770     return false;
2771 }
2772 // Row index from row name (-1 if no names or no match)
row(const char * rowName) const2773 int CoinModel::row(const char *rowName) const
2774 {
2775   assert(!noNames_);
2776   return static_cast< int >(rowName_.hash(rowName));
2777 }
2778 // Column index from column name (-1 if no names or no match)
column(const char * columnName) const2779 int CoinModel::column(const char *columnName) const
2780 {
2781   assert(!noNames_);
2782   return static_cast< int >(columnName_.hash(columnName));
2783 }
2784 // Resize
resize(int maximumRows,int maximumColumns,CoinBigIndex maximumElements)2785 void CoinModel::resize(int maximumRows, int maximumColumns, CoinBigIndex maximumElements)
2786 {
2787   maximumElements = CoinMax(maximumElements, maximumElements_);
2788   if (type_ == 0 || type_ == 2) {
2789     // need to redo row stuff
2790     maximumRows = CoinMax(maximumRows, numberRows_);
2791     if (maximumRows > maximumRows_) {
2792       bool needFill = rowLower_ == NULL;
2793       double *tempArray;
2794       tempArray = new double[maximumRows];
2795       CoinMemcpyN(rowLower_, numberRows_, tempArray);
2796 #ifdef ZEROFAULT
2797       memset(tempArray + numberRows_, 0, (maximumRows - numberRows_) * sizeof(double));
2798 #endif
2799       delete[] rowLower_;
2800       rowLower_ = tempArray;
2801       tempArray = new double[maximumRows];
2802       CoinMemcpyN(rowUpper_, numberRows_, tempArray);
2803 #ifdef ZEROFAULT
2804       memset(tempArray + numberRows_, 0, (maximumRows - numberRows_) * sizeof(double));
2805 #endif
2806       delete[] rowUpper_;
2807       rowUpper_ = tempArray;
2808       int *tempArray2;
2809       tempArray2 = new int[maximumRows];
2810       CoinMemcpyN(rowType_, numberRows_, tempArray2);
2811 #ifdef ZEROFAULT
2812       memset(tempArray2 + numberRows_, 0, (maximumRows - numberRows_) * sizeof(int));
2813 #endif
2814       delete[] rowType_;
2815       rowType_ = tempArray2;
2816       // resize hash
2817       if (!noNames_)
2818         rowName_.resize(maximumRows);
2819       // If we have links we need to resize
2820       if ((links_ & 1) != 0) {
2821         rowList_.resize(maximumRows, maximumElements);
2822       }
2823       // If we have start then we need to resize that
2824       if (type_ == 0) {
2825         CoinBigIndex *tempArray2;
2826         tempArray2 = new CoinBigIndex[maximumRows + 1];
2827 #ifdef ZEROFAULT
2828         memset(tempArray2, 0, (maximumRows + 1) * sizeof(CoinBigIndex));
2829 #endif
2830         if (start_) {
2831           CoinMemcpyN(start_, (numberRows_ + 1), tempArray2);
2832           delete[] start_;
2833         } else {
2834           tempArray2[0] = 0;
2835         }
2836         start_ = tempArray2;
2837       }
2838       maximumRows_ = maximumRows;
2839       // Fill
2840       if (needFill) {
2841         int save = numberRows_ - 1;
2842         numberRows_ = 0;
2843         fillRows(save, true);
2844       }
2845     }
2846   } else if (type_ == 3) {
2847     badType();
2848   }
2849   if (type_ == 1 || type_ == 2) {
2850     // need to redo column stuff
2851     maximumColumns = CoinMax(maximumColumns, numberColumns_);
2852     if (maximumColumns > maximumColumns_) {
2853       bool needFill = columnLower_ == NULL;
2854       double *tempArray;
2855       tempArray = new double[maximumColumns];
2856       CoinMemcpyN(columnLower_, numberColumns_, tempArray);
2857 #ifdef ZEROFAULT
2858       memset(tempArray + numberColumns_, 0,
2859         (maximumColumns - numberColumns_) * sizeof(double));
2860 #endif
2861       delete[] columnLower_;
2862       columnLower_ = tempArray;
2863       tempArray = new double[maximumColumns];
2864       CoinMemcpyN(columnUpper_, numberColumns_, tempArray);
2865 #ifdef ZEROFAULT
2866       memset(tempArray + numberColumns_, 0,
2867         (maximumColumns - numberColumns_) * sizeof(double));
2868 #endif
2869       delete[] columnUpper_;
2870       columnUpper_ = tempArray;
2871       tempArray = new double[maximumColumns];
2872       CoinMemcpyN(objective_, numberColumns_, tempArray);
2873 #ifdef ZEROFAULT
2874       memset(tempArray + numberColumns_, 0,
2875         (maximumColumns - numberColumns_) * sizeof(double));
2876 #endif
2877       delete[] objective_;
2878       objective_ = tempArray;
2879       int *tempArray2;
2880       tempArray2 = new int[maximumColumns];
2881       CoinMemcpyN(columnType_, numberColumns_, tempArray2);
2882 #ifdef ZEROFAULT
2883       memset(tempArray2 + numberColumns_, 0,
2884         (maximumColumns - numberColumns_) * sizeof(int));
2885 #endif
2886       delete[] columnType_;
2887       columnType_ = tempArray2;
2888       tempArray2 = new int[maximumColumns];
2889       CoinMemcpyN(integerType_, numberColumns_, tempArray2);
2890 #ifdef ZEROFAULT
2891       memset(tempArray2 + numberColumns_, 0,
2892         (maximumColumns - numberColumns_) * sizeof(int));
2893 #endif
2894       delete[] integerType_;
2895       integerType_ = tempArray2;
2896       // resize hash
2897       if (!noNames_)
2898         columnName_.resize(maximumColumns);
2899       // If we have links we need to resize
2900       if ((links_ & 2) != 0) {
2901         columnList_.resize(maximumColumns, maximumElements);
2902       }
2903       // If we have start then we need to resize that
2904       if (type_ == 1) {
2905         CoinBigIndex *tempArray2;
2906         tempArray2 = new CoinBigIndex[maximumColumns + 1];
2907 #ifdef ZEROFAULT
2908         memset(tempArray2, 0, (maximumColumns + 1) * sizeof(CoinBigIndex));
2909 #endif
2910         if (start_) {
2911           CoinMemcpyN(start_, (numberColumns_ + 1), tempArray2);
2912           delete[] start_;
2913         } else {
2914           tempArray2[0] = 0;
2915         }
2916         start_ = tempArray2;
2917       }
2918       maximumColumns_ = maximumColumns;
2919       // Fill
2920       if (needFill) {
2921         int save = numberColumns_ - 1;
2922         numberColumns_ = 0;
2923         fillColumns(save, true);
2924       }
2925     }
2926   }
2927   if (type_ == 3)
2928     badType();
2929   if (maximumElements > maximumElements_) {
2930     CoinModelTriple *tempArray = new CoinModelTriple[maximumElements];
2931     CoinMemcpyN(elements_, numberElements_, tempArray);
2932 #ifdef ZEROFAULT
2933     memset(tempArray + numberElements_, 0,
2934       (maximumElements - numberElements_) * sizeof(CoinModelTriple));
2935 #endif
2936     delete[] elements_;
2937     elements_ = tempArray;
2938     if (hashElements_.numberItems())
2939       hashElements_.resize(maximumElements, elements_);
2940     maximumElements_ = maximumElements;
2941     // If we have links we need to resize
2942     if ((links_ & 1) != 0) {
2943       rowList_.resize(maximumRows_, maximumElements_);
2944     }
2945     if ((links_ & 2) != 0) {
2946       columnList_.resize(maximumColumns_, maximumElements_);
2947     }
2948   }
2949 }
fillRows(int whichRow,bool forceCreation,bool fromAddRow)2950 void CoinModel::fillRows(int whichRow, bool forceCreation, bool fromAddRow)
2951 {
2952   if (forceCreation || fromAddRow) {
2953     if (type_ == -1) {
2954       // initial
2955       type_ = 0;
2956       resize(CoinMax(100, whichRow + 1), 0, 1000);
2957     } else if (type_ == 1) {
2958       type_ = 2;
2959     }
2960     if (!rowLower_) {
2961       // need to set all
2962       whichRow = numberRows_ - 1;
2963       numberRows_ = 0;
2964       if (type_ != 3)
2965         resize(CoinMax(100, whichRow + 1), 0, 0);
2966       else
2967         resize(CoinMax(1, whichRow + 1), 0, 0);
2968     }
2969     if (whichRow >= maximumRows_) {
2970       if (type_ != 3)
2971         resize(CoinMax((3 * maximumRows_) / 2, whichRow + 1), 0, 0);
2972       else
2973         resize(CoinMax(1, whichRow + 1), 0, 0);
2974     }
2975   }
2976   if (whichRow >= numberRows_ && rowLower_) {
2977     // Need to fill
2978     int i;
2979     for (i = numberRows_; i <= whichRow; i++) {
2980       rowLower_[i] = -COIN_DBL_MAX;
2981       rowUpper_[i] = COIN_DBL_MAX;
2982       rowType_[i] = 0;
2983     }
2984   }
2985   if (!fromAddRow) {
2986     numberRows_ = CoinMax(whichRow + 1, numberRows_);
2987     // If simple minded then delete start
2988     if (start_) {
2989       delete[] start_;
2990       start_ = NULL;
2991       assert(!links_);
2992       // mixed - do linked lists for rows
2993       createList(1);
2994     }
2995   }
2996 }
fillColumns(int whichColumn,bool forceCreation,bool fromAddColumn)2997 void CoinModel::fillColumns(int whichColumn, bool forceCreation, bool fromAddColumn)
2998 {
2999   if (forceCreation || fromAddColumn) {
3000     if (type_ == -1) {
3001       // initial
3002       type_ = 1;
3003       resize(0, CoinMax(100, whichColumn + 1), 1000);
3004     } else if (type_ == 0) {
3005       type_ = 2;
3006     }
3007     if (!objective_) {
3008       // need to set all
3009       whichColumn = numberColumns_ - 1;
3010       numberColumns_ = 0;
3011       if (type_ != 3)
3012         resize(0, CoinMax(100, whichColumn + 1), 0);
3013       else
3014         resize(0, CoinMax(1, whichColumn + 1), 0);
3015     }
3016     if (whichColumn >= maximumColumns_) {
3017       if (type_ != 3)
3018         resize(0, CoinMax((3 * maximumColumns_) / 2, whichColumn + 1), 0);
3019       else
3020         resize(0, CoinMax(1, whichColumn + 1), 0);
3021     }
3022   }
3023   if (whichColumn >= numberColumns_ && objective_) {
3024     // Need to fill
3025     int i;
3026     for (i = numberColumns_; i <= whichColumn; i++) {
3027       columnLower_[i] = 0.0;
3028       columnUpper_[i] = COIN_DBL_MAX;
3029       objective_[i] = 0.0;
3030       integerType_[i] = 0;
3031       columnType_[i] = 0;
3032     }
3033   }
3034   if (!fromAddColumn) {
3035     numberColumns_ = CoinMax(whichColumn + 1, numberColumns_);
3036     // If simple minded then delete start
3037     if (start_) {
3038       delete[] start_;
3039       start_ = NULL;
3040       assert(!links_);
3041       // mixed - do linked lists for columns
3042       createList(2);
3043     }
3044   }
3045 }
3046 // Fill in default linked list information
fillList(int which,CoinModelLinkedList & list,int type) const3047 void CoinModel::fillList(int which, CoinModelLinkedList &list, int type) const
3048 {
3049   if ((links_ & type) == 0) {
3050     // Create list
3051     assert(!list.numberMajor());
3052     if (type == 1) {
3053       list.create(maximumRows_, maximumElements_, numberRows_, numberColumns_, 0,
3054         numberElements_, elements_);
3055     } else {
3056       list.create(maximumColumns_, maximumElements_, numberColumns_, numberRows_, 1,
3057         numberElements_, elements_);
3058     }
3059     if (links_ == 1 && type == 2) {
3060       columnList_.synchronize(rowList_);
3061     } else if (links_ == 2 && type == 1) {
3062       rowList_.synchronize(columnList_);
3063     }
3064     links_ |= type;
3065   }
3066   int number = list.numberMajor();
3067   if (which >= number) {
3068     // may still need to extend list or fill it in
3069     if (which >= list.maximumMajor()) {
3070       list.resize((which * 3) / 2 + 100, list.maximumElements());
3071     }
3072     list.fill(number, which + 1);
3073   }
3074 }
3075 /* Gets sorted row - user must provide enough space
3076    (easiest is allocate number of columns).
3077    Returns number of elements
3078 */
getRow(int whichRow,int * column,double * element)3079 int CoinModel::getRow(int whichRow, int *column, double *element)
3080 {
3081   if (!hashElements_.maximumItems()) {
3082     // set up number of items
3083     hashElements_.setNumberItems(numberElements_);
3084     hashElements_.resize(maximumElements_, elements_);
3085   }
3086   assert(whichRow >= 0);
3087   int n = 0;
3088   if (whichRow < numberRows_) {
3089     CoinModelLink triple = firstInRow(whichRow);
3090     bool sorted = true;
3091     int last = -1;
3092     while (triple.column() >= 0) {
3093       int iColumn = triple.column();
3094       assert(whichRow == triple.row());
3095       if (iColumn < last)
3096         sorted = false;
3097       last = iColumn;
3098       if (column)
3099         column[n] = iColumn;
3100       if (element)
3101         element[n] = triple.value();
3102       n++;
3103       triple = next(triple);
3104     }
3105     if (!sorted) {
3106       CoinSort_2(column, column + n, element);
3107     }
3108   }
3109   return n;
3110 }
3111 /* Gets sorted column - user must provide enough space
3112    (easiest is allocate number of rows).
3113    Returns number of elements
3114 */
getColumn(int whichColumn,int * row,double * element)3115 int CoinModel::getColumn(int whichColumn, int *row, double *element)
3116 {
3117   if (!hashElements_.maximumItems()) {
3118     // set up number of items
3119     hashElements_.setNumberItems(numberElements_);
3120     hashElements_.resize(maximumElements_, elements_);
3121   }
3122   assert(whichColumn >= 0);
3123   int n = 0;
3124   if (whichColumn < numberColumns_) {
3125     CoinModelLink triple = firstInColumn(whichColumn);
3126     bool sorted = true;
3127     int last = -1;
3128     while (triple.column() >= 0) {
3129       int iRow = triple.row();
3130       assert(whichColumn == triple.column());
3131       if (iRow < last)
3132         sorted = false;
3133       last = iRow;
3134       if (row)
3135         row[n] = iRow;
3136       if (element)
3137         element[n] = triple.value();
3138       n++;
3139       triple = next(triple);
3140     }
3141     if (!sorted) {
3142       CoinSort_2(row, row + n, element);
3143     }
3144   }
3145   return n;
3146 }
3147 /* Create a linked list and synchronize free
3148    type 1 for row 2 for column
3149    Marked as const as list is mutable */
createList(int type) const3150 void CoinModel::createList(int type) const
3151 {
3152   type_ = 2;
3153   if (type == 1) {
3154     assert((links_ & 1) == 0);
3155     rowList_.create(maximumRows_, maximumElements_,
3156       numberRows_, numberColumns_, 0,
3157       numberElements_, elements_);
3158     if (links_ == 2) {
3159       // synchronize free list
3160       rowList_.synchronize(columnList_);
3161     }
3162     links_ |= 1;
3163   } else {
3164     assert((links_ & 2) == 0);
3165     columnList_.create(maximumColumns_, maximumElements_,
3166       numberColumns_, numberRows_, 1,
3167       numberElements_, elements_);
3168     if (links_ == 1) {
3169       // synchronize free list
3170       columnList_.synchronize(rowList_);
3171     }
3172     links_ |= 2;
3173   }
3174 }
3175 // Checks that links are consistent
validateLinks() const3176 void CoinModel::validateLinks() const
3177 {
3178   if ((links_ & 1)) {
3179     // validate row links
3180     rowList_.validateLinks(elements_);
3181   }
3182   if ((links_ & 2)) {
3183     // validate column links
3184     columnList_.validateLinks(elements_);
3185   }
3186 }
3187 // returns jColumn (-2 if linear term, -1 if unknown) and coefficient
decodeBit(char * phrase,char * & nextPhrase,double & coefficient,bool ifFirst) const3188 int CoinModel::decodeBit(char *phrase, char *&nextPhrase, double &coefficient, bool ifFirst) const
3189 {
3190   char *pos = phrase;
3191   // may be leading - (or +)
3192   char *pos2 = pos;
3193   double value = 1.0;
3194   if (*pos2 == '-' || *pos2 == '+')
3195     pos2++;
3196   // next terminator * or + or -
3197   while (*pos2) {
3198     if (*pos2 == '*') {
3199       break;
3200     } else if (*pos2 == '-' || *pos2 == '+') {
3201       if (pos2 == pos || *(pos2 - 1) != 'e')
3202         break;
3203     }
3204     pos2++;
3205   }
3206   // if * must be number otherwise must be name
3207   if (*pos2 == '*') {
3208     char *pos3 = pos;
3209     while (pos3 != pos2) {
3210 #ifndef NDEBUG
3211       char x = *pos3;
3212 #endif
3213       pos3++;
3214       assert((x >= '0' && x <= '9') || x == '.' || x == '+' || x == '-' || x == 'e');
3215     }
3216     char saved = *pos2;
3217     *pos2 = '\0';
3218     value = atof(pos);
3219     *pos2 = saved;
3220     // and down to next
3221     pos2++;
3222     pos = pos2;
3223     while (*pos2) {
3224       if (*pos2 == '-' || *pos2 == '+')
3225         break;
3226       pos2++;
3227     }
3228   }
3229   char saved = *pos2;
3230   *pos2 = '\0';
3231   // now name
3232   // might have + or -
3233   if (*pos == '+') {
3234     pos++;
3235   } else if (*pos == '-') {
3236     pos++;
3237     assert(value == 1.0);
3238     value = -value;
3239   }
3240   int jColumn = column(pos);
3241   // must be column unless first when may be linear term
3242   if (jColumn < 0) {
3243     if (ifFirst) {
3244       char *pos3 = pos;
3245       while (pos3 != pos2) {
3246 #ifndef NDEBUG
3247         char x = *pos3;
3248 #endif
3249         pos3++;
3250         assert((x >= '0' && x <= '9') || x == '.' || x == '+' || x == '-' || x == 'e');
3251       }
3252       assert(*pos2 == '\0');
3253       // keep possible -
3254       value = value * atof(pos);
3255       jColumn = -2;
3256     } else {
3257       // bad
3258       *pos2 = saved;
3259       printf("bad nonlinear term %s\n", phrase);
3260       // maybe return -1
3261       abort();
3262     }
3263   }
3264   *pos2 = saved;
3265   pos = pos2;
3266   coefficient = value;
3267   nextPhrase = pos;
3268   return jColumn;
3269 }
3270 /* Gets correct form for a quadratic row - user to delete
3271    If row is not quadratic then returns which other variables are involved
3272    with tiny elements and count of total number of variables which could not
3273    be put in quadratic form
3274 */
3275 CoinPackedMatrix *
quadraticRow(int rowNumber,double * linearRow,int & numberBad) const3276 CoinModel::quadraticRow(int rowNumber, double *linearRow,
3277   int &numberBad) const
3278 {
3279   numberBad = 0;
3280   CoinZeroN(linearRow, numberColumns_);
3281   int numberElements = 0;
3282   assert(rowNumber >= -1 && rowNumber < numberRows_);
3283   if (rowNumber != -1) {
3284     // not objective
3285     CoinModelLink triple = firstInRow(rowNumber);
3286     while (triple.column() >= 0) {
3287       int iColumn = triple.column();
3288       const char *expr = getElementAsString(rowNumber, iColumn);
3289       if (strcmp(expr, "Numeric")) {
3290         // try and see which columns
3291         assert(strlen(expr) < 20000);
3292         char temp[20000];
3293         strcpy(temp, expr);
3294         char *pos = temp;
3295         bool ifFirst = true;
3296         while (*pos) {
3297           double value;
3298           int jColumn = decodeBit(pos, pos, value, ifFirst);
3299           // must be column unless first when may be linear term
3300           if (jColumn >= 0) {
3301             numberElements++;
3302           } else if (jColumn == -2) {
3303             linearRow[iColumn] = value;
3304           } else if (jColumn == -1) {
3305             // nonlinear term - we will just be marking
3306             numberElements++;
3307           } else {
3308             printf("bad nonlinear term %s\n", temp);
3309             abort();
3310           }
3311           ifFirst = false;
3312         }
3313       } else {
3314         linearRow[iColumn] = getElement(rowNumber, iColumn);
3315       }
3316       triple = next(triple);
3317     }
3318     if (!numberElements) {
3319       return NULL;
3320     } else {
3321       int *column = new int[numberElements];
3322       int *column2 = new int[numberElements];
3323       double *element = new double[numberElements];
3324       numberElements = 0;
3325       CoinModelLink triple = firstInRow(rowNumber);
3326       while (triple.column() >= 0) {
3327         int iColumn = triple.column();
3328         const char *expr = getElementAsString(rowNumber, iColumn);
3329         if (strcmp(expr, "Numeric")) {
3330           // try and see which columns
3331           assert(strlen(expr) < 20000);
3332           char temp[20000];
3333           strcpy(temp, expr);
3334           char *pos = temp;
3335           bool ifFirst = true;
3336           while (*pos) {
3337             double value;
3338             int jColumn = decodeBit(pos, pos, value, ifFirst);
3339             // must be column unless first when may be linear term
3340             if (jColumn >= 0) {
3341               column[numberElements] = iColumn;
3342               column2[numberElements] = jColumn;
3343               element[numberElements++] = value;
3344             } else if (jColumn == -1) {
3345               // nonlinear term - we will just be marking
3346               assert(jColumn >= 0);
3347               column[numberElements] = iColumn;
3348               column2[numberElements] = jColumn;
3349               element[numberElements++] = 1.0e-100;
3350               numberBad++;
3351             } else if (jColumn != -2) {
3352               printf("bad nonlinear term %s\n", temp);
3353               abort();
3354             }
3355             ifFirst = false;
3356           }
3357         }
3358         triple = next(triple);
3359       }
3360       CoinPackedMatrix *newMatrix = new CoinPackedMatrix(true, column2, column, element, numberElements);
3361       delete[] column;
3362       delete[] column2;
3363       delete[] element;
3364       return newMatrix;
3365     }
3366   } else {
3367     // objective
3368     int iColumn;
3369     for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
3370       const char *expr = getColumnObjectiveAsString(iColumn);
3371       if (strcmp(expr, "Numeric")) {
3372         // try and see which columns
3373         assert(strlen(expr) < 20000);
3374         char temp[20000];
3375         strcpy(temp, expr);
3376         char *pos = temp;
3377         bool ifFirst = true;
3378         while (*pos) {
3379           double value;
3380           int jColumn = decodeBit(pos, pos, value, ifFirst);
3381           // must be column unless first when may be linear term
3382           if (jColumn >= 0) {
3383             numberElements++;
3384           } else if (jColumn == -2) {
3385             linearRow[iColumn] = value;
3386           } else if (jColumn == -1) {
3387             // nonlinear term - we will just be marking
3388             numberElements++;
3389           } else {
3390             printf("bad nonlinear term %s\n", temp);
3391             abort();
3392           }
3393           ifFirst = false;
3394         }
3395       } else {
3396         linearRow[iColumn] = getElement(rowNumber, iColumn);
3397       }
3398     }
3399     if (!numberElements) {
3400       return NULL;
3401     } else {
3402       int *column = new int[numberElements];
3403       int *column2 = new int[numberElements];
3404       double *element = new double[numberElements];
3405       numberElements = 0;
3406       for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
3407         const char *expr = getColumnObjectiveAsString(iColumn);
3408         if (strcmp(expr, "Numeric")) {
3409           // try and see which columns
3410           assert(strlen(expr) < 20000);
3411           char temp[20000];
3412           strcpy(temp, expr);
3413           char *pos = temp;
3414           bool ifFirst = true;
3415           while (*pos) {
3416             double value;
3417             int jColumn = decodeBit(pos, pos, value, ifFirst);
3418             // must be column unless first when may be linear term
3419             if (jColumn >= 0) {
3420               column[numberElements] = iColumn;
3421               column2[numberElements] = jColumn;
3422               element[numberElements++] = value;
3423             } else if (jColumn == -1) {
3424               // nonlinear term - we will just be marking
3425               assert(jColumn >= 0);
3426               column[numberElements] = iColumn;
3427               column2[numberElements] = jColumn;
3428               element[numberElements++] = 1.0e-100;
3429               numberBad++;
3430             } else if (jColumn != -2) {
3431               printf("bad nonlinear term %s\n", temp);
3432               abort();
3433             }
3434             ifFirst = false;
3435           }
3436         }
3437       }
3438       return new CoinPackedMatrix(true, column2, column, element, numberElements);
3439     }
3440   }
3441 }
3442 // Replaces a quadratic row
replaceQuadraticRow(int rowNumber,const double * linearRow,const CoinPackedMatrix * quadraticPart)3443 void CoinModel::replaceQuadraticRow(int rowNumber, const double *linearRow, const CoinPackedMatrix *quadraticPart)
3444 {
3445   assert(rowNumber >= -1 && rowNumber < numberRows_);
3446   if (rowNumber >= 0) {
3447     CoinModelLink triple = firstInRow(rowNumber);
3448     while (triple.column() >= 0) {
3449       int iColumn = triple.column();
3450       deleteElement(rowNumber, iColumn);
3451       // triple stale - so start over
3452       triple = firstInRow(rowNumber);
3453     }
3454     const double *element = quadraticPart->getElements();
3455     const int *column = quadraticPart->getIndices();
3456     const CoinBigIndex *columnStart = quadraticPart->getVectorStarts();
3457     const int *columnLength = quadraticPart->getVectorLengths();
3458     int numberLook = quadraticPart->getNumCols();
3459     int i;
3460     for (i = 0; i < numberLook; i++) {
3461       if (!columnLength[i]) {
3462         // just linear part
3463         if (linearRow[i])
3464           setElement(rowNumber, i, linearRow[i]);
3465       } else {
3466         char temp[10000];
3467         int put = 0;
3468         char temp2[30];
3469         bool first = true;
3470         if (linearRow[i]) {
3471           sprintf(temp, "%g", linearRow[i]);
3472           first = false;
3473           /* temp is at most 10000 long, so static_cast is safe */
3474           put = static_cast< int >(strlen(temp));
3475         }
3476         for (CoinBigIndex j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) {
3477           int jColumn = column[j];
3478           double value = element[j];
3479           if (value < 0.0 || first)
3480             sprintf(temp2, "%g*c%7.7d", value, jColumn);
3481           else
3482             sprintf(temp2, "+%g*c%7.7d", value, jColumn);
3483           int nextPut = put + static_cast< int >(strlen(temp2));
3484           assert(nextPut < 10000);
3485           strcpy(temp + put, temp2);
3486           put = nextPut;
3487         }
3488         setElement(rowNumber, i, temp);
3489       }
3490     }
3491     // rest of linear
3492     for (; i < numberColumns_; i++) {
3493       if (linearRow[i])
3494         setElement(rowNumber, i, linearRow[i]);
3495     }
3496   } else {
3497     // objective
3498     int iColumn;
3499     for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
3500       setColumnObjective(iColumn, 0.0);
3501     }
3502     const double *element = quadraticPart->getElements();
3503     const int *column = quadraticPart->getIndices();
3504     const CoinBigIndex *columnStart = quadraticPart->getVectorStarts();
3505     const int *columnLength = quadraticPart->getVectorLengths();
3506     int numberLook = quadraticPart->getNumCols();
3507     int i;
3508     for (i = 0; i < numberLook; i++) {
3509       if (!columnLength[i]) {
3510         // just linear part
3511         if (linearRow[i])
3512           setColumnObjective(i, linearRow[i]);
3513       } else {
3514         char temp[10000];
3515         int put = 0;
3516         char temp2[30];
3517         bool first = true;
3518         if (linearRow[i]) {
3519           sprintf(temp, "%g", linearRow[i]);
3520           first = false;
3521           /* temp is at most 10000 long, so static_cast is safe */
3522           put = static_cast< int >(strlen(temp));
3523         }
3524         for (CoinBigIndex j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) {
3525           int jColumn = column[j];
3526           double value = element[j];
3527           if (value < 0.0 || first)
3528             sprintf(temp2, "%g*c%7.7d", value, jColumn);
3529           else
3530             sprintf(temp2, "+%g*c%7.7d", value, jColumn);
3531           int nextPut = put + static_cast< int >(strlen(temp2));
3532           assert(nextPut < 10000);
3533           strcpy(temp + put, temp2);
3534           put = nextPut;
3535         }
3536         setColumnObjective(i, temp);
3537       }
3538     }
3539     // rest of linear
3540     for (; i < numberColumns_; i++) {
3541       if (linearRow[i])
3542         setColumnObjective(i, linearRow[i]);
3543     }
3544   }
3545 }
3546 /* If possible return a model where if all variables marked nonzero are fixed
3547       the problem will be linear.  At present may only work if quadratic.
3548       Returns NULL if not possible
3549 */
3550 CoinModel *
reorder(const char * mark) const3551 CoinModel::reorder(const char *mark) const
3552 {
3553   // redo array so 2 high priority nonlinear, 1 nonlinear, 0 linear
3554   char *highPriority = new char[numberColumns_];
3555   double *linear = new double[numberColumns_];
3556   CoinModel *newModel = new CoinModel(*this);
3557   int iRow;
3558   for (iRow = -1; iRow < numberRows_; iRow++) {
3559     int numberBad;
3560     CoinPackedMatrix *row = quadraticRow(iRow, linear, numberBad);
3561     assert(!numberBad); // fix later
3562     if (row) {
3563       // see if valid
3564       //const double * element = row->getElements();
3565       const int *column = row->getIndices();
3566       const CoinBigIndex *columnStart = row->getVectorStarts();
3567       const int *columnLength = row->getVectorLengths();
3568       int numberLook = row->getNumCols();
3569       for (int i = 0; i < numberLook; i++) {
3570         if (mark[i])
3571           highPriority[i] = 2;
3572         else
3573           highPriority[i] = 1;
3574         for (CoinBigIndex j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) {
3575           int iColumn = column[j];
3576           if (mark[iColumn])
3577             highPriority[iColumn] = 2;
3578           else
3579             highPriority[iColumn] = 1;
3580         }
3581       }
3582       delete row;
3583     }
3584   }
3585   for (iRow = -1; iRow < numberRows_; iRow++) {
3586     int numberBad;
3587     CoinPackedMatrix *row = quadraticRow(iRow, linear, numberBad);
3588     if (row) {
3589       // see if valid
3590       const double *element = row->getElements();
3591       const int *columnLow = row->getIndices();
3592       const CoinBigIndex *columnHigh = row->getVectorStarts();
3593       const int *columnLength = row->getVectorLengths();
3594       int numberLook = row->getNumCols();
3595       int canSwap = 0;
3596       for (int i = 0; i < numberLook; i++) {
3597         // this one needs to be available
3598         int iPriority = highPriority[i];
3599         for (CoinBigIndex j = columnHigh[i]; j < columnHigh[i] + columnLength[i]; j++) {
3600           int iColumn = columnLow[j];
3601           if (highPriority[iColumn] <= 1) {
3602             assert(highPriority[iColumn] == 1);
3603             if (iPriority == 1) {
3604               canSwap = -1; // no good
3605               break;
3606             } else {
3607               canSwap = 1;
3608             }
3609           }
3610         }
3611       }
3612       if (canSwap) {
3613         if (canSwap > 0) {
3614           // rewrite row
3615           /* get triples
3616 	     then swap ones needed
3617 	     then create packedmatrix
3618 	     then replace row
3619 	  */
3620           CoinBigIndex numberElements = columnHigh[numberLook];
3621           int *columnHigh2 = new int[numberElements];
3622           int *columnLow2 = new int[numberElements];
3623           double *element2 = new double[numberElements];
3624           for (int i = 0; i < numberLook; i++) {
3625             // this one needs to be available
3626             int iPriority = highPriority[i];
3627             if (iPriority == 2) {
3628               for (CoinBigIndex j = columnHigh[i]; j < columnHigh[i] + columnLength[i]; j++) {
3629                 columnHigh2[j] = i;
3630                 columnLow2[j] = columnLow[j];
3631                 element2[j] = element[j];
3632               }
3633             } else {
3634               for (CoinBigIndex j = columnHigh[i]; j < columnHigh[i] + columnLength[i]; j++) {
3635                 columnLow2[j] = i;
3636                 columnHigh2[j] = columnLow[j];
3637                 element2[j] = element[j];
3638               }
3639             }
3640           }
3641           delete row;
3642           row = new CoinPackedMatrix(true, columnHigh2, columnLow2, element2, numberElements);
3643           delete[] columnHigh2;
3644           delete[] columnLow2;
3645           delete[] element2;
3646           // Now replace row
3647           newModel->replaceQuadraticRow(iRow, linear, row);
3648           delete row;
3649         } else {
3650           delete row;
3651           delete newModel;
3652           newModel = NULL;
3653           printf("Unable to use priority - row %d\n", iRow);
3654           break;
3655         }
3656       }
3657     }
3658   }
3659   delete[] highPriority;
3660   delete[] linear;
3661   return newModel;
3662 }
3663 // Sets cut marker array
setCutMarker(int size,const int * marker)3664 void CoinModel::setCutMarker(int size, const int *marker)
3665 {
3666   delete[] cut_;
3667   cut_ = new int[maximumRows_];
3668   CoinZeroN(cut_, maximumRows_);
3669   CoinMemcpyN(marker, size, cut_);
3670 }
3671 // Sets priority array
setPriorities(int size,const int * priorities)3672 void CoinModel::setPriorities(int size, const int *priorities)
3673 {
3674   delete[] priority_;
3675   priority_ = new int[maximumColumns_];
3676   CoinZeroN(priority_, maximumColumns_);
3677   CoinMemcpyN(priorities, size, priority_);
3678 }
3679 /* Sets columnObjective array
3680  */
setObjective(int numberColumns,const double * objective)3681 void CoinModel::setObjective(int numberColumns, const double *objective)
3682 {
3683   fillColumns(numberColumns, true, true);
3684   for (int i = 0; i < numberColumns; i++) {
3685     objective_[i] = objective[i];
3686     columnType_[i] &= ~4;
3687   }
3688 }
3689 /* Sets columnLower array
3690  */
setColumnLower(int numberColumns,const double * columnLower)3691 void CoinModel::setColumnLower(int numberColumns, const double *columnLower)
3692 {
3693   fillColumns(numberColumns, true, true);
3694   for (int i = 0; i < numberColumns; i++) {
3695     columnLower_[i] = columnLower[i];
3696     columnType_[i] &= ~1;
3697   }
3698 }
3699 /* Sets columnUpper array
3700  */
setColumnUpper(int numberColumns,const double * columnUpper)3701 void CoinModel::setColumnUpper(int numberColumns, const double *columnUpper)
3702 {
3703   fillColumns(numberColumns, true, true);
3704   for (int i = 0; i < numberColumns; i++) {
3705     columnUpper_[i] = columnUpper[i];
3706     columnType_[i] &= ~2;
3707   }
3708 }
3709 /* Sets rowLower array
3710  */
setRowLower(int numberRows,const double * rowLower)3711 void CoinModel::setRowLower(int numberRows, const double *rowLower)
3712 {
3713   fillColumns(numberRows, true, true);
3714   for (int i = 0; i < numberRows; i++) {
3715     rowLower_[i] = rowLower[i];
3716     rowType_[i] &= ~1;
3717   }
3718 }
3719 /* Sets rowUpper array
3720  */
setRowUpper(int numberRows,const double * rowUpper)3721 void CoinModel::setRowUpper(int numberRows, const double *rowUpper)
3722 {
3723   fillColumns(numberRows, true, true);
3724   for (int i = 0; i < numberRows; i++) {
3725     rowUpper_[i] = rowUpper[i];
3726     rowType_[i] &= ~2;
3727   }
3728 }
3729 // Pass in CoinPackedMatrix (and switch off element updates)
passInMatrix(const CoinPackedMatrix & matrix)3730 void CoinModel::passInMatrix(const CoinPackedMatrix &matrix)
3731 {
3732   type_ = 3;
3733   packedMatrix_ = new CoinPackedMatrix(matrix);
3734 }
3735 // Convert elements to CoinPackedMatrix (and switch off element updates)
convertMatrix()3736 int CoinModel::convertMatrix()
3737 {
3738   int numberErrors = 0;
3739   if (type_ != 3) {
3740     // If strings then do copies
3741     if (string_.numberItems()) {
3742       numberErrors = createArrays(rowLower_, rowUpper_,
3743         columnLower_, columnUpper_,
3744         objective_, integerType_, associated_);
3745     }
3746     CoinPackedMatrix matrix;
3747     createPackedMatrix(matrix, associated_);
3748     packedMatrix_ = new CoinPackedMatrix(matrix);
3749     type_ = 3;
3750   }
3751   return numberErrors;
3752 }
3753 // Aborts with message about packedMatrix
badType() const3754 void CoinModel::badType() const
3755 {
3756   fprintf(stderr, "******** operation not allowed when in block mode ****\n");
3757   abort();
3758 }
3759 
3760 //#############################################################################
3761 // Methods to input a problem
3762 //#############################################################################
3763 /** A function to convert from the lb/ub style of constraint
3764     definition to the sense/rhs/range style */
convertBoundToSense(const double lower,const double upper,char & sense,double & right,double & range)3765 void convertBoundToSense(const double lower, const double upper,
3766   char &sense, double &right,
3767   double &range)
3768 {
3769   double inf = 1.0e-30;
3770   range = 0.0;
3771   if (lower > -inf) {
3772     if (upper < inf) {
3773       right = upper;
3774       if (upper == lower) {
3775         sense = 'E';
3776       } else {
3777         sense = 'R';
3778         range = upper - lower;
3779       }
3780     } else {
3781       sense = 'G';
3782       right = lower;
3783     }
3784   } else {
3785     if (upper < inf) {
3786       sense = 'L';
3787       right = upper;
3788     } else {
3789       sense = 'N';
3790       right = 0.0;
3791     }
3792   }
3793 }
3794 
3795 //-----------------------------------------------------------------------------
3796 /** A function to convert from the sense/rhs/range style of
3797     constraint definition to the lb/ub style */
convertSenseToBound(const char sense,const double right,const double range,double & lower,double & upper)3798 void convertSenseToBound(const char sense, const double right,
3799   const double range,
3800   double &lower, double &upper)
3801 {
3802   double inf = COIN_DBL_MAX;
3803   switch (sense) {
3804   case 'E':
3805     lower = upper = right;
3806     break;
3807   case 'L':
3808     lower = -inf;
3809     upper = right;
3810     break;
3811   case 'G':
3812     lower = right;
3813     upper = inf;
3814     break;
3815   case 'R':
3816     lower = right - range;
3817     upper = right;
3818     break;
3819   case 'N':
3820     lower = -inf;
3821     upper = inf;
3822     break;
3823   }
3824 }
3825 
loadBlock(const CoinPackedMatrix & matrix,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub)3826 void CoinModel::loadBlock(const CoinPackedMatrix &matrix,
3827   const double *collb, const double *colub,
3828   const double *obj,
3829   const double *rowlb, const double *rowub)
3830 {
3831   passInMatrix(matrix);
3832   int numberRows = matrix.getNumRows();
3833   int numberColumns = matrix.getNumCols();
3834   setObjective(numberColumns, obj);
3835   setRowLower(numberRows, rowlb);
3836   setRowUpper(numberRows, rowub);
3837   setColumnLower(numberColumns, collb);
3838   setColumnUpper(numberColumns, colub);
3839 }
3840 
3841 //-----------------------------------------------------------------------------
3842 
loadBlock(const CoinPackedMatrix & matrix,const double * collb,const double * colub,const double * obj,const char * rowsen,const double * rowrhs,const double * rowrng)3843 void CoinModel::loadBlock(const CoinPackedMatrix &matrix,
3844   const double *collb, const double *colub,
3845   const double *obj,
3846   const char *rowsen, const double *rowrhs,
3847   const double *rowrng)
3848 {
3849   // If any of Rhs NULLs then create arrays
3850   int numrows = matrix.getNumRows();
3851   const char *rowsenUse = rowsen;
3852   if (!rowsen) {
3853     char *rowsen = new char[numrows];
3854     for (int i = 0; i < numrows; i++)
3855       rowsen[i] = 'G';
3856     rowsenUse = rowsen;
3857   }
3858   const double *rowrhsUse = rowrhs;
3859   if (!rowrhs) {
3860     double *rowrhs = new double[numrows];
3861     for (int i = 0; i < numrows; i++)
3862       rowrhs[i] = 0.0;
3863     rowrhsUse = rowrhs;
3864   }
3865   const double *rowrngUse = rowrng;
3866   if (!rowrng) {
3867     double *rowrng = new double[numrows];
3868     for (int i = 0; i < numrows; i++)
3869       rowrng[i] = 0.0;
3870     rowrngUse = rowrng;
3871   }
3872   double *rowlb = new double[numrows];
3873   double *rowub = new double[numrows];
3874   for (int i = numrows - 1; i >= 0; --i) {
3875     convertSenseToBound(rowsenUse[i], rowrhsUse[i], rowrngUse[i], rowlb[i], rowub[i]);
3876   }
3877   if (rowsen != rowsenUse)
3878     delete[] rowsenUse;
3879   if (rowrhs != rowrhsUse)
3880     delete[] rowrhsUse;
3881   if (rowrng != rowrngUse)
3882     delete[] rowrngUse;
3883   loadBlock(matrix, collb, colub, obj, rowlb, rowub);
3884   delete[] rowlb;
3885   delete[] rowub;
3886 }
3887 
3888 //-----------------------------------------------------------------------------
3889 
loadBlock(const int numcols,const int numrows,const CoinBigIndex * start,const int * index,const double * value,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub)3890 void CoinModel::loadBlock(const int numcols, const int numrows,
3891   const CoinBigIndex *start, const int *index,
3892   const double *value,
3893   const double *collb, const double *colub,
3894   const double *obj,
3895   const double *rowlb, const double *rowub)
3896 {
3897   CoinBigIndex numberElements = start[numcols];
3898   int *length = new int[numcols];
3899   for (int i = 0; i < numcols; i++)
3900     length[i] = static_cast< int >(start[i + 1] - start[i]);
3901   CoinPackedMatrix matrix(true, numrows, numcols, numberElements, value,
3902     index, start, length, 0.0, 0.0);
3903   loadBlock(matrix, collb, colub, obj, rowlb, rowub);
3904   delete[] length;
3905 }
3906 //-----------------------------------------------------------------------------
3907 
loadBlock(const int numcols,const int numrows,const CoinBigIndex * start,const int * index,const double * value,const double * collb,const double * colub,const double * obj,const char * rowsen,const double * rowrhs,const double * rowrng)3908 void CoinModel::loadBlock(const int numcols, const int numrows,
3909   const CoinBigIndex *start, const int *index,
3910   const double *value,
3911   const double *collb, const double *colub,
3912   const double *obj,
3913   const char *rowsen, const double *rowrhs,
3914   const double *rowrng)
3915 {
3916   // If any of Rhs NULLs then create arrays
3917   const char *rowsenUse = rowsen;
3918   if (!rowsen) {
3919     char *rowsen = new char[numrows];
3920     for (int i = 0; i < numrows; i++)
3921       rowsen[i] = 'G';
3922     rowsenUse = rowsen;
3923   }
3924   const double *rowrhsUse = rowrhs;
3925   if (!rowrhs) {
3926     double *rowrhs = new double[numrows];
3927     for (int i = 0; i < numrows; i++)
3928       rowrhs[i] = 0.0;
3929     rowrhsUse = rowrhs;
3930   }
3931   const double *rowrngUse = rowrng;
3932   if (!rowrng) {
3933     double *rowrng = new double[numrows];
3934     for (int i = 0; i < numrows; i++)
3935       rowrng[i] = 0.0;
3936     rowrngUse = rowrng;
3937   }
3938   double *rowlb = new double[numrows];
3939   double *rowub = new double[numrows];
3940   for (int i = numrows - 1; i >= 0; --i) {
3941     convertSenseToBound(rowsenUse[i], rowrhsUse[i], rowrngUse[i], rowlb[i], rowub[i]);
3942   }
3943   if (rowsen != rowsenUse)
3944     delete[] rowsenUse;
3945   if (rowrhs != rowrhsUse)
3946     delete[] rowrhsUse;
3947   if (rowrng != rowrngUse)
3948     delete[] rowrngUse;
3949   CoinBigIndex numberElements = start[numcols];
3950   int *length = new int[numcols];
3951   for (int i = 0; i < numcols; i++)
3952     length[i] = static_cast< int >(start[i + 1] - start[i]);
3953   CoinPackedMatrix matrix(true, numrows, numcols, numberElements, value,
3954     index, start, length, 0.0, 0.0);
3955   loadBlock(matrix, collb, colub, obj, rowlb, rowub);
3956   delete[] length;
3957   delete[] rowlb;
3958   delete[] rowub;
3959 }
3960 /* Returns which parts of model are set
3961    1 - matrix
3962    2 - rhs
3963    4 - row names
3964    8 - column bounds and/or objective
3965    16 - column names
3966    32 - integer types
3967 */
whatIsSet() const3968 int CoinModel::whatIsSet() const
3969 {
3970   int type = (numberElements_) ? 1 : 0;
3971   bool defaultValues = true;
3972   if (rowLower_) {
3973     for (int i = 0; i < numberRows_; i++) {
3974       if (rowLower_[i] != -COIN_DBL_MAX) {
3975         defaultValues = false;
3976         break;
3977       }
3978       if (rowUpper_[i] != COIN_DBL_MAX) {
3979         defaultValues = false;
3980         break;
3981       }
3982     }
3983   }
3984   if (!defaultValues)
3985     type |= 2;
3986   if (rowName_.numberItems())
3987     type |= 4;
3988   defaultValues = true;
3989   if (columnLower_) {
3990     for (int i = 0; i < numberColumns_; i++) {
3991       if (objective_[i] != 0.0) {
3992         defaultValues = false;
3993         break;
3994       }
3995       if (columnLower_[i] != 0.0) {
3996         defaultValues = false;
3997         break;
3998       }
3999       if (columnUpper_[i] != COIN_DBL_MAX) {
4000         defaultValues = false;
4001         break;
4002       }
4003     }
4004   }
4005   if (!defaultValues)
4006     type |= 8;
4007   if (columnName_.numberItems())
4008     type |= 16;
4009   defaultValues = true;
4010   if (integerType_) {
4011     for (int i = 0; i < numberColumns_; i++) {
4012       if (integerType_[i]) {
4013         defaultValues = false;
4014         break;
4015       }
4016     }
4017   }
4018   if (!defaultValues)
4019     type |= 32;
4020   return type;
4021 }
4022 // For decomposition set original row and column indices
setOriginalIndices(const int * row,const int * column)4023 void CoinModel::setOriginalIndices(const int *row, const int *column)
4024 {
4025   if (!rowType_)
4026     rowType_ = new int[numberRows_];
4027   memcpy(rowType_, row, numberRows_ * sizeof(int));
4028   if (!columnType_)
4029     columnType_ = new int[numberColumns_];
4030   memcpy(columnType_, column, numberColumns_ * sizeof(int));
4031 }
4032 
4033 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
4034 */
4035