From 041bfed0b09e201f7e40511c1c05d27f319f12f1 Mon Sep 17 00:00:00 2001
From: Alexandre <alexandre.perles@gmail.com>
Date: Fri, 6 Oct 2023 10:50:44 +0200
Subject: [PATCH] Structure code

---
 .../groovy/TemperatureClustering.groovy       |  6 +--
 .../TwoDimensionsPointsClustering.groovy      |  4 +-
 .../java/fr/irit/smac/amas4dc/AMAS4DC.java    |  5 ++-
 .../fr/irit/smac/amas4dc/amas/AMASOption.java |  2 -
 .../amas4dc/amas/DynamicClusteringAMAS.java   |  2 +-
 .../amas/DynamicClusteringEnvironment.java    |  3 +-
 .../irit/smac/amas4dc/amas/MASSettings.java   |  6 ++-
 .../smac/amas4dc/amas/agent/ClusterAgent.java | 38 ++++++-------------
 .../amas4dc/amas/agent/DataPointAgent.java    | 10 ++---
 .../AMAS4DCCommandAndQueryHandler.java        |  4 +-
 .../command/NewDataPointCommand.java          |  2 +-
 .../amas/controller/query/ExtendedResult.java |  3 +-
 .../amas4dc/amas/controller/query/Result.java |  2 +-
 .../messages/EvaluatedDistanceMessage.java    |  2 +-
 .../messages/InformMostSimilarMessage.java    |  3 +-
 ...estClusterDistanceToBeAbsorbedMessage.java |  2 +-
 ...tDataPointDistanceToBeAbsorbedMessage.java |  2 +-
 .../fr/irit/smac/amas4dc/cluster/Cluster.java |  7 +---
 .../smac/amas4dc/cluster/ExtendedCluster.java |  2 +-
 .../cluster/{ => datapoint}/DataPoint.java    |  2 +-
 .../{ => datapoint}/DataPointDatabase.java    |  4 +-
 .../{ => datapoint}/DataPointFuser.java       |  2 +-
 .../distance}/ClusterDistance.java            |  4 +-
 .../{ => distance}/DistanceMethod.java        |  4 +-
 .../CalinskiHarabazIndex.java                 |  5 ++-
 .../SilhouetteScoreCalculator.java            |  4 +-
 .../ExtendedClusterException.java             |  2 +-
 .../{ => exception}/FusionException.java      |  2 +-
 src/test/groovy/SimpleClusteringIT.groovy     |  6 +--
 .../smac/amas4dc/amas/ClusterAgentTest.groovy |  6 +--
 30 files changed, 64 insertions(+), 82 deletions(-)
 rename src/main/java/fr/irit/smac/amas4dc/cluster/{ => datapoint}/DataPoint.java (61%)
 rename src/main/java/fr/irit/smac/amas4dc/cluster/{ => datapoint}/DataPointDatabase.java (88%)
 rename src/main/java/fr/irit/smac/amas4dc/cluster/{ => datapoint}/DataPointFuser.java (72%)
 rename src/main/java/fr/irit/smac/amas4dc/{amas => cluster/distance}/ClusterDistance.java (57%)
 rename src/main/java/fr/irit/smac/amas4dc/cluster/{ => distance}/DistanceMethod.java (55%)
 rename src/main/java/fr/irit/smac/amas4dc/cluster/{ => evaluation}/CalinskiHarabazIndex.java (91%)
 rename src/main/java/fr/irit/smac/amas4dc/cluster/{ => evaluation}/SilhouetteScoreCalculator.java (92%)
 rename src/main/java/fr/irit/smac/amas4dc/cluster/{ => exception}/ExtendedClusterException.java (72%)
 rename src/main/java/fr/irit/smac/amas4dc/cluster/{ => exception}/FusionException.java (71%)

