int ipm_solve(glp_prob *P, const glp_iptcp *parm) { struct csa _dsa, *csa = &_dsa; int m = P->m; int n = P->n; int nnz = P->nnz; GLPROW *row; GLPCOL *col; GLPAIJ *aij; int i, j, loc, ret, *A_ind, *A_ptr; double dir, *A_val, *b, *c, *x, *y, *z; xassert(m > 0); xassert(n > 0); /* allocate working arrays */ A_ptr = xcalloc(1+m+1, sizeof(int)); A_ind = xcalloc(1+nnz, sizeof(int)); A_val = xcalloc(1+nnz, sizeof(double)); b = xcalloc(1+m, sizeof(double)); c = xcalloc(1+n, sizeof(double)); x = xcalloc(1+n, sizeof(double)); y = xcalloc(1+m, sizeof(double)); z = xcalloc(1+n, sizeof(double)); /* prepare rows and constraint coefficients */ loc = 1; for (i = 1; i <= m; i++) { row = P->row[i]; xassert(row->type == GLP_FX); b[i] = row->lb * row->rii; A_ptr[i] = loc; for (aij = row->ptr; aij != NULL; aij = aij->r_next) { A_ind[loc] = aij->col->j; A_val[loc] = row->rii * aij->val * aij->col->sjj; loc++; } } A_ptr[m+1] = loc; xassert(loc-1 == nnz); /* prepare columns and objective coefficients */ if (P->dir == GLP_MIN) dir = +1.0; else if (P->dir == GLP_MAX) dir = -1.0; else xassert(P != P); c[0] = dir * P->c0; for (j = 1; j <= n; j++) { col = P->col[j]; xassert(col->type == GLP_LO && col->lb == 0.0); c[j] = dir * col->coef * col->sjj; } /* allocate and initialize the common storage area */ csa->m = m; csa->n = n; csa->A_ptr = A_ptr; csa->A_ind = A_ind; csa->A_val = A_val; csa->b = b; csa->c = c; csa->x = x; csa->y = y; csa->z = z; csa->parm = parm; initialize(csa); /* solve LP with the interior-point method */ ret = ipm_main(csa); /* deallocate the common storage area */ terminate(csa); /* determine solution status */ if (ret == 0) { /* optimal solution found */ P->ipt_stat = GLP_OPT; ret = 0; } else if (ret == 1) { /* problem has no feasible (primal or dual) solution */ P->ipt_stat = GLP_NOFEAS; ret = 0; } else if (ret == 2) { /* no convergence */ P->ipt_stat = GLP_INFEAS; ret = GLP_ENOCVG; } else if (ret == 3) { /* iteration limit exceeded */ P->ipt_stat = GLP_INFEAS; ret = GLP_EITLIM; } else if (ret == 4) { /* numeric instability on solving Newtonian system */ P->ipt_stat = GLP_INFEAS; ret = GLP_EINSTAB; } else xassert(ret != ret); /* store row solution components */ for (i = 1; i <= m; i++) { row = P->row[i]; row->pval = row->lb; row->dval = dir * y[i] * row->rii; } /* store column solution components */ P->ipt_obj = P->c0; for (j = 1; j <= n; j++) { col = P->col[j]; col->pval = x[j] * col->sjj; col->dval = dir * z[j] / col->sjj; P->ipt_obj += col->coef * col->pval; } /* free working arrays */ xfree(A_ptr); xfree(A_ind); xfree(A_val); xfree(b); xfree(c); xfree(x); xfree(y); xfree(z); return ret; }
int lpx_interior(LPX *_lp) { /* easy-to-use driver to the interior-point method */ struct dsa _dsa, *dsa = &_dsa; int ret, status; double *row_pval, *row_dval, *col_pval, *col_dval; /* initialize working area */ dsa->lp = _lp; dsa->orig_m = lpx_get_num_rows(dsa->lp); dsa->orig_n = lpx_get_num_cols(dsa->lp); dsa->ref = NULL; dsa->m = 0; dsa->n = 0; dsa->size = 0; dsa->ne = 0; dsa->ia = NULL; dsa->ja = NULL; dsa->ar = NULL; dsa->b = NULL; dsa->c = NULL; dsa->x = NULL; dsa->y = NULL; dsa->z = NULL; /* check if the problem is empty */ if (!(dsa->orig_m > 0 && dsa->orig_n > 0)) { print("lpx_interior: problem has no rows and/or columns"); ret = LPX_E_FAULT; goto done; } /* issue warning about dense columns */ if (dsa->orig_m >= 200) { int j, len, ndc = 0; for (j = 1; j <= dsa->orig_n; j++) { len = lpx_get_mat_col(dsa->lp, j, NULL, NULL); if ((double)len > 0.30 * (double)dsa->orig_m) ndc++; } if (ndc == 1) print("lpx_interior: WARNING: PROBLEM HAS ONE DENSE COLUMN") ; else if (ndc > 0) print("lpx_interior: WARNING: PROBLEM HAS %d DENSE COLUMNS", ndc); } /* determine dimension of transformed LP */ print("lpx_interior: original LP problem has %d rows and %d colum" "ns", dsa->orig_m, dsa->orig_n); calc_mn(dsa); print("lpx_interior: transformed LP problem has %d rows and %d co" "lumns", dsa->m, dsa->n); /* transform original LP to standard formulation */ dsa->ref = ucalloc(1+dsa->orig_m+dsa->orig_n, sizeof(int)); dsa->size = lpx_get_num_nz(dsa->lp); if (dsa->size < dsa->m) dsa->size = dsa->m; if (dsa->size < dsa->n) dsa->size = dsa->n; dsa->ne = 0; dsa->ia = ucalloc(1+dsa->size, sizeof(int)); dsa->ja = ucalloc(1+dsa->size, sizeof(int)); dsa->ar = ucalloc(1+dsa->size, sizeof(double)); dsa->b = ucalloc(1+dsa->m, sizeof(double)); dsa->c = ucalloc(1+dsa->n, sizeof(double)); transform(dsa); /* solve the transformed LP problem */ { int *A_ptr = ucalloc(1+dsa->m+1, sizeof(int)); int *A_ind = ucalloc(1+dsa->ne, sizeof(int)); double *A_val = ucalloc(1+dsa->ne, sizeof(double)); int i, k, pos, len; /* determine row lengths */ for (i = 1; i <= dsa->m; i++) A_ptr[i] = 0; for (k = 1; k <= dsa->ne; k++) A_ptr[dsa->ia[k]]++; /* set up row pointers */ pos = 1; for (i = 1; i <= dsa->m; i++) len = A_ptr[i], pos += len, A_ptr[i] = pos; A_ptr[dsa->m+1] = pos; insist(pos - 1 == dsa->ne); /* build the matrix */ for (k = 1; k <= dsa->ne; k++) { pos = --A_ptr[dsa->ia[k]]; A_ind[pos] = dsa->ja[k]; A_val[pos] = dsa->ar[k]; } ufree(dsa->ia), dsa->ia = NULL; ufree(dsa->ja), dsa->ja = NULL; ufree(dsa->ar), dsa->ar = NULL; dsa->x = ucalloc(1+dsa->n, sizeof(double)); dsa->y = ucalloc(1+dsa->m, sizeof(double)); dsa->z = ucalloc(1+dsa->n, sizeof(double)); ret = ipm_main(dsa->m, dsa->n, A_ptr, A_ind, A_val, dsa->b, dsa->c, dsa->x, dsa->y, dsa->z); ufree(A_ptr); ufree(A_ind); ufree(A_val); ufree(dsa->b), dsa->b = NULL; ufree(dsa->c), dsa->c = NULL; } /* analyze return code reported by the solver */ switch (ret) { case 0: /* optimal solution found */ ret = LPX_E_OK; break; case 1: /* problem has no feasible (primal or dual) solution */ ret = LPX_E_NOFEAS; break; case 2: /* no convergence */ ret = LPX_E_NOCONV; break; case 3: /* iterations limit exceeded */ ret = LPX_E_ITLIM; break; case 4: /* numerical instability on solving Newtonian system */ ret = LPX_E_INSTAB; break; default: insist(ret != ret); } /* recover solution of original LP */ row_pval = ucalloc(1+dsa->orig_m, sizeof(double)); row_dval = ucalloc(1+dsa->orig_m, sizeof(double)); col_pval = ucalloc(1+dsa->orig_n, sizeof(double)); col_dval = ucalloc(1+dsa->orig_n, sizeof(double)); restore(dsa, row_pval, row_dval, col_pval, col_dval); ufree(dsa->ref), dsa->ref = NULL; ufree(dsa->x), dsa->x = NULL; ufree(dsa->y), dsa->y = NULL; ufree(dsa->z), dsa->z = NULL; /* store solution components into the problem object */ status = (ret == LPX_E_OK ? LPX_T_OPT : LPX_T_UNDEF); lpx_put_ipt_soln(dsa->lp, status, row_pval, row_dval, col_pval, col_dval); ufree(row_pval); ufree(row_dval); ufree(col_pval); ufree(col_dval); done: /* return to the calling program */ return ret; }