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