1 /* rdprob.c (read problem data in GLPK format) */
2 
3 /***********************************************************************
4 *  This code is part of GLPK (GNU Linear Programming Kit).
5 *  Copyright (C) 2010-2016 Free Software Foundation, Inc.
6 *  Written by Andrew Makhorin <mao@gnu.org>.
7 *
8 *  GLPK is free software: you can redistribute it and/or modify it
9 *  under the terms of the GNU General Public License as published by
10 *  the Free Software Foundation, either version 3 of the License, or
11 *  (at your option) any later version.
12 *
13 *  GLPK is distributed in the hope that it will be useful, but WITHOUT
14 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 *  License for more details.
17 *
18 *  You should have received a copy of the GNU General Public License
19 *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
20 ***********************************************************************/
21 
22 #include "dimacs.h"
23 #include "misc.h"
24 #include "prob.h"
25 
26 #define xfprintf        glp_format
27 #define error           dmx_error
28 #define warning         dmx_warning
29 #define read_char       dmx_read_char
30 #define read_designator dmx_read_designator
31 #define read_field      dmx_read_field
32 #define end_of_line     dmx_end_of_line
33 #define check_int       dmx_check_int
34 
35 /***********************************************************************
36 *  NAME
37 *
38 *  glp_read_prob - read problem data in GLPK format
39 *
40 *  SYNOPSIS
41 *
42 *  int glp_read_prob(glp_prob *P, int flags, const char *fname);
43 *
44 *  The routine glp_read_prob reads problem data in GLPK LP/MIP format
45 *  from a text file.
46 *
47 *  RETURNS
48 *
49 *  If the operation was successful, the routine returns zero. Otherwise
50 *  it prints an error message and returns non-zero. */
51 
glp_read_prob(glp_prob * P,int flags,const char * fname)52 int glp_read_prob(glp_prob *P, int flags, const char *fname)
53 {     DMX _csa, *csa = &_csa;
54       int mip, m, n, nnz, ne, i, j, k, type, kind, ret, *ln = NULL,
55          *ia = NULL, *ja = NULL;
56       double lb, ub, temp, *ar = NULL;
57       char *rf = NULL, *cf = NULL;
58 #if 0 /* 04/IV-2016 */
59       if (P == NULL || P->magic != GLP_PROB_MAGIC)
60          xerror("glp_read_prob: P = %p; invalid problem object\n",
61             P);
62 #endif
63       if (flags != 0)
64          xerror("glp_read_prob: flags = %d; invalid parameter\n",
65             flags);
66       if (fname == NULL)
67          xerror("glp_read_prob: fname = %d; invalid parameter\n",
68             fname);
69       glp_erase_prob(P);
70       if (setjmp(csa->jump))
71       {  ret = 1;
72          goto done;
73       }
74       csa->fname = fname;
75       csa->fp = NULL;
76       csa->count = 0;
77       csa->c = '\n';
78       csa->field[0] = '\0';
79       csa->empty = csa->nonint = 0;
80       xprintf("Reading problem data from '%s'...\n", fname);
81       csa->fp = glp_open(fname, "r");
82       if (csa->fp == NULL)
83       {  xprintf("Unable to open '%s' - %s\n", fname, get_err_msg());
84          longjmp(csa->jump, 1);
85       }
86       /* read problem line */
87       read_designator(csa);
88       if (strcmp(csa->field, "p") != 0)
89          error(csa, "problem line missing or invalid");
90       read_field(csa);
91       if (strcmp(csa->field, "lp") == 0)
92          mip = 0;
93       else if (strcmp(csa->field, "mip") == 0)
94          mip = 1;
95       else
96          error(csa, "wrong problem designator; 'lp' or 'mip' expected");
97       read_field(csa);
98       if (strcmp(csa->field, "min") == 0)
99          glp_set_obj_dir(P, GLP_MIN);
100       else if (strcmp(csa->field, "max") == 0)
101          glp_set_obj_dir(P, GLP_MAX);
102       else
103          error(csa, "objective sense missing or invalid");
104       read_field(csa);
105       if (!(str2int(csa->field, &m) == 0 && m >= 0))
106          error(csa, "number of rows missing or invalid");
107       read_field(csa);
108       if (!(str2int(csa->field, &n) == 0 && n >= 0))
109          error(csa, "number of columns missing or invalid");
110       read_field(csa);
111       if (!(str2int(csa->field, &nnz) == 0 && nnz >= 0))
112          error(csa, "number of constraint coefficients missing or inval"
113             "id");
114       if (m > 0)
115       {  glp_add_rows(P, m);
116          for (i = 1; i <= m; i++)
117             glp_set_row_bnds(P, i, GLP_FX, 0.0, 0.0);
118       }
119       if (n > 0)
120       {  glp_add_cols(P, n);
121          for (j = 1; j <= n; j++)
122          {  if (!mip)
123                glp_set_col_bnds(P, j, GLP_LO, 0.0, 0.0);
124             else
125                glp_set_col_kind(P, j, GLP_BV);
126          }
127       }
128       end_of_line(csa);
129       /* allocate working arrays */
130       rf = xcalloc(1+m, sizeof(char));
131       memset(rf, 0, 1+m);
132       cf = xcalloc(1+n, sizeof(char));
133       memset(cf, 0, 1+n);
134       ln = xcalloc(1+nnz, sizeof(int));
135       ia = xcalloc(1+nnz, sizeof(int));
136       ja = xcalloc(1+nnz, sizeof(int));
137       ar = xcalloc(1+nnz, sizeof(double));
138       /* read descriptor lines */
139       ne = 0;
140       for (;;)
141       {  read_designator(csa);
142          if (strcmp(csa->field, "i") == 0)
143          {  /* row descriptor */
144             read_field(csa);
145             if (str2int(csa->field, &i) != 0)
146                error(csa, "row number missing or invalid");
147             if (!(1 <= i && i <= m))
148                error(csa, "row number out of range");
149             read_field(csa);
150             if (strcmp(csa->field, "f") == 0)
151                type = GLP_FR;
152             else if (strcmp(csa->field, "l") == 0)
153                type = GLP_LO;
154             else if (strcmp(csa->field, "u") == 0)
155                type = GLP_UP;
156             else if (strcmp(csa->field, "d") == 0)
157                type = GLP_DB;
158             else if (strcmp(csa->field, "s") == 0)
159                type = GLP_FX;
160             else
161                error(csa, "row type missing or invalid");
162             if (type == GLP_LO || type == GLP_DB || type == GLP_FX)
163             {  read_field(csa);
164                if (str2num(csa->field, &lb) != 0)
165                   error(csa, "row lower bound/fixed value missing or in"
166                      "valid");
167             }
168             else
169                lb = 0.0;
170             if (type == GLP_UP || type == GLP_DB)
171             {  read_field(csa);
172                if (str2num(csa->field, &ub) != 0)
173                   error(csa, "row upper bound missing or invalid");
174             }
175             else
176                ub = 0.0;
177             if (rf[i] & 0x01)
178                error(csa, "duplicate row descriptor");
179             glp_set_row_bnds(P, i, type, lb, ub), rf[i] |= 0x01;
180          }
181          else if (strcmp(csa->field, "j") == 0)
182          {  /* column descriptor */
183             read_field(csa);
184             if (str2int(csa->field, &j) != 0)
185                error(csa, "column number missing or invalid");
186             if (!(1 <= j && j <= n))
187                error(csa, "column number out of range");
188             if (!mip)
189                kind = GLP_CV;
190             else
191             {  read_field(csa);
192                if (strcmp(csa->field, "c") == 0)
193                   kind = GLP_CV;
194                else if (strcmp(csa->field, "i") == 0)
195                   kind = GLP_IV;
196                else if (strcmp(csa->field, "b") == 0)
197                {  kind = GLP_IV;
198                   type = GLP_DB, lb = 0.0, ub = 1.0;
199                   goto skip;
200                }
201                else
202                   error(csa, "column kind missing or invalid");
203             }
204             read_field(csa);
205             if (strcmp(csa->field, "f") == 0)
206                type = GLP_FR;
207             else if (strcmp(csa->field, "l") == 0)
208                type = GLP_LO;
209             else if (strcmp(csa->field, "u") == 0)
210                type = GLP_UP;
211             else if (strcmp(csa->field, "d") == 0)
212                type = GLP_DB;
213             else if (strcmp(csa->field, "s") == 0)
214                type = GLP_FX;
215             else
216                error(csa, "column type missing or invalid");
217             if (type == GLP_LO || type == GLP_DB || type == GLP_FX)
218             {  read_field(csa);
219                if (str2num(csa->field, &lb) != 0)
220                   error(csa, "column lower bound/fixed value missing or"
221                      " invalid");
222             }
223             else
224                lb = 0.0;
225             if (type == GLP_UP || type == GLP_DB)
226             {  read_field(csa);
227                if (str2num(csa->field, &ub) != 0)
228                   error(csa, "column upper bound missing or invalid");
229             }
230             else
231                ub = 0.0;
232 skip:       if (cf[j] & 0x01)
233                error(csa, "duplicate column descriptor");
234             glp_set_col_kind(P, j, kind);
235             glp_set_col_bnds(P, j, type, lb, ub), cf[j] |= 0x01;
236          }
237          else if (strcmp(csa->field, "a") == 0)
238          {  /* coefficient descriptor */
239             read_field(csa);
240             if (str2int(csa->field, &i) != 0)
241                error(csa, "row number missing or invalid");
242             if (!(0 <= i && i <= m))
243                error(csa, "row number out of range");
244             read_field(csa);
245             if (str2int(csa->field, &j) != 0)
246                error(csa, "column number missing or invalid");
247             if (!((i == 0 ? 0 : 1) <= j && j <= n))
248                error(csa, "column number out of range");
249             read_field(csa);
250             if (i == 0)
251             {  if (str2num(csa->field, &temp) != 0)
252                   error(csa, "objective %s missing or invalid",
253                      j == 0 ? "constant term" : "coefficient");
254                if (cf[j] & 0x10)
255                   error(csa, "duplicate objective %s",
256                      j == 0 ? "constant term" : "coefficient");
257                glp_set_obj_coef(P, j, temp), cf[j] |= 0x10;
258             }
259             else
260             {  if (str2num(csa->field, &temp) != 0)
261                   error(csa, "constraint coefficient missing or invalid"
262                      );
263                if (ne == nnz)
264                   error(csa, "too many constraint coefficient descripto"
265                      "rs");
266                ln[++ne] = csa->count;
267                ia[ne] = i, ja[ne] = j, ar[ne] = temp;
268             }
269          }
270          else if (strcmp(csa->field, "n") == 0)
271          {  /* symbolic name descriptor */
272             read_field(csa);
273             if (strcmp(csa->field, "p") == 0)
274             {  /* problem name */
275                read_field(csa);
276                if (P->name != NULL)
277                   error(csa, "duplicate problem name");
278                glp_set_prob_name(P, csa->field);
279             }
280             else if (strcmp(csa->field, "z") == 0)
281             {  /* objective name */
282                read_field(csa);
283                if (P->obj != NULL)
284                   error(csa, "duplicate objective name");
285                glp_set_obj_name(P, csa->field);
286             }
287             else if (strcmp(csa->field, "i") == 0)
288             {  /* row name */
289                read_field(csa);
290                if (str2int(csa->field, &i) != 0)
291                   error(csa, "row number missing or invalid");
292                if (!(1 <= i && i <= m))
293                   error(csa, "row number out of range");
294                read_field(csa);
295                if (P->row[i]->name != NULL)
296                   error(csa, "duplicate row name");
297                glp_set_row_name(P, i, csa->field);
298             }
299             else if (strcmp(csa->field, "j") == 0)
300             {  /* column name */
301                read_field(csa);
302                if (str2int(csa->field, &j) != 0)
303                   error(csa, "column number missing or invalid");
304                if (!(1 <= j && j <= n))
305                   error(csa, "column number out of range");
306                read_field(csa);
307                if (P->col[j]->name != NULL)
308                   error(csa, "duplicate column name");
309                glp_set_col_name(P, j, csa->field);
310             }
311             else
312                error(csa, "object designator missing or invalid");
313          }
314          else if (strcmp(csa->field, "e") == 0)
315             break;
316          else
317             error(csa, "line designator missing or invalid");
318          end_of_line(csa);
319       }
320       if (ne < nnz)
321          error(csa, "too few constraint coefficient descriptors");
322       xassert(ne == nnz);
323       k = glp_check_dup(m, n, ne, ia, ja);
324       xassert(0 <= k && k <= nnz);
325       if (k > 0)
326       {  csa->count = ln[k];
327          error(csa, "duplicate constraint coefficient");
328       }
329       glp_load_matrix(P, ne, ia, ja, ar);
330       /* print some statistics */
331       if (P->name != NULL)
332          xprintf("Problem: %s\n", P->name);
333       if (P->obj != NULL)
334          xprintf("Objective: %s\n", P->obj);
335       xprintf("%d row%s, %d column%s, %d non-zero%s\n",
336          m, m == 1 ? "" : "s", n, n == 1 ? "" : "s", nnz, nnz == 1 ?
337          "" : "s");
338       if (glp_get_num_int(P) > 0)
339       {  int ni = glp_get_num_int(P);
340          int nb = glp_get_num_bin(P);
341          if (ni == 1)
342          {  if (nb == 0)
343                xprintf("One variable is integer\n");
344             else
345                xprintf("One variable is binary\n");
346          }
347          else
348          {  xprintf("%d integer variables, ", ni);
349             if (nb == 0)
350                xprintf("none");
351             else if (nb == 1)
352                xprintf("one");
353             else if (nb == ni)
354                xprintf("all");
355             else
356                xprintf("%d", nb);
357             xprintf(" of which %s binary\n", nb == 1 ? "is" : "are");
358          }
359       }
360       xprintf("%d lines were read\n", csa->count);
361       /* problem data has been successfully read */
362       glp_sort_matrix(P);
363       ret = 0;
364 done: if (csa->fp != NULL) glp_close(csa->fp);
365       if (rf != NULL) xfree(rf);
366       if (cf != NULL) xfree(cf);
367       if (ln != NULL) xfree(ln);
368       if (ia != NULL) xfree(ia);
369       if (ja != NULL) xfree(ja);
370       if (ar != NULL) xfree(ar);
371       if (ret) glp_erase_prob(P);
372       return ret;
373 }
374 
375 /* eof */
376