我正在尝试使用Java API进行热门启动,并在将初始解决方案传递给模型时遇到一些问题。 在我的模型文件(.mod)中,我有一个2D决策变量,定义为,
range nodes = 1..5;
range vehicles = 1..2;
dvar int service_time[nodes][vehicles];
在我的java文件中,我正在构建如下模型,并尝试使用addMipStart()函数将初始解决方案传递给上述决策变量(如here所述),
static public void main(String[] args) throws Exception {
int status = 127;
try {
IloOplFactory.setDebugMode(true);
IloOplFactory oplF = new IloOplFactory();
IloOplErrorHandler errHandler = oplF.createOplErrorHandler(System.out);
IloOplModelSource modelSource = oplF.createOplModelSource(DATADIR + "/myModFile.mod");
IloOplSettings settings = oplF.createOplSettings(errHandler);
IloOplModelDefinition def = oplF.createOplModelDefinition(modelSource, settings);
IloCplex cplex = oplF.createCplex();
IloOplModel opl = oplF.createOplModel(def, cplex);
//adding the custom data source
IloOplDataSource dataSource = new VRPDataSource(oplF);
opl.addDataSource(dataSource);
//generating the model
opl.generate();
//creating the initial solution
int i = 5;
int j = 2;
IloIntVar[][] var2D = new IloIntVar[i][];
double[][] var2D_startingVals = new double[i][];
for(int index1=0; index1 < i; index1++){
var2D[index1] = new IloIntVar[j];
var2D_startingVals[index1] = new double[j];
for(int index2 = 0; index2 < j; index2++){
String varName = "service_time("+ (index1+1) +")("+ (index2+1) +")";
var2D[index1][index2] = cplex.intVar(0, 50, varName);
//lets assume a unit matrix as the starting solution
var2D_startingVals[index1][index2] = 1;
}
}
//flatten the multi-dimensional IloNumVar and double arrays
IloNumVar[] flat_var2D = new IloNumVar[i*j];
double[] flat_var2D_startingVals = new double[i*j];
for(int index1=0; index1 < i; index1++){
for(int index2=0; index2 < j; index2++){
flat_var2D[index1*j + index2] = var2D[index1][index2];
flat_var2D_startingVals[index1*j + index2] = var2D_startingVals[index1][index2];
}
}
// adding the MIPStart
cplex.addMIPStart(flat_var2D, flat_var2D_startingVals, IloCplex.MIPStartEffort.Auto, "addMIPStart start");
if(cplex.solve()){
// more code
}else{
// more code
}
// more code
}catch(Exception ex){
// more code
}
}
不幸的是我在调用cplex.addMIPStart()函数的行中有例外,
[java] ### CONCERT exception: The referenced IloExtractable has not been extracted by the IloAlgorithm
[java] ilog.concert.IloException: The referenced IloExtractable has not been extracted by the IloAlgorithm
[java] at ilog.cplex.cppimpl.cplex_wrapJNI.IloCplex_addMIPStart__SWIG_0(Native Method)
[java] at ilog.cplex.cppimpl.IloCplex.addMIPStart(IloCplex.java:866)
[java] at ilog.cplex.IloCplex.addMIPStart(IloCplex.java:13219)
[java] at ilog.cplex.IloCplex.addMIPStart(IloCplex.java:13228)
[java] at myJavaClass.myJavaClass.main(myJavaClass.java:412)
我认为错误是由于我准备初始解决方案的方式,有人可以帮我解决这个问题。
非常感谢。
答案 0 :(得分:0)
问题是您正在创建新变量,而不是引用模型中的现有变量。这些新变量在目标,约束等中不存在,因此您获得IloException
(请参阅this技术说明)。
您应该能够访问现有变量,执行以下操作(请注意,此代码尚未经过测试):
IloIntRange nodes = opl.getElement("nodes").asIntRange();
IloIntRange vehicles = opl.getElement("vehicles").asIntRange();
IloIntVarMap serviceTime = opl.getElement("service_time").asIntVarMap();
final int nbNodes = nodes.getSize();
final int nbVehicles = vehicles.getSize();
IloNumVar[] startX = new IloNumVar[nbNodes * nbVehicles];
double[] startVals = new double[nbNodes * nbVehicles];
for (int i = 0; i < nbNodes; i++) {
IloIntVarMap inner = serviceTime.getSub(nodes.getValue(i));
for (int j = 0; j < nbVehicles; j++) {
int idx = i * nbVehicles + j;
startX[idx] = inner.get(vehicles.getValue(j));
startVals[idx] = 1.0;
}
}
cplex.addMIPStart(startX, startVals);
查看Iterators.java示例和getElement的文档。