简体   繁体   English

在Java API中使用OPL模型时出现CPLEX热启动错误

[英]CPLEX warm start error when using OPL model in Java API

I am trying to do a warm start using the Java API and having some issues when passing the initial solution to the model. 我正在尝试使用Java API进行一个良好的开端,并且在将初始解决方案传递给模型时遇到一些问题。 In my model file(.mod) I have a 2D decision variable defined as, 在我的模型文件(.mod)中,我定义了一个2D决策变量,

range nodes = 1..5;
range vehicles = 1..2;
dvar int service_time[nodes][vehicles];

In my java file I am building the model as below and trying to pass an initial solution to the above decision variable using the addMipStart() function (as described here ), 在我的java文件我建立的模型如下,并试图通过初步的解决方案使用addMipStart()函数上述决定变量(如描述这里

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
    }
}

Unfortunately I am having an exception in the line which calls the cplex.addMIPStart() function as, 不幸的是,我在调用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)

I am thinking the error is due to the way I prepare the initial solution, can somebody please help me to sort this out. 我认为错误是由于我准备初始解决方案的方式而引起的,是否可以有人帮助我解决该问题。

Thank you very much. 非常感谢你。

The problem is that you're creating new variables, not referencing the existing variables in the model. 问题在于您正在创建变量,而不是引用模型中的现有变量。 These new variables do not exist in the objective, constraints, etc., so you get the IloException (see this technote). 这些新变量在目标,约束等中不存在,因此您将获得IloException (请参阅技术说明)。

You should be able to access the existing variables doing something like the following ( note that this code has not been tested ): 您应该能够执行以下操作来访问现有变量( 请注意,此代码尚未经过测试 ):

    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);

Take a look at the Iterators.java example and the documentation for getElement . 看一下Iterators.java示例和getElement文档。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM