Example #1
0
int main(int argc, char *argv[])
{     LPX *lp;
      MPL *mpl = NULL;
      int ret;
      ulong_t start;
      /* parse command line parameters */
      parse_cmdline(argc, argv);
      /* set available memory limit */
      if (memlim >= 0)
         lib_mem_limit(ulmul(ulset(0, 1048576), ulset(0, memlim)));
      /* remove all output files specified in the command line */
      if (display != NULL) remove(display);
      if (out_bas != NULL) remove(out_bas);
      if (out_sol != NULL) remove(out_sol);
      if (out_bnds != NULL) remove(out_bnds);
      if (out_mps != NULL) remove(out_mps);
      if (out_freemps != NULL) remove(out_freemps);
      if (out_cpxlp != NULL) remove(out_cpxlp);
      if (out_txt != NULL) remove(out_txt);
      if (out_glp != NULL) remove(out_glp);
      if (log_file != NULL) remove(log_file);
      /* open hardcopy file, if necessary */
      if (log_file != NULL)
      {  if (lib_open_log(log_file))
         {  print("Unable to create log file");
            exit(EXIT_FAILURE);
         }
      }
      /* read problem data from the input file */
      if (in_file == NULL)
      {  print("No input file specified; try %s --help", argv[0]);
         exit(EXIT_FAILURE);
      }
      switch (format)
      {  case 0:
            lp = lpx_read_mps(in_file);
            if (lp == NULL)
            {  print("MPS file processing error");
               exit(EXIT_FAILURE);
            }
            orig = 1;
            break;
         case 1:
            lp = lpx_read_cpxlp(in_file);
            if (lp == NULL)
            {  print("CPLEX LP file processing error");
               exit(EXIT_FAILURE);
            }
            break;
         case 2:
            /* initialize the translator database */
            mpl = mpl_initialize();
            /* read model section and optional data section */
            ret = mpl_read_model(mpl, in_file, in_data != NULL);
            if (ret == 4)
err:        {  print("Model processing error");
               exit(EXIT_FAILURE);
            }
            xassert(ret == 1 || ret == 2);
            /* read data section, if necessary */
            if (in_data != NULL)
            {  xassert(ret == 1);
               ret = mpl_read_data(mpl, in_data);
               if (ret == 4) goto err;
               xassert(ret == 2);
            }
            /* generate model */
            ret = mpl_generate(mpl, display);
            if (ret == 4) goto err;
            /* extract problem instance */
            lp = lpx_extract_prob(mpl);
            xassert(lp != NULL);
            break;
         case 3:
            lp = lpx_read_prob(in_file);
            if (lp == NULL)
            {  print("GNU LP file processing error");
               exit(EXIT_FAILURE);
            }
            break;
         case 4:
            lp = lpx_read_freemps(in_file);
            if (lp == NULL)
            {  print("MPS file processing error");
               exit(EXIT_FAILURE);
            }
            break;
         default:
            xassert(format != format);
      }
      /* order rows and columns of the constraint matrix */
      lpx_order_matrix(lp);
      /* change problem name (if required) */
      if (newname != NULL) lpx_set_prob_name(lp, newname);
      /* change optimization direction (if required) */
      if (dir != 0) lpx_set_obj_dir(lp, dir);
      /* write problem in fixed MPS format (if required) */
      if (out_mps != NULL)
      {  lpx_set_int_parm(lp, LPX_K_MPSORIG, orig);
         ret = lpx_write_mps(lp, out_mps);
         if (ret != 0)
         {  print("Unable to write problem in fixed MPS format");
            exit(EXIT_FAILURE);
         }
      }
      /* write problem in free MPS format (if required) */
      if (out_freemps != NULL)
      {  ret = lpx_write_freemps(lp, out_freemps);
         if (ret != 0)
         {  print("Unable to write problem in free MPS format");
            exit(EXIT_FAILURE);
         }
      }
      /* write problem in CPLEX LP format (if required) */
      if (out_cpxlp != NULL)
      {  ret = lpx_write_cpxlp(lp, out_cpxlp);
         if (ret != 0)
         {  print("Unable to write problem in CPLEX LP format");
            exit(EXIT_FAILURE);
         }
      }
      /* write problem in plain text format (if required) */
      if (out_txt != NULL)
      {  lpx_set_int_parm(lp, LPX_K_LPTORIG, orig);
         ret = lpx_print_prob(lp, out_txt);
         if (ret != 0)
         {  print("Unable to write problem in plain text format");
            exit(EXIT_FAILURE);
         }
      }
      /* write problem in GNU LP format (if required) */
      if (out_glp != NULL)
      {  ret = lpx_write_prob(lp, out_glp);
         if (ret != 0)
         {  print("Unable to write problem in GNU LP format");
            exit(EXIT_FAILURE);
         }
      }
      /* if only data check is required, skip computations */
      if (check) goto skip;
      /* scale the problem data (if required) */
      if (scale && (!presol || method == 1)) lpx_scale_prob(lp);
      /* build initial LP basis */
      if (method == 0 && !presol && in_bas == NULL)
      {  switch (basis)
         {  case 0:
               lpx_std_basis(lp);
               break;
            case 1:
               if (lpx_get_num_rows(lp) > 0 && lpx_get_num_cols(lp) > 0)
                  lpx_adv_basis(lp);
               break;
            case 2:
               if (lpx_get_num_rows(lp) > 0 && lpx_get_num_cols(lp) > 0)
                  lpx_cpx_basis(lp);
               break;
            default:
               xassert(basis != basis);
         }
      }
      /* or read initial basis from input text file in MPS format */
      if (in_bas != NULL)
      {  if (method != 0)
         {  print("Initial LP basis is useless for interior-point solve"
               "r and therefore ignored");
            goto nobs;
         }
         lpx_set_int_parm(lp, LPX_K_MPSORIG, orig);
         ret = lpx_read_bas(lp, in_bas);
         if (ret != 0)
         {  print("Unable to read initial LP basis");
            exit(EXIT_FAILURE);
         }
         if (presol)
         {  presol = 0;
            print("LP presolver disabled because initial LP basis has b"
               "een provided");
         }
nobs:    ;
      }
      /* set some control parameters, which might be changed in the
         command line */
      lpx_set_int_parm(lp, LPX_K_BFTYPE, bf_type);
      lpx_set_int_parm(lp, LPX_K_PRICE, price);
      if (!relax) lpx_set_real_parm(lp, LPX_K_RELAX, 0.0);
      lpx_set_int_parm(lp, LPX_K_PRESOL, presol);
      lpx_set_int_parm(lp, LPX_K_BRANCH, branch);
      lpx_set_int_parm(lp, LPX_K_BTRACK, btrack);
      lpx_set_real_parm(lp, LPX_K_TMLIM, (double)tmlim);
      lpx_set_int_parm(lp, LPX_K_BINARIZE, binarize);
      lpx_set_int_parm(lp, LPX_K_USECUTS, use_cuts);
      /* solve the problem */
      start = xtime();
      switch (method)
      {  case 0:
            if (nomip || lpx_get_class(lp) == LPX_LP)
            {  ret = (!exact ? lpx_simplex(lp) : lpx_exact(lp));
               if (xcheck)
               {  if (!presol || ret == LPX_E_OK)
                     lpx_exact(lp);
                  else
                     print("If you need checking final basis for non-op"
                        "timal solution, use --nopresol");
               }
               if (presol && ret != LPX_E_OK && (out_bas != NULL ||
                  out_sol != NULL))
                  print("If you need actual output for non-optimal solu"
                     "tion, use --nopresol");
            }
            else
            {  method = 2;
               if (!intopt)
               {  ret = (!exact ? lpx_simplex(lp) : lpx_exact(lp));
                  if (xcheck && (!presol || ret == LPX_E_OK))
                     lpx_exact(lp);
                  lpx_integer(lp);
               }
               else
                  lpx_intopt(lp);
            }
            break;
         case 1:
            if (nomip || lpx_get_class(lp) == LPX_LP)
               lpx_interior(lp);
            else
            {  print("Interior-point method is not able to solve MIP pr"
                  "oblem; use --simplex");
               exit(EXIT_FAILURE);
            }
            break;
         default:
            xassert(method != method);
      }
      /* display statistics */
      print("Time used:   %.1f secs", xdifftime(xtime(), start));
      {  ulong_t tpeak;
         char buf[50];
         lib_mem_usage(NULL, NULL, NULL, &tpeak);
         print("Memory used: %.1f Mb (%s bytes)",
            (4294967296.0 * tpeak.hi + tpeak.lo) / 1048576.0,
            ultoa(tpeak, buf, 10));
      }
      if (mpl != NULL && mpl_has_solve_stmt(mpl))
      {  int n, j, round;
         /* store the solution to the translator database */
         n = lpx_get_num_cols(lp);
         round = lpx_get_int_parm(lp, LPX_K_ROUND);
         lpx_set_int_parm(lp, LPX_K_ROUND, 1);
         switch (method)
         {  case 0:
               for (j = 1; j <= n; j++)
                  mpl_put_col_value(mpl, j, lpx_get_col_prim(lp, j));
               break;
            case 1:
               for (j = 1; j <= n; j++)
                  mpl_put_col_value(mpl, j, lpx_ipt_col_prim(lp, j));
               break;
            case 2:
               for (j = 1; j <= n; j++)
                  mpl_put_col_value(mpl, j, lpx_mip_col_val(lp, j));
               break;
            default:
               xassert(method != method);
         }
         lpx_set_int_parm(lp, LPX_K_ROUND, round);
         /* perform postsolving */
         ret = mpl_postsolve(mpl);
         if (ret == 4)
         {  print("Model postsolving error");
            exit(EXIT_FAILURE);
         }
         xassert(ret == 3);
      }
      /* write final LP basis (if required) */
      if (out_bas != NULL)
      {  lpx_set_int_parm(lp, LPX_K_MPSORIG, orig);
         ret = lpx_write_bas(lp, out_bas);
         if (ret != 0)
         {  print("Unable to write final LP basis");
            exit(EXIT_FAILURE);
         }
      }
      /* write problem solution found by the solver (if required) */
      if (out_sol != NULL)
      {  switch (method)
         {  case 0:
               ret = lpx_print_sol(lp, out_sol);
               break;
            case 1:
               ret = lpx_print_ips(lp, out_sol);
               break;
            case 2:
               ret = lpx_print_mip(lp, out_sol);
               break;
            default:
               xassert(method != method);
         }
         if (ret != 0)
         {  print("Unable to write problem solution");
            exit(EXIT_FAILURE);
         }
      }
      /* write sensitivity bounds information (if required) */
      if (out_bnds != NULL)
      {  if (method != 0)
         {  print("Cannot write sensitivity bounds information for inte"
               "rior-point or MIP solution");
            exit(EXIT_FAILURE);
         }
         ret = lpx_print_sens_bnds(lp, out_bnds);
         if (ret != 0)
         {  print("Unable to write sensitivity bounds information");
            exit(EXIT_FAILURE);
         }
      }
skip: /* delete the problem object */
      lpx_delete_prob(lp);
      /* if the translator database exists, destroy it */
      if (mpl != NULL) mpl_terminate(mpl);
      xassert(gmp_pool_count() == 0);
      gmp_free_mem();
      /* close the hardcopy file */
      if (log_file != NULL) lib_close_log();
      /* check that no memory blocks are still allocated */
      {  int count;
         ulong_t total;
         lib_mem_usage(&count, NULL, &total, NULL);
         xassert(count == 0);
         xassert(total.lo == 0 && total.hi == 0);
      }
      /* free the library environment */
      lib_free_env();
      /* return to the control program */
      return 0;
}
Example #2
0
void ios_feas_pump(glp_tree *T)
{     glp_prob *P = T->mip;
      int n = P->n;
      glp_prob *lp = NULL;
      struct VAR *var = NULL;
      RNG *rand = NULL;
      GLPCOL *col;
      glp_smcp parm;
      int j, k, new_x, nfail, npass, nv, ret, stalling;
      double dist, tol;
      xassert(glp_get_status(P) == GLP_OPT);
      /* this heuristic is applied only once on the root level */
      if (!(T->curr->level == 0 && T->curr->solved == 1)) goto done;
      /* determine number of binary variables */
      nv = 0;
      for (j = 1; j <= n; j++)
      {  col = P->col[j];
         /* if x[j] is continuous, skip it */
         if (col->kind == GLP_CV) continue;
         /* if x[j] is fixed, skip it */
         if (col->type == GLP_FX) continue;
         /* x[j] is non-fixed integer */
         xassert(col->kind == GLP_IV);
         if (col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0)
         {  /* x[j] is binary */
            nv++;
         }
         else
         {  /* x[j] is general integer */
            if (T->parm->msg_lev >= GLP_MSG_ALL)
               xprintf("FPUMP heuristic cannot be applied due to genera"
                  "l integer variables\n");
            goto done;
         }
      }
      /* there must be at least one binary variable */
      if (nv == 0) goto done;
      if (T->parm->msg_lev >= GLP_MSG_ALL)
         xprintf("Applying FPUMP heuristic...\n");
      /* build the list of binary variables */
      var = xcalloc(1+nv, sizeof(struct VAR));
      k = 0;
      for (j = 1; j <= n; j++)
      {  col = P->col[j];
         if (col->kind == GLP_IV && col->type == GLP_DB)
            var[++k].j = j;
      }
      xassert(k == nv);
      /* create working problem object */
      lp = glp_create_prob();
more: /* copy the original problem object to keep it intact */
      glp_copy_prob(lp, P, GLP_OFF);
      /* we are interested to find an integer feasible solution, which
         is better than the best known one */
      if (P->mip_stat == GLP_FEAS)
      {  int *ind;
         double *val, bnd;
         /* add a row and make it identical to the objective row */
         glp_add_rows(lp, 1);
         ind = xcalloc(1+n, sizeof(int));
         val = xcalloc(1+n, sizeof(double));
         for (j = 1; j <= n; j++)
         {  ind[j] = j;
            val[j] = P->col[j]->coef;
         }
         glp_set_mat_row(lp, lp->m, n, ind, val);
         xfree(ind);
         xfree(val);
         /* introduce upper (minimization) or lower (maximization)
            bound to the original objective function; note that this
            additional constraint is not violated at the optimal point
            to LP relaxation */
#if 0 /* modified by xypron <*****@*****.**> */
         if (P->dir == GLP_MIN)
         {  bnd = P->mip_obj - 0.10 * (1.0 + fabs(P->mip_obj));
            if (bnd < P->obj_val) bnd = P->obj_val;
            glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0);
         }
         else if (P->dir == GLP_MAX)
         {  bnd = P->mip_obj + 0.10 * (1.0 + fabs(P->mip_obj));
            if (bnd > P->obj_val) bnd = P->obj_val;
            glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0);
         }
         else
            xassert(P != P);
