int lpx_eval_tab_row(LPX *lp, int k, int ind[], double val[]) { /* compute row of the simplex tableau */ return glp_eval_tab_row(lp, k, ind, val); }
int glp_gmi_cut(glp_prob *P, int j, int ind[/*1+n*/], double val[/*1+n*/], double phi[/*1+m+n*/]) { int m = P->m; int n = P->n; GLPROW *row; GLPCOL *col; GLPAIJ *aij; int i, k, len, kind, stat; double lb, ub, alfa, beta, ksi, phi1, rhs; /* sanity checks */ if (!(P->m == 0 || P->valid)) { /* current basis factorization is not valid */ return -1; } if (!(P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS)) { /* current basic solution is not optimal */ return -2; } if (!(1 <= j && j <= n)) { /* column ordinal number is out of range */ return -3; } col = P->col[j]; if (col->kind != GLP_IV) { /* x[j] is not of integral kind */ return -4; } if (col->type == GLP_FX || col->stat != GLP_BS) { /* x[j] is either fixed or non-basic */ return -5; } if (fabs(col->prim - floor(col->prim + 0.5)) < 0.001) { /* primal value of x[j] is too close to nearest integer */ return -6; } /* compute row of the simplex tableau, which (row) corresponds * to specified basic variable xB[i] = x[j]; see (23) */ len = glp_eval_tab_row(P, m+j, ind, val); /* determine beta[i], which a value of xB[i] in optimal solution * to current LP relaxation; note that this value is the same as * if it would be computed with formula (27); it is assumed that * beta[i] is fractional enough */ beta = P->col[j]->prim; /* compute cut coefficients phi and right-hand side rho, which * correspond to formula (30); dense format is used, because rows * of the simplex tableau are usually dense */ for (k = 1; k <= m+n; k++) phi[k] = 0.0; rhs = f(beta); /* initial value of rho; see (28), (32) */ for (j = 1; j <= len; j++) { /* determine original number of non-basic variable xN[j] */ k = ind[j]; xassert(1 <= k && k <= m+n); /* determine the kind, bounds and current status of xN[j] in * optimal solution to LP relaxation */ if (k <= m) { /* auxiliary variable */ row = P->row[k]; kind = GLP_CV; lb = row->lb; ub = row->ub; stat = row->stat; } else { /* structural variable */ col = P->col[k-m]; kind = col->kind; lb = col->lb; ub = col->ub; stat = col->stat; } /* xN[j] cannot be basic */ xassert(stat != GLP_BS); /* determine row coefficient ksi[i,j] at xN[j]; see (23) */ ksi = val[j]; /* if ksi[i,j] is too large in magnitude, report failure */ if (fabs(ksi) > 1e+05) return -7; /* if ksi[i,j] is too small in magnitude, skip it */ if (fabs(ksi) < 1e-10) goto skip; /* compute row coefficient alfa[i,j] at y[j]; see (26) */ switch (stat) { case GLP_NF: /* xN[j] is free (unbounded) having non-zero ksi[i,j]; * report failure */ return -8; case GLP_NL: /* xN[j] has active lower bound */ alfa = - ksi; break; case GLP_NU: /* xN[j] has active upper bound */ alfa = + ksi; break; case GLP_NS: /* xN[j] is fixed; skip it */ goto skip; default: xassert(stat != stat); } /* compute cut coefficient phi'[j] at y[j]; see (21), (28) */ switch (kind) { case GLP_IV: /* y[j] is integer */ if (fabs(alfa - floor(alfa + 0.5)) < 1e-10) { /* alfa[i,j] is close to nearest integer; skip it */ goto skip; } else if (f(alfa) <= f(beta)) phi1 = f(alfa); else phi1 = (f(beta) / (1.0 - f(beta))) * (1.0 - f(alfa)); break; case GLP_CV: /* y[j] is continuous */ if (alfa >= 0.0) phi1 = + alfa; else phi1 = (f(beta) / (1.0 - f(beta))) * (- alfa); break; default: xassert(kind != kind); } /* compute cut coefficient phi[j] at xN[j] and update right- * hand side rho; see (31), (32) */ switch (stat) { case GLP_NL: /* xN[j] has active lower bound */ phi[k] = + phi1; rhs += phi1 * lb; break; case GLP_NU: /* xN[j] has active upper bound */ phi[k] = - phi1; rhs -= phi1 * ub; break; default: xassert(stat != stat); } skip: ; } /* now the cut has the form sum_k phi[k] * x[k] >= rho, where cut * coefficients are stored in the array phi in dense format; * x[1,...,m] are auxiliary variables, x[m+1,...,m+n] are struc- * tural variables; see (30) */ /* eliminate auxiliary variables in order to express the cut only * through structural variables; see (33) */ for (i = 1; i <= m; i++) { if (fabs(phi[i]) < 1e-10) continue; /* auxiliary variable x[i] has non-zero cut coefficient */ row = P->row[i]; /* x[i] cannot be fixed variable */ xassert(row->type != GLP_FX); /* substitute x[i] = sum_j a[i,j] * x[m+j] */ for (aij = row->ptr; aij != NULL; aij = aij->r_next) phi[m+aij->col->j] += phi[i] * aij->val; } /* convert the final cut to sparse format and substitute fixed * (structural) variables */ len = 0; for (j = 1; j <= n; j++) { if (fabs(phi[m+j]) < 1e-10) continue; /* structural variable x[m+j] has non-zero cut coefficient */ col = P->col[j]; if (col->type == GLP_FX) { /* eliminate x[m+j] */ rhs -= phi[m+j] * col->lb; } else { len++; ind[len] = j; val[len] = phi[m+j]; } } if (fabs(rhs) < 1e-12) rhs = 0.0; ind[0] = 0, val[0] = rhs; /* the cut has been successfully generated */ return len; }
static int branch_drtom(glp_tree *T, int *_next) { glp_prob *mip = T->mip; int m = mip->m; int n = mip->n; char *non_int = T->non_int; int j, jj, k, t, next, kase, len, stat, *ind; double x, dk, alfa, delta_j, delta_k, delta_z, dz_dn, dz_up, dd_dn, dd_up, degrad, *val; /* basic solution of LP relaxation must be optimal */ xassert(glp_get_status(mip) == GLP_OPT); /* allocate working arrays */ ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); /* nothing has been chosen so far */ jj = 0, degrad = -1.0; /* walk through the list of columns (structural variables) */ for (j = 1; j <= n; j++) { /* if j-th column is not marked as fractional, skip it */ if (!non_int[j]) continue; /* obtain (fractional) value of j-th column in basic solution of LP relaxation */ x = glp_get_col_prim(mip, j); /* since the value of j-th column is fractional, the column is basic; compute corresponding row of the simplex table */ len = glp_eval_tab_row(mip, m+j, ind, val); /* the following fragment computes a change in the objective function: delta Z = new Z - old Z, where old Z is the objective value in the current optimal basis, and new Z is the objective value in the adjacent basis, for two cases: 1) if new upper bound ub' = floor(x[j]) is introduced for j-th column (down branch); 2) if new lower bound lb' = ceil(x[j]) is introduced for j-th column (up branch); since in both cases the solution remaining dual feasible becomes primal infeasible, one implicit simplex iteration is performed to determine the change delta Z; it is obvious that new Z, which is never better than old Z, is a lower (minimization) or upper (maximization) bound of the objective function for down- and up-branches. */ for (kase = -1; kase <= +1; kase += 2) { /* if kase < 0, the new upper bound of x[j] is introduced; in this case x[j] should decrease in order to leave the basis and go to its new upper bound */ /* if kase > 0, the new lower bound of x[j] is introduced; in this case x[j] should increase in order to leave the basis and go to its new lower bound */ /* apply the dual ratio test in order to determine which auxiliary or structural variable should enter the basis to keep dual feasibility */ k = glp_dual_rtest(mip, len, ind, val, kase, 1e-9); if (k != 0) k = ind[k]; /* if no non-basic variable has been chosen, LP relaxation of corresponding branch being primal infeasible and dual unbounded has no primal feasible solution; in this case the change delta Z is formally set to infinity */ if (k == 0) { delta_z = (T->mip->dir == GLP_MIN ? +DBL_MAX : -DBL_MAX); goto skip; } /* row of the simplex table that corresponds to non-basic variable x[k] choosen by the dual ratio test is: x[j] = ... + alfa * x[k] + ... where alfa is the influence coefficient (an element of the simplex table row) */ /* determine the coefficient alfa */ for (t = 1; t <= len; t++) if (ind[t] == k) break; xassert(1 <= t && t <= len); alfa = val[t]; /* since in the adjacent basis the variable x[j] becomes non-basic, knowing its value in the current basis we can determine its change delta x[j] = new x[j] - old x[j] */ delta_j = (kase < 0 ? floor(x) : ceil(x)) - x; /* and knowing the coefficient alfa we can determine the corresponding change delta x[k] = new x[k] - old x[k], where old x[k] is a value of x[k] in the current basis, and new x[k] is a value of x[k] in the adjacent basis */ delta_k = delta_j / alfa; /* Tomlin noticed that if the variable x[k] is of integer kind, its change cannot be less (eventually) than one in the magnitude */ if (k > m && glp_get_col_kind(mip, k-m) != GLP_CV) { /* x[k] is structural integer variable */ if (fabs(delta_k - floor(delta_k + 0.5)) > 1e-3) { if (delta_k > 0.0) delta_k = ceil(delta_k); /* +3.14 -> +4 */ else delta_k = floor(delta_k); /* -3.14 -> -4 */ } } /* now determine the status and reduced cost of x[k] in the current basis */ if (k <= m) { stat = glp_get_row_stat(mip, k); dk = glp_get_row_dual(mip, k); } else { stat = glp_get_col_stat(mip, k-m); dk = glp_get_col_dual(mip, k-m); } /* if the current basis is dual degenerate, some reduced costs which are close to zero may have wrong sign due to round-off errors, so correct the sign of d[k] */ switch (T->mip->dir) { case GLP_MIN: if (stat == GLP_NL && dk < 0.0 || stat == GLP_NU && dk > 0.0 || stat == GLP_NF) dk = 0.0; break; case GLP_MAX: if (stat == GLP_NL && dk > 0.0 || stat == GLP_NU && dk < 0.0 || stat == GLP_NF) dk = 0.0; break; default: xassert(T != T); } /* now knowing the change of x[k] and its reduced cost d[k] we can compute the corresponding change in the objective function delta Z = new Z - old Z = d[k] * delta x[k]; note that due to Tomlin's modification new Z can be even worse than in the adjacent basis */ delta_z = dk * delta_k; skip: /* new Z is never better than old Z, therefore the change delta Z is always non-negative (in case of minimization) or non-positive (in case of maximization) */ switch (T->mip->dir) { case GLP_MIN: xassert(delta_z >= 0.0); break; case GLP_MAX: xassert(delta_z <= 0.0); break; default: xassert(T != T); } /* save the change in the objective fnction for down- and up-branches, respectively */ if (kase < 0) dz_dn = delta_z; else dz_up = delta_z; } /* thus, in down-branch no integer feasible solution can be better than Z + dz_dn, and in up-branch no integer feasible solution can be better than Z + dz_up, where Z is value of the objective function in the current basis */ /* following the heuristic by Driebeck and Tomlin we choose a column (i.e. structural variable) which provides largest degradation of the objective function in some of branches; besides, we select the branch with smaller degradation to be solved next and keep other branch with larger degradation in the active list hoping to minimize the number of further backtrackings */ if (degrad < fabs(dz_dn) || degrad < fabs(dz_up)) { jj = j; if (fabs(dz_dn) < fabs(dz_up)) { /* select down branch to be solved next */ next = GLP_DN_BRNCH; degrad = fabs(dz_up); } else { /* select up branch to be solved next */ next = GLP_UP_BRNCH; degrad = fabs(dz_dn); } /* save the objective changes for printing */ dd_dn = dz_dn, dd_up = dz_up; /* if down- or up-branch has no feasible solution, we does not need to consider other candidates (in principle, the corresponding branch could be pruned right now) */ if (degrad == DBL_MAX) break; } } /* free working arrays */ xfree(ind); xfree(val); /* something must be chosen */ xassert(1 <= jj && jj <= n); #if 1 /* 02/XI-2009 */ if (degrad < 1e-6 * (1.0 + 0.001 * fabs(mip->obj_val))) { jj = branch_mostf(T, &next); goto done; } #endif if (T->parm->msg_lev >= GLP_MSG_DBG) { xprintf("branch_drtom: column %d chosen to branch on\n", jj); if (fabs(dd_dn) == DBL_MAX) xprintf("branch_drtom: down-branch is infeasible\n"); else xprintf("branch_drtom: down-branch bound is %.9e\n", lpx_get_obj_val(mip) + dd_dn); if (fabs(dd_up) == DBL_MAX) xprintf("branch_drtom: up-branch is infeasible\n"); else xprintf("branch_drtom: up-branch bound is %.9e\n", lpx_get_obj_val(mip) + dd_up); } done: *_next = next; return jj; }
static void gen_cut(glp_tree *tree, struct worka *worka, int j) { /* this routine tries to generate Gomory's mixed integer cut for specified structural variable x[m+j] of integer kind, which is basic and has fractional value in optimal solution to current LP relaxation */ glp_prob *mip = tree->mip; int m = mip->m; int n = mip->n; int *ind = worka->ind; double *val = worka->val; double *phi = worka->phi; int i, k, len, kind, stat; double lb, ub, alfa, beta, ksi, phi1, rhs; /* compute row of the simplex tableau, which (row) corresponds to specified basic variable xB[i] = x[m+j]; see (23) */ len = glp_eval_tab_row(mip, m+j, ind, val); /* determine beta[i], which a value of xB[i] in optimal solution to current LP relaxation; note that this value is the same as if it would be computed with formula (27); it is assumed that beta[i] is fractional enough */ beta = mip->col[j]->prim; /* compute cut coefficients phi and right-hand side rho, which correspond to formula (30); dense format is used, because rows of the simplex tableau is usually dense */ for (k = 1; k <= m+n; k++) phi[k] = 0.0; rhs = f(beta); /* initial value of rho; see (28), (32) */ for (j = 1; j <= len; j++) { /* determine original number of non-basic variable xN[j] */ k = ind[j]; xassert(1 <= k && k <= m+n); /* determine the kind, bounds and current status of xN[j] in optimal solution to LP relaxation */ if (k <= m) { /* auxiliary variable */ GLPROW *row = mip->row[k]; kind = GLP_CV; lb = row->lb; ub = row->ub; stat = row->stat; } else { /* structural variable */ GLPCOL *col = mip->col[k-m]; kind = col->kind; lb = col->lb; ub = col->ub; stat = col->stat; } /* xN[j] cannot be basic */ xassert(stat != GLP_BS); /* determine row coefficient ksi[i,j] at xN[j]; see (23) */ ksi = val[j]; /* if ksi[i,j] is too large in the magnitude, do not generate the cut */ if (fabs(ksi) > 1e+05) goto fini; /* if ksi[i,j] is too small in the magnitude, skip it */ if (fabs(ksi) < 1e-10) goto skip; /* compute row coefficient alfa[i,j] at y[j]; see (26) */ switch (stat) { case GLP_NF: /* xN[j] is free (unbounded) having non-zero ksi[i,j]; do not generate the cut */ goto fini; case GLP_NL: /* xN[j] has active lower bound */ alfa = - ksi; break; case GLP_NU: /* xN[j] has active upper bound */ alfa = + ksi; break; case GLP_NS: /* xN[j] is fixed; skip it */ goto skip; default: xassert(stat != stat); } /* compute cut coefficient phi'[j] at y[j]; see (21), (28) */ switch (kind) { case GLP_IV: /* y[j] is integer */ if (fabs(alfa - floor(alfa + 0.5)) < 1e-10) { /* alfa[i,j] is close to nearest integer; skip it */ goto skip; } else if (f(alfa) <= f(beta)) phi1 = f(alfa); else phi1 = (f(beta) / (1.0 - f(beta))) * (1.0 - f(alfa)); break; case GLP_CV: /* y[j] is continuous */ if (alfa >= 0.0) phi1 = + alfa; else phi1 = (f(beta) / (1.0 - f(beta))) * (- alfa); break; default: xassert(kind != kind); } /* compute cut coefficient phi[j] at xN[j] and update right- hand side rho; see (31), (32) */ switch (stat) { case GLP_NL: /* xN[j] has active lower bound */ phi[k] = + phi1; rhs += phi1 * lb; break; case GLP_NU: /* xN[j] has active upper bound */ phi[k] = - phi1; rhs -= phi1 * ub; break; default: xassert(stat != stat); } skip: ; } /* now the cut has the form sum_k phi[k] * x[k] >= rho, where cut coefficients are stored in the array phi in dense format; x[1,...,m] are auxiliary variables, x[m+1,...,m+n] are struc- tural variables; see (30) */ /* eliminate auxiliary variables in order to express the cut only through structural variables; see (33) */ for (i = 1; i <= m; i++) { GLPROW *row; GLPAIJ *aij; if (fabs(phi[i]) < 1e-10) continue; /* auxiliary variable x[i] has non-zero cut coefficient */ row = mip->row[i]; /* x[i] cannot be fixed */ xassert(row->type != GLP_FX); /* substitute x[i] = sum_j a[i,j] * x[m+j] */ for (aij = row->ptr; aij != NULL; aij = aij->r_next) phi[m+aij->col->j] += phi[i] * aij->val; } /* convert the final cut to sparse format and substitute fixed (structural) variables */ len = 0; for (j = 1; j <= n; j++) { GLPCOL *col; if (fabs(phi[m+j]) < 1e-10) continue; /* structural variable x[m+j] has non-zero cut coefficient */ col = mip->col[j]; if (col->type == GLP_FX) { /* eliminate x[m+j] */ rhs -= phi[m+j] * col->lb; } else { len++; ind[len] = j; val[len] = phi[m+j]; } } if (fabs(rhs) < 1e-12) rhs = 0.0; /* if the cut inequality seems to be badly scaled, reject it to avoid numeric difficulties */ for (k = 1; k <= len; k++) { if (fabs(val[k]) < 1e-03) goto fini; if (fabs(val[k]) > 1e+03) goto fini; } /* add the cut to the cut pool for further consideration */ #if 0 ios_add_cut_row(tree, pool, GLP_RF_GMI, len, ind, val, GLP_LO, rhs); #else glp_ios_add_row(tree, NULL, GLP_RF_GMI, 0, len, ind, val, GLP_LO, rhs); #endif fini: return; }