src/glpdmx.c
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 06 Dec 2010 13:09:21 +0100
changeset 1 c445c931472f
permissions -rw-r--r--
Import glpk-4.45

- Generated files and doc/notes are removed
alpar@1
     1
/* glpdmx.c (reading/writing data in DIMACS format) */
alpar@1
     2
alpar@1
     3
/***********************************************************************
alpar@1
     4
*  This code is part of GLPK (GNU Linear Programming Kit).
alpar@1
     5
*
alpar@1
     6
*  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
alpar@1
     7
*  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
alpar@1
     8
*  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
alpar@1
     9
*  E-mail: <mao@gnu.org>.
alpar@1
    10
*
alpar@1
    11
*  GLPK is free software: you can redistribute it and/or modify it
alpar@1
    12
*  under the terms of the GNU General Public License as published by
alpar@1
    13
*  the Free Software Foundation, either version 3 of the License, or
alpar@1
    14
*  (at your option) any later version.
alpar@1
    15
*
alpar@1
    16
*  GLPK is distributed in the hope that it will be useful, but WITHOUT
alpar@1
    17
*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
alpar@1
    18
*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
alpar@1
    19
*  License for more details.
alpar@1
    20
*
alpar@1
    21
*  You should have received a copy of the GNU General Public License
alpar@1
    22
*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
alpar@1
    23
***********************************************************************/
alpar@1
    24
alpar@1
    25
#define _GLPSTD_STDIO
alpar@1
    26
#include "glpapi.h"
alpar@1
    27
alpar@1
    28
struct csa
alpar@1
    29
{     /* common storage area */
alpar@1
    30
      jmp_buf jump;
alpar@1
    31
      /* label for go to in case of error */
alpar@1
    32
      const char *fname;
alpar@1
    33
      /* name of input text file */
alpar@1
    34
      XFILE *fp;
alpar@1
    35
      /* stream assigned to input text file */
alpar@1
    36
      int count;
alpar@1
    37
      /* line count */
alpar@1
    38
      int c;
alpar@1
    39
      /* current character */
alpar@1
    40
      char field[255+1];
alpar@1
    41
      /* data field */
alpar@1
    42
      int empty;
alpar@1
    43
      /* warning 'empty line ignored' was printed */
alpar@1
    44
      int nonint;
alpar@1
    45
      /* warning 'non-integer data detected' was printed */
alpar@1
    46
};
alpar@1
    47
alpar@1
    48
static void error(struct csa *csa, const char *fmt, ...)
alpar@1
    49
{     /* print error message and terminate processing */
alpar@1
    50
      va_list arg;
alpar@1
    51
      xprintf("%s:%d: error: ", csa->fname, csa->count);
alpar@1
    52
      va_start(arg, fmt);
alpar@1
    53
      xvprintf(fmt, arg);
alpar@1
    54
      va_end(arg);
alpar@1
    55
      xprintf("\n");
alpar@1
    56
      longjmp(csa->jump, 1);
alpar@1
    57
      /* no return */
alpar@1
    58
}
alpar@1
    59
alpar@1
    60
static void warning(struct csa *csa, const char *fmt, ...)
alpar@1
    61
{     /* print warning message and continue processing */
alpar@1
    62
      va_list arg;
alpar@1
    63
      xprintf("%s:%d: warning: ", csa->fname, csa->count);
alpar@1
    64
      va_start(arg, fmt);
alpar@1
    65
      xvprintf(fmt, arg);
alpar@1
    66
      va_end(arg);
alpar@1
    67
      xprintf("\n");
alpar@1
    68
      return;
alpar@1
    69
}
alpar@1
    70
alpar@1
    71
static void read_char(struct csa *csa)
alpar@1
    72
{     /* read character from input text file */
alpar@1
    73
      int c;
alpar@1
    74
      if (csa->c == '\n') csa->count++;
alpar@1
    75
      c = xfgetc(csa->fp);
alpar@1
    76
      if (c < 0)
alpar@1
    77
      {  if (xferror(csa->fp))
alpar@1
    78
            error(csa, "read error - %s", xerrmsg());
alpar@1
    79
         else if (csa->c == '\n')
alpar@1
    80
            error(csa, "unexpected end of file");
alpar@1
    81
         else
alpar@1
    82
         {  warning(csa, "missing final end of line");
alpar@1
    83
            c = '\n';
alpar@1
    84
         }
alpar@1
    85
      }
alpar@1
    86
      else if (c == '\n')
alpar@1
    87
         ;
alpar@1
    88
      else if (isspace(c))
alpar@1
    89
         c = ' ';
alpar@1
    90
      else if (iscntrl(c))
alpar@1
    91
         error(csa, "invalid control character 0x%02X", c);
alpar@1
    92
      csa->c = c;
alpar@1
    93
      return;
alpar@1
    94
}
alpar@1
    95
alpar@1
    96
static void read_designator(struct csa *csa)
alpar@1
    97
{     /* read one-character line designator */
alpar@1
    98
      xassert(csa->c == '\n');
alpar@1
    99
      read_char(csa);
alpar@1
   100
      for (;;)
alpar@1
   101
      {  /* skip preceding white-space characters */
alpar@1
   102
         while (csa->c == ' ')
alpar@1
   103
            read_char(csa);
alpar@1
   104
         if (csa->c == '\n')
alpar@1
   105
         {  /* ignore empty line */
alpar@1
   106
            if (!csa->empty)
alpar@1
   107
            {  warning(csa, "empty line ignored");
alpar@1
   108
               csa->empty = 1;
alpar@1
   109
            }
alpar@1
   110
            read_char(csa);
alpar@1
   111
         }
alpar@1
   112
         else if (csa->c == 'c')
alpar@1
   113
         {  /* skip comment line */
alpar@1
   114
            while (csa->c != '\n')
alpar@1
   115
               read_char(csa);
alpar@1
   116
            read_char(csa);
alpar@1
   117
         }
alpar@1
   118
         else
alpar@1
   119
         {  /* hmm... looks like a line designator */
alpar@1
   120
            csa->field[0] = (char)csa->c, csa->field[1] = '\0';
alpar@1
   121
            /* check that it is followed by a white-space character */
alpar@1
   122
            read_char(csa);
alpar@1
   123
            if (!(csa->c == ' ' || csa->c == '\n'))
alpar@1
   124
               error(csa, "line designator missing or invalid");
alpar@1
   125
            break;
alpar@1
   126
         }
alpar@1
   127
      }
alpar@1
   128
      return;
alpar@1
   129
}
alpar@1
   130
alpar@1
   131
static void read_field(struct csa *csa)
alpar@1
   132
{     /* read data field */
alpar@1
   133
      int len = 0;
alpar@1
   134
      /* skip preceding white-space characters */
alpar@1
   135
      while (csa->c == ' ')
alpar@1
   136
         read_char(csa);
alpar@1
   137
      /* scan data field */
alpar@1
   138
      if (csa->c == '\n')
alpar@1
   139
         error(csa, "unexpected end of line");
alpar@1
   140
      while (!(csa->c == ' ' || csa->c == '\n'))
alpar@1
   141
      {  if (len == sizeof(csa->field)-1)
alpar@1
   142
            error(csa, "data field `%.15s...' too long", csa->field);
alpar@1
   143
         csa->field[len++] = (char)csa->c;
alpar@1
   144
         read_char(csa);
alpar@1
   145
      }
alpar@1
   146
      csa->field[len] = '\0';
alpar@1
   147
      return;
alpar@1
   148
}
alpar@1
   149
alpar@1
   150
static void end_of_line(struct csa *csa)
alpar@1
   151
{     /* skip white-space characters until end of line */
alpar@1
   152
      while (csa->c == ' ')
alpar@1
   153
         read_char(csa);
alpar@1
   154
      if (csa->c != '\n')
alpar@1
   155
         error(csa, "too many data fields specified");
alpar@1
   156
      return;
alpar@1
   157
}
alpar@1
   158
alpar@1
   159
static void check_int(struct csa *csa, double num)
alpar@1
   160
{     /* print a warning if non-integer data are detected */
alpar@1
   161
      if (!csa->nonint && num != floor(num))
alpar@1
   162
      {  warning(csa, "non-integer data detected");
alpar@1
   163
         csa->nonint = 1;
alpar@1
   164
      }
alpar@1
   165
      return;
alpar@1
   166
}
alpar@1
   167
alpar@1
   168
/***********************************************************************
alpar@1
   169
*  NAME
alpar@1
   170
*
alpar@1
   171
*  glp_read_mincost - read min-cost flow problem data in DIMACS format
alpar@1
   172
*
alpar@1
   173
*  SYNOPSIS
alpar@1
   174
*
alpar@1
   175
*  int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
alpar@1
   176
*     int a_cost, const char *fname);
alpar@1
   177
*
alpar@1
   178
*  DESCRIPTION
alpar@1
   179
*
alpar@1
   180
*  The routine glp_read_mincost reads minimum cost flow problem data in
alpar@1
   181
*  DIMACS format from a text file.
alpar@1
   182
*
alpar@1
   183
*  RETURNS
alpar@1
   184
*
alpar@1
   185
*  If the operation was successful, the routine returns zero. Otherwise
alpar@1
   186
*  it prints an error message and returns non-zero. */
alpar@1
   187
alpar@1
   188
int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
alpar@1
   189
      int a_cost, const char *fname)