#else
         bnd = 0.1 * P->obj_val + 0.9 * P->mip_obj;
         /* xprintf("bnd = %f\n", bnd); */
         if (P->dir == GLP_MIN)
            glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0);
         else if (P->dir == GLP_MAX)
            glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0);
         else
            xassert(P != P);
#endif
      }
      /* reset pass count */
      npass = 0;
      /* invalidate the rounded point */
      for (k = 1; k <= nv; k++)
         var[k].x = -1;
pass: /* next pass starts here */
      npass++;
      if (T->parm->msg_lev >= GLP_MSG_ALL)
         xprintf("Pass %d\n", npass);
      /* initialize minimal distance between the basic point and the
         rounded one obtained during this pass */
      dist = DBL_MAX;
      /* reset failure count (the number of succeeded iterations failed
         to improve the distance) */
      nfail = 0;
      /* if it is not the first pass, perturb the last rounded point
         rather than construct it from the basic solution */
      if (npass > 1)
      {  double rho, temp;
         if (rand == NULL)
            rand = rng_create_rand();
         for (k = 1; k <= nv; k++)
         {  j = var[k].j;
            col = lp->col[j];
            rho = rng_uniform(rand, -0.3, 0.7);
            if (rho < 0.0) rho = 0.0;
            temp = fabs((double)var[k].x - col->prim);
            if (temp + rho > 0.5) var[k].x = 1 - var[k].x;
         }
         goto skip;
      }
loop: /* innermost loop begins here */
      /* round basic solution (which is assumed primal feasible) */
      stalling = 1;
      for (k = 1; k <= nv; k++)
      {  col = lp->col[var[k].j];
         if (col->prim < 0.5)
         {  /* rounded value is 0 */
            new_x = 0;
         }
         else
         {  /* rounded value is 1 */
            new_x = 1;
         }
         if (var[k].x != new_x)
         {  stalling = 0;
            var[k].x = new_x;
         }
      }
      /* if the rounded point has not changed (stalling), choose and
         flip some its entries heuristically */
      if (stalling)
      {  /* compute d[j] = |x[j] - round(x[j])| */
         for (k = 1; k <= nv; k++)
         {  col = lp->col[var[k].j];
            var[k].d = fabs(col->prim - (double)var[k].x);
         }
         /* sort the list of binary variables by descending d[j] */
         qsort(&var[1], nv, sizeof(struct VAR), fcmp);
         /* choose and flip some rounded components */
         for (k = 1; k <= nv; k++)
         {  if (k >= 5 && var[k].d < 0.35 || k >= 10) break;
            var[k].x = 1 - var[k].x;
         }
      }
skip: /* check if the time limit has been exhausted */
      if (T->parm->tm_lim < INT_MAX &&
         (double)(T->parm->tm_lim - 1) <=
         1000.0 * xdifftime(xtime(), T->tm_beg)) goto done;
      /* build the objective, which is the distance between the current
         (basic) point and the rounded one */
      lp->dir = GLP_MIN;
      lp->c0 = 0.0;
      for (j = 1; j <= n; j++)
         lp->col[j]->coef = 0.0;
      for (k = 1; k <= nv; k++)
      {  j = var[k].j;
         if (var[k].x == 0)
            lp->col[j]->coef = +1.0;
         else
         {  lp->col[j]->coef = -1.0;
            lp->c0 += 1.0;
         }
      }
      /* minimize the distance with the simplex method */
      glp_init_smcp(&parm);
      if (T->parm->msg_lev <= GLP_MSG_ERR)
         parm.msg_lev = T->parm->msg_lev;
      else if (T->parm->msg_lev <= GLP_MSG_ALL)
      {  parm.msg_lev = GLP_MSG_ON;
         parm.out_dly = 10000;
      }
      ret = glp_simplex(lp, &parm);
      if (ret != 0)
      {  if (T->parm->msg_lev >= GLP_MSG_ERR)
            xprintf("Warning: glp_simplex returned %d\n", ret);
         goto done;
      }
      ret = glp_get_status(lp);
      if (ret != GLP_OPT)
      {  if (T->parm->msg_lev >= GLP_MSG_ERR)
            xprintf("Warning: glp_get_status returned %d\n", ret);
         goto done;
      }
      if (T->parm->msg_lev >= GLP_MSG_DBG)
         xprintf("delta = %g\n", lp->obj_val);
      /* check if the basic solution is integer feasible; note that it
         may be so even if the minimial distance is positive */
      tol = 0.3 * T->parm->tol_int;
      for (k = 1; k <= nv; k++)
      {  col = lp->col[var[k].j];
         if (tol < col->prim && col->prim < 1.0 - tol) break;
      }
      if (k > nv)
      {  /* okay; the basic solution seems to be integer feasible */
         double *x = xcalloc(1+n, sizeof(double));
         for (j = 1; j <= n; j++)
         {  x[j] = lp->col[j]->prim;
            if (P->col[j]->kind == GLP_IV) x[j] = floor(x[j] + 0.5);
         }
#if 1 /* modified by xypron <*****@*****.**> */
         /* reset direction and right-hand side of objective */
         lp->c0  = P->c0;
         lp->dir = P->dir;
         /* fix integer variables */
         for (k = 1; k <= nv; k++)
#if 0 /* 18/VI-2013; fixed by mao
       * this bug causes numerical instability, because column statuses
       * are not changed appropriately */
         {  lp->col[var[k].j]->lb   = x[var[k].j];
            lp->col[var[k].j]->ub   = x[var[k].j];
            lp->col[var[k].j]->type = GLP_FX;
         }
#else
            glp_set_col_bnds(lp, var[k].j, GLP_FX, x[var[k].j], 0.);
#endif
         /* copy original objective function */
         for (j = 1; j <= n; j++)
            lp->col[j]->coef = P->col[j]->coef;
         /* solve original LP and copy result */
         ret = glp_simplex(lp, &parm);
         if (ret != 0)
         {  if (T->parm->msg_lev >= GLP_MSG_ERR)
               xprintf("Warning: glp_simplex returned %d\n", ret);
            goto done;
         }
         ret = glp_get_status(lp);
         if (ret != GLP_OPT)
         {  if (T->parm->msg_lev >= GLP_MSG_ERR)
               xprintf("Warning: glp_get_status returned %d\n", ret);
            goto done;
         }
         for (j = 1; j <= n; j++)
            if (P->col[j]->kind != GLP_IV) x[j] = lp->col[j]->prim;
#endif
         ret = glp_ios_heur_sol(T, x);
         xfree(x);
         if (ret == 0)
         {  /* the integer solution is accepted */
            if (ios_is_hopeful(T, T->curr->bound))
            {  /* it is reasonable to apply the heuristic once again */
               goto more;
            }
            else
            {  /* the best known integer feasible solution just found
                  is close to optimal solution to LP relaxation */
               goto done;
            }
         }
      }
