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