コード例 #1
0
/** propagate the given binary variable/column using the root reduced cost stored in the SCIP internal data structers
 *  and check if the implictions can be useful. Deppending on that implictions are used or not used during the search to
 *  strength the reduced costs.
 */
static
SCIP_RETCODE propagateRootRedcostBinvar(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_PROPDATA*        propdata,           /**< propagator data structure */
   SCIP_VAR*             var,                /**< variable to use for propagation */
   SCIP_COL*             col,                /**< LP column of the variable */
   SCIP_Real             cutoffbound,        /**< the current cutoff bound */
   int*                  nchgbds             /**< pointer to count the number of bound changes */
   )
{
   SCIP_Real rootredcost;
   SCIP_Real rootsol;
   SCIP_Real rootlpobjval;

   assert(SCIPgetDepth(scip) == 0);

   /* skip binary variable if it is locally fixed */
   if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5 )
      return SCIP_OKAY;

   rootredcost = SCIPvarGetBestRootRedcost(var);
   rootsol = SCIPvarGetBestRootSol(var);
   rootlpobjval = SCIPvarGetBestRootLPObjval(var);

   if( SCIPisFeasZero(scip, rootredcost) )
      return SCIP_OKAY;

   assert(rootlpobjval != SCIP_INVALID); /*lint !e777*/

   if( rootsol > 0.5 )
   {
      assert(!SCIPisFeasPositive(scip, rootredcost));

      /* update maximum reduced cost of a single binary variable */
      propdata->maxredcost = MAX(propdata->maxredcost, -rootredcost);

      if( rootlpobjval - rootredcost > cutoffbound )
      {
         SCIPdebugMessage("globally fix binary variable <%s> to 1.0\n", SCIPvarGetName(var));

         SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
         (*nchgbds)++;
         return SCIP_OKAY;
      }
   }
   else
   {
      assert(!SCIPisFeasNegative(scip, rootredcost));

      /* update maximum reduced cost of a single binary variable */
      propdata->maxredcost = MAX(propdata->maxredcost, rootredcost);

      if( rootlpobjval + rootredcost > cutoffbound )
      {
         SCIPdebugMessage("globally fix binary variable <%s> to 0.0\n", SCIPvarGetName(var));

         SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
         (*nchgbds)++;
         return SCIP_OKAY;
      }
   }

   /* evaluate if the implications are useful; the implications are seen to be useful if they provide an increase for
    * the root reduced costs
    */
   if( !propdata->usefullimplics )
   {
      SCIP_Real lbredcost;
      SCIP_Real ubredcost;

      lbredcost = SCIPgetVarImplRedcost(scip, var, FALSE);
      assert(!SCIPisFeasPositive(scip, lbredcost));

      ubredcost = SCIPgetVarImplRedcost(scip, var, TRUE);
      assert(!SCIPisFeasNegative(scip, ubredcost));

      switch( SCIPcolGetBasisStatus(col) )
      {
      case SCIP_BASESTAT_LOWER:
         ubredcost -= SCIPgetVarRedcost(scip, var);
         assert(!SCIPisFeasNegative(scip, ubredcost));
         break;

      case SCIP_BASESTAT_UPPER:
         lbredcost -= SCIPgetVarRedcost(scip, var);
         assert(!SCIPisFeasPositive(scip, lbredcost));
         break;

      case SCIP_BASESTAT_BASIC:
      case SCIP_BASESTAT_ZERO:
      default:
         break;
      }

      propdata->usefullimplics = (lbredcost < 0.0) || (ubredcost > 0.0);
   }

   return SCIP_OKAY;
}
コード例 #2
0
/** calculate score and preferred rounding direction for the candidate variable; the best candidate maximizes the
 *  score
 */
static
SCIP_DECL_DIVESETGETSCORE(divesetGetScoreFracdiving)
{
   SCIP_Real obj;
   SCIP_Real objnorm;
   SCIP_Real objgain;
   SCIP_Bool mayrounddown;
   SCIP_Bool mayroundup;

   /* score fractionality if candidate is an SOS1 variable */
   if ( divetype == SCIP_DIVETYPE_SOS1VARIABLE )
   {
      *score = candsfrac;

      /* 'round' in nonzero direction, i.e., fix the candidates neighbors in the conflict graph to zero */
      *roundup = SCIPisFeasPositive(scip, candsol);

      return SCIP_OKAY;
   }

   mayrounddown = SCIPvarMayRoundDown(cand);
   mayroundup = SCIPvarMayRoundUp(cand);

   /* choose rounding direction:
    * - if variable may be rounded in either both or neither direction, round corresponding to the fractionality
    * - otherwise, round in the infeasible direction, because feasible direction is tried by rounding
    *   the current fractional solution
    */
   if( mayrounddown != mayroundup )
      *roundup = mayrounddown;
   else
      *roundup = (candsfrac > 0.5);

   obj = SCIPvarGetObj(cand);
   objnorm = SCIPgetObjNorm(scip);

   /* divide by objective norm to normalize obj into [-1,1] */
   if( SCIPisPositive(scip, objnorm) )
      obj /= objnorm;

   /* calculate objective gain and fractionality for the selected rounding direction */
   if( *roundup )
   {
      candsfrac = 1.0 - candsfrac;
      objgain = obj * candsfrac;
   }
   else
      objgain = -obj * candsfrac;

   assert(objgain >= -1.0 && objgain <= 1.0);

      /* penalize too small fractions */
      if( candsfrac < 0.01 )
         candsfrac += 10.0;

      /* prefer decisions on binary variables */
      if( !SCIPvarIsBinary(cand) )
         candsfrac *= 1000.0;

      /* prefer variables which cannot be rounded by scoring their fractionality */
      if( !(mayrounddown || mayroundup) )
         *score = -candsfrac;
      else
         *score =  -2.0 - objgain;

      return SCIP_OKAY;
}
コード例 #3
0
/** propagate the given binary variable/column using the reduced cost */
static
SCIP_RETCODE propagateRedcostBinvar(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_PROPDATA*        propdata,           /**< propagator data structure */
   SCIP_VAR*             var,                /**< variable to use for propagation */
   SCIP_COL*             col,                /**< LP column of the variable */
   SCIP_Real             requiredredcost,    /**< required reduset cost to be able to fix a binary variable */
   int*                  nchgbds,            /**< pointer to count the number of bound changes */
   SCIP_Bool*            cutoff              /**< pointer to store if an cutoff was detected */
   )
{
   SCIP_Real lbredcost;
   SCIP_Real ubredcost;
   SCIP_Real redcost;

   /* skip binary variable if it is locally fixed */
   if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5 )
      return SCIP_OKAY;

   /* first use the redcost cost to fix the binary variable */
   switch( SCIPcolGetBasisStatus(col) )
   {
   case SCIP_BASESTAT_LOWER:
      redcost = SCIPgetVarRedcost(scip, var);
      assert(!SCIPisFeasNegative(scip, redcost));

      if( redcost > requiredredcost )
      {
         SCIPdebugMessage("variable <%s>: fixed 0.0 (requiredredcost <%g>, redcost <%g>)\n",
            SCIPvarGetName(var), requiredredcost, redcost);

         SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
         (*nchgbds)++;
         return SCIP_OKAY;
      }
      break;

   case SCIP_BASESTAT_UPPER:
      redcost = SCIPgetVarRedcost(scip, var);
      assert(!SCIPisFeasPositive(scip, redcost));

      if( -redcost > requiredredcost )
      {
         SCIPdebugMessage("variable <%s>: fixed 1.0 (requiredredcost <%g>, redcost <%g>)\n",
            SCIPvarGetName(var), requiredredcost, redcost);

         SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
         (*nchgbds)++;
         return SCIP_OKAY;
      }
      break;

   case SCIP_BASESTAT_BASIC:
      return SCIP_OKAY;

   case SCIP_BASESTAT_ZERO:
      assert(SCIPisFeasZero(scip, SCIPgetColRedcost(scip, col)));
      return SCIP_OKAY;

   default:
      SCIPerrorMessage("invalid basis state\n");
      return SCIP_INVALIDDATA;
   }

   /* second, if the implications should be used and if the implications are seen to be promising used the implied
    * reduced costs to fix the binary variable
    */
   if( propdata->useimplics && propdata->usefullimplics )
   {
      /* collect implied reduced costs if the variable would be fixed to its lower bound */
      lbredcost = SCIPgetVarImplRedcost(scip, var, FALSE);
      assert(!SCIPisFeasPositive(scip, lbredcost) || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) );

      /* collect implied reduced costs if the variable would be fixed to its upper bound */
      ubredcost = SCIPgetVarImplRedcost(scip, var, TRUE);
      assert(!SCIPisFeasNegative(scip, ubredcost) || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) );

      if( -lbredcost > requiredredcost && ubredcost > requiredredcost )
      {
         SCIPdebugMessage("variable <%s>: cutoff (requiredredcost <%g>, lbredcost <%g>, ubredcost <%g>)\n",
            SCIPvarGetName(var), requiredredcost, lbredcost, ubredcost);

         (*cutoff) = TRUE;
      }
      else if( -lbredcost > requiredredcost )
      {
         SCIPdebugMessage("variable <%s>: fixed 1.0 (requiredredcost <%g>, redcost <%g>, lbredcost <%g>)\n",
            SCIPvarGetName(var), requiredredcost, redcost, lbredcost);

         SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
         (*nchgbds)++;
      }
      else if( ubredcost > requiredredcost )
      {
         SCIPdebugMessage("variable <%s>: fixed 0.0 (requiredredcost <%g>, redcost <%g>, ubredcost <%g>)\n",
            SCIPvarGetName(var), requiredredcost, redcost, ubredcost);

         SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
         (*nchgbds)++;
      }

      /* update maximum reduced cost of a single binary variable */
      propdata->maxredcost = MAX3(propdata->maxredcost, -lbredcost, ubredcost);
   }

   return SCIP_OKAY;
}
コード例 #4
0
/** propagate the given none binary variable/column using the reduced cost */
static
SCIP_RETCODE propagateRedcostVar(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_VAR*             var,                /**< variable to use for propagation */
   SCIP_COL*             col,                /**< LP column of the variable */
   SCIP_Real             lpobjval,           /**< objective value of the current LP */
   SCIP_Real             cutoffbound,        /**< the current cutoff bound */
   int*                  nchgbds             /**< pointer to count the number of bound changes */
   )
{
   SCIP_Real redcost;

   switch( SCIPcolGetBasisStatus(col) )
   {
   case SCIP_BASESTAT_LOWER:
      redcost = SCIPgetColRedcost(scip, col);

      assert(!SCIPisFeasNegative(scip, redcost) || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) );
      if( SCIPisFeasPositive(scip, redcost) )
      {
         SCIP_Real oldlb;
         SCIP_Real oldub;

         oldlb = SCIPvarGetLbLocal(var);
         oldub = SCIPvarGetUbLocal(var);
         assert(SCIPisEQ(scip, oldlb, SCIPcolGetLb(col)));
         assert(SCIPisEQ(scip, oldub, SCIPcolGetUb(col)));

        if( SCIPisFeasLT(scip, oldlb, oldub) )
         {
            SCIP_Real newub;
            SCIP_Bool strengthen;

            /* calculate reduced cost based bound */
            newub = (cutoffbound - lpobjval) / redcost + oldlb;

            /* check, if new bound is good enough:
             *  - integer variables: take all possible strengthenings
             *  - continuous variables: strengthening must cut part of the variable's dynamic range, and
             *                          at least 20% of the current domain
             */
            if( SCIPvarIsIntegral(var) )
            {
               newub = SCIPadjustedVarUb(scip, var, newub);
               strengthen = (newub < oldub - 0.5);
            }
            else
               strengthen = (newub < SCIPcolGetMaxPrimsol(col) && newub <= 0.2 * oldlb + 0.8 * oldub);

            if( strengthen )
            {
               /* strengthen upper bound */
               SCIPdebugMessage("redcost strengthening upper bound: <%s> [%g,%g] -> [%g,%g] (ub=%g, lb=%g, redcost=%g)\n",
                  SCIPvarGetName(var), oldlb, oldub, oldlb, newub, cutoffbound, lpobjval, redcost);
               SCIP_CALL( SCIPchgVarUb(scip, var, newub) );
               (*nchgbds)++;
            }
         }
      }
      break;

   case SCIP_BASESTAT_BASIC:
      break;

   case SCIP_BASESTAT_UPPER:
      redcost = SCIPgetColRedcost(scip, col);

      assert(!SCIPisFeasPositive(scip, redcost) || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) );
      if( SCIPisFeasNegative(scip, redcost) )
      {
         SCIP_Real oldlb;
         SCIP_Real oldub;

         oldlb = SCIPvarGetLbLocal(var);
         oldub = SCIPvarGetUbLocal(var);
         assert(SCIPisEQ(scip, oldlb, SCIPcolGetLb(col)));
         assert(SCIPisEQ(scip, oldub, SCIPcolGetUb(col)));

         if( SCIPisFeasLT(scip, oldlb, oldub) )
         {
            SCIP_Real newlb;
            SCIP_Bool strengthen;

            /* calculate reduced cost based bound */
            newlb = (cutoffbound - lpobjval) / redcost + oldub;

            /* check, if new bound is good enough:
             *  - integer variables: take all possible strengthenings
             *  - continuous variables: strengthening must cut part of the variable's dynamic range, and
             *                          at least 20% of the current domain
             */
            if( SCIPvarIsIntegral(var) )
            {
               newlb = SCIPadjustedVarLb(scip, var, newlb);
               strengthen = (newlb > oldlb + 0.5);
            }
            else
               strengthen = (newlb > SCIPcolGetMinPrimsol(col) && newlb >= 0.8 * oldlb + 0.2 * oldub);

            /* check, if new bound is good enough: at least 20% strengthening for continuous variables */
            if( strengthen )
            {
               /* strengthen lower bound */
               SCIPdebugMessage("redcost strengthening lower bound: <%s> [%g,%g] -> [%g,%g] (ub=%g, lb=%g, redcost=%g)\n",
                  SCIPvarGetName(var), oldlb, oldub, newlb, oldub, cutoffbound, lpobjval, redcost);
               SCIP_CALL( SCIPchgVarLb(scip, var, newlb) );
               (*nchgbds)++;
            }
         }
      }
      break;

   case SCIP_BASESTAT_ZERO:
      assert(SCIPisFeasZero(scip, SCIPgetColRedcost(scip, col)));
      break;

   default:
      SCIPerrorMessage("invalid basis state\n");
      return SCIP_INVALIDDATA;
   }

   return SCIP_OKAY;
}
コード例 #5
0
ファイル: heur_actconsdiving.c プロジェクト: hhexiy/scip
/** returns a score value for the given variable based on the active constraints that the variable appears in */
static
SCIP_Real getNActiveConsScore(
    SCIP*                 scip,               /**< SCIP data structure */
    SCIP_VAR*             var,                /**< variable to get the score value for */
    SCIP_Real*            downscore,          /**< pointer to store the score for branching downwards */
    SCIP_Real*            upscore             /**< pointer to store the score for branching upwards */
)
{
    SCIP_COL* col;
    SCIP_ROW** rows;
    SCIP_Real* vals;
    int nrows;
    int r;
    int nactrows;
    SCIP_Real downcoefsum;
    SCIP_Real upcoefsum;
    SCIP_Real score;

    assert(downscore != NULL);
    assert(upscore != NULL);

    *downscore = 0.0;
    *upscore = 0.0;
    if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
        return 0.0;

    col = SCIPvarGetCol(var);
    assert(col != NULL);

    rows = SCIPcolGetRows(col);
    vals = SCIPcolGetVals(col);
    nrows = SCIPcolGetNLPNonz(col);
    nactrows = 0;
    downcoefsum = 0.0;
    upcoefsum = 0.0;
    for( r = 0; r < nrows; ++r )
    {
        SCIP_Real activity;
        SCIP_Real lhs;
        SCIP_Real rhs;
        SCIP_Real dualsol;

        /* calculate number of active constraint sides, i.e., count equations as two */
        lhs = SCIProwGetLhs(rows[r]);
        rhs = SCIProwGetRhs(rows[r]);
        activity = SCIPgetRowLPActivity(scip, rows[r]);
        dualsol = SCIProwGetDualsol(rows[r]);
        if( SCIPisFeasEQ(scip, activity, lhs) )
        {
            SCIP_Real coef;

            nactrows++;
            coef = vals[r] / SCIProwGetNorm(rows[r]);
            if( SCIPisFeasPositive(scip, dualsol) )
            {
                if( coef > 0.0 )
                    downcoefsum += coef;
                else
                    upcoefsum -= coef;
            }
        }
        else if( SCIPisFeasEQ(scip, activity, rhs) )
        {
            SCIP_Real coef;

            nactrows++;
            coef = vals[r] / SCIProwGetNorm(rows[r]);
            if( SCIPisFeasNegative(scip, dualsol) )
            {
                if( coef > 0.0 )
                    upcoefsum += coef;
                else
                    downcoefsum -= coef;
            }
        }
    }
    score = 1e-3*nactrows + (downcoefsum + 1e-6) * (upcoefsum + 1e-6);
    *downscore = -downcoefsum;
    *upscore = -upcoefsum;

    return score;
}
コード例 #6
0
ファイル: misc.c プロジェクト: aimanqais/gerardus
/** transforms given solution of the master problem into solution of the original problem
 *  @todo think about types of epsilons used in this method
 */