Example #3
0
int ssx_driver(SSX *ssx)
{     int m = ssx->m;
      int *type = ssx->type;
      mpq_t *lb = ssx->lb;
      mpq_t *ub = ssx->ub;
      int *Q_col = ssx->Q_col;
      mpq_t *bbar = ssx->bbar;
      int i, k, ret;
      ssx->tm_beg = xtime();
      /* factorize the initial basis matrix */
      if (ssx_factorize(ssx))
      {  xprintf("Initial basis matrix is singular\n");
         ret = 7;
         goto done;
      }
      /* compute values of basic variables */
      ssx_eval_bbar(ssx);
      /* check if the initial basic solution is primal feasible */
      for (i = 1; i <= m; i++)
      {  int t;
         k = Q_col[i]; /* x[k] = xB[i] */
         t = type[k];
         if (t == SSX_LO || t == SSX_DB || t == SSX_FX)
         {  /* x[k] has lower bound */
            if (mpq_cmp(bbar[i], lb[k]) < 0)
            {  /* which is violated */
               break;
            }
         }
         if (t == SSX_UP || t == SSX_DB || t == SSX_FX)
         {  /* x[k] has upper bound */
            if (mpq_cmp(bbar[i], ub[k]) > 0)
            {  /* which is violated */
               break;
            }
         }
      }
      if (i > m)
      {  /* no basic variable violates its bounds */
         ret = 0;
         goto skip;
      }
      /* phase I: find primal feasible solution */
      ret = ssx_phase_I(ssx);
      switch (ret)
      {  case 0:
            ret = 0;
            break;
         case 1:
            //xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n");
            ret = 1;
            break;
         case 2:
            xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n");
            ret = 3;
            break;
         case 3:
            xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
            ret = 5;
            break;
         default:
            xassert(ret != ret);
      }
      /* compute values of basic variables (actually only the objective
         value needs to be computed) */
      ssx_eval_bbar(ssx);
skip: /* compute simplex multipliers */
      ssx_eval_pi(ssx);
      /* compute reduced costs of non-basic variables */
      ssx_eval_cbar(ssx);
      /* if phase I failed, do not start phase II */
      if (ret != 0) goto done;
      /* phase II: find optimal solution */
      ret = ssx_phase_II(ssx);
      switch (ret)
      {  case 0:
            //xprintf("OPTIMAL SOLUTION FOUND\n");
            ret = 0;
            break;
         case 1:
            //xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n");
            ret = 2;
            break;
         case 2:
            xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n");
            ret = 4;
            break;
         case 3:
            xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
            ret = 6;
            break;
         default:
            xassert(ret != ret);
      }
done: /* decrease the time limit by the spent amount of time */
      if (ssx->tm_lim >= 0.0)
#if 0
      {  ssx->tm_lim -= utime() - ssx->tm_beg;
#else
      {  ssx->tm_lim -= xdifftime(xtime(), ssx->tm_beg);
#endif
         if (ssx->tm_lim < 0.0) ssx->tm_lim = 0.0;
      }
      return ret;
}
Example #4
0
int ssx_phase_I(SSX *ssx)
{     int m = ssx->m;
      int n = ssx->n;
      int *type = ssx->type;
      mpq_t *lb = ssx->lb;
      mpq_t *ub = ssx->ub;
      mpq_t *coef = ssx->coef;
      int *A_ptr = ssx->A_ptr;
      int *A_ind = ssx->A_ind;
      mpq_t *A_val = ssx->A_val;
      int *Q_col = ssx->Q_col;
      mpq_t *bbar = ssx->bbar;
      mpq_t *pi = ssx->pi;
      mpq_t *cbar = ssx->cbar;
      int *orig_type, orig_dir;
      mpq_t *orig_lb, *orig_ub, *orig_coef;
      int i, k, ret;
      /* save components of the original LP problem, which are changed
         by the routine */
      orig_type = xcalloc(1+m+n, sizeof(int));
      orig_lb = xcalloc(1+m+n, sizeof(mpq_t));
      orig_ub = xcalloc(1+m+n, sizeof(mpq_t));
      orig_coef = xcalloc(1+m+n, sizeof(mpq_t));
      for (k = 1; k <= m+n; k++)
      {  orig_type[k] = type[k];
         mpq_init(orig_lb[k]);
         mpq_set(orig_lb[k], lb[k]);
         mpq_init(orig_ub[k]);
         mpq_set(orig_ub[k], ub[k]);
      }
      orig_dir = ssx->dir;
      for (k = 0; k <= m+n; k++)
      {  mpq_init(orig_coef[k]);
         mpq_set(orig_coef[k], coef[k]);
      }
      /* build an artificial basic solution, which is primal feasible,
         and also build an auxiliary objective function to minimize the
         sum of infeasibilities for the original problem */
      ssx->dir = SSX_MIN;
      for (k = 0; k <= m+n; k++) mpq_set_si(coef[k], 0, 1);
      mpq_set_si(bbar[0], 0, 1);
      for (i = 1; i <= m; i++)
      {  int t;
         k = Q_col[i]; /* x[k] = xB[i] */
         t = type[k];
         if (t == SSX_LO || t == SSX_DB || t == SSX_FX)
         {  /* in the original problem x[k] has lower bound */
            if (mpq_cmp(bbar[i], lb[k]) < 0)
            {  /* which is violated */
               type[k] = SSX_UP;
               mpq_set(ub[k], lb[k]);
               mpq_set_si(lb[k], 0, 1);
               mpq_set_si(coef[k], -1, 1);
               mpq_add(bbar[0], bbar[0], ub[k]);
               mpq_sub(bbar[0], bbar[0], bbar[i]);
            }
         }
         if (t == SSX_UP || t == SSX_DB || t == SSX_FX)
         {  /* in the original problem x[k] has upper bound */
            if (mpq_cmp(bbar[i], ub[k]) > 0)
            {  /* which is violated */
               type[k] = SSX_LO;
               mpq_set(lb[k], ub[k]);
               mpq_set_si(ub[k], 0, 1);
               mpq_set_si(coef[k], +1, 1);
               mpq_add(bbar[0], bbar[0], bbar[i]);
               mpq_sub(bbar[0], bbar[0], lb[k]);
            }
         }
      }
      /* now the initial basic solution should be primal feasible due
         to changes of bounds of some basic variables, which turned to
         implicit artifical variables */
      /* compute simplex multipliers and reduced costs */
      ssx_eval_pi(ssx);
      ssx_eval_cbar(ssx);
      /* display initial progress of the search */
      show_progress(ssx, 1);
      /* main loop starts here */
      for (;;)
      {  /* display current progress of the search */
#if 0
         if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001)
#else
         if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001)
#endif
            show_progress(ssx, 1);
         /* we do not need to wait until all artificial variables have
            left the basis */
         if (mpq_sgn(bbar[0]) == 0)
         {  /* the sum of infeasibilities is zero, therefore the current
               solution is primal feasible for the original problem */
            ret = 0;
            break;
         }
         /* check if the iterations limit has been exhausted */
         if (ssx->it_lim == 0)
         {  ret = 2;
            break;
         }
         /* check if the time limit has been exhausted */
#if 0
         if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg)
#else
         if (ssx->tm_lim >= 0.0 &&
             ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg))
#endif
         {  ret = 3;
            break;
         }
         /* choose non-basic variable xN[q] */
         ssx_chuzc(ssx);
         /* if xN[q] cannot be chosen, the sum of infeasibilities is
            minimal but non-zero; therefore the original problem has no
            primal feasible solution */
         if (ssx->q == 0)
         {  ret = 1;
            break;
         }
         /* compute q-th column of the simplex table */
         ssx_eval_col(ssx);
         /* choose basic variable xB[p] */
         ssx_chuzr(ssx);
         /* the sum of infeasibilities cannot be negative, therefore
            the auxiliary lp problem cannot have unbounded solution */
         xassert(ssx->p != 0);
         /* update values of basic variables */
         ssx_update_bbar(ssx);
         if (ssx->p > 0)
         {  /* compute p-th row of the inverse inv(B) */
            ssx_eval_rho(ssx);
            /* compute p-th row of the simplex table */
            ssx_eval_row(ssx);
            xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0);
            /* update simplex multipliers */
            ssx_update_pi(ssx);
            /* update reduced costs of non-basic variables */
            ssx_update_cbar(ssx);
         }
         /* xB[p] is leaving the basis; if it is implicit artificial
            variable, the corresponding residual vanishes; therefore
            bounds of this variable should be restored to the original
            values */
         if (ssx->p > 0)
         {  k = Q_col[ssx->p]; /* x[k] = xB[p] */
            if (type[k] != orig_type[k])
            {  /* x[k] is implicit artificial variable */
               type[k] = orig_type[k];
               mpq_set(lb[k], orig_lb[k]);
               mpq_set(ub[k], orig_ub[k]);
               xassert(ssx->p_stat == SSX_NL || ssx->p_stat == SSX_NU);
               ssx->p_stat = (ssx->p_stat == SSX_NL ? SSX_NU : SSX_NL);
               if (type[k] == SSX_FX) ssx->p_stat = SSX_NS;
               /* nullify the objective coefficient at x[k] */
               mpq_set_si(coef[k], 0, 1);
               /* since coef[k] has been changed, we need to compute
                  new reduced cost of x[k], which it will have in the
                  adjacent basis */
               /* the formula d[j] = cN[j] - pi' * N[j] is used (note
                  that the vector pi is not changed, because it depends
                  on objective coefficients at basic variables, but in
                  the adjacent basis, for which the vector pi has been
                  just recomputed, x[k] is non-basic) */
               if (k <= m)
               {  /* x[k] is auxiliary variable */
                  mpq_neg(cbar[ssx->q], pi[k]);
               }
               else
               {  /* x[k] is structural variable */
                  int ptr;
                  mpq_t temp;
                  mpq_init(temp);
                  mpq_set_si(cbar[ssx->q], 0, 1);
                  for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++)
                  {  mpq_mul(temp, pi[A_ind[ptr]], A_val[ptr]);
                     mpq_add(cbar[ssx->q], cbar[ssx->q], temp);
                  }
                  mpq_clear(temp);
               }
            }
         }
         /* jump to the adjacent vertex of the polyhedron */
         ssx_change_basis(ssx);
         /* one simplex iteration has been performed */
         if (ssx->it_lim > 0) ssx->it_lim--;
         ssx->it_cnt++;
      }
      /* display final progress of the search */
      show_progress(ssx, 1);
      /* restore components of the original problem, which were changed
         by the routine */
      for (k = 1; k <= m+n; k++)
      {  type[k] = orig_type[k];
         mpq_set(lb[k], orig_lb[k]);
         mpq_clear(orig_lb[k]);
         mpq_set(ub[k], orig_ub[k]);
         mpq_clear(orig_ub[k]);
      }
      ssx->dir = orig_dir;
      for (k = 0; k <= m+n; k++)
      {  mpq_set(coef[k], orig_coef[k]);
         mpq_clear(orig_coef[k]);
      }
      xfree(orig_type);
      xfree(orig_lb);
      xfree(orig_ub);
      xfree(orig_coef);
      /* return to the calling program */
      return ret;
}
Example #5
0
int ios_pcost_branch(glp_tree *T, int *_next)
{     /* choose branching variable with pseudocost branching */
      glp_long t = xtime();
      int j, jjj, sel;
      double beta, psi, d1, d2, d, dmax;
      /* initialize the working arrays */
      if (T->pcost == NULL)
         T->pcost = ios_pcost_init(T);
      /* nothing has been chosen so far */
      jjj = 0, dmax = -1.0;
      /* go through the list of branching candidates */
      for (j = 1; j <= T->n; j++)
      {  if (!glp_ios_can_branch(T, j)) continue;
         /* determine primal value of x[j] in optimal solution to LP
            relaxation of the current subproblem */
         beta = T->mip->col[j]->prim;
         /* estimate pseudocost of x[j] for down-branch */
         psi = eval_psi(T, j, GLP_DN_BRNCH);
         if (psi == DBL_MAX)
         {  /* down-branch has no primal feasible solution */
            jjj = j, sel = GLP_DN_BRNCH;
            goto done;
         }
         /* estimate degradation of the objective for down-branch */
         d1 = psi * (beta - floor(beta));
         /* estimate pseudocost of x[j] for up-branch */
         psi = eval_psi(T, j, GLP_UP_BRNCH);
         if (psi == DBL_MAX)
         {  /* up-branch has no primal feasible solution */
            jjj = j, sel = GLP_UP_BRNCH;
            goto done;
         }
         /* estimate degradation of the objective for up-branch */
         d2 = psi * (ceil(beta) - beta);
         /* determine d = max(d1, d2) */
         d = (d1 > d2 ? d1 : d2);
         /* choose x[j] which provides maximal estimated degradation of
            the objective either in down- or up-branch */
         if (dmax < d)
         {  dmax = d;
            jjj = j;
            /* continue the search from a subproblem, where degradation
               is less than in other one */
            sel = (d1 <= d2 ? GLP_DN_BRNCH : GLP_UP_BRNCH);
         }
         /* display progress of pseudocost initialization */
         if (T->parm->msg_lev >= GLP_ON)
         {  if (xdifftime(xtime(), t) >= 10.0)
            {  progress(T);
               t = xtime();
            }
         }
      }
      if (dmax == 0.0)
      {  /* no degradation is indicated; choose a variable having most
            fractional value */
         jjj = branch_mostf(T, &sel);
      }
done: *_next = sel;
      return jjj;
}
Example #6
0
int ssx_phase_II(SSX *ssx)
{     int ret;
      /* display initial progress of the search */
      show_progress(ssx, 2);
      /* main loop starts here */
      for (;;)
      {  /* display current progress of the search */
#if 0
         if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001)
#else
         if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001)