alpar@1
   190
{     struct csa _csa, *csa = &_csa;
alpar@1
   191
      glp_vertex *v;
alpar@1
   192
      glp_arc *a;
alpar@1
   193
      int i, j, k, nv, na, ret = 0;
alpar@1
   194
      double rhs, low, cap, cost;
alpar@1
   195
      char *flag = NULL;
alpar@1
   196
      if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
alpar@1
   197
         xerror("glp_read_mincost: v_rhs = %d; invalid offset\n",
alpar@1
   198
            v_rhs);
alpar@1
   199
      if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
alpar@1
   200
         xerror("glp_read_mincost: a_low = %d; invalid offset\n",
alpar@1
   201
            a_low);
alpar@1
   202
      if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
alpar@1
   203
         xerror("glp_read_mincost: a_cap = %d; invalid offset\n",
alpar@1
   204
            a_cap);
alpar@1
   205
      if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
alpar@1
   206
         xerror("glp_read_mincost: a_cost = %d; invalid offset\n",
alpar@1
   207
            a_cost);
alpar@1
   208
      glp_erase_graph(G, G->v_size, G->a_size);
alpar@1
   209
      if (setjmp(csa->jump))
alpar@1
   210
      {  ret = 1;
alpar@1
   211
         goto done;
alpar@1
   212
      }
alpar@1
   213
      csa->fname = fname;
alpar@1
   214
      csa->fp = NULL;
alpar@1
   215
      csa->count = 0;
alpar@1
   216
      csa->c = '\n';
alpar@1
   217
      csa->field[0] = '\0';
alpar@1
   218
      csa->empty = csa->nonint = 0;
alpar@1
   219
      xprintf("Reading min-cost flow problem data from `%s'...\n",
alpar@1
   220
         fname);
alpar@1
   221
      csa->fp = xfopen(fname, "r");
alpar@1
   222
      if (csa->fp == NULL)
alpar@1
   223
      {  xprintf("Unable to open `%s' - %s\n", fname, xerrmsg());
alpar@1
   224
         longjmp(csa->jump, 1);
alpar@1
   225
      }
alpar@1
   226
      /* read problem line */
alpar@1
   227
      read_designator(csa);
alpar@1
   228
      if (strcmp(csa->field, "p") != 0)
alpar@1
   229
         error(csa, "problem line missing or invalid");
alpar@1
   230
      read_field(csa);
alpar@1
   231
      if (strcmp(csa->field, "min") != 0)
alpar@1
   232
         error(csa, "wrong problem designator; `min' expected");
alpar@1
   233
      read_field(csa);
alpar@1
   234
      if (!(str2int(csa->field, &nv) == 0 && nv >= 0))
alpar@1
   235
         error(csa, "number of nodes missing or invalid");
alpar@1
   236
      read_field(csa);
alpar@1
   237
      if (!(str2int(csa->field, &na) == 0 && na >= 0))
alpar@1
   238
         error(csa, "number of arcs missing or invalid");
alpar@1
   239
      xprintf("Flow network has %d node%s and %d arc%s\n",
alpar@1
   240
         nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s");
alpar@1
   241
      if (nv > 0) glp_add_vertices(G, nv);
alpar@1
   242
      end_of_line(csa);
alpar@1
   243
      /* read node descriptor lines */
alpar@1
   244
      flag = xcalloc(1+nv, sizeof(char));
alpar@1
   245
      memset(&flag[1], 0, nv * sizeof(char));
alpar@1
   246
      if (v_rhs >= 0)
alpar@1
   247
      {  rhs = 0.0;
alpar@1
   248
         for (i = 1; i <= nv; i++)
alpar@1
   249
         {  v = G->v[i];
alpar@1
   250
            memcpy((char *)v->data + v_rhs, &rhs, sizeof(double));
alpar@1
   251
         }
alpar@1
   252
      }
alpar@1
   253
      for (;;)
alpar@1
   254
      {  read_designator(csa);
alpar@1
   255
         if (strcmp(csa->field, "n") != 0) break;
alpar@1
   256
         read_field(csa);
alpar@1
   257
         if (str2int(csa->field, &i) != 0)
alpar@1
   258
            error(csa, "node number missing or invalid");
alpar@1
   259
         if (!(1 <= i && i <= nv))
alpar@1
   260
            error(csa, "node number %d out of range", i);
alpar@1
   261
         if (flag[i])
alpar@1
   262
            error(csa, "duplicate descriptor of node %d", i);
alpar@1
   263
         read_field(csa);
alpar@1
   264
         if (str2num(csa->field, &rhs) != 0)
alpar@1
   265
            error(csa, "node supply/demand missing or invalid");
alpar@1
   266
         check_int(csa, rhs);
alpar@1
   267
         if (v_rhs >= 0)
alpar@1
   268
         {  v = G->v[i];
alpar@1
   269
            memcpy((char *)v->data + v_rhs, &rhs, sizeof(double));
alpar@1
   270
         }
alpar@1
   271
         flag[i] = 1;
alpar@1
   272
         end_of_line(csa);
alpar@1
   273
      }
alpar@1
   274
      xfree(flag), flag = NULL;
alpar@1
   275
      /* read arc descriptor lines */
alpar@1
   276
      for (k = 1; k <= na; k++)
alpar@1
   277
      {  if (k > 1) read_designator(csa);
alpar@1
   278
         if (strcmp(csa->field, "a") != 0)
alpar@1
   279
            error(csa, "wrong line designator; `a' expected");
alpar@1
   280
         read_field(csa);
alpar@1
   281
         if (str2int(csa->field, &i) != 0)
alpar@1
   282
            error(csa, "starting node number missing or invalid");
alpar@1
   283
         if (!(1 <= i && i <= nv))
alpar@1
   284
            error(csa, "starting node number %d out of range", i);
alpar@1
   285
         read_field(csa);
alpar@1
   286
         if (str2int(csa->field, &j) != 0)
alpar@1
   287
            error(csa, "ending node number missing or invalid");
alpar@1
   288
         if (!(1 <= j && j <= nv))
alpar@1
   289
            error(csa, "ending node number %d out of range", j);
alpar@1
   290
         read_field(csa);
alpar@1
   291
         if (!(str2num(csa->field, &low) == 0 && low >= 0.0))
alpar@1
   292
            error(csa, "lower bound of arc flow missing or invalid");
alpar@1
   293
         check_int(csa, low);
alpar@1
   294
         read_field(csa);
alpar@1
   295
         if (!(str2num(csa->field, &cap) == 0 && cap >= low))
alpar@1
   296
            error(csa, "upper bound of arc flow missing or invalid");
alpar@1
   297
         check_int(csa, cap);
alpar@1
   298
         read_field(csa);
alpar@1
   299
         if (str2num(csa->field, &cost) != 0)
alpar@1
   300
            error(csa, "per-unit cost of arc flow missing or invalid");
alpar@1
   301
         check_int(csa, cost);
alpar@1
   302
         a = glp_add_arc(G, i, j);
alpar@1
   303
         if (a_low >= 0)
alpar@1
   304
            memcpy((char *)a->data + a_low, &low, sizeof(double));
alpar@1
   305
         if (a_cap >= 0)
alpar@1
   306
            memcpy((char *)a->data + a_cap, &cap, sizeof(double));
alpar@1
   307
         if (a_cost >= 0)
alpar@1
   308
            memcpy((char *)a->data + a_cost, &cost, sizeof(double));
alpar@1
   309
         end_of_line(csa);
alpar@1
   310
      }
alpar@1
   311
      xprintf("%d lines were read\n", csa->count);
alpar@1
   312
done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
alpar@1
   313
      if (csa->fp != NULL) xfclose(csa->fp);
alpar@1
   314
      if (flag != NULL) xfree(flag);
alpar@1
   315
      return ret;
alpar@1
   316
}
alpar@1
   317
alpar@1
   318
/***********************************************************************
alpar@1
   319
*  NAME
alpar@1
   320
*
alpar@1
   321
*  glp_write_mincost - write min-cost flow problem data in DIMACS format
alpar@1
   322
*
alpar@1
   323
*  SYNOPSIS
alpar@1
   324
*
alpar@1
   325
*  int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
alpar@1
   326
*     int a_cost, const char *fname);
alpar@1
   327
*
alpar@1
   328
*  DESCRIPTION
alpar@1
   329
*
alpar@1
   330
*  The routine glp_write_mincost writes minimum cost flow problem data
alpar@1
   331
*  in DIMACS format to a text file.
alpar@1
   332
*
alpar@1
   333
*  RETURNS
alpar@1
   334
*
alpar@1
   335
*  If the operation was successful, the routine returns zero. Otherwise
alpar@1
   336
*  it prints an error message and returns non-zero. */
alpar@1
   337
alpar@1
   338
int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap,
alpar@1
   339
      int a_cost, const char *fname)
alpar@1
   340
{     XFILE *fp;
alpar@1
   341
      glp_vertex *v;
alpar@1
   342
      glp_arc *a;
alpar@1
   343
      int i, count = 0, ret;
alpar@1
   344
      double rhs, low, cap, cost;
alpar@1
   345
      if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
alpar@1
   346
         xerror("glp_write_mincost: v_rhs = %d; invalid offset\n",
alpar@1
   347
            v_rhs);
alpar@1
   348
      if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
alpar@1
   349
         xerror("glp_write_mincost: a_low = %d; invalid offset\n",
alpar@1
   350
            a_low);
alpar@1
   351
      if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
alpar@1
   352
         xerror("glp_write_mincost: a_cap = %d; invalid offset\n",
alpar@1
   353
            a_cap);
alpar@1
   354
      if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
alpar@1
   355
         xerror("glp_write_mincost: a_cost = %d; invalid offset\n",
alpar@1
   356
            a_cost);
alpar@1
   357
      xprintf("Writing min-cost flow problem data to `%s'...\n",
alpar@1
   358
         fname);
alpar@1
   359
      fp = xfopen(fname, "w");
alpar@1
   360
      if (fp == NULL)
alpar@1
   361
      {  xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
alpar@1
   362
         ret = 1;
alpar@1
   363
         goto done;
alpar@1
   364
      }
alpar@1
   365
      xfprintf(fp, "c %s\n",
alpar@1
   366
         G->name == NULL ? "unknown" : G->name), count++;
alpar@1
   367
      xfprintf(fp, "p min %d %d\n", G->nv, G->na), count++;
alpar@1
   368
      if (v_rhs >= 0)
alpar@1
   369
      {  for (i = 1; i <= G->nv; i++)
alpar@1
   370
         {  v = G->v[i];
alpar@1
   371
            memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double));
alpar@1
   372
            if (rhs != 0.0)
alpar@1
   373
               xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, rhs), count++;
alpar@1
   374
         }
alpar@1
   375
      }
alpar@1
   376
      for (i = 1; i <= G->nv; i++)
alpar@1
   377
      {  v = G->v[i];
alpar@1
   378
         for (a = v->out; a != NULL; a = a->t_next)
alpar@1
   379
         {  if (a_low >= 0)
alpar@1
   380
               memcpy(&low, (char *)a->data + a_low, sizeof(double));
alpar@1
   381
            else
alpar@1
   382
               low = 0.0;
alpar@1
   383
            if (a_cap >= 0)
alpar@1
   384
               memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
alpar@1
   385
            else
alpar@1
   386
               cap = 1.0;
alpar@1
   387
            if (a_cost >= 0)
alpar@1
   388
               memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
alpar@1
   389
            else
alpar@1
   390
               cost = 0.0;
alpar@1
   391
            xfprintf(fp, "a %d %d %.*g %.*g %.*g\n",
alpar@1
   392
               a->tail->i, a->head->i, DBL_DIG, low, DBL_DIG, cap,
alpar@1
   393
               DBL_DIG, cost), count++;
alpar@1
   394
         }
alpar@1
   395
      }
