1 /* glpdmx.c (reading/writing data in DIMACS format) */
3 /***********************************************************************
4 * This code is part of GLPK (GNU Linear Programming Kit).
6 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
7 * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
8 * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
9 * E-mail: <mao@gnu.org>.
11 * GLPK is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
16 * GLPK is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 * License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
23 ***********************************************************************/
29 { /* common storage area */
31 /* label for go to in case of error */
33 /* name of input text file */
35 /* stream assigned to input text file */
39 /* current character */
43 /* warning 'empty line ignored' was printed */
45 /* warning 'non-integer data detected' was printed */
48 static void error(struct csa *csa, const char *fmt, ...)
49 { /* print error message and terminate processing */
51 xprintf("%s:%d: error: ", csa->fname, csa->count);
56 longjmp(csa->jump, 1);
60 static void warning(struct csa *csa, const char *fmt, ...)
61 { /* print warning message and continue processing */
63 xprintf("%s:%d: warning: ", csa->fname, csa->count);
71 static void read_char(struct csa *csa)
72 { /* read character from input text file */
74 if (csa->c == '\n') csa->count++;
77 { if (xferror(csa->fp))
78 error(csa, "read error - %s", xerrmsg());
79 else if (csa->c == '\n')
80 error(csa, "unexpected end of file");
82 { warning(csa, "missing final end of line");
91 error(csa, "invalid control character 0x%02X", c);
96 static void read_designator(struct csa *csa)
97 { /* read one-character line designator */
98 xassert(csa->c == '\n');
101 { /* skip preceding white-space characters */
102 while (csa->c == ' ')
105 { /* ignore empty line */
107 { warning(csa, "empty line ignored");
112 else if (csa->c == 'c')
113 { /* skip comment line */
114 while (csa->c != '\n')
119 { /* hmm... looks like a line designator */
120 csa->field[0] = (char)csa->c, csa->field[1] = '\0';
121 /* check that it is followed by a white-space character */
123 if (!(csa->c == ' ' || csa->c == '\n'))
124 error(csa, "line designator missing or invalid");
131 static void read_field(struct csa *csa)
132 { /* read data field */
134 /* skip preceding white-space characters */
135 while (csa->c == ' ')
137 /* scan data field */
139 error(csa, "unexpected end of line");
140 while (!(csa->c == ' ' || csa->c == '\n'))
141 { if (len == sizeof(csa->field)-1)
142 error(csa, "data field `%.15s...' too long", csa->field);
143 csa->field[len++] = (char)csa->c;
146 csa->field[len] = '\0';
150 static void end_of_line(struct csa *csa)
151 { /* skip white-space characters until end of line */
152 while (csa->c == ' ')
155 error(csa, "too many data fields specified");
159 static void check_int(struct csa *csa, double num)
160 { /* print a warning if non-integer data are detected */
161 if (!csa->nonint && num != floor(num))
162 { warning(csa, "non-integer data detected");
168 /***********************************************************************
171 * glp_read_mincost - read min-cost flow problem data in DIMACS format
175 * int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
176 * int a_cost, const char *fname);
180 * The routine glp_read_mincost reads minimum cost flow problem data in
181 * DIMACS format from a text file.
185 * If the operation was successful, the routine returns zero. Otherwise
186 * it prints an error message and returns non-zero. */
188 int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
189 int a_cost, const char *fname)
190 { struct csa _csa, *csa = &_csa;
193 int i, j, k, nv, na, ret = 0;
194 double rhs, low, cap, cost;
196 if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
197 xerror("glp_read_mincost: v_rhs = %d; invalid offset\n",
199 if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
200 xerror("glp_read_mincost: a_low = %d; invalid offset\n",
202 if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
203 xerror("glp_read_mincost: a_cap = %d; invalid offset\n",
205 if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
206 xerror("glp_read_mincost: a_cost = %d; invalid offset\n",
208 glp_erase_graph(G, G->v_size, G->a_size);
209 if (setjmp(csa->jump))
217 csa->field[0] = '\0';
218 csa->empty = csa->nonint = 0;
219 xprintf("Reading min-cost flow problem data from `%s'...\n",
221 csa->fp = xfopen(fname, "r");
223 { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg());
224 longjmp(csa->jump, 1);
226 /* read problem line */
227 read_designator(csa);
228 if (strcmp(csa->field, "p") != 0)
229 error(csa, "problem line missing or invalid");
231 if (strcmp(csa->field, "min") != 0)
232 error(csa, "wrong problem designator; `min' expected");
234 if (!(str2int(csa->field, &nv) == 0 && nv >= 0))
235 error(csa, "number of nodes missing or invalid");
237 if (!(str2int(csa->field, &na) == 0 && na >= 0))
238 error(csa, "number of arcs missing or invalid");
239 xprintf("Flow network has %d node%s and %d arc%s\n",
240 nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s");
241 if (nv > 0) glp_add_vertices(G, nv);
243 /* read node descriptor lines */
244 flag = xcalloc(1+nv, sizeof(char));
245 memset(&flag[1], 0, nv * sizeof(char));
248 for (i = 1; i <= nv; i++)
250 memcpy((char *)v->data + v_rhs, &rhs, sizeof(double));
254 { read_designator(csa);
255 if (strcmp(csa->field, "n") != 0) break;
257 if (str2int(csa->field, &i) != 0)
258 error(csa, "node number missing or invalid");
259 if (!(1 <= i && i <= nv))
260 error(csa, "node number %d out of range", i);
262 error(csa, "duplicate descriptor of node %d", i);
264 if (str2num(csa->field, &rhs) != 0)
265 error(csa, "node supply/demand missing or invalid");
269 memcpy((char *)v->data + v_rhs, &rhs, sizeof(double));
274 xfree(flag), flag = NULL;
275 /* read arc descriptor lines */
276 for (k = 1; k <= na; k++)
277 { if (k > 1) read_designator(csa);
278 if (strcmp(csa->field, "a") != 0)
279 error(csa, "wrong line designator; `a' expected");
281 if (str2int(csa->field, &i) != 0)
282 error(csa, "starting node number missing or invalid");
283 if (!(1 <= i && i <= nv))
284 error(csa, "starting node number %d out of range", i);
286 if (str2int(csa->field, &j) != 0)
287 error(csa, "ending node number missing or invalid");
288 if (!(1 <= j && j <= nv))
289 error(csa, "ending node number %d out of range", j);
291 if (!(str2num(csa->field, &low) == 0 && low >= 0.0))
292 error(csa, "lower bound of arc flow missing or invalid");
295 if (!(str2num(csa->field, &cap) == 0 && cap >= low))
296 error(csa, "upper bound of arc flow missing or invalid");
299 if (str2num(csa->field, &cost) != 0)
300 error(csa, "per-unit cost of arc flow missing or invalid");
301 check_int(csa, cost);
302 a = glp_add_arc(G, i, j);
304 memcpy((char *)a->data + a_low, &low, sizeof(double));
306 memcpy((char *)a->data + a_cap, &cap, sizeof(double));
308 memcpy((char *)a->data + a_cost, &cost, sizeof(double));
311 xprintf("%d lines were read\n", csa->count);
312 done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
313 if (csa->fp != NULL) xfclose(csa->fp);
314 if (flag != NULL) xfree(flag);
318 /***********************************************************************
321 * glp_write_mincost - write min-cost flow problem data in DIMACS format
325 * int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
326 * int a_cost, const char *fname);
330 * The routine glp_write_mincost writes minimum cost flow problem data
331 * in DIMACS format to a text file.
335 * If the operation was successful, the routine returns zero. Otherwise
336 * it prints an error message and returns non-zero. */
338 int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
339 int a_cost, const char *fname)
343 int i, count = 0, ret;
344 double rhs, low, cap, cost;
345 if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
346 xerror("glp_write_mincost: v_rhs = %d; invalid offset\n",
348 if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
349 xerror("glp_write_mincost: a_low = %d; invalid offset\n",
351 if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
352 xerror("glp_write_mincost: a_cap = %d; invalid offset\n",
354 if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
355 xerror("glp_write_mincost: a_cost = %d; invalid offset\n",
357 xprintf("Writing min-cost flow problem data to `%s'...\n",
359 fp = xfopen(fname, "w");
361 { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
365 xfprintf(fp, "c %s\n",
366 G->name == NULL ? "unknown" : G->name), count++;
367 xfprintf(fp, "p min %d %d\n", G->nv, G->na), count++;
369 { for (i = 1; i <= G->nv; i++)
371 memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double));
373 xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, rhs), count++;
376 for (i = 1; i <= G->nv; i++)
378 for (a = v->out; a != NULL; a = a->t_next)
380 memcpy(&low, (char *)a->data + a_low, sizeof(double));
384 memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
388 memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
391 xfprintf(fp, "a %d %d %.*g %.*g %.*g\n",
392 a->tail->i, a->head->i, DBL_DIG, low, DBL_DIG, cap,
393 DBL_DIG, cost), count++;
396 xfprintf(fp, "c eof\n"), count++;
399 { xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
403 xprintf("%d lines were written\n", count);
405 done: if (fp != NULL) xfclose(fp);
409 /***********************************************************************
412 * glp_read_maxflow - read maximum flow problem data in DIMACS format
416 * int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap,
417 * const char *fname);
421 * The routine glp_read_maxflow reads maximum flow problem data in
422 * DIMACS format from a text file.
426 * If the operation was successful, the routine returns zero. Otherwise
427 * it prints an error message and returns non-zero. */
429 int glp_read_maxflow(glp_graph *G, int *_s, int *_t, int a_cap,
431 { struct csa _csa, *csa = &_csa;
433 int i, j, k, s, t, nv, na, ret = 0;
435 if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
436 xerror("glp_read_maxflow: a_cap = %d; invalid offset\n",
438 glp_erase_graph(G, G->v_size, G->a_size);
439 if (setjmp(csa->jump))
447 csa->field[0] = '\0';
448 csa->empty = csa->nonint = 0;
449 xprintf("Reading maximum flow problem data from `%s'...\n",
451 csa->fp = xfopen(fname, "r");
453 { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg());
454 longjmp(csa->jump, 1);
456 /* read problem line */
457 read_designator(csa);
458 if (strcmp(csa->field, "p") != 0)
459 error(csa, "problem line missing or invalid");
461 if (strcmp(csa->field, "max") != 0)
462 error(csa, "wrong problem designator; `max' expected");
464 if (!(str2int(csa->field, &nv) == 0 && nv >= 2))
465 error(csa, "number of nodes missing or invalid");
467 if (!(str2int(csa->field, &na) == 0 && na >= 0))
468 error(csa, "number of arcs missing or invalid");
469 xprintf("Flow network has %d node%s and %d arc%s\n",
470 nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s");
471 if (nv > 0) glp_add_vertices(G, nv);
473 /* read node descriptor lines */
476 { read_designator(csa);
477 if (strcmp(csa->field, "n") != 0) break;
479 if (str2int(csa->field, &i) != 0)
480 error(csa, "node number missing or invalid");
481 if (!(1 <= i && i <= nv))
482 error(csa, "node number %d out of range", i);
484 if (strcmp(csa->field, "s") == 0)
486 error(csa, "only one source node allowed");
489 else if (strcmp(csa->field, "t") == 0)
491 error(csa, "only one sink node allowed");
495 error(csa, "wrong node designator; `s' or `t' expected");
497 error(csa, "source and sink nodes must be distinct");
501 error(csa, "source node descriptor missing\n");
503 error(csa, "sink node descriptor missing\n");
504 if (_s != NULL) *_s = s;
505 if (_t != NULL) *_t = t;
506 /* read arc descriptor lines */
507 for (k = 1; k <= na; k++)
508 { if (k > 1) read_designator(csa);
509 if (strcmp(csa->field, "a") != 0)
510 error(csa, "wrong line designator; `a' expected");
512 if (str2int(csa->field, &i) != 0)
513 error(csa, "starting node number missing or invalid");
514 if (!(1 <= i && i <= nv))
515 error(csa, "starting node number %d out of range", i);
517 if (str2int(csa->field, &j) != 0)
518 error(csa, "ending node number missing or invalid");
519 if (!(1 <= j && j <= nv))
520 error(csa, "ending node number %d out of range", j);
522 if (!(str2num(csa->field, &cap) == 0 && cap >= 0.0))
523 error(csa, "arc capacity missing or invalid");
525 a = glp_add_arc(G, i, j);
527 memcpy((char *)a->data + a_cap, &cap, sizeof(double));
530 xprintf("%d lines were read\n", csa->count);
531 done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
532 if (csa->fp != NULL) xfclose(csa->fp);
536 /***********************************************************************
539 * glp_write_maxflow - write maximum flow problem data in DIMACS format
543 * int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap,
544 * const char *fname);
548 * The routine glp_write_maxflow writes maximum flow problem data in
549 * DIMACS format to a text file.
553 * If the operation was successful, the routine returns zero. Otherwise
554 * it prints an error message and returns non-zero. */
556 int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap,
561 int i, count = 0, ret;
563 if (!(1 <= s && s <= G->nv))
564 xerror("glp_write_maxflow: s = %d; source node number out of r"
566 if (!(1 <= t && t <= G->nv))
567 xerror("glp_write_maxflow: t = %d: sink node number out of ran"
569 if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
570 xerror("glp_write_mincost: a_cap = %d; invalid offset\n",
572 xprintf("Writing maximum flow problem data to `%s'...\n",
574 fp = xfopen(fname, "w");
576 { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
580 xfprintf(fp, "c %s\n",
581 G->name == NULL ? "unknown" : G->name), count++;
582 xfprintf(fp, "p max %d %d\n", G->nv, G->na), count++;
583 xfprintf(fp, "n %d s\n", s), count++;
584 xfprintf(fp, "n %d t\n", t), count++;
585 for (i = 1; i <= G->nv; i++)
587 for (a = v->out; a != NULL; a = a->t_next)
589 memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
592 xfprintf(fp, "a %d %d %.*g\n",
593 a->tail->i, a->head->i, DBL_DIG, cap), count++;
596 xfprintf(fp, "c eof\n"), count++;
599 { xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
603 xprintf("%d lines were written\n", count);
605 done: if (fp != NULL) xfclose(fp);
609 /***********************************************************************
612 * glp_read_asnprob - read assignment problem data in DIMACS format
616 * int glp_read_asnprob(glp_graph *G, int v_set, int a_cost,
617 * const char *fname);
621 * The routine glp_read_asnprob reads assignment problem data in DIMACS
622 * format from a text file.
626 * If the operation was successful, the routine returns zero. Otherwise
627 * it prints an error message and returns non-zero. */
629 int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char
631 { struct csa _csa, *csa = &_csa;
634 int nv, na, n1, i, j, k, ret = 0;
637 if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
638 xerror("glp_read_asnprob: v_set = %d; invalid offset\n",
640 if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
641 xerror("glp_read_asnprob: a_cost = %d; invalid offset\n",
643 glp_erase_graph(G, G->v_size, G->a_size);
644 if (setjmp(csa->jump))
652 csa->field[0] = '\0';
653 csa->empty = csa->nonint = 0;
654 xprintf("Reading assignment problem data from `%s'...\n", fname);
655 csa->fp = xfopen(fname, "r");
657 { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg());
658 longjmp(csa->jump, 1);
660 /* read problem line */
661 read_designator(csa);
662 if (strcmp(csa->field, "p") != 0)
663 error(csa, "problem line missing or invalid");
665 if (strcmp(csa->field, "asn") != 0)
666 error(csa, "wrong problem designator; `asn' expected");
668 if (!(str2int(csa->field, &nv) == 0 && nv >= 0))
669 error(csa, "number of nodes missing or invalid");
671 if (!(str2int(csa->field, &na) == 0 && na >= 0))
672 error(csa, "number of arcs missing or invalid");
673 if (nv > 0) glp_add_vertices(G, nv);
675 /* read node descriptor lines */
676 flag = xcalloc(1+nv, sizeof(char));
677 memset(&flag[1], 0, nv * sizeof(char));
680 { read_designator(csa);
681 if (strcmp(csa->field, "n") != 0) break;
683 if (str2int(csa->field, &i) != 0)
684 error(csa, "node number missing or invalid");
685 if (!(1 <= i && i <= nv))
686 error(csa, "node number %d out of range", i);
688 error(csa, "duplicate descriptor of node %d", i);
693 "Assignment problem has %d + %d = %d node%s and %d arc%s\n",
694 n1, nv - n1, nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s");
696 { for (i = 1; i <= nv; i++)
698 k = (flag[i] ? 0 : 1);
699 memcpy((char *)v->data + v_set, &k, sizeof(int));
702 /* read arc descriptor lines */
703 for (k = 1; k <= na; k++)
704 { if (k > 1) read_designator(csa);
705 if (strcmp(csa->field, "a") != 0)
706 error(csa, "wrong line designator; `a' expected");
708 if (str2int(csa->field, &i) != 0)
709 error(csa, "starting node number missing or invalid");
710 if (!(1 <= i && i <= nv))
711 error(csa, "starting node number %d out of range", i);
713 error(csa, "node %d cannot be a starting node", i);
715 if (str2int(csa->field, &j) != 0)
716 error(csa, "ending node number missing or invalid");
717 if (!(1 <= j && j <= nv))
718 error(csa, "ending node number %d out of range", j);
720 error(csa, "node %d cannot be an ending node", j);
722 if (str2num(csa->field, &cost) != 0)
723 error(csa, "arc cost missing or invalid");
724 check_int(csa, cost);
725 a = glp_add_arc(G, i, j);
727 memcpy((char *)a->data + a_cost, &cost, sizeof(double));
730 xprintf("%d lines were read\n", csa->count);
731 done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
732 if (csa->fp != NULL) xfclose(csa->fp);
733 if (flag != NULL) xfree(flag);
737 /***********************************************************************
740 * glp_write_asnprob - write assignment problem data in DIMACS format
744 * int glp_write_asnprob(glp_graph *G, int v_set, int a_cost,
745 * const char *fname);
749 * The routine glp_write_asnprob writes assignment problem data in
750 * DIMACS format to a text file.
754 * If the operation was successful, the routine returns zero. Otherwise
755 * it prints an error message and returns non-zero. */
757 int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char
762 int i, k, count = 0, ret;
764 if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
765 xerror("glp_write_asnprob: v_set = %d; invalid offset\n",
767 if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
768 xerror("glp_write_asnprob: a_cost = %d; invalid offset\n",
770 xprintf("Writing assignment problem data to `%s'...\n", fname);
771 fp = xfopen(fname, "w");
773 { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
777 xfprintf(fp, "c %s\n",
778 G->name == NULL ? "unknown" : G->name), count++;
779 xfprintf(fp, "p asn %d %d\n", G->nv, G->na), count++;
780 for (i = 1; i <= G->nv; i++)
783 memcpy(&k, (char *)v->data + v_set, sizeof(int));
785 k = (v->out != NULL ? 0 : 1);
787 xfprintf(fp, "n %d\n", i), count++;
789 for (i = 1; i <= G->nv; i++)
791 for (a = v->out; a != NULL; a = a->t_next)
793 memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
796 xfprintf(fp, "a %d %d %.*g\n",
797 a->tail->i, a->head->i, DBL_DIG, cost), count++;
800 xfprintf(fp, "c eof\n"), count++;
803 { xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
807 xprintf("%d lines were written\n", count);
809 done: if (fp != NULL) xfclose(fp);
813 /***********************************************************************
816 * glp_read_ccdata - read graph in DIMACS clique/coloring format
820 * int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname);
824 * The routine glp_read_ccdata reads an (undirected) graph in DIMACS
825 * clique/coloring format from a text file.
829 * If the operation was successful, the routine returns zero. Otherwise
830 * it prints an error message and returns non-zero. */
832 int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname)
833 { struct csa _csa, *csa = &_csa;
835 int i, j, k, nv, ne, ret = 0;
838 if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double))
839 xerror("glp_read_ccdata: v_wgt = %d; invalid offset\n",
841 glp_erase_graph(G, G->v_size, G->a_size);
842 if (setjmp(csa->jump))
850 csa->field[0] = '\0';
851 csa->empty = csa->nonint = 0;
852 xprintf("Reading graph from `%s'...\n", fname);
853 csa->fp = xfopen(fname, "r");
855 { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg());
856 longjmp(csa->jump, 1);
858 /* read problem line */
859 read_designator(csa);
860 if (strcmp(csa->field, "p") != 0)
861 error(csa, "problem line missing or invalid");
863 if (strcmp(csa->field, "edge") != 0)
864 error(csa, "wrong problem designator; `edge' expected");
866 if (!(str2int(csa->field, &nv) == 0 && nv >= 0))
867 error(csa, "number of vertices missing or invalid");
869 if (!(str2int(csa->field, &ne) == 0 && ne >= 0))
870 error(csa, "number of edges missing or invalid");
871 xprintf("Graph has %d vert%s and %d edge%s\n",
872 nv, nv == 1 ? "ex" : "ices", ne, ne == 1 ? "" : "s");
873 if (nv > 0) glp_add_vertices(G, nv);
875 /* read node descriptor lines */
876 flag = xcalloc(1+nv, sizeof(char));
877 memset(&flag[1], 0, nv * sizeof(char));
880 for (i = 1; i <= nv; i++)
882 memcpy((char *)v->data + v_wgt, &w, sizeof(double));
886 { read_designator(csa);
887 if (strcmp(csa->field, "n") != 0) break;
889 if (str2int(csa->field, &i) != 0)
890 error(csa, "vertex number missing or invalid");
891 if (!(1 <= i && i <= nv))
892 error(csa, "vertex number %d out of range", i);
894 error(csa, "duplicate descriptor of vertex %d", i);
896 if (str2num(csa->field, &w) != 0)
897 error(csa, "vertex weight missing or invalid");
901 memcpy((char *)v->data + v_wgt, &w, sizeof(double));
906 xfree(flag), flag = NULL;
907 /* read edge descriptor lines */
908 for (k = 1; k <= ne; k++)
909 { if (k > 1) read_designator(csa);
910 if (strcmp(csa->field, "e") != 0)
911 error(csa, "wrong line designator; `e' expected");
913 if (str2int(csa->field, &i) != 0)
914 error(csa, "first vertex number missing or invalid");
915 if (!(1 <= i && i <= nv))
916 error(csa, "first vertex number %d out of range", i);
918 if (str2int(csa->field, &j) != 0)
919 error(csa, "second vertex number missing or invalid");
920 if (!(1 <= j && j <= nv))
921 error(csa, "second vertex number %d out of range", j);
922 glp_add_arc(G, i, j);
925 xprintf("%d lines were read\n", csa->count);
926 done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
927 if (csa->fp != NULL) xfclose(csa->fp);
928 if (flag != NULL) xfree(flag);
932 /***********************************************************************
935 * glp_write_ccdata - write graph in DIMACS clique/coloring format
939 * int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname);
943 * The routine glp_write_ccdata writes the specified graph in DIMACS
944 * clique/coloring format to a text file.
948 * If the operation was successful, the routine returns zero. Otherwise
949 * it prints an error message and returns non-zero. */
951 int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname)
955 int i, count = 0, ret;
957 if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double))
958 xerror("glp_write_ccdata: v_wgt = %d; invalid offset\n",
960 xprintf("Writing graph to `%s'\n", fname);
961 fp = xfopen(fname, "w");
963 { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
967 xfprintf(fp, "c %s\n",
968 G->name == NULL ? "unknown" : G->name), count++;
969 xfprintf(fp, "p edge %d %d\n", G->nv, G->na), count++;
971 { for (i = 1; i <= G->nv; i++)
973 memcpy(&w, (char *)v->data + v_wgt, sizeof(double));
975 xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, w), count++;
978 for (i = 1; i <= G->nv; i++)
980 for (e = v->out; e != NULL; e = e->t_next)
981 xfprintf(fp, "e %d %d\n", e->tail->i, e->head->i), count++;
983 xfprintf(fp, "c eof\n"), count++;
986 { xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
990 xprintf("%d lines were written\n", count);
992 done: if (fp != NULL) xfclose(fp);
996 /***********************************************************************
999 * glp_read_prob - read problem data in GLPK format
1003 * int glp_read_prob(glp_prob *P, int flags, const char *fname);
1005 * The routine glp_read_prob reads problem data in GLPK LP/MIP format
1010 * If the operation was successful, the routine returns zero. Otherwise
1011 * it prints an error message and returns non-zero. */
1013 int glp_read_prob(glp_prob *P, int flags, const char *fname)
1014 { struct csa _csa, *csa = &_csa;
1015 int mip, m, n, nnz, ne, i, j, k, type, kind, ret, *ln = NULL,
1016 *ia = NULL, *ja = NULL;
1017 double lb, ub, temp, *ar = NULL;
1018 char *rf = NULL, *cf = NULL;
1019 if (P == NULL || P->magic != GLP_PROB_MAGIC)
1020 xerror("glp_read_prob: P = %p; invalid problem object\n",
1023 xerror("glp_read_prob: flags = %d; invalid parameter\n",
1026 xerror("glp_read_prob: fname = %d; invalid parameter\n",
1029 if (setjmp(csa->jump))
1037 csa->field[0] = '\0';
1038 csa->empty = csa->nonint = 0;
1039 xprintf("Reading problem data from `%s'...\n", fname);
1040 csa->fp = xfopen(fname, "r");
1041 if (csa->fp == NULL)
1042 { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg());
1043 longjmp(csa->jump, 1);
1045 /* read problem line */
1046 read_designator(csa);
1047 if (strcmp(csa->field, "p") != 0)
1048 error(csa, "problem line missing or invalid");
1050 if (strcmp(csa->field, "lp") == 0)
1052 else if (strcmp(csa->field, "mip") == 0)
1055 error(csa, "wrong problem designator; `lp' or `mip' expected\n"
1058 if (strcmp(csa->field, "min") == 0)
1059 glp_set_obj_dir(P, GLP_MIN);
1060 else if (strcmp(csa->field, "max") == 0)
1061 glp_set_obj_dir(P, GLP_MAX);
1063 error(csa, "objective sense missing or invalid");
1065 if (!(str2int(csa->field, &m) == 0 && m >= 0))
1066 error(csa, "number of rows missing or invalid");
1068 if (!(str2int(csa->field, &n) == 0 && n >= 0))
1069 error(csa, "number of columns missing or invalid");
1071 if (!(str2int(csa->field, &nnz) == 0 && nnz >= 0))
1072 error(csa, "number of constraint coefficients missing or inval"
1075 { glp_add_rows(P, m);
1076 for (i = 1; i <= m; i++)
1077 glp_set_row_bnds(P, i, GLP_FX, 0.0, 0.0);
1080 { glp_add_cols(P, n);
1081 for (j = 1; j <= n; j++)
1083 glp_set_col_bnds(P, j, GLP_LO, 0.0, 0.0);
1085 glp_set_col_kind(P, j, GLP_BV);
1089 /* allocate working arrays */
1090 rf = xcalloc(1+m, sizeof(char));
1092 cf = xcalloc(1+n, sizeof(char));
1094 ln = xcalloc(1+nnz, sizeof(int));
1095 ia = xcalloc(1+nnz, sizeof(int));
1096 ja = xcalloc(1+nnz, sizeof(int));
1097 ar = xcalloc(1+nnz, sizeof(double));
1098 /* read descriptor lines */
1101 { read_designator(csa);
1102 if (strcmp(csa->field, "i") == 0)
1103 { /* row descriptor */
1105 if (str2int(csa->field, &i) != 0)
1106 error(csa, "row number missing or invalid");
1107 if (!(1 <= i && i <= m))
1108 error(csa, "row number out of range");
1110 if (strcmp(csa->field, "f") == 0)
1112 else if (strcmp(csa->field, "l") == 0)
1114 else if (strcmp(csa->field, "u") == 0)
1116 else if (strcmp(csa->field, "d") == 0)
1118 else if (strcmp(csa->field, "s") == 0)
1121 error(csa, "row type missing or invalid");
1122 if (type == GLP_LO || type == GLP_DB || type == GLP_FX)
1124 if (str2num(csa->field, &lb) != 0)
1125 error(csa, "row lower bound/fixed value missing or in"
1130 if (type == GLP_UP || type == GLP_DB)
1132 if (str2num(csa->field, &ub) != 0)
1133 error(csa, "row upper bound missing or invalid");
1138 error(csa, "duplicate row descriptor");
1139 glp_set_row_bnds(P, i, type, lb, ub), rf[i] |= 0x01;
1141 else if (strcmp(csa->field, "j") == 0)
1142 { /* column descriptor */
1144 if (str2int(csa->field, &j) != 0)
1145 error(csa, "column number missing or invalid");
1146 if (!(1 <= j && j <= n))
1147 error(csa, "column number out of range");
1152 if (strcmp(csa->field, "c") == 0)
1154 else if (strcmp(csa->field, "i") == 0)
1156 else if (strcmp(csa->field, "b") == 0)
1158 type = GLP_DB, lb = 0.0, ub = 1.0;
1162 error(csa, "column kind missing or invalid");
1165 if (strcmp(csa->field, "f") == 0)
1167 else if (strcmp(csa->field, "l") == 0)
1169 else if (strcmp(csa->field, "u") == 0)
1171 else if (strcmp(csa->field, "d") == 0)
1173 else if (strcmp(csa->field, "s") == 0)
1176 error(csa, "column type missing or invalid");
1177 if (type == GLP_LO || type == GLP_DB || type == GLP_FX)
1179 if (str2num(csa->field, &lb) != 0)
1180 error(csa, "column lower bound/fixed value missing or"
1185 if (type == GLP_UP || type == GLP_DB)
1187 if (str2num(csa->field, &ub) != 0)
1188 error(csa, "column upper bound missing or invalid");
1192 skip: if (cf[j] & 0x01)
1193 error(csa, "duplicate column descriptor");
1194 glp_set_col_kind(P, j, kind);
1195 glp_set_col_bnds(P, j, type, lb, ub), cf[j] |= 0x01;
1197 else if (strcmp(csa->field, "a") == 0)
1198 { /* coefficient descriptor */
1200 if (str2int(csa->field, &i) != 0)
1201 error(csa, "row number missing or invalid");
1202 if (!(0 <= i && i <= m))
1203 error(csa, "row number out of range");
1205 if (str2int(csa->field, &j) != 0)
1206 error(csa, "column number missing or invalid");
1207 if (!((i == 0 ? 0 : 1) <= j && j <= n))
1208 error(csa, "column number out of range");
1211 { if (str2num(csa->field, &temp) != 0)
1212 error(csa, "objective %s missing or invalid",
1213 j == 0 ? "constant term" : "coefficient");
1215 error(csa, "duplicate objective %s",
1216 j == 0 ? "constant term" : "coefficient");
1217 glp_set_obj_coef(P, j, temp), cf[j] |= 0x10;
1220 { if (str2num(csa->field, &temp) != 0)
1221 error(csa, "constraint coefficient missing or invalid"
1224 error(csa, "too many constraint coefficient descripto"
1226 ln[++ne] = csa->count;
1227 ia[ne] = i, ja[ne] = j, ar[ne] = temp;
1230 else if (strcmp(csa->field, "n") == 0)
1231 { /* symbolic name descriptor */
1233 if (strcmp(csa->field, "p") == 0)
1234 { /* problem name */
1236 if (P->name != NULL)
1237 error(csa, "duplicate problem name");
1238 glp_set_prob_name(P, csa->field);
1240 else if (strcmp(csa->field, "z") == 0)
1241 { /* objective name */
1244 error(csa, "duplicate objective name");
1245 glp_set_obj_name(P, csa->field);
1247 else if (strcmp(csa->field, "i") == 0)
1250 if (str2int(csa->field, &i) != 0)
1251 error(csa, "row number missing or invalid");
1252 if (!(1 <= i && i <= m))
1253 error(csa, "row number out of range");
1255 if (P->row[i]->name != NULL)
1256 error(csa, "duplicate row name");
1257 glp_set_row_name(P, i, csa->field);
1259 else if (strcmp(csa->field, "j") == 0)
1262 if (str2int(csa->field, &j) != 0)
1263 error(csa, "column number missing or invalid");
1264 if (!(1 <= j && j <= n))
1265 error(csa, "column number out of range");
1267 if (P->col[j]->name != NULL)
1268 error(csa, "duplicate column name");
1269 glp_set_col_name(P, j, csa->field);
1272 error(csa, "object designator missing or invalid");
1274 else if (strcmp(csa->field, "e") == 0)
1277 error(csa, "line designator missing or invalid");
1281 error(csa, "too few constraint coefficient descriptors");
1283 k = glp_check_dup(m, n, ne, ia, ja);
1284 xassert(0 <= k && k <= nnz);
1286 { csa->count = ln[k];
1287 error(csa, "duplicate constraint coefficient");
1289 glp_load_matrix(P, ne, ia, ja, ar);
1290 /* print some statistics */
1291 if (P->name != NULL)
1292 xprintf("Problem: %s\n", P->name);
1294 xprintf("Objective: %s\n", P->obj);
1295 xprintf("%d row%s, %d column%s, %d non-zero%s\n",
1296 m, m == 1 ? "" : "s", n, n == 1 ? "" : "s", nnz, nnz == 1 ?
1298 if (glp_get_num_int(P) > 0)
1299 { int ni = glp_get_num_int(P);
1300 int nb = glp_get_num_bin(P);
1303 xprintf("One variable is integer\n");
1305 xprintf("One variable is binary\n");
1308 { xprintf("%d integer variables, ", ni);
1317 xprintf(" of which %s binary\n", nb == 1 ? "is" : "are");
1320 xprintf("%d lines were read\n", csa->count);
1321 /* problem data has been successfully read */
1324 done: if (csa->fp != NULL) xfclose(csa->fp);
1325 if (rf != NULL) xfree(rf);
1326 if (cf != NULL) xfree(cf);
1327 if (ln != NULL) xfree(ln);
1328 if (ia != NULL) xfree(ia);
1329 if (ja != NULL) xfree(ja);
1330 if (ar != NULL) xfree(ar);
1331 if (ret) glp_erase_prob(P);
1335 /***********************************************************************
1338 * glp_write_prob - write problem data in GLPK format
1342 * int glp_write_prob(glp_prob *P, int flags, const char *fname);
1344 * The routine glp_write_prob writes problem data in GLPK LP/MIP format
1349 * If the operation was successful, the routine returns zero. Otherwise
1350 * it prints an error message and returns non-zero. */
1352 int glp_write_prob(glp_prob *P, int flags, const char *fname)
1357 int mip, i, j, count, ret;
1358 if (P == NULL || P->magic != GLP_PROB_MAGIC)
1359 xerror("glp_write_prob: P = %p; invalid problem object\n",
1362 xerror("glp_write_prob: flags = %d; invalid parameter\n",
1365 xerror("glp_write_prob: fname = %d; invalid parameter\n",
1367 xprintf("Writing problem data to `%s'...\n", fname);
1368 fp = xfopen(fname, "w"), count = 0;
1370 { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
1374 /* write problem line */
1375 mip = (glp_get_num_int(P) > 0);
1376 xfprintf(fp, "p %s %s %d %d %d\n", !mip ? "lp" : "mip",
1377 P->dir == GLP_MIN ? "min" : P->dir == GLP_MAX ? "max" : "???",
1378 P->m, P->n, P->nnz), count++;
1379 if (P->name != NULL)
1380 xfprintf(fp, "n p %s\n", P->name), count++;
1382 xfprintf(fp, "n z %s\n", P->obj), count++;
1383 /* write row descriptors */
1384 for (i = 1; i <= P->m; i++)
1386 if (row->type == GLP_FX && row->lb == 0.0)
1388 xfprintf(fp, "i %d ", i), count++;
1389 if (row->type == GLP_FR)
1390 xfprintf(fp, "f\n");
1391 else if (row->type == GLP_LO)
1392 xfprintf(fp, "l %.*g\n", DBL_DIG, row->lb);
1393 else if (row->type == GLP_UP)
1394 xfprintf(fp, "u %.*g\n", DBL_DIG, row->ub);
1395 else if (row->type == GLP_DB)
1396 xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, row->lb, DBL_DIG,
1398 else if (row->type == GLP_FX)
1399 xfprintf(fp, "s %.*g\n", DBL_DIG, row->lb);
1401 xassert(row != row);
1402 skip1: if (row->name != NULL)
1403 xfprintf(fp, "n i %d %s\n", i, row->name), count++;
1405 /* write column descriptors */
1406 for (j = 1; j <= P->n; j++)
1408 if (!mip && col->type == GLP_LO && col->lb == 0.0)
1410 if (mip && col->kind == GLP_IV && col->type == GLP_DB &&
1411 col->lb == 0.0 && col->ub == 1.0)
1413 xfprintf(fp, "j %d ", j), count++;
1415 { if (col->kind == GLP_CV)
1417 else if (col->kind == GLP_IV)
1420 xassert(col != col);
1422 if (col->type == GLP_FR)
1423 xfprintf(fp, "f\n");
1424 else if (col->type == GLP_LO)
1425 xfprintf(fp, "l %.*g\n", DBL_DIG, col->lb);
1426 else if (col->type == GLP_UP)
1427 xfprintf(fp, "u %.*g\n", DBL_DIG, col->ub);
1428 else if (col->type == GLP_DB)
1429 xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, col->lb, DBL_DIG,
1431 else if (col->type == GLP_FX)
1432 xfprintf(fp, "s %.*g\n", DBL_DIG, col->lb);
1434 xassert(col != col);
1435 skip2: if (col->name != NULL)
1436 xfprintf(fp, "n j %d %s\n", j, col->name), count++;
1438 /* write objective coefficient descriptors */
1440 xfprintf(fp, "a 0 0 %.*g\n", DBL_DIG, P->c0), count++;
1441 for (j = 1; j <= P->n; j++)
1443 if (col->coef != 0.0)
1444 xfprintf(fp, "a 0 %d %.*g\n", j, DBL_DIG, col->coef),
1447 /* write constraint coefficient descriptors */
1448 for (i = 1; i <= P->m; i++)
1450 for (aij = row->ptr; aij != NULL; aij = aij->r_next)
1451 xfprintf(fp, "a %d %d %.*g\n", i, aij->col->j, DBL_DIG,
1454 /* write end line */
1455 xfprintf(fp, "e o f\n"), count++;
1458 { xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
1462 xprintf("%d lines were written\n", count);
1464 done: if (fp != NULL) xfclose(fp);