package preypredator; import it.unimi.dsi.fastutil.ints.IntArrayList; import java.io.IOException; import java.util.Arrays; import java.util.Random; import org.perf4j.StopWatch; import org.perf4j.slf4j.Slf4JStopWatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import joptsimple.OptionParser; import joptsimple.OptionSet; public class PreyPredator2 { private final static Logger logger = LoggerFactory.getLogger(PreyPredator2.class); private final StopWatch watch = new Slf4JStopWatch(); private final StopWatch runWatch = new Slf4JStopWatch(); //public static final int WIDTH = 1000; //public static final int HEIGHT = 1000; public static final int GRASS_MIN = 0; public static final int GRASS_MAX = 100; public static final int GRASS_ORIG = 20; public static final float GRASS_FACT = 1.0f; public static final int GRASS_GROWTH = 10; public static final int PREY_ORIG = 10; //public static final int PREY_RADIUS = 20; public static final int PREY_MAX = 50; public static final int PRED_ORIG = 10; //public static final int PRED_RADIUS = 20; public static final int PRED_MAX = 100; // Attributes private final PPGrid grass; private final PPGrid preys; private final PPGrid preds; // Temporary buffers used in each step private final IntArrayList preysX; private final IntArrayList preysY; private final IntArrayList predsX; private final IntArrayList predsY; private final int nbPreds; private final int nbPreys; private final int range; private final PPRuntime runtime; //OCLChrono chrono = new OCLChrono("preypredator"); private final int size; public PreyPredator2(int size, int nbPreys, int nbPredators, int range, PPRuntime runtime) { this.grass = new PPGrid(size, size); this.preys = new PPGrid(size, size); this.preds = new PPGrid(size, size); this.size = size; this.nbPreds = nbPredators; this.nbPreys = nbPreys; this.range = range; this.preysX = new IntArrayList(); this.preysY = new IntArrayList(); this.predsX = new IntArrayList(); this.predsY = new IntArrayList(); this.runtime = runtime; } public void setup() { watch.start("pp_setup"); initGrid(grass.getStorage(), (int) (grass.getStorage().length * 0.8), GRASS_ORIG); initGrid(preys.getStorage(), nbPreys, PREY_ORIG); initGrid(preds.getStorage(), nbPreds, PRED_ORIG); watch.stop(); } public void update_positions() { //chrono.start("update_positions"); preysX.clear(); preysY.clear(); predsX.clear(); predsY.clear(); for (int j = 0; j < size; j++) { for (int i = 0; i < size; i++) { if (preys.get(i, j) > 0) { preysX.add(i); preysY.add(j); } if (preds.get(i, j) > 0) { predsX.add(i); predsY.add(j); } } } //System.out.println(chrono.stop()); } public void step() { watch.start("pp_step"); //OCLChrono stepChrono = new OCLChrono("step"); //stepChrono.start(); update_positions(); runWatch.start("pp_grass"); runtime.growGrass(grass, GRASS_FACT, GRASS_GROWTH, GRASS_MIN, GRASS_MAX); runWatch.stop(); int[] newPreysX = new int[preysX.size()]; int[] newPreysY = new int[preysY.size()]; int[] newPredsX = new int[predsX.size()]; int[] newPredsY = new int[predsY.size()]; runWatch.start("pp_move_preys"); if (preysX.size() > 0) { runtime.selectMaxTarget(grass, range, preysX.toIntArray(), preysY.toIntArray(), newPreysX, newPreysY); } runWatch.stop(); /* for (int i = 0; i < preysX.size(); i++) { System.out.println("Prey: (" + preysX.get(i) + ", " + preysY.get(i) + ") => (" + newPreysX[i] + ", " + newPreysY[i] + ")"); }*/ // PREYS for (int i = 0; i < preysX.size(); i++) { final int oldPos = preys.offset(preysX.get(i), preysY.get(i)); final int newPos = preys.offset(newPreysX[i], newPreysY[i]); // Check an eventual conflict with another prey if (preys.get(newPos) > 0) { continue; } // Movement preys.set(newPos, preys.get(oldPos)); preys.set(oldPos, 0); // Eating if (grass.get(newPos) >= 0) { preys.set(newPos, clamp(preys.get(newPos) + grass.get(newPos), 0, PREY_MAX)); grass.set(newPos, 0); } // Reproduction if (preys.get(newPos) == PREY_MAX) { preys.set(oldPos, PREY_ORIG); } } runWatch.start("pp_move_preds"); if (predsX.size() > 0) { int [] predsXbis = predsX.toIntArray(); int [] predsYbis = predsY.toIntArray(); runtime.selectMaxTarget(preys, (int) Math.round(range * 1.5), predsXbis, predsYbis, newPredsX, newPredsY); } runWatch.stop(); /*for (int i = 0; i < predsX.size(); i++) { System.out.println("Pred: (" + predsX.get(i) + ", " + predsY.get(i) + ") => (" + newPredsX[i] + ", " + newPredsY[i] + ")"); }*/ // PREDATOR for (int i = 0; i < predsX.size(); i++) { final int pos = predsY.get(i) * size + predsX.get(i); final int newPos = newPredsY[i] * size + newPredsX[i]; // Check an eventual conflict with another predator if (preds.get(newPos) > 0) { continue; } // Movement preds.set(newPos, preds.get(pos)); preds.set(pos, 0); // Eating if (preys.get(newPos) >= 0) { preds.set(newPos, clamp(preds.get(newPos) + preys.get(newPos), 0, PRED_MAX)); preys.set(newPos, 0); } // Reproduction if (preds.get(newPos) == PRED_MAX) { preds.set(pos, PRED_ORIG); } } /*System.out.println(grass); System.out.println(preys);*/ //System.out.println(preds); //logger.info(stepChrono.stop().toString()); watch.stop(); } private void initGrid(int[] grid, int nbCells, int value) { int remainingCells = nbCells; Random rng = new Random(); while (remainingCells > 0) { final int pos = rng.nextInt(grid.length); if (grid[pos] == 0) { grid[pos] = value; remainingCells--; } } } // Helpers private int clamp(int value, int min, int max) { return Math.max(min, Math.min(value, max)); } public static void main(String[] args) { OptionParser parser = new OptionParser(); parser.acceptsAll(Arrays.asList("g", "gpu", "opencl"), "Enable OpenCL support") .withOptionalArg().ofType(Boolean.class).defaultsTo(true); parser.acceptsAll(Arrays.asList("h", "help"), "Print this help"); parser.accepts("size", "Size of the grid (side)").withRequiredArg() .ofType(Integer.class).defaultsTo(1000); parser.accepts("preys", "Number of Preys to use").withRequiredArg() .ofType(Integer.class).defaultsTo(10000); parser.accepts("preds", "Number of Predators to use").withRequiredArg() .ofType(Integer.class).defaultsTo(5000); parser.accepts("range", "Range to use for preys (x 1.5 for predators)").withRequiredArg() .ofType(Integer.class).defaultsTo(100); OptionSet options = parser.parse(args); if (options.has("help")) { try { parser.printHelpOn(System.out); return; } catch (IOException e) { System.err.println("Failed to print help to standard output"); e.printStackTrace(); } } PPRuntime runtime; if ((Boolean) (options.valueOf("gpu"))) { logger.info("Use OpenCL runtime on first available GPU"); runtime = new PPRuntimeGPU(); } else { logger.info("Use Java Runtime"); runtime = new PPRuntimeCPU(); } int size = (Integer) options.valueOf("size"); int nbPreys = (Integer) options.valueOf("preys"); int nbPreds = (Integer) options.valueOf("preds"); int range = (Integer) options.valueOf("range"); logger.info( "size: " + size + ", nbPreys: " + nbPreys + ", nbPreds: " + nbPreds + ", range: " + range ); //PPRuntime runtime = new PPRuntimeGPU(ContextType.ALL); //PPRuntime runtime = new PPRuntimeCPU(); PreyPredator2 simulation = new PreyPredator2(size, nbPreys, nbPreds, range, runtime); simulation.setup(); for (int i = 0; i < 50; i++) { simulation.step(); } } }