/* glpsol_dan.c */ /* Modification to glpsol.c done by Daniel Segre' on June 27, 2001 */ /* Compiled (in glpk-2.4.1 directory) with the following command: gcc mysamples/glpsol_dan.c -I include libglpk.a -lm (which does not require installation) */ /*---------------------------------------------------------------------- -- This file is a part of the GLPK package. -- -- Copyright (C) 2000, 2001 Andrew Makhorin , -- Department for Applied Informatics, -- Moscow Aviation Institute, Moscow, Russia. -- All rights reserved. -- -- This code is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 2 of the License, or -- (at your option) any later version. -- -- This software is distributed "as is" in the hope that it will be -- useful, but WITHOUT ANY WARRANTY; without even the implied warranty -- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ----------------------------------------------------------------------*/ #include #include #include #include "glpk.h" #include "glpset.h" /*---------------------------------------------------------------------- -- This program is a stand-alone LP/MIP solver. For pure LP problems -- either the revised simplex method or the primal dual interior-point -- method can be used. For MIP problems the branch-and-bound procedure -- based on the revised simplex method is used. ----------------------------------------------------------------------*/ static char *version = "GLPSOL -- GLPK LP/MIP Solver, Version 2.4"; static char *in_fname = ""; /* name of the input text file */ static int format = 'M'; /* format of the input text file: 'M' - MPS 'L' - GLPK/L */ static int check = 0; /* if this flag is set, only input data checking is required */ static int method = 'S'; /* the method which should be used for solving a problem: 'S' - simplex method 'I' - interior point method */ static char *out_fname = "dan_output"; /* name of the output text file to which the final solution should be sent using printable format (optional) */ static int nomip = 0; /* if this flag is set, the solver considers all integer variables as continuous (this allows solving MIP problem as pure LP) */ /*---------------------------------------------------------------------- -- display_help - display help. -- -- This routine displays help information about the program as it is -- required by the GNU Coding Standards. */ static void display_help(char *my_name) { print("Usage: %s [options...] filename", my_name); print(""); print("General options:"); print(" --mps read LP/MIP data using MPS format (de" "fault)"); print(" --lpm read LP/MIP model written in GLPK/L m" "odeling"); print(" language"); print(" --check do not solve the problem, check input" " data only"); print(" --gener filename send generated LP/MIP problem to file" "name using"); print(" plain text format (has sense for --lp" "m only)"); print(" --min minimize the objective function"); print(" --max maximize the objective function"); print(" --ini find initial solution only"); print(" --any find any feasible solution"); print(" --fin find final solution (default)"); print(" --simplex use revised simplex method (default)") ; print(" --interior use interior point method (for pure L" "P only)"); print(" -o filename, --output filename"); print(" send solution to filename using print" "able format"); print(" --scale scale the problem (default)"); print(" --noscale do not scale the problem"); print(" --sum enable multiplets in constraint matri" "x (will be"); print(" replaced by their sum)"); print(" --nosum disable multiplets in constraint matr" "ix (default)"); print(" -h, --help display this help information and exi" "t"); print(" -v, --version display program version and exit"); print(""); print("Options specific to simplex method:"); print(" --textbook use options --noscale, --efi, --prima" "l, --nosteep,"); print(" --norelax, --first, and --lifo by def" "ault"); print(" --efi use EFI"); print(" --rfi-bg use RFI + Bartels and Golub updating " "technique"); print(" (default)"); print(" --rfi-ft use RFI + Forrest and Tomlin updating" " technique"); print(" --primal find feasible solution using primal s" "implex"); print(" (default)"); print(" --dual find feasible solution using dual sim" "plex"); print(" --steep use steepest edge technique (default)" ); print(" --nosteep use standard \"textbook\" pricing"); print(" --relax use Harris' two-pass ratio test (defa" "ult)"); print(" --norelax use standard \"textbook\" ratio test") ; print(""); print("Options specific to MIP:"); print(" --nomip consider all integer variables as con" "tinuous"); print(" (this allows solving MIP problem as p" "ure LP)"); print(" --first branch on first integer variable"); print(" --last branch on last integer variable"); print(" --drtom branch using heuristic by Driebeck an" "d Tomlin"); print(" (default)"); print(" --fifo backtrack using FIFO heuristic"); print(" --lifo backtrack using LIFO heuristic"); print(" --bestp backtrack using the best projection h" "euristic"); print(" (default)"); print(""); print("See the official GNU webpage dedicated to GLPK at"); print(""); print(""); print("Please, report bugs to "); exit(EXIT_SUCCESS); /* no return */ } /*---------------------------------------------------------------------- -- display_version - display version. -- -- This routine displays version information for the program as it is -- required by the GNU Coding Standards. */ static void display_version(void) { print("%s", version); print("Copyright (C) 2000, 2001 Andrew Makhorin "); print("This program is free software; you may redistribute it und" "er the terms of"); print("the GNU General Public License. This program has absolutel" "y no warranty."); exit(EXIT_SUCCESS); /* no return */ } /*---------------------------------------------------------------------- -- process_cmdline - process command line parameters. -- -- This routine processes parameters specified in command line. */ #define param(str) (strcmp(argv[k], str) == 0) static void process_cmdline(int argc, char *argv[]) { int k; for (k = 1; k < argc; k++) { if (param("--mps")) format = 'M'; else if (param("--lpm")) format = 'L'; else if (param("--check")) check = 1; else if (param("--gener")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { error("No gener file name specified"); exit(EXIT_FAILURE); } glp_set_cpar("fn_gener", argv[k]); } else if (param("--min")) glp_set_ipar("obj_dir", GLP_MIN); else if (param("--max")) glp_set_ipar("obj_dir", GLP_MAX); else if (param("--ini")) glp_set_ipar("option", GLP_INI); else if (param("--any")) glp_set_ipar("option", GLP_ANY); else if (param("--fin")) glp_set_ipar("option", GLP_FIN); else if (param("--simplex")) method = 'S'; else if (param("--interior")) method = 'I'; else if (param("-o") || param("--output")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { error("No output file name specified"); exit(EXIT_FAILURE); } out_fname = argv[k]; } else if (param("--scale")) glp_set_ipar("scale", GLP_YES); else if (param("--noscale")) glp_set_ipar("scale", GLP_NO); else if (param("--sum")) glp_set_ipar("sum_aij", GLP_YES); else if (param("--nosum")) glp_set_ipar("sum_aij", GLP_NO); else if (param("-h") || param("--help")) display_help(argv[0]); else if (param("-v") || param("--version")) display_version(); else if (param("--textbook")) { glp_set_ipar("scale", GLP_NO); glp_set_ipar("spx_form", GLP_EFI); glp_set_ipar("spx_use_dual", GLP_NO); glp_set_ipar("spx_steep", GLP_NO); glp_set_ipar("spx_relax", GLP_NO); glp_set_ipar("branch", GLP_FIRST); glp_set_ipar("btrack", GLP_LIFO); } else if (param("--efi")) glp_set_ipar("spx_form", GLP_EFI); else if (param("--rfi-bg")) glp_set_ipar("spx_form", GLP_RFI_BG); else if (param("--rfi-ft")) glp_set_ipar("spx_form", GLP_RFI_FT); else if (param("--primal")) glp_set_ipar("spx_use_dual", GLP_NO); else if (param("--dual")) glp_set_ipar("spx_use_dual", GLP_YES); else if (param("--steep")) glp_set_ipar("spx_steep", GLP_YES); else if (param("--nosteep")) glp_set_ipar("spx_steep", GLP_NO); else if (param("--relax")) glp_set_ipar("spx_relax", GLP_YES); else if (param("--norelax")) glp_set_ipar("spx_relax", GLP_NO); else if (param("--nomip")) nomip = 1; else if (param("--first")) glp_set_ipar("mip_branch", GLP_FIRST); else if (param("--last")) glp_set_ipar("mip_branch", GLP_LAST); else if (param("--drtom")) glp_set_ipar("mip_branch", GLP_DRTOM); else if (param("--fifo")) glp_set_ipar("mip_btrack", GLP_FIFO); else if (param("--lifo")) glp_set_ipar("mip_btrack", GLP_LIFO); else if (param("--bestp")) glp_set_ipar("mip_btrack", GLP_BESTP); else if (argv[k][0] == '-' || (argv[k][0] == '-' && argv[k][1] == '-')) { error("Invalid option `%s'; try %s --help", argv[k], argv[0]); exit(EXIT_FAILURE); } else { if (in_fname[0] != '\0') { error("Only one input file allowed"); exit(EXIT_FAILURE); } in_fname = argv[k]; } } return; } /*---------------------------------------------------------------------- -- main - main routine. -- -- This main routine is called by the control program and manages the -- solving process. */ int main(int argc, char *argv[]) { int option, nc_int, ret; clock_t t_start; /* initialize GLPK API */ glp_initialize(); /* process command line parameters */ process_cmdline(argc, argv); /* read LP problem data from the input file */ if (in_fname[0] == '\0') { error("No input file name specified; try %s --help", argv[0]); exit(EXIT_FAILURE); } glp_get_ipar("option", &option); switch (format) { case 'M': if (glp_read_mps(in_fname) != 0) { error("MPS file processing error"); exit(EXIT_FAILURE); } break; case 'L': if (glp_read_lpm(in_fname) != 0) { error("Model description processing error"); exit(EXIT_FAILURE); } break; default: insist(format != format); } glp_set_ipar("option", option); if (check) goto skip; /* solve LP/MIP problem */ t_start = clock(); glp_get_ipar("nc_int", &nc_int); switch (method) { case 'S': if (nc_int == 0 || nomip) ret = glp_simplex(); else ret = glp_integer(); break; case 'I': if (nc_int == 0 || nomip) ret = glp_interior(); else { error("Unable to solve MIP problem using interior point " "method"); exit(EXIT_FAILURE); } break; default: insist(method != method); } switch (ret) { case 0: break; case 1: error("Unable to solve the problem because of errors"); exit(EXIT_FAILURE); case 2: error("Optimization terminated because of solver failure"); break; default: insist(ret != ret); } /* display statistics */ print("Time used: %.1f secs", (double)(clock() - t_start) / (double)CLOCKS_PER_SEC); print("Memory used: %.1fM (%d bytes)", (double)mem_tpeak / (1024.0 * 1024.0), mem_tpeak); /* write final solution found by the solver */ if (out_fname[0] != '\0' && glp_print_sol(out_fname) != 0) { error("Unable to write problem solution"); exit(EXIT_FAILURE); } skip: /* terminate GLPK API */ /* glp_print_sol() */ glp_terminate(); /* exit to the control program */ return 0; } /* eof */