diff --git a/src/experiments/groovy/TemperatureClustering.groovy b/src/experiments/groovy/TemperatureClustering.groovy
index 5f804ea..cecc709 100644
--- a/src/experiments/groovy/TemperatureClustering.groovy
+++ b/src/experiments/groovy/TemperatureClustering.groovy
@@ -2,9 +2,9 @@ import fr.irit.smac.amas4dc.AMAS4DC
 import fr.irit.smac.amas4dc.amas.AMASOption
 import fr.irit.smac.amas4dc.amas.MASSettings
 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.datapoint.DataPoint
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPointFuser
+import fr.irit.smac.amas4dc.cluster.distance.DistanceMethod
 import fr.irit.smac.lxplot.LxPlot
 import groovy.transform.ToString
 
diff --git a/src/experiments/groovy/TwoDimensionsPointsClustering.groovy b/src/experiments/groovy/TwoDimensionsPointsClustering.groovy
index 16ee07a..79eb2e4 100644
--- a/src/experiments/groovy/TwoDimensionsPointsClustering.groovy
+++ b/src/experiments/groovy/TwoDimensionsPointsClustering.groovy
@@ -2,8 +2,8 @@ import fr.irit.smac.amas4dc.AMAS4DC
 import fr.irit.smac.amas4dc.amas.AMASOption
 import fr.irit.smac.amas4dc.amas.MASSettings
 import fr.irit.smac.amas4dc.cluster.Cluster
-import fr.irit.smac.amas4dc.cluster.DataPoint
-import fr.irit.smac.amas4dc.cluster.DistanceMethod
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint
+import fr.irit.smac.amas4dc.cluster.distance.DistanceMethod
 import fr.irit.smac.lxplot.LxPlot
 import fr.irit.smac.lxplot.commons.ChartType
 import groovy.transform.ToString
diff --git a/src/main/java/fr/irit/smac/amas4dc/AMAS4DC.java b/src/main/java/fr/irit/smac/amas4dc/AMAS4DC.java
index 6433f9b..6dd9cfb 100644
--- a/src/main/java/fr/irit/smac/amas4dc/AMAS4DC.java
+++ b/src/main/java/fr/irit/smac/amas4dc/AMAS4DC.java
@@ -8,7 +8,7 @@ import fr.irit.smac.amas4dc.amas.controller.query.ExtendedResult;
 import fr.irit.smac.amas4dc.amas.controller.query.Result;
 import fr.irit.smac.amas4dc.amas.controller.query.RetrieveClustersExtendedResultQuery;
 import fr.irit.smac.amas4dc.amas.controller.query.RetrieveClustersResultQuery;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 
 import java.util.List;
 
