0

私はcplex Java APIを使用しています。大きな配列のCplex NullPointerException

次のコードが使用されます。

//init cplex 
IloCplex cplex = new IloCplex(); 
cplex.setParam(IloCplex.IntParam.Threads, 1); 
//is commodity k,l routed over i and j 
//x ijkl 
IloIntVar[] x = cplex.boolVarArray(inst.getSize()*inst.getSize()*inst.getSize()*inst.getSize()); 
for (int i = 0; i < x.length; i++) { 
    x[i] = cplex.boolVar(); 
} 

//is node a hub 
IloIntVar[] y = cplex.boolVarArray(inst.getSize()); 
for (int i = 0; i < y.length; i++) { 
    y[i] = cplex.boolVar(); 
} 

//=== FITTNESS FUNCTION === 
IloLinearNumExpr expr = cplex.linearNumExpr(); 
//first big sum 
for(int k=0;k<inst.getSize();k++){ 
    for(int i=0;i<inst.getSize();i++) { 
     for(int j=0;j<inst.getSize();j++) { 
      for(int l=0;l<inst.getSize();l++) { 
       expr.addTerm(c[i][j][k][l], x[Static.quadToLinear(i, j, k, l, inst.getSize())]); 
      } 
     } 
    } 
} 
//second sum 
for(int i=0;i<inst.getSize();i++) { 
    expr.addTerm(inst.getFixed(i), y[i]); 
} 
//minimise it 
cplex.addMinimize(expr); 

だから私はちょうど2つのブールベクトルxとyを使用しています。このスニペットは、inst.getSize()が25などの小規模のインスタンスではうまく動作します。ただし、サイズが40のインスタンスの場合は、最後の行でクラッシュします。

Exception in thread "main" java.lang.NullPointerException 
at ilog.cplex.CpxNumVar.unmark(CpxNumVar.java:296) 
at ilog.cplex.CpxLinearExpr.unmarkVars(CpxLinearExpr.java:402) 
at ilog.cplex.CpxLinearExpr.removeDuplicates(CpxLinearExpr.java:515) 
at ilog.cplex.CpxLinearExpr.removeDuplicates(CpxLinearExpr.java:489) 
at ilog.cplex.CpxObjective.setExpr(CpxObjective.java:108) 
at ilog.cplex.CpxObjective.<init>(CpxObjective.java:362) 
at ilog.cplex.IloCplexModeler.objective(IloCplexModeler.java:706) 
at ilog.cplex.IloCplexModeler.addObjective(IloCplexModeler.java:768) 
at ilog.cplex.IloCplexModeler.addMinimize(IloCplexModeler.java:790) 
at ExactSolver.main(ExactSolver.java:69) 

アイデアはありますか?私はそれはあなたが作成...

+0

私はJava APIに精通していませんが、.net APIのcplex.BoolVarArray()はブール変数を作成してモデルに追加しています。 cplex.boolvarを呼び出すと、別のブール変数を作成できます。つまり、ループの最初の2つは必要ありません。 – willem

+0

サイドノートでは、モデルに制約がないことを認識していますか?私はあなたが後でそれらを追加する予定だと思いますか? – willem

+0

@willem、でも、それらは衝突しないでください。 – Stasik

答えて

0

の作業を取得する必要があり、その後、

x[i] = cplex.boolVar(); 

を呼び出すことにより、製剤に新しい変数を追加

IloIntVar[] x = cplex.boolVarArray 
    (inst.getSize()*inst.getSize()*inst.getSize()*inst.getSize()); 

を呼び出すことで、モデルにブール変数を追加しますが、古い変数はまだ定式化されていますが、もはやそれらへの参照はありません。これは問題を引き起こすかもしれませんが、あなたが望むことは間違いありません。 (IIntVarがJava IloIntVarの.NET変異体である)私はJavaで適切にこれを行う方法がわからないけど、ネットで私はどちらか

IIntvar[] x = new IIntvar[size]; 
for (int i = 0; i < x.length; i++) { 
    x[i] = cplex.boolVar(); 
} 

または

IIntVar[] x= cplex.BoolVarArray(size); 
//No for loop! 

を行うだろう。 と同じです。です。ループの最初の2つをコメントアウトして、エラーの内容を確認してください。

+0

それは助けにはなりませんでしたが、私は別の何かを見つけました:) – Stasik

+0

@Stasik Okですが、あなたのプログラムは変更後に小さな.size()のために働いていましたか?もしそうなら、上記の理由で変更を実装することをお勧めします。 – willem

+0

はい、動作は変更されませんでした。私はループを削除しました。しかし、Javaのガベージコレクタは、未使用の変数を削除する必要があります...私はそうですか? – Stasik

1

いくつかの試行錯誤の後、私はこれが一種のメモリ問題であることを知りました。

JVMに十分なヒープスペースを追加します。 -Xms512M -Xmx750Mは問題を解決し、プログラムを期待どおりに実行させます。

関連する問題