alpar@1
   396
      xfprintf(fp, "c eof\n"), count++;
alpar@1
   397
      xfflush(fp);
alpar@1
   398
      if (xferror(fp))
alpar@1
   399
      {  xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
alpar@1
   400
         ret = 1;
alpar@1
   401
         goto done;
alpar@1
   402
      }
alpar@1
   403
      xprintf("%d lines were written\n", count);
alpar@1
   404
      ret = 0;
alpar@1
   405
done: if (fp != NULL) xfclose(fp);
alpar@1
   406
      return ret;
alpar@1
   407
}
alpar@1
   408
alpar@1
   409
/***********************************************************************
alpar@1
   410
*  NAME
alpar@1
   411
*
alpar@1
   412
*  glp_read_maxflow - read maximum flow problem data in DIMACS format
alpar@1
   413
*
alpar@1
   414
*  SYNOPSIS
alpar@1
   415
*
alpar@1
   416
*  int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap,
alpar@1
   417
*     const char *fname);
alpar@1
   418
*
alpar@1
   419
*  DESCRIPTION
alpar@1
   420
*
alpar@1
   421
*  The routine glp_read_maxflow reads maximum flow problem data in
alpar@1
   422
*  DIMACS format from a text file.
alpar@1
   423
*
alpar@1
   424
*  RETURNS
alpar@1
   425
*
alpar@1
   426
*  If the operation was successful, the routine returns zero. Otherwise
alpar@1
   427
*  it prints an error message and returns non-zero. */
alpar@1
   428
alpar@1
   429
int glp_read_maxflow(glp_graph *G, int *_s, int *_t, int a_cap,
alpar@1
   430
      const char *fname)
alpar@1
   431
{     struct csa _csa, *csa = &_csa;
alpar@1
   432
      glp_arc *a;
alpar@1
   433
      int i, j, k, s, t, nv, na, ret = 0;
alpar@1
   434
      double cap;
alpar@1
   435
      if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
alpar@1
   436
         xerror("glp_read_maxflow: a_cap = %d; invalid offset\n",
alpar@1
   437
            a_cap);
alpar@1
   438
      glp_erase_graph(G, G->v_size, G->a_size);
alpar@1
   439
      if (setjmp(csa->jump))
alpar@1
   440
      {  ret = 1;
alpar@1
   441
         goto done;
alpar@1
   442
      }
alpar@1
   443
      csa->fname = fname;
alpar@1
   444
      csa->fp = NULL;
alpar@1
   445
      csa->count = 0;
alpar@1
   446
      csa->c = '\n';
alpar@1
   447
      csa->field[0] = '\0';
alpar@1
   448
      csa->empty = csa->nonint = 0;
alpar@1
   449
      xprintf("Reading maximum flow problem data from `%s'...\n",
alpar@1
   450
         fname);
alpar@1
   451
      csa->fp = xfopen(fname, "r");
alpar@1
   452
      if (csa->fp == NULL)
alpar@1
   453
      {  xprintf("Unable to open `%s' - %s\n", fname, xerrmsg());
alpar@1
   454
         longjmp(csa->jump, 1);
alpar@1
   455
      }
alpar@1
   456
      /* read problem line */
alpar@1
   457
      read_designator(csa);
alpar@1
   458
      if (strcmp(csa->field, "p") != 0)
alpar@1
   459
         error(csa, "problem line missing or invalid");
alpar@1
   460
      read_field(csa);
alpar@1
   461
      if (strcmp(csa->field, "max") != 0)
alpar@1
   462
         error(csa, "wrong problem designator; `max' expected");
alpar@1
   463
      read_field(csa);
alpar@1
   464
      if (!(str2int(csa->field, &nv) == 0 && nv >= 2))
alpar@1
   465
         error(csa, "number of nodes missing or invalid");
alpar@1
   466
      read_field(csa);
alpar@1
   467
      if (!(str2int(csa->field, &na) == 0 && na >= 0))
alpar@1
   468
         error(csa, "number of arcs missing or invalid");
alpar@1
   469
      xprintf("Flow network has %d node%s and %d arc%s\n",
alpar@1
   470
         nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s");
alpar@1
   471
      if (nv > 0) glp_add_vertices(G, nv);
alpar@1
   472
      end_of_line(csa);
alpar@1
   473
      /* read node descriptor lines */
alpar@1
   474
      s = t = 0;
alpar@1
   475
      for (;;)
alpar@1
   476
      {  read_designator(csa);
alpar@1
   477
         if (strcmp(csa->field, "n") != 0) break;
alpar@1
   478
         read_field(csa);
alpar@1
   479
         if (str2int(csa->field, &i) != 0)
alpar@1
   480
            error(csa, "node number missing or invalid");
alpar@1
   481
         if (!(1 <= i && i <= nv))
alpar@1
   482
            error(csa, "node number %d out of range", i);
alpar@1
   483
         read_field(csa);
alpar@1
   484
         if (strcmp(csa->field, "s") == 0)
alpar@1
   485
         {  if (s > 0)
alpar@1
   486
               error(csa, "only one source node allowed");
alpar@1
   487
            s = i;
alpar@1
   488
         }
alpar@1
   489
         else if (strcmp(csa->field, "t") == 0)
alpar@1
   490
         {  if (t > 0)
alpar@1
   491
               error(csa, "only one sink node allowed");
alpar@1
   492
            t = i;
alpar@1
   493
         }
alpar@1
   494
         else
alpar@1
   495
            error(csa, "wrong node designator; `s' or `t' expected");
alpar@1
   496
         if (s > 0 && s == t)
alpar@1
   497
            error(csa, "source and sink nodes must be distinct");
alpar@1
   498
         end_of_line(csa);
alpar@1
   499
      }
alpar@1
   500
      if (s == 0)
alpar@1
   501
         error(csa, "source node descriptor missing\n");
alpar@1
   502
      if (t == 0)
alpar@1
   503
         error(csa, "sink node descriptor missing\n");
alpar@1
   504
      if (_s != NULL) *_s = s;
alpar@1
   505
      if (_t != NULL) *_t = t;
alpar@1
   506
      /* read arc descriptor lines */
alpar@1
   507
      for (k = 1; k <= na; k++)
alpar@1
   508
      {  if (k > 1) read_designator(csa);
alpar@1
   509
         if (strcmp(csa->field, "a") != 0)
alpar@1
   510
            error(csa, "wrong line designator; `a' expected");
alpar@1
   511
         read_field(csa);
alpar@1
   512
         if (str2int(csa->field, &i) != 0)
alpar@1
   513
            error(csa, "starting node number missing or invalid");
alpar@1
   514
         if (!(1 <= i && i <= nv))
alpar@1
   515
            error(csa, "starting node number %d out of range", i);
alpar@1
   516
         read_field(csa);
alpar@1
   517
         if (str2int(csa->field, &j) != 0)
alpar@1
   518
            error(csa, "ending node number missing or invalid");
alpar@1
   519
         if (!(1 <= j && j <= nv))
alpar@1
   520
            error(csa, "ending node number %d out of range", j);
alpar@1
   521
         read_field(csa);
alpar@1
   522
         if (!(str2num(csa->field, &cap) == 0 && cap >= 0.0))
alpar@1
   523
            error(csa, "arc capacity missing or invalid");
alpar@1
   524
         check_int(csa, cap);
alpar@1
   525
         a = glp_add_arc(G, i, j);
alpar@1
   526
         if (a_cap >= 0)
alpar@1
   527
            memcpy((char *)a->data + a_cap, &cap, sizeof(double));
alpar@1
   528
         end_of_line(csa);
alpar@1
   529
      }
alpar@1
   530
      xprintf("%d lines were read\n", csa->count);
alpar@1
   531
done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
alpar@1
   532
      if (csa->fp != NULL) xfclose(csa->fp);
alpar@1
   533
      return ret;
alpar@1
   534
}
alpar@1
   535
alpar@1
   536
/***********************************************************************
alpar@1
   537
*  NAME
alpar@1
   538
*
alpar@1
   539
*  glp_write_maxflow - write maximum flow problem data in DIMACS format
alpar@1
   540
*
alpar@1
   541
*  SYNOPSIS
alpar@1
   542
*
alpar@1
   543
*  int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap,
alpar@1
   544
*     const char *fname);
alpar@1
   545
*
alpar@1
   546
*  DESCRIPTION
alpar@1
   547
*
alpar@1
   548
*  The routine glp_write_maxflow writes maximum flow problem data in
alpar@1
   549
*  DIMACS format to a text file.
alpar@1
   550
*
alpar@1
   551
*  RETURNS
alpar@1
   552
*
alpar@1
   553
*  If the operation was successful, the routine returns zero. Otherwise
alpar@1
   554
*  it prints an error message and returns non-zero. */
alpar@1
   555
alpar@1
   556
int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap,
alpar@1
   557
      const char *fname)
