diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fc..fae0804 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/dev/oxoo2a/sim4da/Actor.java b/src/main/java/dev/oxoo2a/sim4da/Actor.java new file mode 100644 index 0000000..3f01622 --- /dev/null +++ b/src/main/java/dev/oxoo2a/sim4da/Actor.java @@ -0,0 +1,75 @@ +package dev.oxoo2a.sim4da; + +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +public class Actor { + private boolean active; + private double p; + private String lastAction; + private int senderId; + private int receiverId; + private int[] vectorClock; + + public Actor(int numActors) { + active = true; + p = 1.0; + vectorClock = new int[numActors]; + } + + //converging to 0. + public void updateP(int time) { + p -= 0.1; + if (p < 0.0) { + p = 0.0; // Ensure p does not go below 0 + } + } + + public boolean isActive(int actorIndex) { + if (active) { + System.out.println("[Actor " + actorIndex + " is active. ]"); + } else { + System.out.println("[Actor " + actorIndex + " is inactive. Last action: " + lastAction + "]"); + } + return active; + } + + public void receiveMessage(int senderId, int receiverId, int[] senderVectorClock) { + active = true; + this.senderId = senderId; + this.receiverId = receiverId; + lastAction = "Received from Actor " + senderId; + + for (int i = 0; i < vectorClock.length; i++) { + vectorClock[i] = Math.max(vectorClock[i], senderVectorClock[i]); + } + + vectorClock[receiverId]++; + + System.out.println("Actor " + receiverId + " received a message from Actor " + senderId + + " with Vector Clock: " + Arrays.toString(vectorClock)); + } + + + public boolean sendMessage(List actors, int senderIndex) { + if (active && Math.random() < p) { + active = false; + int receiverIndex = getRandoReceiverWithoutSender(actors, senderIndex); + int senderId = actors.indexOf(this); + actors.get(receiverIndex).receiveMessage(senderId, receiverIndex, vectorClock.clone()); + lastAction = "Sent to Actor " + receiverIndex; + return true; + } + return false; + } + + //to avoid an actor sending messages to themselves. + private int getRandoReceiverWithoutSender(List actors, int senderIndex) { + int receiverIndex; + do { + receiverIndex = new Random().nextInt(actors.size()); + } while (receiverIndex == senderIndex); + return receiverIndex; + } +} diff --git a/src/main/java/dev/oxoo2a/sim4da/DSSimulation.java b/src/main/java/dev/oxoo2a/sim4da/DSSimulation.java new file mode 100644 index 0000000..ad90884 --- /dev/null +++ b/src/main/java/dev/oxoo2a/sim4da/DSSimulation.java @@ -0,0 +1,81 @@ +package dev.oxoo2a.sim4da; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class DSSimulation { + private static final int NUM_ACTORS = 4; + private static final int MAX_STEPS = 100; + + public static void main(String[] args) { + List actors = new ArrayList<>(); + for (int i = 0; i < NUM_ACTORS; i++) { + actors.add(new Actor(NUM_ACTORS)); + } + + for (int i = 0; i < actors.size(); i++) { + actors.get(i).isActive(i); // Prints initial status of each actor with index + } + + int time = 1; + int steps = 0; + + DoubleCountingActor doubleCountingActor = new DoubleCountingActor(NUM_ACTORS); + LaggingStateVector vectorClockActor = new LaggingStateVector(NUM_ACTORS); + + while (steps < MAX_STEPS) { + System.out.println("------------------------------"); + System.out.println("Step " + steps + " starting..."); + System.out.println("------------------------------"); + + List activeActors = new ArrayList<>(); + for (int i = 0; i < actors.size(); i++) { + Actor actor = actors.get(i); + actor.updateP(time); + if (actor.isActive(i)) { + activeActors.add(actor); + } + } + + boolean anyMessagesSent = false; + for (Actor actor : activeActors) { + int senderIndex = actors.indexOf(actor); + if (actor.sendMessage(actors, senderIndex)) { + anyMessagesSent = true; + doubleCountingActor.receiveMessage(senderIndex); + } + } + + doubleCountingActor.actorTerminated(activeActors.size()); + + int[] senderVectorClock = new int[NUM_ACTORS]; + vectorClockActor.receiveMessage(activeActors, steps % NUM_ACTORS, senderVectorClock); + + System.out.println("Step " + steps + ": Active actors: " + activeActors.size()); + System.out.println("Event Clock: " + Arrays.toString(vectorClockActor.getVectorClock())); + + if (!anyMessagesSent) { + break; + } + + steps++; + time++; + } + + boolean doubleCountingTerminated = doubleCountingActor.hasTerminated(); + boolean vectorClockTerminated = vectorClockActor.hasTerminated(); + + if (doubleCountingTerminated) { + System.out.println("Double Counting Termination: All actors have terminated!"); + } else { + System.out.println("Double Counting Termination: Not all actors have terminated yet."); + } + + if (vectorClockTerminated) { + System.out.println("Lagging State Vector Termination: All actors have terminated!"); + } else { + System.out.println("Lagging State Vector Termination: Not all actors have terminated yet."); + } + } +} diff --git a/src/main/java/dev/oxoo2a/sim4da/DoubleCountingActor.java b/src/main/java/dev/oxoo2a/sim4da/DoubleCountingActor.java new file mode 100644 index 0000000..61d08c3 --- /dev/null +++ b/src/main/java/dev/oxoo2a/sim4da/DoubleCountingActor.java @@ -0,0 +1,45 @@ +package dev.oxoo2a.sim4da; + +import java.util.HashSet; +import java.util.Set; + +public class DoubleCountingActor { + private Set receivedMessages; + private Set terminatedActors; + private int count; + private int numActors; + + public DoubleCountingActor(int numActors) { + this.numActors = numActors; + receivedMessages = new HashSet<>(); + terminatedActors = new HashSet<>(); + count = 0; + } + + public void receiveMessage(int senderId) { + receivedMessages.add(senderId); + //System.out.println("Actor " + senderId + " received a message."); + + // Check termination based on the received messages + if (receivedMessages.size() == numActors) { + actorTerminated(1); + } + } + + public void actorTerminated(int numTerminatedActors) { + for (int i = 0; i < numTerminatedActors; i++) { + terminatedActors.add(count); + count++; + } + + if (terminatedActors.size() == numActors) { + System.out.println("All actors have terminated."); + } //else { + // System.out.println("Actor " + numTerminatedActors + " inactive."); + //} + } + + public boolean hasTerminated() { + return terminatedActors.size() == count; + } +} diff --git a/src/main/java/dev/oxoo2a/sim4da/LaggingStateVector.java b/src/main/java/dev/oxoo2a/sim4da/LaggingStateVector.java new file mode 100644 index 0000000..1dc006c --- /dev/null +++ b/src/main/java/dev/oxoo2a/sim4da/LaggingStateVector.java @@ -0,0 +1,45 @@ +package dev.oxoo2a.sim4da; + +import java.util.Arrays; +import java.util.List; + +public class LaggingStateVector { + private int[] vectorClock; + private int numActors; + + public LaggingStateVector(int numActors) { + this.numActors = numActors; + vectorClock = new int[numActors]; + } + + public void receiveMessage(List actors, int senderId, int[] senderVectorClock) { + for (int i = 0; i < numActors; i++) { + vectorClock[i] = Math.max(vectorClock[i], senderVectorClock[i]); + } + vectorClock[senderId]++; + + // Check termination based on the lagging state vector + for (int i = 0; i < numActors; i++) { + if (i != senderId && vectorClock[i] == vectorClock[senderId] - 1) { + vectorClock[i]++; + } + } + } + + public boolean hasTerminated() { + for (int i = 0; i < numActors; i++) { + if (vectorClock[i] == 0) + return false; + } + return true; + } + + public int[] getVectorClock() { + return vectorClock.clone(); + } + + @Override + public String toString() { + return Arrays.toString(vectorClock); + } +}