123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- /* glpssx02.c */
- /***********************************************************************
- * This code is part of GLPK (GNU Linear Programming Kit).
- *
- * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
- * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
- * E-mail: <mao@gnu.org>.
- *
- * GLPK is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GLPK is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
- ***********************************************************************/
- #include "glpenv.h"
- #include "glpssx.h"
- static void show_progress(SSX *ssx, int phase)
- { /* this auxiliary routine displays information about progress of
- the search */
- int i, def = 0;
- for (i = 1; i <= ssx->m; i++)
- if (ssx->type[ssx->Q_col[i]] == SSX_FX) def++;
- xprintf("%s%6d: %s = %22.15g (%d)\n", phase == 1 ? " " : "*",
- ssx->it_cnt, phase == 1 ? "infsum" : "objval",
- mpq_get_d(ssx->bbar[0]), def);
- #if 0
- ssx->tm_lag = utime();
- #else
- ssx->tm_lag = xtime();
- #endif
- return;
- }
- /*----------------------------------------------------------------------
- // ssx_phase_I - find primal feasible solution.
- //
- // This routine implements phase I of the primal simplex method.
- //
- // On exit the routine returns one of the following codes:
- //
- // 0 - feasible solution found;
- // 1 - problem has no feasible solution;
- // 2 - iterations limit exceeded;
- // 3 - time limit exceeded.
- ----------------------------------------------------------------------*/
- int ssx_phase_I(SSX *ssx)
- { int m = ssx->m;
- int n = ssx->n;
- int *type = ssx->type;
- mpq_t *lb = ssx->lb;
- mpq_t *ub = ssx->ub;
- mpq_t *coef = ssx->coef;
- int *A_ptr = ssx->A_ptr;
- int *A_ind = ssx->A_ind;
- mpq_t *A_val = ssx->A_val;
- int *Q_col = ssx->Q_col;
- mpq_t *bbar = ssx->bbar;
- mpq_t *pi = ssx->pi;
- mpq_t *cbar = ssx->cbar;
- int *orig_type, orig_dir;
- mpq_t *orig_lb, *orig_ub, *orig_coef;
- int i, k, ret;
- /* save components of the original LP problem, which are changed
- by the routine */
- orig_type = xcalloc(1+m+n, sizeof(int));
- orig_lb = xcalloc(1+m+n, sizeof(mpq_t));
- orig_ub = xcalloc(1+m+n, sizeof(mpq_t));
- orig_coef = xcalloc(1+m+n, sizeof(mpq_t));
- for (k = 1; k <= m+n; k++)
- { orig_type[k] = type[k];
- mpq_init(orig_lb[k]);
- mpq_set(orig_lb[k], lb[k]);
- mpq_init(orig_ub[k]);
- mpq_set(orig_ub[k], ub[k]);
- }
- orig_dir = ssx->dir;
- for (k = 0; k <= m+n; k++)
- { mpq_init(orig_coef[k]);
- mpq_set(orig_coef[k], coef[k]);
- }
- /* build an artificial basic solution, which is primal feasible,
- and also build an auxiliary objective function to minimize the
- sum of infeasibilities for the original problem */
- ssx->dir = SSX_MIN;
- for (k = 0; k <= m+n; k++) mpq_set_si(coef[k], 0, 1);
- mpq_set_si(bbar[0], 0, 1);
- for (i = 1; i <= m; i++)
- { int t;
- k = Q_col[i]; /* x[k] = xB[i] */
- t = type[k];
- if (t == SSX_LO || t == SSX_DB || t == SSX_FX)
- { /* in the original problem x[k] has lower bound */
- if (mpq_cmp(bbar[i], lb[k]) < 0)
- { /* which is violated */
- type[k] = SSX_UP;
- mpq_set(ub[k], lb[k]);
- mpq_set_si(lb[k], 0, 1);
- mpq_set_si(coef[k], -1, 1);
- mpq_add(bbar[0], bbar[0], ub[k]);
- mpq_sub(bbar[0], bbar[0], bbar[i]);
- }
- }
- if (t == SSX_UP || t == SSX_DB || t == SSX_FX)
- { /* in the original problem x[k] has upper bound */
- if (mpq_cmp(bbar[i], ub[k]) > 0)
- { /* which is violated */
- type[k] = SSX_LO;
- mpq_set(lb[k], ub[k]);
- mpq_set_si(ub[k], 0, 1);
- mpq_set_si(coef[k], +1, 1);
- mpq_add(bbar[0], bbar[0], bbar[i]);
- mpq_sub(bbar[0], bbar[0], lb[k]);
- }
- }
- }
- /* now the initial basic solution should be primal feasible due
- to changes of bounds of some basic variables, which turned to
- implicit artifical variables */
- /* compute simplex multipliers and reduced costs */
- ssx_eval_pi(ssx);
- ssx_eval_cbar(ssx);
- /* display initial progress of the search */
- show_progress(ssx, 1);
- /* main loop starts here */
- for (;;)
- { /* display current progress of the search */
- #if 0
- if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001)
- #else
- if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001)
- #endif
- show_progress(ssx, 1);
- /* we do not need to wait until all artificial variables have
- left the basis */
- if (mpq_sgn(bbar[0]) == 0)
- { /* the sum of infeasibilities is zero, therefore the current
- solution is primal feasible for the original problem */
- ret = 0;
- break;
- }
- /* check if the iterations limit has been exhausted */
- if (ssx->it_lim == 0)
- { ret = 2;
- break;
- }
- /* check if the time limit has been exhausted */
- #if 0
- if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg)
- #else
- if (ssx->tm_lim >= 0.0 &&
- ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg))
- #endif
- { ret = 3;
- break;
- }
- /* choose non-basic variable xN[q] */
- ssx_chuzc(ssx);
- /* if xN[q] cannot be chosen, the sum of infeasibilities is
- minimal but non-zero; therefore the original problem has no
- primal feasible solution */
- if (ssx->q == 0)
- { ret = 1;
- break;
- }
- /* compute q-th column of the simplex table */
- ssx_eval_col(ssx);
- /* choose basic variable xB[p] */
- ssx_chuzr(ssx);
- /* the sum of infeasibilities cannot be negative, therefore
- the auxiliary lp problem cannot have unbounded solution */
- xassert(ssx->p != 0);
- /* update values of basic variables */
- ssx_update_bbar(ssx);
- if (ssx->p > 0)
- { /* compute p-th row of the inverse inv(B) */
- ssx_eval_rho(ssx);
- /* compute p-th row of the simplex table */
- ssx_eval_row(ssx);
- xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0);
- /* update simplex multipliers */
- ssx_update_pi(ssx);
- /* update reduced costs of non-basic variables */
- ssx_update_cbar(ssx);
- }
- /* xB[p] is leaving the basis; if it is implicit artificial
- variable, the corresponding residual vanishes; therefore
- bounds of this variable should be restored to the original
- values */
- if (ssx->p > 0)
- { k = Q_col[ssx->p]; /* x[k] = xB[p] */
- if (type[k] != orig_type[k])
- { /* x[k] is implicit artificial variable */
- type[k] = orig_type[k];
- mpq_set(lb[k], orig_lb[k]);
- mpq_set(ub[k], orig_ub[k]);
- xassert(ssx->p_stat == SSX_NL || ssx->p_stat == SSX_NU);
- ssx->p_stat = (ssx->p_stat == SSX_NL ? SSX_NU : SSX_NL);
- if (type[k] == SSX_FX) ssx->p_stat = SSX_NS;
- /* nullify the objective coefficient at x[k] */
- mpq_set_si(coef[k], 0, 1);
- /* since coef[k] has been changed, we need to compute
- new reduced cost of x[k], which it will have in the
- adjacent basis */
- /* the formula d[j] = cN[j] - pi' * N[j] is used (note
- that the vector pi is not changed, because it depends
- on objective coefficients at basic variables, but in
- the adjacent basis, for which the vector pi has been
- just recomputed, x[k] is non-basic) */
- if (k <= m)
- { /* x[k] is auxiliary variable */
- mpq_neg(cbar[ssx->q], pi[k]);
- }
- else
- { /* x[k] is structural variable */
- int ptr;
- mpq_t temp;
- mpq_init(temp);
- mpq_set_si(cbar[ssx->q], 0, 1);
- for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++)
- { mpq_mul(temp, pi[A_ind[ptr]], A_val[ptr]);
- mpq_add(cbar[ssx->q], cbar[ssx->q], temp);
- }
- mpq_clear(temp);
- }
- }
- }
- /* jump to the adjacent vertex of the polyhedron */
- ssx_change_basis(ssx);
- /* one simplex iteration has been performed */
- if (ssx->it_lim > 0) ssx->it_lim--;
- ssx->it_cnt++;
- }
- /* display final progress of the search */
- show_progress(ssx, 1);
- /* restore components of the original problem, which were changed
- by the routine */
- for (k = 1; k <= m+n; k++)
- { type[k] = orig_type[k];
- mpq_set(lb[k], orig_lb[k]);
- mpq_clear(orig_lb[k]);
- mpq_set(ub[k], orig_ub[k]);
- mpq_clear(orig_ub[k]);
- }
- ssx->dir = orig_dir;
- for (k = 0; k <= m+n; k++)
- { mpq_set(coef[k], orig_coef[k]);
- mpq_clear(orig_coef[k]);
- }
- xfree(orig_type);
- xfree(orig_lb);
- xfree(orig_ub);
- xfree(orig_coef);
- /* return to the calling program */
- return ret;
- }
- /*----------------------------------------------------------------------
- // ssx_phase_II - find optimal solution.
- //
- // This routine implements phase II of the primal simplex method.
- //
- // On exit the routine returns one of the following codes:
- //
- // 0 - optimal solution found;
- // 1 - problem has unbounded solution;
- // 2 - iterations limit exceeded;
- // 3 - time limit exceeded.
- ----------------------------------------------------------------------*/
- int ssx_phase_II(SSX *ssx)
- { int ret;
- /* display initial progress of the search */
- show_progress(ssx, 2);
- /* main loop starts here */
- for (;;)
- { /* display current progress of the search */
- #if 0
- if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001)
- #else
- if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001)
- #endif
- show_progress(ssx, 2);
- /* check if the iterations limit has been exhausted */
- if (ssx->it_lim == 0)
- { ret = 2;
- break;
- }
- /* check if the time limit has been exhausted */
- #if 0
- if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg)
- #else
- if (ssx->tm_lim >= 0.0 &&
- ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg))
- #endif
- { ret = 3;
- break;
- }
- /* choose non-basic variable xN[q] */
- ssx_chuzc(ssx);
- /* if xN[q] cannot be chosen, the current basic solution is
- dual feasible and therefore optimal */
- if (ssx->q == 0)
- { ret = 0;
- break;
- }
- /* compute q-th column of the simplex table */
- ssx_eval_col(ssx);
- /* choose basic variable xB[p] */
- ssx_chuzr(ssx);
- /* if xB[p] cannot be chosen, the problem has no dual feasible
- solution (i.e. unbounded) */
- if (ssx->p == 0)
- { ret = 1;
- break;
- }
- /* update values of basic variables */
- ssx_update_bbar(ssx);
- if (ssx->p > 0)
- { /* compute p-th row of the inverse inv(B) */
- ssx_eval_rho(ssx);
- /* compute p-th row of the simplex table */
- ssx_eval_row(ssx);
- xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0);
- #if 0
- /* update simplex multipliers */
- ssx_update_pi(ssx);
- #endif
- /* update reduced costs of non-basic variables */
- ssx_update_cbar(ssx);
- }
- /* jump to the adjacent vertex of the polyhedron */
- ssx_change_basis(ssx);
- /* one simplex iteration has been performed */
- if (ssx->it_lim > 0) ssx->it_lim--;
- ssx->it_cnt++;
- }
- /* display final progress of the search */
- show_progress(ssx, 2);
- /* return to the calling program */
- return ret;
- }
- /*----------------------------------------------------------------------
- // ssx_driver - base driver to exact simplex method.
- //
- // This routine is a base driver to a version of the primal simplex
- // method using exact (bignum) arithmetic.
- //
- // On exit the routine returns one of the following codes:
- //
- // 0 - optimal solution found;
- // 1 - problem has no feasible solution;
- // 2 - problem has unbounded solution;
- // 3 - iterations limit exceeded (phase I);
- // 4 - iterations limit exceeded (phase II);
- // 5 - time limit exceeded (phase I);
- // 6 - time limit exceeded (phase II);
- // 7 - initial basis matrix is exactly singular.
- ----------------------------------------------------------------------*/
- int ssx_driver(SSX *ssx)
- { int m = ssx->m;
- int *type = ssx->type;
- mpq_t *lb = ssx->lb;
- mpq_t *ub = ssx->ub;
- int *Q_col = ssx->Q_col;
- mpq_t *bbar = ssx->bbar;
- int i, k, ret;
- ssx->tm_beg = xtime();
- /* factorize the initial basis matrix */
- if (ssx_factorize(ssx))
- { xprintf("Initial basis matrix is singular\n");
- ret = 7;
- goto done;
- }
- /* compute values of basic variables */
- ssx_eval_bbar(ssx);
- /* check if the initial basic solution is primal feasible */
- for (i = 1; i <= m; i++)
- { int t;
- k = Q_col[i]; /* x[k] = xB[i] */
- t = type[k];
- if (t == SSX_LO || t == SSX_DB || t == SSX_FX)
- { /* x[k] has lower bound */
- if (mpq_cmp(bbar[i], lb[k]) < 0)
- { /* which is violated */
- break;
- }
- }
- if (t == SSX_UP || t == SSX_DB || t == SSX_FX)
- { /* x[k] has upper bound */
- if (mpq_cmp(bbar[i], ub[k]) > 0)
- { /* which is violated */
- break;
- }
- }
- }
- if (i > m)
- { /* no basic variable violates its bounds */
- ret = 0;
- goto skip;
- }
- /* phase I: find primal feasible solution */
- ret = ssx_phase_I(ssx);
- switch (ret)
- { case 0:
- ret = 0;
- break;
- case 1:
- xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n");
- ret = 1;
- break;
- case 2:
- xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n");
- ret = 3;
- break;
- case 3:
- xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
- ret = 5;
- break;
- default:
- xassert(ret != ret);
- }
- /* compute values of basic variables (actually only the objective
- value needs to be computed) */
- ssx_eval_bbar(ssx);
- skip: /* compute simplex multipliers */
- ssx_eval_pi(ssx);
- /* compute reduced costs of non-basic variables */
- ssx_eval_cbar(ssx);
- /* if phase I failed, do not start phase II */
- if (ret != 0) goto done;
- /* phase II: find optimal solution */
- ret = ssx_phase_II(ssx);
- switch (ret)
- { case 0:
- xprintf("OPTIMAL SOLUTION FOUND\n");
- ret = 0;
- break;
- case 1:
- xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n");
- ret = 2;
- break;
- case 2:
- xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n");
- ret = 4;
- break;
- case 3:
- xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
- ret = 6;
- break;
- default:
- xassert(ret != ret);
- }
- done: /* decrease the time limit by the spent amount of time */
- if (ssx->tm_lim >= 0.0)
- #if 0
- { ssx->tm_lim -= utime() - ssx->tm_beg;
- #else
- { ssx->tm_lim -= xdifftime(xtime(), ssx->tm_beg);
- #endif
- if (ssx->tm_lim < 0.0) ssx->tm_lim = 0.0;
- }
- return ret;
- }
- /* eof */
|