alpar@1
   558
{     XFILE *fp;
alpar@1
   559
      glp_vertex *v;
alpar@1
   560
      glp_arc *a;
alpar@1
   561
      int i, count = 0, ret;
alpar@1
   562
      double cap;
alpar@1
   563
      if (!(1 <= s && s <= G->nv))
alpar@1
   564
         xerror("glp_write_maxflow: s = %d; source node number out of r"
alpar@1
   565
            "ange\n", s);
alpar@1
   566
      if (!(1 <= t && t <= G->nv))
alpar@1
   567
         xerror("glp_write_maxflow: t = %d: sink node number out of ran"
alpar@1
   568
            "ge\n", t);
alpar@1
   569
      if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
alpar@1
   570
         xerror("glp_write_mincost: a_cap = %d; invalid offset\n",
alpar@1
   571
            a_cap);
alpar@1
   572
      xprintf("Writing maximum flow problem data to `%s'...\n",
alpar@1
   573
         fname);
alpar@1
   574
      fp = xfopen(fname, "w");
alpar@1
   575
      if (fp == NULL)
alpar@1
   576
      {  xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
alpar@1
   577
         ret = 1;
alpar@1
   578
         goto done;
alpar@1
   579
      }
alpar@1
   580
      xfprintf(fp, "c %s\n",
alpar@1
   581
         G->name == NULL ? "unknown" : G->name), count++;
alpar@1
   582
      xfprintf(fp, "p max %d %d\n", G->nv, G->na), count++;
alpar@1
   583
      xfprintf(fp, "n %d s\n", s), count++;
alpar@1
   584
      xfprintf(fp, "n %d t\n", t), count++;
alpar@1
   585
      for (i = 1; i <= G->nv; i++)
alpar@1
   586
      {  v = G->v[i];
alpar@1
   587
         for (a = v->out; a != NULL; a = a->t_next)
alpar@1
   588
         {  if (a_cap >= 0)
alpar@1
   589
               memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
alpar@1
   590
            else
alpar@1
   591
               cap = 1.0;
alpar@1
   592
            xfprintf(fp, "a %d %d %.*g\n",
alpar@1
   593
               a->tail->i, a->head->i, DBL_DIG, cap), count++;
alpar@1
   594
         }
alpar@1
   595
      }
alpar@1
   596
      xfprintf(fp, "c eof\n"), count++;
alpar@1
   597
      xfflush(fp);
alpar@1
   598
      if (xferror(fp))
alpar@1
   599
      {  xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
alpar@1
   600
         ret = 1;
alpar@1
   601
         goto done;
alpar@1
   602
      }
alpar@1
   603
      xprintf("%d lines were written\n", count);
alpar@1
   604
      ret = 0;
alpar@1
   605
done: if (fp != NULL) xfclose(fp);
alpar@1
   606
      return ret;
alpar@1
   607
}
alpar@1
   608
alpar@1
   609
/***********************************************************************
alpar@1
   610
*  NAME
alpar@1
   611
*
alpar@1
   612
*  glp_read_asnprob - read assignment problem data in DIMACS format
alpar@1
   613
*
alpar@1
   614
*  SYNOPSIS
alpar@1
   615
*
alpar@1
   616
*  int glp_read_asnprob(glp_graph *G, int v_set, int a_cost,
alpar@1
   617
*     const char *fname);
alpar@1
   618
*
alpar@1
   619
*  DESCRIPTION
alpar@1
   620
*
alpar@1
   621
*  The routine glp_read_asnprob reads assignment problem data in DIMACS
alpar@1
   622
*  format from a text file.
alpar@1
   623
*
alpar@1
   624
*  RETURNS
alpar@1
   625
*
alpar@1
   626
*  If the operation was successful, the routine returns zero. Otherwise
alpar@1
   627
*  it prints an error message and returns non-zero. */
alpar@1
   628
alpar@1
   629
int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char
alpar@1
   630
      *fname)
alpar@1
   631
{     struct csa _csa, *csa = &_csa;
alpar@1
   632
      glp_vertex *v;
alpar@1
   633
      glp_arc *a;
alpar@1
   634
      int nv, na, n1, i, j, k, ret = 0;
alpar@1
   635
      double cost;
alpar@1
   636
      char *flag = NULL;
alpar@1
   637
      if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
alpar@1
   638
         xerror("glp_read_asnprob: v_set = %d; invalid offset\n",
alpar@1
   639
            v_set);
alpar@1
   640
      if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
alpar@1
   641
         xerror("glp_read_asnprob: a_cost = %d; invalid offset\n",
alpar@1
   642
            a_cost);
alpar@1
   643
      glp_erase_graph(G, G->v_size, G->a_size);
alpar@1
   644
      if (setjmp(csa->jump))
alpar@1
   645
      {  ret = 1;
alpar@1
   646
         goto done;
alpar@1
   647
      }
alpar@1
   648
      csa->fname = fname;
alpar@1
   649
      csa->fp = NULL;
alpar@1
   650
      csa->count = 0;
alpar@1
   651
      csa->c = '\n';
alpar@1
   652
      csa->field[0] = '\0';
alpar@1
   653
      csa->empty = csa->nonint = 0;
alpar@1
   654
      xprintf("Reading assignment problem data from `%s'...\n", fname);
alpar@1
   655
      csa->fp = xfopen(fname, "r");
alpar@1
   656
      if (csa->fp == NULL)
alpar@1
   657
      {  xprintf("Unable to open `%s' - %s\n", fname, xerrmsg());
alpar@1
   658
         longjmp(csa->jump, 1);
alpar@1
   659
      }
alpar@1
   660
      /* read problem line */
alpar@1
   661
      read_designator(csa);
alpar@1
   662
      if (strcmp(csa->field, "p") != 0)
alpar@1
   663
         error(csa, "problem line missing or invalid");
alpar@1
   664
      read_field(csa);
alpar@1
   665
      if (strcmp(csa->field, "asn") != 0)
alpar@1
   666
         error(csa, "wrong problem designator; `asn' expected");
alpar@1
   667
      read_field(csa);
alpar@1
   668
      if (!(str2int(csa->field, &nv) == 0 && nv >= 0))
alpar@1
   669
         error(csa, "number of nodes missing or invalid");
alpar@1
   670
      read_field(csa);
alpar@1
   671
      if (!(str2int(csa->field, &na) == 0 && na >= 0))
alpar@1
   672
         error(csa, "number of arcs missing or invalid");
alpar@1
   673
      if (nv > 0) glp_add_vertices(G, nv);
alpar@1
   674
      end_of_line(csa);
alpar@1
   675
      /* read node descriptor lines */
alpar@1
   676
      flag = xcalloc(1+nv, sizeof(char));
alpar@1
   677
      memset(&flag[1], 0, nv * sizeof(char));
alpar@1
   678
      n1 = 0;
alpar@1
   679
      for (;;)
alpar@1
   680
      {  read_designator(csa);
alpar@1
   681
         if (strcmp(csa->field, "n") != 0) break;
alpar@1
   682
         read_field(csa);
alpar@1
   683
         if (str2int(csa->field, &i) != 0)
alpar@1
   684
            error(csa, "node number missing or invalid");
alpar@1
   685
         if (!(1 <= i && i <= nv))
alpar@1
   686
            error(csa, "node number %d out of range", i);
alpar@1
   687
         if (flag[i])
alpar@1
   688
            error(csa, "duplicate descriptor of node %d", i);
alpar@1
   689
         flag[i] = 1, n1++;
alpar@1
   690
         end_of_line(csa);
alpar@1
   691
      }
alpar@1
   692
      xprintf(
alpar@1
   693
         "Assignment problem has %d + %d = %d node%s and %d arc%s\n",
alpar@1
   694
         n1, nv - n1, nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s");
alpar@1
   695
      if (v_set >= 0)
alpar@1
   696
      {  for (i = 1; i <= nv; i++)
alpar@1
   697
         {  v = G->v[i];
alpar@1
   698
            k = (flag[i] ? 0 : 1);
alpar@1
   699
            memcpy((char *)v->data + v_set, &k, sizeof(int));
alpar@1
   700
         }
alpar@1
   701
      }
alpar@1
   702
      /* read arc descriptor lines */
alpar@1
   703
      for (k = 1; k <= na; k++)
alpar@1
   704
      {  if (k > 1) read_designator(csa);
alpar@1
   705
         if (strcmp(csa->field, "a") != 0)
alpar@1
   706
            error(csa, "wrong line designator; `a' expected");
alpar@1
   707
         read_field(csa);
alpar@1
   708
         if (str2int(csa->field, &i) != 0)
alpar@1
   709
            error(csa, "starting node number missing or invalid");
alpar@1
   710
         if (!(1 <= i && i <= nv))
alpar@1
   711
            error(csa, "starting node number %d out of range", i);
alpar@1
   712
         if (!flag[i])
alpar@1
   713
            error(csa, "node %d cannot be a starting node", i);
alpar@1
   714
         read_field(csa);
alpar@1
   715
         if (str2int(csa->field, &j) != 0)
alpar@1
   716
            error(csa, "ending node number missing or invalid");
alpar@1
   717
         if (!(1 <= j && j <= nv))
alpar@1
   718
            error(csa, "ending node number %d out of range", j);
alpar@1
   719
         if (flag[j])
alpar@1
   720
            error(csa, "node %d cannot be an ending node", j);
alpar@1
   721
         read_field(csa);
alpar@1
   722
         if (str2num(csa->field, &cost) != 0)
alpar@1
   723
            error(csa, "arc cost missing or invalid");
alpar@1
   724
         check_int(csa, cost);
alpar@1
   725
         a = glp_add_arc(G, i, j);
alpar@1
   726
         if (a_cost >= 0)
alpar@1
   727
            memcpy((char *)a->data + a_cost, &cost, sizeof(double));
alpar@1
   728
         end_of_line(csa);
alpar@1
   729
      }
alpar@1
   730
      xprintf("%d lines were read\n", csa->count);
alpar@1
   731
done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
alpar@1
   732
      if (csa->fp != NULL) xfclose(csa->fp);
alpar@1
   733
      if (flag != NULL) xfree(flag);
alpar@1
   734
      return ret;
alpar@1
   735
}
alpar@1
   736
alpar@1
   737
/***********************************************************************
alpar@1
   738
*  NAME
alpar@1
   739
*
alpar@1
   740
*  glp_write_asnprob - write assignment problem data in DIMACS format
alpar@1
   741
*
alpar@1
   742
*  SYNOPSIS
alpar@1
   743
*
alpar@1
   744
*  int glp_write_asnprob(glp_graph *G, int v_set, int a_cost,
alpar@1
   745
*     const char *fname);
alpar@1
   746
*
alpar@1
   747
*  DESCRIPTION
alpar@1
   748
*
alpar@1
   749
*  The routine glp_write_asnprob writes assignment problem data in
alpar@1
   750
*  DIMACS format to a text file.
alpar@1
   751
*
alpar@1
   752
*  RETURNS
alpar@1
   753
*
alpar@1
   754
*  If the operation was successful, the routine returns zero. Otherwise
alpar@1
   755
*  it prints an error message and returns non-zero. */
alpar@1
   756
alpar@1
   757
int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char
alpar@1
   758
      *fname)
