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; }
void ssx_change_basis(SSX *ssx) { int m = ssx->m; int n = ssx->n; int *type = ssx->type; int *stat = ssx->stat; int *Q_row = ssx->Q_row; int *Q_col = ssx->Q_col; int p = ssx->p; int q = ssx->q; int p_stat = ssx->p_stat; int k, kp, kq; if (p < 0) { /* special case: xN[q] goes to its opposite bound */ xassert(1 <= q && q <= n); k = Q_col[m+q]; /* x[k] = xN[q] */ xassert(type[k] == SSX_DB); switch (stat[k]) { case SSX_NL: stat[k] = SSX_NU; break; case SSX_NU: stat[k] = SSX_NL; break; default: xassert(stat != stat); } } else { /* xB[p] leaves the basis, xN[q] enters the basis */ xassert(1 <= p && p <= m); xassert(1 <= q && q <= n); kp = Q_col[p]; /* x[kp] = xB[p] */ kq = Q_col[m+q]; /* x[kq] = xN[q] */ /* check non-basic status of xB[p] which becomes xN[q] */ switch (type[kp]) { case SSX_FR: xassert(p_stat == SSX_NF); break; case SSX_LO: xassert(p_stat == SSX_NL); break; case SSX_UP: xassert(p_stat == SSX_NU); break; case SSX_DB: xassert(p_stat == SSX_NL || p_stat == SSX_NU); break; case SSX_FX: xassert(p_stat == SSX_NS); break; default: xassert(type != type); } /* swap xB[p] and xN[q] */ stat[kp] = (char)p_stat, stat[kq] = SSX_BS; Q_row[kp] = m+q, Q_row[kq] = p; Q_col[p] = kq, Q_col[m+q] = kp; /* update factorization of the basis matrix */ if (bfx_update(ssx->binv, p)) { if (ssx_factorize(ssx)) xassert(("Internal error: basis matrix is singular", 0)); } } return; }