2016-01-28 495 views
3

我用cplex來解決旅行商問題(TSP)。 考慮到如果x[i][j]=1,則路徑從城市轉到城市Ĵ,否則療法是這些城市之間沒有路徑。 相應的矩陣:使用java cplex解決TSP,getValues的變量給出了一個錯誤

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();  
} 
} 
+0

「告訴我們什麼錯誤消息的確切措辭是「(取自」如何詢問「幫助:http://stackoverflow.com/help/mcve) –

+0

發佈初始化」x「並將其添加到模型中的代碼。這是真正導致錯誤的原因。 –

+0

如何將'x'與'cplx'關聯起來?你應該發佈一個完整的小例子,我們可以運行自己來重現錯誤。 –

回答

1

在IBM的知識中心在this page來看,該參數getValue()必須是用於構建要解決的模型的東西,如示例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("-"); 
    } 
} 
+0

謝謝first.I已將x添加到我的模型:'IloNumVar [] [] x = new IloNumVar [n] []; (int i = 0; i Joyee

+2

僅創建變量並不足以讓它們提取到CPLEX中。只有實際出現在約束或目標中的變量纔會被提取到CPLEX中。因此,取決於您如何構建模型,可能沒有任何約束包含您創建的一些變量。它是否第一次在循環中倒下?是否有一個約束表示x [0] [0]的任何內容? – TimChippingtonDerrick

+0

@TimChippingtonDerrick。你是對的。通過發佈的代碼,這個省略非常明顯。 –