COIN-OR::LEMON - Graph Library

source: glpk-cmake/src/glpapi11.c @ 1:c445c931472f

Last change on this file since 1:c445c931472f was 1:c445c931472f, checked in by Alpar Juttner <alpar@…>, 14 years ago

Import glpk-4.45

  • Generated files and doc/notes are removed
File size: 43.5 KB
Line 
1/* glpapi11.c (utility routines) */
2
3/***********************************************************************
4*  This code is part of GLPK (GNU Linear Programming Kit).
5*
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>.
10*
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.
15*
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.
20*
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***********************************************************************/
24
25#include "glpapi.h"
26
27int glp_print_sol(glp_prob *P, const char *fname)
28{     /* write basic solution in printable format */
29      XFILE *fp;
30      GLPROW *row;
31      GLPCOL *col;
32      int i, j, t, ae_ind, re_ind, ret;
33      double ae_max, re_max;
34      xprintf("Writing basic solution to `%s'...\n", fname);
35      fp = xfopen(fname, "w");
36      if (fp == NULL)
37      {  xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
38         ret = 1;
39         goto done;
40      }
41      xfprintf(fp, "%-12s%s\n", "Problem:",
42         P->name == NULL ? "" : P->name);
43      xfprintf(fp, "%-12s%d\n", "Rows:", P->m);
44      xfprintf(fp, "%-12s%d\n", "Columns:", P->n);
45      xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz);
46      t = glp_get_status(P);
47      xfprintf(fp, "%-12s%s\n", "Status:",
48         t == GLP_OPT    ? "OPTIMAL" :
49         t == GLP_FEAS   ? "FEASIBLE" :
50         t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" :
51         t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" :
52         t == GLP_UNBND  ? "UNBOUNDED" :
53         t == GLP_UNDEF  ? "UNDEFINED" : "???");
54      xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:",
55         P->obj == NULL ? "" : P->obj,
56         P->obj == NULL ? "" : " = ", P->obj_val,
57         P->dir == GLP_MIN ? "MINimum" :
58         P->dir == GLP_MAX ? "MAXimum" : "???");
59      xfprintf(fp, "\n");
60      xfprintf(fp, "   No.   Row name   St   Activity     Lower bound  "
61         " Upper bound    Marginal\n");
62      xfprintf(fp, "------ ------------ -- ------------- ------------- "
63         "------------- -------------\n");
64      for (i = 1; i <= P->m; i++)
65      {  row = P->row[i];
66         xfprintf(fp, "%6d ", i);
67         if (row->name == NULL || strlen(row->name) <= 12)
68            xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name);
69         else
70            xfprintf(fp, "%s\n%20s", row->name, "");
71         xfprintf(fp, "%s ",
72            row->stat == GLP_BS ? "B " :
73            row->stat == GLP_NL ? "NL" :
74            row->stat == GLP_NU ? "NU" :
75            row->stat == GLP_NF ? "NF" :
76            row->stat == GLP_NS ? "NS" : "??");
77         xfprintf(fp, "%13.6g ",
78            fabs(row->prim) <= 1e-9 ? 0.0 : row->prim);
79         if (row->type == GLP_LO || row->type == GLP_DB ||
80             row->type == GLP_FX)
81            xfprintf(fp, "%13.6g ", row->lb);
82         else
83            xfprintf(fp, "%13s ", "");
84         if (row->type == GLP_UP || row->type == GLP_DB)
85            xfprintf(fp, "%13.6g ", row->ub);
86         else
87            xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : "");
88         if (row->stat != GLP_BS)
89         {  if (fabs(row->dual) <= 1e-9)
90               xfprintf(fp, "%13s", "< eps");
91            else
92               xfprintf(fp, "%13.6g ", row->dual);
93         }
94         xfprintf(fp, "\n");
95      }
96      xfprintf(fp, "\n");
97      xfprintf(fp, "   No. Column name  St   Activity     Lower bound  "
98         " Upper bound    Marginal\n");
99      xfprintf(fp, "------ ------------ -- ------------- ------------- "
100         "------------- -------------\n");
101      for (j = 1; j <= P->n; j++)
102      {  col = P->col[j];
103         xfprintf(fp, "%6d ", j);
104         if (col->name == NULL || strlen(col->name) <= 12)
105            xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name);
106         else
107            xfprintf(fp, "%s\n%20s", col->name, "");
108         xfprintf(fp, "%s ",
109            col->stat == GLP_BS ? "B " :
110            col->stat == GLP_NL ? "NL" :
111            col->stat == GLP_NU ? "NU" :
112            col->stat == GLP_NF ? "NF" :
113            col->stat == GLP_NS ? "NS" : "??");
114         xfprintf(fp, "%13.6g ",
115            fabs(col->prim) <= 1e-9 ? 0.0 : col->prim);
116         if (col->type == GLP_LO || col->type == GLP_DB ||
117             col->type == GLP_FX)
118            xfprintf(fp, "%13.6g ", col->lb);
119         else
120            xfprintf(fp, "%13s ", "");
121         if (col->type == GLP_UP || col->type == GLP_DB)
122            xfprintf(fp, "%13.6g ", col->ub);
123         else
124            xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : "");
125         if (col->stat != GLP_BS)
126         {  if (fabs(col->dual) <= 1e-9)
127               xfprintf(fp, "%13s", "< eps");
128            else
129               xfprintf(fp, "%13.6g ", col->dual);
130         }
131         xfprintf(fp, "\n");
132      }
133      xfprintf(fp, "\n");
134      xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n");
135      xfprintf(fp, "\n");
136      _glp_check_kkt(P, GLP_SOL, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
137         &re_ind);
138      xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n",
139         ae_max, ae_ind);
140      xfprintf(fp, "        max.rel.err = %.2e on row %d\n",
141         re_max, re_ind);
142      xfprintf(fp, "%8s%s\n", "",
143         re_max <= 1e-9 ? "High quality" :
144         re_max <= 1e-6 ? "Medium quality" :
145         re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG");
146      xfprintf(fp, "\n");
147      _glp_check_kkt(P, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
148         &re_ind);
149      xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n",
150            ae_max, ae_ind <= P->m ? "row" : "column",
151            ae_ind <= P->m ? ae_ind : ae_ind - P->m);
152      xfprintf(fp, "        max.rel.err = %.2e on %s %d\n",
153            re_max, re_ind <= P->m ? "row" : "column",
154            re_ind <= P->m ? re_ind : re_ind - P->m);
155      xfprintf(fp, "%8s%s\n", "",
156         re_max <= 1e-9 ? "High quality" :
157         re_max <= 1e-6 ? "Medium quality" :
158         re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL"
159            "E");
160      xfprintf(fp, "\n");
161      _glp_check_kkt(P, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max,
162         &re_ind);
163      xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n",
164         ae_max, ae_ind == 0 ? 0 : ae_ind - P->m);
165      xfprintf(fp, "        max.rel.err = %.2e on column %d\n",
166         re_max, re_ind == 0 ? 0 : re_ind - P->m);
167      xfprintf(fp, "%8s%s\n", "",
168         re_max <= 1e-9 ? "High quality" :
169         re_max <= 1e-6 ? "Medium quality" :
170         re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG");
171      xfprintf(fp, "\n");
172      _glp_check_kkt(P, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max,
173         &re_ind);
174      xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n",
175            ae_max, ae_ind <= P->m ? "row" : "column",
176            ae_ind <= P->m ? ae_ind : ae_ind - P->m);
177      xfprintf(fp, "        max.rel.err = %.2e on %s %d\n",
178            re_max, re_ind <= P->m ? "row" : "column",
179            re_ind <= P->m ? re_ind : re_ind - P->m);
180      xfprintf(fp, "%8s%s\n", "",
181         re_max <= 1e-9 ? "High quality" :
182         re_max <= 1e-6 ? "Medium quality" :
183         re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE")
184            ;
185      xfprintf(fp, "\n");
186      xfprintf(fp, "End of output\n");
187      xfflush(fp);
188      if (xferror(fp))
189      {  xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
190         ret = 1;
191         goto done;
192      }
193      ret = 0;
194done: if (fp != NULL) xfclose(fp);
195      return ret;
196}
197
198/***********************************************************************
199*  NAME
200*
201*  glp_read_sol - read basic solution from text file
202*
203*  SYNOPSIS
204*
205*  int glp_read_sol(glp_prob *lp, const char *fname);
206*
207*  DESCRIPTION
208*
209*  The routine glp_read_sol reads basic solution from a text file whose
210*  name is specified by the parameter fname into the problem object.
211*
212*  For the file format see description of the routine glp_write_sol.
213*
214*  RETURNS
215*
216*  On success the routine returns zero, otherwise non-zero. */
217
218int glp_read_sol(glp_prob *lp, const char *fname)
219{     glp_data *data;
220      jmp_buf jump;
221      int i, j, k, ret = 0;
222      xprintf("Reading basic solution from `%s'...\n", fname);
223      data = glp_sdf_open_file(fname);
224      if (data == NULL)
225      {  ret = 1;
226         goto done;
227      }
228      if (setjmp(jump))
229      {  ret = 1;
230         goto done;
231      }
232      glp_sdf_set_jump(data, jump);
233      /* number of rows, number of columns */
234      k = glp_sdf_read_int(data);
235      if (k != lp->m)
236         glp_sdf_error(data, "wrong number of rows\n");
237      k = glp_sdf_read_int(data);
238      if (k != lp->n)
239         glp_sdf_error(data, "wrong number of columns\n");
240      /* primal status, dual status, objective value */
241      k = glp_sdf_read_int(data);
242      if (!(k == GLP_UNDEF || k == GLP_FEAS || k == GLP_INFEAS ||
243            k == GLP_NOFEAS))
244         glp_sdf_error(data, "invalid primal status\n");
245      lp->pbs_stat = k;
246      k = glp_sdf_read_int(data);
247      if (!(k == GLP_UNDEF || k == GLP_FEAS || k == GLP_INFEAS ||
248            k == GLP_NOFEAS))
249         glp_sdf_error(data, "invalid dual status\n");
250      lp->dbs_stat = k;
251      lp->obj_val = glp_sdf_read_num(data);
252      /* rows (auxiliary variables) */
253      for (i = 1; i <= lp->m; i++)
254      {  GLPROW *row = lp->row[i];
255         /* status, primal value, dual value */
256         k = glp_sdf_read_int(data);
257         if (!(k == GLP_BS || k == GLP_NL || k == GLP_NU ||
258               k == GLP_NF || k == GLP_NS))
259            glp_sdf_error(data, "invalid row status\n");
260         glp_set_row_stat(lp, i, k);
261         row->prim = glp_sdf_read_num(data);
262         row->dual = glp_sdf_read_num(data);
263      }
264      /* columns (structural variables) */
265      for (j = 1; j <= lp->n; j++)
266      {  GLPCOL *col = lp->col[j];
267         /* status, primal value, dual value */
268         k = glp_sdf_read_int(data);
269         if (!(k == GLP_BS || k == GLP_NL || k == GLP_NU ||
270               k == GLP_NF || k == GLP_NS))
271            glp_sdf_error(data, "invalid column status\n");
272         glp_set_col_stat(lp, j, k);
273         col->prim = glp_sdf_read_num(data);
274         col->dual = glp_sdf_read_num(data);
275      }
276      xprintf("%d lines were read\n", glp_sdf_line(data));
277done: if (ret) lp->pbs_stat = lp->dbs_stat = GLP_UNDEF;
278      if (data != NULL) glp_sdf_close_file(data);
279      return ret;
280}
281
282/***********************************************************************
283*  NAME
284*
285*  glp_write_sol - write basic solution to text file
286*
287*  SYNOPSIS
288*
289*  int glp_write_sol(glp_prob *lp, const char *fname);
290*
291*  DESCRIPTION
292*
293*  The routine glp_write_sol writes the current basic solution to a
294*  text file whose name is specified by the parameter fname. This file
295*  can be read back with the routine glp_read_sol.
296*
297*  RETURNS
298*
299*  On success the routine returns zero, otherwise non-zero.
300*
301*  FILE FORMAT
302*
303*  The file created by the routine glp_write_sol is a plain text file,
304*  which contains the following information:
305*
306*     m n
307*     p_stat d_stat obj_val
308*     r_stat[1] r_prim[1] r_dual[1]
309*     . . .
310*     r_stat[m] r_prim[m] r_dual[m]
311*     c_stat[1] c_prim[1] c_dual[1]
312*     . . .
313*     c_stat[n] c_prim[n] c_dual[n]
314*
315*  where:
316*  m is the number of rows (auxiliary variables);
317*  n is the number of columns (structural variables);
318*  p_stat is the primal status of the basic solution (GLP_UNDEF = 1,
319*     GLP_FEAS = 2, GLP_INFEAS = 3, or GLP_NOFEAS = 4);
320*  d_stat is the dual status of the basic solution (GLP_UNDEF = 1,
321*     GLP_FEAS = 2, GLP_INFEAS = 3, or GLP_NOFEAS = 4);
322*  obj_val is the objective value;
323*  r_stat[i], i = 1,...,m, is the status of i-th row (GLP_BS = 1,
324*     GLP_NL = 2, GLP_NU = 3, GLP_NF = 4, or GLP_NS = 5);
325*  r_prim[i], i = 1,...,m, is the primal value of i-th row;
326*  r_dual[i], i = 1,...,m, is the dual value of i-th row;
327*  c_stat[j], j = 1,...,n, is the status of j-th column (GLP_BS = 1,
328*     GLP_NL = 2, GLP_NU = 3, GLP_NF = 4, or GLP_NS = 5);
329*  c_prim[j], j = 1,...,n, is the primal value of j-th column;
330*  c_dual[j], j = 1,...,n, is the dual value of j-th column. */
331
332int glp_write_sol(glp_prob *lp, const char *fname)
333{     XFILE *fp;
334      int i, j, ret = 0;
335      xprintf("Writing basic solution to `%s'...\n", fname);
336      fp = xfopen(fname, "w");
337      if (fp == NULL)
338      {  xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
339         ret = 1;
340         goto done;
341      }
342      /* number of rows, number of columns */
343      xfprintf(fp, "%d %d\n", lp->m, lp->n);
344      /* primal status, dual status, objective value */
345      xfprintf(fp, "%d %d %.*g\n", lp->pbs_stat, lp->dbs_stat, DBL_DIG,
346         lp->obj_val);
347      /* rows (auxiliary variables) */
348      for (i = 1; i <= lp->m; i++)
349      {  GLPROW *row = lp->row[i];
350         /* status, primal value, dual value */
351         xfprintf(fp, "%d %.*g %.*g\n", row->stat, DBL_DIG, row->prim,
352            DBL_DIG, row->dual);
353      }
354      /* columns (structural variables) */
355      for (j = 1; j <= lp->n; j++)
356      {  GLPCOL *col = lp->col[j];
357         /* status, primal value, dual value */
358         xfprintf(fp, "%d %.*g %.*g\n", col->stat, DBL_DIG, col->prim,
359            DBL_DIG, col->dual);
360      }
361      xfflush(fp);
362      if (xferror(fp))
363      {  xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
364         ret = 1;
365         goto done;
366      }
367      xprintf("%d lines were written\n", 2 + lp->m + lp->n);
368done: if (fp != NULL) xfclose(fp);
369      return ret;
370}
371
372/**********************************************************************/
373
374static char *format(char buf[13+1], double x)
375{     /* format floating-point number in MPS/360-like style */
376      if (x == -DBL_MAX)
377         strcpy(buf, "         -Inf");
378      else if (x == +DBL_MAX)
379         strcpy(buf, "         +Inf");
380      else if (fabs(x) <= 999999.99998)
381      {  sprintf(buf, "%13.5f", x);
382#if 1
383         if (strcmp(buf, "      0.00000") == 0 ||
384             strcmp(buf, "     -0.00000") == 0)
385            strcpy(buf, "       .     ");
386         else if (memcmp(buf, "      0.", 8) == 0)
387            memcpy(buf, "       .", 8);
388         else if (memcmp(buf, "     -0.", 8) == 0)
389            memcpy(buf, "      -.", 8);
390#endif
391      }
392      else
393         sprintf(buf, "%13.6g", x);
394      return buf;
395}
396
397int glp_print_ranges(glp_prob *P, int len, const int list[],
398      int flags, const char *fname)
399{     /* print sensitivity analysis report */
400      XFILE *fp = NULL;
401      GLPROW *row;
402      GLPCOL *col;
403      int m, n, pass, k, t, numb, type, stat, var1, var2, count, page,
404         ret;
405      double lb, ub, slack, coef, prim, dual, value1, value2, coef1,
406         coef2, obj1, obj2;
407      const char *name, *limit;
408      char buf[13+1];
409      /* sanity checks */
410      if (P == NULL || P->magic != GLP_PROB_MAGIC)
411         xerror("glp_print_ranges: P = %p; invalid problem object\n",
412            P);
413      m = P->m, n = P->n;
414      if (len < 0)
415         xerror("glp_print_ranges: len = %d; invalid list length\n",
416            len);
417      if (len > 0)
418      {  if (list == NULL)
419            xerror("glp_print_ranges: list = %p: invalid parameter\n",
420               list);
421         for (t = 1; t <= len; t++)
422         {  k = list[t];
423            if (!(1 <= k && k <= m+n))
424               xerror("glp_print_ranges: list[%d] = %d; row/column numb"
425                  "er out of range\n", t, k);
426         }
427      }
428      if (flags != 0)
429         xerror("glp_print_ranges: flags = %d; invalid parameter\n",
430            flags);
431      if (fname == NULL)
432         xerror("glp_print_ranges: fname = %p; invalid parameter\n",
433            fname);
434      if (glp_get_status(P) != GLP_OPT)
435      {  xprintf("glp_print_ranges: optimal basic solution required\n");
436         ret = 1;
437         goto done;
438      }
439      if (!glp_bf_exists(P))
440      {  xprintf("glp_print_ranges: basis factorization required\n");
441         ret = 2;
442         goto done;
443      }
444      /* start reporting */
445      xprintf("Write sensitivity analysis report to `%s'...\n", fname);
446      fp = xfopen(fname, "w");
447      if (fp == NULL)
448      {  xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
449         ret = 3;
450         goto done;
451      }
452      page = count = 0;
453      for (pass = 1; pass <= 2; pass++)
454      for (t = 1; t <= (len == 0 ? m+n : len); t++)
455      {  if (t == 1) count = 0;
456         k = (len == 0 ? t : list[t]);
457         if (pass == 1 && k > m || pass == 2 && k <= m)
458            continue;
459         if (count == 0)
460         {  xfprintf(fp, "GLPK %-4s - SENSITIVITY ANALYSIS REPORT%73sPa"
461               "ge%4d\n", glp_version(), "", ++page);
462            xfprintf(fp, "\n");
463            xfprintf(fp, "%-12s%s\n", "Problem:",
464               P->name == NULL ? "" : P->name);
465            xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:",
466               P->obj == NULL ? "" : P->obj,
467               P->obj == NULL ? "" : " = ", P->obj_val,
468               P->dir == GLP_MIN ? "MINimum" :
469               P->dir == GLP_MAX ? "MAXimum" : "???");
470            xfprintf(fp, "\n");
471            xfprintf(fp, "%6s %-12s %2s %13s %13s %13s  %13s %13s %13s "
472               "%s\n", "No.", pass == 1 ? "Row name" : "Column name",
473               "St", "Activity", pass == 1 ? "Slack" : "Obj coef",
474               "Lower bound", "Activity", "Obj coef", "Obj value at",
475               "Limiting");
476            xfprintf(fp, "%6s %-12s %2s %13s %13s %13s  %13s %13s %13s "
477               "%s\n", "", "", "", "", "Marginal", "Upper bound",
478               "range", "range", "break point", "variable");
479            xfprintf(fp, "------ ------------ -- ------------- --------"
480               "----- -------------  ------------- ------------- ------"
481               "------- ------------\n");
482         }
483         if (pass == 1)
484         {  numb = k;
485            xassert(1 <= numb && numb <= m);
486            row = P->row[numb];
487            name = row->name;
488            type = row->type;
489            lb = glp_get_row_lb(P, numb);
490            ub = glp_get_row_ub(P, numb);
491            coef = 0.0;
492            stat = row->stat;
493            prim = row->prim;
494            if (type == GLP_FR)
495               slack = - prim;
496            else if (type == GLP_LO)
497               slack = lb - prim;
498            else if (type == GLP_UP || type == GLP_DB || type == GLP_FX)
499               slack = ub - prim;
500            dual = row->dual;
501         }
502         else
503         {  numb = k - m;
504            xassert(1 <= numb && numb <= n);
505            col = P->col[numb];
506            name = col->name;
507            lb = glp_get_col_lb(P, numb);
508            ub = glp_get_col_ub(P, numb);
509            coef = col->coef;
510            stat = col->stat;
511            prim = col->prim;
512            slack = 0.0;
513            dual = col->dual;
514         }
515         if (stat != GLP_BS)
516         {  glp_analyze_bound(P, k, &value1, &var1, &value2, &var2);
517            if (stat == GLP_NF)
518               coef1 = coef2 = coef;
519            else if (stat == GLP_NS)
520               coef1 = -DBL_MAX, coef2 = +DBL_MAX;
521            else if (stat == GLP_NL && P->dir == GLP_MIN ||
522                     stat == GLP_NU && P->dir == GLP_MAX)
523               coef1 = coef - dual, coef2 = +DBL_MAX;
524            else
525               coef1 = -DBL_MAX, coef2 = coef - dual;
526            if (value1 == -DBL_MAX)
527            {  if (dual < -1e-9)
528                  obj1 = +DBL_MAX;
529               else if (dual > +1e-9)
530                  obj1 = -DBL_MAX;
531               else
532                  obj1 = P->obj_val;
533            }
534            else
535               obj1 = P->obj_val + dual * (value1 - prim);
536            if (value2 == +DBL_MAX)
537            {  if (dual < -1e-9)
538                  obj2 = -DBL_MAX;
539               else if (dual > +1e-9)
540                  obj2 = +DBL_MAX;
541               else
542                  obj2 = P->obj_val;
543            }
544            else
545               obj2 = P->obj_val + dual * (value2 - prim);
546         }
547         else
548         {  glp_analyze_coef(P, k, &coef1, &var1, &value1, &coef2,
549               &var2, &value2);
550            if (coef1 == -DBL_MAX)
551            {  if (prim < -1e-9)
552                  obj1 = +DBL_MAX;
553               else if (prim > +1e-9)
554                  obj1 = -DBL_MAX;
555               else
556                  obj1 = P->obj_val;
557            }
558            else
559               obj1 = P->obj_val + (coef1 - coef) * prim;
560            if (coef2 == +DBL_MAX)
561            {  if (prim < -1e-9)
562                  obj2 = -DBL_MAX;
563               else if (prim > +1e-9)
564                  obj2 = +DBL_MAX;
565               else
566                  obj2 = P->obj_val;
567            }
568            else
569               obj2 = P->obj_val + (coef2 - coef) * prim;
570         }
571         /*** first line ***/
572         /* row/column number */
573         xfprintf(fp, "%6d", numb);
574         /* row/column name */
575         xfprintf(fp, " %-12.12s", name == NULL ? "" : name);
576         if (name != NULL && strlen(name) > 12)
577            xfprintf(fp, "%s\n%6s %12s", name+12, "", "");
578         /* row/column status */
579         xfprintf(fp, " %2s",
580            stat == GLP_BS ? "BS" : stat == GLP_NL ? "NL" :
581            stat == GLP_NU ? "NU" : stat == GLP_NF ? "NF" :
582            stat == GLP_NS ? "NS" : "??");
583         /* row/column activity */
584         xfprintf(fp, " %s", format(buf, prim));
585         /* row slack, column objective coefficient */
586         xfprintf(fp, " %s", format(buf, k <= m ? slack : coef));
587         /* row/column lower bound */
588         xfprintf(fp, " %s", format(buf, lb));
589         /* row/column activity range */
590         xfprintf(fp, "  %s", format(buf, value1));
591         /* row/column objective coefficient range */
592         xfprintf(fp, " %s", format(buf, coef1));
593         /* objective value at break point */
594         xfprintf(fp, " %s", format(buf, obj1));
595         /* limiting variable name */
596         if (var1 != 0)
597         {  if (var1 <= m)
598               limit = glp_get_row_name(P, var1);
599            else
600               limit = glp_get_col_name(P, var1 - m);
601            if (limit != NULL)
602               xfprintf(fp, " %s", limit);
603         }
604         xfprintf(fp, "\n");
605         /*** second line ***/
606         xfprintf(fp, "%6s %-12s %2s %13s", "", "", "", "");
607         /* row/column reduced cost */
608         xfprintf(fp, " %s", format(buf, dual));
609         /* row/column upper bound */
610         xfprintf(fp, " %s", format(buf, ub));
611         /* row/column activity range */
612         xfprintf(fp, "  %s", format(buf, value2));
613         /* row/column objective coefficient range */
614         xfprintf(fp, " %s", format(buf, coef2));
615         /* objective value at break point */
616         xfprintf(fp, " %s", format(buf, obj2));
617         /* limiting variable name */
618         if (var2 != 0)
619         {  if (var2 <= m)
620               limit = glp_get_row_name(P, var2);
621            else
622               limit = glp_get_col_name(P, var2 - m);
623            if (limit != NULL)
624               xfprintf(fp, " %s", limit);
625         }
626         xfprintf(fp, "\n");
627         xfprintf(fp, "\n");
628         /* print 10 items per page */
629         count = (count + 1) % 10;
630      }
631      xfprintf(fp, "End of report\n");
632      xfflush(fp);
633      if (xferror(fp))
634      {  xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
635         ret = 4;
636         goto done;
637      }
638      ret = 0;
639done: if (fp != NULL) xfclose(fp);
640      return ret;
641}
642
643/**********************************************************************/
644
645int glp_print_ipt(glp_prob *P, const char *fname)
646{     /* write interior-point solution in printable format */
647      XFILE *fp;
648      GLPROW *row;
649      GLPCOL *col;
650      int i, j, t, ae_ind, re_ind, ret;
651      double ae_max, re_max;
652      xprintf("Writing interior-point solution to `%s'...\n", fname);
653      fp = xfopen(fname, "w");
654      if (fp == NULL)
655      {  xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
656         ret = 1;
657         goto done;
658      }
659      xfprintf(fp, "%-12s%s\n", "Problem:",
660         P->name == NULL ? "" : P->name);
661      xfprintf(fp, "%-12s%d\n", "Rows:", P->m);
662      xfprintf(fp, "%-12s%d\n", "Columns:", P->n);
663      xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz);
664      t = glp_ipt_status(P);
665      xfprintf(fp, "%-12s%s\n", "Status:",
666         t == GLP_OPT    ? "OPTIMAL" :
667         t == GLP_UNDEF  ? "UNDEFINED" :
668         t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" :
669         t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" : "???");
670      xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:",
671         P->obj == NULL ? "" : P->obj,
672         P->obj == NULL ? "" : " = ", P->ipt_obj,
673         P->dir == GLP_MIN ? "MINimum" :
674         P->dir == GLP_MAX ? "MAXimum" : "???");
675      xfprintf(fp, "\n");
676      xfprintf(fp, "   No.   Row name        Activity     Lower bound  "
677         " Upper bound    Marginal\n");
678      xfprintf(fp, "------ ------------    ------------- ------------- "
679         "------------- -------------\n");
680      for (i = 1; i <= P->m; i++)
681      {  row = P->row[i];
682         xfprintf(fp, "%6d ", i);
683         if (row->name == NULL || strlen(row->name) <= 12)
684            xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name);
685         else
686            xfprintf(fp, "%s\n%20s", row->name, "");
687         xfprintf(fp, "%3s", "");
688         xfprintf(fp, "%13.6g ",
689            fabs(row->pval) <= 1e-9 ? 0.0 : row->pval);
690         if (row->type == GLP_LO || row->type == GLP_DB ||
691             row->type == GLP_FX)
692            xfprintf(fp, "%13.6g ", row->lb);
693         else
694            xfprintf(fp, "%13s ", "");
695         if (row->type == GLP_UP || row->type == GLP_DB)
696            xfprintf(fp, "%13.6g ", row->ub);
697         else
698            xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : "");
699         if (fabs(row->dval) <= 1e-9)
700            xfprintf(fp, "%13s", "< eps");
701         else
702            xfprintf(fp, "%13.6g ", row->dval);
703         xfprintf(fp, "\n");
704      }
705      xfprintf(fp, "\n");
706      xfprintf(fp, "   No. Column name       Activity     Lower bound  "
707         " Upper bound    Marginal\n");
708      xfprintf(fp, "------ ------------    ------------- ------------- "
709         "------------- -------------\n");
710      for (j = 1; j <= P->n; j++)
711      {  col = P->col[j];
712         xfprintf(fp, "%6d ", j);
713         if (col->name == NULL || strlen(col->name) <= 12)
714            xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name);
715         else
716            xfprintf(fp, "%s\n%20s", col->name, "");
717         xfprintf(fp, "%3s", "");
718         xfprintf(fp, "%13.6g ",
719            fabs(col->pval) <= 1e-9 ? 0.0 : col->pval);
720         if (col->type == GLP_LO || col->type == GLP_DB ||
721             col->type == GLP_FX)
722            xfprintf(fp, "%13.6g ", col->lb);
723         else
724            xfprintf(fp, "%13s ", "");
725         if (col->type == GLP_UP || col->type == GLP_DB)
726            xfprintf(fp, "%13.6g ", col->ub);
727         else
728            xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : "");
729         if (fabs(col->dval) <= 1e-9)
730            xfprintf(fp, "%13s", "< eps");
731         else
732            xfprintf(fp, "%13.6g ", col->dval);
733         xfprintf(fp, "\n");
734      }
735      xfprintf(fp, "\n");
736      xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n");
737      xfprintf(fp, "\n");
738      _glp_check_kkt(P, GLP_IPT, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
739         &re_ind);
740      xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n",
741         ae_max, ae_ind);
742      xfprintf(fp, "        max.rel.err = %.2e on row %d\n",
743         re_max, re_ind);
744      xfprintf(fp, "%8s%s\n", "",
745         re_max <= 1e-9 ? "High quality" :
746         re_max <= 1e-6 ? "Medium quality" :
747         re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG");
748      xfprintf(fp, "\n");
749      _glp_check_kkt(P, GLP_IPT, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
750         &re_ind);
751      xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n",
752            ae_max, ae_ind <= P->m ? "row" : "column",
753            ae_ind <= P->m ? ae_ind : ae_ind - P->m);
754      xfprintf(fp, "        max.rel.err = %.2e on %s %d\n",
755            re_max, re_ind <= P->m ? "row" : "column",
756            re_ind <= P->m ? re_ind : re_ind - P->m);
757      xfprintf(fp, "%8s%s\n", "",
758         re_max <= 1e-9 ? "High quality" :
759         re_max <= 1e-6 ? "Medium quality" :
760         re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL"
761            "E");
762      xfprintf(fp, "\n");
763      _glp_check_kkt(P, GLP_IPT, GLP_KKT_DE, &ae_max, &ae_ind, &re_max,
764         &re_ind);
765      xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n",
766         ae_max, ae_ind == 0 ? 0 : ae_ind - P->m);
767      xfprintf(fp, "        max.rel.err = %.2e on column %d\n",
768         re_max, re_ind == 0 ? 0 : re_ind - P->m);
769      xfprintf(fp, "%8s%s\n", "",
770         re_max <= 1e-9 ? "High quality" :
771         re_max <= 1e-6 ? "Medium quality" :
772         re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG");
773      xfprintf(fp, "\n");
774      _glp_check_kkt(P, GLP_IPT, GLP_KKT_DB, &ae_max, &ae_ind, &re_max,
775         &re_ind);
776      xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n",
777            ae_max, ae_ind <= P->m ? "row" : "column",
778            ae_ind <= P->m ? ae_ind : ae_ind - P->m);
779      xfprintf(fp, "        max.rel.err = %.2e on %s %d\n",
780            re_max, re_ind <= P->m ? "row" : "column",
781            re_ind <= P->m ? re_ind : re_ind - P->m);
782      xfprintf(fp, "%8s%s\n", "",
783         re_max <= 1e-9 ? "High quality" :
784         re_max <= 1e-6 ? "Medium quality" :
785         re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE")
786            ;
787      xfprintf(fp, "\n");
788      xfprintf(fp, "End of output\n");
789      xfflush(fp);
790      if (xferror(fp))
791      {  xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
792         ret = 1;
793         goto done;
794      }
795      ret = 0;
796done: if (fp != NULL) xfclose(fp);
797      return ret;
798}
799
800/***********************************************************************
801*  NAME
802*
803*  glp_read_ipt - read interior-point solution from text file
804*
805*  SYNOPSIS
806*
807*  int glp_read_ipt(glp_prob *lp, const char *fname);
808*
809*  DESCRIPTION
810*
811*  The routine glp_read_ipt reads interior-point solution from a text
812*  file whose name is specified by the parameter fname into the problem
813*  object.
814*
815*  For the file format see description of the routine glp_write_ipt.
816*
817*  RETURNS
818*
819*  On success the routine returns zero, otherwise non-zero. */
820
821int glp_read_ipt(glp_prob *lp, const char *fname)
822{     glp_data *data;
823      jmp_buf jump;
824      int i, j, k, ret = 0;
825      xprintf("Reading interior-point solution from `%s'...\n", fname);
826      data = glp_sdf_open_file(fname);
827      if (data == NULL)
828      {  ret = 1;
829         goto done;
830      }
831      if (setjmp(jump))
832      {  ret = 1;
833         goto done;
834      }
835      glp_sdf_set_jump(data, jump);
836      /* number of rows, number of columns */
837      k = glp_sdf_read_int(data);
838      if (k != lp->m)
839         glp_sdf_error(data, "wrong number of rows\n");
840      k = glp_sdf_read_int(data);
841      if (k != lp->n)
842         glp_sdf_error(data, "wrong number of columns\n");
843      /* solution status, objective value */
844      k = glp_sdf_read_int(data);
845      if (!(k == GLP_UNDEF || k == GLP_OPT))
846         glp_sdf_error(data, "invalid solution status\n");
847      lp->ipt_stat = k;
848      lp->ipt_obj = glp_sdf_read_num(data);
849      /* rows (auxiliary variables) */
850      for (i = 1; i <= lp->m; i++)
851      {  GLPROW *row = lp->row[i];
852         /* primal value, dual value */
853         row->pval = glp_sdf_read_num(data);
854         row->dval = glp_sdf_read_num(data);
855      }
856      /* columns (structural variables) */
857      for (j = 1; j <= lp->n; j++)
858      {  GLPCOL *col = lp->col[j];
859         /* primal value, dual value */
860         col->pval = glp_sdf_read_num(data);
861         col->dval = glp_sdf_read_num(data);
862      }
863      xprintf("%d lines were read\n", glp_sdf_line(data));
864done: if (ret) lp->ipt_stat = GLP_UNDEF;
865      if (data != NULL) glp_sdf_close_file(data);
866      return ret;
867}
868
869/***********************************************************************
870*  NAME
871*
872*  glp_write_ipt - write interior-point solution to text file
873*
874*  SYNOPSIS
875*
876*  int glp_write_ipt(glp_prob *lp, const char *fname);
877*
878*  DESCRIPTION
879*
880*  The routine glp_write_ipt writes the current interior-point solution
881*  to a text file whose name is specified by the parameter fname. This
882*  file can be read back with the routine glp_read_ipt.
883*
884*  RETURNS
885*
886*  On success the routine returns zero, otherwise non-zero.
887*
888*  FILE FORMAT
889*
890*  The file created by the routine glp_write_ipt is a plain text file,
891*  which contains the following information:
892*
893*     m n
894*     stat obj_val
895*     r_prim[1] r_dual[1]
896*     . . .
897*     r_prim[m] r_dual[m]
898*     c_prim[1] c_dual[1]
899*     . . .
900*     c_prim[n] c_dual[n]
901*
902*  where:
903*  m is the number of rows (auxiliary variables);
904*  n is the number of columns (structural variables);
905*  stat is the solution status (GLP_UNDEF = 1 or GLP_OPT = 5);
906*  obj_val is the objective value;
907*  r_prim[i], i = 1,...,m, is the primal value of i-th row;
908*  r_dual[i], i = 1,...,m, is the dual value of i-th row;
909*  c_prim[j], j = 1,...,n, is the primal value of j-th column;
910*  c_dual[j], j = 1,...,n, is the dual value of j-th column. */
911
912int glp_write_ipt(glp_prob *lp, const char *fname)
913{     XFILE *fp;
914      int i, j, ret = 0;
915      xprintf("Writing interior-point solution to `%s'...\n", fname);
916      fp = xfopen(fname, "w");
917      if (fp == NULL)
918      {  xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
919         ret = 1;
920         goto done;
921      }
922      /* number of rows, number of columns */
923      xfprintf(fp, "%d %d\n", lp->m, lp->n);
924      /* solution status, objective value */
925      xfprintf(fp, "%d %.*g\n", lp->ipt_stat, DBL_DIG, lp->ipt_obj);
926      /* rows (auxiliary variables) */
927      for (i = 1; i <= lp->m; i++)
928      {  GLPROW *row = lp->row[i];
929         /* primal value, dual value */
930         xfprintf(fp, "%.*g %.*g\n", DBL_DIG, row->pval, DBL_DIG,
931            row->dval);
932      }
933      /* columns (structural variables) */
934      for (j = 1; j <= lp->n; j++)
935      {  GLPCOL *col = lp->col[j];
936         /* primal value, dual value */
937         xfprintf(fp, "%.*g %.*g\n", DBL_DIG, col->pval, DBL_DIG,
938            col->dval);
939      }
940      xfflush(fp);
941      if (xferror(fp))
942      {  xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
943         ret = 1;
944         goto done;
945      }
946      xprintf("%d lines were written\n", 2 + lp->m + lp->n);
947done: if (fp != NULL) xfclose(fp);
948      return ret;
949}
950
951/**********************************************************************/
952
953int glp_print_mip(glp_prob *P, const char *fname)
954{     /* write MIP solution in printable format */
955      XFILE *fp;
956      GLPROW *row;
957      GLPCOL *col;
958      int i, j, t, ae_ind, re_ind, ret;
959      double ae_max, re_max;
960      xprintf("Writing MIP solution to `%s'...\n", fname);
961      fp = xfopen(fname, "w");
962      if (fp == NULL)
963      {  xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
964         ret = 1;
965         goto done;
966      }
967      xfprintf(fp, "%-12s%s\n", "Problem:",
968         P->name == NULL ? "" : P->name);
969      xfprintf(fp, "%-12s%d\n", "Rows:", P->m);
970      xfprintf(fp, "%-12s%d (%d integer, %d binary)\n", "Columns:",
971         P->n, glp_get_num_int(P), glp_get_num_bin(P));
972      xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz);
973      t = glp_mip_status(P);
974      xfprintf(fp, "%-12s%s\n", "Status:",
975         t == GLP_OPT    ? "INTEGER OPTIMAL" :
976         t == GLP_FEAS   ? "INTEGER NON-OPTIMAL" :
977         t == GLP_NOFEAS ? "INTEGER EMPTY" :
978         t == GLP_UNDEF  ? "INTEGER UNDEFINED" : "???");
979      xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:",
980         P->obj == NULL ? "" : P->obj,
981         P->obj == NULL ? "" : " = ", P->mip_obj,
982         P->dir == GLP_MIN ? "MINimum" :
983         P->dir == GLP_MAX ? "MAXimum" : "???");
984      xfprintf(fp, "\n");
985      xfprintf(fp, "   No.   Row name        Activity     Lower bound  "
986         " Upper bound\n");
987      xfprintf(fp, "------ ------------    ------------- ------------- "
988         "-------------\n");
989      for (i = 1; i <= P->m; i++)
990      {  row = P->row[i];
991         xfprintf(fp, "%6d ", i);
992         if (row->name == NULL || strlen(row->name) <= 12)
993            xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name);
994         else
995            xfprintf(fp, "%s\n%20s", row->name, "");
996         xfprintf(fp, "%3s", "");
997         xfprintf(fp, "%13.6g ",
998            fabs(row->mipx) <= 1e-9 ? 0.0 : row->mipx);
999         if (row->type == GLP_LO || row->type == GLP_DB ||
1000             row->type == GLP_FX)
1001            xfprintf(fp, "%13.6g ", row->lb);
1002         else
1003            xfprintf(fp, "%13s ", "");
1004         if (row->type == GLP_UP || row->type == GLP_DB)
1005            xfprintf(fp, "%13.6g ", row->ub);
1006         else
1007            xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : "");
1008         xfprintf(fp, "\n");
1009      }
1010      xfprintf(fp, "\n");
1011      xfprintf(fp, "   No. Column name       Activity     Lower bound  "
1012         " Upper bound\n");
1013      xfprintf(fp, "------ ------------    ------------- ------------- "
1014         "-------------\n");
1015      for (j = 1; j <= P->n; j++)
1016      {  col = P->col[j];
1017         xfprintf(fp, "%6d ", j);
1018         if (col->name == NULL || strlen(col->name) <= 12)
1019            xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name);
1020         else
1021            xfprintf(fp, "%s\n%20s", col->name, "");
1022         xfprintf(fp, "%s  ",
1023            col->kind == GLP_CV ? " " :
1024            col->kind == GLP_IV ? "*" : "?");
1025         xfprintf(fp, "%13.6g ",
1026            fabs(col->mipx) <= 1e-9 ? 0.0 : col->mipx);
1027         if (col->type == GLP_LO || col->type == GLP_DB ||
1028             col->type == GLP_FX)
1029            xfprintf(fp, "%13.6g ", col->lb);
1030         else
1031            xfprintf(fp, "%13s ", "");
1032         if (col->type == GLP_UP || col->type == GLP_DB)
1033            xfprintf(fp, "%13.6g ", col->ub);
1034         else
1035            xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : "");
1036         xfprintf(fp, "\n");
1037      }
1038      xfprintf(fp, "\n");
1039      xfprintf(fp, "Integer feasibility conditions:\n");
1040      xfprintf(fp, "\n");
1041      _glp_check_kkt(P, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
1042         &re_ind);
1043      xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n",
1044         ae_max, ae_ind);
1045      xfprintf(fp, "        max.rel.err = %.2e on row %d\n",
1046         re_max, re_ind);
1047      xfprintf(fp, "%8s%s\n", "",
1048         re_max <= 1e-9 ? "High quality" :
1049         re_max <= 1e-6 ? "Medium quality" :
1050         re_max <= 1e-3 ? "Low quality" : "SOLUTION IS WRONG");
1051      xfprintf(fp, "\n");
1052      _glp_check_kkt(P, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
1053         &re_ind);
1054      xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n",
1055            ae_max, ae_ind <= P->m ? "row" : "column",
1056            ae_ind <= P->m ? ae_ind : ae_ind - P->m);
1057      xfprintf(fp, "        max.rel.err = %.2e on %s %d\n",
1058            re_max, re_ind <= P->m ? "row" : "column",
1059            re_ind <= P->m ? re_ind : re_ind - P->m);
1060      xfprintf(fp, "%8s%s\n", "",
1061         re_max <= 1e-9 ? "High quality" :
1062         re_max <= 1e-6 ? "Medium quality" :
1063         re_max <= 1e-3 ? "Low quality" : "SOLUTION IS INFEASIBLE");
1064      xfprintf(fp, "\n");
1065      xfprintf(fp, "End of output\n");
1066      xfflush(fp);
1067      if (xferror(fp))
1068      {  xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
1069         ret = 1;
1070         goto done;
1071      }
1072      ret = 0;
1073done: if (fp != NULL) xfclose(fp);
1074      return ret;
1075}
1076
1077/***********************************************************************
1078*  NAME
1079*
1080*  glp_read_mip - read MIP solution from text file
1081*
1082*  SYNOPSIS
1083*
1084*  int glp_read_mip(glp_prob *mip, const char *fname);
1085*
1086*  DESCRIPTION
1087*
1088*  The routine glp_read_mip reads MIP solution from a text file whose
1089*  name is specified by the parameter fname into the problem object.
1090*
1091*  For the file format see description of the routine glp_write_mip.
1092*
1093*  RETURNS
1094*
1095*  On success the routine returns zero, otherwise non-zero. */
1096
1097int glp_read_mip(glp_prob *mip, const char *fname)
1098{     glp_data *data;
1099      jmp_buf jump;
1100      int i, j, k, ret = 0;
1101      xprintf("Reading MIP solution from `%s'...\n", fname);
1102      data = glp_sdf_open_file(fname);
1103      if (data == NULL)
1104      {  ret = 1;
1105         goto done;
1106      }
1107      if (setjmp(jump))
1108      {  ret = 1;
1109         goto done;
1110      }
1111      glp_sdf_set_jump(data, jump);
1112      /* number of rows, number of columns */
1113      k = glp_sdf_read_int(data);
1114      if (k != mip->m)
1115         glp_sdf_error(data, "wrong number of rows\n");
1116      k = glp_sdf_read_int(data);
1117      if (k != mip->n)
1118         glp_sdf_error(data, "wrong number of columns\n");
1119      /* solution status, objective value */
1120      k = glp_sdf_read_int(data);
1121      if (!(k == GLP_UNDEF || k == GLP_OPT || k == GLP_FEAS ||
1122            k == GLP_NOFEAS))
1123         glp_sdf_error(data, "invalid solution status\n");
1124      mip->mip_stat = k;
1125      mip->mip_obj = glp_sdf_read_num(data);
1126      /* rows (auxiliary variables) */
1127      for (i = 1; i <= mip->m; i++)
1128      {  GLPROW *row = mip->row[i];
1129         row->mipx = glp_sdf_read_num(data);
1130      }
1131      /* columns (structural variables) */
1132      for (j = 1; j <= mip->n; j++)
1133      {  GLPCOL *col = mip->col[j];
1134         col->mipx = glp_sdf_read_num(data);
1135         if (col->kind == GLP_IV && col->mipx != floor(col->mipx))
1136            glp_sdf_error(data, "non-integer column value");
1137      }
1138      xprintf("%d lines were read\n", glp_sdf_line(data));
1139done: if (ret) mip->mip_stat = GLP_UNDEF;
1140      if (data != NULL) glp_sdf_close_file(data);
1141      return ret;
1142}
1143
1144/***********************************************************************
1145*  NAME
1146*
1147*  glp_write_mip - write MIP solution to text file
1148*
1149*  SYNOPSIS
1150*
1151*  int glp_write_mip(glp_prob *mip, const char *fname);
1152*
1153*  DESCRIPTION
1154*
1155*  The routine glp_write_mip writes the current MIP solution to a text
1156*  file whose name is specified by the parameter fname. This file can
1157*  be read back with the routine glp_read_mip.
1158*
1159*  RETURNS
1160*
1161*  On success the routine returns zero, otherwise non-zero.
1162*
1163*  FILE FORMAT
1164*
1165*  The file created by the routine glp_write_sol is a plain text file,
1166*  which contains the following information:
1167*
1168*     m n
1169*     stat obj_val
1170*     r_val[1]
1171*     . . .
1172*     r_val[m]
1173*     c_val[1]
1174*     . . .
1175*     c_val[n]
1176*
1177*  where:
1178*  m is the number of rows (auxiliary variables);
1179*  n is the number of columns (structural variables);
1180*  stat is the solution status (GLP_UNDEF = 1, GLP_FEAS = 2,
1181*     GLP_NOFEAS = 4, or GLP_OPT = 5);
1182*  obj_val is the objective value;
1183*  r_val[i], i = 1,...,m, is the value of i-th row;
1184*  c_val[j], j = 1,...,n, is the value of j-th column. */
1185
1186int glp_write_mip(glp_prob *mip, const char *fname)
1187{     XFILE *fp;
1188      int i, j, ret = 0;
1189      xprintf("Writing MIP solution to `%s'...\n", fname);
1190      fp = xfopen(fname, "w");
1191      if (fp == NULL)
1192      {  xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
1193         ret = 1;
1194         goto done;
1195      }
1196      /* number of rows, number of columns */
1197      xfprintf(fp, "%d %d\n", mip->m, mip->n);
1198      /* solution status, objective value */
1199      xfprintf(fp, "%d %.*g\n", mip->mip_stat, DBL_DIG, mip->mip_obj);
1200      /* rows (auxiliary variables) */
1201      for (i = 1; i <= mip->m; i++)
1202         xfprintf(fp, "%.*g\n", DBL_DIG, mip->row[i]->mipx);
1203      /* columns (structural variables) */
1204      for (j = 1; j <= mip->n; j++)
1205         xfprintf(fp, "%.*g\n", DBL_DIG, mip->col[j]->mipx);
1206      xfflush(fp);
1207      if (xferror(fp))
1208      {  xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
1209         ret = 1;
1210         goto done;
1211      }
1212      xprintf("%d lines were written\n", 2 + mip->m + mip->n);
1213done: if (fp != NULL) xfclose(fp);
1214      return ret;
1215}
1216
1217/* eof */
Note: See TracBrowser for help on using the repository browser.