1 /* mpl.c (processing model in GNU MathProg language) */
2 
3 /***********************************************************************
4 *  This code is part of GLPK (GNU Linear Programming Kit).
5 *  Copyright (C) 2008-2016 Free Software Foundation, Inc.
6 *  Written by Andrew Makhorin <mao@gnu.org>.
7 *
8 *  GLPK is free software: you can redistribute it and/or modify it
9 *  under the terms of the GNU General Public License as published by
10 *  the Free Software Foundation, either version 3 of the License, or
11 *  (at your option) any later version.
12 *
13 *  GLPK is distributed in the hope that it will be useful, but WITHOUT
14 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 *  License for more details.
17 *
18 *  You should have received a copy of the GNU General Public License
19 *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
20 ***********************************************************************/
21 
22 #include "mpl.h"
23 #include "prob.h"
24 
glp_mpl_alloc_wksp(void)25 glp_tran *glp_mpl_alloc_wksp(void)
26 {     /* allocate the MathProg translator workspace */
27       glp_tran *tran;
28       tran = mpl_initialize();
29       return tran;
30 }
31 
glp_mpl_init_rand(glp_tran * tran,int seed)32 void glp_mpl_init_rand(glp_tran *tran, int seed)
33 {     /* initialize pseudo-random number generator */
34       if (tran->phase != 0)
35          xerror("glp_mpl_init_rand: invalid call sequence\n");
36       rng_init_rand(tran->rand, seed);
37       return;
38 }
39 
glp_mpl_read_model(glp_tran * tran,const char * fname,int skip)40 int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip)
41 {     /* read and translate model section */
42       int ret;
43       if (tran->phase != 0)
44          xerror("glp_mpl_read_model: invalid call sequence\n");
45       ret = mpl_read_model(tran, (char *)fname, skip);
46       if (ret == 1 || ret == 2)
47          ret = 0;
48       else if (ret == 4)
49          ret = 1;
50       else
51          xassert(ret != ret);
52       return ret;
53 }
54 
glp_mpl_read_data(glp_tran * tran,const char * fname)55 int glp_mpl_read_data(glp_tran *tran, const char *fname)
56 {     /* read and translate data section */
57       int ret;
58       if (!(tran->phase == 1 || tran->phase == 2))
59          xerror("glp_mpl_read_data: invalid call sequence\n");
60       ret = mpl_read_data(tran, (char *)fname);
61       if (ret == 2)
62          ret = 0;
63       else if (ret == 4)
64          ret = 1;
65       else
66          xassert(ret != ret);
67       return ret;
68 }
69 
glp_mpl_generate(glp_tran * tran,const char * fname)70 int glp_mpl_generate(glp_tran *tran, const char *fname)
71 {     /* generate the model */
72       int ret;
73       if (!(tran->phase == 1 || tran->phase == 2))
74          xerror("glp_mpl_generate: invalid call sequence\n");
75       ret = mpl_generate(tran, (char *)fname);
76       if (ret == 3)
77          ret = 0;
78       else if (ret == 4)
79          ret = 1;
80       return ret;
81 }
82 
glp_mpl_build_prob(glp_tran * tran,glp_prob * prob)83 void glp_mpl_build_prob(glp_tran *tran, glp_prob *prob)
84 {     /* build LP/MIP problem instance from the model */
85       int m, n, i, j, t, kind, type, len, *ind;
86       double lb, ub, *val;
87       if (tran->phase != 3)
88          xerror("glp_mpl_build_prob: invalid call sequence\n");
89       /* erase the problem object */
90       glp_erase_prob(prob);
91       /* set problem name */
92       glp_set_prob_name(prob, mpl_get_prob_name(tran));
93       /* build rows (constraints) */
94       m = mpl_get_num_rows(tran);
95       if (m > 0)
96          glp_add_rows(prob, m);
97       for (i = 1; i <= m; i++)
98       {  /* set row name */
99          glp_set_row_name(prob, i, mpl_get_row_name(tran, i));
100          /* set row bounds */
101          type = mpl_get_row_bnds(tran, i, &lb, &ub);
102          switch (type)
103          {  case MPL_FR: type = GLP_FR; break;
104             case MPL_LO: type = GLP_LO; break;
105             case MPL_UP: type = GLP_UP; break;
106             case MPL_DB: type = GLP_DB; break;
107             case MPL_FX: type = GLP_FX; break;
108             default: xassert(type != type);
109          }
110          if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb)))
111          {  type = GLP_FX;
112             if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub;
113          }
114          glp_set_row_bnds(prob, i, type, lb, ub);
115          /* warn about non-zero constant term */
116          if (mpl_get_row_c0(tran, i) != 0.0)
117             xprintf("glp_mpl_build_prob: row %s; constant term %.12g ig"
118                "nored\n",
119                mpl_get_row_name(tran, i), mpl_get_row_c0(tran, i));
120       }
121       /* build columns (variables) */
122       n = mpl_get_num_cols(tran);
123       if (n > 0)
124          glp_add_cols(prob, n);
125       for (j = 1; j <= n; j++)
126       {  /* set column name */
127          glp_set_col_name(prob, j, mpl_get_col_name(tran, j));
128          /* set column kind */
129          kind = mpl_get_col_kind(tran, j);
130          switch (kind)
131          {  case MPL_NUM:
132                break;
133             case MPL_INT:
134             case MPL_BIN:
135                glp_set_col_kind(prob, j, GLP_IV);
136                break;
137             default:
138                xassert(kind != kind);
139          }
140          /* set column bounds */
141          type = mpl_get_col_bnds(tran, j, &lb, &ub);
142          switch (type)
143          {  case MPL_FR: type = GLP_FR; break;
144             case MPL_LO: type = GLP_LO; break;
145             case MPL_UP: type = GLP_UP; break;
146             case MPL_DB: type = GLP_DB; break;
147             case MPL_FX: type = GLP_FX; break;
148             default: xassert(type != type);
149          }
150          if (kind == MPL_BIN)
151          {  if (type == GLP_FR || type == GLP_UP || lb < 0.0) lb = 0.0;
152             if (type == GLP_FR || type == GLP_LO || ub > 1.0) ub = 1.0;
153             type = GLP_DB;
154          }
155          if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb)))
156          {  type = GLP_FX;
157             if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub;
158          }
159          glp_set_col_bnds(prob, j, type, lb, ub);
160       }
161       /* load the constraint matrix */
162       ind = xcalloc(1+n, sizeof(int));
163       val = xcalloc(1+n, sizeof(double));
164       for (i = 1; i <= m; i++)
165       {  len = mpl_get_mat_row(tran, i, ind, val);
166          glp_set_mat_row(prob, i, len, ind, val);
167       }
168       /* build objective function (the first objective is used) */
169       for (i = 1; i <= m; i++)
170       {  kind = mpl_get_row_kind(tran, i);
171          if (kind == MPL_MIN || kind == MPL_MAX)
172          {  /* set objective name */
173             glp_set_obj_name(prob, mpl_get_row_name(tran, i));
174             /* set optimization direction */
175             glp_set_obj_dir(prob, kind == MPL_MIN ? GLP_MIN : GLP_MAX);
176             /* set constant term */
177             glp_set_obj_coef(prob, 0, mpl_get_row_c0(tran, i));
178             /* set objective coefficients */
179             len = mpl_get_mat_row(tran, i, ind, val);
180             for (t = 1; t <= len; t++)
181                glp_set_obj_coef(prob, ind[t], val[t]);
182             break;
183          }
184       }
185       /* free working arrays */
186       xfree(ind);
187       xfree(val);
188       return;
189 }
190 
glp_mpl_postsolve(glp_tran * tran,glp_prob * prob,int sol)191 int glp_mpl_postsolve(glp_tran *tran, glp_prob *prob, int sol)
192 {     /* postsolve the model */
193       int i, j, m, n, stat, ret;
194       double prim, dual;
195       if (!(tran->phase == 3 && !tran->flag_p))
196          xerror("glp_mpl_postsolve: invalid call sequence\n");
197       if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP))
198          xerror("glp_mpl_postsolve: sol = %d; invalid parameter\n",
199             sol);
200       m = mpl_get_num_rows(tran);
201       n = mpl_get_num_cols(tran);
202       if (!(m == glp_get_num_rows(prob) &&
203             n == glp_get_num_cols(prob)))
204          xerror("glp_mpl_postsolve: wrong problem object\n");
205       if (!mpl_has_solve_stmt(tran))
206       {  ret = 0;
207          goto done;
208       }
209       for (i = 1; i <= m; i++)
210       {  if (sol == GLP_SOL)
211          {  stat = glp_get_row_stat(prob, i);
212             prim = glp_get_row_prim(prob, i);
213             dual = glp_get_row_dual(prob, i);
214          }
215          else if (sol == GLP_IPT)
216          {  stat = 0;
217             prim = glp_ipt_row_prim(prob, i);
218             dual = glp_ipt_row_dual(prob, i);
219          }
220          else if (sol == GLP_MIP)
221          {  stat = 0;
222             prim = glp_mip_row_val(prob, i);
223             dual = 0.0;
224          }
225          else
226             xassert(sol != sol);
227          if (fabs(prim) < 1e-9) prim = 0.0;
228          if (fabs(dual) < 1e-9) dual = 0.0;
229          mpl_put_row_soln(tran, i, stat, prim, dual);
230       }
231       for (j = 1; j <= n; j++)
232       {  if (sol == GLP_SOL)
233          {  stat = glp_get_col_stat(prob, j);
234             prim = glp_get_col_prim(prob, j);
235             dual = glp_get_col_dual(prob, j);
236          }
237          else if (sol == GLP_IPT)
238          {  stat = 0;
239             prim = glp_ipt_col_prim(prob, j);
240             dual = glp_ipt_col_dual(prob, j);
241          }
242          else if (sol == GLP_MIP)
243          {  stat = 0;
244             prim = glp_mip_col_val(prob, j);
245             dual = 0.0;
246          }
247          else
248             xassert(sol != sol);
249          if (fabs(prim) < 1e-9) prim = 0.0;
250          if (fabs(dual) < 1e-9) dual = 0.0;
251          mpl_put_col_soln(tran, j, stat, prim, dual);
252       }
253       ret = mpl_postsolve(tran);
254       if (ret == 3)
255          ret = 0;
256       else if (ret == 4)
257          ret = 1;
258 done: return ret;
259 }
260 
glp_mpl_free_wksp(glp_tran * tran)261 void glp_mpl_free_wksp(glp_tran *tran)
262 {     /* free the MathProg translator workspace */
263       mpl_terminate(tran);
264       return;
265 }
266 
267 /* eof */
268