diff --git a/.gitignore b/.gitignore index 15ec33b84f7140607f1f6e3f525bc4c6ebac9365..8a57b516d785835db0f24624fd3dd5a85a522cc1 100644 --- a/.gitignore +++ b/.gitignore @@ -22,10 +22,9 @@ # compilated files from intelij target -src/main/resources/output.csv -src/main/resources/output.png -src/main/resources/pythonOutput/*.csv -src/main/resources/pythonOutput/*.png +#output files +*.csv +*.png # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..0e14d8e27d9a933d37bb36785cc9071844d97160 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "disabled" +} \ No newline at end of file diff --git a/src/main/java/agents/Agent.java b/src/main/java/agents/Agent.java index fcd55ead1704e7f779be11bd9b460cfd34f00ef8..56c1ada9e0d1ac205ab52a890a8f41ae670965b1 100644 --- a/src/main/java/agents/Agent.java +++ b/src/main/java/agents/Agent.java @@ -3,4 +3,6 @@ package agents; import behaviors.Wakeable; public interface Agent extends Wakeable { + + String getId(); } diff --git a/src/main/java/agents/RandomWalkingAgent.java b/src/main/java/agents/RandomWalkingAgent.java index 94187e770f7fe05b9ab615d20f84d1a5ac3a288b..c14ce90a6750ec138bda72a8be950264a203d79d 100644 --- a/src/main/java/agents/RandomWalkingAgent.java +++ b/src/main/java/agents/RandomWalkingAgent.java @@ -17,9 +17,11 @@ public class RandomWalkingAgent extends Randomized implements SEIRSAgent { private List<Point> authorizedPositions; private Point nextPosition; + private final String id; public RandomWalkingAgent(Point position, long seed, SEIRSEnvironment environment) { super(seed); + this.id = String.valueOf(seed); this.position = position; this.state = new SuceptibleSEIRSState(this); this.environment = environment; @@ -101,4 +103,9 @@ public class RandomWalkingAgent extends Randomized implements SEIRSAgent { @Override public Point getPosition() { return position; } + @Override + public String getId() { + return this.id; + } + } diff --git a/src/main/java/environment/ChunkedSEIRSEnvironment.java b/src/main/java/environment/ChunkedSEIRSEnvironment.java index 7bfbe659b79c6e7c67d9c4b1f4c4b90ee5dca5fc..e754588c510bf08394ae55fc599747f6881aa4f4 100644 --- a/src/main/java/environment/ChunkedSEIRSEnvironment.java +++ b/src/main/java/environment/ChunkedSEIRSEnvironment.java @@ -19,6 +19,7 @@ public class ChunkedSEIRSEnvironment implements SEIRSEnvironment { public final int size; private final SEIRSAgent[] agents; private List<SEIRSAgent>[][] chunks; + private final List<String> executionOrder = new ArrayList<>(); public ChunkedSEIRSEnvironment(int size, SEIRSAgent[] agents) { this.agents = agents; @@ -111,6 +112,7 @@ public class ChunkedSEIRSEnvironment implements SEIRSEnvironment { chunks[oldPosition.x/CHUNK_SIZE][oldPosition.y/CHUNK_SIZE].remove((SEIRSAgent) agent); chunks[newPosition.x/CHUNK_SIZE][newPosition.y/CHUNK_SIZE].add((SEIRSAgent) agent); } + executionOrder.add(((SEIRSAgent)agent).getId()); } @Override @@ -148,4 +150,9 @@ public class ChunkedSEIRSEnvironment implements SEIRSEnvironment { public int getSize() { return size; } + + @Override + public List<String> getExecutionOrder() { + return executionOrder; + } } diff --git a/src/main/java/environment/Environment.java b/src/main/java/environment/Environment.java index 100ed085ce0e990d6aa695c6b744cbeff5f1bb19..b696e323556c22a407a597b845bb39e58b98d759 100644 --- a/src/main/java/environment/Environment.java +++ b/src/main/java/environment/Environment.java @@ -1,4 +1,7 @@ package environment; +import java.util.List; + public interface Environment { + List<String> getExecutionOrder(); } diff --git a/src/main/java/models/Parameters.java b/src/main/java/models/Parameters.java index 4f0bc859b90e8d5b94707e8fd0f4f7cec56b5c66..6ff1c2ea0910a6553468e72c3e553eeaa394b35f 100644 --- a/src/main/java/models/Parameters.java +++ b/src/main/java/models/Parameters.java @@ -15,5 +15,7 @@ public record Parameters( boolean synchronousMode, boolean graphicalMode, boolean infectionStacks, - boolean wrappingWorld) { + boolean wrappingWorld, + boolean playRecord, + boolean recordExperiment) { } diff --git a/src/main/java/scheduler/DeterministScheduler.java b/src/main/java/scheduler/DeterministScheduler.java new file mode 100644 index 0000000000000000000000000000000000000000..aae3d1ed5db93b9187057c42c91d9bfea2634b75 --- /dev/null +++ b/src/main/java/scheduler/DeterministScheduler.java @@ -0,0 +1,50 @@ +package scheduler; + +import behaviors.Wakeable; +import utils.YamlReader; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.Arrays; +import java.util.EmptyStackException; +import java.util.Stack; + +public class DeterministScheduler implements Scheduler { + + private Wakeable[] agents; + private final Stack<String> wakeUpOrder = new Stack<>(); + + public DeterministScheduler(String csvFile) { + readCSV(csvFile); + System.out.println(wakeUpOrder.size()); + } + + private void readCSV(String file) { + try (BufferedReader br = new BufferedReader(new FileReader(file))) { + String line = br.readLine(); + String[] values = line.split(","); + wakeUpOrder.addAll(Arrays.asList(values)); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void init(Wakeable[] agents) { + this.agents = agents; + } + + @Override + public void doNextCycle() { + for (int i = 0 ; i<agents.length-1; i++) { + try { + int next = Integer.parseInt(wakeUpOrder.pop()); + agents[next-(int)YamlReader.getParams().seed()].wakeUp(); + } catch (EmptyStackException e) { + System.err.println("Last record entry was read, simulation cannot continue further."); + System.exit(1); + } + } + } +} diff --git a/src/main/java/sma/SEIRS_SMA.java b/src/main/java/sma/SEIRS_SMA.java index 12f9669f0f7787db3f71d972d2515315c877e9c4..5800ced539d566aafb8b40756bf1cff42e060c2d 100644 --- a/src/main/java/sma/SEIRS_SMA.java +++ b/src/main/java/sma/SEIRS_SMA.java @@ -9,6 +9,7 @@ import environment.WrappingChunkedSEIRSEnvironment; import models.Parameters; import agents.RandomWalkingAgent; import environment.ChunkedSEIRSEnvironment; +import scheduler.DeterministScheduler; import scheduler.FairAsynchronousScheduler; import scheduler.FairSynchronousScheduler; import scheduler.Scheduler; @@ -19,13 +20,17 @@ import view.FrameBuilder; import view.StatisticsCanvas; import java.awt.*; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.time.Duration; import java.time.Instant; import java.util.Date; import java.util.HashMap; +import java.util.List; -@SuppressWarnings("InfiniteLoopStatement") +@SuppressWarnings({"InfiniteLoopStatement", "ResultOfMethodCallIgnored"}) public class SEIRS_SMA extends Randomized implements SMA{ private final Parameters parameters; @@ -116,10 +121,18 @@ public class SEIRS_SMA extends Randomized implements SMA{ } private void initScheduler() { - if (parameters.synchronousMode()) { - scheduler = new FairSynchronousScheduler(parameters.seed()); + if (parameters.playRecord()) { + if (parameters.recordExperiment()) { + throw new IllegalStateException("You cannot record and play an experiment at the same time. " + + "Please check the parameters.yaml file."); + } + scheduler = new DeterministScheduler("src/main/resources/executionOrder.csv"); } else { - scheduler = new FairAsynchronousScheduler(); + if (parameters.synchronousMode()) { + scheduler = new FairSynchronousScheduler(parameters.seed()); + } else { + scheduler = new FairAsynchronousScheduler(); + } } scheduler.init(agents); } @@ -132,6 +145,26 @@ public class SEIRS_SMA extends Randomized implements SMA{ } } + private void recordExperiment() { + try{ + File file = new File("src/main/resources/executionOrder.csv"); + file.createNewFile(); + FileWriter fw = new FileWriter(file); + BufferedWriter bw = new BufferedWriter(fw); + + List<String> executionOrder= environment.getExecutionOrder(); + + for (int i = 0; i < executionOrder.size()-2; i++) { + bw.write(executionOrder.get(i)+","); + } + bw.write(executionOrder.get(executionOrder.size()-1)); + bw.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + @Override public void run() { Instant startTime = Instant.now(); @@ -146,6 +179,11 @@ public class SEIRS_SMA extends Randomized implements SMA{ doNextCycle(); cpt++; } + + if (parameters.recordExperiment()) { + recordExperiment(); + } + Instant endTime = Instant.now(); System.out.println("Simulation done !"); Duration duration = Duration.between(startTime,endTime); diff --git a/src/main/resources/output.png b/src/main/resources/output.png index 69b8e62af45708270f5e740429befd1f656ec7e1..646a683834196ca79a137a7c6906908de9243c02 100644 Binary files a/src/main/resources/output.png and b/src/main/resources/output.png differ diff --git a/src/main/resources/parameters.yaml b/src/main/resources/parameters.yaml index 78cea5de543adc070cb5755a13862ff21f8807fb..59a063d0cf29a1f078d7ada55e8ec591524d3b9d 100644 --- a/src/main/resources/parameters.yaml +++ b/src/main/resources/parameters.yaml @@ -6,6 +6,8 @@ recoveryRate: 0.14 nbOfCycles: 2000 nbOfPatientZero: 1 population: 3000 +recordExperiment: false +playRecord: true seed: 120 size: 1000 wrappingWorld : true