【问题标题】:How to implement Lazy Constraint Callbacks in CPLEX (java API)如何在 CPLEX (java API) 中实现惰性约束回调
【发布时间】:2019-07-11 14:42:38
【问题描述】:

目前,我正在尝试为具有 MTZ 子巡回消除约束的非对称电容车辆路线问题实施 CPLEX 精确解决方案。

当我尝试实现延迟约束回调时,我的问题出现了。更具体地说,我得到一个空指针异常。几乎没有实现回调的教程,非常感谢您的帮助。

这是我的代码:

CVRP 类

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

import ilog.concert.*;
import ilog.cplex.*;

public class ACVRP {

    // euclidean distance method
    public static double distance(int x1, int y1, int x2, int y2) {
        return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
    }

    public static void solveModel() {
        int n = 32; // number of customers
        int k = 5; // number of vehicles
        int c = 100; // capacity of vehicles

        int datacoords[][] = new int[n][2];
        double[][] node = new double[n][n]; // dissimilarity matrix
        int[] demand = new int[n]; // demand of every customer

        try {

            // load matrixes
            FileReader frd = new FileReader("demands.txt");
            FileReader frcoords = new FileReader("coords.txt");

            BufferedReader brd = new BufferedReader(frd);
            BufferedReader brcoords = new BufferedReader(frcoords);

            String str;
            int counter = 0;

            while ((str = brd.readLine()) != null) {

                String[] splitStr = str.trim().split("\\s+");

                demand[counter] = Integer.parseInt(splitStr[1]);
                counter++;
            }

            counter = 0;

            while ((str = brcoords.readLine()) != null) {

                String[] splitStr = str.trim().split("\\s+");

                datacoords[counter][0] = Integer.parseInt(splitStr[1]);
                datacoords[counter][1] = Integer.parseInt(splitStr[2]);

                counter++;
            }

            for(int i = 0; i < n; i++){
                for(int j = 0; j < n; j++){
                    node[i][j] = distance(datacoords[i][0],datacoords[i][1],datacoords[j][0],datacoords[j][1]);
                //  if (i == j ){
                //      node[i][j] = 99999999;
                //  }
                }
            }


            brd.close();
            brcoords.close();

            IloCplex cplex = new IloCplex();

            // variables
            IloIntVar[][] x = new IloIntVar[n][];
            for (int i = 0; i < n; i++) {
                x[i] = cplex.boolVarArray(n);
                for (int j = 0; j < n; j++) {
                    x[i][j].setName("x." + i + "." + j );
                }
            }

            // mtz variables
            IloNumVar[] u = cplex.numVarArray(n, 0, Double.MAX_VALUE);
            for (int j = 0; j < n; j++) {
                u[j].setName("u." + j);
            }

            //objective
            IloLinearNumExpr conObj = cplex.linearNumExpr();
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if ( i != j ){
                        conObj.addTerm(node[i][j], x[i][j]) ;
                    }
                }
            }
            cplex.addMinimize(conObj);


            // constraints
            for (int i = 1; i < n; i++) {
                IloLinearNumExpr equation1 = cplex.linearNumExpr();
                for (int j = 0; j < n; j++) {
                    if (i!=j) {
                        equation1.addTerm(1.0, x[i][j]);
                    }
                }
                cplex.addEq(equation1, 1.0);
            }

            for (int j = 1; j < n; j++) {
                IloLinearNumExpr equation2 = cplex.linearNumExpr();
                for (int i = 0; i < n; i++) {
                    if (i!=j) {
                        equation2.addTerm(1.0, x[i][j]);
                    }
                }
                cplex.addEq(equation2, 1.0);
            }

            IloLinearNumExpr equation3 = cplex.linearNumExpr();
            for (int i = 1; i < n; i++) {
                equation3.addTerm(1.0, x[i][0]);
            }
            cplex.addEq(equation3, k);

            IloLinearNumExpr equation4 = cplex.linearNumExpr();
            for (int j = 1; j < n; j++) {
                equation4.addTerm(1.0, x[0][j]);
            }
            cplex.addEq(equation4, k);

