/* 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; }
void addInitColumn(IloNumVarArray lambda, IloObjective rmpObj, IloRangeArray maintConEng, IloRangeArray removeMod, IloRangeArray convex, IloNumArray2 addXCol, IloNumArray addZCol, const IloNumArray compCosts, const IloNumArray convexityCoef) { // loop counter IloInt t; // counter for objective function coefficient for lambda // variable to be added. IloNum lambdaObjCoef = 0; // function assumes addXCol and addZCol contains proper values. // calculate objective function coefficient lambdaObjCoef for (t = 0; t < TIME_SPAN; t++) { // for each fixed t: scalar product of x[m]* vector and // component costs vector compCosts[m]: lambdaObjCoef += IloScalProd(addXCol[t],compCosts); // also clear the addXCol subarrays as soon as they // have been used addXCol[t].clear(); } // now add this column and it's associated lambda variable to the RMP. lambda.add(IloNumVar(rmpObj(lambdaObjCoef) + maintConEng(addZCol) + removeMod(addZCol) + convex(convexityCoef), 0.0, 1.0)); // clear addZCol num array. addZCol.clear(); } // END of addColumn
void addColumn(IloCplex subSolver, IloNumVarArray2 x, IloNumVarArray z, IloNumVarArray lambda, IloObjective rmpObj, IloRangeArray maintConEng, IloRangeArray removeMod, IloRangeArray convex, IloNumArray2 addXCol, IloNumArray addZCol, const IloNumArray compCosts, const IloNumArray convexityCoef) { // loop counter IloInt t; // counter for objective function coefficient for lambda // variable to be added. IloNum lambdaObjCoef = 0; // extract subproblem-optimal solution values // (into IloNumArrays addXCol (2d) and addZCol (1d)). // z values: subSolver.getValues(addZCol,z); //cout << endl << endl << "z = " << endl << addZCol << endl; //cin.get(); // !!! OBS !!! // here we might want to save these z values some column pool's custom-nitted class // array. Or to be specific, we want to add the indexes for NON-ZERO-ENTRIES in addZCol // to our class that keep place of columns. // E.g., given variable lambda(m)_(q_m), we want to know in our own class object, // given (m)(q_m), the indexes of non-zeros in that Z column. // and for each t... for (t = 0; t < TIME_SPAN; t++) { // x values: subSolver.getValues(addXCol[t],x[t]); //cout << endl << endl << "x[t=" << t << "] =" << endl << addXCol[t] << endl; } //cin.get(); // calculate objective function coefficient lambdaObjCoef for (t = 0; t < TIME_SPAN; t++) { // for each fixed t: scalar product of x[m]* vector and // component costs vector compCosts[m]: lambdaObjCoef += IloScalProd(addXCol[t],compCosts); // also clear the addXCol subarrays as soon as they // have been used addXCol[t].clear(); } // now add this column and it's associated lambda variable to the RMP. lambda.add(IloNumVar(rmpObj(lambdaObjCoef) + maintConEng(addZCol) + removeMod(addZCol) + convex(convexityCoef), 0.0, 1.0)); // clear addZCol num array. addZCol.clear(); } // END of addColumn
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; }
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(); }
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(); }
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
void makeCuts(const IloNumVarArray vars, IloExprArray lhs, IloNumArray rhs) { IloNumVar x11, x12, x13, x14, x15; IloNumVar x21, x22, x23, x24, x25; IloNumVar x31, x32, x33, x34, x35; IloNumVar x41, x42, x43, x44, x45; IloNumVar x51, x52, x53, x54, x55; IloNumVar w11, w12, w13, w14, w15; IloNumVar w21, w22, w23, w24, w25; IloNumVar w31, w32, w33, w34, w35; IloNumVar w41, w42, w43, w44, w45; IloNumVar w51, w52, w53, w54, w55; IloInt num = vars.getSize(); for (IloInt i = 0; i < num; i++) { if ( strcmp(vars[i].getName(), "X11") == 0 ) x11 = vars[i]; else if ( strcmp(vars[i].getName(), "X12") == 0 ) x12 = vars[i]; else if ( strcmp(vars[i].getName(), "X13") == 0 ) x13 = vars[i]; else if ( strcmp(vars[i].getName(), "X14") == 0 ) x14 = vars[i]; else if ( strcmp(vars[i].getName(), "X15") == 0 ) x15 = vars[i]; else if ( strcmp(vars[i].getName(), "X21") == 0 ) x21 = vars[i]; else if ( strcmp(vars[i].getName(), "X22") == 0 ) x22 = vars[i]; else if ( strcmp(vars[i].getName(), "X23") == 0 ) x23 = vars[i]; else if ( strcmp(vars[i].getName(), "X24") == 0 ) x24 = vars[i]; else if ( strcmp(vars[i].getName(), "X25") == 0 ) x25 = vars[i]; else if ( strcmp(vars[i].getName(), "X31") == 0 ) x31 = vars[i]; else if ( strcmp(vars[i].getName(), "X32") == 0 ) x32 = vars[i]; else if ( strcmp(vars[i].getName(), "X33") == 0 ) x33 = vars[i]; else if ( strcmp(vars[i].getName(), "X34") == 0 ) x34 = vars[i]; else if ( strcmp(vars[i].getName(), "X35") == 0 ) x35 = vars[i]; else if ( strcmp(vars[i].getName(), "X41") == 0 ) x41 = vars[i]; else if ( strcmp(vars[i].getName(), "X42") == 0 ) x42 = vars[i]; else if ( strcmp(vars[i].getName(), "X43") == 0 ) x43 = vars[i]; else if ( strcmp(vars[i].getName(), "X44") == 0 ) x44 = vars[i]; else if ( strcmp(vars[i].getName(), "X45") == 0 ) x45 = vars[i]; else if ( strcmp(vars[i].getName(), "X51") == 0 ) x51 = vars[i]; else if ( strcmp(vars[i].getName(), "X52") == 0 ) x52 = vars[i]; else if ( strcmp(vars[i].getName(), "X53") == 0 ) x53 = vars[i]; else if ( strcmp(vars[i].getName(), "X54") == 0 ) x54 = vars[i]; else if ( strcmp(vars[i].getName(), "X55") == 0 ) x55 = vars[i]; else if ( strcmp(vars[i].getName(), "W11") == 0 ) w11 = vars[i]; else if ( strcmp(vars[i].getName(), "W12") == 0 ) w12 = vars[i]; else if ( strcmp(vars[i].getName(), "W13") == 0 ) w13 = vars[i]; else if ( strcmp(vars[i].getName(), "W14") == 0 ) w14 = vars[i]; else if ( strcmp(vars[i].getName(), "W15") == 0 ) w15 = vars[i]; else if ( strcmp(vars[i].getName(), "W21") == 0 ) w21 = vars[i]; else if ( strcmp(vars[i].getName(), "W22") == 0 ) w22 = vars[i]; else if ( strcmp(vars[i].getName(), "W23") == 0 ) w23 = vars[i]; else if ( strcmp(vars[i].getName(), "W24") == 0 ) w24 = vars[i]; else if ( strcmp(vars[i].getName(), "W25") == 0 ) w25 = vars[i]; else if ( strcmp(vars[i].getName(), "W31") == 0 ) w31 = vars[i]; else if ( strcmp(vars[i].getName(), "W32") == 0 ) w32 = vars[i]; else if ( strcmp(vars[i].getName(), "W33") == 0 ) w33 = vars[i]; else if ( strcmp(vars[i].getName(), "W34") == 0 ) w34 = vars[i]; else if ( strcmp(vars[i].getName(), "W35") == 0 ) w35 = vars[i]; else if ( strcmp(vars[i].getName(), "W41") == 0 ) w41 = vars[i]; else if ( strcmp(vars[i].getName(), "W42") == 0 ) w42 = vars[i]; else if ( strcmp(vars[i].getName(), "W43") == 0 ) w43 = vars[i]; else if ( strcmp(vars[i].getName(), "W44") == 0 ) w44 = vars[i]; else if ( strcmp(vars[i].getName(), "W45") == 0 ) w45 = vars[i]; else if ( strcmp(vars[i].getName(), "W51") == 0 ) w51 = vars[i]; else if ( strcmp(vars[i].getName(), "W52") == 0 ) w52 = vars[i]; else if ( strcmp(vars[i].getName(), "W53") == 0 ) w53 = vars[i]; else if ( strcmp(vars[i].getName(), "W54") == 0 ) w54 = vars[i]; else if ( strcmp(vars[i].getName(), "W55") == 0 ) w55 = vars[i]; } lhs.add(x21 - x22); rhs.add(0.0); lhs.add(x22 - x23); rhs.add(0.0); lhs.add(x23 - x24); rhs.add(0.0); lhs.add(2.08*x11 + 2.98*x21 + 3.47*x31 + 2.24*x41 + 2.08*x51 + 0.25*w11 + 0.25*w21 + 0.25*w31 + 0.25*w41 + 0.25*w51); rhs.add(20.25); lhs.add(2.08*x12 + 2.98*x22 + 3.47*x32 + 2.24*x42 + 2.08*x52 + 0.25*w12 + 0.25*w22 + 0.25*w32 + 0.25*w42 + 0.25*w52); rhs.add(20.25); lhs.add(2.08*x13 + 2.98*x23 + 3.47*x33 + 2.24*x43 + 2.08*x53 + 0.25*w13 + 0.25*w23 + 0.25*w33 + 0.25*w43 + 0.25*w53); rhs.add(20.25); lhs.add(2.08*x14 + 2.98*x24 + 3.47*x34 + 2.24*x44 + 2.08*x54 + 0.25*w14 + 0.25*w24 + 0.25*w34 + 0.25*w44 + 0.25*w54); rhs.add(20.25); lhs.add(2.08*x15 + 2.98*x25 + 3.47*x35 + 2.24*x45 + 2.08*x55 + 0.25*w15 + 0.25*w25 + 0.25*w35 + 0.25*w45 + 0.25*w55); rhs.add(16.25); }
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; }
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(); }