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 ¤t) 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 ¤t) 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