/** creates a subproblem for subscip by fixing a number of variables */
static
SCIP_RETCODE setupSubproblem(
   SCIP*                 scip,               /**< original SCIP data structure */
   SCIP*                 subscip,            /**< SCIP data structure for the subproblem */
   SCIP_VAR**            subvars,            /**< the variables of the subproblem */
   int*                  selection,          /**< pool of solutions crossover will use */
   SCIP_HEURDATA*        heurdata,           /**< primal heuristic data */
   SCIP_Bool*            success             /**< pointer to store whether the problem was created successfully */
   )
{
   SCIP_SOL** sols;                         /* array of all solutions found so far         */
   int nsols;                               /* number of all solutions found so far        */
   int nusedsols;                           /* number of solutions to use in crossover     */

   int i;
   char consname[SCIP_MAXSTRLEN];

   /* get solutions' data */
   nsols = SCIPgetNSols(scip);
   sols = SCIPgetSols(scip);
   nusedsols = heurdata->nusedsols;

   assert(nusedsols > 1);
   assert(nsols >= nusedsols);

   /* use nusedsols best solutions if randomization is deactivated or there are only nusedsols solutions at hand
    * or a good new solution was found since last call */
   if( !heurdata->randomization || nsols == nusedsols || heurdata->prevlastsol != sols[nusedsols-1] )
   {
      SOLTUPLE* elem;
      SCIP_HEUR* solheur;
      SCIP_Longint solnodenum;
      SCIP_Bool allsame;

      for( i = 0; i < nusedsols; i++ )
         selection[i] = i;
      SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );

      solheur = SCIPsolGetHeur(sols[0]);
      solnodenum = SCIPsolGetNodenum(sols[0]);
      allsame = TRUE;

      /* check, whether all solutions have been found by the same heuristic at the same node; in this case we do not run
       * crossover, since it would probably just optimize over the same space as the other heuristic
       */
      for( i = 1; i < nusedsols; i++ )
      {
         if( SCIPsolGetHeur(sols[i]) != solheur || SCIPsolGetNodenum(sols[i]) != solnodenum )
            allsame = FALSE;
      }
      *success = !allsame && !SCIPhashtableExists(heurdata->hashtable, elem);

      /* check, whether solution tuple has already been tried */
      if( !SCIPhashtableExists(heurdata->hashtable, elem) )
      {
         SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
      }

      /* if solution tuple has already been tried, randomization is allowed and enough solutions are at hand, try
       * to randomize another tuple. E.g., this can happen if the last crossover solution was among the best ones */
      if( !(*success) && heurdata->randomization && nsols > nusedsols )
      {
         SCIP_CALL( selectSolsRandomized(scip, selection, heurdata, success) );
      }

   }
   /* otherwise randomize the set of solutions */
   else
   {
      SCIP_CALL( selectSolsRandomized(scip, selection, heurdata, success) );
   }

   /* no acceptable solution tuple could be created */
   if( !(*success) )
      return SCIP_OKAY;

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

   /* set up the variables of the subproblem */
   SCIP_CALL( fixVariables(scip, subscip, subvars, selection, heurdata, success) );

   /* we copy the rows of the LP, if the enough variables could be fixed and we work on the MIP
      relaxation of the problem */
   if( *success && heurdata->uselprows )
   {
      SCIP_CALL( createRows(scip, subscip, subvars) );
   }

   return SCIP_OKAY;
}
Beispiel #2
0
/** problem writing method of reader */
static
SCIP_DECL_READERWRITE(readerWriteCip)
{  /*lint --e{715}*/
   SCIP_HASHTABLE* varhash = NULL;
   SCIP_READERDATA* readerdata;
   int i;

   assert(reader != NULL);
   assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);

   SCIPinfoMessage(scip, file, "STATISTICS\n");
   SCIPinfoMessage(scip, file, "  Problem name     : %s\n", name);
   SCIPinfoMessage(scip, file, "  Variables        : %d (%d binary, %d integer, %d implicit integer, %d continuous)\n",
      nvars, nbinvars, nintvars, nimplvars, ncontvars);
   SCIPinfoMessage(scip, file, "  Constraints      : %d initial, %d maximal\n", startnconss, maxnconss);

   SCIPinfoMessage(scip, file, "OBJECTIVE\n");
   SCIPinfoMessage(scip, file, "  Sense            : %s\n", objsense == SCIP_OBJSENSE_MINIMIZE ? "minimize" : "maximize");
   if( !SCIPisZero(scip, objoffset) )
      SCIPinfoMessage(scip, file, "  Offset           : %+.15g\n", objoffset);
   if( !SCIPisEQ(scip, objscale, 1.0) )
      SCIPinfoMessage(scip, file, "  Scale            : %.15g\n", objscale);

   if ( nfixedvars > 0 )
   {
      /* set up hash table for variables that have been written property (used for writing out fixed vars in the right order) */
      SCIP_CALL( SCIPhashtableCreate(&varhash, SCIPblkmem(scip), SCIPcalcHashtableSize(10 * (nvars + nfixedvars)), hashGetKeyVar, hashKeyEqVar, hashKeyValVar, NULL) );
   }

   if ( nvars + nfixedvars > 0 )
   {
      SCIPinfoMessage(scip, file, "VARIABLES\n");
   }

   if( nvars > 0 )
   {
      for( i = 0; i < nvars; ++i )
      {
         SCIP_VAR* var;

         var = vars[i];
         assert( var != NULL );
         SCIP_CALL( SCIPprintVar(scip, var, file) );
         if ( varhash != NULL )
         {
            /* add free variable to hashtable */
            if ( ! SCIPhashtableExists(varhash, (void*) var) )
            {
               SCIP_CALL( SCIPhashtableInsert(varhash, (void*) var) );
            }
         }
      }
   }

   readerdata = SCIPreaderGetData(reader);
   assert(readerdata != NULL);

   if( readerdata->writefixedvars && nfixedvars > 0 )
   {
      int nwritten = 0;

      SCIPinfoMessage(scip, file, "FIXED\n");

      /* loop through variables until each has been written after the variables that it depends on have been written; this
       * requires several runs over the variables, but the depth (= number of loops) is usually small. */
      while ( nwritten < nfixedvars )
      {
         SCIPdebugMessage("written %d of %d fixed variables.\n", nwritten, nfixedvars);
         for (i = 0; i < nfixedvars; ++i)
         {
            SCIP_VAR* var;
            SCIP_VAR* tmpvar;

            var = fixedvars[i];
            assert( var != NULL );

            /* skip variables already written */
            if ( SCIPhashtableExists(varhash, (void*) var) )
               continue;

            switch ( SCIPvarGetStatus(var) )
            {
            case SCIP_VARSTATUS_FIXED:

               /* fixed variables can simply be output and added to the hashtable */
               SCIP_CALL( SCIPprintVar(scip, var, file) );
               assert( ! SCIPhashtableExists(varhash, (void*) var) );
               SCIP_CALL( SCIPhashtableInsert(varhash, (void*) var) );
               ++nwritten;

               break;

            case SCIP_VARSTATUS_NEGATED:

               tmpvar = SCIPvarGetNegationVar(var);
               assert( tmpvar != NULL );
               assert( var == SCIPvarGetNegatedVar(tmpvar) );

               /* if the negated variable has been written, we can write the current variable */
               if ( SCIPhashtableExists(varhash, (void*) tmpvar) )
               {
                  SCIP_CALL( SCIPprintVar(scip, var, file) );
                  assert( ! SCIPhashtableExists(varhash, (void*) var) );
                  SCIP_CALL( SCIPhashtableInsert(varhash, (void*) var) );
                  ++nwritten;
               }
               break;

            case SCIP_VARSTATUS_AGGREGATED:

               tmpvar = SCIPvarGetAggrVar(var);
               assert( tmpvar != NULL );

               /* if the aggregating variable has been written, we can write the current variable */
               if ( SCIPhashtableExists(varhash, (void*) tmpvar) )
               {
                  SCIP_CALL( SCIPprintVar(scip, var, file) );
                  assert( ! SCIPhashtableExists(varhash, (void*) var) );
                  SCIP_CALL( SCIPhashtableInsert(varhash, (void*) var) );
                  ++nwritten;
               }
               break;

            case SCIP_VARSTATUS_MULTAGGR:
            {
               SCIP_VAR** aggrvars;
               int naggrvars;
               int j;

               /* get the active representation */
               SCIP_CALL( SCIPflattenVarAggregationGraph(scip, var) );

               naggrvars = SCIPvarGetMultaggrNVars(var);
               aggrvars = SCIPvarGetMultaggrVars(var);
               assert(aggrvars != NULL || naggrvars == 0);

               for (j = 0; j < naggrvars; ++j)
               {
                  if( !SCIPhashtableExists(varhash, (void*) aggrvars[j]) ) /*lint !e613*/
                     break;
               }

               /* if all multi-aggregating variables have been written, we can write the current variable */
               if ( j >= naggrvars )
               {
                  SCIP_CALL( SCIPprintVar(scip, var, file) );
                  assert( ! SCIPhashtableExists(varhash, (void*) var) );
                  SCIP_CALL( SCIPhashtableInsert(varhash, (void*) var) );
                  ++nwritten;
               }
               break;
            }

            case SCIP_VARSTATUS_ORIGINAL:
            case SCIP_VARSTATUS_LOOSE:
            case SCIP_VARSTATUS_COLUMN:
               SCIPerrorMessage("Only fixed variables are allowed to be present in fixedvars list.\n");
               SCIPABORT();
               return SCIP_ERROR; /*lint !e527*/
            }
         }
      }
   }

   if( nconss > 0 )
   {
      SCIPinfoMessage(scip, file, "CONSTRAINTS\n");

      for( i = 0; i < nconss; ++i )
      {
         SCIP_CALL( SCIPprintCons(scip, conss[i], file) );
         SCIPinfoMessage(scip, file, ";\n");
      }
   }
   SCIPinfoMessage(scip, file, "END\n");

   *result = SCIP_SUCCESS;

   if( nfixedvars > 0 )
      SCIPhashtableFree(&varhash);
   else
      assert(varhash == NULL);

   return SCIP_OKAY;
}
/** randomly selects the solutions crossover will use from the pool of all solutions found so far */
static
SCIP_RETCODE selectSolsRandomized(
   SCIP*                 scip,               /**< original SCIP data structure */
   int*                  selection,          /**< pool of solutions crossover uses  */
   SCIP_HEURDATA*        heurdata,           /**< primal heuristic data */
   SCIP_Bool*            success             /**< pointer to store whether the process was successful */
   )
{

   int i;
   int j;
   int lastsol;          /* the worst solution possible to choose */
   int nusedsols;        /* number of solutions which will be chosen */

   SOLTUPLE* elem;
   SCIP_SOL** sols;

   /* initialization */
   nusedsols = heurdata->nusedsols;
   lastsol = SCIPgetNSols(scip);
   sols = SCIPgetSols(scip);
   assert(nusedsols < lastsol);

   i = 0;
   *success = FALSE;

   /* perform at maximum 10 restarts and stop as soon as a new set of solutions is found */
   while( !*success && i < 10 )
   {
      SCIP_Bool validtuple;

      validtuple = TRUE;
      for( j = 0; j < nusedsols && validtuple; j++ )
      {
         int k;
         k = SCIPgetRandomInt(nusedsols-j-1, lastsol-1, &heurdata->randseed);

         /* ensure that the solution does not have a similar source as the others */
         while( k >= nusedsols-j-1 && !solHasNewSource(sols, selection, j, k) )
            k--;

         validtuple = (k >= nusedsols-j-1);
         selection[j] = k;
         lastsol = k;
      }

      if( validtuple )
      {
         /* creates an object ready to be inserted into the hashtable */
         SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );

         /* check whether the randomized set is already in the hashtable, if not, insert it */
         if( !SCIPhashtableExists(heurdata->hashtable, elem) )
         {
            SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
            *success = TRUE;
         }
      }
      i++;
   }

   return SCIP_OKAY;
}