Esempio n. 1
0
/* check whether coef is the r-th row of the inverse basis matrix B^-1; this is
 * the case if( coef * B ) is the r-th unit vector */
SCIP_RETCODE SCIPdebugCheckBInvRow(
   SCIP*                 scip,               /**< SCIP data structure */
   int                   r,                  /**< row number */
   SCIP_Real*            coef                /**< r-th row of the inverse basis matrix */
   )
{
   SCIP_Real vecval;
   SCIP_Real matrixval;
   int* basisind;
   int nrows;
   int idx;
   int i;
   int k;

   assert(scip != NULL);

   nrows = SCIPgetNLPRows(scip);

   /* get basic indices for the basic matrix B */
   SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );
   SCIP_CALL( SCIPgetLPBasisInd(scip, basisind) );


   /* loop over the columns of B */
   for( k = 0; k < nrows; ++k )
   {
      vecval = 0.0;

      /* indices of basic columns and rows:
       * - index i >= 0 corresponds to column i,
       * - index i < 0 to row -i-1
       */
      idx = basisind[k];

      /* check if we have a slack variable; this is the case if idx < 0 */
      if( idx >= 0 )
      {
         /* loop over the rows to compute the corresponding value in the unit vector */
         for( i = 0; i < nrows; ++i )
         {
            SCIP_CALL( SCIPlpiGetCoef(scip->lp->lpi, i, idx, &matrixval) );
            vecval += coef[i] * matrixval;
         }
      }
      else
      {
         assert( idx < 0 );

         /* retransform idx
          * - index i >= 0 corresponds to column i,
          * - index i < 0 to row -i-1
          */
         idx = -idx - 1;
         assert( idx >= 0 && idx < nrows );

         /* since idx < 0 we are in the case of a slack variable, i.e., the corresponding column
            is the idx-unit vector; note that some LP solver return a -idx-unit vector */
         /*   vecval = REALABS(coef[idx]);*/
         vecval = coef[idx];
      }

      /* check if vecval fits to the r-th unit vector */
      if( k == r && !SCIPisFeasEQ(scip, vecval, 1.0) )
      {
         /* we expected a 1.0 and found something different */
         SCIPwarningMessage("checked SCIPgetLPBInvRow() found value <%g> expected 1.0\n", vecval);
      }
      else if( k != r && !SCIPisFeasZero(scip, vecval) )
      {
         /* we expected a 0.0 and found something different */
         SCIPwarningMessage("checked SCIPgetLPBInvRow() found value <%g> expected 0.0\n", vecval);
      }
   }

   SCIPfreeBufferArray(scip, &basisind);

   return SCIP_OKAY;
}
Esempio n. 2
0
/** initializes the pricing problem for the given capacity */
static
SCIP_RETCODE initPricing(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_PRICERDATA*      pricerdata,         /**< pricer data */
   SCIP*                 subscip,            /**< pricing SCIP data structure */
   SCIP_VAR**            vars                /**< variable array for the items */
   )
{
   SCIP_CONS** conss;
   SCIP_Longint* vals;
   SCIP_CONS* cons;
   SCIP_VAR* var;
   SCIP_Longint* weights;
   SCIP_Longint capacity;
   SCIP_Real dual;

   int nitems;
   int nvars;
   int c;

   assert( SCIPgetStage(subscip) == SCIP_STAGE_PROBLEM );
   assert(pricerdata != NULL);

   nitems = pricerdata->nitems;
   conss = pricerdata->conss;
   weights = pricerdata->weights;
   capacity = pricerdata->capacity;
   nvars = 0;

   SCIP_CALL( SCIPallocBufferArray(subscip, &vals, nitems) );

   /* create for each order, which is not assigned yet, a variable with objective coefficient */
   for( c = 0; c < nitems; ++c )
   {
      cons = conss[c];

      /* check if each constraint is setppc constraint */
      assert( !strncmp( SCIPconshdlrGetName( SCIPconsGetHdlr(cons) ), "setppc", 6) );

      /* constraints which are (locally) disabled/redundant are not of
       * interest since the corresponding job is assigned to a packing
       */
      if( !SCIPconsIsEnabled(cons) )
         continue;

      if( SCIPgetNFixedonesSetppc(scip, cons) == 1 )
      {
         /* disable constraint locally */
         SCIP_CALL( SCIPdelConsLocal(scip, cons) );
         continue;
      }

      /* dual value in original SCIP */
      dual = SCIPgetDualsolSetppc(scip, cons);
      
      SCIP_CALL( SCIPcreateVarBasic(subscip, &var, SCIPconsGetName(cons), 0.0, 1.0, dual, SCIP_VARTYPE_BINARY) );
      SCIP_CALL( SCIPaddVar(subscip, var) );

      vals[nvars] = weights[c];
      vars[nvars] = var;
      nvars++;

      /* release variable */
      SCIP_CALL( SCIPreleaseVar(subscip, &var) );
   }

   /* create capacity constraint */
   SCIP_CALL( SCIPcreateConsBasicKnapsack(subscip, &cons, "capacity", nvars, vars, vals,
         capacity) );
   
   SCIP_CALL( SCIPaddCons(subscip, cons) );
   SCIP_CALL( SCIPreleaseCons(subscip, &cons) );

   /* add constraint of the branching decisions */
   SCIP_CALL( addBranchingDecisionConss(scip, subscip, vars, pricerdata->conshdlr) );

   /* avoid to generate columns which are fixed to zero */
   SCIP_CALL( addFixedVarsConss(scip, subscip, vars, conss, nitems) );

   SCIPfreeBufferArray(subscip, &vals);

   return SCIP_OKAY;
}
/** execution method of primal heuristic */
static
SCIP_DECL_HEUREXEC(heurExecObjpscostdiving) /*lint --e{715}*/
{  /*lint --e{715}*/
   SCIP_HEURDATA* heurdata;
   SCIP_LPSOLSTAT lpsolstat;
   SCIP_VAR* var;
   SCIP_VAR** lpcands;
   SCIP_Real* lpcandssol;
   SCIP_Real* lpcandsfrac;
   SCIP_Real primsol;
   SCIP_Real frac;
   SCIP_Real pscostquot;
   SCIP_Real bestpscostquot;
   SCIP_Real oldobj;
   SCIP_Real newobj;
   SCIP_Real objscale;
   SCIP_Bool bestcandmayrounddown;
   SCIP_Bool bestcandmayroundup;
   SCIP_Bool bestcandroundup;
   SCIP_Bool mayrounddown;
   SCIP_Bool mayroundup;
   SCIP_Bool roundup;
   SCIP_Bool lperror;
   SCIP_Longint ncalls;
   SCIP_Longint nsolsfound;
   SCIP_Longint nlpiterations;
   SCIP_Longint maxnlpiterations;
   int* roundings;
   int nvars;
   int varidx;
   int nlpcands;
   int startnlpcands;
   int depth;
   int maxdepth;
   int maxdivedepth;
   int divedepth;
   int bestcand;
   int c;

   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;

   /* only call heuristic, if the LP solution is basic (which allows fast resolve in diving) */
   if( !SCIPisLPSolBasic(scip) )
      return SCIP_OKAY;

   /* don't dive two times at the same node */
   if( SCIPgetLastDivenode(scip) == SCIPgetNNodes(scip) && SCIPgetDepth(scip) > 0 )
      return SCIP_OKAY;

   *result = SCIP_DIDNOTRUN;

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

   /* only apply heuristic, if only a few solutions have been found */
   if( heurdata->maxsols >= 0 && SCIPgetNSolsFound(scip) >= heurdata->maxsols )
      return SCIP_OKAY;

   /* only try to dive, if we are in the correct part of the tree, given by minreldepth and maxreldepth */
   depth = SCIPgetDepth(scip);
   maxdepth = SCIPgetMaxDepth(scip);
   maxdepth = MAX(maxdepth, 30);
   if( depth < heurdata->minreldepth*maxdepth || depth > heurdata->maxreldepth*maxdepth )
      return SCIP_OKAY;

   /* calculate the maximal number of LP iterations until heuristic is aborted */
   nlpiterations = SCIPgetNNodeLPIterations(scip);
   ncalls = SCIPheurGetNCalls(heur);
   nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + heurdata->nsuccess;
   maxnlpiterations = (SCIP_Longint)((1.0 + 10.0*(nsolsfound+1.0)/(ncalls+1.0)) * heurdata->maxlpiterquot * nlpiterations);
   maxnlpiterations += heurdata->maxlpiterofs;

   /* don't try to dive, if we took too many LP iterations during diving */
   if( heurdata->nlpiterations >= maxnlpiterations )
      return SCIP_OKAY;

   /* allow at least a certain number of LP iterations in this dive */
   maxnlpiterations = MAX(maxnlpiterations, heurdata->nlpiterations + MINLPITER);

   /* get fractional variables that should be integral */
   SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, &nlpcands, NULL) );

   /* don't try to dive, if there are no fractional variables */
   if( nlpcands == 0 )
      return SCIP_OKAY;

   /* calculate the maximal diving depth */
   nvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
   if( SCIPgetNSolsFound(scip) == 0 )
      maxdivedepth = (int)(heurdata->depthfacnosol * nvars);
   else
      maxdivedepth = (int)(heurdata->depthfac * nvars);
   maxdivedepth = MIN(maxdivedepth, 10*maxdepth);


   *result = SCIP_DIDNOTFIND;

   /* get temporary memory for remembering the current soft roundings */
   SCIP_CALL( SCIPallocBufferArray(scip, &roundings, nvars) );
   BMSclearMemoryArray(roundings, nvars);

   /* start diving */
   SCIP_CALL( SCIPstartDive(scip) );

   SCIPdebugMessage("(node %"SCIP_LONGINT_FORMAT") executing objpscostdiving heuristic: depth=%d, %d fractionals, dualbound=%g, maxnlpiterations=%"SCIP_LONGINT_FORMAT", maxdivedepth=%d\n",
      SCIPgetNNodes(scip), SCIPgetDepth(scip), nlpcands, SCIPgetDualbound(scip), maxnlpiterations, maxdivedepth);

   /* dive as long we are in the given diving depth and iteration limits and fractional variables exist, but
    * - if the last objective change was in a direction, that corresponds to a feasible rounding, we continue in any case
    * - if possible, we dive at least with the depth 10
    * - if the number of fractional variables decreased at least with 1 variable per 2 dive depths, we continue diving
    */
   lperror = FALSE;
   lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
   divedepth = 0;
   bestcandmayrounddown = FALSE;
   bestcandmayroundup = FALSE;
   startnlpcands = nlpcands;
   while( !lperror && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL && nlpcands > 0
      && (divedepth < 10
         || nlpcands <= startnlpcands - divedepth/2
         || (divedepth < maxdivedepth && nlpcands <= startnlpcands - divedepth/10
            && heurdata->nlpiterations < maxnlpiterations)) && !SCIPisStopped(scip) )
   {
      SCIP_RETCODE retcode;

      divedepth++;

      /* choose variable for objective change:
       * - prefer variables that may not be rounded without destroying LP feasibility:
       *   - of these variables, change objective value of variable with largest rel. difference of pseudo cost values
       * - if all remaining fractional variables may be rounded without destroying LP feasibility:
       *   - change objective value of variable with largest rel. difference of pseudo cost values
       */
      bestcand = -1;
      bestpscostquot = -1.0;
      bestcandmayrounddown = TRUE;
      bestcandmayroundup = TRUE;
      bestcandroundup = FALSE;
      for( c = 0; c < nlpcands; ++c )
      {
         var = lpcands[c];
         mayrounddown = SCIPvarMayRoundDown(var);
         mayroundup = SCIPvarMayRoundUp(var);
         primsol = lpcandssol[c];
         frac = lpcandsfrac[c];
         if( mayrounddown || mayroundup )
         {
            /* the candidate may be rounded: choose this candidate only, if the best candidate may also be rounded */
            if( bestcandmayrounddown || bestcandmayroundup )
            {
               /* choose rounding direction:
                * - if variable may be rounded in both directions, round corresponding to the pseudo cost values
                * - otherwise, round in the infeasible direction, because feasible direction is tried by rounding
                *   the current fractional solution
                */
               roundup = FALSE;
               if( mayrounddown && mayroundup )
                  calcPscostQuot(scip, var, primsol, frac, 0, &pscostquot, &roundup);
               else if( mayrounddown )
                  calcPscostQuot(scip, var, primsol, frac, +1, &pscostquot, &roundup);
               else
                  calcPscostQuot(scip, var, primsol, frac, -1, &pscostquot, &roundup);

               /* prefer variables, that have already been soft rounded but failed to get integral */
               varidx = SCIPvarGetProbindex(var);
               assert(0 <= varidx && varidx < nvars);
               if( roundings[varidx] != 0 )
                  pscostquot *= 1000.0;

               /* check, if candidate is new best candidate */
               if( pscostquot > bestpscostquot )
               {
                  bestcand = c;
                  bestpscostquot = pscostquot;
                  bestcandmayrounddown = mayrounddown;
                  bestcandmayroundup = mayroundup;
                  bestcandroundup = roundup;
               }
            }
         }
         else
         {
            /* the candidate may not be rounded: calculate pseudo cost quotient and preferred direction */
            calcPscostQuot(scip, var, primsol, frac, 0, &pscostquot, &roundup);

            /* prefer variables, that have already been soft rounded but failed to get integral */
            varidx = SCIPvarGetProbindex(var);
            assert(0 <= varidx && varidx < nvars);
            if( roundings[varidx] != 0 )
               pscostquot *= 1000.0;

            /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
            if( bestcandmayrounddown || bestcandmayroundup || pscostquot > bestpscostquot )
            {
               bestcand = c;
               bestpscostquot = pscostquot;
               bestcandmayrounddown = FALSE;
               bestcandmayroundup = FALSE;
               bestcandroundup = roundup;
            }
         }
      }
      assert(bestcand != -1);

      /* if all candidates are roundable, try to round the solution */
      if( bestcandmayrounddown || bestcandmayroundup )
      {
         SCIP_Bool success;

         /* create solution from diving LP and try to round it */
         SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
         SCIP_CALL( SCIProundSol(scip, heurdata->sol, &success) );

         if( success )
         {
            SCIPdebugMessage("objpscostdiving found roundable primal solution: obj=%g\n",
               SCIPgetSolOrigObj(scip, heurdata->sol));

            /* try to add solution to SCIP */
            SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, &success) );

            /* check, if solution was feasible and good enough */
            if( success )
            {
               SCIPdebugMessage(" -> solution was feasible and good enough\n");
               *result = SCIP_FOUNDSOL;
            }
         }
      }

      var = lpcands[bestcand];

      /* check, if the best candidate was already subject to soft rounding */
      varidx = SCIPvarGetProbindex(var);
      assert(0 <= varidx && varidx < nvars);
      if( roundings[varidx] == +1 )
      {
         /* variable was already soft rounded upwards: hard round it downwards */
         SCIP_CALL( SCIPchgVarUbDive(scip, var, SCIPfeasFloor(scip, lpcandssol[bestcand])) );
         SCIPdebugMessage("  dive %d/%d: var <%s>, round=%u/%u, sol=%g, was already soft rounded upwards -> bounds=[%g,%g]\n",
            divedepth, maxdivedepth, SCIPvarGetName(var), bestcandmayrounddown, bestcandmayroundup,
            lpcandssol[bestcand], SCIPgetVarLbDive(scip, var), SCIPgetVarUbDive(scip, var));
      }
      else if( roundings[varidx] == -1 )
      {
         /* variable was already soft rounded downwards: hard round it upwards */
         SCIP_CALL( SCIPchgVarLbDive(scip, var, SCIPfeasCeil(scip, lpcandssol[bestcand])) );
         SCIPdebugMessage("  dive %d/%d: var <%s>, round=%u/%u, sol=%g, was already soft rounded downwards -> bounds=[%g,%g]\n",
            divedepth, maxdivedepth, SCIPvarGetName(var), bestcandmayrounddown, bestcandmayroundup,
            lpcandssol[bestcand], SCIPgetVarLbDive(scip, var), SCIPgetVarUbDive(scip, var));
      }
      else
      {
         assert(roundings[varidx] == 0);

         /* apply soft rounding of best candidate via a change in the objective value */
         objscale = divedepth * 1000.0;
         oldobj = SCIPgetVarObjDive(scip, var);
         if( bestcandroundup )
         {
            /* soft round variable up: make objective value (more) negative */
            if( oldobj < 0.0 )
               newobj = objscale * oldobj;
            else
               newobj = -objscale * oldobj;
            newobj = MIN(newobj, -objscale);

            /* remember, that this variable was soft rounded upwards */
            roundings[varidx] = +1;
         }
         else
         {
            /* soft round variable down: make objective value (more) positive */
            if( oldobj > 0.0 )
               newobj = objscale * oldobj;
            else
               newobj = -objscale * oldobj;
            newobj = MAX(newobj, objscale);

            /* remember, that this variable was soft rounded downwards */
            roundings[varidx] = -1;
         }
         SCIP_CALL( SCIPchgVarObjDive(scip, var, newobj) );
         SCIPdebugMessage("  dive %d/%d, LP iter %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT": var <%s>, round=%u/%u, sol=%g, bounds=[%g,%g], obj=%g, newobj=%g\n",
            divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations,
            SCIPvarGetName(var), bestcandmayrounddown, bestcandmayroundup,
            lpcandssol[bestcand], SCIPgetVarLbDive(scip, var), SCIPgetVarUbDive(scip, var), oldobj, newobj);
      }

      /* resolve the diving LP */
      nlpiterations = SCIPgetNLPIterations(scip);
      retcode =  SCIPsolveDiveLP(scip, MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror);
      lpsolstat = SCIPgetLPSolstat(scip);

      /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
       * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
       */
      if( retcode != SCIP_OKAY )
      {
#ifndef NDEBUG
         if( lpsolstat != SCIP_LPSOLSTAT_UNBOUNDEDRAY )
         {
            SCIP_CALL( retcode );
         }
#endif
         SCIPwarningMessage("Error while solving LP in Objpscostdiving heuristic; LP solve terminated with code <%d>\n", retcode);
         SCIPwarningMessage("This does not affect the remaining solution procedure --> continue\n");
      }

      if( lperror )
         break;

      /* update iteration count */
      heurdata->nlpiterations += SCIPgetNLPIterations(scip) - nlpiterations;

      /* get LP solution status  and fractional variables, that should be integral */
      if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
      {
         /* get new fractional variables */
         SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, &nlpcands, NULL) );
      }
      SCIPdebugMessage("   -> lpsolstat=%d, nfrac=%d\n", lpsolstat, nlpcands);
   }

   /* check if a solution has been found */
   if( nlpcands == 0 && !lperror && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
   {
      SCIP_Bool success;

      /* create solution from diving LP */
      SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
      SCIPdebugMessage("objpscostdiving found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));

      /* try to add solution to SCIP */
      SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, &success) );

      /* check, if solution was feasible and good enough */
      if( success )
      {
         SCIPdebugMessage(" -> solution was feasible and good enough\n");
         *result = SCIP_FOUNDSOL;
      }
   }

   /* end diving */
   SCIP_CALL( SCIPendDive(scip) );

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

   /* free temporary memory for remembering the current soft roundings */
   SCIPfreeBufferArray(scip, &roundings);

   SCIPdebugMessage("objpscostdiving heuristic finished\n");

   return SCIP_OKAY;
}
Esempio n. 4
0
/** execution method of presolver */
static
SCIP_DECL_PRESOLEXEC(presolExecDualagg)
{  /*lint --e{715}*/
   SCIP_MATRIX* matrix;
   SCIP_Bool initialized;
   SCIP_Bool complete;

   assert(result != NULL);
   *result = SCIP_DIDNOTRUN;

   if( (SCIPgetStage(scip) != SCIP_STAGE_PRESOLVING) || SCIPinProbing(scip) || SCIPisNLPEnabled(scip) )
      return SCIP_OKAY;

   if( SCIPisStopped(scip) || SCIPgetNActivePricers(scip) > 0 )
      return SCIP_OKAY;

   if( SCIPgetNBinVars(scip) == 0 )
      return SCIP_OKAY;

   if( !SCIPallowDualReds(scip) )
      return SCIP_OKAY;

   *result = SCIP_DIDNOTFIND;

   matrix = NULL;
   SCIP_CALL( SCIPmatrixCreate(scip, &matrix, &initialized, &complete) );

   /* we only work on pure MIPs currently */
   if( initialized && complete )
   {
      AGGRTYPE* aggtypes;
      SCIP_VAR** binvars;
      int nvaragg;
      int ncols;

      ncols = SCIPmatrixGetNColumns(matrix);
      nvaragg = 0;

      SCIP_CALL( SCIPallocBufferArray(scip, &aggtypes, ncols) );
      BMSclearMemoryArray(aggtypes, ncols);

      SCIP_CALL( SCIPallocBufferArray(scip, &binvars, ncols) );
      SCIPdebug( BMSclearMemoryArray(binvars, ncols) );

      /* search for aggregations */
      SCIP_CALL( findUplockAggregations(scip, matrix, &nvaragg, aggtypes, binvars) );
      SCIP_CALL( findDownlockAggregations(scip, matrix, &nvaragg, aggtypes, binvars) );

      /* apply aggregations, if we found any */
      if( nvaragg > 0 )
      {
         int v;

         for( v = 0; v < ncols; v++ )
         {
            if( aggtypes[v] != NOAGG )
            {
               SCIP_Bool infeasible;
               SCIP_Bool redundant;
               SCIP_Bool aggregated;
               SCIP_Real ub;
               SCIP_Real lb;

               ub = SCIPmatrixGetColUb(matrix, v);
               lb = SCIPmatrixGetColLb(matrix, v);

               /* aggregate variable */
               assert(binvars[v] != NULL);
               if( aggtypes[v] == BIN0UBOUND )
               {
                  SCIP_CALL( SCIPaggregateVars(scip, SCIPmatrixGetVar(matrix, v), binvars[v], 1.0, ub-lb,
                        ub, &infeasible, &redundant, &aggregated) );
               }
               else
               {
                  assert(aggtypes[v] == BIN0LBOUND);
                  SCIP_CALL( SCIPaggregateVars(scip, SCIPmatrixGetVar(matrix, v), binvars[v], 1.0, lb-ub,
                        lb, &infeasible, &redundant, &aggregated) );
               }

               /* infeasible aggregation */
               if( infeasible )
               {
                  SCIPdebugMessage(" -> infeasible aggregation\n");
                  *result = SCIP_CUTOFF;
                  return SCIP_OKAY;
               }

               if( aggregated )
                  (*naggrvars)++;
            }
         }

         /* set result pointer */
         if( (*naggrvars) > 0 )
            *result = SCIP_SUCCESS;
      }

      SCIPfreeBufferArray(scip, &binvars);
      SCIPfreeBufferArray(scip, &aggtypes);
   }

   SCIPmatrixFree(scip, &matrix);

   return SCIP_OKAY;
}
Esempio n. 5
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;
}
Esempio n. 6
0
/** create the extra constraint of local branching and add it to subscip */
static
SCIP_RETCODE addLocalBranchingConstraint(
   SCIP*                 scip,               /**< SCIP data structure of the original problem   */
   SCIP*                 subscip,            /**< SCIP data structure of the subproblem         */
   SCIP_VAR**            subvars,            /**< variables of the subproblem                   */
   SCIP_HEURDATA*        heurdata            /**< heuristic's data structure                    */
   )
{
   SCIP_CONS* cons;                        /* local branching constraint to create */
   SCIP_VAR** consvars;
   SCIP_VAR** vars;
   SCIP_SOL* bestsol;

   int nbinvars;
   int i;
   SCIP_Real lhs;
   SCIP_Real rhs;
   SCIP_Real* consvals;
   char consname[SCIP_MAXSTRLEN];

   (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_localbranchcons", SCIPgetProbName(scip));

   /* get the data of the variables and the best solution */
   SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, NULL, NULL, NULL) );
   bestsol = SCIPgetBestSol(scip);
   assert( bestsol != NULL );

   /* memory allocation */
   SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nbinvars) );
   SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nbinvars) );

   /* set initial left and right hand sides of local branching constraint */
   lhs = (SCIP_Real)heurdata->emptyneighborhoodsize + 1.0;
   rhs = (SCIP_Real)heurdata->curneighborhoodsize;

   /* create the distance (to incumbent) function of the binary variables */
   for( i = 0; i < nbinvars; i++ )
   {
      SCIP_Real solval;

      solval = SCIPgetSolVal(scip, bestsol, vars[i]);
      assert( SCIPisFeasIntegral(scip,solval) );

      /* is variable i  part of the binary support of bestsol? */
      if( SCIPisFeasEQ(scip,solval,1.0) )
      {
         consvals[i] = -1.0;
         rhs -= 1.0;
         lhs -= 1.0;
      }
      else
         consvals[i] = 1.0;
      consvars[i] = subvars[i];
      assert( SCIPvarGetType(consvars[i]) == SCIP_VARTYPE_BINARY );
   }

   /* creates localbranching constraint and adds it to subscip */
   SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, consname, nbinvars, consvars, consvals,
         lhs, rhs, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE) );
   SCIP_CALL( SCIPaddCons(subscip, cons) );
   SCIP_CALL( SCIPreleaseCons(subscip, &cons) );

   /* free local memory */
   SCIPfreeBufferArray(scip, &consvals);
   SCIPfreeBufferArray(scip, &consvars);

   return SCIP_OKAY;
}
/** LP solution separation method of separator */
static
SCIP_DECL_SEPAEXECLP(sepaExeclpGomory)
{  /*lint --e{715}*/
   SCIP_SEPADATA* sepadata;
   SCIP_VAR** vars;
   SCIP_COL** cols;
   SCIP_ROW** rows;
   SCIP_Real* binvrow;
   SCIP_Real* cutcoefs;
   SCIP_Real maxscale;
   SCIP_Real minfrac;
   SCIP_Real maxfrac;
   SCIP_Longint maxdnom;
   SCIP_Bool cutoff;
   int* basisind;
   int naddedcuts;
   int nvars;
   int ncols;
   int nrows;
   int ncalls;
   int depth;
   int maxdepth;
   int maxsepacuts;
   int c;
   int i;

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

   *result = SCIP_DIDNOTRUN;

   sepadata = SCIPsepaGetData(sepa);
   assert(sepadata != NULL);

   depth = SCIPgetDepth(scip);
   ncalls = SCIPsepaGetNCallsAtNode(sepa);

   minfrac = sepadata->away;
   maxfrac = 1.0 - sepadata->away;

   /* only call separator, if we are not close to terminating */
   if( SCIPisStopped(scip) )
      return SCIP_OKAY;

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

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

   /* only call separator, if the LP solution is basic */
   if( !SCIPisLPSolBasic(scip) )
      return SCIP_OKAY;

   /* only call separator, if there are fractional variables */
   if( SCIPgetNLPBranchCands(scip) == 0 )
      return SCIP_OKAY;

   /* get variables data */
   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );

   /* get LP data */
   SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
   SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
   if( ncols == 0 || nrows == 0 )
      return SCIP_OKAY;

