Closed schrum2 closed 1 year ago
I've made the abstract weighted sum fitness, but I still need to extend it with a specific fitness pairing to test it out.
Some classes need to be made that extend the new MinecraftWeightedSumFitnessFunction class. For starters, try one that uses both ChangeBlocksFitness and ChangeCenterOfMass, and make both of the weight values be 0.5. Then try running it with plain MAP Elites. If that works, then make a batch file for it.
Caused by: java.lang.NullPointerException at edu.southwestern.tasks.mario.gan.Comm.processCommRecv(Comm.java:59) at edu.southwestern.tasks.mario.gan.Comm.commRecv(Comm.java:50) at edu.southwestern.tasks.evocraft.MinecraftClient.getMinecraftClient(MinecraftClient.java:77) at edu.southwestern.tasks.evocraft.MinecraftClient.clearAreaAroundCorner(MinecraftClient.java:812) at edu.southwestern.tasks.evocraft.MinecraftClient.clearAndVerify(MinecraftClient.java:774) at edu.southwestern.tasks.evocraft.fitness.TimedEvaluationMinecraftFitnessFunction.multipleFitnessScores(TimedEvaluationMinecraftFitnessFunction.java:92) at edu.southwestern.tasks.evocraft.fitness.MinecraftWeightedSumFitnessFunction.fitnessScore(MinecraftWeightedSumFitnessFunction.java:49) at edu.southwestern.tasks.evocraft.MinecraftShapeTask.lambda$2(MinecraftShapeTask.java:448) at java.util.stream.ReferencePipeline$6$1.accept(ReferencePipeline.java:244) at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1384) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) at java.util.stream.Nodes$SizedCollectorTask.compute(Nodes.java:1878) at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731) at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) at java.util.concurrent.ForkJoinTask.doInvoke(ForkJoinTask.java:401) at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:734) at java.util.stream.Nodes.collectDouble(Nodes.java:438) at java.util.stream.DoublePipeline.evaluateToNode(DoublePipeline.java:139) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:541) at java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) at java.util.stream.DoublePipeline.toArray(DoublePipeline.java:508) at edu.southwestern.tasks.evocraft.MinecraftShapeTask.calculateFitnessScores(MinecraftShapeTask.java:448) at edu.southwestern.tasks.evocraft.MinecraftShapeTask.evaluateOneShape(MinecraftShapeTask.java:330) at edu.southwestern.tasks.evocraft.MinecraftShapeTask.evaluateOneShape(MinecraftShapeTask.java:308) at edu.southwestern.tasks.evocraft.MinecraftLonerShapeTask.oneEval(MinecraftLonerShapeTask.java:282) at edu.southwestern.tasks.NoisyLonerTask.evaluate(NoisyLonerTask.java:126) at edu.southwestern.evolution.mapelites.MAPElites.lambda$initialize$0(MAPElites.java:417) at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1384) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291) at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731) at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1067) at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1703) at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:172)
Exception resolved
Was able to run the main method for the ChangeBlockAndChangeCenterOfMassWeightedSumFitness
did not seem to return interesting results. No flying machines.
The next step here is to find a way to log the component fitness scores. I think it will be a bit messy, requiring several methods that return double[]
to instead return Pair<double[],double[]>
. I'll give more details on this later.
My most recent commit above takes some steps toward making it possible to track the component scores, but it is not done yet.
Pure fitness can log weighted sum but map elites crashes when it tries to run
MAP Elites should no longer crash when run with a weighted sum fitness function, though I have not verified this yet. Please check.
However, even though it should not crash, it definitely won't log the desired information yet. You will need to change some of the logging code in MAP Elites itself. In particular, there is a line in MAPElites where this happens:
Float[] elite = ArrayUtils.toObject(archive.getEliteScores());
final int pseudoGeneration = iterations/individualsPerGeneration;
archiveLog.log(pseudoGeneration + "\t" + StringUtils.join(elite, "\t").replaceAll("-Infinity", "X"));
This code is responsible for logging the objective scores across all bins for the one and only one objective. We need to have an operation similar to this for each component objective of a weighted sum. More generally, the scores we are interested in logging will be within the otherStats
field of each Score
instance in a bin, and all scores should have the same number of entries in this array. So, there needs to be a separate log and plot file for each index in otherStats
. Similarly, there needs to be a method in Archive
like getEliteScores()
, except instead of getting the fitness score for each bin, it gets the score in a specific otherStats
index for each bin, as in:
getOtherStatsScores(int index)
Given what this returns, the data can be logged and plotted the same way.
MAPElites also uses this code to compute the max fitness:
Float maximumFitness = StatisticsUtilities.maximum(elite);
and this code to compute QD scores with respect to the fitness scores:
final double qdScore = calculateQDScore(elite);
If you were to simply send an array of otherStats values to these methods, then you would compute both a max score in the other stat, as well as a QD score across the otherStat. This would all need to be logged and plotted with distinct files, but it mostly comes down to copying what is already there with just small tweaks. A method can probably be extracted that creates plt files that differ only in the name of the log file they are plotting, and then the logging commands themselves can just be different log files (though you will need an array of log files for each of the otherStats values).
Definitely want to get this logging into MAP Elites before summer ends @JoannaBlatt
I might have created an issue with pseudoArchive setting due to passing an arraylist of logs that are not set up in MuLambda. This may have backwards compatibility issues.
Currently logs. Handling in setupLogging currently similar to momeLogs, but could probably be handled differently. Issues with negative scores are present. It should probably be accounted for elsewhere.
Running tests now, but all scores should be in the range 0.0 to 1.0 now. Won't be able to check results until Monday though.
Scores to range from 0 to 1 in a separate test that I did, so I'm closing this issue. However, there is a correction for negative scores needed with QD calculations, and that is tracked in this new issue #943
Make a new abstract class called MinecraftWeightedSumFitnessFunction that extends the TimedEvaluationMinecraftFitnessFunction. This abstract class will have a constructor that takes two lists:
Given this information, this fitness function will compute fitness scores across all of the given list of MinecraftFitnessFunctions, but take care to separate them out into those that are TimedEvaluationMinecraftFitnessFunctions and those that are not. However, in order to compute the actual fitness score that will be returned, it will take the array of fitness scores returned, multiply each one by its corresponding weight, and add all the results together into a single fitness score.
Basically, this is a way of solving a multiobjective problem by reducing it to a single objective problem. One would expect this to not do very well, but it is a fair baseline to compare NSGA2 and MOME with.
The reason we are making a separate abstract fitness function for this is that the weights will likely need a bit of tuning. The classes that extend this class will just have a constructor that calls the super constructor with a specific list of fitness functions and weights.