Originally posted by: SystemAdmin
Are you still looking into this? If so, then I suggest to take a look into the CplexServer.java example shipped with CPLEX. This shows how you can create a model and transfer it over an ObjectStream. Similarly, you could create a model and transfer it into an instance of IloCplex. And I think this will work in parallel to some degree.
The following program builds up two disjoint parts of the model in two different threads (I just used two different IloModeler instances and did not bother to actually create the threads) and then collects the per-thread models into one instance of IloCplex:
import ilog.cplex.*;
import ilog.concert.*;
public final class ParMod {
public static void main(String[] args) {
try {
// First "thread".
IloCplexModeler m1 = new IloCplexModeler();
IloNumVar[] x1 = new IloNumVar[2];
x1[0] = m1.numVar(0, 1, "x1");
x1[1] = m1.numVar(0, 1, "x2");
IloRange[] rng1 = new IloRange[1];
rng1[0] = m1.ge(m1.sum(x1[0], x1[1]), 1, "c1"); // x1 + x2 >= 1
// Second "thread".
IloCplexModeler m2 = new IloCplexModeler();
IloNumVar[] x2 = new IloNumVar[2];
x2[0] = m1.numVar(0, 1, "x3");
x2[1] = m1.numVar(0, 1, "x4");
IloRange[] rng2 = new IloRange[1];
rng2[0] = m2.ge(m2.sum(x2[0], x2[1]), 2, "c2"); // x3 + x4 >= 2
// Now collect everything into one IloCplex instance.
IloCplex cplex = new IloCplex();
cplex.add(x1);
cplex.add(x2);
cplex.add(rng1);
cplex.add(rng2);
// Add constraint and objective that have variables from both
// sub-models.
IloRange c3 = cplex.addEq(cplex.sum(cplex.sum(cplex.prod(1, x1[0]), cplex.prod(2, x1[1])),
cplex.sum(cplex.prod(3, x2[0]), cplex.prod(4, x2[1]))),
8, "c3");
cplex.addMinimize(cplex.sum(cplex.sum(x1[0], x1[1]),
cplex.sum(x2[0], x2[1])));
// Export model to file and solve it.
cplex.exportModel("parallel.lp");
cplex.solve();
// Print results.
System.out.println("x1[0] = " + cplex.getValue(x1[0]));
System.out.println("x1[1] = " + cplex.getValue(x1[1]));
System.out.println("x2[0] = " + cplex.getValue(x2[0]));
System.out.println("x2[1] = " + cplex.getValue(x2[1]));
System.out.println("slack[c1] = " + cplex.getSlack(rng1[0]));
System.out.println("slack[c2] = " + cplex.getSlack(rng2[0]));
System.out.println("slack[c3] = " + cplex.getSlack(rng1[0]));
System.out.println("objective = " + cplex.getObjValue());
} catch (IloException e) {
System.err.println(e.getMessage());
e.printStackTrace();
System.exit(-1);
}
}
}
Note that the stuff that is build up by the different threads is disjoint. I don't know how far you can carry this but it might be worth a try.
Depending on what costs the most time in building up your model you could also try the following: Create all variables that exist in the model. Now, instead of building up the constraints as instances of IloNumExpr build up each constraint as an array of IloNumVar and an array of double (I don't discuss lower and upper bounds for constraints since they are handled similarly). For example, an expression like x1+2x2+3x3 would be stored as
new IloNumVar[]{ x1, x2, x3 };
new double[] { 1.0, 2.0, 3.0 };
This can be done in parallel. When you have build up all constraints like this then do one final sequential pass over all these arrays and use IloCplex.scalProd() to create instances of IloLinearNumExpr for each constraint. Depending on how much time you save in the parallel setup of the arrays this may or may not be faster than setting up everything sequentially.
#CPLEXOptimizers#DecisionOptimization