alpar@1
   759
{     XFILE *fp;
alpar@1
   760
      glp_vertex *v;
alpar@1
   761
      glp_arc *a;
alpar@1
   762
      int i, k, count = 0, ret;
alpar@1
   763
      double cost;
alpar@1
   764
      if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
alpar@1
   765
         xerror("glp_write_asnprob: v_set = %d; invalid offset\n",
alpar@1
   766
            v_set);
alpar@1
   767
      if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
alpar@1
   768
         xerror("glp_write_asnprob: a_cost = %d; invalid offset\n",
alpar@1
   769
            a_cost);
alpar@1
   770
      xprintf("Writing assignment problem data to `%s'...\n", fname);
alpar@1
   771
      fp = xfopen(fname, "w");
alpar@1
   772
      if (fp == NULL)
alpar@1
   773
      {  xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
alpar@1
   774
         ret = 1;
alpar@1
   775
         goto done;
alpar@1
   776
      }
alpar@1
   777
      xfprintf(fp, "c %s\n",
alpar@1
   778
         G->name == NULL ? "unknown" : G->name), count++;
alpar@1
   779
      xfprintf(fp, "p asn %d %d\n", G->nv, G->na), count++;
alpar@1
   780
      for (i = 1; i <= G->nv; i++)
alpar@1
   781
      {  v = G->v[i];
alpar@1
   782
         if (v_set >= 0)
alpar@1
   783
            memcpy(&k, (char *)v->data + v_set, sizeof(int));
alpar@1
   784
         else
alpar@1
   785
            k = (v->out != NULL ? 0 : 1);
alpar@1
   786
         if (k == 0)
alpar@1
   787
            xfprintf(fp, "n %d\n", i), count++;
alpar@1
   788
      }
alpar@1
   789
      for (i = 1; i <= G->nv; i++)
alpar@1
   790
      {  v = G->v[i];
alpar@1
   791
         for (a = v->out; a != NULL; a = a->t_next)
alpar@1
   792
         {  if (a_cost >= 0)
alpar@1
   793
               memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
alpar@1
   794
            else
alpar@1
   795
               cost = 1.0;
alpar@1
   796
            xfprintf(fp, "a %d %d %.*g\n",
alpar@1
   797
               a->tail->i, a->head->i, DBL_DIG, cost), count++;
alpar@1
   798
         }
alpar@1
   799
      }
alpar@1
   800
      xfprintf(fp, "c eof\n"), count++;
alpar@1
   801
      xfflush(fp);
alpar@1
   802
      if (xferror(fp))
alpar@1
   803
      {  xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
alpar@1
   804
         ret = 1;
alpar@1
   805
         goto done;
alpar@1
   806
      }
alpar@1
   807
      xprintf("%d lines were written\n", count);
alpar@1
   808
      ret = 0;
alpar@1
   809
done: if (fp != NULL) xfclose(fp);
alpar@1
   810
      return ret;
alpar@1
   811
}
alpar@1
   812
alpar@1
   813
/***********************************************************************
alpar@1
   814
*  NAME
alpar@1
   815
*
alpar@1
   816
*  glp_read_ccdata - read graph in DIMACS clique/coloring format
alpar@1
   817
*
alpar@1
   818
*  SYNOPSIS
alpar@1
   819
*
alpar@1
   820
*  int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname);
alpar@1
   821
*
alpar@1
   822
*  DESCRIPTION
alpar@1
   823
*
alpar@1
   824
*  The routine glp_read_ccdata reads an (undirected) graph in DIMACS
alpar@1
   825
*  clique/coloring format from a text file.
alpar@1
   826
*
alpar@1
   827
*  RETURNS
alpar@1
   828
*
alpar@1
   829
*  If the operation was successful, the routine returns zero. Otherwise
alpar@1
   830
*  it prints an error message and returns non-zero. */
alpar@1
   831
alpar@1
   832
int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname)
alpar@1
   833
{     struct csa _csa, *csa = &_csa;
alpar@1
   834
      glp_vertex *v;
alpar@1
   835
      int i, j, k, nv, ne, ret = 0;
alpar@1
   836
      double w;
alpar@1
   837
      char *flag = NULL;
alpar@1
   838
      if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double))
alpar@1
   839
         xerror("glp_read_ccdata: v_wgt = %d; invalid offset\n",
alpar@1
   840
            v_wgt);
alpar@1
   841
      glp_erase_graph(G, G->v_size, G->a_size);
alpar@1
   842
      if (setjmp(csa->jump))
alpar@1
   843
      {  ret = 1;
alpar@1
   844
         goto done;
alpar@1
   845
      }
alpar@1
   846
      csa->fname = fname;
alpar@1
   847
      csa->fp = NULL;
alpar@1
   848
      csa->count = 0;
alpar@1
   849
      csa->c = '\n';
alpar@1
   850
      csa->field[0] = '\0';
alpar@1
   851
      csa->empty = csa->nonint = 0;
alpar@1
   852
      xprintf("Reading graph from `%s'...\n", fname);
alpar@1
   853
      csa->fp = xfopen(fname, "r");
alpar@1
   854
      if (csa->fp == NULL)
alpar@1
   855
      {  xprintf("Unable to open `%s' - %s\n", fname, xerrmsg());
alpar@1
   856
         longjmp(csa->jump, 1);
alpar@1
   857
      }
alpar@1
   858
      /* read problem line */
alpar@1
   859
      read_designator(csa);
alpar@1
   860
      if (strcmp(csa->field, "p") != 0)
alpar@1
   861
         error(csa, "problem line missing or invalid");
alpar@1
   862
      read_field(csa);
alpar@1
   863
      if (strcmp(csa->field, "edge") != 0)
alpar@1
   864
         error(csa, "wrong problem designator; `edge' expected");
alpar@1
   865
      read_field(csa);
alpar@1
   866
      if (!(str2int(csa->field, &nv) == 0 && nv >= 0))
alpar@1
   867
         error(csa, "number of vertices missing or invalid");
alpar@1
   868
      read_field(csa);
alpar@1
   869
      if (!(str2int(csa->field, &ne) == 0 && ne >= 0))
alpar@1
   870
         error(csa, "number of edges missing or invalid");
alpar@1
   871
      xprintf("Graph has %d vert%s and %d edge%s\n",
alpar@1
   872
         nv, nv == 1 ? "ex" : "ices", ne, ne == 1 ? "" : "s");
alpar@1
   873
      if (nv > 0) glp_add_vertices(G, nv);
alpar@1
   874
      end_of_line(csa);
alpar@1
   875
      /* read node descriptor lines */
alpar@1
   876
      flag = xcalloc(1+nv, sizeof(char));
alpar@1
   877
      memset(&flag[1], 0, nv * sizeof(char));
alpar@1
   878
      if (v_wgt >= 0)
alpar@1
   879
      {  w = 1.0;
alpar@1
   880
         for (i = 1; i <= nv; i++)
alpar@1
   881
         {  v = G->v[i];
alpar@1
   882
            memcpy((char *)v->data + v_wgt, &w, sizeof(double));
alpar@1
   883
         }
alpar@1
   884
      }
alpar@1
   885
      for (;;)
alpar@1
   886
      {  read_designator(csa);
alpar@1
   887
         if (strcmp(csa->field, "n") != 0) break;
alpar@1
   888
         read_field(csa);
alpar@1
   889
         if (str2int(csa->field, &i) != 0)
alpar@1
   890
            error(csa, "vertex number missing or invalid");
alpar@1
   891
         if (!(1 <= i && i <= nv))
alpar@1
   892
            error(csa, "vertex number %d out of range", i);
alpar@1
   893
         if (flag[i])
alpar@1
   894
            error(csa, "duplicate descriptor of vertex %d", i);
alpar@1
   895
         read_field(csa);
alpar@1
   896
         if (str2num(csa->field, &w) != 0)
alpar@1
   897
            error(csa, "vertex weight missing or invalid");
alpar@1
   898
         check_int(csa, w);
alpar@1
   899
         if (v_wgt >= 0)
alpar@1
   900
         {  v = G->v[i];
alpar@1
   901
            memcpy((char *)v->data + v_wgt, &w, sizeof(double));
alpar@1
   902
         }
alpar@1
   903
         flag[i] = 1;
alpar@1
   904
         end_of_line(csa);
alpar@1
   905
      }
alpar@1
   906
      xfree(flag), flag = NULL;
alpar@1
   907
      /* read edge descriptor lines */
alpar@1
   908
      for (k = 1; k <= ne; k++)
alpar@1
   909
      {  if (k > 1) read_designator(csa);
alpar@1
   910
         if (strcmp(csa->field, "e") != 0)
alpar@1
   911
            error(csa, "wrong line designator; `e' expected");
alpar@1
   912
         read_field(csa);
alpar@1
   913
         if (str2int(csa->field, &i) != 0)
alpar@1
   914
            error(csa, "first vertex number missing or invalid");
alpar@1
   915
         if (!(1 <= i && i <= nv))
alpar@1
   916
            error(csa, "first vertex number %d out of range", i);
alpar@1
   917
         read_field(csa);
alpar@1
   918
         if (str2int(csa->field, &j) != 0)
alpar@1
   919
            error(csa, "second vertex number missing or invalid");
alpar@1
   920
         if (!(1 <= j && j <= nv))
alpar@1
   921
            error(csa, "second vertex number %d out of range", j);
alpar@1
   922
         glp_add_arc(G, i, j);
alpar@1
   923
         end_of_line(csa);
alpar@1
   924
      }
alpar@1
   925
      xprintf("%d lines were read\n", csa->count);
alpar@1
   926
done: if (ret) glp_erase_graph(G, G->v_size, G->a_size);
alpar@1
   927
      if (csa->fp != NULL) xfclose(csa->fp);
alpar@1
   928
      if (flag != NULL) xfree(flag);
alpar@1
   929
      return ret;
alpar@1
   930
}
alpar@1
   931
alpar@1
   932
/***********************************************************************
alpar@1
   933
*  NAME
alpar@1
   934
*
alpar@1
   935
*  glp_write_ccdata - write graph in DIMACS clique/coloring format
alpar@1
   936
*
alpar@1
   937
*  SYNOPSIS
alpar@1
   938
*
alpar@1
   939
*  int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname);
alpar@1
   940
*
alpar@1
   941
*  DESCRIPTION
alpar@1
   942
*
alpar@1
   943
*  The routine glp_write_ccdata writes the specified graph in DIMACS
alpar@1
   944
*  clique/coloring format to a text file.
alpar@1
   945
*
alpar@1
   946
*  RETURNS
alpar@1
   947
*
alpar@1
   948
*  If the operation was successful, the routine returns zero. Otherwise
alpar@1
   949
*  it prints an error message and returns non-zero. */
alpar@1
   950
alpar@1
   951