#if 0 /* if too many columns, separator is usually very slow: delay it until no other cuts have been found */
   if( ncols >= 50*nrows )
      return SCIP_OKAY;

   if( ncols >= 5*nrows )
   {
      int ncutsfound;

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

   /* set the maximal denominator in rational representation of gomory cut and the maximal scale factor to
    * scale resulting cut to integral values to avoid numerical instabilities
    */
   /**@todo find better but still stable gomory cut settings: look at dcmulti, gesa3, khb0525, misc06, p2756 */
   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;
   }

   /* allocate temporary memory */
   SCIP_CALL( SCIPallocBufferArray(scip, &cutcoefs, nvars) );
   SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );
   SCIP_CALL( SCIPallocBufferArray(scip, &binvrow, nrows) );

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

   /* get the maximal number of cuts allowed in a separation round */
   if( depth == 0 )
      maxsepacuts = sepadata->maxsepacutsroot;
   else
      maxsepacuts = sepadata->maxsepacuts;

   SCIPdebugMessage("searching gomory cuts: %d cols, %d rows, maxdnom=%"SCIP_LONGINT_FORMAT", maxscale=%g, maxcuts=%d\n",
      ncols, nrows, maxdnom, maxscale, maxsepacuts);

   cutoff = FALSE;
   naddedcuts = 0;

   /* for all basic columns belonging to integer variables, try to generate a gomory cut */
   for( i = 0; i < nrows && naddedcuts < maxsepacuts && !SCIPisStopped(scip) && !cutoff; ++i )
   {
      SCIP_Bool tryrow;

      tryrow = FALSE;
      c = basisind[i];
      if( c >= 0 )
      {
         SCIP_VAR* var;

         assert(c < ncols);
         var = SCIPcolGetVar(cols[c]);
         if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS )
         {
            SCIP_Real primsol;

            primsol = SCIPcolGetPrimsol(cols[c]);
            assert(SCIPgetVarSol(scip, var) == primsol); /*lint !e777*/

            if( SCIPfeasFrac(scip, primsol) >= minfrac )
            {
               SCIPdebugMessage("trying gomory cut for col <%s> [%g]\n", SCIPvarGetName(var), primsol);
               tryrow = TRUE;
            }
         }
      }
      else if( sepadata->separaterows )
      {
         SCIP_ROW* row;

         assert(0 <= -c-1 && -c-1 < nrows);
         row = rows[-c-1];
         if( SCIProwIsIntegral(row) && !SCIProwIsModifiable(row) )
         {
            SCIP_Real primsol;

            primsol = SCIPgetRowActivity(scip, row);
            if( SCIPfeasFrac(scip, primsol) >= minfrac )
            {
               SCIPdebugMessage("trying gomory cut for row <%s> [%g]\n", SCIProwGetName(row), primsol);
               tryrow = TRUE;
            }
         }
      }

      if( tryrow )
      {
         SCIP_Real cutrhs;
         SCIP_Real cutact;
         SCIP_Bool success;
         SCIP_Bool cutislocal;

         /* get the row of B^-1 for this basic integer variable with fractional solution value */
         SCIP_CALL( SCIPgetLPBInvRow(scip, i, binvrow) );

         cutact = 0.0;
         cutrhs = SCIPinfinity(scip);

         /* create a MIR cut out of the weighted LP rows using the B^-1 row as weights */
         SCIP_CALL( SCIPcalcMIR(scip, NULL, BOUNDSWITCH, USEVBDS, ALLOWLOCAL, FIXINTEGRALRHS, NULL, NULL,
               (int) MAXAGGRLEN(nvars), sepadata->maxweightrange, minfrac, maxfrac,
               binvrow, 1.0, NULL, NULL, cutcoefs, &cutrhs, &cutact, &success, &cutislocal) );
         assert(ALLOWLOCAL || !cutislocal);

         /* @todo Currently we are using the SCIPcalcMIR() function to compute the coefficients of the Gomory
          *       cut. Alternatively, we could use the direct version (see thesis of Achterberg formula (8.4)) which
          *       leads to cut a of the form \sum a_i x_i \geq 1. Rumor has it that these cuts are better.
          */

         SCIPdebugMessage(" -> success=%u: %g <= %g\n", success, cutact, cutrhs);

         /* if successful, convert dense cut into sparse row, and add the row as a cut */
         if( success && SCIPisFeasGT(scip, cutact, cutrhs) )
         {
            SCIP_ROW* cut;
            char cutname[SCIP_MAXSTRLEN];
            int v;

            /* construct cut name */
            if( c >= 0 )
               (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "gom%d_x%d", SCIPgetNLPs(scip), c);
            else
               (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "gom%d_s%d", SCIPgetNLPs(scip), -c-1);

            /* create empty cut */
            SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &cut, sepa, cutname, -SCIPinfinity(scip), cutrhs,
                  cutislocal, FALSE, sepadata->dynamiccuts) );

            /* cache the row extension and only flush them if the cut gets added */
            SCIP_CALL( SCIPcacheRowExtensions(scip, cut) );

            /* collect all non-zero coefficients */
            for( v = 0; v < nvars; ++v )
            {
               if( !SCIPisZero(scip, cutcoefs[v]) )
               {
                  SCIP_CALL( SCIPaddVarToRow(scip, cut, vars[v], cutcoefs[v]) );
               }
            }

            if( SCIProwGetNNonz(cut) == 0 )
            {
               assert(SCIPisFeasNegative(scip, cutrhs));
               SCIPdebugMessage(" -> gomory cut detected infeasibility with cut 0 <= %f\n", cutrhs);
               cutoff = TRUE;
            }
            else if( SCIProwGetNNonz(cut) == 1 )
            {
               /* add the bound change as cut to avoid that the LP gets modified. that would mean the LP is not flushed
                * and the method SCIPgetLPBInvRow() fails; SCIP internally will apply that bound change automatically
                */
               SCIP_CALL( SCIPaddCut(scip, NULL, cut, TRUE) );
               naddedcuts++;
            }
            else
            {
               /* Only take efficacious cuts, except for cuts with one non-zero coefficients (= bound
                * changes); the latter cuts will be handeled internally in sepastore.
                */
               if( SCIPisCutEfficacious(scip, NULL, cut) )
               {
                  assert(success == TRUE);

                  SCIPdebugMessage(" -> gomory cut for <%s>: act=%f, rhs=%f, eff=%f\n",
                     c >= 0 ? SCIPvarGetName(SCIPcolGetVar(cols[c])) : SCIProwGetName(rows[-c-1]),
                     cutact, cutrhs, SCIPgetCutEfficacy(scip, NULL, cut));

                  if( sepadata->makeintegral )
                  {
                     /* try to scale the cut to integral values */
                     SCIP_CALL( SCIPmakeRowIntegral(scip, cut, -SCIPepsilon(scip), SCIPsumepsilon(scip),
                           maxdnom, maxscale, MAKECONTINTEGRAL, &success) );

                     if( sepadata->forcecuts )
                        success = TRUE;

                     /* in case the left hand side in minus infinity and the right hand side is plus infinity the cut is
                      * useless so we are not taking it at all
                      */
                     if( (SCIPisInfinity(scip, -SCIProwGetLhs(cut)) && SCIPisInfinity(scip, SCIProwGetRhs(cut))) )
                        success = FALSE;

                     /* @todo Trying to make the Gomory cut integral might fail. Due to numerical reasons/arguments we
                      *       currently ignore such cuts. If the cut, however, has small support (let's say smaller or equal to
                      *       5), we might want to add that cut (even it does not have integral coefficients). To be able to
                      *       do that we need to add a rank to the data structure of a row. The rank of original rows are
                      *       zero and for aggregated rows it is the maximum over all used rows plus one.
                      */
                  }

                  if( success )
                  {
                     SCIPdebugMessage(" -> found gomory cut <%s>: act=%f, rhs=%f, norm=%f, eff=%f, min=%f, max=%f (range=%f)\n",
                        cutname, SCIPgetRowLPActivity(scip, cut), SCIProwGetRhs(cut), SCIProwGetNorm(cut),
                        SCIPgetCutEfficacy(scip, NULL, cut),
                        SCIPgetRowMinCoef(scip, cut), SCIPgetRowMaxCoef(scip, cut),
                        SCIPgetRowMaxCoef(scip, cut)/SCIPgetRowMinCoef(scip, cut));

                     /* flush all changes before adding the cut */
                     SCIP_CALL( SCIPflushRowExtensions(scip, cut) );

                     /* add global cuts which are not implicit bound changes to the cut pool */
                     if( !cutislocal )
                     {
                        if( sepadata->delayedcuts )
                        {
                           SCIP_CALL( SCIPaddDelayedPoolCut(scip, cut) );
                        }
                        else
                        {
                           SCIP_CALL( SCIPaddPoolCut(scip, cut) );
                        }
                     }
                     else
                     {
                        /* local cuts we add to the sepastore */
                        SCIP_CALL( SCIPaddCut(scip, NULL, cut, FALSE) );
                     }

                     naddedcuts++;
                  }
               }
            }

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

   /* free temporary memory */
   SCIPfreeBufferArray(scip, &binvrow);
   SCIPfreeBufferArray(scip, &basisind);
   SCIPfreeBufferArray(scip, &cutcoefs);

   SCIPdebugMessage("end searching gomory cuts: found %d cuts\n", naddedcuts);

   sepadata->lastncutsfound = SCIPgetNCutsFound(scip);

   /* evalute the result of the separation */
   if( cutoff )
      *result = SCIP_CUTOFF;
   else if ( naddedcuts > 0 )
      *result = SCIP_SEPARATED;
   else
      *result = SCIP_DIDNOTFIND;

   return SCIP_OKAY;
}
/** execution method of primal heuristic */
static
SCIP_DECL_HEUREXEC(heurExecRootsoldiving) /*lint --e{715}*/
{  /*lint --e{715}*/
   SCIP_HEURDATA* heurdata;
   SCIP_VAR** vars;
   SCIP_Real* rootsol;
   SCIP_Real* objchgvals;
   int* softroundings;
   int* intvalrounds;
   int nvars;
   int nbinvars;
   int nintvars;
   int nlpcands;
   SCIP_LPSOLSTAT lpsolstat;
   SCIP_Real absstartobjval;
   SCIP_Real objstep;
   SCIP_Real alpha;
   SCIP_Real oldobj;
   SCIP_Real newobj;
   SCIP_Bool lperror;
   SCIP_Bool lpsolchanged;
   SCIP_Longint nsolsfound;
   SCIP_Longint ncalls;
   SCIP_Longint nlpiterations;
   SCIP_Longint maxnlpiterations;
   int depth;
   int maxdepth;
   int maxdivedepth;
   int divedepth;
   int startnlpcands;
   int ncycles;
   int i;

   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;

   /* only call heuristic, if the LP solution is basic (which allows fast resolve in diving) */
   if( !SCIPisLPSolBasic(scip) )
      return SCIP_OKAY;

   /* don't dive two times at the same node */
   if( SCIPgetLastDivenode(scip) == SCIPgetNNodes(scip) && SCIPgetDepth(scip) > 0 )
      return SCIP_OKAY;

   *result = SCIP_DIDNOTRUN;

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

   /* only apply heuristic, if only a few solutions have been found */
   if( heurdata->maxsols >= 0 && SCIPgetNSolsFound(scip) >= heurdata->maxsols )
      return SCIP_OKAY;

   /* only try to dive, if we are in the correct part of the tree, given by minreldepth and maxreldepth */
   depth = SCIPgetDepth(scip);
   maxdepth = SCIPgetMaxDepth(scip);
   maxdepth = MAX(maxdepth, 30);
   if( depth < heurdata->minreldepth*maxdepth || depth > heurdata->maxreldepth*maxdepth )
      return SCIP_OKAY;

   /* calculate the maximal number of LP iterations until heuristic is aborted */
   nlpiterations = SCIPgetNNodeLPIterations(scip);
   ncalls = SCIPheurGetNCalls(heur);
   nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + heurdata->nsuccess;
   maxnlpiterations = (SCIP_Longint)((1.0 + 10.0*(nsolsfound+1.0)/(ncalls+1.0)) * heurdata->maxlpiterquot * nlpiterations);
   maxnlpiterations += heurdata->maxlpiterofs;

   /* don't try to dive, if we took too many LP iterations during diving */
   if( heurdata->nlpiterations >= maxnlpiterations )
      return SCIP_OKAY;

   /* allow at least a certain number of LP iterations in this dive */
   maxnlpiterations = MAX(maxnlpiterations, heurdata->nlpiterations + MINLPITER);

   /* get number of fractional variables, that should be integral */
   nlpcands = SCIPgetNLPBranchCands(scip);

   /* don't try to dive, if there are no fractional variables */
   if( nlpcands == 0 )
      return SCIP_OKAY;

   /* calculate the maximal diving depth */
   nvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
   if( SCIPgetNSolsFound(scip) == 0 )
      maxdivedepth = (int)(heurdata->depthfacnosol * nvars);
   else
      maxdivedepth = (int)(heurdata->depthfac * nvars);
   maxdivedepth = MAX(maxdivedepth, 10);

   *result = SCIP_DIDNOTFIND;

   /* get all variables of LP */
   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );

   /* get root solution value of all binary and integer variables */
   SCIP_CALL( SCIPallocBufferArray(scip, &rootsol, nbinvars + nintvars) );
   for( i = 0; i < nbinvars + nintvars; i++ )
      rootsol[i] = SCIPvarGetRootSol(vars[i]);

   /* get current LP objective value, and calculate length of a single step in an objective coefficient */
   absstartobjval = SCIPgetLPObjval(scip);
   absstartobjval = ABS(absstartobjval);
   absstartobjval = MAX(absstartobjval, 1.0);
   objstep = absstartobjval / 10.0;

   /* initialize array storing the preferred soft rounding directions and counting the integral value rounds */
   SCIP_CALL( SCIPallocBufferArray(scip, &softroundings, nbinvars + nintvars) );
   BMSclearMemoryArray(softroundings, nbinvars + nintvars);
   SCIP_CALL( SCIPallocBufferArray(scip, &intvalrounds, nbinvars + nintvars) );
   BMSclearMemoryArray(intvalrounds, nbinvars + nintvars);

   /* allocate temporary memory for buffering objective changes */
   SCIP_CALL( SCIPallocBufferArray(scip, &objchgvals, nbinvars + nintvars) );

   /* start diving */
   SCIP_CALL( SCIPstartDive(scip) );

   SCIPdebugMessage("(node %"SCIP_LONGINT_FORMAT") executing rootsoldiving heuristic: depth=%d, %d fractionals, dualbound=%g, maxnlpiterations=%"SCIP_LONGINT_FORMAT", maxdivedepth=%d, LPobj=%g, objstep=%g\n",
      SCIPgetNNodes(scip), SCIPgetDepth(scip), nlpcands, SCIPgetDualbound(scip), maxnlpiterations, maxdivedepth,
      SCIPgetLPObjval(scip), objstep);

   lperror = FALSE;
   divedepth = 0;
   lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
   alpha = heurdata->alpha;
   ncycles = 0;
   lpsolchanged = TRUE;
   startnlpcands = nlpcands;
   while( !lperror && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL && nlpcands > 0 && ncycles < 10
      && (divedepth < 10
         || nlpcands <= startnlpcands - divedepth/2
         || (divedepth < maxdivedepth && heurdata->nlpiterations < maxnlpiterations))
      && !SCIPisStopped(scip) )
   {
      SCIP_Bool success;
      int hardroundingidx;
      int hardroundingdir;
      SCIP_Real hardroundingoldbd;
      SCIP_Real hardroundingnewbd;
      SCIP_Bool boundschanged;

      SCIP_RETCODE retcode;

      /* create solution from diving LP and try to round it */
      SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
      SCIP_CALL( SCIProundSol(scip, heurdata->sol, &success) );

      if( success )
      {
         SCIPdebugMessage("rootsoldiving found roundable primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));

         /* try to add solution to SCIP */
         SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, &success) );

         /* check, if solution was feasible and good enough */
         if( success )
         {
            SCIPdebugMessage(" -> solution was feasible and good enough\n");
            *result = SCIP_FOUNDSOL;
         }
      }

      divedepth++;
      hardroundingidx = -1;
      hardroundingdir = 0;
      hardroundingoldbd = 0.0;
      hardroundingnewbd = 0.0;
      boundschanged = FALSE;

      SCIPdebugMessage("dive %d/%d, LP iter %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT":\n", divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations);

      /* round solution x* from diving LP:
       *   - x~_j = down(x*_j)    if x*_j is integer or binary variable and x*_j <= root solution_j
       *   - x~_j = up(x*_j)      if x*_j is integer or binary variable and x*_j  > root solution_j
       *   - x~_j = x*_j          if x*_j is continuous variable
       * change objective function in diving LP:
       *   - if x*_j is integral, or j is a continuous variable, set obj'_j = alpha * obj_j
       *   - otherwise, set obj'_j = alpha * obj_j + sign(x*_j - x~_j)
       */
      for( i = 0; i < nbinvars + nintvars; i++ )
      {
         SCIP_VAR* var;
         SCIP_Real solval;

         var = vars[i];
         oldobj = SCIPgetVarObjDive(scip, var);
         newobj = oldobj;

         solval =  SCIPvarGetLPSol(var);
         if( SCIPisFeasIntegral(scip, solval) )
         {
            /* if the variable became integral after a soft rounding, count the rounds; after a while, fix it to its
             * current integral value;
             * otherwise, fade out the objective value
             */
            if( softroundings[i] != 0 && lpsolchanged )
            {
               intvalrounds[i]++;
               if( intvalrounds[i] == 5 && SCIPgetVarLbDive(scip, var) < SCIPgetVarUbDive(scip, var) - 0.5 )
               {
                  /* use exact integral value, if the variable is only integral within numerical tolerances */
                  solval = SCIPfloor(scip, solval+0.5);
                  SCIPdebugMessage(" -> fixing <%s> = %g\n", SCIPvarGetName(var), solval);
                  SCIP_CALL( SCIPchgVarLbDive(scip, var, solval) );
                  SCIP_CALL( SCIPchgVarUbDive(scip, var, solval) );
                  boundschanged = TRUE;
               }
            }
            else
               newobj = alpha * oldobj;
         }
         else if( solval <= rootsol[i] )
         {
            /* if the variable was soft rounded most of the time downwards, round it downwards by changing the bounds;
             * otherwise, apply soft rounding by changing the objective value
             */
            softroundings[i]--;
            if( softroundings[i] <= -10 && hardroundingidx == -1 )
            {
               SCIPdebugMessage(" -> hard rounding <%s>[%g] <= %g\n",
                  SCIPvarGetName(var), solval, SCIPfeasFloor(scip, solval));
               hardroundingidx = i;
               hardroundingdir = -1;
               hardroundingoldbd = SCIPgetVarUbDive(scip, var);
               hardroundingnewbd = SCIPfeasFloor(scip, solval);
               SCIP_CALL( SCIPchgVarUbDive(scip, var, hardroundingnewbd) );
               boundschanged = TRUE;
            }
            else
               newobj = alpha * oldobj + objstep;
         }
         else
         {
            /* if the variable was soft rounded most of the time upwards, round it upwards by changing the bounds;
             * otherwise, apply soft rounding by changing the objective value
             */
            softroundings[i]++;
            if( softroundings[i] >= +10 && hardroundingidx == -1 )
            {
               SCIPdebugMessage(" -> hard rounding <%s>[%g] >= %g\n",
                  SCIPvarGetName(var), solval, SCIPfeasCeil(scip, solval));
               hardroundingidx = i;
               hardroundingdir = +1;
               hardroundingoldbd = SCIPgetVarLbDive(scip, var);
               hardroundingnewbd = SCIPfeasCeil(scip, solval);
               SCIP_CALL( SCIPchgVarLbDive(scip, var, hardroundingnewbd) );
               boundschanged = TRUE;
            }
            else
               newobj = alpha * oldobj - objstep;
         }

         /* remember the objective change */
         objchgvals[i] = newobj;
      }

      /* apply objective changes if there was no bound change */
      if( !boundschanged )
      {
         /* apply cached changes on integer variables */
         for( i = 0; i < nbinvars + nintvars; ++i )
         {
            SCIP_VAR* var;

            var = vars[i];
            SCIPdebugMessage(" -> i=%d  var <%s>, solval=%g, rootsol=%g, oldobj=%g, newobj=%g\n",
               i, SCIPvarGetName(var), SCIPvarGetLPSol(var), rootsol[i], SCIPgetVarObjDive(scip, var), objchgvals[i]);

            SCIP_CALL( SCIPchgVarObjDive(scip, var, objchgvals[i]) );
         }

         /* fade out the objective values of the continuous variables */
         for( i = nbinvars + nintvars; i < nvars; i++ )
         {
            SCIP_VAR* var;

            var = vars[i];
            oldobj = SCIPgetVarObjDive(scip, var);
            newobj = alpha * oldobj;

            SCIPdebugMessage(" -> i=%d  var <%s>, solval=%g, oldobj=%g, newobj=%g\n",
               i, SCIPvarGetName(var), SCIPvarGetLPSol(var), oldobj, newobj);

            SCIP_CALL( SCIPchgVarObjDive(scip, var, newobj) );
         }
      }

   SOLVEAGAIN:
      /* resolve the diving LP */
      nlpiterations = SCIPgetNLPIterations(scip);

      retcode = SCIPsolveDiveLP(scip,  MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror);
      lpsolstat = SCIPgetLPSolstat(scip);

      /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
       * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
       */
      if( retcode != SCIP_OKAY )
      {
#ifndef NDEBUG
         if( lpsolstat != SCIP_LPSOLSTAT_UNBOUNDEDRAY )
         {
            SCIP_CALL( retcode );
         }
#endif
         SCIPwarningMessage(scip, "Error while solving LP in Rootsoldiving heuristic; LP solve terminated with code <%d>\n", retcode);
         SCIPwarningMessage(scip, "This does not affect the remaining solution procedure --> continue\n");
      }

      if( lperror )
         break;

      /* update iteration count */
      heurdata->nlpiterations += SCIPgetNLPIterations(scip) - nlpiterations;

      /* if no LP iterations were performed, we stayed at the same solution -> count this cycling */
      lpsolchanged = (SCIPgetNLPIterations(scip) != nlpiterations);
      if( lpsolchanged )
         ncycles = 0;
      else if( !boundschanged ) /* do not count if integral variables have been fixed */
         ncycles++;

      /* get LP solution status and number of fractional variables, that should be integral */
      if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE && hardroundingidx != -1 )
      {
         SCIP_VAR* var;

         var = vars[hardroundingidx];

         /* round the hard rounded variable to the opposite direction and resolve the LP */
         if( hardroundingdir == -1 )
         {
            SCIPdebugMessage(" -> opposite hard rounding <%s> >= %g\n", SCIPvarGetName(var), hardroundingnewbd + 1.0);
            SCIP_CALL( SCIPchgVarUbDive(scip, var, hardroundingoldbd) );
            SCIP_CALL( SCIPchgVarLbDive(scip, var, hardroundingnewbd + 1.0) );
         }
         else
         {
            SCIPdebugMessage(" -> opposite hard rounding <%s> <= %g\n", SCIPvarGetName(var), hardroundingnewbd - 1.0);
            SCIP_CALL( SCIPchgVarLbDive(scip, var, hardroundingoldbd) );
            SCIP_CALL( SCIPchgVarUbDive(scip, var, hardroundingnewbd - 1.0) );
         }
         hardroundingidx = -1;
         goto SOLVEAGAIN;
      }
      if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
         nlpcands = SCIPgetNLPBranchCands(scip);
      SCIPdebugMessage("   -> lpsolstat=%d, nfrac=%d\n", lpsolstat, nlpcands);
   }

   SCIPdebugMessage("---> diving finished: lpsolstat = %d, depth %d/%d, LP iter %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT"\n",
      lpsolstat, divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations);

   /* check if a solution has been found */
   if( nlpcands == 0 && !lperror && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
   {
      SCIP_Bool success;

      /* create solution from diving LP */
      SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
      SCIPdebugMessage("rootsoldiving found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));

      /* try to add solution to SCIP */
      SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, &success) );

      /* check, if solution was feasible and good enough */
      if( success )
      {
         SCIPdebugMessage(" -> solution was feasible and good enough\n");
         *result = SCIP_FOUNDSOL;
      }
   }

   /* end diving */
   SCIP_CALL( SCIPendDive(scip) );

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

   /* free temporary memory */
   SCIPfreeBufferArray(scip, &objchgvals);
   SCIPfreeBufferArray(scip, &intvalrounds);
   SCIPfreeBufferArray(scip, &softroundings);
   SCIPfreeBufferArray(scip, &rootsol);

   SCIPdebugMessage("rootsoldiving heuristic finished\n");

   return SCIP_OKAY;
}
Esempio n. 9
0
/** execution method of primal heuristic */
static
SCIP_DECL_HEUREXEC(heurExecShifting) /*lint --e{715}*/
{   /*lint --e{715}*/
    SCIP_HEURDATA* heurdata;
    SCIP_SOL* sol;
    SCIP_VAR** lpcands;
    SCIP_Real* lpcandssol;
    SCIP_ROW** lprows;
    SCIP_Real* activities;
    SCIP_ROW** violrows;
    SCIP_Real* nincreases;
    SCIP_Real* ndecreases;
    int* violrowpos;
    int* nfracsinrow;
    SCIP_Real increaseweight;
    SCIP_Real obj;
    SCIP_Real bestshiftval;
    SCIP_Real minobj;
    int nlpcands;
    int nlprows;
    int nvars;
    int nfrac;
    int nviolrows;
    int nprevviolrows;
    int minnviolrows;
    int nnonimprovingshifts;
    int c;
    int r;
    SCIP_Longint nlps;
    SCIP_Longint ncalls;
    SCIP_Longint nsolsfound;
    SCIP_Longint nnodes;

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

    *result = SCIP_DIDNOTRUN;

    /* 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);

    /* don't call heuristic, if we have already processed the current LP solution */
    nlps = SCIPgetNLPs(scip);
    if( nlps == heurdata->lastlp )
        return SCIP_OKAY;
    heurdata->lastlp = nlps;

    /* don't call heuristic, if it was not successful enough in the past */
    ncalls = SCIPheurGetNCalls(heur);
    nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + SCIPheurGetNSolsFound(heur);
    nnodes = SCIPgetNNodes(scip);
    if( nnodes % ((ncalls/100)/(nsolsfound+1)+1) != 0 )
        return SCIP_OKAY;

    /* get fractional variables, that should be integral */
    /* todo check if heuristic should include implicit integer variables for its calculations */
    SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, NULL, &nlpcands, NULL, NULL) );
    nfrac = nlpcands;

    /* only call heuristic, if LP solution is fractional */
    if( nfrac == 0 )
        return SCIP_OKAY;

    *result = SCIP_DIDNOTFIND;

    /* get LP rows */
    SCIP_CALL( SCIPgetLPRowsData(scip, &lprows, &nlprows) );

    SCIPdebugMessage("executing shifting heuristic: %d LP rows, %d fractionals\n", nlprows, nfrac);

    /* get memory for activities, violated rows, and row violation positions */
    nvars = SCIPgetNVars(scip);
    SCIP_CALL( SCIPallocBufferArray(scip, &activities, nlprows) );
    SCIP_CALL( SCIPallocBufferArray(scip, &violrows, nlprows) );
    SCIP_CALL( SCIPallocBufferArray(scip, &violrowpos, nlprows) );
    SCIP_CALL( SCIPallocBufferArray(scip, &nfracsinrow, nlprows) );
    SCIP_CALL( SCIPallocBufferArray(scip, &nincreases, nvars) );
    SCIP_CALL( SCIPallocBufferArray(scip, &ndecreases, nvars) );
    BMSclearMemoryArray(nfracsinrow, nlprows);
    BMSclearMemoryArray(nincreases, nvars);
    BMSclearMemoryArray(ndecreases, nvars);

    /* get the activities for all globally valid rows;
     * the rows should be feasible, but due to numerical inaccuracies in the LP solver, they can be violated
     */
    nviolrows = 0;
    for( r = 0; r < nlprows; ++r )
    {
        SCIP_ROW* row;

        row = lprows[r];
        assert(SCIProwGetLPPos(row) == r);

        if( !SCIProwIsLocal(row) )
        {
            activities[r] = SCIPgetRowActivity(scip, row);
            if( SCIPisFeasLT(scip, activities[r], SCIProwGetLhs(row))
                    || SCIPisFeasGT(scip, activities[r], SCIProwGetRhs(row)) )
            {
                violrows[nviolrows] = row;
                violrowpos[r] = nviolrows;
                nviolrows++;
            }
            else
                violrowpos[r] = -1;
        }
    }

    /* calc the current number of fractional variables in rows */
    for( c = 0; c < nlpcands; ++c )
        addFracCounter(nfracsinrow, nlprows, lpcands[c], +1);

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

    /* copy the current LP solution to the working solution */
    SCIP_CALL( SCIPlinkLPSol(scip, sol) );

    /* calculate the minimal objective value possible after rounding fractional variables */
    minobj = SCIPgetSolTransObj(scip, sol);
    assert(minobj < SCIPgetCutoffbound(scip));
    for( c = 0; c < nlpcands; ++c )
    {
        obj = SCIPvarGetObj(lpcands[c]);
        bestshiftval = obj > 0.0 ? SCIPfeasFloor(scip, lpcandssol[c]) : SCIPfeasCeil(scip, lpcandssol[c]);
        minobj += obj * (bestshiftval - lpcandssol[c]);
    }

    /* try to shift remaining variables in order to become/stay feasible */
    nnonimprovingshifts = 0;
    minnviolrows = INT_MAX;
    increaseweight = 1.0;
    while( (nfrac > 0 || nviolrows > 0) && nnonimprovingshifts < MAXSHIFTINGS )
    {
        SCIP_VAR* shiftvar;
        SCIP_Real oldsolval;
        SCIP_Real newsolval;
        SCIP_Bool oldsolvalisfrac;
        int probindex;

        SCIPdebugMessage("shifting heuristic: nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g), cutoff=%g\n",
                         nfrac, nviolrows, SCIPgetSolOrigObj(scip, sol), SCIPretransformObj(scip, minobj),
                         SCIPretransformObj(scip, SCIPgetCutoffbound(scip)));

        nprevviolrows = nviolrows;

        /* choose next variable to process:
         *  - if a violated row exists, shift a variable decreasing the violation, that has least impact on other rows
         *  - otherwise, shift a variable, that has strongest devastating impact on rows in opposite direction
         */
        shiftvar = NULL;
        oldsolval = 0.0;
        newsolval = 0.0;
        if( nviolrows > 0 && (nfrac == 0 || nnonimprovingshifts < MAXSHIFTINGS-1) )
        {
            SCIP_ROW* row;
            int rowidx;
            int rowpos;
            int direction;

            rowidx = -1;
            rowpos = -1;
            row = NULL;
            if( nfrac > 0 )
            {
                for( rowidx = nviolrows-1; rowidx >= 0; --rowidx )
                {
                    row = violrows[rowidx];
                    rowpos = SCIProwGetLPPos(row);
                    assert(violrowpos[rowpos] == rowidx);
                    if( nfracsinrow[rowpos] > 0 )
                        break;
                }
            }
            if( rowidx == -1 )
            {
                rowidx = SCIPgetRandomInt(0, nviolrows-1, &heurdata->randseed);
                row = violrows[rowidx];
                rowpos = SCIProwGetLPPos(row);
                assert(0 <= rowpos && rowpos < nlprows);
                assert(violrowpos[rowpos] == rowidx);
                assert(nfracsinrow[rowpos] == 0);
            }
            assert(violrowpos[rowpos] == rowidx);

            SCIPdebugMessage("shifting heuristic: try to fix violated row <%s>: %g <= %g <= %g\n",
                             SCIProwGetName(row), SCIProwGetLhs(row), activities[rowpos], SCIProwGetRhs(row));
            SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );

            /* get direction in which activity must be shifted */
            assert(SCIPisFeasLT(scip, activities[rowpos], SCIProwGetLhs(row))
                   || SCIPisFeasGT(scip, activities[rowpos], SCIProwGetRhs(row)));
            direction = SCIPisFeasLT(scip, activities[rowpos], SCIProwGetLhs(row)) ? +1 : -1;

            /* search a variable that can shift the activity in the necessary direction */
            SCIP_CALL( selectShifting(scip, sol, row, activities[rowpos], direction,
                                      nincreases, ndecreases, increaseweight, &shiftvar, &oldsolval, &newsolval) );
        }

        if( shiftvar == NULL && nfrac > 0 )
        {
            SCIPdebugMessage("shifting heuristic: search rounding variable and try to stay feasible\n");
            SCIP_CALL( selectEssentialRounding(scip, sol, minobj, lpcands, nlpcands, &shiftvar, &oldsolval, &newsolval) );
        }

        /* check, whether shifting was possible */
        if( shiftvar == NULL || SCIPisEQ(scip, oldsolval, newsolval) )
        {
            SCIPdebugMessage("shifting heuristic:  -> didn't find a shifting variable\n");
            break;
        }

        SCIPdebugMessage("shifting heuristic:  -> shift var <%s>[%g,%g], type=%d, oldval=%g, newval=%g, obj=%g\n",
                         SCIPvarGetName(shiftvar), SCIPvarGetLbGlobal(shiftvar), SCIPvarGetUbGlobal(shiftvar), SCIPvarGetType(shiftvar),
                         oldsolval, newsolval, SCIPvarGetObj(shiftvar));

        /* update row activities of globally valid rows */
        SCIP_CALL( updateActivities(scip, activities, violrows, violrowpos, &nviolrows, nlprows,
                                    shiftvar, oldsolval, newsolval) );
        if( nviolrows >= nprevviolrows )
            nnonimprovingshifts++;
        else if( nviolrows < minnviolrows )
        {
            minnviolrows = nviolrows;
            nnonimprovingshifts = 0;
        }

        /* store new solution value and decrease fractionality counter */
        SCIP_CALL( SCIPsetSolVal(scip, sol, shiftvar, newsolval) );

        /* update fractionality counter and minimal objective value possible after shifting remaining variables */
        oldsolvalisfrac = !SCIPisFeasIntegral(scip, oldsolval)
                          && (SCIPvarGetType(shiftvar) == SCIP_VARTYPE_BINARY || SCIPvarGetType(shiftvar) == SCIP_VARTYPE_INTEGER);
        obj = SCIPvarGetObj(shiftvar);
        if( (SCIPvarGetType(shiftvar) == SCIP_VARTYPE_BINARY || SCIPvarGetType(shiftvar) == SCIP_VARTYPE_INTEGER)
                && oldsolvalisfrac )
        {
            assert(SCIPisFeasIntegral(scip, newsolval));
            nfrac--;
            nnonimprovingshifts = 0;
            minnviolrows = INT_MAX;
            addFracCounter(nfracsinrow, nlprows, shiftvar, -1);

            /* the rounding was already calculated into the minobj -> update only if rounding in "wrong" direction */
            if( obj > 0.0 && newsolval > oldsolval )
                minobj += obj;
            else if( obj < 0.0 && newsolval < oldsolval )
                minobj -= obj;
        }
        else
        {
            /* update minimal possible objective value */
            minobj += obj * (newsolval - oldsolval);
        }

        /* update increase/decrease arrays */
        if( !oldsolvalisfrac )
        {
            probindex = SCIPvarGetProbindex(shiftvar);
            assert(0 <= probindex && probindex < nvars);
            increaseweight *= WEIGHTFACTOR;
            if( newsolval < oldsolval )
                ndecreases[probindex] += increaseweight;
            else
                nincreases[probindex] += increaseweight;
            if( increaseweight >= 1e+09 )
            {
                int i;

                for( i = 0; i < nvars; ++i )
                {
                    nincreases[i] /= increaseweight;
                    ndecreases[i] /= increaseweight;
                }
                increaseweight = 1.0;
            }
        }

        SCIPdebugMessage("shifting heuristic:  -> nfrac=%d, nviolrows=%d, obj=%g (best possible obj: %g)\n",
                         nfrac, nviolrows, SCIPgetSolOrigObj(scip, sol), SCIPretransformObj(scip, minobj));
    }

    /* check, if the new solution is feasible */
    if( nfrac == 0 && nviolrows == 0 )
    {
        SCIP_Bool stored;

        /* check solution for feasibility, and add it to solution store if possible
         * neither integrality nor feasibility of LP rows has to be checked, because this is already
         * done in the shifting heuristic itself; however, we better check feasibility of LP rows,
         * because of numerical problems with activity updating
         */
        SCIP_CALL( SCIPtrySol(scip, sol, FALSE, FALSE, FALSE, TRUE, &stored) );

        if( stored )
        {
            SCIPdebugMessage("found feasible shifted solution:\n");
            SCIPdebug( SCIP_CALL( SCIPprintSol(scip, sol, NULL, FALSE) ) );
            *result = SCIP_FOUNDSOL;
        }
    }

    /* free memory buffers */
    SCIPfreeBufferArray(scip, &ndecreases);
    SCIPfreeBufferArray(scip, &nincreases);
    SCIPfreeBufferArray(scip, &nfracsinrow);
    SCIPfreeBufferArray(scip, &violrowpos);
    SCIPfreeBufferArray(scip, &violrows);
    SCIPfreeBufferArray(scip, &activities);

    return SCIP_OKAY;
}
Esempio n. 10
0
/** constraint copying method of constraint handler */
static
SCIP_DECL_CONSCOPY(consCopyConjunction)
{  /*lint --e{715}*/
   SCIP_CONSDATA* sourcedata;
   SCIP_CONS** sourceconss;
   SCIP_CONS** conss;
   int nconss;
   int c;

   *valid = TRUE;

   sourcedata = SCIPconsGetData(sourcecons);
   assert(sourcedata != NULL);

   sourceconss = sourcedata->conss;
   nconss = sourcedata->nconss;

   if( nconss > 0 )
   {
      assert(sourceconss != NULL);

      SCIP_CALL( SCIPallocBufferArray(scip, &conss, nconss) );

      /* copy each constraint one by one */
      for( c = 0; c < nconss && (*valid); ++c )
      {
         SCIP_CALL( SCIPgetConsCopy(sourcescip, scip, sourceconss[c], &conss[c], SCIPconsGetHdlr(sourceconss[c]),
               varmap, consmap, SCIPconsGetName(sourceconss[c]),
               SCIPconsIsInitial(sourceconss[c]), SCIPconsIsSeparated(sourceconss[c]), SCIPconsIsEnforced(sourceconss[c]),
               SCIPconsIsChecked(sourceconss[c]), SCIPconsIsPropagated(sourceconss[c]),
               SCIPconsIsLocal(sourceconss[c]), SCIPconsIsModifiable(sourceconss[c]),
               SCIPconsIsDynamic(sourceconss[c]), SCIPconsIsRemovable(sourceconss[c]), SCIPconsIsStickingAtNode(sourceconss[c]),
               global, valid) );
         assert(!(*valid) || conss[c] != NULL);
      }

      if( *valid )
      {
         if( name == NULL )
         {
            SCIP_CALL( SCIPcreateConsConjunction(scip, cons, SCIPconsGetName(sourcecons), nconss, conss,
                  enforce, check, local, modifiable, dynamic) );
         }
         else
         {
            SCIP_CALL( SCIPcreateConsConjunction(scip, cons, name, nconss, conss,
                  enforce, check, local, modifiable, dynamic) );
         }
      }

      /* release the copied constraints */
      for( c = (*valid ? c - 1 : c - 2); c >= 0; --c )
      {
         assert(conss[c] != NULL);
         SCIP_CALL( SCIPreleaseCons(scip, &conss[c]) );
      }

      SCIPfreeBufferArray(scip, &conss);
   }

   return SCIP_OKAY;
}
Esempio n. 11
0
/** 
 *  Preprocessing of the graph, using 2 methods in order to find redundant nodes
 *  that can be deleted and easily colored later.
 *
 *  Foundation of these methods is the computation of a maximum clique C with M nodes. 
 *  After this computation, the following two steps are repeated until no node was deleted
 *  in the last iteration:
 *  
 *  1: Low-Degree:
 *  Iterativly delete all nodes v in the graph G with degree d(v) < M ( don't delete nodes of C )
 *
 *  2: Dominated Neighbourhood:
 *  If the neighbourhood of one node v is part of the neighbourhood of another node w, v can 
 *  be deleted, since it can later get the same color as w.
 */
