src/glpapi19.c
changeset 1 c445c931472f
equal deleted inserted replaced
-1:000000000000 0:68b94f3c1424
       
     1 /* glpapi19.c (stand-alone LP/MIP solver) */
       
     2 
       
     3 /***********************************************************************
       
     4 *  This code is part of GLPK (GNU Linear Programming Kit).
       
     5 *
       
     6 *  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
       
     7 *  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
       
     8 *  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
       
     9 *  E-mail: <mao@gnu.org>.
       
    10 *
       
    11 *  GLPK is free software: you can redistribute it and/or modify it
       
    12 *  under the terms of the GNU General Public License as published by
       
    13 *  the Free Software Foundation, either version 3 of the License, or
       
    14 *  (at your option) any later version.
       
    15 *
       
    16 *  GLPK is distributed in the hope that it will be useful, but WITHOUT
       
    17 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
       
    18 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
       
    19 *  License for more details.
       
    20 *
       
    21 *  You should have received a copy of the GNU General Public License
       
    22 *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
       
    23 ***********************************************************************/
       
    24 
       
    25 #include "glpapi.h"
       
    26 #include "glpgmp.h"
       
    27 
       
    28 struct csa
       
    29 {     /* common storage area */
       
    30       glp_prob *prob;
       
    31       /* LP/MIP problem object */
       
    32       glp_bfcp bfcp;
       
    33       /* basis factorization control parameters */
       
    34       glp_smcp smcp;
       
    35       /* simplex method control parameters */
       
    36       glp_iptcp iptcp;
       
    37       /* interior-point method control parameters */
       
    38       glp_iocp iocp;
       
    39       /* integer optimizer control parameters */
       
    40       glp_tran *tran;
       
    41       /* model translator workspace */
       
    42       glp_graph *graph;
       
    43       /* network problem object */
       
    44       int format;
       
    45       /* problem file format: */
       
    46 #define FMT_MPS_DECK    1  /* fixed MPS */
       
    47 #define FMT_MPS_FILE    2  /* free MPS */
       
    48 #define FMT_LP          3  /* CPLEX LP */
       
    49 #define FMT_GLP         4  /* GLPK LP/MIP */
       
    50 #define FMT_MATHPROG    5  /* MathProg */
       
    51 #define FMT_MIN_COST    6  /* DIMACS min-cost flow */
       
    52 #define FMT_MAX_FLOW    7  /* DIMACS maximum flow */
       
    53       const char *in_file;
       
    54       /* name of input problem file */
       
    55 #define DATA_MAX 10
       
    56       /* maximal number of input data files */
       
    57       int ndf;
       
    58       /* number of input data files specified */
       
    59       const char *in_data[1+DATA_MAX];
       
    60       /* name(s) of input data file(s) */
       
    61       const char *out_dpy;
       
    62       /* name of output file to send display output; NULL means the
       
    63          display output is sent to the terminal */
       
    64       int seed;
       
    65       /* seed value to be passed to the MathProg translator; initially
       
    66          set to 1; 0x80000000 means the value is omitted */
       
    67       int solution;
       
    68       /* solution type flag: */
       
    69 #define SOL_BASIC       1  /* basic */
       
    70 #define SOL_INTERIOR    2  /* interior-point */
       
    71 #define SOL_INTEGER     3  /* mixed integer */
       
    72       const char *in_res;
       
    73       /* name of input solution file in raw format */
       
    74       int dir;
       
    75       /* optimization direction flag:
       
    76          0       - not specified
       
    77          GLP_MIN - minimization
       
    78          GLP_MAX - maximization */
       
    79       int scale;
       
    80       /* automatic problem scaling flag */
       
    81       const char *out_sol;
       
    82       /* name of output solution file in printable format */
       
    83       const char *out_res;
       
    84       /* name of output solution file in raw format */
       
    85       const char *out_ranges;
       
    86       /* name of output file to write sensitivity analysis report */
       
    87       int check;
       
    88       /* input data checking flag; no solution is performed */
       
    89       const char *new_name;
       
    90       /* new name to be assigned to the problem */
       
    91       const char *out_mps;
       
    92       /* name of output problem file in fixed MPS format */
       
    93       const char *out_freemps;
       
    94       /* name of output problem file in free MPS format */
       
    95       const char *out_cpxlp;
       
    96       /* name of output problem file in CPLEX LP format */
       
    97       const char *out_glp;
       
    98       /* name of output problem file in GLPK format */
       
    99       const char *out_pb;
       
   100       /* name of output problem file in OPB format */
       
   101       const char *out_npb;
       
   102       /* name of output problem file in normalized OPB format */
       
   103       const char *log_file;
       
   104       /* name of output file to hardcopy terminal output */
       
   105       int crash;
       
   106       /* initial basis option: */
       
   107 #define USE_STD_BASIS   1  /* use standard basis */
       
   108 #define USE_ADV_BASIS   2  /* use advanced basis */
       
   109 #define USE_CPX_BASIS   3  /* use Bixby's basis */
       
   110 #define USE_INI_BASIS   4  /* use initial basis from ini_file */
       
   111       const char *ini_file;
       
   112       /* name of input file containing initial basis */
       
   113       int exact;
       
   114       /* flag to use glp_exact rather than glp_simplex */
       
   115       int xcheck;
       
   116       /* flag to check final basis with glp_exact */
       
   117       int nomip;
       
   118       /* flag to consider MIP as pure LP */
       
   119 };
       
   120 
       
   121 static void print_help(const char *my_name)
       
   122 {     /* print help information */
       
   123       xprintf("Usage: %s [options...] filename\n", my_name);
       
   124       xprintf("\n");
       
   125       xprintf("General options:\n");
       
   126       xprintf("   --mps             read LP/MIP problem in fixed MPS fo"
       
   127          "rmat\n");
       
   128       xprintf("   --freemps         read LP/MIP problem in free MPS for"
       
   129          "mat (default)\n");
       
   130       xprintf("   --lp              read LP/MIP problem in CPLEX LP for"
       
   131          "mat\n");
       
   132       xprintf("   --glp             read LP/MIP problem in GLPK format "
       
   133          "\n");
       
   134       xprintf("   --math            read LP/MIP model written in GNU Ma"
       
   135          "thProg modeling\n");
       
   136       xprintf("                     language\n");
       
   137       xprintf("   -m filename, --model filename\n");
       
   138       xprintf("                     read model section and optional dat"
       
   139          "a section from\n");
       
   140       xprintf("                     filename (same as --math)\n");
       
   141       xprintf("   -d filename, --data filename\n");
       
   142       xprintf("                     read data section from filename (fo"
       
   143          "r --math only);\n");
       
   144       xprintf("                     if model file also has data section"
       
   145          ", it is ignored\n");
       
   146       xprintf("   -y filename, --display filename\n");
       
   147       xprintf("                     send display output to filename (fo"
       
   148          "r --math only);\n");
       
   149       xprintf("                     by default the output is sent to te"
       
   150          "rminal\n");
       
   151       xprintf("   --seed value      initialize pseudo-random number gen"
       
   152          "erator used in\n");
       
   153       xprintf("                     MathProg model with specified seed "
       
   154          "(any integer);\n");
       
   155       xprintf("                     if seed value is ?, some random see"
       
   156          "d will be used\n");
       
   157       xprintf("   --mincost         read min-cost flow problem in DIMAC"
       
   158          "S format\n");
       
   159       xprintf("   --maxflow         read maximum flow problem in DIMACS"
       
   160          " format\n");
       
   161       xprintf("   --simplex         use simplex method (default)\n");
       
   162       xprintf("   --interior        use interior point method (LP only)"
       
   163          "\n");
       
   164       xprintf("   -r filename, --read filename\n");
       
   165       xprintf("                     read solution from filename rather "
       
   166          "to find it with\n");
       
   167       xprintf("                     the solver\n");
       
   168       xprintf("   --min             minimization\n");
       
   169       xprintf("   --max             maximization\n");
       
   170       xprintf("   --scale           scale problem (default)\n");
       
   171       xprintf("   --noscale         do not scale problem\n");
       
   172       xprintf("   -o filename, --output filename\n");
       
   173       xprintf("                     write solution to filename in print"
       
   174          "able format\n");
       
   175       xprintf("   -w filename, --write filename\n");
       
   176       xprintf("                     write solution to filename in plain"
       
   177          " text format\n");
       
   178       xprintf("   --ranges filename\n");
       
   179       xprintf("                     write sensitivity analysis report t"
       
   180          "o filename in\n");
       
   181       xprintf("                     printable format (simplex only)\n");
       
   182       xprintf("   --tmlim nnn       limit solution time to nnn seconds "
       
   183          "\n");
       
   184       xprintf("   --memlim nnn      limit available memory to nnn megab"
       
   185          "ytes\n");
       
   186       xprintf("   --check           do not solve problem, check input d"
       
   187          "ata only\n");
       
   188       xprintf("   --name probname   change problem name to probname\n");
       
   189       xprintf("   --wmps filename   write problem to filename in fixed "
       
   190          "MPS format\n");
       
   191       xprintf("   --wfreemps filename\n");
       
   192       xprintf("                     write problem to filename in free M"
       
   193          "PS format\n");
       
   194       xprintf("   --wlp filename    write problem to filename in CPLEX "
       
   195          "LP format\n");
       
   196       xprintf("   --wglp filename   write problem to filename in GLPK f"
       
   197          "ormat\n");
       
   198 #if 0
       
   199       xprintf("   --wpb filename    write problem to filename in OPB fo"
       
   200          "rmat\n");
       
   201       xprintf("   --wnpb filename   write problem to filename in normal"
       
   202          "ized OPB format\n");
       
   203 #endif
       
   204       xprintf("   --log filename    write copy of terminal output to fi"
       
   205          "lename\n");
       
   206       xprintf("   -h, --help        display this help information and e"
       
   207          "xit\n");
       
   208       xprintf("   -v, --version     display program version and exit\n")
       
   209          ;
       
   210       xprintf("\n");
       
   211       xprintf("LP basis factorization options:\n");
       
   212       xprintf("   --luf             LU + Forrest-Tomlin update\n");
       
   213       xprintf("                     (faster, less stable; default)\n");
       
   214       xprintf("   --cbg             LU + Schur complement + Bartels-Gol"
       
   215          "ub update\n");
       
   216       xprintf("                     (slower, more stable)\n");
       
   217       xprintf("   --cgr             LU + Schur complement + Givens rota"
       
   218          "tion update\n");
       
   219       xprintf("                     (slower, more stable)\n");
       
   220       xprintf("\n");
       
   221       xprintf("Options specific to simplex solver:\n");
       
   222       xprintf("   --primal          use primal simplex (default)\n");
       
   223       xprintf("   --dual            use dual simplex\n");
       
   224       xprintf("   --std             use standard initial basis of all s"
       
   225          "lacks\n");
       
   226       xprintf("   --adv             use advanced initial basis (default"
       
   227          ")\n");
       
   228       xprintf("   --bib             use Bixby's initial basis\n");
       
   229       xprintf("   --ini filename    use as initial basis previously sav"
       
   230          "ed with -w\n");
       
   231       xprintf("                     (disables LP presolver)\n");
       
   232       xprintf("   --steep           use steepest edge technique (defaul"
       
   233          "t)\n");
       
   234       xprintf("   --nosteep         use standard \"textbook\" pricing\n"
       
   235          );
       
   236       xprintf("   --relax           use Harris' two-pass ratio test (de"
       
   237          "fault)\n");
       
   238       xprintf("   --norelax         use standard \"textbook\" ratio tes"
       
   239          "t\n");
       
   240       xprintf("   --presol          use presolver (default; assumes --s"
       
   241          "cale and --adv)\n");
       
   242       xprintf("   --nopresol        do not use presolver\n");
       
   243       xprintf("   --exact           use simplex method based on exact a"
       
   244          "rithmetic\n");
       
   245       xprintf("   --xcheck          check final basis using exact arith"
       
   246          "metic\n");
       
   247       xprintf("\n");
       
   248       xprintf("Options specific to interior-point solver:\n");
       
   249       xprintf("   --nord            use natural (original) ordering\n");
       
   250       xprintf("   --qmd             use quotient minimum degree orderin"
       
   251          "g\n");
       
   252       xprintf("   --amd             use approximate minimum degree orde"
       
   253          "ring (default)\n");
       
   254       xprintf("   --symamd          use approximate minimum degree orde"
       
   255          "ring\n");
       
   256       xprintf("\n");
       
   257       xprintf("Options specific to MIP solver:\n");
       
   258       xprintf("   --nomip           consider all integer variables as c"
       
   259          "ontinuous\n");
       
   260       xprintf("                     (allows solving MIP as pure LP)\n");
       
   261       xprintf("   --first           branch on first integer variable\n")
       
   262          ;
       
   263       xprintf("   --last            branch on last integer variable\n");
       
   264       xprintf("   --mostf           branch on most fractional variable "
       
   265          "\n");
       
   266       xprintf("   --drtom           branch using heuristic by Driebeck "
       
   267          "and Tomlin\n");
       
   268       xprintf("                     (default)\n");
       
   269       xprintf("   --pcost           branch using hybrid pseudocost heur"
       
   270          "istic (may be\n");
       
   271       xprintf("                     useful for hard instances)\n");
       
   272       xprintf("   --dfs             backtrack using depth first search "
       
   273          "\n");
       
   274       xprintf("   --bfs             backtrack using breadth first searc"
       
   275          "h\n");
       
   276       xprintf("   --bestp           backtrack using the best projection"
       
   277          " heuristic\n");
       
   278       xprintf("   --bestb           backtrack using node with best loca"
       
   279          "l bound\n");
       
   280       xprintf("                     (default)\n");
       
   281       xprintf("   --intopt          use MIP presolver (default)\n");
       
   282       xprintf("   --nointopt        do not use MIP presolver\n");
       
   283       xprintf("   --binarize        replace general integer variables b"
       
   284          "y binary ones\n");
       
   285       xprintf("                     (assumes --intopt)\n");
       
   286       xprintf("   --fpump           apply feasibility pump heuristic\n")
       
   287          ;
       
   288       xprintf("   --gomory          generate Gomory's mixed integer cut"
       
   289          "s\n");
       
   290       xprintf("   --mir             generate MIR (mixed integer roundin"
       
   291          "g) cuts\n");
       
   292       xprintf("   --cover           generate mixed cover cuts\n");
       
   293       xprintf("   --clique          generate clique cuts\n");
       
   294       xprintf("   --cuts            generate all cuts above\n");
       
   295       xprintf("   --mipgap tol      set relative mip gap tolerance to t"
       
   296          "ol\n");
       
   297       xprintf("\n");
       
   298       xprintf("For description of the MPS and CPLEX LP formats see Refe"
       
   299          "rence Manual.\n");
       
   300       xprintf("For description of the modeling language see \"GLPK: Mod"
       
   301          "eling Language\n");
       
   302       xprintf("GNU MathProg\". Both documents are included in the GLPK "
       
   303          "distribution.\n");
       
   304       xprintf("\n");
       
   305       xprintf("See GLPK web page at <http://www.gnu.org/software/glpk/g"
       
   306          "lpk.html>.\n");
       
   307       xprintf("\n");
       
   308       xprintf("Please report bugs to <bug-glpk@gnu.org>.\n");
       
   309       return;
       
   310 }
       
   311 
       
   312 static void print_version(int briefly)
       
   313 {     /* print version information */
       
   314       xprintf("GLPSOL: GLPK LP/MIP Solver, v%s\n", glp_version());
       
   315       if (briefly) goto done;
       
   316       xprintf("\n");
       
   317       xprintf("Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, "
       
   318          "2007, 2008,\n");
       
   319       xprintf("2009, 2010 Andrew Makhorin, Department for Applied Infor"
       
   320          "matics, Moscow\n");
       
   321       xprintf("Aviation Institute, Moscow, Russia. All rights reserved."
       
   322          "\n");
       
   323       xprintf("\n");
       
   324       xprintf("This program has ABSOLUTELY NO WARRANTY.\n");
       
   325       xprintf("\n");
       
   326       xprintf("This program is free software; you may re-distribute it "
       
   327          "under the terms\n");
       
   328       xprintf("of the GNU General Public License version 3 or later.\n")
       
   329          ;
       
   330 done: return;
       
   331 }
       
   332 
       
   333 static int parse_cmdline(struct csa *csa, int argc, const char *argv[])
       
   334 {     /* parse command-line parameters */
       
   335       int k;
       
   336 #define p(str) (strcmp(argv[k], str) == 0)
       
   337       for (k = 1; k < argc; k++)
       
   338       {  if (p("--mps"))
       
   339             csa->format = FMT_MPS_DECK;
       
   340          else if (p("--freemps"))
       
   341             csa->format = FMT_MPS_FILE;
       
   342          else if (p("--lp") || p("--cpxlp"))
       
   343             csa->format = FMT_LP;
       
   344          else if (p("--glp"))
       
   345             csa->format = FMT_GLP;
       
   346          else if (p("--math") || p("-m") || p("--model"))
       
   347             csa->format = FMT_MATHPROG;
       
   348          else if (p("-d") || p("--data"))
       
   349          {  k++;
       
   350             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   351             {  xprintf("No input data file specified\n");
       
   352                return 1;
       
   353             }
       
   354             if (csa->ndf == DATA_MAX)
       
   355             {  xprintf("Too many input data files\n");
       
   356                return 1;
       
   357             }
       
   358             csa->in_data[++(csa->ndf)] = argv[k];
       
   359          }
       
   360          else if (p("-y") || p("--display"))
       
   361          {  k++;
       
   362             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   363             {  xprintf("No display output file specified\n");
       
   364                return 1;
       
   365             }
       
   366             if (csa->out_dpy != NULL)
       
   367             {  xprintf("Only one display output file allowed\n");
       
   368                return 1;
       
   369             }
       
   370             csa->out_dpy = argv[k];
       
   371          }
       
   372          else if (p("--seed"))
       
   373          {  k++;
       
   374             if (k == argc || argv[k][0] == '\0' ||
       
   375                argv[k][0] == '-' && !isdigit((unsigned char)argv[k][1]))
       
   376             {  xprintf("No seed value specified\n");
       
   377                return 1;
       
   378             }
       
   379             if (strcmp(argv[k], "?") == 0)
       
   380                csa->seed = 0x80000000;
       
   381             else if (str2int(argv[k], &csa->seed))
       
   382             {  xprintf("Invalid seed value `%s'\n", argv[k]);
       
   383                return 1;
       
   384             }
       
   385          }
       
   386          else if (p("--mincost"))
       
   387             csa->format = FMT_MIN_COST;
       
   388          else if (p("--maxflow"))
       
   389             csa->format = FMT_MAX_FLOW;
       
   390          else if (p("--simplex"))
       
   391             csa->solution = SOL_BASIC;
       
   392          else if (p("--interior"))
       
   393             csa->solution = SOL_INTERIOR;
       
   394 #if 1 /* 28/V-2010 */
       
   395          else if (p("--alien"))
       
   396             csa->iocp.alien = GLP_ON;
       
   397 #endif
       
   398          else if (p("-r") || p("--read"))
       
   399          {  k++;
       
   400             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   401             {  xprintf("No input solution file specified\n");
       
   402                return 1;
       
   403             }
       
   404             if (csa->in_res != NULL)
       
   405             {  xprintf("Only one input solution file allowed\n");
       
   406                return 1;
       
   407             }
       
   408             csa->in_res = argv[k];
       
   409          }
       
   410          else if (p("--min"))
       
   411             csa->dir = GLP_MIN;
       
   412          else if (p("--max"))
       
   413             csa->dir = GLP_MAX;
       
   414          else if (p("--scale"))
       
   415             csa->scale = 1;
       
   416          else if (p("--noscale"))
       
   417             csa->scale = 0;
       
   418          else if (p("-o") || p("--output"))
       
   419          {  k++;
       
   420             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   421             {  xprintf("No output solution file specified\n");
       
   422                return 1;
       
   423             }
       
   424             if (csa->out_sol != NULL)
       
   425             {  xprintf("Only one output solution file allowed\n");
       
   426                return 1;
       
   427             }
       
   428             csa->out_sol = argv[k];
       
   429          }
       
   430          else if (p("-w") || p("--write"))
       
   431          {  k++;
       
   432             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   433             {  xprintf("No output solution file specified\n");
       
   434                return 1;
       
   435             }
       
   436             if (csa->out_res != NULL)
       
   437             {  xprintf("Only one output solution file allowed\n");
       
   438                return 1;
       
   439             }
       
   440             csa->out_res = argv[k];
       
   441          }
       
   442          else if (p("--ranges") || p("--bounds"))
       
   443          {  k++;
       
   444             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   445             {  xprintf("No output file specified to write sensitivity a"
       
   446                   "nalysis report\n");
       
   447                return 1;
       
   448             }
       
   449             if (csa->out_ranges != NULL)
       
   450             {  xprintf("Only one output file allowed to write sensitivi"
       
   451                   "ty analysis report\n");
       
   452                return 1;
       
   453             }
       
   454             csa->out_ranges = argv[k];
       
   455          }
       
   456          else if (p("--tmlim"))
       
   457          {  int tm_lim;
       
   458             k++;
       
   459             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   460             {  xprintf("No time limit specified\n");
       
   461                return 1;
       
   462             }
       
   463             if (str2int(argv[k], &tm_lim) || tm_lim < 0)
       
   464             {  xprintf("Invalid time limit `%s'\n", argv[k]);
       
   465                return 1;
       
   466             }
       
   467             if (tm_lim <= INT_MAX / 1000)
       
   468                csa->smcp.tm_lim = csa->iocp.tm_lim = 1000 * tm_lim;
       
   469             else
       
   470                csa->smcp.tm_lim = csa->iocp.tm_lim = INT_MAX;
       
   471          }
       
   472          else if (p("--memlim"))
       
   473          {  int mem_lim;
       
   474             k++;
       
   475             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   476             {  xprintf("No memory limit specified\n");
       
   477                return 1;
       
   478             }
       
   479             if (str2int(argv[k], &mem_lim) || mem_lim < 1)
       
   480             {  xprintf("Invalid memory limit `%s'\n", argv[k]);
       
   481                return 1;
       
   482             }
       
   483             glp_mem_limit(mem_lim);
       
   484          }
       
   485          else if (p("--check"))
       
   486             csa->check = 1;
       
   487          else if (p("--name"))
       
   488          {  k++;
       
   489             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   490             {  xprintf("No problem name specified\n");
       
   491                return 1;
       
   492             }
       
   493             if (csa->new_name != NULL)
       
   494             {  xprintf("Only one problem name allowed\n");
       
   495                return 1;
       
   496             }
       
   497             csa->new_name = argv[k];
       
   498          }
       
   499          else if (p("--wmps"))
       
   500          {  k++;
       
   501             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   502             {  xprintf("No fixed MPS output file specified\n");
       
   503                return 1;
       
   504             }
       
   505             if (csa->out_mps != NULL)
       
   506             {  xprintf("Only one fixed MPS output file allowed\n");
       
   507                return 1;
       
   508             }
       
   509             csa->out_mps = argv[k];
       
   510          }
       
   511          else if (p("--wfreemps"))
       
   512          {  k++;
       
   513             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   514             {  xprintf("No free MPS output file specified\n");
       
   515                return 1;
       
   516             }
       
   517             if (csa->out_freemps != NULL)
       
   518             {  xprintf("Only one free MPS output file allowed\n");
       
   519                return 1;
       
   520             }
       
   521             csa->out_freemps = argv[k];
       
   522          }
       
   523          else if (p("--wlp") || p("--wcpxlp") || p("--wlpt"))
       
   524          {  k++;
       
   525             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   526             {  xprintf("No CPLEX LP output file specified\n");
       
   527                return 1;
       
   528             }
       
   529             if (csa->out_cpxlp != NULL)
       
   530             {  xprintf("Only one CPLEX LP output file allowed\n");
       
   531                return 1;
       
   532             }
       
   533             csa->out_cpxlp = argv[k];
       
   534          }
       
   535          else if (p("--wglp"))
       
   536          {  k++;
       
   537             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   538             {  xprintf("No GLPK LP/MIP output file specified\n");
       
   539                return 1;
       
   540             }
       
   541             if (csa->out_glp != NULL)
       
   542             {  xprintf("Only one GLPK LP/MIP output file allowed\n");
       
   543                return 1;
       
   544             }
       
   545             csa->out_glp = argv[k];
       
   546          }
       
   547          else if (p("--wpb"))
       
   548          {  k++;
       
   549             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   550             {  xprintf("No problem output file specified\n");
       
   551                return 1;
       
   552             }
       
   553             if (csa->out_pb != NULL)
       
   554             {  xprintf("Only one OPB output file allowed\n");
       
   555                return 1;
       
   556             }
       
   557             csa->out_pb = argv[k];
       
   558          }
       
   559          else if (p("--wnpb"))
       
   560          {  k++;
       
   561             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   562             {  xprintf("No problem output file specified\n");
       
   563                return 1;
       
   564             }
       
   565             if (csa->out_npb != NULL)
       
   566             {  xprintf("Only one normalized OPB output file allowed\n");
       
   567                return 1;
       
   568             }
       
   569             csa->out_npb = argv[k];
       
   570          }
       
   571          else if (p("--log"))
       
   572          {  k++;
       
   573             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   574             {  xprintf("No log file specified\n");
       
   575                return 1;
       
   576             }
       
   577             if (csa->log_file != NULL)
       
   578             {  xprintf("Only one log file allowed\n");
       
   579                return 1;
       
   580             }
       
   581             csa->log_file = argv[k];
       
   582          }
       
   583          else if (p("-h") || p("--help"))
       
   584          {  print_help(argv[0]);
       
   585             return -1;
       
   586          }
       
   587          else if (p("-v") || p("--version"))
       
   588          {  print_version(0);
       
   589             return -1;
       
   590          }
       
   591          else if (p("--luf"))
       
   592             csa->bfcp.type = GLP_BF_FT;
       
   593          else if (p("--cbg"))
       
   594             csa->bfcp.type = GLP_BF_BG;
       
   595          else if (p("--cgr"))
       
   596             csa->bfcp.type = GLP_BF_GR;
       
   597          else if (p("--primal"))
       
   598             csa->smcp.meth = GLP_PRIMAL;
       
   599          else if (p("--dual"))
       
   600             csa->smcp.meth = GLP_DUAL;
       
   601          else if (p("--std"))
       
   602             csa->crash = USE_STD_BASIS;
       
   603          else if (p("--adv"))
       
   604             csa->crash = USE_ADV_BASIS;
       
   605          else if (p("--bib"))
       
   606             csa->crash = USE_CPX_BASIS;
       
   607          else if (p("--ini"))
       
   608          {  csa->crash = USE_INI_BASIS;
       
   609             csa->smcp.presolve = GLP_OFF;
       
   610             k++;
       
   611             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   612             {  xprintf("No initial basis file specified\n");
       
   613                return 1;
       
   614             }
       
   615             if (csa->ini_file != NULL)
       
   616             {  xprintf("Only one initial basis file allowed\n");
       
   617                return 1;
       
   618             }
       
   619             csa->ini_file = argv[k];
       
   620          }
       
   621          else if (p("--steep"))
       
   622             csa->smcp.pricing = GLP_PT_PSE;
       
   623          else if (p("--nosteep"))
       
   624             csa->smcp.pricing = GLP_PT_STD;
       
   625          else if (p("--relax"))
       
   626             csa->smcp.r_test = GLP_RT_HAR;
       
   627          else if (p("--norelax"))
       
   628             csa->smcp.r_test = GLP_RT_STD;
       
   629          else if (p("--presol"))
       
   630             csa->smcp.presolve = GLP_ON;
       
   631          else if (p("--nopresol"))
       
   632             csa->smcp.presolve = GLP_OFF;
       
   633          else if (p("--exact"))
       
   634             csa->exact = 1;
       
   635          else if (p("--xcheck"))
       
   636             csa->xcheck = 1;
       
   637          else if (p("--nord"))
       
   638             csa->iptcp.ord_alg = GLP_ORD_NONE;
       
   639          else if (p("--qmd"))
       
   640             csa->iptcp.ord_alg = GLP_ORD_QMD;
       
   641          else if (p("--amd"))
       
   642             csa->iptcp.ord_alg = GLP_ORD_AMD;
       
   643          else if (p("--symamd"))
       
   644             csa->iptcp.ord_alg = GLP_ORD_SYMAMD;
       
   645          else if (p("--nomip"))
       
   646             csa->nomip = 1;
       
   647          else if (p("--first"))
       
   648             csa->iocp.br_tech = GLP_BR_FFV;
       
   649          else if (p("--last"))
       
   650             csa->iocp.br_tech = GLP_BR_LFV;
       
   651          else if (p("--drtom"))
       
   652             csa->iocp.br_tech = GLP_BR_DTH;
       
   653          else if (p("--mostf"))
       
   654             csa->iocp.br_tech = GLP_BR_MFV;
       
   655          else if (p("--pcost"))
       
   656             csa->iocp.br_tech = GLP_BR_PCH;
       
   657          else if (p("--dfs"))
       
   658             csa->iocp.bt_tech = GLP_BT_DFS;
       
   659          else if (p("--bfs"))
       
   660             csa->iocp.bt_tech = GLP_BT_BFS;
       
   661          else if (p("--bestp"))
       
   662             csa->iocp.bt_tech = GLP_BT_BPH;
       
   663          else if (p("--bestb"))
       
   664             csa->iocp.bt_tech = GLP_BT_BLB;
       
   665          else if (p("--intopt"))
       
   666             csa->iocp.presolve = GLP_ON;
       
   667          else if (p("--nointopt"))
       
   668             csa->iocp.presolve = GLP_OFF;
       
   669          else if (p("--binarize"))
       
   670             csa->iocp.presolve = csa->iocp.binarize = GLP_ON;
       
   671          else if (p("--fpump"))
       
   672             csa->iocp.fp_heur = GLP_ON;
       
   673          else if (p("--gomory"))
       
   674             csa->iocp.gmi_cuts = GLP_ON;
       
   675          else if (p("--mir"))
       
   676             csa->iocp.mir_cuts = GLP_ON;
       
   677          else if (p("--cover"))
       
   678             csa->iocp.cov_cuts = GLP_ON;
       
   679          else if (p("--clique"))
       
   680             csa->iocp.clq_cuts = GLP_ON;
       
   681          else if (p("--cuts"))
       
   682             csa->iocp.gmi_cuts = csa->iocp.mir_cuts =
       
   683             csa->iocp.cov_cuts = csa->iocp.clq_cuts = GLP_ON;
       
   684          else if (p("--mipgap"))
       
   685          {  double mip_gap;
       
   686             k++;
       
   687             if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-')
       
   688             {  xprintf("No relative gap tolerance specified\n");
       
   689                return 1;
       
   690             }
       
   691             if (str2num(argv[k], &mip_gap) || mip_gap < 0.0)
       
   692             {  xprintf("Invalid relative mip gap tolerance `%s'\n",
       
   693                   argv[k]);
       
   694                return 1;
       
   695             }
       
   696             csa->iocp.mip_gap = mip_gap;
       
   697          }
       
   698          else if (argv[k][0] == '-' ||
       
   699                  (argv[k][0] == '-' && argv[k][1] == '-'))
       
   700          {  xprintf("Invalid option `%s'; try %s --help\n",
       
   701                argv[k], argv[0]);
       
   702             return 1;
       
   703          }
       
   704          else
       
   705          {  if (csa->in_file != NULL)
       
   706             {  xprintf("Only one input problem file allowed\n");
       
   707                return 1;
       
   708             }
       
   709             csa->in_file = argv[k];
       
   710          }
       
   711       }
       
   712 #undef p
       
   713       return 0;
       
   714 }
       
   715 
       
   716 typedef struct { double rhs, pi; } v_data;
       
   717 typedef struct { double low, cap, cost, x; } a_data;
       
   718 
       
   719 int glp_main(int argc, const char *argv[])
       
   720 {     /* stand-alone LP/MIP solver */
       
   721       struct csa _csa, *csa = &_csa;
       
   722       int ret;
       
   723       glp_long start;
       
   724       /* perform initialization */
       
   725       csa->prob = glp_create_prob();
       
   726       glp_get_bfcp(csa->prob, &csa->bfcp);
       
   727       glp_init_smcp(&csa->smcp);
       
   728       csa->smcp.presolve = GLP_ON;
       
   729       glp_init_iptcp(&csa->iptcp);
       
   730       glp_init_iocp(&csa->iocp);
       
   731       csa->iocp.presolve = GLP_ON;
       
   732       csa->tran = NULL;
       
   733       csa->graph = NULL;
       
   734       csa->format = FMT_MPS_FILE;
       
   735       csa->in_file = NULL;
       
   736       csa->ndf = 0;
       
   737       csa->out_dpy = NULL;
       
   738       csa->seed = 1;
       
   739       csa->solution = SOL_BASIC;
       
   740       csa->in_res = NULL;
       
   741       csa->dir = 0;
       
   742       csa->scale = 1;
       
   743       csa->out_sol = NULL;
       
   744       csa->out_res = NULL;
       
   745       csa->out_ranges = NULL;
       
   746       csa->check = 0;
       
   747       csa->new_name = NULL;
       
   748       csa->out_mps = NULL;
       
   749       csa->out_freemps = NULL;
       
   750       csa->out_cpxlp = NULL;
       
   751       csa->out_glp = NULL;
       
   752       csa->out_pb = NULL;
       
   753       csa->out_npb = NULL;
       
   754       csa->log_file = NULL;
       
   755       csa->crash = USE_ADV_BASIS;
       
   756       csa->ini_file = NULL;
       
   757       csa->exact = 0;
       
   758       csa->xcheck = 0;
       
   759       csa->nomip = 0;
       
   760       /* parse command-line parameters */
       
   761       ret = parse_cmdline(csa, argc, argv);
       
   762       if (ret < 0)
       
   763       {  ret = EXIT_SUCCESS;
       
   764          goto done;
       
   765       }
       
   766       if (ret > 0)
       
   767       {  ret = EXIT_FAILURE;
       
   768          goto done;
       
   769       }
       
   770       /*--------------------------------------------------------------*/
       
   771       /* remove all output files specified in the command line */
       
   772       if (csa->out_dpy != NULL) remove(csa->out_dpy);
       
   773       if (csa->out_sol != NULL) remove(csa->out_sol);
       
   774       if (csa->out_res != NULL) remove(csa->out_res);
       
   775       if (csa->out_ranges != NULL) remove(csa->out_ranges);
       
   776       if (csa->out_mps != NULL) remove(csa->out_mps);
       
   777       if (csa->out_freemps != NULL) remove(csa->out_freemps);
       
   778       if (csa->out_cpxlp != NULL) remove(csa->out_cpxlp);
       
   779       if (csa->out_glp != NULL) remove(csa->out_glp);
       
   780       if (csa->out_pb != NULL) remove(csa->out_pb);
       
   781       if (csa->out_npb != NULL) remove(csa->out_npb);
       
   782       if (csa->log_file != NULL) remove(csa->log_file);
       
   783       /*--------------------------------------------------------------*/
       
   784       /* open log file, if required */
       
   785       if (csa->log_file != NULL)
       
   786       {  if (glp_open_tee(csa->log_file))
       
   787          {  xprintf("Unable to create log file\n");
       
   788             ret = EXIT_FAILURE;
       
   789             goto done;
       
   790          }
       
   791       }
       
   792       /*--------------------------------------------------------------*/
       
   793       /* print version information */
       
   794       print_version(1);
       
   795       /*--------------------------------------------------------------*/
       
   796       /* print parameters specified in the command line */
       
   797       if (argc > 1)
       
   798       {  int k, len = INT_MAX;
       
   799          xprintf("Parameter(s) specified in the command line:");
       
   800          for (k = 1; k < argc; k++)
       
   801          {  if (len > 72)
       
   802                xprintf("\n"), len = 0;
       
   803             xprintf(" %s", argv[k]);
       
   804             len += 1 + strlen(argv[k]);
       
   805          }
       
   806          xprintf("\n");
       
   807       }
       
   808       /*--------------------------------------------------------------*/
       
   809       /* read problem data from the input file */
       
   810       if (csa->in_file == NULL)
       
   811       {  xprintf("No input problem file specified; try %s --help\n",
       
   812             argv[0]);
       
   813          ret = EXIT_FAILURE;
       
   814          goto done;
       
   815       }
       
   816       if (csa->format == FMT_MPS_DECK)
       
   817       {  ret = glp_read_mps(csa->prob, GLP_MPS_DECK, NULL,
       
   818             csa->in_file);
       
   819          if (ret != 0)
       
   820 err1:    {  xprintf("MPS file processing error\n");
       
   821             ret = EXIT_FAILURE;
       
   822             goto done;
       
   823          }
       
   824       }
       
   825       else if (csa->format == FMT_MPS_FILE)
       
   826       {  ret = glp_read_mps(csa->prob, GLP_MPS_FILE, NULL,
       
   827             csa->in_file);
       
   828          if (ret != 0) goto err1;
       
   829       }
       
   830       else if (csa->format == FMT_LP)
       
   831       {  ret = glp_read_lp(csa->prob, NULL, csa->in_file);
       
   832          if (ret != 0)
       
   833          {  xprintf("CPLEX LP file processing error\n");
       
   834             ret = EXIT_FAILURE;
       
   835             goto done;
       
   836          }
       
   837       }
       
   838       else if (csa->format == FMT_GLP)
       
   839       {  ret = glp_read_prob(csa->prob, 0, csa->in_file);
       
   840          if (ret != 0)
       
   841          {  xprintf("GLPK LP/MIP file processing error\n");
       
   842             ret = EXIT_FAILURE;
       
   843             goto done;
       
   844          }
       
   845       }
       
   846       else if (csa->format == FMT_MATHPROG)
       
   847       {  int k;
       
   848          /* allocate the translator workspace */
       
   849          csa->tran = glp_mpl_alloc_wksp();
       
   850          /* set seed value */
       
   851          if (csa->seed == 0x80000000)
       
   852          {  csa->seed = glp_time().lo;
       
   853             xprintf("Seed value %d will be used\n", csa->seed);
       
   854          }
       
   855          _glp_mpl_init_rand(csa->tran, csa->seed);
       
   856          /* read model section and optional data section */
       
   857          if (glp_mpl_read_model(csa->tran, csa->in_file, csa->ndf > 0))
       
   858 err2:    {  xprintf("MathProg model processing error\n");
       
   859             ret = EXIT_FAILURE;
       
   860             goto done;
       
   861          }
       
   862          /* read optional data section(s), if necessary */
       
   863          for (k = 1; k <= csa->ndf; k++)
       
   864          {  if (glp_mpl_read_data(csa->tran, csa->in_data[k]))
       
   865                goto err2;
       
   866          }
       
   867          /* generate the model */
       
   868          if (glp_mpl_generate(csa->tran, csa->out_dpy)) goto err2;
       
   869          /* build the problem instance from the model */
       
   870          glp_mpl_build_prob(csa->tran, csa->prob);
       
   871       }
       
   872       else if (csa->format == FMT_MIN_COST)
       
   873       {  csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data));
       
   874          ret = glp_read_mincost(csa->graph, offsetof(v_data, rhs),
       
   875             offsetof(a_data, low), offsetof(a_data, cap),
       
   876             offsetof(a_data, cost), csa->in_file);
       
   877          if (ret != 0)
       
   878          {  xprintf("DIMACS file processing error\n");
       
   879             ret = EXIT_FAILURE;
       
   880             goto done;
       
   881          }
       
   882          glp_mincost_lp(csa->prob, csa->graph, GLP_ON,
       
   883             offsetof(v_data, rhs), offsetof(a_data, low),
       
   884             offsetof(a_data, cap), offsetof(a_data, cost));
       
   885          glp_set_prob_name(csa->prob, csa->in_file);
       
   886       }
       
   887       else if (csa->format == FMT_MAX_FLOW)
       
   888       {  int s, t;
       
   889          csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data));
       
   890          ret = glp_read_maxflow(csa->graph, &s, &t,
       
   891             offsetof(a_data, cap), csa->in_file);
       
   892          if (ret != 0)
       
   893          {  xprintf("DIMACS file processing error\n");
       
   894             ret = EXIT_FAILURE;
       
   895             goto done;
       
   896          }
       
   897          glp_maxflow_lp(csa->prob, csa->graph, GLP_ON, s, t,
       
   898             offsetof(a_data, cap));
       
   899          glp_set_prob_name(csa->prob, csa->in_file);
       
   900       }
       
   901       else
       
   902          xassert(csa != csa);
       
   903       /*--------------------------------------------------------------*/
       
   904       /* change problem name, if required */
       
   905       if (csa->new_name != NULL)
       
   906          glp_set_prob_name(csa->prob, csa->new_name);
       
   907       /* change optimization direction, if required */
       
   908       if (csa->dir != 0)
       
   909          glp_set_obj_dir(csa->prob, csa->dir);
       
   910       /* sort elements of the constraint matrix */
       
   911       glp_sort_matrix(csa->prob);
       
   912       /*--------------------------------------------------------------*/
       
   913       /* write problem data in fixed MPS format, if required */
       
   914       if (csa->out_mps != NULL)
       
   915       {  ret = glp_write_mps(csa->prob, GLP_MPS_DECK, NULL,
       
   916             csa->out_mps);
       
   917          if (ret != 0)
       
   918          {  xprintf("Unable to write problem in fixed MPS format\n");
       
   919             ret = EXIT_FAILURE;
       
   920             goto done;
       
   921          }
       
   922       }
       
   923       /* write problem data in free MPS format, if required */
       
   924       if (csa->out_freemps != NULL)
       
   925       {  ret = glp_write_mps(csa->prob, GLP_MPS_FILE, NULL,
       
   926             csa->out_freemps);
       
   927          if (ret != 0)
       
   928          {  xprintf("Unable to write problem in free MPS format\n");
       
   929             ret = EXIT_FAILURE;
       
   930             goto done;
       
   931          }
       
   932       }
       
   933       /* write problem data in CPLEX LP format, if required */
       
   934       if (csa->out_cpxlp != NULL)
       
   935       {  ret = glp_write_lp(csa->prob, NULL, csa->out_cpxlp);
       
   936          if (ret != 0)
       
   937          {  xprintf("Unable to write problem in CPLEX LP format\n");
       
   938             ret = EXIT_FAILURE;
       
   939             goto done;
       
   940          }
       
   941       }
       
   942       /* write problem data in GLPK format, if required */
       
   943       if (csa->out_glp != NULL)
       
   944       {  ret = glp_write_prob(csa->prob, 0, csa->out_glp);
       
   945          if (ret != 0)
       
   946          {  xprintf("Unable to write problem in GLPK format\n");
       
   947             ret = EXIT_FAILURE;
       
   948             goto done;
       
   949          }
       
   950       }
       
   951       /* write problem data in OPB format, if required */
       
   952       if (csa->out_pb != NULL)
       
   953       {  ret = lpx_write_pb(csa->prob, csa->out_pb, 0, 0);
       
   954          if (ret != 0)
       
   955          {  xprintf("Unable to write problem in OPB format\n");
       
   956             ret = EXIT_FAILURE;
       
   957             goto done;
       
   958          }
       
   959       }
       
   960       /* write problem data in normalized OPB format, if required */
       
   961       if (csa->out_npb != NULL)
       
   962       {  ret = lpx_write_pb(csa->prob, csa->out_npb, 1, 1);
       
   963          if (ret != 0)
       
   964          {  xprintf(
       
   965                "Unable to write problem in normalized OPB format\n");
       
   966             ret = EXIT_FAILURE;
       
   967             goto done;
       
   968          }
       
   969       }
       
   970       /*--------------------------------------------------------------*/
       
   971       /* if only problem data check is required, skip computations */
       
   972       if (csa->check)
       
   973       {  ret = EXIT_SUCCESS;
       
   974          goto done;
       
   975       }
       
   976       /*--------------------------------------------------------------*/
       
   977       /* determine the solution type */
       
   978       if (!csa->nomip &&
       
   979           glp_get_num_int(csa->prob) + glp_get_num_bin(csa->prob) > 0)
       
   980       {  if (csa->solution == SOL_INTERIOR)
       
   981          {  xprintf("Interior-point method is not able to solve MIP pro"
       
   982                "blem; use --simplex\n");
       
   983             ret = EXIT_FAILURE;
       
   984             goto done;
       
   985          }
       
   986          csa->solution = SOL_INTEGER;
       
   987       }
       
   988       /*--------------------------------------------------------------*/
       
   989       /* if solution is provided, read it and skip computations */
       
   990       if (csa->in_res != NULL)
       
   991       {  if (csa->solution == SOL_BASIC)
       
   992             ret = glp_read_sol(csa->prob, csa->in_res);
       
   993          else if (csa->solution == SOL_INTERIOR)
       
   994             ret = glp_read_ipt(csa->prob, csa->in_res);
       
   995          else if (csa->solution == SOL_INTEGER)
       
   996             ret = glp_read_mip(csa->prob, csa->in_res);
       
   997          else
       
   998             xassert(csa != csa);
       
   999          if (ret != 0)
       
  1000          {  xprintf("Unable to read problem solution\n");
       
  1001             ret = EXIT_FAILURE;
       
  1002             goto done;
       
  1003          }
       
  1004          goto skip;
       
  1005       }
       
  1006       /*--------------------------------------------------------------*/
       
  1007       /* scale the problem data, if required */
       
  1008       if (csa->scale)
       
  1009       {  if (csa->solution == SOL_BASIC && !csa->smcp.presolve ||
       
  1010              csa->solution == SOL_INTERIOR ||
       
  1011              csa->solution == SOL_INTEGER && !csa->iocp.presolve)
       
  1012             glp_scale_prob(csa->prob, GLP_SF_AUTO);
       
  1013       }
       
  1014       /*--------------------------------------------------------------*/
       
  1015       /* construct starting LP basis */
       
  1016       if (csa->solution == SOL_BASIC && !csa->smcp.presolve ||
       
  1017           csa->solution == SOL_INTEGER && !csa->iocp.presolve)
       
  1018       {  if (csa->crash == USE_STD_BASIS)
       
  1019             glp_std_basis(csa->prob);
       
  1020          else if (csa->crash == USE_ADV_BASIS)
       
  1021             glp_adv_basis(csa->prob, 0);
       
  1022          else if (csa->crash == USE_CPX_BASIS)
       
  1023             glp_cpx_basis(csa->prob);
       
  1024          else if (csa->crash == USE_INI_BASIS)
       
  1025          {  ret = glp_read_sol(csa->prob, csa->ini_file);
       
  1026             if (ret != 0)
       
  1027             {  xprintf("Unable to read initial basis\n");
       
  1028                ret = EXIT_FAILURE;
       
  1029                goto done;
       
  1030             }
       
  1031          }
       
  1032          else
       
  1033             xassert(csa != csa);
       
  1034       }
       
  1035       /*--------------------------------------------------------------*/
       
  1036       /* solve the problem */
       
  1037       start = xtime();
       
  1038       if (csa->solution == SOL_BASIC)
       
  1039       {  if (!csa->exact)
       
  1040          {  glp_set_bfcp(csa->prob, &csa->bfcp);
       
  1041             glp_simplex(csa->prob, &csa->smcp);
       
  1042             if (csa->xcheck)
       
  1043             {  if (csa->smcp.presolve &&
       
  1044                    glp_get_status(csa->prob) != GLP_OPT)
       
  1045                   xprintf("If you need to check final basis for non-opt"
       
  1046                      "imal solution, use --nopresol\n");
       
  1047                else
       
  1048                   glp_exact(csa->prob, &csa->smcp);
       
  1049             }
       
  1050             if (csa->out_sol != NULL || csa->out_res != NULL)
       
  1051             {  if (csa->smcp.presolve &&
       
  1052                    glp_get_status(csa->prob) != GLP_OPT)
       
  1053                xprintf("If you need actual output for non-optimal solut"
       
  1054                   "ion, use --nopresol\n");
       
  1055             }
       
  1056          }
       
  1057          else
       
  1058             glp_exact(csa->prob, &csa->smcp);
       
  1059       }
       
  1060       else if (csa->solution == SOL_INTERIOR)
       
  1061          glp_interior(csa->prob, &csa->iptcp);
       
  1062       else if (csa->solution == SOL_INTEGER)
       
  1063       {  if (!csa->iocp.presolve)
       
  1064          {  glp_set_bfcp(csa->prob, &csa->bfcp);
       
  1065             glp_simplex(csa->prob, &csa->smcp);
       
  1066          }
       
  1067 #if 0
       
  1068          csa->iocp.msg_lev = GLP_MSG_DBG;
       
  1069          csa->iocp.pp_tech = GLP_PP_NONE;
       
  1070 #endif
       
  1071          glp_intopt(csa->prob, &csa->iocp);
       
  1072       }
       
  1073       else
       
  1074          xassert(csa != csa);
       
  1075       /*--------------------------------------------------------------*/
       
  1076       /* display statistics */
       
  1077       xprintf("Time used:   %.1f secs\n", xdifftime(xtime(), start));
       
  1078       {  glp_long tpeak;
       
  1079          char buf[50];
       
  1080          glp_mem_usage(NULL, NULL, NULL, &tpeak);
       
  1081          xprintf("Memory used: %.1f Mb (%s bytes)\n",
       
  1082             xltod(tpeak) / 1048576.0, xltoa(tpeak, buf));
       
  1083       }
       
  1084       /*--------------------------------------------------------------*/
       
  1085 skip: /* postsolve the model, if necessary */
       
  1086       if (csa->tran != NULL)
       
  1087       {  if (csa->solution == SOL_BASIC)
       
  1088             ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_SOL);
       
  1089          else if (csa->solution == SOL_INTERIOR)
       
  1090             ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_IPT);
       
  1091          else if (csa->solution == SOL_INTEGER)
       
  1092             ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_MIP);
       
  1093          else
       
  1094             xassert(csa != csa);
       
  1095          if (ret != 0)
       
  1096          {  xprintf("Model postsolving error\n");
       
  1097             ret = EXIT_FAILURE;
       
  1098             goto done;
       
  1099          }
       
  1100       }
       
  1101       /*--------------------------------------------------------------*/
       
  1102       /* write problem solution in printable format, if required */
       
  1103       if (csa->out_sol != NULL)
       
  1104       {  if (csa->solution == SOL_BASIC)
       
  1105             ret = lpx_print_sol(csa->prob, csa->out_sol);
       
  1106          else if (csa->solution == SOL_INTERIOR)
       
  1107             ret = lpx_print_ips(csa->prob, csa->out_sol);
       
  1108          else if (csa->solution == SOL_INTEGER)
       
  1109             ret = lpx_print_mip(csa->prob, csa->out_sol);
       
  1110          else
       
  1111             xassert(csa != csa);
       
  1112          if (ret != 0)
       
  1113          {  xprintf("Unable to write problem solution\n");
       
  1114             ret = EXIT_FAILURE;
       
  1115             goto done;
       
  1116          }
       
  1117       }
       
  1118       /* write problem solution in printable format, if required */
       
  1119       if (csa->out_res != NULL)
       
  1120       {  if (csa->solution == SOL_BASIC)
       
  1121             ret = glp_write_sol(csa->prob, csa->out_res);
       
  1122          else if (csa->solution == SOL_INTERIOR)
       
  1123             ret = glp_write_ipt(csa->prob, csa->out_res);
       
  1124          else if (csa->solution == SOL_INTEGER)
       
  1125             ret = glp_write_mip(csa->prob, csa->out_res);
       
  1126          else
       
  1127             xassert(csa != csa);
       
  1128          if (ret != 0)
       
  1129          {  xprintf("Unable to write problem solution\n");
       
  1130             ret = EXIT_FAILURE;
       
  1131             goto done;
       
  1132          }
       
  1133       }
       
  1134       /* write sensitivity analysis report, if required */
       
  1135       if (csa->out_ranges != NULL)
       
  1136       {  if (csa->solution == SOL_BASIC)
       
  1137          {  if (glp_get_status(csa->prob) == GLP_OPT)
       
  1138             {  if (glp_bf_exists(csa->prob))
       
  1139 ranges:        {  ret = glp_print_ranges(csa->prob, 0, NULL, 0,
       
  1140                      csa->out_ranges);
       
  1141                   if (ret != 0)
       
  1142                   {  xprintf("Unable to write sensitivity analysis repo"
       
  1143                         "rt\n");
       
  1144                      ret = EXIT_FAILURE;
       
  1145                      goto done;
       
  1146                   }
       
  1147                }
       
  1148                else
       
  1149                {  ret = glp_factorize(csa->prob);
       
  1150                   if (ret == 0) goto ranges;
       
  1151                   xprintf("Cannot produce sensitivity analysis report d"
       
  1152                      "ue to error in basis factorization (glp_factorize"
       
  1153                      " returned %d); try --nopresol\n", ret);
       
  1154                }
       
  1155             }
       
  1156             else
       
  1157                xprintf("Cannot produce sensitivity analysis report for "
       
  1158                   "non-optimal basic solution\n");
       
  1159          }
       
  1160          else
       
  1161             xprintf("Cannot produce sensitivity analysis report for int"
       
  1162                "erior-point or MIP solution\n");
       
  1163       }
       
  1164       /*--------------------------------------------------------------*/
       
  1165       /* all seems to be ok */
       
  1166       ret = EXIT_SUCCESS;
       
  1167       /*--------------------------------------------------------------*/
       
  1168 done: /* delete the LP/MIP problem object */
       
  1169       if (csa->prob != NULL)
       
  1170          glp_delete_prob(csa->prob);
       
  1171       /* free the translator workspace, if necessary */
       
  1172       if (csa->tran != NULL)
       
  1173          glp_mpl_free_wksp(csa->tran);
       
  1174       /* delete the network problem object, if necessary */
       
  1175       if (csa->graph != NULL)
       
  1176          glp_delete_graph(csa->graph);
       
  1177       xassert(gmp_pool_count() == 0);
       
  1178       gmp_free_mem();
       
  1179       /* close log file, if necessary */
       
  1180       if (csa->log_file != NULL) glp_close_tee();
       
  1181       /* check that no memory blocks are still allocated */
       
  1182       {  int count;
       
  1183          glp_long total;
       
  1184          glp_mem_usage(&count, NULL, &total, NULL);
       
  1185          if (count != 0)
       
  1186             xerror("Error: %d memory block(s) were lost\n", count);
       
  1187          xassert(count == 0);
       
  1188          xassert(total.lo == 0 && total.hi == 0);
       
  1189       }
       
  1190       /* free the GLPK environment */
       
  1191       glp_free_env();
       
  1192       /* return to the control program */
       
  1193       return ret;
       
  1194 }
       
  1195 
       
  1196 /* eof */