예제 #1
0
static int is_binary(LPX *lp, int j)
{     /* this routine checks if variable x[j] is binary */
      return
         lpx_get_col_kind(lp, j) == LPX_IV &&
         lpx_get_col_type(lp, j) == LPX_DB &&
         lpx_get_col_lb(lp, j) == 0.0 && lpx_get_col_ub(lp, j) == 1.0;
}
예제 #2
0
void lpx_get_col_bnds(glp_prob *lp, int j, int *typx, double *lb,
      double *ub)
{     /* retrieve column bounds */
      if (typx != NULL) *typx = lpx_get_col_type(lp, j);
      if (lb != NULL) *lb = lpx_get_col_lb(lp, j);
      if (ub != NULL) *ub = lpx_get_col_ub(lp, j);
      return;
}
예제 #3
0
static void calc_mn(struct dsa *dsa)
{   /* calculate the number of constraints (m) and variables (n) for
       transformed LP */
    LPX *lp = dsa->lp;
    int orig_m = dsa->orig_m;
    int orig_n = dsa->orig_n;
    int i, j, m = 0, n = 0;
    for (i = 1; i <= orig_m; i++)
    {   switch (lpx_get_row_type(lp, i))
        {
        case LPX_FR:
            break;
        case LPX_LO:
            m++;
            n++;
            break;
        case LPX_UP:
            m++;
            n++;
            break;
        case LPX_DB:
            m += 2;
            n += 2;
            break;
        case LPX_FX:
            m++;
            break;
        default:
            insist(lp != lp);
        }
    }
    for (j = 1; j <= orig_n; j++)
    {   switch (lpx_get_col_type(lp, j))
        {
        case LPX_FR:
            n += 2;
            break;
        case LPX_LO:
            n++;
            break;
        case LPX_UP:
            n++;
            break;
        case LPX_DB:
            m++;
            n += 2;
            break;
        case LPX_FX:
            break;
        default:
            insist(lp != lp);
        }
    }
    dsa->m = m;
    dsa->n = n;
    return;
}
예제 #4
0
static double get_col_ub(LPX *lp, int j)
{     /* this routine returns upper bound of column j or +DBL_MAX if
         the column has no upper bound */
      double ub;
      switch (lpx_get_col_type(lp, j))
      {  case LPX_FR:
         case LPX_LO:
            ub = +DBL_MAX;
            break;
         case LPX_UP:
         case LPX_DB:
         case LPX_FX:
            ub = lpx_get_col_ub(lp, j);
            break;
         default:
            xassert(lp != lp);
      }
      return ub;
}
예제 #5
0
static double get_col_lb(LPX *lp, int j)
{     /* this routine returns lower bound of column j or -DBL_MAX if
         the column has no lower bound */
      double lb;
      switch (lpx_get_col_type(lp, j))
      {  case LPX_FR:
         case LPX_UP:
            lb = -DBL_MAX;
            break;
         case LPX_LO:
         case LPX_DB:
         case LPX_FX:
            lb = lpx_get_col_lb(lp, j);
            break;
         default:
            xassert(lp != lp);
      }
      return lb;
}
예제 #6
0
파일: glplpx5.c 프로젝트: MasonXQY/OPSP
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;
}
예제 #7
0
static void restore(struct dsa *dsa, double row_pval[],
                    double row_dval[], double col_pval[], double col_dval[])
{   /* restore solution of original LP */
    LPX *lp = dsa->lp;
    int orig_m = dsa->orig_m;
    int orig_n = dsa->orig_n;
    int *ref = dsa->ref;
    int m = dsa->m;
    double *x = dsa->x;
    double *y = dsa->y;
    int dir = lpx_get_obj_dir(lp);
    int i, j, k, type, t, len, *ind;
    double lb, ub, rii, sjj, temp, *val;
    /* compute primal values of structural variables */
    for (k = 1; k <= orig_n; k++)
    {   j = ref[orig_m+k];
        type = lpx_get_col_type(lp, k);
        sjj = lpx_get_sjj(lp, k);
        lb = lpx_get_col_lb(lp, k) / sjj;
        ub = lpx_get_col_ub(lp, k) / sjj;
        switch (type)
        {
        case LPX_FR:
            /* source: -inf < x < +inf */
            /* result: x = x' - x'', x' >= 0, x'' >= 0 */
            col_pval[k] = x[j] - x[j+1];
            break;
        case LPX_LO:
            /* source: lb <= x < +inf */
            /* result: x = lb + x', x' >= 0 */
            col_pval[k] = lb + x[j];
            break;
        case LPX_UP:
            /* source: -inf < x <= ub */
            /* result: x = ub - x', x' >= 0 */
            col_pval[k] = ub - x[j];
            break;
        case LPX_DB:
            /* source: lb <= x <= ub */
            /* result: x = lb + x', x' + x'' = ub - lb */
            col_pval[k] = lb + x[j];
            break;
        case LPX_FX:
            /* source: x = lb */
            /* result: just substitute */
            col_pval[k] = lb;
            break;
        default:
            insist(type != type);
        }
    }
    /* compute primal values of auxiliary variables */
    /* xR = A * xS */
    ind = ucalloc(1+orig_n, sizeof(int));
    val = ucalloc(1+orig_n, sizeof(double));
    for (k = 1; k <= orig_m; k++)
    {   rii = lpx_get_rii(lp, k);
        temp = 0.0;
        len = lpx_get_mat_row(lp, k, ind, val);
        for (t = 1; t <= len; t++)
        {   sjj = lpx_get_sjj(lp, ind[t]);
            temp += (rii * val[t] * sjj) * col_pval[ind[t]];
        }
        row_pval[k] = temp;
    }
    ufree(ind);
    ufree(val);
    /* compute dual values of auxiliary variables */
    for (k = 1; k <= orig_m; k++)
    {   type = lpx_get_row_type(lp, k);
        i = ref[k];
        switch (type)
        {
        case LPX_FR:
            insist(i == 0);
            row_dval[k] = 0.0;
            break;
        case LPX_LO:
        case LPX_UP:
        case LPX_DB:
        case LPX_FX:
            insist(1 <= i && i <= m);
            row_dval[k] = (dir == LPX_MIN ? +1.0 : -1.0) * y[i];
            break;
        default:
            insist(type != type);
        }
    }
    /* compute dual values of structural variables */
    /* dS = cS - A' * (dR - cR) */
    ind = ucalloc(1+orig_m, sizeof(int));
    val = ucalloc(1+orig_m, sizeof(double));
    for (k = 1; k <= orig_n; k++)
    {   sjj = lpx_get_sjj(lp, k);
        temp = lpx_get_obj_coef(lp, k) / sjj;
        len = lpx_get_mat_col(lp, k, ind, val);
        for (t = 1; t <= len; t++)
        {   rii = lpx_get_rii(lp, ind[t]);
            temp -= (rii * val[t] * sjj) * row_dval[ind[t]];
        }
        col_dval[k] = temp;
    }
    ufree(ind);
    ufree(val);
    /* unscale solution of original LP */
    for (i = 1; i <= orig_m; i++)
    {   rii = lpx_get_rii(lp, i);
        row_pval[i] /= rii;
        row_dval[i] *= rii;
    }
    for (j = 1; j <= orig_n; j++)
    {   sjj = lpx_get_sjj(lp, j);
        col_pval[j] *= sjj;
        col_dval[j] /= sjj;
    }
    return;
}
예제 #8
0
static void transform(struct dsa *dsa)
{   /* transform original LP to standard formulation */
    LPX *lp = dsa->lp;
    int orig_m = dsa->orig_m;
    int orig_n = dsa->orig_n;
    int *ref = dsa->ref;
    int m = dsa->m;
    int n = dsa->n;
    double *b = dsa->b;
    double *c = dsa->c;
    int i, j, k, type, t, ii, len, *ind;
    double lb, ub, coef, rii, sjj, *val;
    /* initialize components of transformed LP */
    dsa->ne = 0;
    for (i = 1; i <= m; i++) b[i] = 0.0;
    c[0] = lpx_get_obj_coef(lp, 0);
    for (j = 1; j <= n; j++) c[j] = 0.0;
    /* i and j are, respectively, ordinal number of current row and
       ordinal number of current column in transformed LP */
    i = j = 0;
    /* transform rows (auxiliary variables) */
    for (k = 1; k <= orig_m; k++)
    {   type = lpx_get_row_type(lp, k);
        rii = lpx_get_rii(lp, k);
        lb = lpx_get_row_lb(lp, k) * rii;
        ub = lpx_get_row_ub(lp, k) * rii;
        switch (type)
        {
        case LPX_FR:
            /* source: -inf < (L.F.) < +inf */
            /* result: ignore free row */
            ref[k] = 0;
            break;
        case LPX_LO:
            /* source: lb <= (L.F.) < +inf */
            /* result: (L.F.) - x' = lb, x' >= 0 */
            i++;
            j++;
            ref[k] = i;
            new_coef(dsa, i, j, -1.0);
            b[i] = lb;
            break;
        case LPX_UP:
            /* source: -inf < (L.F.) <= ub */
            /* result: (L.F.) + x' = ub, x' >= 0 */
            i++;
            j++;
            ref[k] = i;
            new_coef(dsa, i, j, +1.0);
            b[i] = ub;
            break;
        case LPX_DB:
            /* source: lb <= (L.F.) <= ub */
            /* result: (L.F.) - x' = lb, x' + x'' = ub - lb */
            i++;
            j++;
            ref[k] = i;
            new_coef(dsa, i, j, -1.0);
            b[i] = lb;
            i++;
            new_coef(dsa, i, j, +1.0);
            j++;
            new_coef(dsa, i, j, +1.0);
            b[i] = ub - lb;
            break;
        case LPX_FX:
            /* source: (L.F.) = lb */
            /* result: (L.F.) = lb */
            i++;
            ref[k] = i;
            b[i] = lb;
            break;
        default:
            insist(type != type);
        }
    }
    /* transform columns (structural variables) */
    ind = ucalloc(1+orig_m, sizeof(int));
    val = ucalloc(1+orig_m, sizeof(double));
    for (k = 1; k <= orig_n; k++)
    {   type = lpx_get_col_type(lp, k);
        sjj = lpx_get_sjj(lp, k);
        lb = lpx_get_col_lb(lp, k) / sjj;
        ub = lpx_get_col_ub(lp, k) / sjj;
        coef = lpx_get_obj_coef(lp, k) * sjj;
        len = lpx_get_mat_col(lp, k, ind, val);
        for (t = 1; t <= len; t++)
            val[t] *= (lpx_get_rii(lp, ind[t]) * sjj);
        switch (type)
        {
        case LPX_FR:
            /* source: -inf < x < +inf */
            /* result: x = x' - x'', x' >= 0, x'' >= 0 */
            j++;
            ref[orig_m+k] = j;
            for (t = 1; t <= len; t++)
            {   ii = ref[ind[t]];
                if (ii != 0) new_coef(dsa, ii, j, +val[t]);
            }
            c[j] = +coef;
            j++;
            for (t = 1; t <= len; t++)
            {   ii = ref[ind[t]];
                if (ii != 0) new_coef(dsa, ii, j, -val[t]);
            }
            c[j] = -coef;
            break;
        case LPX_LO:
            /* source: lb <= x < +inf */
            /* result: x = lb + x', x' >= 0 */
            j++;
            ref[orig_m+k] = j;
            for (t = 1; t <= len; t++)
            {   ii = ref[ind[t]];
                if (ii != 0)
                {   new_coef(dsa, ii, j, val[t]);
                    b[ii] -= val[t] * lb;
                }
            }
            c[j] = +coef;
            c[0] += c[j] * lb;
            break;
        case LPX_UP:
            /* source: -inf < x <= ub */
            /* result: x = ub - x', x' >= 0 */
            j++;
            ref[orig_m+k] = j;
            for (t = 1; t <= len; t++)
            {   ii = ref[ind[t]];
                if (ii != 0)
                {   new_coef(dsa, ii, j, -val[t]);
                    b[ii] -= val[t] * ub;
                }
            }
            c[j] = -coef;
            c[0] -= c[j] * ub;
            break;
        case LPX_DB:
            /* source: lb <= x <= ub */
            /* result: x = lb + x', x' + x'' = ub - lb */
            j++;
            ref[orig_m+k] = j;
            for (t = 1; t <= len; t++)
            {   ii = ref[ind[t]];
                if (ii != 0)
                {   new_coef(dsa, ii, j, val[t]);
                    b[ii] -= val[t] * lb;
                }
            }
            c[j] = +coef;
            c[0] += c[j] * lb;
            i++;
            new_coef(dsa, i, j, +1.0);
            j++;
            new_coef(dsa, i, j, +1.0);
            b[i] = ub - lb;
            break;
        case LPX_FX:
            /* source: x = lb */
            /* result: just substitute */
            ref[orig_m+k] = 0;
            for (t = 1; t <= len; t++)
            {   ii = ref[ind[t]];
                if (ii != 0) b[ii] -= val[t] * lb;
            }
            c[0] += coef * lb;
            break;
        default:
            insist(type != type);
        }
    }
    ufree(ind);
    ufree(val);
    /* end of transformation */
    insist(i == m && j == n);
    /* change the objective sign in case of maximization */
    if (lpx_get_obj_dir(lp) == LPX_MAX)
        for (j = 0; j <= n; j++) c[j] = -c[j];
    return;
}
예제 #9
0
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;
}
예제 #10
0
void lpx_check_int(LPX *lp, LPXKKT *kkt)
{     int m = lpx_get_num_rows(lp);
      int n = lpx_get_num_cols(lp);
      int *ind, i, len, t, j, k, type;
      double *val, xR_i, g_i, xS_j, temp, lb, ub, x_k, h_k;
      /*--------------------------------------------------------------*/
      /* compute largest absolute and relative errors and corresponding
         row indices for the condition (KKT.PE) */
      kkt->pe_ae_max = 0.0, kkt->pe_ae_row = 0;
      kkt->pe_re_max = 0.0, kkt->pe_re_row = 0;
      ind = xcalloc(1+n, sizeof(int));
      val = xcalloc(1+n, sizeof(double));
      for (i = 1; i <= m; i++)
      {  /* determine xR[i] */
         xR_i = lpx_mip_row_val(lp, i);
         /* g[i] := xR[i] */
         g_i = xR_i;
         /* g[i] := g[i] - (i-th row of A) * xS */
         len = lpx_get_mat_row(lp, i, ind, val);
         for (t = 1; t <= len; t++)
         {  j = ind[t];
            /* determine xS[j] */
            xS_j = lpx_mip_col_val(lp, j);
            /* g[i] := g[i] - a[i,j] * xS[j] */
            g_i -= val[t] * xS_j;
         }
         /* determine absolute error */
         temp = fabs(g_i);
         if (kkt->pe_ae_max < temp)
            kkt->pe_ae_max = temp, kkt->pe_ae_row = i;
         /* determine relative error */
         temp /= (1.0 + fabs(xR_i));
         if (kkt->pe_re_max < temp)
            kkt->pe_re_max = temp, kkt->pe_re_row = i;
      }
      xfree(ind);
      xfree(val);
      /* estimate the solution quality */
      if (kkt->pe_re_max <= 1e-9)
         kkt->pe_quality = 'H';
      else if (kkt->pe_re_max <= 1e-6)
         kkt->pe_quality = 'M';
      else if (kkt->pe_re_max <= 1e-3)
         kkt->pe_quality = 'L';
      else
         kkt->pe_quality = '?';
      /*--------------------------------------------------------------*/
      /* compute largest absolute and relative errors and corresponding
         variable indices for the condition (KKT.PB) */
      kkt->pb_ae_max = 0.0, kkt->pb_ae_ind = 0;
      kkt->pb_re_max = 0.0, kkt->pb_re_ind = 0;
      for (k = 1; k <= m+n; k++)
      {  /* determine x[k] */
         if (k <= m)
         {  i = k;
            type = lpx_get_row_type(lp, i);
            lb = lpx_get_row_lb(lp, i);
            ub = lpx_get_row_ub(lp, i);
            x_k = lpx_mip_row_val(lp, i);
         }
         else
         {  j = k - m;
            type = lpx_get_col_type(lp, j);
            lb = lpx_get_col_lb(lp, j);
            ub = lpx_get_col_ub(lp, j);
            x_k = lpx_mip_col_val(lp, j);
         }
         /* compute h[k] */
         h_k = 0.0;
         switch (type)
         {  case LPX_FR:
               break;
            case LPX_LO:
               if (x_k < lb) h_k = x_k - lb;
               break;
            case LPX_UP:
               if (x_k > ub) h_k = x_k - ub;
               break;
            case LPX_DB:
            case LPX_FX:
               if (x_k < lb) h_k = x_k - lb;
               if (x_k > ub) h_k = x_k - ub;
               break;
            default:
               xassert(type != type);
         }
         /* determine absolute error */
         temp = fabs(h_k);
         if (kkt->pb_ae_max < temp)
            kkt->pb_ae_max = temp, kkt->pb_ae_ind = k;
         /* determine relative error */
         temp /= (1.0 + fabs(x_k));
         if (kkt->pb_re_max < temp)
            kkt->pb_re_max = temp, kkt->pb_re_ind = k;
      }
      /* estimate the solution quality */
      if (kkt->pb_re_max <= 1e-9)
         kkt->pb_quality = 'H';
      else if (kkt->pb_re_max <= 1e-6)
         kkt->pb_quality = 'M';
      else if (kkt->pb_re_max <= 1e-3)
         kkt->pb_quality = 'L';
      else
         kkt->pb_quality = '?';
      return;
}
예제 #11
0
void ipp_load_orig(IPP *ipp, LPX *orig)
{     IPPROW **row;
      IPPCOL *col;
      int i, j, k, type, len, *ind;
      double lb, ub, *val;
      /* save some information about the original problem */
      ipp->orig_m = lpx_get_num_rows(orig);
      ipp->orig_n = lpx_get_num_cols(orig);
      ipp->orig_nnz = lpx_get_num_nz(orig);
      ipp->orig_dir = lpx_get_obj_dir(orig);
      /* allocate working arrays */
      row = xcalloc(1+ipp->orig_m, sizeof(IPPROW *));
      ind = xcalloc(1+ipp->orig_m, sizeof(int));
      val = xcalloc(1+ipp->orig_m, sizeof(double));
      /* copy rows of the original problem into the workspace */
      for (i = 1; i <= ipp->orig_m; i++)
      {  type = lpx_get_row_type(orig, i);
         if (type == LPX_FR || type == LPX_UP)
            lb = -DBL_MAX;
         else
            lb = lpx_get_row_lb(orig, i);
         if (type == LPX_FR || type == LPX_LO)
            ub = +DBL_MAX;
         else
            ub = lpx_get_row_ub(orig, i);
         row[i] = ipp_add_row(ipp, lb, ub);
      }
      /* copy columns of the original problem into the workspace; each
         column created in the workspace is assigned a reference number
         which is its ordinal number in the original problem */
      for (j = 1; j <= ipp->orig_n; j++)
      {  type = lpx_get_col_type(orig, j);
         if (type == LPX_FR || type == LPX_UP)
            lb = -DBL_MAX;
         else
            lb = lpx_get_col_lb(orig, j);
         if (type == LPX_FR || type == LPX_LO)
            ub = +DBL_MAX;
         else
            ub = lpx_get_col_ub(orig, j);
         col = ipp_add_col(ipp, lpx_get_col_kind(orig, j) == LPX_IV,
            lb, ub, lpx_get_obj_coef(orig, j));
         len = lpx_get_mat_col(orig, j, ind, val);
         for (k = 1; k <= len; k++)
            ipp_add_aij(ipp, row[ind[k]], col, val[k]);
      }
      /* copy the constant term of the original objective function */
      ipp->c0 = lpx_get_obj_coef(orig, 0);
      /* if the original problem is maximization, change the sign of
         the objective function, because the transformed problem to be
         processed by the presolver must be minimization */
      if (ipp->orig_dir == LPX_MAX)
      {  for (col = ipp->col_ptr; col != NULL; col = col->next)
            col->c = - col->c;
         ipp->c0 = - ipp->c0;
      }
      /* free working arrays */
      xfree(row);
      xfree(ind);
      xfree(val);
      return;
}
예제 #12
0
int lpx_prim_ratio_test(LPX *lp, int len, const int ind[],
      const double val[], int how, double tol)
{     int i, k, m, n, p, t, typx, tagx;
      double alfa_i, abs_alfa_i, big, eps, bbar_i, lb_i, ub_i, temp,
         teta;
      if (!lpx_is_b_avail(lp))
         xfault("lpx_prim_ratio_test: LP basis is not available\n");
      if (lpx_get_prim_stat(lp) != LPX_P_FEAS)
         xfault("lpx_prim_ratio_test: current basic solution is not pri"
            "mal feasible\n");
      if (!(how == +1 || how == -1))
         xfault("lpx_prim_ratio_test: how = %d; invalid parameter\n",
            how);
      m = lpx_get_num_rows(lp);
      n = lpx_get_num_cols(lp);
      /* compute the largest absolute value of the specified influence
         coefficients */
      big = 0.0;
      for (t = 1; t <= len; t++)
      {  temp = val[t];
         if (temp < 0.0) temp = - temp;
         if (big < temp) big = temp;
      }
      /* compute the absolute tolerance eps used to skip small entries
         of the column */
      if (!(0.0 < tol && tol < 1.0))
         xfault("lpx_prim_ratio_test: tol = %g; invalid tolerance\n",
            tol);
      eps = tol * (1.0 + big);
      /* initial settings */
      p = 0, teta = DBL_MAX, big = 0.0;
      /* walk through the entries of the specified column */
      for (t = 1; t <= len; t++)
      {  /* get the ordinal number of basic variable */
         k = ind[t];
         if (!(1 <= k && k <= m+n))
            xfault("lpx_prim_ratio_test: ind[%d] = %d; variable number "
               "out of range\n", t, k);
         if (k <= m)
            tagx = lpx_get_row_stat(lp, k);
         else
            tagx = lpx_get_col_stat(lp, k-m);
         if (tagx != LPX_BS)
            xfault("lpx_prim_ratio_test: ind[%d] = %d; non-basic variab"
               "le not allowed\n", t, k);
         /* determine index of the variable x[k] in the vector xB */
         if (k <= m)
            i = lpx_get_row_b_ind(lp, k);
         else
            i = lpx_get_col_b_ind(lp, k-m);
         xassert(1 <= i && i <= m);
         /* determine unscaled bounds and value of the basic variable
            xB[i] in the current basic solution */
         if (k <= m)
         {  typx = lpx_get_row_type(lp, k);
            lb_i = lpx_get_row_lb(lp, k);
            ub_i = lpx_get_row_ub(lp, k);
            bbar_i = lpx_get_row_prim(lp, k);
         }
         else
         {  typx = lpx_get_col_type(lp, k-m);
            lb_i = lpx_get_col_lb(lp, k-m);
            ub_i = lpx_get_col_ub(lp, k-m);
            bbar_i = lpx_get_col_prim(lp, k-m);
         }
         /* determine influence coefficient for the basic variable
            x[k] = xB[i] in the explicitly specified column and turn to
            the case of increasing the variable y in order to simplify
            the program logic */
         alfa_i = (how > 0 ? +val[t] : -val[t]);
         abs_alfa_i = (alfa_i > 0.0 ? +alfa_i : -alfa_i);
         /* analyze main cases */
         switch (typx)
         {  case LPX_FR:
               /* xB[i] is free variable */
               continue;
            case LPX_LO:
lo:            /* xB[i] has an lower bound */
               if (alfa_i > - eps) continue;
               temp = (lb_i - bbar_i) / alfa_i;
               break;
            case LPX_UP:
up:            /* xB[i] has an upper bound */
               if (alfa_i < + eps) continue;
               temp = (ub_i - bbar_i) / alfa_i;
               break;
            case LPX_DB:
               /* xB[i] has both lower and upper bounds */
               if (alfa_i < 0.0) goto lo; else goto up;
            case LPX_FX:
               /* xB[i] is fixed variable */
               if (abs_alfa_i < eps) continue;
               temp = 0.0;
               break;
            default:
               xassert(typx != typx);
         }
         /* if the value of the variable xB[i] violates its lower or
            upper bound (slightly, because the current basis is assumed
            to be primal feasible), temp is negative; we can think this
            happens due to round-off errors and the value is exactly on
            the bound; this allows replacing temp by zero */
         if (temp < 0.0) temp = 0.0;
         /* apply the minimal ratio test */
         if (teta > temp || teta == temp && big < abs_alfa_i)
            p = k, teta = temp, big = abs_alfa_i;
      }
      /* return the ordinal number of the chosen basic variable */
      return p;
}
예제 #13
0
int lpx_warm_up(LPX *lp)
{     int m, n, j, k, ret, type, stat, p_stat, d_stat;
      double lb, ub, prim, dual, tol_bnd, tol_dj, dir;
      double *row_prim, *row_dual, *col_prim, *col_dual, sum;
      m = lpx_get_num_rows(lp);
      n = lpx_get_num_cols(lp);
      /* reinvert the basis matrix, if necessary */
      if (lpx_is_b_avail(lp))
         ret = LPX_E_OK;
      else
      {  if (m == 0 || n == 0)
         {  ret = LPX_E_EMPTY;
            goto done;
         }
#if 0
         ret = lpx_invert(lp);
         switch (ret)
         {  case 0:
               ret = LPX_E_OK;
               break;
            case 1:
            case 2:
               ret = LPX_E_SING;
               goto done;
            case 3:
               ret = LPX_E_BADB;
               goto done;
            default:
               xassert(ret != ret);
         }
#else
         switch (glp_factorize(lp))
         {  case 0:
               ret = LPX_E_OK;
               break;
            case GLP_EBADB:
               ret = LPX_E_BADB;
               goto done;
            case GLP_ESING:
            case GLP_ECOND:
               ret = LPX_E_SING;
               goto done;
            default:
               xassert(lp != lp);
         }
#endif
      }
      /* allocate working arrays */
      row_prim = xcalloc(1+m, sizeof(double));
      row_dual = xcalloc(1+m, sizeof(double));
      col_prim = xcalloc(1+n, sizeof(double));
      col_dual = xcalloc(1+n, sizeof(double));
      /* compute primal basic solution components */
      lpx_eval_b_prim(lp, row_prim, col_prim);
      /* determine primal status of basic solution */
      tol_bnd = 3.0 * lpx_get_real_parm(lp, LPX_K_TOLBND);
      p_stat = LPX_P_FEAS;
      for (k = 1; k <= m+n; k++)
      {  if (k <= m)
         {  type = lpx_get_row_type(lp, k);
            lb = lpx_get_row_lb(lp, k);
            ub = lpx_get_row_ub(lp, k);
            prim = row_prim[k];
         }
         else
         {  type = lpx_get_col_type(lp, k-m);
            lb = lpx_get_col_lb(lp, k-m);
            ub = lpx_get_col_ub(lp, k-m);
            prim = col_prim[k-m];
         }
         if (type == LPX_LO || type == LPX_DB || type == LPX_FX)
         {  /* variable x[k] has lower bound */
            if (prim < lb - tol_bnd * (1.0 + fabs(lb)))
            {  p_stat = LPX_P_INFEAS;
               break;
            }
         }
         if (type == LPX_UP || type == LPX_DB || type == LPX_FX)
         {  /* variable x[k] has upper bound */
            if (prim > ub + tol_bnd * (1.0 + fabs(ub)))
            {  p_stat = LPX_P_INFEAS;
               break;
            }
         }
      }
      /* compute dual basic solution components */
      lpx_eval_b_dual(lp, row_dual, col_dual);
      /* determine dual status of basic solution */
      tol_dj = 3.0 * lpx_get_real_parm(lp, LPX_K_TOLDJ);
      dir = (lpx_get_obj_dir(lp) == LPX_MIN ? +1.0 : -1.0);
      d_stat = LPX_D_FEAS;
      for (k = 1; k <= m+n; k++)
      {  if (k <= m)
         {  stat = lpx_get_row_stat(lp, k);
            dual = row_dual[k];
         }
         else
         {  stat = lpx_get_col_stat(lp, k-m);
            dual = col_dual[k-m];
         }
         if (stat == LPX_BS || stat == LPX_NL || stat == LPX_NF)
         {  /* reduced cost of x[k] must be non-negative (minimization)
               or non-positive (maximization) */
            if (dir * dual < - tol_dj)
            {  d_stat = LPX_D_INFEAS;
               break;
            }
         }
         if (stat == LPX_BS || stat == LPX_NU || stat == LPX_NF)
         {  /* reduced cost of x[k] must be non-positive (minimization)
               or non-negative (maximization) */
            if (dir * dual > + tol_dj)
            {  d_stat = LPX_D_INFEAS;
               break;
            }
         }
      }
      /* store basic solution components */
      p_stat = p_stat - LPX_P_UNDEF + GLP_UNDEF;
      d_stat = d_stat - LPX_D_UNDEF + GLP_UNDEF;
      sum = lpx_get_obj_coef(lp, 0);
      for (j = 1; j <= n; j++)
         sum += lpx_get_obj_coef(lp, j) * col_prim[j];
      glp_put_solution(lp, 0, &p_stat, &d_stat, &sum,
         NULL, row_prim, row_dual, NULL, col_prim, col_dual);
      xassert(lpx_is_b_avail(lp));
      /* free working arrays */
      xfree(row_prim);
      xfree(row_dual);
      xfree(col_prim);
      xfree(col_dual);
done: /* return to the calling program */
      return ret;
}
예제 #14
0
static void gen_gomory_cut(LPX *prob, int maxlen)
{     int m = lpx_get_num_rows(prob);
      int n = lpx_get_num_cols(prob);
      int i, j, k, len, cut_j, *ind;
      double x, d, r, temp, cut_d, cut_r, *val, *work;
      insist(lpx_get_status(prob) == LPX_OPT);
      /* allocate working arrays */
      ind = ucalloc(1+n, sizeof(int));
      val = ucalloc(1+n, sizeof(double));
      work = ucalloc(1+m+n, sizeof(double));
      /* nothing is chosen so far */
      cut_j = 0; cut_d = 0.0; cut_r = 0.0;
      /* look through all structural variables */
      for (j = 1; j <= n; j++)
      {  /* if the variable is continuous, skip it */
         if (lpx_get_col_kind(prob, j) != LPX_IV) continue;
         /* if the variable is non-basic, skip it */
         if (lpx_get_col_stat(prob, j) != LPX_BS) continue;
         /* if the variable is fixed, skip it */
         if (lpx_get_col_type(prob, j) == LPX_FX) continue;
         /* obtain current primal value of the variable */
         x = lpx_get_col_prim(prob, j);
         /* if the value is close enough to nearest integer, skip the
            variable */
         if (fabs(x - floor(x + 0.5)) < 1e-4) continue;
         /* compute the row of the simplex table corresponding to the
            variable */
         len = lpx_eval_tab_row(prob, m+j, ind, val);
         len = lpx_remove_tiny(len, ind, NULL, val, 1e-10);
         /* generate Gomory's mixed integer cut:
            a[1]*x[1] + ... + a[n]*x[n] >= b */
         len = lpx_gomory_cut(prob, len, ind, val, work);
         if (len < 0) continue;
         insist(0 <= len && len <= n);
         len = lpx_remove_tiny(len, ind, NULL, val, 1e-10);
         if (fabs(val[0]) < 1e-10) val[0] = 0.0;
         /* if the cut is too long, skip it */
         if (len > maxlen) continue;
         /* if the cut contains coefficients with too large magnitude,
            do not use it to prevent numeric instability */
         for (k = 0; k <= len; k++) /* including rhs */
            if (fabs(val[k]) > 1e+6) break;
         if (k <= len) continue;
         /* at the current point the cut inequality is violated, i.e.
            the residual b - (a[1]*x[1] + ... + a[n]*x[n]) > 0; note
            that for Gomory's cut the residual is less than 1.0 */
         /* in order not to depend on the magnitude of coefficients we
            use scaled residual:
            r = [b - (a[1]*x[1] + ... + a[n]*x[n])] / max(1, |a[j]|) */
         temp = 1.0;
         for (k = 1; k <= len; k++)
            if (temp < fabs(val[k])) temp = fabs(val[k]);
         r = (val[0] - lpx_eval_row(prob, len, ind, val)) / temp;
         if (r < 1e-5) continue;
         /* estimate degradation (worsening) of the objective function
            by one dual simplex step if the cut row would be introduced
            in the problem */
         d = lpx_eval_degrad(prob, len, ind, val, LPX_LO, val[0]);
         /* ignore the sign of degradation */
         d = fabs(d);
         /* which cut should be used? there are two basic cases:
            1) if the degradation is non-zero, we are interested in a
               cut providing maximal degradation;
            2) if the degradation is zero (i.e. a non-basic variable
               which would enter the basis in the adjacent vertex has
               zero reduced cost), we are interested in a cut providing
               maximal scaled residual;
            in both cases it is desired that the cut length (the number
            of inequality coefficients) is possibly short */
         /* if both degradation and scaled residual are small, skip the
            cut */
         if (d < 0.001 && r < 0.001)
            continue;
         /* if there is no cut chosen, choose this cut */
         else if (cut_j == 0)
            ;
         /* if this cut provides stronger degradation and has shorter
            length, choose it */
         else if (cut_d != 0.0 && cut_d < d)
            ;
         /* if this cut provides larger scaled residual and has shorter
            length, choose it */
         else if (cut_d == 0.0 && cut_r < r)
            ;
         /* otherwise skip the cut */
         else
            continue;
         /* save attributes of the cut choosen */
         cut_j = j, cut_r = r, cut_d = d;
      }
      /* if a cut has been chosen, include it to the problem */
      if (cut_j != 0)
      {  j = cut_j;
         /* compute the row of the simplex table */
         len = lpx_eval_tab_row(prob, m+j, ind, val);
         len = lpx_remove_tiny(len, ind, NULL, val, 1e-10);
         /* generate the cut */
         len = lpx_gomory_cut(prob, len, ind, val, work);
         insist(0 <= len && len <= n);
         len = lpx_remove_tiny(len, ind, NULL, val, 1e-10);
         if (fabs(val[0]) < 1e-10) val[0] = 0.0;
         /* include the corresponding row in the problem */
         i = lpx_add_rows(prob, 1);
         lpx_set_row_bnds(prob, i, LPX_LO, val[0], 0.0);
         lpx_set_mat_row(prob, i, len, ind, val);
      }
      /* free working arrays */
      ufree(ind);
      ufree(val);
      ufree(work);
      return;
}
예제 #15
0
int lpx_intopt(LPX *_mip)
{     IPP *ipp = NULL;
      LPX *orig = _mip, *prob = NULL;
      int orig_m, orig_n, i, j, ret, i_stat;
      /* the problem must be of MIP class */
      if (lpx_get_class(orig) != LPX_MIP)
      {  print("lpx_intopt: problem is not of MIP class");
         ret = LPX_E_FAULT;
         goto done;
      }
      /* the problem must have at least one row and one column */
      orig_m = lpx_get_num_rows(orig);
      orig_n = lpx_get_num_cols(orig);
      if (!(orig_m > 0 && orig_n > 0))
      {  print("lpx_intopt: problem has no rows/columns");
         ret = LPX_E_FAULT;
         goto done;
      }
      /* check that each double-bounded row and column has bounds */
      for (i = 1; i <= orig_m; i++)
      {  if (lpx_get_row_type(orig, i) == LPX_DB)
         {  if (lpx_get_row_lb(orig, i) >= lpx_get_row_ub(orig, i))
            {  print("lpx_intopt: row %d has incorrect bounds", i);
               ret = LPX_E_FAULT;
               goto done;
            }
         }
      }
      for (j = 1; j <= orig_n; j++)
      {  if (lpx_get_col_type(orig, j) == LPX_DB)
         {  if (lpx_get_col_lb(orig, j) >= lpx_get_col_ub(orig, j))
            {  print("lpx_intopt: column %d has incorrect bounds", j);
               ret = LPX_E_FAULT;
               goto done;
            }
         }
      }
      /* bounds of all integer variables must be integral */
      for (j = 1; j <= orig_n; j++)
      {  int type;
         double lb, ub;
         if (lpx_get_col_kind(orig, j) != LPX_IV) continue;
         type = lpx_get_col_type(orig, j);
         if (type == LPX_LO || type == LPX_DB || type == LPX_FX)
         {  lb = lpx_get_col_lb(orig, j);
            if (lb != floor(lb))
            {  print("lpx_intopt: integer column %d has non-integer low"
                  "er 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(orig, j);
            if (ub != floor(ub))
            {  print("lpx_intopt: integer column %d has non-integer upp"
                  "er bound %g", j, ub);
               ret = LPX_E_FAULT;
               goto done;
            }
         }
      }
      /* reset the status of MIP solution */
      lpx_put_mip_soln(orig, LPX_I_UNDEF, NULL, NULL);
      /* create MIP presolver workspace */
      ipp = ipp_create_wksp();
      /* load the original problem into the presolver workspace */
      ipp_load_orig(ipp, orig);
      /* perform basic MIP presolve analysis */
      switch (ipp_basic_tech(ipp))
      {  case 0:
            /* no infeasibility is detected */
            break;
         case 1:
nopfs:      /* primal infeasibility is detected */
            print("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION");
            ret = LPX_E_NOPFS;
            goto done;
         case 2:
            /* dual infeasibility is detected */
nodfs:      print("LP RELAXATION HAS NO DUAL FEASIBLE SOLUTION");
            ret = LPX_E_NODFS;
            goto done;
         default:
            insist(ipp != ipp);
      }
      /* reduce column bounds */
      switch (ipp_reduce_bnds(ipp))
      {  case 0:  break;
         case 1:  goto nopfs;
         default: insist(ipp != ipp);
      }
      /* perform basic MIP presolve analysis */
      switch (ipp_basic_tech(ipp))
      {  case 0:  break;
         case 1:  goto nopfs;
         case 2:  goto nodfs;
         default: insist(ipp != ipp);
      }
      /* replace general integer variables by sum of binary variables,
         if required */
      if (lpx_get_int_parm(orig, LPX_K_BINARIZE))
         ipp_binarize(ipp);
      /* perform coefficient reduction */
      ipp_reduction(ipp);
      /* if the resultant problem is empty, it has an empty solution,
         which is optimal */
      if (ipp->row_ptr == NULL || ipp->col_ptr == NULL)
      {  insist(ipp->row_ptr == NULL);
         insist(ipp->col_ptr == NULL);
         print("Objective value = %.10g",
            ipp->orig_dir == LPX_MIN ? +ipp->c0 : -ipp->c0);
         print("INTEGER OPTIMAL SOLUTION FOUND BY MIP PRESOLVER");
         /* allocate recovered solution segment */
         ipp->col_stat = ucalloc(1+ipp->ncols, sizeof(int));
         ipp->col_mipx = ucalloc(1+ipp->ncols, sizeof(double));
         for (j = 1; j <= ipp->ncols; j++) ipp->col_stat[j] = 0;
         /* perform MIP postsolve processing */
         ipp_postsolve(ipp);
         /* unload recovered MIP solution and store it in the original
            problem object */
         ipp_unload_sol(ipp, orig, LPX_I_OPT);
         ret = LPX_E_OK;
         goto done;
      }
      /* build resultant MIP problem object */
      prob = ipp_build_prob(ipp);
      /* display some statistics */
      {  int m = lpx_get_num_rows(prob);
         int n = lpx_get_num_cols(prob);
         int nnz = lpx_get_num_nz(prob);
         int ni = lpx_get_num_int(prob);
         int nb = lpx_get_num_bin(prob);
         char s[50];
         print("lpx_intopt: presolved MIP has %d row%s, %d column%s, %d"
            " non-zero%s", m, m == 1 ? "" : "s", n, n == 1 ? "" : "s",
            nnz, nnz == 1 ? "" : "s");
         if (nb == 0)
            strcpy(s, "none of");
         else if (ni == 1 && nb == 1)
            strcpy(s, "");
         else if (nb == 1)
            strcpy(s, "one of");
         else if (nb == ni)
            strcpy(s, "all of");
         else
            sprintf(s, "%d of", nb);
         print("lpx_intopt: %d integer column%s, %s which %s binary",
            ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are");
      }
      /* inherit some control parameters and statistics */
      lpx_set_int_parm(prob, LPX_K_PRICE, lpx_get_int_parm(orig,
         LPX_K_PRICE));
      lpx_set_real_parm(prob, LPX_K_RELAX, lpx_get_real_parm(orig,
         LPX_K_RELAX));
      lpx_set_real_parm(prob, LPX_K_TOLBND, lpx_get_real_parm(orig,
         LPX_K_TOLBND));
      lpx_set_real_parm(prob, LPX_K_TOLDJ, lpx_get_real_parm(orig,
         LPX_K_TOLDJ));
      lpx_set_real_parm(prob, LPX_K_TOLPIV, lpx_get_real_parm(orig,
         LPX_K_TOLPIV));
      lpx_set_int_parm(prob, LPX_K_ITLIM, lpx_get_int_parm(orig,
         LPX_K_ITLIM));
      lpx_set_int_parm(prob, LPX_K_ITCNT, lpx_get_int_parm(orig,
         LPX_K_ITCNT));
      lpx_set_real_parm(prob, LPX_K_TMLIM, lpx_get_real_parm(orig,
         LPX_K_TMLIM));
      lpx_set_int_parm(prob, LPX_K_BRANCH, lpx_get_int_parm(orig,
         LPX_K_BRANCH));
      lpx_set_int_parm(prob, LPX_K_BTRACK, lpx_get_int_parm(orig,
         LPX_K_BTRACK));
      lpx_set_real_parm(prob, LPX_K_TOLINT, lpx_get_real_parm(orig,
         LPX_K_TOLINT));
      lpx_set_real_parm(prob, LPX_K_TOLOBJ, lpx_get_real_parm(orig,
         LPX_K_TOLOBJ));
      /* build an advanced initial basis */
      lpx_adv_basis(prob);
      /* solve LP relaxation */
      print("Solving LP relaxation...");
      switch (lpx_simplex(prob))
      {  case LPX_E_OK:
            break;
         case LPX_E_ITLIM:
            ret = LPX_E_ITLIM;
            goto done;
         case LPX_E_TMLIM:
            ret = LPX_E_TMLIM;
            goto done;
         default:
            print("lpx_intopt: cannot solve LP relaxation");
            ret = LPX_E_SING;
            goto done;
      }
      /* analyze status of the basic solution */
      switch (lpx_get_status(prob))
      {  case LPX_OPT:
            break;
         case LPX_NOFEAS:
            ret = LPX_E_NOPFS;
            goto done;
         case LPX_UNBND:
            ret = LPX_E_NODFS;
            goto done;
         default:
            insist(prob != prob);
      }
      /* generate cutting planes, if necessary */
      if (lpx_get_int_parm(orig, LPX_K_USECUTS))
      {  ret =  generate_cuts(prob);
         if (ret != LPX_E_OK) goto done;
      }
      /* call the branch-and-bound solver */
      ret = lpx_integer(prob);
      /* determine status of MIP solution */
      i_stat = lpx_mip_status(prob);
      if (i_stat == LPX_I_OPT || i_stat == LPX_I_FEAS)
      {  /* load MIP solution of the resultant problem into presolver
            workspace */
         ipp_load_sol(ipp, prob);
         /* perform MIP postsolve processing */
         ipp_postsolve(ipp);
         /* unload recovered MIP solution and store it in the original
            problem object */
         ipp_unload_sol(ipp, orig, i_stat);
      }
      else
      {  /* just set the status of MIP solution */
         lpx_put_mip_soln(orig, i_stat, NULL, NULL);
      }
done: /* copy back statistics about spent resources */
      if (prob != NULL)
      {  lpx_set_int_parm(orig, LPX_K_ITLIM, lpx_get_int_parm(prob,
            LPX_K_ITLIM));
         lpx_set_int_parm(orig, LPX_K_ITCNT, lpx_get_int_parm(prob,
            LPX_K_ITCNT));
         lpx_set_real_parm(orig, LPX_K_TMLIM, lpx_get_real_parm(prob,
            LPX_K_TMLIM));
      }
      /* delete the resultant problem object */
      if (prob != NULL) lpx_delete_prob(prob);
      /* delete MIP presolver workspace */
      if (ipp != NULL) ipp_delete_wksp(ipp);
      return ret;
}