lemon-project-template-glpk
comparison deps/glpk/src/glpnpp03.c @ 9:33de93886c88
Import GLPK 4.47
author | Alpar Juttner <alpar@cs.elte.hu> |
---|---|
date | Sun, 06 Nov 2011 20:59:10 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:455715bcc104 |
---|---|
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, 2011 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 */ |