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