/** creates the rows of the subproblem */
static
SCIP_RETCODE createRows(
   SCIP*                 scip,               /**< original SCIP data structure */
   SCIP*                 subscip,            /**< SCIP data structure for the subproblem */
   SCIP_VAR**            subvars             /**< the variables of the subproblem */
   )
{
   SCIP_ROW** rows;                          /* original scip rows                       */
   SCIP_CONS* cons;                          /* new constraint                           */
   SCIP_VAR** consvars;                      /* new constraint's variables               */
   SCIP_COL** cols;                          /* original row's columns                   */

   SCIP_Real constant;                       /* constant added to the row                */
   SCIP_Real lhs;                            /* left hand side of the row                */
   SCIP_Real rhs;                            /* left right side of the row               */
   SCIP_Real* vals;                          /* variables' coefficient values of the row */

   int nrows;
   int nnonz;
   int i;
   int j;

   /* get the rows and their number */
   SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );

   /* copy all rows to linear constraints */
   for( i = 0; i < nrows; i++ )
   {
      /* ignore rows that are only locally valid */
      if( SCIProwIsLocal(rows[i]) )
         continue;

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

      assert(lhs <= rhs);

      /* allocate memory array to be filled with the corresponding subproblem variables */
      SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nnonz) );
      for( j = 0; j < nnonz; j++ )
         consvars[j] = subvars[SCIPvarGetProbindex(SCIPcolGetVar(cols[j]))];

      /* create a new linear constraint and add it to the subproblem */
      SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, SCIProwGetName(rows[i]), nnonz, consvars, vals, lhs, rhs,
            TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE) );
      SCIP_CALL( SCIPaddCons(subscip, cons) );
      SCIP_CALL( SCIPreleaseCons(subscip, &cons) );

      /* free temporary memory */
      SCIPfreeBufferArray(scip, &consvars);
   }

   return SCIP_OKAY;
}
예제 #2
0
파일: heur_mutation.c 프로젝트: hhexiy/scip
/** creates a subproblem for subscip by fixing a number of variables */
static
SCIP_RETCODE createSubproblem(
   SCIP*                 scip,               /**< original SCIP data structure                                  */
   SCIP*                 subscip,            /**< SCIP data structure for the subproblem                        */
   SCIP_VAR**            subvars,            /**< the variables of the subproblem                               */
   SCIP_Real             minfixingrate,      /**< percentage of integer variables that have to be fixed         */
   unsigned int*         randseed,           /**< a seed value for the random number generator                  */
   SCIP_Bool             uselprows           /**< should subproblem be created out of the rows in the LP rows?   */
   )
{
   SCIP_VAR** vars;                          /* original scip variables                    */
   SCIP_SOL* sol;                            /* pool of solutions                          */
   SCIP_Bool* marked;                        /* array of markers, which variables to fixed */
   SCIP_Bool fixingmarker;                   /* which flag should label a fixed variable?  */

   int nvars;
   int nbinvars;
   int nintvars;
   int i;
   int j;
   int nmarkers;

   /* get required data of the original problem */
   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
   sol = SCIPgetBestSol(scip);
   assert(sol != NULL);


   SCIP_CALL( SCIPallocBufferArray(scip, &marked, nbinvars+nintvars) );

   if( minfixingrate > 0.5 )
   {
      nmarkers = nbinvars + nintvars - (int) SCIPfloor(scip, minfixingrate*(nbinvars+nintvars));
      fixingmarker = FALSE;
   }
   else
   {
      nmarkers = (int) SCIPceil(scip, minfixingrate*(nbinvars+nintvars));
      fixingmarker = TRUE;
   }
   assert( 0 <= nmarkers && nmarkers <=  SCIPceil(scip,(nbinvars+nintvars)/2.0 ) );

   j = 0;
   BMSclearMemoryArray(marked, nbinvars+nintvars);
   while( j < nmarkers )
   {
      do
      {
         i = SCIPgetRandomInt(0, nbinvars+nintvars-1, randseed);
      }
      while( marked[i] );
      marked[i] = TRUE;
      j++;
   }
   assert( j == nmarkers );

   /* change bounds of variables of the subproblem */
   for( i = 0; i < nbinvars + nintvars; i++ )
   {
      /* fix all randomly marked variables */
      if( marked[i] == fixingmarker )
      {
         SCIP_Real solval;
         SCIP_Real lb;
         SCIP_Real ub;

         solval = SCIPgetSolVal(scip, sol, vars[i]);
         lb = SCIPvarGetLbGlobal(subvars[i]);
         ub = SCIPvarGetUbGlobal(subvars[i]);
         assert(SCIPisLE(scip, lb, ub));
         
         /* due to dual reductions, it may happen that the solution value is not in
            the variable's domain anymore */
         if( SCIPisLT(scip, solval, lb) )
            solval = lb;
         else if( SCIPisGT(scip, solval, ub) )
            solval = ub;
         
         /* perform the bound change */
         if( !SCIPisInfinity(scip, solval) && !SCIPisInfinity(scip, -solval) )
         {
            SCIP_CALL( SCIPchgVarLbGlobal(subscip, subvars[i], solval) );
            SCIP_CALL( SCIPchgVarUbGlobal(subscip, subvars[i], solval) );
         }
      }
   }

   if( uselprows )
   {
      SCIP_ROW** rows;   /* original scip rows */
      int nrows;

      /* get the rows and their number */
      SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );

      /* copy all rows to linear constraints */
      for( i = 0; i < nrows; i++ )
      {
         SCIP_CONS* cons;
         SCIP_VAR** consvars;
         SCIP_COL** cols;
         SCIP_Real constant;
         SCIP_Real lhs;
         SCIP_Real rhs;
         SCIP_Real* vals;
         int nnonz;

         /* ignore rows that are only locally valid */
         if( SCIProwIsLocal(rows[i]) )
            continue;

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

         assert( lhs <= rhs );

         /* allocate memory array to be filled with the corresponding subproblem variables */
         SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nnonz) );
         for( j = 0; j < nnonz; j++ )
            consvars[j] = subvars[SCIPvarGetProbindex(SCIPcolGetVar(cols[j]))];

         /* create a new linear constraint and add it to the subproblem */
         SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, SCIProwGetName(rows[i]), nnonz, consvars, vals, lhs, rhs,
               TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE) );
         SCIP_CALL( SCIPaddCons(subscip, cons) );
         SCIP_CALL( SCIPreleaseCons(subscip, &cons) );

         /* free temporary memory */
         SCIPfreeBufferArray(scip, &consvars);
      }
   }

   SCIPfreeBufferArray(scip, &marked);
   return SCIP_OKAY;
}
예제 #3
0
/** applies a cut that is a bound change directly as bound change instead of adding it as row to the LP */
static
SCIP_RETCODE sepastoreApplyBdchg(
   SCIP_SEPASTORE*       sepastore,          /**< separation storage */
   BMS_BLKMEM*           blkmem,             /**< block memory */
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_STAT*            stat,               /**< problem statistics */
   SCIP_TREE*            tree,               /**< branch and bound tree */
   SCIP_LP*              lp,                 /**< LP data */
   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
   SCIP_ROW*             cut,                /**< cut with a single variable */
   SCIP_Bool*            cutoff              /**< pointer to store whether an empty domain was created */
   )
{
   SCIP_COL** cols;
   SCIP_Real* vals;
   SCIP_VAR* var;
   SCIP_Real lhs;
   SCIP_Real rhs;

   assert(sepastore != NULL);
   assert(!SCIProwIsModifiable(cut));
   assert(SCIProwGetNNonz(cut) == 1);
   assert(cutoff != NULL);

   *cutoff = FALSE;

   /* get the single variable and its coefficient of the cut */
   cols = SCIProwGetCols(cut);
   assert(cols != NULL);
   var = SCIPcolGetVar(cols[0]);
   vals = SCIProwGetVals(cut);
   assert(vals != NULL);
   assert(!SCIPsetIsZero(set, vals[0]));

   /* if the coefficient is nearly zero, we better ignore this cut for numerical reasons */
   if( SCIPsetIsFeasZero(set, vals[0]) )
      return SCIP_OKAY;

   /* get the left hand side of the cut and convert it to a bound */
   lhs = SCIProwGetLhs(cut);
   if( !SCIPsetIsInfinity(set, -lhs) )
   {
      lhs -= SCIProwGetConstant(cut);
      if( vals[0] > 0.0 )
      {
         /* coefficient is positive -> lhs corresponds to lower bound */
         SCIP_CALL( sepastoreApplyLb(sepastore, blkmem, set, stat, tree, lp, branchcand, eventqueue,
               var, lhs/vals[0], cutoff) );
      }
      else
      {
         /* coefficient is negative -> lhs corresponds to upper bound */
         SCIP_CALL( sepastoreApplyUb(sepastore, blkmem, set, stat, tree, lp, branchcand, eventqueue,
               var, lhs/vals[0], cutoff) );
      }
   }

   /* get the right hand side of the cut and convert it to a bound */
   rhs = SCIProwGetRhs(cut);
   if( !SCIPsetIsInfinity(set, rhs) )
   {
      rhs -= SCIProwGetConstant(cut);
      if( vals[0] > 0.0 )
      {
         /* coefficient is positive -> rhs corresponds to upper bound */
         SCIP_CALL( sepastoreApplyUb(sepastore, blkmem, set, stat, tree, lp, branchcand, eventqueue,
               var, rhs/vals[0], cutoff) );
      }
      else
      {
         /* coefficient is negative -> rhs corresponds to lower bound */
         SCIP_CALL( sepastoreApplyLb(sepastore, blkmem, set, stat, tree, lp, branchcand, eventqueue,
               var, rhs/vals[0], cutoff) );
      }
   }

   /* count the bound change as applied cut */
   if( !sepastore->initiallp )
      sepastore->ncutsapplied++;

   return SCIP_OKAY;
}
예제 #4
0
/** creates a subproblem for subscip by fixing a number of variables */
static
SCIP_RETCODE createSubproblem(
   SCIP*                 scip,               /**< original SCIP data structure                                   */
   SCIP*                 subscip,            /**< SCIP data structure for the subproblem                         */
   SCIP_VAR**            subvars,            /**< the variables of the subproblem                                */
   SCIP_Real             minfixingrate,      /**< percentage of integer variables that have to be fixed          */
   SCIP_Bool             binarybounds,       /**< should general integers get binary bounds [floor(.),ceil(.)] ? */
   SCIP_Bool             uselprows,          /**< should subproblem be created out of the rows in the LP rows?   */
   SCIP_Bool*            success             /**< pointer to store whether the problem was created successfully  */
   )
{
   SCIP_VAR** vars;                          /* original SCIP variables */

   SCIP_Real fixingrate;

   int nvars;
   int nbinvars;
   int nintvars;
   int i;
   int fixingcounter;

   assert(scip != NULL);
   assert(subscip != NULL);
   assert(subvars != NULL);

   assert(0.0 <= minfixingrate && minfixingrate <= 1.0);

   /* get required variable data */
   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );

   fixingcounter = 0;

   /* change bounds of variables of the subproblem */
   for( i = 0; i < nbinvars + nintvars; i++ )
   {
      SCIP_Real lpsolval;
      SCIP_Real lb;
      SCIP_Real ub;

      /* get the current LP solution for each variable */
      lpsolval = SCIPgetRelaxSolVal(scip, vars[i]);

      if( SCIPisFeasIntegral(scip, lpsolval) )
      {
         /* fix variables to current LP solution if it is integral,
          * use exact integral value, if the variable is only integral within numerical tolerances
          */
         lb = SCIPfloor(scip, lpsolval+0.5);
         ub = lb;
         fixingcounter++;
      }
      else if( binarybounds )
      {
         /* if the sub problem should be a binary problem, change the bounds to nearest integers */
         lb = SCIPfeasFloor(scip,lpsolval);
         ub = SCIPfeasCeil(scip,lpsolval);
      }
      else
      {
         /* otherwise just copy bounds */
         lb =  SCIPvarGetLbGlobal(vars[i]);
         ub =  SCIPvarGetUbGlobal(vars[i]);
      }

      /* perform the bound change */
      SCIP_CALL( SCIPchgVarLbGlobal(subscip, subvars[i], lb) );
      SCIP_CALL( SCIPchgVarUbGlobal(subscip, subvars[i], ub) );
   }

   /* abort, if all integer variables were fixed (which should not happen for MIP) */
   if( fixingcounter == nbinvars + nintvars )
   {
      *success = FALSE;
      return SCIP_OKAY;
   }
   else
      fixingrate = fixingcounter / (SCIP_Real)(MAX(nbinvars + nintvars, 1));
   SCIPdebugMessage("fixing rate: %g = %d of %d\n", fixingrate, fixingcounter, nbinvars + nintvars);

   /* abort, if the amount of fixed variables is insufficient */
   if( fixingrate < minfixingrate )
   {
      *success = FALSE;
      return SCIP_OKAY;
   }

   if( uselprows )
   {
      SCIP_ROW** rows;                          /* original scip rows                         */
      int nrows;

      /* get the rows and their number */
      SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );

      /* copy all rows to linear constraints */
      for( i = 0; i < nrows; i++ )
      {
         SCIP_CONS* cons;
         SCIP_VAR** consvars;
         SCIP_COL** cols;
         SCIP_Real constant;
         SCIP_Real lhs;
         SCIP_Real rhs;
         SCIP_Real* vals;
         int nnonz;
         int j;

         /* ignore rows that are only locally valid */
         if( SCIProwIsLocal(rows[i]) )
            continue;

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

         assert( lhs <= rhs );

         /* allocate memory array to be filled with the corresponding subproblem variables */
         SCIP_CALL( SCIPallocBufferArray(subscip, &consvars, nnonz) );
         for( j = 0; j < nnonz; j++ )
            consvars[j] = subvars[SCIPvarGetProbindex(SCIPcolGetVar(cols[j]))];

         /* create a new linear constraint and add it to the subproblem */
         SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, SCIProwGetName(rows[i]), nnonz, consvars, vals, lhs, rhs,
               TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE) );
         SCIP_CALL( SCIPaddCons(subscip, cons) );
         SCIP_CALL( SCIPreleaseCons(subscip, &cons) );

         /* free temporary memory */
         SCIPfreeBufferArray(subscip, &consvars);
      }
   }

   *success = TRUE;
   return SCIP_OKAY;
}
/** calculates the initial mean and variance of the row activity normal distribution.
 *
 *  The mean value \f$ \mu \f$ is given by \f$ \mu = \sum_i=1^n c_i * (lb_i +ub_i) / 2 \f$ where
 *  \f$n \f$ is the number of variables, and \f$ c_i, lb_i, ub_i \f$ are the variable coefficient and
 *  bounds, respectively. With the same notation, the variance \f$ \sigma^2 \f$ is given by
 *  \f$ \sigma^2 = \sum_i=1^n c_i^2 * \sigma^2_i \f$, with the variance being
 *  \f$ \sigma^2_i = ((ub_i - lb_i + 1)^2 - 1) / 12 \f$ for integer variables and
 *  \f$ \sigma^2_i = (ub_i - lb_i)^2 / 12 \f$ for continuous variables.
 */