#endif
            show_progress(ssx, 2);
         /* check if the iterations limit has been exhausted */
         if (ssx->it_lim == 0)
         {  ret = 2;
            break;
         }
         /* check if the time limit has been exhausted */
#if 0
         if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg)
#else
         if (ssx->tm_lim >= 0.0 &&
             ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg))
#endif
         {  ret = 3;
            break;
         }
         /* choose non-basic variable xN[q] */
         ssx_chuzc(ssx);
         /* if xN[q] cannot be chosen, the current basic solution is
            dual feasible and therefore optimal */
         if (ssx->q == 0)
         {  ret = 0;
            break;
         }
         /* compute q-th column of the simplex table */
         ssx_eval_col(ssx);
         /* choose basic variable xB[p] */
         ssx_chuzr(ssx);
         /* if xB[p] cannot be chosen, the problem has no dual feasible
            solution (i.e. unbounded) */
         if (ssx->p == 0)
         {  ret = 1;
            break;
         }
         /* update values of basic variables */
         ssx_update_bbar(ssx);
         if (ssx->p > 0)
         {  /* compute p-th row of the inverse inv(B) */
            ssx_eval_rho(ssx);
            /* compute p-th row of the simplex table */
            ssx_eval_row(ssx);
            xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0);
#if 0
            /* update simplex multipliers */
            ssx_update_pi(ssx);
#endif
            /* update reduced costs of non-basic variables */
            ssx_update_cbar(ssx);
         }
         /* jump to the adjacent vertex of the polyhedron */
         ssx_change_basis(ssx);
         /* one simplex iteration has been performed */
         if (ssx->it_lim > 0) ssx->it_lim--;
         ssx->it_cnt++;
      }
      /* display final progress of the search */
      show_progress(ssx, 2);
      /* return to the calling program */
      return ret;
}
Example #7
0
static void choose_pivot(struct csa *csa)
{     SPXLP *lp = csa->lp;
      int m = lp->m;
      int n = lp->n;
      double *l = lp->l;
      int *head = lp->head;
      SPXAT *at = csa->at;
      SPXNT *nt = csa->nt;
      double *beta = csa->beta;
      double *d = csa->d;
      SPYSE *se = csa->se;
      int *list = csa->list;
      double *rho = csa->work;
      double *trow = csa->work1;
      int nnn, try, k, p, q, t;
      xassert(csa->beta_st);
      xassert(csa->d_st);
      /* initial number of eligible basic variables */
      nnn = csa->num;
      /* nothing has been chosen so far */
      csa->p = 0;
      try = 0;
try:  /* choose basic variable xB[p] */
      xassert(nnn > 0);
      try++;
      if (se == NULL)
      {  /* dual Dantzig's rule */
         p = spy_chuzr_std(lp, beta, nnn, list);
      }
      else
      {  /* dual projected steepest edge */
         p = spy_chuzr_pse(lp, se, beta, nnn, list);
      }
      xassert(1 <= p && p <= m);
      /* compute p-th row of inv(B) */
      spx_eval_rho(lp, p, rho);
      /* compute p-th row of the simplex table */
      if (at != NULL)
         spx_eval_trow1(lp, at, rho, trow);
      else
         spx_nt_prod(lp, nt, trow, 1, -1.0, rho);
      /* choose non-basic variable xN[q] */
      k = head[p]; /* x[k] = xB[p] */
      if (!csa->harris)
         q = spy_chuzc_std(lp, d, beta[p] < l[k] ? +1. : -1., trow,
            csa->tol_piv, .30 * csa->tol_dj, .30 * csa->tol_dj1);
      else
         q = spy_chuzc_harris(lp, d, beta[p] < l[k] ? +1. : -1., trow,
            csa->tol_piv, .35 * csa->tol_dj, .35 * csa->tol_dj1);
      /* either keep previous choice or accept new choice depending on
       * which one is better */
      if (csa->p == 0 || q == 0 ||
         fabs(trow[q]) > fabs(csa->trow[csa->q]))
      {  csa->p = p;
         memcpy(&csa->trow[1], &trow[1], (n-m) * sizeof(double));
         csa->q = q;
      }
      /* check if current choice is acceptable */
      if (csa->q == 0 || fabs(csa->trow[csa->q]) >= 0.001)
         goto done;
      if (nnn == 1)
         goto done;
      if (try == 5)
         goto done;
      /* try to choose other xB[p] and xN[q] */
      /* find xB[p] in the list */
      for (t = 1; t <= nnn; t++)
         if (list[t] == p) break;
      xassert(t <= nnn);
      /* move xB[p] to the end of the list */
      list[t] = list[nnn], list[nnn] = p;
      /* and exclude it from consideration */
      nnn--;
      /* repeat the choice */
      goto try;
done: /* the choice has been made */
      return;
}

/***********************************************************************
*  display - display search progress
*
*  This routine displays some information about the search progress
*  that includes:
*
*  search phase;
*
*  number of simplex iterations performed by the solver;
*
*  original objective value (only on phase II);
*
*  sum of (scaled) dual infeasibilities for original bounds;
*
*  number of dual infeasibilities (phase I) or primal infeasibilities
*  (phase II);
*
*  number of basic factorizations since last display output. */

static void display(struct csa *csa, int spec)
{     SPXLP *lp = csa->lp;
      int m = lp->m;
      int n = lp->n;
      int *head = lp->head;
      char *flag = lp->flag;
      double *l = csa->l; /* original lower bounds */
      double *u = csa->u; /* original upper bounds */
      double *beta = csa->beta;
      double *d = csa->d;
      int j, k, nnn;
      double sum;
      /* check if the display output should be skipped */
      if (csa->msg_lev < GLP_MSG_ON) goto skip;
      if (csa->out_dly > 0 &&
         1000.0 * xdifftime(xtime(), csa->tm_beg) < csa->out_dly)
         goto skip;
      if (csa->it_cnt == csa->it_dpy) goto skip;
      if (!spec && csa->it_cnt % csa->out_frq != 0) goto skip;
      /* display search progress depending on search phase */
      switch (csa->phase)
      {  case 1:
            /* compute sum and number of (scaled) dual infeasibilities
             * for original bounds */
            sum = 0.0, nnn = 0;
            for (j = 1; j <= n-m; j++)
            {  k = head[m+j]; /* x[k] = xN[j] */
               if (d[j] > 0.0)
               {  /* xN[j] should have lower bound */
                  if (l[k] == -DBL_MAX)
                  {  sum += d[j];
                     if (d[j] > +1e-7)
                        nnn++;
                  }
               }
               else if (d[j] < 0.0)
               {  /* xN[j] should have upper bound */
                  if (u[k] == +DBL_MAX)
                  {  sum -= d[j];
                     if (d[j] < -1e-7)
                        nnn++;
                  }
               }
            }
            /* on phase I variables have artificial bounds which are
             * meaningless for original LP, so corresponding objective
             * function value is also meaningless */
            xprintf(" %6d: %23s inf = %11.3e (%d)",
               csa->it_cnt, "", sum, nnn);
            break;
         case 2:
            /* compute sum of (scaled) dual infeasibilities */
            sum = 0.0, nnn = 0;
            for (j = 1; j <= n-m; j++)
            {  k = head[m+j]; /* x[k] = xN[j] */
               if (d[j] > 0.0)
               {  /* xN[j] should have its lower bound active */
                  if (l[k] == -DBL_MAX || flag[j])
                     sum += d[j];
               }
               else if (d[j] < 0.0)
               {  /* xN[j] should have its upper bound active */
                  if (l[k] != u[k] && !flag[j])
                     sum -= d[j];
               }
            }
            /* compute number of primal infeasibilities */
            nnn = spy_chuzr_sel(lp, beta, csa->tol_bnd, csa->tol_bnd1,
               NULL);
            xprintf("#%6d: obj = %17.9e inf = %11.3e (%d)",
               csa->it_cnt, (double)csa->dir * spx_eval_obj(lp, beta),
               sum, nnn);
            break;
         default:
            xassert(csa != csa);
      }
      if (csa->inv_cnt)
      {  /* number of basis factorizations performed */
         xprintf(" %d", csa->inv_cnt);
         csa->inv_cnt = 0;
      }
      xprintf("\n");
      csa->it_dpy = csa->it_cnt;
skip: return;
}

/***********************************************************************
*  spy_dual - driver to dual simplex method
*
*  This routine is a driver to the two-phase dual simplex method.
*
*  On exit this routine returns one of the following codes:
*
*  0  LP instance has been successfully solved.
*
*  GLP_EOBJLL
*     Objective lower limit has been reached (maximization).
*
*  GLP_EOBJUL
*     Objective upper limit has been reached (minimization).
*
*  GLP_EITLIM
*     Iteration limit has been exhausted.
*
*  GLP_ETMLIM
*     Time limit has been exhausted.
*
*  GLP_EFAIL
*     The solver failed to solve LP instance. */

