Exemple #1
0
void ipp_unload_sol(IPP *ipp, LPX *orig, int i_stat)
{     int i, j, k, len, *ind;
      double temp, *row_mipx, *val;
      xassert(ipp->orig_m == lpx_get_num_rows(orig));
      xassert(ipp->orig_n == lpx_get_num_cols(orig));
      xassert(ipp->orig_dir == lpx_get_obj_dir(orig));
      /* all columns must be computed/recovered */
      xassert(ipp->orig_n <= ipp->ncols);
      for (j = 1; j <= ipp->ncols; j++) xassert(ipp->col_stat[j]);
      /* compute values of auxiliary variables using known values of
         structural variables (columns) */
      row_mipx = xcalloc(1+ipp->orig_m, sizeof(double));
      ind = xcalloc(1+ipp->orig_n, sizeof(int));
      val = xcalloc(1+ipp->orig_n, sizeof(double));
      for (i = 1; i <= ipp->orig_m; i++)
      {  len = lpx_get_mat_row(orig, i, ind, val);
         temp = 0.0;
         for (k = 1; k <= len; k++)
            temp += val[k] * ipp->col_mipx[ind[k]];
         row_mipx[i] = temp;
      }
      xfree(ind);
      xfree(val);
      /* store solution components into the original problem object */
      lpx_put_mip_soln(orig, i_stat, row_mipx, ipp->col_mipx);
      xfree(row_mipx);
      return;
}
Exemple #2
0
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;
}
Exemple #3
0
void lpp_unload_sol(LPP *lpp, LPX *orig)
{     int i, j, k, m, n, typx, tagx;
      m = lpp->orig_m;
      n = lpp->orig_n;
      insist(m == lpx_get_num_rows(orig));
      insist(n == lpx_get_num_cols(orig));
      insist(lpp->orig_dir == lpx_get_obj_dir(orig));
      /* check row and column statuses */
      insist(m <= lpp->nrows);
      insist(n <= lpp->ncols);
      for (k = 1; k <= m+n; k++)
      {  tagx = (k <= m ? lpp->row_stat[k] : lpp->col_stat[k-m]);
         if (tagx != LPX_BS)
         {  if (k <= m)
               lpx_get_row_bnds(orig, k, &typx, NULL, NULL);
            else
               lpx_get_col_bnds(orig, k-m, &typx, NULL, NULL);
            switch (typx)
            {  case LPX_FR:
                  insist(tagx == LPX_NF);
                  break;
               case LPX_LO:
                  insist(tagx == LPX_NL);
                  break;
               case LPX_UP:
                  insist(tagx == LPX_NU);
                  break;
               case LPX_DB:
                  insist(tagx == LPX_NL || tagx == LPX_NU);
                  break;
               case LPX_FX:
                  insist(tagx == LPX_NS);
                  break;
               default:
                  insist(orig != orig);
            }
         }
      }
      /* if the original problem is maximization, change signs of dual
         values */
      if (lpp->orig_dir == LPX_MAX)
      {  for (i = 1; i <= m; i++) lpp->row_dual[i] = -lpp->row_dual[i];
         for (j = 1; j <= n; j++) lpp->col_dual[j] = -lpp->col_dual[j];
      }
      /* store solution components into the original problem object (it
         is assumed that the recovered solution is optimal) */
      lpx_put_solution(orig, LPX_P_FEAS, LPX_D_FEAS,
         lpp->row_stat, lpp->row_prim, lpp->row_dual,
         lpp->col_stat, lpp->col_prim, lpp->col_dual);
      return;
}
Exemple #4
0
void lpp_load_orig(LPP *lpp, LPX *orig)
{     LPPROW *row;
      LPPCOL *col, **map;
      int i, j, t, len, typx, *ndx;
      double lb, ub, temp, *c, *val;
      /* save some information about the original problem */
      lpp->orig_m = lpx_get_num_rows(orig);
      lpp->orig_n = lpx_get_num_cols(orig);
      lpp->orig_nnz = lpx_get_num_nz(orig);
      lpp->orig_dir = lpx_get_obj_dir(orig);
      /* allocate working arrays */
      c = ucalloc(1+lpp->orig_n, sizeof(double));
      ndx = ucalloc(1+lpp->orig_n, sizeof(int));
      val = ucalloc(1+lpp->orig_n, sizeof(double));
      /* auxiliary variables (i.e. rows) in the original problem may
         have non-zero objective coefficients; so, we substitute these
         auxiliary variables into the objective function in order that
         it depends only on structural variables (i.e. columns); the
         resultant vector of objective coefficients is accumulated in
         the working array c */
      for (j = 1; j <= lpp->orig_n; j++)
         c[j] = lpx_get_col_coef(orig, j);
      for (i = 1; i <= lpp->orig_m; i++)
      {  /* obtain an objective coefficient at i-th row */
         temp = lpx_get_row_coef(orig, i);
         /* substitute i-th row into the objective function */
         if (temp != 0.0)
         {  len = lpx_get_mat_row(orig, i, ndx, val);
            for (t = 1; t <= len; t++) c[ndx[t]] += val[t] * temp;
         }
      }
      /* copy rows of the original problem into the workspace; each
         row created in the workspace is assigned a reference number,
         which is its ordinal number in the original problem */
      for (i = 1; i <= lpp->orig_m; i++)
      {  lpx_get_row_bnds(orig, i, &typx, &lb, &ub);
         if (typx == LPX_FR || typx == LPX_UP) lb = -DBL_MAX;
         if (typx == LPX_FR || typx == LPX_LO) ub = +DBL_MAX;
         if (typx == LPX_FX) ub = lb;
         lpp_add_row(lpp, lb, ub);
      }
      /* copy columns of the original problem into the workspace; each
         column created in the workspace is assigned a reference number,
         which its ordinal number in the original problem */
      for (j = 1; j <= lpp->orig_n; j++)
      {  lpx_get_col_bnds(orig, j, &typx, &lb, &ub);
         if (typx == LPX_FR || typx == LPX_UP) lb = -DBL_MAX;
         if (typx == LPX_FR || typx == LPX_LO) ub = +DBL_MAX;
         if (typx == LPX_FX) ub = lb;
         lpp_add_col(lpp, lb, ub, c[j]);
      }
      /* copy the constant term of the original objective function */
      lpp->c0 = lpx_get_obj_c0(orig);
      /* if the original problem is maximization, change the sign of
         the objective function, because the transformed problem to be
         processed by the presolver must be minimization */
      if (lpp->orig_dir == LPX_MAX)
      {  for (col = lpp->col_ptr; col != NULL; col = col->next)
            col->c = - col->c;
         lpp->c0 = - lpp->c0;
      }
      /* build an auxiliary array to map column ordinal numbers to the
         corresponding pointers */
      insist(sizeof(LPPCOL *) <= sizeof(double));
      map = (LPPCOL **)c;
      for (col = lpp->col_ptr; col != NULL; col = col->next)
         map[col->j] = col;
      /* copy the original constraint matrix into the workspace */
      for (row = lpp->row_ptr; row != NULL; row = row->next)
#if 1
      {  len = lpx_get_mat_row(orig, row->i, ndx, val);
         for (t = 1; t <= len; t++)
            lpp_add_aij(lpp, row, map[ndx[t]], val[t]);
      }
#else /* 27/XI-2003 (the problem persists) */
      {  double big, eps;
         len = lpx_get_mat_row(orig, row->i, ndx, val);
         big = 0.0;
         for (t = 1; t <= len; t++)
            if (big < fabs(val[t])) big = fabs(val[t]);
         eps = 1e-10 * big;
         for (t = 1; t <= len; t++)
         {  if (fabs(val[t]) < eps) continue;
            lpp_add_aij(lpp, row, map[ndx[t]], val[t]);
         }
      }
#endif
      /* free working arrays */
      ufree(c);
      ufree(ndx);
      ufree(val);
      return;
}
Exemple #5
0
int lpx_write_cpxlp(LPX *lp, const char *fname)
{     /* write problem data in CPLEX LP format */
      FILE *fp;
      int nrows, ncols, i, j, t, len, typx, flag, kind, *ind;
      double lb, ub, temp, *val;
      char line[1023+1], term[1023+1], rname[255+1], cname[255+1];
      print("lpx_write_cpxlp: writing problem data to `%s'...", fname);
      /* open the output text file */
      fp = xfopen(fname, "w");
      if (fp == NULL)
      {  print("lpx_write_cpxlp: unable to create `%s' - %s", fname,
            strerror(errno));
         goto fail;
      }
      /* determine the number of rows and columns */
      nrows = lpx_get_num_rows(lp);
      ncols = lpx_get_num_cols(lp);
      /* the problem should contain at least one row and one column */
      if (!(nrows > 0 && ncols > 0))
         fault("lpx_write_cpxlp: problem has no rows/columns");
      /* write problem name */
      {  const char *name = lpx_get_prob_name(lp);
         if (name == NULL) name = "Unknown";
         fprintf(fp, "\\* Problem: %s *\\\n", name);
         fprintf(fp, "\n");
      }
      /* allocate working arrays */
      ind = xcalloc(1+ncols, sizeof(int));
      val = xcalloc(1+ncols, sizeof(double));
      /* write the objective function definition and the constraints
         section */
      for (i = 0; i <= nrows; i++)
      {  if (i == 0)
         {  switch (lpx_get_obj_dir(lp))
            {  case LPX_MIN:
                  fprintf(fp, "Minimize\n");
                  break;
               case LPX_MAX:
                  fprintf(fp, "Maximize\n");
                  break;
               default:
                  xassert(lp != lp);
            }
         }
         else if (i == 1)
         {  temp = lpx_get_obj_coef(lp, 0);
            if (temp != 0.0)
               fprintf(fp, "\\* constant term = %.*g *\\\n", DBL_DIG,
                  temp);
            fprintf(fp, "\n");
            fprintf(fp, "Subject To\n");
         }
         row_name(lp, i, rname);
         if (i == 0)
         {  len = 0;
            for (j = 1; j <= ncols; j++)
            {  temp = lpx_get_obj_coef(lp, j);
               if (temp != 0.0)
                  len++, ind[len] = j, val[len] = temp;
            }
         }
         else
         {  lpx_get_row_bnds(lp, i, &typx, &lb, &ub);
            if (typx == LPX_FR) continue;
            len = lpx_get_mat_row(lp, i, ind, val);
         }
         flag = 0;
more:    if (!flag)
            sprintf(line, " %s:", rname);
         else
            sprintf(line, " %*s ", strlen(rname), "");
         for (t = 1; t <= len; t++)
         {  col_name(lp, ind[t], cname);
            if (val[t] == +1.0)
               sprintf(term, " + %s", cname);
            else if (val[t] == -1.0)
               sprintf(term, " - %s", cname);
            else if (val[t] > 0.0)
               sprintf(term, " + %.*g %s", DBL_DIG, +val[t], cname);
            else if (val[t] < 0.0)
               sprintf(term, " - %.*g %s", DBL_DIG, -val[t], cname);
            else
               xassert(lp != lp);
            if (strlen(line) + strlen(term) > 72)
               fprintf(fp, "%s\n", line), line[0] = '\0';
            strcat(line, term);
         }
         if (len == 0)
         {  /* empty row */
            sprintf(term, " 0 %s", col_name(lp, 1, cname));
            strcat(line, term);
         }
         if (i > 0)
         {  switch (typx)
            {  case LPX_LO:
               case LPX_DB:
                  sprintf(term, " >= %.*g", DBL_DIG, lb);
                  break;
               case LPX_UP:
                  sprintf(term, " <= %.*g", DBL_DIG, ub);
                  break;
               case LPX_FX:
                  sprintf(term, " = %.*g", DBL_DIG, lb);
                  break;
               default:
                  xassert(typx != typx);
            }
            if (strlen(line) + strlen(term) > 72)
               fprintf(fp, "%s\n", line), line[0] = '\0';
            strcat(line, term);
         }
         fprintf(fp, "%s\n", line);
         if (i > 0 && typx == LPX_DB)
         {  /* double-bounded row needs a copy for its upper bound */
            flag = 1;
            typx = LPX_UP;
            goto more;
         }
      }
      /* free working arrays */
      xfree(ind);
      xfree(val);
      /* write the bounds section */
      flag = 0;
      for (j = 1; j <= ncols; j++)
      {  col_name(lp, j, cname);
         lpx_get_col_bnds(lp, j, &typx, &lb, &ub);
         if (typx == LPX_LO && lb == 0.0) continue;
         if (!flag)
         {  fprintf(fp, "\n");
            fprintf(fp, "Bounds\n");
            flag = 1;
         }
         switch (typx)
         {  case LPX_FR:
               fprintf(fp, " %s free\n", cname);
               break;
            case LPX_LO:
               fprintf(fp, " %s >= %.*g\n", cname, DBL_DIG, lb);
               break;
            case LPX_UP:
               fprintf(fp, " %s <= %.*g\n", cname, DBL_DIG, ub);
               break;
            case LPX_DB:
               fprintf(fp, " %.*g <= %s <= %.*g\n", DBL_DIG, lb, cname,
                  DBL_DIG, ub);
               break;
            case LPX_FX:
               fprintf(fp, " %s = %.*g\n", cname, DBL_DIG, lb);
               break;
            default:
               xassert(typx != typx);
         }
      }
      /* write the general section */
      if (lpx_get_class(lp) == LPX_MIP)
      {  flag = 0;
         for (j = 1; j <= ncols; j++)
         {  kind = lpx_get_col_kind(lp, j);
            if (kind == LPX_CV) continue;
            xassert(kind == LPX_IV);
            if (!flag)
            {  fprintf(fp, "\n");
               fprintf(fp, "Generals\n");
               flag = 1;
            }
            fprintf(fp, " %s\n", col_name(lp, j, cname));
         }
      }
      /* write the end keyword */
      fprintf(fp, "\n");
      fprintf(fp, "End\n");
      /* close the output text file */
      fflush(fp);
      if (ferror(fp))
      {  print("lpx_write_cpxlp: write error on `%s' - %s", fname,
            strerror(errno));
         goto fail;
      }
      xfclose(fp);
      /* return to the calling program */
      return 0;
fail: /* the operation failed */
      if (fp != NULL) xfclose(fp);
      return 1;
}
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;
}
int lpx_print_mip(LPX *lp, const char *fname)
{     XFILE *fp;
      int what, round;
#if 0
      if (lpx_get_class(lp) != LPX_MIP)
         fault("lpx_print_mip: error -- not a MIP problem");
#endif
      xprintf(
         "lpx_print_mip: writing MIP problem solution to `%s'...\n",
         fname);
      fp = xfopen(fname, "w");
      if (fp == NULL)
      {  xprintf("lpx_print_mip: 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_int, nc_bin;
         nc = lpx_get_num_cols(lp);
         nc_int = lpx_get_num_int(lp);
         nc_bin = lpx_get_num_bin(lp);
         xfprintf(fp, "%-12s%d (%d integer, %d binary)\n", "Columns:",
            nc, nc_int, nc_bin);
      }
      /* 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_mip_status(lp);
         xfprintf(fp, "%-12s%s\n", "Status:",
            status == LPX_I_UNDEF  ? "INTEGER UNDEFINED" :
            status == LPX_I_OPT    ? "INTEGER OPTIMAL" :
            status == LPX_I_FEAS   ? "INTEGER NON-OPTIMAL" :
            status == LPX_I_NOFEAS ? "INTEGER EMPTY" : "???");
      }
      /* objective function */
      {  char *name;
         int dir;
         double mip_obj;
         name = (void *)lpx_get_obj_name(lp);
         dir = lpx_get_obj_dir(lp);
         mip_obj = lpx_mip_obj_val(lp);
         xfprintf(fp, "%-12s%s%s%.10g %s\n", "Objective:",
            name == NULL ? "" : name,
            name == NULL ? "" : " = ", mip_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      Activity     Lower bound   Upp"
            "er bound\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 kind, typx;
            double lb, ub, vx;
            if (what == 1)
            {  name = lpx_get_row_name(lp, ij);
               if (name == NULL) name = "";
               kind = LPX_CV;
               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);
               vx = lpx_mip_row_val(lp, ij);
               lpx_set_int_parm(lp, LPX_K_ROUND, round);
            }
            else
            {  name = lpx_get_col_name(lp, ij);
               if (name == NULL) name = "";
               kind = lpx_get_col_kind(lp, ij);
               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);
               vx = lpx_mip_col_val(lp, ij);
               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 kind */
            xfprintf(fp, "%s  ",
               kind == LPX_CV ? " " : kind == LPX_IV ? "*" : "?");
            /* row/column primal activity */
            xfprintf(fp, "%13.6g", vx);
            /* row/column lower and upper bounds */
            switch (typx)
            {  case LPX_FR:
                  break;
               case LPX_LO:
                  xfprintf(fp, " %13.6g", lb);
                  break;
               case LPX_UP:
                  xfprintf(fp, " %13s %13.6g", "", ub);
                  break;
               case LPX_DB:
                  xfprintf(fp, " %13.6g %13.6g", lb, ub);
                  break;
               case LPX_FX:
                  xfprintf(fp, " %13.6g %13s", lb, "=");
                  break;
               default:
                  xassert(typx != typx);
            }
            /* end of line */
            xfprintf(fp, "\n");
         }
      }
      xfprintf(fp, "\n");
#if 1
      if (lpx_mip_status(lp) != LPX_I_UNDEF)
      {  int m = lpx_get_num_rows(lp);
         LPXKKT kkt;
         xfprintf(fp, "Integer feasibility conditions:\n\n");
         lpx_check_int(lp, &kkt);
         xfprintf(fp, "INT.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, "        SOLUTION IS WRONG\n");
               break;
         }
         xfprintf(fp, "\n");
         xfprintf(fp, "INT.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, "        SOLUTION IS INFEASIBLE\n");
               break;
         }
         xfprintf(fp, "\n");
      }
#endif
      xfprintf(fp, "End of output\n");
      xfflush(fp);
      if (xferror(fp))
      {  xprintf("lpx_print_mip: can't write to `%s' - %s\n", fname,
            strerror(errno));
         goto fail;
      }
      xfclose(fp);
      return 0;
fail: if (fp != NULL) xfclose(fp);
      return 1;
}
int lpx_print_ips(LPX *lp, const char *fname)
{     XFILE *fp;
      int what, round;
      xprintf("lpx_print_ips: writing LP problem solution to `%s'...\n",
         fname);
      fp = xfopen(fname, "w");
      if (fp == NULL)
      {  xprintf("lpx_print_ips: 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_ipt_status(lp);
         xfprintf(fp, "%-12s%s\n", "Status:",
            status == LPX_T_UNDEF  ? "INTERIOR UNDEFINED" :
            status == LPX_T_OPT    ? "INTERIOR OPTIMAL" : "???");
      }
      /* objective function */
      {  char *name;
         int dir;
         double obj;
         name = (void *)lpx_get_obj_name(lp);
         dir = lpx_get_obj_dir(lp);
         obj = lpx_ipt_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      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);
               vx = lpx_ipt_row_prim(lp, ij);
               dx = lpx_ipt_row_dual(lp, ij);
               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);
               vx = lpx_ipt_col_prim(lp, ij);
               dx = lpx_ipt_col_dual(lp, ij);
               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, "");
            /* two positions are currently not used */
            xfprintf(fp, "   ");
            /* 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 */
            xfprintf(fp, "%13.6g", dx);
            /* end of line */
            xfprintf(fp, "\n");
         }
      }
      xfprintf(fp, "\n");
      xfprintf(fp, "End of output\n");
      xfflush(fp);
      if (xferror(fp))
      {  xprintf("lpx_print_ips: can't write to `%s' - %s\n", fname,
            strerror(errno));
         goto fail;
      }
      xfclose(fp);
      return 0;
