Пример #1
0
/** depending on the LP's solution status, calls reduced cost or Farkas pricing method of variable pricer */
SCIP_RETCODE SCIPpricerExec(
   SCIP_PRICER*          pricer,             /**< variable pricer */
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_PROB*            prob,               /**< transformed problem */
   SCIP_LP*              lp,                 /**< LP data */
   SCIP_PRICESTORE*      pricestore,         /**< pricing storage */
   SCIP_Real*            lowerbound,         /**< local lower bound computed by the pricer */
   SCIP_RESULT*          result              /**< result of the pricing process */
   )
{
   assert(pricer != NULL);
   assert(lowerbound != NULL);
   assert(result != NULL);

   /* set lowerbound and result pointer */
   *lowerbound = - SCIPsetInfinity(set);
   *result = SCIP_SUCCESS;

   /* check if pricer should be delayed */
   if( pricer->delay && SCIPpricestoreGetNVars(pricestore) > 0 )
      return SCIP_OKAY;

   if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_INFEASIBLE )
   {
      SCIP_CALL( SCIPpricerFarkas(pricer, set, prob) );
   }
   else
   {
      *result = SCIP_DIDNOTRUN;
      SCIP_CALL( SCIPpricerRedcost(pricer, set, prob, lowerbound, result) );
   }

   return SCIP_OKAY;
}
Пример #2
0
/** adds problem variables with negative reduced costs to pricing storage */
SCIP_RETCODE SCIPpricestoreAddProbVars(
   SCIP_PRICESTORE*      pricestore,         /**< pricing storage */
   BMS_BLKMEM*           blkmem,             /**< block memory buffers */
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_STAT*            stat,               /**< dynamic problem statistics */
   SCIP_PROB*            prob,               /**< transformed problem after presolve */
   SCIP_TREE*            tree,               /**< branch and bound tree */
   SCIP_LP*              lp,                 /**< LP data */
   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
   )
{
   SCIP_VAR* var;
   SCIP_COL* col;
   SCIP_Bool root;
   SCIP_Bool added;
   int v;
   int abortpricevars;
   int maxpricevars;
   int nfoundvars;

   assert(pricestore != NULL);
   assert(set != NULL);
   assert(stat != NULL);
   assert(prob != NULL);
   assert(lp != NULL);
   assert(lp->solved);
   assert(tree != NULL);
   assert(SCIPtreeHasCurrentNodeLP(tree));
   assert(prob->nvars >= SCIPlpGetNCols(lp));

   /* if all problem variables of status COLUMN are already in the LP, nothing has to be done */
   if( prob->ncolvars == SCIPlpGetNCols(lp) )
      return SCIP_OKAY;

   root = (SCIPtreeGetCurrentDepth(tree) == 0);
   maxpricevars = SCIPsetGetPriceMaxvars(set, root);
   assert(maxpricevars >= 1);
   abortpricevars = (int)(set->price_abortfac * maxpricevars);
   assert(abortpricevars >= maxpricevars);
   
   /**@todo test pricing: is abortpricevars a good idea? -> like strong branching, lookahead, ... */

   pricestore->nprobpricings++;

   /* start timing */
   SCIPclockStart(pricestore->probpricingtime, set);
   
   /* price already existing problem variables */
   nfoundvars = 0;
   for( v = 0; v < prob->nvars && nfoundvars < abortpricevars; ++v )
   {
      var = prob->vars[v];
      if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
      {
         col = SCIPvarGetCol(var);
         assert(col != NULL);
         assert(col->var == var);
         assert(col->len >= 0);
         assert(col->lppos >= -1);
         assert(col->lpipos >= -1);
         assert(SCIPcolIsInLP(col) == (col->lpipos >= 0));
            
         if( !SCIPcolIsInLP(col) )
         {
            SCIPdebugMessage("price column variable <%s> in bounds [%g,%g]\n", 
               SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var));

            /* add variable to pricing storage, if zero is not best bound w.r.t. objective function */
            SCIP_CALL( addBoundViolated(pricestore, blkmem, set, stat, tree, lp, branchcand, eventqueue, var, &added) );

            if( added )
            {
               pricestore->nprobvarsfound++;
               nfoundvars++;
            }
            else if( SCIPcolGetNNonz(col) > 0 )
            {
               SCIP_Real feasibility;
   
               /* a column not in LP that doesn't have zero in its bounds was added by bound checking above */
               assert(!SCIPsetIsPositive(set, SCIPvarGetLbLocal(col->var)));
               assert(!SCIPsetIsNegative(set, SCIPvarGetUbLocal(col->var)));
               
               if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_INFEASIBLE )
               {
                  /* The LP was proven infeasible, so we have an infeasibility proof by the dual Farkas multipliers y.
                   * The valid inequality  y^T A x >= y^T b  is violated by all x, especially by the (for this
                   * inequality most feasible solution) x' defined by 
                   *    x'_i = ub_i, if y^T A_i > 0
                   *    x'_i = lb_i, if y^T A_i <= 0.
                   * Pricing in this case means to add variables i with positive Farkas value, i.e. y^T A_i x'_i > 0
                   */
                  feasibility = -SCIPcolGetFarkasValue(col, stat, lp);
                  SCIPdebugMessage("  <%s> Farkas feasibility: %e\n", SCIPvarGetName(col->var), feasibility);
               }
               else
               {
                  /* The dual LP is feasible, and we have a feasible dual solution. Pricing in this case means to
                   * add variables with negative feasibility, that is
                   *  - positive reduced costs for variables with negative lower bound
                   *  - negative reduced costs for variables with positive upper bound
                   */
                  feasibility = SCIPcolGetFeasibility(col, set, stat, lp);
                  SCIPdebugMessage("  <%s> reduced cost feasibility: %e\n", SCIPvarGetName(col->var), feasibility);
               }
               
               /* the score is -feasibility / (#nonzeros in column + 1) to prefer short columns
                * we must add variables with negative feasibility, but in order to not get a too large lower bound
                * due to missing columns, we better also add variables, that have a very small feasibility
                */
               if( !SCIPsetIsPositive(set, feasibility) )
               {
                  SCIP_CALL( SCIPpricestoreAddVar(pricestore, blkmem, set, eventqueue, lp, var, -feasibility / (col->len+1), root) );
                  pricestore->nprobvarsfound++;
                  nfoundvars++;
               }
            }
         }
      }
   }

   /* stop timing */
   SCIPclockStop(pricestore->probpricingtime, set);

   return SCIP_OKAY;
}