int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname)
alpar@1
   952
{     XFILE *fp;
alpar@1
   953
      glp_vertex *v;
alpar@1
   954
      glp_arc *e;
alpar@1
   955
      int i, count = 0, ret;
alpar@1
   956
      double w;
alpar@1
   957
      if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double))
alpar@1
   958
         xerror("glp_write_ccdata: v_wgt = %d; invalid offset\n",
alpar@1
   959
            v_wgt);
alpar@1
   960
      xprintf("Writing graph to `%s'\n", fname);
alpar@1
   961
      fp = xfopen(fname, "w");
alpar@1
   962
      if (fp == NULL)
alpar@1
   963
      {  xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
alpar@1
   964
         ret = 1;
alpar@1
   965
         goto done;
alpar@1
   966
      }
alpar@1
   967
      xfprintf(fp, "c %s\n",
alpar@1
   968
         G->name == NULL ? "unknown" : G->name), count++;
alpar@1
   969
      xfprintf(fp, "p edge %d %d\n", G->nv, G->na), count++;
alpar@1
   970
      if (v_wgt >= 0)
alpar@1
   971
      {  for (i = 1; i <= G->nv; i++)
alpar@1
   972
         {  v = G->v[i];
alpar@1
   973
            memcpy(&w, (char *)v->data + v_wgt, sizeof(double));
alpar@1
   974
            if (w != 1.0)
alpar@1
   975
               xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, w), count++;
alpar@1
   976
         }
alpar@1
   977
      }
alpar@1
   978
      for (i = 1; i <= G->nv; i++)
alpar@1
   979
      {  v = G->v[i];
alpar@1
   980
         for (e = v->out; e != NULL; e = e->t_next)
alpar@1
   981
            xfprintf(fp, "e %d %d\n", e->tail->i, e->head->i), count++;
alpar@1
   982
      }
alpar@1
   983
      xfprintf(fp, "c eof\n"), count++;
alpar@1
   984
      xfflush(fp);
alpar@1
   985
      if (xferror(fp))
alpar@1
   986
      {  xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
alpar@1
   987
         ret = 1;
alpar@1
   988
         goto done;
alpar@1
   989
      }
alpar@1
   990
      xprintf("%d lines were written\n", count);
alpar@1
   991
      ret = 0;
alpar@1
   992
done: if (fp != NULL) xfclose(fp);
alpar@1
   993
      return ret;
alpar@1
   994
}
alpar@1
   995
alpar@1
   996
/***********************************************************************
alpar@1
   997
*  NAME
alpar@1
   998
*
alpar@1
   999
*  glp_read_prob - read problem data in GLPK format
alpar@1
  1000
*
alpar@1
  1001
*  SYNOPSIS
alpar@1
  1002
*
alpar@1
  1003
*  int glp_read_prob(glp_prob *P, int flags, const char *fname);
alpar@1
  1004
*
alpar@1
  1005
*  The routine glp_read_prob reads problem data in GLPK LP/MIP format
alpar@1
  1006
*  from a text file.
alpar@1
  1007
*
alpar@1
  1008
*  RETURNS
alpar@1
  1009
*
alpar@1
  1010
*  If the operation was successful, the routine returns zero. Otherwise
alpar@1
  1011
*  it prints an error message and returns non-zero. */
alpar@1
  1012
alpar@1
  1013