fail: if (fp != NULL) xfclose(fp);
      return 1;
}
Exemple #9
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;
}
Exemple #10
0
double lpx_eval_degrad(LPX *lp, int len, int ind[], double val[],
      int type, double rhs)
{     int m = lpx_get_num_rows(lp);
      int n = lpx_get_num_cols(lp);
      int dir = lpx_get_obj_dir(lp);
      int q, k;
      double y, delta;
      if (lpx_get_dual_stat(lp) != LPX_D_FEAS)
         fault("lpx_eval_degrad: LP basis is not dual feasible");
      if (!(0 <= len && len <= n))
         fault("lpx_eval_degrad: len = %d; invalid row length", len);
      if (!(type == LPX_LO || type == LPX_UP))
         fault("lpx_eval_degrad: type = %d; invalid row type", type);
      /* compute value of the row auxiliary variable */
      y = lpx_eval_row(lp, len, ind, val);
      /* the inequalitiy constraint is assumed to be violated */
      if (!(type == LPX_LO && y < rhs || type == LPX_UP && y > rhs))
         fault("lpx_eval_degrad: y = %g, rhs = %g; constraint is not vi"
            "olated", y, rhs);
      /* transform the row in order to express y through only non-basic
         variables: y = alfa[1] * xN[1] + ... + alfa[n] * xN[n] */
      len = lpx_transform_row(lp, len, ind, val);
      /* in the adjacent basis y would become non-basic, so in case of
         '>=' it increases and in case of '<=' it decreases; determine
         which non-basic variable x[q], 1 <= q <= m+n, should leave the
         basis to keep dual feasibility */
      q = lpx_dual_ratio_test(lp, len, ind, val,
         type == LPX_LO ? +1 : -1, 1e-7);
      /* q = 0 means no adjacent dual feasible basis exist */
      if (q == 0) return dir == LPX_MIN ? +DBL_MAX : -DBL_MAX;
      /* find the entry corresponding to x[q] in the list */
      for (k = 1; k <= len; k++)
         if (ind[k] == q) break;
      insist(k <= len);
      /* dy = alfa[q] * dx[q], so dx[q] = dy / alfa[q], where dy is a
         change in y, dx[q] is a change in x[q] */
      delta = (rhs - y) / val[k];
#if 0
      /* Tomlin noticed that if the variable x[q] is of integer kind,
         its change cannot be less than one in the magnitude */
      if (q > m && lpx_get_col_kind(lp, q-m) == LPX_IV)
      {  /* x[q] is structural integer variable */
         if (fabs(delta - floor(delta + 0.5)) > 1e-3)
         {  if (delta > 0.0)
               delta = ceil(delta);  /* +3.14 -> +4 */
            else
               delta = floor(delta); /* -3.14 -> -4 */
         }
      }
#endif
      /* dz = lambda[q] * dx[q], where dz is a change in the objective
         function, lambda[q] is a reduced cost of x[q] */
      if (q <= m)
         delta *= lpx_get_row_dual(lp, q);
      else
         delta *= lpx_get_col_dual(lp, q-m);
      /* delta must be >= 0 (in case of minimization) or <= 0 (in case
         of minimization); however, due to round-off errors and finite
         tolerance used to choose x[q], this condition can be slightly
         violated */
      switch (dir)
      {  case LPX_MIN: if (delta < 0.0) delta = 0.0; break;
         case LPX_MAX: if (delta > 0.0) delta = 0.0; break;
         default: insist(dir != dir);
      }
      return delta;
}
Exemple #11
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;
}
Exemple #12
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;
}
Exemple #13
0
void ipp_load_orig(IPP *ipp, LPX *orig)
{     IPPROW **row;
      IPPCOL *col;
      int i, j, k, type, len, *ind;
      double lb, ub, *val;
      /* save some information about the original problem */
      ipp->orig_m = lpx_get_num_rows(orig);
      ipp->orig_n = lpx_get_num_cols(orig);
      ipp->orig_nnz = lpx_get_num_nz(orig);
      ipp->orig_dir = lpx_get_obj_dir(orig);
      /* allocate working arrays */
      row = xcalloc(1+ipp->orig_m, sizeof(IPPROW *));
      ind = xcalloc(1+ipp->orig_m, sizeof(int));
      val = xcalloc(1+ipp->orig_m, sizeof(double));
      /* copy rows of the original problem into the workspace */
      for (i = 1; i <= ipp->orig_m; i++)
      {  type = lpx_get_row_type(orig, i);
         if (type == LPX_FR || type == LPX_UP)
            lb = -DBL_MAX;
         else
            lb = lpx_get_row_lb(orig, i);
         if (type == LPX_FR || type == LPX_LO)
            ub = +DBL_MAX;
         else
            ub = lpx_get_row_ub(orig, i);
         row[i] = ipp_add_row(ipp, lb, ub);
      }
      /* copy columns of the original problem into the workspace; each
         column created in the workspace is assigned a reference number
         which is its ordinal number in the original problem */
      for (j = 1; j <= ipp->orig_n; j++)
      {  type = lpx_get_col_type(orig, j);
         if (type == LPX_FR || type == LPX_UP)
            lb = -DBL_MAX;
         else
            lb = lpx_get_col_lb(orig, j);
         if (type == LPX_FR || type == LPX_LO)
            ub = +DBL_MAX;
         else
            ub = lpx_get_col_ub(orig, j);
         col = ipp_add_col(ipp, lpx_get_col_kind(orig, j) == LPX_IV,
            lb, ub, lpx_get_obj_coef(orig, j));
         len = lpx_get_mat_col(orig, j, ind, val);
         for (k = 1; k <= len; k++)
            ipp_add_aij(ipp, row[ind[k]], col, val[k]);
      }
      /* copy the constant term of the original objective function */
      ipp->c0 = lpx_get_obj_coef(orig, 0);
      /* if the original problem is maximization, change the sign of
         the objective function, because the transformed problem to be
         processed by the presolver must be minimization */
      if (ipp->orig_dir == LPX_MAX)
      {  for (col = ipp->col_ptr; col != NULL; col = col->next)
            col->c = - col->c;
         ipp->c0 = - ipp->c0;
      }
      /* free working arrays */
      xfree(row);
      xfree(ind);
      xfree(val);
      return;
}
int lpx_dual_ratio_test(LPX *lp, int len, const int ind[],
      const double val[], int how, double tol)
{     int k, m, n, t, q, tagx;
      double dir, alfa_j, abs_alfa_j, big, eps, cbar_j, temp, teta;
      if (!lpx_is_b_avail(lp))
         xfault("lpx_dual_ratio_test: LP basis is not available\n");
      if (lpx_get_dual_stat(lp) != LPX_D_FEAS)
         xfault("lpx_dual_ratio_test: current basic solution is not dua"
            "l feasible\n");
      if (!(how == +1 || how == -1))
         xfault("lpx_dual_ratio_test: how = %d; invalid parameter\n",
            how);
      m = lpx_get_num_rows(lp);
      n = lpx_get_num_cols(lp);
      dir = (lpx_get_obj_dir(lp) == LPX_MIN ? +1.0 : -1.0);
      /* compute the largest absolute value of the specified influence
         coefficients */
      big = 0.0;
      for (t = 1; t <= len; t++)
      {  temp = val[t];
         if (temp < 0.0) temp = - temp;
         if (big < temp) big = temp;
      }
      /* compute the absolute tolerance eps used to skip small entries
         of the row */
      if (!(0.0 < tol && tol < 1.0))
         xfault("lpx_dual_ratio_test: tol = %g; invalid tolerance\n",
            tol);
      eps = tol * (1.0 + big);
      /* initial settings */
      q = 0, teta = DBL_MAX, big = 0.0;
      /* walk through the entries of the specified row */
      for (t = 1; t <= len; t++)
      {  /* get ordinal number of non-basic variable */
         k = ind[t];
         if (!(1 <= k && k <= m+n))
            xfault("lpx_dual_ratio_test: ind[%d] = %d; variable number "
               "out of range\n", t, k);
         if (k <= m)
            tagx = lpx_get_row_stat(lp, k);
         else
            tagx = lpx_get_col_stat(lp, k-m);
         if (tagx == LPX_BS)
            xfault("lpx_dual_ratio_test: ind[%d] = %d; basic variable n"
               "ot allowed\n", t, k);
         /* determine unscaled reduced cost of the non-basic variable
            x[k] = xN[j] in the current basic solution */
         if (k <= m)
            cbar_j = lpx_get_row_dual(lp, k);
         else
            cbar_j = lpx_get_col_dual(lp, k-m);
         /* determine influence coefficient at the non-basic variable
            x[k] = xN[j] in the explicitly specified row and turn to
            the case of increasing the variable y in order to simplify
            program logic */
         alfa_j = (how > 0 ? +val[t] : -val[t]);
         abs_alfa_j = (alfa_j > 0.0 ? +alfa_j : -alfa_j);
         /* analyze main cases */
         switch (tagx)
         {  case LPX_NL:
               /* xN[j] is on its lower bound */
               if (alfa_j < +eps) continue;
               temp = (dir * cbar_j) / alfa_j;
               break;
            case LPX_NU:
               /* xN[j] is on its upper bound */
               if (alfa_j > -eps) continue;
               temp = (dir * cbar_j) / alfa_j;
               break;
            case LPX_NF:
               /* xN[j] is non-basic free variable */
               if (abs_alfa_j < eps) continue;
               temp = 0.0;
               break;
            case LPX_NS:
               /* xN[j] is non-basic fixed variable */
               continue;
            default:
               xassert(tagx != tagx);
         }
         /* if the reduced cost of the variable xN[j] violates its zero
            bound (slightly, because the current basis is assumed to be
            dual feasible), temp is negative; we can think this happens
            due to round-off errors and the reduced cost is exact zero;
            this allows replacing temp by zero */
         if (temp < 0.0) temp = 0.0;
         /* apply the minimal ratio test */
         if (teta > temp || teta == temp && big < abs_alfa_j)
            q = k, teta = temp, big = abs_alfa_j;
      }
      /* return the ordinal number of the chosen non-basic variable */
      return q;
}
int lpx_warm_up(LPX *lp)
{     int m, n, j, k, ret, type, stat, p_stat, d_stat;
      double lb, ub, prim, dual, tol_bnd, tol_dj, dir;
      double *row_prim, *row_dual, *col_prim, *col_dual, sum;
      m = lpx_get_num_rows(lp);
      n = lpx_get_num_cols(lp);
      /* reinvert the basis matrix, if necessary */
      if (lpx_is_b_avail(lp))
         ret = LPX_E_OK;
      else
      {  if (m == 0 || n == 0)
         {  ret = LPX_E_EMPTY;
            goto done;
         }
#if 0
         ret = lpx_invert(lp);
         switch (ret)
         {  case 0:
               ret = LPX_E_OK;
               break;
            case 1:
            case 2:
               ret = LPX_E_SING;
               goto done;
            case 3:
               ret = LPX_E_BADB;
               goto done;
            default:
               xassert(ret != ret);
         }
#else
         switch (glp_factorize(lp))
         {  case 0:
               ret = LPX_E_OK;
               break;
            case GLP_EBADB:
               ret = LPX_E_BADB;
               goto done;
            case GLP_ESING:
            case GLP_ECOND:
               ret = LPX_E_SING;
               goto done;
            default:
               xassert(lp != lp);
         }
#endif
      }
      /* allocate working arrays */
      row_prim = xcalloc(1+m, sizeof(double));
      row_dual = xcalloc(1+m, sizeof(double));
      col_prim = xcalloc(1+n, sizeof(double));
      col_dual = xcalloc(1+n, sizeof(double));
      /* compute primal basic solution components */
      lpx_eval_b_prim(lp, row_prim, col_prim);
      /* determine primal status of basic solution */
      tol_bnd = 3.0 * lpx_get_real_parm(lp, LPX_K_TOLBND);
      p_stat = LPX_P_FEAS;
      for (k = 1; k <= m+n; k++)
      {  if (k <= m)
         {  type = lpx_get_row_type(lp, k);
            lb = lpx_get_row_lb(lp, k);
            ub = lpx_get_row_ub(lp, k);
            prim = row_prim[k];
         }
         else
         {  type = lpx_get_col_type(lp, k-m);
            lb = lpx_get_col_lb(lp, k-m);
            ub = lpx_get_col_ub(lp, k-m);
            prim = col_prim[k-m];
         }
         if (type == LPX_LO || type == LPX_DB || type == LPX_FX)
         {  /* variable x[k] has lower bound */
            if (prim < lb - tol_bnd * (1.0 + fabs(lb)))
            {  p_stat = LPX_P_INFEAS;
               break;
            }
         }
         if (type == LPX_UP || type == LPX_DB || type == LPX_FX)
         {  /* variable x[k] has upper bound */
            if (prim > ub + tol_bnd * (1.0 + fabs(ub)))
            {  p_stat = LPX_P_INFEAS;
               break;
            }
         }
      }
      /* compute dual basic solution components */
      lpx_eval_b_dual(lp, row_dual, col_dual);
      /* determine dual status of basic solution */
      tol_dj = 3.0 * lpx_get_real_parm(lp, LPX_K_TOLDJ);
      dir = (lpx_get_obj_dir(lp) == LPX_MIN ? +1.0 : -1.0);
      d_stat = LPX_D_FEAS;
      for (k = 1; k <= m+n; k++)
      {  if (k <= m)
         {  stat = lpx_get_row_stat(lp, k);
            dual = row_dual[k];
         }
         else
         {  stat = lpx_get_col_stat(lp, k-m);
            dual = col_dual[k-m];
         }
         if (stat == LPX_BS || stat == LPX_NL || stat == LPX_NF)
         {  /* reduced cost of x[k] must be non-negative (minimization)
               or non-positive (maximization) */
            if (dir * dual < - tol_dj)
            {  d_stat = LPX_D_INFEAS;
               break;
            }
         }
         if (stat == LPX_BS || stat == LPX_NU || stat == LPX_NF)
         {  /* reduced cost of x[k] must be non-positive (minimization)
               or non-negative (maximization) */
            if (dir * dual > + tol_dj)
            {  d_stat = LPX_D_INFEAS;
               break;
            }
         }
      }
      /* store basic solution components */
      p_stat = p_stat - LPX_P_UNDEF + GLP_UNDEF;
      d_stat = d_stat - LPX_D_UNDEF + GLP_UNDEF;
      sum = lpx_get_obj_coef(lp, 0);
      for (j = 1; j <= n; j++)
         sum += lpx_get_obj_coef(lp, j) * col_prim[j];
      glp_put_solution(lp, 0, &p_stat, &d_stat, &sum,
         NULL, row_prim, row_dual, NULL, col_prim, col_dual);
      xassert(lpx_is_b_avail(lp));
      /* free working arrays */
      xfree(row_prim);
      xfree(row_dual);
      xfree(col_prim);
      xfree(col_dual);
done: /* return to the calling program */
      return ret;
}
Exemple #16
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;
}
Exemple #17
0
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;
}