我目前正在开发一个AI,它将为列表中的每个人做出决策。但是在迭代这个列表时,我得到了ConcurrentModificationException
。我验证了我的removeDeads
函数是否会导致这样的事情,但是因为它不在循环内部,所以它不应该。这是错误堆栈:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:473)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:372)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:945)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:973)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:198)
at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:939)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:893)
at IA.RLAI.play(RLAI.java:48)
at Game.Game.play(Game.java:61)
at Main.start(Main.java:136)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:919)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
... 1 more
Exception running application Main
问题是它永远不会在同一时刻发生。我可以迭代3个人以及15个人。
这是我的代码:
public void play(Population population, Game game) throws Exception {
//looking if some individuals died from the other player
ArrayList<Individual> deads = new ArrayList<>();
for(Individual i: population.getIndividuals()){
if(i.getCurrentHP()==0){
deads.add(i);
}
}
population.getIndividuals().removeAll(deads);
for (Individual dead: deads) {
learn(dead);
}
//Normal individuals
for (Individual me: population.getIndividuals()) {
int size = Math.max(0, me.getMemory().size()-1);
if(me.getMemory().isEmpty()){
System.out.println(me.getMemory().toString());
}else {
System.out.println(me.getMemory().get(size).toString());
}
double[] inputs = new double[153];
int i = 0;
double[] toInsert = getAllyMap(me);
System.arraycopy(toInsert, 0, inputs, i, 49);
i+=49;
toInsert = getEnemyMap(me, game);
System.arraycopy(toInsert, 0, inputs, i, 49);
i+=49;
toInsert = getFoodMap(me);
System.arraycopy(toInsert, 0, inputs, i, 49);
i+=49;
inputs[i++] = me.getPosition().getX()-population.getFoodBase().getX(); //Relative position to foodBase X
inputs[i++] = me.getPosition().getY()-population.getFoodBase().getY(); //Relative position to foodBase Y
inputs[i++] = me.getCurrentHP();
inputs[i++] = me.getCurrentFoodLvl();
inputs[i++] = me.getCurrentFoodStock();
inputs[i++] = population.getMapping().getCase(population.getFoodBase()).getFoodQuantity();
double[] outputs = network.forward(inputs);
//calculus of the probability of the outputs
double sumExp = 0;
for(int j = 0; j<outputs.length; j++){
sumExp += Math.exp(outputs[j]);
}
double[] proba = new double[outputs.length];
for (int j = 0; j<outputs.length; j++){
proba[j] = Math.exp(outputs[j])/sumExp;
}
//determination of the chosen output
double[] probCuml = new double[outputs.length+1];
probCuml[0] = 0;
for (int j = 0; j < outputs.length; j++){
probCuml[j+1] = probCuml[j]+proba[j];
}
double rand = Math.random();
int choice = 1;
for(int j = 1; j<probCuml.length; j++){
if(rand < probCuml[j]){
choice = j-1;
break;
}
}
//Action
switch(choice){
case 0:
me.move(Actions.MoveUp);
break;
case 1:
me.move(Actions.MoveDown);
break;
case 2:
me.move(Actions.MoveRight);
break;
case 3:
me.move(Actions.MoveLeft);
break;
case 4:
Population toAttack = game.getOtherPopulation(population);
me.attack(toAttack);
break;
case 5:
me.collect();
break;
case 6:
me.store();
break;
case 7:
me.eat();
break;
case 8:
me.copulate();
break;
default :
throw new Exception("Out of Possible Choice");
}
me.regen();
if(me.getCurrentHP()<=0){me.addMemory(Reinforcement.Die);}
learn(me);
}
//looking for individuals that die of hunger but as they already learned,
no need to do it again
population.areDead();
System.out.println(" ");
}
这是我的areDead
功能:
public ArrayList<Individual> areDead(){
ArrayList<Individual> areDead = new ArrayList<>();
for (Individual individual: individuals) {
if(individual.getCurrentHP()<=0){
areDead.add(individual);
}
}
individuals.removeAll(areDead);
return areDead;
}
问题是我不知道这个异常来自哪里。它说它来自个人的循环,但没有任何东西可以修改其中的列表。