From 453ccdb47c793503a6f28c592b09866406b3d85d Mon Sep 17 00:00:00 2001
From: Alexandre <alexandre.perles@gmail.com>
Date: Mon, 18 Sep 2023 22:38:51 +0200
Subject: [PATCH] Add database support

---
 .../irit/smac/amas4dc/amas/MASSettings.java   |  9 ++--
 .../smac/amas4dc/amas/agent/ClusterAgent.java | 51 ++++++-------------
 .../amas4dc/amas/agent/DataPointAgent.java    |  3 ++
 .../fr/irit/smac/amas4dc/cluster/Cluster.java | 18 +++----
 .../amas4dc/cluster/DataPointDatabase.java    | 24 +++++++++
 .../smac/amas4dc/cluster/ExtendedCluster.java | 33 ++++--------
 .../smac/amas4dc/event/NewClusterEvent.java   |  8 ---
 .../amas4dc/event/RemoveClusterEvent.java     |  8 ---
 8 files changed, 62 insertions(+), 92 deletions(-)
 create mode 100644 src/main/java/fr/irit/smac/amas4dc/cluster/DataPointDatabase.java
 delete mode 100644 src/main/java/fr/irit/smac/amas4dc/event/NewClusterEvent.java
 delete mode 100644 src/main/java/fr/irit/smac/amas4dc/event/RemoveClusterEvent.java

diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/MASSettings.java b/src/main/java/fr/irit/smac/amas4dc/amas/MASSettings.java
index 52b70da..916cc21 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/MASSettings.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/MASSettings.java
@@ -1,10 +1,7 @@
 package fr.irit.smac.amas4dc.amas;
 
 import fr.irit.smac.amak.event.EventStore;
-import fr.irit.smac.amas4dc.cluster.Cluster;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
-import fr.irit.smac.amas4dc.cluster.DataPointFuser;
-import fr.irit.smac.amas4dc.cluster.DistanceMethod;
+import fr.irit.smac.amas4dc.cluster.*;
 
 import java.util.EnumSet;
 
@@ -13,9 +10,9 @@ public record MASSettings<T extends DataPoint>(
 		float fusionThreshold,
 		EnumSet<AMASOption> amasOptions,
 		DataPointFuser<T> dataPointFuser,
-		EventStore<Cluster<T>> eventStore
+		DataPointDatabase<T> database
 ) {
 	public MASSettings(DistanceMethod<T> distanceMethod, float fusionThreshold, EnumSet<AMASOption> amasOptions, DataPointFuser<T> dataPointFuser) {
-		this(distanceMethod, fusionThreshold, amasOptions, dataPointFuser, null);
+		this(distanceMethod, fusionThreshold, amasOptions, dataPointFuser, new DataPointDatabase<T>());
 	}
 }
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/agent/ClusterAgent.java b/src/main/java/fr/irit/smac/amas4dc/amas/agent/ClusterAgent.java
index 2b2458c..2162b40 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/agent/ClusterAgent.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/agent/ClusterAgent.java
@@ -12,8 +12,6 @@ import fr.irit.smac.amas4dc.amas.messages.RequestClusterDistanceToBeAbsorbedMess
 import fr.irit.smac.amas4dc.cluster.Cluster;
 import fr.irit.smac.amas4dc.cluster.DataPoint;
 import fr.irit.smac.amas4dc.cluster.ExtendedCluster;
-import fr.irit.smac.amas4dc.event.NewClusterEvent;
-import fr.irit.smac.amas4dc.event.RemoveClusterEvent;
 import lombok.Getter;
 
 import java.text.MessageFormat;
@@ -24,7 +22,7 @@ import java.util.logging.Logger;
 public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAMAS<T>, DynamicClusteringEnvironment<T>> {
 	@Getter
 
-	private Cluster<T> cluster;
+	private final Cluster<T> cluster;
 	private State state = State.DORMANT;
 	private State nextState = state;
 
@@ -32,22 +30,22 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM
 
 	//region Action variables
 	//endregion
-	private final Random random = new Random();
 	private static final Logger logger = Logger.getLogger(ClusterAgent.class.getName());
-	private int amountOfCyclesWithTheSameState;
+
 	private Optional<RequestDataPointDistanceToBeAbsorbedMessage> receivedRequestDataPointDistanceToBeAbsorbedMessage = Optional.empty();
 	private Optional<RequestClusterDistanceToBeAbsorbedMessage> receivedRequestClusterDistanceToBeAbsorbedMessage = Optional.empty();
 	private Optional<InformMostSimilarMessage> receivedInformMostSimilarClusterAgentsMessage = Optional.empty();
-	private List<ClusterAgent<T>> requestDistanceMessageSentAgents =  new ArrayList<>();
+	private List<ClusterAgent<T>> requestDistanceMessageSentAgents = new ArrayList<>();
 
 	protected ClusterAgent(DynamicClusteringAMAS amas, T dataPoint) {
 		super(amas);
 		if (logger.isLoggable(Level.INFO))
 			logger.info(this + " created");
 		if (amas.getMasSettings().amasOptions().contains(AMASOption.KeepAllDataPoints))
-			this.setCluster(new ExtendedCluster<T>(dataPoint));
+			cluster = new ExtendedCluster<T>(dataPoint);
 		else
-			this.setCluster(new Cluster<T>(dataPoint));
+			cluster = new Cluster<T>(dataPoint);
+		amas.getMasSettings().database().add(cluster.getRepresentative());
 	}
 
 	public enum State {DORMANT, WAITING_FOR_DISTANCE, DEAD}
@@ -191,7 +189,7 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM
 						                                                                                   getCluster(),
 						                                                                                   othersSimilarClusterAgents));
 						destroy();
