src/glpapi14.c
changeset 1 c445c931472f
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/glpapi14.c	Mon Dec 06 13:09:21 2010 +0100
     1.3 @@ -0,0 +1,274 @@
     1.4 +/* glpapi14.c (processing models in GNU MathProg language) */
     1.5 +
     1.6 +/***********************************************************************
     1.7 +*  This code is part of GLPK (GNU Linear Programming Kit).
     1.8 +*
     1.9 +*  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
    1.10 +*  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
    1.11 +*  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
    1.12 +*  E-mail: <mao@gnu.org>.
    1.13 +*
    1.14 +*  GLPK is free software: you can redistribute it and/or modify it
    1.15 +*  under the terms of the GNU General Public License as published by
    1.16 +*  the Free Software Foundation, either version 3 of the License, or
    1.17 +*  (at your option) any later version.
    1.18 +*
    1.19 +*  GLPK is distributed in the hope that it will be useful, but WITHOUT
    1.20 +*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    1.21 +*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
    1.22 +*  License for more details.
    1.23 +*
    1.24 +*  You should have received a copy of the GNU General Public License
    1.25 +*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
    1.26 +***********************************************************************/
    1.27 +
    1.28 +#define GLP_TRAN_DEFINED
    1.29 +typedef struct MPL glp_tran;
    1.30 +
    1.31 +#include "glpmpl.h"
    1.32 +#include "glpapi.h"
    1.33 +
    1.34 +glp_tran *glp_mpl_alloc_wksp(void)
    1.35 +{     /* allocate the MathProg translator workspace */
    1.36 +      glp_tran *tran;
    1.37 +      tran = mpl_initialize();
    1.38 +      return tran;
    1.39 +}
    1.40 +
    1.41 +#if 1 /* 08/XII-2009 */
    1.42 +void _glp_mpl_init_rand(glp_tran *tran, int seed)
    1.43 +{     if (tran->phase != 0)
    1.44 +         xerror("glp_mpl_init_rand: invalid call sequence\n");
    1.45 +      rng_init_rand(tran->rand, seed);
    1.46 +      return;
    1.47 +}
    1.48 +#endif
    1.49 +
    1.50 +int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip)
    1.51 +{     /* read and translate model section */
    1.52 +      int ret;
    1.53 +      if (tran->phase != 0)
    1.54 +         xerror("glp_mpl_read_model: invalid call sequence\n");
    1.55 +      ret = mpl_read_model(tran, (char *)fname, skip);
    1.56 +      if (ret == 1 || ret == 2)
    1.57 +         ret = 0;
    1.58 +      else if (ret == 4)
    1.59 +         ret = 1;
    1.60 +      else
    1.61 +         xassert(ret != ret);
    1.62 +      return ret;
    1.63 +}
    1.64 +
    1.65 +int glp_mpl_read_data(glp_tran *tran, const char *fname)
    1.66 +{     /* read and translate data section */
    1.67 +      int ret;
    1.68 +      if (!(tran->phase == 1 || tran->phase == 2))
    1.69 +         xerror("glp_mpl_read_data: invalid call sequence\n");
    1.70 +      ret = mpl_read_data(tran, (char *)fname);
    1.71 +      if (ret == 2)
    1.72 +         ret = 0;
    1.73 +      else if (ret == 4)
    1.74 +         ret = 1;
    1.75 +      else
    1.76 +         xassert(ret != ret);
    1.77 +      return ret;
    1.78 +}
    1.79 +
    1.80 +int glp_mpl_generate(glp_tran *tran, const char *fname)
    1.81 +{     /* generate the model */
    1.82 +      int ret;
    1.83 +      if (!(tran->phase == 1 || tran->phase == 2))
    1.84 +         xerror("glp_mpl_generate: invalid call sequence\n");
    1.85 +      ret = mpl_generate(tran, (char *)fname);
    1.86 +      if (ret == 3)
    1.87 +         ret = 0;
    1.88 +      else if (ret == 4)
    1.89 +         ret = 1;
    1.90 +      return ret;
    1.91 +}
    1.92 +
    1.93 +void glp_mpl_build_prob(glp_tran *tran, glp_prob *prob)
    1.94 +{     /* build LP/MIP problem instance from the model */
    1.95 +      int m, n, i, j, t, kind, type, len, *ind;
    1.96 +      double lb, ub, *val;
    1.97 +      if (tran->phase != 3)
    1.98 +         xerror("glp_mpl_build_prob: invalid call sequence\n");
    1.99 +      /* erase the problem object */
   1.100 +      glp_erase_prob(prob);
   1.101 +      /* set problem name */
   1.102 +      glp_set_prob_name(prob, mpl_get_prob_name(tran));
   1.103 +      /* build rows (constraints) */
   1.104 +      m = mpl_get_num_rows(tran);
   1.105 +      if (m > 0)
   1.106 +         glp_add_rows(prob, m);
   1.107 +      for (i = 1; i <= m; i++)
   1.108 +      {  /* set row name */
   1.109 +         glp_set_row_name(prob, i, mpl_get_row_name(tran, i));
   1.110 +         /* set row bounds */
   1.111 +         type = mpl_get_row_bnds(tran, i, &lb, &ub);
   1.112 +         switch (type)
   1.113 +         {  case MPL_FR: type = GLP_FR; break;
   1.114 +            case MPL_LO: type = GLP_LO; break;
   1.115 +            case MPL_UP: type = GLP_UP; break;
   1.116 +            case MPL_DB: type = GLP_DB; break;
   1.117 +            case MPL_FX: type = GLP_FX; break;
   1.118 +            default: xassert(type != type);
   1.119 +         }
   1.120 +         if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb)))
   1.121 +         {  type = GLP_FX;
   1.122 +            if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub;
   1.123 +         }
   1.124 +         glp_set_row_bnds(prob, i, type, lb, ub);
   1.125 +         /* warn about non-zero constant term */
   1.126 +         if (mpl_get_row_c0(tran, i) != 0.0)
   1.127 +            xprintf("glp_mpl_build_prob: row %s; constant term %.12g ig"
   1.128 +               "nored\n",
   1.129 +               mpl_get_row_name(tran, i), mpl_get_row_c0(tran, i));
   1.130 +      }
   1.131 +      /* build columns (variables) */
   1.132 +      n = mpl_get_num_cols(tran);
   1.133 +      if (n > 0)
   1.134 +         glp_add_cols(prob, n);
   1.135 +      for (j = 1; j <= n; j++)
   1.136 +      {  /* set column name */
   1.137 +         glp_set_col_name(prob, j, mpl_get_col_name(tran, j));
   1.138 +         /* set column kind */
   1.139 +         kind = mpl_get_col_kind(tran, j);
   1.140 +         switch (kind)
   1.141 +         {  case MPL_NUM:
   1.142 +               break;
   1.143 +            case MPL_INT:
   1.144 +            case MPL_BIN:
   1.145 +               glp_set_col_kind(prob, j, GLP_IV);
   1.146 +               break;
   1.147 +            default:
   1.148 +               xassert(kind != kind);
   1.149 +         }
   1.150 +         /* set column bounds */
   1.151 +         type = mpl_get_col_bnds(tran, j, &lb, &ub);
   1.152 +         switch (type)
   1.153 +         {  case MPL_FR: type = GLP_FR; break;
   1.154 +            case MPL_LO: type = GLP_LO; break;
   1.155 +            case MPL_UP: type = GLP_UP; break;
   1.156 +            case MPL_DB: type = GLP_DB; break;
   1.157 +            case MPL_FX: type = GLP_FX; break;
   1.158 +            default: xassert(type != type);
   1.159 +         }
   1.160 +         if (kind == MPL_BIN)
   1.161 +         {  if (type == GLP_FR || type == GLP_UP || lb < 0.0) lb = 0.0;
   1.162 +            if (type == GLP_FR || type == GLP_LO || ub > 1.0) ub = 1.0;
   1.163 +            type = GLP_DB;
   1.164 +         }
   1.165 +         if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb)))
   1.166 +         {  type = GLP_FX;
   1.167 +            if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub;
   1.168 +         }
   1.169 +         glp_set_col_bnds(prob, j, type, lb, ub);
   1.170 +      }
   1.171 +      /* load the constraint matrix */
   1.172 +      ind = xcalloc(1+n, sizeof(int));
   1.173 +      val = xcalloc(1+n, sizeof(double));
   1.174 +      for (i = 1; i <= m; i++)
   1.175 +      {  len = mpl_get_mat_row(tran, i, ind, val);
   1.176 +         glp_set_mat_row(prob, i, len, ind, val);
   1.177 +      }
   1.178 +      /* build objective function (the first objective is used) */
   1.179 +      for (i = 1; i <= m; i++)
   1.180 +      {  kind = mpl_get_row_kind(tran, i);
   1.181 +         if (kind == MPL_MIN || kind == MPL_MAX)
   1.182 +         {  /* set objective name */
   1.183 +            glp_set_obj_name(prob, mpl_get_row_name(tran, i));
   1.184 +            /* set optimization direction */
   1.185 +            glp_set_obj_dir(prob, kind == MPL_MIN ? GLP_MIN : GLP_MAX);
   1.186 +            /* set constant term */
   1.187 +            glp_set_obj_coef(prob, 0, mpl_get_row_c0(tran, i));
   1.188 +            /* set objective coefficients */
   1.189 +            len = mpl_get_mat_row(tran, i, ind, val);
   1.190 +            for (t = 1; t <= len; t++)
   1.191 +               glp_set_obj_coef(prob, ind[t], val[t]);
   1.192 +            break;
   1.193 +         }
   1.194 +      }
   1.195 +      /* free working arrays */
   1.196 +      xfree(ind);
   1.197 +      xfree(val);
   1.198 +      return;
   1.199 +}
   1.200 +
   1.201 +int glp_mpl_postsolve(glp_tran *tran, glp_prob *prob, int sol)
   1.202 +{     /* postsolve the model */
   1.203 +      int i, j, m, n, stat, ret;
   1.204 +      double prim, dual;
   1.205 +      if (!(tran->phase == 3 && !tran->flag_p))
   1.206 +         xerror("glp_mpl_postsolve: invalid call sequence\n");
   1.207 +      if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP))
   1.208 +         xerror("glp_mpl_postsolve: sol = %d; invalid parameter\n",
   1.209 +            sol);
   1.210 +      m = mpl_get_num_rows(tran);
   1.211 +      n = mpl_get_num_cols(tran);
   1.212 +      if (!(m == glp_get_num_rows(prob) &&
   1.213 +            n == glp_get_num_cols(prob)))
   1.214 +         xerror("glp_mpl_postsolve: wrong problem object\n");
   1.215 +      if (!mpl_has_solve_stmt(tran))
   1.216 +      {  ret = 0;
   1.217 +         goto done;
   1.218 +      }
   1.219 +      for (i = 1; i <= m; i++)
   1.220 +      {  if (sol == GLP_SOL)
   1.221 +         {  stat = glp_get_row_stat(prob, i);
   1.222 +            prim = glp_get_row_prim(prob, i);
   1.223 +            dual = glp_get_row_dual(prob, i);
   1.224 +         }
   1.225 +         else if (sol == GLP_IPT)
   1.226 +         {  stat = 0;
   1.227 +            prim = glp_ipt_row_prim(prob, i);
   1.228 +            dual = glp_ipt_row_dual(prob, i);
   1.229 +         }
   1.230 +         else if (sol == GLP_MIP)
   1.231 +         {  stat = 0;
   1.232 +            prim = glp_mip_row_val(prob, i);
   1.233 +            dual = 0.0;
   1.234 +         }
   1.235 +         else
   1.236 +            xassert(sol != sol);
   1.237 +         if (fabs(prim) < 1e-9) prim = 0.0;
   1.238 +         if (fabs(dual) < 1e-9) dual = 0.0;
   1.239 +         mpl_put_row_soln(tran, i, stat, prim, dual);
   1.240 +      }
   1.241 +      for (j = 1; j <= n; j++)
   1.242 +      {  if (sol == GLP_SOL)
   1.243 +         {  stat = glp_get_col_stat(prob, j);
   1.244 +            prim = glp_get_col_prim(prob, j);
   1.245 +            dual = glp_get_col_dual(prob, j);
   1.246 +         }
   1.247 +         else if (sol == GLP_IPT)
   1.248 +         {  stat = 0;
   1.249 +            prim = glp_ipt_col_prim(prob, j);
   1.250 +            dual = glp_ipt_col_dual(prob, j);
   1.251 +         }
   1.252 +         else if (sol == GLP_MIP)
   1.253 +         {  stat = 0;
   1.254 +            prim = glp_mip_col_val(prob, j);
   1.255 +            dual = 0.0;
   1.256 +         }
   1.257 +         else
   1.258 +            xassert(sol != sol);
   1.259 +         if (fabs(prim) < 1e-9) prim = 0.0;
   1.260 +         if (fabs(dual) < 1e-9) dual = 0.0;
   1.261 +         mpl_put_col_soln(tran, j, stat, prim, dual);
   1.262 +      }
   1.263 +      ret = mpl_postsolve(tran);
   1.264 +      if (ret == 3)
   1.265 +         ret = 0;
   1.266 +      else if (ret == 4)
   1.267 +         ret = 1;
   1.268 +done: return ret;
   1.269 +}
   1.270 +
   1.271 +void glp_mpl_free_wksp(glp_tran *tran)
   1.272 +{     /* free the MathProg translator workspace */
   1.273 +      mpl_terminate(tran);
   1.274 +      return;
   1.275 +}
   1.276 +
   1.277 +/* eof */