alpar@9: /* glpapi21.c (stand-alone LP/MIP solver) */ alpar@9: alpar@9: /*********************************************************************** alpar@9: * This code is part of GLPK (GNU Linear Programming Kit). alpar@9: * alpar@9: * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, alpar@9: * 2009, 2010, 2011 Andrew Makhorin, Department for Applied Informatics, alpar@9: * Moscow Aviation Institute, Moscow, Russia. All rights reserved. alpar@9: * E-mail: . alpar@9: * alpar@9: * GLPK is free software: you can redistribute it and/or modify it alpar@9: * under the terms of the GNU General Public License as published by alpar@9: * the Free Software Foundation, either version 3 of the License, or alpar@9: * (at your option) any later version. alpar@9: * alpar@9: * GLPK is distributed in the hope that it will be useful, but WITHOUT alpar@9: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY alpar@9: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public alpar@9: * License for more details. alpar@9: * alpar@9: * You should have received a copy of the GNU General Public License alpar@9: * along with GLPK. If not, see . alpar@9: ***********************************************************************/ alpar@9: alpar@9: #include "glpapi.h" alpar@9: #include "glpgmp.h" alpar@9: alpar@9: struct csa alpar@9: { /* common storage area */ alpar@9: glp_prob *prob; alpar@9: /* LP/MIP problem object */ alpar@9: glp_bfcp bfcp; alpar@9: /* basis factorization control parameters */ alpar@9: glp_smcp smcp; alpar@9: /* simplex method control parameters */ alpar@9: glp_iptcp iptcp; alpar@9: /* interior-point method control parameters */ alpar@9: glp_iocp iocp; alpar@9: /* integer optimizer control parameters */ alpar@9: glp_tran *tran; alpar@9: /* model translator workspace */ alpar@9: glp_graph *graph; alpar@9: /* network problem object */ alpar@9: int format; alpar@9: /* problem file format: */ alpar@9: #define FMT_MPS_DECK 1 /* fixed MPS */ alpar@9: #define FMT_MPS_FILE 2 /* free MPS */ alpar@9: #define FMT_LP 3 /* CPLEX LP */ alpar@9: #define FMT_GLP 4 /* GLPK LP/MIP */ alpar@9: #define FMT_MATHPROG 5 /* MathProg */ alpar@9: #define FMT_MIN_COST 6 /* DIMACS min-cost flow */ alpar@9: #define FMT_MAX_FLOW 7 /* DIMACS maximum flow */ alpar@9: #if 1 /* 06/VIII-2011 */ alpar@9: #define FMT_CNF 8 /* DIMACS CNF-SAT */ alpar@9: #endif alpar@9: const char *in_file; alpar@9: /* name of input problem file */ alpar@9: #define DATA_MAX 10 alpar@9: /* maximal number of input data files */ alpar@9: int ndf; alpar@9: /* number of input data files specified */ alpar@9: const char *in_data[1+DATA_MAX]; alpar@9: /* name(s) of input data file(s) */ alpar@9: const char *out_dpy; alpar@9: /* name of output file to send display output; NULL means the alpar@9: display output is sent to the terminal */ alpar@9: int seed; alpar@9: /* seed value to be passed to the MathProg translator; initially alpar@9: set to 1; 0x80000000 means the value is omitted */ alpar@9: int solution; alpar@9: /* solution type flag: */ alpar@9: #define SOL_BASIC 1 /* basic */ alpar@9: #define SOL_INTERIOR 2 /* interior-point */ alpar@9: #define SOL_INTEGER 3 /* mixed integer */ alpar@9: const char *in_res; alpar@9: /* name of input solution file in raw format */ alpar@9: int dir; alpar@9: /* optimization direction flag: alpar@9: 0 - not specified alpar@9: GLP_MIN - minimization alpar@9: GLP_MAX - maximization */ alpar@9: int scale; alpar@9: /* automatic problem scaling flag */ alpar@9: const char *out_sol; alpar@9: /* name of output solution file in printable format */ alpar@9: const char *out_res; alpar@9: /* name of output solution file in raw format */ alpar@9: const char *out_ranges; alpar@9: /* name of output file to write sensitivity analysis report */ alpar@9: int check; alpar@9: /* input data checking flag; no solution is performed */ alpar@9: const char *new_name; alpar@9: /* new name to be assigned to the problem */ alpar@9: const char *out_mps; alpar@9: /* name of output problem file in fixed MPS format */ alpar@9: const char *out_freemps; alpar@9: /* name of output problem file in free MPS format */ alpar@9: const char *out_cpxlp; alpar@9: /* name of output problem file in CPLEX LP format */ alpar@9: const char *out_glp; alpar@9: /* name of output problem file in GLPK format */ alpar@9: const char *out_pb; alpar@9: /* name of output problem file in OPB format */ alpar@9: const char *out_npb; alpar@9: /* name of output problem file in normalized OPB format */ alpar@9: #if 1 /* 06/VIII-2011 */ alpar@9: const char *out_cnf; alpar@9: /* name of output problem file in DIMACS CNF-SAT format */ alpar@9: #endif alpar@9: const char *log_file; alpar@9: /* name of output file to hardcopy terminal output */ alpar@9: int crash; alpar@9: /* initial basis option: */ alpar@9: #define USE_STD_BASIS 1 /* use standard basis */ alpar@9: #define USE_ADV_BASIS 2 /* use advanced basis */ alpar@9: #define USE_CPX_BASIS 3 /* use Bixby's basis */ alpar@9: #define USE_INI_BASIS 4 /* use initial basis from ini_file */ alpar@9: const char *ini_file; alpar@9: /* name of input file containing initial basis */ alpar@9: int exact; alpar@9: /* flag to use glp_exact rather than glp_simplex */ alpar@9: int xcheck; alpar@9: /* flag to check final basis with glp_exact */ alpar@9: int nomip; alpar@9: /* flag to consider MIP as pure LP */ alpar@9: #if 1 /* 15/VIII-2011 */ alpar@9: int minisat; alpar@9: /* option to solve feasibility problem with MiniSat solver */ alpar@9: int use_bnd; alpar@9: /* option to bound objective function */ alpar@9: int obj_bnd; alpar@9: /* upper (minization) or lower (maximization) objective bound */ alpar@9: #endif alpar@9: }; alpar@9: alpar@9: static void print_help(const char *my_name) alpar@9: { /* print help information */ alpar@9: xprintf("Usage: %s [options...] filename\n", my_name); alpar@9: xprintf("\n"); alpar@9: xprintf("General options:\n"); alpar@9: xprintf(" --mps read LP/MIP problem in fixed MPS fo" alpar@9: "rmat\n"); alpar@9: xprintf(" --freemps read LP/MIP problem in free MPS for" alpar@9: "mat (default)\n"); alpar@9: xprintf(" --lp read LP/MIP problem in CPLEX LP for" alpar@9: "mat\n"); alpar@9: xprintf(" --glp read LP/MIP problem in GLPK format " alpar@9: "\n"); alpar@9: xprintf(" --math read LP/MIP model written in GNU Ma" alpar@9: "thProg modeling\n"); alpar@9: xprintf(" language\n"); alpar@9: xprintf(" -m filename, --model filename\n"); alpar@9: xprintf(" read model section and optional dat" alpar@9: "a section from\n"); alpar@9: xprintf(" filename (same as --math)\n"); alpar@9: xprintf(" -d filename, --data filename\n"); alpar@9: xprintf(" read data section from filename (fo" alpar@9: "r --math only);\n"); alpar@9: xprintf(" if model file also has data section" alpar@9: ", it is ignored\n"); alpar@9: xprintf(" -y filename, --display filename\n"); alpar@9: xprintf(" send display output to filename (fo" alpar@9: "r --math only);\n"); alpar@9: xprintf(" by default the output is sent to te" alpar@9: "rminal\n"); alpar@9: xprintf(" --seed value initialize pseudo-random number gen" alpar@9: "erator used in\n"); alpar@9: xprintf(" MathProg model with specified seed " alpar@9: "(any integer);\n"); alpar@9: xprintf(" if seed value is ?, some random see" alpar@9: "d will be used\n"); alpar@9: xprintf(" --mincost read min-cost flow problem in DIMAC" alpar@9: "S format\n"); alpar@9: xprintf(" --maxflow read maximum flow problem in DIMACS" alpar@9: " format\n"); alpar@9: #if 1 /* 06/VIII-2011 */ alpar@9: xprintf(" --cnf read CNF-SAT problem in DIMACS form" alpar@9: "at\n"); alpar@9: #endif alpar@9: xprintf(" --simplex use simplex method (default)\n"); alpar@9: xprintf(" --interior use interior point method (LP only)" alpar@9: "\n"); alpar@9: xprintf(" -r filename, --read filename\n"); alpar@9: xprintf(" read solution from filename rather " alpar@9: "to find it with\n"); alpar@9: xprintf(" the solver\n"); alpar@9: xprintf(" --min minimization\n"); alpar@9: xprintf(" --max maximization\n"); alpar@9: xprintf(" --scale scale problem (default)\n"); alpar@9: xprintf(" --noscale do not scale problem\n"); alpar@9: xprintf(" -o filename, --output filename\n"); alpar@9: xprintf(" write solution to filename in print" alpar@9: "able format\n"); alpar@9: xprintf(" -w filename, --write filename\n"); alpar@9: xprintf(" write solution to filename in plain" alpar@9: " text format\n"); alpar@9: xprintf(" --ranges filename\n"); alpar@9: xprintf(" write sensitivity analysis report t" alpar@9: "o filename in\n"); alpar@9: xprintf(" printable format (simplex only)\n"); alpar@9: xprintf(" --tmlim nnn limit solution time to nnn seconds " alpar@9: "\n"); alpar@9: xprintf(" --memlim nnn limit available memory to nnn megab" alpar@9: "ytes\n"); alpar@9: xprintf(" --check do not solve problem, check input d" alpar@9: "ata only\n"); alpar@9: xprintf(" --name probname change problem name to probname\n"); alpar@9: xprintf(" --wmps filename write problem to filename in fixed " alpar@9: "MPS format\n"); alpar@9: xprintf(" --wfreemps filename\n"); alpar@9: xprintf(" write problem to filename in free M" alpar@9: "PS format\n"); alpar@9: xprintf(" --wlp filename write problem to filename in CPLEX " alpar@9: "LP format\n"); alpar@9: xprintf(" --wglp filename write problem to filename in GLPK f" alpar@9: "ormat\n"); alpar@9: #if 0 alpar@9: xprintf(" --wpb filename write problem to filename in OPB fo" alpar@9: "rmat\n"); alpar@9: xprintf(" --wnpb filename write problem to filename in normal" alpar@9: "ized OPB format\n"); alpar@9: #endif alpar@9: #if 1 /* 06/VIII-2011 */ alpar@9: xprintf(" --wcnf filename write problem to filename in DIMACS" alpar@9: " CNF-SAT format\n"); alpar@9: #endif alpar@9: xprintf(" --log filename write copy of terminal output to fi" alpar@9: "lename\n"); alpar@9: xprintf(" -h, --help display this help information and e" alpar@9: "xit\n"); alpar@9: xprintf(" -v, --version display program version and exit\n") alpar@9: ; alpar@9: xprintf("\n"); alpar@9: xprintf("LP basis factorization options:\n"); alpar@9: xprintf(" --luf LU + Forrest-Tomlin update\n"); alpar@9: xprintf(" (faster, less stable; default)\n"); alpar@9: xprintf(" --cbg LU + Schur complement + Bartels-Gol" alpar@9: "ub update\n"); alpar@9: xprintf(" (slower, more stable)\n"); alpar@9: xprintf(" --cgr LU + Schur complement + Givens rota" alpar@9: "tion update\n"); alpar@9: xprintf(" (slower, more stable)\n"); alpar@9: xprintf("\n"); alpar@9: xprintf("Options specific to simplex solver:\n"); alpar@9: xprintf(" --primal use primal simplex (default)\n"); alpar@9: xprintf(" --dual use dual simplex\n"); alpar@9: xprintf(" --std use standard initial basis of all s" alpar@9: "lacks\n"); alpar@9: xprintf(" --adv use advanced initial basis (default" alpar@9: ")\n"); alpar@9: xprintf(" --bib use Bixby's initial basis\n"); alpar@9: xprintf(" --ini filename use as initial basis previously sav" alpar@9: "ed with -w\n"); alpar@9: xprintf(" (disables LP presolver)\n"); alpar@9: xprintf(" --steep use steepest edge technique (defaul" alpar@9: "t)\n"); alpar@9: xprintf(" --nosteep use standard \"textbook\" pricing\n" alpar@9: ); alpar@9: xprintf(" --relax use Harris' two-pass ratio test (de" alpar@9: "fault)\n"); alpar@9: xprintf(" --norelax use standard \"textbook\" ratio tes" alpar@9: "t\n"); alpar@9: xprintf(" --presol use presolver (default; assumes --s" alpar@9: "cale and --adv)\n"); alpar@9: xprintf(" --nopresol do not use presolver\n"); alpar@9: xprintf(" --exact use simplex method based on exact a" alpar@9: "rithmetic\n"); alpar@9: xprintf(" --xcheck check final basis using exact arith" alpar@9: "metic\n"); alpar@9: xprintf("\n"); alpar@9: xprintf("Options specific to interior-point solver:\n"); alpar@9: xprintf(" --nord use natural (original) ordering\n"); alpar@9: xprintf(" --qmd use quotient minimum degree orderin" alpar@9: "g\n"); alpar@9: xprintf(" --amd use approximate minimum degree orde" alpar@9: "ring (default)\n"); alpar@9: xprintf(" --symamd use approximate minimum degree orde" alpar@9: "ring\n"); alpar@9: xprintf("\n"); alpar@9: xprintf("Options specific to MIP solver:\n"); alpar@9: xprintf(" --nomip consider all integer variables as c" alpar@9: "ontinuous\n"); alpar@9: xprintf(" (allows solving MIP as pure LP)\n"); alpar@9: xprintf(" --first branch on first integer variable\n") alpar@9: ; alpar@9: xprintf(" --last branch on last integer variable\n"); alpar@9: xprintf(" --mostf branch on most fractional variable " alpar@9: "\n"); alpar@9: xprintf(" --drtom branch using heuristic by Driebeck " alpar@9: "and Tomlin\n"); alpar@9: xprintf(" (default)\n"); alpar@9: xprintf(" --pcost branch using hybrid pseudocost heur" alpar@9: "istic (may be\n"); alpar@9: xprintf(" useful for hard instances)\n"); alpar@9: xprintf(" --dfs backtrack using depth first search " alpar@9: "\n"); alpar@9: xprintf(" --bfs backtrack using breadth first searc" alpar@9: "h\n"); alpar@9: xprintf(" --bestp backtrack using the best projection" alpar@9: " heuristic\n"); alpar@9: xprintf(" --bestb backtrack using node with best loca" alpar@9: "l bound\n"); alpar@9: xprintf(" (default)\n"); alpar@9: xprintf(" --intopt use MIP presolver (default)\n"); alpar@9: xprintf(" --nointopt do not use MIP presolver\n"); alpar@9: xprintf(" --binarize replace general integer variables b" alpar@9: "y binary ones\n"); alpar@9: xprintf(" (assumes --intopt)\n"); alpar@9: xprintf(" --fpump apply feasibility pump heuristic\n") alpar@9: ; alpar@9: xprintf(" --gomory generate Gomory's mixed integer cut" alpar@9: "s\n"); alpar@9: xprintf(" --mir generate MIR (mixed integer roundin" alpar@9: "g) cuts\n"); alpar@9: xprintf(" --cover generate mixed cover cuts\n"); alpar@9: xprintf(" --clique generate clique cuts\n"); alpar@9: xprintf(" --cuts generate all cuts above\n"); alpar@9: xprintf(" --mipgap tol set relative mip gap tolerance to t" alpar@9: "ol\n"); alpar@9: #if 1 /* 15/VIII-2011 */ alpar@9: xprintf(" --minisat translate integer feasibility probl" alpar@9: "em to CNF-SAT\n"); alpar@9: xprintf(" and solve it with MiniSat solver\n") alpar@9: ; alpar@9: xprintf(" --objbnd bound add inequality obj <= bound (minimi" alpar@9: "zation) or\n"); alpar@9: xprintf(" obj >= bound (maximization) to inte" alpar@9: "ger feasibility\n"); alpar@9: xprintf(" problem (assumes --minisat)\n"); alpar@9: #endif alpar@9: xprintf("\n"); alpar@9: xprintf("For description of the MPS and CPLEX LP formats see Refe" alpar@9: "rence Manual.\n"); alpar@9: xprintf("For description of the modeling language see \"GLPK: Mod" alpar@9: "eling Language\n"); alpar@9: xprintf("GNU MathProg\". Both documents are included in the GLPK " alpar@9: "distribution.\n"); alpar@9: xprintf("\n"); alpar@9: xprintf("See GLPK web page at .\n"); alpar@9: xprintf("\n"); alpar@9: xprintf("Please report bugs to .\n"); alpar@9: return; alpar@9: } alpar@9: alpar@9: static void print_version(int briefly) alpar@9: { /* print version information */ alpar@9: xprintf("GLPSOL: GLPK LP/MIP Solver, v%s\n", glp_version()); alpar@9: if (briefly) goto done; alpar@9: xprintf("\n"); alpar@9: xprintf("Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, " alpar@9: "2007, 2008,\n"); alpar@9: xprintf("2009, 2010, 2011 Andrew Makhorin, Department for Applied" alpar@9: " Informatics,\n"); alpar@9: xprintf("Moscow Aviation Institute, Moscow, Russia. All rights re" alpar@9: "served.\n"); alpar@9: xprintf("\n"); alpar@9: xprintf("This program has ABSOLUTELY NO WARRANTY.\n"); alpar@9: xprintf("\n"); alpar@9: xprintf("This program is free software; you may re-distribute it " alpar@9: "under the terms\n"); alpar@9: xprintf("of the GNU General Public License version 3 or later.\n") alpar@9: ; alpar@9: done: return; alpar@9: } alpar@9: alpar@9: static int parse_cmdline(struct csa *csa, int argc, const char *argv[]) alpar@9: { /* parse command-line parameters */ alpar@9: int k; alpar@9: #define p(str) (strcmp(argv[k], str) == 0) alpar@9: for (k = 1; k < argc; k++) alpar@9: { if (p("--mps")) alpar@9: csa->format = FMT_MPS_DECK; alpar@9: else if (p("--freemps")) alpar@9: csa->format = FMT_MPS_FILE; alpar@9: else if (p("--lp") || p("--cpxlp")) alpar@9: csa->format = FMT_LP; alpar@9: else if (p("--glp")) alpar@9: csa->format = FMT_GLP; alpar@9: else if (p("--math") || p("-m") || p("--model")) alpar@9: csa->format = FMT_MATHPROG; alpar@9: else if (p("-d") || p("--data")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No input data file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->ndf == DATA_MAX) alpar@9: { xprintf("Too many input data files\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->in_data[++(csa->ndf)] = argv[k]; alpar@9: } alpar@9: else if (p("-y") || p("--display")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No display output file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->out_dpy != NULL) alpar@9: { xprintf("Only one display output file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->out_dpy = argv[k]; alpar@9: } alpar@9: else if (p("--seed")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || alpar@9: argv[k][0] == '-' && !isdigit((unsigned char)argv[k][1])) alpar@9: { xprintf("No seed value specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (strcmp(argv[k], "?") == 0) alpar@9: csa->seed = 0x80000000; alpar@9: else if (str2int(argv[k], &csa->seed)) alpar@9: { xprintf("Invalid seed value `%s'\n", argv[k]); alpar@9: return 1; alpar@9: } alpar@9: } alpar@9: else if (p("--mincost")) alpar@9: csa->format = FMT_MIN_COST; alpar@9: else if (p("--maxflow")) alpar@9: csa->format = FMT_MAX_FLOW; alpar@9: #if 1 /* 06/VIII-2011 */ alpar@9: else if (p("--cnf")) alpar@9: csa->format = FMT_CNF; alpar@9: #endif alpar@9: else if (p("--simplex")) alpar@9: csa->solution = SOL_BASIC; alpar@9: else if (p("--interior")) alpar@9: csa->solution = SOL_INTERIOR; alpar@9: #if 1 /* 28/V-2010 */ alpar@9: else if (p("--alien")) alpar@9: csa->iocp.alien = GLP_ON; alpar@9: #endif alpar@9: else if (p("-r") || p("--read")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No input solution file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->in_res != NULL) alpar@9: { xprintf("Only one input solution file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->in_res = argv[k]; alpar@9: } alpar@9: else if (p("--min")) alpar@9: csa->dir = GLP_MIN; alpar@9: else if (p("--max")) alpar@9: csa->dir = GLP_MAX; alpar@9: else if (p("--scale")) alpar@9: csa->scale = 1; alpar@9: else if (p("--noscale")) alpar@9: csa->scale = 0; alpar@9: else if (p("-o") || p("--output")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No output solution file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->out_sol != NULL) alpar@9: { xprintf("Only one output solution file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->out_sol = argv[k]; alpar@9: } alpar@9: else if (p("-w") || p("--write")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No output solution file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->out_res != NULL) alpar@9: { xprintf("Only one output solution file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->out_res = argv[k]; alpar@9: } alpar@9: else if (p("--ranges") || p("--bounds")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No output file specified to write sensitivity a" alpar@9: "nalysis report\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->out_ranges != NULL) alpar@9: { xprintf("Only one output file allowed to write sensitivi" alpar@9: "ty analysis report\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->out_ranges = argv[k]; alpar@9: } alpar@9: else if (p("--tmlim")) alpar@9: { int tm_lim; alpar@9: k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No time limit specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (str2int(argv[k], &tm_lim) || tm_lim < 0) alpar@9: { xprintf("Invalid time limit `%s'\n", argv[k]); alpar@9: return 1; alpar@9: } alpar@9: if (tm_lim <= INT_MAX / 1000) alpar@9: csa->smcp.tm_lim = csa->iocp.tm_lim = 1000 * tm_lim; alpar@9: else alpar@9: csa->smcp.tm_lim = csa->iocp.tm_lim = INT_MAX; alpar@9: } alpar@9: else if (p("--memlim")) alpar@9: { int mem_lim; alpar@9: k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No memory limit specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (str2int(argv[k], &mem_lim) || mem_lim < 1) alpar@9: { xprintf("Invalid memory limit `%s'\n", argv[k]); alpar@9: return 1; alpar@9: } alpar@9: glp_mem_limit(mem_lim); alpar@9: } alpar@9: else if (p("--check")) alpar@9: csa->check = 1; alpar@9: else if (p("--name")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No problem name specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->new_name != NULL) alpar@9: { xprintf("Only one problem name allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->new_name = argv[k]; alpar@9: } alpar@9: else if (p("--wmps")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No fixed MPS output file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->out_mps != NULL) alpar@9: { xprintf("Only one fixed MPS output file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->out_mps = argv[k]; alpar@9: } alpar@9: else if (p("--wfreemps")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No free MPS output file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->out_freemps != NULL) alpar@9: { xprintf("Only one free MPS output file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->out_freemps = argv[k]; alpar@9: } alpar@9: else if (p("--wlp") || p("--wcpxlp") || p("--wlpt")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No CPLEX LP output file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->out_cpxlp != NULL) alpar@9: { xprintf("Only one CPLEX LP output file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->out_cpxlp = argv[k]; alpar@9: } alpar@9: else if (p("--wglp")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No GLPK LP/MIP output file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->out_glp != NULL) alpar@9: { xprintf("Only one GLPK LP/MIP output file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->out_glp = argv[k]; alpar@9: } alpar@9: else if (p("--wpb")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No problem output file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->out_pb != NULL) alpar@9: { xprintf("Only one OPB output file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->out_pb = argv[k]; alpar@9: } alpar@9: else if (p("--wnpb")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No problem output file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->out_npb != NULL) alpar@9: { xprintf("Only one normalized OPB output file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->out_npb = argv[k]; alpar@9: } alpar@9: #if 1 /* 06/VIII-2011 */ alpar@9: else if (p("--wcnf")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No problem output file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->out_cnf != NULL) alpar@9: { xprintf("Only one output DIMACS CNF-SAT file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->out_cnf = argv[k]; alpar@9: } alpar@9: #endif alpar@9: else if (p("--log")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No log file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->log_file != NULL) alpar@9: { xprintf("Only one log file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->log_file = argv[k]; alpar@9: } alpar@9: else if (p("-h") || p("--help")) alpar@9: { print_help(argv[0]); alpar@9: return -1; alpar@9: } alpar@9: else if (p("-v") || p("--version")) alpar@9: { print_version(0); alpar@9: return -1; alpar@9: } alpar@9: else if (p("--luf")) alpar@9: csa->bfcp.type = GLP_BF_FT; alpar@9: else if (p("--cbg")) alpar@9: csa->bfcp.type = GLP_BF_BG; alpar@9: else if (p("--cgr")) alpar@9: csa->bfcp.type = GLP_BF_GR; alpar@9: else if (p("--primal")) alpar@9: csa->smcp.meth = GLP_PRIMAL; alpar@9: else if (p("--dual")) alpar@9: csa->smcp.meth = GLP_DUAL; alpar@9: else if (p("--std")) alpar@9: csa->crash = USE_STD_BASIS; alpar@9: else if (p("--adv")) alpar@9: csa->crash = USE_ADV_BASIS; alpar@9: else if (p("--bib")) alpar@9: csa->crash = USE_CPX_BASIS; alpar@9: else if (p("--ini")) alpar@9: { csa->crash = USE_INI_BASIS; alpar@9: csa->smcp.presolve = GLP_OFF; alpar@9: k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No initial basis file specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (csa->ini_file != NULL) alpar@9: { xprintf("Only one initial basis file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->ini_file = argv[k]; alpar@9: } alpar@9: else if (p("--steep")) alpar@9: csa->smcp.pricing = GLP_PT_PSE; alpar@9: else if (p("--nosteep")) alpar@9: csa->smcp.pricing = GLP_PT_STD; alpar@9: else if (p("--relax")) alpar@9: csa->smcp.r_test = GLP_RT_HAR; alpar@9: else if (p("--norelax")) alpar@9: csa->smcp.r_test = GLP_RT_STD; alpar@9: else if (p("--presol")) alpar@9: csa->smcp.presolve = GLP_ON; alpar@9: else if (p("--nopresol")) alpar@9: csa->smcp.presolve = GLP_OFF; alpar@9: else if (p("--exact")) alpar@9: csa->exact = 1; alpar@9: else if (p("--xcheck")) alpar@9: csa->xcheck = 1; alpar@9: else if (p("--nord")) alpar@9: csa->iptcp.ord_alg = GLP_ORD_NONE; alpar@9: else if (p("--qmd")) alpar@9: csa->iptcp.ord_alg = GLP_ORD_QMD; alpar@9: else if (p("--amd")) alpar@9: csa->iptcp.ord_alg = GLP_ORD_AMD; alpar@9: else if (p("--symamd")) alpar@9: csa->iptcp.ord_alg = GLP_ORD_SYMAMD; alpar@9: else if (p("--nomip")) alpar@9: csa->nomip = 1; alpar@9: else if (p("--first")) alpar@9: csa->iocp.br_tech = GLP_BR_FFV; alpar@9: else if (p("--last")) alpar@9: csa->iocp.br_tech = GLP_BR_LFV; alpar@9: else if (p("--drtom")) alpar@9: csa->iocp.br_tech = GLP_BR_DTH; alpar@9: else if (p("--mostf")) alpar@9: csa->iocp.br_tech = GLP_BR_MFV; alpar@9: else if (p("--pcost")) alpar@9: csa->iocp.br_tech = GLP_BR_PCH; alpar@9: else if (p("--dfs")) alpar@9: csa->iocp.bt_tech = GLP_BT_DFS; alpar@9: else if (p("--bfs")) alpar@9: csa->iocp.bt_tech = GLP_BT_BFS; alpar@9: else if (p("--bestp")) alpar@9: csa->iocp.bt_tech = GLP_BT_BPH; alpar@9: else if (p("--bestb")) alpar@9: csa->iocp.bt_tech = GLP_BT_BLB; alpar@9: else if (p("--intopt")) alpar@9: csa->iocp.presolve = GLP_ON; alpar@9: else if (p("--nointopt")) alpar@9: csa->iocp.presolve = GLP_OFF; alpar@9: else if (p("--binarize")) alpar@9: csa->iocp.presolve = csa->iocp.binarize = GLP_ON; alpar@9: else if (p("--fpump")) alpar@9: csa->iocp.fp_heur = GLP_ON; alpar@9: else if (p("--gomory")) alpar@9: csa->iocp.gmi_cuts = GLP_ON; alpar@9: else if (p("--mir")) alpar@9: csa->iocp.mir_cuts = GLP_ON; alpar@9: else if (p("--cover")) alpar@9: csa->iocp.cov_cuts = GLP_ON; alpar@9: else if (p("--clique")) alpar@9: csa->iocp.clq_cuts = GLP_ON; alpar@9: else if (p("--cuts")) alpar@9: csa->iocp.gmi_cuts = csa->iocp.mir_cuts = alpar@9: csa->iocp.cov_cuts = csa->iocp.clq_cuts = GLP_ON; alpar@9: else if (p("--mipgap")) alpar@9: { double mip_gap; alpar@9: k++; alpar@9: if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') alpar@9: { xprintf("No relative gap tolerance specified\n"); alpar@9: return 1; alpar@9: } alpar@9: if (str2num(argv[k], &mip_gap) || mip_gap < 0.0) alpar@9: { xprintf("Invalid relative mip gap tolerance `%s'\n", alpar@9: argv[k]); alpar@9: return 1; alpar@9: } alpar@9: csa->iocp.mip_gap = mip_gap; alpar@9: } alpar@9: #if 1 /* 15/VIII-2011 */ alpar@9: else if (p("--minisat")) alpar@9: csa->minisat = 1; alpar@9: else if (p("--objbnd")) alpar@9: { k++; alpar@9: if (k == argc || argv[k][0] == '\0' || alpar@9: argv[k][0] == '-' && !isdigit((unsigned char)argv[k][1])) alpar@9: { xprintf("No objective bound specified\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->minisat = 1; alpar@9: csa->use_bnd = 1; alpar@9: if (str2int(argv[k], &csa->obj_bnd)) alpar@9: { xprintf("Invalid objective bound `%s' (should be integer" alpar@9: " value)\n", argv[k]); alpar@9: return 1; alpar@9: } alpar@9: } alpar@9: #endif alpar@9: else if (argv[k][0] == '-' || alpar@9: (argv[k][0] == '-' && argv[k][1] == '-')) alpar@9: { xprintf("Invalid option `%s'; try %s --help\n", alpar@9: argv[k], argv[0]); alpar@9: return 1; alpar@9: } alpar@9: else alpar@9: { if (csa->in_file != NULL) alpar@9: { xprintf("Only one input problem file allowed\n"); alpar@9: return 1; alpar@9: } alpar@9: csa->in_file = argv[k]; alpar@9: } alpar@9: } alpar@9: #undef p alpar@9: return 0; alpar@9: } alpar@9: alpar@9: typedef struct { double rhs, pi; } v_data; alpar@9: typedef struct { double low, cap, cost, x; } a_data; alpar@9: alpar@9: int glp_main(int argc, const char *argv[]) alpar@9: { /* stand-alone LP/MIP solver */ alpar@9: struct csa _csa, *csa = &_csa; alpar@9: int ret; alpar@9: glp_long start; alpar@9: /* perform initialization */ alpar@9: csa->prob = glp_create_prob(); alpar@9: glp_get_bfcp(csa->prob, &csa->bfcp); alpar@9: glp_init_smcp(&csa->smcp); alpar@9: csa->smcp.presolve = GLP_ON; alpar@9: glp_init_iptcp(&csa->iptcp); alpar@9: glp_init_iocp(&csa->iocp); alpar@9: csa->iocp.presolve = GLP_ON; alpar@9: csa->tran = NULL; alpar@9: csa->graph = NULL; alpar@9: csa->format = FMT_MPS_FILE; alpar@9: csa->in_file = NULL; alpar@9: csa->ndf = 0; alpar@9: csa->out_dpy = NULL; alpar@9: csa->seed = 1; alpar@9: csa->solution = SOL_BASIC; alpar@9: csa->in_res = NULL; alpar@9: csa->dir = 0; alpar@9: csa->scale = 1; alpar@9: csa->out_sol = NULL; alpar@9: csa->out_res = NULL; alpar@9: csa->out_ranges = NULL; alpar@9: csa->check = 0; alpar@9: csa->new_name = NULL; alpar@9: csa->out_mps = NULL; alpar@9: csa->out_freemps = NULL; alpar@9: csa->out_cpxlp = NULL; alpar@9: csa->out_glp = NULL; alpar@9: csa->out_pb = NULL; alpar@9: csa->out_npb = NULL; alpar@9: #if 1 /* 06/VIII-2011 */ alpar@9: csa->out_cnf = NULL; alpar@9: #endif alpar@9: csa->log_file = NULL; alpar@9: csa->crash = USE_ADV_BASIS; alpar@9: csa->ini_file = NULL; alpar@9: csa->exact = 0; alpar@9: csa->xcheck = 0; alpar@9: csa->nomip = 0; alpar@9: #if 1 /* 15/VIII-2011 */ alpar@9: csa->minisat = 0; alpar@9: csa->use_bnd = 0; alpar@9: csa->obj_bnd = 0; alpar@9: #endif alpar@9: /* parse command-line parameters */ alpar@9: ret = parse_cmdline(csa, argc, argv); alpar@9: if (ret < 0) alpar@9: { ret = EXIT_SUCCESS; alpar@9: goto done; alpar@9: } alpar@9: if (ret > 0) alpar@9: { ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* remove all output files specified in the command line */ alpar@9: if (csa->out_dpy != NULL) remove(csa->out_dpy); alpar@9: if (csa->out_sol != NULL) remove(csa->out_sol); alpar@9: if (csa->out_res != NULL) remove(csa->out_res); alpar@9: if (csa->out_ranges != NULL) remove(csa->out_ranges); alpar@9: if (csa->out_mps != NULL) remove(csa->out_mps); alpar@9: if (csa->out_freemps != NULL) remove(csa->out_freemps); alpar@9: if (csa->out_cpxlp != NULL) remove(csa->out_cpxlp); alpar@9: if (csa->out_glp != NULL) remove(csa->out_glp); alpar@9: if (csa->out_pb != NULL) remove(csa->out_pb); alpar@9: if (csa->out_npb != NULL) remove(csa->out_npb); alpar@9: #if 1 /* 06/VIII-2011 */ alpar@9: if (csa->out_cnf != NULL) remove(csa->out_cnf); alpar@9: #endif alpar@9: if (csa->log_file != NULL) remove(csa->log_file); alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* open log file, if required */ alpar@9: if (csa->log_file != NULL) alpar@9: { if (glp_open_tee(csa->log_file)) alpar@9: { xprintf("Unable to create log file\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* print version information */ alpar@9: print_version(1); alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* print parameters specified in the command line */ alpar@9: if (argc > 1) alpar@9: { int k, len = INT_MAX; alpar@9: xprintf("Parameter(s) specified in the command line:"); alpar@9: for (k = 1; k < argc; k++) alpar@9: { if (len > 72) alpar@9: xprintf("\n"), len = 0; alpar@9: xprintf(" %s", argv[k]); alpar@9: len += 1 + strlen(argv[k]); alpar@9: } alpar@9: xprintf("\n"); alpar@9: } alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* read problem data from the input file */ alpar@9: if (csa->in_file == NULL) alpar@9: { xprintf("No input problem file specified; try %s --help\n", alpar@9: argv[0]); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: if (csa->format == FMT_MPS_DECK) alpar@9: { ret = glp_read_mps(csa->prob, GLP_MPS_DECK, NULL, alpar@9: csa->in_file); alpar@9: if (ret != 0) alpar@9: err1: { xprintf("MPS file processing error\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: else if (csa->format == FMT_MPS_FILE) alpar@9: { ret = glp_read_mps(csa->prob, GLP_MPS_FILE, NULL, alpar@9: csa->in_file); alpar@9: if (ret != 0) goto err1; alpar@9: } alpar@9: else if (csa->format == FMT_LP) alpar@9: { ret = glp_read_lp(csa->prob, NULL, csa->in_file); alpar@9: if (ret != 0) alpar@9: { xprintf("CPLEX LP file processing error\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: else if (csa->format == FMT_GLP) alpar@9: { ret = glp_read_prob(csa->prob, 0, csa->in_file); alpar@9: if (ret != 0) alpar@9: { xprintf("GLPK LP/MIP file processing error\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: else if (csa->format == FMT_MATHPROG) alpar@9: { int k; alpar@9: /* allocate the translator workspace */ alpar@9: csa->tran = glp_mpl_alloc_wksp(); alpar@9: /* set seed value */ alpar@9: if (csa->seed == 0x80000000) alpar@9: { csa->seed = glp_time().lo; alpar@9: xprintf("Seed value %d will be used\n", csa->seed); alpar@9: } alpar@9: _glp_mpl_init_rand(csa->tran, csa->seed); alpar@9: /* read model section and optional data section */ alpar@9: if (glp_mpl_read_model(csa->tran, csa->in_file, csa->ndf > 0)) alpar@9: err2: { xprintf("MathProg model processing error\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: /* read optional data section(s), if necessary */ alpar@9: for (k = 1; k <= csa->ndf; k++) alpar@9: { if (glp_mpl_read_data(csa->tran, csa->in_data[k])) alpar@9: goto err2; alpar@9: } alpar@9: /* generate the model */ alpar@9: if (glp_mpl_generate(csa->tran, csa->out_dpy)) goto err2; alpar@9: /* build the problem instance from the model */ alpar@9: glp_mpl_build_prob(csa->tran, csa->prob); alpar@9: } alpar@9: else if (csa->format == FMT_MIN_COST) alpar@9: { csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data)); alpar@9: ret = glp_read_mincost(csa->graph, offsetof(v_data, rhs), alpar@9: offsetof(a_data, low), offsetof(a_data, cap), alpar@9: offsetof(a_data, cost), csa->in_file); alpar@9: if (ret != 0) alpar@9: { xprintf("DIMACS file processing error\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: glp_mincost_lp(csa->prob, csa->graph, GLP_ON, alpar@9: offsetof(v_data, rhs), offsetof(a_data, low), alpar@9: offsetof(a_data, cap), offsetof(a_data, cost)); alpar@9: glp_set_prob_name(csa->prob, csa->in_file); alpar@9: } alpar@9: else if (csa->format == FMT_MAX_FLOW) alpar@9: { int s, t; alpar@9: csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data)); alpar@9: ret = glp_read_maxflow(csa->graph, &s, &t, alpar@9: offsetof(a_data, cap), csa->in_file); alpar@9: if (ret != 0) alpar@9: { xprintf("DIMACS file processing error\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: glp_maxflow_lp(csa->prob, csa->graph, GLP_ON, s, t, alpar@9: offsetof(a_data, cap)); alpar@9: glp_set_prob_name(csa->prob, csa->in_file); alpar@9: } alpar@9: #if 1 /* 06/VIII-2011 */ alpar@9: else if (csa->format == FMT_CNF) alpar@9: { ret = glp_read_cnfsat(csa->prob, csa->in_file); alpar@9: if (ret != 0) alpar@9: { xprintf("DIMACS file processing error\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: glp_set_prob_name(csa->prob, csa->in_file); alpar@9: } alpar@9: #endif alpar@9: else alpar@9: xassert(csa != csa); alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* change problem name, if required */ alpar@9: if (csa->new_name != NULL) alpar@9: glp_set_prob_name(csa->prob, csa->new_name); alpar@9: /* change optimization direction, if required */ alpar@9: if (csa->dir != 0) alpar@9: glp_set_obj_dir(csa->prob, csa->dir); alpar@9: /* sort elements of the constraint matrix */ alpar@9: glp_sort_matrix(csa->prob); alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* write problem data in fixed MPS format, if required */ alpar@9: if (csa->out_mps != NULL) alpar@9: { ret = glp_write_mps(csa->prob, GLP_MPS_DECK, NULL, alpar@9: csa->out_mps); alpar@9: if (ret != 0) alpar@9: { xprintf("Unable to write problem in fixed MPS format\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: /* write problem data in free MPS format, if required */ alpar@9: if (csa->out_freemps != NULL) alpar@9: { ret = glp_write_mps(csa->prob, GLP_MPS_FILE, NULL, alpar@9: csa->out_freemps); alpar@9: if (ret != 0) alpar@9: { xprintf("Unable to write problem in free MPS format\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: /* write problem data in CPLEX LP format, if required */ alpar@9: if (csa->out_cpxlp != NULL) alpar@9: { ret = glp_write_lp(csa->prob, NULL, csa->out_cpxlp); alpar@9: if (ret != 0) alpar@9: { xprintf("Unable to write problem in CPLEX LP format\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: /* write problem data in GLPK format, if required */ alpar@9: if (csa->out_glp != NULL) alpar@9: { ret = glp_write_prob(csa->prob, 0, csa->out_glp); alpar@9: if (ret != 0) alpar@9: { xprintf("Unable to write problem in GLPK format\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: /* write problem data in OPB format, if required */ alpar@9: if (csa->out_pb != NULL) alpar@9: { ret = lpx_write_pb(csa->prob, csa->out_pb, 0, 0); alpar@9: if (ret != 0) alpar@9: { xprintf("Unable to write problem in OPB format\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: /* write problem data in normalized OPB format, if required */ alpar@9: if (csa->out_npb != NULL) alpar@9: { ret = lpx_write_pb(csa->prob, csa->out_npb, 1, 1); alpar@9: if (ret != 0) alpar@9: { xprintf( alpar@9: "Unable to write problem in normalized OPB format\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: #if 1 /* 06/VIII-2011 */ alpar@9: /* write problem data in DIMACS CNF-SAT format, if required */ alpar@9: if (csa->out_cnf != NULL) alpar@9: { ret = glp_write_cnfsat(csa->prob, csa->out_cnf); alpar@9: if (ret != 0) alpar@9: { xprintf( alpar@9: "Unable to write problem in DIMACS CNF-SAT format\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: #endif alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* if only problem data check is required, skip computations */ alpar@9: if (csa->check) alpar@9: { ret = EXIT_SUCCESS; alpar@9: goto done; alpar@9: } alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* determine the solution type */ alpar@9: if (!csa->nomip && alpar@9: glp_get_num_int(csa->prob) + glp_get_num_bin(csa->prob) > 0) alpar@9: { if (csa->solution == SOL_INTERIOR) alpar@9: { xprintf("Interior-point method is not able to solve MIP pro" alpar@9: "blem; use --simplex\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: csa->solution = SOL_INTEGER; alpar@9: } alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* if solution is provided, read it and skip computations */ alpar@9: if (csa->in_res != NULL) alpar@9: { if (csa->solution == SOL_BASIC) alpar@9: ret = glp_read_sol(csa->prob, csa->in_res); alpar@9: else if (csa->solution == SOL_INTERIOR) alpar@9: ret = glp_read_ipt(csa->prob, csa->in_res); alpar@9: else if (csa->solution == SOL_INTEGER) alpar@9: ret = glp_read_mip(csa->prob, csa->in_res); alpar@9: else alpar@9: xassert(csa != csa); alpar@9: if (ret != 0) alpar@9: { xprintf("Unable to read problem solution\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: goto skip; alpar@9: } alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* scale the problem data, if required */ alpar@9: if (csa->scale) alpar@9: { if (csa->solution == SOL_BASIC && !csa->smcp.presolve || alpar@9: csa->solution == SOL_INTERIOR || alpar@9: csa->solution == SOL_INTEGER && !csa->iocp.presolve) alpar@9: glp_scale_prob(csa->prob, GLP_SF_AUTO); alpar@9: } alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* construct starting LP basis */ alpar@9: if (csa->solution == SOL_BASIC && !csa->smcp.presolve || alpar@9: csa->solution == SOL_INTEGER && !csa->iocp.presolve) alpar@9: { if (csa->crash == USE_STD_BASIS) alpar@9: glp_std_basis(csa->prob); alpar@9: else if (csa->crash == USE_ADV_BASIS) alpar@9: glp_adv_basis(csa->prob, 0); alpar@9: else if (csa->crash == USE_CPX_BASIS) alpar@9: glp_cpx_basis(csa->prob); alpar@9: else if (csa->crash == USE_INI_BASIS) alpar@9: { ret = glp_read_sol(csa->prob, csa->ini_file); alpar@9: if (ret != 0) alpar@9: { xprintf("Unable to read initial basis\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: else alpar@9: xassert(csa != csa); alpar@9: } alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* solve the problem */ alpar@9: start = xtime(); alpar@9: if (csa->solution == SOL_BASIC) alpar@9: { if (!csa->exact) alpar@9: { glp_set_bfcp(csa->prob, &csa->bfcp); alpar@9: glp_simplex(csa->prob, &csa->smcp); alpar@9: if (csa->xcheck) alpar@9: { if (csa->smcp.presolve && alpar@9: glp_get_status(csa->prob) != GLP_OPT) alpar@9: xprintf("If you need to check final basis for non-opt" alpar@9: "imal solution, use --nopresol\n"); alpar@9: else alpar@9: glp_exact(csa->prob, &csa->smcp); alpar@9: } alpar@9: if (csa->out_sol != NULL || csa->out_res != NULL) alpar@9: { if (csa->smcp.presolve && alpar@9: glp_get_status(csa->prob) != GLP_OPT) alpar@9: xprintf("If you need actual output for non-optimal solut" alpar@9: "ion, use --nopresol\n"); alpar@9: } alpar@9: } alpar@9: else alpar@9: glp_exact(csa->prob, &csa->smcp); alpar@9: } alpar@9: else if (csa->solution == SOL_INTERIOR) alpar@9: glp_interior(csa->prob, &csa->iptcp); alpar@9: #if 1 /* 15/VIII-2011 */ alpar@9: else if (csa->solution == SOL_INTEGER && csa->minisat) alpar@9: { if (glp_check_cnfsat(csa->prob) == 0) alpar@9: glp_minisat1(csa->prob); alpar@9: else alpar@9: glp_intfeas1(csa->prob, csa->use_bnd, csa->obj_bnd); alpar@9: } alpar@9: #endif alpar@9: else if (csa->solution == SOL_INTEGER) alpar@9: { if (!csa->iocp.presolve) alpar@9: { glp_set_bfcp(csa->prob, &csa->bfcp); alpar@9: glp_simplex(csa->prob, &csa->smcp); alpar@9: } alpar@9: #if 0 alpar@9: csa->iocp.msg_lev = GLP_MSG_DBG; alpar@9: csa->iocp.pp_tech = GLP_PP_NONE; alpar@9: #endif alpar@9: glp_intopt(csa->prob, &csa->iocp); alpar@9: } alpar@9: else alpar@9: xassert(csa != csa); alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* display statistics */ alpar@9: xprintf("Time used: %.1f secs\n", xdifftime(xtime(), start)); alpar@9: { glp_long tpeak; alpar@9: char buf[50]; alpar@9: glp_mem_usage(NULL, NULL, NULL, &tpeak); alpar@9: xprintf("Memory used: %.1f Mb (%s bytes)\n", alpar@9: xltod(tpeak) / 1048576.0, xltoa(tpeak, buf)); alpar@9: } alpar@9: /*--------------------------------------------------------------*/ alpar@9: skip: /* postsolve the model, if necessary */ alpar@9: if (csa->tran != NULL) alpar@9: { if (csa->solution == SOL_BASIC) alpar@9: { if (!(glp_get_status(csa->prob) == GLP_OPT || alpar@9: glp_get_status(csa->prob) == GLP_FEAS)) alpar@9: ret = -1; alpar@9: else alpar@9: ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_SOL); alpar@9: } alpar@9: else if (csa->solution == SOL_INTERIOR) alpar@9: { if (!(glp_ipt_status(csa->prob) == GLP_OPT || alpar@9: glp_ipt_status(csa->prob) == GLP_FEAS)) alpar@9: ret = -1; alpar@9: else alpar@9: ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_IPT); alpar@9: } alpar@9: else if (csa->solution == SOL_INTEGER) alpar@9: { if (!(glp_mip_status(csa->prob) == GLP_OPT || alpar@9: glp_mip_status(csa->prob) == GLP_FEAS)) alpar@9: ret = -1; alpar@9: else alpar@9: ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_MIP); alpar@9: } alpar@9: else alpar@9: xassert(csa != csa); alpar@9: if (ret > 0) alpar@9: { xprintf("Model postsolving error\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* write problem solution in printable format, if required */ alpar@9: if (csa->out_sol != NULL) alpar@9: { if (csa->solution == SOL_BASIC) alpar@9: ret = lpx_print_sol(csa->prob, csa->out_sol); alpar@9: else if (csa->solution == SOL_INTERIOR) alpar@9: ret = lpx_print_ips(csa->prob, csa->out_sol); alpar@9: else if (csa->solution == SOL_INTEGER) alpar@9: ret = lpx_print_mip(csa->prob, csa->out_sol); alpar@9: else alpar@9: xassert(csa != csa); alpar@9: if (ret != 0) alpar@9: { xprintf("Unable to write problem solution\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: /* write problem solution in printable format, if required */ alpar@9: if (csa->out_res != NULL) alpar@9: { if (csa->solution == SOL_BASIC) alpar@9: ret = glp_write_sol(csa->prob, csa->out_res); alpar@9: else if (csa->solution == SOL_INTERIOR) alpar@9: ret = glp_write_ipt(csa->prob, csa->out_res); alpar@9: else if (csa->solution == SOL_INTEGER) alpar@9: ret = glp_write_mip(csa->prob, csa->out_res); alpar@9: else alpar@9: xassert(csa != csa); alpar@9: if (ret != 0) alpar@9: { xprintf("Unable to write problem solution\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: /* write sensitivity analysis report, if required */ alpar@9: if (csa->out_ranges != NULL) alpar@9: { if (csa->solution == SOL_BASIC) alpar@9: { if (glp_get_status(csa->prob) == GLP_OPT) alpar@9: { if (glp_bf_exists(csa->prob)) alpar@9: ranges: { ret = glp_print_ranges(csa->prob, 0, NULL, 0, alpar@9: csa->out_ranges); alpar@9: if (ret != 0) alpar@9: { xprintf("Unable to write sensitivity analysis repo" alpar@9: "rt\n"); alpar@9: ret = EXIT_FAILURE; alpar@9: goto done; alpar@9: } alpar@9: } alpar@9: else alpar@9: { ret = glp_factorize(csa->prob); alpar@9: if (ret == 0) goto ranges; alpar@9: xprintf("Cannot produce sensitivity analysis report d" alpar@9: "ue to error in basis factorization (glp_factorize" alpar@9: " returned %d); try --nopresol\n", ret); alpar@9: } alpar@9: } alpar@9: else alpar@9: xprintf("Cannot produce sensitivity analysis report for " alpar@9: "non-optimal basic solution\n"); alpar@9: } alpar@9: else alpar@9: xprintf("Cannot produce sensitivity analysis report for int" alpar@9: "erior-point or MIP solution\n"); alpar@9: } alpar@9: /*--------------------------------------------------------------*/ alpar@9: /* all seems to be ok */ alpar@9: ret = EXIT_SUCCESS; alpar@9: /*--------------------------------------------------------------*/ alpar@9: done: /* delete the LP/MIP problem object */ alpar@9: if (csa->prob != NULL) alpar@9: glp_delete_prob(csa->prob); alpar@9: /* free the translator workspace, if necessary */ alpar@9: if (csa->tran != NULL) alpar@9: glp_mpl_free_wksp(csa->tran); alpar@9: /* delete the network problem object, if necessary */ alpar@9: if (csa->graph != NULL) alpar@9: glp_delete_graph(csa->graph); alpar@9: xassert(gmp_pool_count() == 0); alpar@9: gmp_free_mem(); alpar@9: /* close log file, if necessary */ alpar@9: if (csa->log_file != NULL) glp_close_tee(); alpar@9: /* check that no memory blocks are still allocated */ alpar@9: { int count; alpar@9: glp_long total; alpar@9: glp_mem_usage(&count, NULL, &total, NULL); alpar@9: if (count != 0) alpar@9: xerror("Error: %d memory block(s) were lost\n", count); alpar@9: xassert(count == 0); alpar@9: xassert(total.lo == 0 && total.hi == 0); alpar@9: } alpar@9: /* free the GLPK environment */ alpar@9: glp_free_env(); alpar@9: /* return to the control program */ alpar@9: return ret; alpar@9: } alpar@9: alpar@9: /* eof */