static 
SCIP_RETCODE preprocessGraph( 
   SCIP*                 scip               /**< SCIP data structure */
   )
{
   SCIP_PROBDATA*   probdata;           /* the problemdata */
   SCIP_Bool        changed;            /* was the graph changed in the last round of preprocessing? */
   SCIP_Bool        dominates;          /* is the neighbourhood of one node dominated by the neigbourhood of another one?*/
   int*             maxcliquenodes;     /* pointer to store nodes of the maximum weight clique */
   int              nmaxcliquenodes;    /* number of nodes in the maximum weight clique */
   TCLIQUE_WEIGHT   maxcliqueweight;    /* weight of the maximum weight clique */
   TCLIQUE_STATUS   status;             /* status of clique-computation */
   TCLIQUE_GRAPH*   currgraph;          /* the current, not preprocessed graph in each step */
   int currnnodes;                      /* the current number of nodes in each step */ 
   int actnewnode;                      /* the number of nodes yet marked for beeing in the graph in the next round */
   int* newnodes;                       /* the nodes that will be in the graph in the next round */
   int* degrees;                        /* the degrees of the nodes */
   int myround;                         /* the number of the current round */
   int ndeletednodes;                   /* the total number of deleted nodes */
   int nnodesdeleteddegreethisround;    /* the number of nodes deleted due to low degree in the current round */
   int nnodesdeletedneighbourthisround; /* the number of nodes deleted due to neighbourhood in the current round */
   int*  firstedge;                     /* pointer for the edges in the graph */
   int*  lastedge;                      /* pointer for the edges in the graph */
   int i;
   int j;
   char opt;

   assert(scip != NULL);
   probdata = SCIPgetProbData(scip);
   assert(probdata != NULL);

   printf("\npreprocessing...\n");

   /* copy the old graph */
   if( !tcliqueCreate(&currgraph) )
   {
      SCIPerrorMessage("could not flush the clique graph\n");
      return SCIP_ERROR;
   }

   assert(currgraph != NULL);

   if( !tcliqueAddNode(currgraph, tcliqueGetNNodes(probdata->oldgraph)-1, 0) )
   {
      SCIPerrorMessage("could not add a node to the clique graph\n");
      return SCIP_ERROR;
   }

   for ( i = 0; i < tcliqueGetNNodes(probdata->oldgraph); i++ )
   {
      /* get adjacent nodes for node i */
      firstedge = tcliqueGetFirstAdjedge(probdata->oldgraph, i);
      lastedge = tcliqueGetLastAdjedge(probdata->oldgraph, i);
      while ( firstedge <= lastedge )
      {
         if ( *firstedge > i )
         {
            if( !tcliqueAddEdge(currgraph, i, *firstedge) )
            {
               SCIPerrorMessage("could not add an edge to the clique graph\n");
               return SCIP_ERROR;
            }
         }
         firstedge++;
      }
   }

   if( !tcliqueFlush(currgraph) )
   {
      SCIPerrorMessage("could not flush the clique graph\n");
      return SCIP_ERROR;
   }

   currnnodes = tcliqueGetNNodes(probdata->oldgraph);

   /* get memory for array of deletednodes */  
   SCIP_CALL( SCIPallocMemoryArray(scip, &(probdata->deletednodes), COLORprobGetOriginalNNodes(scip)) );

   /* get memory for array new2oldnodes */
   SCIP_CALL( SCIPallocMemoryArray(scip, &(probdata->new2oldnode), COLORprobGetOriginalNNodes(scip)) );  

   SCIP_CALL( SCIPallocBufferArray(scip, &newnodes, COLORprobGetOriginalNNodes(scip)) );
   SCIP_CALL( SCIPallocBufferArray(scip, &maxcliquenodes, COLORprobGetOriginalNNodes(scip)) );
   
   for ( i = 0; i < currnnodes; i++ )
   {
      /* set weights of the nodes to 1 */
      tcliqueChangeWeight(currgraph, i, 1);
      /* every node in the graph represents the same node in the original graph */
      probdata->new2oldnode[i] = i;
   } 

   /* compute maximum clique */
   tcliqueMaxClique(NULL, NULL, NULL, NULL, currgraph, NULL, NULL, maxcliquenodes,
      &nmaxcliquenodes, &maxcliqueweight, 0, 0, 50000, 0, INT_MAX, -1, NULL, &status);
   opt = ( status == TCLIQUE_OPTIMAL ? ' ' : '*' );
   printf("size of the maximum clique: %d%c \n", nmaxcliquenodes, opt);

   ndeletednodes = 0;
   nnodesdeleteddegreethisround = 1;
   nnodesdeletedneighbourthisround = 1;
   myround = 0;

   /* main loop */
   while ( (nnodesdeleteddegreethisround > 0) || (nnodesdeletedneighbourthisround > 0) ) 
   {
      myround++;
      nnodesdeleteddegreethisround = 0;
      nnodesdeletedneighbourthisround = 0;
      changed = TRUE;

      /* node degree deletion loop */
      while ( changed == TRUE )
      {
         changed = FALSE;
         actnewnode = 0;
         degrees = tcliqueGetDegrees(currgraph);
         for (i = 0; i < currnnodes; i++)
         {
            /* degree is low, node can be deleted */
            if ( (degrees[i] < nmaxcliquenodes ) 
               && (!COLORprobIsNodeInArray(probdata->new2oldnode[i], maxcliquenodes, nmaxcliquenodes)) )
            {
               probdata->deletednodes[ndeletednodes] = probdata->new2oldnode[i];
               changed = TRUE;
               nnodesdeleteddegreethisround++;
               ndeletednodes++;
            }
            /* node will be in the new graph, because degree is not low enought for deletion or it is in the maxClique */
            else
            {
               newnodes[actnewnode] = probdata->new2oldnode[i];
               actnewnode++;
            }
         }

         /* at least one node was deletet, create new graph ( tclique doesn't support deletion of nodes) */
         if ( changed )
         {
            assert(actnewnode+ndeletednodes == COLORprobGetOriginalNNodes(scip));
            /* create new current graph */
            tcliqueFree(&currgraph);

            if( !tcliqueCreate(&currgraph) )
            {
               SCIPerrorMessage("could not create the clique graph\n");
               return SCIP_ERROR;
            }

            assert(currgraph != NULL);

            if( !tcliqueAddNode(currgraph, actnewnode-1, 0) )
            {
               SCIPerrorMessage("could not add a node to the clique graph\n");
               return SCIP_ERROR;
            }

            for ( i = 0; i < actnewnode; i++ )
            {
               /* get adjacent nodes for node newnodes[i] */
               firstedge = tcliqueGetFirstAdjedge(probdata->oldgraph, newnodes[i]);
               lastedge = tcliqueGetLastAdjedge(probdata->oldgraph, newnodes[i]);
               while ( firstedge <= lastedge )
               {
                  /* try to find a node in newnodes which corresponds 
                     to the node in the old graph, that is the end-node of the edge */
                  for ( j = i+1; j < actnewnode; j++ )
                  {
                     if ( *firstedge == newnodes[j] )
                     {
                        if( !tcliqueAddEdge(currgraph, i, j) )
                        {
                           SCIPerrorMessage("could not add an edge to the clique graph\n");
                           return SCIP_ERROR;
                        }

                        break;
                     }
                  }
                  firstedge++;
               }
            }

            if( !tcliqueFlush(currgraph) )
            {
               SCIPerrorMessage("could not flush the clique graph\n");
               return SCIP_ERROR;
            }

            /* update currnnodes */
            currnnodes = tcliqueGetNNodes(currgraph);
            /* update new2oldnodes */
            for ( i = 0; i < actnewnode; i++ )
            {
               probdata->new2oldnode[i] = newnodes[i];
            }
            /* set the corresponding old node to -1 for all nodes not in the current graph (only for bug-finding) */
            for ( i = actnewnode; i < COLORprobGetOriginalNNodes(scip); i++ )
            {
               probdata->new2oldnode[i] = -1;
            }
         }
      } /* end node degree deletion loop */

      /* set changed to TRUE for getting into the while-loop */
      changed = TRUE;
      /* loop for finding dominated neighbourhoods */
      while ( changed == TRUE )
      {
         changed = FALSE;
         actnewnode = 0;
         /* i is the node which is checked for beeing dominated */
         for ( i = 0; i < currnnodes; i++ )
         {
            assert(!COLORprobIsNodeInArray(probdata->new2oldnode[i], probdata->deletednodes, ndeletednodes));

            /* i must be not in the clique and not yet deleted */
            if ( (!COLORprobIsNodeInArray(probdata->new2oldnode[i], maxcliquenodes, nmaxcliquenodes)) )
            {
               /* j is the node for which is checked whether it dominates i */
               for ( j = 0; j < currnnodes; j++ )
               {
                  /* i must be distinct from j, there must be no edge between i and j, 
                     j may not have been deleted due to degree in the last round */
                  if ( (j != i) && !tcliqueIsEdge(currgraph, i, j) 
                     && (!COLORprobIsNodeInArray(probdata->new2oldnode[j], probdata->deletednodes, ndeletednodes)) )
                     /** @todo only check nodes deleted in the last round */
                  {
                     /* check whether nodes adjacent to i are also adjacent to j <-> j dominates i */
                     dominates = TRUE;
                     /* get adjacent nodes for node i in currgraph */
                     firstedge = tcliqueGetFirstAdjedge(currgraph, i);
                     lastedge = tcliqueGetLastAdjedge(currgraph, i);
                     while ( firstedge <= lastedge )
                     {
                        /* check whether (j,firstedge) is in currgraph, if not, j doesn't dominate i */
                        if ( !tcliqueIsEdge(currgraph, j, *firstedge) )
                        {
                           dominates = FALSE;
                           break;
                        }
                        firstedge++;
                     }
                     if ( dominates )
                     {
                        probdata->deletednodes[ndeletednodes] = probdata->new2oldnode[i];
                        changed = TRUE;
                        ndeletednodes++;
                        nnodesdeletedneighbourthisround++;
                        break; /* for j, because we already now that i is dominated and deleted i */
                     }
                  }
               } /* end for j */
               
               /* if i is dominated by no other node and thus not deleted, 
                  put it into newnodes, so that it is in the next graph */
               if ( ndeletednodes == 0 || probdata->deletednodes[ndeletednodes-1] != probdata->new2oldnode[i])
               {
                  newnodes[actnewnode] = probdata->new2oldnode[i];
                  actnewnode++;
               }
            }
            /* if i is in the maxClique und was thus not deleted,
               put it into newnodes, so that it is in the next graph */
            else
            {
               newnodes[actnewnode] = probdata->new2oldnode[i];
               actnewnode++;
            }
         } /*end for i */

         /* at least one node was deletet, create new graph ( tclique doesn't support deletion of nodes) */
         if ( changed )
         {
            assert(actnewnode+ndeletednodes == COLORprobGetOriginalNNodes(scip));
            /* create new current graph */
            tcliqueFree(&currgraph);

            if( !tcliqueCreate(&currgraph) )
            {
               SCIPerrorMessage("could not create the clique graph\n");
               return SCIP_ERROR;
            }

            assert(currgraph != NULL);

            if( !tcliqueAddNode(currgraph, actnewnode-1, 0) )
            {
               SCIPerrorMessage("could not add a node to the clique graph\n");
               return SCIP_ERROR;
            }

            for ( i = 0; i < actnewnode; i++ )
            {
               /* get adjacent nodes for node newnodes[i] */
               firstedge = tcliqueGetFirstAdjedge(probdata->oldgraph, newnodes[i]);
               lastedge = tcliqueGetLastAdjedge(probdata->oldgraph, newnodes[i]);
               while ( firstedge <= lastedge )
               {
                  /* try to find a node in newnodes which corresponds 
                     to the node in the old graph, that is the end-node of the edge */
                  for ( j = i+1; j < actnewnode; j++ )
                  {
                     if ( *firstedge == newnodes[j] )
                     {

                        if( !tcliqueAddEdge(currgraph, i, j) )
                        {
                           SCIPerrorMessage("could not add an edge to the clique graph\n");
                           return SCIP_ERROR;
                        }
                        break;
                     }
                  }
                  firstedge++;
               }
            }

            if( !tcliqueFlush(currgraph) )
            {
               SCIPerrorMessage("could not flush the clique graph\n");
               return SCIP_ERROR;
            }

            /* update currnnodes */
            currnnodes = tcliqueGetNNodes(currgraph);

            /* update new2oldnodes */
            for ( i = 0; i < actnewnode; i++ )
            {
               probdata->new2oldnode[i] = newnodes[i];
            }

            /* set the corresponding old node to -1 for all nodes not in the current graph (only for bug-finding) */
            for ( i = actnewnode; i < COLORprobGetOriginalNNodes(scip); i++ )
            {
               probdata->new2oldnode[i] = -1;
            }
         }
      } /* end of loop for finding dominated neighbourhoods */
      
      printf("Round %d of preprocessing:\n", myround);
      printf("   deleted low degree vertices: %d\n", nnodesdeleteddegreethisround);
      printf("   deleted almost cliques:      %d\n", nnodesdeletedneighbourthisround);

   }

   for ( i = ndeletednodes; i < COLORprobGetOriginalNNodes(scip); i++ )
   {
      probdata->deletednodes[i] = -1;
   }

   printf("preprocessing overall deleted vertices: %d\n\n", ndeletednodes);
   /* copy preprocessed graph into problem data */
   probdata->graph = currgraph;

   SCIPfreeBufferArray(scip, &newnodes);
   SCIPfreeBufferArray(scip, &maxcliquenodes);

   return SCIP_OKAY;
}
Esempio n. 12
0
/** constraint parsing method of constraint handler */
static
SCIP_DECL_CONSPARSE(consParseConjunction)
{  /*lint --e{715}*/
   SCIP_CONS** conss;
   int nconss;
   int sconss;
   char* token;
   char* saveptr;
   char* nexttokenstart;
   char* copystr;

   assert(scip != NULL);
   assert(conshdlr != NULL);
   assert(cons != NULL);
   assert(success != NULL);
   assert(str != NULL);
   assert(name != NULL);

   SCIPdebugMessage("parsing conjunction <%s>\n", name);

   *success = TRUE;

   /* allocate memory for constraint in conjunction, initial size is set to 10 */
   nconss = 0;
   sconss = 10;
   SCIP_CALL( SCIPallocBufferArray(scip, &conss, sconss) );
   SCIP_CALL( SCIPduplicateBufferArray(scip, &copystr, str, (int)strlen(str)+1) );

   /* find '(' at the beginning, string should start with 'conjunction(' */
   saveptr = strpbrk(copystr, "("); /*lint !e158*/

   if( saveptr == NULL )
   {
      SCIPdebugMessage("error parsing conjunctive constraint: \"%s\"\n", str);
      *success = FALSE;
      goto TERMINATE;
   }

   /* skip '(' */
   ++saveptr;
   /* remember token start position */
   nexttokenstart = saveptr;

   /* brackets '(' and ')' can exist co we check for them and the constraint delimeter */
   saveptr = strpbrk(saveptr, "(,");

   /* brackets '(' and ')' can exist in the rest of the string so we need to skip them to find the end of the first
    * sub-constraint marked by a ','
    */
   if( saveptr != NULL )
   {
      do
      {
	 int bracketcounter = 0;

	 if( *saveptr == '(' )
	 {
	    do
	    {
	       ++bracketcounter;
	       ++saveptr;

	       /* find last ending bracket */
	       while( bracketcounter > 0 )
	       {
		  saveptr = strpbrk(saveptr, "()");

		  if( saveptr != NULL )
		  {
		     if( *saveptr == '(' )
			++bracketcounter;
		     else
			--bracketcounter;

		     ++saveptr;
		  }
		  else
		  {
		     SCIPdebugMessage("error parsing conjunctive constraint: \"%s\"\n", str);
		     *success = FALSE;
		     goto TERMINATE;
		  }
	       }

	       saveptr = strpbrk(saveptr, "(,");
	    }
	    while( saveptr != NULL && *saveptr == '(' );
	 }

	 /* we found a ',' so the end of the first sub-constraint is determined */
	 if( saveptr != NULL )
	 {
	    assert(*saveptr == ',');

	    /* resize constraint array if necessary */
	    if( nconss == sconss )
	    {
	       sconss = SCIPcalcMemGrowSize(scip, nconss+1);
	       assert(nconss < sconss);

	       SCIP_CALL( SCIPreallocBufferArray(scip, &conss, sconss) );
	    }

	    assert(saveptr > nexttokenstart);

	    /* extract token for parsing */
	    SCIP_CALL( SCIPduplicateBufferArray(scip, &token, nexttokenstart, saveptr - nexttokenstart + 1) );
	    token[saveptr - nexttokenstart] = '\0';

	    SCIPdebugMessage("conjunctive parsing token(constraint): %s\n", token);

	    /* parsing a constraint, part of the conjunction */
	    SCIP_CALL( SCIPparseCons(scip, &(conss[nconss]), token, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, success) );

	    SCIPfreeBufferArray(scip, &token);

	    if( *success )
	       ++nconss;
	    else
	    {
	       SCIPdebugMessage("error parsing conjunctive constraint: \"%s\"\n", str);
	       goto TERMINATE;
	    }
	    /* skip ',' delimeter */
	    ++saveptr;
	    /* remember token start position */
	    nexttokenstart = saveptr;

	    saveptr = strpbrk(saveptr, "(,");
	 }
      }
      while( saveptr != NULL );
   }

   /* find end of conjunction constraint */
   saveptr = strrchr(nexttokenstart, ')');

   if( saveptr == NULL )
   {
      SCIPdebugMessage("error parsing conjunctive constraint: \"%s\"\n", str);
      *success = FALSE;
      goto TERMINATE;
   }
   /* parse last sub-constraint */
   else
   {
      /* resize constraint array if necessary */
      if( nconss == sconss )
      {
	 ++sconss;
	 SCIP_CALL( SCIPreallocBufferArray(scip, &conss, sconss) );
      }

      assert(saveptr > nexttokenstart);

      /* extract token for parsing */
      SCIP_CALL( SCIPduplicateBufferArray(scip, &token, nexttokenstart, saveptr - nexttokenstart + 1) );
      token[saveptr - nexttokenstart] = '\0';

      SCIPdebugMessage("conjunctive parsing token(constraint): %s\n", token);

      /* parsing a constraint, part of the conjunction */
      SCIP_CALL( SCIPparseCons(scip, &(conss[nconss]), token, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, success) );

      if( *success )
	 ++nconss;

      SCIPfreeBufferArray(scip, &token);
   }
   assert(nconss > 0 || !(*success));

   /* if parsing sub-constraints was fine, create the conjunctive constraint */
   if( *success )
   {
      /* create conjunctive constraint */
      SCIP_CALL( SCIPcreateConsConjunction(scip, cons, name, nconss, conss,
	    enforce, check, local, modifiable, dynamic) );
   }

   /* free parsed constraints */
   for( --nconss; nconss >= 0; --nconss )
   {
      SCIP_CALL( SCIPreleaseCons(scip, &conss[nconss]) );
   }

 TERMINATE:
   /* free temporary memory */
   SCIPfreeBufferArray(scip, &copystr);
   SCIPfreeBufferArray(scip, &conss);

   return SCIP_OKAY;
}
Esempio n. 13
0
/** creates and captures an indicator constraint
 *
 *  @note @a binvar is checked to be binary only later. This enables a change of the type in
 *  procedures reading an instance.
 *
 *  @note the constraint gets captured, hence at one point you have to release it using the method {@link releaseCons()}
 */
