ILOHEURISTICCALLBACK1(Rounddown, IloNumVarArray, vars) {
   IntegerFeasibilityArray feas;
   IloNumArray             obj;
   IloNumArray             x;
   try {
      feas = IntegerFeasibilityArray(getEnv());
      obj  = IloNumArray(getEnv());
      x    = IloNumArray(getEnv());
      getFeasibilities(feas, vars);
      getObjCoefs     (obj , vars);
      getValues       (x   , vars);

      IloNum objval = getObjValue();
      IloInt cols   = vars.getSize();
      for (IloInt j = 0; j < cols; j++) {
         // Set the fractional variable to zero and update the objective value
         if ( feas[j] == Infeasible ) {
            objval -= x[j] * obj[j];
            x[j] = 0.0;
         }
      }
      setSolution(vars, x, objval);
   }
   catch (...) {
      feas.end();
      obj.end();
      x.end();
      throw;
   }
   feas.end();
   obj.end();
   x.end();
}
Exemple #2
0
ILOBRANCHCALLBACK1(MyBranch, IloNumVarArray, vars) {
   if ( getBranchType() != BranchOnVariable )
      return;

   // Branch on var with largest objective coefficient
   // among those with largest infeasibility

   IloNumArray x;
   IloNumArray obj;
   IntegerFeasibilityArray feas;

   try {
      x    = IloNumArray(getEnv());
      obj  = IloNumArray(getEnv());
      feas = IntegerFeasibilityArray(getEnv());
      getValues(x, vars);
      getObjCoefs(obj, vars);
      getFeasibilities(feas, vars);

      IloInt bestj  = -1;
      IloNum maxinf = 0.0;
      IloNum maxobj = 0.0;
      IloInt cols = vars.getSize();
      for (IloInt j = 0; j < cols; j++) {
         if ( feas[j] == Infeasible ) {
            IloNum xj_inf = x[j] - IloFloor (x[j]);
            if ( xj_inf > 0.5 )
               xj_inf = 1.0 - xj_inf;
            if ( xj_inf >= maxinf                              &&
                 (xj_inf > maxinf || IloAbs (obj[j]) >= maxobj)  ) {
               bestj  = j;
               maxinf = xj_inf;
               maxobj = IloAbs (obj[j]);
            }
         }
      }

      if ( bestj >= 0 ) {
         makeBranch(vars[bestj], x[bestj], IloCplex::BranchUp,   getObjValue());
         makeBranch(vars[bestj], x[bestj], IloCplex::BranchDown, getObjValue());
      }
   }
   catch (...) {
      x.end();
      obj.end();
      feas.end();
      throw;
   }
   x.end();
   obj.end();
   feas.end();
}
ILOCPLEXGOAL1(MyBranchGoal, IloNumVarArray, vars) {
   IloNumArray x;
   IloNumArray obj;
   IntegerFeasibilityArray feas;

   x    = IloNumArray(getEnv());
   obj  = IloNumArray(getEnv());
   feas = IntegerFeasibilityArray(getEnv());
   getValues(x, vars);
   getObjCoefs(obj, vars);
   getFeasibilities(feas, vars);

   IloInt bestj  = -1;
   IloNum maxinf = 0.0;
   IloNum maxobj = 0.0;
   IloInt cols = vars.getSize();
   for (IloInt j = 0; j < cols; j++) {
      if ( feas[j] == Infeasible ) {
         IloNum xj_inf = x[j] - IloFloor (x[j]);
         if ( xj_inf > 0.5 )
            xj_inf = 1.0 - xj_inf;
         if ( xj_inf >= maxinf                             &&
             (xj_inf > maxinf || IloAbs (obj[j]) >= maxobj)  ) {
            bestj  = j;
            maxinf = xj_inf;
            maxobj = IloAbs (obj[j]);
         }
      }
   }

   IloCplex::Goal res;
   if ( bestj >= 0 ) {
      res = AndGoal(OrGoal(vars[bestj] >= IloFloor(x[bestj])+1,
                           vars[bestj] <= IloFloor(x[bestj])),
                    this);
   }

   x.end();
   obj.end();
   feas.end();

   return res;
}
Exemple #4
0
int
main(int argc, char **argv)
{
   char const *modelfile = NULL;
   int jobs = 0;
   char const **machine = 0;

#if defined(USE_MPI)
   int numprocs, rank;

   // Initialize MPI.
   // We must have at least three processors (master and 2 workers) and
   // the master must have rank 0.
   MPI_Init(&argc, &argv);
   MPI_Comm_size (MPI_COMM_WORLD, &numprocs);
   if ( numprocs < 3 ) {
      fprintf (stderr, "Invalid number of processors (%d)\n", numprocs);
      abort ();
   }
   MPI_Comm_rank (MPI_COMM_WORLD, &rank);
   if ( rank != 0 ) {
      fprintf (stderr, "Master must have rank 0!\n");
      MPI_Finalize ();
      abort ();
   }
   machine = new char const*[numprocs];
   for (int i = 0; i < numprocs; ++i)
      machine[i] = "mpimachine";
   jobs = numprocs - 1;
#elif defined(USE_PROCESS)
   // The default binary is CPLEX but that can be overwritten
   // by command line arguments.
   char const *bin = "cplex";

   machine = new char const *[argc];

#elif defined(USE_TCPIP)
   machine = new char const *[argc];
#else
#   error "No transport type selected"
#endif


   // Parse the command line.
   Worker::OUTPUT output = Worker::OUTPUT_SILENT;
   double absgap = 1e-6;
   for (int i = 1; i < argc; ++i) {
      if ( strncmp (argv[i], "-model=", 7) == 0 )
         modelfile = argv[i] + 7;
#if defined(USE_MPI)
      // no MPI specific commands supported
#elif defined(USE_PROCESS)
      // For process transport
      // - machine=<command> specifies the name of a machine to which
      //   we connect (via ssh)
      // -bin=<binary> specifies the binary to execute (default is "cplex")
      else if ( strncmp (argv[i], "-machine=", 9) == 0 )
         machine[jobs++] = argv[i] + 9;
      else if ( strncmp (argv[i], "-bin=", 5) == 0 )
         bin = argv[i] + 5;
#elif defined(USE_TCPIP)
      // For TCP/IP process
      // -address=<host>:<port> specifies a worker address to which to
      //  connect
      else if ( strncmp (argv[i], "-address=", 9) == 0 )
         machine[jobs++] = argv[i];
#endif
      // Further arguments
      // -absgap=<gap>     stop if that absolute gap is reached
      // -output-prefixed  prefix all worker output by the worker number
      // -output-log       output worker log messages
      else if ( strncmp (argv[i], "-absgap=", 8) == 0 )
         absgap = strtod (argv[i] + 8, NULL);
      else if ( strcmp (argv[i], "-output-prefixed") == 0 )
         output = Worker::OUTPUT_PREFIXED;
      else if ( strcmp (argv[i], "-output-log") == 0 )
         output = Worker::OUTPUT_LOG;
   }

   // Validate arguments.
   if ( !modelfile )
      throw "No model file specified with -model=<modelfile>";
   if ( jobs < 1 )
      throw "Invalid job count";
   
   // Find the place at which to find the shared object that implements
   // the user function. On Windows the path to the current directory is
   // likely to contain blanks, so better quote it.
   char cwd[MAX_PATH_LEN];
   char usrfunc[MAX_PATH_LEN];
   getcwd (cwd, sizeof (cwd));
   usrfunc[0] = 0;
#ifdef _WIN32
   strcat (usrfunc, "-libpath=\"");
   strcat (usrfunc, cwd);
   strcat (usrfunc, "\"");
#else
   strcat (usrfunc, "-libpath=");
   strcat (usrfunc, cwd);
#endif

   IloEnv env;
   SolveState state;

   // Initialize the workers.
   // The main thing to do here is to set up the connection arguments
   // for the IloCplex constructor. Once we have them we just instantiate
   // the Worker class. The constructor for this class will also start
   // an asynchronous solve immediately.
   Worker **workers = new Worker*[jobs];
   for (int i = 0; i < jobs; ++i) {
      char const *transport = 0;
      char const *args[16];
      int nextarg = 0;

#if defined(USE_MPI)
      char rankbuf[256];

      sprintf (rankbuf, "-remoterank=%d", i + 1);
      transport = "mpitransport";
      args[nextarg++] = rankbuf;
#elif defined(USE_PROCESS)
      char logbuf[1024];

      transport = "processtransport";
      // If the machine is not "localhost" then use ssh to connect to
      // this machine. Otherwise just fork a process on the local
      // machine.
      if ( machine[i] != NULL && strcmp (machine[i], "localhost") != 0 ) {
         args[nextarg++] = "/usr/bin/ssh";
         args[nextarg++] = machine[i];
      }
      args[nextarg++] = bin;
      args[nextarg++] = "-worker=process";
      if ( machine[i] != NULL )
         args[nextarg++] = "-stdio";
      else
         args[nextarg++] = "-namedpipes=.";
      args[nextarg++] = usrfunc;
      args[nextarg++] = "-userfunction=iloparmipopt_userfunction=REGISTER_USERFUNCTION";
      sprintf (logbuf, "-logfile=server%d.log", i);
      args[nextarg++] = logbuf;
#elif defined(USE_TCPIP)
      transport = "tcpiptransport";
      args[nextarg++] = machine[i];
#endif


      std::cout << "Initializing worker for " << machine[i] << std::endl;
      try {
         workers[i] = new Worker(env, i, &state,
                                 transport, nextarg, args,
                                 modelfile, output, 1e-5);
      } catch (...) {
         while (--i >= 0)
            delete workers[i];
         delete[] workers;
         throw;
      }
   }
   delete[] machine;

   try {
      // At this point all workers have been started and are
      // solving the problem. We just wait until either the first
      // worker has finished or if the best known global primal and dual
      // bounds are close enough.
      IloObjective::Sense const objsen = workers[0]->getObjectiveSense();
      int active = jobs;
      int frequency = 10000; // Print current bounds every two seconds.
      while (active > 0) {
         // Check if we should stop all solves.
         // We stop them if the absolute mipgap is reached.
         if ( state.primal.valid && state.dual.valid &&
              ((objsen == IloObjective::Minimize &&
                state.dual.bound + absgap >= state.primal.bound) ||
               (objsen == IloObjective::Maximize &&
                state.dual.bound - absgap <= state.primal.bound)) )
         {
            std::cout << "Stopping criterion reached. Stopping all pending solves."
                      << std::endl;
            for (int i = 0; i < jobs; ++i)
               workers[i]->kill();
            break;
         }
         if ( --frequency == 0 ) {
            std::cout << "dual=" << state.dual.bound << ", "
                      << "primal=" << state.primal.bound
                      << std::endl;
            frequency = 10000;
         }

         // Loop over all solvers and test if they are still running.
         for (int i = 0; i < jobs; ++i) {
            if ( !workers[i]->isRunning() ) {
               // The job is finished. We have a solution, so kill all
               // others.
               --active;
               std::cout << "First job (" << i << ") is finished, killing the rest"
                         << std::endl;
               for (int j = 0; j < jobs; ++j) {
                  if ( j != i ) {
                     workers[j]->kill();
                     --active;
                  }
               }
               break;
            }
         }
         // Sleep a little so that we do not poll the workers like crazy.
         millisleep (10);
      }

      // All workers have finished or have been killed. Join them.
      // For each worker we print its status, its dettime and its bounds.
      for (int i = 0; i < jobs; ++i) {
         double obj = -IloInfinity;
         bool const result = workers[i]->join();
         if ( !result ) {
            // No feasible solution found (yet) on this machine.
            // Just set objective function to a very big value
            obj = (objsen == IloObjective::Minimize) ? IloInfinity : -IloInfinity;
         }
         else {
            obj = workers[i]->getObjective();
         }

         std::cout << "Job " << i << ": " << obj << ", stat " << workers[i]->getStatus()
                   << std::endl
                   << "\t" << workers[i]->getDetTime() << ", "
                   << workers[i]->getDual() << ", "
                   << workers[i]->getPrimal() << std::endl;
      }

      // Fetch the x vector from the solver that produced the best
      // primal bound.
      int const bestidx = state.primal.idx;
      if ( bestidx < 0 ) {
         std::cout << "No solution (model infeasible)" << std::endl;
      }
      else {
         IloNumArray x = workers[bestidx]->getX();
         std::cout << "Optimal solution:" << std::endl;
         for (IloInt c = 0; c < x.getSize(); ++c)
            std::cout << "x[" << c << "]: " << x[c] << std::endl;
         x.end();
      }

      // Release the workers.
      for (int i = jobs - 1; i >= 0; --i)
         delete workers[i];
      delete[] workers;

      env.end();
   } catch (...) {
      // In case of any error we still need to delete the workers.
      // This is to make sure that we properly disconnect from the
      // remote workers. The destructor of a worker will automatically
      // kill and join the worker if that was not already done.
      for (int i = jobs - 1; i >= 0; --i)
         delete workers[i];
      delete[] workers;
      throw;
   }

#ifdef USE_MPI
   MPI_Finalize ();
#endif


   return 0;
}
ILOBRANCHCALLBACK1(SOSbranch, IloSOS1Array, sos) {
    IloNumArray    x;
    IloNumVarArray var;

    try {
        IloInt i;
        x   = IloNumArray(getEnv());
        var = IloNumVarArray(getEnv());
        IloNum bestx = EPS;
        IloInt besti = -1;
        IloInt bestj = -1;
        IloInt num = sos.getSize();

        for (i = 0; i < num; i++) {
            if ( getFeasibility(sos[i]) == Infeasible ) {
                var.clear();
                sos[i].getVariables(var);
                getValues(x, var);
                IloInt n = var.getSize();
                for (IloInt j = 0; j < n; j++) {
                    IloNum inf = IloAbs(x[j] - IloRound(x[j]));
                    if ( inf > bestx ) {
                        bestx = inf;
                        besti = i;
                        bestj = j;
                    }
                }
            }
        }

        if ( besti >= 0 ) {
            IloCplex::BranchDirectionArray dir;
            IloNumArray                    val;
            try {
                dir = IloCplex::BranchDirectionArray(getEnv());
                val = IloNumArray(getEnv());
                var.clear();
                sos[besti].getVariables(var);
                IloInt n = var.getSize();
                for (IloInt j = 0; j < n; j++) {
                    if ( j != bestj ) {
                        dir.add(IloCplex::BranchDown);
                        val.add(0.0);
                    } else {
                        dir.add(IloCplex::BranchUp);
                        val.add(1.0);
                    }
                }
                makeBranch(var,        val, dir,                  getObjValue());
                makeBranch(var[bestj], 0.0, IloCplex::BranchDown, getObjValue());
            }
            catch (...) {
                dir.end();
                val.end();
                throw;
            }
            dir.end();
            val.end();
        }
    }
    catch (...) {
        var.end();
        x.end();
        throw;
    }

    var.end();
    x.end();
}