|
1 /* glpnpp03.c */ |
|
2 |
|
3 /*********************************************************************** |
|
4 * This code is part of GLPK (GNU Linear Programming Kit). |
|
5 * |
|
6 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, |
|
7 * 2009, 2010 Andrew Makhorin, Department for Applied Informatics, |
|
8 * Moscow Aviation Institute, Moscow, Russia. All rights reserved. |
|
9 * E-mail: <mao@gnu.org>. |
|
10 * |
|
11 * GLPK is free software: you can redistribute it and/or modify it |
|
12 * under the terms of the GNU General Public License as published by |
|
13 * the Free Software Foundation, either version 3 of the License, or |
|
14 * (at your option) any later version. |
|
15 * |
|
16 * GLPK is distributed in the hope that it will be useful, but WITHOUT |
|
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
|
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
|
19 * License for more details. |
|
20 * |
|
21 * You should have received a copy of the GNU General Public License |
|
22 * along with GLPK. If not, see <http://www.gnu.org/licenses/>. |
|
23 ***********************************************************************/ |
|
24 |
|
25 #include "glpnpp.h" |
|
26 |
|
27 /*********************************************************************** |
|
28 * NAME |
|
29 * |
|
30 * npp_empty_row - process empty row |
|
31 * |
|
32 * SYNOPSIS |
|
33 * |
|
34 * #include "glpnpp.h" |
|
35 * int npp_empty_row(NPP *npp, NPPROW *p); |
|
36 * |
|
37 * DESCRIPTION |
|
38 * |
|
39 * The routine npp_empty_row processes row p, which is empty, i.e. |
|
40 * coefficients at all columns in this row are zero: |
|
41 * |
|
42 * L[p] <= sum 0 x[j] <= U[p], (1) |
|
43 * |
|
44 * where L[p] <= U[p]. |
|
45 * |
|
46 * RETURNS |
|
47 * |
|
48 * 0 - success; |
|
49 * |
|
50 * 1 - problem has no primal feasible solution. |
|
51 * |
|
52 * PROBLEM TRANSFORMATION |
|
53 * |
|
54 * If the following conditions hold: |
|
55 * |
|
56 * L[p] <= +eps, U[p] >= -eps, (2) |
|
57 * |
|
58 * where eps is an absolute tolerance for row value, the row p is |
|
59 * redundant. In this case it can be replaced by equivalent redundant |
|
60 * row, which is free (unbounded), and then removed from the problem. |
|
61 * Otherwise, the row p is infeasible and, thus, the problem has no |
|
62 * primal feasible solution. |
|
63 * |
|
64 * RECOVERING BASIC SOLUTION |
|
65 * |
|
66 * See the routine npp_free_row. |
|
67 * |
|
68 * RECOVERING INTERIOR-POINT SOLUTION |
|
69 * |
|
70 * See the routine npp_free_row. |
|
71 * |
|
72 * RECOVERING MIP SOLUTION |
|
73 * |
|
74 * None needed. */ |
|
75 |
|
76 int npp_empty_row(NPP *npp, NPPROW *p) |
|
77 { /* process empty row */ |
|
78 double eps = 1e-3; |
|
79 /* the row must be empty */ |
|
80 xassert(p->ptr == NULL); |
|
81 /* check primal feasibility */ |
|
82 if (p->lb > +eps || p->ub < -eps) |
|
83 return 1; |
|
84 /* replace the row by equivalent free (unbounded) row */ |
|
85 p->lb = -DBL_MAX, p->ub = +DBL_MAX; |
|
86 /* and process it */ |
|
87 npp_free_row(npp, p); |
|
88 return 0; |
|
89 } |
|
90 |
|
91 /*********************************************************************** |
|
92 * NAME |
|
93 * |
|
94 * npp_empty_col - process empty column |
|
95 * |
|
96 * SYNOPSIS |
|
97 * |
|
98 * #include "glpnpp.h" |
|
99 * int npp_empty_col(NPP *npp, NPPCOL *q); |
|
100 * |
|
101 * DESCRIPTION |
|
102 * |
|
103 * The routine npp_empty_col processes column q: |
|
104 * |
|
105 * l[q] <= x[q] <= u[q], (1) |
|
106 * |
|
107 * where l[q] <= u[q], which is empty, i.e. has zero coefficients in |
|
108 * all constraint rows. |
|
109 * |
|
110 * RETURNS |
|
111 * |
|
112 * 0 - success; |
|
113 * |
|
114 * 1 - problem has no dual feasible solution. |
|
115 * |
|
116 * PROBLEM TRANSFORMATION |
|
117 * |
|
118 * The row of the dual system corresponding to the empty column is the |
|
119 * following: |
|
120 * |
|
121 * sum 0 pi[i] + lambda[q] = c[q], (2) |
|
122 * i |
|
123 * |
|
124 * from which it follows that: |
|
125 * |
|
126 * lambda[q] = c[q]. (3) |
|
127 * |
|
128 * If the following condition holds: |
|
129 * |
|
130 * c[q] < - eps, (4) |
|
131 * |
|
132 * where eps is an absolute tolerance for column multiplier, the lower |
|
133 * column bound l[q] must be active to provide dual feasibility (note |
|
134 * that being preprocessed the problem is always minimization). In this |
|
135 * case the column can be fixed on its lower bound and removed from the |
|
136 * problem (if the column is integral, its bounds are also assumed to |
|
137 * be integral). And if the column has no lower bound (l[q] = -oo), the |
|
138 * problem has no dual feasible solution. |
|
139 * |
|
140 * If the following condition holds: |
|
141 * |
|
142 * c[q] > + eps, (5) |
|
143 * |
|
144 * the upper column bound u[q] must be active to provide dual |
|
145 * feasibility. In this case the column can be fixed on its upper bound |
|
146 * and removed from the problem. And if the column has no upper bound |
|
147 * (u[q] = +oo), the problem has no dual feasible solution. |
|
148 * |
|
149 * Finally, if the following condition holds: |
|
150 * |
|
151 * - eps <= c[q] <= +eps, (6) |
|
152 * |
|
153 * dual feasibility does not depend on a particular value of column q. |
|
154 * In this case the column can be fixed either on its lower bound (if |
|
155 * l[q] > -oo) or on its upper bound (if u[q] < +oo) or at zero (if the |
|
156 * column is unbounded) and then removed from the problem. |
|
157 * |
|
158 * RECOVERING BASIC SOLUTION |
|
159 * |
|
160 * See the routine npp_fixed_col. Having been recovered the column |
|
161 * is assigned status GLP_NS. However, if actually it is not fixed |
|
162 * (l[q] < u[q]), its status should be changed to GLP_NL, GLP_NU, or |
|
163 * GLP_NF depending on which bound it was fixed on transformation stage. |
|
164 * |
|
165 * RECOVERING INTERIOR-POINT SOLUTION |
|
166 * |
|
167 * See the routine npp_fixed_col. |
|
168 * |
|
169 * RECOVERING MIP SOLUTION |
|
170 * |
|
171 * See the routine npp_fixed_col. */ |
|
172 |
|
173 struct empty_col |
|
174 { /* empty column */ |
|
175 int q; |
|
176 /* column reference number */ |
|
177 char stat; |
|
178 /* status in basic solution */ |
|
179 }; |
|
180 |
|
181 static int rcv_empty_col(NPP *npp, void *info); |
|
182 |
|
183 int npp_empty_col(NPP *npp, NPPCOL *q) |
|
184 { /* process empty column */ |
|
185 struct empty_col *info; |
|
186 double eps = 1e-3; |
|
187 /* the column must be empty */ |
|
188 xassert(q->ptr == NULL); |
|
189 /* check dual feasibility */ |
|
190 if (q->coef > +eps && q->lb == -DBL_MAX) |
|
191 return 1; |
|
192 if (q->coef < -eps && q->ub == +DBL_MAX) |
|
193 return 1; |
|
194 /* create transformation stack entry */ |
|
195 info = npp_push_tse(npp, |
|
196 rcv_empty_col, sizeof(struct empty_col)); |
|
197 info->q = q->j; |
|
198 /* fix the column */ |
|
199 if (q->lb == -DBL_MAX && q->ub == +DBL_MAX) |
|
200 { /* free column */ |
|
201 info->stat = GLP_NF; |
|
202 q->lb = q->ub = 0.0; |
|
203 } |
|
204 else if (q->ub == +DBL_MAX) |
|
205 lo: { /* column with lower bound */ |
|
206 info->stat = GLP_NL; |
|
207 q->ub = q->lb; |
|
208 } |
|
209 else if (q->lb == -DBL_MAX) |
|
210 up: { /* column with upper bound */ |
|
211 info->stat = GLP_NU; |
|
212 q->lb = q->ub; |
|
213 } |
|
214 else if (q->lb != q->ub) |
|
215 { /* double-bounded column */ |
|
216 if (q->coef >= +DBL_EPSILON) goto lo; |
|
217 if (q->coef <= -DBL_EPSILON) goto up; |
|
218 if (fabs(q->lb) <= fabs(q->ub)) goto lo; else goto up; |
|
219 } |
|
220 else |
|
221 { /* fixed column */ |
|
222 info->stat = GLP_NS; |
|
223 } |
|
224 /* process fixed column */ |
|
225 npp_fixed_col(npp, q); |
|
226 return 0; |
|
227 } |
|
228 |
|
229 static int rcv_empty_col(NPP *npp, void *_info) |
|
230 { /* recover empty column */ |
|
231 struct empty_col *info = _info; |
|
232 if (npp->sol == GLP_SOL) |
|
233 npp->c_stat[info->q] = info->stat; |
|
234 return 0; |
|
235 } |
|
236 |
|
237 /*********************************************************************** |
|
238 * NAME |
|
239 * |
|
240 * npp_implied_value - process implied column value |
|
241 * |
|
242 * SYNOPSIS |
|
243 * |
|
244 * #include "glpnpp.h" |
|
245 * int npp_implied_value(NPP *npp, NPPCOL *q, double s); |
|
246 * |
|
247 * DESCRIPTION |
|
248 * |
|
249 * For column q: |
|
250 * |
|
251 * l[q] <= x[q] <= u[q], (1) |
|
252 * |
|
253 * where l[q] < u[q], the routine npp_implied_value processes its |
|
254 * implied value s[q]. If this implied value satisfies to the current |
|
255 * column bounds and integrality condition, the routine fixes column q |
|
256 * at the given point. Note that the column is kept in the problem in |
|
257 * any case. |
|
258 * |
|
259 * RETURNS |
|
260 * |
|
261 * 0 - column has been fixed; |
|
262 * |
|
263 * 1 - implied value violates to current column bounds; |
|
264 * |
|
265 * 2 - implied value violates integrality condition. |
|
266 * |
|
267 * ALGORITHM |
|
268 * |
|
269 * Implied column value s[q] satisfies to the current column bounds if |
|
270 * the following condition holds: |
|
271 * |
|
272 * l[q] - eps <= s[q] <= u[q] + eps, (2) |
|
273 * |
|
274 * where eps is an absolute tolerance for column value. If the column |
|
275 * is integral, the following condition also must hold: |
|
276 * |
|
277 * |s[q] - floor(s[q]+0.5)| <= eps, (3) |
|
278 * |
|
279 * where floor(s[q]+0.5) is the nearest integer to s[q]. |
|
280 * |
|
281 * If both condition (2) and (3) are satisfied, the column can be fixed |
|
282 * at the value s[q], or, if it is integral, at floor(s[q]+0.5). |
|
283 * Otherwise, if s[q] violates (2) or (3), the problem has no feasible |
|
284 * solution. |
|
285 * |
|
286 * Note: If s[q] is close to l[q] or u[q], it seems to be reasonable to |
|
287 * fix the column at its lower or upper bound, resp. rather than at the |
|
288 * implied value. */ |
|
289 |
|
290 int npp_implied_value(NPP *npp, NPPCOL *q, double s) |
|
291 { /* process implied column value */ |
|
292 double eps, nint; |
|
293 xassert(npp == npp); |
|
294 /* column must not be fixed */ |
|
295 xassert(q->lb < q->ub); |
|
296 /* check integrality */ |
|
297 if (q->is_int) |
|
298 { nint = floor(s + 0.5); |
|
299 if (fabs(s - nint) <= 1e-5) |
|
300 s = nint; |
|
301 else |
|
302 return 2; |
|
303 } |
|
304 /* check current column lower bound */ |
|
305 if (q->lb != -DBL_MAX) |
|
306 { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->lb)); |
|
307 if (s < q->lb - eps) return 1; |
|
308 /* if s[q] is close to l[q], fix column at its lower bound |
|
309 rather than at the implied value */ |
|
310 if (s < q->lb + 1e-3 * eps) |
|
311 { q->ub = q->lb; |
|
312 return 0; |
|
313 } |
|
314 } |
|
315 /* check current column upper bound */ |
|
316 if (q->ub != +DBL_MAX) |
|
317 { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->ub)); |
|
318 if (s > q->ub + eps) return 1; |
|
319 /* if s[q] is close to u[q], fix column at its upper bound |
|
320 rather than at the implied value */ |
|
321 if (s > q->ub - 1e-3 * eps) |
|
322 { q->lb = q->ub; |
|
323 return 0; |
|
324 } |
|
325 } |
|
326 /* fix column at the implied value */ |
|
327 q->lb = q->ub = s; |
|
328 return 0; |
|
329 } |
|
330 |
|
331 /*********************************************************************** |
|
332 * NAME |
|
333 * |
|
334 * npp_eq_singlet - process row singleton (equality constraint) |
|
335 * |
|
336 * SYNOPSIS |
|
337 * |
|
338 * #include "glpnpp.h" |
|
339 * int npp_eq_singlet(NPP *npp, NPPROW *p); |
|
340 * |
|
341 * DESCRIPTION |
|
342 * |
|
343 * The routine npp_eq_singlet processes row p, which is equiality |
|
344 * constraint having the only non-zero coefficient: |
|
345 * |
|
346 * a[p,q] x[q] = b. (1) |
|
347 * |
|
348 * RETURNS |
|
349 * |
|
350 * 0 - success; |
|
351 * |
|
352 * 1 - problem has no primal feasible solution; |
|
353 * |
|
354 * 2 - problem has no integer feasible solution. |
|
355 * |
|
356 * PROBLEM TRANSFORMATION |
|
357 * |
|
358 * The equality constraint defines implied value of column q: |
|
359 * |
|
360 * x[q] = s[q] = b / a[p,q]. (2) |
|
361 * |
|
362 * If the implied value s[q] satisfies to the column bounds (see the |
|
363 * routine npp_implied_value), the column can be fixed at s[q] and |
|
364 * removed from the problem. In this case row p becomes redundant, so |
|
365 * it can be replaced by equivalent free row and also removed from the |
|
366 * problem. |
|
367 * |
|
368 * Note that the routine removes from the problem only row p. Column q |
|
369 * becomes fixed, however, it is kept in the problem. |
|
370 * |
|
371 * RECOVERING BASIC SOLUTION |
|
372 * |
|
373 * In solution to the original problem row p is assigned status GLP_NS |
|
374 * (active equality constraint), and column q is assigned status GLP_BS |
|
375 * (basic column). |
|
376 * |
|
377 * Multiplier for row p can be computed as follows. In the dual system |
|
378 * of the original problem column q corresponds to the following row: |
|
379 * |
|
380 * sum a[i,q] pi[i] + lambda[q] = c[q] ==> |
|
381 * i |
|
382 * |
|
383 * sum a[i,q] pi[i] + a[p,q] pi[p] + lambda[q] = c[q]. |
|
384 * i!=p |
|
385 * |
|
386 * Therefore: |
|
387 * |
|
388 * 1 |
|
389 * pi[p] = ------ (c[q] - lambda[q] - sum a[i,q] pi[i]), (3) |
|
390 * a[p,q] i!=q |
|
391 * |
|
392 * where lambda[q] = 0 (since column[q] is basic), and pi[i] for all |
|
393 * i != p are known in solution to the transformed problem. |
|
394 * |
|
395 * Value of column q in solution to the original problem is assigned |
|
396 * its implied value s[q]. |
|
397 * |
|
398 * RECOVERING INTERIOR-POINT SOLUTION |
|
399 * |
|
400 * Multiplier for row p is computed with formula (3). Value of column |
|
401 * q is assigned its implied value s[q]. |
|
402 * |
|
403 * RECOVERING MIP SOLUTION |
|
404 * |
|
405 * Value of column q is assigned its implied value s[q]. */ |
|
406 |
|
407 struct eq_singlet |
|
408 { /* row singleton (equality constraint) */ |
|
409 int p; |
|
410 /* row reference number */ |
|
411 int q; |
|
412 /* column reference number */ |
|
413 double apq; |
|
414 /* constraint coefficient a[p,q] */ |
|
415 double c; |
|
416 /* objective coefficient at x[q] */ |
|
417 NPPLFE *ptr; |
|
418 /* list of non-zero coefficients a[i,q], i != p */ |
|
419 }; |
|
420 |
|
421 static int rcv_eq_singlet(NPP *npp, void *info); |
|
422 |
|
423 int npp_eq_singlet(NPP *npp, NPPROW *p) |
|
424 { /* process row singleton (equality constraint) */ |
|
425 struct eq_singlet *info; |
|
426 NPPCOL *q; |
|
427 NPPAIJ *aij; |
|
428 NPPLFE *lfe; |
|
429 int ret; |
|
430 double s; |
|
431 /* the row must be singleton equality constraint */ |
|
432 xassert(p->lb == p->ub); |
|
433 xassert(p->ptr != NULL && p->ptr->r_next == NULL); |
|
434 /* compute and process implied column value */ |
|
435 aij = p->ptr; |
|
436 q = aij->col; |
|
437 s = p->lb / aij->val; |
|
438 ret = npp_implied_value(npp, q, s); |
|
439 xassert(0 <= ret && ret <= 2); |
|
440 if (ret != 0) return ret; |
|
441 /* create transformation stack entry */ |
|
442 info = npp_push_tse(npp, |
|
443 rcv_eq_singlet, sizeof(struct eq_singlet)); |
|
444 info->p = p->i; |
|
445 info->q = q->j; |
|
446 info->apq = aij->val; |
|
447 info->c = q->coef; |
|
448 info->ptr = NULL; |
|
449 /* save column coefficients a[i,q], i != p (not needed for MIP |
|
450 solution) */ |
|
451 if (npp->sol != GLP_MIP) |
|
452 { for (aij = q->ptr; aij != NULL; aij = aij->c_next) |
|
453 { if (aij->row == p) continue; /* skip a[p,q] */ |
|
454 lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); |
|
455 lfe->ref = aij->row->i; |
|
456 lfe->val = aij->val; |
|
457 lfe->next = info->ptr; |
|
458 info->ptr = lfe; |
|
459 } |
|
460 } |
|
461 /* remove the row from the problem */ |
|
462 npp_del_row(npp, p); |
|
463 return 0; |
|
464 } |
|
465 |
|
466 static int rcv_eq_singlet(NPP *npp, void *_info) |
|
467 { /* recover row singleton (equality constraint) */ |
|
468 struct eq_singlet *info = _info; |
|
469 NPPLFE *lfe; |
|
470 double temp; |
|
471 if (npp->sol == GLP_SOL) |
|
472 { /* column q must be already recovered as GLP_NS */ |
|
473 if (npp->c_stat[info->q] != GLP_NS) |
|
474 { npp_error(); |
|
475 return 1; |
|
476 } |
|
477 npp->r_stat[info->p] = GLP_NS; |
|
478 npp->c_stat[info->q] = GLP_BS; |
|
479 } |
|
480 if (npp->sol != GLP_MIP) |
|
481 { /* compute multiplier for row p with formula (3) */ |
|
482 temp = info->c; |
|
483 for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) |
|
484 temp -= lfe->val * npp->r_pi[lfe->ref]; |
|
485 npp->r_pi[info->p] = temp / info->apq; |
|
486 } |
|
487 return 0; |
|
488 } |
|
489 |
|
490 /*********************************************************************** |
|
491 * NAME |
|
492 * |
|
493 * npp_implied_lower - process implied column lower bound |
|
494 * |
|
495 * SYNOPSIS |
|
496 * |
|
497 * #include "glpnpp.h" |
|
498 * int npp_implied_lower(NPP *npp, NPPCOL *q, double l); |
|
499 * |
|
500 * DESCRIPTION |
|
501 * |
|
502 * For column q: |
|
503 * |
|
504 * l[q] <= x[q] <= u[q], (1) |
|
505 * |
|
506 * where l[q] < u[q], the routine npp_implied_lower processes its |
|
507 * implied lower bound l'[q]. As the result the current column lower |
|
508 * bound may increase. Note that the column is kept in the problem in |
|
509 * any case. |
|
510 * |
|
511 * RETURNS |
|
512 * |
|
513 * 0 - current column lower bound has not changed; |
|
514 * |
|
515 * 1 - current column lower bound has changed, but not significantly; |
|
516 * |
|
517 * 2 - current column lower bound has significantly changed; |
|
518 * |
|
519 * 3 - column has been fixed on its upper bound; |
|
520 * |
|
521 * 4 - implied lower bound violates current column upper bound. |
|
522 * |
|
523 * ALGORITHM |
|
524 * |
|
525 * If column q is integral, before processing its implied lower bound |
|
526 * should be rounded up: |
|
527 * |
|
528 * ( floor(l'[q]+0.5), if |l'[q] - floor(l'[q]+0.5)| <= eps |
|
529 * l'[q] := < (2) |
|
530 * ( ceil(l'[q]), otherwise |
|
531 * |
|
532 * where floor(l'[q]+0.5) is the nearest integer to l'[q], ceil(l'[q]) |
|
533 * is smallest integer not less than l'[q], and eps is an absolute |
|
534 * tolerance for column value. |
|
535 * |
|
536 * Processing implied column lower bound l'[q] includes the following |
|
537 * cases: |
|
538 * |
|
539 * 1) if l'[q] < l[q] + eps, implied lower bound is redundant; |
|
540 * |
|
541 * 2) if l[q] + eps <= l[q] <= u[q] + eps, current column lower bound |
|
542 * l[q] can be strengthened by replacing it with l'[q]. If in this |
|
543 * case new column lower bound becomes close to current column upper |
|
544 * bound u[q], the column can be fixed on its upper bound; |
|
545 * |
|
546 * 3) if l'[q] > u[q] + eps, implied lower bound violates current |
|
547 * column upper bound u[q], in which case the problem has no primal |
|
548 * feasible solution. */ |
|
549 |
|
550 int npp_implied_lower(NPP *npp, NPPCOL *q, double l) |
|
551 { /* process implied column lower bound */ |
|
552 int ret; |
|
553 double eps, nint; |
|
554 xassert(npp == npp); |
|
555 /* column must not be fixed */ |
|
556 xassert(q->lb < q->ub); |
|
557 /* implied lower bound must be finite */ |
|
558 xassert(l != -DBL_MAX); |
|
559 /* if column is integral, round up l'[q] */ |
|
560 if (q->is_int) |
|
561 { nint = floor(l + 0.5); |
|
562 if (fabs(l - nint) <= 1e-5) |
|
563 l = nint; |
|
564 else |
|
565 l = ceil(l); |
|
566 } |
|
567 /* check current column lower bound */ |
|
568 if (q->lb != -DBL_MAX) |
|
569 { eps = (q->is_int ? 1e-3 : 1e-3 + 1e-6 * fabs(q->lb)); |
|
570 if (l < q->lb + eps) |
|
571 { ret = 0; /* redundant */ |
|
572 goto done; |
|
573 } |
|
574 } |
|
575 /* check current column upper bound */ |
|
576 if (q->ub != +DBL_MAX) |
|
577 { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->ub)); |
|
578 if (l > q->ub + eps) |
|
579 { ret = 4; /* infeasible */ |
|
580 goto done; |
|
581 } |
|
582 /* if l'[q] is close to u[q], fix column at its upper bound */ |
|
583 if (l > q->ub - 1e-3 * eps) |
|
584 { q->lb = q->ub; |
|
585 ret = 3; /* fixed */ |
|
586 goto done; |
|
587 } |
|
588 } |
|
589 /* check if column lower bound changes significantly */ |
|
590 if (q->lb == -DBL_MAX) |
|
591 ret = 2; /* significantly */ |
|
592 else if (q->is_int && l > q->lb + 0.5) |
|
593 ret = 2; /* significantly */ |
|
594 else if (l > q->lb + 0.30 * (1.0 + fabs(q->lb))) |
|
595 ret = 2; /* significantly */ |
|
596 else |
|
597 ret = 1; /* not significantly */ |
|
598 /* set new column lower bound */ |
|
599 q->lb = l; |
|
600 done: return ret; |
|
601 } |
|
602 |
|
603 /*********************************************************************** |
|
604 * NAME |
|
605 * |
|
606 * npp_implied_upper - process implied column upper bound |
|
607 * |
|
608 * SYNOPSIS |
|
609 * |
|
610 * #include "glpnpp.h" |
|
611 * int npp_implied_upper(NPP *npp, NPPCOL *q, double u); |
|
612 * |
|
613 * DESCRIPTION |
|
614 * |
|
615 * For column q: |
|
616 * |
|
617 * l[q] <= x[q] <= u[q], (1) |
|
618 * |
|
619 * where l[q] < u[q], the routine npp_implied_upper processes its |
|
620 * implied upper bound u'[q]. As the result the current column upper |
|
621 * bound may decrease. Note that the column is kept in the problem in |
|
622 * any case. |
|
623 * |
|
624 * RETURNS |
|
625 * |
|
626 * 0 - current column upper bound has not changed; |
|
627 * |
|
628 * 1 - current column upper bound has changed, but not significantly; |
|
629 * |
|
630 * 2 - current column upper bound has significantly changed; |
|
631 * |
|
632 * 3 - column has been fixed on its lower bound; |
|
633 * |
|
634 * 4 - implied upper bound violates current column lower bound. |
|
635 * |
|
636 * ALGORITHM |
|
637 * |
|
638 * If column q is integral, before processing its implied upper bound |
|
639 * should be rounded down: |
|
640 * |
|
641 * ( floor(u'[q]+0.5), if |u'[q] - floor(l'[q]+0.5)| <= eps |
|
642 * u'[q] := < (2) |
|
643 * ( floor(l'[q]), otherwise |
|
644 * |
|
645 * where floor(u'[q]+0.5) is the nearest integer to u'[q], |
|
646 * floor(u'[q]) is largest integer not greater than u'[q], and eps is |
|
647 * an absolute tolerance for column value. |
|
648 * |
|
649 * Processing implied column upper bound u'[q] includes the following |
|
650 * cases: |
|
651 * |
|
652 * 1) if u'[q] > u[q] - eps, implied upper bound is redundant; |
|
653 * |
|
654 * 2) if l[q] - eps <= u[q] <= u[q] - eps, current column upper bound |
|
655 * u[q] can be strengthened by replacing it with u'[q]. If in this |
|
656 * case new column upper bound becomes close to current column lower |
|
657 * bound, the column can be fixed on its lower bound; |
|
658 * |
|
659 * 3) if u'[q] < l[q] - eps, implied upper bound violates current |
|
660 * column lower bound l[q], in which case the problem has no primal |
|
661 * feasible solution. */ |
|
662 |
|
663 int npp_implied_upper(NPP *npp, NPPCOL *q, double u) |
|
664 { int ret; |
|
665 double eps, nint; |
|
666 xassert(npp == npp); |
|
667 /* column must not be fixed */ |
|
668 xassert(q->lb < q->ub); |
|
669 /* implied upper bound must be finite */ |
|
670 xassert(u != +DBL_MAX); |
|
671 /* if column is integral, round down u'[q] */ |
|
672 if (q->is_int) |
|
673 { nint = floor(u + 0.5); |
|
674 if (fabs(u - nint) <= 1e-5) |
|
675 u = nint; |
|
676 else |
|
677 u = floor(u); |
|
678 } |
|
679 /* check current column upper bound */ |
|
680 if (q->ub != +DBL_MAX) |
|
681 { eps = (q->is_int ? 1e-3 : 1e-3 + 1e-6 * fabs(q->ub)); |
|
682 if (u > q->ub - eps) |
|
683 { ret = 0; /* redundant */ |
|
684 goto done; |
|
685 } |
|
686 } |
|
687 /* check current column lower bound */ |
|
688 if (q->lb != -DBL_MAX) |
|
689 { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->lb)); |
|
690 if (u < q->lb - eps) |
|
691 { ret = 4; /* infeasible */ |
|
692 goto done; |
|
693 } |
|
694 /* if u'[q] is close to l[q], fix column at its lower bound */ |
|
695 if (u < q->lb + 1e-3 * eps) |
|
696 { q->ub = q->lb; |
|
697 ret = 3; /* fixed */ |
|
698 goto done; |
|
699 } |
|
700 } |
|
701 /* check if column upper bound changes significantly */ |
|
702 if (q->ub == +DBL_MAX) |
|
703 ret = 2; /* significantly */ |
|
704 else if (q->is_int && u < q->ub - 0.5) |
|
705 ret = 2; /* significantly */ |
|
706 else if (u < q->ub - 0.30 * (1.0 + fabs(q->ub))) |
|
707 ret = 2; /* significantly */ |
|
708 else |
|
709 ret = 1; /* not significantly */ |
|
710 /* set new column upper bound */ |
|
711 q->ub = u; |
|
712 done: return ret; |
|
713 } |
|
714 |
|
715 /*********************************************************************** |
|
716 * NAME |
|
717 * |
|
718 * npp_ineq_singlet - process row singleton (inequality constraint) |
|
719 * |
|
720 * SYNOPSIS |
|
721 * |
|
722 * #include "glpnpp.h" |
|
723 * int npp_ineq_singlet(NPP *npp, NPPROW *p); |
|
724 * |
|
725 * DESCRIPTION |
|
726 * |
|
727 * The routine npp_ineq_singlet processes row p, which is inequality |
|
728 * constraint having the only non-zero coefficient: |
|
729 * |
|
730 * L[p] <= a[p,q] * x[q] <= U[p], (1) |
|
731 * |
|
732 * where L[p] < U[p], L[p] > -oo and/or U[p] < +oo. |
|
733 * |
|
734 * RETURNS |
|
735 * |
|
736 * 0 - current column bounds have not changed; |
|
737 * |
|
738 * 1 - current column bounds have changed, but not significantly; |
|
739 * |
|
740 * 2 - current column bounds have significantly changed; |
|
741 * |
|
742 * 3 - column has been fixed on its lower or upper bound; |
|
743 * |
|
744 * 4 - problem has no primal feasible solution. |
|
745 * |
|
746 * PROBLEM TRANSFORMATION |
|
747 * |
|
748 * Inequality constraint (1) defines implied bounds of column q: |
|
749 * |
|
750 * ( L[p] / a[p,q], if a[p,q] > 0 |
|
751 * l'[q] = < (2) |
|
752 * ( U[p] / a[p,q], if a[p,q] < 0 |
|
753 * |
|
754 * ( U[p] / a[p,q], if a[p,q] > 0 |
|
755 * u'[q] = < (3) |
|
756 * ( L[p] / a[p,q], if a[p,q] < 0 |
|
757 * |
|
758 * If these implied bounds do not violate current bounds of column q: |
|
759 * |
|
760 * l[q] <= x[q] <= u[q], (4) |
|
761 * |
|
762 * they can be used to strengthen the current column bounds: |
|
763 * |
|
764 * l[q] := max(l[q], l'[q]), (5) |
|
765 * |
|
766 * u[q] := min(u[q], u'[q]). (6) |
|
767 * |
|
768 * (See the routines npp_implied_lower and npp_implied_upper.) |
|
769 * |
|
770 * Once bounds of row p (1) have been carried over column q, the row |
|
771 * becomes redundant, so it can be replaced by equivalent free row and |
|
772 * removed from the problem. |
|
773 * |
|
774 * Note that the routine removes from the problem only row p. Column q, |
|
775 * even it has been fixed, is kept in the problem. |
|
776 * |
|
777 * RECOVERING BASIC SOLUTION |
|
778 * |
|
779 * Note that the row in the dual system corresponding to column q is |
|
780 * the following: |
|
781 * |
|
782 * sum a[i,q] pi[i] + lambda[q] = c[q] ==> |
|
783 * i |
|
784 * (7) |
|
785 * sum a[i,q] pi[i] + a[p,q] pi[p] + lambda[q] = c[q], |
|
786 * i!=p |
|
787 * |
|
788 * where pi[i] for all i != p are known in solution to the transformed |
|
789 * problem. Row p does not exist in the transformed problem, so it has |
|
790 * zero multiplier there. This allows computing multiplier for column q |
|
791 * in solution to the transformed problem: |
|
792 * |
|
793 * lambda~[q] = c[q] - sum a[i,q] pi[i]. (8) |
|
794 * i!=p |
|
795 * |
|
796 * Let in solution to the transformed problem column q be non-basic |
|
797 * with lower bound active (GLP_NL, lambda~[q] >= 0), and this lower |
|
798 * bound be implied one l'[q]. From the original problem's standpoint |
|
799 * this then means that actually the original column lower bound l[q] |
|
800 * is inactive, and active is that row bound L[p] or U[p] that defines |
|
801 * the implied bound l'[q] (2). In this case in solution to the |
|
802 * original problem column q is assigned status GLP_BS while row p is |
|
803 * assigned status GLP_NL (if a[p,q] > 0) or GLP_NU (if a[p,q] < 0). |
|
804 * Since now column q is basic, its multiplier lambda[q] is zero. This |
|
805 * allows using (7) and (8) to find multiplier for row p in solution to |
|
806 * the original problem: |
|
807 * |
|
808 * 1 |
|
809 * pi[p] = ------ (c[q] - sum a[i,q] pi[i]) = lambda~[q] / a[p,q] (9) |
|
810 * a[p,q] i!=p |
|
811 * |
|
812 * Now let in solution to the transformed problem column q be non-basic |
|
813 * with upper bound active (GLP_NU, lambda~[q] <= 0), and this upper |
|
814 * bound be implied one u'[q]. As in the previous case this then means |
|
815 * that from the original problem's standpoint actually the original |
|
816 * column upper bound u[q] is inactive, and active is that row bound |
|
817 * L[p] or U[p] that defines the implied bound u'[q] (3). In this case |
|
818 * in solution to the original problem column q is assigned status |
|
819 * GLP_BS, row p is assigned status GLP_NU (if a[p,q] > 0) or GLP_NL |
|
820 * (if a[p,q] < 0), and its multiplier is computed with formula (9). |
|
821 * |
|
822 * Strengthening bounds of column q according to (5) and (6) may make |
|
823 * it fixed. Thus, if in solution to the transformed problem column q is |
|
824 * non-basic and fixed (GLP_NS), we can suppose that if lambda~[q] > 0, |
|
825 * column q has active lower bound (GLP_NL), and if lambda~[q] < 0, |
|
826 * column q has active upper bound (GLP_NU), reducing this case to two |
|
827 * previous ones. If, however, lambda~[q] is close to zero or |
|
828 * corresponding bound of row p does not exist (this may happen if |
|
829 * lambda~[q] has wrong sign due to round-off errors, in which case it |
|
830 * is expected to be close to zero, since solution is assumed to be dual |
|
831 * feasible), column q can be assigned status GLP_BS (basic), and row p |
|
832 * can be made active on its existing bound. In the latter case row |
|
833 * multiplier pi[p] computed with formula (9) will be also close to |
|
834 * zero, and dual feasibility will be kept. |
|
835 * |
|
836 * In all other cases, namely, if in solution to the transformed |
|
837 * problem column q is basic (GLP_BS), or non-basic with original lower |
|
838 * bound l[q] active (GLP_NL), or non-basic with original upper bound |
|
839 * u[q] active (GLP_NU), constraint (1) is inactive. So in solution to |
|
840 * the original problem status of column q remains unchanged, row p is |
|
841 * assigned status GLP_BS, and its multiplier pi[p] is assigned zero |
|
842 * value. |
|
843 * |
|
844 * RECOVERING INTERIOR-POINT SOLUTION |
|
845 * |
|
846 * First, value of multiplier for column q in solution to the original |
|
847 * problem is computed with formula (8). If lambda~[q] > 0 and column q |
|
848 * has implied lower bound, or if lambda~[q] < 0 and column q has |
|
849 * implied upper bound, this means that from the original problem's |
|
850 * standpoint actually row p has corresponding active bound, in which |
|
851 * case its multiplier pi[p] is computed with formula (9). In other |
|
852 * cases, when the sign of lambda~[q] corresponds to original bound of |
|
853 * column q, or when lambda~[q] =~ 0, value of row multiplier pi[p] is |
|
854 * assigned zero value. |
|
855 * |
|
856 * RECOVERING MIP SOLUTION |
|
857 * |
|
858 * None needed. */ |
|
859 |
|
860 struct ineq_singlet |
|
861 { /* row singleton (inequality constraint) */ |
|
862 int p; |
|
863 /* row reference number */ |
|
864 int q; |
|
865 /* column reference number */ |
|
866 double apq; |
|
867 /* constraint coefficient a[p,q] */ |
|
868 double c; |
|
869 /* objective coefficient at x[q] */ |
|
870 double lb; |
|
871 /* row lower bound */ |
|
872 double ub; |
|
873 /* row upper bound */ |
|
874 char lb_changed; |
|
875 /* this flag is set if column lower bound was changed */ |
|
876 char ub_changed; |
|
877 /* this flag is set if column upper bound was changed */ |
|
878 NPPLFE *ptr; |
|
879 /* list of non-zero coefficients a[i,q], i != p */ |
|
880 }; |
|
881 |
|
882 static int rcv_ineq_singlet(NPP *npp, void *info); |
|
883 |
|
884 int npp_ineq_singlet(NPP *npp, NPPROW *p) |
|
885 { /* process row singleton (inequality constraint) */ |
|
886 struct ineq_singlet *info; |
|
887 NPPCOL *q; |
|
888 NPPAIJ *apq, *aij; |
|
889 NPPLFE *lfe; |
|
890 int lb_changed, ub_changed; |
|
891 double ll, uu; |
|
892 /* the row must be singleton inequality constraint */ |
|
893 xassert(p->lb != -DBL_MAX || p->ub != +DBL_MAX); |
|
894 xassert(p->lb < p->ub); |
|
895 xassert(p->ptr != NULL && p->ptr->r_next == NULL); |
|
896 /* compute implied column bounds */ |
|
897 apq = p->ptr; |
|
898 q = apq->col; |
|
899 xassert(q->lb < q->ub); |
|
900 if (apq->val > 0.0) |
|
901 { ll = (p->lb == -DBL_MAX ? -DBL_MAX : p->lb / apq->val); |
|
902 uu = (p->ub == +DBL_MAX ? +DBL_MAX : p->ub / apq->val); |
|
903 } |
|
904 else |
|
905 { ll = (p->ub == +DBL_MAX ? -DBL_MAX : p->ub / apq->val); |
|
906 uu = (p->lb == -DBL_MAX ? +DBL_MAX : p->lb / apq->val); |
|
907 } |
|
908 /* process implied column lower bound */ |
|
909 if (ll == -DBL_MAX) |
|
910 lb_changed = 0; |
|
911 else |
|
912 { lb_changed = npp_implied_lower(npp, q, ll); |
|
913 xassert(0 <= lb_changed && lb_changed <= 4); |
|
914 if (lb_changed == 4) return 4; /* infeasible */ |
|
915 } |
|
916 /* process implied column upper bound */ |
|
917 if (uu == +DBL_MAX) |
|
918 ub_changed = 0; |
|
919 else if (lb_changed == 3) |
|
920 { /* column was fixed on its upper bound due to l'[q] = u[q] */ |
|
921 /* note that L[p] < U[p], so l'[q] = u[q] < u'[q] */ |
|
922 ub_changed = 0; |
|
923 } |
|
924 else |
|
925 { ub_changed = npp_implied_upper(npp, q, uu); |
|
926 xassert(0 <= ub_changed && ub_changed <= 4); |
|
927 if (ub_changed == 4) return 4; /* infeasible */ |
|
928 } |
|
929 /* if neither lower nor upper column bound was changed, the row |
|
930 is originally redundant and can be replaced by free row */ |
|
931 if (!lb_changed && !ub_changed) |
|
932 { p->lb = -DBL_MAX, p->ub = +DBL_MAX; |
|
933 npp_free_row(npp, p); |
|
934 return 0; |
|
935 } |
|
936 /* create transformation stack entry */ |
|
937 info = npp_push_tse(npp, |
|
938 rcv_ineq_singlet, sizeof(struct ineq_singlet)); |
|
939 info->p = p->i; |
|
940 info->q = q->j; |
|
941 info->apq = apq->val; |
|
942 info->c = q->coef; |
|
943 info->lb = p->lb; |
|
944 info->ub = p->ub; |
|
945 info->lb_changed = (char)lb_changed; |
|
946 info->ub_changed = (char)ub_changed; |
|
947 info->ptr = NULL; |
|
948 /* save column coefficients a[i,q], i != p (not needed for MIP |
|
949 solution) */ |
|
950 if (npp->sol != GLP_MIP) |
|
951 { for (aij = q->ptr; aij != NULL; aij = aij->c_next) |
|
952 { if (aij == apq) continue; /* skip a[p,q] */ |
|
953 lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); |
|
954 lfe->ref = aij->row->i; |
|
955 lfe->val = aij->val; |
|
956 lfe->next = info->ptr; |
|
957 info->ptr = lfe; |
|
958 } |
|
959 } |
|
960 /* remove the row from the problem */ |
|
961 npp_del_row(npp, p); |
|
962 return lb_changed >= ub_changed ? lb_changed : ub_changed; |
|
963 } |
|
964 |
|
965 static int rcv_ineq_singlet(NPP *npp, void *_info) |
|
966 { /* recover row singleton (inequality constraint) */ |
|
967 struct ineq_singlet *info = _info; |
|
968 NPPLFE *lfe; |
|
969 double lambda; |
|
970 if (npp->sol == GLP_MIP) goto done; |
|
971 /* compute lambda~[q] in solution to the transformed problem |
|
972 with formula (8) */ |
|
973 lambda = info->c; |
|
974 for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) |
|
975 lambda -= lfe->val * npp->r_pi[lfe->ref]; |
|
976 if (npp->sol == GLP_SOL) |
|
977 { /* recover basic solution */ |
|
978 if (npp->c_stat[info->q] == GLP_BS) |
|
979 { /* column q is basic, so row p is inactive */ |
|
980 npp->r_stat[info->p] = GLP_BS; |
|
981 npp->r_pi[info->p] = 0.0; |
|
982 } |
|
983 else if (npp->c_stat[info->q] == GLP_NL) |
|
984 nl: { /* column q is non-basic with lower bound active */ |
|
985 if (info->lb_changed) |
|
986 { /* it is implied bound, so actually row p is active |
|
987 while column q is basic */ |
|
988 npp->r_stat[info->p] = |
|
989 (char)(info->apq > 0.0 ? GLP_NL : GLP_NU); |
|
990 npp->c_stat[info->q] = GLP_BS; |
|
991 npp->r_pi[info->p] = lambda / info->apq; |
|
992 } |
|
993 else |
|
994 { /* it is original bound, so row p is inactive */ |
|
995 npp->r_stat[info->p] = GLP_BS; |
|
996 npp->r_pi[info->p] = 0.0; |
|
997 } |
|
998 } |
|
999 else if (npp->c_stat[info->q] == GLP_NU) |
|
1000 nu: { /* column q is non-basic with upper bound active */ |
|
1001 if (info->ub_changed) |
|
1002 { /* it is implied bound, so actually row p is active |
|
1003 while column q is basic */ |
|
1004 npp->r_stat[info->p] = |
|
1005 (char)(info->apq > 0.0 ? GLP_NU : GLP_NL); |
|
1006 npp->c_stat[info->q] = GLP_BS; |
|
1007 npp->r_pi[info->p] = lambda / info->apq; |
|
1008 } |
|
1009 else |
|
1010 { /* it is original bound, so row p is inactive */ |
|
1011 npp->r_stat[info->p] = GLP_BS; |
|
1012 npp->r_pi[info->p] = 0.0; |
|
1013 } |
|
1014 } |
|
1015 else if (npp->c_stat[info->q] == GLP_NS) |
|
1016 { /* column q is non-basic and fixed; note, however, that in |
|
1017 in the original problem it is non-fixed */ |
|
1018 if (lambda > +1e-7) |
|
1019 { if (info->apq > 0.0 && info->lb != -DBL_MAX || |
|
1020 info->apq < 0.0 && info->ub != +DBL_MAX || |
|
1021 !info->lb_changed) |
|
1022 { /* either corresponding bound of row p exists or |
|
1023 column q remains non-basic with its original lower |
|
1024 bound active */ |
|
1025 npp->c_stat[info->q] = GLP_NL; |
|
1026 goto nl; |
|
1027 } |
|
1028 } |
|
1029 if (lambda < -1e-7) |
|
1030 { if (info->apq > 0.0 && info->ub != +DBL_MAX || |
|
1031 info->apq < 0.0 && info->lb != -DBL_MAX || |
|
1032 !info->ub_changed) |
|
1033 { /* either corresponding bound of row p exists or |
|
1034 column q remains non-basic with its original upper |
|
1035 bound active */ |
|
1036 npp->c_stat[info->q] = GLP_NU; |
|
1037 goto nu; |
|
1038 } |
|
1039 } |
|
1040 /* either lambda~[q] is close to zero, or corresponding |
|
1041 bound of row p does not exist, because lambda~[q] has |
|
1042 wrong sign due to round-off errors; in the latter case |
|
1043 lambda~[q] is also assumed to be close to zero; so, we |
|
1044 can make row p active on its existing bound and column q |
|
1045 basic; pi[p] will have wrong sign, but it also will be |
|
1046 close to zero (rarus casus of dual degeneracy) */ |
|
1047 if (info->lb != -DBL_MAX && info->ub == +DBL_MAX) |
|
1048 { /* row lower bound exists, but upper bound doesn't */ |
|
1049 npp->r_stat[info->p] = GLP_NL; |
|
1050 } |
|
1051 else if (info->lb == -DBL_MAX && info->ub != +DBL_MAX) |
|
1052 { /* row upper bound exists, but lower bound doesn't */ |
|
1053 npp->r_stat[info->p] = GLP_NU; |
|
1054 } |
|
1055 else if (info->lb != -DBL_MAX && info->ub != +DBL_MAX) |
|
1056 { /* both row lower and upper bounds exist */ |
|
1057 /* to choose proper active row bound we should not use |
|
1058 lambda~[q], because its value being close to zero is |
|
1059 unreliable; so we choose that bound which provides |
|
1060 primal feasibility for original constraint (1) */ |
|
1061 if (info->apq * npp->c_value[info->q] <= |
|
1062 0.5 * (info->lb + info->ub)) |
|
1063 npp->r_stat[info->p] = GLP_NL; |
|
1064 else |
|
1065 npp->r_stat[info->p] = GLP_NU; |
|
1066 } |
|
1067 else |
|
1068 { npp_error(); |
|
1069 return 1; |
|
1070 } |
|
1071 npp->c_stat[info->q] = GLP_BS; |
|
1072 npp->r_pi[info->p] = lambda / info->apq; |
|
1073 } |
|
1074 else |
|
1075 { npp_error(); |
|
1076 return 1; |
|
1077 } |
|
1078 } |
|
1079 if (npp->sol == GLP_IPT) |
|
1080 { /* recover interior-point solution */ |
|
1081 if (lambda > +DBL_EPSILON && info->lb_changed || |
|
1082 lambda < -DBL_EPSILON && info->ub_changed) |
|
1083 { /* actually row p has corresponding active bound */ |
|
1084 npp->r_pi[info->p] = lambda / info->apq; |
|
1085 } |
|
1086 else |
|
1087 { /* either bounds of column q are both inactive or its |
|
1088 original bound is active */ |
|
1089 npp->r_pi[info->p] = 0.0; |
|
1090 } |
|
1091 } |
|
1092 done: return 0; |
|
1093 } |
|
1094 |
|
1095 /*********************************************************************** |
|
1096 * NAME |
|
1097 * |
|
1098 * npp_implied_slack - process column singleton (implied slack variable) |
|
1099 * |
|
1100 * SYNOPSIS |
|
1101 * |
|
1102 * #include "glpnpp.h" |
|
1103 * void npp_implied_slack(NPP *npp, NPPCOL *q); |
|
1104 * |
|
1105 * DESCRIPTION |
|
1106 * |
|
1107 * The routine npp_implied_slack processes column q: |
|
1108 * |
|
1109 * l[q] <= x[q] <= u[q], (1) |
|
1110 * |
|
1111 * where l[q] < u[q], having the only non-zero coefficient in row p, |
|
1112 * which is equality constraint: |
|
1113 * |
|
1114 * sum a[p,j] x[j] + a[p,q] x[q] = b. (2) |
|
1115 * j!=q |
|
1116 * |
|
1117 * PROBLEM TRANSFORMATION |
|
1118 * |
|
1119 * (If x[q] is integral, this transformation must not be used.) |
|
1120 * |
|
1121 * The term a[p,q] x[q] in constraint (2) can be considered as a slack |
|
1122 * variable that allows to carry bounds of column q over row p and then |
|
1123 * remove column q from the problem. |
|
1124 * |
|
1125 * Constraint (2) can be written as follows: |
|
1126 * |
|
1127 * sum a[p,j] x[j] = b - a[p,q] x[q]. (3) |
|
1128 * j!=q |
|
1129 * |
|
1130 * According to (1) constraint (3) is equivalent to the following |
|
1131 * inequality constraint: |
|
1132 * |
|
1133 * L[p] <= sum a[p,j] x[j] <= U[p], (4) |
|
1134 * j!=q |
|
1135 * |
|
1136 * where |
|
1137 * |
|
1138 * ( b - a[p,q] u[q], if a[p,q] > 0 |
|
1139 * L[p] = < (5) |
|
1140 * ( b - a[p,q] l[q], if a[p,q] < 0 |
|
1141 * |
|
1142 * ( b - a[p,q] l[q], if a[p,q] > 0 |
|
1143 * U[p] = < (6) |
|
1144 * ( b - a[p,q] u[q], if a[p,q] < 0 |
|
1145 * |
|
1146 * From (2) it follows that: |
|
1147 * |
|
1148 * 1 |
|
1149 * x[q] = ------ (b - sum a[p,j] x[j]). (7) |
|
1150 * a[p,q] j!=q |
|
1151 * |
|
1152 * In order to eliminate x[q] from the objective row we substitute it |
|
1153 * from (6) to that row: |
|
1154 * |
|
1155 * z = sum c[j] x[j] + c[q] x[q] + c[0] = |
|
1156 * j!=q |
|
1157 * 1 |
|
1158 * = sum c[j] x[j] + c[q] [------ (b - sum a[p,j] x[j])] + c0 = |
|
1159 * j!=q a[p,q] j!=q |
|
1160 * |
|
1161 * = sum c~[j] x[j] + c~[0], |
|
1162 * j!=q |
|
1163 * a[p,j] b |
|
1164 * c~[j] = c[j] - c[q] ------, c~0 = c0 - c[q] ------ (8) |
|
1165 * a[p,q] a[p,q] |
|
1166 * |
|
1167 * are values of objective coefficients and constant term, resp., in |
|
1168 * the transformed problem. |
|
1169 * |
|
1170 * Note that column q is column singleton, so in the dual system of the |
|
1171 * original problem it corresponds to the following row singleton: |
|
1172 * |
|
1173 * a[p,q] pi[p] + lambda[q] = c[q]. (9) |
|
1174 * |
|
1175 * In the transformed problem row (9) would be the following: |
|
1176 * |
|
1177 * a[p,q] pi~[p] + lambda[q] = c~[q] = 0. (10) |
|
1178 * |
|
1179 * Subtracting (10) from (9) we have: |
|
1180 * |
|
1181 * a[p,q] (pi[p] - pi~[p]) = c[q] |
|
1182 * |
|
1183 * that gives the following formula to compute multiplier for row p in |
|
1184 * solution to the original problem using its value in solution to the |
|
1185 * transformed problem: |
|
1186 * |
|
1187 * pi[p] = pi~[p] + c[q] / a[p,q]. (11) |
|
1188 * |
|
1189 * RECOVERING BASIC SOLUTION |
|
1190 * |
|
1191 * Status of column q in solution to the original problem is defined |
|
1192 * by status of row p in solution to the transformed problem and the |
|
1193 * sign of coefficient a[p,q] in the original inequality constraint (2) |
|
1194 * as follows: |
|
1195 * |
|
1196 * +-----------------------+---------+--------------------+ |
|
1197 * | Status of row p | Sign of | Status of column q | |
|
1198 * | (transformed problem) | a[p,q] | (original problem) | |
|
1199 * +-----------------------+---------+--------------------+ |
|
1200 * | GLP_BS | + / - | GLP_BS | |
|
1201 * | GLP_NL | + | GLP_NU | |
|
1202 * | GLP_NL | - | GLP_NL | |
|
1203 * | GLP_NU | + | GLP_NL | |
|
1204 * | GLP_NU | - | GLP_NU | |
|
1205 * | GLP_NF | + / - | GLP_NF | |
|
1206 * +-----------------------+---------+--------------------+ |
|
1207 * |
|
1208 * Value of column q is computed with formula (7). Since originally row |
|
1209 * p is equality constraint, its status is assigned GLP_NS, and value of |
|
1210 * its multiplier pi[p] is computed with formula (11). |
|
1211 * |
|
1212 * RECOVERING INTERIOR-POINT SOLUTION |
|
1213 * |
|
1214 * Value of column q is computed with formula (7). Row multiplier value |
|
1215 * pi[p] is computed with formula (11). |
|
1216 * |
|
1217 * RECOVERING MIP SOLUTION |
|
1218 * |
|
1219 * Value of column q is computed with formula (7). */ |
|
1220 |
|
1221 struct implied_slack |
|
1222 { /* column singleton (implied slack variable) */ |
|
1223 int p; |
|
1224 /* row reference number */ |
|
1225 int q; |
|
1226 /* column reference number */ |
|
1227 double apq; |
|
1228 /* constraint coefficient a[p,q] */ |
|
1229 double b; |
|
1230 /* right-hand side of original equality constraint */ |
|
1231 double c; |
|
1232 /* original objective coefficient at x[q] */ |
|
1233 NPPLFE *ptr; |
|
1234 /* list of non-zero coefficients a[p,j], j != q */ |
|
1235 }; |
|
1236 |
|
1237 static int rcv_implied_slack(NPP *npp, void *info); |
|
1238 |
|
1239 void npp_implied_slack(NPP *npp, NPPCOL *q) |
|
1240 { /* process column singleton (implied slack variable) */ |
|
1241 struct implied_slack *info; |
|
1242 NPPROW *p; |
|
1243 NPPAIJ *aij; |
|
1244 NPPLFE *lfe; |
|
1245 /* the column must be non-integral non-fixed singleton */ |
|
1246 xassert(!q->is_int); |
|
1247 xassert(q->lb < q->ub); |
|
1248 xassert(q->ptr != NULL && q->ptr->c_next == NULL); |
|
1249 /* corresponding row must be equality constraint */ |
|
1250 aij = q->ptr; |
|
1251 p = aij->row; |
|
1252 xassert(p->lb == p->ub); |
|
1253 /* create transformation stack entry */ |
|
1254 info = npp_push_tse(npp, |
|
1255 rcv_implied_slack, sizeof(struct implied_slack)); |
|
1256 info->p = p->i; |
|
1257 info->q = q->j; |
|
1258 info->apq = aij->val; |
|
1259 info->b = p->lb; |
|
1260 info->c = q->coef; |
|
1261 info->ptr = NULL; |
|
1262 /* save row coefficients a[p,j], j != q, and substitute x[q] |
|
1263 into the objective row */ |
|
1264 for (aij = p->ptr; aij != NULL; aij = aij->r_next) |
|
1265 { if (aij->col == q) continue; /* skip a[p,q] */ |
|
1266 lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); |
|
1267 lfe->ref = aij->col->j; |
|
1268 lfe->val = aij->val; |
|
1269 lfe->next = info->ptr; |
|
1270 info->ptr = lfe; |
|
1271 aij->col->coef -= info->c * (aij->val / info->apq); |
|
1272 } |
|
1273 npp->c0 += info->c * (info->b / info->apq); |
|
1274 /* compute new row bounds */ |
|
1275 if (info->apq > 0.0) |
|
1276 { p->lb = (q->ub == +DBL_MAX ? |
|
1277 -DBL_MAX : info->b - info->apq * q->ub); |
|
1278 p->ub = (q->lb == -DBL_MAX ? |
|
1279 +DBL_MAX : info->b - info->apq * q->lb); |
|
1280 } |
|
1281 else |
|
1282 { p->lb = (q->lb == -DBL_MAX ? |
|
1283 -DBL_MAX : info->b - info->apq * q->lb); |
|
1284 p->ub = (q->ub == +DBL_MAX ? |
|
1285 +DBL_MAX : info->b - info->apq * q->ub); |
|
1286 } |
|
1287 /* remove the column from the problem */ |
|
1288 npp_del_col(npp, q); |
|
1289 return; |
|
1290 } |
|
1291 |
|
1292 static int rcv_implied_slack(NPP *npp, void *_info) |
|
1293 { /* recover column singleton (implied slack variable) */ |
|
1294 struct implied_slack *info = _info; |
|
1295 NPPLFE *lfe; |
|
1296 double temp; |
|
1297 if (npp->sol == GLP_SOL) |
|
1298 { /* assign statuses to row p and column q */ |
|
1299 if (npp->r_stat[info->p] == GLP_BS || |
|
1300 npp->r_stat[info->p] == GLP_NF) |
|
1301 npp->c_stat[info->q] = npp->r_stat[info->p]; |
|
1302 else if (npp->r_stat[info->p] == GLP_NL) |
|
1303 npp->c_stat[info->q] = |
|
1304 (char)(info->apq > 0.0 ? GLP_NU : GLP_NL); |
|
1305 else if (npp->r_stat[info->p] == GLP_NU) |
|
1306 npp->c_stat[info->q] = |
|
1307 (char)(info->apq > 0.0 ? GLP_NL : GLP_NU); |
|
1308 else |
|
1309 { npp_error(); |
|
1310 return 1; |
|
1311 } |
|
1312 npp->r_stat[info->p] = GLP_NS; |
|
1313 } |
|
1314 if (npp->sol != GLP_MIP) |
|
1315 { /* compute multiplier for row p */ |
|
1316 npp->r_pi[info->p] += info->c / info->apq; |
|
1317 } |
|
1318 /* compute value of column q */ |
|
1319 temp = info->b; |
|
1320 for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) |
|
1321 temp -= lfe->val * npp->c_value[lfe->ref]; |
|
1322 npp->c_value[info->q] = temp / info->apq; |
|
1323 return 0; |
|
1324 } |
|
1325 |
|
1326 /*********************************************************************** |
|
1327 * NAME |
|
1328 * |
|
1329 * npp_implied_free - process column singleton (implied free variable) |
|
1330 * |
|
1331 * SYNOPSIS |
|
1332 * |
|
1333 * #include "glpnpp.h" |
|
1334 * int npp_implied_free(NPP *npp, NPPCOL *q); |
|
1335 * |
|
1336 * DESCRIPTION |
|
1337 * |
|
1338 * The routine npp_implied_free processes column q: |
|
1339 * |
|
1340 * l[q] <= x[q] <= u[q], (1) |
|
1341 * |
|
1342 * having non-zero coefficient in the only row p, which is inequality |
|
1343 * constraint: |
|
1344 * |
|
1345 * L[p] <= sum a[p,j] x[j] + a[p,q] x[q] <= U[p], (2) |
|
1346 * j!=q |
|
1347 * |
|
1348 * where l[q] < u[q], L[p] < U[p], L[p] > -oo and/or U[p] < +oo. |
|
1349 * |
|
1350 * RETURNS |
|
1351 * |
|
1352 * 0 - success; |
|
1353 * |
|
1354 * 1 - column lower and/or upper bound(s) can be active; |
|
1355 * |
|
1356 * 2 - problem has no dual feasible solution. |
|
1357 * |
|
1358 * PROBLEM TRANSFORMATION |
|
1359 * |
|
1360 * Constraint (2) can be written as follows: |
|
1361 * |
|
1362 * L[p] - sum a[p,j] x[j] <= a[p,q] x[q] <= U[p] - sum a[p,j] x[j], |
|
1363 * j!=q j!=q |
|
1364 * |
|
1365 * from which it follows that: |
|
1366 * |
|
1367 * alfa <= a[p,q] x[q] <= beta, (3) |
|
1368 * |
|
1369 * where |
|
1370 * |
|
1371 * alfa = inf(L[p] - sum a[p,j] x[j]) = |
|
1372 * j!=q |
|
1373 * |
|
1374 * = L[p] - sup sum a[p,j] x[j] = (4) |
|
1375 * j!=q |
|
1376 * |
|
1377 * = L[p] - sum a[p,j] u[j] - sum a[p,j] l[j], |
|
1378 * j in Jp j in Jn |
|
1379 * |
|
1380 * beta = sup(L[p] - sum a[p,j] x[j]) = |
|
1381 * j!=q |
|
1382 * |
|
1383 * = L[p] - inf sum a[p,j] x[j] = (5) |
|
1384 * j!=q |
|
1385 * |
|
1386 * = L[p] - sum a[p,j] l[j] - sum a[p,j] u[j], |
|
1387 * j in Jp j in Jn |
|
1388 * |
|
1389 * Jp = {j != q: a[p,j] > 0}, Jn = {j != q: a[p,j] < 0}. (6) |
|
1390 * |
|
1391 * Inequality (3) defines implied bounds of variable x[q]: |
|
1392 * |
|
1393 * l'[q] <= x[q] <= u'[q], (7) |
|
1394 * |
|
1395 * where |
|
1396 * |
|
1397 * ( alfa / a[p,q], if a[p,q] > 0 |
|
1398 * l'[q] = < (8a) |
|
1399 * ( beta / a[p,q], if a[p,q] < 0 |
|
1400 * |
|
1401 * ( beta / a[p,q], if a[p,q] > 0 |
|
1402 * u'[q] = < (8b) |
|
1403 * ( alfa / a[p,q], if a[p,q] < 0 |
|
1404 * |
|
1405 * Thus, if l'[q] > l[q] - eps and u'[q] < u[q] + eps, where eps is |
|
1406 * an absolute tolerance for column value, column bounds (1) cannot be |
|
1407 * active, in which case column q can be replaced by equivalent free |
|
1408 * (unbounded) column. |
|
1409 * |
|
1410 * Note that column q is column singleton, so in the dual system of the |
|
1411 * original problem it corresponds to the following row singleton: |
|
1412 * |
|
1413 * a[p,q] pi[p] + lambda[q] = c[q], (9) |
|
1414 * |
|
1415 * from which it follows that: |
|
1416 * |
|
1417 * pi[p] = (c[q] - lambda[q]) / a[p,q]. (10) |
|
1418 * |
|
1419 * Let x[q] be implied free (unbounded) variable. Then column q can be |
|
1420 * only basic, so its multiplier lambda[q] is equal to zero, and from |
|
1421 * (10) we have: |
|
1422 * |
|
1423 * pi[p] = c[q] / a[p,q]. (11) |
|
1424 * |
|
1425 * There are possible three cases: |
|
1426 * |
|
1427 * 1) pi[p] < -eps, where eps is an absolute tolerance for row |
|
1428 * multiplier. In this case, to provide dual feasibility of the |
|
1429 * original problem, row p must be active on its lower bound, and |
|
1430 * if its lower bound does not exist (L[p] = -oo), the problem has |
|
1431 * no dual feasible solution; |
|
1432 * |
|
1433 * 2) pi[p] > +eps. In this case row p must be active on its upper |
|
1434 * bound, and if its upper bound does not exist (U[p] = +oo), the |
|
1435 * problem has no dual feasible solution; |
|
1436 * |
|
1437 * 3) -eps <= pi[p] <= +eps. In this case any (either lower or upper) |
|
1438 * bound of row p can be active, because this does not affect dual |
|
1439 * feasibility. |
|
1440 * |
|
1441 * Thus, in all three cases original inequality constraint (2) can be |
|
1442 * replaced by equality constraint, where the right-hand side is either |
|
1443 * lower or upper bound of row p, and bounds of column q can be removed |
|
1444 * that makes it free (unbounded). (May note that this transformation |
|
1445 * can be followed by transformation "Column singleton (implied slack |
|
1446 * variable)" performed by the routine npp_implied_slack.) |
|
1447 * |
|
1448 * RECOVERING BASIC SOLUTION |
|
1449 * |
|
1450 * Status of row p in solution to the original problem is determined |
|
1451 * by its status in solution to the transformed problem and its bound, |
|
1452 * which was choosen to be active: |
|
1453 * |
|
1454 * +-----------------------+--------+--------------------+ |
|
1455 * | Status of row p | Active | Status of row p | |
|
1456 * | (transformed problem) | bound | (original problem) | |
|
1457 * +-----------------------+--------+--------------------+ |
|
1458 * | GLP_BS | L[p] | GLP_BS | |
|
1459 * | GLP_BS | U[p] | GLP_BS | |
|
1460 * | GLP_NS | L[p] | GLP_NL | |
|
1461 * | GLP_NS | U[p] | GLP_NU | |
|
1462 * +-----------------------+--------+--------------------+ |
|
1463 * |
|
1464 * Value of row multiplier pi[p] (as well as value of column q) in |
|
1465 * solution to the original problem is the same as in solution to the |
|
1466 * transformed problem. |
|
1467 * |
|
1468 * RECOVERING INTERIOR-POINT SOLUTION |
|
1469 * |
|
1470 * Value of row multiplier pi[p] in solution to the original problem is |
|
1471 * the same as in solution to the transformed problem. |
|
1472 * |
|
1473 * RECOVERING MIP SOLUTION |
|
1474 * |
|
1475 * None needed. */ |
|
1476 |
|
1477 struct implied_free |
|
1478 { /* column singleton (implied free variable) */ |
|
1479 int p; |
|
1480 /* row reference number */ |
|
1481 char stat; |
|
1482 /* row status: |
|
1483 GLP_NL - active constraint on lower bound |
|
1484 GLP_NU - active constraint on upper bound */ |
|
1485 }; |
|
1486 |
|
1487 static int rcv_implied_free(NPP *npp, void *info); |
|
1488 |
|
1489 int npp_implied_free(NPP *npp, NPPCOL *q) |
|
1490 { /* process column singleton (implied free variable) */ |
|
1491 struct implied_free *info; |
|
1492 NPPROW *p; |
|
1493 NPPAIJ *apq, *aij; |
|
1494 double alfa, beta, l, u, pi, eps; |
|
1495 /* the column must be non-fixed singleton */ |
|
1496 xassert(q->lb < q->ub); |
|
1497 xassert(q->ptr != NULL && q->ptr->c_next == NULL); |
|
1498 /* corresponding row must be inequality constraint */ |
|
1499 apq = q->ptr; |
|
1500 p = apq->row; |
|
1501 xassert(p->lb != -DBL_MAX || p->ub != +DBL_MAX); |
|
1502 xassert(p->lb < p->ub); |
|
1503 /* compute alfa */ |
|
1504 alfa = p->lb; |
|
1505 if (alfa != -DBL_MAX) |
|
1506 { for (aij = p->ptr; aij != NULL; aij = aij->r_next) |
|
1507 { if (aij == apq) continue; /* skip a[p,q] */ |
|
1508 if (aij->val > 0.0) |
|
1509 { if (aij->col->ub == +DBL_MAX) |
|
1510 { alfa = -DBL_MAX; |
|
1511 break; |
|
1512 } |
|
1513 alfa -= aij->val * aij->col->ub; |
|
1514 } |
|
1515 else /* < 0.0 */ |
|
1516 { if (aij->col->lb == -DBL_MAX) |
|
1517 { alfa = -DBL_MAX; |
|
1518 break; |
|
1519 } |
|
1520 alfa -= aij->val * aij->col->lb; |
|
1521 } |
|
1522 } |
|
1523 } |
|
1524 /* compute beta */ |
|
1525 beta = p->ub; |
|
1526 if (beta != +DBL_MAX) |
|
1527 { for (aij = p->ptr; aij != NULL; aij = aij->r_next) |
|
1528 { if (aij == apq) continue; /* skip a[p,q] */ |
|
1529 if (aij->val > 0.0) |
|
1530 { if (aij->col->lb == -DBL_MAX) |
|
1531 { beta = +DBL_MAX; |
|
1532 break; |
|
1533 } |
|
1534 beta -= aij->val * aij->col->lb; |
|
1535 } |
|
1536 else /* < 0.0 */ |
|
1537 { if (aij->col->ub == +DBL_MAX) |
|
1538 { beta = +DBL_MAX; |
|
1539 break; |
|
1540 } |
|
1541 beta -= aij->val * aij->col->ub; |
|
1542 } |
|
1543 } |
|
1544 } |
|
1545 /* compute implied column lower bound l'[q] */ |
|
1546 if (apq->val > 0.0) |
|
1547 l = (alfa == -DBL_MAX ? -DBL_MAX : alfa / apq->val); |
|
1548 else /* < 0.0 */ |
|
1549 l = (beta == +DBL_MAX ? -DBL_MAX : beta / apq->val); |
|
1550 /* compute implied column upper bound u'[q] */ |
|
1551 if (apq->val > 0.0) |
|
1552 u = (beta == +DBL_MAX ? +DBL_MAX : beta / apq->val); |
|
1553 else |
|
1554 u = (alfa == -DBL_MAX ? +DBL_MAX : alfa / apq->val); |
|
1555 /* check if column lower bound l[q] can be active */ |
|
1556 if (q->lb != -DBL_MAX) |
|
1557 { eps = 1e-9 + 1e-12 * fabs(q->lb); |
|
1558 if (l < q->lb - eps) return 1; /* yes, it can */ |
|
1559 } |
|
1560 /* check if column upper bound u[q] can be active */ |
|
1561 if (q->ub != +DBL_MAX) |
|
1562 { eps = 1e-9 + 1e-12 * fabs(q->ub); |
|
1563 if (u > q->ub + eps) return 1; /* yes, it can */ |
|
1564 } |
|
1565 /* okay; make column q free (unbounded) */ |
|
1566 q->lb = -DBL_MAX, q->ub = +DBL_MAX; |
|
1567 /* create transformation stack entry */ |
|
1568 info = npp_push_tse(npp, |
|
1569 rcv_implied_free, sizeof(struct implied_free)); |
|
1570 info->p = p->i; |
|
1571 info->stat = -1; |
|
1572 /* compute row multiplier pi[p] */ |
|
1573 pi = q->coef / apq->val; |
|
1574 /* check dual feasibility for row p */ |
|
1575 if (pi > +DBL_EPSILON) |
|
1576 { /* lower bound L[p] must be active */ |
|
1577 if (p->lb != -DBL_MAX) |
|
1578 nl: { info->stat = GLP_NL; |
|
1579 p->ub = p->lb; |
|
1580 } |
|
1581 else |
|
1582 { if (pi > +1e-5) return 2; /* dual infeasibility */ |
|
1583 /* take a chance on U[p] */ |
|
1584 xassert(p->ub != +DBL_MAX); |
|
1585 goto nu; |
|
1586 } |
|
1587 } |
|
1588 else if (pi < -DBL_EPSILON) |
|
1589 { /* upper bound U[p] must be active */ |
|
1590 if (p->ub != +DBL_MAX) |
|
1591 nu: { info->stat = GLP_NU; |
|
1592 p->lb = p->ub; |
|
1593 } |
|
1594 else |
|
1595 { if (pi < -1e-5) return 2; /* dual infeasibility */ |
|
1596 /* take a chance on L[p] */ |
|
1597 xassert(p->lb != -DBL_MAX); |
|
1598 goto nl; |
|
1599 } |
|
1600 } |
|
1601 else |
|
1602 { /* any bound (either L[p] or U[p]) can be made active */ |
|
1603 if (p->ub == +DBL_MAX) |
|
1604 { xassert(p->lb != -DBL_MAX); |
|
1605 goto nl; |
|
1606 } |
|
1607 if (p->lb == -DBL_MAX) |
|
1608 { xassert(p->ub != +DBL_MAX); |
|
1609 goto nu; |
|
1610 } |
|
1611 if (fabs(p->lb) <= fabs(p->ub)) goto nl; else goto nu; |
|
1612 } |
|
1613 return 0; |
|
1614 } |
|
1615 |
|
1616 static int rcv_implied_free(NPP *npp, void *_info) |
|
1617 { /* recover column singleton (implied free variable) */ |
|
1618 struct implied_free *info = _info; |
|
1619 if (npp->sol == GLP_SOL) |
|
1620 { if (npp->r_stat[info->p] == GLP_BS) |
|
1621 npp->r_stat[info->p] = GLP_BS; |
|
1622 else if (npp->r_stat[info->p] == GLP_NS) |
|
1623 { xassert(info->stat == GLP_NL || info->stat == GLP_NU); |
|
1624 npp->r_stat[info->p] = info->stat; |
|
1625 } |
|
1626 else |
|
1627 { npp_error(); |
|
1628 return 1; |
|
1629 } |
|
1630 } |
|
1631 return 0; |
|
1632 } |
|
1633 |
|
1634 /*********************************************************************** |
|
1635 * NAME |
|
1636 * |
|
1637 * npp_eq_doublet - process row doubleton (equality constraint) |
|
1638 * |
|
1639 * SYNOPSIS |
|
1640 * |
|
1641 * #include "glpnpp.h" |
|
1642 * NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p); |
|
1643 * |
|
1644 * DESCRIPTION |
|
1645 * |
|
1646 * The routine npp_eq_doublet processes row p, which is equality |
|
1647 * constraint having exactly two non-zero coefficients: |
|
1648 * |
|
1649 * a[p,q] x[q] + a[p,r] x[r] = b. (1) |
|
1650 * |
|
1651 * As the result of processing one of columns q or r is eliminated from |
|
1652 * all other rows and, thus, becomes column singleton of type "implied |
|
1653 * slack variable". Row p is not changed and along with column q and r |
|
1654 * remains in the problem. |
|
1655 * |
|
1656 * RETURNS |
|
1657 * |
|
1658 * The routine npp_eq_doublet returns pointer to the descriptor of that |
|
1659 * column q or r which has been eliminated. If, due to some reason, the |
|
1660 * elimination was not performed, the routine returns NULL. |
|
1661 * |
|
1662 * PROBLEM TRANSFORMATION |
|
1663 * |
|
1664 * First, we decide which column q or r will be eliminated. Let it be |
|
1665 * column q. Consider i-th constraint row, where column q has non-zero |
|
1666 * coefficient a[i,q] != 0: |
|
1667 * |
|
1668 * L[i] <= sum a[i,j] x[j] <= U[i]. (2) |
|
1669 * j |
|
1670 * |
|
1671 * In order to eliminate column q from row (2) we subtract from it row |
|
1672 * (1) multiplied by gamma[i] = a[i,q] / a[p,q], i.e. we replace in the |
|
1673 * transformed problem row (2) by its linear combination with row (1). |
|
1674 * This transformation changes only coefficients in columns q and r, |
|
1675 * and bounds of row i as follows: |
|
1676 * |
|
1677 * a~[i,q] = a[i,q] - gamma[i] a[p,q] = 0, (3) |
|
1678 * |
|
1679 * a~[i,r] = a[i,r] - gamma[i] a[p,r], (4) |
|
1680 * |
|
1681 * L~[i] = L[i] - gamma[i] b, (5) |
|
1682 * |
|
1683 * U~[i] = U[i] - gamma[i] b. (6) |
|
1684 * |
|
1685 * RECOVERING BASIC SOLUTION |
|
1686 * |
|
1687 * The transformation of the primal system of the original problem: |
|
1688 * |
|
1689 * L <= A x <= U (7) |
|
1690 * |
|
1691 * is equivalent to multiplying from the left a transformation matrix F |
|
1692 * by components of this primal system, which in the transformed problem |
|
1693 * becomes the following: |
|
1694 * |
|
1695 * F L <= F A x <= F U ==> L~ <= A~x <= U~. (8) |
|
1696 * |
|
1697 * The matrix F has the following structure: |
|
1698 * |
|
1699 * ( 1 -gamma[1] ) |
|
1700 * ( ) |
|
1701 * ( 1 -gamma[2] ) |
|
1702 * ( ) |
|
1703 * ( ... ... ) |
|
1704 * ( ) |
|
1705 * F = ( 1 -gamma[p-1] ) (9) |
|
1706 * ( ) |
|
1707 * ( 1 ) |
|
1708 * ( ) |
|
1709 * ( -gamma[p+1] 1 ) |
|
1710 * ( ) |
|
1711 * ( ... ... ) |
|
1712 * |
|
1713 * where its column containing elements -gamma[i] corresponds to row p |
|
1714 * of the primal system. |
|
1715 * |
|
1716 * From (8) it follows that the dual system of the original problem: |
|
1717 * |
|
1718 * A'pi + lambda = c, (10) |
|
1719 * |
|
1720 * in the transformed problem becomes the following: |
|
1721 * |
|
1722 * A'F'inv(F')pi + lambda = c ==> (A~)'pi~ + lambda = c, (11) |
|
1723 * |
|
1724 * where: |
|
1725 * |
|
1726 * pi~ = inv(F')pi (12) |
|
1727 * |
|
1728 * is the vector of row multipliers in the transformed problem. Thus: |
|
1729 * |
|
1730 * pi = F'pi~. (13) |
|
1731 * |
|
1732 * Therefore, as it follows from (13), value of multiplier for row p in |
|
1733 * solution to the original problem can be computed as follows: |
|
1734 * |
|
1735 * pi[p] = pi~[p] - sum gamma[i] pi~[i], (14) |
|
1736 * i |
|
1737 * |
|
1738 * where pi~[i] = pi[i] is multiplier for row i (i != p). |
|
1739 * |
|
1740 * Note that the statuses of all rows and columns are not changed. |
|
1741 * |
|
1742 * RECOVERING INTERIOR-POINT SOLUTION |
|
1743 * |
|
1744 * Multiplier for row p in solution to the original problem is computed |
|
1745 * with formula (14). |
|
1746 * |
|
1747 * RECOVERING MIP SOLUTION |
|
1748 * |
|
1749 * None needed. */ |
|
1750 |
|
1751 struct eq_doublet |
|
1752 { /* row doubleton (equality constraint) */ |
|
1753 int p; |
|
1754 /* row reference number */ |
|
1755 double apq; |
|
1756 /* constraint coefficient a[p,q] */ |
|
1757 NPPLFE *ptr; |
|
1758 /* list of non-zero coefficients a[i,q], i != p */ |
|
1759 }; |
|
1760 |
|
1761 static int rcv_eq_doublet(NPP *npp, void *info); |
|
1762 |
|
1763 NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p) |
|
1764 { /* process row doubleton (equality constraint) */ |
|
1765 struct eq_doublet *info; |
|
1766 NPPROW *i; |
|
1767 NPPCOL *q, *r; |
|
1768 NPPAIJ *apq, *apr, *aiq, *air, *next; |
|
1769 NPPLFE *lfe; |
|
1770 double gamma; |
|
1771 /* the row must be doubleton equality constraint */ |
|
1772 xassert(p->lb == p->ub); |
|
1773 xassert(p->ptr != NULL && p->ptr->r_next != NULL && |
|
1774 p->ptr->r_next->r_next == NULL); |
|
1775 /* choose column to be eliminated */ |
|
1776 { NPPAIJ *a1, *a2; |
|
1777 a1 = p->ptr, a2 = a1->r_next; |
|
1778 if (fabs(a2->val) < 0.001 * fabs(a1->val)) |
|
1779 { /* only first column can be eliminated, because second one |
|
1780 has too small constraint coefficient */ |
|
1781 apq = a1, apr = a2; |
|
1782 } |
|
1783 else if (fabs(a1->val) < 0.001 * fabs(a2->val)) |
|
1784 { /* only second column can be eliminated, because first one |
|
1785 has too small constraint coefficient */ |
|
1786 apq = a2, apr = a1; |
|
1787 } |
|
1788 else |
|
1789 { /* both columns are appropriate; choose that one which is |
|
1790 shorter to minimize fill-in */ |
|
1791 if (npp_col_nnz(npp, a1->col) <= npp_col_nnz(npp, a2->col)) |
|
1792 { /* first column is shorter */ |
|
1793 apq = a1, apr = a2; |
|
1794 } |
|
1795 else |
|
1796 { /* second column is shorter */ |
|
1797 apq = a2, apr = a1; |
|
1798 } |
|
1799 } |
|
1800 } |
|
1801 /* now columns q and r have been chosen */ |
|
1802 q = apq->col, r = apr->col; |
|
1803 /* create transformation stack entry */ |
|
1804 info = npp_push_tse(npp, |
|
1805 rcv_eq_doublet, sizeof(struct eq_doublet)); |
|
1806 info->p = p->i; |
|
1807 info->apq = apq->val; |
|
1808 info->ptr = NULL; |
|
1809 /* transform each row i (i != p), where a[i,q] != 0, to eliminate |
|
1810 column q */ |
|
1811 for (aiq = q->ptr; aiq != NULL; aiq = next) |
|
1812 { next = aiq->c_next; |
|
1813 if (aiq == apq) continue; /* skip row p */ |
|
1814 i = aiq->row; /* row i to be transformed */ |
|
1815 /* save constraint coefficient a[i,q] */ |
|
1816 if (npp->sol != GLP_MIP) |
|
1817 { lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); |
|
1818 lfe->ref = i->i; |
|
1819 lfe->val = aiq->val; |
|
1820 lfe->next = info->ptr; |
|
1821 info->ptr = lfe; |
|
1822 } |
|
1823 /* find coefficient a[i,r] in row i */ |
|
1824 for (air = i->ptr; air != NULL; air = air->r_next) |
|
1825 if (air->col == r) break; |
|
1826 /* if a[i,r] does not exist, create a[i,r] = 0 */ |
|
1827 if (air == NULL) |
|
1828 air = npp_add_aij(npp, i, r, 0.0); |
|
1829 /* compute gamma[i] = a[i,q] / a[p,q] */ |
|
1830 gamma = aiq->val / apq->val; |
|
1831 /* (row i) := (row i) - gamma[i] * (row p); see (3)-(6) */ |
|
1832 /* new a[i,q] is exact zero due to elimnation; remove it from |
|
1833 row i */ |
|
1834 npp_del_aij(npp, aiq); |
|
1835 /* compute new a[i,r] */ |
|
1836 air->val -= gamma * apr->val; |
|
1837 /* if new a[i,r] is close to zero due to numeric cancelation, |
|
1838 remove it from row i */ |
|
1839 if (fabs(air->val) <= 1e-10) |
|
1840 npp_del_aij(npp, air); |
|
1841 /* compute new lower and upper bounds of row i */ |
|
1842 if (i->lb == i->ub) |
|
1843 i->lb = i->ub = (i->lb - gamma * p->lb); |
|
1844 else |
|
1845 { if (i->lb != -DBL_MAX) |
|
1846 i->lb -= gamma * p->lb; |
|
1847 if (i->ub != +DBL_MAX) |
|
1848 i->ub -= gamma * p->lb; |
|
1849 } |
|
1850 } |
|
1851 return q; |
|
1852 } |
|
1853 |
|
1854 static int rcv_eq_doublet(NPP *npp, void *_info) |
|
1855 { /* recover row doubleton (equality constraint) */ |
|
1856 struct eq_doublet *info = _info; |
|
1857 NPPLFE *lfe; |
|
1858 double gamma, temp; |
|
1859 /* we assume that processing row p is followed by processing |
|
1860 column q as singleton of type "implied slack variable", in |
|
1861 which case row p must always be active equality constraint */ |
|
1862 if (npp->sol == GLP_SOL) |
|
1863 { if (npp->r_stat[info->p] != GLP_NS) |
|
1864 { npp_error(); |
|
1865 return 1; |
|
1866 } |
|
1867 } |
|
1868 if (npp->sol != GLP_MIP) |
|
1869 { /* compute value of multiplier for row p; see (14) */ |
|
1870 temp = npp->r_pi[info->p]; |
|
1871 for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) |
|
1872 { gamma = lfe->val / info->apq; /* a[i,q] / a[p,q] */ |
|
1873 temp -= gamma * npp->r_pi[lfe->ref]; |
|
1874 } |
|
1875 npp->r_pi[info->p] = temp; |
|
1876 } |
|
1877 return 0; |
|
1878 } |
|
1879 |
|
1880 /*********************************************************************** |
|
1881 * NAME |
|
1882 * |
|
1883 * npp_forcing_row - process forcing row |
|
1884 * |
|
1885 * SYNOPSIS |
|
1886 * |
|
1887 * #include "glpnpp.h" |
|
1888 * int npp_forcing_row(NPP *npp, NPPROW *p, int at); |
|
1889 * |
|
1890 * DESCRIPTION |
|
1891 * |
|
1892 * The routine npp_forcing row processes row p of general format: |
|
1893 * |
|
1894 * L[p] <= sum a[p,j] x[j] <= U[p], (1) |
|
1895 * j |
|
1896 * |
|
1897 * l[j] <= x[j] <= u[j], (2) |
|
1898 * |
|
1899 * where L[p] <= U[p] and l[j] < u[j] for all a[p,j] != 0. It is also |
|
1900 * assumed that: |
|
1901 * |
|
1902 * 1) if at = 0 then |L[p] - U'[p]| <= eps, where U'[p] is implied |
|
1903 * row upper bound (see below), eps is an absolute tolerance for row |
|
1904 * value; |
|
1905 * |
|
1906 * 2) if at = 1 then |U[p] - L'[p]| <= eps, where L'[p] is implied |
|
1907 * row lower bound (see below). |
|
1908 * |
|
1909 * RETURNS |
|
1910 * |
|
1911 * 0 - success; |
|
1912 * |
|
1913 * 1 - cannot fix columns due to too small constraint coefficients. |
|
1914 * |
|
1915 * PROBLEM TRANSFORMATION |
|
1916 * |
|
1917 * Implied lower and upper bounds of row (1) are determined by bounds |
|
1918 * of corresponding columns (variables) as follows: |
|
1919 * |
|
1920 * L'[p] = inf sum a[p,j] x[j] = |
|
1921 * j |
|
1922 * (3) |
|
1923 * = sum a[p,j] l[j] + sum a[p,j] u[j], |
|
1924 * j in Jp j in Jn |
|
1925 * |
|
1926 * U'[p] = sup sum a[p,j] x[j] = |
|
1927 * (4) |
|
1928 * = sum a[p,j] u[j] + sum a[p,j] l[j], |
|
1929 * j in Jp j in Jn |
|
1930 * |
|
1931 * Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5) |
|
1932 * |
|
1933 * If L[p] =~ U'[p] (at = 0), solution can be primal feasible only when |
|
1934 * all variables take their boundary values as defined by (4): |
|
1935 * |
|
1936 * ( u[j], if j in Jp |
|
1937 * x[j] = < (6) |
|
1938 * ( l[j], if j in Jn |
|
1939 * |
|
1940 * Similarly, if U[p] =~ L'[p] (at = 1), solution can be primal feasible |
|
1941 * only when all variables take their boundary values as defined by (3): |
|
1942 * |
|
1943 * ( l[j], if j in Jp |
|
1944 * x[j] = < (7) |
|
1945 * ( u[j], if j in Jn |
|
1946 * |
|
1947 * Condition (6) or (7) allows fixing all columns (variables x[j]) |
|
1948 * in row (1) on their bounds and then removing them from the problem |
|
1949 * (see the routine npp_fixed_col). Due to this row p becomes redundant, |
|
1950 * so it can be replaced by equivalent free (unbounded) row and also |
|
1951 * removed from the problem (see the routine npp_free_row). |
|
1952 * |
|
1953 * 1. To apply this transformation row (1) should not have coefficients |
|
1954 * whose magnitude is too small, i.e. all a[p,j] should satisfy to |
|
1955 * the following condition: |
|
1956 * |
|
1957 * |a[p,j]| >= eps * max(1, |a[p,k]|), (8) |
|
1958 * k |
|
1959 * where eps is a relative tolerance for constraint coefficients. |
|
1960 * Otherwise, fixing columns may be numerically unreliable and may |
|
1961 * lead to wrong solution. |
|
1962 * |
|
1963 * 2. The routine fixes columns and remove bounds of row p, however, |
|
1964 * it does not remove the row and columns from the problem. |
|
1965 * |
|
1966 * RECOVERING BASIC SOLUTION |
|
1967 * |
|
1968 * In the transformed problem row p being inactive constraint is |
|
1969 * assigned status GLP_BS (as the result of transformation of free |
|
1970 * row), and all columns in this row are assigned status GLP_NS (as the |
|
1971 * result of transformation of fixed columns). |
|
1972 * |
|
1973 * Note that in the dual system of the transformed (as well as original) |
|
1974 * problem every column j in row p corresponds to the following row: |
|
1975 * |
|
1976 * sum a[i,j] pi[i] + a[p,j] pi[p] + lambda[j] = c[j], (9) |
|
1977 * i!=p |
|
1978 * |
|
1979 * from which it follows that: |
|
1980 * |
|
1981 * lambda[j] = c[j] - sum a[i,j] pi[i] - a[p,j] pi[p]. (10) |
|
1982 * i!=p |
|
1983 * |
|
1984 * In the transformed problem values of all multipliers pi[i] are known |
|
1985 * (including pi[i], whose value is zero, since row p is inactive). |
|
1986 * Thus, using formula (10) it is possible to compute values of |
|
1987 * multipliers lambda[j] for all columns in row p. |
|
1988 * |
|
1989 * Note also that in the original problem all columns in row p are |
|
1990 * bounded, not fixed. So status GLP_NS assigned to every such column |
|
1991 * must be changed to GLP_NL or GLP_NU depending on which bound the |
|
1992 * corresponding column has been fixed. This status change may lead to |
|
1993 * dual feasibility violation for solution of the original problem, |
|
1994 * because now column multipliers must satisfy to the following |
|
1995 * condition: |
|
1996 * |
|
1997 * ( >= 0, if status of column j is GLP_NL, |
|
1998 * lambda[j] < (11) |
|
1999 * ( <= 0, if status of column j is GLP_NU. |
|
2000 * |
|
2001 * If this condition holds, solution to the original problem is the |
|
2002 * same as to the transformed problem. Otherwise, we have to perform |
|
2003 * one degenerate pivoting step of the primal simplex method to obtain |
|
2004 * dual feasible (hence, optimal) solution to the original problem as |
|
2005 * follows. If, on problem transformation, row p was made active on its |
|
2006 * lower bound (case at = 0), we change its status to GLP_NL (or GLP_NS) |
|
2007 * and start increasing its multiplier pi[p]. Otherwise, if row p was |
|
2008 * made active on its upper bound (case at = 1), we change its status |
|
2009 * to GLP_NU (or GLP_NS) and start decreasing pi[p]. From (10) it |
|
2010 * follows that: |
|
2011 * |
|
2012 * delta lambda[j] = - a[p,j] * delta pi[p] = - a[p,j] pi[p]. (12) |
|
2013 * |
|
2014 * Simple analysis of formulae (3)-(5) shows that changing pi[p] in the |
|
2015 * specified direction causes increasing lambda[j] for every column j |
|
2016 * assigned status GLP_NL (delta lambda[j] > 0) and decreasing lambda[j] |
|
2017 * for every column j assigned status GLP_NU (delta lambda[j] < 0). It |
|
2018 * is understood that once the last lambda[q], which violates condition |
|
2019 * (11), has reached zero, multipliers lambda[j] for all columns get |
|
2020 * valid signs. Such column q can be determined as follows. Let d[j] be |
|
2021 * initial value of lambda[j] (i.e. reduced cost of column j) in the |
|
2022 * transformed problem computed with formula (10) when pi[p] = 0. Then |
|
2023 * lambda[j] = d[j] + delta lambda[j], and from (12) it follows that |
|
2024 * lambda[j] becomes zero if: |
|
2025 * |
|
2026 * delta lambda[j] = - a[p,j] pi[p] = - d[j] ==> |
|
2027 * (13) |
|
2028 * pi[p] = d[j] / a[p,j]. |
|
2029 * |
|
2030 * Therefore, the last column q, for which lambda[q] becomes zero, can |
|
2031 * be determined from the following condition: |
|
2032 * |
|
2033 * |d[q] / a[p,q]| = max |pi[p]| = max |d[j] / a[p,j]|, (14) |
|
2034 * j in D j in D |
|
2035 * |
|
2036 * where D is a set of columns j whose, reduced costs d[j] have invalid |
|
2037 * signs, i.e. violate condition (11). (Thus, if D is empty, solution |
|
2038 * to the original problem is the same as solution to the transformed |
|
2039 * problem, and no correction is needed as was noticed above.) In |
|
2040 * solution to the original problem column q is assigned status GLP_BS, |
|
2041 * since it replaces column of auxiliary variable of row p (becoming |
|
2042 * active) in the basis, and multiplier for row p is assigned its new |
|
2043 * value, which is pi[p] = d[q] / a[p,q]. Note that due to primal |
|
2044 * degeneracy values of all columns having non-zero coefficients in row |
|
2045 * p remain unchanged. |
|
2046 * |
|
2047 * RECOVERING INTERIOR-POINT SOLUTION |
|
2048 * |
|
2049 * Value of multiplier pi[p] in solution to the original problem is |
|
2050 * corrected in the same way as for basic solution. Values of all |
|
2051 * columns having non-zero coefficients in row p remain unchanged. |
|
2052 * |
|
2053 * RECOVERING MIP SOLUTION |
|
2054 * |
|
2055 * None needed. */ |
|
2056 |
|
2057 struct forcing_col |
|
2058 { /* column fixed on its bound by forcing row */ |
|
2059 int j; |
|
2060 /* column reference number */ |
|
2061 char stat; |
|
2062 /* original column status: |
|
2063 GLP_NL - fixed on lower bound |
|
2064 GLP_NU - fixed on upper bound */ |
|
2065 double a; |
|
2066 /* constraint coefficient a[p,j] */ |
|
2067 double c; |
|
2068 /* objective coefficient c[j] */ |
|
2069 NPPLFE *ptr; |
|
2070 /* list of non-zero coefficients a[i,j], i != p */ |
|
2071 struct forcing_col *next; |
|
2072 /* pointer to another column fixed by forcing row */ |
|
2073 }; |
|
2074 |
|
2075 struct forcing_row |
|
2076 { /* forcing row */ |
|
2077 int p; |
|
2078 /* row reference number */ |
|
2079 char stat; |
|
2080 /* status assigned to the row if it becomes active: |
|
2081 GLP_NS - active equality constraint |
|
2082 GLP_NL - inequality constraint with lower bound active |
|
2083 GLP_NU - inequality constraint with upper bound active */ |
|
2084 struct forcing_col *ptr; |
|
2085 /* list of all columns having non-zero constraint coefficient |
|
2086 a[p,j] in the forcing row */ |
|
2087 }; |
|
2088 |
|
2089 static int rcv_forcing_row(NPP *npp, void *info); |
|
2090 |
|
2091 int npp_forcing_row(NPP *npp, NPPROW *p, int at) |
|
2092 { /* process forcing row */ |
|
2093 struct forcing_row *info; |
|
2094 struct forcing_col *col = NULL; |
|
2095 NPPCOL *j; |
|
2096 NPPAIJ *apj, *aij; |
|
2097 NPPLFE *lfe; |
|
2098 double big; |
|
2099 xassert(at == 0 || at == 1); |
|
2100 /* determine maximal magnitude of the row coefficients */ |
|
2101 big = 1.0; |
|
2102 for (apj = p->ptr; apj != NULL; apj = apj->r_next) |
|
2103 if (big < fabs(apj->val)) big = fabs(apj->val); |
|
2104 /* if there are too small coefficients in the row, transformation |
|
2105 should not be applied */ |
|
2106 for (apj = p->ptr; apj != NULL; apj = apj->r_next) |
|
2107 if (fabs(apj->val) < 1e-7 * big) return 1; |
|
2108 /* create transformation stack entry */ |
|
2109 info = npp_push_tse(npp, |
|
2110 rcv_forcing_row, sizeof(struct forcing_row)); |
|
2111 info->p = p->i; |
|
2112 if (p->lb == p->ub) |
|
2113 { /* equality constraint */ |
|
2114 info->stat = GLP_NS; |
|
2115 } |
|
2116 else if (at == 0) |
|
2117 { /* inequality constraint; case L[p] = U'[p] */ |
|
2118 info->stat = GLP_NL; |
|
2119 xassert(p->lb != -DBL_MAX); |
|
2120 } |
|
2121 else /* at == 1 */ |
|
2122 { /* inequality constraint; case U[p] = L'[p] */ |
|
2123 info->stat = GLP_NU; |
|
2124 xassert(p->ub != +DBL_MAX); |
|
2125 } |
|
2126 info->ptr = NULL; |
|
2127 /* scan the forcing row, fix columns at corresponding bounds, and |
|
2128 save column information (the latter is not needed for MIP) */ |
|
2129 for (apj = p->ptr; apj != NULL; apj = apj->r_next) |
|
2130 { /* column j has non-zero coefficient in the forcing row */ |
|
2131 j = apj->col; |
|
2132 /* it must be non-fixed */ |
|
2133 xassert(j->lb < j->ub); |
|
2134 /* allocate stack entry to save column information */ |
|
2135 if (npp->sol != GLP_MIP) |
|
2136 { col = dmp_get_atom(npp->stack, sizeof(struct forcing_col)); |
|
2137 col->j = j->j; |
|
2138 col->stat = -1; /* will be set below */ |
|
2139 col->a = apj->val; |
|
2140 col->c = j->coef; |
|
2141 col->ptr = NULL; |
|
2142 col->next = info->ptr; |
|
2143 info->ptr = col; |
|
2144 } |
|
2145 /* fix column j */ |
|
2146 if (at == 0 && apj->val < 0.0 || at != 0 && apj->val > 0.0) |
|
2147 { /* at its lower bound */ |
|
2148 if (npp->sol != GLP_MIP) |
|
2149 col->stat = GLP_NL; |
|
2150 xassert(j->lb != -DBL_MAX); |
|
2151 j->ub = j->lb; |
|
2152 } |
|
2153 else |
|
2154 { /* at its upper bound */ |
|
2155 if (npp->sol != GLP_MIP) |
|
2156 col->stat = GLP_NU; |
|
2157 xassert(j->ub != +DBL_MAX); |
|
2158 j->lb = j->ub; |
|
2159 } |
|
2160 /* save column coefficients a[i,j], i != p */ |
|
2161 if (npp->sol != GLP_MIP) |
|
2162 { for (aij = j->ptr; aij != NULL; aij = aij->c_next) |
|
2163 { if (aij == apj) continue; /* skip a[p,j] */ |
|
2164 lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); |
|
2165 lfe->ref = aij->row->i; |
|
2166 lfe->val = aij->val; |
|
2167 lfe->next = col->ptr; |
|
2168 col->ptr = lfe; |
|
2169 } |
|
2170 } |
|
2171 } |
|
2172 /* make the row free (unbounded) */ |
|
2173 p->lb = -DBL_MAX, p->ub = +DBL_MAX; |
|
2174 return 0; |
|
2175 } |
|
2176 |
|
2177 static int rcv_forcing_row(NPP *npp, void *_info) |
|
2178 { /* recover forcing row */ |
|
2179 struct forcing_row *info = _info; |
|
2180 struct forcing_col *col, *piv; |
|
2181 NPPLFE *lfe; |
|
2182 double d, big, temp; |
|
2183 if (npp->sol == GLP_MIP) goto done; |
|
2184 /* initially solution to the original problem is the same as |
|
2185 to the transformed problem, where row p is inactive constraint |
|
2186 with pi[p] = 0, and all columns are non-basic */ |
|
2187 if (npp->sol == GLP_SOL) |
|
2188 { if (npp->r_stat[info->p] != GLP_BS) |
|
2189 { npp_error(); |
|
2190 return 1; |
|
2191 } |
|
2192 for (col = info->ptr; col != NULL; col = col->next) |
|
2193 { if (npp->c_stat[col->j] != GLP_NS) |
|
2194 { npp_error(); |
|
2195 return 1; |
|
2196 } |
|
2197 npp->c_stat[col->j] = col->stat; /* original status */ |
|
2198 } |
|
2199 } |
|
2200 /* compute reduced costs d[j] for all columns with formula (10) |
|
2201 and store them in col.c instead objective coefficients */ |
|
2202 for (col = info->ptr; col != NULL; col = col->next) |
|
2203 { d = col->c; |
|
2204 for (lfe = col->ptr; lfe != NULL; lfe = lfe->next) |
|
2205 d -= lfe->val * npp->r_pi[lfe->ref]; |
|
2206 col->c = d; |
|
2207 } |
|
2208 /* consider columns j, whose multipliers lambda[j] has wrong |
|
2209 sign in solution to the transformed problem (where lambda[j] = |
|
2210 d[j]), and choose column q, whose multipler lambda[q] reaches |
|
2211 zero last on changing row multiplier pi[p]; see (14) */ |
|
2212 piv = NULL, big = 0.0; |
|
2213 for (col = info->ptr; col != NULL; col = col->next) |
|
2214 { d = col->c; /* d[j] */ |
|
2215 temp = fabs(d / col->a); |
|
2216 if (col->stat == GLP_NL) |
|
2217 { /* column j has active lower bound */ |
|
2218 if (d < 0.0 && big < temp) |
|
2219 piv = col, big = temp; |
|
2220 } |
|
2221 else if (col->stat == GLP_NU) |
|
2222 { /* column j has active upper bound */ |
|
2223 if (d > 0.0 && big < temp) |
|
2224 piv = col, big = temp; |
|
2225 } |
|
2226 else |
|
2227 { npp_error(); |
|
2228 return 1; |
|
2229 } |
|
2230 } |
|
2231 /* if column q does not exist, no correction is needed */ |
|
2232 if (piv != NULL) |
|
2233 { /* correct solution; row p becomes active constraint while |
|
2234 column q becomes basic */ |
|
2235 if (npp->sol == GLP_SOL) |
|
2236 { npp->r_stat[info->p] = info->stat; |
|
2237 npp->c_stat[piv->j] = GLP_BS; |
|
2238 } |
|
2239 /* assign new value to row multiplier pi[p] = d[p] / a[p,q] */ |
|
2240 npp->r_pi[info->p] = piv->c / piv->a; |
|
2241 } |
|
2242 done: return 0; |
|
2243 } |
|
2244 |
|
2245 /*********************************************************************** |
|
2246 * NAME |
|
2247 * |
|
2248 * npp_analyze_row - perform general row analysis |
|
2249 * |
|
2250 * SYNOPSIS |
|
2251 * |
|
2252 * #include "glpnpp.h" |
|
2253 * int npp_analyze_row(NPP *npp, NPPROW *p); |
|
2254 * |
|
2255 * DESCRIPTION |
|
2256 * |
|
2257 * The routine npp_analyze_row performs analysis of row p of general |
|
2258 * format: |
|
2259 * |
|
2260 * L[p] <= sum a[p,j] x[j] <= U[p], (1) |
|
2261 * j |
|
2262 * |
|
2263 * l[j] <= x[j] <= u[j], (2) |
|
2264 * |
|
2265 * where L[p] <= U[p] and l[j] <= u[j] for all a[p,j] != 0. |
|
2266 * |
|
2267 * RETURNS |
|
2268 * |
|
2269 * 0x?0 - row lower bound does not exist or is redundant; |
|
2270 * |
|
2271 * 0x?1 - row lower bound can be active; |
|
2272 * |
|
2273 * 0x?2 - row lower bound is a forcing bound; |
|
2274 * |
|
2275 * 0x0? - row upper bound does not exist or is redundant; |
|
2276 * |
|
2277 * 0x1? - row upper bound can be active; |
|
2278 * |
|
2279 * 0x2? - row upper bound is a forcing bound; |
|
2280 * |
|
2281 * 0x33 - row bounds are inconsistent with column bounds. |
|
2282 * |
|
2283 * ALGORITHM |
|
2284 * |
|
2285 * Analysis of row (1) is based on analysis of its implied lower and |
|
2286 * upper bounds, which are determined by bounds of corresponding columns |
|
2287 * (variables) as follows: |
|
2288 * |
|
2289 * L'[p] = inf sum a[p,j] x[j] = |
|
2290 * j |
|
2291 * (3) |
|
2292 * = sum a[p,j] l[j] + sum a[p,j] u[j], |
|
2293 * j in Jp j in Jn |
|
2294 * |
|
2295 * U'[p] = sup sum a[p,j] x[j] = |
|
2296 * (4) |
|
2297 * = sum a[p,j] u[j] + sum a[p,j] l[j], |
|
2298 * j in Jp j in Jn |
|
2299 * |
|
2300 * Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5) |
|
2301 * |
|
2302 * (Note that bounds of all columns in row p are assumed to be correct, |
|
2303 * so L'[p] <= U'[p].) |
|
2304 * |
|
2305 * Analysis of row lower bound L[p] includes the following cases: |
|
2306 * |
|
2307 * 1) if L[p] > U'[p] + eps, where eps is an absolute tolerance for row |
|
2308 * value, row lower bound L[p] and implied row upper bound U'[p] are |
|
2309 * inconsistent, ergo, the problem has no primal feasible solution; |
|
2310 * |
|
2311 * 2) if U'[p] - eps <= L[p] <= U'[p] + eps, i.e. if L[p] =~ U'[p], |
|
2312 * the row is a forcing row on its lower bound (see description of |
|
2313 * the routine npp_forcing_row); |
|
2314 * |
|
2315 * 3) if L[p] > L'[p] + eps, row lower bound L[p] can be active (this |
|
2316 * conclusion does not account other rows in the problem); |
|
2317 * |
|
2318 * 4) if L[p] <= L'[p] + eps, row lower bound L[p] cannot be active, so |
|
2319 * it is redundant and can be removed (replaced by -oo). |
|
2320 * |
|
2321 * Analysis of row upper bound U[p] is performed in a similar way and |
|
2322 * includes the following cases: |
|
2323 * |
|
2324 * 1) if U[p] < L'[p] - eps, row upper bound U[p] and implied row lower |
|
2325 * bound L'[p] are inconsistent, ergo the problem has no primal |
|
2326 * feasible solution; |
|
2327 * |
|
2328 * 2) if L'[p] - eps <= U[p] <= L'[p] + eps, i.e. if U[p] =~ L'[p], |
|
2329 * the row is a forcing row on its upper bound (see description of |
|
2330 * the routine npp_forcing_row); |
|
2331 * |
|
2332 * 3) if U[p] < U'[p] - eps, row upper bound U[p] can be active (this |
|
2333 * conclusion does not account other rows in the problem); |
|
2334 * |
|
2335 * 4) if U[p] >= U'[p] - eps, row upper bound U[p] cannot be active, so |
|
2336 * it is redundant and can be removed (replaced by +oo). */ |
|
2337 |
|
2338 int npp_analyze_row(NPP *npp, NPPROW *p) |
|
2339 { /* perform general row analysis */ |
|
2340 NPPAIJ *aij; |
|
2341 int ret = 0x00; |
|
2342 double l, u, eps; |
|
2343 xassert(npp == npp); |
|
2344 /* compute implied lower bound L'[p]; see (3) */ |
|
2345 l = 0.0; |
|
2346 for (aij = p->ptr; aij != NULL; aij = aij->r_next) |
|
2347 { if (aij->val > 0.0) |
|
2348 { if (aij->col->lb == -DBL_MAX) |
|
2349 { l = -DBL_MAX; |
|
2350 break; |
|
2351 } |
|
2352 l += aij->val * aij->col->lb; |
|
2353 } |
|
2354 else /* aij->val < 0.0 */ |
|
2355 { if (aij->col->ub == +DBL_MAX) |
|
2356 { l = -DBL_MAX; |
|
2357 break; |
|
2358 } |
|
2359 l += aij->val * aij->col->ub; |
|
2360 } |
|
2361 } |
|
2362 /* compute implied upper bound U'[p]; see (4) */ |
|
2363 u = 0.0; |
|
2364 for (aij = p->ptr; aij != NULL; aij = aij->r_next) |
|
2365 { if (aij->val > 0.0) |
|
2366 { if (aij->col->ub == +DBL_MAX) |
|
2367 { u = +DBL_MAX; |
|
2368 break; |
|
2369 } |
|
2370 u += aij->val * aij->col->ub; |
|
2371 } |
|
2372 else /* aij->val < 0.0 */ |
|
2373 { if (aij->col->lb == -DBL_MAX) |
|
2374 { u = +DBL_MAX; |
|
2375 break; |
|
2376 } |
|
2377 u += aij->val * aij->col->lb; |
|
2378 } |
|
2379 } |
|
2380 /* column bounds are assumed correct, so L'[p] <= U'[p] */ |
|
2381 /* check if row lower bound is consistent */ |
|
2382 if (p->lb != -DBL_MAX) |
|
2383 { eps = 1e-3 + 1e-6 * fabs(p->lb); |
|
2384 if (p->lb - eps > u) |
|
2385 { ret = 0x33; |
|
2386 goto done; |
|
2387 } |
|
2388 } |
|
2389 /* check if row upper bound is consistent */ |
|
2390 if (p->ub != +DBL_MAX) |
|
2391 { eps = 1e-3 + 1e-6 * fabs(p->ub); |
|
2392 if (p->ub + eps < l) |
|
2393 { ret = 0x33; |
|
2394 goto done; |
|
2395 } |
|
2396 } |
|
2397 /* check if row lower bound can be active/forcing */ |
|
2398 if (p->lb != -DBL_MAX) |
|
2399 { eps = 1e-9 + 1e-12 * fabs(p->lb); |
|
2400 if (p->lb - eps > l) |
|
2401 { if (p->lb + eps <= u) |
|
2402 ret |= 0x01; |
|
2403 else |
|
2404 ret |= 0x02; |
|
2405 } |
|
2406 } |
|
2407 /* check if row upper bound can be active/forcing */ |
|
2408 if (p->ub != +DBL_MAX) |
|
2409 { eps = 1e-9 + 1e-12 * fabs(p->ub); |
|
2410 if (p->ub + eps < u) |
|
2411 { /* check if the upper bound is forcing */ |
|
2412 if (p->ub - eps >= l) |
|
2413 ret |= 0x10; |
|
2414 else |
|
2415 ret |= 0x20; |
|
2416 } |
|
2417 } |
|
2418 done: return ret; |
|
2419 } |
|
2420 |
|
2421 /*********************************************************************** |
|
2422 * NAME |
|
2423 * |
|
2424 * npp_inactive_bound - remove row lower/upper inactive bound |
|
2425 * |
|
2426 * SYNOPSIS |
|
2427 * |
|
2428 * #include "glpnpp.h" |
|
2429 * void npp_inactive_bound(NPP *npp, NPPROW *p, int which); |
|
2430 * |
|
2431 * DESCRIPTION |
|
2432 * |
|
2433 * The routine npp_inactive_bound removes lower (if which = 0) or upper |
|
2434 * (if which = 1) bound of row p: |
|
2435 * |
|
2436 * L[p] <= sum a[p,j] x[j] <= U[p], |
|
2437 * |
|
2438 * which (bound) is assumed to be redundant. |
|
2439 * |
|
2440 * PROBLEM TRANSFORMATION |
|
2441 * |
|
2442 * If which = 0, current lower bound L[p] of row p is assigned -oo. |
|
2443 * If which = 1, current upper bound U[p] of row p is assigned +oo. |
|
2444 * |
|
2445 * RECOVERING BASIC SOLUTION |
|
2446 * |
|
2447 * If in solution to the transformed problem row p is inactive |
|
2448 * constraint (GLP_BS), its status is not changed in solution to the |
|
2449 * original problem. Otherwise, status of row p in solution to the |
|
2450 * original problem is defined by its type before transformation and |
|
2451 * its status in solution to the transformed problem as follows: |
|
2452 * |
|
2453 * +---------------------+-------+---------------+---------------+ |
|
2454 * | Row | Flag | Row status in | Row status in | |
|
2455 * | type | which | transfmd soln | original soln | |
|
2456 * +---------------------+-------+---------------+---------------+ |
|
2457 * | sum >= L[p] | 0 | GLP_NF | GLP_NL | |
|
2458 * | sum <= U[p] | 1 | GLP_NF | GLP_NU | |
|
2459 * | L[p] <= sum <= U[p] | 0 | GLP_NU | GLP_NU | |
|
2460 * | L[p] <= sum <= U[p] | 1 | GLP_NL | GLP_NL | |
|
2461 * | sum = L[p] = U[p] | 0 | GLP_NU | GLP_NS | |
|
2462 * | sum = L[p] = U[p] | 1 | GLP_NL | GLP_NS | |
|
2463 * +---------------------+-------+---------------+---------------+ |
|
2464 * |
|
2465 * RECOVERING INTERIOR-POINT SOLUTION |
|
2466 * |
|
2467 * None needed. |
|
2468 * |
|
2469 * RECOVERING MIP SOLUTION |
|
2470 * |
|
2471 * None needed. */ |
|
2472 |
|
2473 struct inactive_bound |
|
2474 { /* row inactive bound */ |
|
2475 int p; |
|
2476 /* row reference number */ |
|
2477 char stat; |
|
2478 /* row status (if active constraint) */ |
|
2479 }; |
|
2480 |
|
2481 static int rcv_inactive_bound(NPP *npp, void *info); |
|
2482 |
|
2483 void npp_inactive_bound(NPP *npp, NPPROW *p, int which) |
|
2484 { /* remove row lower/upper inactive bound */ |
|
2485 struct inactive_bound *info; |
|
2486 if (npp->sol == GLP_SOL) |
|
2487 { /* create transformation stack entry */ |
|
2488 info = npp_push_tse(npp, |
|
2489 rcv_inactive_bound, sizeof(struct inactive_bound)); |
|
2490 info->p = p->i; |
|
2491 if (p->ub == +DBL_MAX) |
|
2492 info->stat = GLP_NL; |
|
2493 else if (p->lb == -DBL_MAX) |
|
2494 info->stat = GLP_NU; |
|
2495 else if (p->lb != p->ub) |
|
2496 info->stat = (char)(which == 0 ? GLP_NU : GLP_NL); |
|
2497 else |
|
2498 info->stat = GLP_NS; |
|
2499 } |
|
2500 /* remove row inactive bound */ |
|
2501 if (which == 0) |
|
2502 { xassert(p->lb != -DBL_MAX); |
|
2503 p->lb = -DBL_MAX; |
|
2504 } |
|
2505 else if (which == 1) |
|
2506 { xassert(p->ub != +DBL_MAX); |
|
2507 p->ub = +DBL_MAX; |
|
2508 } |
|
2509 else |
|
2510 xassert(which != which); |
|
2511 return; |
|
2512 } |
|
2513 |
|
2514 static int rcv_inactive_bound(NPP *npp, void *_info) |
|
2515 { /* recover row status */ |
|
2516 struct inactive_bound *info = _info; |
|
2517 if (npp->sol != GLP_SOL) |
|
2518 { npp_error(); |
|
2519 return 1; |
|
2520 } |
|
2521 if (npp->r_stat[info->p] == GLP_BS) |
|
2522 npp->r_stat[info->p] = GLP_BS; |
|
2523 else |
|
2524 npp->r_stat[info->p] = info->stat; |
|
2525 return 0; |
|
2526 } |
|
2527 |
|
2528 /*********************************************************************** |
|
2529 * NAME |
|
2530 * |
|
2531 * npp_implied_bounds - determine implied column bounds |
|
2532 * |
|
2533 * SYNOPSIS |
|
2534 * |
|
2535 * #include "glpnpp.h" |
|
2536 * void npp_implied_bounds(NPP *npp, NPPROW *p); |
|
2537 * |
|
2538 * DESCRIPTION |
|
2539 * |
|
2540 * The routine npp_implied_bounds inspects general row (constraint) p: |
|
2541 * |
|
2542 * L[p] <= sum a[p,j] x[j] <= U[p], (1) |
|
2543 * |
|
2544 * l[j] <= x[j] <= u[j], (2) |
|
2545 * |
|
2546 * where L[p] <= U[p] and l[j] <= u[j] for all a[p,j] != 0, to compute |
|
2547 * implied bounds of columns (variables x[j]) in this row. |
|
2548 * |
|
2549 * The routine stores implied column bounds l'[j] and u'[j] in column |
|
2550 * descriptors (NPPCOL); it does not change current column bounds l[j] |
|
2551 * and u[j]. (Implied column bounds can be then used to strengthen the |
|
2552 * current column bounds; see the routines npp_implied_lower and |
|
2553 * npp_implied_upper). |
|
2554 * |
|
2555 * ALGORITHM |
|
2556 * |
|
2557 * Current column bounds (2) define implied lower and upper bounds of |
|
2558 * row (1) as follows: |
|
2559 * |
|
2560 * L'[p] = inf sum a[p,j] x[j] = |
|
2561 * j |
|
2562 * (3) |
|
2563 * = sum a[p,j] l[j] + sum a[p,j] u[j], |
|
2564 * j in Jp j in Jn |
|
2565 * |
|
2566 * U'[p] = sup sum a[p,j] x[j] = |
|
2567 * (4) |
|
2568 * = sum a[p,j] u[j] + sum a[p,j] l[j], |
|
2569 * j in Jp j in Jn |
|
2570 * |
|
2571 * Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5) |
|
2572 * |
|
2573 * (Note that bounds of all columns in row p are assumed to be correct, |
|
2574 * so L'[p] <= U'[p].) |
|
2575 * |
|
2576 * If L[p] > L'[p] and/or U[p] < U'[p], the lower and/or upper bound of |
|
2577 * row (1) can be active, in which case such row defines implied bounds |
|
2578 * of its variables. |
|
2579 * |
|
2580 * Let x[k] be some variable having in row (1) coefficient a[p,k] != 0. |
|
2581 * Consider a case when row lower bound can be active (L[p] > L'[p]): |
|
2582 * |
|
2583 * sum a[p,j] x[j] >= L[p] ==> |
|
2584 * j |
|
2585 * |
|
2586 * sum a[p,j] x[j] + a[p,k] x[k] >= L[p] ==> |
|
2587 * j!=k |
|
2588 * (6) |
|
2589 * a[p,k] x[k] >= L[p] - sum a[p,j] x[j] ==> |
|
2590 * j!=k |
|
2591 * |
|
2592 * a[p,k] x[k] >= L[p,k], |
|
2593 * |
|
2594 * where |
|
2595 * |
|
2596 * L[p,k] = inf(L[p] - sum a[p,j] x[j]) = |
|
2597 * j!=k |
|
2598 * |
|
2599 * = L[p] - sup sum a[p,j] x[j] = (7) |
|
2600 * j!=k |
|
2601 * |
|
2602 * = L[p] - sum a[p,j] u[j] - sum a[p,j] l[j]. |
|
2603 * j in Jp\{k} j in Jn\{k} |
|
2604 * |
|
2605 * Thus: |
|
2606 * |
|
2607 * x[k] >= l'[k] = L[p,k] / a[p,k], if a[p,k] > 0, (8) |
|
2608 * |
|
2609 * x[k] <= u'[k] = L[p,k] / a[p,k], if a[p,k] < 0. (9) |
|
2610 * |
|
2611 * where l'[k] and u'[k] are implied lower and upper bounds of variable |
|
2612 * x[k], resp. |
|
2613 * |
|
2614 * Now consider a similar case when row upper bound can be active |
|
2615 * (U[p] < U'[p]): |
|
2616 * |
|
2617 * sum a[p,j] x[j] <= U[p] ==> |
|
2618 * j |
|
2619 * |
|
2620 * sum a[p,j] x[j] + a[p,k] x[k] <= U[p] ==> |
|
2621 * j!=k |
|
2622 * (10) |
|
2623 * a[p,k] x[k] <= U[p] - sum a[p,j] x[j] ==> |
|
2624 * j!=k |
|
2625 * |
|
2626 * a[p,k] x[k] <= U[p,k], |
|
2627 * |
|
2628 * where: |
|
2629 * |
|
2630 * U[p,k] = sup(U[p] - sum a[p,j] x[j]) = |
|
2631 * j!=k |
|
2632 * |
|
2633 * = U[p] - inf sum a[p,j] x[j] = (11) |
|
2634 * j!=k |
|
2635 * |
|
2636 * = U[p] - sum a[p,j] l[j] - sum a[p,j] u[j]. |
|
2637 * j in Jp\{k} j in Jn\{k} |
|
2638 * |
|
2639 * Thus: |
|
2640 * |
|
2641 * x[k] <= u'[k] = U[p,k] / a[p,k], if a[p,k] > 0, (12) |
|
2642 * |
|
2643 * x[k] >= l'[k] = U[p,k] / a[p,k], if a[p,k] < 0. (13) |
|
2644 * |
|
2645 * Note that in formulae (8), (9), (12), and (13) coefficient a[p,k] |
|
2646 * must not be too small in magnitude relatively to other non-zero |
|
2647 * coefficients in row (1), i.e. the following condition must hold: |
|
2648 * |
|
2649 * |a[p,k]| >= eps * max(1, |a[p,j]|), (14) |
|
2650 * j |
|
2651 * |
|
2652 * where eps is a relative tolerance for constraint coefficients. |
|
2653 * Otherwise the implied column bounds can be numerical inreliable. For |
|
2654 * example, using formula (8) for the following inequality constraint: |
|
2655 * |
|
2656 * 1e-12 x1 - x2 - x3 >= 0, |
|
2657 * |
|
2658 * where x1 >= -1, x2, x3, >= 0, may lead to numerically unreliable |
|
2659 * conclusion that x1 >= 0. |
|
2660 * |
|
2661 * Using formulae (8), (9), (12), and (13) to compute implied bounds |
|
2662 * for one variable requires |J| operations, where J = {j: a[p,j] != 0}, |
|
2663 * because this needs computing L[p,k] and U[p,k]. Thus, computing |
|
2664 * implied bounds for all variables in row (1) would require |J|^2 |
|
2665 * operations, that is not a good technique. However, the total number |
|
2666 * of operations can be reduced to |J| as follows. |
|
2667 * |
|
2668 * Let a[p,k] > 0. Then from (7) and (11) we have: |
|
2669 * |
|
2670 * L[p,k] = L[p] - (U'[p] - a[p,k] u[k]) = |
|
2671 * |
|
2672 * = L[p] - U'[p] + a[p,k] u[k], |
|
2673 * |
|
2674 * U[p,k] = U[p] - (L'[p] - a[p,k] l[k]) = |
|
2675 * |
|
2676 * = U[p] - L'[p] + a[p,k] l[k], |
|
2677 * |
|
2678 * where L'[p] and U'[p] are implied row lower and upper bounds defined |
|
2679 * by formulae (3) and (4). Substituting these expressions into (8) and |
|
2680 * (12) gives: |
|
2681 * |
|
2682 * l'[k] = L[p,k] / a[p,k] = u[k] + (L[p] - U'[p]) / a[p,k], (15) |
|
2683 * |
|
2684 * u'[k] = U[p,k] / a[p,k] = l[k] + (U[p] - L'[p]) / a[p,k]. (16) |
|
2685 * |
|
2686 * Similarly, if a[p,k] < 0, according to (7) and (11) we have: |
|
2687 * |
|
2688 * L[p,k] = L[p] - (U'[p] - a[p,k] l[k]) = |
|
2689 * |
|
2690 * = L[p] - U'[p] + a[p,k] l[k], |
|
2691 * |
|
2692 * U[p,k] = U[p] - (L'[p] - a[p,k] u[k]) = |
|
2693 * |
|
2694 * = U[p] - L'[p] + a[p,k] u[k], |
|
2695 * |
|
2696 * and substituting these expressions into (8) and (12) gives: |
|
2697 * |
|
2698 * l'[k] = U[p,k] / a[p,k] = u[k] + (U[p] - L'[p]) / a[p,k], (17) |
|
2699 * |
|
2700 * u'[k] = L[p,k] / a[p,k] = l[k] + (L[p] - U'[p]) / a[p,k]. (18) |
|
2701 * |
|
2702 * Note that formulae (15)-(18) can be used only if L'[p] and U'[p] |
|
2703 * exist. However, if for some variable x[j] it happens that l[j] = -oo |
|
2704 * and/or u[j] = +oo, values of L'[p] (if a[p,j] > 0) and/or U'[p] (if |
|
2705 * a[p,j] < 0) are undefined. Consider, therefore, the most general |
|
2706 * situation, when some column bounds (2) may not exist. |
|
2707 * |
|
2708 * Let: |
|
2709 * |
|
2710 * J' = {j : (a[p,j] > 0 and l[j] = -oo) or |
|
2711 * (19) |
|
2712 * (a[p,j] < 0 and u[j] = +oo)}. |
|
2713 * |
|
2714 * Then (assuming that row upper bound U[p] can be active) the following |
|
2715 * three cases are possible: |
|
2716 * |
|
2717 * 1) |J'| = 0. In this case L'[p] exists, thus, for all variables x[j] |
|
2718 * in row (1) we can use formulae (16) and (17); |
|
2719 * |
|
2720 * 2) J' = {k}. In this case L'[p] = -oo, however, U[p,k] (11) exists, |
|
2721 * so for variable x[k] we can use formulae (12) and (13). Note that |
|
2722 * for all other variables x[j] (j != k) l'[j] = -oo (if a[p,j] < 0) |
|
2723 * or u'[j] = +oo (if a[p,j] > 0); |
|
2724 * |
|
2725 * 3) |J'| > 1. In this case for all variables x[j] in row [1] we have |
|
2726 * l'[j] = -oo (if a[p,j] < 0) or u'[j] = +oo (if a[p,j] > 0). |
|
2727 * |
|
2728 * Similarly, let: |
|
2729 * |
|
2730 * J'' = {j : (a[p,j] > 0 and u[j] = +oo) or |
|
2731 * (20) |
|
2732 * (a[p,j] < 0 and l[j] = -oo)}. |
|
2733 * |
|
2734 * Then (assuming that row lower bound L[p] can be active) the following |
|
2735 * three cases are possible: |
|
2736 * |
|
2737 * 1) |J''| = 0. In this case U'[p] exists, thus, for all variables x[j] |
|
2738 * in row (1) we can use formulae (15) and (18); |
|
2739 * |
|
2740 * 2) J'' = {k}. In this case U'[p] = +oo, however, L[p,k] (7) exists, |
|
2741 * so for variable x[k] we can use formulae (8) and (9). Note that |
|
2742 * for all other variables x[j] (j != k) l'[j] = -oo (if a[p,j] > 0) |
|
2743 * or u'[j] = +oo (if a[p,j] < 0); |
|
2744 * |
|
2745 * 3) |J''| > 1. In this case for all variables x[j] in row (1) we have |
|
2746 * l'[j] = -oo (if a[p,j] > 0) or u'[j] = +oo (if a[p,j] < 0). */ |
|
2747 |
|
2748 void npp_implied_bounds(NPP *npp, NPPROW *p) |
|
2749 { NPPAIJ *apj, *apk; |
|
2750 double big, eps, temp; |
|
2751 xassert(npp == npp); |
|
2752 /* initialize implied bounds for all variables and determine |
|
2753 maximal magnitude of row coefficients a[p,j] */ |
|
2754 big = 1.0; |
|
2755 for (apj = p->ptr; apj != NULL; apj = apj->r_next) |
|
2756 { apj->col->ll.ll = -DBL_MAX, apj->col->uu.uu = +DBL_MAX; |
|
2757 if (big < fabs(apj->val)) big = fabs(apj->val); |
|
2758 } |
|
2759 eps = 1e-6 * big; |
|
2760 /* process row lower bound (assuming that it can be active) */ |
|
2761 if (p->lb != -DBL_MAX) |
|
2762 { apk = NULL; |
|
2763 for (apj = p->ptr; apj != NULL; apj = apj->r_next) |
|
2764 { if (apj->val > 0.0 && apj->col->ub == +DBL_MAX || |
|
2765 apj->val < 0.0 && apj->col->lb == -DBL_MAX) |
|
2766 { if (apk == NULL) |
|
2767 apk = apj; |
|
2768 else |
|
2769 goto skip1; |
|
2770 } |
|
2771 } |
|
2772 /* if a[p,k] = NULL then |J'| = 0 else J' = { k } */ |
|
2773 temp = p->lb; |
|
2774 for (apj = p->ptr; apj != NULL; apj = apj->r_next) |
|
2775 { if (apj == apk) |
|
2776 /* skip a[p,k] */; |
|
2777 else if (apj->val > 0.0) |
|
2778 temp -= apj->val * apj->col->ub; |
|
2779 else /* apj->val < 0.0 */ |
|
2780 temp -= apj->val * apj->col->lb; |
|
2781 } |
|
2782 /* compute column implied bounds */ |
|
2783 if (apk == NULL) |
|
2784 { /* temp = L[p] - U'[p] */ |
|
2785 for (apj = p->ptr; apj != NULL; apj = apj->r_next) |
|
2786 { if (apj->val >= +eps) |
|
2787 { /* l'[j] := u[j] + (L[p] - U'[p]) / a[p,j] */ |
|
2788 apj->col->ll.ll = apj->col->ub + temp / apj->val; |
|
2789 } |
|
2790 else if (apj->val <= -eps) |
|
2791 { /* u'[j] := l[j] + (L[p] - U'[p]) / a[p,j] */ |
|
2792 apj->col->uu.uu = apj->col->lb + temp / apj->val; |
|
2793 } |
|
2794 } |
|
2795 } |
|
2796 else |
|
2797 { /* temp = L[p,k] */ |
|
2798 if (apk->val >= +eps) |
|
2799 { /* l'[k] := L[p,k] / a[p,k] */ |
|
2800 apk->col->ll.ll = temp / apk->val; |
|
2801 } |
|
2802 else if (apk->val <= -eps) |
|
2803 { /* u'[k] := L[p,k] / a[p,k] */ |
|
2804 apk->col->uu.uu = temp / apk->val; |
|
2805 } |
|
2806 } |
|
2807 skip1: ; |
|
2808 } |
|
2809 /* process row upper bound (assuming that it can be active) */ |
|
2810 if (p->ub != +DBL_MAX) |
|
2811 { apk = NULL; |
|
2812 for (apj = p->ptr; apj != NULL; apj = apj->r_next) |
|
2813 { if (apj->val > 0.0 && apj->col->lb == -DBL_MAX || |
|
2814 apj->val < 0.0 && apj->col->ub == +DBL_MAX) |
|
2815 { if (apk == NULL) |
|
2816 apk = apj; |
|
2817 else |
|
2818 goto skip2; |
|
2819 } |
|
2820 } |
|
2821 /* if a[p,k] = NULL then |J''| = 0 else J'' = { k } */ |
|
2822 temp = p->ub; |
|
2823 for (apj = p->ptr; apj != NULL; apj = apj->r_next) |
|
2824 { if (apj == apk) |
|
2825 /* skip a[p,k] */; |
|
2826 else if (apj->val > 0.0) |
|
2827 temp -= apj->val * apj->col->lb; |
|
2828 else /* apj->val < 0.0 */ |
|
2829 temp -= apj->val * apj->col->ub; |
|
2830 } |
|
2831 /* compute column implied bounds */ |
|
2832 if (apk == NULL) |
|
2833 { /* temp = U[p] - L'[p] */ |
|
2834 for (apj = p->ptr; apj != NULL; apj = apj->r_next) |
|
2835 { if (apj->val >= +eps) |
|
2836 { /* u'[j] := l[j] + (U[p] - L'[p]) / a[p,j] */ |
|
2837 apj->col->uu.uu = apj->col->lb + temp / apj->val; |
|
2838 } |
|
2839 else if (apj->val <= -eps) |
|
2840 { /* l'[j] := u[j] + (U[p] - L'[p]) / a[p,j] */ |
|
2841 apj->col->ll.ll = apj->col->ub + temp / apj->val; |
|
2842 } |
|
2843 } |
|
2844 } |
|
2845 else |
|
2846 { /* temp = U[p,k] */ |
|
2847 if (apk->val >= +eps) |
|
2848 { /* u'[k] := U[p,k] / a[p,k] */ |
|
2849 apk->col->uu.uu = temp / apk->val; |
|
2850 } |
|
2851 else if (apk->val <= -eps) |
|
2852 { /* l'[k] := U[p,k] / a[p,k] */ |
|
2853 apk->col->ll.ll = temp / apk->val; |
|
2854 } |
|
2855 } |
|
2856 skip2: ; |
|
2857 } |
|
2858 return; |
|
2859 } |
|
2860 |
|
2861 /* eof */ |