-					}else{
+					} else {
 						nextState = State.DORMANT;
 					}
 				}
@@ -210,51 +208,34 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM
 			logger.info(this + " absorbs the data point " + otherDataPoint);
 
 		T newRepresentative = (T) amas.getMasSettings().dataPointFuser().apply(cluster.getRepresentative(), otherDataPoint);
-		Cluster<T> newCluster;
-		if (getAmas().getMasSettings().amasOptions().contains(AMASOption.KeepAllDataPoints))
-			newCluster = new ExtendedCluster<>(newRepresentative, otherDataPoint, cluster);
-		else
-			newCluster = new Cluster<T>(newRepresentative, otherDataPoint, cluster);
-		setCluster(newCluster);
+		cluster.setRepresentative(newRepresentative);
+		cluster.addDataPoint(otherDataPoint);
 	}
+
 	private void absorbCluster(Cluster<T> otherCluster) {
 		if (logger.isLoggable(Level.INFO))
 			logger.info(this + " absorbs the cluster " + otherCluster);
 
 		T newRepresentative = (T) amas.getMasSettings().dataPointFuser().apply(cluster.getRepresentative(), otherCluster.getRepresentative());
-		Cluster<T> newCluster;
-		if (getAmas().getMasSettings().amasOptions().contains(AMASOption.KeepAllDataPoints))
-			newCluster = new ExtendedCluster<>(newRepresentative, otherCluster, cluster);
-		else
-			newCluster = new Cluster<T>(newRepresentative, otherCluster, cluster);
-		setCluster(newCluster);
-	}
 
-	private void setCluster(Cluster<T> newCluster) {
-		if (cluster != null) {
-			getAmas().getEnvironment().removeFromBucket(cluster.getRepresentative().getBucketId(), this);
-			if (getAmas().getMasSettings().eventStore() != null)
-				getAmas().getMasSettings().eventStore().add(new RemoveClusterEvent(cluster));
-		}
+		cluster.setRepresentative(newRepresentative);
+
+		if (getAmas().getMasSettings().amasOptions().contains(AMASOption.KeepAllDataPoints))
+			((ExtendedCluster<T>) cluster).addClusterContent((ExtendedCluster<T>) otherCluster);
 
-		cluster = newCluster;
-		getAmas().getEnvironment().assignToBucket(cluster.getRepresentative().getBucketId(), this);
-		if (getAmas().getMasSettings().eventStore() != null)
-			getAmas().getMasSettings().eventStore().add(new NewClusterEvent(cluster));
 	}
 
 	@Override
 	protected void onDestroy() {
-		if (cluster != null)
-			if (getAmas().getMasSettings().eventStore() != null)
-				getAmas().getMasSettings().eventStore().add(new RemoveClusterEvent(cluster));
 		nextState = State.DEAD;
+		amas.getMasSettings().database().remove(cluster.getRepresentative());
 	}
 
 
 	private float computeDistance(T other) {
 		return getAmas().getMasSettings().distanceMethod().apply(this.cluster.getRepresentative(), other);
 	}
+
 	private float computeDistance(Cluster<T> other) {
 		return getAmas().getMasSettings().distanceMethod().apply(this.cluster.getRepresentative(), other.getRepresentative());
 	}
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/agent/DataPointAgent.java b/src/main/java/fr/irit/smac/amas4dc/amas/agent/DataPointAgent.java
index 63ea2ff..c7e44df 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/agent/DataPointAgent.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/agent/DataPointAgent.java
@@ -49,6 +49,9 @@ public class DataPointAgent<T extends DataPoint> extends Agent<DynamicClustering
 			agent.getMailbox().receive(new RequestDataPointDistanceToBeAbsorbedMessage<T>(this, dataPoint));
 			requestDistanceMessageSentAgents.add(agent);
 		}
+
+		if (logger.isLoggable(Level.INFO))
+			logger.info(this + " has "+clusterAgentsRoughlySimilarOnReady.size()+" roughly similar");
 	}
 
 	@Override
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/Cluster.java b/src/main/java/fr/irit/smac/amas4dc/cluster/Cluster.java
index ede936d..b4b0753 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/Cluster.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/Cluster.java
@@ -2,6 +2,7 @@ package fr.irit.smac.amas4dc.cluster;
 
 import fr.irit.smac.amas4dc.amas.controller.MissingDataPointsException;
 import lombok.Getter;
