1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/glpapi19.c Mon Dec 06 13:09:21 2010 +0100
1.3 @@ -0,0 +1,1196 @@
1.4 +/* glpapi19.c (stand-alone LP/MIP solver) */
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 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 +#include "glpgmp.h"
1.30 +
1.31 +struct csa
1.32 +{ /* common storage area */
1.33 + glp_prob *prob;
1.34 + /* LP/MIP problem object */
1.35 + glp_bfcp bfcp;
1.36 + /* basis factorization control parameters */
1.37 + glp_smcp smcp;
1.38 + /* simplex method control parameters */
1.39 + glp_iptcp iptcp;
1.40 + /* interior-point method control parameters */
1.41 + glp_iocp iocp;
1.42 + /* integer optimizer control parameters */
1.43 + glp_tran *tran;
1.44 + /* model translator workspace */
1.45 + glp_graph *graph;
1.46 + /* network problem object */
1.47 + int format;
1.48 + /* problem file format: */
1.49 +#define FMT_MPS_DECK 1 /* fixed MPS */
1.50 +#define FMT_MPS_FILE 2 /* free MPS */
1.51 +#define FMT_LP 3 /* CPLEX LP */
1.52 +#define FMT_GLP 4 /* GLPK LP/MIP */
1.53 +#define FMT_MATHPROG 5 /* MathProg */
1.54 +#define FMT_MIN_COST 6 /* DIMACS min-cost flow */
1.55 +#define FMT_MAX_FLOW 7 /* DIMACS maximum flow */
1.56 + const char *in_file;
1.57 + /* name of input problem file */
1.58 +#define DATA_MAX 10
1.59 + /* maximal number of input data files */
1.60 + int ndf;
1.61 + /* number of input data files specified */
1.62 + const char *in_data[1+DATA_MAX];
1.63 + /* name(s) of input data file(s) */
1.64 + const char *out_dpy;
1.65 + /* name of output file to send display output; NULL means the
1.66 + display output is sent to the terminal */
1.67 + int seed;
1.68 + /* seed value to be passed to the MathProg translator; initially
1.69 + set to 1; 0x80000000 means the value is omitted */
1.70 + int solution;
1.71 + /* solution type flag: */
1.72 +#define SOL_BASIC 1 /* basic */
1.73 +#define SOL_INTERIOR 2 /* interior-point */
1.74 +#define SOL_INTEGER 3 /* mixed integer */
1.75 + const char *in_res;
1.76 + /* name of input solution file in raw format */
1.77 + int dir;
1.78 + /* optimization direction flag:
1.79 + 0 - not specified
1.80 + GLP_MIN - minimization
1.81 + GLP_MAX - maximization */
1.82 + int scale;
1.83 + /* automatic problem scaling flag */
1.84 + const char *out_sol;
1.85 + /* name of output solution file in printable format */
1.86 + const char *out_res;
1.87 + /* name of output solution file in raw format */
1.88 + const char *out_ranges;
1.89 + /* name of output file to write sensitivity analysis report */
1.90 + int check;
1.91 + /* input data checking flag; no solution is performed */
1.92 + const char *new_name;
1.93 + /* new name to be assigned to the problem */
1.94 + const char *out_mps;
1.95 + /* name of output problem file in fixed MPS format */
1.96 + const char *out_freemps;
1.97 + /* name of output problem file in free MPS format */
1.98 + const char *out_cpxlp;
1.99 + /* name of output problem file in CPLEX LP format */
1.100 + const char *out_glp;
1.101 + /* name of output problem file in GLPK format */
1.102 + const char *out_pb;
1.103 + /* name of output problem file in OPB format */
1.104 + const char *out_npb;
1.105 + /* name of output problem file in normalized OPB format */
1.106 + const char *log_file;
1.107 + /* name of output file to hardcopy terminal output */
1.108 + int crash;
1.109 + /* initial basis option: */
1.110 +#define USE_STD_BASIS 1 /* use standard basis */
1.111 +#define USE_ADV_BASIS 2 /* use advanced basis */
1.112 +#define USE_CPX_BASIS 3 /* use Bixby's basis */
1.113 +#define USE_INI_BASIS 4 /* use initial basis from ini_file */
1.114 + const char *ini_file;
1.115 + /* name of input file containing initial basis */
1.116 + int exact;
1.117 + /* flag to use glp_exact rather than glp_simplex */
1.118 + int xcheck;
1.119 + /* flag to check final basis with glp_exact */
1.120 + int nomip;
1.121 + /* flag to consider MIP as pure LP */
1.122 +};
1.123 +
1.124 +static void print_help(const char *my_name)
1.125 +{ /* print help information */
1.126 + xprintf("Usage: %s [options...] filename\n", my_name);
1.127 + xprintf("\n");
1.128 + xprintf("General options:\n");
1.129 + xprintf(" --mps read LP/MIP problem in fixed MPS fo"
1.130 + "rmat\n");
1.131 + xprintf(" --freemps read LP/MIP problem in free MPS for"
1.132 + "mat (default)\n");
1.133 + xprintf(" --lp read LP/MIP problem in CPLEX LP for"
1.134 + "mat\n");
1.135 + xprintf(" --glp read LP/MIP problem in GLPK format "
1.136 + "\n");
1.137 + xprintf(" --math read LP/MIP model written in GNU Ma"
1.138 + "thProg modeling\n");
1.139 + xprintf(" language\n");
1.140 + xprintf(" -m filename, --model filename\n");
1.141 + xprintf(" read model section and optional dat"
1.142 + "a section from\n");
1.143 + xprintf(" filename (same as --math)\n");
1.144 + xprintf(" -d filename, --data filename\n");
1.145 + xprintf(" read data section from filename (fo"
1.146 + "r --math only);\n");
1.147 + xprintf(" if model file also has data section"
1.148 + ", it is ignored\n");
1.149 + xprintf(" -y filename, --display filename\n");
1.150 + xprintf(" send display output to filename (fo"
1.151 + "r --math only);\n");
1.152 + xprintf(" by default the output is sent to te"
1.153 + "rminal\n");
1.154 + xprintf(" --seed value initialize pseudo-random number gen"
1.155 + "erator used in\n");
1.156 + xprintf(" MathProg model with specified seed "
1.157 + "(any integer);\n");
1.158 + xprintf(" if seed value is ?, some random see"
1.159 + "d will be used\n");
1.160 + xprintf(" --mincost read min-cost flow problem in DIMAC"
1.161 + "S format\n");
1.162 + xprintf(" --maxflow read maximum flow problem in DIMACS"
1.163 + " format\n");
1.164 + xprintf(" --simplex use simplex method (default)\n");
1.165 + xprintf(" --interior use interior point method (LP only)"
1.166 + "\n");
1.167 + xprintf(" -r filename, --read filename\n");
1.168 + xprintf(" read solution from filename rather "
1.169 + "to find it with\n");
1.170 + xprintf(" the solver\n");
1.171 + xprintf(" --min minimization\n");
1.172 + xprintf(" --max maximization\n");
1.173 + xprintf(" --scale scale problem (default)\n");
1.174 + xprintf(" --noscale do not scale problem\n");
1.175 + xprintf(" -o filename, --output filename\n");
1.176 + xprintf(" write solution to filename in print"
1.177 + "able format\n");
1.178 + xprintf(" -w filename, --write filename\n");
1.179 + xprintf(" write solution to filename in plain"
1.180 + " text format\n");
1.181 + xprintf(" --ranges filename\n");
1.182 + xprintf(" write sensitivity analysis report t"
1.183 + "o filename in\n");
1.184 + xprintf(" printable format (simplex only)\n");
1.185 + xprintf(" --tmlim nnn limit solution time to nnn seconds "
1.186 + "\n");
1.187 + xprintf(" --memlim nnn limit available memory to nnn megab"
1.188 + "ytes\n");
1.189 + xprintf(" --check do not solve problem, check input d"
1.190 + "ata only\n");
1.191 + xprintf(" --name probname change problem name to probname\n");
1.192 + xprintf(" --wmps filename write problem to filename in fixed "
1.193 + "MPS format\n");
1.194 + xprintf(" --wfreemps filename\n");
1.195 + xprintf(" write problem to filename in free M"
1.196 + "PS format\n");
1.197 + xprintf(" --wlp filename write problem to filename in CPLEX "
1.198 + "LP format\n");
1.199 + xprintf(" --wglp filename write problem to filename in GLPK f"
1.200 + "ormat\n");
1.201 +#if 0
1.202 + xprintf(" --wpb filename write problem to filename in OPB fo"
1.203 + "rmat\n");
1.204 + xprintf(" --wnpb filename write problem to filename in normal"
1.205 + "ized OPB format\n");
1.206 +#endif
1.207 + xprintf(" --log filename write copy of terminal output to fi"
1.208 + "lename\n");
1.209 + xprintf(" -h, --help display this help information and e"
1.210 + "xit\n");
1.211 + xprintf(" -v, --version display program version and exit\n")
1.212 + ;
1.213 + xprintf("\n");
1.214 + xprintf("LP basis factorization options:\n");
1.215 + xprintf(" --luf LU + Forrest-Tomlin update\n");
1.216 + xprintf(" (faster, less stable; default)\n");
1.217 + xprintf(" --cbg LU + Schur complement + Bartels-Gol"
1.218 + "ub update\n");
1.219 + xprintf(" (slower, more stable)\n");
1.220 + xprintf(" --cgr LU + Schur complement + Givens rota"
1.221 + "tion update\n");
1.222 + xprintf(" (slower, more stable)\n");
1.223 + xprintf("\n");
1.224 + xprintf("Options specific to simplex solver:\n");
1.225 + xprintf(" --primal use primal simplex (default)\n");
1.226 + xprintf(" --dual use dual simplex\n");
1.227 + xprintf(" --std use standard initial basis of all s"
1.228 + "lacks\n");
1.229 + xprintf(" --adv use advanced initial basis (default"
1.230 + ")\n");
1.231 + xprintf(" --bib use Bixby's initial basis\n");
1.232 + xprintf(" --ini filename use as initial basis previously sav"
1.233 + "ed with -w\n");
1.234 + xprintf(" (disables LP presolver)\n");
1.235 + xprintf(" --steep use steepest edge technique (defaul"
1.236 + "t)\n");
1.237 + xprintf(" --nosteep use standard \"textbook\" pricing\n"
1.238 + );
1.239 + xprintf(" --relax use Harris' two-pass ratio test (de"
1.240 + "fault)\n");
1.241 + xprintf(" --norelax use standard \"textbook\" ratio tes"
1.242 + "t\n");
1.243 + xprintf(" --presol use presolver (default; assumes --s"
1.244 + "cale and --adv)\n");
1.245 + xprintf(" --nopresol do not use presolver\n");
1.246 + xprintf(" --exact use simplex method based on exact a"
1.247 + "rithmetic\n");
1.248 + xprintf(" --xcheck check final basis using exact arith"
1.249 + "metic\n");
1.250 + xprintf("\n");
1.251 + xprintf("Options specific to interior-point solver:\n");
1.252 + xprintf(" --nord use natural (original) ordering\n");
1.253 + xprintf(" --qmd use quotient minimum degree orderin"
1.254 + "g\n");
1.255 + xprintf(" --amd use approximate minimum degree orde"
1.256 + "ring (default)\n");
1.257 + xprintf(" --symamd use approximate minimum degree orde"
1.258 + "ring\n");
1.259 + xprintf("\n");
1.260 + xprintf("Options specific to MIP solver:\n");
1.261 + xprintf(" --nomip consider all integer variables as c"
1.262 + "ontinuous\n");
1.263 + xprintf(" (allows solving MIP as pure LP)\n");
1.264 + xprintf(" --first branch on first integer variable\n")
1.265 + ;
1.266 + xprintf(" --last branch on last integer variable\n");
1.267 + xprintf(" --mostf branch on most fractional variable "
1.268 + "\n");
1.269 + xprintf(" --drtom branch using heuristic by Driebeck "
1.270 + "and Tomlin\n");
1.271 + xprintf(" (default)\n");
1.272 + xprintf(" --pcost branch using hybrid pseudocost heur"
1.273 + "istic (may be\n");
1.274 + xprintf(" useful for hard instances)\n");
1.275 + xprintf(" --dfs backtrack using depth first search "
1.276 + "\n");
1.277 + xprintf(" --bfs backtrack using breadth first searc"
1.278 + "h\n");
1.279 + xprintf(" --bestp backtrack using the best projection"
1.280 + " heuristic\n");
1.281 + xprintf(" --bestb backtrack using node with best loca"
1.282 + "l bound\n");
1.283 + xprintf(" (default)\n");
1.284 + xprintf(" --intopt use MIP presolver (default)\n");
1.285 + xprintf(" --nointopt do not use MIP presolver\n");
1.286 + xprintf(" --binarize replace general integer variables b"
1.287 + "y binary ones\n");
1.288 + xprintf(" (assumes --intopt)\n");
1.289 + xprintf(" --fpump apply feasibility pump heuristic\n")
1.290 + ;
1.291 + xprintf(" --gomory generate Gomory's mixed integer cut"
1.292 + "s\n");
1.293 + xprintf(" --mir generate MIR (mixed integer roundin"
1.294 + "g) cuts\n");
1.295 + xprintf(" --cover generate mixed cover cuts\n");
1.296 + xprintf(" --clique generate clique cuts\n");
1.297 + xprintf(" --cuts generate all cuts above\n");
1.298 + xprintf(" --mipgap tol set relative mip gap tolerance to t"
1.299 + "ol\n");
1.300 + xprintf("\n");
1.301 + xprintf("For description of the MPS and CPLEX LP formats see Refe"
1.302 + "rence Manual.\n");
1.303 + xprintf("For description of the modeling language see \"GLPK: Mod"
1.304 + "eling Language\n");
1.305 + xprintf("GNU MathProg\". Both documents are included in the GLPK "
1.306 + "distribution.\n");
1.307 + xprintf("\n");
1.308 + xprintf("See GLPK web page at <http://www.gnu.org/software/glpk/g"
1.309 + "lpk.html>.\n");
1.310 + xprintf("\n");
1.311 + xprintf("Please report bugs to <bug-glpk@gnu.org>.\n");
1.312 + return;
1.313 +}
1.314 +
1.315 +static void print_version(int briefly)
1.316 +{ /* print version information */
1.317 + xprintf("GLPSOL: GLPK LP/MIP Solver, v%s\n", glp_version());
1.318 + if (briefly) goto done;
1.319 + xprintf("\n");
1.320 + xprintf("Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, "
1.321 + "2007, 2008,\n");
1.322 + xprintf("2009, 2010 Andrew Makhorin, Department for Applied Infor"
1.323 + "matics, Moscow\n");
1.324 + xprintf("Aviation Institute, Moscow, Russia. All rights reserved."
1.325 + "\n");
1.326 + xprintf("\n");
1.327 + xprintf("This program has ABSOLUTELY NO WARRANTY.\n");
1.328 + xprintf("\n");
1.329 + xprintf("This program is free software; you may re-distribute it "
1.330 + "under the terms\n");
1.331 + xprintf("of the GNU General Public License version 3 or later.\n")
1.332 + ;
1.333 +done: return;
1.334 +}
1.335 +
1.336 +static int parse_cmdline(struct csa *csa, int argc, const char *argv[])
1.337 +{ /* parse command-line parameters */
1.338 + int k;
1.339 +#define p(str) (strcmp(argv[k], str) == 0)
1.340 + for (k = 1; k < argc; k++)
1.341 + { if (p("--mps"))
1.342 + csa->format = FMT_MPS_DECK;
1.343 + else if (p("--freemps"))
1.344 + csa->format = FMT_MPS_FILE;
1.345 + else if (p("--lp") || p("--cpxlp"))
1.346 + csa->format = FMT_LP;
1.347 + else if (p("--glp"))
1.348 + csa->format = FMT_GLP;
1.349 + else if (p("--math") || p("-m") || p("--model"))
1.350 + csa->format = FMT_MATHPROG;
1.351 + else if (p("-d") || p("--data"))
1.352 + { k++;
1.353 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.354 + { xprintf("No input data file specified\n");
1.355 + return 1;
1.356 + }
1.357 + if (csa->ndf == DATA_MAX)
1.358 + { xprintf("Too many input data files\n");
1.359 + return 1;
1.360 + }
1.361 + csa->in_data[++(csa->ndf)] = argv[k];
1.362 + }
1.363 + else if (p("-y") || p("--display"))
1.364 + { k++;
1.365 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.366 + { xprintf("No display output file specified\n");
1.367 + return 1;
1.368 + }
1.369 + if (csa->out_dpy != NULL)
1.370 + { xprintf("Only one display output file allowed\n");
1.371 + return 1;
1.372 + }
1.373 + csa->out_dpy = argv[k];
1.374 + }
1.375 + else if (p("--seed"))
1.376 + { k++;
1.377 + if (k == argc || argv[k][0] == '\0' ||
1.378 + argv[k][0] == '-' && !isdigit((unsigned char)argv[k][1]))
1.379 + { xprintf("No seed value specified\n");
1.380 + return 1;
1.381 + }
1.382 + if (strcmp(argv[k], "?") == 0)
1.383 + csa->seed = 0x80000000;
1.384 + else if (str2int(argv[k], &csa->seed))
1.385 + { xprintf("Invalid seed value `%s'\n", argv[k]);
1.386 + return 1;
1.387 + }
1.388 + }
1.389 + else if (p("--mincost"))
1.390 + csa->format = FMT_MIN_COST;
1.391 + else if (p("--maxflow"))
1.392 + csa->format = FMT_MAX_FLOW;
1.393 + else if (p("--simplex"))
1.394 + csa->solution = SOL_BASIC;
1.395 + else if (p("--interior"))
1.396 + csa->solution = SOL_INTERIOR;
1.397 +#if 1 /* 28/V-2010 */
1.398 + else if (p("--alien"))
1.399 + csa->iocp.alien = GLP_ON;
1.400 +#endif
1.401 + else if (p("-r") || p("--read"))
1.402 + { k++;
1.403 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.404 + { xprintf("No input solution file specified\n");
1.405 + return 1;
1.406 + }
1.407 + if (csa->in_res != NULL)
1.408 + { xprintf("Only one input solution file allowed\n");
1.409 + return 1;
1.410 + }
1.411 + csa->in_res = argv[k];
1.412 + }
1.413 + else if (p("--min"))
1.414 + csa->dir = GLP_MIN;
1.415 + else if (p("--max"))
1.416 + csa->dir = GLP_MAX;
1.417 + else if (p("--scale"))
1.418 + csa->scale = 1;
1.419 + else if (p("--noscale"))
1.420 + csa->scale = 0;
1.421 + else if (p("-o") || p("--output"))
1.422 + { k++;
1.423 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.424 + { xprintf("No output solution file specified\n");
1.425 + return 1;
1.426 + }
1.427 + if (csa->out_sol != NULL)
1.428 + { xprintf("Only one output solution file allowed\n");
1.429 + return 1;
1.430 + }
1.431 + csa->out_sol = argv[k];
1.432 + }
1.433 + else if (p("-w") || p("--write"))
1.434 + { k++;
1.435 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.436 + { xprintf("No output solution file specified\n");
1.437 + return 1;
1.438 + }
1.439 + if (csa->out_res != NULL)
1.440 + { xprintf("Only one output solution file allowed\n");
1.441 + return 1;
1.442 + }
1.443 + csa->out_res = argv[k];
1.444 + }
1.445 + else if (p("--ranges") || p("--bounds"))
1.446 + { k++;
1.447 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.448 + { xprintf("No output file specified to write sensitivity a"
1.449 + "nalysis report\n");
1.450 + return 1;
1.451 + }
1.452 + if (csa->out_ranges != NULL)
1.453 + { xprintf("Only one output file allowed to write sensitivi"
1.454 + "ty analysis report\n");
1.455 + return 1;
1.456 + }
1.457 + csa->out_ranges = argv[k];
1.458 + }
1.459 + else if (p("--tmlim"))
1.460 + { int tm_lim;
1.461 + k++;
1.462 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.463 + { xprintf("No time limit specified\n");
1.464 + return 1;
1.465 + }
1.466 + if (str2int(argv[k], &tm_lim) || tm_lim < 0)
1.467 + { xprintf("Invalid time limit `%s'\n", argv[k]);
1.468 + return 1;
1.469 + }
1.470 + if (tm_lim <= INT_MAX / 1000)
1.471 + csa->smcp.tm_lim = csa->iocp.tm_lim = 1000 * tm_lim;
1.472 + else
1.473 + csa->smcp.tm_lim = csa->iocp.tm_lim = INT_MAX;
1.474 + }
1.475 + else if (p("--memlim"))
1.476 + { int mem_lim;
1.477 + k++;
1.478 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.479 + { xprintf("No memory limit specified\n");
1.480 + return 1;
1.481 + }
1.482 + if (str2int(argv[k], &mem_lim) || mem_lim < 1)
1.483 + { xprintf("Invalid memory limit `%s'\n", argv[k]);
1.484 + return 1;
1.485 + }
1.486 + glp_mem_limit(mem_lim);
1.487 + }
1.488 + else if (p("--check"))
1.489 + csa->check = 1;
1.490 + else if (p("--name"))
1.491 + { k++;
1.492 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.493 + { xprintf("No problem name specified\n");
1.494 + return 1;
1.495 + }
1.496 + if (csa->new_name != NULL)
1.497 + { xprintf("Only one problem name allowed\n");
1.498 + return 1;
1.499 + }
1.500 + csa->new_name = argv[k];
1.501 + }
1.502 + else if (p("--wmps"))
1.503 + { k++;
1.504 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.505 + { xprintf("No fixed MPS output file specified\n");
1.506 + return 1;
1.507 + }
1.508 + if (csa->out_mps != NULL)
1.509 + { xprintf("Only one fixed MPS output file allowed\n");
1.510 + return 1;
1.511 + }
1.512 + csa->out_mps = argv[k];
1.513 + }
1.514 + else if (p("--wfreemps"))
1.515 + { k++;
1.516 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.517 + { xprintf("No free MPS output file specified\n");
1.518 + return 1;
1.519 + }
1.520 + if (csa->out_freemps != NULL)
1.521 + { xprintf("Only one free MPS output file allowed\n");
1.522 + return 1;
1.523 + }
1.524 + csa->out_freemps = argv[k];
1.525 + }
1.526 + else if (p("--wlp") || p("--wcpxlp") || p("--wlpt"))
1.527 + { k++;
1.528 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.529 + { xprintf("No CPLEX LP output file specified\n");
1.530 + return 1;
1.531 + }
1.532 + if (csa->out_cpxlp != NULL)
1.533 + { xprintf("Only one CPLEX LP output file allowed\n");
1.534 + return 1;
1.535 + }
1.536 + csa->out_cpxlp = argv[k];
1.537 + }
1.538 + else if (p("--wglp"))
1.539 + { k++;
1.540 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.541 + { xprintf("No GLPK LP/MIP output file specified\n");
1.542 + return 1;
1.543 + }
1.544 + if (csa->out_glp != NULL)
1.545 + { xprintf("Only one GLPK LP/MIP output file allowed\n");
1.546 + return 1;
1.547 + }
1.548 + csa->out_glp = argv[k];
1.549 + }
1.550 + else if (p("--wpb"))
1.551 + { k++;
1.552 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.553 + { xprintf("No problem output file specified\n");
1.554 + return 1;
1.555 + }
1.556 + if (csa->out_pb != NULL)
1.557 + { xprintf("Only one OPB output file allowed\n");
1.558 + return 1;
1.559 + }
1.560 + csa->out_pb = argv[k];
1.561 + }
1.562 + else if (p("--wnpb"))
1.563 + { k++;
1.564 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.565 + { xprintf("No problem output file specified\n");
1.566 + return 1;
1.567 + }
1.568 + if (csa->out_npb != NULL)
1.569 + { xprintf("Only one normalized OPB output file allowed\n");
1.570 + return 1;
1.571 + }
1.572 + csa->out_npb = argv[k];
1.573 + }
1.574 + else if (p("--log"))
1.575 + { k++;
1.576 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.577 + { xprintf("No log file specified\n");
1.578 + return 1;
1.579 + }
1.580 + if (csa->log_file != NULL)
1.581 + { xprintf("Only one log file allowed\n");
1.582 + return 1;
1.583 + }
1.584 + csa->log_file = argv[k];
1.585 + }
1.586 + else if (p("-h") || p("--help"))
1.587 + { print_help(argv[0]);
1.588 + return -1;
1.589 + }
1.590 + else if (p("-v") || p("--version"))
1.591 + { print_version(0);
1.592 + return -1;
1.593 + }
1.594 + else if (p("--luf"))
1.595 + csa->bfcp.type = GLP_BF_FT;
1.596 + else if (p("--cbg"))
1.597 + csa->bfcp.type = GLP_BF_BG;
1.598 + else if (p("--cgr"))
1.599 + csa->bfcp.type = GLP_BF_GR;
1.600 + else if (p("--primal"))
1.601 + csa->smcp.meth = GLP_PRIMAL;
1.602 + else if (p("--dual"))
1.603 + csa->smcp.meth = GLP_DUAL;
1.604 + else if (p("--std"))
1.605 + csa->crash = USE_STD_BASIS;
1.606 + else if (p("--adv"))
1.607 + csa->crash = USE_ADV_BASIS;
1.608 + else if (p("--bib"))
1.609 + csa->crash = USE_CPX_BASIS;
1.610 + else if (p("--ini"))
1.611 + { csa->crash = USE_INI_BASIS;
1.612 + csa->smcp.presolve = GLP_OFF;
1.613 + k++;
1.614 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.615 + { xprintf("No initial basis file specified\n");
1.616 + return 1;
1.617 + }
1.618 + if (csa->ini_file != NULL)
1.619 + { xprintf("Only one initial basis file allowed\n");
1.620 + return 1;
1.621 + }
1.622 + csa->ini_file = argv[k];
1.623 + }
1.624 + else if (p("--steep"))
1.625 + csa->smcp.pricing = GLP_PT_PSE;
1.626 + else if (p("--nosteep"))
1.627 + csa->smcp.pricing = GLP_PT_STD;
1.628 + else if (p("--relax"))
1.629 + csa->smcp.r_test = GLP_RT_HAR;
1.630 + else if (p("--norelax"))
1.631 + csa->smcp.r_test = GLP_RT_STD;
1.632 + else if (p("--presol"))
1.633 + csa->smcp.presolve = GLP_ON;
1.634 + else if (p("--nopresol"))
1.635 + csa->smcp.presolve = GLP_OFF;
1.636 + else if (p("--exact"))
1.637 + csa->exact = 1;
1.638 + else if (p("--xcheck"))
1.639 + csa->xcheck = 1;
1.640 + else if (p("--nord"))
1.641 + csa->iptcp.ord_alg = GLP_ORD_NONE;
1.642 + else if (p("--qmd"))
1.643 + csa->iptcp.ord_alg = GLP_ORD_QMD;
1.644 + else if (p("--amd"))
1.645 + csa->iptcp.ord_alg = GLP_ORD_AMD;
1.646 + else if (p("--symamd"))
1.647 + csa->iptcp.ord_alg = GLP_ORD_SYMAMD;
1.648 + else if (p("--nomip"))
1.649 + csa->nomip = 1;
1.650 + else if (p("--first"))
1.651 + csa->iocp.br_tech = GLP_BR_FFV;
1.652 + else if (p("--last"))
1.653 + csa->iocp.br_tech = GLP_BR_LFV;
1.654 + else if (p("--drtom"))
1.655 + csa->iocp.br_tech = GLP_BR_DTH;
1.656 + else if (p("--mostf"))
1.657 + csa->iocp.br_tech = GLP_BR_MFV;
1.658 + else if (p("--pcost"))
1.659 + csa->iocp.br_tech = GLP_BR_PCH;
1.660 + else if (p("--dfs"))
1.661 + csa->iocp.bt_tech = GLP_BT_DFS;
1.662 + else if (p("--bfs"))
1.663 + csa->iocp.bt_tech = GLP_BT_BFS;
1.664 + else if (p("--bestp"))
1.665 + csa->iocp.bt_tech = GLP_BT_BPH;
1.666 + else if (p("--bestb"))
1.667 + csa->iocp.bt_tech = GLP_BT_BLB;
1.668 + else if (p("--intopt"))
1.669 + csa->iocp.presolve = GLP_ON;
1.670 + else if (p("--nointopt"))
1.671 + csa->iocp.presolve = GLP_OFF;
1.672 + else if (p("--binarize"))
1.673 + csa->iocp.presolve = csa->iocp.binarize = GLP_ON;
1.674 + else if (p("--fpump"))
1.675 + csa->iocp.fp_heur = GLP_ON;
1.676 + else if (p("--gomory"))
1.677 + csa->iocp.gmi_cuts = GLP_ON;
1.678 + else if (p("--mir"))
1.679 + csa->iocp.mir_cuts = GLP_ON;
1.680 + else if (p("--cover"))
1.681 + csa->iocp.cov_cuts = GLP_ON;
1.682 + else if (p("--clique"))
1.683 + csa->iocp.clq_cuts = GLP_ON;
1.684 + else if (p("--cuts"))
1.685 + csa->iocp.gmi_cuts = csa->iocp.mir_cuts =
1.686 + csa->iocp.cov_cuts = csa->iocp.clq_cuts = GLP_ON;
1.687 + else if (p("--mipgap"))
1.688 + { double mip_gap;
1.689 + k++;
1.690 + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
1.691 + { xprintf("No relative gap tolerance specified\n");
1.692 + return 1;
1.693 + }
1.694 + if (str2num(argv[k], &mip_gap) || mip_gap < 0.0)
1.695 + { xprintf("Invalid relative mip gap tolerance `%s'\n",
1.696 + argv[k]);
1.697 + return 1;
1.698 + }
1.699 + csa->iocp.mip_gap = mip_gap;
1.700 + }
1.701 + else if (argv[k][0] == '-' ||
1.702 + (argv[k][0] == '-' && argv[k][1] == '-'))
1.703 + { xprintf("Invalid option `%s'; try %s --help\n",
1.704 + argv[k], argv[0]);
1.705 + return 1;
1.706 + }
1.707 + else
1.708 + { if (csa->in_file != NULL)
1.709 + { xprintf("Only one input problem file allowed\n");
1.710 + return 1;
1.711 + }
1.712 + csa->in_file = argv[k];
1.713 + }
1.714 + }
1.715 +#undef p
1.716 + return 0;
1.717 +}
1.718 +
1.719 +typedef struct { double rhs, pi; } v_data;
1.720 +typedef struct { double low, cap, cost, x; } a_data;
1.721 +
1.722 +int glp_main(int argc, const char *argv[])
1.723 +{ /* stand-alone LP/MIP solver */
1.724 + struct csa _csa, *csa = &_csa;
1.725 + int ret;
1.726 + glp_long start;
1.727 + /* perform initialization */
1.728 + csa->prob = glp_create_prob();
1.729 + glp_get_bfcp(csa->prob, &csa->bfcp);
1.730 + glp_init_smcp(&csa->smcp);
1.731 + csa->smcp.presolve = GLP_ON;
1.732 + glp_init_iptcp(&csa->iptcp);
1.733 + glp_init_iocp(&csa->iocp);
1.734 + csa->iocp.presolve = GLP_ON;
1.735 + csa->tran = NULL;
1.736 + csa->graph = NULL;
1.737 + csa->format = FMT_MPS_FILE;
1.738 + csa->in_file = NULL;
1.739 + csa->ndf = 0;
1.740 + csa->out_dpy = NULL;
1.741 + csa->seed = 1;
1.742 + csa->solution = SOL_BASIC;
1.743 + csa->in_res = NULL;
1.744 + csa->dir = 0;
1.745 + csa->scale = 1;
1.746 + csa->out_sol = NULL;
1.747 + csa->out_res = NULL;
1.748 + csa->out_ranges = NULL;
1.749 + csa->check = 0;
1.750 + csa->new_name = NULL;
1.751 + csa->out_mps = NULL;
1.752 + csa->out_freemps = NULL;
1.753 + csa->out_cpxlp = NULL;
1.754 + csa->out_glp = NULL;
1.755 + csa->out_pb = NULL;
1.756 + csa->out_npb = NULL;
1.757 + csa->log_file = NULL;
1.758 + csa->crash = USE_ADV_BASIS;
1.759 + csa->ini_file = NULL;
1.760 + csa->exact = 0;
1.761 + csa->xcheck = 0;
1.762 + csa->nomip = 0;
1.763 + /* parse command-line parameters */
1.764 + ret = parse_cmdline(csa, argc, argv);
1.765 + if (ret < 0)
1.766 + { ret = EXIT_SUCCESS;
1.767 + goto done;
1.768 + }
1.769 + if (ret > 0)
1.770 + { ret = EXIT_FAILURE;
1.771 + goto done;
1.772 + }
1.773 + /*--------------------------------------------------------------*/
1.774 + /* remove all output files specified in the command line */
1.775 + if (csa->out_dpy != NULL) remove(csa->out_dpy);
1.776 + if (csa->out_sol != NULL) remove(csa->out_sol);
1.777 + if (csa->out_res != NULL) remove(csa->out_res);
1.778 + if (csa->out_ranges != NULL) remove(csa->out_ranges);
1.779 + if (csa->out_mps != NULL) remove(csa->out_mps);
1.780 + if (csa->out_freemps != NULL) remove(csa->out_freemps);
1.781 + if (csa->out_cpxlp != NULL) remove(csa->out_cpxlp);
1.782 + if (csa->out_glp != NULL) remove(csa->out_glp);
1.783 + if (csa->out_pb != NULL) remove(csa->out_pb);
1.784 + if (csa->out_npb != NULL) remove(csa->out_npb);
1.785 + if (csa->log_file != NULL) remove(csa->log_file);
1.786 + /*--------------------------------------------------------------*/
1.787 + /* open log file, if required */
1.788 + if (csa->log_file != NULL)
1.789 + { if (glp_open_tee(csa->log_file))
1.790 + { xprintf("Unable to create log file\n");
1.791 + ret = EXIT_FAILURE;
1.792 + goto done;
1.793 + }
1.794 + }
1.795 + /*--------------------------------------------------------------*/
1.796 + /* print version information */
1.797 + print_version(1);
1.798 + /*--------------------------------------------------------------*/
1.799 + /* print parameters specified in the command line */
1.800 + if (argc > 1)
1.801 + { int k, len = INT_MAX;
1.802 + xprintf("Parameter(s) specified in the command line:");
1.803 + for (k = 1; k < argc; k++)
1.804 + { if (len > 72)
1.805 + xprintf("\n"), len = 0;
1.806 + xprintf(" %s", argv[k]);
1.807 + len += 1 + strlen(argv[k]);
1.808 + }
1.809 + xprintf("\n");
1.810 + }
1.811 + /*--------------------------------------------------------------*/
1.812 + /* read problem data from the input file */
1.813 + if (csa->in_file == NULL)
1.814 + { xprintf("No input problem file specified; try %s --help\n",
1.815 + argv[0]);
1.816 + ret = EXIT_FAILURE;
1.817 + goto done;
1.818 + }
1.819 + if (csa->format == FMT_MPS_DECK)
1.820 + { ret = glp_read_mps(csa->prob, GLP_MPS_DECK, NULL,
1.821 + csa->in_file);
1.822 + if (ret != 0)
1.823 +err1: { xprintf("MPS file processing error\n");
1.824 + ret = EXIT_FAILURE;
1.825 + goto done;
1.826 + }
1.827 + }
1.828 + else if (csa->format == FMT_MPS_FILE)
1.829 + { ret = glp_read_mps(csa->prob, GLP_MPS_FILE, NULL,
1.830 + csa->in_file);
1.831 + if (ret != 0) goto err1;
1.832 + }
1.833 + else if (csa->format == FMT_LP)
1.834 + { ret = glp_read_lp(csa->prob, NULL, csa->in_file);
1.835 + if (ret != 0)
1.836 + { xprintf("CPLEX LP file processing error\n");
1.837 + ret = EXIT_FAILURE;
1.838 + goto done;
1.839 + }
1.840 + }
1.841 + else if (csa->format == FMT_GLP)
1.842 + { ret = glp_read_prob(csa->prob, 0, csa->in_file);
1.843 + if (ret != 0)
1.844 + { xprintf("GLPK LP/MIP file processing error\n");
1.845 + ret = EXIT_FAILURE;
1.846 + goto done;
1.847 + }
1.848 + }
1.849 + else if (csa->format == FMT_MATHPROG)
1.850 + { int k;
1.851 + /* allocate the translator workspace */
1.852 + csa->tran = glp_mpl_alloc_wksp();
1.853 + /* set seed value */
1.854 + if (csa->seed == 0x80000000)
1.855 + { csa->seed = glp_time().lo;
1.856 + xprintf("Seed value %d will be used\n", csa->seed);
1.857 + }
1.858 + _glp_mpl_init_rand(csa->tran, csa->seed);
1.859 + /* read model section and optional data section */
1.860 + if (glp_mpl_read_model(csa->tran, csa->in_file, csa->ndf > 0))
1.861 +err2: { xprintf("MathProg model processing error\n");
1.862 + ret = EXIT_FAILURE;
1.863 + goto done;
1.864 + }
1.865 + /* read optional data section(s), if necessary */
1.866 + for (k = 1; k <= csa->ndf; k++)
1.867 + { if (glp_mpl_read_data(csa->tran, csa->in_data[k]))
1.868 + goto err2;
1.869 + }
1.870 + /* generate the model */
1.871 + if (glp_mpl_generate(csa->tran, csa->out_dpy)) goto err2;
1.872 + /* build the problem instance from the model */
1.873 + glp_mpl_build_prob(csa->tran, csa->prob);
1.874 + }
1.875 + else if (csa->format == FMT_MIN_COST)
1.876 + { csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data));
1.877 + ret = glp_read_mincost(csa->graph, offsetof(v_data, rhs),
1.878 + offsetof(a_data, low), offsetof(a_data, cap),
1.879 + offsetof(a_data, cost), csa->in_file);
1.880 + if (ret != 0)
1.881 + { xprintf("DIMACS file processing error\n");
1.882 + ret = EXIT_FAILURE;
1.883 + goto done;
1.884 + }
1.885 + glp_mincost_lp(csa->prob, csa->graph, GLP_ON,
1.886 + offsetof(v_data, rhs), offsetof(a_data, low),
1.887 + offsetof(a_data, cap), offsetof(a_data, cost));
1.888 + glp_set_prob_name(csa->prob, csa->in_file);
1.889 + }
1.890 + else if (csa->format == FMT_MAX_FLOW)
1.891 + { int s, t;
1.892 + csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data));
1.893 + ret = glp_read_maxflow(csa->graph, &s, &t,
1.894 + offsetof(a_data, cap), csa->in_file);
1.895 + if (ret != 0)
1.896 + { xprintf("DIMACS file processing error\n");
1.897 + ret = EXIT_FAILURE;
1.898 + goto done;
1.899 + }
1.900 + glp_maxflow_lp(csa->prob, csa->graph, GLP_ON, s, t,
1.901 + offsetof(a_data, cap));
1.902 + glp_set_prob_name(csa->prob, csa->in_file);
1.903 + }
1.904 + else
1.905 + xassert(csa != csa);
1.906 + /*--------------------------------------------------------------*/
1.907 + /* change problem name, if required */
1.908 + if (csa->new_name != NULL)
1.909 + glp_set_prob_name(csa->prob, csa->new_name);
1.910 + /* change optimization direction, if required */
1.911 + if (csa->dir != 0)
1.912 + glp_set_obj_dir(csa->prob, csa->dir);
1.913 + /* sort elements of the constraint matrix */
1.914 + glp_sort_matrix(csa->prob);
1.915 + /*--------------------------------------------------------------*/
1.916 + /* write problem data in fixed MPS format, if required */
1.917 + if (csa->out_mps != NULL)
1.918 + { ret = glp_write_mps(csa->prob, GLP_MPS_DECK, NULL,
1.919 + csa->out_mps);
1.920 + if (ret != 0)
1.921 + { xprintf("Unable to write problem in fixed MPS format\n");
1.922 + ret = EXIT_FAILURE;
1.923 + goto done;
1.924 + }
1.925 + }
1.926 + /* write problem data in free MPS format, if required */
1.927 + if (csa->out_freemps != NULL)
1.928 + { ret = glp_write_mps(csa->prob, GLP_MPS_FILE, NULL,
1.929 + csa->out_freemps);
1.930 + if (ret != 0)
1.931 + { xprintf("Unable to write problem in free MPS format\n");
1.932 + ret = EXIT_FAILURE;
1.933 + goto done;
1.934 + }
1.935 + }
1.936 + /* write problem data in CPLEX LP format, if required */
1.937 + if (csa->out_cpxlp != NULL)
1.938 + { ret = glp_write_lp(csa->prob, NULL, csa->out_cpxlp);
1.939 + if (ret != 0)
1.940 + { xprintf("Unable to write problem in CPLEX LP format\n");
1.941 + ret = EXIT_FAILURE;
1.942 + goto done;
1.943 + }
1.944 + }
1.945 + /* write problem data in GLPK format, if required */
1.946 + if (csa->out_glp != NULL)
1.947 + { ret = glp_write_prob(csa->prob, 0, csa->out_glp);
1.948 + if (ret != 0)
1.949 + { xprintf("Unable to write problem in GLPK format\n");
1.950 + ret = EXIT_FAILURE;
1.951 + goto done;
1.952 + }
1.953 + }
1.954 + /* write problem data in OPB format, if required */
1.955 + if (csa->out_pb != NULL)
1.956 + { ret = lpx_write_pb(csa->prob, csa->out_pb, 0, 0);
1.957 + if (ret != 0)
1.958 + { xprintf("Unable to write problem in OPB format\n");
1.959 + ret = EXIT_FAILURE;
1.960 + goto done;
1.961 + }
1.962 + }
1.963 + /* write problem data in normalized OPB format, if required */
1.964 + if (csa->out_npb != NULL)
1.965 + { ret = lpx_write_pb(csa->prob, csa->out_npb, 1, 1);
1.966 + if (ret != 0)
1.967 + { xprintf(
1.968 + "Unable to write problem in normalized OPB format\n");
1.969 + ret = EXIT_FAILURE;
1.970 + goto done;
1.971 + }
1.972 + }
1.973 + /*--------------------------------------------------------------*/
1.974 + /* if only problem data check is required, skip computations */
1.975 + if (csa->check)
1.976 + { ret = EXIT_SUCCESS;
1.977 + goto done;
1.978 + }
1.979 + /*--------------------------------------------------------------*/
1.980 + /* determine the solution type */
1.981 + if (!csa->nomip &&
1.982 + glp_get_num_int(csa->prob) + glp_get_num_bin(csa->prob) > 0)
1.983 + { if (csa->solution == SOL_INTERIOR)
1.984 + { xprintf("Interior-point method is not able to solve MIP pro"
1.985 + "blem; use --simplex\n");
1.986 + ret = EXIT_FAILURE;
1.987 + goto done;
1.988 + }
1.989 + csa->solution = SOL_INTEGER;
1.990 + }
1.991 + /*--------------------------------------------------------------*/
1.992 + /* if solution is provided, read it and skip computations */
1.993 + if (csa->in_res != NULL)
1.994 + { if (csa->solution == SOL_BASIC)
1.995 + ret = glp_read_sol(csa->prob, csa->in_res);
1.996 + else if (csa->solution == SOL_INTERIOR)
1.997 + ret = glp_read_ipt(csa->prob, csa->in_res);
1.998 + else if (csa->solution == SOL_INTEGER)
1.999 + ret = glp_read_mip(csa->prob, csa->in_res);
1.1000 + else
1.1001 + xassert(csa != csa);
1.1002 + if (ret != 0)
1.1003 + { xprintf("Unable to read problem solution\n");
1.1004 + ret = EXIT_FAILURE;
1.1005 + goto done;
1.1006 + }
1.1007 + goto skip;
1.1008 + }
1.1009 + /*--------------------------------------------------------------*/
1.1010 + /* scale the problem data, if required */
1.1011 + if (csa->scale)
1.1012 + { if (csa->solution == SOL_BASIC && !csa->smcp.presolve ||
1.1013 + csa->solution == SOL_INTERIOR ||
1.1014 + csa->solution == SOL_INTEGER && !csa->iocp.presolve)
1.1015 + glp_scale_prob(csa->prob, GLP_SF_AUTO);
1.1016 + }
1.1017 + /*--------------------------------------------------------------*/
1.1018 + /* construct starting LP basis */
1.1019 + if (csa->solution == SOL_BASIC && !csa->smcp.presolve ||
1.1020 + csa->solution == SOL_INTEGER && !csa->iocp.presolve)
1.1021 + { if (csa->crash == USE_STD_BASIS)
1.1022 + glp_std_basis(csa->prob);
1.1023 + else if (csa->crash == USE_ADV_BASIS)
1.1024 + glp_adv_basis(csa->prob, 0);
1.1025 + else if (csa->crash == USE_CPX_BASIS)
1.1026 + glp_cpx_basis(csa->prob);
1.1027 + else if (csa->crash == USE_INI_BASIS)
1.1028 + { ret = glp_read_sol(csa->prob, csa->ini_file);
1.1029 + if (ret != 0)
1.1030 + { xprintf("Unable to read initial basis\n");
1.1031 + ret = EXIT_FAILURE;
1.1032 + goto done;
1.1033 + }
1.1034 + }
1.1035 + else
1.1036 + xassert(csa != csa);
1.1037 + }
1.1038 + /*--------------------------------------------------------------*/
1.1039 + /* solve the problem */
1.1040 + start = xtime();
1.1041 + if (csa->solution == SOL_BASIC)
1.1042 + { if (!csa->exact)
1.1043 + { glp_set_bfcp(csa->prob, &csa->bfcp);
1.1044 + glp_simplex(csa->prob, &csa->smcp);
1.1045 + if (csa->xcheck)
1.1046 + { if (csa->smcp.presolve &&
1.1047 + glp_get_status(csa->prob) != GLP_OPT)
1.1048 + xprintf("If you need to check final basis for non-opt"
1.1049 + "imal solution, use --nopresol\n");
1.1050 + else
1.1051 + glp_exact(csa->prob, &csa->smcp);
1.1052 + }
1.1053 + if (csa->out_sol != NULL || csa->out_res != NULL)
1.1054 + { if (csa->smcp.presolve &&
1.1055 + glp_get_status(csa->prob) != GLP_OPT)
1.1056 + xprintf("If you need actual output for non-optimal solut"
1.1057 + "ion, use --nopresol\n");
1.1058 + }
1.1059 + }
1.1060 + else
1.1061 + glp_exact(csa->prob, &csa->smcp);
1.1062 + }
1.1063 + else if (csa->solution == SOL_INTERIOR)
1.1064 + glp_interior(csa->prob, &csa->iptcp);
1.1065 + else if (csa->solution == SOL_INTEGER)
1.1066 + { if (!csa->iocp.presolve)
1.1067 + { glp_set_bfcp(csa->prob, &csa->bfcp);
1.1068 + glp_simplex(csa->prob, &csa->smcp);
1.1069 + }
1.1070 +#if 0
1.1071 + csa->iocp.msg_lev = GLP_MSG_DBG;
1.1072 + csa->iocp.pp_tech = GLP_PP_NONE;
1.1073 +#endif
1.1074 + glp_intopt(csa->prob, &csa->iocp);
1.1075 + }
1.1076 + else
1.1077 + xassert(csa != csa);
1.1078 + /*--------------------------------------------------------------*/
1.1079 + /* display statistics */
1.1080 + xprintf("Time used: %.1f secs\n", xdifftime(xtime(), start));
1.1081 + { glp_long tpeak;
1.1082 + char buf[50];
1.1083 + glp_mem_usage(NULL, NULL, NULL, &tpeak);
1.1084 + xprintf("Memory used: %.1f Mb (%s bytes)\n",
1.1085 + xltod(tpeak) / 1048576.0, xltoa(tpeak, buf));
1.1086 + }
1.1087 + /*--------------------------------------------------------------*/
1.1088 +skip: /* postsolve the model, if necessary */
1.1089 + if (csa->tran != NULL)
1.1090 + { if (csa->solution == SOL_BASIC)
1.1091 + ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_SOL);
1.1092 + else if (csa->solution == SOL_INTERIOR)
1.1093 + ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_IPT);
1.1094 + else if (csa->solution == SOL_INTEGER)
1.1095 + ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_MIP);
1.1096 + else
1.1097 + xassert(csa != csa);
1.1098 + if (ret != 0)
1.1099 + { xprintf("Model postsolving error\n");
1.1100 + ret = EXIT_FAILURE;
1.1101 + goto done;
1.1102 + }
1.1103 + }
1.1104 + /*--------------------------------------------------------------*/
1.1105 + /* write problem solution in printable format, if required */
1.1106 + if (csa->out_sol != NULL)
1.1107 + { if (csa->solution == SOL_BASIC)
1.1108 + ret = lpx_print_sol(csa->prob, csa->out_sol);
1.1109 + else if (csa->solution == SOL_INTERIOR)
1.1110 + ret = lpx_print_ips(csa->prob, csa->out_sol);
1.1111 + else if (csa->solution == SOL_INTEGER)
1.1112 + ret = lpx_print_mip(csa->prob, csa->out_sol);
1.1113 + else
1.1114 + xassert(csa != csa);
1.1115 + if (ret != 0)
1.1116 + { xprintf("Unable to write problem solution\n");
1.1117 + ret = EXIT_FAILURE;
1.1118 + goto done;
1.1119 + }
1.1120 + }
1.1121 + /* write problem solution in printable format, if required */
1.1122 + if (csa->out_res != NULL)
1.1123 + { if (csa->solution == SOL_BASIC)
1.1124 + ret = glp_write_sol(csa->prob, csa->out_res);
1.1125 + else if (csa->solution == SOL_INTERIOR)
1.1126 + ret = glp_write_ipt(csa->prob, csa->out_res);
1.1127 + else if (csa->solution == SOL_INTEGER)
1.1128 + ret = glp_write_mip(csa->prob, csa->out_res);
1.1129 + else
1.1130 + xassert(csa != csa);
1.1131 + if (ret != 0)
1.1132 + { xprintf("Unable to write problem solution\n");
1.1133 + ret = EXIT_FAILURE;
1.1134 + goto done;
1.1135 + }
1.1136 + }
1.1137 + /* write sensitivity analysis report, if required */
1.1138 + if (csa->out_ranges != NULL)
1.1139 + { if (csa->solution == SOL_BASIC)
1.1140 + { if (glp_get_status(csa->prob) == GLP_OPT)
1.1141 + { if (glp_bf_exists(csa->prob))
1.1142 +ranges: { ret = glp_print_ranges(csa->prob, 0, NULL, 0,
1.1143 + csa->out_ranges);
1.1144 + if (ret != 0)
1.1145 + { xprintf("Unable to write sensitivity analysis repo"
1.1146 + "rt\n");
1.1147 + ret = EXIT_FAILURE;
1.1148 + goto done;
1.1149 + }
1.1150 + }
1.1151 + else
1.1152 + { ret = glp_factorize(csa->prob);
1.1153 + if (ret == 0) goto ranges;
1.1154 + xprintf("Cannot produce sensitivity analysis report d"
1.1155 + "ue to error in basis factorization (glp_factorize"
1.1156 + " returned %d); try --nopresol\n", ret);
1.1157 + }
1.1158 + }
1.1159 + else
1.1160 + xprintf("Cannot produce sensitivity analysis report for "
1.1161 + "non-optimal basic solution\n");
1.1162 + }
1.1163 + else
1.1164 + xprintf("Cannot produce sensitivity analysis report for int"
1.1165 + "erior-point or MIP solution\n");
1.1166 + }
1.1167 + /*--------------------------------------------------------------*/
1.1168 + /* all seems to be ok */
1.1169 + ret = EXIT_SUCCESS;
1.1170 + /*--------------------------------------------------------------*/
1.1171 +done: /* delete the LP/MIP problem object */
1.1172 + if (csa->prob != NULL)
1.1173 + glp_delete_prob(csa->prob);
1.1174 + /* free the translator workspace, if necessary */
1.1175 + if (csa->tran != NULL)
1.1176 + glp_mpl_free_wksp(csa->tran);
1.1177 + /* delete the network problem object, if necessary */
1.1178 + if (csa->graph != NULL)
1.1179 + glp_delete_graph(csa->graph);
1.1180 + xassert(gmp_pool_count() == 0);
1.1181 + gmp_free_mem();
1.1182 + /* close log file, if necessary */
1.1183 + if (csa->log_file != NULL) glp_close_tee();
1.1184 + /* check that no memory blocks are still allocated */
1.1185 + { int count;
1.1186 + glp_long total;
1.1187 + glp_mem_usage(&count, NULL, &total, NULL);
1.1188 + if (count != 0)
1.1189 + xerror("Error: %d memory block(s) were lost\n", count);
1.1190 + xassert(count == 0);
1.1191 + xassert(total.lo == 0 && total.hi == 0);
1.1192 + }
1.1193 + /* free the GLPK environment */
1.1194 + glp_free_env();
1.1195 + /* return to the control program */
1.1196 + return ret;
1.1197 +}
1.1198 +
1.1199 +/* eof */