lemon-project-template-glpk
diff deps/glpk/src/glpapi11.c @ 9:33de93886c88
Import GLPK 4.47
author | Alpar Juttner <alpar@cs.elte.hu> |
---|---|
date | Sun, 06 Nov 2011 20:59:10 +0100 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/deps/glpk/src/glpapi11.c Sun Nov 06 20:59:10 2011 +0100 1.3 @@ -0,0 +1,1217 @@ 1.4 +/* glpapi11.c (utility routines) */ 1.5 + 1.6 +/*********************************************************************** 1.7 +* This code is part of GLPK (GNU Linear Programming Kit). 1.8 +* 1.9 +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 1.10 +* 2009, 2010, 2011 Andrew Makhorin, Department for Applied Informatics, 1.11 +* Moscow Aviation Institute, Moscow, Russia. All rights reserved. 1.12 +* E-mail: <mao@gnu.org>. 1.13 +* 1.14 +* GLPK is free software: you can redistribute it and/or modify it 1.15 +* under the terms of the GNU General Public License as published by 1.16 +* the Free Software Foundation, either version 3 of the License, or 1.17 +* (at your option) any later version. 1.18 +* 1.19 +* GLPK is distributed in the hope that it will be useful, but WITHOUT 1.20 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 1.21 +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 1.22 +* License for more details. 1.23 +* 1.24 +* You should have received a copy of the GNU General Public License 1.25 +* along with GLPK. If not, see <http://www.gnu.org/licenses/>. 1.26 +***********************************************************************/ 1.27 + 1.28 +#include "glpapi.h" 1.29 + 1.30 +int glp_print_sol(glp_prob *P, const char *fname) 1.31 +{ /* write basic solution in printable format */ 1.32 + XFILE *fp; 1.33 + GLPROW *row; 1.34 + GLPCOL *col; 1.35 + int i, j, t, ae_ind, re_ind, ret; 1.36 + double ae_max, re_max; 1.37 + xprintf("Writing basic solution to `%s'...\n", fname); 1.38 + fp = xfopen(fname, "w"); 1.39 + if (fp == NULL) 1.40 + { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); 1.41 + ret = 1; 1.42 + goto done; 1.43 + } 1.44 + xfprintf(fp, "%-12s%s\n", "Problem:", 1.45 + P->name == NULL ? "" : P->name); 1.46 + xfprintf(fp, "%-12s%d\n", "Rows:", P->m); 1.47 + xfprintf(fp, "%-12s%d\n", "Columns:", P->n); 1.48 + xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz); 1.49 + t = glp_get_status(P); 1.50 + xfprintf(fp, "%-12s%s\n", "Status:", 1.51 + t == GLP_OPT ? "OPTIMAL" : 1.52 + t == GLP_FEAS ? "FEASIBLE" : 1.53 + t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" : 1.54 + t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" : 1.55 + t == GLP_UNBND ? "UNBOUNDED" : 1.56 + t == GLP_UNDEF ? "UNDEFINED" : "???"); 1.57 + xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", 1.58 + P->obj == NULL ? "" : P->obj, 1.59 + P->obj == NULL ? "" : " = ", P->obj_val, 1.60 + P->dir == GLP_MIN ? "MINimum" : 1.61 + P->dir == GLP_MAX ? "MAXimum" : "???"); 1.62 + xfprintf(fp, "\n"); 1.63 + xfprintf(fp, " No. Row name St Activity Lower bound " 1.64 + " Upper bound Marginal\n"); 1.65 + xfprintf(fp, "------ ------------ -- ------------- ------------- " 1.66 + "------------- -------------\n"); 1.67 + for (i = 1; i <= P->m; i++) 1.68 + { row = P->row[i]; 1.69 + xfprintf(fp, "%6d ", i); 1.70 + if (row->name == NULL || strlen(row->name) <= 12) 1.71 + xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name); 1.72 + else 1.73 + xfprintf(fp, "%s\n%20s", row->name, ""); 1.74 + xfprintf(fp, "%s ", 1.75 + row->stat == GLP_BS ? "B " : 1.76 + row->stat == GLP_NL ? "NL" : 1.77 + row->stat == GLP_NU ? "NU" : 1.78 + row->stat == GLP_NF ? "NF" : 1.79 + row->stat == GLP_NS ? "NS" : "??"); 1.80 + xfprintf(fp, "%13.6g ", 1.81 + fabs(row->prim) <= 1e-9 ? 0.0 : row->prim); 1.82 + if (row->type == GLP_LO || row->type == GLP_DB || 1.83 + row->type == GLP_FX) 1.84 + xfprintf(fp, "%13.6g ", row->lb); 1.85 + else 1.86 + xfprintf(fp, "%13s ", ""); 1.87 + if (row->type == GLP_UP || row->type == GLP_DB) 1.88 + xfprintf(fp, "%13.6g ", row->ub); 1.89 + else 1.90 + xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : ""); 1.91 + if (row->stat != GLP_BS) 1.92 + { if (fabs(row->dual) <= 1e-9) 1.93 + xfprintf(fp, "%13s", "< eps"); 1.94 + else 1.95 + xfprintf(fp, "%13.6g ", row->dual); 1.96 + } 1.97 + xfprintf(fp, "\n"); 1.98 + } 1.99 + xfprintf(fp, "\n"); 1.100 + xfprintf(fp, " No. Column name St Activity Lower bound " 1.101 + " Upper bound Marginal\n"); 1.102 + xfprintf(fp, "------ ------------ -- ------------- ------------- " 1.103 + "------------- -------------\n"); 1.104 + for (j = 1; j <= P->n; j++) 1.105 + { col = P->col[j]; 1.106 + xfprintf(fp, "%6d ", j); 1.107 + if (col->name == NULL || strlen(col->name) <= 12) 1.108 + xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name); 1.109 + else 1.110 + xfprintf(fp, "%s\n%20s", col->name, ""); 1.111 + xfprintf(fp, "%s ", 1.112 + col->stat == GLP_BS ? "B " : 1.113 + col->stat == GLP_NL ? "NL" : 1.114 + col->stat == GLP_NU ? "NU" : 1.115 + col->stat == GLP_NF ? "NF" : 1.116 + col->stat == GLP_NS ? "NS" : "??"); 1.117 + xfprintf(fp, "%13.6g ", 1.118 + fabs(col->prim) <= 1e-9 ? 0.0 : col->prim); 1.119 + if (col->type == GLP_LO || col->type == GLP_DB || 1.120 + col->type == GLP_FX) 1.121 + xfprintf(fp, "%13.6g ", col->lb); 1.122 + else 1.123 + xfprintf(fp, "%13s ", ""); 1.124 + if (col->type == GLP_UP || col->type == GLP_DB) 1.125 + xfprintf(fp, "%13.6g ", col->ub); 1.126 + else 1.127 + xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : ""); 1.128 + if (col->stat != GLP_BS) 1.129 + { if (fabs(col->dual) <= 1e-9) 1.130 + xfprintf(fp, "%13s", "< eps"); 1.131 + else 1.132 + xfprintf(fp, "%13.6g ", col->dual); 1.133 + } 1.134 + xfprintf(fp, "\n"); 1.135 + } 1.136 + xfprintf(fp, "\n"); 1.137 + xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n"); 1.138 + xfprintf(fp, "\n"); 1.139 + _glp_check_kkt(P, GLP_SOL, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, 1.140 + &re_ind); 1.141 + xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n", 1.142 + ae_max, ae_ind); 1.143 + xfprintf(fp, " max.rel.err = %.2e on row %d\n", 1.144 + re_max, re_ind); 1.145 + xfprintf(fp, "%8s%s\n", "", 1.146 + re_max <= 1e-9 ? "High quality" : 1.147 + re_max <= 1e-6 ? "Medium quality" : 1.148 + re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG"); 1.149 + xfprintf(fp, "\n"); 1.150 + _glp_check_kkt(P, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, 1.151 + &re_ind); 1.152 + xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n", 1.153 + ae_max, ae_ind <= P->m ? "row" : "column", 1.154 + ae_ind <= P->m ? ae_ind : ae_ind - P->m); 1.155 + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", 1.156 + re_max, re_ind <= P->m ? "row" : "column", 1.157 + re_ind <= P->m ? re_ind : re_ind - P->m); 1.158 + xfprintf(fp, "%8s%s\n", "", 1.159 + re_max <= 1e-9 ? "High quality" : 1.160 + re_max <= 1e-6 ? "Medium quality" : 1.161 + re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL" 1.162 + "E"); 1.163 + xfprintf(fp, "\n"); 1.164 + _glp_check_kkt(P, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max, 1.165 + &re_ind); 1.166 + xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n", 1.167 + ae_max, ae_ind == 0 ? 0 : ae_ind - P->m); 1.168 + xfprintf(fp, " max.rel.err = %.2e on column %d\n", 1.169 + re_max, re_ind == 0 ? 0 : re_ind - P->m); 1.170 + xfprintf(fp, "%8s%s\n", "", 1.171 + re_max <= 1e-9 ? "High quality" : 1.172 + re_max <= 1e-6 ? "Medium quality" : 1.173 + re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG"); 1.174 + xfprintf(fp, "\n"); 1.175 + _glp_check_kkt(P, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max, 1.176 + &re_ind); 1.177 + xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n", 1.178 + ae_max, ae_ind <= P->m ? "row" : "column", 1.179 + ae_ind <= P->m ? ae_ind : ae_ind - P->m); 1.180 + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", 1.181 + re_max, re_ind <= P->m ? "row" : "column", 1.182 + re_ind <= P->m ? re_ind : re_ind - P->m); 1.183 + xfprintf(fp, "%8s%s\n", "", 1.184 + re_max <= 1e-9 ? "High quality" : 1.185 + re_max <= 1e-6 ? "Medium quality" : 1.186 + re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE") 1.187 + ; 1.188 + xfprintf(fp, "\n"); 1.189 + xfprintf(fp, "End of output\n"); 1.190 + xfflush(fp); 1.191 + if (xferror(fp)) 1.192 + { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); 1.193 + ret = 1; 1.194 + goto done; 1.195 + } 1.196 + ret = 0; 1.197 +done: if (fp != NULL) xfclose(fp); 1.198 + return ret; 1.199 +} 1.200 + 1.201 +/*********************************************************************** 1.202 +* NAME 1.203 +* 1.204 +* glp_read_sol - read basic solution from text file 1.205 +* 1.206 +* SYNOPSIS 1.207 +* 1.208 +* int glp_read_sol(glp_prob *lp, const char *fname); 1.209 +* 1.210 +* DESCRIPTION 1.211 +* 1.212 +* The routine glp_read_sol reads basic solution from a text file whose 1.213 +* name is specified by the parameter fname into the problem object. 1.214 +* 1.215 +* For the file format see description of the routine glp_write_sol. 1.216 +* 1.217 +* RETURNS 1.218 +* 1.219 +* On success the routine returns zero, otherwise non-zero. */ 1.220 + 1.221 +int glp_read_sol(glp_prob *lp, const char *fname) 1.222 +{ glp_data *data; 1.223 + jmp_buf jump; 1.224 + int i, j, k, ret = 0; 1.225 + xprintf("Reading basic solution from `%s'...\n", fname); 1.226 + data = glp_sdf_open_file(fname); 1.227 + if (data == NULL) 1.228 + { ret = 1; 1.229 + goto done; 1.230 + } 1.231 + if (setjmp(jump)) 1.232 + { ret = 1; 1.233 + goto done; 1.234 + } 1.235 + glp_sdf_set_jump(data, jump); 1.236 + /* number of rows, number of columns */ 1.237 + k = glp_sdf_read_int(data); 1.238 + if (k != lp->m) 1.239 + glp_sdf_error(data, "wrong number of rows\n"); 1.240 + k = glp_sdf_read_int(data); 1.241 + if (k != lp->n) 1.242 + glp_sdf_error(data, "wrong number of columns\n"); 1.243 + /* primal status, dual status, objective value */ 1.244 + k = glp_sdf_read_int(data); 1.245 + if (!(k == GLP_UNDEF || k == GLP_FEAS || k == GLP_INFEAS || 1.246 + k == GLP_NOFEAS)) 1.247 + glp_sdf_error(data, "invalid primal status\n"); 1.248 + lp->pbs_stat = k; 1.249 + k = glp_sdf_read_int(data); 1.250 + if (!(k == GLP_UNDEF || k == GLP_FEAS || k == GLP_INFEAS || 1.251 + k == GLP_NOFEAS)) 1.252 + glp_sdf_error(data, "invalid dual status\n"); 1.253 + lp->dbs_stat = k; 1.254 + lp->obj_val = glp_sdf_read_num(data); 1.255 + /* rows (auxiliary variables) */ 1.256 + for (i = 1; i <= lp->m; i++) 1.257 + { GLPROW *row = lp->row[i]; 1.258 + /* status, primal value, dual value */ 1.259 + k = glp_sdf_read_int(data); 1.260 + if (!(k == GLP_BS || k == GLP_NL || k == GLP_NU || 1.261 + k == GLP_NF || k == GLP_NS)) 1.262 + glp_sdf_error(data, "invalid row status\n"); 1.263 + glp_set_row_stat(lp, i, k); 1.264 + row->prim = glp_sdf_read_num(data); 1.265 + row->dual = glp_sdf_read_num(data); 1.266 + } 1.267 + /* columns (structural variables) */ 1.268 + for (j = 1; j <= lp->n; j++) 1.269 + { GLPCOL *col = lp->col[j]; 1.270 + /* status, primal value, dual value */ 1.271 + k = glp_sdf_read_int(data); 1.272 + if (!(k == GLP_BS || k == GLP_NL || k == GLP_NU || 1.273 + k == GLP_NF || k == GLP_NS)) 1.274 + glp_sdf_error(data, "invalid column status\n"); 1.275 + glp_set_col_stat(lp, j, k); 1.276 + col->prim = glp_sdf_read_num(data); 1.277 + col->dual = glp_sdf_read_num(data); 1.278 + } 1.279 + xprintf("%d lines were read\n", glp_sdf_line(data)); 1.280 +done: if (ret) lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; 1.281 + if (data != NULL) glp_sdf_close_file(data); 1.282 + return ret; 1.283 +} 1.284 + 1.285 +/*********************************************************************** 1.286 +* NAME 1.287 +* 1.288 +* glp_write_sol - write basic solution to text file 1.289 +* 1.290 +* SYNOPSIS 1.291 +* 1.292 +* int glp_write_sol(glp_prob *lp, const char *fname); 1.293 +* 1.294 +* DESCRIPTION 1.295 +* 1.296 +* The routine glp_write_sol writes the current basic solution to a 1.297 +* text file whose name is specified by the parameter fname. This file 1.298 +* can be read back with the routine glp_read_sol. 1.299 +* 1.300 +* RETURNS 1.301 +* 1.302 +* On success the routine returns zero, otherwise non-zero. 1.303 +* 1.304 +* FILE FORMAT 1.305 +* 1.306 +* The file created by the routine glp_write_sol is a plain text file, 1.307 +* which contains the following information: 1.308 +* 1.309 +* m n 1.310 +* p_stat d_stat obj_val 1.311 +* r_stat[1] r_prim[1] r_dual[1] 1.312 +* . . . 1.313 +* r_stat[m] r_prim[m] r_dual[m] 1.314 +* c_stat[1] c_prim[1] c_dual[1] 1.315 +* . . . 1.316 +* c_stat[n] c_prim[n] c_dual[n] 1.317 +* 1.318 +* where: 1.319 +* m is the number of rows (auxiliary variables); 1.320 +* n is the number of columns (structural variables); 1.321 +* p_stat is the primal status of the basic solution (GLP_UNDEF = 1, 1.322 +* GLP_FEAS = 2, GLP_INFEAS = 3, or GLP_NOFEAS = 4); 1.323 +* d_stat is the dual status of the basic solution (GLP_UNDEF = 1, 1.324 +* GLP_FEAS = 2, GLP_INFEAS = 3, or GLP_NOFEAS = 4); 1.325 +* obj_val is the objective value; 1.326 +* r_stat[i], i = 1,...,m, is the status of i-th row (GLP_BS = 1, 1.327 +* GLP_NL = 2, GLP_NU = 3, GLP_NF = 4, or GLP_NS = 5); 1.328 +* r_prim[i], i = 1,...,m, is the primal value of i-th row; 1.329 +* r_dual[i], i = 1,...,m, is the dual value of i-th row; 1.330 +* c_stat[j], j = 1,...,n, is the status of j-th column (GLP_BS = 1, 1.331 +* GLP_NL = 2, GLP_NU = 3, GLP_NF = 4, or GLP_NS = 5); 1.332 +* c_prim[j], j = 1,...,n, is the primal value of j-th column; 1.333 +* c_dual[j], j = 1,...,n, is the dual value of j-th column. */ 1.334 + 1.335 +int glp_write_sol(glp_prob *lp, const char *fname) 1.336 +{ XFILE *fp; 1.337 + int i, j, ret = 0; 1.338 + xprintf("Writing basic solution to `%s'...\n", fname); 1.339 + fp = xfopen(fname, "w"); 1.340 + if (fp == NULL) 1.341 + { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); 1.342 + ret = 1; 1.343 + goto done; 1.344 + } 1.345 + /* number of rows, number of columns */ 1.346 + xfprintf(fp, "%d %d\n", lp->m, lp->n); 1.347 + /* primal status, dual status, objective value */ 1.348 + xfprintf(fp, "%d %d %.*g\n", lp->pbs_stat, lp->dbs_stat, DBL_DIG, 1.349 + lp->obj_val); 1.350 + /* rows (auxiliary variables) */ 1.351 + for (i = 1; i <= lp->m; i++) 1.352 + { GLPROW *row = lp->row[i]; 1.353 + /* status, primal value, dual value */ 1.354 + xfprintf(fp, "%d %.*g %.*g\n", row->stat, DBL_DIG, row->prim, 1.355 + DBL_DIG, row->dual); 1.356 + } 1.357 + /* columns (structural variables) */ 1.358 + for (j = 1; j <= lp->n; j++) 1.359 + { GLPCOL *col = lp->col[j]; 1.360 + /* status, primal value, dual value */ 1.361 + xfprintf(fp, "%d %.*g %.*g\n", col->stat, DBL_DIG, col->prim, 1.362 + DBL_DIG, col->dual); 1.363 + } 1.364 + xfflush(fp); 1.365 + if (xferror(fp)) 1.366 + { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); 1.367 + ret = 1; 1.368 + goto done; 1.369 + } 1.370 + xprintf("%d lines were written\n", 2 + lp->m + lp->n); 1.371 +done: if (fp != NULL) xfclose(fp); 1.372 + return ret; 1.373 +} 1.374 + 1.375 +/**********************************************************************/ 1.376 + 1.377 +static char *format(char buf[13+1], double x) 1.378 +{ /* format floating-point number in MPS/360-like style */ 1.379 + if (x == -DBL_MAX) 1.380 + strcpy(buf, " -Inf"); 1.381 + else if (x == +DBL_MAX) 1.382 + strcpy(buf, " +Inf"); 1.383 + else if (fabs(x) <= 999999.99998) 1.384 + { sprintf(buf, "%13.5f", x); 1.385 +#if 1 1.386 + if (strcmp(buf, " 0.00000") == 0 || 1.387 + strcmp(buf, " -0.00000") == 0) 1.388 + strcpy(buf, " . "); 1.389 + else if (memcmp(buf, " 0.", 8) == 0) 1.390 + memcpy(buf, " .", 8); 1.391 + else if (memcmp(buf, " -0.", 8) == 0) 1.392 + memcpy(buf, " -.", 8); 1.393 +#endif 1.394 + } 1.395 + else 1.396 + sprintf(buf, "%13.6g", x); 1.397 + return buf; 1.398 +} 1.399 + 1.400 +int glp_print_ranges(glp_prob *P, int len, const int list[], 1.401 + int flags, const char *fname) 1.402 +{ /* print sensitivity analysis report */ 1.403 + XFILE *fp = NULL; 1.404 + GLPROW *row; 1.405 + GLPCOL *col; 1.406 + int m, n, pass, k, t, numb, type, stat, var1, var2, count, page, 1.407 + ret; 1.408 + double lb, ub, slack, coef, prim, dual, value1, value2, coef1, 1.409 + coef2, obj1, obj2; 1.410 + const char *name, *limit; 1.411 + char buf[13+1]; 1.412 + /* sanity checks */ 1.413 + if (P == NULL || P->magic != GLP_PROB_MAGIC) 1.414 + xerror("glp_print_ranges: P = %p; invalid problem object\n", 1.415 + P); 1.416 + m = P->m, n = P->n; 1.417 + if (len < 0) 1.418 + xerror("glp_print_ranges: len = %d; invalid list length\n", 1.419 + len); 1.420 + if (len > 0) 1.421 + { if (list == NULL) 1.422 + xerror("glp_print_ranges: list = %p: invalid parameter\n", 1.423 + list); 1.424 + for (t = 1; t <= len; t++) 1.425 + { k = list[t]; 1.426 + if (!(1 <= k && k <= m+n)) 1.427 + xerror("glp_print_ranges: list[%d] = %d; row/column numb" 1.428 + "er out of range\n", t, k); 1.429 + } 1.430 + } 1.431 + if (flags != 0) 1.432 + xerror("glp_print_ranges: flags = %d; invalid parameter\n", 1.433 + flags); 1.434 + if (fname == NULL) 1.435 + xerror("glp_print_ranges: fname = %p; invalid parameter\n", 1.436 + fname); 1.437 + if (glp_get_status(P) != GLP_OPT) 1.438 + { xprintf("glp_print_ranges: optimal basic solution required\n"); 1.439 + ret = 1; 1.440 + goto done; 1.441 + } 1.442 + if (!glp_bf_exists(P)) 1.443 + { xprintf("glp_print_ranges: basis factorization required\n"); 1.444 + ret = 2; 1.445 + goto done; 1.446 + } 1.447 + /* start reporting */ 1.448 + xprintf("Write sensitivity analysis report to `%s'...\n", fname); 1.449 + fp = xfopen(fname, "w"); 1.450 + if (fp == NULL) 1.451 + { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); 1.452 + ret = 3; 1.453 + goto done; 1.454 + } 1.455 + page = count = 0; 1.456 + for (pass = 1; pass <= 2; pass++) 1.457 + for (t = 1; t <= (len == 0 ? m+n : len); t++) 1.458 + { if (t == 1) count = 0; 1.459 + k = (len == 0 ? t : list[t]); 1.460 + if (pass == 1 && k > m || pass == 2 && k <= m) 1.461 + continue; 1.462 + if (count == 0) 1.463 + { xfprintf(fp, "GLPK %-4s - SENSITIVITY ANALYSIS REPORT%73sPa" 1.464 + "ge%4d\n", glp_version(), "", ++page); 1.465 + xfprintf(fp, "\n"); 1.466 + xfprintf(fp, "%-12s%s\n", "Problem:", 1.467 + P->name == NULL ? "" : P->name); 1.468 + xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", 1.469 + P->obj == NULL ? "" : P->obj, 1.470 + P->obj == NULL ? "" : " = ", P->obj_val, 1.471 + P->dir == GLP_MIN ? "MINimum" : 1.472 + P->dir == GLP_MAX ? "MAXimum" : "???"); 1.473 + xfprintf(fp, "\n"); 1.474 + xfprintf(fp, "%6s %-12s %2s %13s %13s %13s %13s %13s %13s " 1.475 + "%s\n", "No.", pass == 1 ? "Row name" : "Column name", 1.476 + "St", "Activity", pass == 1 ? "Slack" : "Obj coef", 1.477 + "Lower bound", "Activity", "Obj coef", "Obj value at", 1.478 + "Limiting"); 1.479 + xfprintf(fp, "%6s %-12s %2s %13s %13s %13s %13s %13s %13s " 1.480 + "%s\n", "", "", "", "", "Marginal", "Upper bound", 1.481 + "range", "range", "break point", "variable"); 1.482 + xfprintf(fp, "------ ------------ -- ------------- --------" 1.483 + "----- ------------- ------------- ------------- ------" 1.484 + "------- ------------\n"); 1.485 + } 1.486 + if (pass == 1) 1.487 + { numb = k; 1.488 + xassert(1 <= numb && numb <= m); 1.489 + row = P->row[numb]; 1.490 + name = row->name; 1.491 + type = row->type; 1.492 + lb = glp_get_row_lb(P, numb); 1.493 + ub = glp_get_row_ub(P, numb); 1.494 + coef = 0.0; 1.495 + stat = row->stat; 1.496 + prim = row->prim; 1.497 + if (type == GLP_FR) 1.498 + slack = - prim; 1.499 + else if (type == GLP_LO) 1.500 + slack = lb - prim; 1.501 + else if (type == GLP_UP || type == GLP_DB || type == GLP_FX) 1.502 + slack = ub - prim; 1.503 + dual = row->dual; 1.504 + } 1.505 + else 1.506 + { numb = k - m; 1.507 + xassert(1 <= numb && numb <= n); 1.508 + col = P->col[numb]; 1.509 + name = col->name; 1.510 + lb = glp_get_col_lb(P, numb); 1.511 + ub = glp_get_col_ub(P, numb); 1.512 + coef = col->coef; 1.513 + stat = col->stat; 1.514 + prim = col->prim; 1.515 + slack = 0.0; 1.516 + dual = col->dual; 1.517 + } 1.518 + if (stat != GLP_BS) 1.519 + { glp_analyze_bound(P, k, &value1, &var1, &value2, &var2); 1.520 + if (stat == GLP_NF) 1.521 + coef1 = coef2 = coef; 1.522 + else if (stat == GLP_NS) 1.523 + coef1 = -DBL_MAX, coef2 = +DBL_MAX; 1.524 + else if (stat == GLP_NL && P->dir == GLP_MIN || 1.525 + stat == GLP_NU && P->dir == GLP_MAX) 1.526 + coef1 = coef - dual, coef2 = +DBL_MAX; 1.527 + else 1.528 + coef1 = -DBL_MAX, coef2 = coef - dual; 1.529 + if (value1 == -DBL_MAX) 1.530 + { if (dual < -1e-9) 1.531 + obj1 = +DBL_MAX; 1.532 + else if (dual > +1e-9) 1.533 + obj1 = -DBL_MAX; 1.534 + else 1.535 + obj1 = P->obj_val; 1.536 + } 1.537 + else 1.538 + obj1 = P->obj_val + dual * (value1 - prim); 1.539 + if (value2 == +DBL_MAX) 1.540 + { if (dual < -1e-9) 1.541 + obj2 = -DBL_MAX; 1.542 + else if (dual > +1e-9) 1.543 + obj2 = +DBL_MAX; 1.544 + else 1.545 + obj2 = P->obj_val; 1.546 + } 1.547 + else 1.548 + obj2 = P->obj_val + dual * (value2 - prim); 1.549 + } 1.550 + else 1.551 + { glp_analyze_coef(P, k, &coef1, &var1, &value1, &coef2, 1.552 + &var2, &value2); 1.553 + if (coef1 == -DBL_MAX) 1.554 + { if (prim < -1e-9) 1.555 + obj1 = +DBL_MAX; 1.556 + else if (prim > +1e-9) 1.557 + obj1 = -DBL_MAX; 1.558 + else 1.559 + obj1 = P->obj_val; 1.560 + } 1.561 + else 1.562 + obj1 = P->obj_val + (coef1 - coef) * prim; 1.563 + if (coef2 == +DBL_MAX) 1.564 + { if (prim < -1e-9) 1.565 + obj2 = -DBL_MAX; 1.566 + else if (prim > +1e-9) 1.567 + obj2 = +DBL_MAX; 1.568 + else 1.569 + obj2 = P->obj_val; 1.570 + } 1.571 + else 1.572 + obj2 = P->obj_val + (coef2 - coef) * prim; 1.573 + } 1.574 + /*** first line ***/ 1.575 + /* row/column number */ 1.576 + xfprintf(fp, "%6d", numb); 1.577 + /* row/column name */ 1.578 + xfprintf(fp, " %-12.12s", name == NULL ? "" : name); 1.579 + if (name != NULL && strlen(name) > 12) 1.580 + xfprintf(fp, "%s\n%6s %12s", name+12, "", ""); 1.581 + /* row/column status */ 1.582 + xfprintf(fp, " %2s", 1.583 + stat == GLP_BS ? "BS" : stat == GLP_NL ? "NL" : 1.584 + stat == GLP_NU ? "NU" : stat == GLP_NF ? "NF" : 1.585 + stat == GLP_NS ? "NS" : "??"); 1.586 + /* row/column activity */ 1.587 + xfprintf(fp, " %s", format(buf, prim)); 1.588 + /* row slack, column objective coefficient */ 1.589 + xfprintf(fp, " %s", format(buf, k <= m ? slack : coef)); 1.590 + /* row/column lower bound */ 1.591 + xfprintf(fp, " %s", format(buf, lb)); 1.592 + /* row/column activity range */ 1.593 + xfprintf(fp, " %s", format(buf, value1)); 1.594 + /* row/column objective coefficient range */ 1.595 + xfprintf(fp, " %s", format(buf, coef1)); 1.596 + /* objective value at break point */ 1.597 + xfprintf(fp, " %s", format(buf, obj1)); 1.598 + /* limiting variable name */ 1.599 + if (var1 != 0) 1.600 + { if (var1 <= m) 1.601 + limit = glp_get_row_name(P, var1); 1.602 + else 1.603 + limit = glp_get_col_name(P, var1 - m); 1.604 + if (limit != NULL) 1.605 + xfprintf(fp, " %s", limit); 1.606 + } 1.607 + xfprintf(fp, "\n"); 1.608 + /*** second line ***/ 1.609 + xfprintf(fp, "%6s %-12s %2s %13s", "", "", "", ""); 1.610 + /* row/column reduced cost */ 1.611 + xfprintf(fp, " %s", format(buf, dual)); 1.612 + /* row/column upper bound */ 1.613 + xfprintf(fp, " %s", format(buf, ub)); 1.614 + /* row/column activity range */ 1.615 + xfprintf(fp, " %s", format(buf, value2)); 1.616 + /* row/column objective coefficient range */ 1.617 + xfprintf(fp, " %s", format(buf, coef2)); 1.618 + /* objective value at break point */ 1.619 + xfprintf(fp, " %s", format(buf, obj2)); 1.620 + /* limiting variable name */ 1.621 + if (var2 != 0) 1.622 + { if (var2 <= m) 1.623 + limit = glp_get_row_name(P, var2); 1.624 + else 1.625 + limit = glp_get_col_name(P, var2 - m); 1.626 + if (limit != NULL) 1.627 + xfprintf(fp, " %s", limit); 1.628 + } 1.629 + xfprintf(fp, "\n"); 1.630 + xfprintf(fp, "\n"); 1.631 + /* print 10 items per page */ 1.632 + count = (count + 1) % 10; 1.633 + } 1.634 + xfprintf(fp, "End of report\n"); 1.635 + xfflush(fp); 1.636 + if (xferror(fp)) 1.637 + { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); 1.638 + ret = 4; 1.639 + goto done; 1.640 + } 1.641 + ret = 0; 1.642 +done: if (fp != NULL) xfclose(fp); 1.643 + return ret; 1.644 +} 1.645 + 1.646 +/**********************************************************************/ 1.647 + 1.648 +int glp_print_ipt(glp_prob *P, const char *fname) 1.649 +{ /* write interior-point solution in printable format */ 1.650 + XFILE *fp; 1.651 + GLPROW *row; 1.652 + GLPCOL *col; 1.653 + int i, j, t, ae_ind, re_ind, ret; 1.654 + double ae_max, re_max; 1.655 + xprintf("Writing interior-point solution to `%s'...\n", fname); 1.656 + fp = xfopen(fname, "w"); 1.657 + if (fp == NULL) 1.658 + { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); 1.659 + ret = 1; 1.660 + goto done; 1.661 + } 1.662 + xfprintf(fp, "%-12s%s\n", "Problem:", 1.663 + P->name == NULL ? "" : P->name); 1.664 + xfprintf(fp, "%-12s%d\n", "Rows:", P->m); 1.665 + xfprintf(fp, "%-12s%d\n", "Columns:", P->n); 1.666 + xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz); 1.667 + t = glp_ipt_status(P); 1.668 + xfprintf(fp, "%-12s%s\n", "Status:", 1.669 + t == GLP_OPT ? "OPTIMAL" : 1.670 + t == GLP_UNDEF ? "UNDEFINED" : 1.671 + t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" : 1.672 + t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" : "???"); 1.673 + xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", 1.674 + P->obj == NULL ? "" : P->obj, 1.675 + P->obj == NULL ? "" : " = ", P->ipt_obj, 1.676 + P->dir == GLP_MIN ? "MINimum" : 1.677 + P->dir == GLP_MAX ? "MAXimum" : "???"); 1.678 + xfprintf(fp, "\n"); 1.679 + xfprintf(fp, " No. Row name Activity Lower bound " 1.680 + " Upper bound Marginal\n"); 1.681 + xfprintf(fp, "------ ------------ ------------- ------------- " 1.682 + "------------- -------------\n"); 1.683 + for (i = 1; i <= P->m; i++) 1.684 + { row = P->row[i]; 1.685 + xfprintf(fp, "%6d ", i); 1.686 + if (row->name == NULL || strlen(row->name) <= 12) 1.687 + xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name); 1.688 + else 1.689 + xfprintf(fp, "%s\n%20s", row->name, ""); 1.690 + xfprintf(fp, "%3s", ""); 1.691 + xfprintf(fp, "%13.6g ", 1.692 + fabs(row->pval) <= 1e-9 ? 0.0 : row->pval); 1.693 + if (row->type == GLP_LO || row->type == GLP_DB || 1.694 + row->type == GLP_FX) 1.695 + xfprintf(fp, "%13.6g ", row->lb); 1.696 + else 1.697 + xfprintf(fp, "%13s ", ""); 1.698 + if (row->type == GLP_UP || row->type == GLP_DB) 1.699 + xfprintf(fp, "%13.6g ", row->ub); 1.700 + else 1.701 + xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : ""); 1.702 + if (fabs(row->dval) <= 1e-9) 1.703 + xfprintf(fp, "%13s", "< eps"); 1.704 + else 1.705 + xfprintf(fp, "%13.6g ", row->dval); 1.706 + xfprintf(fp, "\n"); 1.707 + } 1.708 + xfprintf(fp, "\n"); 1.709 + xfprintf(fp, " No. Column name Activity Lower bound " 1.710 + " Upper bound Marginal\n"); 1.711 + xfprintf(fp, "------ ------------ ------------- ------------- " 1.712 + "------------- -------------\n"); 1.713 + for (j = 1; j <= P->n; j++) 1.714 + { col = P->col[j]; 1.715 + xfprintf(fp, "%6d ", j); 1.716 + if (col->name == NULL || strlen(col->name) <= 12) 1.717 + xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name); 1.718 + else 1.719 + xfprintf(fp, "%s\n%20s", col->name, ""); 1.720 + xfprintf(fp, "%3s", ""); 1.721 + xfprintf(fp, "%13.6g ", 1.722 + fabs(col->pval) <= 1e-9 ? 0.0 : col->pval); 1.723 + if (col->type == GLP_LO || col->type == GLP_DB || 1.724 + col->type == GLP_FX) 1.725 + xfprintf(fp, "%13.6g ", col->lb); 1.726 + else 1.727 + xfprintf(fp, "%13s ", ""); 1.728 + if (col->type == GLP_UP || col->type == GLP_DB) 1.729 + xfprintf(fp, "%13.6g ", col->ub); 1.730 + else 1.731 + xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : ""); 1.732 + if (fabs(col->dval) <= 1e-9) 1.733 + xfprintf(fp, "%13s", "< eps"); 1.734 + else 1.735 + xfprintf(fp, "%13.6g ", col->dval); 1.736 + xfprintf(fp, "\n"); 1.737 + } 1.738 + xfprintf(fp, "\n"); 1.739 + xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n"); 1.740 + xfprintf(fp, "\n"); 1.741 + _glp_check_kkt(P, GLP_IPT, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, 1.742 + &re_ind); 1.743 + xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n", 1.744 + ae_max, ae_ind); 1.745 + xfprintf(fp, " max.rel.err = %.2e on row %d\n", 1.746 + re_max, re_ind); 1.747 + xfprintf(fp, "%8s%s\n", "", 1.748 + re_max <= 1e-9 ? "High quality" : 1.749 + re_max <= 1e-6 ? "Medium quality" : 1.750 + re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG"); 1.751 + xfprintf(fp, "\n"); 1.752 + _glp_check_kkt(P, GLP_IPT, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, 1.753 + &re_ind); 1.754 + xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n", 1.755 + ae_max, ae_ind <= P->m ? "row" : "column", 1.756 + ae_ind <= P->m ? ae_ind : ae_ind - P->m); 1.757 + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", 1.758 + re_max, re_ind <= P->m ? "row" : "column", 1.759 + re_ind <= P->m ? re_ind : re_ind - P->m); 1.760 + xfprintf(fp, "%8s%s\n", "", 1.761 + re_max <= 1e-9 ? "High quality" : 1.762 + re_max <= 1e-6 ? "Medium quality" : 1.763 + re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL" 1.764 + "E"); 1.765 + xfprintf(fp, "\n"); 1.766 + _glp_check_kkt(P, GLP_IPT, GLP_KKT_DE, &ae_max, &ae_ind, &re_max, 1.767 + &re_ind); 1.768 + xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n", 1.769 + ae_max, ae_ind == 0 ? 0 : ae_ind - P->m); 1.770 + xfprintf(fp, " max.rel.err = %.2e on column %d\n", 1.771 + re_max, re_ind == 0 ? 0 : re_ind - P->m); 1.772 + xfprintf(fp, "%8s%s\n", "", 1.773 + re_max <= 1e-9 ? "High quality" : 1.774 + re_max <= 1e-6 ? "Medium quality" : 1.775 + re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG"); 1.776 + xfprintf(fp, "\n"); 1.777 + _glp_check_kkt(P, GLP_IPT, GLP_KKT_DB, &ae_max, &ae_ind, &re_max, 1.778 + &re_ind); 1.779 + xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n", 1.780 + ae_max, ae_ind <= P->m ? "row" : "column", 1.781 + ae_ind <= P->m ? ae_ind : ae_ind - P->m); 1.782 + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", 1.783 + re_max, re_ind <= P->m ? "row" : "column", 1.784 + re_ind <= P->m ? re_ind : re_ind - P->m); 1.785 + xfprintf(fp, "%8s%s\n", "", 1.786 + re_max <= 1e-9 ? "High quality" : 1.787 + re_max <= 1e-6 ? "Medium quality" : 1.788 + re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE") 1.789 + ; 1.790 + xfprintf(fp, "\n"); 1.791 + xfprintf(fp, "End of output\n"); 1.792 + xfflush(fp); 1.793 + if (xferror(fp)) 1.794 + { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); 1.795 + ret = 1; 1.796 + goto done; 1.797 + } 1.798 + ret = 0; 1.799 +done: if (fp != NULL) xfclose(fp); 1.800 + return ret; 1.801 +} 1.802 + 1.803 +/*********************************************************************** 1.804 +* NAME 1.805 +* 1.806 +* glp_read_ipt - read interior-point solution from text file 1.807 +* 1.808 +* SYNOPSIS 1.809 +* 1.810 +* int glp_read_ipt(glp_prob *lp, const char *fname); 1.811 +* 1.812 +* DESCRIPTION 1.813 +* 1.814 +* The routine glp_read_ipt reads interior-point solution from a text 1.815 +* file whose name is specified by the parameter fname into the problem 1.816 +* object. 1.817 +* 1.818 +* For the file format see description of the routine glp_write_ipt. 1.819 +* 1.820 +* RETURNS 1.821 +* 1.822 +* On success the routine returns zero, otherwise non-zero. */ 1.823 + 1.824 +int glp_read_ipt(glp_prob *lp, const char *fname) 1.825 +{ glp_data *data; 1.826 + jmp_buf jump; 1.827 + int i, j, k, ret = 0; 1.828 + xprintf("Reading interior-point solution from `%s'...\n", fname); 1.829 + data = glp_sdf_open_file(fname); 1.830 + if (data == NULL) 1.831 + { ret = 1; 1.832 + goto done; 1.833 + } 1.834 + if (setjmp(jump)) 1.835 + { ret = 1; 1.836 + goto done; 1.837 + } 1.838 + glp_sdf_set_jump(data, jump); 1.839 + /* number of rows, number of columns */ 1.840 + k = glp_sdf_read_int(data); 1.841 + if (k != lp->m) 1.842 + glp_sdf_error(data, "wrong number of rows\n"); 1.843 + k = glp_sdf_read_int(data); 1.844 + if (k != lp->n) 1.845 + glp_sdf_error(data, "wrong number of columns\n"); 1.846 + /* solution status, objective value */ 1.847 + k = glp_sdf_read_int(data); 1.848 + if (!(k == GLP_UNDEF || k == GLP_OPT)) 1.849 + glp_sdf_error(data, "invalid solution status\n"); 1.850 + lp->ipt_stat = k; 1.851 + lp->ipt_obj = glp_sdf_read_num(data); 1.852 + /* rows (auxiliary variables) */ 1.853 + for (i = 1; i <= lp->m; i++) 1.854 + { GLPROW *row = lp->row[i]; 1.855 + /* primal value, dual value */ 1.856 + row->pval = glp_sdf_read_num(data); 1.857 + row->dval = glp_sdf_read_num(data); 1.858 + } 1.859 + /* columns (structural variables) */ 1.860 + for (j = 1; j <= lp->n; j++) 1.861 + { GLPCOL *col = lp->col[j]; 1.862 + /* primal value, dual value */ 1.863 + col->pval = glp_sdf_read_num(data); 1.864 + col->dval = glp_sdf_read_num(data); 1.865 + } 1.866 + xprintf("%d lines were read\n", glp_sdf_line(data)); 1.867 +done: if (ret) lp->ipt_stat = GLP_UNDEF; 1.868 + if (data != NULL) glp_sdf_close_file(data); 1.869 + return ret; 1.870 +} 1.871 + 1.872 +/*********************************************************************** 1.873 +* NAME 1.874 +* 1.875 +* glp_write_ipt - write interior-point solution to text file 1.876 +* 1.877 +* SYNOPSIS 1.878 +* 1.879 +* int glp_write_ipt(glp_prob *lp, const char *fname); 1.880 +* 1.881 +* DESCRIPTION 1.882 +* 1.883 +* The routine glp_write_ipt writes the current interior-point solution 1.884 +* to a text file whose name is specified by the parameter fname. This 1.885 +* file can be read back with the routine glp_read_ipt. 1.886 +* 1.887 +* RETURNS 1.888 +* 1.889 +* On success the routine returns zero, otherwise non-zero. 1.890 +* 1.891 +* FILE FORMAT 1.892 +* 1.893 +* The file created by the routine glp_write_ipt is a plain text file, 1.894 +* which contains the following information: 1.895 +* 1.896 +* m n 1.897 +* stat obj_val 1.898 +* r_prim[1] r_dual[1] 1.899 +* . . . 1.900 +* r_prim[m] r_dual[m] 1.901 +* c_prim[1] c_dual[1] 1.902 +* . . . 1.903 +* c_prim[n] c_dual[n] 1.904 +* 1.905 +* where: 1.906 +* m is the number of rows (auxiliary variables); 1.907 +* n is the number of columns (structural variables); 1.908 +* stat is the solution status (GLP_UNDEF = 1 or GLP_OPT = 5); 1.909 +* obj_val is the objective value; 1.910 +* r_prim[i], i = 1,...,m, is the primal value of i-th row; 1.911 +* r_dual[i], i = 1,...,m, is the dual value of i-th row; 1.912 +* c_prim[j], j = 1,...,n, is the primal value of j-th column; 1.913 +* c_dual[j], j = 1,...,n, is the dual value of j-th column. */ 1.914 + 1.915 +int glp_write_ipt(glp_prob *lp, const char *fname) 1.916 +{ XFILE *fp; 1.917 + int i, j, ret = 0; 1.918 + xprintf("Writing interior-point solution to `%s'...\n", fname); 1.919 + fp = xfopen(fname, "w"); 1.920 + if (fp == NULL) 1.921 + { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); 1.922 + ret = 1; 1.923 + goto done; 1.924 + } 1.925 + /* number of rows, number of columns */ 1.926 + xfprintf(fp, "%d %d\n", lp->m, lp->n); 1.927 + /* solution status, objective value */ 1.928 + xfprintf(fp, "%d %.*g\n", lp->ipt_stat, DBL_DIG, lp->ipt_obj); 1.929 + /* rows (auxiliary variables) */ 1.930 + for (i = 1; i <= lp->m; i++) 1.931 + { GLPROW *row = lp->row[i]; 1.932 + /* primal value, dual value */ 1.933 + xfprintf(fp, "%.*g %.*g\n", DBL_DIG, row->pval, DBL_DIG, 1.934 + row->dval); 1.935 + } 1.936 + /* columns (structural variables) */ 1.937 + for (j = 1; j <= lp->n; j++) 1.938 + { GLPCOL *col = lp->col[j]; 1.939 + /* primal value, dual value */ 1.940 + xfprintf(fp, "%.*g %.*g\n", DBL_DIG, col->pval, DBL_DIG, 1.941 + col->dval); 1.942 + } 1.943 + xfflush(fp); 1.944 + if (xferror(fp)) 1.945 + { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); 1.946 + ret = 1; 1.947 + goto done; 1.948 + } 1.949 + xprintf("%d lines were written\n", 2 + lp->m + lp->n); 1.950 +done: if (fp != NULL) xfclose(fp); 1.951 + return ret; 1.952 +} 1.953 + 1.954 +/**********************************************************************/ 1.955 + 1.956 +int glp_print_mip(glp_prob *P, const char *fname) 1.957 +{ /* write MIP solution in printable format */ 1.958 + XFILE *fp; 1.959 + GLPROW *row; 1.960 + GLPCOL *col; 1.961 + int i, j, t, ae_ind, re_ind, ret; 1.962 + double ae_max, re_max; 1.963 + xprintf("Writing MIP solution to `%s'...\n", fname); 1.964 + fp = xfopen(fname, "w"); 1.965 + if (fp == NULL) 1.966 + { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); 1.967 + ret = 1; 1.968 + goto done; 1.969 + } 1.970 + xfprintf(fp, "%-12s%s\n", "Problem:", 1.971 + P->name == NULL ? "" : P->name); 1.972 + xfprintf(fp, "%-12s%d\n", "Rows:", P->m); 1.973 + xfprintf(fp, "%-12s%d (%d integer, %d binary)\n", "Columns:", 1.974 + P->n, glp_get_num_int(P), glp_get_num_bin(P)); 1.975 + xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz); 1.976 + t = glp_mip_status(P); 1.977 + xfprintf(fp, "%-12s%s\n", "Status:", 1.978 + t == GLP_OPT ? "INTEGER OPTIMAL" : 1.979 + t == GLP_FEAS ? "INTEGER NON-OPTIMAL" : 1.980 + t == GLP_NOFEAS ? "INTEGER EMPTY" : 1.981 + t == GLP_UNDEF ? "INTEGER UNDEFINED" : "???"); 1.982 + xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", 1.983 + P->obj == NULL ? "" : P->obj, 1.984 + P->obj == NULL ? "" : " = ", P->mip_obj, 1.985 + P->dir == GLP_MIN ? "MINimum" : 1.986 + P->dir == GLP_MAX ? "MAXimum" : "???"); 1.987 + xfprintf(fp, "\n"); 1.988 + xfprintf(fp, " No. Row name Activity Lower bound " 1.989 + " Upper bound\n"); 1.990 + xfprintf(fp, "------ ------------ ------------- ------------- " 1.991 + "-------------\n"); 1.992 + for (i = 1; i <= P->m; i++) 1.993 + { row = P->row[i]; 1.994 + xfprintf(fp, "%6d ", i); 1.995 + if (row->name == NULL || strlen(row->name) <= 12) 1.996 + xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name); 1.997 + else 1.998 + xfprintf(fp, "%s\n%20s", row->name, ""); 1.999 + xfprintf(fp, "%3s", ""); 1.1000 + xfprintf(fp, "%13.6g ", 1.1001 + fabs(row->mipx) <= 1e-9 ? 0.0 : row->mipx); 1.1002 + if (row->type == GLP_LO || row->type == GLP_DB || 1.1003 + row->type == GLP_FX) 1.1004 + xfprintf(fp, "%13.6g ", row->lb); 1.1005 + else 1.1006 + xfprintf(fp, "%13s ", ""); 1.1007 + if (row->type == GLP_UP || row->type == GLP_DB) 1.1008 + xfprintf(fp, "%13.6g ", row->ub); 1.1009 + else 1.1010 + xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : ""); 1.1011 + xfprintf(fp, "\n"); 1.1012 + } 1.1013 + xfprintf(fp, "\n"); 1.1014 + xfprintf(fp, " No. Column name Activity Lower bound " 1.1015 + " Upper bound\n"); 1.1016 + xfprintf(fp, "------ ------------ ------------- ------------- " 1.1017 + "-------------\n"); 1.1018 + for (j = 1; j <= P->n; j++) 1.1019 + { col = P->col[j]; 1.1020 + xfprintf(fp, "%6d ", j); 1.1021 + if (col->name == NULL || strlen(col->name) <= 12) 1.1022 + xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name); 1.1023 + else 1.1024 + xfprintf(fp, "%s\n%20s", col->name, ""); 1.1025 + xfprintf(fp, "%s ", 1.1026 + col->kind == GLP_CV ? " " : 1.1027 + col->kind == GLP_IV ? "*" : "?"); 1.1028 + xfprintf(fp, "%13.6g ", 1.1029 + fabs(col->mipx) <= 1e-9 ? 0.0 : col->mipx); 1.1030 + if (col->type == GLP_LO || col->type == GLP_DB || 1.1031 + col->type == GLP_FX) 1.1032 + xfprintf(fp, "%13.6g ", col->lb); 1.1033 + else 1.1034 + xfprintf(fp, "%13s ", ""); 1.1035 + if (col->type == GLP_UP || col->type == GLP_DB) 1.1036 + xfprintf(fp, "%13.6g ", col->ub); 1.1037 + else 1.1038 + xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : ""); 1.1039 + xfprintf(fp, "\n"); 1.1040 + } 1.1041 + xfprintf(fp, "\n"); 1.1042 + xfprintf(fp, "Integer feasibility conditions:\n"); 1.1043 + xfprintf(fp, "\n"); 1.1044 + _glp_check_kkt(P, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, 1.1045 + &re_ind); 1.1046 + xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n", 1.1047 + ae_max, ae_ind); 1.1048 + xfprintf(fp, " max.rel.err = %.2e on row %d\n", 1.1049 + re_max, re_ind); 1.1050 + xfprintf(fp, "%8s%s\n", "", 1.1051 + re_max <= 1e-9 ? "High quality" : 1.1052 + re_max <= 1e-6 ? "Medium quality" : 1.1053 + re_max <= 1e-3 ? "Low quality" : "SOLUTION IS WRONG"); 1.1054 + xfprintf(fp, "\n"); 1.1055 + _glp_check_kkt(P, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, 1.1056 + &re_ind); 1.1057 + xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n", 1.1058 + ae_max, ae_ind <= P->m ? "row" : "column", 1.1059 + ae_ind <= P->m ? ae_ind : ae_ind - P->m); 1.1060 + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", 1.1061 + re_max, re_ind <= P->m ? "row" : "column", 1.1062 + re_ind <= P->m ? re_ind : re_ind - P->m); 1.1063 + xfprintf(fp, "%8s%s\n", "", 1.1064 + re_max <= 1e-9 ? "High quality" : 1.1065 + re_max <= 1e-6 ? "Medium quality" : 1.1066 + re_max <= 1e-3 ? "Low quality" : "SOLUTION IS INFEASIBLE"); 1.1067 + xfprintf(fp, "\n"); 1.1068 + xfprintf(fp, "End of output\n"); 1.1069 + xfflush(fp); 1.1070 + if (xferror(fp)) 1.1071 + { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); 1.1072 + ret = 1; 1.1073 + goto done; 1.1074 + } 1.1075 + ret = 0; 1.1076 +done: if (fp != NULL) xfclose(fp); 1.1077 + return ret; 1.1078 +} 1.1079 + 1.1080 +/*********************************************************************** 1.1081 +* NAME 1.1082 +* 1.1083 +* glp_read_mip - read MIP solution from text file 1.1084 +* 1.1085 +* SYNOPSIS 1.1086 +* 1.1087 +* int glp_read_mip(glp_prob *mip, const char *fname); 1.1088 +* 1.1089 +* DESCRIPTION 1.1090 +* 1.1091 +* The routine glp_read_mip reads MIP solution from a text file whose 1.1092 +* name is specified by the parameter fname into the problem object. 1.1093 +* 1.1094 +* For the file format see description of the routine glp_write_mip. 1.1095 +* 1.1096 +* RETURNS 1.1097 +* 1.1098 +* On success the routine returns zero, otherwise non-zero. */ 1.1099 + 1.1100 +int glp_read_mip(glp_prob *mip, const char *fname) 1.1101 +{ glp_data *data; 1.1102 + jmp_buf jump; 1.1103 + int i, j, k, ret = 0; 1.1104 + xprintf("Reading MIP solution from `%s'...\n", fname); 1.1105 + data = glp_sdf_open_file(fname); 1.1106 + if (data == NULL) 1.1107 + { ret = 1; 1.1108 + goto done; 1.1109 + } 1.1110 + if (setjmp(jump)) 1.1111 + { ret = 1; 1.1112 + goto done; 1.1113 + } 1.1114 + glp_sdf_set_jump(data, jump); 1.1115 + /* number of rows, number of columns */ 1.1116 + k = glp_sdf_read_int(data); 1.1117 + if (k != mip->m) 1.1118 + glp_sdf_error(data, "wrong number of rows\n"); 1.1119 + k = glp_sdf_read_int(data); 1.1120 + if (k != mip->n) 1.1121 + glp_sdf_error(data, "wrong number of columns\n"); 1.1122 + /* solution status, objective value */ 1.1123 + k = glp_sdf_read_int(data); 1.1124 + if (!(k == GLP_UNDEF || k == GLP_OPT || k == GLP_FEAS || 1.1125 + k == GLP_NOFEAS)) 1.1126 + glp_sdf_error(data, "invalid solution status\n"); 1.1127 + mip->mip_stat = k; 1.1128 + mip->mip_obj = glp_sdf_read_num(data); 1.1129 + /* rows (auxiliary variables) */ 1.1130 + for (i = 1; i <= mip->m; i++) 1.1131 + { GLPROW *row = mip->row[i]; 1.1132 + row->mipx = glp_sdf_read_num(data); 1.1133 + } 1.1134 + /* columns (structural variables) */ 1.1135 + for (j = 1; j <= mip->n; j++) 1.1136 + { GLPCOL *col = mip->col[j]; 1.1137 + col->mipx = glp_sdf_read_num(data); 1.1138 + if (col->kind == GLP_IV && col->mipx != floor(col->mipx)) 1.1139 + glp_sdf_error(data, "non-integer column value"); 1.1140 + } 1.1141 + xprintf("%d lines were read\n", glp_sdf_line(data)); 1.1142 +done: if (ret) mip->mip_stat = GLP_UNDEF; 1.1143 + if (data != NULL) glp_sdf_close_file(data); 1.1144 + return ret; 1.1145 +} 1.1146 + 1.1147 +/*********************************************************************** 1.1148 +* NAME 1.1149 +* 1.1150 +* glp_write_mip - write MIP solution to text file 1.1151 +* 1.1152 +* SYNOPSIS 1.1153 +* 1.1154 +* int glp_write_mip(glp_prob *mip, const char *fname); 1.1155 +* 1.1156 +* DESCRIPTION 1.1157 +* 1.1158 +* The routine glp_write_mip writes the current MIP solution to a text 1.1159 +* file whose name is specified by the parameter fname. This file can 1.1160 +* be read back with the routine glp_read_mip. 1.1161 +* 1.1162 +* RETURNS 1.1163 +* 1.1164 +* On success the routine returns zero, otherwise non-zero. 1.1165 +* 1.1166 +* FILE FORMAT 1.1167 +* 1.1168 +* The file created by the routine glp_write_sol is a plain text file, 1.1169 +* which contains the following information: 1.1170 +* 1.1171 +* m n 1.1172 +* stat obj_val 1.1173 +* r_val[1] 1.1174 +* . . . 1.1175 +* r_val[m] 1.1176 +* c_val[1] 1.1177 +* . . . 1.1178 +* c_val[n] 1.1179 +* 1.1180 +* where: 1.1181 +* m is the number of rows (auxiliary variables); 1.1182 +* n is the number of columns (structural variables); 1.1183 +* stat is the solution status (GLP_UNDEF = 1, GLP_FEAS = 2, 1.1184 +* GLP_NOFEAS = 4, or GLP_OPT = 5); 1.1185 +* obj_val is the objective value; 1.1186 +* r_val[i], i = 1,...,m, is the value of i-th row; 1.1187 +* c_val[j], j = 1,...,n, is the value of j-th column. */ 1.1188 + 1.1189 +int glp_write_mip(glp_prob *mip, const char *fname) 1.1190 +{ XFILE *fp; 1.1191 + int i, j, ret = 0; 1.1192 + xprintf("Writing MIP solution to `%s'...\n", fname); 1.1193 + fp = xfopen(fname, "w"); 1.1194 + if (fp == NULL) 1.1195 + { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); 1.1196 + ret = 1; 1.1197 + goto done; 1.1198 + } 1.1199 + /* number of rows, number of columns */ 1.1200 + xfprintf(fp, "%d %d\n", mip->m, mip->n); 1.1201 + /* solution status, objective value */ 1.1202 + xfprintf(fp, "%d %.*g\n", mip->mip_stat, DBL_DIG, mip->mip_obj); 1.1203 + /* rows (auxiliary variables) */ 1.1204 + for (i = 1; i <= mip->m; i++) 1.1205 + xfprintf(fp, "%.*g\n", DBL_DIG, mip->row[i]->mipx); 1.1206 + /* columns (structural variables) */ 1.1207 + for (j = 1; j <= mip->n; j++) 1.1208 + xfprintf(fp, "%.*g\n", DBL_DIG, mip->col[j]->mipx); 1.1209 + xfflush(fp); 1.1210 + if (xferror(fp)) 1.1211 + { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); 1.1212 + ret = 1; 1.1213 + goto done; 1.1214 + } 1.1215 + xprintf("%d lines were written\n", 2 + mip->m + mip->n); 1.1216 +done: if (fp != NULL) xfclose(fp); 1.1217 + return ret; 1.1218 +} 1.1219 + 1.1220 +/* eof */