int glp_read_prob(glp_prob *P, int flags, const char *fname)
alpar@1
  1014
{     struct csa _csa, *csa = &_csa;
alpar@1
  1015
      int mip, m, n, nnz, ne, i, j, k, type, kind, ret, *ln = NULL,
alpar@1
  1016
         *ia = NULL, *ja = NULL;
alpar@1
  1017
      double lb, ub, temp, *ar = NULL;
alpar@1
  1018
      char *rf = NULL, *cf = NULL;
alpar@1
  1019
      if (P == NULL || P->magic != GLP_PROB_MAGIC)
alpar@1
  1020
         xerror("glp_read_prob: P = %p; invalid problem object\n",
alpar@1
  1021
            P);
alpar@1
  1022
      if (flags != 0)
alpar@1
  1023
         xerror("glp_read_prob: flags = %d; invalid parameter\n",
alpar@1
  1024
            flags);
alpar@1
  1025
      if (fname == NULL)
alpar@1
  1026
         xerror("glp_read_prob: fname = %d; invalid parameter\n",
alpar@1
  1027
            fname);
alpar@1
  1028
      glp_erase_prob(P);
alpar@1
  1029
      if (setjmp(csa->jump))
alpar@1
  1030
      {  ret = 1;
alpar@1
  1031
         goto done;
alpar@1
  1032
      }
alpar@1
  1033
      csa->fname = fname;
alpar@1
  1034
      csa->fp = NULL;
alpar@1
  1035
      csa->count = 0;
alpar@1
  1036
      csa->c = '\n';
alpar@1
  1037
      csa->field[0] = '\0';
alpar@1
  1038
      csa->empty = csa->nonint = 0;
alpar@1
  1039
      xprintf("Reading problem data from `%s'...\n", fname);
alpar@1
  1040
      csa->fp = xfopen(fname, "r");
alpar@1
  1041
      if (csa->fp == NULL)
alpar@1
  1042
      {  xprintf("Unable to open `%s' - %s\n", fname, xerrmsg());
alpar@1
  1043
         longjmp(csa->jump, 1);
alpar@1
  1044
      }
alpar@1
  1045
      /* read problem line */
alpar@1
  1046
      read_designator(csa);
alpar@1
  1047
      if (strcmp(csa->field, "p") != 0)
alpar@1
  1048
         error(csa, "problem line missing or invalid");
alpar@1
  1049
      read_field(csa);
alpar@1
  1050
      if (strcmp(csa->field, "lp") == 0)
alpar@1
  1051
         mip = 0;
alpar@1
  1052
      else if (strcmp(csa->field, "mip") == 0)
alpar@1
  1053
         mip = 1;
alpar@1
  1054
      else
alpar@1
  1055
         error(csa, "wrong problem designator; `lp' or `mip' expected\n"
alpar@1
  1056
            );
alpar@1
  1057
      read_field(csa);
alpar@1
  1058
      if (strcmp(csa->field, "min") == 0)
alpar@1
  1059
         glp_set_obj_dir(P, GLP_MIN);
alpar@1
  1060
      else if (strcmp(csa->field, "max") == 0)
alpar@1
  1061
         glp_set_obj_dir(P, GLP_MAX);
alpar@1
  1062
      else
alpar@1
  1063
         error(csa, "objective sense missing or invalid");
alpar@1
  1064
      read_field(csa);
alpar@1
  1065
      if (!(str2int(csa->field, &m) == 0 && m >= 0))
alpar@1
  1066
         error(csa, "number of rows missing or invalid");
alpar@1
  1067
      read_field(csa);
alpar@1
  1068
      if (!(str2int(csa->field, &n) == 0 && n >= 0))
alpar@1
  1069
         error(csa, "number of columns missing or invalid");
alpar@1
  1070
      read_field(csa);
alpar@1
  1071
      if (!(str2int(csa->field, &nnz) == 0 && nnz >= 0))
alpar@1
  1072
         error(csa, "number of constraint coefficients missing or inval"
alpar@1
  1073
            "id");
alpar@1
  1074
      if (m > 0)
alpar@1
  1075
      {  glp_add_rows(P, m);
alpar@1
  1076
         for (i = 1; i <= m; i++)
alpar@1
  1077
            glp_set_row_bnds(P, i, GLP_FX, 0.0, 0.0);
alpar@1
  1078
      }
alpar@1
  1079
      if (n > 0)
alpar@1
  1080
      {  glp_add_cols(P, n);
alpar@1
  1081
         for (j = 1; j <= n; j++)
alpar@1
  1082
         {  if (!mip)
alpar@1
  1083
               glp_set_col_bnds(P, j, GLP_LO, 0.0, 0.0);
alpar@1
  1084
            else
alpar@1
  1085
               glp_set_col_kind(P, j, GLP_BV);
alpar@1
  1086
         }
alpar@1
  1087
      }
alpar@1
  1088
      end_of_line(csa);
alpar@1
  1089
      /* allocate working arrays */
alpar@1
  1090
      rf = xcalloc(1+m, sizeof(char));
alpar@1
  1091
      memset(rf, 0, 1+m);
alpar@1
  1092
      cf = xcalloc(1+n, sizeof(char));
alpar@1
  1093
      memset(cf, 0, 1+n);
alpar@1
  1094
      ln = xcalloc(1+nnz, sizeof(int));
alpar@1
  1095
      ia = xcalloc(1+nnz, sizeof(int));
alpar@1
  1096
      ja = xcalloc(1+nnz, sizeof(int));
alpar@1
  1097
      ar = xcalloc(1+nnz, sizeof(double));
alpar@1
  1098
      /* read descriptor lines */
alpar@1
  1099
      ne = 0;
alpar@1
  1100
      for (;;)
alpar@1
  1101
      {  read_designator(csa);
alpar@1
  1102
         if (strcmp(csa->field, "i") == 0)
alpar@1
  1103
         {  /* row descriptor */
alpar@1
  1104
            read_field(csa);
alpar@1
  1105
            if (str2int(csa->field, &i) != 0)
alpar@1
  1106
               error(csa, "row number missing or invalid");
alpar@1
  1107
            if (!(1 <= i && i <= m))
alpar@1
  1108
               error(csa, "row number out of range");
alpar@1
  1109
            read_field(csa);
alpar@1
  1110
            if (strcmp(csa->field, "f") == 0)
alpar@1
  1111
               type = GLP_FR;
alpar@1
  1112
            else if (strcmp(csa->field, "l") == 0)
alpar@1
  1113
               type = GLP_LO;
alpar@1
  1114
            else if (strcmp(csa->field, "u") == 0)
alpar@1
  1115
               type = GLP_UP;
alpar@1
  1116
            else if (strcmp(csa->field, "d") == 0)
alpar@1
  1117
               type = GLP_DB;
alpar@1
  1118
            else if (strcmp(csa->field, "s") == 0)
alpar@1
  1119
               type = GLP_FX;
alpar@1
  1120
            else
alpar@1
  1121
               error(csa, "row type missing or invalid");
alpar@1
  1122
            if (type == GLP_LO || type == GLP_DB || type == GLP_FX)
alpar@1
  1123
            {  read_field(csa);
alpar@1
  1124
               if (str2num(csa->field, &lb) != 0)
alpar@1
  1125
                  error(csa, "row lower bound/fixed value missing or in"
alpar@1
  1126
                     "valid");
alpar@1
  1127
            }
alpar@1
  1128
            else
alpar@1
  1129
               lb = 0.0;
alpar@1
  1130
            if (type == GLP_UP || type == GLP_DB)
alpar@1
  1131
            {  read_field(csa);
alpar@1
  1132
               if (str2num(csa->field, &ub) != 0)
alpar@1
  1133
                  error(csa, "row upper bound missing or invalid");
alpar@1
  1134
            }
alpar@1
  1135
            else
alpar@1
  1136
               ub = 0.0;
alpar@1
  1137
            if (rf[i] & 0x01)
alpar@1
  1138
               error(csa, "duplicate row descriptor");
alpar@1
  1139
            glp_set_row_bnds(P, i, type, lb, ub), rf[i] |= 0x01;
alpar@1
  1140
         }
alpar@1
  1141
         else if (strcmp(csa->field, "j") == 0)
alpar@1
  1142
         {  /* column descriptor */
alpar@1
  1143
            read_field(csa);
alpar@1
  1144
            if (str2int(csa->field, &j) != 0)
alpar@1
  1145
               error(csa, "column number missing or invalid");
alpar@1
  1146
            if (!(1 <= j && j <= n))
alpar@1
  1147
               error(csa, "column number out of range");
alpar@1
  1148
            if (!mip)
alpar@1
  1149
               kind = GLP_CV;
alpar@1
  1150
            else
alpar@1
  1151
            {  read_field(csa);
alpar@1
  1152
               if (strcmp(csa->field, "c") == 0)
alpar@1
  1153
                  kind = GLP_CV;
alpar@1
  1154
               else if (strcmp(csa->field, "i") == 0)
alpar@1
  1155
                  kind = GLP_IV;
alpar@1
  1156
               else if (strcmp(csa->field, "b") == 0)
alpar@1
  1157
               {  kind = GLP_IV;
alpar@1
  1158
                  type = GLP_DB, lb = 0.0, ub = 1.0;
alpar@1
  1159
                  goto skip;
alpar@1
  1160
               }
alpar@1
  1161
               else
alpar@1
  1162
                  error(csa, "column kind missing or invalid");
alpar@1
  1163
            }
alpar@1
  1164
            read_field(csa);
alpar@1
  1165
            if (strcmp(csa->field, "f") == 0)
alpar@1
  1166
               type = GLP_FR;
alpar@1
  1167
            else if (strcmp(csa->field, "l") == 0)
alpar@1
  1168
               type = GLP_LO;
alpar@1
  1169
            else if (strcmp(csa->field, "u") == 0)
alpar@1
  1170
               type = GLP_UP;
alpar@1
  1171
            else if (strcmp(csa->field, "d") == 0)
alpar@1
  1172
               type = GLP_DB;
alpar@1
  1173
            else if (strcmp(csa->field, "s") == 0)
alpar@1
  1174
               type = GLP_FX;
alpar@1
  1175
            else
alpar@1
  1176
               error(csa, "column type missing or invalid");
alpar@1
  1177
            if (type == GLP_LO || type == GLP_DB || type == GLP_FX)
alpar@1
  1178
            {  read_field(csa);
alpar@1
  1179
               if (str2num(csa->field, &lb) != 0)
alpar@1
  1180
                  error(csa, "column lower bound/fixed value missing or"
alpar@1
  1181
                     " invalid");
alpar@1
  1182
            }
alpar@1
  1183
            else
alpar@1
  1184
               lb = 0.0;
alpar@1
  1185
            if (type == GLP_UP || type == GLP_DB)
alpar@1
  1186
            {  read_field(csa);
alpar@1
  1187
               if (str2num(csa->field, &ub) != 0)
alpar@1
  1188
                  error(csa, "column upper bound missing or invalid");
alpar@1
  1189
            }
alpar@1
  1190
            else
alpar@1
  1191
               ub = 0.0;
alpar@1
  1192
skip:       if (cf[j] & 0x01)
alpar@1
  1193
               error(csa, "duplicate column descriptor");
alpar@1
  1194
            glp_set_col_kind(P, j, kind);
alpar@1
  1195
            glp_set_col_bnds(P, j, type, lb, ub), cf[j] |= 0x01;
alpar@1
  1196
         }
alpar@1
  1197
         else if (strcmp(csa->field, "a") == 0)
alpar@1
  1198
         {  /* coefficient descriptor */
alpar@1
  1199
            read_field(csa);
alpar@1
  1200
            if (str2int(csa->field, &i) != 0)
alpar@1
  1201
               error(csa, "row number missing or invalid");
alpar@1
  1202
            if (!(0 <= i && i <= m))
alpar@1
  1203
               error(csa, "row number out of range");
alpar@1
  1204
            read_field(csa);
alpar@1
  1205
            if (str2int(csa->field, &j) != 0)
alpar@1
  1206
               error(csa, "column number missing or invalid");
alpar@1
  1207
            if (!((i == 0 ? 0 : 1) <= j && j <= n))
alpar@1
  1208
               error(csa, "column number out of range");
alpar@1
  1209
            read_field(csa);
alpar@1
  1210
            if (i == 0)
alpar@1
  1211
            {  if (str2num(csa->field, &temp) != 0)
alpar@1
  1212
                  error(csa, "objective %s missing or invalid",
alpar@1
  1213
                     j == 0 ? "constant term" : "coefficient");
alpar@1
  1214
               if (cf[j] & 0x10)
alpar@1
  1215
                  error(csa, "duplicate objective %s",
alpar@1
  1216
                     j == 0 ? "constant term" : "coefficient");
alpar@1
  1217
               glp_set_obj_coef(P, j, temp), cf[j] |= 0x10;
alpar@1
  1218
            }
alpar@1
  1219
            else
alpar@1
  1220
            {  if (str2num(csa->field, &temp) != 0)
alpar@1
  1221
                  error(csa, "constraint coefficient missing or invalid"
alpar@1
  1222
                     );
alpar@1
  1223
               if (ne == nnz)
alpar@1
  1224
                  error(csa, "too many constraint coefficient descripto"
alpar@1
  1225
                     "rs");
alpar@1
  1226
               ln[++ne] = csa->count;
alpar@1
  1227
               ia[ne] = i, ja[ne] = j, ar[ne] = temp;
alpar@1
  1228
            }
alpar@1
  1229
         }
alpar@1
  1230
         else if (strcmp(csa->field, "n") == 0)
alpar@1
  1231
         {  /* symbolic name descriptor */
alpar@1
  1232
            read_field(csa);
alpar@1
  1233
            if (strcmp(csa->field, "p") == 0)
alpar@1
  1234
            {  /* problem name */
alpar@1
  1235
               read_field(csa);
alpar@1
  1236
               if (P->name != NULL)
alpar@1
  1237
                  error(csa, "duplicate problem name");
alpar@1
  1238
               glp_set_prob_name(P, csa->field);
alpar@1
  1239
            }
alpar@1
  1240
            else if (strcmp(csa->field, "z") == 0)
alpar@1
  1241
            {  /* objective name */
alpar@1
  1242
               read_field(csa);
alpar@1
  1243
               if (P->obj != NULL)
alpar@1
  1244
                  error(csa, "duplicate objective name");
alpar@1
  1245
               glp_set_obj_name(P, csa->field);
alpar@1
  1246
            }
alpar@1
  1247
            else if (strcmp(csa->field, "i") == 0)
alpar@1
  1248
            {  /* row name */
alpar@1
  1249
               read_field(csa);
alpar@1
  1250
               if (str2int(csa->field, &i) != 0)
alpar@1
  1251
                  error(csa, "row number missing or invalid");
alpar@1
  1252
               if (!(1 <= i && i <= m))
alpar@1
  1253
                  error(csa, "row number out of range");
alpar@1
  1254
               read_field(csa);
alpar@1
  1255
               if (P->row[i]->name != NULL)
alpar@1
  1256
                  error(csa, "duplicate row name");
alpar@1
  1257
               glp_set_row_name(P, i, csa->field);
alpar@1
  1258
            }
alpar@1
  1259
            else if (strcmp(csa->field, "j") == 0)
alpar@1
  1260
            {  /* column name */
alpar@1
  1261
               read_field(csa);
alpar@1
  1262
               if (str2int(csa->field, &j) != 0)
alpar@1
  1263
                  error(csa, "column number missing or invalid");
alpar@1
  1264
               if (!(1 <= j && j <= n))
alpar@1
  1265
                  error(csa, "column number out of range");
alpar@1
  1266
               read_field(csa);
alpar@1
  1267
               if (P->col[j]->name != NULL)
alpar@1
  1268
                  error(csa, "duplicate column name");
alpar@1
  1269
               glp_set_col_name(P, j, csa->field);
alpar@1
  1270
            }
alpar@1
  1271
            else
alpar@1
  1272
               error(csa, "object designator missing or invalid");
alpar@1
  1273
         }
alpar@1
  1274
         else if (strcmp(csa->field, "e") == 0)
alpar@1
  1275
            break;
alpar@1
  1276
         else
alpar@1
  1277
            error(csa, "line designator missing or invalid");
alpar@1
  1278
         end_of_line(csa);
alpar@1
  1279
      }
alpar@1
  1280
      if (ne < nnz)
alpar@1
  1281
         error(csa, "too few constraint coefficient descriptors");
alpar@1
  1282
      xassert(ne == nnz);
alpar@1
  1283
      k = glp_check_dup(m, n, ne, ia, ja);
alpar@1
  1284
      xassert(0 <= k && k <= nnz);
alpar@1
  1285
      if (k > 0)
alpar@1
  1286
      {  csa->count = ln[k];
alpar@1
  1287
         error(csa, "duplicate constraint coefficient");
alpar@1
  1288
      }
alpar@1
  1289
      glp_load_matrix(P, ne, ia, ja, ar);
alpar@1
  1290
      /* print some statistics */
alpar@1
  1291
      if (P->name != NULL)
alpar@1
  1292
         xprintf("Problem: %s\n", P->name);
alpar@1
  1293
      if (P->obj != NULL)
alpar@1
  1294
         xprintf("Objective: %s\n", P->obj);
alpar@1
  1295
      xprintf("%d row%s, %d column%s, %d non-zero%s\n",
alpar@1
  1296
         m, m == 1 ? "" : "s", n, n == 1 ? "" : "s", nnz, nnz == 1 ?
alpar@1
  1297
         "" : "s");
alpar@1
  1298
      if (glp_get_num_int(P) > 0)
alpar@1
  1299
      {  int ni = glp_get_num_int(P);
alpar@1
  1300
         int nb = glp_get_num_bin(P);
alpar@1
  1301
         if (ni == 1)
alpar@1
  1302
         {  if (nb == 0)
alpar@1
  1303
               xprintf("One variable is integer\n");
alpar@1
  1304
            else
alpar@1
  1305
               xprintf("One variable is binary\n");
alpar@1
  1306
         }
alpar@1
  1307
         else
alpar@1
  1308
         {  xprintf("%d integer variables, ", ni);
alpar@1
  1309
            if (nb == 0)
alpar@1
  1310
               xprintf("none");
alpar@1
  1311
            else if (nb == 1)
alpar@1
  1312
               xprintf("one");
alpar@1
  1313
            else if (nb == ni)
alpar@1
  1314
               xprintf("all");
alpar@1
  1315
            else
alpar@1
  1316
               xprintf("%d", nb);
alpar@1
  1317
            xprintf(" of which %s binary\n", nb == 1 ? "is" : "are");
alpar@1
  1318
         }
alpar@1
  1319
      }
alpar@1
  1320
      xprintf("%d lines were read\n", csa->count);
alpar@1
  1321
      /* problem data has been successfully read */
alpar@1
  1322
      glp_sort_matrix(P);
alpar@1
  1323
      ret = 0;
alpar@1
  1324
done: if (csa->fp != NULL) xfclose(csa->fp);
alpar@1
  1325
      if (rf != NULL) xfree(rf);
alpar@1
  1326
      if (cf != NULL) xfree(cf);
alpar@1
  1327
      if (ln != NULL) xfree(ln);
alpar@1
  1328
      if (ia != NULL) xfree(ia);
alpar@1
  1329
      if (ja != NULL) xfree(ja);
alpar@1
  1330
      if (ar != NULL) xfree(ar);
alpar@1
  1331
      if (ret) glp_erase_prob(P);
alpar@1
  1332
      return ret;
alpar@1
  1333
}
alpar@1
  1334