static int dual_simplex(struct csa *csa)
{     /* dual simplex method main logic routine */
      SPXLP *lp = csa->lp;
      int m = lp->m;
      int n = lp->n;
      double *l = lp->l;
      double *u = lp->u;
      int *head = lp->head;
      SPXNT *nt = csa->nt;
      double *beta = csa->beta;
      double *d = csa->d;
      SPYSE *se = csa->se;
      int *list = csa->list;
      double *trow = csa->trow;
      double *tcol = csa->tcol;
      double *pi = csa->work;
      int msg_lev = csa->msg_lev;
      double tol_bnd = csa->tol_bnd;
      double tol_bnd1 = csa->tol_bnd1;
      double tol_dj = csa->tol_dj;
      double tol_dj1 = csa->tol_dj1;
      int j, k, p_flag, refct, ret;
      check_flags(csa);
loop: /* main loop starts here */
      /* compute factorization of the basis matrix */
      if (!lp->valid)
      {  double cond;
         ret = spx_factorize(lp);
         csa->inv_cnt++;
         if (ret != 0)
         {  if (msg_lev >= GLP_MSG_ERR)
               xprintf("Error: unable to factorize the basis matrix (%d"
                  ")\n", ret);
            csa->p_stat = csa->d_stat = GLP_UNDEF;
            ret = GLP_EFAIL;
            goto fini;
         }
         /* check condition of the basis matrix */
         cond = bfd_condest(lp->bfd);
         if (cond > 1.0 / DBL_EPSILON)
         {  if (msg_lev >= GLP_MSG_ERR)
               xprintf("Error: basis matrix is singular to working prec"
                  "ision (cond = %.3g)\n", cond);
            csa->p_stat = csa->d_stat = GLP_UNDEF;
            ret = GLP_EFAIL;
            goto fini;
         }
         if (cond > 0.001 / DBL_EPSILON)
         {  if (msg_lev >= GLP_MSG_ERR)
               xprintf("Warning: basis matrix is ill-conditioned (cond "
                  "= %.3g)\n", cond);
         }
         /* invalidate basic solution components */
         csa->beta_st = csa->d_st = 0;
      }
      /* compute reduced costs of non-basic variables d = (d[j]) */
      if (!csa->d_st)
      {  spx_eval_pi(lp, pi);
         for (j = 1; j <= n-m; j++)
            d[j] = spx_eval_dj(lp, pi, j);
         csa->d_st = 1; /* just computed */
         /* determine the search phase, if not determined yet (this is
          * performed only once at the beginning of the search for the
          * original bounds) */
         if (!csa->phase)
         {  j = check_feas(csa, 0.97 * tol_dj, 0.97 * tol_dj1, 1);
            if (j > 0)
            {  /* initial basic solution is dual infeasible and cannot
                * be recovered */
               /* start to search for dual feasible solution */
               set_art_bounds(csa);
               csa->phase = 1;
            }
            else
            {  /* initial basic solution is either dual feasible or its
                * dual feasibility has been recovered */
               /* start to search for optimal solution */
               csa->phase = 2;
            }
         }
         /* make sure that current basic solution is dual feasible */
         j = check_feas(csa, tol_dj, tol_dj1, 0);
         if (j)
         {  /* dual feasibility is broken due to excessive round-off
             * errors */
            if (bfd_get_count(lp->bfd))
            {  /* try to provide more accuracy */
               lp->valid = 0;
               goto loop;
            }
            if (msg_lev >= GLP_MSG_ERR)
               xprintf("Warning: numerical instability (dual simplex, p"
                  "hase %s)\n", csa->phase == 1 ? "I" : "II");
            if (csa->dualp)
            {  /* do not continue the search; report failure */
               csa->p_stat = csa->d_stat = GLP_UNDEF;
               ret = -1; /* special case of GLP_EFAIL */
               goto fini;
            }
            /* try to recover dual feasibility */
            j = check_feas(csa, 0.97 * tol_dj, 0.97 * tol_dj1, 1);
            if (j > 0)
            {  /* dual feasibility cannot be recovered (this may happen
                * only on phase II) */
               xassert(csa->phase == 2);
               /* restart to search for dual feasible solution */
               set_art_bounds(csa);
               csa->phase = 1;
            }
         }
      }
      /* at this point the search phase is determined */
      xassert(csa->phase == 1 || csa->phase == 2);
      /* compute values of basic variables beta = (beta[i]) */
      if (!csa->beta_st)
      {  spx_eval_beta(lp, beta);
         csa->beta_st = 1; /* just computed */
      }
      /* reset the dual reference space, if necessary */
      if (se != NULL && !se->valid)
         spy_reset_refsp(lp, se), refct = 1000;
      /* at this point the basis factorization and all basic solution
       * components are valid */
      xassert(lp->valid && csa->beta_st && csa->d_st);
      check_flags(csa);
#if CHECK_ACCURACY
      /* check accuracy of current basic solution components (only for
       * debugging) */
      check_accuracy(csa);
#endif
      /* check if the objective limit has been reached */
      if (csa->phase == 2 && csa->obj_lim != DBL_MAX
         && spx_eval_obj(lp, beta) >= csa->obj_lim)
      {  if (csa->beta_st != 1)
            csa->beta_st = 0;
         if (csa->d_st != 1)
            csa->d_st = 0;
         if (!(csa->beta_st && csa->d_st))
            goto loop;
         display(csa, 1);
         if (msg_lev >= GLP_MSG_ALL)
            xprintf("OBJECTIVE %s LIMIT REACHED; SEARCH TERMINATED\n",
               csa->dir > 0 ? "UPPER" : "LOWER");
         csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, list);
         csa->p_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS);
         csa->d_stat = GLP_FEAS;
         ret = (csa->dir > 0 ? GLP_EOBJUL : GLP_EOBJLL);
         goto fini;
      }
      /* check if the iteration limit has been exhausted */
      if (csa->it_cnt - csa->it_beg >= csa->it_lim)
      {  if (csa->beta_st != 1)
            csa->beta_st = 0;
         if (csa->d_st != 1)
            csa->d_st = 0;
         if (!(csa->beta_st && csa->d_st))
            goto loop;
         display(csa, 1);
         if (msg_lev >= GLP_MSG_ALL)
            xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n");
         if (csa->phase == 1)
         {  set_orig_bounds(csa);
            check_flags(csa);
            spx_eval_beta(lp, beta);
         }
         csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, list);
         csa->p_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS);
         csa->d_stat = (csa->phase == 1 ? GLP_INFEAS : GLP_FEAS);
         ret = GLP_EITLIM;
         goto fini;
      }
      /* check if the time limit has been exhausted */
      if (1000.0 * xdifftime(xtime(), csa->tm_beg) >= csa->tm_lim)
      {  if (csa->beta_st != 1)
            csa->beta_st = 0;
         if (csa->d_st != 1)
            csa->d_st = 0;
         if (!(csa->beta_st && csa->d_st))
            goto loop;
         display(csa, 1);
         if (msg_lev >= GLP_MSG_ALL)
            xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
         if (csa->phase == 1)
         {  set_orig_bounds(csa);
            check_flags(csa);
            spx_eval_beta(lp, beta);
         }
         csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, list);
         csa->p_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS);
         csa->d_stat = (csa->phase == 1 ? GLP_INFEAS : GLP_FEAS);
         ret = GLP_EITLIM;
         goto fini;
      }
      /* display the search progress */
      display(csa, 0);
      /* select eligible basic variables */
      switch (csa->phase)
      {  case 1:
            csa->num = spy_chuzr_sel(lp, beta, 1e-8, 0.0, list);
            break;
         case 2:
            csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, list);
            break;
         default:
            xassert(csa != csa);
      }
      /* check for optimality */
      if (csa->num == 0)
      {  if (csa->beta_st != 1)
            csa->beta_st = 0;
         if (csa->d_st != 1)
            csa->d_st = 0;
         if (!(csa->beta_st && csa->d_st))
            goto loop;
         /* current basis is optimal */
         display(csa, 1);
         switch (csa->phase)
         {  case 1:
               /* check for dual feasibility */
               set_orig_bounds(csa);
               check_flags(csa);
               if (check_feas(csa, tol_dj, tol_dj1, 0) == 0)
               {  /* dual feasible solution found; switch to phase II */
                  csa->phase = 2;
                  xassert(!csa->beta_st);
                  goto loop;
               }
               /* no dual feasible solution exists */
               if (msg_lev >= GLP_MSG_ALL)
                  xprintf("LP HAS NO DUAL FEASIBLE SOLUTION\n");
               spx_eval_beta(lp, beta);
               csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1,
                  list);
               csa->p_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS);
               csa->d_stat = GLP_NOFEAS;
               ret = 0;
               goto fini;
            case 2:
               /* optimal solution found */
               if (msg_lev >= GLP_MSG_ALL)
                  xprintf("OPTIMAL LP SOLUTION FOUND\n");
               csa->p_stat = csa->d_stat = GLP_FEAS;
               ret = 0;
               goto fini;
            default:
               xassert(csa != csa);
         }
      }
      /* choose xB[p] and xN[q] */
      choose_pivot(csa);
      /* check for dual unboundedness */
      if (csa->q == 0)
      {  if (csa->beta_st != 1)
            csa->beta_st = 0;
         if (csa->d_st != 1)
            csa->d_st = 0;
         if (!(csa->beta_st && csa->d_st))
            goto loop;
         display(csa, 1);
         switch (csa->phase)
         {  case 1:
               /* this should never happen */
               if (msg_lev >= GLP_MSG_ERR)
                  xprintf("Error: dual simplex failed\n");
               csa->p_stat = csa->d_stat = GLP_UNDEF;
               ret = GLP_EFAIL;
               goto fini;
            case 2:
               /* dual unboundedness detected */
               if (msg_lev >= GLP_MSG_ALL)
                  xprintf("LP HAS NO PRIMAL FEASIBLE SOLUTION\n");
               csa->p_stat = GLP_NOFEAS;
               csa->d_stat = GLP_FEAS;
               ret = 0;
               goto fini;
            default:
               xassert(csa != csa);
         }
      }
      /* compute q-th column of the simplex table */
      spx_eval_tcol(lp, csa->q, tcol);
      /* FIXME: tcol[p] and trow[q] should be close to each other */
      xassert(tcol[csa->p] != 0.0);
      /* update values of basic variables for adjacent basis */
      k = head[csa->p]; /* x[k] = xB[p] */
      p_flag = (l[k] != u[k] && beta[csa->p] > u[k]);
      spx_update_beta(lp, beta, csa->p, p_flag, csa->q, tcol);
      csa->beta_st = 2;
      /* update reduced costs of non-basic variables for adjacent
       * basis */
      if (spx_update_d(lp, d, csa->p, csa->q, trow, tcol) <= 1e-9)
      {  /* successful updating */
         csa->d_st = 2;
      }
      else
      {  /* new reduced costs are inaccurate */
         csa->d_st = 0;
      }
      /* update steepest edge weights for adjacent basis, if used */
      if (se != NULL)
      {  if (refct > 0)
         {  if (spy_update_gamma(lp, se, csa->p, csa->q, trow, tcol)
               <= 1e-3)
            {  /* successful updating */
               refct--;
            }
            else
            {  /* new weights are inaccurate; reset reference space */
               se->valid = 0;
            }
         }
         else
         {  /* too many updates; reset reference space */
            se->valid = 0;
         }
      }
      /* update matrix N for adjacent basis, if used */
      if (nt != NULL)
         spx_update_nt(lp, nt, csa->p, csa->q);
      /* change current basis header to adjacent one */
      spx_change_basis(lp, csa->p, p_flag, csa->q);
      /* and update factorization of the basis matrix */
      if (csa->p > 0)
         spx_update_invb(lp, csa->p, head[csa->p]);
      /* dual simplex iteration complete */
      csa->it_cnt++;
      goto loop;
