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