JNIEXPORT
jlong JNISCIPCONSINDICATOR(createConsIndicator)(
   JNIEnv*               env,                /**< JNI environment variable */
   jobject               jobj,               /**< JNI class pointer */
   jlong                 jscip,              /**< SCIP data structure */
   jstring               jname,              /**< name of constraint */
   jlong                 jbinvar,            /**< binary indicator variable (or NULL) */
   jint                  nvars,              /**< number of variables in the constraint */
   jlongArray            jvars,              /**< array with variables of constraint entries */
   jdoubleArray          jvals,              /**< values of variables in inequality (or NULL) */
   jdouble               rhs,                /**< rhs of the inequality */
   jboolean              jinitial,           /**< should the LP relaxation of constraint be in the initial LP?
                                             *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
   jboolean              jseparate,          /**< should the constraint be separated during LP processing?
                                             *   Usually set to TRUE. */
   jboolean              jenforce,           /**< should the constraint be enforced during node processing?
                                             *   TRUE for model constraints, FALSE for additional, redundant constraints. */
   jboolean              jcheck,             /**< should the constraint be checked for feasibility?
                                             *   TRUE for model constraints, FALSE for additional, redundant constraints. */
   jboolean              jpropagate,         /**< should the constraint be propagated during node processing?
                                             *   Usually set to TRUE. */
   jboolean              jlocal,             /**< is constraint only valid locally?
                                             *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
   jboolean              jdynamic,           /**< is constraint subject to aging?
                                             *   Usually set to FALSE. Set to TRUE for own cuts which
                                             *   are seperated as constraints. */
   jboolean              jremovable,         /**< should the relaxation be removed from the LP due to aging or cleanup?
                                             *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
   jboolean              jstickingatnode     /**< should the constraint always be kept at the node where it was added, even
                                             *   if it may be moved to a more global node?
                                             *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
   )
{
   SCIP* scip;
   SCIP_CONS* cons;
   const char* name;
   SCIP_VAR* binvar;
   SCIP_VAR** vars;
   SCIP_Real* vals;

   /* convert JNI pointer into C pointer */
   scip = (SCIP*) (size_t) jscip;
   assert(scip != NULL);

   /* convert JNI string into C const char* */
   name = (*env)->GetStringUTFChars(env, jname, NULL);
   if( name == NULL )
      SCIPABORT();

   /* convert JNI pointer into C pointer */
   binvar = (SCIP_VAR*) (size_t) jbinvar;

   JNISCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
   JNISCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );

   (*env)->GetLongArrayRegion(env, jvars, 0, nvars, (jlong*)(*vars));
   (*env)->GetDoubleArrayRegion(env, jvals, 0, nvars, (jdouble*)vals);

   JNISCIP_CALL( SCIPcreateConsIndicator(scip, &cons, name, binvar, (int)nvars, vars, vals, (SCIP_Real)rhs,
         (SCIP_Bool) jinitial, (SCIP_Bool) jseparate, (SCIP_Bool) jenforce, (SCIP_Bool) jcheck, (SCIP_Bool) jpropagate,
         (SCIP_Bool) jlocal, (SCIP_Bool) jdynamic, (SCIP_Bool) jremovable, (SCIP_Bool) jstickingatnode) );

   SCIPfreeBufferArray(scip, &vals);
   SCIPfreeBufferArray(scip, &vars);

   (*env)->ReleaseStringUTFChars(env, jname, name);

   return (jlong)(size_t)cons;
}
Esempio n. 14
0
/** creates a cumulative scheduling problem */
SCIP_RETCODE SCIPcreateSchedulingProblem(
   SCIP*                 scip,               /**< SCIP data structure */
   const char*           problemname,        /**< problem name */
   const char**          jobnames,           /**< job names, or NULL */
   const char**          resourcenames,      /**< resource names, or NULL */
   int**                 demands,            /**< demand matrix resource job demand */
   SCIP_DIGRAPH*         precedencegraph,    /**< direct graph to store the precedence conditions */
   int*                  durations,          /**< array to store the processing for each job */
   int*                  capacities,         /**< array to store the different capacities */
   int                   njobs,              /**< number of jobs to be parsed */
   int                   nresources          /**< number of capacities to be parsed */
   )
{
   SCIP_VAR** jobs;
   SCIP_VAR** vars;
   SCIP_VAR* var;

   SCIP_CONS* cons;

   char name[SCIP_MAXSTRLEN];

   int* consdurations;
   int* consdemands;

   int nvars;
   int ubmakespan;
   int i;
   int j;
   int r;

   assert( scip != NULL );
   assert( njobs >= 0 );

   SCIPdebugMessage( "start method SCIPcreateSchedulingSMProblem\n");

   /* create SCIP data structure */
   SCIP_CALL( SCIPcreateProb(scip, problemname, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );


   /* compute a feasible upper bound on the makespan */
   ubmakespan = computeUbmakespan(durations, njobs);
   ubmakespan *= 100;

   /* allocate buffer for jobs and precedence constraints */
   SCIP_CALL( SCIPallocBufferArray(scip, &jobs, njobs) );

   /* create an activity constraint for each activity */
   for( j = 0; j < njobs - 1; ++j ) /* but not for last job which is the makespan (-1) */
   {
      /* construct variable name */
      if( jobnames != NULL )
         (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "start_%s", jobnames[j]);
      else
         (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "start_%d", j);

      /* create integer starting variable */
      SCIP_CALL( SCIPcreateVar(scip, &var, name, 0.0, (SCIP_Real)ubmakespan, 0.0, SCIP_VARTYPE_INTEGER,
            TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );

      SCIP_CALL( SCIPaddVar(scip, var) );
      SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, var) );
      jobs[j] = var;
      SCIP_CALL( SCIPreleaseVar(scip, &var) );
   }

   /* create makespan variable */
   SCIP_CALL( SCIPcreateVar(scip, &var, "makespan", 0.0, (SCIP_Real)ubmakespan, 1.0, SCIP_VARTYPE_INTEGER,
         TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );

   SCIP_CALL( SCIPaddVar(scip, var) );
   SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, var) );

   jobs[njobs-1] = var;
   SCIP_CALL( SCIPreleaseVar(scip, &var) );

   /* precedence constraints */
   for( j = 0; j < njobs - 1; ++j )
   {
      SCIP_VAR* predvar;
      int nsuccessors;

      nsuccessors = SCIPdigraphGetNSuccessors(precedencegraph, j);

      predvar = jobs[j];
      assert(predvar != NULL);

      if( nsuccessors > 0 )
      {
         int* successors;
         void** distances;

         successors = SCIPdigraphGetSuccessors(precedencegraph, j);
         distances = SCIPdigraphGetSuccessorsDatas(precedencegraph, j);

         for( i = 0; i < nsuccessors; ++i )
         {
            SCIP_VAR* succvar;
            int distance;

            succvar = jobs[successors[i]];
            assert(succvar != NULL);

            (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "precedences_(%d,%d)", j, successors[i]);

            distance = (int)(size_t)distances[i];

            if( distance == INT_MAX )
               distance = durations[j];

            SCIP_CALL( SCIPcreateConsVarbound(scip, &cons, name, predvar, succvar, -1.0,
                  -SCIPinfinity(scip), -distance,
                  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
            SCIP_CALL( SCIPaddCons(scip, cons) );
            SCIP_CALL( SCIPreleaseCons(scip, &cons) );
         }
      }
      else
      {
         /* add precedence constraints for those jobs without successor */
         (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "precedences_(%d,%d)", j, njobs);

         SCIP_CALL( SCIPcreateConsVarbound(scip, &cons, name, predvar, jobs[njobs-1], -1.0,
               -SCIPinfinity(scip), -durations[j],
               TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
         SCIP_CALL( SCIPaddCons(scip, cons) );
         SCIP_CALL( SCIPreleaseCons(scip, &cons) );
      }
   }

   SCIP_CALL( SCIPallocBufferArray(scip, &vars, njobs) );
   SCIP_CALL( SCIPallocBufferArray(scip, &consdemands, njobs) );
   SCIP_CALL( SCIPallocBufferArray(scip, &consdurations, njobs) );

   /* create resource constraints */
   for( r = 0; r < nresources; ++r )
   {
      nvars = 0;
      for( j = 0; j < njobs; ++j ) /* also makespan constraint! */
      {
         if( demands[j][r] > 0 )
         {
            vars[nvars] = jobs[j];
            consdemands[nvars] = demands[j][r];
            consdurations[nvars] = durations[j];
            nvars++;
         }
      }

      if( nvars > 0 )
      {
         /* construct constraint name */
         if( resourcenames != NULL )
            (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "R%s", resourcenames[r]);
         else
            (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "R%d", r);

         SCIP_CALL( SCIPcreateConsCumulative(scip, &cons, name,
               nvars, vars, consdurations, consdemands, capacities[r],
               TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
         SCIP_CALL( SCIPaddCons(scip, cons) );
         SCIP_CALL( SCIPreleaseCons(scip, &cons) );
      }
   }

   /* initialize the problem specific heuristic */
   SCIP_CALL( SCIPinitializeHeurListScheduling(scip, precedencegraph, jobs,
         durations, demands, capacities, njobs, nresources) );

   /* free buffer array */
   SCIPfreeBufferArray(scip, &consdurations);
   SCIPfreeBufferArray(scip, &consdemands);
   SCIPfreeBufferArray(scip, &vars);
   SCIPfreeBufferArray(scip, &jobs);

   return SCIP_OKAY;
}
Esempio n. 15
0
/** prints given linear constraint information in PPM format to file stream */
static
SCIP_RETCODE printLinearCons(
   SCIP*                 scip,               /**< SCIP data structure */
   FILE*                 file,               /**< output file (or NULL for standard output) */
   SCIP_READERDATA*      readerdata,         /**< information for reader */
   SCIP_VAR**            vars,               /**< array of variables */
   SCIP_Real*            vals,               /**< array of coefficients values (or NULL if all coefficient values are 1) */
   int                   nvars,              /**< number of variables */
   int                   ncompletevars,      /**< number of variables in whole problem */
   SCIP_Bool             transformed,        /**< transformed constraint? */
   SCIP_Real*            maxcoef,            /**< maximal coefficient */
   SCIP_Bool             printbool           /**< print row or calculate maximum coefficient */
   )
{
   int v;
   SCIP_VAR** activevars;
   SCIP_Real* activevals;
   int nactivevars;
   SCIP_Real activeconstant = 0.0;

   assert( scip != NULL );
   assert( vars != NULL );
   assert( nvars > 0 );
   assert( readerdata != NULL );

   /* duplicate variable and value array */
   nactivevars = nvars;
   SCIP_CALL( SCIPduplicateBufferArray(scip, &activevars, vars, nactivevars ) );
   if( vals != NULL )
   {
      SCIP_CALL( SCIPduplicateBufferArray(scip, &activevals, vals, nactivevars ) );
   }
   else
   {
      SCIP_CALL( SCIPallocBufferArray(scip, &activevals, nactivevars) );

      for( v = 0; v < nactivevars; ++v )
         activevals[v] = 1.0;
   }

   /* retransform given variables to active variables */
   SCIP_CALL( getActiveVariables(scip, activevars, activevals, &nactivevars, &activeconstant, transformed) );

   if(!readerdata->rgb_relativ)
   {
      if(!printbool)
         for(v = 0; v < nactivevars; ++v)
         {
            if( REALABS(activevals[v]) > *maxcoef)
               *maxcoef = REALABS(activevals[v]);
         }
      else
      {
         assert (*maxcoef > 0);
         /* print constraint */
         printRow(scip, file, readerdata, activevars, activevals, nactivevars, ncompletevars, *maxcoef);
      }
   }
   else
   {
      /* print constraint */
      printRow(scip, file, readerdata, activevars, activevals, nactivevars, ncompletevars, *maxcoef);
   }

   /* free buffer arrays */
   SCIPfreeBufferArray(scip, &activevars);
   SCIPfreeBufferArray(scip, &activevals);

   return SCIP_OKAY;
}
Esempio n. 16
0
static
SCIP_DECL_BRANCHEXECPS(branchExecpsMyfullstrong)
{  /*lint --e{715}*/

	SCIP_PROBDATA*	probdata;
   SCIP_VAR**	cands;
   int	ncands;
	SCIP_NODE*	childnode_0;		/* z_j = 0 */
	SCIP_NODE*	childnode_1;		/* z_j = 1 */

	/* probdata */
	int	p;
	int	ndep;
	SCIP_VAR**	var_z;		/* [p] 01 variables */

	/* "_" means the matrix for blas */
	SCIP_Real*	orig_Q_;		/* [p*p] <- (X^t) X */
	SCIP_Real*	orig_q;		/* [p]   <- (X^t) y */
	SCIP_Real	r;

	int*	Mdep;					/* [ndep] */
	int*	groupX;				/* [ndep*p] */

	int	dim;
	SCIP_Real	RSS;			/* residual sum of square */
	SCIP_Real	RSS_new;
	SCIP_Real*	a;				/* [dim] */

	int	ublb;
	int	*Branchz;			/* [3*p] */
	int	*Branchz_new;		/* [3*p] */

	SCIP_Real*	Q_;	/* sub matrix of orig_Q_ */
	SCIP_Real*	Xy;	/* sub vector of orig_q */ 

	int*	list;			/* list of candidate variables */

	int	i,j,t,memo,ct;
	int	ind;
	int	dpv;

#if MYPARA_LOG
	printf("[myfullstrong brnaching]");
	Longline();
#endif

   /* get branching rule data */
	/*
   SCIP_BRANCHRULEDATA* branchruledata;
   branchruledata = SCIPbranchruleGetData(branchrule);
   assert(branchruledata != NULL);
	*/
	
	/* get problem data*/
	probdata = SCIPgetProbData(scip);
   assert(probdata != NULL);

	p	=	SCIPprobdataGetNexvars(probdata);
	ndep	=	SCIPprobdataGetNdep(probdata);

	orig_Q_	=	SCIPprobdataGetQ(probdata);
	orig_q	=	SCIPprobdataGetq(probdata);
	r	=	SCIPprobdataGetr(probdata);
	var_z		=	SCIPprobdataGetVars_z(probdata);

	if( ndep ){
		Mdep		=	SCIPprobdataGetMdep(probdata);
		groupX	=	SCIPprobdataGetgroupX(probdata);
	}else{
		Mdep		=	NULL;
		groupX	=	NULL;
	}

	/* alloc */
	SCIP_CALL( SCIPallocBufferArray(scip, &list, p));
	SCIP_CALL( SCIPallocBufferArray(scip, &Branchz, 3*p));
	SCIP_CALL( SCIPallocBufferArray(scip, &Branchz_new, 3*p));

	
	GenerateZeroVecInt( p, list);
	GenerateZeroVecInt( 3*p, Branchz);

   /* get pseudo candidates (non-fixed integer variables) */
   SCIP_CALL( SCIPgetPseudoBranchCands(scip, &cands, NULL, &ncands) );
	
	for(i=0; i<ncands; i++){
		for(j=0; j<p; j++){
			if( cands[i]==var_z[j] ){
				list[j] = 1;
				break;	
			}
		}
	}

#if MYPARA_LOG
	printf("list:");
	printintv( p, list);
#endif

	/* get branching info */
	for(i=0; i<p; ++i){
		ublb					=	SCIPround(scip, SCIPcomputeVarUbLocal(scip, var_z[i]) 
								+	SCIPcomputeVarLbLocal(scip, var_z[i]));
		*(Branchz+(ublb*p)+i) 	= 	1;
	}

#if MYPARA_LOG
	for(i=0; i<3; i++){
		for(j=0; j<p; j++){
			printf("%d, ", *(Branchz+(i*p)+j));
		}
		newline();
	}
#endif
	
	RSS = -1.0;
	ind = -1;

	for(i=0; i<p; i++){

		/* copy */
		for(j=0; j<(3*p); j++){
			Branchz_new[j] = Branchz[j];
		}

		/* 
		 * solve 
		 *   Q a = Xy
		 */

		if( list[i] == 1 ){

			Branchz_new[i] = 1;
			Branchz_new[p+i] = 0;
			
			if( ndep ){
				for(t=0; t<ndep; t++){
					memo = -1; 
					for(j=0; j<p; j++){
						if( *(groupX+(t*p)+j)==1 ){
							if( Branchz_new[j]==1 ) break;
							if( Branchz_new[p+j]==1 ) memo=j;
							if( j==Mdep[t] ){
								if( memo==-1 ){
									printf("error in branch_myfullstrong.c\n");
									stop();
								}
								*(Branchz_new+p+memo) = 0;
								*(Branchz_new+memo) = 1;
								break;
							}
						}
					}
				}
			}

			dim = p - sumint( &Branchz_new[0], p);
	
			/* alloc */
			SCIP_CALL( SCIPallocBufferArray( scip, &a, dim));
			SCIP_CALL( SCIPallocBufferArray( scip, &Q_, dim*dim));
			SCIP_CALL( SCIPallocBufferArray( scip, &Xy, dim));

			/* generate Q and Xy */
			/* Q */
			ct = 0;
			for(j=0; j<p; j++){
				if( (Branchz_new[j]==0) && (j != i) ){
					for(t=0; t<p; t++){
						if( (Branchz_new[t]==0) && (t != i ) ){
							Q_[ct++] = mat_( orig_Q_, p, j, t);
						}
					}
				}
			}

			if( ct != (dim*dim) ){
				printf("error in branch_myfullstrong.c\n");
				stop();
			}

			/* Xy */
			ct = 0;
			for(j=0; j<p; j++){
				if( (Branchz_new[j]==0) && (j != i) ){
					Xy[ct++] = orig_q[j];
				}
			}

			if( ct != dim ){
				printf("error in branch_myfullstrong.c\n");
				stop();
			}

			dpv = _dposv_( Q_, Xy, dim, a);

			if( dpv == 0 ){
				/* test */
				RSS_new = RSSvalue( dim, a, Xy, r);
				if( RSS_new > RSS ){
					RSS = RSS_new;
					ind = i;
				}
#if MYPARA_LOG
				printf("%d: RSS = %f\n", i, RSS_new);
#endif
			}

			/* free */
			SCIPfreeBufferArray(scip, &Q_);
			SCIPfreeBufferArray(scip, &Xy);
			SCIPfreeBufferArray(scip, &a);

		 }
	}

#if MYPARA_LOG
	printf("max->%dth var. \n", ind);
#endif

	if( ind == -1 ){
		/* free */
		SCIPfreeBufferArray(scip, &list);
		SCIPfreeBufferArray(scip, &Branchz);
		SCIPfreeBufferArray(scip, &Branchz_new);

   	*result = SCIP_DIDNOTRUN;
		return SCIP_OKAY;
	}

	SCIP_CALL( SCIPbranchVar( scip, var_z[ind], &childnode_0, NULL, &childnode_1));

	/* free */
	SCIPfreeBufferArray(scip, &list);
	SCIPfreeBufferArray(scip, &Branchz);
	SCIPfreeBufferArray(scip, &Branchz_new);

   *result = SCIP_BRANCHED;

   return SCIP_OKAY;
}
Esempio n. 17
0
/** writes problem to file */
SCIP_RETCODE SCIPwritePpm(
   SCIP*                 scip,               /**< SCIP data structure */
   FILE*                 file,               /**< output file, or NULL if standard output should be used */
   const char*           name,               /**< problem name */
   SCIP_READERDATA*      readerdata,         /**< information for reader */
   SCIP_Bool             transformed,        /**< TRUE iff problem is the transformed problem */
   SCIP_VAR**            vars,               /**< array with active variables ordered binary, integer, implicit, continuous */
   int                   nvars,              /**< number of active variables in the problem */
   SCIP_CONS**           conss,              /**< array with constraints of the problem */
   int                   nconss,             /**< number of constraints in the problem */
   SCIP_RESULT*          result              /**< pointer to store the result of the file writing call */
   )
{  /*lint --e{715}*/
   int c;
   int v;
   int i;

   int linecnt;
   char linebuffer[PPM_MAX_LINELEN];

   SCIP_CONSHDLR* conshdlr;
   const char* conshdlrname;
   SCIP_CONS* cons;

   SCIP_VAR** consvars;
   SCIP_Real* consvals;
   int nconsvars;
   int i_max = 1;
   SCIP_Real maxcoef = 0;
   SCIP_Bool printbool = FALSE;

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

   /* print statistics as comment to file */
   if(readerdata->rgb_ascii)
      SCIPinfoMessage(scip, file, "P6\n");
   else
      SCIPinfoMessage(scip, file, "P3\n");
   SCIPinfoMessage(scip, file, "# %s\n", name);
   SCIPinfoMessage(scip, file, "%d %d\n", nvars, nconss);
   SCIPinfoMessage(scip, file, "255\n");

   clearLine(linebuffer, &linecnt);

   if(!(readerdata->rgb_relativ))
   {
      i_max = 2;
   }

   for(i = 0; i < i_max; ++i)
   {
      if(i)
      {
         printbool = TRUE;
         SCIPdebugPrintf("Maximal coefficient = %g\n", maxcoef);
      }


     for(c = 0; c < nconss; ++c)
     {
        cons = conss[c];
        assert( cons != NULL);

        /* in case the transformed is written only constraint are posted which are enabled in the current node */
        assert(!transformed || SCIPconsIsEnabled(cons));

        conshdlr = SCIPconsGetHdlr(cons);
        assert( conshdlr != NULL );

        conshdlrname = SCIPconshdlrGetName(conshdlr);
        assert( transformed == SCIPconsIsTransformed(cons) );

        if( strcmp(conshdlrname, "linear") == 0 )
        {
           consvars = SCIPgetVarsLinear(scip, cons);
           nconsvars = SCIPgetNVarsLinear(scip, cons);
           assert( consvars != NULL || nconsvars == 0 );

           if( nconsvars > 0 )
           {
              SCIP_CALL( printLinearCons(scip, file, readerdata, consvars, SCIPgetValsLinear(scip, cons),
                    nconsvars, nvars, transformed, &maxcoef, printbool) );
           }
        }
        else if( strcmp(conshdlrname, "setppc") == 0 )
        {
           consvars = SCIPgetVarsSetppc(scip, cons);
           nconsvars = SCIPgetNVarsSetppc(scip, cons);
           assert( consvars != NULL || nconsvars == 0 );

           if( nconsvars > 0 )
           {
              SCIP_CALL( printLinearCons(scip, file, readerdata, consvars, NULL,
                    nconsvars, nvars, transformed, &maxcoef, printbool) );
           }
        }
        else if( strcmp(conshdlrname, "logicor") == 0 )
        {
           consvars = SCIPgetVarsLogicor(scip, cons);
           nconsvars = SCIPgetNVarsLogicor(scip, cons);
           assert( consvars != NULL || nconsvars == 0 );

           if( nconsvars > 0 )
           {
              SCIP_CALL( printLinearCons(scip, file, readerdata, consvars, NULL,
                    nconsvars, nvars, transformed, &maxcoef, printbool) );
           }
        }
        else if( strcmp(conshdlrname, "knapsack") == 0 )
        {
           SCIP_Longint* weights;

           consvars = SCIPgetVarsKnapsack(scip, cons);
           nconsvars = SCIPgetNVarsKnapsack(scip, cons);
           assert( consvars != NULL || nconsvars == 0 );

           /* copy Longint array to SCIP_Real array */
           weights = SCIPgetWeightsKnapsack(scip, cons);
           SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
           for( v = 0; v < nconsvars; ++v )
              consvals[v] = (SCIP_Real)weights[v];

           if( nconsvars > 0 )
           {
              SCIP_CALL( printLinearCons(scip, file, readerdata, consvars, consvals, nconsvars, nvars, transformed, &maxcoef, printbool) );
           }

           SCIPfreeBufferArray(scip, &consvals);
        }
        else if( strcmp(conshdlrname, "varbound") == 0 )
        {
           SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
           SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );

           consvars[0] = SCIPgetVarVarbound(scip, cons);
           consvars[1] = SCIPgetVbdvarVarbound(scip, cons);

           consvals[0] = 1.0;
           consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);

           SCIP_CALL( printLinearCons(scip, file, readerdata, consvars, consvals, 2, nvars, transformed, &maxcoef, printbool) );

           SCIPfreeBufferArray(scip, &consvars);
           SCIPfreeBufferArray(scip, &consvals);
        }
        else
        {
           SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
           SCIPinfoMessage(scip, file, "\\ ");
           SCIP_CALL( SCIPprintCons(scip, cons, file) );
           SCIPinfoMessage(scip, file, ";\n");
        }
     }
   }

   *result = SCIP_SUCCESS;

   return SCIP_OKAY;
}
Esempio n. 18
0
/** arbitrary primal solution separation method of separator */
static
SCIP_DECL_SEPAEXECSOL(sepaExecsolImpliedbounds)
{  /*lint --e{715}*/
   SCIP_VAR** vars;
   SCIP_VAR** fracvars;
   SCIP_Real* solvals;
   SCIP_Real* fracvals;
   SCIP_Bool cutoff;
   int nvars;
   int nbinvars;
   int nfracs;
   int ncuts;
   int i;

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

   *result = SCIP_DIDNOTRUN;

   /* gets active problem variables */
   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, NULL, NULL, NULL) );
   if( nbinvars == 0 )
      return SCIP_OKAY;

   /* get solution values for all variables */
   SCIP_CALL( SCIPallocBufferArray(scip, &solvals, nvars) );
   SCIP_CALL( SCIPgetSolVals(scip, sol, nvars, vars, solvals) );

   /* get binary problem variables that are fractional in given solution */
   SCIP_CALL( SCIPallocBufferArray(scip, &fracvars, nbinvars) );
   SCIP_CALL( SCIPallocBufferArray(scip, &fracvals, nbinvars) );
   nfracs = 0;
   for( i = 0; i < nbinvars; ++i )
   {
      if( !SCIPisFeasIntegral(scip, solvals[i]) )
      {
         fracvars[nfracs] = vars[i];
         fracvals[nfracs] = solvals[i];
         nfracs++;
      }
   }

   /* call the cut separation */
   ncuts = 0;
   cutoff = FALSE;

   if( nfracs > 0 )
   {
      SCIP_CALL( separateCuts(scip, sepa, sol, solvals, fracvars, fracvals, nfracs, &cutoff, &ncuts) );
   }

   /* adjust result code */
   if ( cutoff )
      *result = SCIP_CUTOFF;
   else if ( ncuts > 0 )
      *result = SCIP_SEPARATED;
   else
      *result = SCIP_DIDNOTFIND;

   /* free temporary memory */
   SCIPfreeBufferArray(scip, &fracvals);
   SCIPfreeBufferArray(scip, &fracvars);
   SCIPfreeBufferArray(scip, &solvals);

   return SCIP_OKAY;
}
Esempio n. 19
0
/** execution method of primal heuristic */
static
SCIP_DECL_HEUREXEC(heurExecLocalbranching)
{  /*lint --e{715}*/
   SCIP_Longint maxnnodes;                   /* maximum number of subnodes                            */
   SCIP_Longint nsubnodes;                   /* nodelimit for subscip                                 */

   SCIP_HEURDATA* heurdata;
   SCIP* subscip;                            /* the subproblem created by localbranching              */
   SCIP_VAR** subvars;                       /* subproblem's variables                                */
   SCIP_SOL* bestsol;                        /* best solution so far                                  */
   SCIP_EVENTHDLR*       eventhdlr;          /* event handler for LP events                     */

   SCIP_Real timelimit;                      /* timelimit for subscip (equals remaining time of scip) */
   SCIP_Real cutoff;                         /* objective cutoff for the subproblem                   */
   SCIP_Real upperbound;
   SCIP_Real memorylimit;

   SCIP_HASHMAP* varmapfw;                   /* mapping of SCIP variables to sub-SCIP variables */
   SCIP_VAR** vars;

   int nvars;
   int i;

   SCIP_Bool success;

   SCIP_RETCODE retcode;

   assert(heur != NULL);
   assert(scip != NULL);
   assert(result != NULL);

   *result = SCIP_DIDNOTRUN;

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

   /* there should be enough binary variables that a local branching constraint makes sense */
   if( SCIPgetNBinVars(scip) < 2*heurdata->neighborhoodsize )
      return SCIP_OKAY;

   *result = SCIP_DELAYED;

   /* only call heuristic, if an IP solution is at hand */
   if( SCIPgetNSols(scip) <= 0  )
      return SCIP_OKAY;

   bestsol = SCIPgetBestSol(scip);
   assert(bestsol != NULL);

   /* only call heuristic, if the best solution comes from transformed problem */
   if( SCIPsolIsOriginal(bestsol) )
      return SCIP_OKAY;

   /* only call heuristic, if enough nodes were processed since last incumbent */
   if( SCIPgetNNodes(scip) - SCIPgetSolNodenum(scip, bestsol)  < heurdata->nwaitingnodes)
      return SCIP_OKAY;

   /* only call heuristic, if the best solution does not come from trivial heuristic */
   if( SCIPsolGetHeur(bestsol) != NULL && strcmp(SCIPheurGetName(SCIPsolGetHeur(bestsol)), "trivial") == 0 )
      return SCIP_OKAY;

   /* reset neighborhood and minnodes, if new solution was found */
   if( heurdata->lastsol != bestsol )
   {
      heurdata->curneighborhoodsize = heurdata->neighborhoodsize;
      heurdata->curminnodes = heurdata->minnodes;
      heurdata->emptyneighborhoodsize = 0;
      heurdata->callstatus = EXECUTE;
      heurdata->lastsol = bestsol;
   }

   /* if no new solution was found and local branching also seems to fail, just keep on waiting */
   if( heurdata->callstatus == WAITFORNEWSOL )
      return SCIP_OKAY;

   *result = SCIP_DIDNOTRUN;

   /* calculate the maximal number of branching nodes until heuristic is aborted */
   maxnnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));

   /* reward local branching if it succeeded often */
   maxnnodes = (SCIP_Longint)(maxnnodes * (1.0 + 2.0*(SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur)+1.0)));
   maxnnodes -= 100 * SCIPheurGetNCalls(heur);  /* count the setup costs for the sub-MIP as 100 nodes */
   maxnnodes += heurdata->nodesofs;

   /* determine the node limit for the current process */
   nsubnodes = maxnnodes - heurdata->usednodes;
   nsubnodes = MIN(nsubnodes, heurdata->maxnodes);

   /* check whether we have enough nodes left to call sub problem solving */
   if( nsubnodes < heurdata->curminnodes )
      return SCIP_OKAY;

   if( SCIPisStopped(scip) )
      return SCIP_OKAY;

   *result = SCIP_DIDNOTFIND;

   SCIPdebugMessage("running localbranching heuristic ...\n");

   /* get the data of the variables and the best solution */
   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );

   /* initializing the subproblem */
   SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
   SCIP_CALL( SCIPcreate(&subscip) );

   /* create the variable mapping hash map */
   SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), SCIPcalcHashtableSize(5 * nvars)) );
   success = FALSE;
   eventhdlr = NULL;

   if( heurdata->uselprows )
   {
      char probname[SCIP_MAXSTRLEN];

      /* copy all plugins */
      SCIP_CALL( SCIPincludeDefaultPlugins(subscip) );

      /* get name of the original problem and add the string "_localbranchsub" */
      (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_localbranchsub", SCIPgetProbName(scip));

      /* create the subproblem */
      SCIP_CALL( SCIPcreateProb(subscip, probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );

      /* copy all variables */
      SCIP_CALL( SCIPcopyVars(scip, subscip, varmapfw, NULL, TRUE) );
   }
   else
   {
      SCIP_CALL( SCIPcopy(scip, subscip, varmapfw, NULL, "localbranchsub", TRUE, FALSE, TRUE, &success) );

      if( heurdata->copycuts )
      {
         /* copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
         SCIP_CALL( SCIPcopyCuts(scip, subscip, varmapfw, NULL, TRUE, NULL) );
      }

      /* create event handler for LP events */
      SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecLocalbranching, NULL) );
      if( eventhdlr == NULL )
      {
         SCIPerrorMessage("event handler for "HEUR_NAME" heuristic not found.\n");
         return SCIP_PLUGINNOTFOUND;
      }
   }
   SCIPdebugMessage("Copying the plugins was %ssuccessful.\n", success ? "" : "not ");

   for (i = 0; i < nvars; ++i)
      subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);

   /* free hash map */
   SCIPhashmapFree(&varmapfw);

   /* if the subproblem could not be created, free memory and return */
   if( !success )
   {
      *result = SCIP_DIDNOTRUN;
      goto TERMINATE;
   }

   /* do not abort subproblem on CTRL-C */
   SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );

#ifndef SCIP_DEBUG
   /* disable output to console */
   SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
#endif

   /* check whether there is enough time and memory left */
   SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
   if( !SCIPisInfinity(scip, timelimit) )
      timelimit -= SCIPgetSolvingTime(scip);
   SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );

   /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
   if( !SCIPisInfinity(scip, memorylimit) )
   {
      memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
      memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
   }

   /* abort if no time is left or not enough memory to create a copy of SCIP, including external memory usage */
   if( timelimit <= 0.0 || memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0 )
      goto TERMINATE;

   /* set limits for the subproblem */
   heurdata->nodelimit = nsubnodes;
   SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nsubnodes) );
   SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", MAX(10, nsubnodes/10)) );
   SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", 3) );
   SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
   SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );

   /* forbid recursive call of heuristics and separators solving subMIPs */
   SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );

   /* disable cutting plane separation */
   SCIP_CALL( SCIPsetSeparating(subscip, SCIP_PARAMSETTING_OFF, TRUE) );

   /* disable expensive presolving */
   SCIP_CALL( SCIPsetPresolving(subscip, SCIP_PARAMSETTING_FAST, TRUE) );

   /* use best estimate node selection */
   if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
   {
      SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
   }

   /* use inference branching */
   if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
   {
      SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
   }

   /* disable conflict analysis */
   if( !SCIPisParamFixed(subscip, "conflict/useprop") )
   {
      SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useprop", FALSE) );
   }
   if( !SCIPisParamFixed(subscip, "conflict/useinflp") )
   {
      SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useinflp", FALSE) );
   }
   if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
   {
      SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useboundlp", FALSE) );
   }
   if( !SCIPisParamFixed(subscip, "conflict/usesb") )
   {
      SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/usesb", FALSE) );
   }
   if( !SCIPisParamFixed(subscip, "conflict/usepseudo") )
   {
      SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/usepseudo", FALSE) );
   }

   /* employ a limit on the number of enforcement rounds in the quadratic constraint handler; this fixes the issue that
    * sometimes the quadratic constraint handler needs hundreds or thousands of enforcement rounds to determine the
    * feasibility status of a single node without fractional branching candidates by separation (namely for uflquad
    * instances); however, the solution status of the sub-SCIP might get corrupted by this; hence no deductions shall be
    * made for the original SCIP
    */
   if( SCIPfindConshdlr(subscip, "quadratic") != NULL && !SCIPisParamFixed(subscip, "constraints/quadratic/enfolplimit") )
   {
      SCIP_CALL( SCIPsetIntParam(subscip, "constraints/quadratic/enfolplimit", 500) );
   }

   /* copy the original problem and add the local branching constraint */
   if( heurdata->uselprows )
   {
      SCIP_CALL( createSubproblem(scip, subscip, subvars) );
   }
   SCIP_CALL( addLocalBranchingConstraint(scip, subscip, subvars, heurdata) );

   /* add an objective cutoff */
   cutoff = SCIPinfinity(scip);
   assert( !SCIPisInfinity(scip,SCIPgetUpperbound(scip)) );

   upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
   if( !SCIPisInfinity(scip,-1.0*SCIPgetLowerbound(scip)) )
   {
      cutoff = (1-heurdata->minimprove)*SCIPgetUpperbound(scip) + heurdata->minimprove*SCIPgetLowerbound(scip);
   }
   else
   {
      if( SCIPgetUpperbound ( scip ) >= 0 )
         cutoff = ( 1 - heurdata->minimprove ) * SCIPgetUpperbound ( scip );
      else
         cutoff = ( 1 + heurdata->minimprove ) * SCIPgetUpperbound ( scip );
   }
   cutoff = MIN(upperbound, cutoff );
   SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );

   /* catch LP events of sub-SCIP */
   if( !heurdata->uselprows )
   {
      assert(eventhdlr != NULL);

      SCIP_CALL( SCIPtransformProb(subscip) );
      SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, NULL) );
   }

   /* solve the subproblem */
   SCIPdebugMessage("solving local branching subproblem with neighborhoodsize %d and maxnodes %"SCIP_LONGINT_FORMAT"\n",
      heurdata->curneighborhoodsize, nsubnodes);
   retcode = SCIPsolve(subscip);

   /* drop LP events of sub-SCIP */
   if( !heurdata->uselprows )
   {
      assert(eventhdlr != NULL);

      SCIP_CALL( SCIPdropEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, -1) );
   }

   /* Errors in solving the subproblem should not kill the overall solving process
    * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    */
   if( retcode != SCIP_OKAY )
   {
#ifndef NDEBUG
      SCIP_CALL( retcode );
#endif
      SCIPwarningMessage(scip, "Error while solving subproblem in local branching heuristic; sub-SCIP terminated with code <%d>\n",retcode);
   }

   /* print solving statistics of subproblem if we are in SCIP's debug mode */
   SCIPdebug( SCIP_CALL( SCIPprintStatistics(subscip, NULL) ) );

   heurdata->usednodes += SCIPgetNNodes(subscip);
   SCIPdebugMessage("local branching used %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT" nodes\n",
      SCIPgetNNodes(subscip), nsubnodes);

   /* check, whether a solution was found */
   if( SCIPgetNSols(subscip) > 0 )
   {
      SCIP_SOL** subsols;
      int nsubsols;

      /* check, whether a solution was found;
       * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted
       */
      nsubsols = SCIPgetNSols(subscip);
      subsols = SCIPgetSols(subscip);
      success = FALSE;
      for( i = 0; i < nsubsols && !success; ++i )
      {
         SCIP_CALL( createNewSol(scip, subscip, subvars, heur, subsols[i], &success) );
      }
      if( success )
      {
         SCIPdebugMessage("-> accepted solution of value %g\n", SCIPgetSolOrigObj(subscip, subsols[i]));
         *result = SCIP_FOUNDSOL;
      }
   }

   /* check the status of the sub-MIP */
   switch( SCIPgetStatus(subscip) )
   {
   case SCIP_STATUS_OPTIMAL:
   case SCIP_STATUS_BESTSOLLIMIT:
      heurdata->callstatus = WAITFORNEWSOL; /* new solution will immediately be installed at next call */
      SCIPdebugMessage(" -> found new solution\n");
      break;

   case SCIP_STATUS_NODELIMIT:
   case SCIP_STATUS_STALLNODELIMIT:
   case SCIP_STATUS_TOTALNODELIMIT:
      heurdata->callstatus = EXECUTE;
      heurdata->curneighborhoodsize = (heurdata->emptyneighborhoodsize + heurdata->curneighborhoodsize)/2;
      heurdata->curminnodes *= 2;
      SCIPdebugMessage(" -> node limit reached: reduced neighborhood to %d, increased minnodes to %d\n",
         heurdata->curneighborhoodsize, heurdata->curminnodes);
      if( heurdata->curneighborhoodsize <= heurdata->emptyneighborhoodsize )
      {
         heurdata->callstatus = WAITFORNEWSOL;
         SCIPdebugMessage(" -> new neighborhood was already proven to be empty: wait for new solution\n");
      }
      break;

   case SCIP_STATUS_INFEASIBLE:
   case SCIP_STATUS_INFORUNBD:
      heurdata->emptyneighborhoodsize = heurdata->curneighborhoodsize;
      heurdata->curneighborhoodsize += heurdata->curneighborhoodsize/2;
      heurdata->curneighborhoodsize = MAX(heurdata->curneighborhoodsize, heurdata->emptyneighborhoodsize + 2);
      heurdata->callstatus = EXECUTE;
      SCIPdebugMessage(" -> neighborhood is empty: increased neighborhood to %d\n", heurdata->curneighborhoodsize);
      break;

   case SCIP_STATUS_UNKNOWN:
   case SCIP_STATUS_USERINTERRUPT:
   case SCIP_STATUS_TIMELIMIT:
   case SCIP_STATUS_MEMLIMIT:
   case SCIP_STATUS_GAPLIMIT:
   case SCIP_STATUS_SOLLIMIT:
   case SCIP_STATUS_UNBOUNDED:
   default:
      heurdata->callstatus = WAITFORNEWSOL;
      SCIPdebugMessage(" -> unexpected sub-MIP status <%d>: waiting for new solution\n", SCIPgetStatus(subscip));
      break;
   }

 TERMINATE:
   /* free subproblem */
   SCIPfreeBufferArray(scip, &subvars);
   SCIP_CALL( SCIPfree(&subscip) );

   return SCIP_OKAY;
}
/** LP solution separation method of separator */
static
SCIP_DECL_SEPAEXECLP(sepaExeclpRapidlearning)
{/*lint --e{715}*/
   SCIP* subscip;                            /* the subproblem created by rapid learning       */
   SCIP_SEPADATA* sepadata;                  /* separator's private data                       */

   SCIP_VAR** vars;                          /* original problem's variables                   */
   SCIP_VAR** subvars;                       /* subproblem's variables                         */
   SCIP_HASHMAP* varmapfw;                   /* mapping of SCIP variables to sub-SCIP variables */    
   SCIP_HASHMAP* varmapbw;                   /* mapping of sub-SCIP variables to SCIP variables */

   SCIP_CONSHDLR** conshdlrs;                /* array of constraint handler's that might that might obtain conflicts */
   int* oldnconss;                           /* number of constraints without rapid learning conflicts               */

   SCIP_Longint nodelimit;                   /* node limit for the subproblem                  */
   SCIP_Real timelimit;                      /* time limit for the subproblem                  */
   SCIP_Real memorylimit;                    /* memory limit for the subproblem                */

   int nconshdlrs;                           /* size of conshdlr and oldnconss array                      */
   int nfixedvars;                           /* number of variables that could be fixed by rapid learning */
   int nvars;                                /* number of variables                                       */           
   int restartnum;                           /* maximal number of conflicts that should be created        */
   int i;                                    /* counter                                                   */

   SCIP_Bool success;                        /* was problem creation / copying constraint successful? */
   SCIP_RETCODE retcode;                     /* used for catching sub-SCIP errors in debug mode */

   int nconflicts;                          /* statistic: number of conflicts applied         */
   int nbdchgs;                             /* statistic: number of bound changes applied     */
   int n1startinfers;                       /* statistic: number of one side infer values     */
   int n2startinfers;                       /* statistic: number of both side infer values    */

   SCIP_Bool soladded;                      /* statistic: was a new incumbent found?          */
   SCIP_Bool dualboundchg;                  /* statistic: was a new dual bound found?         */
   SCIP_Bool disabledualreductions;         /* TRUE, if dual reductions in sub-SCIP are not valid for original SCIP,
                                             * e.g., because a constraint could not be copied or a primal solution
                                             * could not be copied back 
                                             */

   int ndiscvars;

   soladded = FALSE;

   assert(sepa != NULL);
   assert(scip != NULL);
   assert(result != NULL);

   *result = SCIP_DIDNOTRUN;
   
   ndiscvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip)+SCIPgetNImplVars(scip);

   /* only run when still not fixed binary variables exists */
   if( ndiscvars == 0 )
      return SCIP_OKAY;

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

   /* only run for integer programs */
   if( !sepadata->contvars && ndiscvars != SCIPgetNVars(scip) )
      return SCIP_OKAY;

   /* only run if there are few enough continuous variables */
   if( sepadata->contvars && SCIPgetNContVars(scip) > sepadata->contvarsquot * SCIPgetNVars(scip) )
      return SCIP_OKAY;

   /* do not run if pricers are present */
   if( SCIPgetNActivePricers(scip) > 0 )
      return SCIP_OKAY;

   /* if the separator should be exclusive to the root node, this prevents multiple calls due to restarts */
   if(  SCIPsepaGetFreq(sepa) == 0 && SCIPsepaGetNCalls(sepa) > 0)
      return SCIP_OKAY;

   /* call separator at most once per node */
   if( SCIPsepaGetNCallsAtNode(sepa) > 0 )
      return SCIP_OKAY;

   /* do not call rapid learning, if the problem is too big */
   if( SCIPgetNVars(scip) > sepadata->maxnvars || SCIPgetNConss(scip) > sepadata->maxnconss )
      return SCIP_OKAY; 

   if( SCIPisStopped(scip) )
      return SCIP_OKAY;

   *result = SCIP_DIDNOTFIND;
   
   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );

   /* initializing the subproblem */  
   SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) ); 
   SCIP_CALL( SCIPcreate(&subscip) );
   SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), SCIPcalcHashtableSize(5 * nvars)) );
   success = FALSE;

   /* copy the subproblem */
   SCIP_CALL( SCIPcopy(scip, subscip, varmapfw, NULL, "rapid", FALSE, FALSE, &success) );
   
   if( sepadata->copycuts )
   {
      /** copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
      SCIP_CALL( SCIPcopyCuts(scip, subscip, varmapfw, NULL, FALSE) );
   }

   for( i = 0; i < nvars; i++ )
      subvars[i] = (SCIP_VAR*) (size_t) SCIPhashmapGetImage(varmapfw, vars[i]);
   
   SCIPhashmapFree(&varmapfw);
   
   /* this avoids dual presolving */
   if( !success )
   {
      for( i = 0; i < nvars; i++ )
      {     
         SCIP_CALL( SCIPaddVarLocks(subscip, subvars[i], 1, 1 ) );
      }
   }

   SCIPdebugMessage("Copying SCIP was%s successful.\n", success ? "" : " not");
   
   /* mimic an FD solver: DFS, no LP solving, 1-FUIP instead of all-FUIP */
   SCIP_CALL( SCIPsetIntParam(subscip, "lp/solvefreq", -1) );
   SCIP_CALL( SCIPsetIntParam(subscip, "conflict/fuiplevels", 1) );
   SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/dfs/stdpriority", INT_MAX/4) ); 
   SCIP_CALL( SCIPsetBoolParam(subscip, "constraints/disableenfops", TRUE) );
   SCIP_CALL( SCIPsetIntParam(subscip, "propagating/pseudoobj/freq", -1) );

   /* use inference branching */
   SCIP_CALL( SCIPsetBoolParam(subscip, "branching/inference/useweightedsum", FALSE) );

   /* only create short conflicts */
   SCIP_CALL( SCIPsetRealParam(subscip, "conflict/maxvarsfac", 0.05) );
  
   /* set limits for the subproblem */
   nodelimit = SCIPgetNLPIterations(scip);
   nodelimit = MAX(sepadata->minnodes, nodelimit);
   nodelimit = MIN(sepadata->maxnodes, nodelimit);

   restartnum = 1000;
   
   /* check whether there is enough time and memory left */
   SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
   if( !SCIPisInfinity(scip, timelimit) )
      timelimit -= SCIPgetSolvingTime(scip);
   SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
   if( !SCIPisInfinity(scip, memorylimit) )   
      memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
   if( timelimit <= 0.0 || memorylimit <= 0.0 )
      goto TERMINATE;

   SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nodelimit/5) );
   SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
   SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );
   SCIP_CALL( SCIPsetIntParam(subscip, "limits/restarts", 0) );
   SCIP_CALL( SCIPsetIntParam(subscip, "conflict/restartnum", restartnum) );

   /* forbid recursive call of heuristics and separators solving subMIPs */
   SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );

   /* disable cutting plane separation */
   SCIP_CALL( SCIPsetSeparating(subscip, SCIP_PARAMSETTING_OFF, TRUE) );

   /* disable expensive presolving */
   SCIP_CALL( SCIPsetPresolving(subscip, SCIP_PARAMSETTING_FAST, TRUE) );

   /* do not abort subproblem on CTRL-C */
   SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );

#ifndef SCIP_DEBUG
   /* disable output to console */
   SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
#endif

   /* add an objective cutoff */
   SCIP_CALL( SCIPsetObjlimit(subscip, SCIPgetUpperbound(scip)) );

   /* create the variable mapping hash map */
   SCIP_CALL( SCIPhashmapCreate(&varmapbw, SCIPblkmem(scip), SCIPcalcHashtableSize(5 * nvars)) );

   /* store reversing mapping of variables */
   SCIP_CALL( SCIPtransformProb(subscip) );
   for( i = 0; i < nvars; ++i)
   {  
      SCIP_CALL( SCIPhashmapInsert(varmapbw, SCIPvarGetTransVar(subvars[i]), vars[i]) );
   }

   /** allocate memory for constraints storage. Each constraint that will be created from now on will be a conflict.
    *  Therefore, we need to remember oldnconss to get the conflicts from the FD search. 
    */
   nconshdlrs = 4;
   SCIP_CALL( SCIPallocBufferArray(scip, &conshdlrs, nconshdlrs) );
   SCIP_CALL( SCIPallocBufferArray(scip, &oldnconss, nconshdlrs) );

   /* store number of constraints before rapid learning search */
   conshdlrs[0] = SCIPfindConshdlr(subscip, "bounddisjunction");
   conshdlrs[1] = SCIPfindConshdlr(subscip, "setppc");
   conshdlrs[2] = SCIPfindConshdlr(subscip, "linear");
   conshdlrs[3] = SCIPfindConshdlr(subscip, "logicor");

   /* redundant constraints might be eliminated in presolving */
   SCIP_CALL( SCIPpresolve(subscip));

   for( i = 0; i < nconshdlrs; ++i)
   {
      if( conshdlrs[i] != NULL )
         oldnconss[i] = SCIPconshdlrGetNConss(conshdlrs[i]);
   }

   nfixedvars = SCIPgetNFixedVars(scip);
   
   /* solve the subproblem */
   retcode = SCIPsolve(subscip);
   
   /* Errors in solving the subproblem should not kill the overall solving process 
    * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    */
   if( retcode != SCIP_OKAY )
   { 
#ifndef NDEBUG
      SCIP_CALL( retcode );     
#endif
      SCIPwarningMessage("Error while solving subproblem in rapid learning separator; sub-SCIP terminated with code <%d>\n",retcode);
   }
 
   /* abort solving, if limit of applied conflicts is reached */
   if( SCIPgetNConflictConssApplied(subscip) >= restartnum )
   {
      SCIPdebugMessage("finish after %lld successful conflict calls.\n", SCIPgetNConflictConssApplied(subscip)); 
   }
   /* if the first 20% of the solution process were successful, proceed */
   else if( (sepadata->applyprimalsol && SCIPgetNSols(subscip) > 0 && SCIPisFeasLT(scip, SCIPgetUpperbound(subscip), SCIPgetUpperbound(scip) ) )
      || (sepadata->applybdchgs && SCIPgetNFixedVars(subscip) > nfixedvars)
      || (sepadata->applyconflicts && SCIPgetNConflictConssApplied(subscip) > 0) ) 
   {
      SCIPdebugMessage("proceed solving after the first 20%% of the solution process, since:\n");

      if( SCIPgetNSols(subscip) > 0 && SCIPisFeasLE(scip, SCIPgetUpperbound(subscip), SCIPgetUpperbound(scip) ) )
      {
         SCIPdebugMessage("   - there was a better solution (%f < %f)\n",SCIPgetUpperbound(subscip), SCIPgetUpperbound(scip));
      }
      if( SCIPgetNFixedVars(subscip) > nfixedvars )
      {
         SCIPdebugMessage("   - there were %d variables fixed\n", SCIPgetNFixedVars(scip)-nfixedvars );
      }
      if( SCIPgetNConflictConssFound(subscip) > 0 )
      {
         SCIPdebugMessage("   - there were %lld conflict constraints created\n", SCIPgetNConflictConssApplied(subscip));
      }

      /* set node limit to 100% */
      SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nodelimit) );

      /* solve the subproblem */
      retcode = SCIPsolve(subscip);
   
      /* Errors in solving the subproblem should not kill the overall solving process 
       * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
       */
      if( retcode != SCIP_OKAY )
      { 
#ifndef NDEBUG
         SCIP_CALL( retcode );     
#endif
         SCIPwarningMessage("Error while solving subproblem in rapid learning separator; sub-SCIP terminated with code <%d>\n",retcode);
      }
   }
   else
   {
      SCIPdebugMessage("do not proceed solving after the first 20%% of the solution process.\n");
   }

#ifdef SCIP_DEBUG
   SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
