int CClp_load_warmstart(CClp *lp, CClp_warmstart *warm) { /* RESTORES the warmstart information in warm. */ int i, j, m, n, tagx, type, *rstat, *cstat; m = lpx_get_num_rows(lp->lp); n = lpx_get_num_cols(lp->lp); cstat = warm->cstat; rstat = warm->rstat; if (cstat == NULL || rstat == NULL) { print("CClp_load_warmstart: no basis information"); return 0; } for (j = 0; j < n; j++) { if (cstat[j] == IS_BASIC) tagx = LPX_BS; else { lpx_get_col_bnds(lp->lp, j+1, &type, NULL, NULL); switch (type) { case LPX_FR: tagx = LPX_NF; break; case LPX_LO: tagx = LPX_NL; break; case LPX_UP: tagx = LPX_NU; break; case LPX_DB: tagx = (cstat[j] == AT_UPPER ? LPX_NU : LPX_NL); break; case LPX_FX: tagx = LPX_NS; break; default: insist(type != type); } } lpx_set_col_stat(lp->lp, j+1, tagx); } for (i = 0; i < m; i++) { if (rstat[i] == IS_BASIC) tagx = LPX_BS; else { lpx_get_row_bnds(lp->lp, i+1, &type, NULL, NULL); switch (type) { case LPX_FR: tagx = LPX_NF; break; case LPX_LO: tagx = LPX_NL; break; case LPX_UP: tagx = LPX_NU; break; case LPX_DB: tagx = (rstat[i] == AT_UPPER ? LPX_NU : LPX_NL); break; case LPX_FX: tagx = LPX_NS; break; default: insist(type != type); } } lpx_set_row_stat(lp->lp, i+1, tagx); } return 0; }
void lpx_std_basis(LPX *lp) { int i, j, m, n, type; double lb, ub; /* all auxiliary variables are basic */ m = lpx_get_num_rows(lp); for (i = 1; i <= m; i++) lpx_set_row_stat(lp, i, LPX_BS); /* all structural variables are non-basic */ n = lpx_get_num_cols(lp); for (j = 1; j <= n; j++) { type = lpx_get_col_type(lp, j); lb = lpx_get_col_lb(lp, j); ub = lpx_get_col_ub(lp, j); if (type != LPX_DB || fabs(lb) <= fabs(ub)) lpx_set_col_stat(lp, j, LPX_NL); else lpx_set_col_stat(lp, j, LPX_NU); } return; }
void adv_basis(glp_prob *lp) { int m = lpx_get_num_rows(lp); int n = lpx_get_num_cols(lp); int i, j, jj, k, size; int *rn, *cn, *rn_inv, *cn_inv; int typx, *tagx = xcalloc(1+m+n, sizeof(int)); double lb, ub; xprintf("Crashing...\n"); if (m == 0) xerror("glp_adv_basis: problem has no rows\n"); if (n == 0) xerror("glp_adv_basis: problem has no columns\n"); /* use the routine triang (see above) to find maximal triangular part of the augmented constraint matrix A~ = (I|-A); in order to prevent columns of fixed variables to be included in the triangular part, such columns are implictly removed from the matrix A~ by the routine adv_mat */ rn = xcalloc(1+m, sizeof(int)); cn = xcalloc(1+m+n, sizeof(int)); size = triang(m, m+n, lp, mat, rn, cn); if (lpx_get_int_parm(lp, LPX_K_MSGLEV) >= 3) xprintf("Size of triangular part = %d\n", size); /* the first size rows and columns of the matrix P*A~*Q (where P and Q are permutation matrices defined by the arrays rn and cn) form a lower triangular matrix; build the arrays (rn_inv and cn_inv), which define the matrices inv(P) and inv(Q) */ rn_inv = xcalloc(1+m, sizeof(int)); cn_inv = xcalloc(1+m+n, sizeof(int)); for (i = 1; i <= m; i++) rn_inv[rn[i]] = i; for (j = 1; j <= m+n; j++) cn_inv[cn[j]] = j; /* include the columns of the matrix A~, which correspond to the first size columns of the matrix P*A~*Q, in the basis */ for (k = 1; k <= m+n; k++) tagx[k] = -1; for (jj = 1; jj <= size; jj++) { j = cn_inv[jj]; /* the j-th column of A~ is the jj-th column of P*A~*Q */ tagx[j] = LPX_BS; } /* if size < m, we need to add appropriate columns of auxiliary variables to the basis */ for (jj = size + 1; jj <= m; jj++) { /* the jj-th column of P*A~*Q should be replaced by the column of the auxiliary variable, for which the only unity element is placed in the position [jj,jj] */ i = rn_inv[jj]; /* the jj-th row of P*A~*Q is the i-th row of A~, but in the i-th row of A~ the unity element belongs to the i-th column of A~; therefore the disired column corresponds to the i-th auxiliary variable (note that this column doesn't belong to the triangular part found by the routine triang) */ xassert(1 <= i && i <= m); xassert(cn[i] > size); tagx[i] = LPX_BS; } /* free working arrays */ xfree(rn); xfree(cn); xfree(rn_inv); xfree(cn_inv); /* build tags of non-basic variables */ for (k = 1; k <= m+n; k++) { if (tagx[k] != LPX_BS) { if (k <= m) lpx_get_row_bnds(lp, k, &typx, &lb, &ub); else lpx_get_col_bnds(lp, k-m, &typx, &lb, &ub); switch (typx) { case LPX_FR: tagx[k] = LPX_NF; break; case LPX_LO: tagx[k] = LPX_NL; break; case LPX_UP: tagx[k] = LPX_NU; break; case LPX_DB: tagx[k] = (fabs(lb) <= fabs(ub) ? LPX_NL : LPX_NU); break; case LPX_FX: tagx[k] = LPX_NS; break; default: xassert(typx != typx); } } } for (k = 1; k <= m+n; k++) { if (k <= m) lpx_set_row_stat(lp, k, tagx[k]); else lpx_set_col_stat(lp, k-m, tagx[k]); } xfree(tagx); return; }
int lpx_integer(LPX *mip) { int m = lpx_get_num_rows(mip); int n = lpx_get_num_cols(mip); MIPTREE *tree; LPX *lp; int ret, i, j, stat, type, len, *ind; double lb, ub, coef, *val; #if 0 /* the problem must be of MIP class */ if (lpx_get_class(mip) != LPX_MIP) { print("lpx_integer: problem is not of MIP class"); ret = LPX_E_FAULT; goto done; } #endif /* an optimal solution of LP relaxation must be known */ if (lpx_get_status(mip) != LPX_OPT) { print("lpx_integer: optimal solution of LP relaxation required" ); ret = LPX_E_FAULT; goto done; } /* bounds of all integer variables must be integral */ for (j = 1; j <= n; j++) { if (lpx_get_col_kind(mip, j) != LPX_IV) continue; type = lpx_get_col_type(mip, j); if (type == LPX_LO || type == LPX_DB || type == LPX_FX) { lb = lpx_get_col_lb(mip, j); if (lb != floor(lb)) { print("lpx_integer: integer column %d has non-integer lo" "wer bound or fixed value %g", j, lb); ret = LPX_E_FAULT; goto done; } } if (type == LPX_UP || type == LPX_DB) { ub = lpx_get_col_ub(mip, j); if (ub != floor(ub)) { print("lpx_integer: integer column %d has non-integer up" "per bound %g", j, ub); ret = LPX_E_FAULT; goto done; } } } /* it seems all is ok */ if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 2) print("Integer optimization begins..."); /* create the branch-and-bound tree */ tree = mip_create_tree(m, n, lpx_get_obj_dir(mip)); /* set up column kinds */ for (j = 1; j <= n; j++) tree->int_col[j] = (lpx_get_col_kind(mip, j) == LPX_IV); /* access the LP relaxation template */ lp = tree->lp; /* set up the objective function */ tree->int_obj = 1; for (j = 0; j <= tree->n; j++) { coef = lpx_get_obj_coef(mip, j); lpx_set_obj_coef(lp, j, coef); if (coef != 0.0 && !(tree->int_col[j] && coef == floor(coef))) tree->int_obj = 0; } if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 2 && tree->int_obj) print("Objective function is integral"); /* set up the constraint matrix */ ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); for (i = 1; i <= m; i++) { len = lpx_get_mat_row(mip, i, ind, val); lpx_set_mat_row(lp, i, len, ind, val); } xfree(ind); xfree(val); /* set up scaling matrices */ for (i = 1; i <= m; i++) lpx_set_rii(lp, i, lpx_get_rii(mip, i)); for (j = 1; j <= n; j++) lpx_set_sjj(lp, j, lpx_get_sjj(mip, j)); /* revive the root subproblem */ mip_revive_node(tree, 1); /* set up row attributes for the root subproblem */ for (i = 1; i <= m; i++) { type = lpx_get_row_type(mip, i); lb = lpx_get_row_lb(mip, i); ub = lpx_get_row_ub(mip, i); stat = lpx_get_row_stat(mip, i); lpx_set_row_bnds(lp, i, type, lb, ub); lpx_set_row_stat(lp, i, stat); } /* set up column attributes for the root subproblem */ for (j = 1; j <= n; j++) { type = lpx_get_col_type(mip, j); lb = lpx_get_col_lb(mip, j); ub = lpx_get_col_ub(mip, j); stat = lpx_get_col_stat(mip, j); lpx_set_col_bnds(lp, j, type, lb, ub); lpx_set_col_stat(lp, j, stat); } /* freeze the root subproblem */ mip_freeze_node(tree); /* inherit some control parameters and statistics */ tree->msg_lev = lpx_get_int_parm(mip, LPX_K_MSGLEV); if (tree->msg_lev > 2) tree->msg_lev = 2; tree->branch = lpx_get_int_parm(mip, LPX_K_BRANCH); tree->btrack = lpx_get_int_parm(mip, LPX_K_BTRACK); tree->tol_int = lpx_get_real_parm(mip, LPX_K_TOLINT); tree->tol_obj = lpx_get_real_parm(mip, LPX_K_TOLOBJ); tree->tm_lim = lpx_get_real_parm(mip, LPX_K_TMLIM); lpx_set_int_parm(lp, LPX_K_BFTYPE, lpx_get_int_parm(mip, LPX_K_BFTYPE)); lpx_set_int_parm(lp, LPX_K_PRICE, lpx_get_int_parm(mip, LPX_K_PRICE)); lpx_set_real_parm(lp, LPX_K_RELAX, lpx_get_real_parm(mip, LPX_K_RELAX)); lpx_set_real_parm(lp, LPX_K_TOLBND, lpx_get_real_parm(mip, LPX_K_TOLBND)); lpx_set_real_parm(lp, LPX_K_TOLDJ, lpx_get_real_parm(mip, LPX_K_TOLDJ)); lpx_set_real_parm(lp, LPX_K_TOLPIV, lpx_get_real_parm(mip, LPX_K_TOLPIV)); lpx_set_int_parm(lp, LPX_K_ITLIM, lpx_get_int_parm(mip, LPX_K_ITLIM)); lpx_set_int_parm(lp, LPX_K_ITCNT, lpx_get_int_parm(mip, LPX_K_ITCNT)); /* reset the status of MIP solution */ lpx_put_mip_soln(mip, LPX_I_UNDEF, NULL, NULL); /* try solving the problem */ ret = mip_driver(tree); /* if an integer feasible solution has been found, copy it to the MIP problem object */ if (tree->found) lpx_put_mip_soln(mip, LPX_I_FEAS, &tree->mipx[0], &tree->mipx[m]); /* copy back statistics about spent resources */ lpx_set_real_parm(mip, LPX_K_TMLIM, tree->tm_lim); lpx_set_int_parm(mip, LPX_K_ITLIM, lpx_get_int_parm(lp, LPX_K_ITLIM)); lpx_set_int_parm(mip, LPX_K_ITCNT, lpx_get_int_parm(lp, LPX_K_ITCNT)); /* analyze exit code reported by the mip driver */ switch (ret) { case MIP_E_OK: if (tree->found) { if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 3) print("INTEGER OPTIMAL SOLUTION FOUND"); lpx_put_mip_soln(mip, LPX_I_OPT, NULL, NULL); } else { if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 3) print("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION"); lpx_put_mip_soln(mip, LPX_I_NOFEAS, NULL, NULL); } ret = LPX_E_OK; break; case MIP_E_ITLIM: if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 3) print("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED"); ret = LPX_E_ITLIM; break; case MIP_E_TMLIM: if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 3) print("TIME LIMIT EXCEEDED; SEARCH TERMINATED"); ret = LPX_E_TMLIM; break; case MIP_E_ERROR: if (lpx_get_int_parm(mip, LPX_K_MSGLEV) >= 1) print("lpx_integer: cannot solve current LP relaxation"); ret = LPX_E_SING; break; default: xassert(ret != ret); } /* delete the branch-and-bound tree */ mip_delete_tree(tree); done: /* return to the application program */ return ret; }