src/glpapi19.c
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 06 Dec 2010 13:09:21 +0100
changeset 1 c445c931472f
permissions -rw-r--r--
Import glpk-4.45

- Generated files and doc/notes are removed
     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 */