Originally posted by: SystemAdmin
>
> Thank you Daniel. I have two follow up questions:
>
> If you mean only "the time to create new objects in every callback" by "the additional overhead", then it is not a problem since "Build_Time"s are relatively small. As I was reading my question again, I realized that I couldn't clearly explain myself. My concern is to lose the useful information (variable values, optimal basis, duals, etc..) that can be used in the (re)optimization of next sub-problem and shorten the time (some of the information is going to be valid since feasible space is the same for all sub-problems (i.e. only objective coefficients change)). So, does it (keeping these info) shortens the optimization time if the only difference between two problems is the objective coefficients?
>
OK, I see. In this case re-creating a new environment in each callback invocation will result in losing any sort of warmstart information. You could of course store the warmstart information in some global data and feed it back to the solver after re-creating the environment. But that is essentially the same as working with a global environment :-)
So I would go for what you describe below.
> I am afraid you are right about the tidiness of the "new sub-problem environment" approach, however I think I have a solution to the problems related to parallelism of sub-problem environments. Since Cplex gives each thread an id number, if we create #_of_processors number of sub-problem environments (before cplex.solve()) then each callback calls the sub-problem that is indexed with the cplex_thread_id. Therefore, each sub-problem environment can be simultaneously accessed from only one thread and information of the last solution can be used in the re-optimization (and my programming knowledge is not enough :( to understand whether this makes sense or not?).
>
Yes, that makes a lot of sense and I think in your case is one way to go.
Another (more elegant IMO) way is to not use the ILOLAZYCONSTRAINTCALLBACKX() macro. If you don't use that macro but implement your class manually then you will notice that you have to implement a function duplicateCallback(). This function is used to duplicate the callback for each thread that CPLEX uses. The trick is to not
copy the thread-local environment here but to instead create a
new thread local environment for each thread (untested):
class LazyConstraintCallback :
public IloCplex::LazyConstraintCallbackI
{
// Your callback members here ... IloEnv threadEnv;
// Thread local environment for subproblems. IloModel threadModel;
// Thread local model IloCplex threadCplex;
// Thread local solver
public: LazyConstraintCallback(
/* initializers for your callback members */) :
// Initialize your callback members. ...
// and create a _new_ environment, model, solver for each thread threadEnv(), threadModel(threadEnv), threadCplex(threadModel)
{
} ~LazyConstraintCallback()
{ threadEnv.end();
} CallbackI *duplicateCallback()
const
{
return
new (getEnv()) LazyConstraintCallback(
/* initializers for your callback members */);
}
void main()
{
// separation code, use threadModel and threadCplex to solve the subproblem.
}
};
#CPLEXOptimizers#DecisionOptimization