alpar@1
  1335
/***********************************************************************
alpar@1
  1336
*  NAME
alpar@1
  1337
*
alpar@1
  1338
*  glp_write_prob - write problem data in GLPK format
alpar@1
  1339
*
alpar@1
  1340
*  SYNOPSIS
alpar@1
  1341
*
alpar@1
  1342
*  int glp_write_prob(glp_prob *P, int flags, const char *fname);
alpar@1
  1343
*
alpar@1
  1344
*  The routine glp_write_prob writes problem data in GLPK LP/MIP format
alpar@1
  1345
*  to a text file.
alpar@1
  1346
*
alpar@1
  1347
*  RETURNS
alpar@1
  1348
*
alpar@1
  1349
*  If the operation was successful, the routine returns zero. Otherwise
alpar@1
  1350
*  it prints an error message and returns non-zero. */
alpar@1
  1351
alpar@1
  1352
int glp_write_prob(glp_prob *P, int flags, const char *fname)
alpar@1
  1353
{     XFILE *fp;
alpar@1
  1354
      GLPROW *row;
alpar@1
  1355
      GLPCOL *col;
alpar@1
  1356
      GLPAIJ *aij;
alpar@1
  1357
      int mip, i, j, count, ret;
alpar@1
  1358
      if (P == NULL || P->magic != GLP_PROB_MAGIC)
alpar@1
  1359
         xerror("glp_write_prob: P = %p; invalid problem object\n",
alpar@1
  1360
            P);
alpar@1
  1361
      if (flags != 0)
alpar@1
  1362
         xerror("glp_write_prob: flags = %d; invalid parameter\n",
alpar@1
  1363
            flags);
alpar@1
  1364
      if (fname == NULL)
alpar@1
  1365
         xerror("glp_write_prob: fname = %d; invalid parameter\n",
alpar@1
  1366
            fname);
alpar@1
  1367
      xprintf("Writing problem data to `%s'...\n", fname);
alpar@1
  1368
      fp = xfopen(fname, "w"), count = 0;
alpar@1
  1369
      if (fp == NULL)
alpar@1
  1370
      {  xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
alpar@1
  1371
         ret = 1;
alpar@1
  1372
         goto done;
alpar@1
  1373
      }
alpar@1
  1374
      /* write problem line */
alpar@1
  1375
      mip = (glp_get_num_int(P) > 0);
alpar@1
  1376
      xfprintf(fp, "p %s %s %d %d %d\n", !mip ? "lp" : "mip",
alpar@1
  1377
         P->dir == GLP_MIN ? "min" : P->dir == GLP_MAX ? "max" : "???",
alpar@1
  1378
         P->m, P->n, P->nnz), count++;
alpar@1
  1379
      if (P->name != NULL)
alpar@1
  1380
         xfprintf(fp, "n p %s\n", P->name), count++;
alpar@1
  1381
      if (P->obj != NULL)
alpar@1
  1382
         xfprintf(fp, "n z %s\n", P->obj), count++;
alpar@1
  1383
      /* write row descriptors */
alpar@1
  1384
      for (i = 1; i <= P->m; i++)
alpar@1
  1385
      {  row = P->row[i];
alpar@1
  1386
         if (row->type == GLP_FX && row->lb == 0.0)
alpar@1
  1387
            goto skip1;
alpar@1
  1388
         xfprintf(fp, "i %d ", i), count++;
alpar@1
  1389
         if (row->type == GLP_FR)
alpar@1
  1390
            xfprintf(fp, "f\n");
alpar@1
  1391
         else if (row->type == GLP_LO)
alpar@1
  1392
            xfprintf(fp, "l %.*g\n", DBL_DIG, row->lb);
alpar@1
  1393
         else if (row->type == GLP_UP)
alpar@1
  1394
            xfprintf(fp, "u %.*g\n", DBL_DIG, row->ub);
alpar@1
  1395
         else if (row->type == GLP_DB)
alpar@1
  1396
            xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, row->lb, DBL_DIG,
alpar@1
  1397
                  row->ub);
alpar@1
  1398
         else if (row->type == GLP_FX)
alpar@1
  1399
            xfprintf(fp, "s %.*g\n", DBL_DIG, row->lb);
alpar@1
  1400
         else
alpar@1
  1401
            xassert(row != row);
alpar@1
  1402
skip1:   if (row->name != NULL)
alpar@1
  1403
            xfprintf(fp, "n i %d %s\n", i, row->name), count++;
alpar@1
  1404
      }
alpar@1
  1405
      /* write column descriptors */
alpar@1
  1406
      for (j = 1; j <= P->n; j++)
alpar@1
  1407
      {  col = P->col[j];
alpar@1
  1408
         if (!mip && col->type == GLP_LO && col->lb == 0.0)
alpar@1
  1409
            goto skip2;
alpar@1
  1410
         if (mip && col->kind == GLP_IV && col->type == GLP_DB &&
alpar@1
  1411
             col->lb == 0.0 && col->ub == 1.0)
alpar@1
  1412
            goto skip2;
alpar@1
  1413
         xfprintf(fp, "j %d ", j), count++;
alpar@1
  1414
         if (mip)
alpar@1
  1415
         {  if (col->kind == GLP_CV)
alpar@1
  1416
               xfprintf(fp, "c ");
alpar@1
  1417
            else if (col->kind == GLP_IV)
alpar@1
  1418
               xfprintf(fp, "i ");
alpar@1
  1419
            else
alpar@1
  1420
               xassert(col != col);
alpar@1
  1421
         }
alpar@1
  1422
         if (col->type == GLP_FR)
alpar@1
  1423
            xfprintf(fp, "f\n");
alpar@1
  1424
         else if (col->type == GLP_LO)
alpar@1
  1425
            xfprintf(fp, "l %.*g\n", DBL_DIG, col->lb);
alpar@1
  1426
         else if (col->type == GLP_UP)
alpar@1
  1427
            xfprintf(fp, "u %.*g\n", DBL_DIG, col->ub);
alpar@1
  1428
         else if (col->type == GLP_DB)
alpar@1
  1429
            xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, col->lb, DBL_DIG,
alpar@1
  1430
                  col->ub);
alpar@1
  1431
         else if (col->type == GLP_FX)
alpar@1
  1432
            xfprintf(fp, "s %.*g\n", DBL_DIG, col->lb);
alpar@1
  1433
         else
alpar@1
  1434
            xassert(col != col);
alpar@1
  1435
skip2:   if (col->name != NULL)
alpar@1
  1436
            xfprintf(fp, "n j %d %s\n", j, col->name), count++;
alpar@1
  1437
      }
alpar@1
  1438
      /* write objective coefficient descriptors */
alpar@1
  1439
      if (P->c0 != 0.0)
alpar@1
  1440
         xfprintf(fp, "a 0 0 %.*g\n", DBL_DIG, P->c0), count++;
alpar@1
  1441
      for (j = 1; j <= P->n; j++)
alpar@1
  1442
      {  col = P->col[j];
alpar@1
  1443
         if (col->coef != 0.0)
alpar@1
  1444
            xfprintf(fp, "a 0 %d %.*g\n", j, DBL_DIG, col->coef),
alpar@1
  1445
               count++;
alpar@1
  1446
      }
alpar@1
  1447
      /* write constraint coefficient descriptors */
alpar@1
  1448
      for (i = 1; i <= P->m; i++)
alpar@1
  1449
      {  row = P->row[i];
alpar@1
  1450
         for (aij = row->ptr; aij != NULL; aij = aij->r_next)
alpar@1
  1451
            xfprintf(fp, "a %d %d %.*g\n", i, aij->col->j, DBL_DIG,
alpar@1
  1452
               aij->val), count++;
alpar@1
  1453
      }
alpar@1
  1454
      /* write end line */
alpar@1
  1455
      xfprintf(fp, "e o f\n"), count++;
alpar@1
  1456
      xfflush(fp);
alpar@1
  1457
      if (xferror(fp))
alpar@1
  1458
      {  xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
alpar@1
  1459
         ret = 1;
alpar@1
  1460
         goto done;
alpar@1
  1461
      }
alpar@1
  1462
      xprintf("%d lines were written\n", count);
alpar@1
  1463
      ret = 0;
alpar@1
  1464
done: if (fp != NULL) xfclose(fp);
alpar@1
  1465
      return ret;
alpar@1
  1466
}
alpar@1
  1467
alpar@1
  1468
/* eof */