Пример #1
0
/** creates and captures a variable bound constraint: lhs <= x + c*y <= rhs
 *
 *  @note the constraint gets captured, hence at one point you have to release it using the method {@link releaseCons()}
 */
JNIEXPORT
jlong JNISCIPCONSVARBOUND(createConsVarbound)(
   JNIEnv*               env,                /**< JNI environment variable */
   jobject               jobj,               /**< JNI class pointer */
   jlong                 jscip,              /**< SCIP data structure */
   jstring               jname,              /**< name of constraint */
   jlong                 jvar,               /**< variable x that has variable bound */
   jlong                 jvbdvar,            /**< binary, integer or implicit integer bounding variable y */
   jdouble               jvbdcoef,           /**< coefficient c of bounding variable y */
   jdouble               jlhs,               /**< left hand side of variable bound inequality */
   jdouble               jrhs,               /**< right hand side of variable bound 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              jmodifiable,        /**< 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              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* var;
   SCIP_VAR* vbdvar;
   jboolean iscopy;

   /* 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, &iscopy);
   if( name == NULL )
      SCIPABORT();

   assert(iscopy);

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

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

   JNISCIP_CALL( SCIPcreateConsVarbound(scip, &cons, name, var, vbdvar, (SCIP_Real)jvbdcoef, (SCIP_Real)jlhs, (SCIP_Real)jrhs, (SCIP_Bool) jinitial, (SCIP_Bool) jseparate, (SCIP_Bool) jenforce, (SCIP_Bool) jcheck, (SCIP_Bool) jpropagate,
	 (SCIP_Bool) jlocal, (SCIP_Bool) jmodifiable, (SCIP_Bool) jdynamic, (SCIP_Bool) jremovable, (SCIP_Bool) jstickingatnode) );

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

   return (jlong)(size_t)cons;
}
/** add branching decisions constraints to the sub SCIP */
static
SCIP_RETCODE addBranchingDecisionConss(
    SCIP* scip, /**< SCIP data structure */
    SCIP* subscip, /**< pricing SCIP data structure */
    SCIP_VAR** vars, /**< variable array of the subscuip oder variables */
    SCIP_CONSHDLR* conshdlr /**< constraint handler for branching data */
) {
    SCIP_CONS** conss;
    SCIP_CONS* cons;
    int nconss;
    int id1;
    int id2;
    CONSTYPE type;

    SCIP_Real vbdcoef;
    SCIP_Real lhs;
    SCIP_Real rhs;

    int c;

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

    /* collect all branching decision constraints */
    conss = SCIPconshdlrGetConss(conshdlr);
    nconss = SCIPconshdlrGetNConss(conshdlr);

    /* loop over all branching decision constraints and apply the branching decision if the corresponding constraint is active */
    for (c = 0; c < nconss; ++c) {
        cons = conss[c];

        /* ignore constraints which are not active since these are not laying on the current active path of the search tree */
        if (!SCIPconsIsActive(cons))
            continue;

        /* collect the two item ids and the branching type (SAME or DIFFER) on which the constraint branched */
        id1 = SCIPgetItemid1Samediff(scip, cons);
        id2 = SCIPgetItemid2Samediff(scip, cons);
        type = SCIPgetTypeSamediff(scip, cons);

        SCIPdebugMessage("create varbound for %s(%d,%d)\n", type == SAME ? "same" : "diff",
                         SCIPprobdataGetIds(SCIPgetProbData(scip))[id1], SCIPprobdataGetIds(SCIPgetProbData(scip))[id2]);

        /* depending on the branching type select the correct left and right hand side for the linear constraint which
         * enforces this branching decision in the pricing problem MIP
         */
        if (type == SAME) {
            lhs = 0.0;
            rhs = 0.0;
            vbdcoef = -1.0;
        } else if (type == DIFFER) {
            lhs = -SCIPinfinity(scip);
            rhs = 1.0;
            vbdcoef = 1.0;
        } else {
            SCIPerrorMessage("unknow constraint type <%d>\n, type");
            return SCIP_INVALIDDATA;
        }

        /* add linear (in that case a variable bound) constraint to pricing MIP depending on the branching type:
         *
         * - branching type SAME:  x1 = x2 <=> x1 - x2 = 0 <=> 0 <= x1 - x2 <= 0
         *
         * - branching type DIFFER:  x1 - x2 <= 1 <=> -inf <= x1 - x2 <= 1
         *
         */
        SCIP_CALL(SCIPcreateConsVarbound(subscip, &cons, SCIPconsGetName(conss[c]),
                                         vars[id1], vars[id2], vbdcoef, lhs, rhs,                                // TODO: Alert! id1 and id2 might not be the correct indices of the vars (if some constraints are skipped)
                                         TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE));

        SCIPdebug(SCIPprintCons(subscip, cons, NULL));

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

    return SCIP_OKAY;
}
Пример #3
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;
}