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