fini: return ret;
}
Example #8
0
static int wclique(int _n, int w[], unsigned char _a[], int sol[])
{     struct dsa _dsa, *dsa = &_dsa;
      int i, j, p, max_wt, max_nwt, wth, *used, *nwt, *pos;
      xlong_t timer;
      n = _n;
      wt = &w[1];
      a = _a;
      record = 0;
      rec_level = 0;
      rec = &sol[1];
      clique = xcalloc(n, sizeof(int));
      set = xcalloc(n, sizeof(int));
      used = xcalloc(n, sizeof(int));
      nwt = xcalloc(n, sizeof(int));
      pos = xcalloc(n, sizeof(int));
      /* start timer */
      timer = xtime();
      /* order vertices */
      for (i = 0; i < n; i++)
      {  nwt[i] = 0;
         for (j = 0; j < n; j++)
            if (is_edge(dsa, i, j)) nwt[i] += wt[j];
      }
      for (i = 0; i < n; i++)
         used[i] = 0;
      for (i = n-1; i >= 0; i--)
      {  max_wt = -1;
         max_nwt = -1;
         for (j = 0; j < n; j++)
         {  if ((!used[j]) && ((wt[j] > max_wt) || (wt[j] == max_wt
               && nwt[j] > max_nwt)))
            {  max_wt = wt[j];
               max_nwt = nwt[j];
               p = j;
            }
         }
         pos[i] = p;
         used[p] = 1;
         for (j = 0; j < n; j++)
            if ((!used[j]) && (j != p) && (is_edge(dsa, p, j)))
               nwt[j] -= wt[p];
      }
      /* main routine */
      wth = 0;
      for (i = 0; i < n; i++)
      {  wth += wt[pos[i]];
         sub(dsa, i, pos, 0, 0, wth);
         clique[pos[i]] = record;
#if 0
         if (utime() >= timer + 5.0)
#else
         if (xdifftime(xtime(), timer) >= 5.0 - 0.001)
#endif
         {  /* print current record and reset timer */
            xprintf("level = %d (%d); best = %d\n", i+1, n, record);
#if 0
            timer = utime();
#else
            timer = xtime();
#endif
         }
      }
      xfree(clique);
      xfree(set);
      xfree(used);
      xfree(nwt);
      xfree(pos);
      /* return the solution found */
      for (i = 1; i <= rec_level; i++) sol[i]++;
      return rec_level;
}
Example #9
0
static int wclique(SCG *g, const int w[], int sol[])
{     int n = g->n;
      const *wt = &w[1];
      struct dsa _dsa, *dsa = &_dsa;
      int i, j, p, max_wt, max_nwt, wth, *used, *nwt, *pos;
      xlong_t timer;
      xassert(n > 0);
      dsa->g = g;
      dsa->i = 0;
      dsa->nadj = 0;
      dsa->adj = xcalloc(1+n, sizeof(int));
      dsa->flag = xcalloc(1+n, sizeof(char));
      memset(&dsa->flag[1], 0, n);
      dsa->wt = wt;
      dsa->record = 0;
      dsa->rec_level = 0;
      dsa->rec = &sol[1];
      dsa->clique = xcalloc(n, sizeof(int));
      dsa->set = xcalloc(n, sizeof(int));
      used = xcalloc(n, sizeof(int));
      nwt = xcalloc(n, sizeof(int));
      pos = xcalloc(n, sizeof(int));
      /* start timer */
      timer = xtime();
      /* order vertices */
      for (i = 0; i < n; i++)
      {  nwt[i] = 0;
         for (j = 0; j < n; j++)
            if (is_edge(dsa, i, j)) nwt[i] += wt[j];
      }
      for (i = 0; i < n; i++)
         used[i] = 0;
      for (i = n-1; i >= 0; i--)
      {  max_wt = -1;
         max_nwt = -1;
         for (j = 0; j < n; j++)
         {  if ((!used[j]) && ((wt[j] > max_wt) || (wt[j] == max_wt
               && nwt[j] > max_nwt)))
            {  max_wt = wt[j];
               max_nwt = nwt[j];
               p = j;
            }
         }
         pos[i] = p;
         used[p] = 1;
         for (j = 0; j < n; j++)
            if ((!used[j]) && (j != p) && (is_edge(dsa, p, j)))
               nwt[j] -= wt[p];
      }
      /* main routine */
      wth = 0;
      for (i = 0; i < n; i++)
      {  wth += wt[pos[i]];
         sub(dsa, i, pos, 0, 0, wth);
         dsa->clique[pos[i]] = dsa->record;
#if _GLPSCG_DEBUG
         ;
#else
         if (xdifftime(xtime(), timer) >= 5.0 - 0.001)
#endif
         {  /* print current record and reset timer */
            xprintf("level = %d (%d); best = %d\n", i+1, n,
               dsa->record);
            timer = xtime();
         }
      }
      xfree(dsa->adj);
      xfree(dsa->flag);
      xfree(dsa->clique);
      xfree(dsa->set);
      xfree(used);
      xfree(nwt);
      xfree(pos);
      /* return the solution found */
      for (i = 1; i <= dsa->rec_level; i++) sol[i]++;
      return dsa->rec_level;
}
Example #10
0
int ios_driver(glp_tree *T)
{     int p, curr_p, p_stat, d_stat, ret;
#if 1 /* carry out to glp_tree */
      int pred_p = 0;
      /* if the current subproblem has been just created due to
         branching, pred_p is the reference number of its parent
         subproblem, otherwise pred_p is zero */
#endif
      glp_long ttt = T->tm_beg;
#if 0
      ((glp_iocp *)T->parm)->msg_lev = GLP_MSG_DBG;
#endif
      /* on entry to the B&B driver it is assumed that the active list
         contains the only active (i.e. root) subproblem, which is the
         original MIP problem to be solved */
loop: /* main loop starts here */
      /* at this point the current subproblem does not exist */
      xassert(T->curr == NULL);
      /* if the active list is empty, the search is finished */
      if (T->head == NULL)
      {  if (T->parm->msg_lev >= GLP_MSG_DBG)
            xprintf("Active list is empty!\n");
         xassert(dmp_in_use(T->pool).lo == 0);
         ret = 0;
         goto done;
      }
      /* select some active subproblem to continue the search */
      xassert(T->next_p == 0);
      /* let the application program select subproblem */
      if (T->parm->cb_func != NULL)
      {  xassert(T->reason == 0);
         T->reason = GLP_ISELECT;
         T->parm->cb_func(T, T->parm->cb_info);
         T->reason = 0;
         if (T->stop)
         {  ret = GLP_ESTOP;
            goto done;
         }
      }
      if (T->next_p != 0)
      {  /* the application program has selected something */
         ;
      }
      else if (T->a_cnt == 1)
      {  /* the only active subproblem exists, so select it */
         xassert(T->head->next == NULL);
         T->next_p = T->head->p;
      }
      else if (T->child != 0)
      {  /* select one of branching childs suggested by the branching
            heuristic */
         T->next_p = T->child;
      }
      else
      {  /* select active subproblem as specified by the backtracking
            technique option */
         T->next_p = ios_choose_node(T);
      }
      /* the active subproblem just selected becomes current */
      ios_revive_node(T, T->next_p);
      T->next_p = T->child = 0;
      /* invalidate pred_p, if it is not the reference number of the
         parent of the current subproblem */
      if (T->curr->up != NULL && T->curr->up->p != pred_p) pred_p = 0;
      /* determine the reference number of the current subproblem */
      p = T->curr->p;
      if (T->parm->msg_lev >= GLP_MSG_DBG)
      {  xprintf("-----------------------------------------------------"
            "-------------------\n");
         xprintf("Processing node %d at level %d\n", p, T->curr->level);
      }
      /* if it is the root subproblem, initialize cut generators */
      if (p == 1)
      {  if (T->parm->gmi_cuts == GLP_ON)
         {  if (T->parm->msg_lev >= GLP_MSG_ALL)
               xprintf("Gomory's cuts enabled\n");
         }
         if (T->parm->mir_cuts == GLP_ON)
         {  if (T->parm->msg_lev >= GLP_MSG_ALL)
               xprintf("MIR cuts enabled\n");
            xassert(T->mir_gen == NULL);
            T->mir_gen = ios_mir_init(T);
         }
         if (T->parm->cov_cuts == GLP_ON)
         {  if (T->parm->msg_lev >= GLP_MSG_ALL)
               xprintf("Cover cuts enabled\n");
         }
         if (T->parm->clq_cuts == GLP_ON)
         {  xassert(T->clq_gen == NULL);
            if (T->parm->msg_lev >= GLP_MSG_ALL)
               xprintf("Clique cuts enabled\n");
            T->clq_gen = ios_clq_init(T);
         }
      }
more: /* minor loop starts here */
      /* at this point the current subproblem needs either to be solved
         for the first time or re-optimized due to reformulation */
      /* display current progress of the search */
      if (T->parm->msg_lev >= GLP_MSG_DBG ||
          T->parm->msg_lev >= GLP_MSG_ON &&
        (double)(T->parm->out_frq - 1) <=
            1000.0 * xdifftime(xtime(), T->tm_lag))
         show_progress(T, 0);
      if (T->parm->msg_lev >= GLP_MSG_ALL &&
            xdifftime(xtime(), ttt) >= 60.0)
#if 0 /* 16/II-2012 */
      {  glp_long total;
         glp_mem_usage(NULL, NULL, &total, NULL);
         xprintf("Time used: %.1f secs.  Memory used: %.1f Mb.\n",
            xdifftime(xtime(), T->tm_beg), xltod(total) / 1048576.0);
         ttt = xtime();
      }
#else
      {  size_t total;
         glp_mem_usage(NULL, NULL, &total, NULL);
         xprintf("Time used: %.1f secs.  Memory used: %.1f Mb.\n",
            xdifftime(xtime(), T->tm_beg), (double)total / 1048576.0);
         ttt = xtime();
      }
#endif
      /* check the mip gap */
      if (T->parm->mip_gap > 0.0 &&
          ios_relative_gap(T) <= T->parm->mip_gap)
      {  if (T->parm->msg_lev >= GLP_MSG_DBG)
            xprintf("Relative gap tolerance reached; search terminated "
               "\n");
         ret = GLP_EMIPGAP;
         goto done;
      }
      /* check if the time limit has been exhausted */
      if (T->parm->tm_lim < INT_MAX &&
         (double)(T->parm->tm_lim - 1) <=
         1000.0 * xdifftime(xtime(), T->tm_beg))
      {  if (T->parm->msg_lev >= GLP_MSG_DBG)
            xprintf("Time limit exhausted; search terminated\n");
         ret = GLP_ETMLIM;
         goto done;
      }
      /* let the application program preprocess the subproblem */
      if (T->parm->cb_func != NULL)
      {  xassert(T->reason == 0);
         T->reason = GLP_IPREPRO;
         T->parm->cb_func(T, T->parm->cb_info);
         T->reason = 0;
         if (T->stop)
         {  ret = GLP_ESTOP;
            goto done;
         }
      }
      /* perform basic preprocessing */
      if (T->parm->pp_tech == GLP_PP_NONE)
         ;
      else if (T->parm->pp_tech == GLP_PP_ROOT)
      {  if (T->curr->level == 0)
         {  if (ios_preprocess_node(T, 100))
               goto fath;
         }
      }
      else if (T->parm->pp_tech == GLP_PP_ALL)
      {  if (ios_preprocess_node(T, T->curr->level == 0 ? 100 : 10))
            goto fath;
      }
      else
         xassert(T != T);
      /* preprocessing may improve the global bound */
      if (!is_branch_hopeful(T, p))
      {  xprintf("*** not tested yet ***\n");
         goto fath;
      }
      /* solve LP relaxation of the current subproblem */
      if (T->parm->msg_lev >= GLP_MSG_DBG)
         xprintf("Solving LP relaxation...\n");
      ret = ios_solve_node(T);
      if (!(ret == 0 || ret == GLP_EOBJLL || ret == GLP_EOBJUL))
      {  if (T->parm->msg_lev >= GLP_MSG_ERR)
            xprintf("ios_driver: unable to solve current LP relaxation;"
               " glp_simplex returned %d\n", ret);
         ret = GLP_EFAIL;
         goto done;
      }
      /* analyze status of the basic solution to LP relaxation found */
      p_stat = T->mip->pbs_stat;
      d_stat = T->mip->dbs_stat;
      if (p_stat == GLP_FEAS && d_stat == GLP_FEAS)
      {  /* LP relaxation has optimal solution */
         if (T->parm->msg_lev >= GLP_MSG_DBG)
            xprintf("Found optimal solution to LP relaxation\n");
      }
      else if (d_stat == GLP_NOFEAS)
      {  /* LP relaxation has no dual feasible solution */
         /* since the current subproblem cannot have a larger feasible
            region than its parent, there is something wrong */
         if (T->parm->msg_lev >= GLP_MSG_ERR)
            xprintf("ios_driver: current LP relaxation has no dual feas"
               "ible solution\n");
         ret = GLP_EFAIL;
         goto done;
      }
      else if (p_stat == GLP_INFEAS && d_stat == GLP_FEAS)
      {  /* LP relaxation has no primal solution which is better than
            the incumbent objective value */
         xassert(T->mip->mip_stat == GLP_FEAS);
         if (T->parm->msg_lev >= GLP_MSG_DBG)
            xprintf("LP relaxation has no solution better than incumben"
               "t objective value\n");
         /* prune the branch */
         goto fath;
      }
      else if (p_stat == GLP_NOFEAS)
      {  /* LP relaxation has no primal feasible solution */
         if (T->parm->msg_lev >= GLP_MSG_DBG)
            xprintf("LP relaxation has no feasible solution\n");
         /* prune the branch */
         goto fath;
      }
      else
      {  /* other cases cannot appear */
         xassert(T->mip != T->mip);
      }
      /* at this point basic solution to LP relaxation of the current
         subproblem is optimal */
      xassert(p_stat == GLP_FEAS && d_stat == GLP_FEAS);
      xassert(T->curr != NULL);
      T->curr->lp_obj = T->mip->obj_val;
      /* thus, it defines a local bound to integer optimal solution of
         the current subproblem */
      {  double bound = T->mip->obj_val;
         /* some local bound to the current subproblem could be already
            set before, so we should only improve it */
         bound = ios_round_bound(T, bound);
         if (T->mip->dir == GLP_MIN)
         {  if (T->curr->bound < bound)
               T->curr->bound = bound;
         }
         else if (T->mip->dir == GLP_MAX)
         {  if (T->curr->bound > bound)
               T->curr->bound = bound;
         }
         else
            xassert(T->mip != T->mip);
         if (T->parm->msg_lev >= GLP_MSG_DBG)
            xprintf("Local bound is %.9e\n", bound);
      }
      /* if the local bound indicates that integer optimal solution of
         the current subproblem cannot be better than the global bound,
         prune the branch */
      if (!is_branch_hopeful(T, p))
      {  if (T->parm->msg_lev >= GLP_MSG_DBG)
            xprintf("Current branch is hopeless and can be pruned\n");
         goto fath;
      }
      /* let the application program generate additional rows ("lazy"
         constraints) */
      xassert(T->reopt == 0);
      xassert(T->reinv == 0);
      if (T->parm->cb_func != NULL)
      {  xassert(T->reason == 0);
         T->reason = GLP_IROWGEN;
         T->parm->cb_func(T, T->parm->cb_info);
         T->reason = 0;
         if (T->stop)
         {  ret = GLP_ESTOP;
            goto done;
         }
         if (T->reopt)
         {  /* some rows were added; re-optimization is needed */
            T->reopt = T->reinv = 0;
            goto more;
         }
         if (T->reinv)
         {  /* no rows were added, however, some inactive rows were
               removed */
            T->reinv = 0;
            xassert(glp_factorize(T->mip) == 0);
         }
      }
      /* check if the basic solution is integer feasible */
      check_integrality(T);
      /* if the basic solution satisfies to all integrality conditions,
         it is a new, better integer feasible solution */
      if (T->curr->ii_cnt == 0)
      {  if (T->parm->msg_lev >= GLP_MSG_DBG)
            xprintf("New integer feasible solution found\n");
         if (T->parm->msg_lev >= GLP_MSG_ALL)
            display_cut_info(T);
         record_solution(T);
         if (T->parm->msg_lev >= GLP_MSG_ON)
            show_progress(T, 1);
         /* make the application program happy */
         if (T->parm->cb_func != NULL)
         {  xassert(T->reason == 0);
            T->reason = GLP_IBINGO;
            T->parm->cb_func(T, T->parm->cb_info);
            T->reason = 0;
            if (T->stop)
            {  ret = GLP_ESTOP;
               goto done;
            }
         }
         /* since the current subproblem has been fathomed, prune its
            branch */
         goto fath;
      }
      /* at this point basic solution to LP relaxation of the current
         subproblem is optimal, but integer infeasible */
      /* try to fix some non-basic structural variables of integer kind
         on their current bounds due to reduced costs */
      if (T->mip->mip_stat == GLP_FEAS)
         fix_by_red_cost(T);
      /* let the application program try to find some solution to the
         original MIP with a primal heuristic */
      if (T->parm->cb_func != NULL)
      {  xassert(T->reason == 0);
         T->reason = GLP_IHEUR;
         T->parm->cb_func(T, T->parm->cb_info);
         T->reason = 0;
         if (T->stop)
         {  ret = GLP_ESTOP;
            goto done;
         }
         /* check if the current branch became hopeless */
         if (!is_branch_hopeful(T, p))
         {  if (T->parm->msg_lev >= GLP_MSG_DBG)
               xprintf("Current branch became hopeless and can be prune"
                  "d\n");
            goto fath;
         }
      }
      /* try to find solution with the feasibility pump heuristic */
      if (T->parm->fp_heur)
      {  xassert(T->reason == 0);
         T->reason = GLP_IHEUR;
         ios_feas_pump(T);
         T->reason = 0;
         /* check if the current branch became hopeless */
         if (!is_branch_hopeful(T, p))
         {  if (T->parm->msg_lev >= GLP_MSG_DBG)
               xprintf("Current branch became hopeless and can be prune"
                  "d\n");
            goto fath;
         }
      }
      /* it's time to generate cutting planes */
      xassert(T->local != NULL);
      xassert(T->local->size == 0);
      /* let the application program generate some cuts; note that it
         can add cuts either to the local cut pool or directly to the
         current subproblem */
      if (T->parm->cb_func != NULL)
      {  xassert(T->reason == 0);
         T->reason = GLP_ICUTGEN;
         T->parm->cb_func(T, T->parm->cb_info);
         T->reason = 0;
         if (T->stop)
         {  ret = GLP_ESTOP;
            goto done;
         }
      }
      /* try to generate generic cuts with built-in generators
         (as suggested by Matteo Fischetti et al. the built-in cuts
         are not generated at each branching node; an intense attempt
         of generating new cuts is only made at the root node, and then
         a moderate effort is spent after each backtracking step) */
      if (T->curr->level == 0 || pred_p == 0)
      {  xassert(T->reason == 0);
         T->reason = GLP_ICUTGEN;
         generate_cuts(T);
         T->reason = 0;
      }
      /* if the local cut pool is not empty, select useful cuts and add
         them to the current subproblem */
      if (T->local->size > 0)
      {  xassert(T->reason == 0);
         T->reason = GLP_ICUTGEN;
         ios_process_cuts(T);
         T->reason = 0;
      }
      /* clear the local cut pool */
      ios_clear_pool(T, T->local);
      /* perform re-optimization, if necessary */
      if (T->reopt)
      {  T->reopt = 0;
         T->curr->changed++;
         goto more;
      }
      /* no cuts were generated; remove inactive cuts */
      remove_cuts(T);
      if (T->parm->msg_lev >= GLP_MSG_ALL && T->curr->level == 0)
         display_cut_info(T);
      /* update history information used on pseudocost branching */
      if (T->pcost != NULL) ios_pcost_update(T);
      /* it's time to perform branching */
      xassert(T->br_var == 0);
      xassert(T->br_sel == 0);
      /* let the application program choose variable to branch on */
      if (T->parm->cb_func != NULL)
      {  xassert(T->reason == 0);
         xassert(T->br_var == 0);
         xassert(T->br_sel == 0);
         T->reason = GLP_IBRANCH;
         T->parm->cb_func(T, T->parm->cb_info);
         T->reason = 0;
         if (T->stop)
         {  ret = GLP_ESTOP;
            goto done;
         }
      }
      /* if nothing has been chosen, choose some variable as specified
         by the branching technique option */
      if (T->br_var == 0)
         T->br_var = ios_choose_var(T, &T->br_sel);
      /* perform actual branching */
      curr_p = T->curr->p;
      ret = branch_on(T, T->br_var, T->br_sel);
      T->br_var = T->br_sel = 0;
      if (ret == 0)
      {  /* both branches have been created */
         pred_p = curr_p;
         goto loop;
      }
      else if (ret == 1)
      {  /* one branch is hopeless and has been pruned, so now the
            current subproblem is other branch */
         /* the current subproblem should be considered as a new one,
            since one bound of the branching variable was changed */
         T->curr->solved = T->curr->changed = 0;
         goto more;
      }
      else if (ret == 2)
      {  /* both branches are hopeless and have been pruned; new
            subproblem selection is needed to continue the search */
         goto fath;
      }
      else
         xassert(ret != ret);
fath: /* the current subproblem has been fathomed */
      if (T->parm->msg_lev >= GLP_MSG_DBG)
         xprintf("Node %d fathomed\n", p);
      /* freeze the current subproblem */
      ios_freeze_node(T);
      /* and prune the corresponding branch of the tree */
      ios_delete_node(T, p);
      /* if a new integer feasible solution has just been found, other
         branches may become hopeless and therefore must be pruned */
      if (T->mip->mip_stat == GLP_FEAS) cleanup_the_tree(T);
      /* new subproblem selection is needed due to backtracking */
      pred_p = 0;
      goto loop;
done: /* display progress of the search on exit from the solver */
      if (T->parm->msg_lev >= GLP_MSG_ON)
         show_progress(T, 0);
      if (T->mir_gen != NULL)
         ios_mir_term(T->mir_gen), T->mir_gen = NULL;
      if (T->clq_gen != NULL)
         ios_clq_term(T->clq_gen), T->clq_gen = NULL;
      /* return to the calling program */
      return ret;
}
Example #11
0
int glp_main(int argc, const char *argv[])
{     /* stand-alone LP/MIP solver */
      struct csa _csa, *csa = &_csa;
      int ret;
      xlong_t start;
      /* perform initialization */
      csa->prob = glp_create_prob();
      glp_get_bfcp(csa->prob, &csa->bfcp);
      glp_init_smcp(&csa->smcp);
      csa->smcp.presolve = GLP_ON;
      glp_init_iocp(&csa->iocp);
      csa->iocp.presolve = GLP_ON;
      csa->tran = NULL;
      csa->graph = NULL;
      csa->format = FMT_MPS_FILE;
      csa->in_file = NULL;
      csa->ndf = 0;
      csa->out_dpy = NULL;
      csa->solution = SOL_BASIC;
      csa->in_res = NULL;
      csa->dir = 0;
      csa->scale = 1;
      csa->out_sol = NULL;
      csa->out_res = NULL;
      csa->out_bnds = NULL;
      csa->check = 0;
      csa->new_name = NULL;
      csa->out_mps = NULL;
      csa->out_freemps = NULL;
      csa->out_cpxlp = NULL;
      csa->out_pb = NULL;
      csa->out_npb = NULL;
      csa->log_file = NULL;
      csa->crash = USE_ADV_BASIS;
      csa->exact = 0;
      csa->xcheck = 0;
      csa->nomip = 0;
      /* parse command-line parameters */
      ret = parse_cmdline(csa, argc, argv);
      if (ret < 0)
      {  ret = EXIT_SUCCESS;
         goto done;
      }
      if (ret > 0)
      {  ret = EXIT_FAILURE;
         goto done;
      }
      /*--------------------------------------------------------------*/
      /* remove all output files specified in the command line */
      if (csa->out_dpy != NULL) remove(csa->out_dpy);
      if (csa->out_sol != NULL) remove(csa->out_sol);
      if (csa->out_res != NULL) remove(csa->out_res);
      if (csa->out_bnds != NULL) remove(csa->out_bnds);
      if (csa->out_mps != NULL) remove(csa->out_mps);
      if (csa->out_freemps != NULL) remove(csa->out_freemps);
      if (csa->out_cpxlp != NULL) remove(csa->out_cpxlp);
      if (csa->out_pb != NULL) remove(csa->out_pb);
      if (csa->out_npb != NULL) remove(csa->out_npb);
      if (csa->log_file != NULL) remove(csa->log_file);
      /*--------------------------------------------------------------*/
      /* open log file, if required */
      if (csa->log_file != NULL)
      {  if (lib_open_log(csa->log_file))
         {  xprintf("Unable to create log file\n");
            ret = EXIT_FAILURE;
            goto done;
         }
      }
      /*--------------------------------------------------------------*/
      /* read problem data from the input file */
      if (csa->in_file == NULL)
      {  xprintf("No input problem file specified; try %s --help\n",
            argv[0]);
         ret = EXIT_FAILURE;
         goto done;
      }
      if (csa->format == FMT_MPS_DECK)
      {  ret = glp_read_mps(csa->prob, GLP_MPS_DECK, NULL,
            csa->in_file);
         if (ret != 0)
err1:    {  xprintf("MPS file processing error\n");
            ret = EXIT_FAILURE;
            goto done;
         }
      }
      else if (csa->format == FMT_MPS_FILE)
      {  ret = glp_read_mps(csa->prob, GLP_MPS_FILE, NULL,
            csa->in_file);
         if (ret != 0) goto err1;
      }
      else if (csa->format == FMT_CPLEX_LP)
      {  ret = glp_read_lp(csa->prob, NULL, csa->in_file);
         if (ret != 0)
         {  xprintf("CPLEX LP file processing error\n");
            ret = EXIT_FAILURE;
            goto done;
         }
      }
      else if (csa->format == FMT_MATHPROG)
      {  int k;
         /* allocate the translator workspace */
         csa->tran = glp_mpl_alloc_wksp();
         /* read model section and optional data section */
         if (glp_mpl_read_model(csa->tran, csa->in_file, csa->ndf > 0))
err2:    {  xprintf("MathProg model processing error\n");
            ret = EXIT_FAILURE;
            goto done;
         }
         /* read optional data section(s), if necessary */
         for (k = 1; k <= csa->ndf; k++)
         {  if (glp_mpl_read_data(csa->tran, csa->in_data[k]))
               goto err2;
         }
         /* generate the model */
         if (glp_mpl_generate(csa->tran, csa->out_dpy)) goto err2;
         /* build the problem instance from the model */
         glp_mpl_build_prob(csa->tran, csa->prob);
      }
      else if (csa->format == FMT_MIN_COST)
      {  csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data));
         ret = glp_read_mincost(csa->graph, offsetof(v_data, rhs),
            offsetof(a_data, low), offsetof(a_data, cap),
            offsetof(a_data, cost), csa->in_file);
         if (ret != 0)
         {  xprintf("DIMACS file processing error\n");
            ret = EXIT_FAILURE;
            goto done;
         }
         glp_mincost_lp(csa->prob, csa->graph, GLP_ON,
            offsetof(v_data, rhs), offsetof(a_data, low),
            offsetof(a_data, cap), offsetof(a_data, cost));
         glp_set_prob_name(csa->prob, csa->in_file);
      }
      else if (csa->format == FMT_MAX_FLOW)
      {  int s, t;
         csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data));
         ret = glp_read_maxflow(csa->graph, &s, &t,
            offsetof(a_data, cap), csa->in_file);
         if (ret != 0)
         {  xprintf("DIMACS file processing error\n");
            ret = EXIT_FAILURE;
            goto done;
         }
         glp_maxflow_lp(csa->prob, csa->graph, GLP_ON, s, t,
            offsetof(a_data, cap));
         glp_set_prob_name(csa->prob, csa->in_file);
      }
      else
         xassert(csa != csa);
      /*--------------------------------------------------------------*/
      /* change problem name, if required */
      if (csa->new_name != NULL)
         glp_set_prob_name(csa->prob, csa->new_name);
      /* change optimization direction, if required */
      if (csa->dir != 0)
         glp_set_obj_dir(csa->prob, csa->dir);
      /* order rows and columns of the constraint matrix */
      lpx_order_matrix(csa->prob);
      /*--------------------------------------------------------------*/
      /* write problem data in fixed MPS format, if required */
      if (csa->out_mps != NULL)
      {  ret = glp_write_mps(csa->prob, GLP_MPS_DECK, NULL,
            csa->out_mps);
         if (ret != 0)
         {  xprintf("Unable to write problem in fixed MPS format\n");
            ret = EXIT_FAILURE;
            goto done;
         }
      }
      /* write problem data in free MPS format, if required */
      if (csa->out_freemps != NULL)
      {  ret = glp_write_mps(csa->prob, GLP_MPS_FILE, NULL,
            csa->out_freemps);
         if (ret != 0)
         {  xprintf("Unable to write problem in free MPS format\n");
            ret = EXIT_FAILURE;
            goto done;
         }
      }
      /* write problem data in CPLEX LP format, if required */
      if (csa->out_cpxlp != NULL)
      {  ret = glp_write_lp(csa->prob, NULL, csa->out_cpxlp);
         if (ret != 0)
         {  xprintf("Unable to write problem in CPLEX LP format\n");
            ret = EXIT_FAILURE;
            goto done;
         }
      }
      /* write problem data in OPB format, if required */
      if (csa->out_pb != NULL)
      {  ret = lpx_write_pb(csa->prob, csa->out_pb, 0, 0);
         if (ret != 0)
         {  xprintf("Unable to write problem in OPB format\n");
            ret = EXIT_FAILURE;
            goto done;
         }
      }
      /* write problem data in normalized OPB format, if required */
      if (csa->out_npb != NULL)
      {  ret = lpx_write_pb(csa->prob, csa->out_npb, 1, 1);
         if (ret != 0)
         {  xprintf(
               "Unable to write problem in normalized OPB format\n");
            ret = EXIT_FAILURE;
            goto done;
         }
      }
      /*--------------------------------------------------------------*/
      /* if only problem data check is required, skip computations */
      if (csa->check)
      {  ret = EXIT_SUCCESS;
         goto done;
      }
      /*--------------------------------------------------------------*/
      /* determine the solution type */
      if (!csa->nomip &&
          glp_get_num_int(csa->prob) + glp_get_num_bin(csa->prob) > 0)
      {  if (csa->solution == SOL_INTERIOR)
         {  xprintf("Interior-point method is not able to solve MIP pro"
               "blem; use --simplex\n");
            ret = EXIT_FAILURE;
            goto done;
         }
         csa->solution = SOL_INTEGER;
      }
      /*--------------------------------------------------------------*/
      /* if solution is provided, read it and skip computations */
      if (csa->in_res != NULL)
      {  if (csa->solution == SOL_BASIC)
            ret = glp_read_sol(csa->prob, csa->in_res);
         else if (csa->solution == SOL_INTERIOR)
            ret = glp_read_ipt(csa->prob, csa->in_res);
         else if (csa->solution == SOL_INTEGER)
            ret = glp_read_mip(csa->prob, csa->in_res);
         else
            xassert(csa != csa);
         if (ret != 0)
         {  xprintf("Unable to read problem solution\n");
            ret = EXIT_FAILURE;
            goto done;
         }
         goto skip;
      }
      /*--------------------------------------------------------------*/
      /* scale the problem data, if required */
      if (csa->scale)
      {  if (csa->solution == SOL_BASIC && !csa->smcp.presolve ||
             csa->solution == SOL_INTERIOR ||
             csa->solution == SOL_INTEGER && !csa->iocp.presolve)
            glp_scale_prob(csa->prob, GLP_SF_AUTO);
      }
      /* construct starting LP basis */
      if (csa->solution == SOL_BASIC && !csa->smcp.presolve ||
          csa->solution == SOL_INTEGER && !csa->iocp.presolve)
      {  if (csa->crash == USE_STD_BASIS)
            glp_std_basis(csa->prob);
         else if (csa->crash == USE_ADV_BASIS)
            glp_adv_basis(csa->prob, 0);
         else if (csa->crash == USE_CPX_BASIS)
            glp_cpx_basis(csa->prob);
         else
            xassert(csa != csa);
      }
      /*--------------------------------------------------------------*/
      /* solve the problem */
      start = xtime();
      if (csa->solution == SOL_BASIC)
      {  if (!csa->exact)
         {  glp_set_bfcp(csa->prob, &csa->bfcp);
            glp_simplex(csa->prob, &csa->smcp);
            if (csa->xcheck)
            {  if (csa->smcp.presolve &&
                   glp_get_status(csa->prob) != GLP_OPT)
                  xprintf("If you need to check final basis for non-opt"
                     "imal solution, use --nopresol\n");
               else
                  glp_exact(csa->prob, &csa->smcp);
            }
            if (csa->out_sol != NULL || csa->out_res != NULL)
            {  if (csa->smcp.presolve &&
                   glp_get_status(csa->prob) != GLP_OPT)
               xprintf("If you need actual output for non-optimal solut"
                  "ion, use --nopresol\n");
            }
         }
         else
            glp_exact(csa->prob, &csa->smcp);
      }
      else if (csa->solution == SOL_INTERIOR)
         glp_interior(csa->prob, NULL);
      else if (csa->solution == SOL_INTEGER)
      {  if (!csa->iocp.presolve)
         {  glp_set_bfcp(csa->prob, &csa->bfcp);
            glp_simplex(csa->prob, &csa->smcp);
         }
         glp_intopt(csa->prob, &csa->iocp);
      }
      else
         xassert(csa != csa);
      /*--------------------------------------------------------------*/
      /* display statistics */
      xprintf("Time used:   %.1f secs\n", xdifftime(xtime(), start));
      {  xlong_t tpeak;
         char buf[50];
         lib_mem_usage(NULL, NULL, NULL, &tpeak);
         xprintf("Memory used: %.1f Mb (%s bytes)\n",
            xltod(tpeak) / 1048576.0, xltoa(tpeak, buf));
      }
      /*--------------------------------------------------------------*/