static
void rowCalculateGauss(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_HEURDATA*        heurdata,           /**< the heuristic rule data */
   SCIP_ROW*             row,                /**< the row for which the gaussian normal distribution has to be calculated */
   SCIP_Real*            mu,                 /**< pointer to store the mean value of the gaussian normal distribution */
   SCIP_Real*            sigma2,             /**< pointer to store the variance value of the gaussian normal distribution */
   int*                  rowinfinitiesdown,  /**< pointer to store the number of variables with infinite bounds to DECREASE activity */
   int*                  rowinfinitiesup     /**< pointer to store the number of variables with infinite bounds to INCREASE activity */
   )
{
   SCIP_COL** rowcols;
   SCIP_Real* rowvals;
   int nrowvals;
   int c;

   assert(scip != NULL);
   assert(row != NULL);
   assert(mu != NULL);
   assert(sigma2 != NULL);
   assert(rowinfinitiesup != NULL);
   assert(rowinfinitiesdown != NULL);

   rowcols = SCIProwGetCols(row);
   rowvals = SCIProwGetVals(row);
   nrowvals = SCIProwGetNNonz(row);

   assert(nrowvals == 0 || rowcols != NULL);
   assert(nrowvals == 0 || rowvals != NULL);

   *mu = SCIProwGetConstant(row);
   *sigma2 = 0.0;
   *rowinfinitiesdown = 0;
   *rowinfinitiesup = 0;

   /* loop over nonzero row coefficients and sum up the variable contributions to mu and sigma2 */
   for( c = 0; c < nrowvals; ++c )
   {
      SCIP_VAR* colvar;
      SCIP_Real colval;
      SCIP_Real colvarlb;
      SCIP_Real colvarub;
      SCIP_Real squarecoeff;
      SCIP_Real varvariance;
      SCIP_Real varmean;
      int varindex;

      assert(rowcols[c] != NULL);
      colvar = SCIPcolGetVar(rowcols[c]);
      assert(colvar != NULL);

      colval = rowvals[c];
      colvarlb = SCIPvarGetLbLocal(colvar);
      colvarub = SCIPvarGetUbLocal(colvar);

      varmean = 0.0;
      varvariance = 0.0;
      varindex = SCIPvarGetProbindex(colvar);
      assert((heurdata->currentlbs[varindex] == SCIP_INVALID)
            == (heurdata->currentubs[varindex] == SCIP_INVALID)); /*lint !e777 doesn't like comparing floats for equality */

      /* variable bounds need to be watched from now on */
      if( heurdata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777 doesn't like comparing floats for equality */
         heurdataUpdateCurrentBounds(scip, heurdata, colvar);

      assert(!SCIPisInfinity(scip, colvarlb));
      assert(!SCIPisInfinity(scip, -colvarub));
      assert(SCIPisFeasLE(scip, colvarlb, colvarub));

      /* variables with infinite bounds are skipped for the calculation of the variance; they need to
       * be accounted for by the counters for infinite row activity decrease and increase and they
       * are used to shift the row activity mean in case they have one nonzero, but finite bound */
      if( SCIPisInfinity(scip, -colvarlb) || SCIPisInfinity(scip, colvarub) )
      {
         if( SCIPisInfinity(scip, colvarub) )
         {
         /* an infinite upper bound gives the row an infinite maximum activity or minimum activity, if the coefficient is
          * positive or negative, resp.
          */
            if( colval < 0.0 )
               ++(*rowinfinitiesdown);
            else
               ++(*rowinfinitiesup);
         }

         /* an infinite lower bound gives the row an infinite maximum activity or minimum activity, if the coefficient is
          * negative or positive, resp.
          */
         if( SCIPisInfinity(scip, -colvarlb) )
         {
            if( colval > 0.0 )
               ++(*rowinfinitiesdown);
            else
               ++(*rowinfinitiesup);
         }
      }
      SCIPvarCalcDistributionParameters(scip, colvarlb, colvarub, SCIPvarGetType(colvar), &varmean, &varvariance);

      /* actual values are updated; the contribution of the variable to mu is the arithmetic mean of its bounds */
      *mu += colval * varmean;

      /* the variance contribution of a variable is c^2 * (u - l)^2 / 12.0 for continuous and c^2 * ((u - l + 1)^2 - 1) / 12.0 for integer */
      squarecoeff = SQUARED(colval);
      *sigma2 += squarecoeff * varvariance;

      assert(!SCIPisFeasNegative(scip, *sigma2));
   }

   SCIPdebug( SCIPprintRow(scip, row, NULL) );
   SCIPdebugMessage("  Row %s has a mean value of %g at a sigma2 of %g \n", SCIProwGetName(row), *mu, *sigma2);
}
예제 #6
0
/** 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;
}
예제 #7
0
/** checks whether given row is valid for the debugging solution */
SCIP_RETCODE SCIPdebugCheckRow(
   SCIP_SET*             set,                /**< global SCIP settings */
   SCIP_ROW*             row                 /**< row to check for validity */
   )
{
   SCIP_COL** cols;
   SCIP_Real* vals;
   SCIP_Real lhs;
   SCIP_Real rhs;
   int nnonz;
   int i;
   SCIP_Real minactivity;
   SCIP_Real maxactivity;
   SCIP_Real solval;

   assert(set != NULL);
   assert(row != NULL);

   /* check if we are in the original problem and not in a sub MIP */
   if( !isSolutionInMip(set) )
      return SCIP_OKAY;

   /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */
   if( debugSolIsAchieved(set) )
      return SCIP_OKAY;

   /* if the row is only locally valid, check whether the debugging solution is contained in the local subproblem */
   if( SCIProwIsLocal(row) )
   {
      SCIP_Bool solcontained;

      SCIP_CALL( isSolutionInNode(SCIPblkmem(set->scip), set, SCIPgetCurrentNode(set->scip), &solcontained) );
      if( !solcontained )
         return SCIP_OKAY;
   }

   cols = SCIProwGetCols(row);
   vals = SCIProwGetVals(row);
   nnonz = SCIProwGetNNonz(row);
   lhs = SCIProwGetLhs(row);
   rhs = SCIProwGetRhs(row);

   /* calculate row's activity on debugging solution */
   minactivity = SCIProwGetConstant(row);
   maxactivity = minactivity;
   for( i = 0; i < nnonz; ++i )
   {
      SCIP_VAR* var;

      /* get solution value of variable in debugging solution */
      var = SCIPcolGetVar(cols[i]);
      SCIP_CALL( getSolutionValue(set, var, &solval) );

      if( solval != SCIP_UNKNOWN ) /*lint !e777*/
      {
         minactivity += vals[i] * solval;
         maxactivity += vals[i] * solval;
      }
      else if( vals[i] > 0.0 )
      {
         minactivity += vals[i] * SCIPvarGetLbGlobal(var);
         maxactivity += vals[i] * SCIPvarGetUbGlobal(var);
      }
      else if( vals[i] < 0.0 )
      {
         minactivity += vals[i] * SCIPvarGetUbGlobal(var);
         maxactivity += vals[i] * SCIPvarGetLbGlobal(var);
      }
   }
   SCIPdebugMessage("debugging solution on row <%s>: %g <= [%g,%g] <= %g\n",
      SCIProwGetName(row), lhs, minactivity, maxactivity, rhs);

   /* check row for violation */
   if( SCIPsetIsFeasLT(set, maxactivity, lhs) || SCIPsetIsFeasGT(set, minactivity, rhs) )
   {
      printf("***** debug: row <%s> violates debugging solution (lhs=%.15g, rhs=%.15g, activity=[%.15g,%.15g], local=%d)\n",
         SCIProwGetName(row), lhs, rhs, minactivity, maxactivity, SCIProwIsLocal(row));
      SCIProwPrint(row, NULL);

      /* output row with solution values */
      printf("\n\n");
      printf("***** debug: violated row <%s>:\n", SCIProwGetName(row));
      printf(" %.15g <= %.15g", lhs, SCIProwGetConstant(row));
      for( i = 0; i < nnonz; ++i )
      {
         /* get solution value of variable in debugging solution */
         SCIP_CALL( getSolutionValue(set, SCIPcolGetVar(cols[i]), &solval) );
         printf(" %+.15g<%s>[%.15g]", vals[i], SCIPvarGetName(SCIPcolGetVar(cols[i])), solval);
      }
      printf(" <= %.15g\n", rhs);

      SCIPABORT();
   }

   return SCIP_OKAY;
}
예제 #8
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;
}