#endif

   disabledualreductions = FALSE;

   /* check, whether a solution was found */
   if( sepadata->applyprimalsol && SCIPgetNSols(subscip) > 0 && SCIPfindHeur(scip, "trysol") != NULL )
   {
      SCIP_HEUR* heurtrysol;
      SCIP_SOL** subsols;
      int nsubsols;

      /* check, whether a solution was found;
       * due to numerics, it might happen that not all solutions are feasible -> try all solutions until was declared to be feasible 
       */
      nsubsols = SCIPgetNSols(subscip);
      subsols = SCIPgetSols(subscip);
      soladded = FALSE;
      heurtrysol = SCIPfindHeur(scip, "trysol");

      /* sequentially add solutions to trysol heuristic */
      for( i = 0; i < nsubsols && !soladded; ++i )
      {
         SCIPdebugMessage("Try to create new solution by copying subscip solution.\n");
         SCIP_CALL( createNewSol(scip, subscip, subvars, heurtrysol, subsols[i], &soladded) );
      }
      if( !soladded || !SCIPisEQ(scip, SCIPgetSolOrigObj(subscip, subsols[i-1]), SCIPgetSolOrigObj(subscip, subsols[0])) )
         disabledualreductions = TRUE;
   }

   /* if the sub problem was solved completely, we update the dual bound */
   dualboundchg = FALSE;
   if( sepadata->applysolved && !disabledualreductions 
      && (SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL || SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE) )
   {
      /* we need to multiply the dualbound with the scaling factor and add the offset, 
       * because this information has been disregarded in the sub-SCIP */
      SCIPdebugMessage("Update old dualbound %g to new dualbound %g.\n", SCIPgetDualbound(scip), SCIPgetTransObjscale(scip) * SCIPgetDualbound(subscip) + SCIPgetTransObjoffset(scip));

      SCIP_CALL( SCIPupdateLocalDualbound(scip, SCIPgetDualbound(subscip) * SCIPgetTransObjscale(scip) + SCIPgetTransObjoffset(scip)) );
      dualboundchg = TRUE;
   }

   /* check, whether conflicts were created */
   nconflicts = 0;
   if( sepadata->applyconflicts && !disabledualreductions && SCIPgetNConflictConssApplied(subscip) > 0 )
   {
      SCIP_HASHMAP* consmap;
      int hashtablesize;

      assert(SCIPgetNConflictConssApplied(subscip) < (SCIP_Longint) INT_MAX);
      hashtablesize = (int) SCIPgetNConflictConssApplied(subscip);
      assert(hashtablesize < INT_MAX/5);
      hashtablesize *= 5;

      /* create the variable mapping hash map */
      SCIP_CALL( SCIPhashmapCreate(&consmap, SCIPblkmem(scip), SCIPcalcHashtableSize(hashtablesize)) );

      /* loop over all constraint handlers that might contain conflict constraints */
      for( i = 0; i < nconshdlrs; ++i)
      {
         /* copy constraints that have been created in FD run */
         if( conshdlrs[i] != NULL && SCIPconshdlrGetNConss(conshdlrs[i]) > oldnconss[i] )
         {
            SCIP_CONS** conss;
            int c;
            int nconss;
            
            nconss = SCIPconshdlrGetNConss(conshdlrs[i]);
            conss = SCIPconshdlrGetConss(conshdlrs[i]);

            /* loop over all constraints that have been added in sub-SCIP run, these are the conflicts */            
            for( c = oldnconss[i]; c < nconss; ++c)
            {
               SCIP_CONS* cons;
               SCIP_CONS* conscopy;
               
               cons = conss[c];
               assert(cons != NULL);        

               success = FALSE;

               SCIP_CALL( SCIPgetConsCopy(subscip, scip, cons, &conscopy, conshdlrs[i], varmapbw, consmap, NULL,
                     SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
                     SCIPconsIsPropagated(cons), TRUE, FALSE, SCIPconsIsDynamic(cons), 
                     SCIPconsIsRemovable(cons), FALSE, TRUE, &success) );

               if( success )
               {
                  nconflicts++;
                  SCIP_CALL( SCIPaddCons(scip, conscopy) );
                  SCIP_CALL( SCIPreleaseCons(scip, &conscopy) );
               }
               else
               {
                  SCIPdebugMessage("failed to copy conflict constraint %s back to original SCIP\n", SCIPconsGetName(cons));
               }
            }
         }
      }   
      SCIPhashmapFree(&consmap);
   }

   /* check, whether tighter global bounds were detected */
   nbdchgs = 0;
   if( sepadata->applybdchgs && !disabledualreductions )
      for( i = 0; i < nvars; ++i )
      {
         SCIP_Bool infeasible;
         SCIP_Bool tightened;
         
         assert(SCIPisLE(scip, SCIPvarGetLbGlobal(vars[i]), SCIPvarGetLbGlobal(subvars[i]))); 
         assert(SCIPisLE(scip, SCIPvarGetLbGlobal(subvars[i]), SCIPvarGetUbGlobal(subvars[i])));
         assert(SCIPisLE(scip, SCIPvarGetUbGlobal(subvars[i]), SCIPvarGetUbGlobal(vars[i])));  
         
         /* update the bounds of the original SCIP, if a better bound was proven in the sub-SCIP */
         SCIP_CALL( SCIPtightenVarUb(scip, vars[i], SCIPvarGetUbGlobal(subvars[i]), FALSE, &infeasible, &tightened) );
         if( tightened ) 
            nbdchgs++;
         
         SCIP_CALL( SCIPtightenVarLb(scip, vars[i], SCIPvarGetLbGlobal(subvars[i]), FALSE, &infeasible, &tightened) );
         if( tightened )
            nbdchgs++;   
      }

   n1startinfers = 0;
   n2startinfers = 0;

   /* install start values for inference branching */
   if( sepadata->applyinfervals && (!sepadata->reducedinfer || soladded || nbdchgs+nconflicts > 0) )
   {
      for( i = 0; i < nvars; ++i )
      {
         SCIP_Real downinfer;
         SCIP_Real upinfer;
         SCIP_Real downvsids;
         SCIP_Real upvsids;
         SCIP_Real downconflen;
         SCIP_Real upconflen;
        
         /* copy downwards branching statistics */
         downvsids = SCIPgetVarVSIDS(subscip, subvars[i], SCIP_BRANCHDIR_DOWNWARDS);            
         downconflen = SCIPgetVarAvgConflictlength(subscip, subvars[i], SCIP_BRANCHDIR_DOWNWARDS);
         downinfer = SCIPgetVarAvgInferences(subscip, subvars[i], SCIP_BRANCHDIR_DOWNWARDS);            
         
         /* copy upwards branching statistics */
         upvsids = SCIPgetVarVSIDS(subscip, subvars[i], SCIP_BRANCHDIR_UPWARDS);                     
         upconflen = SCIPgetVarAvgConflictlength(subscip, subvars[i], SCIP_BRANCHDIR_UPWARDS);
         upinfer = SCIPgetVarAvgInferences(subscip, subvars[i], SCIP_BRANCHDIR_UPWARDS);            
        
         /* memorize statistics */
         if( downinfer+downconflen+downvsids > 0.0 || upinfer+upconflen+upvsids != 0 )
            n1startinfers++;
         
         if( downinfer+downconflen+downvsids > 0.0 && upinfer+upconflen+upvsids != 0 )
            n2startinfers++;
         
         SCIP_CALL( SCIPinitVarBranchStats(scip, vars[i], 0.0, 0.0, downvsids, upvsids, downconflen, upconflen, downinfer, upinfer, 0.0, 0.0) );
      }   
   }
   
   SCIPdebugPrintf("XXX Rapidlearning added %d conflicts, changed %d bounds, %s primal solution, %s dual bound improvement.\n", nconflicts, nbdchgs, soladded ? "found" : "no", 
      dualboundchg ? "found" : "no");

   SCIPdebugPrintf("YYY Infervalues initialized on one side: %5.2f %% of variables, %5.2f %% on both sides\n", 
      100.0 * n1startinfers/(SCIP_Real)nvars, 100.0 * n2startinfers/(SCIP_Real)nvars);

   /* change result pointer */
   if( nconflicts > 0 || dualboundchg )
      *result = SCIP_CONSADDED;
   else if( nbdchgs > 0 )
      *result = SCIP_REDUCEDDOM;
  
   /* free local data */
   SCIPfreeBufferArray(scip, &oldnconss);
   SCIPfreeBufferArray(scip, &conshdlrs);

   SCIPhashmapFree(&varmapbw);

 TERMINATE:
   /* free subproblem */
   SCIPfreeBufferArray(scip, &subvars);
   SCIP_CALL( SCIPfree(&subscip) );
  
   return SCIP_OKAY;
}
Esempio n. 21
0
/** writes problem to file */
SCIP_RETCODE SCIPwriteCcg(
   SCIP*                 scip,               /**< SCIP data structure */
   FILE*                 file,               /**< output file, or NULL if standard output should be used */
   const char*           name,               /**< problem name */
   SCIP_Bool             transformed,        /**< TRUE iff problem is the transformed problem */
   SCIP_VAR**            vars,               /**< array with active variables ordered binary, integer, implicit, continuous */
   int                   nvars,              /**< number of active variables in the problem */
   SCIP_CONS**           conss,              /**< array with constraints of the problem */
   int                   nconss,             /**< number of constraints in the problem */
   SCIP_RESULT*          result              /**< pointer to store the result of the file writing call */
   )
{  /*lint --e{715}*/
   int c;
   int v;
   int i;

   SCIP_CONSHDLR* conshdlr;
   const char* conshdlrname;
   SCIP_CONS* cons;

   SCIP_VAR** consvars;
   SCIP_Real* consvals;
   int nconsvars;

   SparseGraph G;

   assert( scip != NULL );
   assert( nvars >= 0 );

   /* initialize graph */
   SCIP_CALL( initGraph(scip, &G, (unsigned int) nvars, 10) );

   /* check all constraints */
   for( c = 0; c < nconss; ++c)
   {
      cons = conss[c];
      assert( cons != NULL);

      /* in case the transformed is written only constraint are posted which are enabled in the current node */
      assert(!transformed || SCIPconsIsEnabled(cons));

      conshdlr = SCIPconsGetHdlr(cons);
      assert( conshdlr != NULL );

      conshdlrname = SCIPconshdlrGetName(conshdlr);
      assert( transformed == SCIPconsIsTransformed(cons) );

      if( strcmp(conshdlrname, "linear") == 0 )
      {  
         consvars = SCIPgetVarsLinear(scip, cons);
         nconsvars = SCIPgetNVarsLinear(scip, cons);
         assert( consvars != NULL || nconsvars == 0 );

         if( nconsvars > 0 ) 
         { 
            SCIP_CALL( handleLinearCons(scip, SCIPgetVarsLinear(scip, cons), SCIPgetValsLinear(scip, cons),
                  SCIPgetNVarsLinear(scip, cons), transformed, &G) );
         }
      }
      else if( strcmp(conshdlrname, "setppc") == 0 )
      {
         consvars = SCIPgetVarsSetppc(scip, cons);
         nconsvars = SCIPgetNVarsSetppc(scip, cons);
         assert( consvars != NULL || nconsvars == 0 );

         if( nconsvars > 0 ) 
         {
            SCIP_CALL( handleLinearCons(scip, consvars, NULL, nconsvars, transformed, &G) );
         }
      }
      else if( strcmp(conshdlrname, "logicor") == 0 )
      {  
         consvars = SCIPgetVarsLogicor(scip, cons);
         nconsvars = SCIPgetNVarsLogicor(scip, cons);
         assert( consvars != NULL || nconsvars == 0 );

         if( nconsvars > 0 ) 
         { 
            SCIP_CALL( handleLinearCons(scip, SCIPgetVarsLogicor(scip, cons), NULL, SCIPgetNVarsLogicor(scip, cons), transformed, &G) );
         }
      }
      else if( strcmp(conshdlrname, "knapsack") == 0 )
      {
         SCIP_Longint* w;

         consvars = SCIPgetVarsKnapsack(scip, cons);
         nconsvars = SCIPgetNVarsKnapsack(scip, cons);
         assert( consvars != NULL || nconsvars == 0 );

         /* copy Longint array to SCIP_Real array */
         w = SCIPgetWeightsKnapsack(scip, cons);
         SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
         for( v = 0; v < nconsvars; ++v )
            consvals[v] = (SCIP_Real)w[v];

         if( nconsvars > 0 ) 
         { 
            SCIP_CALL( handleLinearCons(scip, consvars, consvals, nconsvars, transformed, &G) );
         }
         SCIPfreeBufferArray(scip, &consvals);
      }
      else if( strcmp(conshdlrname, "varbound") == 0 )
      {
         SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 2) );
         SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 2) );

         consvars[0] = SCIPgetVarVarbound(scip, cons);
         consvars[1] = SCIPgetVbdvarVarbound(scip, cons);

         consvals[0] = 1.0;
         consvals[1] = SCIPgetVbdcoefVarbound(scip, cons);

         SCIP_CALL( handleLinearCons(scip, consvars, consvals, 2, transformed, &G) );

         SCIPfreeBufferArray(scip, &consvars);
         SCIPfreeBufferArray(scip, &consvals);
      }
      else
      {
         SCIPwarningMessage(scip, "constraint handler <%s> cannot print requested format\n", conshdlrname );
         SCIPinfoMessage(scip, file, "\\ ");
         SCIP_CALL( SCIPprintCons(scip, cons, file) );
         SCIPinfoMessage(scip, file, ";\n");
      }
   }

   /* output graph */
   SCIPinfoMessage(scip, file, "c graph generated from %s\n", name);
   SCIPinfoMessage(scip, file, "p edge %d %d\n", nvars, G.m);

   for( i = 0; i < nvars; ++i )
   {
      unsigned int k;
      int a;

      k = 0;
      a = G.A[i][k];
      while( a >= 0 )
      {
         /* only output edges from lower to higher number */
         if( i < a )
         {
            /* note: node numbers start with 1 in the DIMACS format */
            SCIPinfoMessage(scip, file, "e %d %d %f\n", i+1, a+1, G.W[i][k]);
         }

         a = G.A[i][++k];
         assert( k <= G.size[i] );
      }
      assert( k == G.deg[i] );
   }

   freeGraph(scip, &G);

   *result = SCIP_SUCCESS;

   return SCIP_OKAY;
}
Esempio n. 22
0
/** problem reading method of reader */
static
SCIP_DECL_READERREAD(readerReadBpa)
{  /*lint --e{715}*/
   SCIP_FILE* file;
   SCIP_Longint* weights;
   int* ids;
   SCIP_Bool error;

   char name[SCIP_MAXSTRLEN];
   char format[16];
   char buffer[SCIP_MAXSTRLEN];
   int capacity;
   int nitems;
   int bestsolvalue;
   int nread;
   int weight;
   int nweights;
   int lineno;

   *result = SCIP_DIDNOTRUN;

   /* open file */
   file = SCIPfopen(filename, "r");
   if( file == NULL )
   {
      SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
      SCIPprintSysError(filename);
      return SCIP_NOFILE;
   }

   lineno = 0;
   sprintf(name, "++ uninitialized ++");

   /* read problem name */
   if( !SCIPfeof(file) )
   {
      /* get next line */
      if( SCIPfgets(buffer, (int)sizeof(buffer), file) == NULL )
         return SCIP_READERROR;
      lineno++;

      /* parse dimension line */
      sprintf(format, "%%%ds\n", SCIP_MAXSTRLEN);
      nread = sscanf(buffer, format, name);
      if( nread == 0 )
      {
         SCIPwarningMessage(scip, "invalid input line %d in file <%s>: <%s>\n", lineno, filename, buffer);
         return SCIP_READERROR;
      }

      SCIPdebugMessage("problem name <%s>\n", name);
   }

   capacity = 0;
   nitems = 0;

   /* read problem dimension */
   if( !SCIPfeof(file) )
   {
      /* get next line */
      if( SCIPfgets(buffer, (int)sizeof(buffer), file) == NULL )
         return SCIP_READERROR;
      lineno++;

      /* parse dimension line */
      nread = sscanf(buffer, "%d %d %d\n", &capacity, &nitems, &bestsolvalue);
      if( nread < 2 )
      {
         SCIPwarningMessage(scip, "invalid input line %d in file <%s>: <%s>\n", lineno, filename, buffer);
         return SCIP_READERROR;
      }

      SCIPdebugMessage("capacity = <%d>, number of items = <%d>, best known solution = <%d>\n", capacity, nitems, bestsolvalue);
   }


   /* allocate buffer memory for storing the weights and ids temporary */
   SCIP_CALL( SCIPallocBufferArray(scip, &weights, nitems) );
   SCIP_CALL( SCIPallocBufferArray(scip, &ids, nitems) );

   /* pasre weights */
   nweights = 0;
   error = FALSE;

   while( !SCIPfeof(file) && !error )
   {
      /* get next line */
      if( SCIPfgets(buffer, (int)sizeof(buffer), file) == NULL )
         break;
      lineno++;

      /* parse the line */
      nread = sscanf(buffer, "%d\n", &weight);
      if( nread == 0 )
      {
         SCIPwarningMessage(scip, "invalid input line %d in file <%s>: <%s>\n", lineno, filename, buffer);
         error = TRUE;
         break;
      }

      SCIPdebugMessage("found weight %d <%d>\n", nweights, weight);
      weights[nweights] = weight;
      ids[nweights] = nweights;
      nweights++;

      if( nweights == nitems )
         break;
   }

   if( nweights < nitems )
   {
      SCIPwarningMessage(scip, "set nitems from <%d> to <%d> since the file <%s> only contains <%d> weights\n", nitems, weights, filename, weights);
      nitems = nweights;
   }

   if( !error )
   {
      /* create a new problem in SCIP */
      SCIP_CALL( SCIPprobdataCreate(scip, name, ids, weights, nitems, (SCIP_Longint)capacity) );
   }

   (void)SCIPfclose(file);
   SCIPfreeBufferArray(scip, &ids);
   SCIPfreeBufferArray(scip, &weights);

   if( error )
      return SCIP_READERROR;

   *result = SCIP_SUCCESS;

   return SCIP_OKAY;
}
Esempio n. 23
0
/** main procedure of the RENS heuristic, creates and solves a subMIP */
SCIP_RETCODE SCIPapplyGcgrens(
   SCIP*                 scip,               /**< original SCIP data structure                                   */
   SCIP_HEUR*            heur,               /**< heuristic data structure                                       */
   SCIP_RESULT*          result,             /**< result data structure                                          */
   SCIP_Real             minfixingrate,      /**< minimum percentage of integer variables that have to be fixed  */
   SCIP_Real             minimprove,         /**< factor by which RENS should at least improve the incumbent     */
   SCIP_Longint          maxnodes,           /**< maximum number of  nodes for the subproblem                    */
   SCIP_Longint          nstallnodes,        /**< number of stalling nodes for the subproblem                    */
   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* subscip;                            /* the subproblem created by RENS                  */
   SCIP_HASHMAP* varmapfw;                   /* mapping of SCIP variables to sub-SCIP variables */
   SCIP_VAR** vars;                          /* original problem's variables                    */
   SCIP_VAR** subvars;                       /* subproblem's variables                          */

   SCIP_Real cutoff;                         /* objective cutoff for the subproblem             */
   SCIP_Real timelimit;
   SCIP_Real memorylimit;

   int nvars;
   int i;

   SCIP_Bool success;
   SCIP_RETCODE retcode;

   assert(scip != NULL);
   assert(heur != NULL);
   assert(result != NULL);

   assert(maxnodes >= 0);
   assert(nstallnodes >= 0);

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

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

   /* initialize the subproblem */
   SCIP_CALL( SCIPcreate(&subscip) );

   /* create the variable mapping hash map */
   SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), SCIPcalcHashtableSize(5 * nvars)) );
   SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );

   if( uselprows )
   {
      char probname[SCIP_MAXSTRLEN];

      /* copy all plugins */
      SCIP_CALL( SCIPincludeDefaultPlugins(subscip) );

      /* get name of the original problem and add the string "_gcgrenssub" */
      (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_gcgrenssub", SCIPgetProbName(scip));

      /* create the subproblem */
      SCIP_CALL( SCIPcreateProb(subscip, probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );

      /* copy all variables */
      SCIP_CALL( SCIPcopyVars(scip, subscip, varmapfw, NULL, TRUE) );
   }
   else
   {
      SCIP_Bool valid;
      SCIP_HEURDATA* heurdata;

      valid = FALSE;

      SCIP_CALL( SCIPcopy(scip, subscip, varmapfw, NULL, "gcgrens", TRUE, FALSE, TRUE, &valid) ); /** @todo check for thread safeness */

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

      if( heurdata->copycuts )
      {
         /** copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
         SCIP_CALL( SCIPcopyCuts(scip, subscip, varmapfw, NULL, TRUE, NULL) );
      }

      SCIPdebugMessage("Copying the SCIP instance was %s complete.\n", valid ? "" : "not ");
   }

   for( i = 0; i < nvars; i++ )
     subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);

   /* free hash map */
   SCIPhashmapFree(&varmapfw);

   /* create a new problem, which fixes variables with same value in bestsol and LP relaxation */
   SCIP_CALL( createSubproblem(scip, subscip, subvars, minfixingrate, binarybounds, uselprows, &success) );
   SCIPdebugMessage("RENS subproblem: %d vars, %d cons, success=%u\n", SCIPgetNVars(subscip), SCIPgetNConss(subscip), success);

   /* do not abort subproblem on CTRL-C */
   SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );

   /* disable output to console */
   SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );

   /* check whether there is enough time and memory left */
   timelimit = 0.0;
   memorylimit = 0.0;
   SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
   if( !SCIPisInfinity(scip, timelimit) )
      timelimit -= SCIPgetSolvingTime(scip);
   SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
   if( !SCIPisInfinity(scip, memorylimit) )
      memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
   if( timelimit <= 0.0 || memorylimit <= 0.0 )
      goto TERMINATE;

   /* set limits for the subproblem */
   SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", nstallnodes) );
   SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", maxnodes) );
   SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
   SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );

   /* forbid recursive call of heuristics and separators solving sub-SCIPs */
   SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );

   /* disable cutting plane separation */
   SCIP_CALL( SCIPsetSeparating(subscip, SCIP_PARAMSETTING_OFF, TRUE) );

   /* disable expensive presolving */
   SCIP_CALL( SCIPsetPresolving(subscip, SCIP_PARAMSETTING_FAST, TRUE) );

   /* use best estimate node selection */
   if( SCIPfindNodesel(scip, "estimate") != NULL )
   {
      SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
   }

   /* use inference branching */
   if( SCIPfindBranchrule(scip, "inference") != NULL )
   {
      SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
   }

   /* disable conflict analysis */
   SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useprop", FALSE) );
   SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useinflp", FALSE) );
   SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useboundlp", FALSE) );
   SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/usesb", FALSE) );
   SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/usepseudo", FALSE) );


#ifdef SCIP_DEBUG
   /* for debugging RENS, enable MIP output */
   SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
   SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
