0

Я использую Java API cplex.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); 

Так что я просто использовать два булевы векторы х и у. Этот фрагмент отлично работает для небольших экземпляров, где 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() allready создает и добавляет логические переменные в модель. Вызывая cplex.boolvar, вы создаете другую логическую переменную. Для этого вам не нужны первые два цикла. – willem

+0

На боковой ноте вы знаете, что в вашей модели нет ограничений, не так ли? Предполагаю, вы планируете добавить их позже? – willem

+0

@willem, ну, но они не должны разбиваться – Stasik

ответ

0

Вы создавать и добавлять булевы переменные в модели, вызвав

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

затем добавить новые переменные в композиции по телефону

x[i] = cplex.boolVar(); 

Но старые переменные все еще находятся в формулировке, хотя у вас больше нет ссылок на них. Это может вызвать проблемы, и это определенно не то, что вам нужно. Я не знаю, как сделать это правильно в Java, но в .net я бы сделать что-либо

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! 

(IIntVar является .net вариант Java IloIntVar). То же самое для y. Попробуйте прокомментировать первые два цикла и посмотрите, что происходит с ошибкой.

+0

это не помогло, однако я нашел что-то еще :) – Stasik

+0

@Stasik Хорошо, но ваша программа продолжала работать для небольшого .size() после изменения? Если это так, я бы рекомендовал внедрить изменения по указанным причинам. – willem

+0

Да, поведение не изменилось. Я удалил петли. Однако сборщик мусора Java должен был удалить неиспользуемые переменные ... Я прав? – Stasik

1

После некоторых проб и ошибок я узнал, что это своего рода проблема с памятью.

Добавление достаточного количества кучи в JVM, например. -Xms512M -Xmx750M решает проблему и позволяет программе работать как ожидалось.

 Смежные вопросы

  • Нет связанных вопросов^_^