package io.vivarium.experiment; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import io.vivarium.audit.ActionFrequencyBlueprint; import io.vivarium.audit.AuditBlueprint; import io.vivarium.audit.CensusBlueprint; import io.vivarium.core.CreatureBlueprint; import io.vivarium.core.GridWorldBlueprint; import io.vivarium.core.processor.NeuralNetworkBlueprint; import io.vivarium.scripts.CreateWorld; import io.vivarium.scripts.RunSimulation; import io.vivarium.serialization.FileIO; import io.vivarium.serialization.Format; import io.vivarium.util.Functions; import io.vivarium.util.Rand; import io.vivarium.util.concurrency.ThreadRandAllocator; public class MutationRateLocal { private static final int WORLD_SIZE = 100; private static final int LIFE_TIMES_PER_SIMULATION = 1000; private static final int TICKS_PER_SIMULATION = LIFE_TIMES_PER_SIMULATION * 20_000; private static final int MAX_SIMULATIONS = 101; private static final int PEAK_THREAD_THROUGHPUT = 4; private static final int MIN_MUTATION_EXPONENT = -15; private static final int MAX_MUTATION_EXPONENT = -5; /** * Runs the MutationRate experiment. * * Hypothesis: There is an optimal mutation rate for population health. * * @param args * @throws InterruptedException * Not really... */ public static void main(String[] args) throws InterruptedException { // If we're running multi-threaded code, we need to use a multi-threaded random allocator Rand.setAllocator(new ThreadRandAllocator()); // Set up thread pool ExecutorService executorService = Executors.newFixedThreadPool(PEAK_THREAD_THROUGHPUT); Collection<WorldRunner> tasks = new LinkedList<>(); double[] mutationRates = Functions.generateDitherArray(MIN_MUTATION_EXPONENT, MAX_MUTATION_EXPONENT, MAX_SIMULATIONS); for (int i = 0; i < MAX_SIMULATIONS; i++) { double mutationRateExponent = Math.round(mutationRates[i] * 100) / 100.0; // Record the thread name String name = "mutation=2^" + mutationRateExponent; // Make a world blueprint GridWorldBlueprint worldBlueprint = GridWorldBlueprint.makeDefault(); worldBlueprint.setSize(WORLD_SIZE); // Set creature blueprint ArrayList<CreatureBlueprint> creatureBlueprints = new ArrayList<>(); CreatureBlueprint creatureBlueprint = CreatureBlueprint.makeDefault(); NeuralNetworkBlueprint processorBlueprint = (NeuralNetworkBlueprint) creatureBlueprint .getProcessorBlueprints()[0]; processorBlueprint.setMutationRateExponent(mutationRateExponent); ((NeuralNetworkBlueprint) creatureBlueprint.getProcessorBlueprints()[0]) .setNormalizeAfterMutation(Math.sqrt(42)); creatureBlueprints.add(creatureBlueprint); worldBlueprint.setCreatureBlueprints(creatureBlueprints); // Set audit functions ArrayList<AuditBlueprint> auditBlueprints = new ArrayList<>(); auditBlueprints.add(new ActionFrequencyBlueprint()); auditBlueprints.add(new CensusBlueprint()); worldBlueprint.setAuditBlueprints(auditBlueprints); // Save the world blueprint FileIO.saveSerializer(worldBlueprint, name + "_blueprint.viv", Format.JSON); // Create callable log("Generating world blueprint " + name); tasks.add(new WorldRunner(name)); } // Do the work! executorService.invokeAll(tasks); log("Awating"); executorService.shutdown(); executorService.awaitTermination(10_000, TimeUnit.DAYS); log("Completed"); } private static class WorldRunner implements Callable<Object> { private final String _name; WorldRunner(String name) { this._name = name; } @Override public Object call() { try { // Create a world { log("Generating world " + _name); String[] args = { "-b", _name + "_blueprint.viv", "-o", _name + "_initial.viv" }; CreateWorld.main(args); } // Run the world { log("Starting simulation of world " + _name); String[] args = { "-i", _name + "_initial.viv", "-o", _name + "_complete.viv", "-t", "" + TICKS_PER_SIMULATION }; RunSimulation.main(args); log("Completeing simulation of world " + _name); } } catch (Exception e) { e.printStackTrace(); } return null; } } private synchronized static void log(String event) { System.out.println(event); } }