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