alpar@1
|
1 |
/* glpssx02.c */
|
alpar@1
|
2 |
|
alpar@1
|
3 |
/***********************************************************************
|
alpar@1
|
4 |
* This code is part of GLPK (GNU Linear Programming Kit).
|
alpar@1
|
5 |
*
|
alpar@1
|
6 |
* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
|
alpar@1
|
7 |
* 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
|
alpar@1
|
8 |
* Moscow Aviation Institute, Moscow, Russia. All rights reserved.
|
alpar@1
|
9 |
* E-mail: <mao@gnu.org>.
|
alpar@1
|
10 |
*
|
alpar@1
|
11 |
* GLPK is free software: you can redistribute it and/or modify it
|
alpar@1
|
12 |
* under the terms of the GNU General Public License as published by
|
alpar@1
|
13 |
* the Free Software Foundation, either version 3 of the License, or
|
alpar@1
|
14 |
* (at your option) any later version.
|
alpar@1
|
15 |
*
|
alpar@1
|
16 |
* GLPK is distributed in the hope that it will be useful, but WITHOUT
|
alpar@1
|
17 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
alpar@1
|
18 |
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
alpar@1
|
19 |
* License for more details.
|
alpar@1
|
20 |
*
|
alpar@1
|
21 |
* You should have received a copy of the GNU General Public License
|
alpar@1
|
22 |
* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
|
alpar@1
|
23 |
***********************************************************************/
|
alpar@1
|
24 |
|
alpar@1
|
25 |
#include "glpenv.h"
|
alpar@1
|
26 |
#include "glpssx.h"
|
alpar@1
|
27 |
|
alpar@1
|
28 |
static void show_progress(SSX *ssx, int phase)
|
alpar@1
|
29 |
{ /* this auxiliary routine displays information about progress of
|
alpar@1
|
30 |
the search */
|
alpar@1
|
31 |
int i, def = 0;
|
alpar@1
|
32 |
for (i = 1; i <= ssx->m; i++)
|
alpar@1
|
33 |
if (ssx->type[ssx->Q_col[i]] == SSX_FX) def++;
|
alpar@1
|
34 |
xprintf("%s%6d: %s = %22.15g (%d)\n", phase == 1 ? " " : "*",
|
alpar@1
|
35 |
ssx->it_cnt, phase == 1 ? "infsum" : "objval",
|
alpar@1
|
36 |
mpq_get_d(ssx->bbar[0]), def);
|
alpar@1
|
37 |
#if 0
|
alpar@1
|
38 |
ssx->tm_lag = utime();
|
alpar@1
|
39 |
#else
|
alpar@1
|
40 |
ssx->tm_lag = xtime();
|
alpar@1
|
41 |
#endif
|
alpar@1
|
42 |
return;
|
alpar@1
|
43 |
}
|
alpar@1
|
44 |
|
alpar@1
|
45 |
/*----------------------------------------------------------------------
|
alpar@1
|
46 |
// ssx_phase_I - find primal feasible solution.
|
alpar@1
|
47 |
//
|
alpar@1
|
48 |
// This routine implements phase I of the primal simplex method.
|
alpar@1
|
49 |
//
|
alpar@1
|
50 |
// On exit the routine returns one of the following codes:
|
alpar@1
|
51 |
//
|
alpar@1
|
52 |
// 0 - feasible solution found;
|
alpar@1
|
53 |
// 1 - problem has no feasible solution;
|
alpar@1
|
54 |
// 2 - iterations limit exceeded;
|
alpar@1
|
55 |
// 3 - time limit exceeded.
|
alpar@1
|
56 |
----------------------------------------------------------------------*/
|
alpar@1
|
57 |
|
alpar@1
|
58 |
int ssx_phase_I(SSX *ssx)
|
alpar@1
|
59 |
{ int m = ssx->m;
|
alpar@1
|
60 |
int n = ssx->n;
|
alpar@1
|
61 |
int *type = ssx->type;
|
alpar@1
|
62 |
mpq_t *lb = ssx->lb;
|
alpar@1
|
63 |
mpq_t *ub = ssx->ub;
|
alpar@1
|
64 |
mpq_t *coef = ssx->coef;
|
alpar@1
|
65 |
int *A_ptr = ssx->A_ptr;
|
alpar@1
|
66 |
int *A_ind = ssx->A_ind;
|
alpar@1
|
67 |
mpq_t *A_val = ssx->A_val;
|
alpar@1
|
68 |
int *Q_col = ssx->Q_col;
|
alpar@1
|
69 |
mpq_t *bbar = ssx->bbar;
|
alpar@1
|
70 |
mpq_t *pi = ssx->pi;
|
alpar@1
|
71 |
mpq_t *cbar = ssx->cbar;
|
alpar@1
|
72 |
int *orig_type, orig_dir;
|
alpar@1
|
73 |
mpq_t *orig_lb, *orig_ub, *orig_coef;
|
alpar@1
|
74 |
int i, k, ret;
|
alpar@1
|
75 |
/* save components of the original LP problem, which are changed
|
alpar@1
|
76 |
by the routine */
|
alpar@1
|
77 |
orig_type = xcalloc(1+m+n, sizeof(int));
|
alpar@1
|
78 |
orig_lb = xcalloc(1+m+n, sizeof(mpq_t));
|
alpar@1
|
79 |
orig_ub = xcalloc(1+m+n, sizeof(mpq_t));
|
alpar@1
|
80 |
orig_coef = xcalloc(1+m+n, sizeof(mpq_t));
|
alpar@1
|
81 |
for (k = 1; k <= m+n; k++)
|
alpar@1
|
82 |
{ orig_type[k] = type[k];
|
alpar@1
|
83 |
mpq_init(orig_lb[k]);
|
alpar@1
|
84 |
mpq_set(orig_lb[k], lb[k]);
|
alpar@1
|
85 |
mpq_init(orig_ub[k]);
|
alpar@1
|
86 |
mpq_set(orig_ub[k], ub[k]);
|
alpar@1
|
87 |
}
|
alpar@1
|
88 |
orig_dir = ssx->dir;
|
alpar@1
|
89 |
for (k = 0; k <= m+n; k++)
|
alpar@1
|
90 |
{ mpq_init(orig_coef[k]);
|
alpar@1
|
91 |
mpq_set(orig_coef[k], coef[k]);
|
alpar@1
|
92 |
}
|
alpar@1
|
93 |
/* build an artificial basic solution, which is primal feasible,
|
alpar@1
|
94 |
and also build an auxiliary objective function to minimize the
|
alpar@1
|
95 |
sum of infeasibilities for the original problem */
|
alpar@1
|
96 |
ssx->dir = SSX_MIN;
|
alpar@1
|
97 |
for (k = 0; k <= m+n; k++) mpq_set_si(coef[k], 0, 1);
|
alpar@1
|
98 |
mpq_set_si(bbar[0], 0, 1);
|
alpar@1
|
99 |
for (i = 1; i <= m; i++)
|
alpar@1
|
100 |
{ int t;
|
alpar@1
|
101 |
k = Q_col[i]; /* x[k] = xB[i] */
|
alpar@1
|
102 |
t = type[k];
|
alpar@1
|
103 |
if (t == SSX_LO || t == SSX_DB || t == SSX_FX)
|
alpar@1
|
104 |
{ /* in the original problem x[k] has lower bound */
|
alpar@1
|
105 |
if (mpq_cmp(bbar[i], lb[k]) < 0)
|
alpar@1
|
106 |
{ /* which is violated */
|
alpar@1
|
107 |
type[k] = SSX_UP;
|
alpar@1
|
108 |
mpq_set(ub[k], lb[k]);
|
alpar@1
|
109 |
mpq_set_si(lb[k], 0, 1);
|
alpar@1
|
110 |
mpq_set_si(coef[k], -1, 1);
|
alpar@1
|
111 |
mpq_add(bbar[0], bbar[0], ub[k]);
|
alpar@1
|
112 |
mpq_sub(bbar[0], bbar[0], bbar[i]);
|
alpar@1
|
113 |
}
|
alpar@1
|
114 |
}
|
alpar@1
|
115 |
if (t == SSX_UP || t == SSX_DB || t == SSX_FX)
|
alpar@1
|
116 |
{ /* in the original problem x[k] has upper bound */
|
alpar@1
|
117 |
if (mpq_cmp(bbar[i], ub[k]) > 0)
|
alpar@1
|
118 |
{ /* which is violated */
|
alpar@1
|
119 |
type[k] = SSX_LO;
|
alpar@1
|
120 |
mpq_set(lb[k], ub[k]);
|
alpar@1
|
121 |
mpq_set_si(ub[k], 0, 1);
|
alpar@1
|
122 |
mpq_set_si(coef[k], +1, 1);
|
alpar@1
|
123 |
mpq_add(bbar[0], bbar[0], bbar[i]);
|
alpar@1
|
124 |
mpq_sub(bbar[0], bbar[0], lb[k]);
|
alpar@1
|
125 |
}
|
alpar@1
|
126 |
}
|
alpar@1
|
127 |
}
|
alpar@1
|
128 |
/* now the initial basic solution should be primal feasible due
|
alpar@1
|
129 |
to changes of bounds of some basic variables, which turned to
|
alpar@1
|
130 |
implicit artifical variables */
|
alpar@1
|
131 |
/* compute simplex multipliers and reduced costs */
|
alpar@1
|
132 |
ssx_eval_pi(ssx);
|
alpar@1
|
133 |
ssx_eval_cbar(ssx);
|
alpar@1
|
134 |
/* display initial progress of the search */
|
alpar@1
|
135 |
show_progress(ssx, 1);
|
alpar@1
|
136 |
/* main loop starts here */
|
alpar@1
|
137 |
for (;;)
|
alpar@1
|
138 |
{ /* display current progress of the search */
|
alpar@1
|
139 |
#if 0
|
alpar@1
|
140 |
if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001)
|
alpar@1
|
141 |
#else
|
alpar@1
|
142 |
if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001)
|
alpar@1
|
143 |
#endif
|
alpar@1
|
144 |
show_progress(ssx, 1);
|
alpar@1
|
145 |
/* we do not need to wait until all artificial variables have
|
alpar@1
|
146 |
left the basis */
|
alpar@1
|
147 |
if (mpq_sgn(bbar[0]) == 0)
|
alpar@1
|
148 |
{ /* the sum of infeasibilities is zero, therefore the current
|
alpar@1
|
149 |
solution is primal feasible for the original problem */
|
alpar@1
|
150 |
ret = 0;
|
alpar@1
|
151 |
break;
|
alpar@1
|
152 |
}
|
alpar@1
|
153 |
/* check if the iterations limit has been exhausted */
|
alpar@1
|
154 |
if (ssx->it_lim == 0)
|
alpar@1
|
155 |
{ ret = 2;
|
alpar@1
|
156 |
break;
|
alpar@1
|
157 |
}
|
alpar@1
|
158 |
/* check if the time limit has been exhausted */
|
alpar@1
|
159 |
#if 0
|
alpar@1
|
160 |
if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg)
|
alpar@1
|
161 |
#else
|
alpar@1
|
162 |
if (ssx->tm_lim >= 0.0 &&
|
alpar@1
|
163 |
ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg))
|
alpar@1
|
164 |
#endif
|
alpar@1
|
165 |
{ ret = 3;
|
alpar@1
|
166 |
break;
|
alpar@1
|
167 |
}
|
alpar@1
|
168 |
/* choose non-basic variable xN[q] */
|
alpar@1
|
169 |
ssx_chuzc(ssx);
|
alpar@1
|
170 |
/* if xN[q] cannot be chosen, the sum of infeasibilities is
|
alpar@1
|
171 |
minimal but non-zero; therefore the original problem has no
|
alpar@1
|
172 |
primal feasible solution */
|
alpar@1
|
173 |
if (ssx->q == 0)
|
alpar@1
|
174 |
{ ret = 1;
|
alpar@1
|
175 |
break;
|
alpar@1
|
176 |
}
|
alpar@1
|
177 |
/* compute q-th column of the simplex table */
|
alpar@1
|
178 |
ssx_eval_col(ssx);
|
alpar@1
|
179 |
/* choose basic variable xB[p] */
|
alpar@1
|
180 |
ssx_chuzr(ssx);
|
alpar@1
|
181 |
/* the sum of infeasibilities cannot be negative, therefore
|
alpar@1
|
182 |
the auxiliary lp problem cannot have unbounded solution */
|
alpar@1
|
183 |
xassert(ssx->p != 0);
|
alpar@1
|
184 |
/* update values of basic variables */
|
alpar@1
|
185 |
ssx_update_bbar(ssx);
|
alpar@1
|
186 |
if (ssx->p > 0)
|
alpar@1
|
187 |
{ /* compute p-th row of the inverse inv(B) */
|
alpar@1
|
188 |
ssx_eval_rho(ssx);
|
alpar@1
|
189 |
/* compute p-th row of the simplex table */
|
alpar@1
|
190 |
ssx_eval_row(ssx);
|
alpar@1
|
191 |
xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0);
|
alpar@1
|
192 |
/* update simplex multipliers */
|
alpar@1
|
193 |
ssx_update_pi(ssx);
|
alpar@1
|
194 |
/* update reduced costs of non-basic variables */
|
alpar@1
|
195 |
ssx_update_cbar(ssx);
|
alpar@1
|
196 |
}
|
alpar@1
|
197 |
/* xB[p] is leaving the basis; if it is implicit artificial
|
alpar@1
|
198 |
variable, the corresponding residual vanishes; therefore
|
alpar@1
|
199 |
bounds of this variable should be restored to the original
|
alpar@1
|
200 |
values */
|
alpar@1
|
201 |
if (ssx->p > 0)
|
alpar@1
|
202 |
{ k = Q_col[ssx->p]; /* x[k] = xB[p] */
|
alpar@1
|
203 |
if (type[k] != orig_type[k])
|
alpar@1
|
204 |
{ /* x[k] is implicit artificial variable */
|
alpar@1
|
205 |
type[k] = orig_type[k];
|
alpar@1
|
206 |
mpq_set(lb[k], orig_lb[k]);
|
alpar@1
|
207 |
mpq_set(ub[k], orig_ub[k]);
|
alpar@1
|
208 |
xassert(ssx->p_stat == SSX_NL || ssx->p_stat == SSX_NU);
|
alpar@1
|
209 |
ssx->p_stat = (ssx->p_stat == SSX_NL ? SSX_NU : SSX_NL);
|
alpar@1
|
210 |
if (type[k] == SSX_FX) ssx->p_stat = SSX_NS;
|
alpar@1
|
211 |
/* nullify the objective coefficient at x[k] */
|
alpar@1
|
212 |
mpq_set_si(coef[k], 0, 1);
|
alpar@1
|
213 |
/* since coef[k] has been changed, we need to compute
|
alpar@1
|
214 |
new reduced cost of x[k], which it will have in the
|
alpar@1
|
215 |
adjacent basis */
|
alpar@1
|
216 |
/* the formula d[j] = cN[j] - pi' * N[j] is used (note
|
alpar@1
|
217 |
that the vector pi is not changed, because it depends
|
alpar@1
|
218 |
on objective coefficients at basic variables, but in
|
alpar@1
|
219 |
the adjacent basis, for which the vector pi has been
|
alpar@1
|
220 |
just recomputed, x[k] is non-basic) */
|
alpar@1
|
221 |
if (k <= m)
|
alpar@1
|
222 |
{ /* x[k] is auxiliary variable */
|
alpar@1
|
223 |
mpq_neg(cbar[ssx->q], pi[k]);
|
alpar@1
|
224 |
}
|
alpar@1
|
225 |
else
|
alpar@1
|
226 |
{ /* x[k] is structural variable */
|
alpar@1
|
227 |
int ptr;
|
alpar@1
|
228 |
mpq_t temp;
|
alpar@1
|
229 |
mpq_init(temp);
|
alpar@1
|
230 |
mpq_set_si(cbar[ssx->q], 0, 1);
|
alpar@1
|
231 |
for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++)
|
alpar@1
|
232 |
{ mpq_mul(temp, pi[A_ind[ptr]], A_val[ptr]);
|
alpar@1
|
233 |
mpq_add(cbar[ssx->q], cbar[ssx->q], temp);
|
alpar@1
|
234 |
}
|
alpar@1
|
235 |
mpq_clear(temp);
|
alpar@1
|
236 |
}
|
alpar@1
|
237 |
}
|
alpar@1
|
238 |
}
|
alpar@1
|
239 |
/* jump to the adjacent vertex of the polyhedron */
|
alpar@1
|
240 |
ssx_change_basis(ssx);
|
alpar@1
|
241 |
/* one simplex iteration has been performed */
|
alpar@1
|
242 |
if (ssx->it_lim > 0) ssx->it_lim--;
|
alpar@1
|
243 |
ssx->it_cnt++;
|
alpar@1
|
244 |
}
|
alpar@1
|
245 |
/* display final progress of the search */
|
alpar@1
|
246 |
show_progress(ssx, 1);
|
alpar@1
|
247 |
/* restore components of the original problem, which were changed
|
alpar@1
|
248 |
by the routine */
|
alpar@1
|
249 |
for (k = 1; k <= m+n; k++)
|
alpar@1
|
250 |
{ type[k] = orig_type[k];
|
alpar@1
|
251 |
mpq_set(lb[k], orig_lb[k]);
|
alpar@1
|
252 |
mpq_clear(orig_lb[k]);
|
alpar@1
|
253 |
mpq_set(ub[k], orig_ub[k]);
|
alpar@1
|
254 |
mpq_clear(orig_ub[k]);
|
alpar@1
|
255 |
}
|
alpar@1
|
256 |
ssx->dir = orig_dir;
|
alpar@1
|
257 |
for (k = 0; k <= m+n; k++)
|
alpar@1
|
258 |
{ mpq_set(coef[k], orig_coef[k]);
|
alpar@1
|
259 |
mpq_clear(orig_coef[k]);
|
alpar@1
|
260 |
}
|
alpar@1
|
261 |
xfree(orig_type);
|
alpar@1
|
262 |
xfree(orig_lb);
|
alpar@1
|
263 |
xfree(orig_ub);
|
alpar@1
|
264 |
xfree(orig_coef);
|
alpar@1
|
265 |
/* return to the calling program */
|
alpar@1
|
266 |
return ret;
|
alpar@1
|
267 |
}
|
alpar@1
|
268 |
|
alpar@1
|
269 |
/*----------------------------------------------------------------------
|
alpar@1
|
270 |
// ssx_phase_II - find optimal solution.
|
alpar@1
|
271 |
//
|
alpar@1
|
272 |
// This routine implements phase II of the primal simplex method.
|
alpar@1
|
273 |
//
|
alpar@1
|
274 |
// On exit the routine returns one of the following codes:
|
alpar@1
|
275 |
//
|
alpar@1
|
276 |
// 0 - optimal solution found;
|
alpar@1
|
277 |
// 1 - problem has unbounded solution;
|
alpar@1
|
278 |
// 2 - iterations limit exceeded;
|
alpar@1
|
279 |
// 3 - time limit exceeded.
|
alpar@1
|
280 |
----------------------------------------------------------------------*/
|
alpar@1
|
281 |
|
alpar@1
|
282 |
int ssx_phase_II(SSX *ssx)
|
alpar@1
|
283 |
{ int ret;
|
alpar@1
|
284 |
/* display initial progress of the search */
|
alpar@1
|
285 |
show_progress(ssx, 2);
|
alpar@1
|
286 |
/* main loop starts here */
|
alpar@1
|
287 |
for (;;)
|
alpar@1
|
288 |
{ /* display current progress of the search */
|
alpar@1
|
289 |
#if 0
|
alpar@1
|
290 |
if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001)
|
alpar@1
|
291 |
#else
|
alpar@1
|
292 |
if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001)
|
alpar@1
|
293 |
#endif
|
alpar@1
|
294 |
show_progress(ssx, 2);
|
alpar@1
|
295 |
/* check if the iterations limit has been exhausted */
|
alpar@1
|
296 |
if (ssx->it_lim == 0)
|
alpar@1
|
297 |
{ ret = 2;
|
alpar@1
|
298 |
break;
|
alpar@1
|
299 |
}
|
alpar@1
|
300 |
/* check if the time limit has been exhausted */
|
alpar@1
|
301 |
#if 0
|
alpar@1
|
302 |
if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg)
|
alpar@1
|
303 |
#else
|
alpar@1
|
304 |
if (ssx->tm_lim >= 0.0 &&
|
alpar@1
|
305 |
ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg))
|
alpar@1
|
306 |
#endif
|
alpar@1
|
307 |
{ ret = 3;
|
alpar@1
|
308 |
break;
|
alpar@1
|
309 |
}
|
alpar@1
|
310 |
/* choose non-basic variable xN[q] */
|
alpar@1
|
311 |
ssx_chuzc(ssx);
|
alpar@1
|
312 |
/* if xN[q] cannot be chosen, the current basic solution is
|
alpar@1
|
313 |
dual feasible and therefore optimal */
|
alpar@1
|
314 |
if (ssx->q == 0)
|
alpar@1
|
315 |
{ ret = 0;
|
alpar@1
|
316 |
break;
|
alpar@1
|
317 |
}
|
alpar@1
|
318 |
/* compute q-th column of the simplex table */
|
alpar@1
|
319 |
ssx_eval_col(ssx);
|
alpar@1
|
320 |
/* choose basic variable xB[p] */
|
alpar@1
|
321 |
ssx_chuzr(ssx);
|
alpar@1
|
322 |
/* if xB[p] cannot be chosen, the problem has no dual feasible
|
alpar@1
|
323 |
solution (i.e. unbounded) */
|
alpar@1
|
324 |
if (ssx->p == 0)
|
alpar@1
|
325 |
{ ret = 1;
|
alpar@1
|
326 |
break;
|
alpar@1
|
327 |
}
|
alpar@1
|
328 |
/* update values of basic variables */
|
alpar@1
|
329 |
ssx_update_bbar(ssx);
|
alpar@1
|
330 |
if (ssx->p > 0)
|
alpar@1
|
331 |
{ /* compute p-th row of the inverse inv(B) */
|
alpar@1
|
332 |
ssx_eval_rho(ssx);
|
alpar@1
|
333 |
/* compute p-th row of the simplex table */
|
alpar@1
|
334 |
ssx_eval_row(ssx);
|
alpar@1
|
335 |
xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0);
|
alpar@1
|
336 |
#if 0
|
alpar@1
|
337 |
/* update simplex multipliers */
|
alpar@1
|
338 |
ssx_update_pi(ssx);
|
alpar@1
|
339 |
#endif
|
alpar@1
|
340 |
/* update reduced costs of non-basic variables */
|
alpar@1
|
341 |
ssx_update_cbar(ssx);
|
alpar@1
|
342 |
}
|
alpar@1
|
343 |
/* jump to the adjacent vertex of the polyhedron */
|
alpar@1
|
344 |
ssx_change_basis(ssx);
|
alpar@1
|
345 |
/* one simplex iteration has been performed */
|
alpar@1
|
346 |
if (ssx->it_lim > 0) ssx->it_lim--;
|
alpar@1
|
347 |
ssx->it_cnt++;
|
alpar@1
|
348 |
}
|
alpar@1
|
349 |
/* display final progress of the search */
|
alpar@1
|
350 |
show_progress(ssx, 2);
|
alpar@1
|
351 |
/* return to the calling program */
|
alpar@1
|
352 |
return ret;
|
alpar@1
|
353 |
}
|
alpar@1
|
354 |
|
alpar@1
|
355 |
/*----------------------------------------------------------------------
|
alpar@1
|
356 |
// ssx_driver - base driver to exact simplex method.
|
alpar@1
|
357 |
//
|
alpar@1
|
358 |
// This routine is a base driver to a version of the primal simplex
|
alpar@1
|
359 |
// method using exact (bignum) arithmetic.
|
alpar@1
|
360 |
//
|
alpar@1
|
361 |
// On exit the routine returns one of the following codes:
|
alpar@1
|
362 |
//
|
alpar@1
|
363 |
// 0 - optimal solution found;
|
alpar@1
|
364 |
// 1 - problem has no feasible solution;
|
alpar@1
|
365 |
// 2 - problem has unbounded solution;
|
alpar@1
|
366 |
// 3 - iterations limit exceeded (phase I);
|
alpar@1
|
367 |
// 4 - iterations limit exceeded (phase II);
|
alpar@1
|
368 |
// 5 - time limit exceeded (phase I);
|
alpar@1
|
369 |
// 6 - time limit exceeded (phase II);
|
alpar@1
|
370 |
// 7 - initial basis matrix is exactly singular.
|
alpar@1
|
371 |
----------------------------------------------------------------------*/
|
alpar@1
|
372 |
|
alpar@1
|
373 |
int ssx_driver(SSX *ssx)
|
alpar@1
|
374 |
{ int m = ssx->m;
|
alpar@1
|
375 |
int *type = ssx->type;
|
alpar@1
|
376 |
mpq_t *lb = ssx->lb;
|
alpar@1
|
377 |
mpq_t *ub = ssx->ub;
|
alpar@1
|
378 |
int *Q_col = ssx->Q_col;
|
alpar@1
|
379 |
mpq_t *bbar = ssx->bbar;
|
alpar@1
|
380 |
int i, k, ret;
|
alpar@1
|
381 |
ssx->tm_beg = xtime();
|
alpar@1
|
382 |
/* factorize the initial basis matrix */
|
alpar@1
|
383 |
if (ssx_factorize(ssx))
|
alpar@1
|
384 |
{ xprintf("Initial basis matrix is singular\n");
|
alpar@1
|
385 |
ret = 7;
|
alpar@1
|
386 |
goto done;
|
alpar@1
|
387 |
}
|
alpar@1
|
388 |
/* compute values of basic variables */
|
alpar@1
|
389 |
ssx_eval_bbar(ssx);
|
alpar@1
|
390 |
/* check if the initial basic solution is primal feasible */
|
alpar@1
|
391 |
for (i = 1; i <= m; i++)
|
alpar@1
|
392 |
{ int t;
|
alpar@1
|
393 |
k = Q_col[i]; /* x[k] = xB[i] */
|
alpar@1
|
394 |
t = type[k];
|
alpar@1
|
395 |
if (t == SSX_LO || t == SSX_DB || t == SSX_FX)
|
alpar@1
|
396 |
{ /* x[k] has lower bound */
|
alpar@1
|
397 |
if (mpq_cmp(bbar[i], lb[k]) < 0)
|
alpar@1
|
398 |
{ /* which is violated */
|
alpar@1
|
399 |
break;
|
alpar@1
|
400 |
}
|
alpar@1
|
401 |
}
|
alpar@1
|
402 |
if (t == SSX_UP || t == SSX_DB || t == SSX_FX)
|
alpar@1
|
403 |
{ /* x[k] has upper bound */
|
alpar@1
|
404 |
if (mpq_cmp(bbar[i], ub[k]) > 0)
|
alpar@1
|
405 |
{ /* which is violated */
|
alpar@1
|
406 |
break;
|
alpar@1
|
407 |
}
|
alpar@1
|
408 |
}
|
alpar@1
|
409 |
}
|
alpar@1
|
410 |
if (i > m)
|
alpar@1
|
411 |
{ /* no basic variable violates its bounds */
|
alpar@1
|
412 |
ret = 0;
|
alpar@1
|
413 |
goto skip;
|
alpar@1
|
414 |
}
|
alpar@1
|
415 |
/* phase I: find primal feasible solution */
|
alpar@1
|
416 |
ret = ssx_phase_I(ssx);
|
alpar@1
|
417 |
switch (ret)
|
alpar@1
|
418 |
{ case 0:
|
alpar@1
|
419 |
ret = 0;
|
alpar@1
|
420 |
break;
|
alpar@1
|
421 |
case 1:
|
alpar@1
|
422 |
xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n");
|
alpar@1
|
423 |
ret = 1;
|
alpar@1
|
424 |
break;
|
alpar@1
|
425 |
case 2:
|
alpar@1
|
426 |
xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n");
|
alpar@1
|
427 |
ret = 3;
|
alpar@1
|
428 |
break;
|
alpar@1
|
429 |
case 3:
|
alpar@1
|
430 |
xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
|
alpar@1
|
431 |
ret = 5;
|
alpar@1
|
432 |
break;
|
alpar@1
|
433 |
default:
|
alpar@1
|
434 |
xassert(ret != ret);
|
alpar@1
|
435 |
}
|
alpar@1
|
436 |
/* compute values of basic variables (actually only the objective
|
alpar@1
|
437 |
value needs to be computed) */
|
alpar@1
|
438 |
ssx_eval_bbar(ssx);
|
alpar@1
|
439 |
skip: /* compute simplex multipliers */
|
alpar@1
|
440 |
ssx_eval_pi(ssx);
|
alpar@1
|
441 |
/* compute reduced costs of non-basic variables */
|
alpar@1
|
442 |
ssx_eval_cbar(ssx);
|
alpar@1
|
443 |
/* if phase I failed, do not start phase II */
|
alpar@1
|
444 |
if (ret != 0) goto done;
|
alpar@1
|
445 |
/* phase II: find optimal solution */
|
alpar@1
|
446 |
ret = ssx_phase_II(ssx);
|
alpar@1
|
447 |
switch (ret)
|
alpar@1
|
448 |
{ case 0:
|
alpar@1
|
449 |
xprintf("OPTIMAL SOLUTION FOUND\n");
|
alpar@1
|
450 |
ret = 0;
|
alpar@1
|
451 |
break;
|
alpar@1
|
452 |
case 1:
|
alpar@1
|
453 |
xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n");
|
alpar@1
|
454 |
ret = 2;
|
alpar@1
|
455 |
break;
|
alpar@1
|
456 |
case 2:
|
alpar@1
|
457 |
xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n");
|
alpar@1
|
458 |
ret = 4;
|
alpar@1
|
459 |
break;
|
alpar@1
|
460 |
case 3:
|
alpar@1
|
461 |
xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
|
alpar@1
|
462 |
ret = 6;
|
alpar@1
|
463 |
break;
|
alpar@1
|
464 |
default:
|
alpar@1
|
465 |
xassert(ret != ret);
|
alpar@1
|
466 |
}
|
alpar@1
|
467 |
done: /* decrease the time limit by the spent amount of time */
|
alpar@1
|
468 |
if (ssx->tm_lim >= 0.0)
|
alpar@1
|
469 |
#if 0
|
alpar@1
|
470 |
{ ssx->tm_lim -= utime() - ssx->tm_beg;
|
alpar@1
|
471 |
#else
|
alpar@1
|
472 |
{ ssx->tm_lim -= xdifftime(xtime(), ssx->tm_beg);
|
alpar@1
|
473 |
#endif
|
alpar@1
|
474 |
if (ssx->tm_lim < 0.0) ssx->tm_lim = 0.0;
|
alpar@1
|
475 |
}
|
alpar@1
|
476 |
return ret;
|
alpar@1
|
477 |
}
|
alpar@1
|
478 |
|
alpar@1
|
479 |
/* eof */
|