コード例 #1
0
ファイル: glplpp1.c プロジェクト: ecotox/pacfm
void lpp_load_sol(LPP *lpp, LPX *prob)
{     int i, j, ref, stat;
      double prim, dual;
      insist(lpp->m == lpx_get_num_rows(prob));
      insist(lpp->n == lpx_get_num_cols(prob));
      insist(lpp->orig_dir == lpx_get_obj_dir(prob));
      insist(lpx_get_status(prob) != LPX_UNDEF);
      for (i = 1; i <= lpp->m; i++)
      {  lpx_get_row_info(prob, i, &stat, &prim, &dual);
         ref = lpp->row_ref[i];
         insist(1 <= ref && ref <= lpp->nrows);
         insist(lpp->row_stat[ref] == 0);
         lpp->row_stat[ref] = stat;
         lpp->row_prim[ref] = prim;
         lpp->row_dual[ref] =
            (lpp->orig_dir == LPX_MIN ? + dual : - dual);
      }
      for (j = 1; j <= lpp->n; j++)
      {  lpx_get_col_info(prob, j, &stat, &prim, &dual);
         ref = lpp->col_ref[j];
         insist(1 <= ref && ref <= lpp->ncols);
         insist(lpp->col_stat[ref] == 0);
         lpp->col_stat[ref] = stat;
         lpp->col_prim[ref] = prim;
         lpp->col_dual[ref] =
            (lpp->orig_dir == LPX_MIN ? + dual : - dual);
      }
      ufree(lpp->row_ref), lpp->row_ref = NULL;
      ufree(lpp->col_ref), lpp->col_ref = NULL;
      return;
}
コード例 #2
0
ファイル: lpglpk40.c プロジェクト: ecotox/pacfm
int CClp_opt(CClp *lp, int method)
{     /* CALLS designated LP solution method. */
      int stat, ret;
      if (MSGLEV >= 1)
      {  int m = lpx_get_num_rows(lp->lp);
         int n = lpx_get_num_cols(lp->lp);
         int nz = lpx_get_num_nz(lp->lp);
         print("CClp_opt: %-11s m = %d; n = %d; nz = %d",
            method == CClp_METHOD_DUAL ? "(dual)" : "(primal)",
            m, n, nz);
      }
      lpx_set_int_parm(lp->lp, LPX_K_DUAL, method == CClp_METHOD_DUAL);
      switch (MSGLEV)
      {  case 0:
            lpx_set_int_parm(lp->lp, LPX_K_MSGLEV, 0);
            lpx_set_int_parm(lp->lp, LPX_K_OUTFRQ, 1000000);
            lpx_set_real_parm(lp->lp, LPX_K_OUTDLY, 1e6);
            break;
         case 1:
            lpx_set_int_parm(lp->lp, LPX_K_MSGLEV, 2);
            lpx_set_int_parm(lp->lp, LPX_K_OUTFRQ, 200);
            lpx_set_real_parm(lp->lp, LPX_K_OUTDLY, 5.0);
            break;
         case 2:
            lpx_set_int_parm(lp->lp, LPX_K_MSGLEV, 3);
            lpx_set_int_parm(lp->lp, LPX_K_OUTFRQ, 200);
            lpx_set_real_parm(lp->lp, LPX_K_OUTDLY, 0.0);
            break;
         default:
            insist(MSGLEV != MSGLEV);
      }
      ret = lpx_simplex(lp->lp);
      if (ret == LPX_E_FAULT)
      {  if (MSGLEV >= 1) print("CClp_opt: restarting from advanced bas"
            "is...");
         lpx_adv_basis(lp->lp);
         ret = lpx_simplex(lp->lp);
      }
      if (ret != LPX_E_OK)
      {  print("CClp_opt: lpx_simplex failed; return code = %d", ret);
         ret = 1;
         goto done;
      }
      stat = lpx_get_status(lp->lp);
      if (stat == LPX_OPT)
         ret = 0;
      else if (stat == LPX_NOFEAS)
         ret = 2;
      else
      {  print("CClp_opt: optimization status = %d", stat);
         ret = 1;
      }
done: return ret;
}
コード例 #3
0
int lpx_print_prob(LPX *lp, const char *fname)
{     XFILE *fp;
      int m, n, mip, i, j, len, t, type, *ndx;
      double coef, lb, ub, *val;
      char *str, name[255+1];
      xprintf("lpx_write_prob: writing problem data to `%s'...\n",
         fname);
      fp = xfopen(fname, "w");
      if (fp == NULL)
      {  xprintf("lpx_write_prob: unable to create `%s' - %s\n",
            fname, strerror(errno));
         goto fail;
      }
      m = lpx_get_num_rows(lp);
      n = lpx_get_num_cols(lp);
      mip = (lpx_get_class(lp) == LPX_MIP);
      str = (void *)lpx_get_prob_name(lp);
      xfprintf(fp, "Problem:    %s\n", str == NULL ? "(unnamed)" : str);
      xfprintf(fp, "Class:      %s\n", !mip ? "LP" : "MIP");
      xfprintf(fp, "Rows:       %d\n", m);
      if (!mip)
         xfprintf(fp, "Columns:    %d\n", n);
      else
         xfprintf(fp, "Columns:    %d (%d integer, %d binary)\n",
            n, lpx_get_num_int(lp), lpx_get_num_bin(lp));
      xfprintf(fp, "Non-zeros:  %d\n", lpx_get_num_nz(lp));
      xfprintf(fp, "\n");
      xfprintf(fp, "*** OBJECTIVE FUNCTION ***\n");
      xfprintf(fp, "\n");
      switch (lpx_get_obj_dir(lp))
      {  case LPX_MIN:
            xfprintf(fp, "Minimize:");
            break;
         case LPX_MAX:
            xfprintf(fp, "Maximize:");
            break;
         default:
            xassert(lp != lp);
      }
      str = (void *)lpx_get_obj_name(lp);
      xfprintf(fp, " %s\n", str == NULL ? "(unnamed)" : str);
      coef = lpx_get_obj_coef(lp, 0);
      if (coef != 0.0)
         xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, coef,
            "(constant term)");
      for (i = 1; i <= m; i++)
