Example #1
0
/** adds coefficient to linear constraint (if it is not zero) */
JNIEXPORT
void JNISCIPCONSLINEAR(addCoefLinear)(
   JNIEnv*               env,                /**< JNI environment variable */
   jobject               jobj,               /**< JNI class pointer */
   jlong                 jscip,              /**< SCIP data structure */
   jlong                 jcons,              /**< constraint data */
   jlong                 jvar,               /**< variable of constraint entry */
   jdouble               val                 /**< coefficient of constraint entry */
   )
{
   SCIP* scip;
   SCIP_CONS* cons;
   SCIP_VAR* var;

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

   /* convert JNI pointer into C pointer */
   cons = (SCIP_CONS*) (size_t) jcons;
   assert( cons != NULL);

   /* convert JNI pointer into C pointer */
   var = (SCIP_VAR*) (size_t) jvar;
   assert(var != NULL);

   JNISCIP_CALL( SCIPaddCoefLinear(scip, cons, var, (SCIP_Real) val) );
}
Example #2
0
/** creates and captures a linear constraint
 *  in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
 *  method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
 *
 *  @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
 *
 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
 */
JNIEXPORT
jlong JNISCIPCONSLINEAR(createConsBasicLinear)(
   JNIEnv*               env,                /**< JNI environment variable */
   jobject               jobj,               /**< JNI class pointer */
   jlong                 jscip,              /**< SCIP data structure */
   jstring               jname,              /**< name of constraint */
   jint                  jnvars,             /**< number of nonzeros in the constraint */
   jlongArray            jvars,              /**< array with variables of constraint entries */
   jdoubleArray          jvals,              /**< array with coefficients of constraint entries */
   jdouble               jlhs,               /**< left hand side of constraint */
   jdouble               jrhs                /**< right hand side of constraint */
   )
{
   SCIP* scip;
   SCIP_CONS* cons;
   const char* name;
   int nvars;

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

   /* create linear constraint with zero variables */
   JNISCIP_CALL( SCIPcreateConsBasicLinear(scip, &cons, name, 0, NULL, NULL, (SCIP_Real) jlhs, (SCIP_Real) jrhs) );

   /* convert JNI integer into integer */
   nvars = (int)jnvars;

   if( nvars > 0 )
   {
      jlong* vars;
      jdouble* vals;
      int v;

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

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

      for( v = 0; v < nvars; ++v )
      {
         JNISCIP_CALL( SCIPaddCoefLinear(scip, cons, (SCIP_VAR*)(size_t)vars[v], (SCIP_Real)vals[v]));
      }

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

   /* relase string object */
   (*env)->ReleaseStringUTFChars(env, jname, name);

   return (jlong)(size_t)cons;
}
Example #3
0
/** creates and captures a linear constraint
 *
 *  @note the constraint gets captured, hence at one point you have to release it using the method {@link releaseCons()}
 */
JNIEXPORT
jlong JNISCIPCONSLINEAR(createConsLinear)(
   JNIEnv*               env,                /**< JNI environment variable */
   jobject               jobj,               /**< JNI class pointer */
   jlong                 jscip,              /**< SCIP data structure */
   jstring               jname,              /**< name of constraint */
   jint                  jnvars,             /**< number of nonzeros in the constraint */
   jlongArray            jvars,              /**< array with variables of constraint entries */
   jdoubleArray          jvals,              /**< array with coefficients of constraint entries */
   jdouble               jlhs,               /**< left hand side of constraint */
   jdouble               jrhs,               /**< right hand side of constraint */
   jboolean              initial,            /**< should the LP relaxation of constraint be in the initial LP?
                                              *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
   jboolean              separate,           /**< should the constraint be separated during LP processing?
                                              *   Usually set to TRUE. */
   jboolean              enforce,            /**< should the constraint be enforced during node processing?
                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
   jboolean              check,              /**< should the constraint be checked for feasibility?
                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
   jboolean              propagate,          /**< should the constraint be propagated during node processing?
                                              *   Usually set to TRUE. */
   jboolean              local,              /**< is constraint only valid locally?
                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
   jboolean              modifiable,         /**< is constraint modifiable (subject to column generation)?
                                              *   Usually set to FALSE. In column generation applications, set to TRUE if pricing
                                              *   adds coefficients to this constraint. */
   jboolean              dynamic,            /**< is constraint subject to aging?
                                              *   Usually set to FALSE. Set to TRUE for own cuts which
                                              *   are seperated as constraints. */
   jboolean              removable,          /**< 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              stickingatnode      /**< 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;
   int nvars;

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

   /* create linear constraint with zero variables */
   JNISCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, 0, NULL, NULL, (SCIP_Real) jlhs, (SCIP_Real) jrhs,
         (SCIP_Bool) initial, (SCIP_Bool) separate, (SCIP_Bool) enforce, (SCIP_Bool) check, (SCIP_Bool) propagate,
         (SCIP_Bool) local, (SCIP_Bool) modifiable, (SCIP_Bool) dynamic, (SCIP_Bool) removable, (SCIP_Bool) stickingatnode) );

   /* convert JNI integer into integer */
   nvars = (int)jnvars;

   if( nvars > 0 )
   {
      jlong* vars;
      jdouble* vals;
      int v;

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

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

      for( v = 0; v < nvars; ++v )
      {
         JNISCIP_CALL( SCIPaddCoefLinear(scip, cons, (SCIP_VAR*)(size_t)vars[v], (SCIP_Real)vals[v]));
      }

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

   /* relase string object */
   (*env)->ReleaseStringUTFChars(env, jname, name);

   return (jlong)(size_t)cons;
}
Example #4
0
/** method for either Farkas or Redcost pricing */
static
SCIP_RETCODE pricing(
   SCIP*                 scip,               /**< SCIP data structure */
   SCIP_PRICER*          pricer,             /**< pricer */
   SCIP_Real*            lowerbound,         /**< lowerbound pointer */
   SCIP_Bool             farkas              /**< TRUE: Farkas pricing; FALSE: Redcost pricing */
   )
{
   SCIP_PRICERDATA* pricerdata; /* the data of the pricer */
   SCIP_PROBDATA* probdata;
   GRAPH* graph;
   SCIP_VAR* var;
   PATH* path;
   SCIP_Real* edgecosts;  /* edgecosts of the current subproblem */
   char varname[SCIP_MAXSTRLEN];
   SCIP_Real newlowerbound = -SCIPinfinity(scip);
   SCIP_Real redcost;   /* reduced cost */
   int tail;
   int e;
   int t;
   int i;

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

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

   /* get problem data */
   probdata = SCIPgetProbData(scip);
   assert(probdata != NULL);

   SCIPdebugMessage("solstat=%d\n", SCIPgetLPSolstat(scip));

   if( !farkas && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
      newlowerbound = SCIPgetSolTransObj(scip, NULL);

   SCIPdebug( SCIP_CALL( SCIPprintSol(scip, NULL, NULL, FALSE) ) );

# if 0
   if ( pricerdata->lowerbound <= 4 )
   {
      char label[SCIP_MAXSTRLEN];
      (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "X%g.gml", pricerdata->lowerbound);
      SCIP_CALL( SCIPprobdataPrintGraph(scip, label , NULL, TRUE) );
      pricerdata->lowerbound++;
   }
#endif
   /* get the graph*/
   graph = SCIPprobdataGetGraph(probdata);

   /* get dual solutions and save them in mi and pi */
   for( t = 0; t < pricerdata->realnterms; ++t )
   {
      if( farkas )
      {
	 pricerdata->mi[t] = SCIPgetDualfarkasLinear(scip, pricerdata->pathcons[t]);
      }
      else
      {
         pricerdata->mi[t] = SCIPgetDualsolLinear(scip, pricerdata->pathcons[t]);
         assert(!SCIPisNegative(scip, pricerdata->mi[t]));
      }
   }

   for( e = 0; e < pricerdata->nedges; ++e )
   {
      if( !pricerdata->bigt )
      {
         for( t = 0; t < pricerdata->realnterms; ++t )
         {
            if( farkas )
	    {
               pricerdata->pi[t * pricerdata->nedges + e] = SCIPgetDualfarkasLinear(
                  scip, pricerdata->edgecons[t * pricerdata->nedges + e]);
	    }
            else
	    {
               pricerdata->pi[t * pricerdata->nedges + e] = SCIPgetDualsolLinear(
                  scip, pricerdata->edgecons[t * pricerdata->nedges + e]);
	    }
         }
      }
      else
      {
         if( farkas )
	 {
	    pricerdata->pi[e] = SCIPgetDualfarkasLinear(
               scip, pricerdata->edgecons[e]);
	 }
	 else
	 {
	    pricerdata->pi[e] = SCIPgetDualsolLinear(
               scip, pricerdata->edgecons[e]);
	 }
      }
   }

   SCIP_CALL( SCIPallocMemoryArray(scip, &path, graph->knots) );
   SCIP_CALL( SCIPallocMemoryArray(scip, &edgecosts, pricerdata->nedges) );

   if( pricerdata->bigt )
   {
      for( e = 0; e < pricerdata->nedges; ++e )
      {
         edgecosts[e] = (-pricerdata->pi[e]);
      }
   }
   /* find shortest r-t (r root, t terminal) paths and create corresponding variables iff reduced cost < 0 */
   for( t = 0; t < pricerdata->realnterms; ++t )
   {
      for( e = 0; e < pricerdata->nedges; ++e )
      {
	 if( !pricerdata->bigt )
	 {
            edgecosts[e] = (-pricerdata->pi[t * pricerdata->nedges + e]);
	 }

         assert(!SCIPisNegative(scip, edgecosts[e]));
      }

      for( i = 0; i < graph->knots; i++ )
         graph->mark[i] = 1;

      graph_path_exec(scip, graph, FSP_MODE, pricerdata->root, edgecosts, path);

      /* compute reduced cost of shortest path to terminal t */
      redcost = 0.0;
      tail = pricerdata->realterms[t];
      while( tail != pricerdata->root )
      {
         redcost += edgecosts[path[tail].edge];
	 tail = graph->tail[path[tail].edge];
      }
      redcost -= pricerdata->mi[t];

      if( !farkas && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
      {
         newlowerbound += redcost;
      }
      /* check if reduced cost < 0 */
      if( SCIPisNegative(scip, redcost) )
      {
	 /* create variable to the shortest path (having reduced cost < 0) */
         var = NULL;
	 sprintf(varname, "PathVar%d_%d", t, pricerdata->ncreatedvars[t]);
         ++(pricerdata->ncreatedvars[t]);

         SCIP_CALL( SCIPcreateVarBasic(scip, &var, varname, 0.0, SCIPinfinity(scip), 0.0, SCIP_VARTYPE_CONTINUOUS) );
         SCIP_CALL( SCIPaddPricedVar(scip, var, -redcost) );
         tail = pricerdata->realterms[t];
         while( tail != pricerdata->root )
         {
            /* add variable to constraints */
	    if( !pricerdata->bigt )
	    {
	       SCIP_CALL( SCIPaddCoefLinear(scip, pricerdata->edgecons[t * pricerdata->nedges + path[tail].edge], var, 1.0) );
	    }
	    else
	    {
	       SCIP_CALL( SCIPaddCoefLinear(scip, pricerdata->edgecons[path[tail].edge], var, 1.0) );
	    }

	    tail = graph->tail[path[tail].edge];
         }
         SCIP_CALL( SCIPaddCoefLinear(scip, pricerdata->pathcons[t], var, 1.0) );
      }
   }

   if( !farkas && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
      *lowerbound = newlowerbound;

   SCIPfreeMemoryArray(scip, &edgecosts);
   SCIPfreeMemoryArray(scip, &path);

   return SCIP_OKAY;
}
Example #5
0
/** main procedure of the zeroobj heuristic, creates and solves a sub-SCIP */
SCIP_RETCODE SCIPapplyZeroobj(
   SCIP*                 scip,               /**< original SCIP data structure                                        */
   SCIP_HEUR*            heur,               /**< heuristic data structure                                            */
   SCIP_RESULT*          result,             /**< result data structure                                               */
   SCIP_Real             minimprove,         /**< factor by which zeroobj should at least improve the incumbent      */
   SCIP_Longint          nnodes              /**< node limit for the subproblem                                       */
   )
{
   SCIP*                 subscip;            /* the subproblem created by zeroobj              */
   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_HEURDATA*        heurdata;           /* heuristic's private data structure              */
   SCIP_EVENTHDLR*       eventhdlr;          /* event handler for LP events                     */

   SCIP_Real cutoff;                         /* objective cutoff for the subproblem             */
   SCIP_Real timelimit;                      /* time limit for zeroobj subproblem              */
   SCIP_Real memorylimit;                    /* memory limit for zeroobj subproblem            */
   SCIP_Real large;

   int nvars;                                /* number of original problem's variables          */
   int i;

   SCIP_Bool success;
   SCIP_Bool valid;
   SCIP_RETCODE retcode;
   SCIP_SOL** subsols;
   int nsubsols;

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

   assert(nnodes >= 0);
   assert(0.0 <= minimprove && minimprove <= 1.0);

   *result = SCIP_DIDNOTRUN;

   /* only call heuristic once at the root */
   if( SCIPgetDepth(scip) <= 0 && SCIPheurGetNCalls(heur) > 0 )
      return SCIP_OKAY;

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

   /* only call the heuristic if we do not have an incumbent  */
   if( SCIPgetNSolsFound(scip) > 0 && heurdata->onlywithoutsol )
      return SCIP_OKAY;

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

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

   *result = SCIP_DIDNOTFIND;

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

   /* different methods to create sub-problem: either copy LP relaxation or the CIP with all constraints */
   valid = FALSE;

   /* copy complete SCIP instance */
   SCIP_CALL( SCIPcopy(scip, subscip, varmapfw, NULL, "zeroobj", TRUE, FALSE, TRUE, &valid) );
   SCIPdebugMessage("Copying the SCIP instance was %s complete.\n", valid ? "" : "not ");

   /* create event handler for LP events */
   eventhdlr = NULL;
   SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecZeroobj, NULL) );
   if( eventhdlr == NULL )
   {
      SCIPerrorMessage("event handler for "HEUR_NAME" heuristic not found.\n");
      return SCIP_PLUGINNOTFOUND;
   }

   /* determine large value to set variables to */
   large = SCIPinfinity(scip);
   if( !SCIPisInfinity(scip, 0.1 / SCIPfeastol(scip)) )
      large = 0.1 / SCIPfeastol(scip);

   /* get variable image and change to 0.0 in sub-SCIP */
   for( i = 0; i < nvars; i++ )
   {
      SCIP_Real adjustedbound;
      SCIP_Real lb;
      SCIP_Real ub;
      SCIP_Real inf;
      
      subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
      SCIP_CALL( SCIPchgVarObj(subscip, subvars[i], 0.0) );

      lb = SCIPvarGetLbGlobal(subvars[i]);
      ub = SCIPvarGetUbGlobal(subvars[i]);
      inf = SCIPinfinity(subscip);

      /* adjust infinite bounds in order to avoid that variables with non-zero objective 
       * get fixed to infinite value in zeroobj subproblem
       */
      if( SCIPisInfinity(subscip, ub ) )
      {
         adjustedbound = MAX(large, lb+large);
         adjustedbound = MIN(adjustedbound, inf);
         SCIP_CALL( SCIPchgVarUbGlobal(subscip, subvars[i], adjustedbound) );
      }
      if( SCIPisInfinity(subscip, -lb ) )
      {
         adjustedbound = MIN(-large, ub-large);
         adjustedbound = MAX(adjustedbound, -inf);
         SCIP_CALL( SCIPchgVarLbGlobal(subscip, subvars[i], adjustedbound) );
      }
   }

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

   /* 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 limits for the subproblem */
   SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nnodes) );
   SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
   SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );
   SCIP_CALL( SCIPsetIntParam(subscip, "limits/solutions", 1) );

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

   /* disable expensive techniques that merely work on the dual bound */

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

   /* disable expensive presolving */
   SCIP_CALL( SCIPsetPresolving(subscip, SCIP_PARAMSETTING_FAST, TRUE) );
   if( !SCIPisParamFixed(subscip, "presolving/maxrounds") )
   {
      SCIP_CALL( SCIPsetIntParam(subscip, "presolving/maxrounds", 50) );
   }

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

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

   /* 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", 10) );
   }

   /* disable feaspump and fracdiving */
   if( !SCIPisParamFixed(subscip, "heuristics/feaspump/freq") )
   {
      SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/feaspump/freq", -1) );
   }
   if( !SCIPisParamFixed(subscip, "heuristics/fracdiving/freq") )
   {
      SCIP_CALL( SCIPsetIntParam(subscip, "heuristics/fracdiving/freq", -1) );
   }

   /* restrict LP iterations */
   SCIP_CALL( SCIPsetLongintParam(subscip, "lp/iterlim", 2*heurdata->maxlpiters / MAX(1,nnodes)) );
   SCIP_CALL( SCIPsetLongintParam(subscip, "lp/rootiterlim", heurdata->maxlpiters) );

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

   /* if there is already a solution, add an objective cutoff */
   if( SCIPgetNSols(scip) > 0 )
   {
      SCIP_Real upperbound;
      SCIP_CONS* origobjcons;
#ifndef NDEBUG
      int nobjvars;
      nobjvars = 0;
#endif

      cutoff = SCIPinfinity(scip);
      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( SCIPcreateConsLinear(subscip, &origobjcons, "objbound_of_origscip", 0, NULL, NULL, -SCIPinfinity(subscip), cutoff,
            TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
      for( i = 0; i < nvars; ++i)
      {
         if( !SCIPisFeasZero(subscip, SCIPvarGetObj(vars[i])) )
         {
            SCIP_CALL( SCIPaddCoefLinear(subscip, origobjcons, subvars[i], SCIPvarGetObj(vars[i])) );
#ifndef NDEBUG
            nobjvars++;
#endif
         }
      }
      SCIP_CALL( SCIPaddCons(subscip, origobjcons) );
      SCIP_CALL( SCIPreleaseCons(subscip, &origobjcons) );
      assert(nobjvars == SCIPgetNObjVars(scip));
   }

   /* catch LP events of sub-SCIP */
   SCIP_CALL( SCIPtransformProb(subscip) );
   SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_NODESOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, NULL) );

   SCIPdebugMessage("solving subproblem: nnodes=%"SCIP_LONGINT_FORMAT"\n", nnodes);
   retcode = SCIPsolve(subscip);

   /* drop LP events of sub-SCIP */
   SCIP_CALL( SCIPdropEvent(subscip, SCIP_EVENTTYPE_NODESOLVED, 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 zeroobj 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 || heurdata->addallsols); ++i )
   {
      SCIP_CALL( createNewSol(scip, subscip, subvars, heur, subsols[i], &success) );
      if( success )
         *result = SCIP_FOUNDSOL;
   }

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

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

   return SCIP_OKAY;
}
Example #6
0
/* standard "main" method for mex interface */
void mexFunction(
   int                   nlhs,               /* number of expected outputs */
   mxArray*              plhs[],             /* array of pointers to output arguments */
   int                   nrhs,               /* number of inputs */
   const mxArray*        prhs[]              /* array of pointers to input arguments */
   )
{
   SCIP* scip;
   SCIP_VAR** vars;
   SCIP_Real* objs;
   SCIP_Real* lhss;
   SCIP_Real* rhss;
   SCIP_Real* lbs;
   SCIP_Real* ubs;
   SCIP_Real* matrix;
   SCIP_Real* bestsol;
   SCIP_Real* objval;
   char* vartypes;
   char objsense[SCIP_MAXSTRLEN];

   int nvars;
   int nconss;
   int stringsize;
   int i;

   if( SCIPmajorVersion() < 2 )
   {
      mexErrMsgTxt("SCIP versions less than 2.0 are not supported\n");
      return;
   }

   /* initialize SCIP */
   SCIP_CALL_ABORT( SCIPcreate(&scip) );

   /* output SCIP information */
   SCIPprintVersion(scip, NULL);

   /* include default SCIP plugins */
   SCIP_CALL_ABORT( SCIPincludeDefaultPlugins(scip) );

   if( nlhs != 2 || nrhs != 8 )
      mexErrMsgTxt("invalid number of parameters. Call as [bestsol, objval] = matscip(matrix, lhs, rhs, obj, lb, ub, vartype, objsense)\n");

   if( mxIsSparse(prhs[0]) )
      mexErrMsgTxt("sparse matrices are not supported yet"); /* ???????? of course this has to change */

   /* get linear constraint coefficient matrix */
   matrix = mxGetPr(prhs[0]);
   if( matrix == NULL )
      mexErrMsgTxt("matrix must not be NULL");
   if( mxGetNumberOfDimensions(prhs[0]) != 2 )
      mexErrMsgTxt("matrix must have exactly two dimensions");

   /* get dimensions of matrix */
   nconss = mxGetM(prhs[0]);
   nvars = mxGetN(prhs[0]);
   assert(nconss > 0);
   assert(nvars > 0);

   /* get left hand sides of linear constraints */
   lhss = mxGetPr(prhs[1]);
   if( mxGetM(prhs[1]) != nconss )
      mexErrMsgTxt("dimension of left hand side vector does not match matrix dimension");
   assert(lhss != NULL);

   /* get right hand sides of linear constraints */
   rhss = mxGetPr(prhs[2]);
   if( mxGetM(prhs[2]) != nconss )
      mexErrMsgTxt("dimension of right hand side vector does not match matrix dimension");
   assert(rhss != NULL);

   /* get objective coefficients */
   objs = mxGetPr(prhs[3]);
   if( mxGetM(prhs[3]) != nvars )
      mexErrMsgTxt("dimension of objective coefficient vector does not match matrix dimension");

   /* get lower bounds of variables */
   lbs = mxGetPr(prhs[4]);
   if( mxGetM(prhs[4]) != nvars )
      mexErrMsgTxt("dimension of lower bound vector does not match matrix dimension");

   /* get upper bounds of variables */
   ubs = mxGetPr(prhs[5]);
   if( mxGetM(prhs[5]) != nvars )
      mexErrMsgTxt("dimension of upper bound vector does not match matrix dimension");

   /* allocate memory for variable type characters */
   SCIP_CALL_ABORT( SCIPallocMemoryArray(scip, &vartypes, nvars+1) );

   /* get variable types */
   if( mxGetString(prhs[6], vartypes, nvars+1)  != 0 )
      mexErrMsgTxt("Error when parsing variable types, maybe a wrong vector dimension?");

   /* get objective sense */
   stringsize = mxGetNumberOfElements(prhs[7]);
   if( stringsize != 3 )
      mexErrMsgTxt("objective sense must be a three character word: \"max\" or \"min\"");
   if( mxGetString(prhs[7], objsense, stringsize+1) != 0)
      mexErrMsgTxt("Error when parsing objective sense string");
   if( strcmp(objsense,"max") != 0 && strcmp(objsense,"min") != 0 )
      mexErrMsgTxt("objective sense must be either \"max\" or \"min\"");

   /* get output parameters */
   plhs[0] = mxCreateDoubleMatrix(nvars, 1, mxREAL);
   bestsol = mxGetPr(plhs[0]);
   plhs[1] = mxCreateDoubleScalar(mxREAL);
   objval  = mxGetPr(plhs[1]);

   /* create SCIP problem */
   SCIP_CALL_ABORT( SCIPcreateProb(scip, "mex_prob", NULL, NULL, NULL, NULL, NULL, NULL, NULL) );

   /* allocate memory for variable array */
   SCIP_CALL_ABORT( SCIPallocMemoryArray(scip, &vars, nvars) );

   /* create variables */
   for( i = 0; i < nvars; ++i)
   {
      SCIP_VARTYPE vartype;
      char varname[SCIP_MAXSTRLEN];

      /* convert vartype character to SCIP vartype */
      if( vartypes[i] == 'i' )
         vartype = SCIP_VARTYPE_INTEGER;
      else if( vartypes[i] == 'b' )
         vartype = SCIP_VARTYPE_BINARY;
      else if( vartypes[i] == 'c' )
         vartype = SCIP_VARTYPE_CONTINUOUS;
      else
         mexErrMsgTxt("unkown variable type");

      /* variables get canonic names x_i */
      (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "x_%d", i);

      /* create variable object and add it to SCIP */
      SCIP_CALL_ABORT( SCIPcreateVar(scip, &vars[i], varname, lbs[i], ubs[i], objs[i],
            vartype, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
      assert(vars[i] != NULL);
      SCIP_CALL_ABORT( SCIPaddVar(scip, vars[i]) );
   }

   /* create linear constraints */
   for( i = 0; i < nconss; ++i )
   {
      SCIP_CONS* cons;
      char consname[SCIP_MAXSTRLEN];
      int j;

      /* constraints get canonic names cons_i */
      (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cons_%d", i);

      /* create empty linear constraint */
      SCIP_CALL_ABORT( SCIPcreateConsLinear(scip, &cons, consname, 0, NULL, NULL, lhss[i], rhss[i],
            TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );

      /* add non-zero coefficients to linear constraint */
      for( j = 0; j < nvars; ++j )
      {
         if( !SCIPisFeasZero(scip, matrix[i+j*nconss]) )
         {
            SCIP_CALL_ABORT( SCIPaddCoefLinear(scip, cons, vars[j], matrix[i+j*nconss]) );
         }
      }

      /* add constraint to SCIP and release it */
      SCIP_CALL_ABORT( SCIPaddCons(scip, cons) );
      SCIP_CALL_ABORT( SCIPreleaseCons(scip, &cons) );
   }

   /* set objective sense in SCIP */
   if( strcmp(objsense,"max") == 0)
   {
      SCIP_CALL_ABORT( SCIPsetObjsense(scip, SCIP_OBJSENSE_MAXIMIZE) );
   }
   else if( strcmp(objsense,"min") == 0)
   {
      SCIP_CALL_ABORT( SCIPsetObjsense(scip, SCIP_OBJSENSE_MINIMIZE) );
   }
   else
      /* this should have been caught earlier when parsing objsense */
      mexErrMsgTxt("unkown objective sense");

   /* solve SCIP problem */
   SCIP_CALL_ABORT( SCIPsolve(scip) );

   /* if SCIP found a solution, pass it back into MATLAB output parameters */
   if( SCIPgetNSols > 0 )
   {
      SCIP_SOL* scipbestsol;

      /* get incumbent solution vector */
      scipbestsol = SCIPgetBestSol(scip);
      assert(scipbestsol != NULL);

      /* get objective value of incumbent solution */
      *objval = SCIPgetSolOrigObj(scip, scipbestsol);
      assert(!SCIPisInfinity(scip, REALABS(*objval)));

      /* copy solution values into output vector */
      for( i = 0; i < nvars; ++i )
         bestsol[i] = SCIPgetSolVal(scip,scipbestsol,vars[i]);
   }

   /* release variables */
   for( i = 0; i < nvars; ++i )
   {
      SCIP_CALL_ABORT( SCIPreleaseVar(scip, &vars[i]) );
   }

   /* free memory for variable arrays */
   SCIPfreeMemoryArray(scip, &vartypes);
   SCIPfreeMemoryArray(scip, &vars);

   /* deinitialize SCIP */
   SCIP_CALL_ABORT( SCIPfree(&scip) );

   /* check for memory leaks */
   BMScheckEmptyMemory();

   return;
}
/** 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* values;
    SCIP_Longint* weights;
    SCIP_Longint* capacities;
    int nbins;
    int b;

    SCIP_Real timelimit;
    SCIP_Real memorylimit;

    SCIP_Real dualHallBound;

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

    (*result) = SCIP_DIDNOTRUN;

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

    capacities = pricerdata->capacities;
    conss = pricerdata->conss;
    ids = pricerdata->ids;
    values = pricerdata->values;
    weights = pricerdata->weights;
    nitems = pricerdata->nitems;
    nbins = pricerdata->nbins;

    dualHallBound = 0.0;

    // run pricing problem for each bin
    for (b = 0; b < nbins; ++b) {

        // assert(SCIPgetDualsolLinear(scip, conss[nitems+b])<= 0);
        // TODO edit if correct objsense
        dualHallBound -= SCIPgetDualsolLinear(scip, conss[nitems+b]);

        if (b < nbins-1 && capacities[b+1] == capacities[b])
            continue;

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

        /* free sub SCIP */
        SCIP_CALL(SCIPcreateProb(subscip, "pricing", NULL, NULL, NULL, NULL, NULL, NULL, NULL));
        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, b));

        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("solution in pricing problem (capacity <%d>) is infeasible\n", capacities[b]);
                continue;
            }

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

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

                nconss = 0;
                totalvalue = 0.0;
                totalweight = 0.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;
                        totalvalue+= values[o];
                        totalweight += weights[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, -totalvalue, 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));
                }

                /* add variable to hall constraints */
                for (v = 0; v <= b; v++) {
                    SCIP_CALL(SCIPaddCoefLinear(scip, conss[nitems+v], var, 1.0));
                    if (totalweight <= capacities[v] && v < b && capacities[b] != capacities[b+1])
                        break;
                }

                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;
}
Example #8
0
/** branching execution method for fractional LP solutions */
static
SCIP_DECL_BRANCHEXECLP(branchExeclpStp)
{  /*lint --e{715}*/
   SCIP_PROBDATA* probdata;
   SCIP_CONS* consin;
   SCIP_CONS* consout;
   SCIP_NODE* vertexin;
   SCIP_NODE* vertexout;
   SCIP_VAR** edgevars;
   SCIP_Real estimatein;
   SCIP_Real estimateout;
   GRAPH* g;
   int e;
   int branchvertex;

   assert(branchrule != NULL);
   assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
   assert(scip != NULL);
   assert(result != NULL);

   SCIPdebugMessage("Execlp method of Stp branching\n ");
   estimatein = SCIPgetUpperbound(scip);
   estimateout = SCIPgetUpperbound(scip);
   *result = SCIP_DIDNOTRUN;

   /* get problem data */
   probdata = SCIPgetProbData(scip);
   assert(probdata != NULL);

   /* get graph */
   g = SCIPprobdataGetGraph(probdata);
   assert(g != NULL);


   /* get vertex to branch on */
   SCIP_CALL( selectBranchingVertex(scip, &branchvertex) );

   if( branchvertex == UNKNOWN )
   {
      SCIPdebugMessage("Branching did not run \n");
      return SCIP_OKAY;
   }

   edgevars = SCIPprobdataGetEdgeVars(scip);

   /* create constraints */
   SCIP_CALL( SCIPcreateConsLinear(scip, &consin, "consin", 0,
         NULL, NULL, 1.0, 1.0,
         TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );

   SCIP_CALL( SCIPcreateConsLinear(scip, &consout, "consout", 0,
         NULL, NULL, 0.0, 0.0,
         TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE) );

   for( e = g->inpbeg[branchvertex]; e != EAT_LAST; e = g->ieat[e] )
   {
      SCIP_CALL( SCIPaddCoefLinear(scip, consin,  edgevars[e], 1.0) );
      SCIP_CALL( SCIPaddCoefLinear(scip, consout, edgevars[e], 1.0) );
      SCIP_CALL( SCIPaddCoefLinear(scip, consout, edgevars[flipedge(e)], 1.0) );
   }

   /* create the child nodes */
   SCIP_CALL( SCIPcreateChild(scip, &vertexin, 1.0, estimatein) );

   SCIP_CALL( SCIPcreateChild(scip, &vertexout, 1.0, estimateout) );

   assert(vertexin != NULL);
   assert(vertexout != NULL);

   SCIP_CALL( SCIPaddConsNode(scip, vertexin, consin, NULL) );
   SCIP_CALL( SCIPaddConsNode(scip, vertexout, consout, NULL) );

   /* relase constraints */
   SCIP_CALL( SCIPreleaseCons(scip, &consin) );
   SCIP_CALL( SCIPreleaseCons(scip, &consout) );

   SCIPdebugMessage("Branched on stp vertex %d \n", branchvertex);

   *result = SCIP_BRANCHED;


   return SCIP_OKAY;
}