skip: /* postsolve the model, if necessary */
      if (csa->tran != NULL)
      {  if (csa->solution == SOL_BASIC)
            ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_SOL);
         else if (csa->solution == SOL_INTERIOR)
            ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_IPT);
         else if (csa->solution == SOL_INTEGER)
            ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_MIP);
         else
            xassert(csa != csa);
         if (ret != 0)
         {  xprintf("Model postsolving error\n");
            ret = EXIT_FAILURE;
            goto done;
         }
      }
      /*--------------------------------------------------------------*/
      /* write problem solution in printable format, if required */
      if (csa->out_sol != NULL)
      {  if (csa->solution == SOL_BASIC)
            ret = lpx_print_sol(csa->prob, csa->out_sol);
         else if (csa->solution == SOL_INTERIOR)
            ret = lpx_print_ips(csa->prob, csa->out_sol);
         else if (csa->solution == SOL_INTEGER)
            ret = lpx_print_mip(csa->prob, csa->out_sol);
         else
            xassert(csa != csa);
         if (ret != 0)
         {  xprintf("Unable to write problem solution\n");
            ret = EXIT_FAILURE;
            goto done;
         }
      }
      /* write problem solution in printable format, if required */
      if (csa->out_res != NULL)
      {  if (csa->solution == SOL_BASIC)
            ret = glp_write_sol(csa->prob, csa->out_res);
         else if (csa->solution == SOL_INTERIOR)
            ret = glp_write_ipt(csa->prob, csa->out_res);
         else if (csa->solution == SOL_INTEGER)
            ret = glp_write_mip(csa->prob, csa->out_res);
         else
            xassert(csa != csa);
         if (ret != 0)
         {  xprintf("Unable to write problem solution\n");
            ret = EXIT_FAILURE;
            goto done;
         }
      }
      /* write sensitivity bounds information, if required */
      if (csa->out_bnds != NULL)
      {  if (csa->solution == SOL_BASIC)
         {  ret = lpx_print_sens_bnds(csa->prob, csa->out_bnds);
            if (ret != 0)
            {  xprintf("Unable to write sensitivity bounds information "
                  "\n");
               ret = EXIT_FAILURE;
               goto done;
            }
         }
         else
            xprintf("Cannot write sensitivity bounds information for in"
               "terior-point or MIP solution\n");
      }
      /*--------------------------------------------------------------*/
      /* all seems to be ok */
      ret = EXIT_SUCCESS;
      /*--------------------------------------------------------------*/
done: /* delete the LP/MIP problem object */
      if (csa->prob != NULL)
         glp_delete_prob(csa->prob);
      /* free the translator workspace, if necessary */
      if (csa->tran != NULL)
         glp_mpl_free_wksp(csa->tran);
      /* delete the network problem object, if necessary */
      if (csa->graph != NULL)
         glp_delete_graph(csa->graph);
      xassert(gmp_pool_count() == 0);
      gmp_free_mem();
      /* close log file, if necessary */
      if (csa->log_file != NULL) lib_close_log();
      /* check that no memory blocks are still allocated */
      {  int count;
         xlong_t total;
         lib_mem_usage(&count, NULL, &total, NULL);
         if (count != 0)
            xerror("Error: %d memory block(s) were lost\n", count);
         xassert(count == 0);
         xassert(total.lo == 0 && total.hi == 0);
      }
      /* free the library environment */
      lib_free_env();
      /* return to the control program */
      return ret;
}