1 /* $Id: CoinLpIO.cpp 2122 2019-04-08 03:26:16Z stefan $ */
2 // Last edit: 11/5/08
3 //
4 // Name: CoinLpIO.cpp; Support for Lp files
5 // Author: Francois Margot
6 // Tepper School of Business
7 // Carnegie Mellon University, Pittsburgh, PA 15213
8 // Date: 12/28/03
9 //-----------------------------------------------------------------------------
10 // Copyright (C) 2003, Francois Margot, International Business Machines
11 // Corporation and others. All Rights Reserved.
12 // This code is licensed under the terms of the Eclipse Public License (EPL).
13
14 #include "CoinUtilsConfig.h"
15
16 #include <cmath>
17 #include <cfloat>
18 #include <cctype>
19 #include <cassert>
20 #include <string>
21 #include <cstdarg>
22
23 #include "CoinError.hpp"
24 #include "CoinHelperFunctions.hpp"
25 #include "CoinPackedMatrix.hpp"
26 #include "CoinLpIO.hpp"
27 #include "CoinMpsIO.hpp"
28 #include "CoinFinite.hpp"
29 #include "CoinSort.hpp"
30
31 using namespace std;
32
33 //#define LPIO_DEBUG
34
35 /************************************************************************/
36
CoinLpIO()37 CoinLpIO::CoinLpIO()
38 : problemName_(CoinStrdup(""))
39 , defaultHandler_(true)
40 , numberRows_(0)
41 , numberColumns_(0)
42 , numberElements_(0)
43 , matrixByColumn_(NULL)
44 , matrixByRow_(NULL)
45 , rowlower_(NULL)
46 , rowupper_(NULL)
47 , collower_(NULL)
48 , colupper_(NULL)
49 , rhs_(NULL)
50 , rowrange_(NULL)
51 , rowsense_(NULL)
52 , num_objectives_(0)
53 , integerType_(NULL)
54 , set_(NULL)
55 , numberSets_(0)
56 , fileName_(NULL)
57 , infinity_(COIN_DBL_MAX)
58 , epsilon_(1e-5)
59 , numberAcross_(10)
60 , decimals_(9)
61 , wasMaximization_(false)
62 , input_(NULL)
63 {
64 for (int j = 0; j < MAX_OBJECTIVES; j++) {
65 objective_[j] = NULL;
66 objName_[j] = NULL;
67 objectiveOffset_[j] = 0;
68 }
69 card_previous_names_[0] = 0;
70 card_previous_names_[1] = 0;
71 previous_names_[0] = NULL;
72 previous_names_[1] = NULL;
73
74 maxHash_[0] = 0;
75 numberHash_[0] = 0;
76 hash_[0] = NULL;
77 names_[0] = NULL;
78 maxHash_[1] = 0;
79 numberHash_[1] = 0;
80 hash_[1] = NULL;
81 names_[1] = NULL;
82 handler_ = new CoinMessageHandler();
83 messages_ = CoinMessage();
84 }
85
86 //-------------------------------------------------------------------
87 // Copy constructor
88 //-------------------------------------------------------------------
CoinLpIO(const CoinLpIO & rhs)89 CoinLpIO::CoinLpIO(const CoinLpIO &rhs)
90 : problemName_(CoinStrdup(""))
91 , defaultHandler_(true)
92 , numberRows_(0)
93 , numberColumns_(0)
94 , numberElements_(0)
95 , matrixByColumn_(NULL)
96 , matrixByRow_(NULL)
97 , rowlower_(NULL)
98 , rowupper_(NULL)
99 , collower_(NULL)
100 , colupper_(NULL)
101 , rhs_(NULL)
102 , rowrange_(NULL)
103 , rowsense_(NULL)
104 , integerType_(NULL)
105 , set_(NULL)
106 , numberSets_(0)
107 , fileName_(CoinStrdup(""))
108 , infinity_(COIN_DBL_MAX)
109 , epsilon_(1e-5)
110 , numberAcross_(10)
111 , input_(NULL)
112 {
113 num_objectives_ = rhs.num_objectives_;
114 for (int j = 0; j < MAX_OBJECTIVES; j++) {
115 objective_[j] = NULL;
116 if (j < num_objectives_) {
117 objName_[j] = CoinStrdup(rhs.objName_[j]);
118 } else {
119 objName_[j] = NULL;
120 }
121 objectiveOffset_[j] = 0;
122 }
123 card_previous_names_[0] = 0;
124 card_previous_names_[1] = 0;
125 previous_names_[0] = NULL;
126 previous_names_[1] = NULL;
127 maxHash_[0] = 0;
128 numberHash_[0] = 0;
129 hash_[0] = NULL;
130 names_[0] = NULL;
131 maxHash_[1] = 0;
132 numberHash_[1] = 0;
133 hash_[1] = NULL;
134 names_[1] = NULL;
135
136 if (rhs.rowlower_ != NULL || rhs.collower_ != NULL) {
137 gutsOfCopy(rhs);
138 }
139
140 defaultHandler_ = rhs.defaultHandler_;
141
142 if (defaultHandler_) {
143 handler_ = new CoinMessageHandler(*rhs.handler_);
144 } else {
145 handler_ = rhs.handler_;
146 }
147
148 messages_ = CoinMessage();
149 }
150
gutsOfCopy(const CoinLpIO & rhs)151 void CoinLpIO::gutsOfCopy(const CoinLpIO &rhs)
152 {
153 defaultHandler_ = rhs.defaultHandler_;
154
155 if (rhs.matrixByRow_) {
156 matrixByRow_ = new CoinPackedMatrix(*(rhs.matrixByRow_));
157 }
158
159 numberElements_ = rhs.numberElements_;
160 numberRows_ = rhs.numberRows_;
161 numberColumns_ = rhs.numberColumns_;
162 decimals_ = rhs.decimals_;
163 wasMaximization_ = rhs.wasMaximization_;
164
165 if (rhs.rowlower_) {
166 rowlower_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
167 rowupper_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
168 memcpy(rowlower_, rhs.rowlower_, numberRows_ * sizeof(double));
169 memcpy(rowupper_, rhs.rowupper_, numberRows_ * sizeof(double));
170 rowrange_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
171 rowsense_ = reinterpret_cast< char * >(malloc(numberRows_ * sizeof(char)));
172 rhs_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
173 memcpy(rowrange_, rhs.getRowRange(), numberRows_ * sizeof(double));
174 memcpy(rowsense_, rhs.getRowSense(), numberRows_ * sizeof(char));
175 memcpy(rhs_, rhs.getRightHandSide(), numberRows_ * sizeof(double));
176 }
177
178 if (rhs.collower_) {
179 collower_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
180 colupper_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
181 memcpy(collower_, rhs.collower_, numberColumns_ * sizeof(double));
182 memcpy(colupper_, rhs.colupper_, numberColumns_ * sizeof(double));
183 for (int j = 0; j < num_objectives_; j++) {
184 objective_[j] = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
185 memcpy(objective_[j], rhs.objective_[j], numberColumns_ * sizeof(double));
186 }
187 }
188
189 if (rhs.integerType_) {
190 integerType_ = reinterpret_cast< char * >(malloc(numberColumns_ * sizeof(char)));
191 memcpy(integerType_, rhs.integerType_, numberColumns_ * sizeof(char));
192 }
193 numberSets_ = rhs.numberSets_;
194 if (numberSets_) {
195 set_ = new CoinSet *[numberSets_];
196 for (int j = 0; j < numberSets_; j++)
197 set_[j] = new CoinSet(*rhs.set_[j]);
198 }
199
200 free(fileName_);
201 free(problemName_);
202 fileName_ = CoinStrdup(rhs.fileName_);
203 problemName_ = CoinStrdup(rhs.problemName_);
204 numberHash_[0] = rhs.numberHash_[0];
205 numberHash_[1] = rhs.numberHash_[1];
206 maxHash_[0] = rhs.maxHash_[0];
207 maxHash_[1] = rhs.maxHash_[1];
208 infinity_ = rhs.infinity_;
209 numberAcross_ = rhs.numberAcross_;
210 for (int j = 0; j < num_objectives_; j++) {
211 objectiveOffset_[j] = rhs.objectiveOffset_[j];
212 }
213 int section;
214
215 for (section = 0; section < 2; section++) {
216 if (numberHash_[section]) {
217 char **names2 = rhs.names_[section];
218 names_[section] = reinterpret_cast< char ** >(malloc(maxHash_[section] * sizeof(char *)));
219 char **names = names_[section];
220 int i;
221
222 for (i = 0; i < numberHash_[section]; i++) {
223 names[i] = CoinStrdup(names2[i]);
224 }
225
226 hash_[section] = new CoinHashLink[maxHash_[section]];
227 std::memcpy(hash_[section], rhs.hash_[section], maxHash_[section] * sizeof(CoinHashLink));
228 }
229 }
230 }
231
232 CoinLpIO &
operator =(const CoinLpIO & rhs)233 CoinLpIO::operator=(const CoinLpIO &rhs)
234 {
235 if (this != &rhs) {
236 gutsOfDestructor();
237
238 if (rhs.rowlower_ != NULL || rhs.collower_ != NULL) {
239 gutsOfCopy(rhs);
240 }
241
242 defaultHandler_ = rhs.defaultHandler_;
243
244 if (defaultHandler_) {
245 handler_ = new CoinMessageHandler(*rhs.handler_);
246 } else {
247 handler_ = rhs.handler_;
248 }
249
250 messages_ = CoinMessage();
251 }
252
253 return *this;
254 }
255
gutsOfDestructor()256 void CoinLpIO::gutsOfDestructor()
257 {
258 freeAll();
259
260 if (defaultHandler_) {
261 delete handler_;
262 handler_ = NULL;
263 }
264 }
265
266 /************************************************************************/
~CoinLpIO()267 CoinLpIO::~CoinLpIO()
268 {
269 stopHash(0);
270 stopHash(1);
271 freeAll();
272 if (defaultHandler_) {
273 delete handler_;
274 handler_ = NULL;
275 }
276 }
277
278 /************************************************************************/
freePreviousNames(const int section)279 void CoinLpIO::freePreviousNames(const int section)
280 {
281
282 int j;
283
284 if (previous_names_[section] != NULL) {
285 for (j = 0; j < card_previous_names_[section]; j++) {
286 free(previous_names_[section][j]);
287 }
288 free(previous_names_[section]);
289 }
290 previous_names_[section] = NULL;
291 card_previous_names_[section] = 0;
292 } /* freePreviousNames */
293
294 /************************************************************************/
freeAll()295 void CoinLpIO::freeAll()
296 {
297
298 delete matrixByColumn_;
299 matrixByColumn_ = NULL;
300 delete matrixByRow_;
301 matrixByRow_ = NULL;
302 free(rowupper_);
303 rowupper_ = NULL;
304 free(rowlower_);
305 rowlower_ = NULL;
306 free(colupper_);
307 colupper_ = NULL;
308 free(collower_);
309 collower_ = NULL;
310 free(rhs_);
311 rhs_ = NULL;
312 free(rowrange_);
313 rowrange_ = NULL;
314 free(rowsense_);
315 rowsense_ = NULL;
316 for (int j = 0; j < num_objectives_; j++) {
317 free(objective_[j]);
318 objective_[j] = NULL;
319 }
320 free(integerType_);
321 integerType_ = NULL;
322 for (int j = 0; j < numberSets_; j++)
323 delete set_[j];
324 delete[] set_;
325 set_ = NULL;
326 numberSets_ = 0;
327 free(problemName_);
328 problemName_ = NULL;
329 free(fileName_);
330 fileName_ = NULL;
331
332 freePreviousNames(0);
333 freePreviousNames(1);
334 delete input_;
335 input_ = NULL;
336 }
337
338 /*************************************************************************/
getProblemName() const339 const char *CoinLpIO::getProblemName() const
340 {
341 return problemName_;
342 }
343
setProblemName(const char * name)344 void CoinLpIO::setProblemName(const char *name)
345 {
346 free(problemName_);
347 problemName_ = CoinStrdup(name);
348 }
349
350 /*************************************************************************/
getNumCols() const351 int CoinLpIO::getNumCols() const
352 {
353 return numberColumns_;
354 }
355
356 /*************************************************************************/
getNumRows() const357 int CoinLpIO::getNumRows() const
358 {
359 return numberRows_;
360 }
361
362 /*************************************************************************/
getNumElements() const363 CoinBigIndex CoinLpIO::getNumElements() const
364 {
365 return numberElements_;
366 }
367
368 /*************************************************************************/
getColLower() const369 const double *CoinLpIO::getColLower() const
370 {
371 return collower_;
372 }
373
374 /*************************************************************************/
getColUpper() const375 const double *CoinLpIO::getColUpper() const
376 {
377 return colupper_;
378 }
379
380 /*************************************************************************/
getRowLower() const381 const double *CoinLpIO::getRowLower() const
382 {
383 return rowlower_;
384 }
385
386 /*************************************************************************/
getRowUpper() const387 const double *CoinLpIO::getRowUpper() const
388 {
389 return rowupper_;
390 }
391
392 /*************************************************************************/
393 /** A quick inlined function to convert from lb/ub style constraint
394 definition to sense/rhs/range style */
395 inline void
convertBoundToSense(const double lower,const double upper,char & sense,double & right,double & range) const396 CoinLpIO::convertBoundToSense(const double lower, const double upper,
397 char &sense, double &right,
398 double &range) const
399 {
400 range = 0.0;
401 if (lower > -infinity_) {
402 if (upper < infinity_) {
403 right = upper;
404 if (upper == lower) {
405 sense = 'E';
406 } else {
407 sense = 'R';
408 range = upper - lower;
409 }
410 } else {
411 sense = 'G';
412 right = lower;
413 }
414 } else {
415 if (upper < infinity_) {
416 sense = 'L';
417 right = upper;
418 } else {
419 sense = 'N';
420 right = 0.0;
421 }
422 }
423 }
424
425 /*************************************************************************/
getRowSense() const426 const char *CoinLpIO::getRowSense() const
427 {
428 if (rowsense_ == NULL) {
429 int nr = numberRows_;
430 rowsense_ = reinterpret_cast< char * >(malloc(nr * sizeof(char)));
431
432 double dum1, dum2;
433 int i;
434 for (i = 0; i < nr; i++) {
435 convertBoundToSense(rowlower_[i], rowupper_[i], rowsense_[i], dum1, dum2);
436 }
437 }
438 return rowsense_;
439 }
440
441 /*************************************************************************/
getRightHandSide() const442 const double *CoinLpIO::getRightHandSide() const
443 {
444 if (rhs_ == NULL) {
445 int nr = numberRows_;
446 rhs_ = reinterpret_cast< double * >(malloc(nr * sizeof(double)));
447
448 char dum1;
449 double dum2;
450 int i;
451 for (i = 0; i < nr; i++) {
452 convertBoundToSense(rowlower_[i], rowupper_[i], dum1, rhs_[i], dum2);
453 }
454 }
455 return rhs_;
456 }
457
458 /*************************************************************************/
getRowRange() const459 const double *CoinLpIO::getRowRange() const
460 {
461 if (rowrange_ == NULL) {
462 int nr = numberRows_;
463 rowrange_ = reinterpret_cast< double * >(malloc(nr * sizeof(double)));
464 std::fill(rowrange_, rowrange_ + nr, 0.0);
465
466 char dum1;
467 double dum2;
468 int i;
469 for (i = 0; i < nr; i++) {
470 convertBoundToSense(rowlower_[i], rowupper_[i], dum1, dum2, rowrange_[i]);
471 }
472 }
473 return rowrange_;
474 }
475
476 /*************************************************************************/
getNumObjectives() const477 const int CoinLpIO::getNumObjectives() const
478 {
479 return num_objectives_;
480 }
481
482 /*************************************************************************/
getObjCoefficients() const483 const double *CoinLpIO::getObjCoefficients() const
484 {
485 return objective_[0];
486 }
487
488 /*************************************************************************/
getObjCoefficients(int j) const489 const double *CoinLpIO::getObjCoefficients(int j) const
490 {
491 return objective_[j];
492 }
493
494 /*************************************************************************/
getMatrixByRow() const495 const CoinPackedMatrix *CoinLpIO::getMatrixByRow() const
496 {
497 return matrixByRow_;
498 }
499
500 /*************************************************************************/
getMatrixByCol() const501 const CoinPackedMatrix *CoinLpIO::getMatrixByCol() const
502 {
503 if (matrixByColumn_ == NULL && matrixByRow_) {
504 matrixByColumn_ = new CoinPackedMatrix(*matrixByRow_);
505 matrixByColumn_->reverseOrdering();
506 }
507 return matrixByColumn_;
508 }
509
510 /*************************************************************************/
getObjName() const511 const char *CoinLpIO::getObjName() const
512 {
513 return objName_[0];
514 }
515
516 /*************************************************************************/
getObjName(int j) const517 const char *CoinLpIO::getObjName(int j) const
518 {
519 return objName_[j];
520 }
521
522 /*************************************************************************/
checkRowNames()523 void CoinLpIO::checkRowNames()
524 {
525
526 int i, nrow = getNumRows();
527
528 if (numberHash_[0] != nrow + 1) {
529 setDefaultRowNames();
530 handler_->message(COIN_GENERAL_WARNING, messages_) << "### CoinLpIO::checkRowNames(): non distinct or missing row names or objective function name.\nNow using default row names."
531 << CoinMessageEol;
532 }
533
534 char const *const *rowNames = getRowNames();
535 const char *rSense = getRowSense();
536 char rName[256];
537
538 // Check that row names and objective function name are all distinct,
539 /// even after adding "_low" to ranged constraint names
540
541 for (i = 0; i < nrow; i++) {
542 if (rSense[i] == 'R') {
543 sprintf(rName, "%s_low", rowNames[i]);
544 if (findHash(rName, 0) != -1) {
545 setDefaultRowNames();
546 char printBuffer[512];
547 sprintf(printBuffer, "### CoinLpIO::checkRowNames(): ranged constraint %d has a name %s identical to another constraint name or objective function name.\nUse getPreviousNames() to get the old row names.\nNow using default row names.", i, rName);
548 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
549 << CoinMessageEol;
550 break;
551 }
552 }
553 }
554 } /* checkRowNames */
555
556 /*************************************************************************/
checkColNames()557 void CoinLpIO::checkColNames()
558 {
559
560 int ncol = getNumCols();
561
562 if (numberHash_[1] != ncol) {
563 setDefaultColNames();
564 handler_->message(COIN_GENERAL_WARNING, messages_) << "### CoinLpIO::checkColNames(): non distinct or missing column names.\nNow using default column names."
565 << CoinMessageEol;
566 }
567 } /* checkColNames */
568
569 /*************************************************************************/
getPreviousRowNames(char const * const * prev,int * card_prev) const570 void CoinLpIO::getPreviousRowNames(char const *const *prev,
571 int *card_prev) const
572 {
573 *card_prev = card_previous_names_[0];
574 prev = previous_names_[0];
575 }
576
577 /*************************************************************************/
getPreviousColNames(char const * const * prev,int * card_prev) const578 void CoinLpIO::getPreviousColNames(char const *const *prev,
579 int *card_prev) const
580 {
581 *card_prev = card_previous_names_[1];
582 prev = previous_names_[1];
583 }
584
585 /*************************************************************************/
getRowNames() const586 char const *const *CoinLpIO::getRowNames() const
587 {
588 return names_[0];
589 }
590
591 /*************************************************************************/
getColNames() const592 char const *const *CoinLpIO::getColNames() const
593 {
594 return names_[1];
595 }
596
597 /*************************************************************************/
rowName(int index) const598 const char *CoinLpIO::rowName(int index) const
599 {
600
601 if ((names_[0] != NULL) && (index >= 0) && (index < numberRows_ + 1)) {
602 return names_[0][index];
603 } else {
604 return NULL;
605 }
606 }
607
608 /*************************************************************************/
columnName(int index) const609 const char *CoinLpIO::columnName(int index) const
610 {
611
612 if ((names_[1] != NULL) && (index >= 0) && (index < numberColumns_)) {
613 return names_[1][index];
614 } else {
615 return NULL;
616 }
617 }
618
619 /*************************************************************************/
rowIndex(const char * name) const620 int CoinLpIO::rowIndex(const char *name) const
621 {
622
623 if (!hash_[0]) {
624 return -1;
625 }
626 return findHash(name, 0);
627 }
628
629 /*************************************************************************/
columnIndex(const char * name) const630 int CoinLpIO::columnIndex(const char *name) const
631 {
632
633 if (!hash_[1]) {
634 return -1;
635 }
636 return findHash(name, 1);
637 }
638
639 /************************************************************************/
getInfinity() const640 double CoinLpIO::getInfinity() const
641 {
642 return infinity_;
643 }
644
645 /************************************************************************/
setInfinity(const double value)646 void CoinLpIO::setInfinity(const double value)
647 {
648 if (value >= 1.0e20) {
649 infinity_ = value;
650 } else {
651 char str[8192];
652 sprintf(str, "### ERROR: value: %f\n", value);
653 throw CoinError(str, "setInfinity", "CoinLpIO", __FILE__, __LINE__);
654 }
655 }
656
657 /************************************************************************/
getEpsilon() const658 double CoinLpIO::getEpsilon() const
659 {
660 return epsilon_;
661 }
662
663 /************************************************************************/
setEpsilon(const double value)664 void CoinLpIO::setEpsilon(const double value)
665 {
666 if (value < 0.1) {
667 epsilon_ = value;
668 } else {
669 char str[8192];
670 sprintf(str, "### ERROR: value: %f\n", value);
671 throw CoinError(str, "setEpsilon", "CoinLpIO", __FILE__, __LINE__);
672 }
673 }
674
675 /************************************************************************/
getNumberAcross() const676 int CoinLpIO::getNumberAcross() const
677 {
678 return numberAcross_;
679 }
680
681 /************************************************************************/
setNumberAcross(const int value)682 void CoinLpIO::setNumberAcross(const int value)
683 {
684 if (value > 0) {
685 numberAcross_ = value;
686 } else {
687 char str[8192];
688 sprintf(str, "### ERROR: value: %d\n", value);
689 throw CoinError(str, "setNumberAcross", "CoinLpIO", __FILE__, __LINE__);
690 }
691 }
692
693 /************************************************************************/
getDecimals() const694 int CoinLpIO::getDecimals() const
695 {
696 return decimals_;
697 }
698
699 /************************************************************************/
setDecimals(const int value)700 void CoinLpIO::setDecimals(const int value)
701 {
702 if (value > 0) {
703 decimals_ = value;
704 } else {
705 char str[8192];
706 sprintf(str, "### ERROR: value: %d\n", value);
707 throw CoinError(str, "setDecimals", "CoinLpIO", __FILE__, __LINE__);
708 }
709 }
710
711 /************************************************************************/
objectiveOffset() const712 double CoinLpIO::objectiveOffset() const
713 {
714 return objectiveOffset_[0];
715 }
716
717 /************************************************************************/
objectiveOffset(int j) const718 double CoinLpIO::objectiveOffset(int j) const
719 {
720 return objectiveOffset_[j];
721 }
722
723 /************************************************************************/
isInteger(int columnNumber) const724 bool CoinLpIO::isInteger(int columnNumber) const
725 {
726 const char *intType = integerType_;
727 if (intType == NULL)
728 return false;
729 assert(columnNumber >= 0 && columnNumber < numberColumns_);
730 if (intType[columnNumber] != 0)
731 return true;
732 return false;
733 }
734
735 /************************************************************************/
integerColumns() const736 const char *CoinLpIO::integerColumns() const
737 {
738 return integerType_;
739 }
740
741 /************************************************************************/
setLpDataWithoutRowAndColNames(const CoinPackedMatrix & m,const double * collb,const double * colub,const double * obj_coeff,const char * is_integer,const double * rowlb,const double * rowub)742 void CoinLpIO::setLpDataWithoutRowAndColNames(
743 const CoinPackedMatrix &m,
744 const double *collb, const double *colub,
745 const double *obj_coeff,
746 const char *is_integer,
747 const double *rowlb, const double *rowub)
748 {
749
750 setLpDataWithoutRowAndColNames(m, collb, colub, &obj_coeff, 1, is_integer,
751 rowlb, rowub);
752 }
753
754 /************************************************************************/
setLpDataWithoutRowAndColNames(const CoinPackedMatrix & m,const double * collb,const double * colub,const double * obj_coeff[MAX_OBJECTIVES],int num_objectives,const char * is_integer,const double * rowlb,const double * rowub)755 void CoinLpIO::setLpDataWithoutRowAndColNames(
756 const CoinPackedMatrix &m,
757 const double *collb, const double *colub,
758 const double *obj_coeff[MAX_OBJECTIVES],
759 int num_objectives,
760 const char *is_integer,
761 const double *rowlb, const double *rowub)
762 {
763
764 freeAll();
765 problemName_ = CoinStrdup("");
766
767 if (m.isColOrdered()) {
768 matrixByRow_ = new CoinPackedMatrix();
769 matrixByRow_->reverseOrderedCopyOf(m);
770 } else {
771 matrixByRow_ = new CoinPackedMatrix(m);
772 }
773 numberColumns_ = matrixByRow_->getNumCols();
774 numberRows_ = matrixByRow_->getNumRows();
775
776 rowlower_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
777 rowupper_ = reinterpret_cast< double * >(malloc(numberRows_ * sizeof(double)));
778 collower_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
779 colupper_ = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
780 std::copy(rowlb, rowlb + numberRows_, rowlower_);
781 std::copy(rowub, rowub + numberRows_, rowupper_);
782 std::copy(collb, collb + numberColumns_, collower_);
783 std::copy(colub, colub + numberColumns_, colupper_);
784 num_objectives_ = num_objectives;
785 for (int j = 0; j < num_objectives; j++) {
786 objective_[j] = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
787 std::copy(obj_coeff[j], obj_coeff[j] + numberColumns_, objective_[j]);
788 }
789
790 if (is_integer) {
791 integerType_ = reinterpret_cast< char * >(malloc(numberColumns_ * sizeof(char)));
792 std::copy(is_integer, is_integer + numberColumns_, integerType_);
793 } else {
794 integerType_ = 0;
795 }
796
797 if ((numberHash_[0] > 0) && (numberHash_[0] != numberRows_ + 1)) {
798 stopHash(0);
799 }
800 if ((numberHash_[1] > 0) && (numberHash_[1] != numberColumns_)) {
801 stopHash(1);
802 }
803 } /* SetLpDataWithoutRowAndColNames */
804
805 /*************************************************************************/
setDefaultRowNames()806 void CoinLpIO::setDefaultRowNames()
807 {
808
809 int i, nrow = getNumRows();
810 char **defaultRowNames = reinterpret_cast< char ** >(malloc((nrow + 1) * sizeof(char *)));
811 char buff[1024];
812
813 for (i = 0; i < nrow; i++) {
814 sprintf(buff, "cons%d", i);
815 defaultRowNames[i] = CoinStrdup(buff);
816 }
817 sprintf(buff, "obj");
818 defaultRowNames[nrow] = CoinStrdup(buff);
819
820 stopHash(0);
821 startHash(defaultRowNames, nrow + 1, 0);
822 objName_[0] = CoinStrdup("obj");
823
824 for (i = 0; i < nrow + 1; i++) {
825 free(defaultRowNames[i]);
826 }
827 free(defaultRowNames);
828
829 } /* setDefaultRowNames */
830
831 /*************************************************************************/
setDefaultColNames()832 void CoinLpIO::setDefaultColNames()
833 {
834
835 int j, ncol = getNumCols();
836 char **defaultColNames = reinterpret_cast< char ** >(malloc(ncol * sizeof(char *)));
837 char buff[256];
838
839 for (j = 0; j < ncol; j++) {
840 sprintf(buff, "x%d", j);
841 defaultColNames[j] = CoinStrdup(buff);
842 }
843 stopHash(1);
844 startHash(defaultColNames, ncol, 1);
845
846 for (j = 0; j < ncol; j++) {
847 free(defaultColNames[j]);
848 }
849 free(defaultColNames);
850
851 } /* setDefaultColNames */
852
853 /*************************************************************************/
setLpDataRowAndColNames(char const * const * const rownames,char const * const * const colnames)854 void CoinLpIO::setLpDataRowAndColNames(char const *const *const rownames,
855 char const *const *const colnames)
856 {
857
858 int nrow = getNumRows();
859 int ncol = getNumCols();
860
861 if (rownames != NULL) {
862 if (are_invalid_names(rownames, nrow + 1, true)) {
863 setDefaultRowNames();
864 handler_->message(COIN_GENERAL_WARNING, messages_) << "### CoinLpIO::setLpDataRowAndColNames(): Invalid row names\nUse getPreviousNames() to get the old row names.\nNow using default row names."
865 << CoinMessageEol;
866 } else {
867 stopHash(0);
868 startHash(rownames, nrow + 1, 0);
869 objName_[0] = CoinStrdup(rownames[nrow]);
870 checkRowNames();
871 }
872 } else {
873 if (objName_[0] == NULL) {
874 objName_[0] = CoinStrdup("obj");
875 }
876 }
877
878 if (colnames != NULL) {
879 if (are_invalid_names(colnames, ncol, false)) {
880 setDefaultColNames();
881 handler_->message(COIN_GENERAL_WARNING, messages_) << "### CoinLpIO::setLpDataRowAndColNames(): Invalid column names\nNow using default row names."
882 << CoinMessageEol;
883 } else {
884 stopHash(1);
885 startHash(colnames, ncol, 1);
886 checkColNames();
887 }
888 }
889 } /* setLpDataColAndRowNames */
890 // Load in SOS stuff
loadSOS(int numberSets,const CoinSet * sets)891 void CoinLpIO::loadSOS(int numberSets, const CoinSet *sets)
892 {
893 if (numberSets_) {
894 for (int i = 0; i < numberSets_; i++)
895 delete set_[i];
896 delete[] set_;
897 set_ = NULL;
898 numberSets_ = 0;
899 }
900 if (numberSets) {
901 numberSets_ = numberSets;
902 set_ = new CoinSet *[numberSets_];
903 for (int i = 0; i < numberSets_; i++)
904 set_[i] = new CoinSet(sets[i]);
905 }
906 }
907
908 // Load in SOS stuff
loadSOS(int numberSets,const CoinSet ** sets)909 void CoinLpIO::loadSOS(int numberSets, const CoinSet **sets)
910 {
911 if (numberSets_) {
912 for (int i = 0; i < numberSets_; i++)
913 delete set_[i];
914 delete[] set_;
915 set_ = NULL;
916 numberSets_ = 0;
917 }
918 if (numberSets) {
919 numberSets_ = numberSets;
920 set_ = new CoinSet *[numberSets_];
921 for (int i = 0; i < numberSets_; i++)
922 set_[i] = new CoinSet(*sets[i]);
923 }
924 }
925
926 /************************************************************************/
out_coeff(FILE * fp,const double v,const int print_1) const927 void CoinLpIO::out_coeff(FILE *fp, const double v, const int print_1) const
928 {
929
930 double lp_eps = getEpsilon();
931
932 if (!print_1) {
933 if (fabs(v - 1) < lp_eps) {
934 return;
935 }
936 if (fabs(v + 1) < lp_eps) {
937 fprintf(fp, " -");
938 return;
939 }
940 }
941
942 double frac = v - floor(v);
943
944 if (frac < lp_eps) {
945 fprintf(fp, " %.0f", floor(v));
946 } else {
947 if (frac > 1 - lp_eps) {
948 fprintf(fp, " %.0f", floor(v + 0.5));
949 } else {
950 int decimals = getDecimals();
951 char form[15];
952 sprintf(form, " %%.%df", decimals);
953 fprintf(fp, form, v);
954 }
955 }
956 } /* out_coeff */
957
958 /************************************************************************/
writeLp(const char * filename,const double epsilon,const int numberAcross,const int decimals,const bool useRowNames)959 int CoinLpIO::writeLp(const char *filename, const double epsilon,
960 const int numberAcross, const int decimals,
961 const bool useRowNames)
962 {
963
964 FILE *fp = NULL;
965 fp = fopen(filename, "w");
966 if (!fp) {
967 char str[8192];
968 sprintf(str, "### ERROR: unable to open file %s\n", filename);
969 throw CoinError(str, "writeLP", "CoinLpIO", __FILE__, __LINE__);
970 }
971 int nerr = writeLp(fp, epsilon, numberAcross, decimals, useRowNames);
972 fclose(fp);
973 return (nerr);
974 }
975
976 /************************************************************************/
writeLp(FILE * fp,const double epsilon,const int numberAcross,const int decimals,const bool useRowNames)977 int CoinLpIO::writeLp(FILE *fp, const double epsilon,
978 const int numberAcross, const int decimals,
979 const bool useRowNames)
980 {
981
982 setEpsilon(epsilon);
983 setNumberAcross(numberAcross);
984 setDecimals(decimals);
985 return writeLp(fp, useRowNames);
986 }
987
988 /************************************************************************/
writeLp(const char * filename,const bool useRowNames)989 int CoinLpIO::writeLp(const char *filename, const bool useRowNames)
990 {
991 FILE *fp = NULL;
992 fp = fopen(filename, "w");
993 if (!fp) {
994 char str[8192];
995 sprintf(str, "### ERROR: unable to open file %s\n", filename);
996 throw CoinError(str, "writeLP", "CoinLpIO", __FILE__, __LINE__);
997 }
998 int nerr = writeLp(fp, useRowNames);
999 fclose(fp);
1000 return (nerr);
1001 }
1002
1003 /************************************************************************/
writeLp(FILE * fp,const bool useRowNames)1004 int CoinLpIO::writeLp(FILE *fp, const bool useRowNames)
1005 {
1006 double lp_eps = getEpsilon();
1007 double lp_inf = getInfinity();
1008 int numberAcross = getNumberAcross();
1009
1010 int i, cnt_print, loc_row_names = 0, loc_col_names = 0;
1011 CoinBigIndex j;
1012 char **prowNames = NULL, **pcolNames = NULL;
1013
1014 const int *indices = matrixByRow_->getIndices();
1015 const double *elements = matrixByRow_->getElements();
1016 int ncol = getNumCols();
1017 int nrow = getNumRows();
1018 const double *collow = getColLower();
1019 const double *colup = getColUpper();
1020 const double *rowlow = getRowLower();
1021 const double *rowup = getRowUpper();
1022 const char *integerType = integerColumns();
1023 char const *const *rowNames = getRowNames();
1024 char const *const *colNames = getColNames();
1025
1026 char buff[256];
1027
1028 if (rowNames == NULL) {
1029 loc_row_names = 1;
1030 prowNames = reinterpret_cast< char ** >(malloc((nrow + 1) * sizeof(char *)));
1031
1032 for (j = 0; j < nrow; j++) {
1033 sprintf(buff, "cons%d", j);
1034 prowNames[j] = CoinStrdup(buff);
1035 }
1036 prowNames[nrow] = CoinStrdup("obj");
1037 rowNames = prowNames;
1038 }
1039
1040 if (colNames == NULL) {
1041 loc_col_names = 1;
1042 pcolNames = reinterpret_cast< char ** >(malloc(ncol * sizeof(char *)));
1043
1044 for (j = 0; j < ncol; j++) {
1045 sprintf(buff, "x%d", j);
1046 pcolNames[j] = CoinStrdup(buff);
1047 }
1048 colNames = pcolNames;
1049 }
1050
1051 #ifdef LPIO_DEBUG
1052 printf("CoinLpIO::writeLp(): numberRows: %d numberColumns: %d\n",
1053 nrow, ncol);
1054 #endif
1055
1056 fprintf(fp, "\\Problem name: %s\n\n", getProblemName());
1057 fprintf(fp, "Minimize\n");
1058
1059 for (int k = 0; k < num_objectives_; k++) {
1060 if (useRowNames) {
1061 fprintf(fp, "%s:", objName_[k]);
1062 }
1063
1064 cnt_print = 0;
1065 for (j = 0; j < ncol; j++) {
1066 if ((cnt_print > 0) && (objective_[k][j] > lp_eps)) {
1067 fprintf(fp, " +");
1068 }
1069 if (fabs(objective_[k][j]) > lp_eps) {
1070 out_coeff(fp, objective_[k][j], 0);
1071 fprintf(fp, " %s", colNames[j]);
1072 cnt_print++;
1073 if (cnt_print % numberAcross == 0) {
1074 fprintf(fp, "\n");
1075 }
1076 }
1077 }
1078
1079 if ((cnt_print > 0) && (objectiveOffset_[k] > lp_eps)) {
1080 fprintf(fp, " +");
1081 }
1082 if (fabs(objectiveOffset_[k]) > lp_eps) {
1083 out_coeff(fp, objectiveOffset_[k], 1);
1084 cnt_print++;
1085 }
1086 if ((cnt_print == 0) || (cnt_print % numberAcross != 0)) {
1087 fprintf(fp, "\n");
1088 }
1089 }
1090
1091 fprintf(fp, "Subject To\n");
1092
1093 int cnt_out_rows = 0;
1094
1095 for (i = 0; i < nrow; i++) {
1096 cnt_print = 0;
1097
1098 if (useRowNames) {
1099 fprintf(fp, "%s: ", rowNames[i]);
1100 }
1101 cnt_out_rows++;
1102
1103 for (j = matrixByRow_->getVectorFirst(i);
1104 j < matrixByRow_->getVectorLast(i); j++) {
1105 if ((cnt_print > 0) && (elements[j] > lp_eps)) {
1106 fprintf(fp, " +");
1107 }
1108 if (fabs(elements[j]) > lp_eps) {
1109 out_coeff(fp, elements[j], 0);
1110 fprintf(fp, " %s", colNames[indices[j]]);
1111 cnt_print++;
1112 if (cnt_print % numberAcross == 0) {
1113 fprintf(fp, "\n");
1114 }
1115 }
1116 }
1117
1118 if (rowup[i] - rowlow[i] < lp_eps) {
1119 fprintf(fp, " =");
1120 out_coeff(fp, rowlow[i], 1);
1121 fprintf(fp, "\n");
1122 } else {
1123 if (rowup[i] < lp_inf) {
1124 fprintf(fp, " <=");
1125 out_coeff(fp, rowup[i], 1);
1126 fprintf(fp, "\n");
1127
1128 if (rowlower_[i] > -lp_inf) {
1129
1130 cnt_print = 0;
1131
1132 if (useRowNames) {
1133 fprintf(fp, "%s_low:", rowNames[i]);
1134 }
1135 cnt_out_rows++;
1136
1137 for (j = matrixByRow_->getVectorFirst(i);
1138 j < matrixByRow_->getVectorLast(i); j++) {
1139 if ((cnt_print > 0) && (elements[j] > lp_eps)) {
1140 fprintf(fp, " +");
1141 }
1142 if (fabs(elements[j]) > lp_eps) {
1143 out_coeff(fp, elements[j], 0);
1144 fprintf(fp, " %s", colNames[indices[j]]);
1145 cnt_print++;
1146 if (cnt_print % numberAcross == 0) {
1147 fprintf(fp, "\n");
1148 }
1149 }
1150 }
1151 fprintf(fp, " >=");
1152 out_coeff(fp, rowlow[i], 1);
1153 fprintf(fp, "\n");
1154 }
1155
1156 } else {
1157 fprintf(fp, " >=");
1158 out_coeff(fp, rowlow[i], 1);
1159 fprintf(fp, "\n");
1160 }
1161 }
1162 }
1163
1164 #ifdef LPIO_DEBUG
1165 printf("CoinLpIO::writeLp(): Done with constraints\n");
1166 #endif
1167
1168 fprintf(fp, "Bounds\n");
1169
1170 for (j = 0; j < ncol; j++) {
1171 if ((collow[j] > -lp_inf) && (colup[j] < lp_inf)) {
1172 out_coeff(fp, collow[j], 1);
1173 fprintf(fp, " <= %s <=", colNames[j]);
1174 out_coeff(fp, colup[j], 1);
1175 fprintf(fp, "\n");
1176 }
1177 if ((collow[j] == -lp_inf) && (colup[j] < lp_inf)) {
1178 fprintf(fp, "%s <=", colNames[j]);
1179 out_coeff(fp, colup[j], 1);
1180 fprintf(fp, "\n");
1181 }
1182 if ((collow[j] > -lp_inf) && (colup[j] == lp_inf)) {
1183 if (fabs(collow[j]) > lp_eps) {
1184 out_coeff(fp, collow[j], 1);
1185 fprintf(fp, " <= %s\n", colNames[j]);
1186 }
1187 }
1188 if (collow[j] == -lp_inf) {
1189 fprintf(fp, " %s Free\n", colNames[j]);
1190 }
1191 }
1192
1193 #ifdef LPIO_DEBUG
1194 printf("CoinLpIO::writeLp(): Done with bounds\n");
1195 #endif
1196
1197 bool semis = false;
1198 if (integerType != NULL) {
1199 int first_int = 1;
1200 cnt_print = 0;
1201 for (j = 0; j < ncol; j++) {
1202 if (integerType[j] == 1 || integerType[j] == 4) {
1203
1204 if (first_int) {
1205 fprintf(fp, "Integers\n");
1206 first_int = 0;
1207 }
1208
1209 fprintf(fp, "%s ", colNames[j]);
1210 cnt_print++;
1211 if (cnt_print % numberAcross == 0) {
1212 fprintf(fp, "\n");
1213 }
1214 }
1215 if (integerType[j] > 1)
1216 semis = true;
1217 }
1218
1219 if (cnt_print % numberAcross != 0) {
1220 fprintf(fp, "\n");
1221 }
1222 if (semis) {
1223 int first_int = 1;
1224 cnt_print = 0;
1225 for (j = 0; j < ncol; j++) {
1226 if (integerType[j] > 2) {
1227
1228 if (first_int) {
1229 fprintf(fp, "Semis\n");
1230 first_int = 0;
1231 }
1232
1233 fprintf(fp, "%s ", colNames[j]);
1234 cnt_print++;
1235 if (cnt_print % numberAcross == 0) {
1236 fprintf(fp, "\n");
1237 }
1238 }
1239 }
1240
1241 if (cnt_print % numberAcross != 0) {
1242 fprintf(fp, "\n");
1243 }
1244 }
1245 }
1246
1247 #ifdef LPIO_DEBUG
1248 printf("CoinLpIO::writeLp(): Done with integers\n");
1249 #endif
1250
1251 if (set_ != NULL) {
1252 fprintf(fp, "SOS\n");
1253 double lp_eps = getEpsilon();
1254 int decimals = getDecimals();
1255 char form[15];
1256 sprintf(form, "%%.%df", decimals);
1257 for (int iSet = 0; iSet < numberSets_; iSet++) {
1258 cnt_print = 0;
1259 const CoinSet *set = set_[iSet];
1260 // no space as readLp gets marginally confused
1261 fprintf(fp, "set%d:S%c::", iSet, '0' + set->setType());
1262 const int *which = set->which();
1263 const double *weights = set->weights();
1264 int numberEntries = set->numberEntries();
1265 for (j = 0; j < numberEntries; j++) {
1266 int iColumn = which[j];
1267 fprintf(fp, " %s:", colNames[iColumn]);
1268 // modified out_coeff (no leading space)
1269 double v = weights[j];
1270 double frac = v - floor(v);
1271
1272 if (frac < lp_eps) {
1273 fprintf(fp, "%.0f", floor(v));
1274 } else {
1275 if (frac > 1 - lp_eps) {
1276 fprintf(fp, "%.0f", floor(v + 0.5));
1277 } else {
1278 fprintf(fp, form, v);
1279 }
1280 }
1281 cnt_print++;
1282 if (cnt_print % numberAcross == 0) {
1283 fprintf(fp, "\n");
1284 }
1285 }
1286
1287 if (cnt_print % numberAcross != 0) {
1288 fprintf(fp, "\n");
1289 }
1290 }
1291 }
1292
1293 #ifdef LPIO_DEBUG
1294 printf("CoinLpIO::writeLp(): Done with SOS\n");
1295 #endif
1296
1297 fprintf(fp, "End\n");
1298
1299 if (loc_row_names) {
1300 for (j = 0; j < nrow + 1; j++) {
1301 free(prowNames[j]);
1302 }
1303 free(prowNames);
1304 }
1305
1306 if (loc_col_names) {
1307 for (j = 0; j < ncol; j++) {
1308 free(pcolNames[j]);
1309 }
1310 free(pcolNames);
1311 }
1312 return 0;
1313 } /* writeLp */
1314
1315 /*************************************************************************/
find_obj() const1316 int CoinLpIO::find_obj() const
1317 {
1318
1319 char buff[1024];
1320
1321 sprintf(buff, "aa");
1322 size_t lbuff = strlen(buff);
1323
1324 while (((lbuff != 8) || (CoinStrNCaseCmp(buff, "minimize", 8) != 0)) && ((lbuff != 3) || (CoinStrNCaseCmp(buff, "min", 3) != 0)) && ((lbuff != 8) || (CoinStrNCaseCmp(buff, "maximize", 8) != 0)) && ((lbuff != 3) || (CoinStrNCaseCmp(buff, "max", 3) != 0))) {
1325
1326 int x = fscanfLpIO(buff);
1327 lbuff = strlen(buff);
1328
1329 if (x <= 0) {
1330 char str[8192];
1331 sprintf(str, "### ERROR: Unable to locate objective function\n");
1332 throw CoinError(str, "find_obj", "CoinLpIO", __FILE__, __LINE__);
1333 }
1334 }
1335
1336 if (((lbuff == 8) && (CoinStrNCaseCmp(buff, "minimize", 8) == 0)) || ((lbuff == 3) && (CoinStrNCaseCmp(buff, "min", 3) == 0))) {
1337 return (1);
1338 }
1339 return (-1);
1340 } /* find_obj */
1341
1342 /*************************************************************************/
is_subject_to(const char * buff) const1343 int CoinLpIO::is_subject_to(const char *buff) const
1344 {
1345
1346 size_t lbuff = strlen(buff);
1347
1348 if (((lbuff == 4) && (CoinStrNCaseCmp(buff, "s.t.", 4) == 0)) || ((lbuff == 3) && (CoinStrNCaseCmp(buff, "st.", 3) == 0)) || ((lbuff == 2) && (CoinStrNCaseCmp(buff, "st", 2) == 0))) {
1349 return (1);
1350 }
1351 if ((lbuff == 7) && (CoinStrNCaseCmp(buff, "subject", 7) == 0)) {
1352 return (2);
1353 }
1354 return (0);
1355 } /* is_subject_to */
1356
1357 /*************************************************************************/
first_is_number(const char * buff) const1358 int CoinLpIO::first_is_number(const char *buff) const
1359 {
1360
1361 size_t pos;
1362 char str_num[] = "1234567890";
1363
1364 pos = strcspn(buff, str_num);
1365 if (pos == 0) {
1366 return (1);
1367 }
1368 return (0);
1369 } /* first_is_number */
1370
1371 /*************************************************************************/
is_sense(const char * buff) const1372 int CoinLpIO::is_sense(const char *buff) const
1373 {
1374
1375 size_t pos;
1376 char str_sense[] = "<>=";
1377
1378 pos = strcspn(buff, str_sense);
1379 if (pos == 0) {
1380 if (strcmp(buff, "<=") == 0) {
1381 return (0);
1382 }
1383 if (strcmp(buff, "=") == 0) {
1384 return (1);
1385 }
1386 if (strcmp(buff, ">=") == 0) {
1387 return (2);
1388 }
1389
1390 printf("### ERROR: CoinLpIO: is_sense(): string: %s \n", buff);
1391 }
1392 return (-1);
1393 } /* is_sense */
1394
1395 /*************************************************************************/
is_free(const char * buff) const1396 int CoinLpIO::is_free(const char *buff) const
1397 {
1398
1399 size_t lbuff = strlen(buff);
1400
1401 if ((lbuff == 4) && (CoinStrNCaseCmp(buff, "free", 4) == 0)) {
1402 return (1);
1403 }
1404 return (0);
1405 } /* is_free */
1406
1407 /*************************************************************************/
is_inf(const char * buff) const1408 int CoinLpIO::is_inf(const char *buff) const
1409 {
1410
1411 size_t lbuff = strlen(buff);
1412
1413 if ((lbuff == 3) && (CoinStrNCaseCmp(buff, "inf", 3) == 0)) {
1414 return (1);
1415 }
1416 return (0);
1417 } /* is_inf */
1418
1419 /*************************************************************************/
is_comment(const char * buff) const1420 int CoinLpIO::is_comment(const char *buff) const
1421 {
1422
1423 if ((buff[0] == '/') || (buff[0] == '\\')) {
1424 return (1);
1425 }
1426 return (0);
1427 } /* is_comment */
1428
1429 /*************************************************************************/
skip_comment(char * buff) const1430 void CoinLpIO::skip_comment(char *buff) const
1431 {
1432
1433 while (strcspn(buff, "\n") == strlen(buff)) { // end of line not read yet
1434 // keep going until in correct buffer
1435 while (bufferLength_ < 0) {
1436 if (fscanfLpIO(buff) == 0)
1437 throw("bad fgets");
1438 }
1439 // and throw away
1440 bufferPosition_ = bufferLength_;
1441 break;
1442 }
1443 } /* skip_comment */
1444
1445 /*************************************************************************/
is_invalid_name(const char * name,const bool ranged) const1446 int CoinLpIO::is_invalid_name(const char *name,
1447 const bool ranged) const
1448 {
1449
1450 size_t pos, lname, valid_lname = 100;
1451 char str_valid[] = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\"!#$%&(),.;?@_'`{}~";
1452
1453 if (ranged) {
1454 valid_lname -= 4; // will add "_low" when writing the Lp file
1455 }
1456
1457 if (name == NULL) {
1458 lname = 0;
1459 } else {
1460 lname = strlen(name);
1461 }
1462 if (lname < 1) {
1463 handler_->message(COIN_GENERAL_WARNING, messages_) << "### CoinLpIO::is_invalid_name(): Name is empty"
1464 << CoinMessageEol;
1465 return (5);
1466 }
1467 if (lname > valid_lname) {
1468 char printBuffer[512];
1469 sprintf(printBuffer, "### CoinLpIO::is_invalid_name(): Name %s is too long",
1470 name);
1471 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
1472 << CoinMessageEol;
1473 return (1);
1474 }
1475 if (first_is_number(name)) {
1476 char printBuffer[512];
1477 sprintf(printBuffer, "### CoinLpIO::is_invalid_name(): Name %s should not start with a number", name);
1478 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
1479 << CoinMessageEol;
1480 return (2);
1481 }
1482 pos = strspn(name, str_valid);
1483 if (pos != lname) {
1484 char printBuffer[512];
1485 sprintf(printBuffer, "### CoinLpIO::is_invalid_name(): Name %s contains illegal character '%c'", name, name[pos]);
1486 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
1487 << CoinMessageEol;
1488 return (3);
1489 }
1490
1491 if ((is_keyword(name)) || (is_free(name) || (is_inf(name)))) {
1492 return (4);
1493 }
1494
1495 return (0);
1496 } /* is_invalid_name */
1497
1498 /*************************************************************************/
are_invalid_names(char const * const * const vnames,const int card_vnames,const bool check_ranged) const1499 int CoinLpIO::are_invalid_names(char const *const *const vnames,
1500 const int card_vnames,
1501 const bool check_ranged) const
1502 {
1503
1504 int i, invalid = 0, flag, nrows = getNumRows();
1505 bool is_ranged = 0;
1506 const char *rSense = getRowSense();
1507
1508 if ((check_ranged) && (card_vnames != nrows + 1)) {
1509 char str[8192];
1510 sprintf(str, "### ERROR: card_vnames: %d number of rows: %d\n",
1511 card_vnames, getNumRows());
1512 throw CoinError(str, "are_invalid_names", "CoinLpIO", __FILE__, __LINE__);
1513 }
1514
1515 for (i = 0; i < card_vnames; i++) {
1516
1517 if ((check_ranged) && (i < nrows) && (rSense[i] == 'R')) {
1518 is_ranged = true;
1519 } else {
1520 is_ranged = false;
1521 }
1522 flag = is_invalid_name(vnames[i], is_ranged);
1523 if (flag) {
1524 char printBuffer[512];
1525 sprintf(printBuffer, "### CoinLpIO::are_invalid_names(): Invalid name: vnames[%d]: %s",
1526 i, vnames[i]);
1527 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
1528 << CoinMessageEol;
1529 invalid = flag;
1530 }
1531 }
1532 return (invalid);
1533 } /* are_invalid_names */
1534
1535 /*************************************************************************/
read_monom_obj(double * coeff,char ** name,int * cnt,char ** obj_name,int * num_objectives,int * obj_starts)1536 int CoinLpIO::read_monom_obj(double *coeff, char **name, int *cnt,
1537 char **obj_name, int *num_objectives, int *obj_starts)
1538 {
1539
1540 double mult;
1541 char buff[1024] = "aa", loc_name[1024], *start;
1542 int read_st = 0;
1543
1544 int x = fscanfLpIO(buff);
1545
1546 if (x <= 0) {
1547 char str[8192];
1548 sprintf(str, "### ERROR: Unable to read objective function\n");
1549 throw CoinError(str, "read_monom_obj", "CoinLpIO", __FILE__, __LINE__);
1550 }
1551
1552 if (buff[strlen(buff) - 1] == ':') {
1553 buff[strlen(buff) - 1] = '\0';
1554
1555 #ifdef LPIO_DEBUG
1556 printf("CoinLpIO: read_monom_obj(): obj_name: %s\n", buff);
1557 #endif
1558
1559 if (*num_objectives == MAX_OBJECTIVES) {
1560 char str[8192];
1561 sprintf(str, "### ERROR: Too many objective functions.\n");
1562 sprintf(str, "### ERROR: Change MAX_OBJECTIVES to larger number.\n");
1563 throw CoinError(str, "read_monom_obj", "CoinLpIO", __FILE__, __LINE__);
1564 }
1565 obj_name[*num_objectives] = CoinStrdup(buff);
1566 obj_starts[(*num_objectives)++] = *cnt;
1567 return (0);
1568 }
1569
1570 if (*num_objectives == 0) {
1571 obj_starts[(*num_objectives)++] = *cnt;
1572 }
1573
1574 read_st = is_subject_to(buff);
1575
1576 #ifdef LPIO_DEBUG
1577 printf("read_monom_obj: first buff: (%s)\n", buff);
1578 #endif
1579
1580 if (read_st > 0) {
1581 return (read_st);
1582 }
1583
1584 start = buff;
1585 mult = 1;
1586 if (buff[0] == '+') {
1587 mult = 1;
1588 if (strlen(buff) == 1) {
1589 fscanfLpIO(buff);
1590 start = buff;
1591 } else {
1592 start = &(buff[1]);
1593 }
1594 }
1595
1596 if (buff[0] == '-') {
1597 mult = -1;
1598 if (strlen(buff) == 1) {
1599 fscanfLpIO(buff);
1600 start = buff;
1601 } else {
1602 start = &(buff[1]);
1603 }
1604 }
1605
1606 if (first_is_number(start)) {
1607 coeff[*cnt] = atof(start);
1608 sprintf(loc_name, "aa");
1609 fscanfLpIO(loc_name);
1610 } else {
1611 coeff[*cnt] = 1;
1612 strcpy(loc_name, start);
1613 }
1614
1615 read_st = is_subject_to(loc_name);
1616
1617 #ifdef LPIO_DEBUG
1618 printf("read_monom_obj: second buff: (%s)\n", buff);
1619 #endif
1620
1621 if (read_st > 0) {
1622 setObjectiveOffset(mult * coeff[*cnt]);
1623
1624 #ifdef LPIO_DEBUG
1625 printf("read_monom_obj: objectiveOffset: %f\n", objectiveOffset_);
1626 #endif
1627
1628 return (read_st);
1629 }
1630
1631 coeff[*cnt] *= mult;
1632 name[*cnt] = CoinStrdup(loc_name);
1633
1634 #ifdef LPIO_DEBUG
1635 printf("read_monom_obj: (%f) (%s)\n", coeff[*cnt], name[*cnt]);
1636 #endif
1637
1638 (*cnt)++;
1639
1640 return (read_st);
1641 } /* read_monom_obj */
1642
1643 /*************************************************************************/
read_monom_row(char * start_str,double * coeff,char ** name,int cnt_coeff) const1644 int CoinLpIO::read_monom_row(char *start_str,
1645 double *coeff, char **name,
1646 int cnt_coeff) const
1647 {
1648
1649 double mult;
1650 char buff[1024], loc_name[1024], *start;
1651 int read_sense = -1;
1652
1653 sprintf(buff, "%s", start_str);
1654 read_sense = is_sense(buff);
1655 if (read_sense > -1) {
1656 return (read_sense);
1657 }
1658
1659 start = buff;
1660 mult = 1;
1661 if (buff[0] == '+') {
1662 mult = 1;
1663 if (strlen(buff) == 1) {
1664 fscanfLpIO(buff);
1665 start = buff;
1666 } else {
1667 start = &(buff[1]);
1668 }
1669 }
1670
1671 if (buff[0] == '-') {
1672 mult = -1;
1673 if (strlen(buff) == 1) {
1674 fscanfLpIO(buff);
1675 start = buff;
1676 } else {
1677 start = &(buff[1]);
1678 }
1679 }
1680
1681 if (first_is_number(start)) {
1682 coeff[cnt_coeff] = atof(start);
1683 fscanfLpIO(loc_name);
1684 } else {
1685 coeff[cnt_coeff] = 1;
1686 strcpy(loc_name, start);
1687 }
1688
1689 coeff[cnt_coeff] *= mult;
1690 #ifdef KILL_ZERO_READLP
1691 if (fabs(coeff[cnt_coeff]) > epsilon_)
1692 name[cnt_coeff] = CoinStrdup(loc_name);
1693 else
1694 read_sense = -2; // effectively zero
1695 #else
1696 name[cnt_coeff] = CoinStrdup(loc_name);
1697 #endif
1698
1699 #ifdef LPIO_DEBUG
1700 printf("CoinLpIO: read_monom_row: (%f) (%s)\n",
1701 coeff[cnt_coeff], name[cnt_coeff]);
1702 #endif
1703 return (read_sense);
1704 } /* read_monom_row */
1705
1706 /*************************************************************************/
realloc_coeff(double ** coeff,char *** colNames,int * maxcoeff) const1707 void CoinLpIO::realloc_coeff(double **coeff, char ***colNames,
1708 int *maxcoeff) const
1709 {
1710
1711 *maxcoeff *= 5;
1712
1713 *colNames = reinterpret_cast< char ** >(realloc((*colNames), (*maxcoeff + 1) * sizeof(char *)));
1714 *coeff = reinterpret_cast< double * >(realloc((*coeff), (*maxcoeff + 1) * sizeof(double)));
1715
1716 } /* realloc_coeff */
1717
1718 /*************************************************************************/
realloc_row(char *** rowNames,CoinBigIndex ** start,double ** rhs,double ** rowlow,double ** rowup,int * maxrow) const1719 void CoinLpIO::realloc_row(char ***rowNames, CoinBigIndex **start, double **rhs,
1720 double **rowlow, double **rowup, int *maxrow) const
1721 {
1722
1723 *maxrow *= 5;
1724 *rowNames = reinterpret_cast< char ** >(realloc((*rowNames), (*maxrow + 1) * sizeof(char *)));
1725 *start = reinterpret_cast< CoinBigIndex * >(realloc((*start), (*maxrow + 1) * sizeof(CoinBigIndex)));
1726 *rhs = reinterpret_cast< double * >(realloc((*rhs), (*maxrow + 1) * sizeof(double)));
1727 *rowlow = reinterpret_cast< double * >(realloc((*rowlow), (*maxrow + 1) * sizeof(double)));
1728 *rowup = reinterpret_cast< double * >(realloc((*rowup), (*maxrow + 1) * sizeof(double)));
1729
1730 } /* realloc_row */
1731
1732 /*************************************************************************/
realloc_col(double ** collow,double ** colup,char ** is_int,int * maxcol) const1733 void CoinLpIO::realloc_col(double **collow, double **colup, char **is_int,
1734 int *maxcol) const
1735 {
1736 *maxcol += 100;
1737 *collow = reinterpret_cast< double * >(realloc((*collow), (*maxcol + 1) * sizeof(double)));
1738 *colup = reinterpret_cast< double * >(realloc((*colup), (*maxcol + 1) * sizeof(double)));
1739 *is_int = reinterpret_cast< char * >(realloc((*is_int), (*maxcol + 1) * sizeof(char)));
1740 // clean values
1741 double lp_inf = getInfinity();
1742 for (int i = (*maxcol) - 100; i < *maxcol; i++) {
1743 (*collow)[i] = 0;
1744 (*colup)[i] = lp_inf;
1745 (*is_int)[i] = 0;
1746 }
1747
1748 } /* realloc_col */
1749
1750 /*************************************************************************/
read_row(char * buff,double ** pcoeff,char *** pcolNames,int * cnt_coeff,int * maxcoeff,double * rhs,double * rowlow,double * rowup,int * cnt_row,double inf) const1751 void CoinLpIO::read_row(char *buff,
1752 double **pcoeff, char ***pcolNames,
1753 int *cnt_coeff,
1754 int *maxcoeff,
1755 double *rhs, double *rowlow, double *rowup,
1756 int *cnt_row, double inf) const
1757 {
1758
1759 int read_sense = -1;
1760 char start_str[1024];
1761
1762 sprintf(start_str, "%s", buff);
1763
1764 while (read_sense < 0) {
1765
1766 if ((*cnt_coeff) == (*maxcoeff)) {
1767 realloc_coeff(pcoeff, pcolNames, maxcoeff);
1768 }
1769 read_sense = read_monom_row(start_str,
1770 *pcoeff, *pcolNames, *cnt_coeff);
1771 #ifdef KILL_ZERO_READLP
1772 if (read_sense != -2) // see if zero
1773 #endif
1774 (*cnt_coeff)++;
1775
1776 int x = fscanfLpIO(start_str);
1777
1778 if (x <= 0) {
1779 char str[8192];
1780 sprintf(str, "### ERROR: Unable to read row monomial\n");
1781 throw CoinError(str, "read_monom_row", "CoinLpIO", __FILE__, __LINE__);
1782 }
1783 }
1784 (*cnt_coeff)--;
1785
1786 rhs[*cnt_row] = atof(start_str);
1787
1788 switch (read_sense) {
1789 case 0:
1790 rowlow[*cnt_row] = -inf;
1791 rowup[*cnt_row] = rhs[*cnt_row];
1792 break;
1793 case 1:
1794 rowlow[*cnt_row] = rhs[*cnt_row];
1795 rowup[*cnt_row] = rhs[*cnt_row];
1796 break;
1797 case 2:
1798 rowlow[*cnt_row] = rhs[*cnt_row];
1799 rowup[*cnt_row] = inf;
1800 break;
1801 default:
1802 break;
1803 }
1804 (*cnt_row)++;
1805
1806 } /* read_row */
1807
1808 /*************************************************************************/
is_keyword(const char * buff) const1809 int CoinLpIO::is_keyword(const char *buff) const
1810 {
1811
1812 size_t lbuff = strlen(buff);
1813
1814 if (((lbuff == 5) && (CoinStrNCaseCmp(buff, "bound", 5) == 0)) || ((lbuff == 6) && (CoinStrNCaseCmp(buff, "bounds", 6) == 0))) {
1815 return (1);
1816 }
1817
1818 if (((lbuff == 7) && (CoinStrNCaseCmp(buff, "integer", 7) == 0)) || ((lbuff == 8) && (CoinStrNCaseCmp(buff, "integers", 8) == 0))) {
1819 return (2);
1820 }
1821
1822 if (((lbuff == 7) && (CoinStrNCaseCmp(buff, "general", 7) == 0)) || ((lbuff == 8) && (CoinStrNCaseCmp(buff, "generals", 8) == 0))) {
1823 return (2);
1824 }
1825
1826 if (((lbuff == 6) && (CoinStrNCaseCmp(buff, "binary", 6) == 0)) || ((lbuff == 8) && (CoinStrNCaseCmp(buff, "binaries", 8) == 0))) {
1827 return (3);
1828 }
1829
1830 if (((lbuff == 15) && (CoinStrNCaseCmp(buff, "semi-continuous", 15) == 0)) || ((lbuff == 4) && (CoinStrNCaseCmp(buff, "semi", 4) == 0)) || ((lbuff == 5) && (CoinStrNCaseCmp(buff, "semis", 5) == 0))) {
1831 return (4);
1832 }
1833
1834 if ((lbuff == 3) && (CoinStrNCaseCmp(buff, "sos", 3) == 0)) {
1835 return (5);
1836 }
1837
1838 if ((lbuff == 3) && (CoinStrNCaseCmp(buff, "end", 3) == 0)) {
1839 return (6);
1840 }
1841
1842 return (0);
1843
1844 } /* is_keyword */
1845
1846 /*************************************************************************/
readLp(const char * filename,const double epsilon)1847 void CoinLpIO::readLp(const char *filename, const double epsilon)
1848 {
1849 setEpsilon(epsilon);
1850 readLp(filename);
1851 }
1852
1853 /*************************************************************************/
readLp(const char * filename)1854 void CoinLpIO::readLp(const char *filename)
1855 {
1856 delete input_;
1857 input_ = NULL;
1858 bool readable = false;
1859 // see if just .lp
1860 int length = strlen(filename);
1861 if ((length > 3 && !strncmp(filename + length - 3, ".lp", 3))) {
1862 FILE *fp = fopen(filename, "r");
1863 if (fp) {
1864 readable = true;
1865 input_ = new CoinPlainFileInput(fp);
1866 }
1867 } else if (strstr(filename, ".lp")) {
1868 std::string fname(filename);
1869 readable = fileCoinReadable(fname);
1870 if (readable)
1871 input_ = CoinFileInput::create(fname);
1872 }
1873 if (!readable) {
1874 char str[8192];
1875 sprintf(str, "### ERROR: Unable to open file %s for reading\n", filename);
1876 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
1877 }
1878 readLp();
1879 }
1880
1881 /*************************************************************************/
readLp(FILE * fp,const double epsilon)1882 void CoinLpIO::readLp(FILE *fp, const double epsilon)
1883 {
1884 setEpsilon(epsilon);
1885 readLp(fp);
1886 }
1887
1888 /*************************************************************************/
readLp(FILE * fp)1889 void CoinLpIO::readLp(FILE *fp)
1890 {
1891 delete input_;
1892 input_ = new CoinPlainFileInput(fp);
1893 readLp();
1894 }
1895 /*************************************************************************/
readLp()1896 void CoinLpIO::readLp()
1897 {
1898
1899 int maxrow = 1000;
1900 int maxcoeff = 40000;
1901 double lp_eps = getEpsilon();
1902 double lp_inf = getInfinity();
1903
1904 char buff[1024];
1905 bufferPosition_ = 0;
1906 bufferLength_ = 0;
1907 eofFound_ = false;
1908
1909 int objsense, cnt_coeff = 0, cnt_row = 0, cnt_obj = 0;
1910 int num_objectives = 0;
1911 char *objName[MAX_OBJECTIVES] = { NULL, NULL };
1912 int obj_starts[MAX_OBJECTIVES + 1];
1913 char **colNames = reinterpret_cast< char ** >(malloc((maxcoeff + 1) * sizeof(char *)));
1914 double *coeff = reinterpret_cast< double * >(malloc((maxcoeff + 1) * sizeof(double)));
1915 char **rowNames = reinterpret_cast< char ** >(malloc((maxrow + MAX_OBJECTIVES) * sizeof(char *)));
1916 CoinBigIndex *start = reinterpret_cast< CoinBigIndex * >(malloc((maxrow + MAX_OBJECTIVES) * sizeof(CoinBigIndex)));
1917 double *rhs = reinterpret_cast< double * >(malloc((maxrow + 1) * sizeof(double)));
1918 double *rowlow = reinterpret_cast< double * >(malloc((maxrow + 1) * sizeof(double)));
1919 double *rowup = reinterpret_cast< double * >(malloc((maxrow + 1) * sizeof(double)));
1920
1921 int i;
1922
1923 objsense = find_obj();
1924
1925 int read_st = 0;
1926 while (!read_st) {
1927 read_st = read_monom_obj(coeff, colNames, &cnt_obj, objName, &num_objectives, obj_starts);
1928
1929 if (cnt_obj == maxcoeff) {
1930 realloc_coeff(&coeff, &colNames, &maxcoeff);
1931 }
1932 }
1933
1934 obj_starts[num_objectives] = cnt_obj;
1935 start[0] = cnt_obj;
1936 cnt_coeff = cnt_obj;
1937
1938 if (read_st == 2) {
1939 int x = fscanfLpIO(buff);
1940 if (x <= 0)
1941 throw("bad fscanf");
1942 size_t lbuff = strlen(buff);
1943
1944 if ((lbuff != 2) || (CoinStrNCaseCmp(buff, "to", 2) != 0)) {
1945 char str[8192];
1946 sprintf(str, "### ERROR: Can not locate keyword 'Subject To'\n");
1947 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
1948 }
1949 }
1950
1951 fscanfLpIO(buff);
1952
1953 while (!is_keyword(buff)) {
1954 if (buff[strlen(buff) - 1] == ':') {
1955 buff[strlen(buff) - 1] = '\0';
1956
1957 #ifdef LPIO_DEBUG
1958 printf("CoinLpIO::readLp(): rowName[%d]: %s\n", cnt_row, buff);
1959 #endif
1960
1961 rowNames[cnt_row] = CoinStrdup(buff);
1962 fscanfLpIO(buff);
1963 } else {
1964 char rname[15];
1965 sprintf(rname, "cons%d", cnt_row);
1966 rowNames[cnt_row] = CoinStrdup(rname);
1967 }
1968 read_row(buff,
1969 &coeff, &colNames, &cnt_coeff, &maxcoeff, rhs, rowlow, rowup,
1970 &cnt_row, lp_inf);
1971 fscanfLpIO(buff);
1972 start[cnt_row] = cnt_coeff;
1973
1974 if (cnt_row == maxrow) {
1975 realloc_row(&rowNames, &start, &rhs, &rowlow, &rowup, &maxrow);
1976 }
1977 }
1978
1979 numberRows_ = cnt_row;
1980
1981 stopHash(1);
1982 startHash(colNames, cnt_coeff, 1);
1983
1984 COINColumnIndex icol;
1985 int read_sense1, read_sense2;
1986 double bnd1 = 0, bnd2 = 0;
1987
1988 int maxcol = numberHash_[1] + 100;
1989
1990 double *collow = reinterpret_cast< double * >(malloc((maxcol + 1) * sizeof(double)));
1991 double *colup = reinterpret_cast< double * >(malloc((maxcol + 1) * sizeof(double)));
1992 char *is_int = reinterpret_cast< char * >(malloc((maxcol + 1) * sizeof(char)));
1993 int has_int = 0;
1994
1995 for (i = 0; i < maxcol; i++) {
1996 collow[i] = 0;
1997 colup[i] = lp_inf;
1998 is_int[i] = 0;
1999 }
2000
2001 int done = 0;
2002
2003 while (!done) {
2004 switch (is_keyword(buff)) {
2005
2006 case 1: /* Bounds section */
2007 fscanfLpIO(buff);
2008
2009 while (is_keyword(buff) == 0) {
2010
2011 read_sense1 = -1;
2012 read_sense2 = -1;
2013 int mult = 1;
2014 char *start_str = buff;
2015
2016 if (buff[0] == '-' || buff[0] == '+') {
2017 mult = (buff[0] == '-') ? -1 : +1;
2018 if (strlen(buff) == 1) {
2019 fscanfLpIO(buff);
2020 start_str = buff;
2021 } else {
2022 start_str = &(buff[1]);
2023 }
2024 }
2025
2026 int scan_sense = 0;
2027 if (first_is_number(start_str)) {
2028 bnd1 = mult * atof(start_str);
2029 scan_sense = 1;
2030 } else {
2031 if (is_inf(start_str)) {
2032 bnd1 = mult * lp_inf;
2033 scan_sense = 1;
2034 }
2035 }
2036 if (scan_sense) {
2037 fscanfLpIO(buff);
2038 read_sense1 = is_sense(buff);
2039 if (read_sense1 < 0) {
2040 char str[8192];
2041 sprintf(str, "### ERROR: Bounds; expect a sense, get: %s\n", buff);
2042 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
2043 }
2044 fscanfLpIO(buff);
2045 }
2046
2047 icol = findHash(buff, 1);
2048 if (icol < 0) {
2049 char printBuffer[512];
2050 sprintf(printBuffer, "### CoinLpIO::readLp(): Variable %s does not appear in objective function or constraints", buff);
2051 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
2052 << CoinMessageEol;
2053 insertHash(buff, 1);
2054 icol = findHash(buff, 1);
2055 if (icol == maxcol) {
2056 realloc_col(&collow, &colup, &is_int, &maxcol);
2057 }
2058 }
2059
2060 fscanfLpIO(buff);
2061 if (is_free(buff)) {
2062 collow[icol] = -lp_inf;
2063 fscanfLpIO(buff);
2064 } else {
2065 read_sense2 = is_sense(buff);
2066 if (read_sense2 > -1) {
2067 fscanfLpIO(buff);
2068 mult = 1;
2069 start_str = buff;
2070
2071 if (buff[0] == '-' || buff[0] == '+') {
2072 mult = (buff[0] == '-') ? -1 : +1;
2073 if (strlen(buff) == 1) {
2074 fscanfLpIO(buff);
2075 start_str = buff;
2076 } else {
2077 start_str = &(buff[1]);
2078 }
2079 }
2080 if (first_is_number(start_str)) {
2081 bnd2 = mult * atof(start_str);
2082 fscanfLpIO(buff);
2083 } else {
2084 if (is_inf(start_str)) {
2085 bnd2 = mult * lp_inf;
2086 fscanfLpIO(buff);
2087 } else {
2088 char str[8192];
2089 sprintf(str, "### ERROR: Bounds; expect a number, get: %s\n",
2090 buff);
2091 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
2092 }
2093 }
2094 }
2095
2096 if ((read_sense1 > -1) && (read_sense2 > -1)) {
2097 if (read_sense1 != read_sense2) {
2098 char str[8192];
2099 sprintf(str, "### ERROR: Bounds; variable: %s read_sense1: %d read_sense2: %d\n",
2100 buff, read_sense1, read_sense2);
2101 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
2102 } else {
2103 if (read_sense1 == 1) {
2104 if (fabs(bnd1 - bnd2) > lp_eps) {
2105 char str[8192];
2106 sprintf(str, "### ERROR: Bounds; variable: %s read_sense1: %d read_sense2: %d bnd1: %f bnd2: %f\n",
2107 buff, read_sense1, read_sense2, bnd1, bnd2);
2108 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
2109 }
2110 collow[icol] = bnd1;
2111 colup[icol] = bnd1;
2112 }
2113 if (read_sense1 == 0) {
2114 collow[icol] = bnd1;
2115 colup[icol] = bnd2;
2116 }
2117 if (read_sense1 == 2) {
2118 colup[icol] = bnd1;
2119 collow[icol] = bnd2;
2120 }
2121 }
2122 } else {
2123 if (read_sense1 > -1) {
2124 switch (read_sense1) {
2125 case 0:
2126 collow[icol] = bnd1;
2127 break;
2128 case 1:
2129 collow[icol] = bnd1;
2130 colup[icol] = bnd1;
2131 break;
2132 case 2:
2133 colup[icol] = bnd1;
2134 break;
2135 }
2136 }
2137 if (read_sense2 > -1) {
2138 switch (read_sense2) {
2139 case 0:
2140 colup[icol] = bnd2;
2141 break;
2142 case 1:
2143 collow[icol] = bnd2;
2144 colup[icol] = bnd2;
2145 break;
2146 case 2:
2147 collow[icol] = bnd2;
2148 break;
2149 }
2150 }
2151 }
2152 }
2153 }
2154 break;
2155
2156 case 2: /* Integers/Generals section */
2157
2158 fscanfLpIO(buff);
2159
2160 while (is_keyword(buff) == 0) {
2161
2162 icol = findHash(buff, 1);
2163
2164 #ifdef LPIO_DEBUG
2165 printf("CoinLpIO::readLp(): Integer: colname: (%s) icol: %d\n",
2166 buff, icol);
2167 #endif
2168
2169 if (icol < 0) {
2170 char printBuffer[512];
2171 sprintf(printBuffer, "### CoinLpIO::readLp(): Integer variable %s does not appear in objective function or constraints", buff);
2172 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
2173 << CoinMessageEol;
2174 insertHash(buff, 1);
2175 icol = findHash(buff, 1);
2176 if (icol == maxcol) {
2177 realloc_col(&collow, &colup, &is_int, &maxcol);
2178 }
2179
2180 #ifdef LPIO_DEBUG
2181 printf("CoinLpIO::readLp(): Integer: colname: (%s) icol: %d\n",
2182 buff, icol);
2183 #endif
2184 }
2185 if (is_int[icol] == 3)
2186 is_int[icol] = 4;
2187 else
2188 is_int[icol] = 1;
2189 has_int = 1;
2190 fscanfLpIO(buff);
2191 };
2192 break;
2193
2194 case 3: /* Binaries section */
2195
2196 fscanfLpIO(buff);
2197
2198 while (is_keyword(buff) == 0) {
2199
2200 icol = findHash(buff, 1);
2201
2202 #ifdef LPIO_DEBUG
2203 printf("CoinLpIO::readLp(): binary: colname: (%s) icol: %d\n",
2204 buff, icol);
2205 #endif
2206
2207 if (icol < 0) {
2208 char printBuffer[512];
2209 sprintf(printBuffer, "### CoinLpIO::readLp(): Binary variable %s does not appear in objective function or constraints", buff);
2210 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
2211 << CoinMessageEol;
2212 insertHash(buff, 1);
2213 icol = findHash(buff, 1);
2214 if (icol == maxcol) {
2215 realloc_col(&collow, &colup, &is_int, &maxcol);
2216 }
2217 #ifdef LPIO_DEBUG
2218 printf("CoinLpIO::readLp(): binary: colname: (%s) icol: %d\n",
2219 buff, icol);
2220 #endif
2221 }
2222
2223 is_int[icol] = 1;
2224 has_int = 1;
2225 if (collow[icol] < 0) {
2226 collow[icol] = 0;
2227 }
2228 if (colup[icol] > 1) {
2229 colup[icol] = 1;
2230 }
2231 fscanfLpIO(buff);
2232 }
2233 break;
2234 case 4: /* Semis section */
2235
2236 fscanfLpIO(buff);
2237
2238 while (is_keyword(buff) == 0) {
2239
2240 icol = findHash(buff, 1);
2241
2242 #ifdef LPIO_DEBUG
2243 printf("CoinLpIO::readLp(): Semi: colname: (%s) icol: %d\n",
2244 buff, icol);
2245 #endif
2246
2247 if (icol < 0) {
2248 char printBuffer[512];
2249 sprintf(printBuffer, "### CoinLpIO::readLp(): Semi-continuous variable %s does not appear in objective function or constraints", buff);
2250 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
2251 << CoinMessageEol;
2252 insertHash(buff, 1);
2253 icol = findHash(buff, 1);
2254 if (icol == maxcol) {
2255 realloc_col(&collow, &colup, &is_int, &maxcol);
2256 }
2257
2258 #ifdef LPIO_DEBUG
2259 printf("CoinLpIO::readLp(): Semi-continuous: colname: (%s) icol: %d\n",
2260 buff, icol);
2261 #endif
2262 }
2263 if (is_int[icol] == 1)
2264 is_int[icol] = 4;
2265 else
2266 is_int[icol] = 3;
2267 has_int = 1;
2268 fscanfLpIO(buff);
2269 };
2270 break;
2271
2272 case 5: /* sos section */
2273 {
2274 numberSets_ = 0;
2275 int maxSets = 10;
2276 CoinSet **set = new CoinSet *[maxSets];
2277 int maxEntries = 100;
2278 double *weights = new double[maxEntries];
2279 int *which = new int[maxEntries];
2280 char printBuffer[512];
2281 int numberBad = 0;
2282 bool maybeSetName;
2283 fscanfLpIO(buff);
2284 while (true) {
2285 int numberEntries = 0;
2286 int setType = -1;
2287 int goodLine = 2;
2288 bool endLine = false;
2289 bool gotStart = false;
2290 maybeSetName = false;
2291 while (!endLine) {
2292 if (is_keyword(buff) == 0) {
2293 // see if ::
2294 char *next = strstr(buff, "::");
2295 if (!gotStart) {
2296 if (!next) {
2297 // OK first time - may be name of set
2298 if (goodLine == 2) {
2299 int length = strlen(buff);
2300 if (buff[length - 1] == ':') {
2301 goodLine = 1;
2302 // merge to get rid of space
2303 char temp[200];
2304 strcpy(temp, buff);
2305 fscanfLpIO(buff); // try again
2306 strcat(temp, buff);
2307 strcpy(buff, temp);
2308 if (maybeSetName) {
2309 // get rid of error
2310 numberBad--;
2311 maybeSetName = false;
2312 }
2313 continue;
2314 } else {
2315 goodLine = 0;
2316 }
2317 } else {
2318 goodLine = 0;
2319 }
2320 } else {
2321 // check nothing or set name
2322 if (strchr(buff, ':') < next || next == buff + 2) {
2323 // be lazy and assume set name
2324 // get type
2325 next -= 2;
2326 if (next >= buff && (!strncmp(next, "S1::", 4) || !strncmp(next, "S2::", 4))) {
2327 setType = next[1] - '0';
2328 gotStart = true;
2329 } else {
2330 // error
2331 goodLine = 0;
2332 }
2333 } else {
2334 goodLine = 0;
2335 }
2336 }
2337 } else if (next) {
2338 // end of set
2339 endLine = true;
2340 }
2341 } else {
2342 endLine = true;
2343 }
2344 if (!goodLine) {
2345 endLine = true;
2346 }
2347 while (!endLine) {
2348 fscanfLpIO(buff);
2349 if (is_keyword(buff) == 0 && !strstr(buff, "::")) {
2350 // expect pair
2351 char *start_str = buff;
2352 char *next = strchr(start_str, ':');
2353 if (!next) {
2354 endLine = true;
2355 goodLine = 0;
2356 } else {
2357 *next = '\0';
2358 int iColumn = columnIndex(start_str);
2359 *next = ':';
2360 if (iColumn >= 0) {
2361 int length = strlen(next + 1);
2362 if (!length) {
2363 // assume user put in spaces
2364 fscanfLpIO(buff);
2365 if (is_keyword(buff) != 0 || strstr(buff, "::")) {
2366 goodLine = 0;
2367 } else {
2368 next = buff - 1;
2369 }
2370 }
2371 double value = atof(next + 1);
2372 if (numberEntries == maxEntries) {
2373 maxEntries = 2 * maxEntries;
2374 double *tempD = new double[maxEntries];
2375 int *tempI = new int[maxEntries];
2376 memcpy(tempD, weights, numberEntries * sizeof(double));
2377 memcpy(tempI, which, numberEntries * sizeof(int));
2378 delete[] weights;
2379 weights = tempD;
2380 delete[] which;
2381 which = tempI;
2382 }
2383 weights[numberEntries] = value;
2384 which[numberEntries++] = iColumn;
2385 } else {
2386 // no match - assume start of next set
2387 if (!numberBad) {
2388 sprintf(printBuffer, "### CoinLpIO::readLp(): Variable %s not found or no weight",
2389 buff);
2390 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
2391 << CoinMessageEol;
2392 sprintf(printBuffer,
2393 "Assuming next set name - consider no set names or use setnn:S1:: (no spaces)");
2394 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
2395 << CoinMessageEol;
2396 maybeSetName = true;
2397 }
2398 numberBad++;
2399 endLine = true;
2400 }
2401 }
2402 } else {
2403 endLine = true;
2404 }
2405 }
2406 if (!goodLine) {
2407 // print bad line
2408 setType = 3;
2409 sprintf(printBuffer, "### CoinLpIO::readLp(): bad SOS item %s", buff);
2410 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
2411 << CoinMessageEol;
2412 numberBad++;
2413 endLine = true;
2414 break;
2415 }
2416 }
2417 if (setType == 1 || setType == 2) {
2418 if (!numberEntries) {
2419 // empty set - error
2420 sprintf(printBuffer, "### CoinLpIO::readLp(): set %d is empty", numberSets_);
2421 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
2422 << CoinMessageEol;
2423 } else {
2424 CoinSort_2(weights, weights + numberEntries, which);
2425 double last = weights[0];
2426 for (int i = 1; i < numberEntries; i++) {
2427 if (fabs(last - weights[i]) < 1.0e-12) {
2428 setType = 3;
2429 break;
2430 }
2431 }
2432 if (setType != 3) {
2433 if (numberSets_ == maxSets) {
2434 maxSets *= 2;
2435 CoinSet **temp = new CoinSet *[maxSets];
2436 memcpy(temp, set, numberSets_ * sizeof(CoinSet *));
2437 delete[] set;
2438 set = temp;
2439 }
2440 CoinSosSet *newSet = new CoinSosSet(numberEntries, which, weights, setType);
2441 set[numberSets_++] = newSet;
2442 } else {
2443 sprintf(printBuffer, "### CoinLpIO::readLp(): set %d has duplicate weights",
2444 numberSets_);
2445 handler_->message(COIN_GENERAL_WARNING, messages_) << printBuffer
2446 << CoinMessageEol;
2447 }
2448 }
2449 }
2450 if (is_keyword(buff) || (numberBad && !maybeSetName))
2451 break; // end
2452 }
2453 delete[] weights;
2454 delete[] which;
2455 if (numberSets_) {
2456 set_ = new CoinSet *[numberSets_];
2457 memcpy(set_, set, numberSets_ * sizeof(CoinSet *));
2458 delete[] set;
2459 }
2460 } break;
2461
2462 case 6:
2463 done = 1;
2464 break;
2465
2466 default:
2467 char str[8192];
2468 sprintf(str, "### ERROR: Lost while reading: (%s)\n", buff);
2469 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
2470 break;
2471 }
2472 }
2473
2474 #ifdef LPIO_DEBUG
2475 printf("CoinLpIO::readLp(): Done with reading the Lp file\n");
2476 #endif
2477
2478 int *ind = reinterpret_cast< int * >(malloc((maxcoeff + 1) * sizeof(int)));
2479
2480 for (i = 0; i < cnt_coeff; i++) {
2481 ind[i] = findHash(colNames[i], 1);
2482
2483 #ifdef LPIO_DEBUG
2484 printf("CoinLpIO::readLp(): name[%d]: (%s) ind: %d\n",
2485 i, colNames[i], ind[i]);
2486 #endif
2487
2488 if (ind[i] < 0) {
2489 char str[8192];
2490 sprintf(str, "### ERROR: Hash table: %s not found\n", colNames[i]);
2491 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
2492 }
2493 }
2494
2495 numberColumns_ = numberHash_[1];
2496 numberElements_ = cnt_coeff - start[0];
2497
2498 double *obj[MAX_OBJECTIVES];
2499 // Check for duplicates - first in objectives
2500 int * whichColumn = new int [numberColumns_];
2501 char * inRow = new char[numberColumns_];
2502 memset(inRow,0,numberColumns_);
2503 int numberDuplicates = 0;
2504
2505 for (int j = 0; j < num_objectives; j++) {
2506 obj[j] = reinterpret_cast< double * >(malloc(numberColumns_ * sizeof(double)));
2507 memset(obj[j], 0, numberColumns_ * sizeof(double));
2508
2509 for (i = obj_starts[j]; i < obj_starts[j + 1]; i++) {
2510 icol = findHash(colNames[i], 1);
2511 if (icol < 0) {
2512 char str[8192];
2513 sprintf(str, "### ERROR: Hash table: %s (obj) not found\n", colNames[i]);
2514 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
2515 }
2516 if (!inRow[icol])
2517 inRow[icol]=1;
2518 else
2519 numberDuplicates++;
2520 obj[j][icol] += objsense * coeff[i];
2521 }
2522 memset(inRow,0,numberColumns_);
2523 }
2524 if (numberDuplicates) {
2525 char str[8192];
2526 sprintf(str, "### ERROR: %d duplicates in objective\n",
2527 numberDuplicates);
2528 handler_->message(COIN_GENERAL_INFO, messages_) << str
2529 << CoinMessageEol;
2530 }
2531
2532 if (objsense == -1) {
2533 handler_->message(COIN_GENERAL_INFO, messages_) << " CoinLpIO::readLp(): Maximization problem reformulated as minimization"
2534 << CoinMessageEol;
2535 for (int j = 0; j < num_objectives_; j++) {
2536 objectiveOffset_[j] = -objectiveOffset_[j];
2537 }
2538 wasMaximization_ = true;
2539 }
2540
2541
2542 for (i = 0; i < cnt_row + 1; i++) {
2543 start[i] -= cnt_obj;
2544 }
2545 // Check for duplicates
2546 for (int iRow = 0;iRow<numberRows_;iRow++) {
2547 CoinBigIndex startRow = start[iRow]+cnt_obj;
2548 CoinBigIndex endRow = start[iRow+1]+cnt_obj;
2549 for (CoinBigIndex j=startRow;j<endRow;j++) {
2550 int iColumn = ind[j];
2551 if (!inRow[iColumn])
2552 inRow[iColumn]=1;
2553 else
2554 numberDuplicates ++;
2555 }
2556 for (CoinBigIndex j=startRow;j<endRow;j++) {
2557 int iColumn = ind[j];
2558 inRow[iColumn] = 0;
2559 }
2560 }
2561 delete [] inRow;
2562 delete [] whichColumn;
2563 if (numberDuplicates) {
2564 char str[8192];
2565 sprintf(str, "### ERROR: %d duplicates in objective and matrix\n",
2566 numberDuplicates);
2567 handler_->message(COIN_GENERAL_INFO, messages_) << str
2568 << CoinMessageEol;
2569 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
2570 }
2571 CoinPackedMatrix *matrix = new CoinPackedMatrix(false,
2572 numberColumns_, numberRows_, numberElements_,
2573 &(coeff[cnt_obj]), &(ind[cnt_obj]), start, NULL);
2574
2575 #ifdef LPIO_DEBUG
2576 matrix->dumpMatrix();
2577 #endif
2578 // save sets
2579 CoinSet **saveSet = set_;
2580 int saveNumberSets = numberSets_;
2581 set_ = NULL;
2582 numberSets_ = 0;
2583
2584 setLpDataWithoutRowAndColNames(*matrix, collow, colup,
2585 const_cast< const double ** >(obj),
2586 num_objectives, has_int ? is_int : 0, rowlow, rowup);
2587
2588 set_ = saveSet;
2589 numberSets_ = saveNumberSets;
2590
2591 for (int j = 0; j < num_objectives; j++) {
2592 if (objName[j] == NULL) {
2593 rowNames[cnt_row + j] = CoinStrdup("obj");
2594 } else {
2595 rowNames[cnt_row + j] = CoinStrdup(objName[j]);
2596 }
2597 }
2598 // Hash tables for column names are already set up
2599 setLpDataRowAndColNames(rowNames, NULL);
2600
2601 if (are_invalid_names(names_[1], numberHash_[1], false)) {
2602 setDefaultColNames();
2603 handler_->message(COIN_GENERAL_WARNING, messages_) << "### CoinLpIO::readLp(): Invalid column names\nNow using default column names."
2604 << CoinMessageEol;
2605 }
2606
2607 for (i = 0; i < cnt_coeff; i++) {
2608 free(colNames[i]);
2609 }
2610 free(colNames);
2611
2612 for (i = 0; i < cnt_row + 1; i++) {
2613 free(rowNames[i]);
2614 }
2615 free(rowNames);
2616
2617 for (int j = 0; j < num_objectives; j++) {
2618 free(objName[j]);
2619 }
2620
2621 #ifdef LPIO_DEBUG
2622 writeLp("readlp.xxx");
2623 printf("CoinLpIO::readLp(): read Lp file written in file readlp.xxx\n");
2624 #endif
2625
2626 free(coeff);
2627 free(start);
2628 free(ind);
2629 free(colup);
2630 free(collow);
2631 free(rhs);
2632 free(rowlow);
2633 free(rowup);
2634 free(is_int);
2635 for (int j = 0; j < num_objectives; j++) {
2636 free(obj[j]);
2637 }
2638 delete matrix;
2639
2640 } /* readLp */
2641
2642 /*************************************************************************/
print() const2643 void CoinLpIO::print() const
2644 {
2645
2646 printf("problemName_: %s\n", problemName_);
2647 printf("numberRows_: %d\n", numberRows_);
2648 printf("numberColumns_: %d\n", numberColumns_);
2649
2650 printf("matrixByRows_:\n");
2651 matrixByRow_->dumpMatrix();
2652
2653 int i;
2654 printf("rowlower_:\n");
2655 for (i = 0; i < numberRows_; i++) {
2656 printf("%.5f ", rowlower_[i]);
2657 }
2658 printf("\n");
2659
2660 printf("rowupper_:\n");
2661 for (i = 0; i < numberRows_; i++) {
2662 printf("%.5f ", rowupper_[i]);
2663 }
2664 printf("\n");
2665
2666 printf("collower_:\n");
2667 for (i = 0; i < numberColumns_; i++) {
2668 printf("%.5f ", collower_[i]);
2669 }
2670 printf("\n");
2671
2672 printf("colupper_:\n");
2673 for (i = 0; i < numberColumns_; i++) {
2674 printf("%.5f ", colupper_[i]);
2675 }
2676 printf("\n");
2677
2678 for (int j = 0; j < num_objectives_; j++) {
2679 printf("objective_[%i]:\n", j);
2680 for (i = 0; i < numberColumns_; i++) {
2681 printf("%.5f ", objective_[j][i]);
2682 }
2683 }
2684 printf("\n");
2685
2686 if (integerType_ != NULL) {
2687 printf("integerType_:\n");
2688 for (i = 0; i < numberColumns_; i++) {
2689 printf("%c ", integerType_[i]);
2690 }
2691 } else {
2692 printf("integerType_: NULL\n");
2693 }
2694
2695 printf("\n");
2696 if (fileName_ != NULL) {
2697 printf("fileName_: %s\n", fileName_);
2698 }
2699 printf("infinity_: %.5f\n", infinity_);
2700 } /* print */
2701
2702 /*************************************************************************/
2703 // Hash functions slightly modified from CoinMpsIO.cpp
2704
2705 namespace {
2706 const int mmult[] = {
2707 262139, 259459, 256889, 254291, 251701, 249133, 246709, 244247,
2708 241667, 239179, 236609, 233983, 231289, 228859, 226357, 223829,
2709 221281, 218849, 216319, 213721, 211093, 208673, 206263, 203773,
2710 201233, 198637, 196159, 193603, 191161, 188701, 186149, 183761,
2711 181303, 178873, 176389, 173897, 171469, 169049, 166471, 163871,
2712 161387, 158941, 156437, 153949, 151531, 149159, 146749, 144299,
2713 141709, 139369, 136889, 134591, 132169, 129641, 127343, 124853,
2714 122477, 120163, 117757, 115361, 112979, 110567, 108179, 105727,
2715 103387, 101021, 98639, 96179, 93911, 91583, 89317, 86939, 84521,
2716 82183, 79939, 77587, 75307, 72959, 70793, 68447, 66103
2717 };
compute_hash(const char * name,int maxsiz,int length)2718 int compute_hash(const char *name, int maxsiz, int length)
2719 {
2720
2721 int n = 0;
2722 int j;
2723
2724 const int nEntriesMMult = sizeof(mmult) / sizeof(int);
2725
2726 for (j = 0; j < length; ++j) {
2727 int iname = name[j];
2728
2729 n += mmult[j % nEntriesMMult] * iname;
2730 }
2731 return (abs(n) % maxsiz); /* integer abs */
2732 }
2733 } // end file-local namespace
2734
2735 /************************************************************************/
2736 // startHash. Creates hash list for names
2737 // setup names_[section] with names in the same order as in the parameter,
2738 // but removes duplicates
2739
startHash(char const * const * const names,const COINColumnIndex number,int section)2740 void CoinLpIO::startHash(char const *const *const names,
2741 const COINColumnIndex number, int section)
2742 {
2743 maxHash_[section] = 4 * number;
2744 int maxhash = maxHash_[section];
2745 COINColumnIndex i, ipos, iput;
2746
2747 names_[section] = reinterpret_cast< char ** >(malloc(maxhash * sizeof(char *)));
2748 hash_[section] = new CoinHashLink[maxhash];
2749
2750 CoinHashLink *hashThis = hash_[section];
2751 char **hashNames = names_[section];
2752
2753 for (i = 0; i < maxhash; i++) {
2754 hashThis[i].index = -1;
2755 hashThis[i].next = -1;
2756 }
2757
2758 /*
2759 * Initialize the hash table. Only the index of the first name that
2760 * hashes to a value is entered in the table; subsequent names that
2761 * collide with it are not entered.
2762 */
2763
2764 for (i = 0; i < number; i++) {
2765 const char *thisName = names[i];
2766 int length = CoinStrlenAsInt(thisName);
2767
2768 ipos = compute_hash(thisName, maxhash, length);
2769 if (hashThis[ipos].index == -1) {
2770 hashThis[ipos].index = i; // will be changed below
2771 }
2772 }
2773
2774 /*
2775 * Now take care of the names that collided in the preceding loop,
2776 * by finding some other entry in the table for them.
2777 * Since there are as many entries in the table as there are names,
2778 * there must be room for them.
2779 * Also setting up hashNames.
2780 */
2781
2782 int cnt_distinct = 0;
2783
2784 iput = -1;
2785 for (i = 0; i < number; i++) {
2786 const char *thisName = names[i];
2787 int length = CoinStrlenAsInt(thisName);
2788
2789 ipos = compute_hash(thisName, maxhash, length);
2790
2791 while (1) {
2792 COINColumnIndex j1 = hashThis[ipos].index;
2793
2794 if (j1 == i) {
2795
2796 // first occurence of thisName in the parameter "names"
2797
2798 hashThis[ipos].index = cnt_distinct;
2799 hashNames[cnt_distinct] = CoinStrdup(thisName);
2800 cnt_distinct++;
2801 break;
2802 } else {
2803
2804 #ifdef LPIO_DEBUG
2805 if (j1 > i) {
2806 char str[8192];
2807 sprintf(str, "### ERROR: Hash table: j1: %d i: %d\n", j1, i);
2808 throw CoinError(str, "startHash", "CoinLpIO", __FILE__, __LINE__);
2809 }
2810 #endif
2811
2812 if (strcmp(thisName, hashNames[j1]) == 0) {
2813
2814 // thisName already entered
2815
2816 break;
2817 } else {
2818 // Collision; check if thisName already entered
2819
2820 COINColumnIndex k = hashThis[ipos].next;
2821
2822 if (k == -1) {
2823
2824 // thisName not found; enter it
2825
2826 while (1) {
2827 ++iput;
2828 if (iput > maxhash) {
2829 char str[8192];
2830 sprintf(str, "### ERROR: Hash table: too many names\n");
2831 throw CoinError(str, "startHash", "CoinLpIO", __FILE__, __LINE__);
2832 break;
2833 }
2834 if (hashThis[iput].index == -1) {
2835 break;
2836 }
2837 }
2838 hashThis[ipos].next = iput;
2839 hashThis[iput].index = cnt_distinct;
2840 hashNames[cnt_distinct] = CoinStrdup(thisName);
2841 cnt_distinct++;
2842 break;
2843 } else {
2844 ipos = k;
2845
2846 // continue the check with names in collision
2847 }
2848 }
2849 }
2850 }
2851 }
2852
2853 numberHash_[section] = cnt_distinct;
2854
2855 } /* startHash */
2856
2857 /**************************************************************************/
2858 // stopHash. Deletes hash storage
stopHash(int section)2859 void CoinLpIO::stopHash(int section)
2860 {
2861 freePreviousNames(section);
2862 previous_names_[section] = names_[section];
2863 card_previous_names_[section] = numberHash_[section];
2864
2865 delete[] hash_[section];
2866 hash_[section] = NULL;
2867
2868 maxHash_[section] = 0;
2869 numberHash_[section] = 0;
2870
2871 if (section == 0) {
2872 for (int j = 0; j < num_objectives_; j++) {
2873 if (objName_[j] != NULL) {
2874 free(objName_[j]);
2875 objName_[j] = NULL;
2876 }
2877 }
2878 }
2879 } /* stopHash */
2880
2881 /**********************************************************************/
2882 // findHash. -1 not found
2883 COINColumnIndex
findHash(const char * name,int section) const2884 CoinLpIO::findHash(const char *name, int section) const
2885 {
2886 COINColumnIndex found = -1;
2887
2888 char **names = names_[section];
2889 CoinHashLink *hashThis = hash_[section];
2890 COINColumnIndex maxhash = maxHash_[section];
2891 COINColumnIndex ipos;
2892
2893 /* default if we don't find anything */
2894 if (!maxhash)
2895 return -1;
2896
2897 int length = CoinStrlenAsInt(name);
2898
2899 ipos = compute_hash(name, maxhash, length);
2900 while (1) {
2901 COINColumnIndex j1 = hashThis[ipos].index;
2902
2903 if (j1 >= 0) {
2904 char *thisName2 = names[j1];
2905
2906 if (strcmp(name, thisName2) != 0) {
2907 COINColumnIndex k = hashThis[ipos].next;
2908
2909 if (k != -1)
2910 ipos = k;
2911 else
2912 break;
2913 } else {
2914 found = j1;
2915 break;
2916 }
2917 } else {
2918 found = -1;
2919 break;
2920 }
2921 }
2922 return found;
2923 } /* findHash */
2924
2925 /*********************************************************************/
insertHash(const char * thisName,int section)2926 void CoinLpIO::insertHash(const char *thisName, int section)
2927 {
2928
2929 int number = numberHash_[section];
2930 int maxhash = maxHash_[section];
2931
2932 CoinHashLink *hashThis = hash_[section];
2933 char **hashNames = names_[section];
2934
2935 int iput = -1;
2936 int length = CoinStrlenAsInt(thisName);
2937
2938 int ipos = compute_hash(thisName, maxhash, length);
2939
2940 while (1) {
2941 COINColumnIndex j1 = hashThis[ipos].index;
2942
2943 if (j1 == -1) {
2944 hashThis[ipos].index = number;
2945 break;
2946 } else {
2947 char *thisName2 = hashNames[j1];
2948
2949 if (strcmp(thisName, thisName2) != 0) {
2950 COINColumnIndex k = hashThis[ipos].next;
2951
2952 if (k == -1) {
2953 while (1) {
2954 ++iput;
2955 if (iput == maxhash) {
2956 char str[8192];
2957 sprintf(str, "### ERROR: Hash table: too many names\n");
2958 throw CoinError(str, "insertHash", "CoinLpIO", __FILE__, __LINE__);
2959 break;
2960 }
2961 if (hashThis[iput].index == -1) {
2962 break;
2963 }
2964 }
2965 hashThis[ipos].next = iput;
2966 hashThis[iput].index = number;
2967 break;
2968 } else {
2969 ipos = k;
2970 /* nothing worked - try it again */
2971 }
2972 }
2973 }
2974 }
2975
2976 hashNames[number] = CoinStrdup(thisName);
2977 (numberHash_[section])++;
2978 }
2979 // Pass in Message handler (not deleted at end)
passInMessageHandler(CoinMessageHandler * handler)2980 void CoinLpIO::passInMessageHandler(CoinMessageHandler *handler)
2981 {
2982 if (defaultHandler_)
2983 delete handler_;
2984 defaultHandler_ = false;
2985 handler_ = handler;
2986 }
2987 // Set language
newLanguage(CoinMessages::Language language)2988 void CoinLpIO::newLanguage(CoinMessages::Language language)
2989 {
2990 messages_ = CoinMessage(language);
2991 }
2992
2993 // Get next line into inputBuffer_ (returns number in)
newCardLpIO() const2994 int CoinLpIO::newCardLpIO() const
2995 {
2996 while (bufferPosition_ == bufferLength_) {
2997 // new line
2998 bufferPosition_ = 0;
2999 bufferLength_ = 0;
3000 char *ok = input_->gets(inputBuffer_, 1024);
3001 if (!ok)
3002 return 0;
3003 int length = strlen(inputBuffer_);
3004 // take off blanks or below
3005 if (length && length < 1023) {
3006 length--;
3007 while(length>=0) {
3008 if (inputBuffer_[length]<=' ')
3009 length--;
3010 else
3011 break;
3012 }
3013 // but put back something
3014 inputBuffer_[length+1]='\n';
3015 inputBuffer_[length+2]='\0';
3016 }
3017 // go to single blanks and remove all blanks before :: or :
3018 char *colons = strstr(inputBuffer_, "::");
3019 int nn = 0;
3020 if (colons) {
3021 nn = colons - inputBuffer_;
3022 for (int i = 0; i < nn; i++) {
3023 if (inputBuffer_[i] != ' ')
3024 inputBuffer_[bufferLength_++] = inputBuffer_[i];
3025 }
3026 }
3027 bool gotEol = false;
3028 while (nn < 1024) {
3029 if (inputBuffer_[nn] == ':') {
3030 // take out blank before
3031 if (inputBuffer_[bufferLength_ - 1] == ' ')
3032 bufferLength_--;
3033 }
3034 if (inputBuffer_[nn] == '\t')
3035 inputBuffer_[nn] = ' ';
3036 if (inputBuffer_[nn] == '\0' || inputBuffer_[nn] == '\n' || inputBuffer_[nn] == '\r') {
3037 if (inputBuffer_[nn] == '\n' || inputBuffer_[nn] == '\r')
3038 gotEol = true;
3039 break;
3040 }
3041 if (inputBuffer_[nn] != ' ' || inputBuffer_[nn + 1] != ' ')
3042 inputBuffer_[bufferLength_++] = inputBuffer_[nn];
3043 nn++;
3044 }
3045 if (gotEol) {
3046 //inputBuffer_[bufferLength_]='\n';
3047 inputBuffer_[bufferLength_] = '\0';
3048 }
3049 if (inputBuffer_[0] == ' ')
3050 bufferPosition_++;
3051 if (!gotEol)
3052 bufferLength_ = -bufferLength_;
3053 }
3054 return abs(bufferLength_);
3055 }
3056
3057 // Get next string (returns number in)
fscanfLpIO(char * buff) const3058 int CoinLpIO::fscanfLpIO(char *buff) const
3059 {
3060 assert(input_);
3061 if (bufferPosition_ == bufferLength_) {
3062 int returnCode = newCardLpIO();
3063 if (!returnCode) {
3064 if (eofFound_)
3065 return 0;
3066 eofFound_ = true;
3067 handler_->message(COIN_GENERAL_WARNING, messages_) << "### CoinLpIO::scan_next(): End inserted" << CoinMessageEol;
3068 strcpy(buff, "End");
3069 }
3070 }
3071 char *space = strchr(inputBuffer_ + bufferPosition_, ' ');
3072 int n = 0;
3073 int start = 0;
3074 if (space)
3075 n = space - (inputBuffer_ + bufferPosition_);
3076 if (n == 0) {
3077 if (bufferLength_ >= 0) {
3078 n = bufferLength_ - bufferPosition_;
3079 } else {
3080 // partial line - get more
3081 start = CoinMax(abs(bufferLength_) - bufferPosition_, 0);
3082 memcpy(buff, inputBuffer_ + bufferPosition_, start);
3083 bufferPosition_ = bufferLength_;
3084 int returnCode = newCardLpIO();
3085 if (!returnCode)
3086 return 0;
3087 if (inputBuffer_[0] != ' ') {
3088 space = strchr(inputBuffer_, ' ');
3089 assert(space || bufferLength_ > 0);
3090 if (space)
3091 n = space - (inputBuffer_ + bufferPosition_);
3092 else
3093 n = bufferLength_ - bufferPosition_;
3094 } else {
3095 n = 0;
3096 }
3097 }
3098 }
3099 memcpy(buff + start, inputBuffer_ + bufferPosition_, n);
3100 bufferPosition_ += n;
3101 if (inputBuffer_[bufferPosition_] == ' ')
3102 bufferPosition_++;
3103 buff[start + n] = '\0';
3104 while (is_comment(buff)) {
3105 skip_comment(buff);
3106 int x = fscanfLpIO(buff);
3107 if (x <= 0) {
3108 handler_->message(COIN_GENERAL_WARNING, messages_) << "### CoinLpIO::scan_next(): field expected" << CoinMessageEol;
3109 throw("bad fscanf");
3110 }
3111 }
3112 return n + start;
3113 }
3114
3115 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
3116 */
3117