#if 0
      {  coef = lpx_get_row_coef(lp, i);
#else
      {  coef = 0.0;
#endif
         if (coef != 0.0)
            xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, coef,
               row_name(lp, i, name));
      }
      for (j = 1; j <= n; j++)
      {  coef = lpx_get_obj_coef(lp, j);
         if (coef != 0.0)
            xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, coef,
               col_name(lp, j, name));
      }
      xfprintf(fp, "\n");
      xfprintf(fp, "*** ROWS (CONSTRAINTS) ***\n");
      ndx = xcalloc(1+n, sizeof(int));
      val = xcalloc(1+n, sizeof(double));
      for (i = 1; i <= m; i++)
      {  xfprintf(fp, "\n");
         xfprintf(fp, "Row %d: %s", i, row_name(lp, i, name));
         lpx_get_row_bnds(lp, i, &type, &lb, &ub);
         switch (type)
         {  case LPX_FR:
               xfprintf(fp, " free");
               break;
            case LPX_LO:
               xfprintf(fp, " >= %.*g", DBL_DIG, lb);
               break;
            case LPX_UP:
               xfprintf(fp, " <= %.*g", DBL_DIG, ub);
               break;
            case LPX_DB:
               xfprintf(fp, " >= %.*g <= %.*g", DBL_DIG, lb, DBL_DIG,
                  ub);
               break;
            case LPX_FX:
               xfprintf(fp, " = %.*g", DBL_DIG, lb);
               break;
            default:
               xassert(type != type);
         }
         xfprintf(fp, "\n");
#if 0
         coef = lpx_get_row_coef(lp, i);
#else
         coef = 0.0;
#endif
         if (coef != 0.0)
            xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, coef,
               "(objective)");
         len = lpx_get_mat_row(lp, i, ndx, val);
         for (t = 1; t <= len; t++)
            xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, val[t],
               col_name(lp, ndx[t], name));
      }
      xfree(ndx);
      xfree(val);
      xfprintf(fp, "\n");
      xfprintf(fp, "*** COLUMNS (VARIABLES) ***\n");
      ndx = xcalloc(1+m, sizeof(int));
      val = xcalloc(1+m, sizeof(double));
      for (j = 1; j <= n; j++)
      {  xfprintf(fp, "\n");
         xfprintf(fp, "Col %d: %s", j, col_name(lp, j, name));
         if (mip)
         {  switch (lpx_get_col_kind(lp, j))
            {  case LPX_CV:
                  break;
               case LPX_IV:
                  xfprintf(fp, " integer");
                  break;
               default:
                  xassert(lp != lp);
            }
         }
         lpx_get_col_bnds(lp, j, &type, &lb, &ub);
         switch (type)
         {  case LPX_FR:
               xfprintf(fp, " free");
               break;
            case LPX_LO:
               xfprintf(fp, " >= %.*g", DBL_DIG, lb);
               break;
            case LPX_UP:
               xfprintf(fp, " <= %.*g", DBL_DIG, ub);
               break;
            case LPX_DB:
               xfprintf(fp, " >= %.*g <= %.*g", DBL_DIG, lb, DBL_DIG,
                  ub);
               break;
            case LPX_FX:
               xfprintf(fp, " = %.*g", DBL_DIG, lb);
               break;
            default:
               xassert(type != type);
         }
         xfprintf(fp, "\n");
         coef = lpx_get_obj_coef(lp, j);
         if (coef != 0.0)
            xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, coef,
               "(objective)");
         len = lpx_get_mat_col(lp, j, ndx, val);
         for (t = 1; t <= len; t++)
            xfprintf(fp, "%*.*g %s\n", DBL_DIG+7, DBL_DIG, val[t],
               row_name(lp, ndx[t], name));
      }
      xfree(ndx);
      xfree(val);
      xfprintf(fp, "\n");
      xfprintf(fp, "End of output\n");
      xfflush(fp);
      if (xferror(fp))
      {  xprintf("lpx_write_prob: write error on `%s' - %s\n", fname,
            strerror(errno));
         goto fail;
      }
      xfclose(fp);
      return 0;
fail: if (fp != NULL) xfclose(fp);
      return 1;
}

#undef row_name
#undef col_name

/*----------------------------------------------------------------------
-- lpx_print_sol - write LP problem solution in printable format.
--
-- *Synopsis*
--
-- #include "glplpx.h"
-- int lpx_print_sol(LPX *lp, char *fname);
--
-- *Description*
--
-- The routine lpx_print_sol writes the current basic solution of an LP
-- problem, which is specified by the pointer lp, to a text file, whose
-- name is the character string fname, in printable format.
--
-- Information reported by the routine lpx_print_sol is intended mainly
-- for visual analysis.
--
-- *Returns*
--
-- If the operation was successful, the routine returns zero. Otherwise
-- the routine prints an error message and returns non-zero. */