#endif


   /* if the subproblem could not be created, free memory and return */
   if( !success )
   {
      *result = SCIP_DIDNOTRUN;
      SCIPfreeBufferArray(scip, &subvars);
      SCIP_CALL( SCIPfree(&subscip) );
      return SCIP_OKAY;
   }

   /* if there is already a solution, add an objective cutoff */
   if( SCIPgetNSols(scip) > 0 )
   {
      SCIP_Real upperbound;
      assert( !SCIPisInfinity(scip,SCIPgetUpperbound(scip)) );

      upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);

      if( !SCIPisInfinity(scip,-1.0*SCIPgetLowerbound(scip)) )
      {
         cutoff = (1-minimprove)*SCIPgetUpperbound(scip) + minimprove*SCIPgetLowerbound(scip);
      }
      else
      {
         if( SCIPgetUpperbound ( scip ) >= 0 )
            cutoff = ( 1 - minimprove ) * SCIPgetUpperbound ( scip );
         else
            cutoff = ( 1 + minimprove ) * SCIPgetUpperbound ( scip );
      }
      cutoff = MIN(upperbound, cutoff);
      SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
   }

   /* presolve the subproblem */
   retcode = SCIPpresolve(subscip);

   /* Errors in solving the subproblem should not kill the overall solving process
    * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
    */
   if( retcode != SCIP_OKAY )
   {
#ifndef NDEBUG
      SCIP_CALL( retcode );
#endif
      SCIPwarningMessage(scip, "Error while presolving subproblem in GCG RENS heuristic; sub-SCIP terminated with code <%d>\n",retcode);
   }

   SCIPdebugMessage("GCG RENS presolved subproblem: %d vars, %d cons, success=%u\n", SCIPgetNVars(subscip), SCIPgetNConss(subscip), success);

   /* after presolving, we should have at least reached a certain fixing rate over ALL variables (including continuous)
    * to ensure that not only the MIP but also the LP relaxation is easy enough
    */
   if( ( nvars - SCIPgetNVars(subscip) ) / (SCIP_Real)nvars >= minfixingrate / 2.0 )
   {
      SCIP_SOL** subsols;
      int nsubsols;

      /* solve the subproblem */
      SCIPdebugMessage("solving subproblem: nstallnodes=%"SCIP_LONGINT_FORMAT", maxnodes=%"SCIP_LONGINT_FORMAT"\n", nstallnodes, maxnodes);
      retcode = SCIPsolve(subscip);

      /* Errors in solving the subproblem should not kill the overall solving process
       * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
       */
      if( retcode != SCIP_OKAY )
      {
#ifndef NDEBUG
         SCIP_CALL( retcode );
#endif
         SCIPwarningMessage(scip, "Error while solving subproblem in GCG RENS heuristic; sub-SCIP terminated with code <%d>\n",retcode);
      }

      /* check, whether a solution was found;
       * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted
       */
      nsubsols = SCIPgetNSols(subscip);
      subsols = SCIPgetSols(subscip);
      success = FALSE;
      for( i = 0; i < nsubsols && !success; ++i )
      {
         SCIP_CALL( createNewSol(scip, subscip, subvars, heur, subsols[i], &success) );
      }
      if( success )
         *result = SCIP_FOUNDSOL;
   }

 TERMINATE:
   /* free subproblem */
   SCIPfreeBufferArray(scip, &subvars);
   SCIP_CALL( SCIPfree(&subscip) );

   return SCIP_OKAY;
}
/** execution method of primal heuristic */
static
SCIP_DECL_HEUREXEC(heurExecCrossover)
{  /*lint --e{715}*/
   SCIP_HEURDATA* heurdata;                  /* primal heuristic data                               */
   SCIP* subscip;                            /* the subproblem created by crossover                 */
   SCIP_HASHMAP* varmapfw;                   /* mapping of SCIP variables to sub-SCIP variables */

   SCIP_VAR** vars;                          /* original problem's variables                        */
   SCIP_VAR** subvars;                       /* subproblem's variables                              */
   SCIP_SOL** sols;

   SCIP_Real memorylimit;                    /* memory limit for the subproblem                     */
   SCIP_Real timelimit;                      /* time limit for the subproblem                       */
   SCIP_Real cutoff;                         /* objective cutoff for the subproblem                 */
   SCIP_Real upperbound;
   SCIP_Bool success;

   SCIP_Longint nstallnodes;                 /* node limit for the subproblem                       */

   int* selection;                           /* pool of solutions crossover uses                    */
   int nvars;                                /* number of original problem's variables              */
   int nbinvars;
   int nintvars;
   int nusedsols;
   int i;

   SCIP_RETCODE retcode;

   assert(heur != NULL);
   assert(scip != NULL);
   assert(result != NULL);

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

   *result = SCIP_DELAYED;

   /* only call heuristic, if enough solutions are at hand */
   if( SCIPgetNSols(scip) < nusedsols  )
      return SCIP_OKAY;

   sols = SCIPgetSols(scip);
   assert(sols != NULL);

   /* if one good solution was found, heuristic should not be delayed any longer */
   if( sols[nusedsols-1] != heurdata->prevlastsol )
   {
      heurdata->nextnodenumber = SCIPgetNNodes(scip);
      if( sols[0] != heurdata->prevbestsol )
         heurdata->nfailures = 0;
   }
   /* in nonrandomized mode: only recall heuristic, if at least one new good solution was found in the meantime */
   else if( !heurdata->randomization )
      return SCIP_OKAY;

   /* if heuristic should be delayed, wait until certain number of nodes is reached */
   if( SCIPgetNNodes(scip) < heurdata->nextnodenumber )
      return SCIP_OKAY;

   /* only call heuristic, if enough nodes were processed since last incumbent */
   if( SCIPgetNNodes(scip) - SCIPgetSolNodenum(scip,SCIPgetBestSol(scip))  < heurdata->nwaitingnodes
      && (SCIPgetDepth(scip) > 0 || !heurdata->dontwaitatroot) )
      return SCIP_OKAY;

   *result = SCIP_DIDNOTRUN;

   /* calculate the maximal number of branching nodes until heuristic is aborted */
   nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));

   /* reward Crossover if it succeeded often */
   nstallnodes = (SCIP_Longint)
      (nstallnodes * (1.0 + 2.0*(SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur)+1.0)));

   /* count the setup costs for the sub-MIP as 100 nodes */
   nstallnodes -= 100 * SCIPheurGetNCalls(heur);
   nstallnodes += heurdata->nodesofs;

   /* determine the node limit for the current process */
   nstallnodes -= heurdata->usednodes;
   nstallnodes = MIN(nstallnodes, heurdata->maxnodes);

   /* check whether we have enough nodes left to call subproblem solving */
   if( nstallnodes < heurdata->minnodes )
      return SCIP_OKAY;

   if( SCIPisStopped(scip) )
     return SCIP_OKAY;

   *result = SCIP_DIDNOTFIND;

   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
   assert(nvars > 0);

   /* check whether discrete variables are available */
   if( nbinvars == 0 && nintvars == 0 )
      return SCIP_OKAY;

   /* initializing the subproblem */
   SCIP_CALL( SCIPcreate(&subscip) );

   /* create the variable mapping hash map */
   SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), SCIPcalcHashtableSize(5 * nvars)) );
   success = FALSE;

   if( heurdata->uselprows )
   {
      char probname[SCIP_MAXSTRLEN];

      /* copy all plugins */
      SCIP_CALL( SCIPincludeDefaultPlugins(subscip) );

      /* get name of the original problem and add the string "_crossoversub" */
      (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_crossoversub", SCIPgetProbName(scip));

      /* create the subproblem */
      SCIP_CALL( SCIPcreateProb(subscip, probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );

      /* copy all variables */
      SCIP_CALL( SCIPcopyVars(scip, subscip, varmapfw, NULL, TRUE) );
   }
   else
   {
      SCIP_CALL( SCIPcopy(scip, subscip, varmapfw, NULL, "crossover", TRUE, FALSE, TRUE, &success) );

      if( heurdata->copycuts )
      {
         /** copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
         SCIP_CALL( SCIPcopyCuts(scip, subscip, varmapfw, NULL, TRUE, NULL) );
      }
   }

   SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
   SCIP_CALL( SCIPallocBufferArray(scip, &selection, nusedsols) );

   for( i = 0; i < nvars; i++ )
     subvars[i] = (SCIP_VAR*) (size_t) SCIPhashmapGetImage(varmapfw, vars[i]);

   /* free hash map */
   SCIPhashmapFree(&varmapfw);

   success = FALSE;

   /* create a new problem, which fixes variables with same value in a certain set of solutions */
   SCIP_CALL( setupSubproblem(scip, subscip, subvars, selection, heurdata, &success) );

   heurdata->prevbestsol = SCIPgetBestSol(scip);
   heurdata->prevlastsol = sols[heurdata->nusedsols-1];

   /* if creation of sub-SCIP was aborted (e.g. due to number of fixings), free sub-SCIP and abort */
   if( !success )
   {
      *result = SCIP_DIDNOTRUN;

      /* this run will be counted as a failure since no new solution tuple could be generated or the neighborhood of the
       * solution was not fruitful in the sense that it was too big
       */
      updateFailureStatistic(scip, heurdata);

      goto TERMINATE;
   }

   /* do not abort subproblem on CTRL-C */
   SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );

   /* disable output to console */
   SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );

   /* check whether there is enough time and memory left */
   SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
   if( !SCIPisInfinity(scip, timelimit) )
      timelimit -= SCIPgetSolvingTime(scip);
   SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );

   /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
   if( !SCIPisInfinity(scip, memorylimit) )
   {
      memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
      memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
   }

   /* abort if no time is left or not enough memory to create a copy of SCIP, including external memory usage */
   if( timelimit <= 0.0 || memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0 )
      goto TERMINATE;

   /* set limits for the subproblem */
   SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nstallnodes) );
   SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
   SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );

   /* forbid recursive call of heuristics and separators solving subMIPs */
   SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );

   /* disable cutting plane separation */
   SCIP_CALL( SCIPsetSeparating(subscip, SCIP_PARAMSETTING_OFF, TRUE) );

   /* disable expensive presolving */
   SCIP_CALL( SCIPsetPresolving(subscip, SCIP_PARAMSETTING_FAST, TRUE) );

   /* use best estimate node selection */
   if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
   {
      SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
   }

   /* use inference branching */
   if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
   {
      SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
   }

   /* disable conflict analysis */
   if( !SCIPisParamFixed(subscip, "conflict/useprop") )
   {
      SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useprop", FALSE) );
   }
   if( !SCIPisParamFixed(subscip, "conflict/useinflp") )
   {
      SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useinflp", FALSE) );
   }
   if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
   {
      SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useboundlp", FALSE) );
   }
   if( !SCIPisParamFixed(subscip, "conflict/usesb") )
   {
      SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/usesb", FALSE) );
   }
   if( !SCIPisParamFixed(subscip, "conflict/usepseudo") )
   {
      SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/usepseudo", FALSE) );
   }

   /* add an objective cutoff */
   cutoff = SCIPinfinity(scip);
   assert(!SCIPisInfinity(scip, SCIPgetUpperbound(scip)));

   upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
   if( !SCIPisInfinity(scip,-1.0*SCIPgetLowerbound(scip)) )
   {
      cutoff = (1-heurdata->minimprove)*SCIPgetUpperbound(scip) + heurdata->minimprove*SCIPgetLowerbound(scip);
   }
   else
   {
      if( SCIPgetUpperbound ( scip ) >= 0 )
         cutoff = ( 1 - heurdata->minimprove ) * SCIPgetUpperbound ( scip );
      else
         cutoff = ( 1 + heurdata->minimprove ) * SCIPgetUpperbound ( scip );
   }
   cutoff = MIN(upperbound, cutoff );
   SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );

   /* permute the subproblem to increase diversification */
   if( heurdata->permute )
   {
      SCIP_CALL( SCIPpermuteProb(subscip, (unsigned int) SCIPheurGetNCalls(heur), TRUE, TRUE, TRUE, TRUE, TRUE) );
   }

   /* solve the subproblem */
   SCIPdebugMessage("Solve Crossover subMIP\n");
   retcode = SCIPsolve(subscip);

   /* Errors in solving the subproblem should not kill the overall solving process.
    * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
   if( retcode != SCIP_OKAY )
   {
#ifndef NDEBUG
      SCIP_CALL( retcode );
#endif
      SCIPwarningMessage(scip, "Error while solving subproblem in Crossover heuristic; sub-SCIP terminated with code <%d>\n", retcode);
   }

   heurdata->usednodes += SCIPgetNNodes(subscip);

   /* check, whether a solution was found */
   if( SCIPgetNSols(subscip) > 0 )
   {
      SCIP_SOL** subsols;
      int nsubsols;
      int solindex;                             /* index of the solution created by crossover          */

      /* check, whether a solution was found;
       * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted */
      nsubsols = SCIPgetNSols(subscip);
      subsols = SCIPgetSols(subscip);
      success = FALSE;
      solindex = -1;
      for( i = 0; i < nsubsols && !success; ++i )
      {
         SCIP_CALL( createNewSol(scip, subscip, subvars, heur, subsols[i], &solindex, &success) );
      }

      if( success )
      {
         int tmp;

         assert(solindex != -1);

         *result = SCIP_FOUNDSOL;

         /* insert all crossings of the new solution and (nusedsols-1) of its parents into the hashtable
          * in order to avoid incest ;)
          */
         for( i = 0; i < nusedsols; i++ )
         {
            SOLTUPLE* elem;
            tmp = selection[i];
            selection[i] = solindex;

            SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );
            SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
            selection[i] = tmp;
         }

         /* if solution was among the best ones, crossover should not be called until another good solution was found */
         if( !heurdata->randomization )
         {
            heurdata->prevbestsol = SCIPgetBestSol(scip);
            heurdata->prevlastsol = SCIPgetSols(scip)[heurdata->nusedsols-1];
         }
      }

      /* if solution is not better then incumbent or could not be added to problem => run is counted as a failure */
      if( !success || solindex != SCIPsolGetIndex(SCIPgetBestSol(scip)) )
         updateFailureStatistic(scip, heurdata);
   }
   else
   {
      /* if no new solution was found, run was a failure */
      updateFailureStatistic(scip, heurdata);
   }

 TERMINATE:
   /* free subproblem */
   SCIPfreeBufferArray(scip, &selection);
   SCIPfreeBufferArray(scip, &subvars);
   SCIP_CALL( SCIPfree(&subscip) );

   return SCIP_OKAY;
}
Esempio n. 25
0
/** avoid to generate columns which are fixed to zero; therefore add for each variable which is fixed to zero a
 *  corresponding logicor constraint to forbid this column
 *
 * @note variable which are fixed locally to zero should not be generated again by the pricing MIP
 */
static
SCIP_RETCODE addFixedVarsConss(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP*                 subscip,            /**< pricing SCIP data structure */
   SCIP_VAR**            vars,               /**< variable array of the subscuip */
   SCIP_CONS**           conss,              /**< array of setppc constraint for each item one */
   int                   nitems              /**< number of items */
   )
{
   SCIP_VAR** origvars;
   int norigvars;

   SCIP_CONS* cons;
   int* consids;
   int nconsids;
   int consid;
   int nvars;

   SCIP_VAR** logicorvars;
   SCIP_VAR* var;
   SCIP_VARDATA* vardata;
   SCIP_Bool needed;
   int nlogicorvars;

   int v;
   int c;
   int o;

   /* collect all variable which are currently existing */
   origvars = SCIPgetVars(scip);
   norigvars = SCIPgetNVars(scip);

   /* loop over all these variables and check if they are fixed to zero */
   for( v = 0; v < norigvars; ++v )
   {
      assert(SCIPvarGetType(origvars[v]) == SCIP_VARTYPE_BINARY);

      /* if the upper bound is smaller than 0.5 if follows due to the integrality that the binary variable is fixed to zero */
      if( SCIPvarGetUbLocal(origvars[v]) < 0.5 )
      {
         SCIPdebugMessage("variable <%s> glb=[%.15g,%.15g] loc=[%.15g,%.15g] is fixed to zero\n",
            SCIPvarGetName(origvars[v]), SCIPvarGetLbGlobal(origvars[v]), SCIPvarGetUbGlobal(origvars[v]),
            SCIPvarGetLbLocal(origvars[v]), SCIPvarGetUbLocal(origvars[v]) );

         /* coolect the constraints/items the variable belongs to */
         vardata = SCIPvarGetData(origvars[v]);
         nconsids = SCIPvardataGetNConsids(vardata);
         consids = SCIPvardataGetConsids(vardata);
         needed = TRUE;

         SCIP_CALL( SCIPallocBufferArray(subscip, &logicorvars, nitems) );
         nlogicorvars = 0;
         consid = consids[0];
         nvars = 0;

         /* loop over these items and create a linear (logicor) constraint which forbids this item combination in the
          * pricing problem; thereby check if this item combination is already forbidden
          */
         for( c = 0, o = 0; o < nitems && needed; ++o )
         {
            assert(o <= consid);
            cons = conss[o];

            if( SCIPconsIsEnabled(cons) )
            {
               assert( SCIPgetNFixedonesSetppc(scip, cons) == 0 );

               var = vars[nvars];
               nvars++;
               assert(var != NULL);

               if( o == consid )
               {
                  SCIP_CALL( SCIPgetNegatedVar(subscip, var, &var) );
               }

               logicorvars[nlogicorvars] = var;
               nlogicorvars++;
            }
            else if( o == consid )
               needed = FALSE;

            if( o == consid )
            {
               c++;
               if ( c == nconsids )
                  consid = nitems + 100;
               else
               {
                  assert(consid < consids[c]);
                  consid = consids[c];
               }
            }
         }

         if( needed )
         {
            SCIP_CALL( SCIPcreateConsBasicLogicor(subscip, &cons, SCIPvarGetName(origvars[v]), nlogicorvars, logicorvars) );
            SCIP_CALL( SCIPsetConsInitial(subscip, cons, FALSE) );

            SCIP_CALL( SCIPaddCons(subscip, cons) );
            SCIP_CALL( SCIPreleaseCons(subscip, &cons) );
         }

         SCIPfreeBufferArray(subscip, &logicorvars);
      }
   }

   return SCIP_OKAY;
}
Esempio n. 26
0
/** execution method of primal heuristic */
static
SCIP_DECL_HEUREXEC(heurExecForward)
{  /*lint --e{715}*/
	
   SCIP_PROBDATA* probdata;
	int	n;
	int	p;
	int	ndep;

	/* "_" means the matrix for blas */
	SCIP_Real*	y;				/* [n] */
	SCIP_Real*	orig_X_;		/* [n*p] */
	SCIP_Real*	orig_Q_;		/* [p*p] <- (X^t) X */
	SCIP_Real*	orig_q;		/* [p]   <- (X^t) y */
	SCIP_Real	r;

	int*	Mdep;					/* [ndep] */
	int*	groupX;				/* [ndep*p] */

	/* for forward selection */
	int	dim;
	int*	list;					/* [p] */
	SCIP_Real*	a;				/* [dim] */
	SCIP_Real*	a_old;		/* [dim-1] */
	SCIP_Real*	a_new;		/* [dim] */
	SCIP_Real	RSS;			/* residual sum of square */
	SCIP_Real	RSS_new;
	SCIP_Real	AIC;
	SCIP_Real	AIC_new;

	int	ublb;
	int	*Branchz;		/* [3*p] */

	/*
	 *	X: sub matrix of orig_X_ 
	 *	Y:	(X^t X)^-1 
	 * X_new = (X, x_i);
	 * Z: (X_new ^t X_new)^-1
	 *		= ( V   v
	 			 v^t u )
	 */

	SCIP_Real*	Xy;	/* sub vector of orig_q */ 
	SCIP_Real*	X_;	
	SCIP_Real*	Y_;	/* [(dim-1)*(dim-1)] */
	SCIP_Real*	Z_;	/* [dim*dim] */
	SCIP_Real*	W_;	/* [dim*dim] */
	SCIP_Real*	V_;	/* [(dim-1)*(dim-1)] */
	SCIP_Real*	v;		/* [dim-1] */
	SCIP_Real	u;
	
	SCIP_Real*	b;		/* [dim-1] */
	SCIP_Real*	c;		/* [dim-1] */
	SCIP_Real*	d;		/* [n] */

	/* variables */
	SCIP_VAR**	var_a;		/* [p] continuous variables */
	SCIP_VAR**	var_z;		/* [p] 01 variables */
	SCIP_VAR**	var_ep;		/* [n] continuous variables */
	SCIP_VAR*	var_rss;		/* continuous variable, residual sum of squares */
	SCIP_VAR*	var_log;		/* continuous variable, log(rss) */

	/* set solution */ 
	SCIP_Real *ep;
	
	int	nsols;
	int	store;
	SCIP_SOL**	sols;
	SCIP_Real	objval;

	SCIP_SOL*	sol;
	SCIP_Real*	solvals;
	SCIP_Bool	success;
	int			nvars	=	SCIPgetNVars(scip);
	SCIP_VAR**	vars;

	int 	i,j,t,ct;
	int	memo;

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

#if MYPARA_LOG
	printf("forward selection!\n");
#endif

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

	/* get values from probdata */
   probdata = SCIPgetProbData(scip);
   assert(probdata != NULL);

	n	=	SCIPprobdataGetNdatas(probdata);
	p	=	SCIPprobdataGetNexvars(probdata);
	ndep	=	SCIPprobdataGetNdep(probdata);

	y	=	SCIPprobdataGety(probdata);
	orig_X_	=	SCIPprobdataGetX(probdata);
	orig_Q_	=	SCIPprobdataGetQ(probdata);
	orig_q	=	SCIPprobdataGetq(probdata);
	r	=	SCIPprobdataGetr(probdata);

	if( ndep ){
		Mdep		=	SCIPprobdataGetMdep(probdata);
		groupX	=	SCIPprobdataGetgroupX(probdata);
	}else{
		Mdep		=	NULL;
		groupX	=	NULL;
	}

	/* variables */
	var_a		=	SCIPprobdataGetVars_a(probdata);
	var_z		=	SCIPprobdataGetVars_z(probdata);
	var_ep	=	SCIPprobdataGetVars_ep(probdata);
	var_rss	=	SCIPprobdataGetVar_rss(probdata);
	var_log	=	SCIPprobdataGetVar_log(probdata);

	/* get branching info */
	/* alloc */
	SCIP_CALL( SCIPallocBufferArray(scip, &Branchz, 3*p));
	
	GenerateZeroVecInt( 3*p, Branchz);

	for(i=0; i<p; ++i){
		ublb					=	SCIPround(scip, SCIPcomputeVarUbLocal(scip, var_z[i]) 
								+	SCIPcomputeVarLbLocal(scip, var_z[i]));
		*(Branchz+(ublb*p)+i) 	= 	1;
	}

#if MYPARA_LOG
	for(i=0; i<3; i++){
		for(j=0; j<p; j++){
			printf("%d, ", *(Branchz+(i*p)+j));
		}
		newline();
	}
#endif

	if( ndep ){
		for(i=0; i<ndep; i++){
			memo = -1; 
			for(j=0; j<p; j++){
				if( *(groupX+(i*p)+j)==1 ){
					if( *(Branchz+j)==1 ) break;
					if( *(Branchz+p+j)==1 ) memo=j;
					if( j==Mdep[i] ){
						if( memo==-1 ){
							printf("error in heur_backward.c\n");
							stop();
						}
						*(Branchz+p+memo) = 0;
						*(Branchz+memo) = 1;
						break;
					}
				}
			}
		}
	}
	
#if MYPARA_LOG
	printf("linear dependent\n");
	if( ndep ){
		for(i=0; i<3; i++){
			for(j=0; j<p; j++){
				printf("%d, ", *(Branchz+(i*p)+j));
			}
			newline();
		}
	}
#endif
	
	/* alloc */
	SCIP_CALL( SCIPallocBufferArray(scip, &X_, n*p));
	SCIP_CALL( SCIPallocBufferArray(scip, &Xy, p));
	SCIP_CALL( SCIPallocBufferArray(scip, &d, n));
	SCIP_CALL( SCIPallocBufferArray(scip, &list, p));
	
	/* initialize from Branchz */
#if MYPARA_LOG
	printf("initialization\n");
#endif

	GenerateZeroVecInt( p, list);

	dim = 0;
	memo = -1;
	AIC = 1e+06;
	SCIP_CALL( SCIPallocBufferArray(scip, &a_old, dim+1));

	for(i=0; i<p; i++){
		
		if( Branchz[i]==1 ){ /* if z_i is fixed to 0 */
			list[i] = -1;
		}else if( Branchz[p+i]==1 ){ /* if z_i is unfixed */
			list[i] = 0;
		}else if( Branchz[2*p+i]==1 ){ /* if z_i is fixed 1 */
			dim++;
			list[i] = dim;

			if( dim == 1 ){

				a_old[0] = orig_q[i] / mat_( orig_Q_, p, i, i);
				RSS = RSSvalue( 1, a_old, &orig_q[i], r);
				AIC = AICvalue( n, dim, RSS);

				/* update X_ and Xy */
				mydcopy_( &orig_X_[n * i], &X_[n * (dim-1)], n);
				Xy[dim-1] = orig_q[i];

				/* generate Y ( dim = 1 ) */
				SCIP_CALL( SCIPallocBufferArray( scip, &Y_, dim*dim));
				Y_[0] = 1 / mat_( orig_Q_, p, i, i);
		
			}else{
				/* alloc */
				SCIPfreeBufferArray(scip, &a_old);
				SCIP_CALL( SCIPallocBufferArray( scip, &a_old, dim));
				SCIP_CALL( SCIPallocBufferArray( scip, &b, dim-1));
				SCIP_CALL( SCIPallocBufferArray( scip, &c, dim-1));
				SCIP_CALL( SCIPallocBufferArray( scip, &v, dim-1));
				SCIP_CALL( SCIPallocBufferArray( scip, &V_, (dim-1)*(dim-1)));
				SCIP_CALL( SCIPallocBufferArray( scip, &Z_, (dim)*(dim)));
				
				/* 1. b <- X^t x_i */
				dgemv_t( X_, n, dim-1, &orig_X_[n * i], b);
				//printv( dim-1, b);

				/* 2. c <- Y b */
				dgemv_2( Y_, dim-1, dim-1, b, c);
				//printv( dim-1, c);

				/* 3. d <- - X c + x_i */
				dgemv_1( X_, n, dim-1, c, &orig_X_[n * i], -1.0, 1.0, d);
				//printv( n, d);

				/* 4. u <- 1/<x_i, d> */
				u = 1.0 / myddot_( &orig_X_[n * i], d, n);
				//prints(u);
				
				/* 5. v <- - u c */
				mydscal_( c, dim-1, -u, v);
				//printv( dim-1, v);

				/* 6. V <- Y + u c c^t */
				dger_1( Y_, c, c, dim-1, dim-1, u, V_);
				//printM_( V_, dim-1, dim-1);

				/* 7. Z */
				/* V */
				for(j=0; j<(dim-1); j++){
					for(t=0; t<(dim-1); t++){
						*(Z_ + j + (t*dim) ) = mat_( V_, dim-1, j, t);
					}
				}
				/* v */
				for(j=0; j<(dim-1); j++){
					*(Z_ + dim-1 + (j*dim) )  = v[j];
					*(Z_ + j + ((dim-1)*dim)) = v[j];
				}

				/* u */
				*(Z_ + dim-1 + ((dim-1)*dim)) = u;
				//printM_( Z_, dim, dim);

				/* 8. a_old <- Z (Xy) */
				Xy[dim-1] = orig_q[i];
				dgemv_2( Z_, dim, dim, Xy, a_old);
				//printv( dim, a_old);

				RSS = RSSvalue( dim, a_old, Xy, r);
				AIC = AICvalue( n, dim, RSS);

				/* copy */
				SCIPfreeBufferArray(scip, &Y_);
				SCIP_CALL( SCIPallocBufferArray(scip, &Y_, dim*dim));
				mydcopy_( Z_, Y_, dim*dim);
	
				/* update X_ and Xy */
				mydcopy_( &orig_X_[n * i], &X_[n * (dim-1)], n);
				Xy[dim-1] = orig_q[i];

				/* free */
				SCIPfreeBufferArray(scip, &b);
				SCIPfreeBufferArray(scip, &c);
				SCIPfreeBufferArray(scip, &v);
				SCIPfreeBufferArray(scip, &V_);
				SCIPfreeBufferArray(scip, &Z_);
			}

#if MYPARA_LOG
			printf("---> %dth variable, AIC:%f\n", i, AIC);
#endif

		}else{
			printf("error:heur_forward.c\n");
			stop();
		}
	}


	if( dim == 0 ){
#if MYPARA_LOG
		printf("[dim:0]\n");
#endif
		dim++;
		RSS = 1e+06;
		for(i=0; i<p; i++){
			if( list[i] == 0 ){
				a_old[0] = orig_q[i] / mat_( orig_Q_, p, i, i);
				RSS_new = RSSvalue( 1, a_old, &orig_q[i], r);
				if( RSS_new < RSS ){
					RSS = RSS_new;
					memo = i;
				}
#if MYPARA_LOG
			printf("%d: RSS = %f\n", i, RSS_new);
#endif
			}
		}
		
		if( memo < 0 || memo >= p ){
			printf("error in heur_forward.c\n");
			stop();
		}
	
		AIC = AICvalue( n, dim, RSS);
		list[memo] = dim;
		
		/* update X_ and Xy */
		mydcopy_( &orig_X_[n * memo], &X_[n * (dim-1)], n);
		Xy[dim-1] = orig_q[memo];
	
		/* generate Y ( dim = 1 ) */
		SCIP_CALL( SCIPallocBufferArray( scip, &Y_, dim*dim));
		Y_[0] = 1 / mat_( orig_Q_, p, memo, memo);
	
#if MYPARA_LOG
		printf("---> %dth variable, AIC:%f\n", memo, AIC);
#endif
	} /* if ( dim==0 ) */

	while(1){
		dim++;
		memo = -1;
		RSS = 1e+06;
#if MYPARA_LOG
		printf("(dim=%d) ", dim);
		Longline();
#endif

		/* alloc */
		SCIP_CALL( SCIPallocBufferArray( scip, &a_new, dim));
		SCIP_CALL( SCIPallocBufferArray( scip, &a, dim));
		SCIP_CALL( SCIPallocBufferArray( scip, &b, dim-1));
		SCIP_CALL( SCIPallocBufferArray( scip, &c, dim-1));
		SCIP_CALL( SCIPallocBufferArray( scip, &v, dim-1));
		SCIP_CALL( SCIPallocBufferArray( scip, &V_, (dim-1)*(dim-1)));
		SCIP_CALL( SCIPallocBufferArray( scip, &Z_, (dim)*(dim)));
		SCIP_CALL( SCIPallocBufferArray( scip, &W_, (dim)*(dim)));
		
		for(i=0; i<p; i++){
			/*
			 * 1. b <- X^t x_i
			 * 2.	c <- Y b
			 * 3. d <- - X c + x_i
			 * 4. u <- 1 / <x_i, d> 
			 * 5. v <- - u c
			 * 6. V <- Y + u c c^t
			 * 7. Z <- ( V    v
			 	          v^t  u )
			 * 8. a_new <- Z (Xy)
			 */

			if( list[i]==0 ){

				/* 1. b <- X^t x_i */
				dgemv_t( X_, n, dim-1, &orig_X_[n * i], b);
				//printv( dim-1, b);

				/* 2. c <- Y b */
				dgemv_2( Y_, dim-1, dim-1, b, c);
				//printv( dim-1, c);

				/* 3. d <- - X c + x_i */
				dgemv_1( X_, n, dim-1, c, &orig_X_[n * i], -1.0, 1.0, d);
				//printv( n, d);

				/* 4. u <- 1/<x_i, d> */
				u = 1.0 / myddot_( &orig_X_[n * i], d, n);
				//prints(u);
				
				/* 5. v <- - u c */
				mydscal_( c, dim-1, -u, v);
				//printv( dim-1, v);

				/* 6. V <- Y + u c c^t */
				dger_1( Y_, c, c, dim-1, dim-1, u, V_);
				//printM_( V_, dim-1, dim-1);

				/* 7. Z */
				/* V */
				for(j=0; j<(dim-1); j++){
					for(t=0; t<(dim-1); t++){
						*(Z_ + j + (t*dim) ) = mat_( V_, dim-1, j, t);
					}
				}
				/* v */
				for(j=0; j<(dim-1); j++){
					*(Z_ + dim-1 + (j*dim) )  = v[j];
					*(Z_ + j + ((dim-1)*dim)) = v[j];
				}

				/* u */
				*(Z_ + dim-1 + ((dim-1)*dim)) = u;
				//printM_( Z_, dim, dim);

				/* 8. a_new <- Z (Xy) */
				Xy[dim-1] = orig_q[i];
				dgemv_2( Z_, dim, dim, Xy, a_new);
				//printv( dim, a_new);

				/* test */
				RSS_new = RSSvalue( dim, a_new, Xy, r);
				if( RSS_new < RSS ){
					RSS = RSS_new;
					memo = i;
					mydcopy_( Z_, W_, dim*dim);
					mydcopy_( a_new, a, dim);
				}

#if MYPARA_LOG
				printf("%d: RSS = %f\n", i, RSS_new);
#endif

			}
		}

		if( memo < 0 || memo >= p ){
			if( memo == -1 ){
				for(i=0; i<p; i++){
					if( list[i] == 0 ){
						memo = i;
						break;
					}
				}
				if( memo != -1 ){
					printf("error in heur_forward.c\n");
					stop();
				}
			}else{
				printf("error in heur_forward.c\n");
				stop();
			}
		}

		AIC_new = AICvalue( n, dim, RSS);
		if( AIC_new < AIC ){
			AIC = AIC_new;
			list[memo] = dim;

#if MYPARA_LOG
			printf("---> %dth variable, AIC:%f\n", memo, AIC);
#endif

			/* copy and free */
			SCIPfreeBufferArray(scip, &Y_);
			SCIP_CALL( SCIPallocBufferArray(scip, &Y_, dim*dim));
			mydcopy_( W_, Y_, dim*dim);

			SCIPfreeBufferArray(scip, &a_old);
			SCIP_CALL( SCIPallocBufferArray(scip, &a_old, dim));
			mydcopy_( a, a_old, dim);

			/* update X_ and Xy */
			mydcopy_( &orig_X_[n * memo], &X_[n * (dim-1)], n);
			Xy[dim-1] = orig_q[memo];

		}else{
			memo = -1;
			SCIPfreeBufferArray(scip, Y_);
#if MYPARA_LOG
			printf("--> no selection, (AIC:%f)\n", AIC_new);
#endif
		}

		/* free */
		SCIPfreeBufferArray(scip, &a_new);
		SCIPfreeBufferArray(scip, &a);
		SCIPfreeBufferArray(scip, &b);
		SCIPfreeBufferArray(scip, &c);
		SCIPfreeBufferArray(scip, &v);
		SCIPfreeBufferArray(scip, &V_);
		SCIPfreeBufferArray(scip, &Z_);
		SCIPfreeBufferArray(scip, &W_);

		if( memo == -1 ){
			dim--;
			break;
		}
	}

	nsols = SCIPgetNSols(scip);
	
	if( nsols < MP_NUM_SOL ){
		store = 1;
	}else{
		sols = SCIPgetSols(scip);
		objval = AIC;
		nsols = MP_NUM_SOL;

		if( objval < SCIPgetSolOrigObj(scip,sols[nsols-1]) ){
			store = 1;
		}else{
			store = 0;
		}
	}

	if( store ){
		/*  generate solution  */
		/* alloc */
		SCIP_CALL( SCIPallocBufferArray(scip, &ep, n));
		dgemv_1( X_, n, dim, a_old, y, -1.0, 1.0, ep);
		
	
		/* set solution */
		/* alloc */
		SCIP_CALL( SCIPallocBufferArray(scip, &solvals, nvars));
		SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars));
	
		ct=0;
		
		/* a */
		for(i=0; i<p; ++i){
			vars[ct] = var_a[i];
			if( list[i] > 0 ){
				solvals[ct] = a_old[list[i]-1];
			}else{
				solvals[ct] = 0.0;
			}
			ct++;
		}
	
		/* z */
		for(i=0; i<p; i++){
			vars[ct] = var_z[i];
			if( list[i] > 0 ){
				solvals[ct] = 1.0;
			}else{
				solvals[ct] = 0.0;
			}
			ct++;
		}
	
		/* ep */
		for(i=0; i<n; ++i){
			vars[ct]		=	var_ep[i];
			solvals[ct]	=	ep[i];
			ct++;
		}
	
		vars[ct]		=	var_rss;
		solvals[ct] =	myddot_( ep, ep, n);
		ct++;
	
		vars[ct]		=	var_log;
		solvals[ct]	=	log(myddot_( ep, ep, n));
		ct++;
	
		if( ct!=nvars ){
			SCIPerrorMessage("It is unexpected error in set sol,");
			printf("( ct, nvars) = ( %d, %d)", ct, nvars);
			stop();
		}
	
		SCIP_CALL( SCIPcreateSol(scip, &sol, heur));
		SCIP_CALL( SCIPsetSolVals(scip, sol, nvars, vars, solvals));
		SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, FALSE, TRUE, TRUE, &success));

		/* free */
		SCIPfreeBufferArray(scip, &ep);
		SCIPfreeBufferArray(scip, &solvals);
		SCIPfreeBufferArray(scip, &vars);
	}

	/* free */
	SCIPfreeBufferArray(scip, &d);
	SCIPfreeBufferArray(scip, &X_);
	SCIPfreeBufferArray(scip, &Xy);
	SCIPfreeBufferArray(scip, &a_old);
	SCIPfreeBufferArray(scip, &list);
	SCIPfreeBufferArray(scip, &Branchz);

	*result = SCIP_FOUNDSOL;
   return SCIP_OKAY;
}
Esempio n. 27
0
/** reduced cost pricing method of variable pricer for feasible LPs */
static
SCIP_DECL_PRICERREDCOST(pricerRedcostBinpacking)
{  /*lint --e{715}*/
   SCIP* subscip;
   SCIP_PRICERDATA* pricerdata;
   SCIP_CONS** conss;
   SCIP_VAR** vars;
   int* ids;
   SCIP_Bool addvar;

   SCIP_SOL** sols;
   int nsols;
   int s;

   int nitems;
   SCIP_Longint capacity;

   SCIP_Real timelimit;
   SCIP_Real memorylimit;

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

   (*result) = SCIP_DIDNOTRUN;

   /* get the pricer data */
   pricerdata = SCIPpricerGetData(pricer);
   assert(pricerdata != NULL);

   capacity = pricerdata->capacity;
   conss = pricerdata->conss;
   ids = pricerdata->ids;
   nitems = pricerdata->nitems;

   /* get the remaining time and memory limit */
   SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
   if( !SCIPisInfinity(scip, timelimit) )
      timelimit -= SCIPgetSolvingTime(scip);
   SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
   if( !SCIPisInfinity(scip, memorylimit) )
      memorylimit -= SCIPgetMemUsed(scip)/1048576.0;

   /* initialize SCIP */
   SCIP_CALL( SCIPcreate(&subscip) );
   SCIP_CALL( SCIPincludeDefaultPlugins(subscip) );

   /* create problem in sub SCIP */
   SCIP_CALL( SCIPcreateProbBasic(subscip, "pricing") );
   SCIP_CALL( SCIPsetObjsense(subscip, SCIP_OBJSENSE_MAXIMIZE) );

   /* do not abort subproblem on CTRL-C */
   SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );

   /* disable output to console */
   SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );

   /* set time and memory limit */
   SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
   SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );

   SCIP_CALL( SCIPallocMemoryArray(subscip, &vars, nitems) );

   /* initialization local pricing problem */
   SCIP_CALL( initPricing(scip, pricerdata, subscip, vars) );

   SCIPdebugMessage("solve pricer problem\n");

   /* solve sub SCIP */
   SCIP_CALL( SCIPsolve(subscip) );

   sols = SCIPgetSols(subscip);
   nsols = SCIPgetNSols(subscip);
   addvar = FALSE;

   /* loop over all solutions and create the corresponding column to master if the reduced cost are negative for master,
    * that is the objective value i greater than 1.0
    */
   for( s = 0; s < nsols; ++s )
   {
      SCIP_Bool feasible;
      SCIP_SOL* sol;

      /* the soultion should be sorted w.r.t. the objective function value */
      assert(s == 0 || SCIPisFeasGE(subscip, SCIPgetSolOrigObj(subscip, sols[s-1]), SCIPgetSolOrigObj(subscip, sols[s])));

      sol = sols[s];
      assert(sol != NULL);

      /* check if solution is feasible in original sub SCIP */
      SCIP_CALL( SCIPcheckSolOrig(subscip, sol, &feasible, FALSE, FALSE ) );

      if( !feasible )
      {
         SCIPwarningMessage(scip, "solution in pricing problem (capacity <%d>) is infeasible\n", capacity);
         continue;
      }

      /* check if the solution has a value greater than 1.0 */
      if( SCIPisFeasGT(subscip, SCIPgetSolOrigObj(subscip, sol), 1.0) )
      {
         SCIP_VAR* var;
         SCIP_VARDATA* vardata;
         int* consids;
         char strtmp[SCIP_MAXSTRLEN];
         char name[SCIP_MAXSTRLEN];
         int nconss;
         int o;
         int v;

         SCIPdebug( SCIP_CALL( SCIPprintSol(subscip, sol, NULL, FALSE) ) );

         nconss = 0;
         (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "items");

         SCIP_CALL( SCIPallocBufferArray(scip, &consids, nitems) );

         /* check which variables are fixed -> which item belongs to this packing */
         for( o = 0, v = 0; o < nitems; ++o )
         {
            if( !SCIPconsIsEnabled(conss[o]) )
               continue;

            assert(SCIPgetNFixedonesSetppc(scip, conss[o]) == 0);

            if( SCIPgetSolVal(subscip, sol, vars[v]) > 0.5 )
            {
               (void) SCIPsnprintf(strtmp, SCIP_MAXSTRLEN, "_%d", ids[o]);
               strcat(name, strtmp);

               consids[nconss] = o;
               nconss++;
            }
            else
               assert( SCIPisFeasEQ(subscip, SCIPgetSolVal(subscip, sol, vars[v]), 0.0) );

            v++;
         }

         SCIP_CALL( SCIPvardataCreateBinpacking(scip, &vardata, consids, nconss) );

         /* create variable for a new column with objective function coefficient 0.0 */
         SCIP_CALL( SCIPcreateVarBinpacking(scip, &var, name, 1.0, FALSE, TRUE, vardata) );

         /* add the new variable to the pricer store */
         SCIP_CALL( SCIPaddPricedVar(scip, var, 1.0) );
         addvar = TRUE;

         /* change the upper bound of the binary variable to lazy since the upper bound is already enforced due to
          * the objective function the set covering constraint; The reason for doing is that, is to avoid the bound
          * of x <= 1 in the LP relaxation since this bound constraint would produce a dual variable which might have
          * a positive reduced cost
          */
         SCIP_CALL( SCIPchgVarUbLazy(scip, var, 1.0) );

         /* check which variable are fixed -> which orders belong to this packing */
         for( v = 0; v < nconss; ++v )
         {
            assert(SCIPconsIsEnabled(conss[consids[v]]));
            SCIP_CALL( SCIPaddCoefSetppc(scip, conss[consids[v]], var) );
         }

         SCIPdebug(SCIPprintVar(scip, var, NULL) );
         SCIP_CALL( SCIPreleaseVar(scip, &var) );

         SCIPfreeBufferArray(scip, &consids);
      }
      else
         break;
   }

   /* free pricer MIP */
   SCIPfreeMemoryArray(subscip, &vars);

   if( addvar || SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL )
      (*result) = SCIP_SUCCESS;

   /* free sub SCIP */
   SCIP_CALL( SCIPfree(&subscip) );

   return SCIP_OKAY;
}
Esempio n. 28
0
/** LP solution separation method of separator */
static
SCIP_DECL_SEPAEXECLP(sepaExeclpStrongcg)
{  /*lint --e{715}*/
   SCIP_SEPADATA* sepadata;
   SCIP_VAR** vars;
   SCIP_COL** cols;
   SCIP_ROW** rows;
   SCIP_Real* varsolvals;
   SCIP_Real* binvrow;
   SCIP_Real* cutcoefs;
   SCIP_Real cutrhs;
   SCIP_Real cutact;
   SCIP_Real maxscale;
   SCIP_Longint maxdnom;
   int* basisind;
   int* inds;
   int ninds;
   int nvars;
   int ncols;
   int nrows;
   int ncalls;
   int depth;
   int maxdepth;
   int maxsepacuts;
   int ncuts;
   int c;
   int i;
   int cutrank;
   SCIP_Bool success;
   SCIP_Bool cutislocal;
   char normtype;

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

   *result = SCIP_DIDNOTRUN;

   sepadata = SCIPsepaGetData(sepa);
   assert(sepadata != NULL);

   depth = SCIPgetDepth(scip);
   ncalls = SCIPsepaGetNCallsAtNode(sepa);

   /* only call separator, if we are not close to terminating */
   if( SCIPisStopped(scip) )
      return SCIP_OKAY;

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

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

   /* only call separator, if the LP solution is basic */
   if( !SCIPisLPSolBasic(scip) )
      return SCIP_OKAY;

   /* only call separator, if there are fractional variables */
   if( SCIPgetNLPBranchCands(scip) == 0 )
      return SCIP_OKAY;

   /* get variables data */
   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );

   /* get LP data */
   SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
   SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
   if( ncols == 0 || nrows == 0 )
      return SCIP_OKAY;

