diff --git a/README.md b/README.md index 9c9720709357aa5c95577199daf9dbb2116f3cbf..bb81a9ccd16cf1a0b71b244cd3a72f1b4d9a3b89 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ project(':amas4dc').projectDir = new File(settingsDir, '../amas4dc') ## Usage example ```java -var amas4dc = new AMAS4DC<CustomDataPoint>(new MASSettings(new CustomDataPointSimilarityScoreMethod(), 0.5f, EnumSet.noneOf(AMASOption), new CustomDataPointFuser())) +var amas4dc = new AMAS4DC<CustomDataPoint>(new MASSettings(new CustomDataPointDistanceMethod(), 0.5f, EnumSet.noneOf(AMASOption), new CustomDataPointFuser())) amas4dc.fit([new CustomDataPoint(1), new CustomDataPoint(2)]) var results = amas4dc.retrieveClusters() diff --git a/src/experiments/groovy/TemperatureClustering.groovy b/src/experiments/groovy/TemperatureClustering.groovy index a603ff82b00ff5d4c9fce2d856e78a7b79dabcf7..5f804eadd44f5bfd88e524b2921c975e29afee8a 100644 --- a/src/experiments/groovy/TemperatureClustering.groovy +++ b/src/experiments/groovy/TemperatureClustering.groovy @@ -4,7 +4,7 @@ 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.SimilarityScoreMethod +import fr.irit.smac.amas4dc.cluster.DistanceMethod import fr.irit.smac.lxplot.LxPlot import groovy.transform.ToString @@ -15,7 +15,7 @@ import java.util.List class TemperatureClustering { static void main(String[] args) { - def amas4dc = new AMAS4DC<TemperatureDataPoint>(new MASSettings<TemperatureDataPoint>(new TemperatureSimilarityMethod(), + def amas4dc = new AMAS4DC<TemperatureDataPoint>(new MASSettings<TemperatureDataPoint>(new TemperatureDistanceMethod(), 0.5f, EnumSet.of(AMASOption.KeepAllDataPoints), new TemperatureDataPointFuser())) @@ -63,7 +63,7 @@ class TemperatureClustering { var results = amas4dc.retrieveExtendedClusters() println(results) plotter.renderClusters(results.clusters()) - LxPlot.getChart("Silhouette score").add(i, results.silhouetteScore()) + LxPlot.getChart("Silhouette distance").add(i, results.silhouetteScore()) sleep(1000) } } @@ -100,7 +100,7 @@ class TemperatureClustering { } } - static class TemperatureSimilarityMethod implements SimilarityScoreMethod<TemperatureDataPoint> { + static class TemperatureDistanceMethod implements DistanceMethod<TemperatureDataPoint> { @Override float apply(TemperatureDataPoint dp1, TemperatureDataPoint dp2) { @@ -117,8 +117,8 @@ class TemperatureClustering { temporallySimilar = false } if (Math.abs(dp1.degrees - dp2.degrees) < 1 && temporallySimilar) - return 1; - return 0; + return 0; + return 1; } @Override diff --git a/src/experiments/groovy/TwoDimensionsPointsClustering.groovy b/src/experiments/groovy/TwoDimensionsPointsClustering.groovy index 31d9bbb526bcc3c142b6c47bb41e281d3e846ee6..16ee07a97cd61760075fe34a268b4367ec2f8686 100644 --- a/src/experiments/groovy/TwoDimensionsPointsClustering.groovy +++ b/src/experiments/groovy/TwoDimensionsPointsClustering.groovy @@ -3,7 +3,7 @@ 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.SimilarityScoreMethod +import fr.irit.smac.amas4dc.cluster.DistanceMethod import fr.irit.smac.lxplot.LxPlot import fr.irit.smac.lxplot.commons.ChartType import groovy.transform.ToString @@ -13,7 +13,7 @@ import java.awt.geom.Point2D class TwoDimensionsPointsClustering { static void main(String[] args) { - def amas4dc = new AMAS4DC<TwoDimensionsDataPoint>(new MASSettings(new TwoDimensionsSimilarityMethod(), 0.5f, EnumSet.noneOf(AMASOption), (TwoDimensionsDataPoint dp1, TwoDimensionsDataPoint dp2) -> { + def amas4dc = new AMAS4DC<TwoDimensionsDataPoint>(new MASSettings(new TwoDimensionsDistanceMethod(), 0.5f, EnumSet.noneOf(AMASOption), (TwoDimensionsDataPoint dp1, TwoDimensionsDataPoint dp2) -> { return new TwoDimensionsDataPoint(new Point2D.Double((dp1.getPoint2D().getX() + dp2.getPoint2D().getX()) / 2, (dp1.getPoint2D().getY() + dp2.getPoint2D().getY()) / 2)) })) @@ -48,13 +48,13 @@ class TwoDimensionsPointsClustering { } } - static class TwoDimensionsSimilarityMethod implements SimilarityScoreMethod<TwoDimensionsDataPoint> { + static class TwoDimensionsDistanceMethod implements DistanceMethod<TwoDimensionsDataPoint> { @Override float apply(TwoDimensionsDataPoint dp1, TwoDimensionsDataPoint dp2) { if (dp1.point2D.distance(dp2.point2D) < 10) - return 1; - return 0 + return 0 + return 1 } @Override diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/ClusterSimilarityScore.java b/src/main/java/fr/irit/smac/amas4dc/amas/ClusterDistance.java similarity index 58% rename from src/main/java/fr/irit/smac/amas4dc/amas/ClusterSimilarityScore.java rename to src/main/java/fr/irit/smac/amas4dc/amas/ClusterDistance.java index a0889f40399b93435946ac686f653b580450f885..c454eb4bd9acd3d7a53aeab229d6b4b1d6319a51 100644 --- a/src/main/java/fr/irit/smac/amas4dc/amas/ClusterSimilarityScore.java +++ b/src/main/java/fr/irit/smac/amas4dc/amas/ClusterDistance.java @@ -4,6 +4,6 @@ package fr.irit.smac.amas4dc.amas; import fr.irit.smac.amas4dc.cluster.Cluster; import fr.irit.smac.amas4dc.cluster.DataPoint; -public record ClusterSimilarityScore<T extends DataPoint>(Cluster<T> cluster, float score) { +public record ClusterDistance<T extends DataPoint>(Cluster<T> cluster, float distance) { } 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 f4a04b84aae0374bcccd8af17e5e9a5e9f03a752..52b70da5d0d2646ea4d1a56f1797830ba09e598e 100644 --- a/src/main/java/fr/irit/smac/amas4dc/amas/MASSettings.java +++ b/src/main/java/fr/irit/smac/amas4dc/amas/MASSettings.java @@ -4,18 +4,18 @@ 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.SimilarityScoreMethod; +import fr.irit.smac.amas4dc.cluster.DistanceMethod; import java.util.EnumSet; public record MASSettings<T extends DataPoint>( - SimilarityScoreMethod<T> similarityScoreMethod, + DistanceMethod<T> distanceMethod, float fusionThreshold, EnumSet<AMASOption> amasOptions, DataPointFuser<T> dataPointFuser, EventStore<Cluster<T>> eventStore ) { - public MASSettings(SimilarityScoreMethod<T> similarityScoreMethod, float fusionThreshold, EnumSet<AMASOption> amasOptions, DataPointFuser<T> dataPointFuser) { - this(similarityScoreMethod, fusionThreshold, amasOptions, dataPointFuser, null); + public MASSettings(DistanceMethod<T> distanceMethod, float fusionThreshold, EnumSet<AMASOption> amasOptions, DataPointFuser<T> dataPointFuser) { + this(distanceMethod, fusionThreshold, amasOptions, dataPointFuser, null); } } 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 884ac32ffa4bfedfa7a1295ae084dbdf18a06dad..90b9075fe17fb7db9aa0e5f827fe153a8bcc4dfc 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,13 +2,13 @@ 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.ClusterSimilarityScore; +import fr.irit.smac.amas4dc.amas.ClusterDistance; import fr.irit.smac.amas4dc.amas.DynamicClusteringAMAS; import fr.irit.smac.amas4dc.amas.DynamicClusteringEnvironment; -import fr.irit.smac.amas4dc.amas.messages.EvaluatedScoreMessage; +import fr.irit.smac.amas4dc.amas.messages.EvaluatedDistanceMessage; import fr.irit.smac.amas4dc.amas.messages.InformMostSimilarMessage; -import fr.irit.smac.amas4dc.amas.messages.RequestDataPointSimilarityToBeAbsorbedMessage; -import fr.irit.smac.amas4dc.amas.messages.RequestClusterSimilarityToBeAbsorbedMessage; +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.ExtendedCluster; @@ -28,17 +28,17 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM private State state = State.DORMANT; private State nextState = state; - private final Map<ClusterAgent<T>, ClusterSimilarityScore<T>> similarityScoresReceived = new HashMap<>(); + private final Map<ClusterAgent<T>, ClusterDistance<T>> distancesReceived = new HashMap<>(); //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<RequestDataPointSimilarityToBeAbsorbedMessage> receivedRequestDataPointSimilarityToBeAbsorbedMessage = Optional.empty(); - private Optional<RequestClusterSimilarityToBeAbsorbedMessage> receivedRequestClusterSimilarityToBeAbsorbedMessage = Optional.empty(); + private Optional<RequestDataPointDistanceToBeAbsorbedMessage> receivedRequestDataPointDistanceToBeAbsorbedMessage = Optional.empty(); + private Optional<RequestClusterDistanceToBeAbsorbedMessage> receivedRequestClusterDistanceToBeAbsorbedMessage = Optional.empty(); private Optional<InformMostSimilarMessage> receivedInformMostSimilarClusterAgentsMessage = Optional.empty(); - private List<ClusterAgent<T>> requestSimilarityMessageSentAgents = new ArrayList<>(); + private List<ClusterAgent<T>> requestDistanceMessageSentAgents = new ArrayList<>(); protected ClusterAgent(DynamicClusteringAMAS amas, T dataPoint) { super(amas); @@ -50,7 +50,7 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM this.setCluster(new Cluster<T>(dataPoint)); } - public enum State {DORMANT, WAITING_FOR_SIMILARITY, DEAD} + public enum State {DORMANT, WAITING_FOR_DISTANCE, DEAD} public State getState() { return state; @@ -72,8 +72,8 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM @Override protected void onPerceive() { receivedInformMostSimilarClusterAgentsMessage = Optional.empty(); - receivedRequestDataPointSimilarityToBeAbsorbedMessage = Optional.empty(); - receivedRequestClusterSimilarityToBeAbsorbedMessage = Optional.empty(); + receivedRequestDataPointDistanceToBeAbsorbedMessage = Optional.empty(); + receivedRequestClusterDistanceToBeAbsorbedMessage = Optional.empty(); switch (state) { case DORMANT -> { this.receivedInformMostSimilarClusterAgentsMessage = this.getMailbox().read(InformMostSimilarMessage.class); @@ -82,24 +82,24 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM logger.info(this + " received a list of candidates similar cluster agents"); return; } - this.receivedRequestDataPointSimilarityToBeAbsorbedMessage = this.getMailbox().read(RequestDataPointSimilarityToBeAbsorbedMessage.class); - if (receivedRequestDataPointSimilarityToBeAbsorbedMessage.isPresent()) { + this.receivedRequestDataPointDistanceToBeAbsorbedMessage = this.getMailbox().read(RequestDataPointDistanceToBeAbsorbedMessage.class); + if (receivedRequestDataPointDistanceToBeAbsorbedMessage.isPresent()) { if (logger.isLoggable(Level.INFO)) - logger.info(this + " received a request for similarity to be absorbed"); + logger.info(this + " received a request for distance to be absorbed"); return; } - this.receivedRequestClusterSimilarityToBeAbsorbedMessage = this.getMailbox().read(RequestClusterSimilarityToBeAbsorbedMessage.class); - if (receivedRequestClusterSimilarityToBeAbsorbedMessage.isPresent()) { + this.receivedRequestClusterDistanceToBeAbsorbedMessage = this.getMailbox().read(RequestClusterDistanceToBeAbsorbedMessage.class); + if (receivedRequestClusterDistanceToBeAbsorbedMessage.isPresent()) { if (logger.isLoggable(Level.INFO)) - logger.info(this + " received a request for similarity to be absorbed"); + logger.info(this + " received a request for distance to be absorbed"); return; } } - case WAITING_FOR_SIMILARITY -> { - while (mailbox.hasMessageOfType(EvaluatedScoreMessage.class)) { - var evaluatedScoreMessage = this.getMailbox().read(EvaluatedScoreMessage.class); - if (evaluatedScoreMessage.isPresent()) { - similarityScoresReceived.put((ClusterAgent<T>) evaluatedScoreMessage.get().getSender(), new ClusterSimilarityScore<T>(evaluatedScoreMessage.get().getCluster(), evaluatedScoreMessage.get().getSimilarityScore())); + case WAITING_FOR_DISTANCE -> { + while (mailbox.hasMessageOfType(EvaluatedDistanceMessage.class)) { + var evaluatedDistanceMessage = this.getMailbox().read(EvaluatedDistanceMessage.class); + if (evaluatedDistanceMessage.isPresent()) { + distancesReceived.put((ClusterAgent<T>) evaluatedDistanceMessage.get().getSender(), new ClusterDistance<T>(evaluatedDistanceMessage.get().getCluster(), evaluatedDistanceMessage.get().getDistance())); } } clearDeadAgentsFromThoseWeExpectAnAnswerFrom(); @@ -109,11 +109,11 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM private void clearDeadAgentsFromThoseWeExpectAnAnswerFrom() { - requestSimilarityMessageSentAgents.removeIf(a -> a.getState() == ClusterAgent.State.DEAD && !similarityScoresReceived.keySet().contains(a)); + requestDistanceMessageSentAgents.removeIf(a -> a.getState() == ClusterAgent.State.DEAD && !distancesReceived.keySet().contains(a)); for (var key : - similarityScoresReceived.keySet()) { - if (!requestSimilarityMessageSentAgents.contains(key)) - similarityScoresReceived.remove(key); + distancesReceived.keySet()) { + if (!requestDistanceMessageSentAgents.contains(key)) + distancesReceived.remove(key); } } @@ -121,18 +121,18 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM protected void onDecideAndAct() { switch (state) { case DORMANT -> { - if (receivedRequestDataPointSimilarityToBeAbsorbedMessage.isPresent()) { - float similarityScore = computeSimilarityScore((T) receivedRequestDataPointSimilarityToBeAbsorbedMessage.get().getDataPoint()); - var message = new EvaluatedScoreMessage<T>(this, cluster, similarityScore); - var sender = receivedRequestDataPointSimilarityToBeAbsorbedMessage.get().getSender(); + if (receivedRequestDataPointDistanceToBeAbsorbedMessage.isPresent()) { + float distance = computeDistance((T) receivedRequestDataPointDistanceToBeAbsorbedMessage.get().getDataPoint()); + var message = new EvaluatedDistanceMessage<T>(this, cluster, distance); + var sender = receivedRequestDataPointDistanceToBeAbsorbedMessage.get().getSender(); if (logger.isLoggable(Level.INFO)) { logger.info(this + " --> " + sender + " " + message); } sender.getMailbox().receive(message); - } else if (receivedRequestClusterSimilarityToBeAbsorbedMessage.isPresent()) { - float similarityScore = computeSimilarityScore((Cluster<T>) receivedRequestClusterSimilarityToBeAbsorbedMessage.get().getCluster()); - var message = new EvaluatedScoreMessage<T>(this, cluster, similarityScore); - var sender = receivedRequestClusterSimilarityToBeAbsorbedMessage.get().getSender(); + } else if (receivedRequestClusterDistanceToBeAbsorbedMessage.isPresent()) { + float distance = computeDistance((Cluster<T>) receivedRequestClusterDistanceToBeAbsorbedMessage.get().getCluster()); + var message = new EvaluatedDistanceMessage<T>(this, cluster, distance); + var sender = receivedRequestClusterDistanceToBeAbsorbedMessage.get().getSender(); if (logger.isLoggable(Level.INFO)) { logger.info(this + " --> " + sender + " " + message); } @@ -145,12 +145,12 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM absorbCluster(informMostSimilarMessage.getCluster()); List<ClusterAgent<T>> otherSimilarClusterAgents = ((InformMostSimilarMessage<T>) informMostSimilarMessage).getOtherSimilarClusterAgents(); for (var otherClusterAgent : otherSimilarClusterAgents) { - otherClusterAgent.getMailbox().receive(new RequestClusterSimilarityToBeAbsorbedMessage(this, cluster)); + otherClusterAgent.getMailbox().receive(new RequestClusterDistanceToBeAbsorbedMessage(this, cluster)); } if (!otherSimilarClusterAgents.isEmpty()) { - this.requestSimilarityMessageSentAgents.clear(); - this.requestSimilarityMessageSentAgents.addAll(otherSimilarClusterAgents); - nextState = State.WAITING_FOR_SIMILARITY; + this.requestDistanceMessageSentAgents.clear(); + this.requestDistanceMessageSentAgents.addAll(otherSimilarClusterAgents); + nextState = State.WAITING_FOR_DISTANCE; } else { nextState = State.DORMANT; } @@ -163,20 +163,20 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM */ } } - case WAITING_FOR_SIMILARITY -> { - if (requestSimilarityMessageSentAgents.size() == similarityScoresReceived.size()) { + case WAITING_FOR_DISTANCE -> { + if (requestDistanceMessageSentAgents.size() == distancesReceived.size()) { - float mostSimilarClusterAgentScore = -1; + float mostSimilarClusterAgentDistance = Float.MAX_VALUE; var allSimilarClusterAgents = new HashMap<ClusterAgent<T>, Double>(); Optional<ClusterAgent<T>> mostSimilarClusterAgent = Optional.empty(); var othersSimilarClusterAgents = new ArrayList<ClusterAgent<T>>(); - for (var ssr : similarityScoresReceived.entrySet()) { - if (ssr.getValue().score() >= getAmas().getMasSettings().fusionThreshold()) { - if (mostSimilarClusterAgentScore == -1 || ssr.getValue().score() > mostSimilarClusterAgentScore) { + for (var ssr : distancesReceived.entrySet()) { + if (ssr.getValue().distance() <= getAmas().getMasSettings().fusionThreshold()) { + if (mostSimilarClusterAgentDistance == Float.MAX_VALUE || ssr.getValue().distance() < mostSimilarClusterAgentDistance) { mostSimilarClusterAgent = Optional.of(ssr.getKey()); - mostSimilarClusterAgentScore = ssr.getValue().score(); + mostSimilarClusterAgentDistance = ssr.getValue().distance(); } - allSimilarClusterAgents.put(ssr.getKey(), (double) ssr.getValue().score()); + allSimilarClusterAgents.put(ssr.getKey(), (double) ssr.getValue().distance()); } } for (var ca : allSimilarClusterAgents.keySet()) { @@ -252,10 +252,10 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM } - private float computeSimilarityScore(T other) { - return getAmas().getMasSettings().similarityScoreMethod().apply(this.cluster.getRepresentative(), other); + private float computeDistance(T other) { + return getAmas().getMasSettings().distanceMethod().apply(this.cluster.getRepresentative(), other); } - private float computeSimilarityScore(Cluster<T> other) { - return getAmas().getMasSettings().similarityScoreMethod().apply(this.cluster.getRepresentative(), other.getRepresentative()); + 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 44f713e496d1f88e4efb480fb7b1f67ef45b3900..23609328d0307401bcb522670c26feb20785eb9f 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,13 +1,12 @@ package fr.irit.smac.amas4dc.amas.agent; import fr.irit.smac.amak.Agent; -import fr.irit.smac.amas4dc.amas.ClusterSimilarityScore; +import fr.irit.smac.amas4dc.amas.ClusterDistance; import fr.irit.smac.amas4dc.amas.DynamicClusteringAMAS; import fr.irit.smac.amas4dc.amas.DynamicClusteringEnvironment; -import fr.irit.smac.amas4dc.amas.messages.EvaluatedScoreMessage; +import fr.irit.smac.amas4dc.amas.messages.EvaluatedDistanceMessage; import fr.irit.smac.amas4dc.amas.messages.InformMostSimilarMessage; -import fr.irit.smac.amas4dc.amas.messages.RequestClusterSimilarityToBeAbsorbedMessage; -import fr.irit.smac.amas4dc.amas.messages.RequestDataPointSimilarityToBeAbsorbedMessage; +import fr.irit.smac.amas4dc.amas.messages.RequestDataPointDistanceToBeAbsorbedMessage; import fr.irit.smac.amas4dc.cluster.Cluster; import fr.irit.smac.amas4dc.cluster.DataPoint; @@ -19,8 +18,8 @@ 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 final T dataPoint; - private final List<ClusterAgent<T>> requestSimilarityMessageSentAgents = new ArrayList<>(); - private final Map<ClusterAgent<T>, ClusterSimilarityScore<T>> similarityScoresReceived = new HashMap<>(); + 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) { @@ -32,7 +31,7 @@ public class DataPointAgent<T extends DataPoint> extends Agent<DynamicClustering private boolean isRoughlySimilarTo(ClusterAgent<T> otherClusterAgent) { - return getAmas().getMasSettings().similarityScoreMethod().areRoughlySimilar(dataPoint, otherClusterAgent.getCluster().getRepresentative()); + return getAmas().getMasSettings().distanceMethod().areRoughlySimilar(dataPoint, otherClusterAgent.getCluster().getRepresentative()); } @Override @@ -46,18 +45,18 @@ public class DataPointAgent<T extends DataPoint> extends Agent<DynamicClustering } for (var agent : clusterAgentsRoughlySimilarOnReady) { if (logger.isLoggable(Level.INFO)) - logger.info(this + " sends RequestSimilarityToBeAbsorbedMessage to " + agent); - agent.getMailbox().receive(new RequestDataPointSimilarityToBeAbsorbedMessage<T>(this, dataPoint)); - requestSimilarityMessageSentAgents.add(agent); + logger.info(this + " sends RequestDataPointDistanceToBeAbsorbedMessage to " + agent); + agent.getMailbox().receive(new RequestDataPointDistanceToBeAbsorbedMessage<T>(this, dataPoint)); + requestDistanceMessageSentAgents.add(agent); } } @Override protected void onPerceive() { - while (mailbox.hasMessageOfType(EvaluatedScoreMessage.class)) { - var evaluatedScoreMessage = this.getMailbox().read(EvaluatedScoreMessage.class); + while (mailbox.hasMessageOfType(EvaluatedDistanceMessage.class)) { + var evaluatedScoreMessage = this.getMailbox().read(EvaluatedDistanceMessage.class); if (evaluatedScoreMessage.isPresent()) { - similarityScoresReceived.put((ClusterAgent<T>) evaluatedScoreMessage.get().getSender(), new ClusterSimilarityScore<T>(evaluatedScoreMessage.get().getCluster(), evaluatedScoreMessage.get().getSimilarityScore())); + distancesReceived.put((ClusterAgent<T>) evaluatedScoreMessage.get().getSender(), new ClusterDistance<T>(evaluatedScoreMessage.get().getCluster(), evaluatedScoreMessage.get().getDistance())); } } clearDeadAgentsFromThoseWeExpectAnAnswerFrom(); @@ -65,25 +64,26 @@ public class DataPointAgent<T extends DataPoint> extends Agent<DynamicClustering @Override protected void onDecideAndAct() { + // TODO Refactor this code to avoid duplicated code with ClusterAgent var othersSimilarClusterAgents = new ArrayList<ClusterAgent<T>>(); Optional<ClusterAgent<T>> mostSimilarClusterAgent = Optional.empty(); - if (requestSimilarityMessageSentAgents.size() == similarityScoresReceived.size()) { + if (requestDistanceMessageSentAgents.size() == distancesReceived.size()) { if (logger.isLoggable(Level.INFO)) { - for (var e : similarityScoresReceived.entrySet()) { - logger.info(this + " received similarity score " + e.getValue() + " from " + e.getKey()); + for (var e : distancesReceived.entrySet()) { + logger.info(this + " received distance " + e.getValue() + " from " + e.getKey()); } } - float mostSimilarClusterAgentScore = -1; + float mostSimilarClusterAgentScore = Float.MAX_VALUE; var allSimilarClusterAgents = new HashMap<ClusterAgent<T>, Double>(); - for (var ssr : similarityScoresReceived.entrySet()) { - if (ssr.getValue().score() >= getAmas().getMasSettings().fusionThreshold()) { - if (mostSimilarClusterAgentScore == -1 || ssr.getValue().score() > mostSimilarClusterAgentScore) { + for (var ssr : distancesReceived.entrySet()) { + if (ssr.getValue().distance() <= getAmas().getMasSettings().fusionThreshold()) { + if (mostSimilarClusterAgentScore == Float.MAX_VALUE || ssr.getValue().distance() < mostSimilarClusterAgentScore) { mostSimilarClusterAgent = Optional.of(ssr.getKey()); - mostSimilarClusterAgentScore = ssr.getValue().score(); + mostSimilarClusterAgentScore = ssr.getValue().distance(); } - allSimilarClusterAgents.put(ssr.getKey(), (double) ssr.getValue().score()); + allSimilarClusterAgents.put(ssr.getKey(), (double) ssr.getValue().distance()); } } if (mostSimilarClusterAgent.isPresent()) { @@ -93,7 +93,7 @@ public class DataPointAgent<T extends DataPoint> extends Agent<DynamicClustering } if (logger.isLoggable(Level.INFO)) - logger.info(this + " decides to bo absorbed"); + logger.info(this + " decides to be absorbed"); mostSimilarClusterAgent.get().getMailbox().receive(new InformMostSimilarMessage<T>(this, dataPoint, othersSimilarClusterAgents)); @@ -111,31 +111,12 @@ public class DataPointAgent<T extends DataPoint> extends Agent<DynamicClustering logger.info(MessageFormat.format("{0} dies", this)); } - private List<Cluster<T>> getReceivedClustersWithSimilarityScoreAboveFusionThreshold(Map<ClusterAgent<T>, ClusterSimilarityScore<T>> similarityScoresReceived) { - float highestScore = Float.MIN_VALUE; - List<Cluster<T>> clustersWithHighestScore = new ArrayList<>(); - for (var e : similarityScoresReceived.entrySet()) { - float clusterScore = e.getValue().score(); - if (clusterScore >= getAmas().getMasSettings().fusionThreshold()) { - Cluster<T> cluster = e.getValue().cluster(); - if (Math.abs(clusterScore - highestScore) < FLOAT_COMPARISON_EPSILON) { - clustersWithHighestScore.add(cluster); - } else if (clusterScore > highestScore) { - clustersWithHighestScore.clear(); - clustersWithHighestScore.add(cluster); - highestScore = clusterScore; - } - } - } - return clustersWithHighestScore; - } - private void clearDeadAgentsFromThoseWeExpectAnAnswerFrom() { - requestSimilarityMessageSentAgents.removeIf(a -> a.getState() == ClusterAgent.State.DEAD && !similarityScoresReceived.keySet().contains(a)); + requestDistanceMessageSentAgents.removeIf(a -> a.getState() == ClusterAgent.State.DEAD && !distancesReceived.keySet().contains(a)); for (var key : - similarityScoresReceived.keySet()) { - if (!requestSimilarityMessageSentAgents.contains(key)) - similarityScoresReceived.remove(key); + distancesReceived.keySet()) { + if (!requestDistanceMessageSentAgents.contains(key)) + distancesReceived.remove(key); } } diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/messages/EvaluatedScoreMessage.java b/src/main/java/fr/irit/smac/amas4dc/amas/messages/EvaluatedDistanceMessage.java similarity index 56% rename from src/main/java/fr/irit/smac/amas4dc/amas/messages/EvaluatedScoreMessage.java rename to src/main/java/fr/irit/smac/amas4dc/amas/messages/EvaluatedDistanceMessage.java index 98755561c3208b4aa08f61cc0e8da3368d95ecf5..18a885c2ae6fa7b83a0a1a27f5aea67c51a0ec29 100644 --- a/src/main/java/fr/irit/smac/amas4dc/amas/messages/EvaluatedScoreMessage.java +++ b/src/main/java/fr/irit/smac/amas4dc/amas/messages/EvaluatedDistanceMessage.java @@ -1,6 +1,5 @@ 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.cluster.Cluster; @@ -9,15 +8,15 @@ import lombok.Getter; import lombok.ToString; @ToString -public class EvaluatedScoreMessage<T extends DataPoint> extends Message<ClusterAgent<T>> { +public class EvaluatedDistanceMessage<T extends DataPoint> extends Message<ClusterAgent<T>> { @Getter private final Cluster<T> cluster; @Getter - private final float similarityScore; + private final float distance; - public EvaluatedScoreMessage(ClusterAgent<T> sender, Cluster<T> cluster, float similarityScore) { + public EvaluatedDistanceMessage(ClusterAgent<T> sender, Cluster<T> cluster, float distance) { super(sender); this.cluster = cluster; - this.similarityScore = similarityScore; + this.distance = distance; } } diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestClusterSimilarityToBeAbsorbedMessage.java b/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestClusterDistanceToBeAbsorbedMessage.java similarity index 56% rename from src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestClusterSimilarityToBeAbsorbedMessage.java rename to src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestClusterDistanceToBeAbsorbedMessage.java index acf0b9085664d2402a666418f8764674caacb467..af4c75a159953430b3afba748110c78822a4d5c3 100644 --- a/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestClusterSimilarityToBeAbsorbedMessage.java +++ b/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestClusterDistanceToBeAbsorbedMessage.java @@ -2,16 +2,15 @@ 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.amas.agent.DataPointAgent; import fr.irit.smac.amas4dc.cluster.Cluster; import fr.irit.smac.amas4dc.cluster.DataPoint; import lombok.Getter; -public class RequestClusterSimilarityToBeAbsorbedMessage<T extends DataPoint> extends Message<ClusterAgent<T>> { +public class RequestClusterDistanceToBeAbsorbedMessage<T extends DataPoint> extends Message<ClusterAgent<T>> { @Getter private final Cluster<T> cluster; - public RequestClusterSimilarityToBeAbsorbedMessage(ClusterAgent<T> sender, Cluster<T> cluster) { + public RequestClusterDistanceToBeAbsorbedMessage(ClusterAgent<T> sender, Cluster<T> cluster) { super(sender); this.cluster = cluster; } 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 new file mode 100644 index 0000000000000000000000000000000000000000..8610e8823026b04ad1d3a712c3ebce1e9771dd50 --- /dev/null +++ b/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestDataPointDistanceToBeAbsorbedMessage.java @@ -0,0 +1,16 @@ +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 lombok.Getter; + +public class RequestDataPointDistanceToBeAbsorbedMessage<T extends DataPoint> extends Message<DataPointAgent<T>> { + @Getter + private final T dataPoint; + + public RequestDataPointDistanceToBeAbsorbedMessage(DataPointAgent<T> sender, T dataPoint) { + super(sender); + this.dataPoint = dataPoint; + } +} diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestDataPointSimilarityToBeAbsorbedMessage.java b/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestDataPointSimilarityToBeAbsorbedMessage.java deleted file mode 100644 index 3001370aa37a1a8165defa7896d02f0a4462cddc..0000000000000000000000000000000000000000 --- a/src/main/java/fr/irit/smac/amas4dc/amas/messages/RequestDataPointSimilarityToBeAbsorbedMessage.java +++ /dev/null @@ -1,18 +0,0 @@ -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.amas.agent.DataPointAgent; -import fr.irit.smac.amas4dc.cluster.Cluster; -import fr.irit.smac.amas4dc.cluster.DataPoint; -import lombok.Getter; - -public class RequestDataPointSimilarityToBeAbsorbedMessage<T extends DataPoint> extends Message<DataPointAgent<T>> { - @Getter - private final T dataPoint; - - public RequestDataPointSimilarityToBeAbsorbedMessage(DataPointAgent<T> sender, T dataPoint) { - super(sender); - this.dataPoint = dataPoint; - } -} diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/CalinskiHarabazIndex.java b/src/main/java/fr/irit/smac/amas4dc/cluster/CalinskiHarabazIndex.java index dc343f9313dbaeefc31153e58177162823efbab8..554fa6bf51b6451c445ab42b01a5de750bd45a20 100644 --- a/src/main/java/fr/irit/smac/amas4dc/cluster/CalinskiHarabazIndex.java +++ b/src/main/java/fr/irit/smac/amas4dc/cluster/CalinskiHarabazIndex.java @@ -23,7 +23,7 @@ public class CalinskiHarabazIndex<T extends DataPoint> { var ssb = 0.0; for (var cluster : clusters) { - var centroidDist = 1.0/masSettings.similarityScoreMethod().apply(cluster.getRepresentative(), centroid); + var centroidDist = 1.0/masSettings.distanceMethod().apply(cluster.getRepresentative(), centroid); ssb += centroidDist * centroidDist * cluster.getContent().size(); } @@ -38,7 +38,7 @@ public class CalinskiHarabazIndex<T extends DataPoint> { var clusterSumDist = 0.0; for (var point : cluster.getContent()) { - var dist = 1.0/masSettings.similarityScoreMethod().apply(point, clusterCentroid); + var dist = 1.0/masSettings.distanceMethod().apply(point, clusterCentroid); clusterSumDist += dist * dist; } diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/SimilarityScoreMethod.java b/src/main/java/fr/irit/smac/amas4dc/cluster/DistanceMethod.java similarity index 52% rename from src/main/java/fr/irit/smac/amas4dc/cluster/SimilarityScoreMethod.java rename to src/main/java/fr/irit/smac/amas4dc/cluster/DistanceMethod.java index a6e40d90a87b9e5a22d7336e8ffff230324ac53b..7d1f1bf21e13edfe0251904c285d4a6d309c3dbf 100644 --- a/src/main/java/fr/irit/smac/amas4dc/cluster/SimilarityScoreMethod.java +++ b/src/main/java/fr/irit/smac/amas4dc/cluster/DistanceMethod.java @@ -1,10 +1,7 @@ package fr.irit.smac.amas4dc.cluster; -public interface SimilarityScoreMethod<T extends DataPoint> { - float MAX_SIMILARITY_VALUE = 1.0f; - +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/FusionException.java b/src/main/java/fr/irit/smac/amas4dc/cluster/FusionException.java new file mode 100644 index 0000000000000000000000000000000000000000..f81880eb92c4185f5552ddce2eac03ee0806b1d0 --- /dev/null +++ b/src/main/java/fr/irit/smac/amas4dc/cluster/FusionException.java @@ -0,0 +1,7 @@ +package fr.irit.smac.amas4dc.cluster; + +public class FusionException extends RuntimeException { + public FusionException(String message) { + super(message); + } +} diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/SilhouetteScoreCalculator.java b/src/main/java/fr/irit/smac/amas4dc/cluster/SilhouetteScoreCalculator.java index 1dc6bd75188e425371aa7900498320c5503b36f8..f389f58cf36c540fe13f8b5e2cc2e17cf62d064c 100644 --- a/src/main/java/fr/irit/smac/amas4dc/cluster/SilhouetteScoreCalculator.java +++ b/src/main/java/fr/irit/smac/amas4dc/cluster/SilhouetteScoreCalculator.java @@ -10,7 +10,7 @@ import java.util.List; public class SilhouetteScoreCalculator<T extends DataPoint> { public double compute(MASSettings<T> masSettings, List<ExtendedCluster<T>> clusters) { if (!masSettings.amasOptions().contains(AMASOption.KeepAllDataPoints)) - throw new MissingDataPointsException("AMAS option KeepAllDataPoints must be set to compute silhouette score"); + throw new MissingDataPointsException("AMAS option KeepAllDataPoints must be set to compute silhouette distance"); var ss = 0.0; if (clusters.isEmpty()) return ss; @@ -48,7 +48,7 @@ public class SilhouetteScoreCalculator<T extends DataPoint> { private double averageDistanceTo(MASSettings<T> masSettings, T dataPoint, List<T> otherDataPoints) { if (otherDataPoints.size() == 1 && otherDataPoints.get(0) == dataPoint) return 0; - var distance = SimilarityScoreMethod.MAX_SIMILARITY_VALUE - otherDataPoints.stream().filter(i -> i != dataPoint).mapToDouble(i2 -> masSettings.similarityScoreMethod().apply(dataPoint, i2)).average().getAsDouble(); + var distance = otherDataPoints.stream().filter(i -> i != dataPoint).mapToDouble(i2 -> masSettings.distanceMethod().apply(dataPoint, i2)).average().getAsDouble(); return distance; } diff --git a/src/test/groovy/SimpleClusteringIT.groovy b/src/test/groovy/SimpleClusteringIT.groovy index ced6dec1e065aaa9704edafd51f4943a86e0da47..22c7d85c3a06d6e31f82c78c8108ea05ae6755e9 100644 --- a/src/test/groovy/SimpleClusteringIT.groovy +++ b/src/test/groovy/SimpleClusteringIT.groovy @@ -2,13 +2,13 @@ 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.SimilarityScoreMethod +import fr.irit.smac.amas4dc.cluster.DistanceMethod import spock.lang.Specification class SimpleClusteringIT extends Specification { def "Clustering of two similar 1D objects"() { given: - def amas4dc = new AMAS4DC<OneDDataPoint>(new MASSettings(new OneDSimilarityScoreMethod(), 0.5f, EnumSet.noneOf(AMASOption), (OneDDataPoint dp1, OneDDataPoint dp2) -> { + def amas4dc = new AMAS4DC<OneDDataPoint>(new MASSettings(new OneDDistanceMethod(), 1f, EnumSet.noneOf(AMASOption), (OneDDataPoint dp1, OneDDataPoint dp2) -> { return new OneDDataPoint(dp1.value + (dp2.value - dp1.value) * 0.1f) })) @@ -29,11 +29,11 @@ class SimpleClusteringIT extends Specification { } } - class OneDSimilarityScoreMethod implements SimilarityScoreMethod<OneDDataPoint> { + class OneDDistanceMethod implements DistanceMethod<OneDDataPoint> { @Override float apply(OneDDataPoint dp1, OneDDataPoint dp2) { - return Math.abs(dp1.value - dp2.value) <= 1f ? 1f : 0f; + return Math.abs(dp1.value - dp2.value); } @Override 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 9f91ccb0f55f22b16102d25a259a8d0dcfa2cf9b..a485f349b0a60f835c96219a5afe01a69a39c487 100644 --- a/src/test/groovy/fr/irit/smac/amas4dc/amas/ClusterAgentTest.groovy +++ b/src/test/groovy/fr/irit/smac/amas4dc/amas/ClusterAgentTest.groovy @@ -4,27 +4,27 @@ package fr.irit.smac.amas4dc.amas import fr.irit.smac.amak.messaging.Mailbox import fr.irit.smac.amas4dc.amas.agent.ClusterAgent import fr.irit.smac.amas4dc.amas.agent.DataPointAgent -import fr.irit.smac.amas4dc.amas.messages.EvaluatedScoreMessage -import fr.irit.smac.amas4dc.amas.messages.RequestClusterSimilarityToBeAbsorbedMessage -import fr.irit.smac.amas4dc.amas.messages.RequestDataPointSimilarityToBeAbsorbedMessage +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.SimilarityScoreMethod +import fr.irit.smac.amas4dc.cluster.DistanceMethod import spock.lang.Specification import spock.util.concurrent.BlockingVariable class ClusterAgentTest extends Specification { - def "When an agent in DORMANT receives a RequestDataPointSimilarityToBeAbsorbedMessage, it should reply with a similarity score"() { + def "When an agent in DORMANT receives a RequestDataPointDistanceToBeAbsorbedMessage, it should reply with a distance"() { given: def messageReceivedByRequester = new BlockingVariable() - def similarityScoreMethodMock = Mock(SimilarityScoreMethod) - similarityScoreMethodMock.apply(_, _) >> 0.3 + def distanceMethodMock = Mock(DistanceMethod) + distanceMethodMock.apply(_, _) >> 0.3 def amasMock = Mock(DynamicClusteringAMAS<DataPoint>) - amasMock.getMasSettings() >> new MASSettings(similarityScoreMethodMock, 0.5f, EnumSet.noneOf(AMASOption), Mock(DataPointFuser)) + amasMock.getMasSettings() >> new MASSettings(distanceMethodMock, 0.5f, EnumSet.noneOf(AMASOption), Mock(DataPointFuser)) amasMock.getEnvironment() >> Mock(DynamicClusteringEnvironment) def agent = new ClusterAgent(amasMock, Mock(DataPoint)) @@ -38,23 +38,23 @@ class ClusterAgentTest extends Specification { requesterAgentMock.getMailbox() >> requesterMailboxMock when: - agent.mailbox.receive(new RequestDataPointSimilarityToBeAbsorbedMessage(requesterAgentMock, Mock(DataPoint))) + agent.mailbox.receive(new RequestDataPointDistanceToBeAbsorbedMessage(requesterAgentMock, Mock(DataPoint))) agent.cycle() agent.cycle() then: - messageReceivedByRequester.get()[0] instanceof EvaluatedScoreMessage - ((EvaluatedScoreMessage) (messageReceivedByRequester.get()[0])).similarityScore == 0.3f + messageReceivedByRequester.get()[0] instanceof EvaluatedDistanceMessage + ((EvaluatedDistanceMessage) (messageReceivedByRequester.get()[0])).distance == 0.3f } - def "When an agent in DORMANT receives a RequestClusterSimilarityToBeAbsorbedMessage, it should reply with a similarity score"() { + def "When an agent in DORMANT receives a RequestClusterDistanceToBeAbsorbedMessage, it should reply with a distance"() { given: def messageReceivedByRequester = new BlockingVariable() - def similarityScoreMethodMock = Mock(SimilarityScoreMethod) - similarityScoreMethodMock.apply(_, _) >> 0.3 + def distanceMethodMock = Mock(DistanceMethod) + distanceMethodMock.apply(_, _) >> 0.3 def amasMock = Mock(DynamicClusteringAMAS<DataPoint>) - amasMock.getMasSettings() >> new MASSettings(similarityScoreMethodMock, 0.5f, EnumSet.noneOf(AMASOption), Mock(DataPointFuser)) + amasMock.getMasSettings() >> new MASSettings(distanceMethodMock, 0.5f, EnumSet.noneOf(AMASOption), Mock(DataPointFuser)) amasMock.getEnvironment() >> Mock(DynamicClusteringEnvironment) def agent = new ClusterAgent(amasMock, Mock(DataPoint)) @@ -68,12 +68,12 @@ class ClusterAgentTest extends Specification { requesterAgentMock.getMailbox() >> requesterMailboxMock when: - agent.mailbox.receive(new RequestClusterSimilarityToBeAbsorbedMessage(requesterAgentMock, Mock(Cluster))) + agent.mailbox.receive(new RequestClusterDistanceToBeAbsorbedMessage(requesterAgentMock, Mock(Cluster))) agent.cycle() agent.cycle() then: - messageReceivedByRequester.get()[0] instanceof EvaluatedScoreMessage - ((EvaluatedScoreMessage) (messageReceivedByRequester.get()[0])).similarityScore == 0.3f + messageReceivedByRequester.get()[0] instanceof EvaluatedDistanceMessage + ((EvaluatedDistanceMessage) (messageReceivedByRequester.get()[0])).distance == 0.3f } }