int lpx_print_sol(LPX *lp, const char *fname)
{     XFILE *fp;
      int what, round;
      xprintf(
         "lpx_print_sol: writing LP problem solution to `%s'...\n",
         fname);
      fp = xfopen(fname, "w");
      if (fp == NULL)
      {  xprintf("lpx_print_sol: can't create `%s' - %s\n", fname,
            strerror(errno));
         goto fail;
      }
      /* problem name */
      {  const char *name;
         name = lpx_get_prob_name(lp);
         if (name == NULL) name = "";
         xfprintf(fp, "%-12s%s\n", "Problem:", name);
      }
      /* number of rows (auxiliary variables) */
      {  int nr;
         nr = lpx_get_num_rows(lp);
         xfprintf(fp, "%-12s%d\n", "Rows:", nr);
      }
      /* number of columns (structural variables) */
      {  int nc;
         nc = lpx_get_num_cols(lp);
         xfprintf(fp, "%-12s%d\n", "Columns:", nc);
      }
      /* number of non-zeros (constraint coefficients) */
      {  int nz;
         nz = lpx_get_num_nz(lp);
         xfprintf(fp, "%-12s%d\n", "Non-zeros:", nz);
      }
      /* solution status */
      {  int status;
         status = lpx_get_status(lp);
         xfprintf(fp, "%-12s%s\n", "Status:",
            status == LPX_OPT    ? "OPTIMAL" :
            status == LPX_FEAS   ? "FEASIBLE" :
            status == LPX_INFEAS ? "INFEASIBLE (INTERMEDIATE)" :
            status == LPX_NOFEAS ? "INFEASIBLE (FINAL)" :
            status == LPX_UNBND  ? "UNBOUNDED" :
            status == LPX_UNDEF  ? "UNDEFINED" : "???");
      }
      /* objective function */
      {  char *name;
         int dir;
         double obj;
         name = (void *)lpx_get_obj_name(lp);
         dir = lpx_get_obj_dir(lp);
         obj = lpx_get_obj_val(lp);
         xfprintf(fp, "%-12s%s%s%.10g %s\n", "Objective:",
            name == NULL ? "" : name,
            name == NULL ? "" : " = ", obj,
            dir == LPX_MIN ? "(MINimum)" :
            dir == LPX_MAX ? "(MAXimum)" : "(" "???" ")");
      }
      /* main sheet */
      for (what = 1; what <= 2; what++)
      {  int mn, ij;
         xfprintf(fp, "\n");
         xfprintf(fp, "   No. %-12s St   Activity     Lower bound   Upp"
            "er bound    Marginal\n",
            what == 1 ? "  Row name" : "Column name");
         xfprintf(fp, "------ ------------ -- ------------- -----------"
            "-- ------------- -------------\n");
         mn = (what == 1 ? lpx_get_num_rows(lp) : lpx_get_num_cols(lp));
         for (ij = 1; ij <= mn; ij++)
         {  const char *name;
            int typx, tagx;
            double lb, ub, vx, dx;
            if (what == 1)
            {  name = lpx_get_row_name(lp, ij);
               if (name == NULL) name = "";
               lpx_get_row_bnds(lp, ij, &typx, &lb, &ub);
               round = lpx_get_int_parm(lp, LPX_K_ROUND);
               lpx_set_int_parm(lp, LPX_K_ROUND, 1);
               lpx_get_row_info(lp, ij, &tagx, &vx, &dx);
               lpx_set_int_parm(lp, LPX_K_ROUND, round);
            }
            else
            {  name = lpx_get_col_name(lp, ij);
               if (name == NULL) name = "";
               lpx_get_col_bnds(lp, ij, &typx, &lb, &ub);
               round = lpx_get_int_parm(lp, LPX_K_ROUND);
               lpx_set_int_parm(lp, LPX_K_ROUND, 1);
               lpx_get_col_info(lp, ij, &tagx, &vx, &dx);
               lpx_set_int_parm(lp, LPX_K_ROUND, round);
            }
            /* row/column ordinal number */
            xfprintf(fp, "%6d ", ij);
            /* row column/name */
            if (strlen(name) <= 12)
               xfprintf(fp, "%-12s ", name);
            else
               xfprintf(fp, "%s\n%20s", name, "");
            /* row/column status */
            xfprintf(fp, "%s ",
               tagx == LPX_BS ? "B " :
               tagx == LPX_NL ? "NL" :
               tagx == LPX_NU ? "NU" :
               tagx == LPX_NF ? "NF" :
               tagx == LPX_NS ? "NS" : "??");
            /* row/column primal activity */
            xfprintf(fp, "%13.6g ", vx);
            /* row/column lower bound */
            if (typx == LPX_LO || typx == LPX_DB || typx == LPX_FX)
               xfprintf(fp, "%13.6g ", lb);
            else
               xfprintf(fp, "%13s ", "");
            /* row/column upper bound */
            if (typx == LPX_UP || typx == LPX_DB)
               xfprintf(fp, "%13.6g ", ub);
            else if (typx == LPX_FX)
               xfprintf(fp, "%13s ", "=");
            else
               xfprintf(fp, "%13s ", "");
            /* row/column dual activity */
            if (tagx != LPX_BS)
            {  if (dx == 0.0)
                  xfprintf(fp, "%13s", "< eps");
               else
                  xfprintf(fp, "%13.6g", dx);
            }
            /* end of line */
            xfprintf(fp, "\n");
         }
      }
      xfprintf(fp, "\n");
#if 1
      if (lpx_get_prim_stat(lp) != LPX_P_UNDEF &&
          lpx_get_dual_stat(lp) != LPX_D_UNDEF)
      {  int m = lpx_get_num_rows(lp);
         LPXKKT kkt;
         xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n\n");
         lpx_check_kkt(lp, 1, &kkt);
         xfprintf(fp, "KKT.PE: max.abs.err. = %.2e on row %d\n",
            kkt.pe_ae_max, kkt.pe_ae_row);
         xfprintf(fp, "        max.rel.err. = %.2e on row %d\n",
            kkt.pe_re_max, kkt.pe_re_row);
         switch (kkt.pe_quality)
         {  case 'H':
               xfprintf(fp, "        High quality\n");
               break;
            case 'M':
               xfprintf(fp, "        Medium quality\n");
               break;
            case 'L':
               xfprintf(fp, "        Low quality\n");
               break;
            default:
               xfprintf(fp, "        PRIMAL SOLUTION IS WRONG\n");
               break;
         }
         xfprintf(fp, "\n");
         xfprintf(fp, "KKT.PB: max.abs.err. = %.2e on %s %d\n",
            kkt.pb_ae_max, kkt.pb_ae_ind <= m ? "row" : "column",
            kkt.pb_ae_ind <= m ? kkt.pb_ae_ind : kkt.pb_ae_ind - m);
         xfprintf(fp, "        max.rel.err. = %.2e on %s %d\n",
            kkt.pb_re_max, kkt.pb_re_ind <= m ? "row" : "column",
            kkt.pb_re_ind <= m ? kkt.pb_re_ind : kkt.pb_re_ind - m);
         switch (kkt.pb_quality)
         {  case 'H':
               xfprintf(fp, "        High quality\n");
               break;
            case 'M':
               xfprintf(fp, "        Medium quality\n");
               break;
            case 'L':
               xfprintf(fp, "        Low quality\n");
               break;
            default:
               xfprintf(fp, "        PRIMAL SOLUTION IS INFEASIBLE\n");
               break;
         }
         xfprintf(fp, "\n");
         xfprintf(fp, "KKT.DE: max.abs.err. = %.2e on column %d\n",
            kkt.de_ae_max, kkt.de_ae_col);
         xfprintf(fp, "        max.rel.err. = %.2e on column %d\n",
            kkt.de_re_max, kkt.de_re_col);
         switch (kkt.de_quality)
         {  case 'H':
               xfprintf(fp, "        High quality\n");
               break;
            case 'M':
               xfprintf(fp, "        Medium quality\n");
               break;
            case 'L':
               xfprintf(fp, "        Low quality\n");
               break;
            default:
               xfprintf(fp, "        DUAL SOLUTION IS WRONG\n");
               break;
         }
         xfprintf(fp, "\n");
         xfprintf(fp, "KKT.DB: max.abs.err. = %.2e on %s %d\n",
            kkt.db_ae_max, kkt.db_ae_ind <= m ? "row" : "column",
            kkt.db_ae_ind <= m ? kkt.db_ae_ind : kkt.db_ae_ind - m);
         xfprintf(fp, "        max.rel.err. = %.2e on %s %d\n",
            kkt.db_re_max, kkt.db_re_ind <= m ? "row" : "column",
            kkt.db_re_ind <= m ? kkt.db_re_ind : kkt.db_re_ind - m);
         switch (kkt.db_quality)
         {  case 'H':
               xfprintf(fp, "        High quality\n");
               break;
            case 'M':
               xfprintf(fp, "        Medium quality\n");
               break;
            case 'L':
               xfprintf(fp, "        Low quality\n");
               break;
            default:
               xfprintf(fp, "        DUAL SOLUTION IS INFEASIBLE\n");
               break;
         }
         xfprintf(fp, "\n");
      }
#endif
#if 1
      if (lpx_get_status(lp) == LPX_UNBND)
      {  int m = lpx_get_num_rows(lp);
         int k = lpx_get_ray_info(lp);
         xfprintf(fp, "Unbounded ray: %s %d\n",
            k <= m ? "row" : "column", k <= m ? k : k - m);
         xfprintf(fp, "\n");
      }
#endif
      xfprintf(fp, "End of output\n");
      xfflush(fp);
      if (xferror(fp))
      {  xprintf("lpx_print_sol: can't write to `%s' - %s\n", fname,
            strerror(errno));
         goto fail;
      }
      xfclose(fp);
      return 0;
fail: if (fp != NULL) xfclose(fp);
      return 1;
}
コード例 #4
0
ファイル: lpglpk40.c プロジェクト: ecotox/pacfm
int CClp_limited_dualopt(CClp *lp, int iterationlim, int *status,
      double *objupperlim)
{     /* CALLS the dual simplex method with a limit on the number of
         pivots.
         - upperbound it is used to cutoff the dual simplex method (when
           the objective value reaches upperbound); it can be NULL;
         - status returns the status of the optimization (it can be
           NULL). */
      int stat, ret;
      insist(iterationlim == iterationlim);
      insist(objupperlim == objupperlim);
      if (MSGLEV >= 1)
      {  int m = lpx_get_num_rows(lp->lp);
         int n = lpx_get_num_cols(lp->lp);
         int nz = lpx_get_num_nz(lp->lp);
         print("CClp_limited_dualopt: m = %d; n = %d; nz = %d", m, n,
            nz);
      }
      lpx_set_int_parm(lp->lp, LPX_K_DUAL, 1);
      switch (MSGLEV)
      {  case 0:
            lpx_set_int_parm(lp->lp, LPX_K_MSGLEV, 0);
            lpx_set_int_parm(lp->lp, LPX_K_OUTFRQ, 1000000);
            lpx_set_real_parm(lp->lp, LPX_K_OUTDLY, 1e6);
            break;
         case 1:
            lpx_set_int_parm(lp->lp, LPX_K_MSGLEV, 2);
            lpx_set_int_parm(lp->lp, LPX_K_OUTFRQ, 200);
            lpx_set_real_parm(lp->lp, LPX_K_OUTDLY, 5.0);
            break;
         case 2:
            lpx_set_int_parm(lp->lp, LPX_K_MSGLEV, 3);
            lpx_set_int_parm(lp->lp, LPX_K_OUTFRQ, 200);
            lpx_set_real_parm(lp->lp, LPX_K_OUTDLY, 0.0);
            break;
         default:
            insist(MSGLEV != MSGLEV);
      }
      ret = lpx_simplex(lp->lp);
      if (ret == LPX_E_FAULT)
      {  if (MSGLEV >= 1) print("CClp_limited_dualopt: restarting from "
            "advanced basis...");
         lpx_adv_basis(lp->lp);
         ret = lpx_simplex(lp->lp);
      }
      if (ret != LPX_E_OK)
      {  print("CClp_limited_dualopt: lpx_simplex failed; return code ="
            " %d", ret);
         if (status) *status = CClp_FAILURE;
         ret = 1;
         goto done;
      }
      stat = lpx_get_status(lp->lp);
      if (stat == LPX_OPT)
      {  if (status) *status = CClp_SUCCESS;
         ret = 0;
      }
      else if (stat == LPX_NOFEAS)
      {  if (status) *status = CClp_INFEASIBLE;
         ret = 0;
      }
      else
      {  print("CClp_limited_dualopt: optimization status = %d", stat);
         if (status) *status = CClp_FAILURE;
         ret = 1;
      }
done: return ret;
}
コード例 #5
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;
}
コード例 #6
0
ファイル: GLPKapi.cpp プロジェクト: ModelSEED/Model-SEED-core
OptSolutionData* GLPKRunSolver(int ProbType) {
	OptSolutionData* NewSolution = NULL;

	int NumVariables = lpx_get_num_cols(GLPKModel);

	int Status = 0;
	if (ProbType == MILP) {
		Status = lpx_simplex(GLPKModel);
		if (Status != LPX_E_OK) {
			FErrorFile() << "Failed to optimize problem." << endl;
			FlushErrorFile();
			return NULL;
		}
		Status = lpx_integer(GLPKModel);
		if (Status != LPX_E_OK) {
			FErrorFile() << "Failed to optimize problem." << endl;
			FlushErrorFile();
			return NULL;
		}
		NewSolution = new OptSolutionData;

		Status = lpx_mip_status(GLPKModel);
		if (Status == LPX_I_UNDEF || Status == LPX_I_NOFEAS) {
			NewSolution->Status = INFEASIBLE;
			return NewSolution;
		} else if (Status == LPX_I_FEAS) {
			NewSolution->Status = UNBOUNDED;
			return NewSolution;
		} else if (Status == LPX_I_OPT) {
			NewSolution->Status = SUCCESS;
		} else {
			delete NewSolution;
			FErrorFile() << "Problem status unrecognized." << endl;
			FlushErrorFile();
			return NULL;
		}

		NewSolution->Objective = lpx_mip_obj_val(GLPKModel);
	
		NewSolution->SolutionData.resize(NumVariables);
		for (int i=0; i < NumVariables; i++) {
			NewSolution->SolutionData[i] = lpx_mip_col_val(GLPKModel, i+1);
		}
	} else if (ProbType == LP) {
		//First we check the basis matrix to ensure it is not sigular
		if (lpx_warm_up(GLPKModel) != LPX_E_OK) {
			lpx_adv_basis(GLPKModel);
		}
		Status = lpx_simplex(GLPKModel);
		if (Status == LPX_E_FAULT) {
			Status = lpx_warm_up(GLPKModel);
			if (Status == LPX_E_BADB) {  /* the basis is invalid; build some valid basis */
				lpx_adv_basis(GLPKModel);
				Status = lpx_simplex(GLPKModel);
			}
		}
		if (Status != LPX_E_OK) {
			FErrorFile() << "Failed to optimize problem." << endl;
			FlushErrorFile();
			return NULL;
		}
		NewSolution = new OptSolutionData;

		Status = lpx_get_status(GLPKModel);
		if (Status == LPX_INFEAS || Status == LPX_NOFEAS || Status == LPX_UNDEF) {
			cout << "Model is infeasible" << endl;
			FErrorFile() << "Model is infeasible" << endl;
			FlushErrorFile();
			NewSolution->Status = INFEASIBLE;
			return NewSolution;
		} else if (Status == LPX_FEAS || Status == LPX_UNBND) {
			cout << "Model is unbounded" << endl;
			FErrorFile() << "Model is unbounded" << endl;
			FlushErrorFile();
			NewSolution->Status = UNBOUNDED;
			return NewSolution;
		} else if (Status == LPX_OPT) {
			NewSolution->Status = SUCCESS;
		} else {
			delete NewSolution;
			FErrorFile() << "Problem status unrecognized." << endl;
			FlushErrorFile();
			return NULL;
		}

		NewSolution->Objective = lpx_get_obj_val(GLPKModel);
	
		NewSolution->SolutionData.resize(NumVariables);
		for (int i=0; i < NumVariables; i++) {
			NewSolution->SolutionData[i] = lpx_get_col_prim(GLPKModel, i+1);
		}
	} else {
		FErrorFile() << "Optimization problem type cannot be handled by GLPK solver." << endl;
		FlushErrorFile();
		return NULL;
	}

	return NewSolution;
}
コード例 #7
0
ファイル: glplpx6d.c プロジェクト: ChrisMoreton/Test3
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;
}
コード例 #8
0
ファイル: glplpx6d.c プロジェクト: ChrisMoreton/Test3
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;
}
コード例 #9
0
ファイル: glplpx6d.c プロジェクト: ChrisMoreton/Test3
static int generate_cuts(LPX *prob)
{     int prob_m, prob_n, prob_nz, msg_lev, dual, nrows, it_cnt, ret;
      double out_dly, tm_lim, tm_lag = 0.0, tm_beg = utime();
      print("Generating cutting planes...");
      /* determine the number of rows, columns, and non-zeros on entry
         to the routine */
      prob_m = lpx_get_num_rows(prob);
      prob_n = lpx_get_num_cols(prob);
      prob_nz = lpx_get_num_nz(prob);
      /* save some control parameters */
      msg_lev = lpx_get_int_parm(prob, LPX_K_MSGLEV);
      dual = lpx_get_int_parm(prob, LPX_K_DUAL);
      out_dly = lpx_get_real_parm(prob, LPX_K_OUTDLY);
      tm_lim = lpx_get_real_parm(prob, LPX_K_TMLIM);
      /* and set their new values needed for re-optimization */
      lpx_set_int_parm(prob, LPX_K_MSGLEV, 1);
      lpx_set_int_parm(prob, LPX_K_DUAL, 1);
      lpx_set_real_parm(prob, LPX_K_OUTDLY, 10.0);
      lpx_set_real_parm(prob, LPX_K_TMLIM, -1.0);
loop: /* main loop starts here */
      /* display current status of the problem */
      if (utime() - tm_lag >= 5.0 - 0.001)
         show_status(prob, prob_m, prob_nz), tm_lag = utime();
      /* check if the patience has been exhausted */
      if (tm_lim >= 0.0 && tm_lim <= utime() - tm_beg)
      {  ret = LPX_E_TMLIM;
         goto done;
      }
      /* not more than 500 cut inequalities are allowed */
      if (lpx_get_num_rows(prob) - prob_m >= 500)
      {  ret = LPX_E_OK;
         goto done;
      }
      /* not more than 50,000 cut coefficients are allowed */
      if (lpx_get_num_nz(prob) - prob_nz >= 50000)
      {  ret = LPX_E_OK;
         goto done;
      }
      /* try to generate Gomory's mixed integer cut */
      nrows = lpx_get_num_rows(prob);
      gen_gomory_cut(prob, prob_n);
      if (nrows == lpx_get_num_rows(prob))
      {  /* nothing has been generated */
         ret = LPX_E_OK;
         goto done;
      }
      /* re-optimize current LP relaxation using dual simplex */
      it_cnt = lpx_get_int_parm(prob, LPX_K_ITCNT);
      switch (lpx_simplex(prob))
      {  case LPX_E_OK:
            break;
         case LPX_E_ITLIM:
            ret = LPX_E_ITLIM;
            goto done;
         default:
            ret = LPX_E_SING;
            goto done;
      }
      if (it_cnt == lpx_get_int_parm(prob, LPX_K_ITCNT))
      {  ret = LPX_E_OK;
         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;
         default:
            insist(prob != prob);
      }
      /* continue generating cutting planes */
      goto loop;
done: /* display final status of the problem */
      show_status(prob, prob_m, prob_nz);
      switch (ret)
      {  case LPX_E_OK:
            break;
         case LPX_E_NOPFS:
            print("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION");
            break;
         case LPX_E_ITLIM:
            print("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED");
            break;
         case LPX_E_TMLIM:
            print("TIME LIMIT EXCEEDED; SEARCH TERMINATED");
            break;
         case LPX_E_SING:
            print("lpx_intopt: cannot re-optimize LP relaxation");
            break;
         default:
            insist(ret != ret);
      }
      /* decrease the time limit by spent amount of the time */
      if (tm_lim >= 0.0)
      {  tm_lim -= (utime() - tm_beg);
         if (tm_lim < 0.0) tm_lim = 0.0;
      }
      /* restore some control parameters and update statistics */
      lpx_set_int_parm(prob, LPX_K_MSGLEV, msg_lev);
      lpx_set_int_parm(prob, LPX_K_DUAL, dual);
      lpx_set_real_parm(prob, LPX_K_OUTDLY, out_dly);
      lpx_set_real_parm(prob, LPX_K_TMLIM, tm_lim);
      return ret;
}
コード例 #10
0
ファイル: glplpx8b.c プロジェクト: ChrisMoreton/Test3
int lpx_print_sens_bnds(LPX *lp, char *fname)
{     FILE *fp = NULL;
      int what, round;
      print("lpx_print_sens_bnds: writing LP problem solution bounds to"
         " `%s'...", fname);
#if 1
      /* added by mao */
      /* this routine needs factorization of the current basis matrix
         which, however, does not exist if the basic solution was
         obtained by the lp presolver; therefore we should warm up the
         basis to be sure that the factorization is valid (note that if
         the factorization exists, lpx_warm_up does nothing) */
      lpx_warm_up(lp);
#endif
#if 0 /* 21/XII-2003 by mao */
      if (lp->b_stat == LPX_B_UNDEF)
#else
      if (!lpx_is_b_avail(lp))
#endif
      {  print("lpx_print_sens_bnds: basis information not available (m"
            "ay be a presolve issue)");
         goto fail;
      }
      fp = ufopen(fname, "w");
      if (fp == NULL)
      {  print("lpx_print_sens_bnds: can't create `%s' - %s", fname,
            strerror(errno));
         goto fail;
      }
      /* problem name */
      {  char *name;
         name = lpx_get_prob_name(lp);
         if (name == NULL) name = "";
         fprintf(fp, "%-12s%s\n", "Problem:", name);
      }
      /* number of rows (auxiliary variables) */
      {  int nr;
         nr = lpx_get_num_rows(lp);
         fprintf(fp, "%-12s%d\n", "Rows:", nr);
      }
      /* number of columns (structural variables) */
      {  int nc;
         nc = lpx_get_num_cols(lp);
         fprintf(fp, "%-12s%d\n", "Columns:", nc);
      }
      /* number of non-zeros (constraint coefficients) */
      {  int nz;
         nz = lpx_get_num_nz(lp);
         fprintf(fp, "%-12s%d\n", "Non-zeros:", nz);
      }
      /* solution status */
      {  int status;
         status = lpx_get_status(lp);
         fprintf(fp, "%-12s%s\n", "Status:",
            status == LPX_OPT    ? "OPTIMAL" :
            status == LPX_FEAS   ? "FEASIBLE" :
            status == LPX_INFEAS ? "INFEASIBLE (INTERMEDIATE)" :
            status == LPX_NOFEAS ? "INFEASIBLE (FINAL)" :
            status == LPX_UNBND  ? "UNBOUNDED" :
            status == LPX_UNDEF  ? "UNDEFINED" : "???");
      }
      /* explanation/warning */
      {  fprintf(fp, "\nExplanation:  This file presents amounts by whi"
            "ch objective coefficients,\n");
         fprintf(fp, "constraint bounds, and variable bounds may be cha"
            "nged in the original problem\n");
         fprintf(fp, "while the optimal basis remains the same.  Note t"
            "hat the optimal solution\n");
         fprintf(fp, "and objective value may change even though the ba"
            "sis remains the same.\n");
         fprintf(fp, "These bounds assume that all parameters remain fi"
            "xed except the one in\n");
         fprintf(fp, "question.  If more than one parameter is changed,"
            " it is possible for the\n");
         fprintf(fp, "optimal basis to change even though each paramete"
            "r stays within its bounds.\n");
         fprintf(fp, "For more details, consult a text on linear progra"
            "mming.\n");
      }
      /* Sensitivity ranges if solution was optimal */
      {  int status;
         status = lpx_get_status(lp);
         if (status == LPX_OPT)
         {  int i,j,k,m,n;
            int dir;
            double max_inc, max_dec;
            int *index;
            double *val;
            fprintf(fp, "\nObjective Coefficient Analysis\n");
            fprintf(fp, "   No.  Column name St    Value       Max incr"
               "ease  Max decrease\n");
            fprintf(fp, "------ ------------ -- ------------- ---------"
               "---- ------------- \n");
            n = lpx_get_num_cols(lp);
            m = lpx_get_num_rows(lp);
            dir = lpx_get_obj_dir(lp);
            /* allocate memory for index and val arrays */
            index = ucalloc(1+n+m, sizeof(int));
            val   = ucalloc(1+n+m, sizeof(double));
            for (j = 1; j <= n; j++)
            {  char *name;
               int typx, tagx;
               double lb, ub, vx, dx;
               name = lpx_get_col_name(lp, j);
               if (name == NULL) name = "";
               lpx_get_col_bnds(lp, j, &typx, &lb, &ub);
#if 0 /* 21/XII-2003 by mao */
               round = lp->round, lp->round = 1;
               lpx_get_col_info(lp, j, &tagx, &vx, &dx);
               lp->round = round;
#else
               round = lpx_get_int_parm(lp, LPX_K_ROUND);
               lpx_set_int_parm(lp, LPX_K_ROUND, 1);
               lpx_get_col_info(lp, j, &tagx, &vx, &dx);
               lpx_set_int_parm(lp, LPX_K_ROUND, round);
#endif
               /* row/column ordinal number */
               fprintf(fp, "%6d ", j);
               /* row column/name */
               if (strlen(name) <= 12)
                  fprintf(fp, "%-12s ", name);
               else
                  fprintf(fp, "%s\n%20s", name, "");
               /* row/column status */
               fprintf(fp, "%s ",
                  tagx == LPX_BS ? "B " :
                  tagx == LPX_NL ? "NL" :
                  tagx == LPX_NU ? "NU" :
                  tagx == LPX_NF ? "NF" :
                  tagx == LPX_NS ? "NS" : "??");
               /* objective coefficient */
               fprintf(fp, "%13.6g ", lpx_get_obj_coef(lp, j));
               if (tagx == LPX_NL)
               {  if (dir==LPX_MIN)
                  {  /* reduced cost must be positive */
                     max_inc = DBL_MAX; /* really represents infinity */
                     max_dec = dx;
                  }
                  else
                  {  /* reduced cost must be negative */
                     max_inc = -dx;
                     max_dec = DBL_MAX; /* means infinity */
                  }
               }
               if (tagx == LPX_NU)
               {  if (dir==LPX_MIN)
                  {  /* reduced cost must be negative */
                     max_inc = -dx;
                     max_dec = DBL_MAX;
                  }
                  else
                  {  max_inc = DBL_MAX;
                     max_dec = dx;
                  }
               }
               if (tagx == LPX_NF)
               {  /* can't change nonbasic free variables' cost */
                  max_inc = 0.0;
                  max_dec = 0.0;
               }
               if (tagx == LPX_NS)
               {  /* doesn't matter what happens to the cost */
                  max_inc = DBL_MAX;
                  max_dec = DBL_MAX;
               }
               if (tagx == LPX_BS)
               {  int len;
                  /* We need to see how this objective coefficient
                     affects reduced costs of other variables */
                  len = lpx_eval_tab_row(lp, m+j, index, val);
                  max_inc = DBL_MAX;
                  max_dec = DBL_MAX;
                  for (i = 1; i <= len; i++)
                  {  /*int stat;*/
                     int tagx2;
                     double vx2, dx2;
                     double delta;
                     if (index[i]>m)
                        lpx_get_col_info(lp, index[i]-m, &tagx2, &vx2,
                           &dx2);
                     else
                        lpx_get_row_info(lp, index[i], &tagx2, &vx2,
                           &dx2);
                     if (tagx2 == LPX_NL)
                     {  if (val[i] != 0.0)
                        {  delta = dx2 / val[i];
                           if (delta < 0 && -delta < max_inc)
                              max_inc = -delta;
                           else if (delta >0 && delta < max_dec)
                              max_dec = delta;
                        }
                     }
                     if (tagx2 == LPX_NU)
                     {  if (val[i] != 0.0)
                        {  delta = dx2 / val[i];
                           if (delta < 0 && -delta < max_inc)
                              max_inc = -delta;
                           else if (delta > 0 && delta < max_dec)
                              max_dec = delta;
                        }
                     }
                     if (tagx2 == LPX_NF)
                     {  if (val[i] != 0.0)
                        {  max_inc = 0.0;
                           max_dec = 0.0;
                        }
                     }
                  }
               }
               if (max_inc == -0.0) max_inc = 0.0;
               if (max_dec == -0.0) max_dec = 0.0;
               if (max_inc == DBL_MAX)
                  fprintf(fp, "%13s ", "infinity");
               else if (max_inc < 1.0e-12 && max_inc > 0)
                  fprintf(fp, "%13s ", "< eps");
               else
                  fprintf(fp, "%13.6g ", max_inc);
               if (max_dec == DBL_MAX)
                  fprintf(fp, "%13s ", "infinity");
               else if (max_dec < 1.0e-12 && max_dec > 0)
                  fprintf(fp, "%13s ", "< eps");
               else
                  fprintf(fp, "%13.6g ", max_dec);
               fprintf(fp, "\n");
            }
            for (what = 1; what <= 2; what++)
            {  int ij, mn;
               fprintf(fp, "\n");
               fprintf(fp, "%s Analysis\n",
                  what==1? "Constraint Bounds":"Variable Bounds");
               fprintf(fp, "   No. %12s St    Value       Max increase "
                  " Max decrease\n",
                  what==1 ? " Row name":"Column name");
               fprintf(fp, "------ ------------ -- ------------- ------"
                  "------- ------------- \n");
               mn = what==1 ? m : n;
               for (ij = 1; ij <= mn; ij++)
               {  char *name;
                  int typx, tagx;
                  double lb, ub, vx, dx;
                  if (what==1)
                     name = lpx_get_row_name(lp, ij);
                  else
                     name = lpx_get_col_name(lp, ij);
                  if (name == NULL) name = "";
#if 0 /* 21/XII-2003 by mao */
                  if (what==1)
                  {  lpx_get_row_bnds(lp, ij, &typx, &lb, &ub);
                     round = lp->round, lp->round = 1;
                     lpx_get_row_info(lp, ij, &tagx, &vx, &dx);
                     lp->round = round;
                  }
                  else
                  {  lpx_get_col_bnds(lp, ij, &typx, &lb, &ub);
                     round = lp->round, lp->round = 1;
                     lpx_get_col_info(lp, ij, &tagx, &vx, &dx);
                     lp->round = round;
                  }
#else
                  round = lpx_get_int_parm(lp, LPX_K_ROUND);
                  lpx_set_int_parm(lp, LPX_K_ROUND, 1);
                  if (what==1)
                  {  lpx_get_row_bnds(lp, ij, &typx, &lb, &ub);
                     lpx_get_row_info(lp, ij, &tagx, &vx, &dx);
                  }
                  else
                  {  lpx_get_col_bnds(lp, ij, &typx, &lb, &ub);
                     lpx_get_col_info(lp, ij, &tagx, &vx, &dx);
                  }
                  lpx_set_int_parm(lp, LPX_K_ROUND, round);
#endif
                  /* row/column ordinal number */
                  fprintf(fp, "%6d ", ij);
                  /* row column/name */
                  if (strlen(name) <= 12)
                     fprintf(fp, "%-12s ", name);
                  else
                     fprintf(fp, "%s\n%20s", name, "");
                  /* row/column status */
                  fprintf(fp, "%s ",
                     tagx == LPX_BS ? "B " :
                     tagx == LPX_NL ? "NL" :
                     tagx == LPX_NU ? "NU" :
                     tagx == LPX_NF ? "NF" :
                     tagx == LPX_NS ? "NS" : "??");
                  fprintf(fp, "\n");
                  /* first check lower bound */
                  if (typx == LPX_LO || typx == LPX_DB ||
                      typx == LPX_FX)
                  {  int at_lower;
                     at_lower = 0;
                     if (tagx == LPX_BS || tagx == LPX_NU)
                     {  max_inc = vx - lb;
                        max_dec = DBL_MAX;
                     }
                     if (tagx == LPX_NS)
                     {  max_inc = 0.0;
                        max_dec = 0.0;
                        if (dir == LPX_MIN && dx > 0) at_lower = 1;
                        if (dir == LPX_MAX && dx < 0) at_lower = 1;
                     }
                     if (tagx == LPX_NL || at_lower == 1)
                     {  int len;
                        /* we have to see how it affects basic
                           variables */
                        len = lpx_eval_tab_col(lp, what==1?ij:ij+m,
                           index, val);
                        k = lpx_prim_ratio_test(lp, len, index, val, 1,
                           10e-7);
                        max_inc = DBL_MAX;
                        if (k != 0)
                        {  /*int stat;*/
                           int tagx2, typx2;
                           double vx2, dx2, lb2, ub2;
                           /*double delta;*/
                           double alpha;
                           int l;
                           for (l = 1; l <= len; l++)
                              if (index[l] == k) alpha = val[l];
                           if (k>m)
                           {  lpx_get_col_info(lp, k-m, &tagx2, &vx2,
                                 &dx2);
                              lpx_get_col_bnds(lp, k-m, &typx2, &lb2,
                                 &ub2);
                           }
                           else
                           {  lpx_get_row_info(lp, k, &tagx2, &vx2,
                                 &dx2);
                              lpx_get_row_bnds(lp, k, &typx2, &lb2,
                                 &ub2);
                           }
                           /* Check which direction;
                              remember this is upper bound */
                           if (alpha > 0)
                              max_inc = (ub2 - vx2)/ alpha;
                           else
                              max_inc = (lb2 - vx2)/ alpha;
                        }
                        /* now check lower bound */
                        k = lpx_prim_ratio_test(lp, len, index, val, -1,
                           10e-7);
                        max_dec = DBL_MAX;
                        if (k != 0)
                        {  /*int stat;*/
                           int tagx2, typx2;
                           double vx2, dx2, lb2, ub2;
                           /*double delta;*/
                           double alpha;
                           int l;
                           for (l = 1; l <= len; l++)
                              if (index[l] == k) alpha = val[l];
                           if (k>m)
                           {  lpx_get_col_info(lp, k-m, &tagx2, &vx2,
                                 &dx2);
                              lpx_get_col_bnds(lp, k-m, &typx2, &lb2,
                                 &ub2);
                           }
                           else
                           {  lpx_get_row_info(lp, k, &tagx2, &vx2,
                                 &dx2);
                              lpx_get_row_bnds(lp, k, &typx2, &lb2,
                                 &ub2);
                           }
                           /* Check which direction;
                              remember this is lower bound */
                           if (alpha > 0)
                              max_dec = (vx2 - lb2)/ alpha;
                           else
                              max_dec = (vx2 - ub2)/ alpha;
                        }
                     }
                     /* bound */
                     if (typx == LPX_DB || typx == LPX_FX)
                     {  if (max_inc > ub - lb)
                           max_inc = ub - lb;
                     }
                     fprintf(fp, "         LOWER         %13.6g ", lb);
                     if (max_inc == -0.0) max_inc = 0.0;
                     if (max_dec == -0.0) max_dec = 0.0;
                     if (max_inc == DBL_MAX)
                        fprintf(fp, "%13s ", "infinity");
                     else if (max_inc < 1.0e-12 && max_inc > 0)
                        fprintf(fp, "%13s ", "< eps");
                     else
                        fprintf(fp, "%13.6g ", max_inc);
                     if (max_dec == DBL_MAX)
                        fprintf(fp, "%13s ", "infinity");
                     else if (max_dec < 1.0e-12 && max_dec > 0)
                        fprintf(fp, "%13s ", "< eps");
                     else
                        fprintf(fp, "%13.6g ", max_dec);
                     fprintf(fp, "\n");
                  }
                  /* now check upper bound */
                  if (typx == LPX_UP || typx == LPX_DB ||
                     typx == LPX_FX)
                  {  int at_upper;
                     at_upper = 0;
                     if (tagx == LPX_BS || tagx == LPX_NL)
                     {  max_inc = DBL_MAX;
                        max_dec = ub - vx;
                     }
                     if (tagx == LPX_NS)
                     {  max_inc = 0.0;
                        max_dec = 0.0;
                        if (dir == LPX_MIN && dx < 0) at_upper = 1;
                        if (dir == LPX_MAX && dx > 0) at_upper = 1;
                     }
                     if (tagx == LPX_NU || at_upper == 1)
                     {  int len;
                        /* we have to see how it affects basic
                           variables */
                        len = lpx_eval_tab_col(lp, what==1?ij:ij+m,
                           index, val);
                        k = lpx_prim_ratio_test(lp, len, index, val, 1,
                           10e-7);
                        max_inc = DBL_MAX;
                        if (k != 0)
                        {  /*int stat;*/
                           int tagx2, typx2;
                           double vx2, dx2, lb2, ub2;
                           /*double delta;*/
                           double alpha;
                           int l;
                           for (l = 1; l <= len; l++)
                              if (index[l] == k) alpha = val[l];
                           if (k>m)
                           {  lpx_get_col_info(lp, k-m, &tagx2, &vx2,
                                 &dx2);
                              lpx_get_col_bnds(lp, k-m, &typx2, &lb2,
                                 &ub2);
                           }
                           else
                           {  lpx_get_row_info(lp, k, &tagx2, &vx2,
                                 &dx2);
                              lpx_get_row_bnds(lp, k, &typx2, &lb2,
                                 &ub2);
                           }
                           /* Check which direction;
                              remember this is upper bound */
                           if (alpha > 0)
                              max_inc = (ub2 - vx2)/ alpha;
                           else
                              max_inc = (lb2 - vx2)/ alpha;
                        }
                        /* now check lower bound */
                        k = lpx_prim_ratio_test(lp, len, index, val, -1,
                           10e-7);
                        max_dec = DBL_MAX;
                        if (k != 0)
                        {  /*int stat;*/
                           int tagx2, typx2;
                           double vx2, dx2, lb2, ub2;
                           /*double delta;*/
                           double alpha;
                           int l;
                           for (l = 1; l <= len; l++)
                              if (index[l] == k) alpha = val[l];
                           if (k>m)
                           {  lpx_get_col_info(lp, k-m, &tagx2, &vx2,
                                 &dx2);
                              lpx_get_col_bnds(lp, k-m, &typx2, &lb2,
                                 &ub2);
                           }
                           else
                           {  lpx_get_row_info(lp, k, &tagx2, &vx2,
                                 &dx2);
                              lpx_get_row_bnds(lp, k, &typx2, &lb2,
                                 &ub2);
                           }
                           /* Check which direction;
                              remember this is lower bound */
                           if (alpha > 0)
                              max_dec = (vx2 - lb2)/ alpha;
                           else
                              max_dec = (vx2 - ub2)/ alpha;
                        }
                     }
                     if (typx == LPX_DB || typx == LPX_FX)
                     {  if (max_dec > ub - lb)
                           max_dec = ub - lb;
                     }
                     /* bound */
                     fprintf(fp, "         UPPER         %13.6g ", ub);
                     if (max_inc == -0.0) max_inc = 0.0;
                     if (max_dec == -0.0) max_dec = 0.0;
                     if (max_inc == DBL_MAX)
                        fprintf(fp, "%13s ", "infinity");
                     else if (max_inc < 1.0e-12 && max_inc > 0)
                        fprintf(fp, "%13s ", "< eps");
                     else
                        fprintf(fp, "%13.6g ", max_inc);
                     if (max_dec == DBL_MAX)
                        fprintf(fp, "%13s ", "infinity");
                     else if (max_dec < 1.0e-12 && max_dec > 0)
                        fprintf(fp, "%13s ", "< eps");
                     else
                        fprintf(fp, "%13.6g ", max_dec);
                     fprintf(fp, "\n");
                  }
               }
            }
            /* free the memory we used */
            ufree(index);
            ufree(val);
         }
         else fprintf(fp, "No range information since solution is not o"
            "ptimal.\n");
      }
      fprintf(fp, "\n");
      fprintf(fp, "End of output\n");
      fflush(fp);
      if (ferror(fp))
      {  print("lpx_print_sens_bnds: can't write to `%s' - %s", fname,
            strerror(errno));
         goto fail;
      }
      ufclose(fp);
      return 0;
fail: if (fp != NULL) ufclose(fp);
      return 1;
}