【问题标题】:Using java cplex to solve TSP, getValues of variables gives an error使用java cplex解决TSP,变量getValues报错
【发布时间】:2016-05-05 21:09:47
【问题描述】:

我使用cplex 来解决旅行商问题(TSP)。 假设如果x[i][j]=1,那么路径从城市i到城市j,否则,这些城市之间没有道路。 对应的矩阵:

IloNumVar[][] x = new IloNumVar[n][];
for(int i = 0; i < n; i++){
    x[i] = cplex.boolVarArray(n);
}

cplex 完成求解时,我想像这样获取x 的值:

if(cplex.solve()){
    double[][] var = new double[n][n];
    for(int i = 0; i<x.length; i++){
        for(int j = 0 ; j < x[i].length; j ++){
            var[i][j] = cplex.getValue(x[i][j]);
            if(var[i][j] ==1){
                System.out.print(i + "  "+ j);
            }       
        }   
    }
}

但它给出了一个错误。我会感谢任何可以提供一些建议的人。 错误在:

 var[i][j] = cplex.getValue(x[i][j]);

解释是:

Exception in thread "main"  ilog.cplex.IloCplex$UnknownObjectException: CPLEX Error: object is unknown to IloCplex
at ilog.cplex.IloCplex.getValue(IloCplex.java:6495)

整个代码如下:

import java.io.IOException;
import ilog.concert.*;
import ilog.cplex.IloCplex;

public class TSP {
public static void solveMe(int n) throws IloException, IOException{

    //random data
    double[] xPos = new double[n];
    double[] yPos = new double[n];
    for (int i = 0; i < n; i ++){
        xPos[i] = Math.random()*100;
        yPos[i] = Math.random()*100;
    }

    double[][] c = new double[n][n];
    for (int i = 0 ; i < n; i++){
        for (int j = 0 ; j < n; j++)
        c[i][j] = Math.sqrt(Math.pow(xPos[i]-xPos[j], 2)+ Math.pow(yPos[i]-yPos[j],2));
    }

    //model

    IloCplex cplex = new IloCplex();

    //variables
    IloNumVar[][] x = new IloNumVar[n][];

    for(int i = 0; i < n; i++){
        x[i] = cplex.boolVarArray(n);
    }

    IloNumVar[] u = cplex.numVarArray(n, 0, Double.MAX_VALUE);

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

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

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


    for(int i = 1; i < n; i++){
        for(int j = 1; j < n; j++){
            if(i != j){
                IloLinearNumExpr expr = cplex.linearNumExpr();
                expr.addTerm(1.0, u[i]);
                expr.addTerm(-1.0, u[j]);
                expr.addTerm(n-1, x[i][j]);
                cplex.addLe(expr, n-2);
            }
        }
    }

    //solve mode
    if(cplex.solve()){
        System.out.println();
        System.out.println("Solution status = "+ cplex.getStatus());
        System.out.println();
        System.out.println("cost = " + cplex.getObjValue());
        for(int i = 0; i<x.length; i++){
            for(int j = 0 ; j < x[i].length; j ++){
                    System.out.print(cplex.getValue(x[i][j]));                          
            }   
        }   
    }

    //end
    cplex.end();    
}
}

【问题讨论】:

  • “告诉我们错误信息的确切措辞是什么”(摘自“如何提问”帮助:stackoverflow.com/help/mcve
  • 发布初始化x的代码并将其添加到模型中。这才是真正导致错误的原因。
  • 您如何对x 将其与cplx 关联?您真的应该发布一个完整的最小示例,我们可以自己运行以重现错误。
  • @Mad Physicist 非常感谢您能分享时间来运行它。
  • @Joyee。我没有机会运行代码,但我确实看到了一个我认为可以解决您的问题的主要问题。答案已更新。

标签: java cplex getvalue


【解决方案1】:

查看 IBM 知识中心的 this pagegetValue() 的参数必须是用于构建您正在求解的模型的内容,如示例 here。由于varn x n,您应该将x 初始化为IloNumVar[][] x = new IloNumVar[n][n];。在调用solve() 之前的某个时间点,x每个 元素都应该添加到您的模型中。

在您的设置中,x 的对角线元素永远不会被模型引用。你会注意到你所有的设置循环都有一个条件if(i != j)。要解决您的问题,请在至少一个循环中添加 else 子句,或者如果这没有意义(我怀疑是这样),请与输入保持一致地打印输出:

for(int i = 0; i<x.length; i++) {
    for(int j = 0 ; j < x[i].length; j ++) {
        if(i != j)
            System.out.print(cplex.getValue(x[i][j]));
        else
            System.out.print("-");
    }   
}

【讨论】:

  • 首先谢谢。我已经在我的模型中添加了x:IloNumVar[][] x = new IloNumVar[n][]; for(int i = 0; i &lt; n; i++){ x[i] = cplex.boolVarArray(n); }如果我没有getValues of variables。它可以解决。
  • 仅仅创建变量并不一定足以将它们提取到 CPLEX 中。只有实际出现在约束或目标中的变量才会被提取到 CPLEX 中。因此,根据您构建模型的方式,可能不存在包含您创建的某些变量的任何约束。它会在第一次循环时摔倒吗?是否有任何关于 x[0][0] 的约束?
  • @TimChippingtonDerrick。你说的对。使用发布的代码,遗漏非常明显。
  • @TimChippingtonDerrick 你是对的。我已经解决了这个问题。谢谢
  • @MadPhysicist。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多