+import lombok.Setter;
 import lombok.ToString;
 
 import java.util.ArrayList;
@@ -12,25 +13,18 @@ import java.util.UUID;
 @ToString
 public class Cluster<T extends DataPoint> {
 	@Getter
-	private final String id = UUID.randomUUID().toString();
+	@Setter
+	private T representative;
 	@Getter
-	private final T representative;
-	@Getter
-	private final int size;
+	private int size;
 
 	public Cluster(T representative) {
 		this.representative = representative;
 		this.size = 1;
 	}
-
-	public Cluster(T representative, Cluster<T> c1, Cluster<T> c2) {
-		this.representative = representative;
-		this.size = c1.size + c2.size;
+	public void addDataPoint(T dataPoint) {
+		size++;
 	}
 
-	public Cluster(T representative, T newDataPoint, Cluster<T> c2) {
-		this.representative = representative;
-		this.size = 1 + c2.size;
-	}
 }
 
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/DataPointDatabase.java b/src/main/java/fr/irit/smac/amas4dc/cluster/DataPointDatabase.java
new file mode 100644
index 0000000..efc7c14
--- /dev/null
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/DataPointDatabase.java
@@ -0,0 +1,24 @@
+package fr.irit.smac.amas4dc.cluster;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class DataPointDatabase<T extends DataPoint> {
+	private List<T> content = new ArrayList<>();
+	public void add(T newDataPoint) {
+		content.add(newDataPoint);
+	}
+
+	public void remove(T dataPoint) {
+		content.remove(dataPoint);
+	}
+
+	public List<T> get() {
+		return Collections.unmodifiableList(content);
+	}
+
+	public boolean contains(T dataPoint) {
+		return content.contains(dataPoint);
+	}
+}
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/ExtendedCluster.java b/src/main/java/fr/irit/smac/amas4dc/cluster/ExtendedCluster.java
index d2bc0c0..fc4a7d4 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/ExtendedCluster.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/ExtendedCluster.java
@@ -8,35 +8,22 @@ import java.util.List;
 
 public class ExtendedCluster<T extends DataPoint> extends Cluster<T> {
 	@Getter
-	private final List<T> content;
+	private final List<T> content = new ArrayList<>();
 
 	public ExtendedCluster(T representative) {
 		super(representative);
-		this.content = Collections.singletonList(representative);
+		this.content.add(representative);
 	}
 
-	public ExtendedCluster(T representative, Cluster<T> c1, Cluster<T> c2) {
-		super(representative, c1, c2);
-
-		if (!(c1 instanceof ExtendedCluster<T> ec1) || !(c2 instanceof ExtendedCluster<T> ec2))
-			throw new ExtendedClusterException("ExtendedCluster can only be made out of two ExtendedCluster objects");
-
-		var content = new ArrayList<T>(ec1.getContent());
-		content.addAll(ec2.getContent());
-
-		this.content = Collections.unmodifiableList(content);
+	@Override
+	public void addDataPoint(T dataPoint) {
+		super.addDataPoint(dataPoint);
+		content.add(dataPoint);
 	}
 
-	public ExtendedCluster(T representative, T newDataPoint, Cluster<T> c2) {
-		super(representative, newDataPoint, c2);
-
-		if (!(c2 instanceof ExtendedCluster<T> ec2))
-			throw new ExtendedClusterException("ExtendedCluster can only be made out of an ExtendedCluster object");
-
-		var content = new ArrayList<T>();
-		content.add(newDataPoint);
-		content.addAll(ec2.getContent());
-
-		this.content = Collections.unmodifiableList(content);
+	public void addClusterContent(ExtendedCluster<T> otherCluster) {
+		for (var dp : otherCluster.getContent()) {
+			addDataPoint(dp);
+		}
 	}
 }
diff --git a/src/main/java/fr/irit/smac/amas4dc/event/NewClusterEvent.java b/src/main/java/fr/irit/smac/amas4dc/event/NewClusterEvent.java
deleted file mode 100644
index 8c71881..0000000
--- a/src/main/java/fr/irit/smac/amas4dc/event/NewClusterEvent.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package fr.irit.smac.amas4dc.event;
-
-import fr.irit.smac.amak.event.Event;
-import fr.irit.smac.amas4dc.cluster.Cluster;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
-
-public record NewClusterEvent<T extends DataPoint>(Cluster<T> cluster) implements Event {
-}
diff --git a/src/main/java/fr/irit/smac/amas4dc/event/RemoveClusterEvent.java b/src/main/java/fr/irit/smac/amas4dc/event/RemoveClusterEvent.java
deleted file mode 100644
index be840a5..0000000
--- a/src/main/java/fr/irit/smac/amas4dc/event/RemoveClusterEvent.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package fr.irit.smac.amas4dc.event;
-
-import fr.irit.smac.amak.event.Event;
-import fr.irit.smac.amas4dc.cluster.Cluster;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
-
-public record RemoveClusterEvent<T extends DataPoint>(Cluster<T> cluster) implements Event {
-}
-- 
GitLab