Beispiel #1
0
/* prüft, die Länge der Tour, dabei ist
 * sol ein Array, dass die Werte der Kanten enthält (angeordnet als LU Dreieck),
 * visited ist ein Hilfsarray, dass sich merkt, welche Punkte schon besucht wurden
 * tol ist die numerische Toleranz (vgl. andere Bsp. für Lazy Constraints)
 * */
int getTourLen(IloNumArray sol, IloNumArray visited, IloNum tol, tour_t *tour, bool mip)
{
    int j;
    const int n = sol.getSize();
    const int N = sqrt(n);
    int last = -1;
    int length = 0;
    int current = 0;

    visited.clear();
    visited.add(n, 0.0); // mit 0 initialisieren

    // Problemgröße von 0? Das sollte nicht passieren
    if(n == 0)
    {
        printf(ERROR "argghh! zero! zero length LP representation!\n");
        return (N+1);
    }

    // bis ich wieder da ankomme, wo ich gewesen bin
    while(visited[current] == 0)
    {
        length++;
        visited[current] = length; // notiere Position auf der Stadt

        // suche die nächste Stadt in der Waagerechten des UL Dreiecks
        for(j=0; j<current; j++)
            if(j != last && sol[current*N + j] >= 1.0-tol)
                break;

        // wenn ich nicht abgebrochen habe -> nicht gefunden
        // suche die nächste Stadt in der Senkrechten des UL Dreiecks
        if(j == current)
            for(j = current+1; j < N; j++)
                if(j != last && sol[j*N + current] >= 1.0-tol)
                    break;

        // es gibt keinen Nachbarn ?! Das sollte nicht passieren.
        if(j == N)
        {
            if(mip)
                printf(ERROR "argghh! separated point! no neighbors! everybody panic!\n");
            return (N+1);
        }

        // gehe zur nächsten Stadt
        last = current;
        current = j;

        if(tour != NULL)
            tour->push_back(current);
    }

    // Länge der getroffenen Subtour
    return length;
}
IloNum sumArray(IloNumArray redCosts) { 

	// delcare loop counter:
	IloInt m;

	// default/starting value: 0.
	IloNum arrSum = 0.0;
	
	// loop over the array members
	for (m = 0; m < redCosts.getSize(); m++) {
		
		// add member by member
		arrSum += redCosts[m];
	}

	// return minimum
	return arrSum;

} // END of sumArray
IloNum minMemberValue(IloNumArray redCosts) { 

	// delcare loop counter:
	IloInt m;

	// default/starting minimum: 0.
	IloNum currentMin = 0.0;
	
	// loop over the array members
	for (m = 0; m < redCosts.getSize(); m++) {

		// see if current members improves minimum
		if (redCosts[m] < currentMin) {
			currentMin = redCosts[m];
		}
	}

	// return minimum
	return currentMin;

} // END of minMemberValue				
Beispiel #4
0
bool getCut( IloNumArray& vals, IloNumVarArray& vars, CutMode cutmode, int set, 
						IloCplex::ControlCallbackI::IntegerFeasibilityArray feas, 
						IloRange& cut, int** graph, int* old_winner ){

	int n = vals.getSize()/2;
	
	bool marked[n];
	for( int i = 0; i < n; ++i )
		marked[i] = false;
	
	int winner;
	int count_marked = 0;
	list<int> indices;

	int acc[n][n];//mudar para lista adjacencia
	memset(acc, 0, sizeof(acc));
	
	static int cont=0;
	for( int i = 0; i < n; ++i ){
			if(feas[i+n*set] == IloCplex::ControlCallbackI::Infeasible)
				marked[i] = false;
			else{
				marked[i]=true;
				count_marked++;
			}
		}


		//int cont=0;
		int cnt=0;
		while( count_marked < n ){
			//choose the star node
			cnt++;


			winner = -1;
			for( int i = 0; i < n; ++i ){
				if(old_winner[i+n*set])continue;

				if( !marked[i] ){
					if( winner == -1 ){
						winner = i;
					}
					else if( cutmode == CLQ2B && fabs(vals[i+n*set]-0.5) < fabs(vals[winner+n*set]-0.5) && vals[i+n*set] > 0 && vals[i+n*set] < 1 ){
						winner = i;
					}
					else if( cutmode == CLQ2A && vals[i+n*set] > vals[winner+n*set] && vals[i+n*set] < 1 ){
						winner = i;
					}
				}
			}
			if(winner==-1)return false; //??

			old_winner[winner+n*set]=1;
			++count_marked;
			marked[winner] = true;
			indices.push_back( winner+n*set );
		

			for( int i = 0; i < n; ++i ){
				if( !graph[i][winner] ){
					if( !marked[i] ){
						marked[i] = true;
						++count_marked;
					}
				}
			}
		}
	
	list<int>::iterator it = indices.begin();
	float sum = 0;
	while( it != indices.end() ){
		sum += vals[*it];
		++it;
	}
	for(list<int>::iterator it1 = indices.begin(); it1!= indices.end(); it1++){
		for(list<int>::iterator it2 = indices.begin(); it2!= indices.end(); it2++){
			int v1 = *it1;
			int v2 = *it2;
			if(v1==v2)continue;
			v1 -= n*set;
			v2 -= n*set;
			if(!graph[v1][v2] || !graph[v2][v1]){
				puts("ERRO NAO CLICK");
				printf("%d %d\n", v1, v2);
				exit(-1);
			}
		}
	}
	
	if(sum > 1+0.000001 ){
		it = indices.begin();
		while( it != indices.end() ){
			cut.setLinearCoef( vars[*it], 1 );
			//printf("x[%d] ", *it);
			++it;
		}
		//printf(" <= 1\n");
		return true;
	}
	return false;
}
Beispiel #5
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;
}