1/* $Id: CoinLpIO.cpp 1545 2012-07-29 18:35:03Z unxusr $ */
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 "CoinFinite.hpp"
28
29using namespace std;
30
31//#define LPIO_DEBUG
32
33/************************************************************************/
34
35CoinLpIO::CoinLpIO() :
36 problemName_(CoinStrdup("")),
37 defaultHandler_(true),
38 numberRows_(0),
39 numberColumns_(0),
40 numberElements_(0),
41 matrixByColumn_(NULL),
42 matrixByRow_(NULL),
43 rowlower_(NULL),
44 rowupper_(NULL),
45 collower_(NULL),
46 colupper_(NULL),
47 rhs_(NULL),
48 rowrange_(NULL),
49 rowsense_(NULL),
50 objective_(NULL),
51 objectiveOffset_(0),
52 integerType_(NULL),
53 fileName_(NULL),
54 infinity_(COIN_DBL_MAX),
55 epsilon_(1e-5),
56 numberAcross_(10),
57 decimals_(5),
58 objName_(NULL)
59{
60 card_previous_names_[0] = 0;
61 card_previous_names_[1] = 0;
62 previous_names_[0] = NULL;
63 previous_names_[1] = NULL;
64
65 maxHash_[0]=0;
66 numberHash_[0]=0;
67 hash_[0] = NULL;
68 names_[0] = NULL;
69 maxHash_[1] = 0;
70 numberHash_[1] = 0;
71 hash_[1] = NULL;
72 names_[1] = NULL;
73 handler_ = new CoinMessageHandler();
74 messages_ = CoinMessage();
75}
76
77/************************************************************************/
78CoinLpIO::~CoinLpIO() {
79 stopHash(0);
80 stopHash(1);
81 freeAll();
82 if (defaultHandler_) {
83 delete handler_;
84 }
85}
86
87/************************************************************************/
88void
89CoinLpIO::freePreviousNames(const int section) {
90
91 int j;
92
93 if(previous_names_[section] != NULL) {
94 for(j=0; j<card_previous_names_[section]; j++) {
95 free(previous_names_[section][j]);
96 }
97 free(previous_names_[section]);
98 }
99 previous_names_[section] = NULL;
100 card_previous_names_[section] = 0;
101} /* freePreviousNames */
102
103/************************************************************************/
104void
105CoinLpIO::freeAll() {
106
107 delete matrixByColumn_;
108 delete matrixByRow_;
109 free(rowupper_);
110 rowupper_ = NULL;
111 free(rowlower_);
112 rowlower_ = NULL;
113 free(colupper_);
114 colupper_ = NULL;
115 free(collower_);
116 collower_ = NULL;
117 free(rhs_);
118 rhs_ = NULL;
119 free(rowrange_);
120 rowrange_ = NULL;
121 free(rowsense_);
122 rowsense_ = NULL;
123 free(objective_);
124 objective_ = NULL;
125 free(integerType_);
126 integerType_ = NULL;
127 free(problemName_);
128 problemName_ = NULL;
129 free(fileName_);
130 fileName_ = NULL;
131
132 freePreviousNames(0);
133 freePreviousNames(1);
134}
135
136/*************************************************************************/
137const char * CoinLpIO::getProblemName() const
138{
139 return problemName_;
140}
141
142void
143CoinLpIO::setProblemName (const char *name)
144{
145 free(problemName_) ;
146 problemName_ = CoinStrdup(name);
147}
148
149/*************************************************************************/
150int CoinLpIO::getNumCols() const
151{
152 return numberColumns_;
153}
154
155/*************************************************************************/
156int CoinLpIO::getNumRows() const
157{
158 return numberRows_;
159}
160
161/*************************************************************************/
162int CoinLpIO::getNumElements() const
163{
164 return numberElements_;
165}
166
167/*************************************************************************/
168const double * CoinLpIO::getColLower() const
169{
170 return collower_;
171}
172
173/*************************************************************************/
174const double * CoinLpIO::getColUpper() const
175{
176 return colupper_;
177}
178
179/*************************************************************************/
180const double * CoinLpIO::getRowLower() const
181{
182 return rowlower_;
183}
184
185/*************************************************************************/
186const double * CoinLpIO::getRowUpper() const
187{
188 return rowupper_;
189}
190
191/*************************************************************************/
192/** A quick inlined function to convert from lb/ub style constraint
193 definition to sense/rhs/range style */
194inline void
195CoinLpIO::convertBoundToSense(const double lower, const double upper,
196 char& sense, double& right,
197 double& range) const
198{
199 range = 0.0;
200 if (lower > -infinity_) {
201 if (upper < infinity_) {
202 right = upper;
203 if (upper==lower) {
204 sense = 'E';
205 } else {
206 sense = 'R';
207 range = upper - lower;
208 }
209 } else {
210 sense = 'G';
211 right = lower;
212 }
213 } else {
214 if (upper < infinity_) {
215 sense = 'L';
216 right = upper;
217 } else {
218 sense = 'N';
219 right = 0.0;
220 }
221 }
222}
223
224/*************************************************************************/
225 const char * CoinLpIO::getRowSense() const
226{
227 if(rowsense_ == NULL) {
228 int nr=numberRows_;
229 rowsense_ = reinterpret_cast<char *> (malloc(nr*sizeof(char)));
230
231 double dum1,dum2;
232 int i;
233 for(i=0; i<nr; i++) {
234 convertBoundToSense(rowlower_[i],rowupper_[i],rowsense_[i],dum1,dum2);
235 }
236 }
237 return rowsense_;
238}
239
240/*************************************************************************/
241const double * CoinLpIO::getRightHandSide() const
242{
243 if(rhs_==NULL) {
244 int nr=numberRows_;
245 rhs_ = reinterpret_cast<double *> (malloc(nr*sizeof(double)));
246
247 char dum1;
248 double dum2;
249 int i;
250 for (i=0; i<nr; i++) {
251 convertBoundToSense(rowlower_[i],rowupper_[i],dum1,rhs_[i],dum2);
252 }
253 }
254 return rhs_;
255}
256
257/*************************************************************************/
258const double * CoinLpIO::getRowRange() const
259{
260 if (rowrange_ == NULL) {
261 int nr=numberRows_;
262 rowrange_ = reinterpret_cast<double *> (malloc(nr*sizeof(double)));
263 std::fill(rowrange_,rowrange_+nr,0.0);
264
265 char dum1;
266 double dum2;
267 int i;
268 for (i=0; i<nr; i++) {
269 convertBoundToSense(rowlower_[i],rowupper_[i],dum1,dum2,rowrange_[i]);
270 }
271 }
272 return rowrange_;
273}
274
275/*************************************************************************/
276const double * CoinLpIO::getObjCoefficients() const
277{
278 return objective_;
279}
280
281/*************************************************************************/
282const CoinPackedMatrix * CoinLpIO::getMatrixByRow() const
283{
284 return matrixByRow_;
285}
286
287/*************************************************************************/
288const CoinPackedMatrix * CoinLpIO::getMatrixByCol() const
289{
290 if (matrixByColumn_ == NULL && matrixByRow_) {
291 matrixByColumn_ = new CoinPackedMatrix(*matrixByRow_);
292 matrixByColumn_->reverseOrdering();
293 }
294 return matrixByColumn_;
295}
296
297/*************************************************************************/
298const char * CoinLpIO::getObjName() const
299{
300 return objName_;
301}
302
303/*************************************************************************/
304void CoinLpIO::checkRowNames() {
305
306 int i, nrow = getNumRows();
307
308 if(numberHash_[0] != nrow+1) {
309 setDefaultRowNames();
310 handler_->message(COIN_GENERAL_WARNING,messages_)<<
311 "### CoinLpIO::checkRowNames(): non distinct or missing row names or objective function name.\nNow using default row names."
312 <<CoinMessageEol;
313 }
314
315 char const * const * rowNames = getRowNames();
316 const char *rSense = getRowSense();
317 char rName[256];
318
319 // Check that row names and objective function name are all distinct,
320 /// even after adding "_low" to ranged constraint names
321
322 for(i=0; i<nrow; i++) {
323 if(rSense[i] == 'R') {
324 sprintf(rName, "%s_low", rowNames[i]);
325 if(findHash(rName, 0) != -1) {
326 setDefaultRowNames();
327 char printBuffer[512];
328 sprintf(printBuffer,"### CoinLpIO::checkRowNames(): ranged constraint %d hasa 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);
329 handler_->message(COIN_GENERAL_WARNING,messages_)<<printBuffer
330 <<CoinMessageEol;
331 break;
332 }
333 }
334 }
335} /* checkRowNames */
336
337/*************************************************************************/
338void CoinLpIO::checkColNames() {
339
340 int ncol = getNumCols();
341
342 if(numberHash_[1] != ncol) {
343 setDefaultColNames();
344 handler_->message(COIN_GENERAL_WARNING,messages_)<<
345 "### CoinLpIO::checkColNames(): non distinct or missing column names.\nNow using default column names."
346 <<CoinMessageEol;
347 }
348} /* checkColNames */
349
350/*************************************************************************/
351void CoinLpIO::getPreviousRowNames(char const * const * prev,
352 int *card_prev) const
353{
354 *card_prev = card_previous_names_[0];
355 prev = previous_names_[0];
356}
357
358/*************************************************************************/
359void CoinLpIO::getPreviousColNames(char const * const * prev,
360 int *card_prev) const
361{
362 *card_prev = card_previous_names_[1];
363 prev = previous_names_[1];
364}
365
366/*************************************************************************/
367char const * const * CoinLpIO::getRowNames() const
368{
369 return names_[0];
370}
371
372/*************************************************************************/
373char const * const * CoinLpIO::getColNames() const
374{
375 return names_[1];
376}
377
378/*************************************************************************/
379const char * CoinLpIO::rowName(int index) const {
380
381 if((names_[0] != NULL) && (index >= 0) && (index < numberRows_+1)) {
382 return names_[0][index];
383 }
384 else {
385 return NULL;
386 }
387}
388
389/*************************************************************************/
390const char * CoinLpIO::columnName(int index) const {
391
392 if((names_[1] != NULL) && (index >= 0) && (index < numberColumns_)) {
393 return names_[1][index];
394 }
395 else {
396 return NULL;
397 }
398}
399
400/*************************************************************************/
401int CoinLpIO::rowIndex(const char * name) const {
402
403 if (!hash_[0]) {
404 return -1;
405 }
406 return findHash(name , 0);
407}
408
409/*************************************************************************/
410int CoinLpIO::columnIndex(const char * name) const {
411
412 if (!hash_[1]) {
413 return -1;
414 }
415 return findHash(name , 1);
416}
417
418/************************************************************************/
419double CoinLpIO::getInfinity() const
420{
421 return infinity_;
422}
423
424/************************************************************************/
425void CoinLpIO::setInfinity(const double value)
426{
427 if (value >= 1.0e20) {
428 infinity_ = value;
429 }
430 else {
431 char str[8192];
432 sprintf(str,"### ERROR: value: %f\n", value);
433 throw CoinError(str, "setInfinity", "CoinLpIO", __FILE__, __LINE__);
434 }
435}
436
437/************************************************************************/
438double CoinLpIO::getEpsilon() const
439{
440 return epsilon_;
441}
442
443/************************************************************************/
444void CoinLpIO::setEpsilon(const double value)
445{
446 if (value < 0.1) {
447 epsilon_ = value;
448 }
449 else {
450 char str[8192];
451 sprintf(str,"### ERROR: value: %f\n", value);
452 throw CoinError(str, "setEpsilon", "CoinLpIO", __FILE__, __LINE__);
453 }
454}
455
456/************************************************************************/
457int CoinLpIO::getNumberAcross() const
458{
459 return numberAcross_;
460}
461
462/************************************************************************/
463void CoinLpIO::setNumberAcross(const int value)
464{
465 if (value > 0) {
466 numberAcross_ = value;
467 }
468 else {
469 char str[8192];
470 sprintf(str,"### ERROR: value: %d\n", value);
471 throw CoinError(str, "setNumberAcross", "CoinLpIO", __FILE__, __LINE__);
472 }
473}
474
475/************************************************************************/
476int CoinLpIO::getDecimals() const
477{
478 return decimals_;
479}
480
481/************************************************************************/
482void CoinLpIO::setDecimals(const int value)
483{
484 if (value > 0) {
485 decimals_ = value;
486 }
487 else {
488 char str[8192];
489 sprintf(str,"### ERROR: value: %d\n", value);
490 throw CoinError(str, "setDecimals", "CoinLpIO", __FILE__, __LINE__);
491 }
492}
493
494/************************************************************************/
495double CoinLpIO::objectiveOffset() const
496{
497 return objectiveOffset_;
498}
499
500/************************************************************************/
501bool CoinLpIO::isInteger(int columnNumber) const
502{
503 const char * intType = integerType_;
504 if (intType == NULL) return false;
505 assert (columnNumber >= 0 && columnNumber < numberColumns_);
506 if (intType[columnNumber] != 0) return true;
507 return false;
508}
509
510/************************************************************************/
511const char * CoinLpIO::integerColumns() const
512{
513 return integerType_;
514}
515
516/************************************************************************/
517void
518CoinLpIO::setLpDataWithoutRowAndColNames(
519 const CoinPackedMatrix& m,
520 const double *collb, const double *colub,
521 const double *obj_coeff,
522 const char *is_integer,
523 const double *rowlb, const double *rowub) {
524
525 freeAll();
526 problemName_ = CoinStrdup("");
527
528 if (m.isColOrdered()) {
529 matrixByRow_ = new CoinPackedMatrix();
530 matrixByRow_->reverseOrderedCopyOf(m);
531 }
532 else {
533 matrixByRow_ = new CoinPackedMatrix(m);
534 }
535 numberColumns_ = matrixByRow_->getNumCols();
536 numberRows_ = matrixByRow_->getNumRows();
537
538 rowlower_ = reinterpret_cast<double *> (malloc (numberRows_ * sizeof(double)));
539 rowupper_ = reinterpret_cast<double *> (malloc (numberRows_ * sizeof(double)));
540 collower_ = reinterpret_cast<double *> (malloc (numberColumns_ * sizeof(double)));
541 colupper_ = reinterpret_cast<double *> (malloc (numberColumns_ * sizeof(double)));
542 objective_ = reinterpret_cast<double *> (malloc (numberColumns_ * sizeof(double)));
543 std::copy(rowlb, rowlb + numberRows_, rowlower_);
544 std::copy(rowub, rowub + numberRows_, rowupper_);
545 std::copy(collb, collb + numberColumns_, collower_);
546 std::copy(colub, colub + numberColumns_, colupper_);
547 std::copy(obj_coeff, obj_coeff + numberColumns_, objective_);
548
549 if (is_integer) {
550 integerType_ = reinterpret_cast<char *> (malloc (numberColumns_ * sizeof(char)));
551 std::copy(is_integer, is_integer + numberColumns_, integerType_);
552 }
553 else {
554 integerType_ = 0;
555 }
556
557 if((numberHash_[0] > 0) && (numberHash_[0] != numberRows_+1)) {
558 stopHash(0);
559 }
560 if((numberHash_[1] > 0) && (numberHash_[1] != numberColumns_)) {
561 stopHash(1);
562 }
563} /* SetLpDataWithoutRowAndColNames */
564
565/*************************************************************************/
566void CoinLpIO::setDefaultRowNames() {
567
568 int i, nrow = getNumRows();
569 char **defaultRowNames = reinterpret_cast<char **> (malloc ((nrow+1) * sizeof(char *)));
570 char buff[1024];
571
572 for(i=0; i<nrow; i++) {
573 sprintf(buff, "cons%d", i);
574 defaultRowNames[i] = CoinStrdup(buff);
575 }
576 sprintf(buff, "obj");
577 defaultRowNames[nrow] = CoinStrdup(buff);
578
579 stopHash(0);
580 startHash(defaultRowNames, nrow+1, 0);
581 objName_ = CoinStrdup("obj");
582
583 for(i=0; i<nrow+1; i++) {
584 free(defaultRowNames[i]);
585 }
586 free(defaultRowNames);
587
588} /* setDefaultRowNames */
589
590/*************************************************************************/
591void CoinLpIO::setDefaultColNames() {
592
593 int j, ncol = getNumCols();
594 char **defaultColNames = reinterpret_cast<char **> (malloc (ncol * sizeof(char *)));
595 char buff[256];
596
597 for(j=0; j<ncol; j++) {
598 sprintf(buff, "x%d", j);
599 defaultColNames[j] = CoinStrdup(buff);
600 }
601 stopHash(1);
602 startHash(defaultColNames, ncol, 1);
603
604 for(j=0; j<ncol; j++) {
605 free(defaultColNames[j]);
606 }
607 free(defaultColNames);
608
609} /* setDefaultColNames */
610
611/*************************************************************************/
612void CoinLpIO::setLpDataRowAndColNames(char const * const * const rownames,
613 char const * const * const colnames) {
614
615 int nrow = getNumRows();
616 int ncol = getNumCols();
617
618 if(rownames != NULL) {
619 if(are_invalid_names(rownames, nrow+1, true)) {
620 setDefaultRowNames();
621 handler_->message(COIN_GENERAL_WARNING,messages_)<<
622 "### CoinLpIO::setLpDataRowAndColNames(): Invalid row names\nUse getPreviousNames() to get the old row names.\nNow using default row names."
623 <<CoinMessageEol;
624 }
625 else {
626 stopHash(0);
627 startHash(rownames, nrow+1, 0);
628 objName_ = CoinStrdup(rownames[nrow]);
629 checkRowNames();
630 }
631 }
632 else {
633 if(objName_ == NULL) {
634 objName_ = CoinStrdup("obj");
635 }
636 }
637
638 if(colnames != NULL) {
639 if(are_invalid_names(colnames, ncol, false)) {
640 setDefaultColNames();
641 handler_->message(COIN_GENERAL_WARNING,messages_)<<
642 "### CoinLpIO::setLpDataRowAndColNames(): Invalid column names\nNow using default row names."
643 <<CoinMessageEol;
644 }
645 else {
646 stopHash(1);
647 startHash(colnames, ncol, 1);
648 checkColNames();
649 }
650 }
651} /* setLpDataColAndRowNames */
652
653/************************************************************************/
654void
655CoinLpIO::out_coeff(FILE *fp, const double v, const int print_1) const {
656
657 double lp_eps = getEpsilon();
658
659 if(!print_1) {
660 if(fabs(v-1) < lp_eps) {
661 return;
662 }
663 if(fabs(v+1) < lp_eps) {
664 fprintf(fp, " -");
665 return;
666 }
667 }
668
669 double frac = v - floor(v);
670
671 if(frac < lp_eps) {
672 fprintf(fp, " %.0f", floor(v));
673 }
674 else {
675 if(frac > 1 - lp_eps) {
676 fprintf(fp, " %.0f", floor(v+0.5));
677 }
678 else {
679 int decimals = getDecimals();
680 char form[15];
681 sprintf(form, " %%.%df", decimals);
682 fprintf(fp, form, v);
683 }
684 }
685} /* out_coeff */
686
687/************************************************************************/
688int
689CoinLpIO::writeLp(const char *filename, const double epsilon,
690 const int numberAcross, const int decimals,
691 const bool useRowNames) {
692
693 FILE *fp = NULL;
694 fp = fopen(filename,"w");
695 if (!fp) {
696 char str[8192];
697 sprintf(str,"### ERROR: unable to open file %s\n", filename);
698 throw CoinError(str, "writeLP", "CoinLpIO", __FILE__, __LINE__);
699 }
700 int nerr = writeLp(fp, epsilon, numberAcross, decimals, useRowNames);
701 fclose(fp);
702 return(nerr);
703}
704
705/************************************************************************/
706int
707CoinLpIO::writeLp(FILE *fp, const double epsilon,
708 const int numberAcross, const int decimals,
709 const bool useRowNames) {
710
711 setEpsilon(epsilon);
712 setNumberAcross(numberAcross);
713 setDecimals(decimals);
714 return writeLp(fp, useRowNames);
715}
716
717/************************************************************************/
718int
719CoinLpIO::writeLp(const char *filename, const bool useRowNames)
720{
721 FILE *fp = NULL;
722 fp = fopen(filename,"w");
723 if (!fp) {
724 char str[8192];
725 sprintf(str,"### ERROR: unable to open file %s\n", filename);
726 throw CoinError(str, "writeLP", "CoinLpIO", __FILE__, __LINE__);
727 }
728 int nerr = writeLp(fp, useRowNames);
729 fclose(fp);
730 return(nerr);
731}
732
733/************************************************************************/
734int
735CoinLpIO::writeLp(FILE *fp, const bool useRowNames)
736{
737 double lp_eps = getEpsilon();
738 double lp_inf = getInfinity();
739 int numberAcross = getNumberAcross();
740
741 int i, j, cnt_print, loc_row_names = 0, loc_col_names = 0;
742 char **prowNames = NULL, **pcolNames = NULL;
743
744 const int *indices = matrixByRow_->getIndices();
745 const double *elements = matrixByRow_->getElements();
746 int ncol = getNumCols();
747 int nrow = getNumRows();
748 const double *collow = getColLower();
749 const double *colup = getColUpper();
750 const double *rowlow = getRowLower();
751 const double *rowup = getRowUpper();
752 const double *obj = getObjCoefficients();
753 const char *integerType = integerColumns();
754 char const * const * rowNames = getRowNames();
755 char const * const * colNames = getColNames();
756
757 char buff[256];
758
759 if(rowNames == NULL) {
760 loc_row_names = 1;
761 prowNames = reinterpret_cast<char **> (malloc ((nrow+1) * sizeof(char *)));
762
763 for (j=0; j<nrow; j++) {
764 sprintf(buff, "cons%d", j);
765 prowNames[j] = CoinStrdup(buff);
766 }
767 prowNames[nrow] = CoinStrdup("obj");
768 rowNames = prowNames;
769 }
770
771 if(colNames == NULL) {
772 loc_col_names = 1;
773 pcolNames = reinterpret_cast<char **> (malloc (ncol * sizeof(char *)));
774
775 for (j=0; j<ncol; j++) {
776 sprintf(buff, "x%d", j);
777 pcolNames[j] = CoinStrdup(buff);
778 }
779 colNames = pcolNames;
780 }
781
782#ifdef LPIO_DEBUG
783 printf("CoinLpIO::writeLp(): numberRows: %d numberColumns: %d\n",
784 nrow, ncol);
785#endif
786
787 fprintf(fp, "\\Problem name: %s\n\n", getProblemName());
788 fprintf(fp, "Minimize\n");
789
790 if(useRowNames) {
791 fprintf(fp, "%s:", objName_);
792 }
793
794 cnt_print = 0;
795 for(j=0; j<ncol; j++) {
796 if((cnt_print > 0) && (objective_[j] > lp_eps)) {
797 fprintf(fp, " +");
798 }
799 if(fabs(obj[j]) > lp_eps) {
800 out_coeff(fp, obj[j], 0);
801 fprintf(fp, " %s", colNames[j]);
802 cnt_print++;
803 if(cnt_print % numberAcross == 0) {
804 fprintf(fp, "\n");
805 }
806 }
807 }
808
809 if((cnt_print > 0) && (objectiveOffset_ > lp_eps)) {
810 fprintf(fp, " +");
811 }
812 if(fabs(objectiveOffset_) > lp_eps) {
813 out_coeff(fp, objectiveOffset_, 1);
814 cnt_print++;
815 }
816
817 if(cnt_print % numberAcross != 0) {
818 fprintf(fp, "\n");
819 }
820
821 fprintf(fp, "Subject To\n");
822
823 int cnt_out_rows = 0;
824
825 for(i=0; i<nrow; i++) {
826 cnt_print = 0;
827
828 if(useRowNames) {
829 fprintf(fp, "%s: ", rowNames[i]);
830 }
831 cnt_out_rows++;
832
833 for(j=matrixByRow_->getVectorFirst(i);
834 j<matrixByRow_->getVectorLast(i); j++) {
835 if((cnt_print > 0) && (elements[j] > lp_eps)) {
836 fprintf(fp, " +");
837 }
838 if(fabs(elements[j]) > lp_eps) {
839 out_coeff(fp, elements[j], 0);
840 fprintf(fp, " %s", colNames[indices[j]]);
841 cnt_print++;
842 if(cnt_print % numberAcross == 0) {
843 fprintf(fp, "\n");
844 }
845 }
846 }
847
848 if(rowup[i] - rowlow[i] < lp_eps) {
849 fprintf(fp, " =");
850 out_coeff(fp, rowlow[i], 1);
851 fprintf(fp, "\n");
852 }
853 else {
854 if(rowup[i] < lp_inf) {
855 fprintf(fp, " <=");
856 out_coeff(fp, rowup[i], 1);
857 fprintf(fp, "\n");
858
859 if(rowlower_[i] > -lp_inf) {
860
861 cnt_print = 0;
862
863 if(useRowNames) {
864 fprintf(fp, "%s_low:", rowNames[i]);
865 }
866 cnt_out_rows++;
867
868 for(j=matrixByRow_->getVectorFirst(i);
869 j<matrixByRow_->getVectorLast(i); j++) {
870 if((cnt_print>0) && (elements[j] > lp_eps)) {
871 fprintf(fp, " +");
872 }
873 if(fabs(elements[j]) > lp_eps) {
874 out_coeff(fp, elements[j], 0);
875 fprintf(fp, " %s", colNames[indices[j]]);
876 cnt_print++;
877 if(cnt_print % numberAcross == 0) {
878 fprintf(fp, "\n");
879 }
880 }
881 }
882 fprintf(fp, " >=");
883 out_coeff(fp, rowlow[i], 1);
884 fprintf(fp, "\n");
885 }
886
887 }
888 else {
889 fprintf(fp, " >=");
890 out_coeff(fp, rowlow[i], 1);
891 fprintf(fp, "\n");
892 }
893 }
894 }
895
896#ifdef LPIO_DEBUG
897 printf("CoinLpIO::writeLp(): Done with constraints\n");
898#endif
899
900 fprintf(fp, "Bounds\n");
901
902 for(j=0; j<ncol; j++) {
903 if((collow[j] > -lp_inf) && (colup[j] < lp_inf)) {
904 out_coeff(fp, collow[j], 1);
905 fprintf(fp, " <= %s <=", colNames[j]);
906 out_coeff(fp, colup[j], 1);
907 fprintf(fp, "\n");
908 }
909 if((collow[j] == -lp_inf) && (colup[j] < lp_inf)) {
910 fprintf(fp, "%s <=", colNames[j]);
911 out_coeff(fp, colup[j], 1);
912 fprintf(fp, "\n");
913 }
914 if((collow[j] > -lp_inf) && (colup[j] == lp_inf)) {
915 if(fabs(collow[j]) > lp_eps) {
916 out_coeff(fp, collow[j], 1);
917 fprintf(fp, " <= %s\n", colNames[j]);
918 }
919 }
920 if(collow[j] == -lp_inf) {
921 fprintf(fp, " %s Free\n", colNames[j]);
922 }
923 }
924
925#ifdef LPIO_DEBUG
926 printf("CoinLpIO::writeLp(): Done with bounds\n");
927#endif
928
929 if(integerType != NULL) {
930 int first_int = 1;
931 cnt_print = 0;
932 for(j=0; j<ncol; j++) {
933 if(integerType[j] == 1) {
934
935 if(first_int) {
936 fprintf(fp, "Integers\n");
937 first_int = 0;
938 }
939
940 fprintf(fp, "%s ", colNames[j]);
941 cnt_print++;
942 if(cnt_print % numberAcross == 0) {
943 fprintf(fp, "\n");
944 }
945 }
946 }
947
948 if(cnt_print % numberAcross != 0) {
949 fprintf(fp, "\n");
950 }
951 }
952
953#ifdef LPIO_DEBUG
954 printf("CoinLpIO::writeLp(): Done with integers\n");
955#endif
956
957 fprintf(fp, "End\n");
958
959 if(loc_row_names) {
960 for(j=0; j<nrow+1; j++) {
961 free(prowNames[j]);
962 }
963 free(prowNames);
964 }
965
966 if(loc_col_names) {
967 for(j=0; j<ncol; j++) {
968 free(pcolNames[j]);
969 }
970 free(pcolNames);
971 }
972 return 0;
973} /* writeLp */
974
975/*************************************************************************/
976int
977CoinLpIO::find_obj(FILE *fp) const {
978
979 char buff[1024];
980
981 sprintf(buff, "aa");
982 size_t lbuff = strlen(buff);
983
984 while(((lbuff != 8) || (CoinStrNCaseCmp(buff, "minimize", 8) != 0)) &&
985 ((lbuff != 3) || (CoinStrNCaseCmp(buff, "min", 3) != 0)) &&
986 ((lbuff != 8) || (CoinStrNCaseCmp(buff, "maximize", 8) != 0)) &&
987 ((lbuff != 3) || (CoinStrNCaseCmp(buff, "max", 3) != 0))) {
988
989 scan_next(buff, fp);
990 lbuff = strlen(buff);
991
992 if(feof(fp)) {
993 char str[8192];
994 sprintf(str,"### ERROR: Unable to locate objective function\n");
995 throw CoinError(str, "find_obj", "CoinLpIO", __FILE__, __LINE__);
996 }
997 }
998
999 if(((lbuff == 8) && (CoinStrNCaseCmp(buff, "minimize", 8) == 0)) ||
1000 ((lbuff == 3) && (CoinStrNCaseCmp(buff, "min", 3) == 0))) {
1001 return(1);
1002 }
1003 return(-1);
1004} /* find_obj */
1005
1006/*************************************************************************/
1007int
1008CoinLpIO::is_subject_to(const char *buff) const {
1009
1010 size_t lbuff = strlen(buff);
1011
1012 if(((lbuff == 4) && (CoinStrNCaseCmp(buff, "s.t.", 4) == 0)) ||
1013 ((lbuff == 3) && (CoinStrNCaseCmp(buff, "st.", 3) == 0)) ||
1014 ((lbuff == 2) && (CoinStrNCaseCmp(buff, "st", 2) == 0))) {
1015 return(1);
1016 }
1017 if((lbuff == 7) && (CoinStrNCaseCmp(buff, "subject", 7) == 0)) {
1018 return(2);
1019 }
1020 return(0);
1021} /* is_subject_to */
1022
1023/*************************************************************************/
1024int
1025CoinLpIO::first_is_number(const char *buff) const {
1026
1027 size_t pos;
1028 char str_num[] = "1234567890";
1029
1030 pos = strcspn (buff, str_num);
1031 if (pos == 0) {
1032 return(1);
1033 }
1034 return(0);
1035} /* first_is_number */
1036
1037/*************************************************************************/
1038int
1039CoinLpIO::is_sense(const char *buff) const {
1040
1041 size_t pos;
1042 char str_sense[] = "<>=";
1043
1044 pos = strcspn(buff, str_sense);
1045 if(pos == 0) {
1046 if(strcmp(buff, "<=") == 0) {
1047 return(0);
1048 }
1049 if(strcmp(buff, "=") == 0) {
1050 return(1);
1051 }
1052 if(strcmp(buff, ">=") == 0) {
1053 return(2);
1054 }
1055
1056 printf("### ERROR: CoinLpIO: is_sense(): string: %s \n", buff);
1057 }
1058 return(-1);
1059} /* is_sense */
1060
1061/*************************************************************************/
1062int
1063CoinLpIO::is_free(const char *buff) const {
1064
1065 size_t lbuff = strlen(buff);
1066
1067 if((lbuff == 4) && (CoinStrNCaseCmp(buff, "free", 4) == 0)) {
1068 return(1);
1069 }
1070 return(0);
1071} /* is_free */
1072
1073/*************************************************************************/
1074int
1075CoinLpIO::is_inf(const char *buff) const {
1076
1077 size_t lbuff = strlen(buff);
1078
1079 if((lbuff == 3) && (CoinStrNCaseCmp(buff, "inf", 3) == 0)) {
1080 return(1);
1081 }
1082 return(0);
1083} /* is_inf */
1084
1085/*************************************************************************/
1086int
1087CoinLpIO::is_comment(const char *buff) const {
1088
1089 if((buff[0] == '/') || (buff[0] == '\\')) {
1090 return(1);
1091 }
1092 return(0);
1093} /* is_comment */
1094
1095/*************************************************************************/
1096void
1097CoinLpIO::skip_comment(char *buff, FILE *fp) const {
1098
1099 while(strcspn(buff, "\n") == strlen(buff)) { // end of line not read yet
1100 if(feof(fp)) {
1101 char str[8192];
1102 sprintf(str,"### ERROR: end of file reached while skipping comment\n");
1103 throw CoinError(str, "skip_comment", "CoinLpIO", __FILE__, __LINE__);
1104 }
1105 if(ferror(fp)) {
1106 char str[8192];
1107 sprintf(str,"### ERROR: error while skipping comment\n");
1108 throw CoinError(str, "skip_comment", "CoinLpIO", __FILE__, __LINE__);
1109 }
1110 char * x=fgets(buff, sizeof(buff), fp);
1111 if (!x)
1112 throw("bad fgets");
1113 }
1114} /* skip_comment */
1115
1116/*************************************************************************/
1117void
1118CoinLpIO::scan_next(char *buff, FILE *fp) const {
1119
1120 int x=fscanf(fp, "%s", buff);
1121 if (x<=0)
1122 throw("bad fscanf");
1123 while(is_comment(buff)) {
1124 skip_comment(buff, fp);
1125 x=fscanf(fp, "%s", buff);
1126 if (x<=0)
1127 throw("bad fscanf");
1128 }
1129
1130#ifdef LPIO_DEBUG
1131 printf("CoinLpIO::scan_next: (%s)\n", buff);
1132#endif
1133
1134} /* scan_next */
1135
1136/*************************************************************************/
1137int
1138CoinLpIO::is_invalid_name(const char *name,
1139 const bool ranged) const {
1140
1141 size_t pos, lname, valid_lname = 100;
1142 char str_valid[] = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\"!#$%&(),.;?@_'`{}~";
1143
1144 if(ranged) {
1145 valid_lname -= 4; // will add "_low" when writing the Lp file
1146 }
1147
1148 if(name == NULL) {
1149 lname = 0;
1150 }
1151 else {
1152 lname = strlen(name);
1153 }
1154 if(lname < 1) {
1155 handler_->message(COIN_GENERAL_WARNING,messages_)<<
1156 "### CoinLpIO::is_invalid_name(): Name is empty"
1157 <<CoinMessageEol;
1158 return(5);
1159 }
1160 if(lname > valid_lname) {
1161 char printBuffer[512];
1162 sprintf(printBuffer,"### CoinLpIO::is_invalid_name(): Name %s is too long",
1163 name);
1164 handler_->message(COIN_GENERAL_WARNING,messages_)<<printBuffer
1165 <<CoinMessageEol;
1166 return(1);
1167 }
1168 if(first_is_number(name)) {
1169 char printBuffer[512];
1170 sprintf(printBuffer,"### CoinLpIO::is_invalid_name(): Name %s should not start with a number", name);
1171 handler_->message(COIN_GENERAL_WARNING,messages_)<<printBuffer
1172 <<CoinMessageEol;
1173 return(2);
1174 }
1175 pos = strspn(name, str_valid);
1176 if(pos != lname) {
1177 char printBuffer[512];
1178 sprintf(printBuffer,"### CoinLpIO::is_invalid_name(): Name %s contains illegal character '%c'", name, name[pos]);
1179 handler_->message(COIN_GENERAL_WARNING,messages_)<<printBuffer
1180 <<CoinMessageEol;
1181 return(3);
1182 }
1183
1184 if((is_keyword(name)) || (is_free(name) || (is_inf(name)))) {
1185 return(4);
1186 }
1187
1188 return(0);
1189} /* is_invalid_name */
1190
1191/*************************************************************************/
1192int
1193CoinLpIO::are_invalid_names(char const * const * const vnames,
1194 const int card_vnames,
1195 const bool check_ranged) const {
1196
1197 int i, invalid = 0, flag, nrows = getNumRows();
1198 bool is_ranged = 0;
1199 const char * rSense = getRowSense();
1200
1201 if((check_ranged) && (card_vnames != nrows+1)) {
1202 char str[8192];
1203 sprintf(str,"### ERROR: card_vnames: %d number of rows: %d\n",
1204 card_vnames, getNumRows());
1205 throw CoinError(str, "are_invalid_names", "CoinLpIO", __FILE__, __LINE__);
1206 }
1207
1208 for(i=0; i<card_vnames; i++) {
1209
1210 if((check_ranged) && (i < nrows) && (rSense[i] == 'R')) {
1211 is_ranged = true;
1212 }
1213 else {
1214 is_ranged = false;
1215 }
1216 flag = is_invalid_name(vnames[i], is_ranged);
1217 if(flag) {
1218 char printBuffer[512];
1219 sprintf(printBuffer,"### CoinLpIO::are_invalid_names(): Invalid name: vnames[%d]: %s",
1220 i, vnames[i]);
1221 handler_->message(COIN_GENERAL_WARNING,messages_)<<printBuffer
1222 <<CoinMessageEol;
1223 invalid = flag;
1224 }
1225 }
1226 return(invalid);
1227} /* are_invalid_names */
1228
1229/*************************************************************************/
1230int
1231CoinLpIO::read_monom_obj(FILE *fp, double *coeff, char **name, int *cnt,
1232 char **obj_name) {
1233
1234 double mult;
1235 char buff[1024] = "aa", loc_name[1024], *start;
1236 int read_st = 0;
1237
1238 scan_next(buff, fp);
1239
1240 if(feof(fp)) {
1241 char str[8192];
1242 sprintf(str,"### ERROR: Unable to read objective function\n");
1243 throw CoinError(str, "read_monom_obj", "CoinLpIO", __FILE__, __LINE__);
1244 }
1245
1246 if(buff[strlen(buff)-1] == ':') {
1247 buff[strlen(buff)-1] = '\0';
1248
1249#ifdef LPIO_DEBUG
1250 printf("CoinLpIO: read_monom_obj(): obj_name: %s\n", buff);
1251#endif
1252
1253 *obj_name = CoinStrdup(buff);
1254 return(0);
1255 }
1256
1257
1258 read_st = is_subject_to(buff);
1259
1260#ifdef LPIO_DEBUG
1261 printf("read_monom_obj: first buff: (%s)\n", buff);
1262#endif
1263
1264 if(read_st > 0) {
1265 return(read_st);
1266 }
1267
1268 start = buff;
1269 mult = 1;
1270 if(buff[0] == '+') {
1271 mult = 1;
1272 if(strlen(buff) == 1) {
1273 scan_next(buff, fp);
1274 start = buff;
1275 }
1276 else {
1277 start = &(buff[1]);
1278 }
1279 }
1280
1281 if(buff[0] == '-') {
1282 mult = -1;
1283 if(strlen(buff) == 1) {
1284 scan_next(buff, fp);
1285 start = buff;
1286 }
1287 else {
1288 start = &(buff[1]);
1289 }
1290 }
1291
1292 if(first_is_number(start)) {
1293 coeff[*cnt] = atof(start);
1294 sprintf(loc_name, "aa");
1295 scan_next(loc_name, fp);
1296 }
1297 else {
1298 coeff[*cnt] = 1;
1299 strcpy(loc_name, start);
1300 }
1301
1302 read_st = is_subject_to(loc_name);
1303
1304#ifdef LPIO_DEBUG
1305 printf("read_monom_obj: second buff: (%s)\n", buff);
1306#endif
1307
1308 if(read_st > 0) {
1309 setObjectiveOffset(mult * coeff[*cnt]);
1310
1311#ifdef LPIO_DEBUG
1312 printf("read_monom_obj: objectiveOffset: %f\n", objectiveOffset_);
1313#endif
1314
1315 return(read_st);
1316 }
1317
1318 coeff[*cnt] *= mult;
1319 name[*cnt] = CoinStrdup(loc_name);
1320
1321#ifdef LPIO_DEBUG
1322 printf("read_monom_obj: (%f) (%s)\n", coeff[*cnt], name[*cnt]);
1323#endif
1324
1325 (*cnt)++;
1326
1327 return(read_st);
1328} /* read_monom_obj */
1329
1330/*************************************************************************/
1331int
1332CoinLpIO::read_monom_row(FILE *fp, char *start_str,
1333 double *coeff, char **name,
1334 int cnt_coeff) const {
1335
1336 double mult;
1337 char buff[1024], loc_name[1024], *start;
1338 int read_sense = -1;
1339
1340 sprintf(buff, "%s", start_str);
1341 read_sense = is_sense(buff);
1342 if(read_sense > -1) {
1343 return(read_sense);
1344 }
1345
1346 start = buff;
1347 mult = 1;
1348 if(buff[0] == '+') {
1349 mult = 1;
1350 if(strlen(buff) == 1) {
1351 scan_next(buff, fp);
1352 start = buff;
1353 }
1354 else {
1355 start = &(buff[1]);
1356 }
1357 }
1358
1359 if(buff[0] == '-') {
1360 mult = -1;
1361 if(strlen(buff) == 1) {
1362 scan_next(buff, fp);
1363 start = buff;
1364 }
1365 else {
1366 start = &(buff[1]);
1367 }
1368 }
1369
1370 if(first_is_number(start)) {
1371 coeff[cnt_coeff] = atof(start);
1372 scan_next(loc_name, fp);
1373 }
1374 else {
1375 coeff[cnt_coeff] = 1;
1376 strcpy(loc_name, start);
1377 }
1378
1379 coeff[cnt_coeff] *= mult;
1380#ifdef KILL_ZERO_READLP
1381 if (fabs(coeff[cnt_coeff])>epsilon_)
1382 name[cnt_coeff] = CoinStrdup(loc_name);
1383 else
1384 read_sense=-2; // effectively zero
1385#else
1386 name[cnt_coeff] = CoinStrdup(loc_name);
1387#endif
1388
1389#ifdef LPIO_DEBUG
1390 printf("CoinLpIO: read_monom_row: (%f) (%s)\n",
1391 coeff[cnt_coeff], name[cnt_coeff]);
1392#endif
1393 return(read_sense);
1394} /* read_monom_row */
1395
1396/*************************************************************************/
1397void
1398CoinLpIO::realloc_coeff(double **coeff, char ***colNames,
1399 int *maxcoeff) const {
1400
1401 *maxcoeff *= 5;
1402
1403 *colNames = reinterpret_cast<char **> (realloc ((*colNames), (*maxcoeff+1) * sizeof(char *)));
1404 *coeff = reinterpret_cast<double *> (realloc ((*coeff), (*maxcoeff+1) * sizeof(double)));
1405
1406} /* realloc_coeff */
1407
1408/*************************************************************************/
1409void
1410CoinLpIO::realloc_row(char ***rowNames, int **start, double **rhs,
1411 double **rowlow, double **rowup, int *maxrow) const {
1412
1413 *maxrow *= 5;
1414 *rowNames = reinterpret_cast<char **> (realloc ((*rowNames), (*maxrow+1) * sizeof(char *)));
1415 *start = reinterpret_cast<int *> (realloc ((*start), (*maxrow+1) * sizeof(int)));
1416 *rhs = reinterpret_cast<double *> (realloc ((*rhs), (*maxrow+1) * sizeof(double)));
1417 *rowlow = reinterpret_cast<double *> (realloc ((*rowlow), (*maxrow+1) * sizeof(double)));
1418 *rowup = reinterpret_cast<double *> (realloc ((*rowup), (*maxrow+1) * sizeof(double)));
1419
1420} /* realloc_row */
1421
1422/*************************************************************************/
1423void
1424CoinLpIO::realloc_col(double **collow, double **colup, char **is_int,
1425 int *maxcol) const {
1426
1427 *maxcol += 100;
1428 *collow = reinterpret_cast<double *> (realloc ((*collow), (*maxcol+1) * sizeof(double)));
1429 *colup = reinterpret_cast<double *> (realloc ((*colup), (*maxcol+1) * sizeof(double)));
1430 *is_int = reinterpret_cast<char *> (realloc ((*is_int), (*maxcol+1) * sizeof(char)));
1431
1432} /* realloc_col */
1433
1434/*************************************************************************/
1435void
1436CoinLpIO::read_row(FILE *fp, char *buff,
1437 double **pcoeff, char ***pcolNames,
1438 int *cnt_coeff,
1439 int *maxcoeff,
1440 double *rhs, double *rowlow, double *rowup,
1441 int *cnt_row, double inf) const {
1442
1443 int read_sense = -1;
1444 char start_str[1024];
1445
1446 sprintf(start_str, "%s", buff);
1447
1448 while(read_sense < 0) {
1449
1450 if((*cnt_coeff) == (*maxcoeff)) {
1451 realloc_coeff(pcoeff, pcolNames, maxcoeff);
1452 }
1453 read_sense = read_monom_row(fp, start_str,
1454 *pcoeff, *pcolNames, *cnt_coeff);
1455#ifdef KILL_ZERO_READLP
1456 if (read_sense!=-2) // see if zero
1457#endif
1458 (*cnt_coeff)++;
1459
1460 scan_next(start_str, fp);
1461
1462 if(feof(fp)) {
1463 char str[8192];
1464 sprintf(str,"### ERROR: Unable to read row monomial\n");
1465 throw CoinError(str, "read_monom_row", "CoinLpIO", __FILE__, __LINE__);
1466 }
1467 }
1468 (*cnt_coeff)--;
1469
1470 rhs[*cnt_row] = atof(start_str);
1471
1472 switch(read_sense) {
1473 case 0: rowlow[*cnt_row] = -inf; rowup[*cnt_row] = rhs[*cnt_row];
1474 break;
1475 case 1: rowlow[*cnt_row] = rhs[*cnt_row]; rowup[*cnt_row] = rhs[*cnt_row];
1476 break;
1477 case 2: rowlow[*cnt_row] = rhs[*cnt_row]; rowup[*cnt_row] = inf;
1478 break;
1479 default: break;
1480 }
1481 (*cnt_row)++;
1482
1483} /* read_row */
1484
1485/*************************************************************************/
1486int
1487CoinLpIO::is_keyword(const char *buff) const {
1488
1489 size_t lbuff = strlen(buff);
1490
1491 if(((lbuff == 5) && (CoinStrNCaseCmp(buff, "bound", 5) == 0)) ||
1492 ((lbuff == 6) && (CoinStrNCaseCmp(buff, "bounds", 6) == 0))) {
1493 return(1);
1494 }
1495
1496 if(((lbuff == 7) && (CoinStrNCaseCmp(buff, "integer", 7) == 0)) ||
1497 ((lbuff == 8) && (CoinStrNCaseCmp(buff, "integers", 8) == 0))) {
1498 return(2);
1499 }
1500
1501 if(((lbuff == 7) && (CoinStrNCaseCmp(buff, "general", 7) == 0)) ||
1502 ((lbuff == 8) && (CoinStrNCaseCmp(buff, "generals", 8) == 0))) {
1503 return(2);
1504 }
1505
1506 if(((lbuff == 6) && (CoinStrNCaseCmp(buff, "binary", 6) == 0)) ||
1507 ((lbuff == 8) && (CoinStrNCaseCmp(buff, "binaries", 8) == 0))) {
1508 return(3);
1509 }
1510
1511 if((lbuff == 3) && (CoinStrNCaseCmp(buff, "end", 3) == 0)) {
1512 return(4);
1513 }
1514
1515 return(0);
1516
1517} /* is_keyword */
1518
1519/*************************************************************************/
1520void
1521CoinLpIO::readLp(const char *filename, const double epsilon)
1522{
1523 setEpsilon(epsilon);
1524 readLp(filename);
1525}
1526
1527/*************************************************************************/
1528void
1529CoinLpIO::readLp(const char *filename)
1530{
1531 FILE *fp = fopen(filename, "r");
1532 if(!fp) {
1533 char str[8192];
1534 sprintf(str,"### ERROR: Unable to open file %s for reading\n", filename);
1535 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
1536 }
1537 readLp(fp);
1538 fclose(fp);
1539}
1540
1541/*************************************************************************/
1542void
1543CoinLpIO::readLp(FILE* fp, const double epsilon)
1544{
1545 setEpsilon(epsilon);
1546 readLp(fp);
1547}
1548
1549/*************************************************************************/
1550void
1551CoinLpIO::readLp(FILE* fp)
1552{
1553
1554 int maxrow = 1000;
1555 int maxcoeff = 40000;
1556 double lp_eps = getEpsilon();
1557 double lp_inf = getInfinity();
1558
1559 char buff[1024];
1560
1561 int objsense, cnt_coeff = 0, cnt_row = 0, cnt_obj = 0;
1562 char *objName = NULL;
1563
1564 char **colNames = reinterpret_cast<char **> (malloc ((maxcoeff+1) * sizeof(char *)));
1565 double *coeff = reinterpret_cast<double *> (malloc ((maxcoeff+1) * sizeof(double)));
1566
1567 char **rowNames = reinterpret_cast<char **> (malloc ((maxrow+1) * sizeof(char *)));
1568 int *start = reinterpret_cast<int *> (malloc ((maxrow+1) * sizeof(int)));
1569 double *rhs = reinterpret_cast<double *> (malloc ((maxrow+1) * sizeof(double)));
1570 double *rowlow = reinterpret_cast<double *> (malloc ((maxrow+1) * sizeof(double)));
1571 double *rowup = reinterpret_cast<double *> (malloc ((maxrow+1) * sizeof(double)));
1572
1573 int i;
1574
1575 objsense = find_obj(fp);
1576
1577 int read_st = 0;
1578 while(!read_st) {
1579 read_st = read_monom_obj(fp, coeff, colNames, &cnt_obj, &objName);
1580
1581 if(cnt_obj == maxcoeff) {
1582 realloc_coeff(&coeff, &colNames, &maxcoeff);
1583 }
1584 }
1585
1586 start[0] = cnt_obj;
1587 cnt_coeff = cnt_obj;
1588
1589 if(read_st == 2) {
1590 int x=fscanf(fp, "%s", buff);
1591 if (x<=0)
1592 throw("bad fscanf");
1593 size_t lbuff = strlen(buff);
1594
1595 if((lbuff != 2) || (CoinStrNCaseCmp(buff, "to", 2) != 0)) {
1596 char str[8192];
1597 sprintf(str,"### ERROR: Can not locate keyword 'Subject To'\n");
1598 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
1599 }
1600 }
1601
1602 scan_next(buff, fp);
1603
1604 while(!is_keyword(buff)) {
1605 if(buff[strlen(buff)-1] == ':') {
1606 buff[strlen(buff)-1] = '\0';
1607
1608#ifdef LPIO_DEBUG
1609 printf("CoinLpIO::readLp(): rowName[%d]: %s\n", cnt_row, buff);
1610#endif
1611
1612 rowNames[cnt_row] = CoinStrdup(buff);
1613 scan_next(buff, fp);
1614 }
1615 else {
1616 char rname[15];
1617 sprintf(rname, "cons%d", cnt_row);
1618 rowNames[cnt_row] = CoinStrdup(rname);
1619 }
1620 read_row(fp, buff,
1621 &coeff, &colNames, &cnt_coeff, &maxcoeff, rhs, rowlow, rowup,
1622 &cnt_row, lp_inf);
1623 scan_next(buff, fp);
1624 start[cnt_row] = cnt_coeff;
1625
1626 if(cnt_row == maxrow) {
1627 realloc_row(&rowNames, &start, &rhs, &rowlow, &rowup, &maxrow);
1628 }
1629
1630 }
1631
1632 numberRows_ = cnt_row;
1633
1634 stopHash(1);
1635 startHash(colNames, cnt_coeff, 1);
1636
1637 COINColumnIndex icol;
1638 int read_sense1, read_sense2;
1639 double bnd1 = 0, bnd2 = 0;
1640
1641 int maxcol = numberHash_[1] + 100;
1642
1643 double *collow = reinterpret_cast<double *> (malloc ((maxcol+1) * sizeof(double)));
1644 double *colup = reinterpret_cast<double *> (malloc ((maxcol+1) * sizeof(double)));
1645 char *is_int = reinterpret_cast<char *> (malloc ((maxcol+1) * sizeof(char)));
1646 int has_int = 0;
1647
1648 for (i=0; i<maxcol; i++) {
1649 collow[i] = 0;
1650 colup[i] = lp_inf;
1651 is_int[i] = 0;
1652 }
1653
1654 int done = 0;
1655
1656 while(!done) {
1657 switch(is_keyword(buff)) {
1658
1659 case 1: /* Bounds section */
1660 scan_next(buff, fp);
1661
1662 while(is_keyword(buff) == 0) {
1663
1664 read_sense1 = -1;
1665 read_sense2 = -1;
1666 int mult = 1;
1667 char *start_str = buff;
1668
1669 if(buff[0] == '-' || buff[0] == '+') {
1670 mult = (buff[0] == '-') ? -1 : +1;
1671 if(strlen(buff) == 1) {
1672 scan_next(buff, fp);
1673 start_str = buff;
1674 }
1675 else {
1676 start_str = &(buff[1]);
1677 }
1678 }
1679
1680 int scan_sense = 0;
1681 if(first_is_number(start_str)) {
1682 bnd1 = mult * atof(start_str);
1683 scan_sense = 1;
1684 }
1685 else {
1686 if(is_inf(start_str)) {
1687 bnd1 = mult * lp_inf;
1688 scan_sense = 1;
1689 }
1690 }
1691 if(scan_sense) {
1692 scan_next(buff, fp);
1693 read_sense1 = is_sense(buff);
1694 if(read_sense1 < 0) {
1695 char str[8192];
1696 sprintf(str,"### ERROR: Bounds; expect a sense, get: %s\n", buff);
1697 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
1698 }
1699 scan_next(buff, fp);
1700 }
1701
1702 icol = findHash(buff, 1);
1703 if(icol < 0) {
1704 char printBuffer[512];
1705 sprintf(printBuffer,"### CoinLpIO::readLp(): Variable %s does not appear in objective function or constraints", buff);
1706 handler_->message(COIN_GENERAL_WARNING,messages_)<<printBuffer
1707 <<CoinMessageEol;
1708 insertHash(buff, 1);
1709 icol = findHash(buff, 1);
1710 if(icol == maxcol) {
1711 realloc_col(&collow, &colup, &is_int, &maxcol);
1712 }
1713 }
1714
1715 scan_next(buff, fp);
1716 if(is_free(buff)) {
1717 collow[icol] = -lp_inf;
1718 scan_next(buff, fp);
1719 }
1720 else {
1721 read_sense2 = is_sense(buff);
1722 if(read_sense2 > -1) {
1723 scan_next(buff, fp);
1724 mult = 1;
1725 start_str = buff;
1726
1727 if(buff[0] == '-'||buff[0] == '+') {
1728 mult = (buff[0] == '-') ? -1 : +1;
1729 if(strlen(buff) == 1) {
1730 scan_next(buff, fp);
1731 start_str = buff;
1732 }
1733 else {
1734 start_str = &(buff[1]);
1735 }
1736 }
1737 if(first_is_number(start_str)) {
1738 bnd2 = mult * atof(start_str);
1739 scan_next(buff, fp);
1740 }
1741 else {
1742 if(is_inf(start_str)) {
1743 bnd2 = mult * lp_inf;
1744 scan_next(buff, fp);
1745 }
1746 else {
1747 char str[8192];
1748 sprintf(str,"### ERROR: Bounds; expect a number, get: %s\n",
1749 buff);
1750 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
1751 }
1752 }
1753 }
1754
1755 if((read_sense1 > -1) && (read_sense2 > -1)) {
1756 if(read_sense1 != read_sense2) {
1757 char str[8192];
1758 sprintf(str,"### ERROR: Bounds; variable: %s read_sense1: %d read_sense2: %d\n",
1759 buff, read_sense1, read_sense2);
1760 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
1761 }
1762 else {
1763 if(read_sense1 == 1) {
1764 if(fabs(bnd1 - bnd2) > lp_eps) {
1765 char str[8192];
1766 sprintf(str,"### ERROR: Bounds; variable: %s read_sense1: %d read_sense2: %d bnd1: %f bnd2: %f\n",
1767 buff, read_sense1, read_sense2, bnd1, bnd2);
1768 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
1769 }
1770 collow[icol] = bnd1;
1771 colup[icol] = bnd1;
1772 }
1773 if(read_sense1 == 0) {
1774 collow[icol] = bnd1;
1775 colup[icol] = bnd2;
1776 }
1777 if(read_sense1 == 2) {
1778 colup[icol] = bnd1;
1779 collow[icol] = bnd2;
1780 }
1781 }
1782 }
1783 else {
1784 if(read_sense1 > -1) {
1785 switch(read_sense1) {
1786 case 0: collow[icol] = bnd1; break;
1787 case 1: collow[icol] = bnd1; colup[icol] = bnd1; break;
1788 case 2: colup[icol] = bnd1; break;
1789 }
1790 }
1791 if(read_sense2 > -1) {
1792 switch(read_sense2) {
1793 case 0: colup[icol] = bnd2; break;
1794 case 1: collow[icol] = bnd2; colup[icol] = bnd2; break;
1795 case 2: collow[icol] = bnd2; break;
1796 }
1797 }
1798 }
1799 }
1800 }
1801 break;
1802
1803 case 2: /* Integers/Generals section */
1804
1805 scan_next(buff, fp);
1806
1807 while(is_keyword(buff) == 0) {
1808
1809 icol = findHash(buff, 1);
1810
1811#ifdef LPIO_DEBUG
1812 printf("CoinLpIO::readLp(): Integer: colname: (%s) icol: %d\n",
1813 buff, icol);
1814#endif
1815
1816 if(icol < 0) {
1817 char printBuffer[512];
1818 sprintf(printBuffer,"### CoinLpIO::readLp(): Integer variable %s does not appear in objective function or constraints", buff);
1819 handler_->message(COIN_GENERAL_WARNING,messages_)<<printBuffer
1820 <<CoinMessageEol;
1821 insertHash(buff, 1);
1822 icol = findHash(buff, 1);
1823 if(icol == maxcol) {
1824 realloc_col(&collow, &colup, &is_int, &maxcol);
1825 }
1826
1827#ifdef LPIO_DEBUG
1828 printf("CoinLpIO::readLp(): Integer: colname: (%s) icol: %d\n",
1829 buff, icol);
1830#endif
1831
1832 }
1833 is_int[icol] = 1;
1834 has_int = 1;
1835 scan_next(buff, fp);
1836 };
1837 break;
1838
1839 case 3: /* Binaries section */
1840
1841 scan_next(buff, fp);
1842
1843 while(is_keyword(buff) == 0) {
1844
1845 icol = findHash(buff, 1);
1846
1847#ifdef LPIO_DEBUG
1848 printf("CoinLpIO::readLp(): binary: colname: (%s) icol: %d\n",
1849 buff, icol);
1850#endif
1851
1852 if(icol < 0) {
1853 char printBuffer[512];
1854 sprintf(printBuffer,"### CoinLpIO::readLp(): Binary variable %s does not appear in objective function or constraints", buff);
1855 handler_->message(COIN_GENERAL_WARNING,messages_)<<printBuffer
1856 <<CoinMessageEol;
1857 insertHash(buff, 1);
1858 icol = findHash(buff, 1);
1859 if(icol == maxcol) {
1860 realloc_col(&collow, &colup, &is_int, &maxcol);
1861 }
1862#ifdef LPIO_DEBUG
1863 printf("CoinLpIO::readLp(): binary: colname: (%s) icol: %d\n",
1864 buff, icol);
1865#endif
1866
1867 }
1868
1869 is_int[icol] = 1;
1870 has_int = 1;
1871 if(collow[icol] < 0) {
1872 collow[icol] = 0;
1873 }
1874 if(colup[icol] > 1) {
1875 colup[icol] = 1;
1876 }
1877 scan_next(buff, fp);
1878 }
1879 break;
1880
1881 case 4: done = 1; break;
1882
1883 default:
1884 char str[8192];
1885 sprintf(str,"### ERROR: Lost while reading: (%s)\n", buff);
1886 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
1887 break;
1888 }
1889 }
1890
1891#ifdef LPIO_DEBUG
1892 printf("CoinLpIO::readLp(): Done with reading the Lp file\n");
1893#endif
1894
1895 int *ind = reinterpret_cast<int *> (malloc ((maxcoeff+1) * sizeof(int)));
1896
1897 for(i=0; i<cnt_coeff; i++) {
1898 ind[i] = findHash(colNames[i], 1);
1899
1900#ifdef LPIO_DEBUG
1901 printf("CoinLpIO::readLp(): name[%d]: (%s) ind: %d\n",
1902 i, colNames[i], ind[i]);
1903#endif
1904
1905 if(ind[i] < 0) {
1906 char str[8192];
1907 sprintf(str,"### ERROR: Hash table: %s not found\n", colNames[i]);
1908 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
1909 }
1910 }
1911
1912 numberColumns_ = numberHash_[1];
1913 numberElements_ = cnt_coeff - start[0];
1914
1915 double *obj = reinterpret_cast<double *> (malloc (numberColumns_ * sizeof(double)));
1916 memset(obj, 0, numberColumns_ * sizeof(double));
1917
1918 for(i=0; i<cnt_obj; i++) {
1919 icol = findHash(colNames[i], 1);
1920 if(icol < 0) {
1921 char str[8192];
1922 sprintf(str,"### ERROR: Hash table: %s (obj) not found\n", colNames[i]);
1923 throw CoinError(str, "readLp", "CoinLpIO", __FILE__, __LINE__);
1924 }
1925 obj[icol] = objsense * coeff[i];
1926 }
1927
1928 if (objsense == -1) {
1929 handler_->message(COIN_GENERAL_INFO,messages_)<<
1930 " CoinLpIO::readLp(): Maximization problem reformulated as minimization"
1931 <<CoinMessageEol;
1932 objectiveOffset_ = -objectiveOffset_;
1933 }
1934
1935
1936 for(i=0; i<cnt_row+1; i++) {
1937 start[i] -= cnt_obj;
1938 }
1939
1940 CoinPackedMatrix *matrix =
1941 new CoinPackedMatrix(false,
1942 numberColumns_, numberRows_, numberElements_,
1943 &(coeff[cnt_obj]), &(ind[cnt_obj]), start, NULL);
1944
1945#ifdef LPIO_DEBUG
1946 matrix->dumpMatrix();
1947#endif
1948
1949 setLpDataWithoutRowAndColNames(*matrix, collow, colup,
1950 obj, has_int ? is_int : 0, rowlow, rowup);
1951
1952
1953 if(objName == NULL) {
1954 rowNames[cnt_row] = CoinStrdup("obj");
1955 }
1956 else {
1957 rowNames[cnt_row] = CoinStrdup(objName);
1958 }
1959
1960 // Hash tables for column names are already set up
1961 setLpDataRowAndColNames(rowNames, NULL);
1962
1963 if(are_invalid_names(names_[1], numberHash_[1], false)) {
1964 setDefaultColNames();
1965 handler_->message(COIN_GENERAL_WARNING,messages_)<<
1966 "### CoinLpIO::readLp(): Invalid column names\nNow using default column names."
1967 <<CoinMessageEol;
1968 }
1969
1970 for(i=0; i<cnt_coeff; i++) {
1971 free(colNames[i]);
1972 }
1973 free(colNames);
1974
1975 for(i=0; i<cnt_row+1; i++) {
1976 free(rowNames[i]);
1977 }
1978 free(rowNames);
1979
1980 free(objName);
1981
1982#ifdef LPIO_DEBUG
1983 writeLp("readlp.xxx");
1984 printf("CoinLpIO::readLp(): read Lp file written in file readlp.xxx\n");
1985#endif
1986
1987 free(coeff);
1988 free(start);
1989 free(ind);
1990 free(colup);
1991 free(collow);
1992 free(rhs);
1993 free(rowlow);
1994 free(rowup);
1995 free(is_int);
1996 free(obj);
1997 delete matrix;
1998
1999} /* readLp */
2000
2001/*************************************************************************/
2002void
2003CoinLpIO::print() const {
2004
2005 printf("problemName_: %s\n", problemName_);
2006 printf("numberRows_: %d\n", numberRows_);
2007 printf("numberColumns_: %d\n", numberColumns_);
2008
2009 printf("matrixByRows_:\n");
2010 matrixByRow_->dumpMatrix();
2011
2012 int i;
2013 printf("rowlower_:\n");
2014 for(i=0; i<numberRows_; i++) {
2015 printf("%.5f ", rowlower_[i]);
2016 }
2017 printf("\n");
2018
2019 printf("rowupper_:\n");
2020 for(i=0; i<numberRows_; i++) {
2021 printf("%.5f ", rowupper_[i]);
2022 }
2023 printf("\n");
2024
2025 printf("collower_:\n");
2026 for(i=0; i<numberColumns_; i++) {
2027 printf("%.5f ", collower_[i]);
2028 }
2029 printf("\n");
2030
2031 printf("colupper_:\n");
2032 for(i=0; i<numberColumns_; i++) {
2033 printf("%.5f ", colupper_[i]);
2034 }
2035 printf("\n");
2036
2037 printf("objective_:\n");
2038 for(i=0; i<numberColumns_; i++) {
2039 printf("%.5f ", objective_[i]);
2040 }
2041 printf("\n");
2042
2043 if(integerType_ != NULL) {
2044 printf("integerType_:\n");
2045 for(i=0; i<numberColumns_; i++) {
2046 printf("%c ", integerType_[i]);
2047 }
2048 }
2049 else {
2050 printf("integerType_: NULL\n");
2051 }
2052
2053 printf("\n");
2054 if(fileName_ != NULL) {
2055 printf("fileName_: %s\n", fileName_);
2056 }
2057 printf("infinity_: %.5f\n", infinity_);
2058} /* print */
2059
2060
2061/*************************************************************************/
2062// Hash functions slightly modified from CoinMpsIO.cpp
2063
2064namespace {
2065 const int mmult[] = {
2066 262139, 259459, 256889, 254291, 251701, 249133, 246709, 244247,
2067 241667, 239179, 236609, 233983, 231289, 228859, 226357, 223829,
2068 221281, 218849, 216319, 213721, 211093, 208673, 206263, 203773,
2069 201233, 198637, 196159, 193603, 191161, 188701, 186149, 183761,
2070 181303, 178873, 176389, 173897, 171469, 169049, 166471, 163871,
2071 161387, 158941, 156437, 153949, 151531, 149159, 146749, 144299,
2072 141709, 139369, 136889, 134591, 132169, 129641, 127343, 124853,
2073 122477, 120163, 117757, 115361, 112979, 110567, 108179, 105727,
2074 103387, 101021, 98639, 96179, 93911, 91583, 89317, 86939, 84521,
2075 82183, 79939, 77587, 75307, 72959, 70793, 68447, 66103
2076 };
2077 int compute_hash(const char *name, int maxsiz, int length)
2078{
2079
2080 int n = 0;
2081 int j;
2082
2083 for ( j = 0; j < length; ++j ) {
2084 int iname = name[j];
2085
2086 n += mmult[j] * iname;
2087 }
2088 return ( abs ( n ) % maxsiz ); /* integer abs */
2089}
2090} // end file-local namespace
2091
2092/************************************************************************/
2093// startHash. Creates hash list for names
2094// setup names_[section] with names in the same order as in the parameter,
2095// but removes duplicates
2096
2097void
2098CoinLpIO::startHash(char const * const * const names,
2099 const COINColumnIndex number, int section)
2100{
2101 maxHash_[section] = 4 * number;
2102 int maxhash = maxHash_[section];
2103 COINColumnIndex i, ipos, iput;
2104
2105 names_[section] = reinterpret_cast<char **> (malloc(maxhash * sizeof(char *)));
2106 hash_[section] = new CoinHashLink[maxhash];
2107
2108 CoinHashLink * hashThis = hash_[section];
2109 char **hashNames = names_[section];
2110
2111 for ( i = 0; i < maxhash; i++ ) {
2112 hashThis[i].index = -1;
2113 hashThis[i].next = -1;
2114 }
2115
2116 /*
2117 * Initialize the hash table. Only the index of the first name that
2118 * hashes to a value is entered in the table; subsequent names that
2119 * collide with it are not entered.
2120 */
2121
2122 for (i=0; i<number; i++) {
2123 const char *thisName = names[i];
2124 int length = CoinStrlenAsInt(thisName);
2125
2126 ipos = compute_hash(thisName, maxhash, length);
2127 if (hashThis[ipos].index == -1) {
2128 hashThis[ipos].index = i; // will be changed below
2129 }
2130 }
2131
2132 /*
2133 * Now take care of the names that collided in the preceding loop,
2134 * by finding some other entry in the table for them.
2135 * Since there are as many entries in the table as there are names,
2136 * there must be room for them.
2137 * Also setting up hashNames.
2138 */
2139
2140 int cnt_distinct = 0;
2141
2142 iput = -1;
2143 for (i=0; i<number; i++) {
2144 const char *thisName = names[i];
2145 int length = CoinStrlenAsInt(thisName);
2146
2147 ipos = compute_hash(thisName, maxhash, length);
2148
2149 while (1) {
2150 COINColumnIndex j1 = hashThis[ipos].index;
2151
2152 if(j1 == i) {
2153
2154 // first occurence of thisName in the parameter "names"
2155
2156 hashThis[ipos].index = cnt_distinct;
2157 hashNames[cnt_distinct] = CoinStrdup(thisName);
2158 cnt_distinct++;
2159 break;
2160 }
2161 else {
2162
2163#ifdef LPIO_DEBUG
2164 if(j1 > i) {
2165 char str[8192];
2166 sprintf(str,"### ERROR: Hash table: j1: %d i: %d\n", j1, i);
2167 throw CoinError(str, "startHash", "CoinLpIO", __FILE__, __LINE__);
2168 }
2169#endif
2170
2171 if (strcmp(thisName, hashNames[j1]) == 0) {
2172
2173 // thisName already entered
2174
2175 break;
2176 }
2177 else {
2178 // Collision; check if thisName already entered
2179
2180 COINColumnIndex k = hashThis[ipos].next;
2181
2182 if (k == -1) {
2183
2184 // thisName not found; enter it
2185
2186 while (1) {
2187 ++iput;
2188 if (iput > maxhash) {
2189 char str[8192];
2190 sprintf(str,"### ERROR: Hash table: too many names\n");
2191 throw CoinError(str, "startHash", "CoinLpIO", __FILE__, __LINE__);
2192 break;
2193 }
2194 if (hashThis[iput].index == -1) {
2195 break;
2196 }
2197 }
2198 hashThis[ipos].next = iput;
2199 hashThis[iput].index = cnt_distinct;
2200 hashNames[cnt_distinct] = CoinStrdup(thisName);
2201 cnt_distinct++;
2202 break;
2203 }
2204 else {
2205 ipos = k;
2206
2207 // continue the check with names in collision
2208
2209 }
2210 }
2211 }
2212 }
2213 }
2214
2215 numberHash_[section] = cnt_distinct;
2216
2217} /* startHash */
2218
2219/**************************************************************************/
2220// stopHash. Deletes hash storage
2221void
2222CoinLpIO::stopHash(int section)
2223{
2224 freePreviousNames(section);
2225 previous_names_[section] = names_[section];
2226 card_previous_names_[section] = numberHash_[section];
2227
2228 delete[] hash_[section];
2229 hash_[section] = NULL;
2230
2231 maxHash_[section] = 0;
2232 numberHash_[section] = 0;
2233
2234 if(section == 0) {
2235 free(objName_);
2236 objName_ = NULL;
2237 }
2238} /* stopHash */
2239
2240/**********************************************************************/
2241// findHash. -1 not found
2242COINColumnIndex
2243CoinLpIO::findHash(const char *name, int section) const
2244{
2245 COINColumnIndex found = -1;
2246
2247 char ** names = names_[section];
2248 CoinHashLink * hashThis = hash_[section];
2249 COINColumnIndex maxhash = maxHash_[section];
2250 COINColumnIndex ipos;
2251
2252 /* default if we don't find anything */
2253 if (!maxhash)
2254 return -1;
2255
2256 int length = CoinStrlenAsInt(name);
2257
2258 ipos = compute_hash(name, maxhash, length);
2259 while (1) {
2260 COINColumnIndex j1 = hashThis[ipos].index;
2261
2262 if (j1 >= 0) {
2263 char *thisName2 = names[j1];
2264
2265 if (strcmp (name, thisName2) != 0) {
2266 COINColumnIndex k = hashThis[ipos].next;
2267
2268 if (k != -1)
2269 ipos = k;
2270 else
2271 break;
2272 }
2273 else {
2274 found = j1;
2275 break;
2276 }
2277 }
2278 else {
2279 found = -1;
2280 break;
2281 }
2282 }
2283 return found;
2284} /* findHash */
2285
2286/*********************************************************************/
2287void
2288CoinLpIO::insertHash(const char *thisName, int section)
2289{
2290
2291 int number = numberHash_[section];
2292 int maxhash = maxHash_[section];
2293
2294 CoinHashLink * hashThis = hash_[section];
2295 char **hashNames = names_[section];
2296
2297 int iput = -1;
2298 int length = CoinStrlenAsInt(thisName);
2299
2300 int ipos = compute_hash(thisName, maxhash, length);
2301
2302 while (1) {
2303 COINColumnIndex j1 = hashThis[ipos].index;
2304
2305 if (j1 == -1) {
2306 hashThis[ipos].index = number;
2307 break;
2308 }
2309 else {
2310 char *thisName2 = hashNames[j1];
2311
2312 if ( strcmp (thisName, thisName2) != 0 ) {
2313 COINColumnIndex k = hashThis[ipos].next;
2314
2315 if (k == -1) {
2316 while (1) {
2317 ++iput;
2318 if (iput == maxhash) {
2319 char str[8192];
2320 sprintf(str,"### ERROR: Hash table: too many names\n");
2321 throw CoinError(str, "insertHash", "CoinLpIO", __FILE__, __LINE__);
2322 break;
2323 }
2324 if (hashThis[iput].index == -1) {
2325 break;
2326 }
2327 }
2328 hashThis[ipos].next = iput;
2329 hashThis[iput].index = number;
2330 break;
2331 }
2332 else {
2333 ipos = k;
2334 /* nothing worked - try it again */
2335 }
2336 }
2337 }
2338 }
2339
2340 hashNames[number] = CoinStrdup(thisName);
2341 (numberHash_[section])++;
2342
2343}
2344// Pass in Message handler (not deleted at end)
2345void
2346CoinLpIO::passInMessageHandler(CoinMessageHandler * handler)
2347{
2348 if (defaultHandler_)
2349 delete handler_;
2350 defaultHandler_=false;
2351 handler_=handler;
2352}
2353// Set language
2354void
2355CoinLpIO::newLanguage(CoinMessages::Language language)
2356{
2357 messages_ = CoinMessage(language);
2358}
2359