int main(int argc, char *argv[]) { LPX *lp; MPL *mpl = NULL; int ret; ulong_t start; /* parse command line parameters */ parse_cmdline(argc, argv); /* set available memory limit */ if (memlim >= 0) lib_mem_limit(ulmul(ulset(0, 1048576), ulset(0, memlim))); /* remove all output files specified in the command line */ if (display != NULL) remove(display); if (out_bas != NULL) remove(out_bas); if (out_sol != NULL) remove(out_sol); if (out_bnds != NULL) remove(out_bnds); if (out_mps != NULL) remove(out_mps); if (out_freemps != NULL) remove(out_freemps); if (out_cpxlp != NULL) remove(out_cpxlp); if (out_txt != NULL) remove(out_txt); if (out_glp != NULL) remove(out_glp); if (log_file != NULL) remove(log_file); /* open hardcopy file, if necessary */ if (log_file != NULL) { if (lib_open_log(log_file)) { print("Unable to create log file"); exit(EXIT_FAILURE); } } /* read problem data from the input file */ if (in_file == NULL) { print("No input file specified; try %s --help", argv[0]); exit(EXIT_FAILURE); } switch (format) { case 0: lp = lpx_read_mps(in_file); if (lp == NULL) { print("MPS file processing error"); exit(EXIT_FAILURE); } orig = 1; break; case 1: lp = lpx_read_cpxlp(in_file); if (lp == NULL) { print("CPLEX LP file processing error"); exit(EXIT_FAILURE); } break; case 2: /* initialize the translator database */ mpl = mpl_initialize(); /* read model section and optional data section */ ret = mpl_read_model(mpl, in_file, in_data != NULL); if (ret == 4) err: { print("Model processing error"); exit(EXIT_FAILURE); } xassert(ret == 1 || ret == 2); /* read data section, if necessary */ if (in_data != NULL) { xassert(ret == 1); ret = mpl_read_data(mpl, in_data); if (ret == 4) goto err; xassert(ret == 2); } /* generate model */ ret = mpl_generate(mpl, display); if (ret == 4) goto err; /* extract problem instance */ lp = lpx_extract_prob(mpl); xassert(lp != NULL); break; case 3: lp = lpx_read_prob(in_file); if (lp == NULL) { print("GNU LP file processing error"); exit(EXIT_FAILURE); } break; case 4: lp = lpx_read_freemps(in_file); if (lp == NULL) { print("MPS file processing error"); exit(EXIT_FAILURE); } break; default: xassert(format != format); } /* order rows and columns of the constraint matrix */ lpx_order_matrix(lp); /* change problem name (if required) */ if (newname != NULL) lpx_set_prob_name(lp, newname); /* change optimization direction (if required) */ if (dir != 0) lpx_set_obj_dir(lp, dir); /* write problem in fixed MPS format (if required) */ if (out_mps != NULL) { lpx_set_int_parm(lp, LPX_K_MPSORIG, orig); ret = lpx_write_mps(lp, out_mps); if (ret != 0) { print("Unable to write problem in fixed MPS format"); exit(EXIT_FAILURE); } } /* write problem in free MPS format (if required) */ if (out_freemps != NULL) { ret = lpx_write_freemps(lp, out_freemps); if (ret != 0) { print("Unable to write problem in free MPS format"); exit(EXIT_FAILURE); } } /* write problem in CPLEX LP format (if required) */ if (out_cpxlp != NULL) { ret = lpx_write_cpxlp(lp, out_cpxlp); if (ret != 0) { print("Unable to write problem in CPLEX LP format"); exit(EXIT_FAILURE); } } /* write problem in plain text format (if required) */ if (out_txt != NULL) { lpx_set_int_parm(lp, LPX_K_LPTORIG, orig); ret = lpx_print_prob(lp, out_txt); if (ret != 0) { print("Unable to write problem in plain text format"); exit(EXIT_FAILURE); } } /* write problem in GNU LP format (if required) */ if (out_glp != NULL) { ret = lpx_write_prob(lp, out_glp); if (ret != 0) { print("Unable to write problem in GNU LP format"); exit(EXIT_FAILURE); } } /* if only data check is required, skip computations */ if (check) goto skip; /* scale the problem data (if required) */ if (scale && (!presol || method == 1)) lpx_scale_prob(lp); /* build initial LP basis */ if (method == 0 && !presol && in_bas == NULL) { switch (basis) { case 0: lpx_std_basis(lp); break; case 1: if (lpx_get_num_rows(lp) > 0 && lpx_get_num_cols(lp) > 0) lpx_adv_basis(lp); break; case 2: if (lpx_get_num_rows(lp) > 0 && lpx_get_num_cols(lp) > 0) lpx_cpx_basis(lp); break; default: xassert(basis != basis); } } /* or read initial basis from input text file in MPS format */ if (in_bas != NULL) { if (method != 0) { print("Initial LP basis is useless for interior-point solve" "r and therefore ignored"); goto nobs; } lpx_set_int_parm(lp, LPX_K_MPSORIG, orig); ret = lpx_read_bas(lp, in_bas); if (ret != 0) { print("Unable to read initial LP basis"); exit(EXIT_FAILURE); } if (presol) { presol = 0; print("LP presolver disabled because initial LP basis has b" "een provided"); } nobs: ; } /* set some control parameters, which might be changed in the command line */ lpx_set_int_parm(lp, LPX_K_BFTYPE, bf_type); lpx_set_int_parm(lp, LPX_K_PRICE, price); if (!relax) lpx_set_real_parm(lp, LPX_K_RELAX, 0.0); lpx_set_int_parm(lp, LPX_K_PRESOL, presol); lpx_set_int_parm(lp, LPX_K_BRANCH, branch); lpx_set_int_parm(lp, LPX_K_BTRACK, btrack); lpx_set_real_parm(lp, LPX_K_TMLIM, (double)tmlim); lpx_set_int_parm(lp, LPX_K_BINARIZE, binarize); lpx_set_int_parm(lp, LPX_K_USECUTS, use_cuts); /* solve the problem */ start = xtime(); switch (method) { case 0: if (nomip || lpx_get_class(lp) == LPX_LP) { ret = (!exact ? lpx_simplex(lp) : lpx_exact(lp)); if (xcheck) { if (!presol || ret == LPX_E_OK) lpx_exact(lp); else print("If you need checking final basis for non-op" "timal solution, use --nopresol"); } if (presol && ret != LPX_E_OK && (out_bas != NULL || out_sol != NULL)) print("If you need actual output for non-optimal solu" "tion, use --nopresol"); } else { method = 2; if (!intopt) { ret = (!exact ? lpx_simplex(lp) : lpx_exact(lp)); if (xcheck && (!presol || ret == LPX_E_OK)) lpx_exact(lp); lpx_integer(lp); } else lpx_intopt(lp); } break; case 1: if (nomip || lpx_get_class(lp) == LPX_LP) lpx_interior(lp); else { print("Interior-point method is not able to solve MIP pr" "oblem; use --simplex"); exit(EXIT_FAILURE); } break; default: xassert(method != method); } /* display statistics */ print("Time used: %.1f secs", xdifftime(xtime(), start)); { ulong_t tpeak; char buf[50]; lib_mem_usage(NULL, NULL, NULL, &tpeak); print("Memory used: %.1f Mb (%s bytes)", (4294967296.0 * tpeak.hi + tpeak.lo) / 1048576.0, ultoa(tpeak, buf, 10)); } if (mpl != NULL && mpl_has_solve_stmt(mpl)) { int n, j, round; /* store the solution to the translator database */ n = lpx_get_num_cols(lp); round = lpx_get_int_parm(lp, LPX_K_ROUND); lpx_set_int_parm(lp, LPX_K_ROUND, 1); switch (method) { case 0: for (j = 1; j <= n; j++) mpl_put_col_value(mpl, j, lpx_get_col_prim(lp, j)); break; case 1: for (j = 1; j <= n; j++) mpl_put_col_value(mpl, j, lpx_ipt_col_prim(lp, j)); break; case 2: for (j = 1; j <= n; j++) mpl_put_col_value(mpl, j, lpx_mip_col_val(lp, j)); break; default: xassert(method != method); } lpx_set_int_parm(lp, LPX_K_ROUND, round); /* perform postsolving */ ret = mpl_postsolve(mpl); if (ret == 4) { print("Model postsolving error"); exit(EXIT_FAILURE); } xassert(ret == 3); } /* write final LP basis (if required) */ if (out_bas != NULL) { lpx_set_int_parm(lp, LPX_K_MPSORIG, orig); ret = lpx_write_bas(lp, out_bas); if (ret != 0) { print("Unable to write final LP basis"); exit(EXIT_FAILURE); } } /* write problem solution found by the solver (if required) */ if (out_sol != NULL) { switch (method) { case 0: ret = lpx_print_sol(lp, out_sol); break; case 1: ret = lpx_print_ips(lp, out_sol); break; case 2: ret = lpx_print_mip(lp, out_sol); break; default: xassert(method != method); } if (ret != 0) { print("Unable to write problem solution"); exit(EXIT_FAILURE); } } /* write sensitivity bounds information (if required) */ if (out_bnds != NULL) { if (method != 0) { print("Cannot write sensitivity bounds information for inte" "rior-point or MIP solution"); exit(EXIT_FAILURE); } ret = lpx_print_sens_bnds(lp, out_bnds); if (ret != 0) { print("Unable to write sensitivity bounds information"); exit(EXIT_FAILURE); } } skip: /* delete the problem object */ lpx_delete_prob(lp); /* if the translator database exists, destroy it */ if (mpl != NULL) mpl_terminate(mpl); xassert(gmp_pool_count() == 0); gmp_free_mem(); /* close the hardcopy file */ if (log_file != NULL) lib_close_log(); /* check that no memory blocks are still allocated */ { int count; ulong_t total; lib_mem_usage(&count, NULL, &total, NULL); xassert(count == 0); xassert(total.lo == 0 && total.hi == 0); } /* free the library environment */ lib_free_env(); /* return to the control program */ return 0; }
int glp_main(int argc, const char *argv[]) { /* stand-alone LP/MIP solver */ struct csa _csa, *csa = &_csa; int ret; xlong_t start; /* perform initialization */ csa->prob = glp_create_prob(); glp_get_bfcp(csa->prob, &csa->bfcp); glp_init_smcp(&csa->smcp); csa->smcp.presolve = GLP_ON; glp_init_iocp(&csa->iocp); csa->iocp.presolve = GLP_ON; csa->tran = NULL; csa->graph = NULL; csa->format = FMT_MPS_FILE; csa->in_file = NULL; csa->ndf = 0; csa->out_dpy = NULL; csa->solution = SOL_BASIC; csa->in_res = NULL; csa->dir = 0; csa->scale = 1; csa->out_sol = NULL; csa->out_res = NULL; csa->out_bnds = NULL; csa->check = 0; csa->new_name = NULL; csa->out_mps = NULL; csa->out_freemps = NULL; csa->out_cpxlp = NULL; csa->out_pb = NULL; csa->out_npb = NULL; csa->log_file = NULL; csa->crash = USE_ADV_BASIS; csa->exact = 0; csa->xcheck = 0; csa->nomip = 0; /* parse command-line parameters */ ret = parse_cmdline(csa, argc, argv); if (ret < 0) { ret = EXIT_SUCCESS; goto done; } if (ret > 0) { ret = EXIT_FAILURE; goto done; } /*--------------------------------------------------------------*/ /* remove all output files specified in the command line */ if (csa->out_dpy != NULL) remove(csa->out_dpy); if (csa->out_sol != NULL) remove(csa->out_sol); if (csa->out_res != NULL) remove(csa->out_res); if (csa->out_bnds != NULL) remove(csa->out_bnds); if (csa->out_mps != NULL) remove(csa->out_mps); if (csa->out_freemps != NULL) remove(csa->out_freemps); if (csa->out_cpxlp != NULL) remove(csa->out_cpxlp); if (csa->out_pb != NULL) remove(csa->out_pb); if (csa->out_npb != NULL) remove(csa->out_npb); if (csa->log_file != NULL) remove(csa->log_file); /*--------------------------------------------------------------*/ /* open log file, if required */ if (csa->log_file != NULL) { if (lib_open_log(csa->log_file)) { xprintf("Unable to create log file\n"); ret = EXIT_FAILURE; goto done; } } /*--------------------------------------------------------------*/ /* read problem data from the input file */ if (csa->in_file == NULL) { xprintf("No input problem file specified; try %s --help\n", argv[0]); ret = EXIT_FAILURE; goto done; } if (csa->format == FMT_MPS_DECK) { ret = glp_read_mps(csa->prob, GLP_MPS_DECK, NULL, csa->in_file); if (ret != 0) err1: { xprintf("MPS file processing error\n"); ret = EXIT_FAILURE; goto done; } } else if (csa->format == FMT_MPS_FILE) { ret = glp_read_mps(csa->prob, GLP_MPS_FILE, NULL, csa->in_file); if (ret != 0) goto err1; } else if (csa->format == FMT_CPLEX_LP) { ret = glp_read_lp(csa->prob, NULL, csa->in_file); if (ret != 0) { xprintf("CPLEX LP file processing error\n"); ret = EXIT_FAILURE; goto done; } } else if (csa->format == FMT_MATHPROG) { int k; /* allocate the translator workspace */ csa->tran = glp_mpl_alloc_wksp(); /* read model section and optional data section */ if (glp_mpl_read_model(csa->tran, csa->in_file, csa->ndf > 0)) err2: { xprintf("MathProg model processing error\n"); ret = EXIT_FAILURE; goto done; } /* read optional data section(s), if necessary */ for (k = 1; k <= csa->ndf; k++) { if (glp_mpl_read_data(csa->tran, csa->in_data[k])) goto err2; } /* generate the model */ if (glp_mpl_generate(csa->tran, csa->out_dpy)) goto err2; /* build the problem instance from the model */ glp_mpl_build_prob(csa->tran, csa->prob); } else if (csa->format == FMT_MIN_COST) { csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data)); ret = glp_read_mincost(csa->graph, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost), csa->in_file); if (ret != 0) { xprintf("DIMACS file processing error\n"); ret = EXIT_FAILURE; goto done; } glp_mincost_lp(csa->prob, csa->graph, GLP_ON, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost)); glp_set_prob_name(csa->prob, csa->in_file); } else if (csa->format == FMT_MAX_FLOW) { int s, t; csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data)); ret = glp_read_maxflow(csa->graph, &s, &t, offsetof(a_data, cap), csa->in_file); if (ret != 0) { xprintf("DIMACS file processing error\n"); ret = EXIT_FAILURE; goto done; } glp_maxflow_lp(csa->prob, csa->graph, GLP_ON, s, t, offsetof(a_data, cap)); glp_set_prob_name(csa->prob, csa->in_file); } else xassert(csa != csa); /*--------------------------------------------------------------*/ /* change problem name, if required */ if (csa->new_name != NULL) glp_set_prob_name(csa->prob, csa->new_name); /* change optimization direction, if required */ if (csa->dir != 0) glp_set_obj_dir(csa->prob, csa->dir); /* order rows and columns of the constraint matrix */ lpx_order_matrix(csa->prob); /*--------------------------------------------------------------*/ /* write problem data in fixed MPS format, if required */ if (csa->out_mps != NULL) { ret = glp_write_mps(csa->prob, GLP_MPS_DECK, NULL, csa->out_mps); if (ret != 0) { xprintf("Unable to write problem in fixed MPS format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in free MPS format, if required */ if (csa->out_freemps != NULL) { ret = glp_write_mps(csa->prob, GLP_MPS_FILE, NULL, csa->out_freemps); if (ret != 0) { xprintf("Unable to write problem in free MPS format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in CPLEX LP format, if required */ if (csa->out_cpxlp != NULL) { ret = glp_write_lp(csa->prob, NULL, csa->out_cpxlp); if (ret != 0) { xprintf("Unable to write problem in CPLEX LP format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in OPB format, if required */ if (csa->out_pb != NULL) { ret = lpx_write_pb(csa->prob, csa->out_pb, 0, 0); if (ret != 0) { xprintf("Unable to write problem in OPB format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in normalized OPB format, if required */ if (csa->out_npb != NULL) { ret = lpx_write_pb(csa->prob, csa->out_npb, 1, 1); if (ret != 0) { xprintf( "Unable to write problem in normalized OPB format\n"); ret = EXIT_FAILURE; goto done; } } /*--------------------------------------------------------------*/ /* if only problem data check is required, skip computations */ if (csa->check) { ret = EXIT_SUCCESS; goto done; } /*--------------------------------------------------------------*/ /* determine the solution type */ if (!csa->nomip && glp_get_num_int(csa->prob) + glp_get_num_bin(csa->prob) > 0) { if (csa->solution == SOL_INTERIOR) { xprintf("Interior-point method is not able to solve MIP pro" "blem; use --simplex\n"); ret = EXIT_FAILURE; goto done; } csa->solution = SOL_INTEGER; } /*--------------------------------------------------------------*/ /* if solution is provided, read it and skip computations */ if (csa->in_res != NULL) { if (csa->solution == SOL_BASIC) ret = glp_read_sol(csa->prob, csa->in_res); else if (csa->solution == SOL_INTERIOR) ret = glp_read_ipt(csa->prob, csa->in_res); else if (csa->solution == SOL_INTEGER) ret = glp_read_mip(csa->prob, csa->in_res); else xassert(csa != csa); if (ret != 0) { xprintf("Unable to read problem solution\n"); ret = EXIT_FAILURE; goto done; } goto skip; } /*--------------------------------------------------------------*/ /* scale the problem data, if required */ if (csa->scale) { if (csa->solution == SOL_BASIC && !csa->smcp.presolve || csa->solution == SOL_INTERIOR || csa->solution == SOL_INTEGER && !csa->iocp.presolve) glp_scale_prob(csa->prob, GLP_SF_AUTO); } /* construct starting LP basis */ if (csa->solution == SOL_BASIC && !csa->smcp.presolve || csa->solution == SOL_INTEGER && !csa->iocp.presolve) { if (csa->crash == USE_STD_BASIS) glp_std_basis(csa->prob); else if (csa->crash == USE_ADV_BASIS) glp_adv_basis(csa->prob, 0); else if (csa->crash == USE_CPX_BASIS) glp_cpx_basis(csa->prob); else xassert(csa != csa); } /*--------------------------------------------------------------*/ /* solve the problem */ start = xtime(); if (csa->solution == SOL_BASIC) { if (!csa->exact) { glp_set_bfcp(csa->prob, &csa->bfcp); glp_simplex(csa->prob, &csa->smcp); if (csa->xcheck) { if (csa->smcp.presolve && glp_get_status(csa->prob) != GLP_OPT) xprintf("If you need to check final basis for non-opt" "imal solution, use --nopresol\n"); else glp_exact(csa->prob, &csa->smcp); } if (csa->out_sol != NULL || csa->out_res != NULL) { if (csa->smcp.presolve && glp_get_status(csa->prob) != GLP_OPT) xprintf("If you need actual output for non-optimal solut" "ion, use --nopresol\n"); } } else glp_exact(csa->prob, &csa->smcp); } else if (csa->solution == SOL_INTERIOR) glp_interior(csa->prob, NULL); else if (csa->solution == SOL_INTEGER) { if (!csa->iocp.presolve) { glp_set_bfcp(csa->prob, &csa->bfcp); glp_simplex(csa->prob, &csa->smcp); } glp_intopt(csa->prob, &csa->iocp); } else xassert(csa != csa); /*--------------------------------------------------------------*/ /* display statistics */ xprintf("Time used: %.1f secs\n", xdifftime(xtime(), start)); { xlong_t tpeak; char buf[50]; lib_mem_usage(NULL, NULL, NULL, &tpeak); xprintf("Memory used: %.1f Mb (%s bytes)\n", xltod(tpeak) / 1048576.0, xltoa(tpeak, buf)); } /*--------------------------------------------------------------*/ skip: /* postsolve the model, if necessary */ if (csa->tran != NULL) { if (csa->solution == SOL_BASIC) ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_SOL); else if (csa->solution == SOL_INTERIOR) ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_IPT); else if (csa->solution == SOL_INTEGER) ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_MIP); else xassert(csa != csa); if (ret != 0) { xprintf("Model postsolving error\n"); ret = EXIT_FAILURE; goto done; } } /*--------------------------------------------------------------*/ /* write problem solution in printable format, if required */ if (csa->out_sol != NULL) { if (csa->solution == SOL_BASIC) ret = lpx_print_sol(csa->prob, csa->out_sol); else if (csa->solution == SOL_INTERIOR) ret = lpx_print_ips(csa->prob, csa->out_sol); else if (csa->solution == SOL_INTEGER) ret = lpx_print_mip(csa->prob, csa->out_sol); else xassert(csa != csa); if (ret != 0) { xprintf("Unable to write problem solution\n"); ret = EXIT_FAILURE; goto done; } } /* write problem solution in printable format, if required */ if (csa->out_res != NULL) { if (csa->solution == SOL_BASIC) ret = glp_write_sol(csa->prob, csa->out_res); else if (csa->solution == SOL_INTERIOR) ret = glp_write_ipt(csa->prob, csa->out_res); else if (csa->solution == SOL_INTEGER) ret = glp_write_mip(csa->prob, csa->out_res); else xassert(csa != csa); if (ret != 0) { xprintf("Unable to write problem solution\n"); ret = EXIT_FAILURE; goto done; } } /* write sensitivity bounds information, if required */ if (csa->out_bnds != NULL) { if (csa->solution == SOL_BASIC) { ret = lpx_print_sens_bnds(csa->prob, csa->out_bnds); if (ret != 0) { xprintf("Unable to write sensitivity bounds information " "\n"); ret = EXIT_FAILURE; goto done; } } else xprintf("Cannot write sensitivity bounds information for in" "terior-point or MIP solution\n"); } /*--------------------------------------------------------------*/ /* all seems to be ok */ ret = EXIT_SUCCESS; /*--------------------------------------------------------------*/ done: /* delete the LP/MIP problem object */ if (csa->prob != NULL) glp_delete_prob(csa->prob); /* free the translator workspace, if necessary */ if (csa->tran != NULL) glp_mpl_free_wksp(csa->tran); /* delete the network problem object, if necessary */ if (csa->graph != NULL) glp_delete_graph(csa->graph); xassert(gmp_pool_count() == 0); gmp_free_mem(); /* close log file, if necessary */ if (csa->log_file != NULL) lib_close_log(); /* check that no memory blocks are still allocated */ { int count; xlong_t total; lib_mem_usage(&count, NULL, &total, NULL); if (count != 0) xerror("Error: %d memory block(s) were lost\n", count); xassert(count == 0); xassert(total.lo == 0 && total.hi == 0); } /* free the library environment */ lib_free_env(); /* return to the control program */ return ret; }