Esempio n. 1
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;
}
Esempio n. 2
0
void lpx_check_kkt(LPX *lp, int scaled, LPXKKT *kkt)
{     int m = lpx_get_num_rows(lp);
      int n = lpx_get_num_cols(lp);
#if 0 /* 21/XII-2003 */
      int *typx = lp->typx;
      double *lb = lp->lb;
      double *ub = lp->ub;
      double *rs = lp->rs;
#else
      int typx, tagx;
      double lb, ub;
#endif
      int dir = lpx_get_obj_dir(lp);
#if 0 /* 21/XII-2003 */
      double *coef = lp->coef;
#endif
#if 0 /* 22/XII-2003 */
      int *A_ptr = lp->A->ptr;
      int *A_len = lp->A->len;
      int *A_ndx = lp->A->ndx;
      double *A_val = lp->A->val;
#endif
      int *A_ndx;
      double *A_val;
#if 0 /* 21/XII-2003 */
      int *tagx = lp->tagx;
      int *posx = lp->posx;
      int *indx = lp->indx;
      double *bbar = lp->bbar;
      double *cbar = lp->cbar;
#endif
      int beg, end, i, j, k, t;
      double cR_i, cS_j, c_k, xR_i, xS_j, x_k, dR_i, dS_j, d_k;
      double g_i, h_k, u_j, v_k, temp, rii, sjj;
      if (lpx_get_prim_stat(lp) == LPX_P_UNDEF)
         xfault("lpx_check_kkt: primal basic solution is undefined\n");
      if (lpx_get_dual_stat(lp) == LPX_D_UNDEF)
         xfault("lpx_check_kkt: dual basic solution is undefined\n");
      /*--------------------------------------------------------------*/
      /* 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;
      A_ndx = xcalloc(1+n, sizeof(int));
      A_val = xcalloc(1+n, sizeof(double));
      for (i = 1; i <= m; i++)
      {  /* determine xR[i] */
#if 0 /* 21/XII-2003 */
         if (tagx[i] == LPX_BS)
            xR_i = bbar[posx[i]];
         else
            xR_i = spx_eval_xn_j(lp, posx[i] - m);
#else
         lpx_get_row_info(lp, i, NULL, &xR_i, NULL);
         xR_i *= lpx_get_rii(lp, i);
#endif
         /* g[i] := xR[i] */
         g_i = xR_i;
         /* g[i] := g[i] - (i-th row of A) * xS */
         beg = 1;
         end = lpx_get_mat_row(lp, i, A_ndx, A_val);
         for (t = beg; t <= end; t++)
         {  j = m + A_ndx[t]; /* a[i,j] != 0 */
            /* determine xS[j] */
#if 0 /* 21/XII-2003 */
            if (tagx[j] == LPX_BS)
               xS_j = bbar[posx[j]];
            else
               xS_j = spx_eval_xn_j(lp, posx[j] - m);
#else
            lpx_get_col_info(lp, j-m, NULL, &xS_j, NULL);
            xS_j /= lpx_get_sjj(lp, j-m);
#endif
            /* g[i] := g[i] - a[i,j] * xS[j] */
            rii = lpx_get_rii(lp, i);
            sjj = lpx_get_sjj(lp, j-m);
            g_i -= (rii * A_val[t] * sjj) * xS_j;
         }
         /* unscale xR[i] and g[i] (if required) */
         if (!scaled)
         {  rii = lpx_get_rii(lp, i);
            xR_i /= rii, g_i /= rii;
         }
         /* 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(A_ndx);
      xfree(A_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)
         {  lpx_get_row_bnds(lp, k, &typx, &lb, &ub);
            rii = lpx_get_rii(lp, k);
            lb *= rii;
            ub *= rii;
            lpx_get_row_info(lp, k, &tagx, &x_k, NULL);
            x_k *= rii;
         }
         else
         {  lpx_get_col_bnds(lp, k-m, &typx, &lb, &ub);
            sjj = lpx_get_sjj(lp, k-m);
            lb /= sjj;
            ub /= sjj;
            lpx_get_col_info(lp, k-m, &tagx, &x_k, NULL);
            x_k /= sjj;
         }
         /* skip non-basic variable */
         if (tagx != LPX_BS) continue;
         /* compute h[k] */
         h_k = 0.0;
         switch (typx)
         {  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(typx != typx);
         }
         /* unscale x[k] and h[k] (if required) */
         if (!scaled)
         {  if (k <= m)
            {  rii = lpx_get_rii(lp, k);
               x_k /= rii, h_k /= rii;
            }
            else
            {  sjj = lpx_get_sjj(lp, k-m);
               x_k *= sjj, h_k *= sjj;
            }
         }
         /* 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 = '?';
      /*--------------------------------------------------------------*/
      /* compute largest absolute and relative errors and corresponding
         column indices for the condition (KKT.DE) */
      kkt->de_ae_max = 0.0, kkt->de_ae_col = 0;
      kkt->de_re_max = 0.0, kkt->de_re_col = 0;
      A_ndx = xcalloc(1+m, sizeof(int));
      A_val = xcalloc(1+m, sizeof(double));
      for (j = m+1; j <= m+n; j++)
      {  /* determine cS[j] */
#if 0 /* 21/XII-2003 */
         cS_j = coef[j];
#else
         sjj = lpx_get_sjj(lp, j-m);
         cS_j = lpx_get_obj_coef(lp, j-m) * sjj;
#endif
         /* determine dS[j] */
#if 0 /* 21/XII-2003 */
         if (tagx[j] == LPX_BS)
            dS_j = 0.0;
         else
            dS_j = cbar[posx[j] - m];
#else
         lpx_get_col_info(lp, j-m, NULL, NULL, &dS_j);
         dS_j *= sjj;
#endif
         /* u[j] := dS[j] - cS[j] */
         u_j = dS_j - cS_j;
         /* u[j] := u[j] + (j-th column of A) * (dR - cR) */
         beg = 1;
         end = lpx_get_mat_col(lp, j-m, A_ndx, A_val);
         for (t = beg; t <= end; t++)
         {  i = A_ndx[t]; /* a[i,j] != 0 */
            /* determine cR[i] */
#if 0 /* 21/XII-2003 */
            cR_i = coef[i];
#else
            cR_i = 0.0;
#endif
            /* determine dR[i] */
#if 0 /* 21/XII-2003 */
            if (tagx[i] == LPX_BS)
               dR_i = 0.0;
            else
               dR_i = cbar[posx[i] - m];
#else
            lpx_get_row_info(lp, i, NULL, NULL, &dR_i);
            rii = lpx_get_rii(lp, i);
            dR_i /= rii;
#endif
            /* u[j] := u[j] + a[i,j] * (dR[i] - cR[i]) */
            rii = lpx_get_rii(lp, i);
            sjj = lpx_get_sjj(lp, j-m);
            u_j += (rii * A_val[t] * sjj) * (dR_i - cR_i);
         }
         /* unscale cS[j], dS[j], and u[j] (if required) */
         if (!scaled)
         {  sjj = lpx_get_sjj(lp, j-m);
            cS_j /= sjj, dS_j /= sjj, u_j /= sjj;
         }
         /* determine absolute error */
         temp = fabs(u_j);
         if (kkt->de_ae_max < temp)
            kkt->de_ae_max = temp, kkt->de_ae_col = j - m;
         /* determine relative error */
         temp /= (1.0 + fabs(dS_j - cS_j));
         if (kkt->de_re_max < temp)
            kkt->de_re_max = temp, kkt->de_re_col = j - m;
      }
      xfree(A_ndx);
      xfree(A_val);
      /* estimate the solution quality */
      if (kkt->de_re_max <= 1e-9)
         kkt->de_quality = 'H';
      else if (kkt->de_re_max <= 1e-6)
         kkt->de_quality = 'M';
      else if (kkt->de_re_max <= 1e-3)
         kkt->de_quality = 'L';
      else
         kkt->de_quality = '?';
      /*--------------------------------------------------------------*/
      /* compute largest absolute and relative errors and corresponding
         variable indices for the condition (KKT.DB) */
      kkt->db_ae_max = 0.0, kkt->db_ae_ind = 0;
      kkt->db_re_max = 0.0, kkt->db_re_ind = 0;
      for (k = 1; k <= m+n; k++)
      {  /* determine c[k] */
#if 0 /* 21/XII-2003 */
         c_k = coef[k];
#else
         if (k <= m)
            c_k = 0.0;
         else
         {  sjj = lpx_get_sjj(lp, k-m);
            c_k = lpx_get_obj_coef(lp, k-m) / sjj;
         }
#endif
         /* determine d[k] */
#if 0 /* 21/XII-2003 */
         d_k = cbar[j-m];
#else
         if (k <= m)
         {  lpx_get_row_info(lp, k, &tagx, NULL, &d_k);
            rii = lpx_get_rii(lp, k);
            d_k /= rii;
         }
         else
         {  lpx_get_col_info(lp, k-m, &tagx, NULL, &d_k);
            sjj = lpx_get_sjj(lp, k-m);
            d_k *= sjj;
         }
#endif
         /* skip basic variable */
         if (tagx == LPX_BS) continue;
         /* compute v[k] */
         v_k = 0.0;
         switch (tagx)
         {  case LPX_NL:
               switch (dir)
               {  case LPX_MIN:
                     if (d_k < 0.0) v_k = d_k;
                     break;
                  case LPX_MAX:
                     if (d_k > 0.0) v_k = d_k;
                     break;
                  default:
                     xassert(dir != dir);
               }
               break;
            case LPX_NU:
               switch (dir)
               {  case LPX_MIN:
                     if (d_k > 0.0) v_k = d_k;
                     break;
                  case LPX_MAX:
                     if (d_k < 0.0) v_k = d_k;
                     break;
                  default:
                     xassert(dir != dir);
               }
               break;
            case LPX_NF:
               v_k = d_k;
               break;
            case LPX_NS:
               break;
            default:
               xassert(tagx != tagx);
         }
         /* unscale c[k], d[k], and v[k] (if required) */
         if (!scaled)
         {  if (k <= m)
            {  rii = lpx_get_rii(lp, k);
               c_k *= rii, d_k *= rii, v_k *= rii;
            }
            else
            {  sjj = lpx_get_sjj(lp, k-m);
               c_k /= sjj, d_k /= sjj, v_k /= sjj;
            }
         }
         /* determine absolute error */
         temp = fabs(v_k);
         if (kkt->db_ae_max < temp)
            kkt->db_ae_max = temp, kkt->db_ae_ind = k;
         /* determine relative error */
         temp /= (1.0 + fabs(d_k - c_k));
         if (kkt->db_re_max < temp)
            kkt->db_re_max = temp, kkt->db_re_ind = k;
      }
      /* estimate the solution quality */
      if (kkt->db_re_max <= 1e-9)
         kkt->db_quality = 'H';
      else if (kkt->db_re_max <= 1e-6)
         kkt->db_quality = 'M';
      else if (kkt->db_re_max <= 1e-3)
         kkt->db_quality = 'L';
      else
         kkt->db_quality = '?';
      /* complementary slackness is always satisfied by definition for
         any basic solution, so not checked */
      kkt->cs_ae_max = 0.0, kkt->cs_ae_ind = 0;
      kkt->cs_re_max = 0.0, kkt->cs_re_ind = 0;
      kkt->cs_quality = 'H';
      return;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}