            cplex.use(new LazyContstraintMTZ(n, c, demand, x, u, cplex));

            //parameters
            //cplex.setParam(IloCplex.Param.TimeLimit,50);
            //cplex.setParam(IloCplex.Param.Preprocessing.Reduce, 0); 
           // cplex.setParam(IloCplex.Param.RootAlgorithm, IloCplex.Algorithm.Primal); 


            // solve model
            cplex.solve();
            cplex.exportModel("model.lp");
            System.out.println(cplex.getBestObjValue());
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if (i != j) {
                        if (cplex.getValue(x[i][j]) != 0) {
                            System.out.println("name: " + x[i][j].getName() + " value: " + cplex.getValue(x[i][j]));
                        }
                    }
                }
            }
            // end
            cplex.end();

        } catch (IloException | NumberFormatException | IOException exc) {
            exc.printStackTrace();
        }
    }

}

惰性约束类:

import ilog.concert.*;
import ilog.cplex.*;

public class LazyContstraintMTZ extends IloCplex.LazyConstraintCallback {

    int n; // number of customers
    int c; // capacity of vehicles
    int[] demand; // demand of every customer
    IloIntVar[][] x;
    IloNumVar[] u;
    IloCplex cplex;
    IloRange[] rng;

    //constructor
    LazyContstraintMTZ(int n, int c, int[] demand, IloIntVar[][] x, IloNumVar[] u, IloCplex cplex){
        this.n = n;
        this.c = c;
        this.demand = demand;
        this.x = x;
        this.u = u;
        this.cplex = cplex;
    }


    protected void main() throws IloException {

        // Get the current x solution

    //  double[][] sol = new double[n][n];
    //  for (int i = 0; i < n; i++) {
    //      for (int j = 0; j < n; j++) {
    //          sol[i][j] = cplex.getValue(x[i][j]);
    //      }
    //  }


        for (int i = 1; i < n; i++) {
            for (int j = 1; j < n; j++) {
                if (i!=j && demand[i]+demand[j]<=c){
                    IloLinearNumExpr equation5 = cplex.linearNumExpr();
                    equation5.addTerm(1.0, u[i]);
                    equation5.addTerm(-1.0, u[j]);
                    equation5.addTerm(c, x[i][j]);
                    rng[i].setExpr(equation5);
                    rng[i].setBounds(Double.MIN_VALUE, c-demand[j]);
                    cplex.addLazyConstraint(rng[i]);                
                }
            }
        }

        for (int i = 1; i < n; i++) {
            IloLinearNumExpr equation6 = cplex.linearNumExpr();
            equation6.addTerm(1.0, u[i]);
            rng[i].setExpr(equation6);
            rng[i].setBounds(demand[i], c);
            cplex.addLazyConstraint(rng[i]);
        }

    }

}

【问题讨论】:

  • 尝试在LazyContstraintMTZ.main 的代码周围放置一个try/catch 语句。只需打印出您在此处捕获的任何异常(例如,e.printStackTrace();),然后重新抛出它(例如,throw e;)。这应该会给你一些关于问题可能来自哪里的信息。
  • 还可以尝试添加更多老式打印语句以查看代码一直在执行的操作以及错误发生之前代码中发生的情况

标签: java callback cplex


【解决方案1】:

据我所知,rng 从未在您的回调类中初始化。所以它总是null,一旦你尝试在其中设置一个元素,你就会得到 NullPointerException。

请注意,您甚至不需要该数组。而不是

rng[i].setExpr(equation5);
rng[i].setBounds(Double.MIN_VALUE, c-demand[j]);
cplex.addLazyConstraint(rng[i]);

你可以写

IloRange rng = cplex.range(Double.MIN_VALUE, equation5, c - demand[j]);
cplex.addLazyConstraint(rng);

equation6 也是如此)。

另请注意,Double.MIN_VALUE 可能不是您想要的。这给出了大于 0 的最小可表示数字。我猜你想要的是 Double.NEGATIVE_INFINITY 来指定一个没有下限的范围。在这种情况下,您也可以只写

IloRange rng = cplex.le(equation5, c - demand[j]);

【讨论】:

    猜你喜欢
    • 2020-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多