alpar@1: /* glpapi14.c (processing models in GNU MathProg language) */ alpar@1: alpar@1: /*********************************************************************** alpar@1: * This code is part of GLPK (GNU Linear Programming Kit). alpar@1: * alpar@1: * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, alpar@1: * 2009, 2010 Andrew Makhorin, Department for Applied Informatics, alpar@1: * Moscow Aviation Institute, Moscow, Russia. All rights reserved. alpar@1: * E-mail: . alpar@1: * alpar@1: * GLPK is free software: you can redistribute it and/or modify it alpar@1: * under the terms of the GNU General Public License as published by alpar@1: * the Free Software Foundation, either version 3 of the License, or alpar@1: * (at your option) any later version. alpar@1: * alpar@1: * GLPK is distributed in the hope that it will be useful, but WITHOUT alpar@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY alpar@1: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public alpar@1: * License for more details. alpar@1: * alpar@1: * You should have received a copy of the GNU General Public License alpar@1: * along with GLPK. If not, see . alpar@1: ***********************************************************************/ alpar@1: alpar@1: #define GLP_TRAN_DEFINED alpar@1: typedef struct MPL glp_tran; alpar@1: alpar@1: #include "glpmpl.h" alpar@1: #include "glpapi.h" alpar@1: alpar@1: glp_tran *glp_mpl_alloc_wksp(void) alpar@1: { /* allocate the MathProg translator workspace */ alpar@1: glp_tran *tran; alpar@1: tran = mpl_initialize(); alpar@1: return tran; alpar@1: } alpar@1: alpar@1: #if 1 /* 08/XII-2009 */ alpar@1: void _glp_mpl_init_rand(glp_tran *tran, int seed) alpar@1: { if (tran->phase != 0) alpar@1: xerror("glp_mpl_init_rand: invalid call sequence\n"); alpar@1: rng_init_rand(tran->rand, seed); alpar@1: return; alpar@1: } alpar@1: #endif alpar@1: alpar@1: int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip) alpar@1: { /* read and translate model section */ alpar@1: int ret; alpar@1: if (tran->phase != 0) alpar@1: xerror("glp_mpl_read_model: invalid call sequence\n"); alpar@1: ret = mpl_read_model(tran, (char *)fname, skip); alpar@1: if (ret == 1 || ret == 2) alpar@1: ret = 0; alpar@1: else if (ret == 4) alpar@1: ret = 1; alpar@1: else alpar@1: xassert(ret != ret); alpar@1: return ret; alpar@1: } alpar@1: alpar@1: int glp_mpl_read_data(glp_tran *tran, const char *fname) alpar@1: { /* read and translate data section */ alpar@1: int ret; alpar@1: if (!(tran->phase == 1 || tran->phase == 2)) alpar@1: xerror("glp_mpl_read_data: invalid call sequence\n"); alpar@1: ret = mpl_read_data(tran, (char *)fname); alpar@1: if (ret == 2) alpar@1: ret = 0; alpar@1: else if (ret == 4) alpar@1: ret = 1; alpar@1: else alpar@1: xassert(ret != ret); alpar@1: return ret; alpar@1: } alpar@1: alpar@1: int glp_mpl_generate(glp_tran *tran, const char *fname) alpar@1: { /* generate the model */ alpar@1: int ret; alpar@1: if (!(tran->phase == 1 || tran->phase == 2)) alpar@1: xerror("glp_mpl_generate: invalid call sequence\n"); alpar@1: ret = mpl_generate(tran, (char *)fname); alpar@1: if (ret == 3) alpar@1: ret = 0; alpar@1: else if (ret == 4) alpar@1: ret = 1; alpar@1: return ret; alpar@1: } alpar@1: alpar@1: void glp_mpl_build_prob(glp_tran *tran, glp_prob *prob) alpar@1: { /* build LP/MIP problem instance from the model */ alpar@1: int m, n, i, j, t, kind, type, len, *ind; alpar@1: double lb, ub, *val; alpar@1: if (tran->phase != 3) alpar@1: xerror("glp_mpl_build_prob: invalid call sequence\n"); alpar@1: /* erase the problem object */ alpar@1: glp_erase_prob(prob); alpar@1: /* set problem name */ alpar@1: glp_set_prob_name(prob, mpl_get_prob_name(tran)); alpar@1: /* build rows (constraints) */ alpar@1: m = mpl_get_num_rows(tran); alpar@1: if (m > 0) alpar@1: glp_add_rows(prob, m); alpar@1: for (i = 1; i <= m; i++) alpar@1: { /* set row name */ alpar@1: glp_set_row_name(prob, i, mpl_get_row_name(tran, i)); alpar@1: /* set row bounds */ alpar@1: type = mpl_get_row_bnds(tran, i, &lb, &ub); alpar@1: switch (type) alpar@1: { case MPL_FR: type = GLP_FR; break; alpar@1: case MPL_LO: type = GLP_LO; break; alpar@1: case MPL_UP: type = GLP_UP; break; alpar@1: case MPL_DB: type = GLP_DB; break; alpar@1: case MPL_FX: type = GLP_FX; break; alpar@1: default: xassert(type != type); alpar@1: } alpar@1: if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb))) alpar@1: { type = GLP_FX; alpar@1: if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub; alpar@1: } alpar@1: glp_set_row_bnds(prob, i, type, lb, ub); alpar@1: /* warn about non-zero constant term */ alpar@1: if (mpl_get_row_c0(tran, i) != 0.0) alpar@1: xprintf("glp_mpl_build_prob: row %s; constant term %.12g ig" alpar@1: "nored\n", alpar@1: mpl_get_row_name(tran, i), mpl_get_row_c0(tran, i)); alpar@1: } alpar@1: /* build columns (variables) */ alpar@1: n = mpl_get_num_cols(tran); alpar@1: if (n > 0) alpar@1: glp_add_cols(prob, n); alpar@1: for (j = 1; j <= n; j++) alpar@1: { /* set column name */ alpar@1: glp_set_col_name(prob, j, mpl_get_col_name(tran, j)); alpar@1: /* set column kind */ alpar@1: kind = mpl_get_col_kind(tran, j); alpar@1: switch (kind) alpar@1: { case MPL_NUM: alpar@1: break; alpar@1: case MPL_INT: alpar@1: case MPL_BIN: alpar@1: glp_set_col_kind(prob, j, GLP_IV); alpar@1: break; alpar@1: default: alpar@1: xassert(kind != kind); alpar@1: } alpar@1: /* set column bounds */ alpar@1: type = mpl_get_col_bnds(tran, j, &lb, &ub); alpar@1: switch (type) alpar@1: { case MPL_FR: type = GLP_FR; break; alpar@1: case MPL_LO: type = GLP_LO; break; alpar@1: case MPL_UP: type = GLP_UP; break; alpar@1: case MPL_DB: type = GLP_DB; break; alpar@1: case MPL_FX: type = GLP_FX; break; alpar@1: default: xassert(type != type); alpar@1: } alpar@1: if (kind == MPL_BIN) alpar@1: { if (type == GLP_FR || type == GLP_UP || lb < 0.0) lb = 0.0; alpar@1: if (type == GLP_FR || type == GLP_LO || ub > 1.0) ub = 1.0; alpar@1: type = GLP_DB; alpar@1: } alpar@1: if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb))) alpar@1: { type = GLP_FX; alpar@1: if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub; alpar@1: } alpar@1: glp_set_col_bnds(prob, j, type, lb, ub); alpar@1: } alpar@1: /* load the constraint matrix */ alpar@1: ind = xcalloc(1+n, sizeof(int)); alpar@1: val = xcalloc(1+n, sizeof(double)); alpar@1: for (i = 1; i <= m; i++) alpar@1: { len = mpl_get_mat_row(tran, i, ind, val); alpar@1: glp_set_mat_row(prob, i, len, ind, val); alpar@1: } alpar@1: /* build objective function (the first objective is used) */ alpar@1: for (i = 1; i <= m; i++) alpar@1: { kind = mpl_get_row_kind(tran, i); alpar@1: if (kind == MPL_MIN || kind == MPL_MAX) alpar@1: { /* set objective name */ alpar@1: glp_set_obj_name(prob, mpl_get_row_name(tran, i)); alpar@1: /* set optimization direction */ alpar@1: glp_set_obj_dir(prob, kind == MPL_MIN ? GLP_MIN : GLP_MAX); alpar@1: /* set constant term */ alpar@1: glp_set_obj_coef(prob, 0, mpl_get_row_c0(tran, i)); alpar@1: /* set objective coefficients */ alpar@1: len = mpl_get_mat_row(tran, i, ind, val); alpar@1: for (t = 1; t <= len; t++) alpar@1: glp_set_obj_coef(prob, ind[t], val[t]); alpar@1: break; alpar@1: } alpar@1: } alpar@1: /* free working arrays */ alpar@1: xfree(ind); alpar@1: xfree(val); alpar@1: return; alpar@1: } alpar@1: alpar@1: int glp_mpl_postsolve(glp_tran *tran, glp_prob *prob, int sol) alpar@1: { /* postsolve the model */ alpar@1: int i, j, m, n, stat, ret; alpar@1: double prim, dual; alpar@1: if (!(tran->phase == 3 && !tran->flag_p)) alpar@1: xerror("glp_mpl_postsolve: invalid call sequence\n"); alpar@1: if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP)) alpar@1: xerror("glp_mpl_postsolve: sol = %d; invalid parameter\n", alpar@1: sol); alpar@1: m = mpl_get_num_rows(tran); alpar@1: n = mpl_get_num_cols(tran); alpar@1: if (!(m == glp_get_num_rows(prob) && alpar@1: n == glp_get_num_cols(prob))) alpar@1: xerror("glp_mpl_postsolve: wrong problem object\n"); alpar@1: if (!mpl_has_solve_stmt(tran)) alpar@1: { ret = 0; alpar@1: goto done; alpar@1: } alpar@1: for (i = 1; i <= m; i++) alpar@1: { if (sol == GLP_SOL) alpar@1: { stat = glp_get_row_stat(prob, i); alpar@1: prim = glp_get_row_prim(prob, i); alpar@1: dual = glp_get_row_dual(prob, i); alpar@1: } alpar@1: else if (sol == GLP_IPT) alpar@1: { stat = 0; alpar@1: prim = glp_ipt_row_prim(prob, i); alpar@1: dual = glp_ipt_row_dual(prob, i); alpar@1: } alpar@1: else if (sol == GLP_MIP) alpar@1: { stat = 0; alpar@1: prim = glp_mip_row_val(prob, i); alpar@1: dual = 0.0; alpar@1: } alpar@1: else alpar@1: xassert(sol != sol); alpar@1: if (fabs(prim) < 1e-9) prim = 0.0; alpar@1: if (fabs(dual) < 1e-9) dual = 0.0; alpar@1: mpl_put_row_soln(tran, i, stat, prim, dual); alpar@1: } alpar@1: for (j = 1; j <= n; j++) alpar@1: { if (sol == GLP_SOL) alpar@1: { stat = glp_get_col_stat(prob, j); alpar@1: prim = glp_get_col_prim(prob, j); alpar@1: dual = glp_get_col_dual(prob, j); alpar@1: } alpar@1: else if (sol == GLP_IPT) alpar@1: { stat = 0; alpar@1: prim = glp_ipt_col_prim(prob, j); alpar@1: dual = glp_ipt_col_dual(prob, j); alpar@1: } alpar@1: else if (sol == GLP_MIP) alpar@1: { stat = 0; alpar@1: prim = glp_mip_col_val(prob, j); alpar@1: dual = 0.0; alpar@1: } alpar@1: else alpar@1: xassert(sol != sol); alpar@1: if (fabs(prim) < 1e-9) prim = 0.0; alpar@1: if (fabs(dual) < 1e-9) dual = 0.0; alpar@1: mpl_put_col_soln(tran, j, stat, prim, dual); alpar@1: } alpar@1: ret = mpl_postsolve(tran); alpar@1: if (ret == 3) alpar@1: ret = 0; alpar@1: else if (ret == 4) alpar@1: ret = 1; alpar@1: done: return ret; alpar@1: } alpar@1: alpar@1: void glp_mpl_free_wksp(glp_tran *tran) alpar@1: { /* free the MathProg translator workspace */ alpar@1: mpl_terminate(tran); alpar@1: return; alpar@1: } alpar@1: alpar@1: /* eof */