SCIP_RETCODE GCGrelaxTransformMastersolToOrigsol(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_SOL*             mastersol,          /**< solution of the master problem, or NULL for current LP solution */
   SCIP_SOL**            origsol             /**< pointer to store the new created original problem's solution */
   )
{
   SCIP* masterprob;
   int npricingprobs;
   int* blocknrs;
   SCIP_Real* blockvalue;
   SCIP_Real increaseval;
   SCIP_VAR** mastervars;
   SCIP_Real* mastervals;
   int nmastervars;
   SCIP_VAR** vars;
   int nvars;
   SCIP_Real feastol;
   int i;
   int j;

   assert(scip != NULL);
   assert(origsol != NULL);

   masterprob = GCGrelaxGetMasterprob(scip);
   npricingprobs = GCGrelaxGetNPricingprobs(scip);

   assert( !SCIPisInfinity(scip, SCIPgetSolOrigObj(masterprob, mastersol)) );
   
   SCIP_CALL( SCIPcreateSol(scip, origsol, GCGrelaxGetProbingheur(scip)) );

   SCIP_CALL( SCIPallocBufferArray(scip, &blockvalue, npricingprobs) );
   SCIP_CALL( SCIPallocBufferArray(scip, &blocknrs, npricingprobs) );

   /* get variables of the master problem and their solution values */
   SCIP_CALL( SCIPgetVarsData(masterprob, &mastervars, &nmastervars, NULL, NULL, NULL, NULL) );
   assert(mastervars != NULL);
   assert(nmastervars >= 0);

   SCIP_CALL( SCIPallocBufferArray(scip, &mastervals, nmastervars) );
   SCIP_CALL( SCIPgetSolVals(masterprob, mastersol, nmastervars, mastervars, mastervals) );

   /* initialize the block values for the pricing problems */
   for( i = 0; i < npricingprobs; i++ )
   {
      blockvalue[i] = 0.0;
      blocknrs[i] = 0;
   }

   /* loop over all given master variables */
   for( i = 0; i < nmastervars; i++ )
   {
      SCIP_VAR** origvars;
      int norigvars;
      SCIP_Real* origvals;
      SCIP_Bool isray;
      int blocknr;

      origvars = GCGmasterVarGetOrigvars(mastervars[i]);
      norigvars = GCGmasterVarGetNOrigvars(mastervars[i]);
      origvals = GCGmasterVarGetOrigvals(mastervars[i]);
      blocknr = GCGvarGetBlock(mastervars[i]);
      isray = GCGmasterVarIsRay(mastervars[i]);

      assert(GCGvarIsMaster(mastervars[i]));
      assert(!SCIPisFeasNegative(scip, mastervals[i]));

      /** @todo handle infinite master solution values */
      assert(!SCIPisInfinity(scip, mastervals[i]));

      /* first of all, handle variables representing rays */
      if( isray )
      {
         assert(blocknr >= 0);
         /* we also want to take into account variables representing rays, that have a small value (between normal and feas eps),
          * so we do no feas comparison here */
         if( SCIPisPositive(scip, mastervals[i]) )
         {
            /* loop over all original variables contained in the current master variable */
            for( j = 0; j < norigvars; j++ )
            {
               if( SCIPisZero(scip, origvals[j]) )
                  break;

               assert(!SCIPisZero(scip, origvals[j]));

               /* the original variable is a linking variable: just transfer the solution value of the direct copy (this is done later) */
               if( GCGvarIsLinking(origvars[j]) )
                  continue;

               SCIPdebugMessage("Increasing value of %s by %f because of %s\n", SCIPvarGetName(origvars[j]), origvals[j] * mastervals[i], SCIPvarGetName(mastervars[i]));
               /* increase the corresponding value */
               SCIP_CALL( SCIPincSolVal(scip, *origsol, origvars[j], origvals[j] * mastervals[i]) );
            }
         }
         mastervals[i] = 0.0;
         continue;
      }

      /* handle the variables with value >= 1 to get integral values in original solution */
      while( SCIPisFeasGE(scip, mastervals[i], 1.0) )
      {
         /* variable was directly transferred to the master problem (only in linking conss or linking variable) */
         /** @todo this may be the wrong place for this case, handle it before the while loop
          * and remove the similar case in the next while loop */
         if( blocknr == -1 )
         {
            assert(norigvars == 1);
            assert(origvals[0] == 1.0);

            /* increase the corresponding value */
            SCIPdebugMessage("Increasing value of %s by %f because of %s\n", SCIPvarGetName(origvars[0]), origvals[0] * mastervals[i],  SCIPvarGetName(mastervars[i]));
            SCIP_CALL( SCIPincSolVal(scip, *origsol, origvars[0], origvals[0] * mastervals[i]) );
            mastervals[i] = 0.0;
         }
         else
         {
            assert(blocknr >= 0);
            /* loop over all original variables contained in the current master variable */
            for( j = 0; j < norigvars; j++ )
            {
               SCIP_VAR* pricingvar;
               int norigpricingvars;
               SCIP_VAR** origpricingvars;
               if( SCIPisZero(scip, origvals[j]) )
                  break;
               assert(!SCIPisZero(scip, origvals[j]));

               /* the original variable is a linking variable: just transfer the solution value of the direct copy (this is done above) */
               if( GCGvarIsLinking(origvars[j]) )
                  continue;

               pricingvar = GCGoriginalVarGetPricingVar(origvars[j]);
               assert(GCGvarIsPricing(pricingvar));

               norigpricingvars = GCGpricingVarGetNOrigvars(pricingvar);
               origpricingvars = GCGpricingVarGetOrigvars(pricingvar);

               /* just in case a variable has a value higher than the number of blocks, it represents */
               if( norigpricingvars <= blocknrs[blocknr] )
               {
                  SCIPdebugMessage("Increasing value of %s by %f because of %s\n", SCIPvarGetName(origpricingvars[norigpricingvars-1]), mastervals[i] * origvals[j], SCIPvarGetName(mastervars[i]));
                  /* increase the corresponding value */
                  SCIP_CALL( SCIPincSolVal(scip, *origsol, origpricingvars[norigpricingvars-1], mastervals[i] * origvals[j]) );
                  mastervals[i] = 1.0;
               }
               /* this should be default */
               else
               {
                  SCIPdebugMessage("Increasing value of %s by %f because of %s\n", SCIPvarGetName(origpricingvars[blocknrs[blocknr]]), origvals[j], SCIPvarGetName(mastervars[i]) );
                  /* increase the corresponding value */
                  SCIP_CALL( SCIPincSolVal(scip, *origsol, origpricingvars[blocknrs[blocknr]], origvals[j]) );
               }
            }
            mastervals[i] = mastervals[i] - 1.0;
            blocknrs[blocknr]++;
         }
      }
   }

   /* loop over all given master variables */
   for( i = 0; i < nmastervars; i++ )
   {
      SCIP_VAR** origvars;
      int norigvars;
      SCIP_Real* origvals;
      int blocknr;

      origvars = GCGmasterVarGetOrigvars(mastervars[i]);
      norigvars = GCGmasterVarGetNOrigvars(mastervars[i]);
      origvals = GCGmasterVarGetOrigvals(mastervars[i]);
      blocknr = GCGvarGetBlock(mastervars[i]);

      if( SCIPisFeasZero(scip, mastervals[i]) )
      {
         continue;
      }
      assert(SCIPisFeasGE(scip, mastervals[i], 0.0) && SCIPisFeasLT(scip, mastervals[i], 1.0));

      while( SCIPisFeasPositive(scip, mastervals[i]) )
      {
         assert(GCGvarIsMaster(mastervars[i]));
         assert(!GCGmasterVarIsRay(mastervars[i]));

         if( blocknr == -1 )
         {
            assert(norigvars == 1);
            assert(origvals[0] == 1.0);

            SCIPdebugMessage("Increasing value of %s by %f because of %s\n", SCIPvarGetName(origvars[0]), origvals[0] * mastervals[i], SCIPvarGetName(mastervars[i]) );
            /* increase the corresponding value */
            SCIP_CALL( SCIPincSolVal(scip, *origsol, origvars[0], origvals[0] * mastervals[i]) );
            mastervals[i] = 0.0;
         }
         else
         {
            increaseval = MIN(mastervals[i], 1.0 - blockvalue[blocknr]);
            /* loop over all original variables contained in the current master variable */
            for( j = 0; j < norigvars; j++ )
            {
               SCIP_VAR* pricingvar;
               int norigpricingvars;
               SCIP_VAR** origpricingvars;

               if( SCIPisZero(scip, origvals[j]) )
                  continue;

               /* the original variable is a linking variable: just transfer the solution value of the direct copy (this is done above) */
               if( GCGvarIsLinking(origvars[j]) )
                  continue;

               pricingvar = GCGoriginalVarGetPricingVar(origvars[j]);
               assert(GCGvarIsPricing(pricingvar));

               norigpricingvars = GCGpricingVarGetNOrigvars(pricingvar);
               origpricingvars = GCGpricingVarGetOrigvars(pricingvar);

               if( norigpricingvars <= blocknrs[blocknr] )
               {
                  increaseval = mastervals[i];

                  SCIPdebugMessage("Increasing value of %s by %f because of %s\n", SCIPvarGetName(origpricingvars[norigpricingvars-1]), origvals[j] * increaseval, SCIPvarGetName(mastervars[i]) );
                  /* increase the corresponding value */
                  SCIP_CALL( SCIPincSolVal(scip, *origsol, origpricingvars[norigpricingvars-1], origvals[j] * increaseval) );
               }
               else
               {
                  /* increase the corresponding value */
                  SCIPdebugMessage("Increasing value of %s by %f because of %s\n", SCIPvarGetName(origpricingvars[blocknrs[blocknr]]), origvals[j] * increaseval, SCIPvarGetName(mastervars[i]) );
                  SCIP_CALL( SCIPincSolVal(scip, *origsol, origpricingvars[blocknrs[blocknr]], origvals[j] * increaseval) );
               }
            }

            mastervals[i] = mastervals[i] - increaseval;
            if( SCIPisFeasZero(scip, mastervals[i]) )
            {
               mastervals[i] = 0.0;
            }
            blockvalue[blocknr] += increaseval;

            /* if the value assigned to the block is equal to 1, this block is full and we take the next block */
            if( SCIPisFeasGE(scip, blockvalue[blocknr], 1.0) )
            {
               blockvalue[blocknr] = 0.0;
               blocknrs[blocknr]++;
            }
         }
      }
   }

   SCIPfreeBufferArray(scip, &mastervals);
   SCIPfreeBufferArray(scip, &blocknrs);
   SCIPfreeBufferArray(scip, &blockvalue);

   /* if the solution violates one of its bounds by more than feastol
    * and less than 10*feastol, round it and print a warning
    */
   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
   SCIP_CALL( SCIPgetRealParam(scip, "numerics/feastol", &feastol) );
   for( i = 0; i < nvars; ++i )
   {
      SCIP_Real solval;
      SCIP_Real lb;
      SCIP_Real ub;

      solval = SCIPgetSolVal(scip, *origsol, vars[i]);
      lb = SCIPvarGetLbLocal(vars[i]);
      ub = SCIPvarGetUbLocal(vars[i]);

      if( SCIPisFeasGT(scip, solval, ub) && EPSEQ(solval, ub, 10 * feastol) )
      {
         SCIP_CALL( SCIPsetSolVal(scip, *origsol, vars[i], ub) );
         SCIPwarningMessage(scip, "Variable %s rounded from %g to %g in relaxation solution\n",
            SCIPvarGetName(vars[i]), solval, ub);
      }
      else if( SCIPisFeasLT(scip, solval, lb) && EPSEQ(solval, lb, 10 * feastol) )
      {
         SCIP_CALL( SCIPsetSolVal(scip, *origsol, vars[i], lb) );
         SCIPwarningMessage(scip, "Variable %s rounded from %g to %g in relaxation solution\n",
            SCIPvarGetName(vars[i]), solval, lb);
      }
   }

   return SCIP_OKAY;
}
コード例 #7
0
/** returns a score value for the given variable based on the active constraints that the variable appears in */
static
SCIP_Real getNActiveConsScore(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_SOL*             sol,                /**< working solution */
   SCIP_VAR*             var,                /**< variable to get the score value for */
   SCIP_Real*            downscore,          /**< pointer to store the score for branching downwards */
   SCIP_Real*            upscore             /**< pointer to store the score for branching upwards */
   )
{
   SCIP_COL* col;
   SCIP_ROW** rows;
   SCIP_Real* vals;
   int nrows;
   int r;
   int nactrows;
   SCIP_Real nlprows;
   SCIP_Real downcoefsum;
   SCIP_Real upcoefsum;
   SCIP_Real score;

   assert(downscore != NULL);
   assert(upscore != NULL);

   *downscore = 0.0;
   *upscore = 0.0;
   if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN )
      return 0.0;

   col = SCIPvarGetCol(var);
   assert(col != NULL);

   rows = SCIPcolGetRows(col);
   vals = SCIPcolGetVals(col);
   nrows = SCIPcolGetNLPNonz(col);
   nactrows = 0;
   downcoefsum = 0.0;
   upcoefsum = 0.0;
   for( r = 0; r < nrows; ++r )
   {
      SCIP_ROW* row;
      SCIP_Real activity;
      SCIP_Real lhs;
      SCIP_Real rhs;
      SCIP_Real dualsol;

      row = rows[r];
      /* calculate number of active constraint sides, i.e., count equations as two */
      lhs = SCIProwGetLhs(row);
      rhs = SCIProwGetRhs(row);

      /* @todo this is suboptimal because activity is calculated by looping over all nonzeros of this row, need to
       * store LP activities instead (which cannot be retrieved if no LP was solved at this node)
       */
      activity = SCIPgetRowSolActivity(scip, row, sol);

      dualsol = SCIProwGetDualsol(row);
      if( SCIPisFeasEQ(scip, activity, lhs) )
      {
         SCIP_Real coef;

         nactrows++;
         coef = vals[r] / SCIProwGetNorm(row);
         if( SCIPisFeasPositive(scip, dualsol) )
         {
            if( coef > 0.0 )
               downcoefsum += coef;
            else
               upcoefsum -= coef;
         }
      }
      else if( SCIPisFeasEQ(scip, activity, rhs) )
      {
         SCIP_Real coef;

         nactrows++;
         coef = vals[r] / SCIProwGetNorm(row);
         if( SCIPisFeasNegative(scip, dualsol) )
         {
            if( coef > 0.0 )
               upcoefsum += coef;
            else
               downcoefsum -= coef;
         }
      }
   }

   /* use the number of LP rows for normalization */
   nlprows = (SCIP_Real)SCIPgetNLPRows(scip);
   upcoefsum /= nlprows;
   downcoefsum /= nlprows;

   /* calculate the score using SCIP's branch score. Pass NULL as variable to not have the var branch factor influence
    * the result
    */
   score = nactrows / nlprows + SCIPgetBranchScore(scip, NULL, downcoefsum, upcoefsum);

   assert(score <= 3.0);
   assert(score >= 0.0);

   *downscore = downcoefsum;
   *upscore = upcoefsum;

   return score;
}
コード例 #8
0
/** execution method of primal heuristic */
static
SCIP_DECL_HEUREXEC(heurExecZirounding)
{  /*lint --e{715}*/
   SCIP_HEURDATA*     heurdata;
   SCIP_SOL*          sol;
   SCIP_VAR**         lpcands;
   SCIP_VAR**         zilpcands;

   SCIP_VAR**         slackvars;
   SCIP_Real*         upslacks;
   SCIP_Real*         downslacks;
   SCIP_Real*         activities;
   SCIP_Real*         slackvarcoeffs;
   SCIP_Bool*         rowneedsslackvar;

   SCIP_ROW**         rows;
   SCIP_Real*         lpcandssol;
   SCIP_Real*         solarray;

   SCIP_Longint       nlps;
   int                currentlpcands;
   int                nlpcands;
   int                nimplfracs;
   int                i;
   int                c;
   int                nslacks;
   int                nroundings;

   SCIP_RETCODE       retcode;

   SCIP_Bool          improvementfound;
   SCIP_Bool          numericalerror;

   assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
   assert(result != NULL);
   assert(SCIPhasCurrentNodeLP(scip));

   *result = SCIP_DIDNOTRUN;

   /* do not call heuristic of node was already detected to be infeasible */
   if( nodeinfeasible )
      return SCIP_OKAY;

   /* only call heuristic if an optimal LP-solution is at hand */
   if( SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
      return SCIP_OKAY;

   /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
   if( SCIPisGE(scip, SCIPgetLPObjval(scip), SCIPgetCutoffbound(scip)) )
      return SCIP_OKAY;

   /* get heuristic data */
   heurdata = SCIPheurGetData(heur);
   assert(heurdata != NULL);

   /* Do not call heuristic if deactivation check is enabled and percentage of found solutions in relation
    * to number of calls falls below heurdata->stoppercentage */
   if( heurdata->stopziround && SCIPheurGetNCalls(heur) >= heurdata->minstopncalls
      && SCIPheurGetNSolsFound(heur)/(SCIP_Real)SCIPheurGetNCalls(heur) < heurdata->stoppercentage )
      return SCIP_OKAY;

   /* assure that heuristic has not already been called after the last LP had been solved */
   nlps = SCIPgetNLPs(scip);
   if( nlps == heurdata->lastlp )
      return SCIP_OKAY;

   heurdata->lastlp = nlps;

   /* get fractional variables */
   SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, NULL, &nlpcands, NULL, &nimplfracs) );
   nlpcands = nlpcands + nimplfracs;
   /* make sure that there is at least one fractional variable that should be integral */
   if( nlpcands == 0 )
      return SCIP_OKAY;

   assert(nlpcands > 0);
   assert(lpcands != NULL);
   assert(lpcandssol != NULL);

   /* get LP rows data */
   rows    = SCIPgetLPRows(scip);
   nslacks = SCIPgetNLPRows(scip);

   /* cannot do anything if LP is empty */
   if( nslacks == 0 )
      return SCIP_OKAY;

   assert(rows != NULL);
   assert(nslacks > 0);

   /* get the working solution from heuristic's local data */
   sol = heurdata->sol;
   assert(sol != NULL);

   *result = SCIP_DIDNOTFIND;

   solarray = NULL;
   zilpcands = NULL;

   retcode = SCIP_OKAY;
   /* copy the current LP solution to the working solution and allocate memory for local data */
   SCIP_CALL( SCIPlinkLPSol(scip, sol) );
   SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &solarray, nlpcands), TERMINATE);
   SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &zilpcands, nlpcands), TERMINATE);

   /* copy necessary data to local arrays */
   BMScopyMemoryArray(solarray, lpcandssol, nlpcands);
   BMScopyMemoryArray(zilpcands, lpcands, nlpcands);

   /* allocate buffer data arrays */
   SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &slackvars, nslacks), TERMINATE);
   SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &upslacks, nslacks), TERMINATE);
   SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &downslacks, nslacks), TERMINATE);
   SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &slackvarcoeffs, nslacks), TERMINATE);
   SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &rowneedsslackvar, nslacks), TERMINATE);
   SCIP_CALL_TERMINATE(retcode, SCIPallocBufferArray(scip, &activities, nslacks), TERMINATE);

   BMSclearMemoryArray(slackvars, nslacks);
   BMSclearMemoryArray(slackvarcoeffs, nslacks);
   BMSclearMemoryArray(rowneedsslackvar, nslacks);

   numericalerror = FALSE;
   nroundings = 0;

   /* loop over fractional variables and involved LP rows to find all rows which require a slack variable */
   for( c = 0; c < nlpcands; ++c )
   {
      SCIP_VAR* cand;
      SCIP_ROW** candrows;
      int r;
      int ncandrows;

      cand = zilpcands[c];
      assert(cand != NULL);
      assert(SCIPcolGetLPPos(SCIPvarGetCol(cand)) >= 0);

      candrows = SCIPcolGetRows(SCIPvarGetCol(cand));
      ncandrows = SCIPcolGetNLPNonz(SCIPvarGetCol(cand));

      assert(candrows == NULL || ncandrows > 0);

      for( r = 0; r < ncandrows; ++r )
      {
         int rowpos;

         assert(candrows != NULL); /* to please flexelint */
         assert(candrows[r] != NULL);
         rowpos = SCIProwGetLPPos(candrows[r]);

         if( rowpos >= 0 && SCIPisFeasEQ(scip, SCIProwGetLhs(candrows[r]), SCIProwGetRhs(candrows[r])) )
         {
            rowneedsslackvar[rowpos] = TRUE;
            SCIPdebugMessage("  Row %s needs slack variable for variable %s\n", SCIProwGetName(candrows[r]), SCIPvarGetName(cand));
         }
      }
   }

   /* calculate row slacks for every every row that belongs to the current LP and ensure, that the current solution
    * has no violated constraint -- if any constraint is violated, i.e. a slack is significantly smaller than zero,
    * this will cause the termination of the heuristic because Zirounding does not provide feasibility recovering
    */
   for( i = 0; i < nslacks; ++i )
   {
      SCIP_ROW*          row;
      SCIP_Real          lhs;
      SCIP_Real          rhs;

      row = rows[i];

      assert(row != NULL);

      lhs = SCIProwGetLhs(row);
      rhs = SCIProwGetRhs(row);

      /* get row activity */
      activities[i] = SCIPgetRowActivity(scip, row);
      assert(SCIPisFeasLE(scip, lhs, activities[i]) && SCIPisFeasLE(scip, activities[i], rhs));

      /* in special case if LHS or RHS is (-)infinity slacks have to be initialized as infinity */
      if( SCIPisInfinity(scip, -lhs) )
         downslacks[i] = SCIPinfinity(scip);
      else
         downslacks[i] = activities[i] - lhs;

      if( SCIPisInfinity(scip, rhs) )
         upslacks[i] = SCIPinfinity(scip);
      else
         upslacks[i] = rhs - activities[i];

      SCIPdebugMessage("lhs:%5.2f <= act:%5.2g <= rhs:%5.2g --> down: %5.2g, up:%5.2g\n", lhs, activities[i], rhs, downslacks[i], upslacks[i]);

      /* row is an equation. Try to find a slack variable in the row, i.e.,
       * a continuous variable which occurs only in this row. If no such variable exists,
       * there is no hope for an IP-feasible solution in this round
       */
      if( SCIPisFeasEQ(scip, lhs, rhs) && rowneedsslackvar[i] )
      {
         /* @todo: This is only necessary for rows containing fractional variables. */
         rowFindSlackVar(scip, row, &(slackvars[i]), &(slackvarcoeffs[i]));

         if( slackvars[i] == NULL )
         {
            SCIPdebugMessage("No slack variable found for equation %s, terminating ZI Round heuristic\n", SCIProwGetName(row));
            goto TERMINATE;
         }
         else
         {
            SCIP_Real ubslackvar;
            SCIP_Real lbslackvar;
            SCIP_Real solvalslackvar;
            SCIP_Real coeffslackvar;
            SCIP_Real ubgap;
            SCIP_Real lbgap;

            assert(SCIPvarGetType(slackvars[i]) == SCIP_VARTYPE_CONTINUOUS);
            solvalslackvar = SCIPgetSolVal(scip, sol, slackvars[i]);
            ubslackvar = SCIPvarGetUbGlobal(slackvars[i]);
            lbslackvar = SCIPvarGetLbGlobal(slackvars[i]);

            coeffslackvar = slackvarcoeffs[i];
            assert(!SCIPisFeasZero(scip, coeffslackvar));

            ubgap = ubslackvar - solvalslackvar;
            lbgap = solvalslackvar - lbslackvar;

            if( SCIPisFeasZero(scip, ubgap) )
              ubgap = 0.0;
            if( SCIPisFeasZero(scip, lbgap) )
              lbgap = 0.0;

            if( SCIPisFeasPositive(scip, coeffslackvar) )
            {
              if( !SCIPisInfinity(scip, lbslackvar) )
                upslacks[i] += coeffslackvar * lbgap;
              else
                upslacks[i] = SCIPinfinity(scip);
              if( !SCIPisInfinity(scip, ubslackvar) )
                downslacks[i] += coeffslackvar * ubgap;
              else
                downslacks[i] = SCIPinfinity(scip);
            }
            else
            {
               if( !SCIPisInfinity(scip, ubslackvar) )
                  upslacks[i] -= coeffslackvar * ubgap;
               else
                  upslacks[i] = SCIPinfinity(scip);
               if( !SCIPisInfinity(scip, lbslackvar) )
                  downslacks[i] -= coeffslackvar * lbgap;
               else
                  downslacks[i] = SCIPinfinity(scip);
            }
            SCIPdebugMessage("  Slack variable for row %s at pos %d: %g <= %s = %g <= %g; Coeff %g, upslack = %g, downslack = %g  \n",
               SCIProwGetName(row), SCIProwGetLPPos(row), lbslackvar, SCIPvarGetName(slackvars[i]), solvalslackvar, ubslackvar, coeffslackvar,
               upslacks[i], downslacks[i]);
         }
      }
      /* due to numerical inaccuracies, the rows might be feasible, even if the slacks are
       * significantly smaller than zero -> terminate
       */
      if( SCIPisFeasLT(scip, upslacks[i], 0.0) || SCIPisFeasLT(scip, downslacks[i], 0.0) )
         goto TERMINATE;
   }

   assert(nslacks == 0 || (upslacks != NULL && downslacks != NULL && activities != NULL));

   /* initialize number of remaining variables and flag to enter the main loop */
   currentlpcands = nlpcands;
   improvementfound = TRUE;

   /* iterate over variables as long as there are fractional variables left */
   while( currentlpcands > 0 && improvementfound && (heurdata->maxroundingloops == -1 || nroundings < heurdata->maxroundingloops) )
   {  /*lint --e{850}*/
      improvementfound = FALSE;
      nroundings++;
      SCIPdebugMessage("zirounding enters while loop for %d time with %d candidates left. \n", nroundings, currentlpcands);

      /* check for every remaining fractional variable if a shifting decreases ZI-value of the variable */
      for( c = 0; c < currentlpcands; ++c )
      {
         SCIP_VAR* var;
         SCIP_Real oldsolval;
         SCIP_Real upperbound;
         SCIP_Real lowerbound;
         SCIP_Real up;
         SCIP_Real down;
         SCIP_Real ziup;
         SCIP_Real zidown;
         SCIP_Real zicurrent;
         SCIP_Real shiftval;

         DIRECTION direction;

         /* get values from local data */
         oldsolval = solarray[c];
         var = zilpcands[c];

         assert(!SCIPisFeasIntegral(scip, oldsolval));
         assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);

         /* calculate bounds for variable and make sure that there are no numerical inconsistencies */
         upperbound = SCIPinfinity(scip);
         lowerbound = SCIPinfinity(scip);
         calculateBounds(scip, var, oldsolval, &upperbound, &lowerbound, upslacks, downslacks, nslacks, &numericalerror);

         if( numericalerror )
            goto TERMINATE;

         /* calculate the possible values after shifting */
         up   = oldsolval + upperbound;
         down = oldsolval - lowerbound;

         /* if the variable is integer or implicit binary, do not shift further than the nearest integer */
         if( SCIPvarGetType(var) != SCIP_VARTYPE_BINARY)
         {
            SCIP_Real ceilx;
            SCIP_Real floorx;

            ceilx = SCIPfeasCeil(scip, oldsolval);
            floorx = SCIPfeasFloor(scip, oldsolval);
            up   = MIN(up, ceilx);
            down = MAX(down, floorx);
         }

         /* calculate necessary values */
         ziup      = getZiValue(scip, up);
         zidown    = getZiValue(scip, down);
         zicurrent = getZiValue(scip, oldsolval);

         /* calculate the shifting direction that reduces ZI-value the most,
          * if both directions improve ZI-value equally, take the direction which improves the objective
          */
         if( SCIPisFeasLT(scip, zidown, zicurrent) || SCIPisFeasLT(scip, ziup, zicurrent) )
         {
            if( SCIPisFeasEQ(scip,ziup, zidown) )
               direction  = SCIPisFeasGE(scip, SCIPvarGetObj(var), 0.0) ? DIRECTION_DOWN : DIRECTION_UP;
            else if( SCIPisFeasLT(scip, zidown, ziup) )
               direction = DIRECTION_DOWN;
            else
               direction = DIRECTION_UP;

            /* once a possible shifting direction and value have been found, variable value is updated */
            shiftval = (direction == DIRECTION_UP ? up - oldsolval : down - oldsolval);

            /* this improves numerical stability in some cases */
            if( direction == DIRECTION_UP )
               shiftval = MIN(shiftval, upperbound);
            else
               shiftval = MIN(shiftval, lowerbound);
            /* update the solution */
            solarray[c] = direction == DIRECTION_UP ? up : down;
            SCIP_CALL( SCIPsetSolVal(scip, sol, var, solarray[c]) );

            /* update the rows activities and slacks */
            SCIP_CALL( updateSlacks(scip, sol, var, shiftval, upslacks,
                  downslacks, activities, slackvars, slackvarcoeffs, nslacks) );

            SCIPdebugMessage("zirounding update step : %d var index, oldsolval=%g, shiftval=%g\n",
               SCIPvarGetIndex(var), oldsolval, shiftval);
            /* since at least one improvement has been found, heuristic will enter main loop for another time because the improvement
             * might affect many LP rows and their current slacks and thus make further rounding steps possible */
            improvementfound = TRUE;
         }

         /* if solution value of variable has become feasibly integral due to rounding step,
          * variable is put at the end of remaining candidates array so as not to be considered in future loops
          */
         if( SCIPisFeasIntegral(scip, solarray[c]) )
         {
            zilpcands[c] = zilpcands[currentlpcands - 1];
            solarray[c] = solarray[currentlpcands - 1];
            currentlpcands--;

            /* counter is decreased if end of candidates array has not been reached yet */
            if( c < currentlpcands )
               c--;
         }
         else if( nroundings == heurdata->maxroundingloops - 1 )
            goto TERMINATE;
      }
   }

   /* in case that no candidate is left for rounding after the final main loop
    * the found solution has to be checked for feasibility in the original problem
    */
   if( currentlpcands == 0 )
   {
      SCIP_Bool stored;
      SCIP_CALL(SCIPtrySol(scip, sol, FALSE, FALSE, TRUE, FALSE, &stored));
      if( stored )
      {
#ifdef SCIP_DEBUG
         SCIPdebugMessage("found feasible rounded solution:\n");
         SCIP_CALL( SCIPprintSol(scip, sol, NULL, FALSE) );
#endif
         SCIPstatisticMessage("  ZI Round solution value: %g \n", SCIPgetSolOrigObj(scip, sol));

         *result = SCIP_FOUNDSOL;
      }
   }

   /* free memory for all locally allocated data */
 TERMINATE:
   SCIPfreeBufferArrayNull(scip, &activities);
   SCIPfreeBufferArrayNull(scip, &rowneedsslackvar);
   SCIPfreeBufferArrayNull(scip, &slackvarcoeffs);
   SCIPfreeBufferArrayNull(scip, &downslacks);
   SCIPfreeBufferArrayNull(scip, &upslacks);
   SCIPfreeBufferArrayNull(scip, &slackvars);
   SCIPfreeBufferArrayNull(scip, &zilpcands);
   SCIPfreeBufferArrayNull(scip, &solarray);

   return retcode;
}
コード例 #9
0
ファイル: sepa_disjunctive.c プロジェクト: gorhan/LFOS
/** LP solution separation method for disjunctive cuts */
static
SCIP_DECL_SEPAEXECLP(sepaExeclpDisjunctive)
{
   SCIP_SEPADATA* sepadata;
   SCIP_CONSHDLR* conshdlr;
   SCIP_DIGRAPH* conflictgraph;
   SCIP_ROW** rows;
   SCIP_COL** cols;
   SCIP_Real* cutcoefs = NULL;
   SCIP_Real* simplexcoefs1 = NULL;
   SCIP_Real* simplexcoefs2 = NULL;
   SCIP_Real* coef = NULL;
   SCIP_Real* binvrow = NULL;
   SCIP_Real* rowsmaxval = NULL;
   SCIP_Real* violationarray = NULL;
   int* fixings1 = NULL;
   int* fixings2 = NULL;
   int* basisind = NULL;
   int* basisrow = NULL;
   int* varrank = NULL;
   int* edgearray = NULL;
   int nedges;
   int ndisjcuts;
   int nrelevantedges;
   int nsos1vars;
   int nconss;
   int maxcuts;
   int ncalls;
   int depth;
   int ncols;
   int nrows;
   int ind;
   int j;
   int i;

   assert( sepa != NULL );
   assert( strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0 );
   assert( scip != NULL );
   assert( result != NULL );

   *result = SCIP_DIDNOTRUN;

   /* only generate disjunctive cuts if we are not close to terminating */
   if ( SCIPisStopped(scip) )
      return SCIP_OKAY;

   /* only generate disjunctive cuts if an optimal LP solution is at hand */
   if ( SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
      return SCIP_OKAY;

   /* only generate disjunctive cuts if the LP solution is basic */
   if ( ! SCIPisLPSolBasic(scip) )
      return SCIP_OKAY;

   /* get LP data */
   SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
   SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );

   /* return if LP has no columns or no rows */
   if ( ncols == 0 || nrows == 0 )
      return SCIP_OKAY;

   assert( cols != NULL );
   assert( rows != NULL );

   /* get sepa data */
   sepadata = SCIPsepaGetData(sepa);
   assert( sepadata != NULL );

   /* get constraint handler */
   conshdlr = sepadata->conshdlr;
   if ( conshdlr == NULL )
      return SCIP_OKAY;

   /* get number of constraints */
   nconss = SCIPconshdlrGetNConss(conshdlr);
   if ( nconss == 0 )
      return SCIP_OKAY;

   /* check for maxdepth < depth, maxinvcutsroot = 0 and maxinvcuts = 0 */
   depth = SCIPgetDepth(scip);
   if ( ( sepadata->maxdepth >= 0 && sepadata->maxdepth < depth )
      || ( depth == 0 && sepadata->maxinvcutsroot == 0 )
      || ( depth > 0 && sepadata->maxinvcuts == 0 ) )
      return SCIP_OKAY;

   /* only call the cut separator a given number of times at each node */
   ncalls = SCIPsepaGetNCallsAtNode(sepa);
   if ( (depth == 0 && sepadata->maxroundsroot >= 0 && ncalls >= sepadata->maxroundsroot)
      || (depth > 0 && sepadata->maxrounds >= 0 && ncalls >= sepadata->maxrounds) )
      return SCIP_OKAY;

   /* get conflict graph and number of conflict graph edges (note that the digraph arcs were added in both directions) */
   conflictgraph = SCIPgetConflictgraphSOS1(conshdlr);
   nedges = (int)SCIPceil(scip, (SCIP_Real)SCIPdigraphGetNArcs(conflictgraph)/2);

   /* if too many conflict graph edges, the separator can be slow: delay it until no other cuts have been found */
   if ( sepadata->maxconfsdelay >= 0 && nedges >= sepadata->maxconfsdelay )
   {
      int ncutsfound;

      ncutsfound = SCIPgetNCutsFound(scip);
      if ( ncutsfound > sepadata->lastncutsfound || ! SCIPsepaWasLPDelayed(sepa) )
      {
         sepadata->lastncutsfound = ncutsfound;
         *result = SCIP_DELAYED;
         return SCIP_OKAY;
      }
   }

   /* check basis status */
   for (j = 0; j < ncols; ++j)
   {
      if ( SCIPcolGetBasisStatus(cols[j]) == SCIP_BASESTAT_ZERO )
         return SCIP_OKAY;
   }

   /* get number of SOS1 variables */
   nsos1vars = SCIPgetNSOS1Vars(conshdlr);

   /* allocate buffer arrays */
   SCIP_CALL( SCIPallocBufferArray(scip, &edgearray, nedges) );
   SCIP_CALL( SCIPallocBufferArray(scip, &fixings1, nedges) );
   SCIP_CALL( SCIPallocBufferArray(scip, &fixings2, nedges) );
   SCIP_CALL( SCIPallocBufferArray(scip, &violationarray, nedges) );

   /* get all violated conflicts {i, j} in the conflict graph and sort them based on the degree of a violation value */
   nrelevantedges = 0;
   for (j = 0; j < nsos1vars; ++j)
   {
      SCIP_VAR* var;

      var = SCIPnodeGetVarSOS1(conflictgraph, j);

      if ( SCIPvarIsActive(var) && ! SCIPisFeasZero(scip, SCIPcolGetPrimsol(SCIPvarGetCol(var))) && SCIPcolGetBasisStatus(SCIPvarGetCol(var)) == SCIP_BASESTAT_BASIC )
      {
         int* succ;
         int nsucc;

         /* get successors and number of successors */
         nsucc = SCIPdigraphGetNSuccessors(conflictgraph, j);
         succ = SCIPdigraphGetSuccessors(conflictgraph, j);

         for (i = 0; i < nsucc; ++i)
         {
            SCIP_VAR* varsucc;
            int succind;

            succind = succ[i];
            varsucc = SCIPnodeGetVarSOS1(conflictgraph, succind);
            if ( SCIPvarIsActive(varsucc) && succind < j && ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, NULL, varsucc) ) &&
                 SCIPcolGetBasisStatus(SCIPvarGetCol(varsucc)) == SCIP_BASESTAT_BASIC )
            {
               fixings1[nrelevantedges] = j;
               fixings2[nrelevantedges] = succind;
               edgearray[nrelevantedges] = nrelevantedges;
               violationarray[nrelevantedges++] = SCIPgetSolVal(scip, NULL, var) * SCIPgetSolVal(scip, NULL, varsucc);
            }
         }
      }
   }

   /* sort violation score values */
   if ( nrelevantedges > 0)
      SCIPsortDownRealInt(violationarray, edgearray, nrelevantedges);
   else
   {
      SCIPfreeBufferArrayNull(scip, &violationarray);
      SCIPfreeBufferArrayNull(scip, &fixings2);
      SCIPfreeBufferArrayNull(scip, &fixings1);
      SCIPfreeBufferArrayNull(scip, &edgearray);

      return SCIP_OKAY;
   }
   SCIPfreeBufferArrayNull(scip, &violationarray);

   /* compute maximal number of cuts */
   if ( SCIPgetDepth(scip) == 0 )
      maxcuts = MIN(sepadata->maxinvcutsroot, nrelevantedges);
   else
      maxcuts = MIN(sepadata->maxinvcuts, nrelevantedges);
   assert( maxcuts > 0 );

   /* allocate buffer arrays */
   SCIP_CALL( SCIPallocBufferArray(scip, &varrank, ncols) );
   SCIP_CALL( SCIPallocBufferArray(scip, &rowsmaxval, nrows) );
   SCIP_CALL( SCIPallocBufferArray(scip, &basisrow, ncols) );
   SCIP_CALL( SCIPallocBufferArray(scip, &binvrow, nrows) );
   SCIP_CALL( SCIPallocBufferArray(scip, &coef, ncols) );
   SCIP_CALL( SCIPallocBufferArray(scip, &simplexcoefs1, ncols) );
   SCIP_CALL( SCIPallocBufferArray(scip, &simplexcoefs2, ncols) );
   SCIP_CALL( SCIPallocBufferArray(scip, &cutcoefs, ncols) );
   SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );

   /* get basis indices */
   SCIP_CALL( SCIPgetLPBasisInd(scip, basisind) );

   /* create vector "basisrow" with basisrow[column of non-slack basis variable] = corresponding row of B^-1;
    * compute maximum absolute value of nonbasic row coefficients */
   for (j = 0; j < nrows; ++j)
   {
      SCIP_COL** rowcols;
      SCIP_Real* rowvals;
      SCIP_ROW* row;
      SCIP_Real val;
      SCIP_Real max = 0.0;
      int nnonz;

      /* fill basisrow vector */
      ind = basisind[j];
      if ( ind >= 0 )
         basisrow[ind] = j;

      /* compute maximum absolute value of nonbasic row coefficients */
      row = rows[j];
      assert( row != NULL );
      rowvals = SCIProwGetVals(row);
      nnonz = SCIProwGetNNonz(row);
      rowcols = SCIProwGetCols(row);

      for (i = 0; i < nnonz; ++i)
      {
         if ( SCIPcolGetBasisStatus(rowcols[i]) == SCIP_BASESTAT_LOWER  || SCIPcolGetBasisStatus(rowcols[i]) == SCIP_BASESTAT_UPPER )
         {
            val = REALABS(rowvals[i]);
            if ( SCIPisFeasGT(scip, val, max) )
               max = REALABS(val);
         }
      }

      /* handle slack variable coefficient and save maximum value */
      rowsmaxval[j] = MAX(max, 1.0);
   }

   /* initialize variable ranks with -1 */
   for (j = 0; j < ncols; ++j)
      varrank[j] = -1;

   /* free buffer array */
   SCIPfreeBufferArrayNull(scip, &basisind);

   /* for the most promising disjunctions: try to generate disjunctive cuts */
   ndisjcuts = 0;
   for (i = 0; i < maxcuts; ++i)
   {
      SCIP_Bool madeintegral;
      SCIP_Real cutlhs1;
      SCIP_Real cutlhs2;
      SCIP_Real bound1;
      SCIP_Real bound2;
      SCIP_ROW* row = NULL;
      SCIP_VAR* var;
      SCIP_COL* col;

      int nonbasicnumber;
      int cutrank = 0;
      int edgenumber;
      int rownnonz;

      edgenumber = edgearray[i];

      /* determine first simplex row */
      var = SCIPnodeGetVarSOS1(conflictgraph, fixings1[edgenumber]);
      col = SCIPvarGetCol(var);
      ind = SCIPcolGetLPPos(col);
      assert( ind >= 0 );
      assert( SCIPcolGetBasisStatus(col) == SCIP_BASESTAT_BASIC );

      /* get the 'ind'th row of B^-1 and B^-1 \cdot A */
      SCIP_CALL( SCIPgetLPBInvRow(scip, basisrow[ind], binvrow, NULL, NULL) );
      SCIP_CALL( SCIPgetLPBInvARow(scip, basisrow[ind], binvrow, coef, NULL, NULL) );

      /* get the simplex-coefficients of the non-basic variables */
      SCIP_CALL( getSimplexCoefficients(scip, rows, nrows, cols, ncols, coef, binvrow, simplexcoefs1, &nonbasicnumber) );

      /* get rank of variable if not known already */
      if ( varrank[ind] < 0 )
         varrank[ind] = getVarRank(scip, binvrow, rowsmaxval, sepadata->maxweightrange, rows, nrows);
      cutrank = MAX(cutrank, varrank[ind]);

      /* get right hand side and bound of simplex talbeau row */
      cutlhs1 = SCIPcolGetPrimsol(col);
      if ( SCIPisFeasPositive(scip, cutlhs1) )
         bound1 = SCIPcolGetUb(col);
      else
         bound1 = SCIPcolGetLb(col);


      /* determine second simplex row */
      var = SCIPnodeGetVarSOS1(conflictgraph, fixings2[edgenumber]);
      col = SCIPvarGetCol(var);
      ind = SCIPcolGetLPPos(col);
      assert( ind >= 0 );
      assert( SCIPcolGetBasisStatus(col) == SCIP_BASESTAT_BASIC );

      /* get the 'ind'th row of B^-1 and B^-1 \cdot A */
      SCIP_CALL( SCIPgetLPBInvRow(scip, basisrow[ind], binvrow, NULL, NULL) );
      SCIP_CALL( SCIPgetLPBInvARow(scip, basisrow[ind], binvrow, coef, NULL, NULL) );

      /* get the simplex-coefficients of the non-basic variables */
      SCIP_CALL( getSimplexCoefficients(scip, rows, nrows, cols, ncols, coef, binvrow, simplexcoefs2, &nonbasicnumber) );

      /* get rank of variable if not known already */
      if ( varrank[ind] < 0 )
         varrank[ind] = getVarRank(scip, binvrow, rowsmaxval, sepadata->maxweightrange, rows, nrows);
      cutrank = MAX(cutrank, varrank[ind]);

      /* get right hand side and bound of simplex talbeau row */
      cutlhs2 = SCIPcolGetPrimsol(col);
      if ( SCIPisFeasPositive(scip, cutlhs2) )
         bound2 = SCIPcolGetUb(col);
      else
         bound2 = SCIPcolGetLb(col);

      /* add coefficients to cut */
      SCIP_CALL( generateDisjCutSOS1(scip, sepa, rows, nrows, cols, ncols, ndisjcuts, TRUE, sepadata->strengthen, cutlhs1, cutlhs2, bound1, bound2, simplexcoefs1, simplexcoefs2, cutcoefs, &row, &madeintegral) );
      if ( row == NULL )
         continue;

      /* raise cutrank for present cut */
      ++cutrank;

      /* check if there are numerical evidences */
      if ( ( madeintegral && ( sepadata->maxrankintegral == -1 || cutrank <= sepadata->maxrankintegral ) )
         || ( ! madeintegral && ( sepadata->maxrank == -1 || cutrank <= sepadata->maxrank ) ) )
      {
         /* possibly add cut to LP if it is useful; in case the lhs of the cut is minus infinity (due to scaling) the cut is useless */
         rownnonz = SCIProwGetNNonz(row);
         if ( rownnonz > 0 && ! SCIPisInfinity(scip, -SCIProwGetLhs(row)) && ! SCIProwIsInLP(row) && SCIPisCutEfficacious(scip, NULL, row) )
         {
            SCIP_Bool infeasible;

            /* set cut rank */
            SCIProwChgRank(row, cutrank);

            /* add cut */
            SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, &infeasible) );
            SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
            if ( infeasible )
            {
               *result = SCIP_CUTOFF;
               break;
            }
            ++ndisjcuts;
         }
      }

      /* release row */
      SCIP_CALL( SCIPreleaseRow(scip, &row) );
   }

   /* save total number of cuts found so far */
   sepadata->lastncutsfound = SCIPgetNCutsFound(scip);

   /* evaluate the result of the separation */
   if ( *result != SCIP_CUTOFF )
   {
      if ( ndisjcuts > 0 )
         *result = SCIP_SEPARATED;
      else
         *result = SCIP_DIDNOTFIND;
   }

   SCIPdebugMessage("Number of found disjunctive cuts: %d.\n", ndisjcuts);

   /* free buffer arrays */
   SCIPfreeBufferArrayNull(scip, &cutcoefs);
   SCIPfreeBufferArrayNull(scip, &simplexcoefs2);
   SCIPfreeBufferArrayNull(scip, &simplexcoefs1);
   SCIPfreeBufferArrayNull(scip, &coef);
   SCIPfreeBufferArrayNull(scip, &binvrow);
   SCIPfreeBufferArrayNull(scip, &basisrow);
   SCIPfreeBufferArrayNull(scip, &fixings2);
   SCIPfreeBufferArrayNull(scip, &fixings1);
   SCIPfreeBufferArrayNull(scip, &edgearray);
   SCIPfreeBufferArrayNull(scip, &rowsmaxval);
   SCIPfreeBufferArrayNull(scip, &varrank);

   return SCIP_OKAY;
}
コード例 #10
0
ファイル: sepa_disjunctive.c プロジェクト: gorhan/LFOS
/** computes a disjunctive cut inequality based on two simplex taubleau rows */
static
SCIP_RETCODE generateDisjCutSOS1(
   SCIP*                 scip,               /**< SCIP pointer */
   SCIP_SEPA*            sepa,               /**< separator */
   SCIP_ROW**            rows,               /**< LP rows */
   int                   nrows,              /**< number of LP rows */
   SCIP_COL**            cols,               /**< LP columns */
   int                   ncols,              /**< number of LP columns */
   int                   ndisjcuts,          /**< number of disjunctive cuts found so far */
   SCIP_Bool             scale,              /**< should cut be scaled */
   SCIP_Bool             strengthen,         /**< should cut be strengthened if integer variables are present */
   SCIP_Real             cutlhs1,            /**< left hand side of the first simplex row */
   SCIP_Real             cutlhs2,            /**< left hand side of the second simplex row */
   SCIP_Real             bound1,             /**< bound of first simplex row */
   SCIP_Real             bound2,             /**< bound of second simplex row */
   SCIP_Real*            simplexcoefs1,      /**< simplex coefficients of first row */
   SCIP_Real*            simplexcoefs2,      /**< simplex coefficients of second row */
   SCIP_Real*            cutcoefs,           /**< pointer to store cut coefficients (length: nscipvars) */
   SCIP_ROW**            row,                /**< pointer to store disjunctive cut inequality */
   SCIP_Bool*            madeintegral        /**< pointer to store whether cut has been scaled to integral values */
   )
{
   char cutname[SCIP_MAXSTRLEN];
   SCIP_COL** rowcols;
   SCIP_COL* col;
   SCIP_Real* rowvals;
   SCIP_Real lhsrow;
   SCIP_Real rhsrow;
   SCIP_Real cutlhs;
   SCIP_Real sgn;
   SCIP_Real lb;
   SCIP_Real ub;
   int nonbasicnumber = 0;
   int rownnonz;
   int ind;
   int r;
   int c;

   assert( scip != NULL );
   assert( row != NULL );
   assert( rows != NULL );
   assert( cols != NULL );
   assert( simplexcoefs1 != NULL );
   assert( simplexcoefs2 != NULL );
   assert( cutcoefs != NULL );
   assert( sepa != NULL );
   assert( madeintegral != NULL );

   *madeintegral = FALSE;

   /* check signs */
   if ( SCIPisFeasPositive(scip, cutlhs1) == SCIPisFeasPositive(scip, cutlhs2) )
      sgn = 1.0;
   else
      sgn = -1.0;

   /* check bounds */
   if ( SCIPisInfinity(scip, REALABS(bound1)) || SCIPisInfinity(scip, REALABS(bound2)) )
      strengthen = FALSE;

   /* compute left hand side of row (a later update is possible, see below) */
   cutlhs = sgn * cutlhs1 * cutlhs2;

   /* add cut-coefficients of the non-basic non-slack variables */
   for (c = 0; c < ncols; ++c)
   {
      col = cols[c];
      assert( col != NULL );
      ind = SCIPcolGetLPPos(col);
      assert( ind >= 0 );

      if ( SCIPcolGetBasisStatus(col) == SCIP_BASESTAT_LOWER )
      {
         lb = SCIPcolGetLb(col);

         /* for integer variables we may obtain stronger coefficients */
         if ( strengthen && SCIPcolIsIntegral(col) )
         {
            SCIP_Real mval;
            SCIP_Real mvalfloor;
            SCIP_Real mvalceil;

            mval = (cutlhs2 * simplexcoefs1[nonbasicnumber] - cutlhs1 * simplexcoefs2[nonbasicnumber]) / (cutlhs2 * bound1 + cutlhs1 * bound2);
            mvalfloor = SCIPfloor(scip, mval);
            mvalceil = SCIPceil(scip, mval);

            cutcoefs[ind] = MIN(sgn * cutlhs2 * (simplexcoefs1[nonbasicnumber] - mvalfloor * bound1), sgn * cutlhs1 * (simplexcoefs2[nonbasicnumber] + mvalceil * bound2));
            assert( SCIPisFeasLE(scip, cutcoefs[ind], MAX(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber])) );
         }
         else
            cutcoefs[ind] = MAX(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);

         cutlhs += cutcoefs[ind] * lb;
         ++nonbasicnumber;
      }
      else if ( SCIPcolGetBasisStatus(col) == SCIP_BASESTAT_UPPER )
      {
         ub = SCIPcolGetUb(col);

         /* for integer variables we may obtain stronger coefficients */
         if ( strengthen && SCIPcolIsIntegral(col) )
         {
            SCIP_Real mval;
            SCIP_Real mvalfloor;
            SCIP_Real mvalceil;

            mval = (cutlhs2 * simplexcoefs1[nonbasicnumber] - cutlhs1 * simplexcoefs2[nonbasicnumber]) / (cutlhs2 * bound1 + cutlhs1 * bound2);
            mvalfloor = SCIPfloor(scip, -mval);
            mvalceil = SCIPceil(scip, -mval);

            cutcoefs[ind] = MAX(sgn * cutlhs2 * (simplexcoefs1[nonbasicnumber] + mvalfloor * bound1), sgn * cutlhs1 * (simplexcoefs2[nonbasicnumber] - mvalceil * bound2));
            assert( SCIPisFeasLE(scip, -cutcoefs[ind], -MIN(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber])) );
         }
         else
            cutcoefs[ind] = MIN(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);

         cutlhs += cutcoefs[ind] * ub;
         ++nonbasicnumber;
      }
      else
      {
         assert( SCIPcolGetBasisStatus(col) != SCIP_BASESTAT_ZERO );
         cutcoefs[ind] = 0.0;
      }
   }

   /* add cut-coefficients of the non-basic slack variables */
   for (r = 0; r < nrows; ++r)
   {
      rhsrow = SCIProwGetRhs(rows[r]) - SCIProwGetConstant(rows[r]);
      lhsrow = SCIProwGetLhs(rows[r]) - SCIProwGetConstant(rows[r]);

      assert( SCIProwGetBasisStatus(rows[r]) != SCIP_BASESTAT_ZERO );
      assert( SCIPisFeasZero(scip, lhsrow - rhsrow) || SCIPisNegative(scip, lhsrow - rhsrow) );
      assert( SCIProwIsInLP(rows[r]) );

      if ( SCIProwGetBasisStatus(rows[r]) != SCIP_BASESTAT_BASIC )
      {
         SCIP_Real cutcoef;

         if ( SCIProwGetBasisStatus(rows[r]) == SCIP_BASESTAT_UPPER )
         {
            assert( SCIPisFeasZero(scip, SCIPgetRowLPActivity(scip, rows[r]) - SCIProwGetRhs(rows[r])) );

            cutcoef = MAX(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
            cutlhs -= cutcoef * rhsrow;
            ++nonbasicnumber;
         }
         else /* SCIProwGetBasisStatus(rows[r]) == SCIP_BASESTAT_LOWER */
         {
            assert( SCIProwGetBasisStatus(rows[r]) == SCIP_BASESTAT_LOWER );
            assert( SCIPisFeasZero(scip, SCIPgetRowLPActivity(scip, rows[r]) - SCIProwGetLhs(rows[r])) );

            cutcoef = MIN(sgn * cutlhs2 * simplexcoefs1[nonbasicnumber], sgn * cutlhs1 * simplexcoefs2[nonbasicnumber]);
            cutlhs -= cutcoef * lhsrow;
            ++nonbasicnumber;
         }

         rownnonz = SCIProwGetNNonz(rows[r]);
         rowvals = SCIProwGetVals(rows[r]);
         rowcols = SCIProwGetCols(rows[r]);

         for (c = 0; c < rownnonz; ++c)
         {
            ind = SCIPcolGetLPPos(rowcols[c]);

            /* if column is not in LP, then return without generating cut */
            if ( ind < 0 )
            {
               *row = NULL;
               return SCIP_OKAY;
            }

            cutcoefs[ind] -= cutcoef * rowvals[c];
         }
      }
   }

   /* create cut */
   (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "%s_%d_%d", SCIPsepaGetName(sepa), SCIPgetNLPs(scip), ndisjcuts);
   if ( SCIPgetDepth(scip) == 0 )
      SCIP_CALL( SCIPcreateEmptyRowSepa(scip, row, sepa, cutname, cutlhs, SCIPinfinity(scip), FALSE, FALSE, TRUE) );
   else
      SCIP_CALL( SCIPcreateEmptyRowSepa(scip, row, sepa, cutname, cutlhs, SCIPinfinity(scip), TRUE, FALSE, TRUE) );

   SCIP_CALL( SCIPcacheRowExtensions(scip, *row) );
   for (c = 0; c < ncols; ++c)
   {
      ind = SCIPcolGetLPPos(cols[c]);
      assert( ind >= 0 );
      if ( ! SCIPisFeasZero(scip, cutcoefs[ind]) )
      {
         SCIP_CALL( SCIPaddVarToRow(scip, *row, SCIPcolGetVar(cols[c]), cutcoefs[ind] ) );
      }
   }
   SCIP_CALL( SCIPflushRowExtensions(scip, *row) );

   /* try to scale the cut to integral values
    * @todo find better but still stable disjunctive cut settings
    */
   if ( scale )
   {
      int maxdepth;
      int depth;
      SCIP_Longint maxdnom;
      SCIP_Real maxscale;

      depth = SCIPgetDepth(scip);
      assert( depth >= 0 );
      maxdepth = SCIPgetMaxDepth(scip);
      if ( depth == 0 )
      {
         maxdnom = 1000;
         maxscale = 1000.0;
      }
      else if ( depth <= maxdepth/4 )
      {
         maxdnom = 1000;
         maxscale = 1000.0;
      }
      else if ( depth <= maxdepth/2 )
      {
         maxdnom = 100;
         maxscale = 100.0;
      }
      else
      {
         maxdnom = 10;
         maxscale = 10.0;
      }

      SCIP_CALL( SCIPmakeRowIntegral(scip, *row, -SCIPepsilon(scip), SCIPsumepsilon(scip), maxdnom, maxscale, TRUE, madeintegral) );
   }

   return SCIP_OKAY;
}
コード例 #11
0
/** execution method of primal heuristic */
static
SCIP_DECL_HEUREXEC(heurExecOctane)
{  /*lint --e{715}*/
   SCIP_HEURDATA* heurdata;
   SCIP_SOL* sol;
   SCIP_SOL** first_sols;     /* stores the first ffirst sols in order to check for common violation of a row */

   SCIP_VAR** vars;           /* the variables of the problem */
   SCIP_VAR** fracvars;       /* variables, that are fractional in current LP solution */
   SCIP_VAR** subspacevars;   /* the variables on which the search is performed. Either coinciding with vars or with the
                               * space of all fractional variables of the current LP solution */

   SCIP_Real p;               /* n/2 - <delta,x> ( for some facet delta ) */
   SCIP_Real q;               /* <delta,a> */

   SCIP_Real* rayorigin;      /* origin of the ray, vector x in paper */
   SCIP_Real* raydirection;   /* direction of the ray, vector a in paper */
   SCIP_Real* negquotient;    /* negated quotient of rayorigin and raydirection, vector v in paper */
   SCIP_Real* lambda;         /* stores the distance of the facets (s.b.) to the origin of the ray */

   SCIP_Bool usefracspace;    /* determines whether the search concentrates on fractional variables and fixes integer ones */
   SCIP_Bool cons_viol;       /* used for checking whether a linear constraint is violated by one of the possible solutions */
   SCIP_Bool success;
   SCIP_Bool* sign;           /* signature of the direction of the ray */
   SCIP_Bool** facets;        /* list of extended facets */

   int nvars;            /* number of variables  */
   int nbinvars;         /* number of 0-1-variables */
   int nfracvars;        /* number of fractional variables in current LP solution */
   int nsubspacevars;    /* dimension of the subspace on which the search is performed */
   int nfacets;          /* number of facets hidden by the ray that where already found */
   int i;                /* counter */
   int j;                /* counter */
   int f_max;            /* {0,1}-points to be checked */
   int f_first;          /* {0,1}-points to be generated at first in order to check whether a restart is necessary */
   int r;                /* counter */
   int firstrule;

   int* perm;            /* stores the way in which the coordinates were permuted */
   int* fracspace;       /* maps the variables of the subspace to the original variables */

   assert(heur != NULL);
   assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
   assert(scip != NULL);
   assert(result != NULL);
   assert(SCIPhasCurrentNodeLP(scip));

   *result = SCIP_DELAYED;

   /* only call heuristic, if an optimal LP solution is at hand */
   if( SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
      return SCIP_OKAY;

   *result = SCIP_DIDNOTRUN;

   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, NULL, NULL, NULL) );

   /* OCTANE is for use in 0-1 programs only */
   if( nvars != nbinvars )
      return SCIP_OKAY;

   /* get heuristic's data */
   heurdata = SCIPheurGetData(heur);
   assert( heurdata != NULL );

   /* don't call heuristic, if it was not successful enough in the past */
   /*lint --e{647}*/
   if( SCIPgetNNodes(scip) % (SCIPheurGetNCalls(heur) / (100 * SCIPheurGetNBestSolsFound(heur) + 10*heurdata->nsuccess + 1) + 1) != 0 )
      return SCIP_OKAY;

   SCIP_CALL( SCIPgetLPBranchCands(scip, &fracvars, NULL, NULL, &nfracvars, NULL) );

   /* don't use integral starting points */
   if( nfracvars == 0 )
      return SCIP_OKAY;

   /* get working pointers from heurdata */
   sol = heurdata->sol;
   assert( sol != NULL );
   f_max = heurdata->f_max;
   f_first = heurdata->f_first;
   usefracspace = heurdata->usefracspace;

   SCIP_CALL( SCIPallocBufferArray(scip, &fracspace, nvars) );

   /* determine the space one which OCTANE should work either as the whole space or as the space of fractional variables */
   if( usefracspace )
   {
      nsubspacevars = nfracvars;
      SCIP_CALL( SCIPallocBufferArray(scip, &subspacevars, nsubspacevars) );
      BMScopyMemoryArray(subspacevars, fracvars, nsubspacevars);
      for( i = nvars - 1; i >= 0; --i )
         fracspace[i] = -1;
      for( i = nsubspacevars - 1; i >= 0; --i )
         fracspace[SCIPvarGetProbindex(subspacevars[i])] = i;
   }
   else
   {
      int currentindex;

      nsubspacevars = nvars;
      SCIP_CALL( SCIPallocBufferArray(scip, &subspacevars, nsubspacevars) );

      /* only copy the variables which are in the current LP */
      currentindex = 0;
      for( i = 0; i < nvars; ++i )
      {
         if( SCIPcolGetLPPos(SCIPvarGetCol(vars[i])) >= 0 )
         {
            subspacevars[currentindex] = vars[i];
            fracspace[i] = currentindex;
            ++currentindex;

         }
         else
         {
            fracspace[i] = -1;
            --nsubspacevars;
         }
      }
   }

   /* nothing to do for empty search space */
   if( nsubspacevars == 0 )
      return SCIP_OKAY;

   assert(0 < nsubspacevars && nsubspacevars <= nvars);

   for( i = 0; i < nsubspacevars; i++)
      assert(fracspace[SCIPvarGetProbindex(subspacevars[i])] == i);

   /* at most 2^(n-1) facets can be hit */
   if( nsubspacevars < 30 )
   {
      /*lint --e{701}*/
      assert(f_max > 0);
      f_max = MIN(f_max, 1 << (nsubspacevars - 1) );
   }

   f_first = MIN(f_first, f_max);

   /* memory allocation */
   SCIP_CALL( SCIPallocBufferArray(scip, &rayorigin, nsubspacevars) );
   SCIP_CALL( SCIPallocBufferArray(scip, &raydirection, nsubspacevars) );
   SCIP_CALL( SCIPallocBufferArray(scip, &negquotient, nsubspacevars) );
   SCIP_CALL( SCIPallocBufferArray(scip, &sign, nsubspacevars) );
   SCIP_CALL( SCIPallocBufferArray(scip, &perm, nsubspacevars) );
   SCIP_CALL( SCIPallocBufferArray(scip, &lambda, f_max + 1) );
   SCIP_CALL( SCIPallocBufferArray(scip, &facets, f_max + 1) );
   for( i = f_max; i >= 0; --i )
   {
      /*lint --e{866}*/
      SCIP_CALL( SCIPallocBufferArray(scip, &facets[i], nsubspacevars) );
   }
   SCIP_CALL( SCIPallocBufferArray(scip, &first_sols, f_first) );

   *result = SCIP_DIDNOTFIND;

   /* starting OCTANE */
   SCIPdebugMessage("run Octane heuristic on %s variables, which are %d vars, generate at most %d facets, using rule number %d\n",
      usefracspace ? "fractional" : "all", nsubspacevars, f_max, (heurdata->lastrule+1)%5);

   /* generate starting point in original coordinates */
   SCIP_CALL( generateStartingPoint(scip, rayorigin, subspacevars, nsubspacevars) );
   for( i = nsubspacevars - 1; i >= 0; --i )
      rayorigin[i] -= 0.5;

   firstrule = heurdata->lastrule;
   ++firstrule;
   for( r = firstrule; r <= firstrule + 10 && !SCIPisStopped(scip); r++ )
   {
      SCIP_ROW** rows;
      int nrows;

      /* generate shooting ray in original coordinates by certain rules */
      switch(r % 5)
      {
      case 1:
         if( heurdata->useavgnbray )
         {
            SCIP_CALL( generateAverageNBRay(scip, raydirection, fracspace, subspacevars, nsubspacevars) );
         }
         break;
      case 2:
         if( heurdata->useobjray )
         {
            SCIP_CALL( generateObjectiveRay(scip, raydirection, subspacevars, nsubspacevars) );
         }
         break;
      case 3:
         if( heurdata->usediffray )
         {
            SCIP_CALL( generateDifferenceRay(scip, raydirection, subspacevars, nsubspacevars) );
         }
         break;
      case 4:
         if( heurdata->useavgwgtray && SCIPisLPSolBasic(scip) )
         {
            SCIP_CALL( generateAverageRay(scip, raydirection, subspacevars, nsubspacevars, TRUE) );
         }
         break;
      case 0:
         if( heurdata->useavgray && SCIPisLPSolBasic(scip) )
         {
            SCIP_CALL( generateAverageRay(scip, raydirection, subspacevars, nsubspacevars, FALSE) );
         }
         break;
      default:
         SCIPerrorMessage("invalid ray rule identifier\n");
         SCIPABORT();
      }

      /* there must be a feasible direction for the shooting ray */
      if( isZero(scip, raydirection, nsubspacevars) )
         continue;

      /* transform coordinates such that raydirection >= 0 */
      flipCoords(rayorigin, raydirection, sign, nsubspacevars);

      for( i = f_max - 1; i >= 0; --i)
         lambda[i] = SCIPinfinity(scip);

      /* calculate negquotient, initialize perm, facets[0], p, and q */
      p = 0.5 * nsubspacevars;
      q = 0.0;
      for( i = nsubspacevars - 1; i >= 0; --i )
      {
         /* calculate negquotient, the ratio of rayorigin and raydirection, paying special attention to the case raydirection[i] == 0 */
         if( SCIPisFeasZero(scip, raydirection[i]) )
         {
            if( rayorigin[i] < 0 )
               negquotient[i] = SCIPinfinity(scip);
            else
               negquotient[i] = -SCIPinfinity(scip);
         }
         else
            negquotient[i] = - (rayorigin[i] / raydirection[i]);

         perm[i] = i;

         /* initialization of facets[0] to the all-one facet with p and q its characteristic values */
         facets[0][i] = TRUE;
         p -= rayorigin[i];
         q += raydirection[i];
      }

      assert(SCIPisPositive(scip, q));

      /* resort the coordinates in nonincreasing order of negquotient */
      SCIPsortDownRealRealRealBoolPtr( negquotient, raydirection, rayorigin, sign, (void**) subspacevars, nsubspacevars);

#ifndef NDEBUG
      for( i = 0; i < nsubspacevars; i++ )
         assert( raydirection[i] >= 0 );
      for( i = 1; i < nsubspacevars; i++ )
         assert( negquotient[i - 1] >= negquotient[i] );
#endif
      /* finished initialization */

      /* find the first facet of the octahedron hit by a ray shot from rayorigin into direction raydirection */
      for( i = 0; i < nsubspacevars && negquotient[i] * q > p; ++i )
      {
         facets[0][i] = FALSE;
         p += 2 * rayorigin[i];
         q -= 2 * raydirection[i];
         assert(SCIPisPositive(scip, p));
         assert(SCIPisPositive(scip, q));
      }

      /* avoid dividing by values close to 0.0 */
      if( !SCIPisFeasPositive(scip, q) )
         continue;

      /* assert necessary for flexelint */
      assert(q > 0);
      lambda[0] = p / q;

      nfacets = 1;

      /* find the first facets hit by the ray */
      for( i = 0; i < nfacets && i < f_first; ++i)
         generateNeighborFacets(scip, facets, lambda, rayorigin, raydirection, negquotient, nsubspacevars, f_max, i, &nfacets);

      /* construct the first ffirst possible solutions */
      for( i = 0; i < nfacets && i < f_first; ++i )
      {
         SCIP_CALL( SCIPcreateSol(scip, &first_sols[i], heur) );
         SCIP_CALL( getSolFromFacet(scip, facets[i], first_sols[i], sign, subspacevars, nsubspacevars) );
         assert( first_sols[i] != NULL );
      }

      /* try, whether there is a row violated by all of the first ffirst solutions */
      cons_viol = FALSE;
      SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
      for( i = nrows - 1; i >= 0; --i )
      {
         if( !SCIProwIsLocal(rows[i]) )
         {
            SCIP_COL** cols;
            SCIP_Real constant;
            SCIP_Real lhs;
            SCIP_Real rhs;
            SCIP_Real rowval;
            SCIP_Real* coeffs;
            int nnonzerovars;
            int k;

            /* get the row's data */
            constant = SCIProwGetConstant(rows[i]);
            lhs = SCIProwGetLhs(rows[i]);
            rhs = SCIProwGetRhs(rows[i]);
            coeffs = SCIProwGetVals(rows[i]);
            nnonzerovars = SCIProwGetNNonz(rows[i]);
            cols = SCIProwGetCols(rows[i]);
            rowval = constant;

            for( j = nnonzerovars - 1; j >= 0; --j )
               rowval += coeffs[j] * SCIPgetSolVal(scip, first_sols[0], SCIPcolGetVar(cols[j]));

            /* if the row's lhs is violated by the first sol, test, whether it is violated by the next ones, too */
            if( lhs > rowval )
            {
               cons_viol = TRUE;
               for( k = MIN(f_first, nfacets) - 1; k > 0; --k )
               {
                  rowval = constant;
                  for( j = nnonzerovars - 1; j >= 0; --j )
                     rowval += coeffs[j] * SCIPgetSolVal(scip, first_sols[k], SCIPcolGetVar(cols[j]));
                  if( lhs <= rowval )
                  {
                     cons_viol = FALSE;
                     break;
                  }
               }
            }
            /* dito for the right hand side */
            else if( rhs < rowval )
            {
               cons_viol = TRUE;
               for( k = MIN(f_first, nfacets) - 1; k > 0; --k )
               {
                  rowval = constant;
                  for( j = nnonzerovars - 1; j >= 0; --j )
                     rowval += coeffs[j] * SCIPgetSolVal(scip, first_sols[k], SCIPcolGetVar(cols[j]));
                  if( rhs >= rowval )
                  {
                     cons_viol = FALSE;
                     break;
                  }
               }
            }
            /* break as soon as one row is violated by all of the ffirst solutions */
            if( cons_viol )
               break;
         }
      }


      if( !cons_viol )
      {
         /* if there was no row violated by all solutions, try whether one or more of them are feasible */
         for( i = MIN(f_first, nfacets) - 1; i >= 0; --i )
         {
            assert(first_sols[i] != NULL);
            SCIP_CALL( SCIPtrySol(scip, first_sols[i], FALSE, TRUE, FALSE, TRUE, &success) );
            if( success )
               *result = SCIP_FOUNDSOL;
         }
         /* search for further facets and construct and try solutions out of facets fixed as closest ones */
         for( i = f_first; i < f_max; ++i)
         {
            if( i >= nfacets )
               break;
            generateNeighborFacets(scip, facets, lambda, rayorigin, raydirection, negquotient, nsubspacevars, f_max, i, &nfacets);
            SCIP_CALL( getSolFromFacet(scip, facets[i], sol, sign, subspacevars, nsubspacevars) );
            SCIP_CALL( SCIPtrySol(scip, sol, FALSE, TRUE, FALSE, TRUE, &success) );
            if( success )
               *result = SCIP_FOUNDSOL;
         }
      }

      /* finished OCTANE */
      for( i = MIN(f_first, nfacets) - 1; i >= 0; --i )
      {
         SCIP_CALL( SCIPfreeSol(scip, &first_sols[i]) );
      }
   }
   heurdata->lastrule = r;

   if( *result == SCIP_FOUNDSOL )
      ++(heurdata->nsuccess);

   /* free temporary memory */
   SCIPfreeBufferArray(scip, &first_sols);
   for( i = f_max; i >= 0; --i )
      SCIPfreeBufferArray(scip, &facets[i]);
   SCIPfreeBufferArray(scip, &facets);
   SCIPfreeBufferArray(scip, &lambda);
   SCIPfreeBufferArray(scip, &perm);
   SCIPfreeBufferArray(scip, &sign);
   SCIPfreeBufferArray(scip, &negquotient);
   SCIPfreeBufferArray(scip, &raydirection);
   SCIPfreeBufferArray(scip, &rayorigin);
   SCIPfreeBufferArray(scip, &subspacevars);
   SCIPfreeBufferArray(scip, &fracspace);

   return SCIP_OKAY;
}
コード例 #12
0
/** generates all facets, from which facet i could be obtained by a decreasing + to - flip
 *  or a nonincreasing - to + flip and tests whether they are among the fmax nearest ones
 */