@@ -18,13 +18,16 @@ public class AMAS4DC<T extends DataPoint> {
 	public AMAS4DC(MASSettings<T> masSettings) {
 		this.controller = new AMAS4DCCommandAndQueryHandler<T>(masSettings);
 	}
+
 	public void fit(List<T> data) {
 		controller.handle(new NewDataPointCommand<T>(data));
 		controller.handle(new SolveCommand());
 	}
+
 	public Result<T> retrieveClusters() {
 		return controller.handle(new RetrieveClustersResultQuery());
 	}
+
 	public ExtendedResult<T> retrieveExtendedClusters() {
 		return controller.handle(new RetrieveClustersExtendedResultQuery());
 	}
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/AMASOption.java b/src/main/java/fr/irit/smac/amas4dc/amas/AMASOption.java
index 943fd10..b9fec55 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/AMASOption.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/AMASOption.java
@@ -1,7 +1,5 @@
 package fr.irit.smac.amas4dc.amas;
 
 public enum AMASOption {
-	@Deprecated
-	Forget,
 	KeepAllDataPoints
 }
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/DynamicClusteringAMAS.java b/src/main/java/fr/irit/smac/amas4dc/amas/DynamicClusteringAMAS.java
index 680929a..6819af7 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/DynamicClusteringAMAS.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/DynamicClusteringAMAS.java
@@ -3,7 +3,7 @@ package fr.irit.smac.amas4dc.amas;
 import fr.irit.smac.amak.Amas;
 import fr.irit.smac.amas4dc.amas.agent.ClusterAgent;
 import fr.irit.smac.amas4dc.amas.agent.DataPointAgent;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 import lombok.Getter;
 import lombok.Setter;
 
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/DynamicClusteringEnvironment.java b/src/main/java/fr/irit/smac/amas4dc/amas/DynamicClusteringEnvironment.java
index 83f61c6..24dcd28 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/DynamicClusteringEnvironment.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/DynamicClusteringEnvironment.java
@@ -2,7 +2,7 @@ package fr.irit.smac.amas4dc.amas;
 
 import fr.irit.smac.amak.Environment;
 import fr.irit.smac.amas4dc.amas.agent.ClusterAgent;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 import lombok.Getter;
 
 import java.util.*;
@@ -13,7 +13,6 @@ import java.util.logging.Logger;
 public class DynamicClusteringEnvironment<T extends DataPoint> extends Environment {
 
 	private final Queue<T> pendingAdditionDataPoints = new ConcurrentLinkedQueue<>();
-	private static final Logger logger = Logger.getLogger(DynamicClusteringEnvironment.class.getName());
 	@Getter
 	private T lastPolledPendingDataPoint = null;
 	private final Map<Integer, List<ClusterAgent<T>>> buckets = new ConcurrentHashMap<>();
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 916cc21..fcedf34 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/MASSettings.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/MASSettings.java
@@ -1,7 +1,9 @@
 package fr.irit.smac.amas4dc.amas;
 
-import fr.irit.smac.amak.event.EventStore;
-import fr.irit.smac.amas4dc.cluster.*;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPointDatabase;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPointFuser;
+import fr.irit.smac.amas4dc.cluster.distance.DistanceMethod;
 
 import java.util.EnumSet;
 
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 96fdc46..a1e45e0 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
@@ -2,7 +2,7 @@ package fr.irit.smac.amas4dc.amas.agent;
 
 import fr.irit.smac.amak.Agent;
 import fr.irit.smac.amas4dc.amas.AMASOption;
-import fr.irit.smac.amas4dc.amas.ClusterDistance;
+import fr.irit.smac.amas4dc.cluster.distance.ClusterDistance;
 import fr.irit.smac.amas4dc.amas.DynamicClusteringAMAS;
 import fr.irit.smac.amas4dc.amas.DynamicClusteringEnvironment;
 import fr.irit.smac.amas4dc.amas.messages.EvaluatedDistanceMessage;
@@ -10,7 +10,7 @@ import fr.irit.smac.amas4dc.amas.messages.InformMostSimilarMessage;
 import fr.irit.smac.amas4dc.amas.messages.RequestDataPointDistanceToBeAbsorbedMessage;
 import fr.irit.smac.amas4dc.amas.messages.RequestClusterDistanceToBeAbsorbedMessage;
 import fr.irit.smac.amas4dc.cluster.Cluster;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 import fr.irit.smac.amas4dc.cluster.ExtendedCluster;
 import lombok.Getter;
 
@@ -20,22 +20,18 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAMAS<T>, DynamicClusteringEnvironment<T>> {
+	private static final Logger logger = Logger.getLogger(ClusterAgent.class.getName());
 	@Getter
-
 	private final Cluster<T> cluster;
 	private State state = State.DORMANT;
-	private State nextState = state;
 
 	private final Map<ClusterAgent<T>, ClusterDistance<T>> distancesReceived = new HashMap<>();
 
-	//region Action variables
-	//endregion
-	private static final Logger logger = Logger.getLogger(ClusterAgent.class.getName());
 
 	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 final List<ClusterAgent<T>> requestDistanceMessageSentAgents = new ArrayList<>();
 
 	protected ClusterAgent(DynamicClusteringAMAS amas, T dataPoint) {
 		super(amas);
@@ -91,7 +87,6 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM
 				if (receivedRequestClusterDistanceToBeAbsorbedMessage.isPresent()) {
 					if (logger.isLoggable(Level.INFO))
 						logger.info(this + " received a request for distance to be absorbed");
-					return;
 				}
 			}
 			case WAITING_FOR_DISTANCE -> {
@@ -108,7 +103,7 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM
 
 
 	private void clearDeadAgentsFromThoseWeExpectAnAnswerFrom() {
-		requestDistanceMessageSentAgents.removeIf(a -> a.getState() == ClusterAgent.State.DEAD && !distancesReceived.keySet().contains(a));
+		requestDistanceMessageSentAgents.removeIf(a -> a.getState() == ClusterAgent.State.DEAD && !distancesReceived.containsKey(a));
 		for (var key :
 				distancesReceived.keySet()) {
 			if (!requestDistanceMessageSentAgents.contains(key))
@@ -118,6 +113,7 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM
 
 	@Override
 	protected void onDecideAndAct() {
+		State nextState = null;
 		switch (state) {
 			case DORMANT -> {
 				if (receivedRequestDataPointDistanceToBeAbsorbedMessage.isPresent()) {
@@ -154,13 +150,6 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM
 					} else {
 						nextState = State.DORMANT;
 					}
-				} else if (amas.getMasSettings().amasOptions().contains(AMASOption.Forget)) {
-					// TODO decide to die logic
-					/*
-					if (dieCondition()) {
-						destroy();
-					}
-					*/
 				}
 			}
 			case WAITING_FOR_DISTANCE -> {
@@ -197,19 +186,15 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM
 				}
 			}
 		}
-		applyNextState();
-	}
-
-
-	private void applyNextState() {
-		state = nextState;
+		if (nextState != null)
+			state = nextState;
 	}
 
 	private void absorbDataPoint(T otherDataPoint) {
 		if (logger.isLoggable(Level.INFO))
 			logger.info(this + " absorbs the data point " + otherDataPoint);
 
-		T newRepresentative = (T) amas.getMasSettings().dataPointFuser().apply(cluster.getRepresentative(), otherDataPoint);
+		amas.getMasSettings().dataPointFuser().apply(cluster.getRepresentative(), otherDataPoint);
 		cluster.addDataPoint(otherDataPoint);
 	}
 
@@ -218,8 +203,7 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM
 			logger.info(this + " absorbs the cluster " + otherCluster);
 
 		amas.getMasSettings().dataPointFuser().apply(cluster.getRepresentative(), otherCluster.getRepresentative());
-
-
+		
 		if (getAmas().getMasSettings().amasOptions().contains(AMASOption.KeepAllDataPoints))
 			((ExtendedCluster<T>) cluster).addClusterContent((ExtendedCluster<T>) otherCluster);
 		else
@@ -229,7 +213,7 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM
 
 	@Override
 	protected void onDestroy() {
-		nextState = State.DEAD;
+		state = State.DEAD;
 		amas.getMasSettings().database().remove(cluster.getRepresentative());
 		getAmas().getEnvironment().removeFromBucket(cluster.getRepresentative().getBucketId(), this);
 	}
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 87792ba..d525868 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
@@ -1,14 +1,13 @@
 package fr.irit.smac.amas4dc.amas.agent;
 
 import fr.irit.smac.amak.Agent;
-import fr.irit.smac.amas4dc.amas.ClusterDistance;
+import fr.irit.smac.amas4dc.cluster.distance.ClusterDistance;
 import fr.irit.smac.amas4dc.amas.DynamicClusteringAMAS;
 import fr.irit.smac.amas4dc.amas.DynamicClusteringEnvironment;
 import fr.irit.smac.amas4dc.amas.messages.EvaluatedDistanceMessage;
 import fr.irit.smac.amas4dc.amas.messages.InformMostSimilarMessage;
 import fr.irit.smac.amas4dc.amas.messages.RequestDataPointDistanceToBeAbsorbedMessage;
-import fr.irit.smac.amas4dc.cluster.Cluster;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 
 import java.text.MessageFormat;
 import java.util.*;
@@ -16,11 +15,10 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 public class DataPointAgent<T extends DataPoint> extends Agent<DynamicClusteringAMAS<T>, DynamicClusteringEnvironment<T>> {
-	private static final float FLOAT_COMPARISON_EPSILON = 0.000001f;
+	private static final Logger logger = Logger.getLogger(DataPointAgent.class.getName());
 	private final T dataPoint;
 	private final List<ClusterAgent<T>> requestDistanceMessageSentAgents = new ArrayList<>();
 	private final Map<ClusterAgent<T>, ClusterDistance<T>> distancesReceived = new HashMap<>();
-	private static final Logger logger = Logger.getLogger(DataPointAgent.class.getName());
 
 	public DataPointAgent(DynamicClusteringAMAS<T> amas, T dataPoint) {
 		super(amas);
@@ -115,7 +113,7 @@ public class DataPointAgent<T extends DataPoint> extends Agent<DynamicClustering
 	}
 
 	private void clearDeadAgentsFromThoseWeExpectAnAnswerFrom() {
-		requestDistanceMessageSentAgents.removeIf(a -> a.getState() == ClusterAgent.State.DEAD && !distancesReceived.keySet().contains(a));
+		requestDistanceMessageSentAgents.removeIf(a -> a.getState() == ClusterAgent.State.DEAD && !distancesReceived.containsKey(a));
 		for (var key :
 				distancesReceived.keySet()) {
 			if (!requestDistanceMessageSentAgents.contains(key))
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/controller/AMAS4DCCommandAndQueryHandler.java b/src/main/java/fr/irit/smac/amas4dc/amas/controller/AMAS4DCCommandAndQueryHandler.java
index f984f25..b33dfb9 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/controller/AMAS4DCCommandAndQueryHandler.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/controller/AMAS4DCCommandAndQueryHandler.java
@@ -10,9 +10,9 @@ import fr.irit.smac.amas4dc.amas.controller.query.ExtendedResult;
 import fr.irit.smac.amas4dc.amas.controller.query.Result;
 import fr.irit.smac.amas4dc.amas.controller.query.RetrieveClustersExtendedResultQuery;
 import fr.irit.smac.amas4dc.amas.controller.query.RetrieveClustersResultQuery;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 import fr.irit.smac.amas4dc.cluster.ExtendedCluster;
-import fr.irit.smac.amas4dc.cluster.SilhouetteScoreCalculator;
+import fr.irit.smac.amas4dc.cluster.evaluation.SilhouetteScoreCalculator;
 import lombok.Getter;
 
 import java.util.concurrent.Executors;
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/controller/command/NewDataPointCommand.java b/src/main/java/fr/irit/smac/amas4dc/amas/controller/command/NewDataPointCommand.java
index 70c99e2..105ff84 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/controller/command/NewDataPointCommand.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/controller/command/NewDataPointCommand.java
@@ -1,6 +1,6 @@
 package fr.irit.smac.amas4dc.amas.controller.command;
 
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 
 import java.util.List;
 
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/controller/query/ExtendedResult.java b/src/main/java/fr/irit/smac/amas4dc/amas/controller/query/ExtendedResult.java
index 97ef4f1..5b42601 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/controller/query/ExtendedResult.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/controller/query/ExtendedResult.java
@@ -1,8 +1,7 @@
 package fr.irit.smac.amas4dc.amas.controller.query;
 
 import fr.irit.smac.amas4dc.amas.MASSettings;
-import fr.irit.smac.amas4dc.cluster.Cluster;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 import fr.irit.smac.amas4dc.cluster.ExtendedCluster;
 
 import java.util.List;
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/controller/query/Result.java b/src/main/java/fr/irit/smac/amas4dc/amas/controller/query/Result.java
index 500d99e..2ee3487 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/controller/query/Result.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/controller/query/Result.java
@@ -2,7 +2,7 @@ package fr.irit.smac.amas4dc.amas.controller.query;
 
 import fr.irit.smac.amas4dc.amas.MASSettings;
 import fr.irit.smac.amas4dc.cluster.Cluster;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 
 import java.util.List;
 
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/messages/EvaluatedDistanceMessage.java b/src/main/java/fr/irit/smac/amas4dc/amas/messages/EvaluatedDistanceMessage.java
index 18a885c..e813d5a 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/messages/EvaluatedDistanceMessage.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/messages/EvaluatedDistanceMessage.java
@@ -3,7 +3,7 @@ package fr.irit.smac.amas4dc.amas.messages;
 import fr.irit.smac.amak.messaging.Message;
 import fr.irit.smac.amas4dc.amas.agent.ClusterAgent;
 import fr.irit.smac.amas4dc.cluster.Cluster;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 import lombok.Getter;
 import lombok.ToString;
 
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/messages/InformMostSimilarMessage.java b/src/main/java/fr/irit/smac/amas4dc/amas/messages/InformMostSimilarMessage.java
index 5cf0d9b..c268633 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/messages/InformMostSimilarMessage.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/messages/InformMostSimilarMessage.java
@@ -3,9 +3,8 @@ package fr.irit.smac.amas4dc.amas.messages;
 import fr.irit.smac.amak.Agent;
 import fr.irit.smac.amak.messaging.Message;
 import fr.irit.smac.amas4dc.amas.agent.ClusterAgent;
-import fr.irit.smac.amas4dc.amas.agent.DataPointAgent;
 import fr.irit.smac.amas4dc.cluster.Cluster;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 import lombok.Getter;
 
 import java.util.List;
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestClusterDistanceToBeAbsorbedMessage.java b/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestClusterDistanceToBeAbsorbedMessage.java
index af4c75a..dddbd42 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestClusterDistanceToBeAbsorbedMessage.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestClusterDistanceToBeAbsorbedMessage.java
@@ -3,7 +3,7 @@ package fr.irit.smac.amas4dc.amas.messages;
 import fr.irit.smac.amak.messaging.Message;
 import fr.irit.smac.amas4dc.amas.agent.ClusterAgent;
 import fr.irit.smac.amas4dc.cluster.Cluster;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 import lombok.Getter;
 
 public class RequestClusterDistanceToBeAbsorbedMessage<T extends DataPoint> extends Message<ClusterAgent<T>> {
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestDataPointDistanceToBeAbsorbedMessage.java b/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestDataPointDistanceToBeAbsorbedMessage.java
index 8610e88..273fefc 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestDataPointDistanceToBeAbsorbedMessage.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestDataPointDistanceToBeAbsorbedMessage.java
@@ -2,7 +2,7 @@ package fr.irit.smac.amas4dc.amas.messages;
 
 import fr.irit.smac.amak.messaging.Message;
 import fr.irit.smac.amas4dc.amas.agent.DataPointAgent;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 import lombok.Getter;
 
 public class RequestDataPointDistanceToBeAbsorbedMessage<T extends DataPoint> extends Message<DataPointAgent<T>> {
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 cb7330d..048d423 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/Cluster.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/Cluster.java
@@ -1,15 +1,10 @@
 package fr.irit.smac.amas4dc.cluster;
 
-import fr.irit.smac.amas4dc.amas.controller.MissingDataPointsException;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.ToString;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.UUID;
-
 @ToString
 public class Cluster<T extends DataPoint> {
 	@Getter
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 fc4a7d4..5c5a116 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/ExtendedCluster.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/ExtendedCluster.java
@@ -1,9 +1,9 @@
 package fr.irit.smac.amas4dc.cluster;
 
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 import lombok.Getter;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 
 public class ExtendedCluster<T extends DataPoint> extends Cluster<T> {
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/DataPoint.java b/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPoint.java
similarity index 61%
rename from src/main/java/fr/irit/smac/amas4dc/cluster/DataPoint.java
rename to src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPoint.java
index ac62dcb..5199f76 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/DataPoint.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPoint.java
@@ -1,4 +1,4 @@
-package fr.irit.smac.amas4dc.cluster;
+package fr.irit.smac.amas4dc.cluster.datapoint;
 
 public interface DataPoint {
 	default int getBucketId() {
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/DataPointDatabase.java b/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPointDatabase.java
similarity index 88%
rename from src/main/java/fr/irit/smac/amas4dc/cluster/DataPointDatabase.java
rename to src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPointDatabase.java
index 0f8cb53..cb29e9b 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/DataPointDatabase.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPointDatabase.java
@@ -1,4 +1,4 @@
-package fr.irit.smac.amas4dc.cluster;
+package fr.irit.smac.amas4dc.cluster.datapoint;
 
 import java.util.*;
 import java.util.logging.Level;
@@ -6,7 +6,7 @@ import java.util.logging.Logger;
 
 public class DataPointDatabase<T extends DataPoint> {
 	private static final Logger logger = Logger.getLogger(DataPointDatabase.class.getName());
-	private Set<T> content = new HashSet<>();
+	private final Set<T> content = new HashSet<>();
 	private T lastModifiedDataPoint;
 
 	public void add(T newDataPoint) {
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/DataPointFuser.java b/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPointFuser.java
similarity index 72%
rename from src/main/java/fr/irit/smac/amas4dc/cluster/DataPointFuser.java
rename to src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPointFuser.java
index 9d833f0..90788b8 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/DataPointFuser.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPointFuser.java
@@ -1,4 +1,4 @@
-package fr.irit.smac.amas4dc.cluster;
+package fr.irit.smac.amas4dc.cluster.datapoint;
 
 import java.util.function.BiFunction;
 
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/ClusterDistance.java b/src/main/java/fr/irit/smac/amas4dc/cluster/distance/ClusterDistance.java
similarity index 57%
rename from src/main/java/fr/irit/smac/amas4dc/amas/ClusterDistance.java
rename to src/main/java/fr/irit/smac/amas4dc/cluster/distance/ClusterDistance.java
index c454eb4..8165099 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/ClusterDistance.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/distance/ClusterDistance.java
@@ -1,8 +1,8 @@
-package fr.irit.smac.amas4dc.amas;
+package fr.irit.smac.amas4dc.cluster.distance;
 
 
 import fr.irit.smac.amas4dc.cluster.Cluster;
-import fr.irit.smac.amas4dc.cluster.DataPoint;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 
 public record ClusterDistance<T extends DataPoint>(Cluster<T> cluster, float distance) {
 
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/DistanceMethod.java b/src/main/java/fr/irit/smac/amas4dc/cluster/distance/DistanceMethod.java
similarity index 55%
rename from src/main/java/fr/irit/smac/amas4dc/cluster/DistanceMethod.java
rename to src/main/java/fr/irit/smac/amas4dc/cluster/distance/DistanceMethod.java
index 7d1f1bf..14046ee 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/DistanceMethod.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/distance/DistanceMethod.java
@@ -1,6 +1,8 @@
-package fr.irit.smac.amas4dc.cluster;
+package fr.irit.smac.amas4dc.cluster.distance;
 
 
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
+
 public interface DistanceMethod<T extends DataPoint> {
 	float apply(T dp1, T dp2);
 	boolean areRoughlySimilar(T dp1, T dp2);
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/CalinskiHarabazIndex.java b/src/main/java/fr/irit/smac/amas4dc/cluster/evaluation/CalinskiHarabazIndex.java
similarity index 91%
rename from src/main/java/fr/irit/smac/amas4dc/cluster/CalinskiHarabazIndex.java
rename to src/main/java/fr/irit/smac/amas4dc/cluster/evaluation/CalinskiHarabazIndex.java
index 72bcbf1..9c95f33 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/CalinskiHarabazIndex.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/evaluation/CalinskiHarabazIndex.java
@@ -1,6 +1,8 @@
-package fr.irit.smac.amas4dc.cluster;
+package fr.irit.smac.amas4dc.cluster.evaluation;
 
 import fr.irit.smac.amas4dc.amas.MASSettings;
+import fr.irit.smac.amas4dc.cluster.ExtendedCluster;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 
 import java.util.List;
 
@@ -11,7 +13,6 @@ public class CalinskiHarabazIndex<T extends DataPoint> {
 		var ssw = computeWithinClusterVariance(clusters, masSettings);
 
 		if (ssw == 0) {
-			// Avoid division by zero
 			return Double.POSITIVE_INFINITY;
 		}
 
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/SilhouetteScoreCalculator.java b/src/main/java/fr/irit/smac/amas4dc/cluster/evaluation/SilhouetteScoreCalculator.java
similarity index 92%
rename from src/main/java/fr/irit/smac/amas4dc/cluster/SilhouetteScoreCalculator.java
rename to src/main/java/fr/irit/smac/amas4dc/cluster/evaluation/SilhouetteScoreCalculator.java
index f389f58..065f4d6 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/SilhouetteScoreCalculator.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/evaluation/SilhouetteScoreCalculator.java
@@ -1,8 +1,10 @@
-package fr.irit.smac.amas4dc.cluster;
+package fr.irit.smac.amas4dc.cluster.evaluation;
 
 import fr.irit.smac.amas4dc.amas.AMASOption;
 import fr.irit.smac.amas4dc.amas.MASSettings;
 import fr.irit.smac.amas4dc.amas.controller.MissingDataPointsException;
+import fr.irit.smac.amas4dc.cluster.ExtendedCluster;
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/ExtendedClusterException.java b/src/main/java/fr/irit/smac/amas4dc/cluster/exception/ExtendedClusterException.java
similarity index 72%
rename from src/main/java/fr/irit/smac/amas4dc/cluster/ExtendedClusterException.java
rename to src/main/java/fr/irit/smac/amas4dc/cluster/exception/ExtendedClusterException.java
index 2ae326c..e005e93 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/ExtendedClusterException.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/exception/ExtendedClusterException.java
@@ -1,4 +1,4 @@
-package fr.irit.smac.amas4dc.cluster;
+package fr.irit.smac.amas4dc.cluster.exception;
 
 public class ExtendedClusterException extends RuntimeException {
 	public ExtendedClusterException(String s) {
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/FusionException.java b/src/main/java/fr/irit/smac/amas4dc/cluster/exception/FusionException.java
similarity index 71%
rename from src/main/java/fr/irit/smac/amas4dc/cluster/FusionException.java
rename to src/main/java/fr/irit/smac/amas4dc/cluster/exception/FusionException.java
index f81880e..542709b 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/FusionException.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/exception/FusionException.java
@@ -1,4 +1,4 @@
-package fr.irit.smac.amas4dc.cluster;
+package fr.irit.smac.amas4dc.cluster.exception;
 
 public class FusionException extends RuntimeException {
 	public FusionException(String message) {
diff --git a/src/test/groovy/SimpleClusteringIT.groovy b/src/test/groovy/SimpleClusteringIT.groovy
index ba75ddc..fdbd112 100644
--- a/src/test/groovy/SimpleClusteringIT.groovy
+++ b/src/test/groovy/SimpleClusteringIT.groovy
@@ -1,9 +1,9 @@
 import fr.irit.smac.amas4dc.AMAS4DC
 import fr.irit.smac.amas4dc.amas.AMASOption
 import fr.irit.smac.amas4dc.amas.MASSettings
-import fr.irit.smac.amas4dc.cluster.DataPoint
-import fr.irit.smac.amas4dc.cluster.DataPointDatabase
-import fr.irit.smac.amas4dc.cluster.DistanceMethod
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPointDatabase
+import fr.irit.smac.amas4dc.cluster.distance.DistanceMethod
 import spock.lang.Specification
 
 class SimpleClusteringIT extends Specification {
diff --git a/src/test/groovy/fr/irit/smac/amas4dc/amas/ClusterAgentTest.groovy b/src/test/groovy/fr/irit/smac/amas4dc/amas/ClusterAgentTest.groovy
index a485f34..842141c 100644
--- a/src/test/groovy/fr/irit/smac/amas4dc/amas/ClusterAgentTest.groovy
+++ b/src/test/groovy/fr/irit/smac/amas4dc/amas/ClusterAgentTest.groovy
@@ -8,9 +8,9 @@ import fr.irit.smac.amas4dc.amas.messages.EvaluatedDistanceMessage
 import fr.irit.smac.amas4dc.amas.messages.RequestClusterDistanceToBeAbsorbedMessage
 import fr.irit.smac.amas4dc.amas.messages.RequestDataPointDistanceToBeAbsorbedMessage
 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.datapoint.DataPoint
+import fr.irit.smac.amas4dc.cluster.datapoint.DataPointFuser
+import fr.irit.smac.amas4dc.cluster.distance.DistanceMethod
 import spock.lang.Specification
 import spock.util.concurrent.BlockingVariable
 
-- 
GitLab