#if 0 /* if too many columns, separator is usually very slow: delay it until no other cuts have been found */
   if( ncols >= 50*nrows )
      return SCIP_OKAY;
   if( ncols >= 5*nrows )
   {
      int ncutsfound;

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

   /* get the type of norm to use for efficacy calculations */
   SCIP_CALL( SCIPgetCharParam(scip, "separating/efficacynorm", &normtype) );

   /* set the maximal denominator in rational representation of strong CG cut and the maximal scale factor to
    * scale resulting cut to integral values to avoid numerical instabilities
    */
   /**@todo find better but still stable strong CG cut settings: look at dcmulti, gesa3, khb0525, misc06, p2756 */
   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;
   }

   *result = SCIP_DIDNOTFIND;

   /* allocate temporary memory */
   SCIP_CALL( SCIPallocBufferArray(scip, &cutcoefs, nvars) );
   SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );
   SCIP_CALL( SCIPallocBufferArray(scip, &binvrow, nrows) );
   SCIP_CALL( SCIPallocBufferArray(scip, &inds, nrows) );
   varsolvals = NULL; /* allocate this later, if needed */

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

   /* get the maximal number of cuts allowed in a separation round */
   if( depth == 0 )
      maxsepacuts = sepadata->maxsepacutsroot;
   else
      maxsepacuts = sepadata->maxsepacuts;

   SCIPdebugMessage("searching strong CG cuts: %d cols, %d rows, maxdnom=%" SCIP_LONGINT_FORMAT ", maxscale=%g, maxcuts=%d\n",
      ncols, nrows, maxdnom, maxscale, maxsepacuts);

   /* for all basic columns belonging to integer variables, try to generate a strong CG cut */
   ncuts = 0;
   for( i = 0; i < nrows && ncuts < maxsepacuts && !SCIPisStopped(scip) && *result != SCIP_CUTOFF; ++i )
   {
      SCIP_Bool tryrow;

      tryrow = FALSE;
      c = basisind[i];
      if( c >= 0 )
      {
         SCIP_VAR* var;

         assert(c < ncols);
         var = SCIPcolGetVar(cols[c]);
         if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS )
         {
            SCIP_Real primsol;

            primsol = SCIPcolGetPrimsol(cols[c]);
            assert(SCIPgetVarSol(scip, var) == primsol); /*lint !e777*/

            if( SCIPfeasFrac(scip, primsol) >= MINFRAC )
            {
               SCIPdebugMessage("trying strong CG cut for col <%s> [%g]\n", SCIPvarGetName(var), primsol);
               tryrow = TRUE;
            }
         }
      }
#ifdef SEPARATEROWS
      else
      {
         SCIP_ROW* row;

         assert(0 <= -c-1 && -c-1 < nrows);
         row = rows[-c-1];
         if( SCIProwIsIntegral(row) && !SCIProwIsModifiable(row) )
         {
            SCIP_Real primsol;

            primsol = SCIPgetRowActivity(scip, row);
            if( SCIPfeasFrac(scip, primsol) >= MINFRAC )
            {
               SCIPdebugMessage("trying strong CG cut for row <%s> [%g]\n", SCIProwGetName(row), primsol);
               tryrow = TRUE;
            }
         }
      }
#endif

      if( tryrow )
      {
         /* get the row of B^-1 for this basic integer variable with fractional solution value */
         SCIP_CALL( SCIPgetLPBInvRow(scip, i, binvrow, inds, &ninds) );

#ifdef SCIP_DEBUG
         /* initialize variables, that might not have been initialized in SCIPcalcMIR if success == FALSE */
         cutact = 0.0;
         cutrhs = SCIPinfinity(scip);
#endif
         /* create a strong CG cut out of the weighted LP rows using the B^-1 row as weights */
         SCIP_CALL( SCIPcalcStrongCG(scip, BOUNDSWITCH, USEVBDS, ALLOWLOCAL, (int) MAXAGGRLEN(nvars), sepadata->maxweightrange, MINFRAC, MAXFRAC,
               binvrow, inds, ninds, 1.0, cutcoefs, &cutrhs, &cutact, &success, &cutislocal, &cutrank) );
         assert(ALLOWLOCAL || !cutislocal);
         SCIPdebugMessage(" -> success=%u: %g <= %g\n", success, cutact, cutrhs);

         /* if successful, convert dense cut into sparse row, and add the row as a cut */
         if( success && SCIPisFeasGT(scip, cutact, cutrhs) )
         {
            SCIP_VAR** cutvars;
            SCIP_Real* cutvals;
            SCIP_Real cutnorm;
            int cutlen;

            /* if this is the first successful cut, get the LP solution for all COLUMN variables */
            if( varsolvals == NULL )
            {
               int v;

               SCIP_CALL( SCIPallocBufferArray(scip, &varsolvals, nvars) );
               for( v = 0; v < nvars; ++v )
               {
                  if( SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_COLUMN )
                     varsolvals[v] = SCIPvarGetLPSol(vars[v]);
               }
            }
            assert(varsolvals != NULL);

            /* get temporary memory for storing the cut as sparse row */
            SCIP_CALL( SCIPallocBufferArray(scip, &cutvars, nvars) );
            SCIP_CALL( SCIPallocBufferArray(scip, &cutvals, nvars) );

            /* store the cut as sparse row, calculate activity and norm of cut */
            SCIP_CALL( storeCutInArrays(scip, nvars, vars, cutcoefs, varsolvals, normtype,
                  cutvars, cutvals, &cutlen, &cutact, &cutnorm) );

            SCIPdebugMessage(" -> strong CG cut for <%s>: act=%f, rhs=%f, norm=%f, eff=%f, rank=%d\n",
               c >= 0 ? SCIPvarGetName(SCIPcolGetVar(cols[c])) : SCIProwGetName(rows[-c-1]),
               cutact, cutrhs, cutnorm, (cutact - cutrhs)/cutnorm, cutrank);

            if( SCIPisPositive(scip, cutnorm) && SCIPisEfficacious(scip, (cutact - cutrhs)/cutnorm) )
            {
               SCIP_ROW* cut;
               char cutname[SCIP_MAXSTRLEN];

               /* create the cut */
               if( c >= 0 )
                  (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "scg%d_x%d", SCIPgetNLPs(scip), c);
               else
                  (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "scg%d_s%d", SCIPgetNLPs(scip), -c-1);
               SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &cut, sepa, cutname, -SCIPinfinity(scip), cutrhs, cutislocal, FALSE, sepadata->dynamiccuts) );
               SCIP_CALL( SCIPaddVarsToRow(scip, cut, cutlen, cutvars, cutvals) );
               /*SCIPdebug( SCIP_CALL(SCIPprintRow(scip, cut, NULL)) );*/
               SCIProwChgRank(cut, cutrank);

               assert(success);
#ifdef MAKECUTINTEGRAL
               /* try to scale the cut to integral values */
               SCIP_CALL( SCIPmakeRowIntegral(scip, cut, -SCIPepsilon(scip), SCIPsumepsilon(scip),
                     maxdnom, maxscale, MAKECONTINTEGRAL, &success) );
#else
#ifdef MAKEINTCUTINTEGRAL
               /* try to scale the cut to integral values if there are no continuous variables
                *  -> leads to an integral slack variable that can later be used for other cuts
                */
               {
                  int k = 0;
                  while ( k < cutlen && SCIPvarIsIntegral(cutvars[k]) )
                     ++k;
                  if( k == cutlen )
                  {
                     SCIP_CALL( SCIPmakeRowIntegral(scip, cut, -SCIPepsilon(scip), SCIPsumepsilon(scip),
                           maxdnom, maxscale, MAKECONTINTEGRAL, &success) );
                  }
               }
#endif
#endif

#ifndef FORCECUTINTEGRAL
               success = TRUE;
#endif

               if( success )
               {
                  if( !SCIPisCutEfficacious(scip, NULL, cut) )
                  {
                     SCIPdebugMessage(" -> strong CG cut <%s> no longer efficacious: act=%f, rhs=%f, norm=%f, eff=%f\n",
                        cutname, SCIPgetRowLPActivity(scip, cut), SCIProwGetRhs(cut), SCIProwGetNorm(cut),
                        SCIPgetCutEfficacy(scip, NULL, cut));
                     /*SCIPdebug( SCIP_CALL(SCIPprintRow(scip, cut, NULL)) );*/
                     success = FALSE;
                  }
                  else
                  {
                     SCIP_Bool infeasible;

                     SCIPdebugMessage(" -> found strong CG cut <%s>: act=%f, rhs=%f, norm=%f, eff=%f, min=%f, max=%f (range=%f)\n",
                        cutname, SCIPgetRowLPActivity(scip, cut), SCIProwGetRhs(cut), SCIProwGetNorm(cut),
                        SCIPgetCutEfficacy(scip, NULL, cut),
                        SCIPgetRowMinCoef(scip, cut), SCIPgetRowMaxCoef(scip, cut),
                        SCIPgetRowMaxCoef(scip, cut)/SCIPgetRowMinCoef(scip, cut));
                     /*SCIPdebug( SCIP_CALL(SCIPprintRow(scip, cut, NULL)) );*/
                     SCIP_CALL( SCIPaddCut(scip, NULL, cut, FALSE, &infeasible) );
                     if ( infeasible )
                        *result = SCIP_CUTOFF;
                     else
                     {
                        if( !cutislocal )
                        {
                           SCIP_CALL( SCIPaddPoolCut(scip, cut) );
                        }
                        *result = SCIP_SEPARATED;
                     }
                     ncuts++;
                  }
               }
               else
               {
                  SCIPdebugMessage(" -> strong CG cut <%s> couldn't be scaled to integral coefficients: act=%f, rhs=%f, norm=%f, eff=%f\n",
                     cutname, cutact, cutrhs, cutnorm, SCIPgetCutEfficacy(scip, NULL, cut));
               }

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

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

   /* free temporary memory */
   SCIPfreeBufferArrayNull(scip, &varsolvals);
   SCIPfreeBufferArray(scip, &inds);
   SCIPfreeBufferArray(scip, &binvrow);
   SCIPfreeBufferArray(scip, &basisind);
   SCIPfreeBufferArray(scip, &cutcoefs);

   SCIPdebugMessage("end searching strong CG cuts: found %d cuts\n", ncuts);

   sepadata->lastncutsfound = SCIPgetNCutsFound(scip);

   return SCIP_OKAY;
}
Esempio n. 29
0
/** evalutate solution */
SCIP_RETCODE LOPevalSolution(
   SCIP*                 scip                /**< SCIP data structure */
   )
{
   SCIP_PROBDATA* probdata;
   SCIP_VAR*** vars;
   SCIP_SOL* sol;
   int* outDegree;
   int* indices;
   int i;
   int j;
   int n;

   /* get problem data */
   probdata = SCIPgetProbData(scip);
   assert( probdata != NULL );
   assert( probdata->vars != NULL );

   n = probdata->n;
   vars = probdata->vars;
   sol = SCIPgetBestSol(scip);

   if ( sol == NULL )
      printf("\nNo solution found.\n");
   else
   {
      SCIP_CALL( SCIPallocBufferArray(scip, &outDegree, n) );
      SCIP_CALL( SCIPallocBufferArray(scip, &indices, n) );

      /* compute out-degree */
      for (i = 0; i < n; ++i)
      {
	 int deg = 0;
	 for (j = 0; j < n; ++j)
	 {
	    SCIP_Real val;
	    if (j == i)
	       continue;

	    val = SCIPgetSolVal(scip, sol, vars[i][j]);
	    assert( SCIPisIntegral(scip, val) );
	    if ( val < 0.5 )
	       ++deg;
	 }
	 outDegree[i] = deg;
	 indices[i] = i;
      }

      /* sort such that degrees are non-decreasing */
      SCIPsortIntInt(outDegree, indices, n);

      /* output */
      printf("\nFinal order:\n");
      for (i = 0; i < n; ++i)
	 printf("%d ", indices[i]);
      printf("\n");

      SCIPfreeBufferArray(scip, &indices);
      SCIPfreeBufferArray(scip, &outDegree);
   }

   return SCIP_OKAY;
}
Esempio n. 30
0
/** problem reading method of reader */
static
SCIP_DECL_READERREAD(readerReadCip)
{  /*lint --e{715}*/

   CIPINPUT cipinput;
   SCIP_Real objscale;
   SCIP_Real objoffset;
   SCIP_Bool dynamicconss;
   SCIP_Bool dynamiccols;
   SCIP_Bool dynamicrows;

   SCIP_Bool initialvar;
   SCIP_Bool removablevar;
   SCIP_Bool initialcons;
   SCIP_Bool removablecons;
   
   if( NULL == (cipinput.file = SCIPfopen(filename, "r")) )
   {
      SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
      SCIPprintSysError(filename);
      return SCIP_NOFILE;
   }

   cipinput.len = 131071;
   SCIP_CALL( SCIPallocBufferArray(scip, &(cipinput.strbuf), cipinput.len) );

   cipinput.linenumber = 0;
   cipinput.section = CIP_START;
   cipinput.haserror = FALSE;
   cipinput.endfile = FALSE;
   cipinput.readingsize = 65535;

   SCIP_CALL( SCIPcreateProb(scip, filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
   
   SCIP_CALL( SCIPgetBoolParam(scip, "reading/"READER_NAME"/dynamiccols", &dynamiccols) );
   SCIP_CALL( SCIPgetBoolParam(scip, "reading/"READER_NAME"/dynamicconss", &dynamicconss) );
   SCIP_CALL( SCIPgetBoolParam(scip, "reading/"READER_NAME"/dynamicrows", &dynamicrows) );

   initialvar = !dynamiccols;
   removablevar = dynamiccols;
   
   initialcons = !dynamicrows;
   removablecons = dynamicrows;

   objscale = 1.0;
   objoffset = 0.0;

   while( cipinput.section != CIP_END && !cipinput.haserror )
   {
      /* get next input string */
      SCIP_CALL( getInputString(scip, &cipinput) );

      if( cipinput.endfile )
         break;
      
      switch( cipinput.section )
      {
      case CIP_START:
         SCIP_CALL( getStart(scip, &cipinput) );
         break;
      case CIP_STATISTIC:
         SCIP_CALL( getStatistic(scip, &cipinput) );
         break;
      case CIP_OBJECTIVE:
         SCIP_CALL( getObjective(scip, &cipinput, &objscale, &objoffset) );
         break;
      case CIP_VARS:
         SCIP_CALL( getVariable(scip, &cipinput, initialvar, removablevar, objscale) );
         break;
      case CIP_FIXEDVARS:
         SCIP_CALL( getFixedVariables(scip, &cipinput) );
         break;
      case CIP_CONSTRAINTS:
         SCIP_CALL( getConstraints(scip, &cipinput, initialcons, dynamicconss, removablecons) );
         break;
      default:
         SCIPerrorMessage("invalid CIP state\n");
         SCIPABORT();
      } /*lint !e788*/ 
   }

   if( !SCIPisZero(scip, objoffset) && !cipinput.haserror )
   {
      SCIP_VAR* objoffsetvar;

      objoffset *= objscale;
      SCIP_CALL( SCIPcreateVar(scip, &objoffsetvar, "objoffset", objoffset, objoffset, 1.0, SCIP_VARTYPE_CONTINUOUS,
         TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) );
      SCIP_CALL( SCIPaddVar(scip, objoffsetvar) );
      SCIP_CALL( SCIPreleaseVar(scip, &objoffsetvar) );
      SCIPdebugMessage("added variables <objoffset> for objective offset of <%g>\n", objoffset);
   }

   /* close file stream */
   SCIPfclose(cipinput.file);
   
   if( cipinput.section != CIP_END && !cipinput.haserror )
   {
      SCIPerrorMessage("unexpected EOF\n");
   }

   SCIPfreeBufferArray(scip, &cipinput.strbuf);

   if( cipinput.haserror )
      return SCIP_READERROR;

   /* successfully parsed cip format */
   *result = SCIP_SUCCESS;
   return SCIP_OKAY;
}