static
void generateNeighborFacets(
   SCIP*                 scip,               /**< SCIP data structure                   */
   SCIP_Bool**           facets,             /**< facets got so far                     */
   SCIP_Real*            lambda,             /**< distances of the facets               */
   SCIP_Real*            rayorigin,          /**< origin of the shooting ray            */
   SCIP_Real*            raydirection,       /**< direction of the shooting ray         */
   SCIP_Real*            negquotient,        /**< array by which coordinates are sorted */
   int                   nsubspacevars,      /**< dimension of fractional space         */
   int                   f_max,              /**< maximal number of facets to create    */
   int                   i,                  /**< current facet                         */
   int*                  nfacets             /**< number of facets                      */
   )
{
   SCIP_Real p;
   SCIP_Real q;
   SCIP_Real lam;
   int minplus;
   int j;

   assert(scip != NULL);
   assert(facets != NULL);
   assert(facets[i] != NULL);
   assert(lambda != NULL);
   assert(rayorigin != NULL);
   assert(raydirection != NULL);
   assert(negquotient != NULL);
   assert(nfacets != NULL);
   assert(0 <= i && i < f_max);

   /* determine the p and q values of the next facet to fix as a closest one */
   p = 0.5 * nsubspacevars;
   q = 0.0;
   for( j = nsubspacevars - 1; j >= 0; --j )
   {
      if( facets[i][j] )
      {
         p -= rayorigin[j];
         q += raydirection[j];
      }
      else
      {
         p += rayorigin[j];
         q -= raydirection[j];
      }
   }

   /* get the first + entry of the facet */
   minplus = -1;
   for( j = 0; j < nsubspacevars; ++j )
   {
      if( facets[i][j] )
      {
         minplus = j;
         break;
      }
   }

   /* facet (- - ... -) cannot be hit, because raydirection >= 0 */
   assert(minplus >= 0);
   assert(q != 0.0);
   assert(SCIPisFeasEQ(scip, lambda[i], p/q));
   assert(lambda[i] >= 0.0);

   /* reverse search for facets from which the actual facet can be got by a single, decreasing + to - flip */
   /* a facet will be inserted into the queue, iff it is one of the fmax closest ones already found */
   for( j = 0; j < nsubspacevars && !facets[i][j] && SCIPisFeasGT(scip, negquotient[j], lambda[i]); ++j )
   {
      if( SCIPisFeasPositive(scip, q + 2*raydirection[j]) )
      {
         lam = (p - 2*rayorigin[j]) / (q + 2*raydirection[j]);
         tryToInsert(scip, facets, lambda, i, j, f_max, nsubspacevars, lam, nfacets);
      }
   }
   
   /* reverse search for facets from which the actual facet can be got by a single, nonincreasing - to + flip */
   /* a facet will be inserted into the queue, iff it is one of the fmax closest ones already found */
   for( j = nsubspacevars - 1; j >= 0 && facets[i][j] && SCIPisFeasLE(scip, negquotient[j], lambda[i]); --j )
   {
      if( SCIPisFeasPositive(scip, q - 2*raydirection[j]) )
      {
         lam = (p + 2*rayorigin[j]) / (q - 2*raydirection[j]);
         if( negquotient[minplus] <= lam )
            tryToInsert(scip, facets, lambda, i, j, f_max, nsubspacevars, lam, nfacets);
      }
   }
#ifndef NDEBUG
   for( j = 1; j < f_max; j++)
      assert(SCIPisFeasGE(scip, lambda[j], lambda[j-1]));
#endif
}
コード例 #13
0
/** generates the direction of the shooting ray as the average of the normalized non-basic vars and rows */
static
SCIP_RETCODE generateAverageNBRay(
   SCIP*                 scip,               /**< SCIP data structure                   */
   SCIP_Real*            raydirection,       /**< shooting ray                          */
   int*                  fracspace,          /**< index set of fractional variables     */
   SCIP_VAR**            subspacevars,       /**< pointer to fractional space variables */
   int                   nsubspacevars       /**< dimension of fractional space         */
   )
{
   SCIP_ROW** rows;
   SCIP_COL** cols;
   int nrows;
   int ncols;
   int i;

   assert(scip != NULL);
   assert(raydirection != NULL);
   assert(fracspace != NULL);
   assert(subspacevars != NULL);

   SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
   SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );

   /* add up non-basic variables */
   for( i = nsubspacevars - 1; i >= 0; --i )
   {
      SCIP_Real solval;

      solval = SCIPvarGetLPSol(subspacevars[i]);

      if( SCIPisFeasEQ(scip, solval, SCIPvarGetLbLocal(subspacevars[i])) )
         raydirection[i] = +1.0;
      else if( SCIPisFeasEQ(scip, solval, SCIPvarGetUbLocal(subspacevars[i])) )
         raydirection[i] = -1.0;
      else
         raydirection[i] = 0.0;
   }

   /* add up non-basic rows */
   for( i = nrows - 1; i >= 0; --i )
   {
      SCIP_Real dualsol;
      SCIP_Real factor;
      SCIP_Real* coeffs;
      SCIP_Real rownorm;
      int j;
      int nnonz;

      dualsol = SCIProwGetDualsol(rows[i]);
      if( SCIPisFeasPositive(scip, dualsol) )
         factor = 1.0;
      else if( SCIPisFeasNegative(scip, dualsol) )
         factor = -1.0;
      else
         continue;

      /* get the row's data */
      coeffs = SCIProwGetVals(rows[i]);
      cols = SCIProwGetCols(rows[i]);

      nnonz = SCIProwGetNNonz(rows[i]);

      rownorm = 0.0;
      for( j = nnonz - 1; j >= 0; --j )
      {
         SCIP_VAR* var;
         var = SCIPcolGetVar(cols[j]);
         if( fracspace[SCIPvarGetProbindex(var)] >= 0 )
            rownorm += coeffs[j] * coeffs[j];
      }

      if( SCIPisFeasZero(scip,rownorm) )
         continue;
      else
      {
         assert(rownorm > 0);
         rownorm = SQRT(rownorm);
      }

      for( j = nnonz - 1; j >= 0; --j )
      {
         SCIP_VAR* var;
         int f;

         var = SCIPcolGetVar(cols[j]);
         f = fracspace[SCIPvarGetProbindex(var)];

         if( f >= 0 )
         {
            raydirection[f] += factor * coeffs[j] / rownorm;
            assert(SCIP_REAL_MIN <= raydirection[f] && raydirection[f]  <= SCIP_REAL_MAX);
         }
      }
   }
   return SCIP_OKAY;
}