Commit 1c483936 authored by dinhan93's avatar dinhan93

Merge remote-tracking branch 'origin/ML_clustering' into ML_clustering

# Conflicts:
#	src/main/java/de/monticore/lang/monticar/generator/middleware/Simulation/MonteCarloIntegration.java
parents c3685b33 b165a3be
Pipeline #111097 passed with stages
in 15 minutes and 58 seconds
...@@ -105,7 +105,8 @@ Clustering Parameters: ...@@ -105,7 +105,8 @@ Clustering Parameters:
| numberOfClusters | int | ❓ | Number of clusters the subcomponents should be divided into<br> Overrides numberOfClusters in algorithmParameters | | numberOfClusters | int | ❓ | Number of clusters the subcomponents should be divided into<br> Overrides numberOfClusters in algorithmParameters |
| flatten | bool | ❓ | Replace all components with their subcomponents execpt when it is atomic or the flatten level is reached | | flatten | bool | ❓ | Replace all components with their subcomponents execpt when it is atomic or the flatten level is reached |
| flattenLevel | int | ❓ | Maximal level of component flattening | | flattenLevel | int | ❓ | Maximal level of component flattening |
| chooseBy | String | ❓ | Strategie to choose from the resulting clusterings<br> bestWithFittingN(Default): if numberOfClusters is set, all results with a different number of clusters are ignored<br> bestOverall: ignore numberOfClusters, choose result with best score | | metric | String | ❓ | Metric to evaluate the quality of the resulting clusters. Available: "CommunicationCost"(Default), "Silhouette"|
| chooseBy | String | ❓ | Strategy to choose from the resulting clusterings<br> bestWithFittingN(Default): if numberOfClusters is set, all results with a different number of clusters are ignored<br> bestOverall: ignore numberOfClusters, choose result with best score |
| algorithmParameters | List<Object> | ❓ | Used to specify which algorithms(and their parameters) are used for clustering | | algorithmParameters | List<Object> | ❓ | Used to specify which algorithms(and their parameters) are used for clustering |
There are 4 different Clustering Algorithms with distinct parameters There are 4 different Clustering Algorithms with distinct parameters
......
...@@ -108,7 +108,7 @@ public class DistributedTargetGenerator extends CMakeGenerator { ...@@ -108,7 +108,7 @@ public class DistributedTargetGenerator extends CMakeGenerator {
//Cluster //Cluster
if(clusteringParameters.getAlgorithmParameters().size() > 0) { if(clusteringParameters.getAlgorithmParameters().size() > 0) {
clusteringResults = AutomaticClusteringHelper.executeClusteringFromParams(componentInstanceSymbol, clusteringParameters.getAlgorithmParameters()); clusteringResults = ClusteringResultList.fromParametersList(componentInstanceSymbol, clusteringParameters.getAlgorithmParameters(), clusteringParameters.getMetric());
Optional<Integer> nOpt = clusteringParameters.getNumberOfClusters(); Optional<Integer> nOpt = clusteringParameters.getNumberOfClusters();
for(ClusteringResult c : clusteringResults){ for(ClusteringResult c : clusteringResults){
String prefix = nOpt.isPresent() && !c.hasNumberOfClusters(nOpt.get()) ? "[IGNORED]" : ""; String prefix = nOpt.isPresent() && !c.hasNumberOfClusters(nOpt.get()) ? "[IGNORED]" : "";
......
...@@ -10,6 +10,7 @@ import java.io.FileReader; ...@@ -10,6 +10,7 @@ import java.io.FileReader;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
public class CliParametersLoader { public class CliParametersLoader {
...@@ -45,17 +46,19 @@ public class CliParametersLoader { ...@@ -45,17 +46,19 @@ public class CliParametersLoader {
.create(); .create();
JsonDeserializer<DynamicSpectralClusteringCliParameters> desCliParameters = new StrictJsonDeserializer<>(Arrays.asList("modelsDir","outputDir","rootModel","generators","emadlBackend","writeTagFile","clusteringParameters"), delegateGson); JsonDeserializer<CliParameters> desCliParameters = new StrictJsonDeserializer<>(Arrays.asList("emadlBackend","writeTagFile","clusteringParameters","modelsDir","outputDir","rootModel","generators"), delegateGson);
JsonDeserializer<ClusteringParameters> desClustering = new StrictJsonDeserializer<>(Arrays.asList("numberOfClusters","flatten","flattenLevel","chooseBy","algorithmParameters"), delegateGson); JsonDeserializer<ClusteringParameters> desClustering = new StrictJsonDeserializer<>(Arrays.asList("numberOfClusters","flatten","flattenLevel","chooseBy","algorithmParameters", "metric"), delegateGson);
JsonDeserializer<DynamicSpectralClusteringCliParameters> desSpectral = new StrictJsonDeserializer<>(Arrays.asList("numberOfClusters","l","sigma"), delegateGson); JsonDeserializer<DynamicSpectralClusteringCliParameters> desSpectral = new StrictJsonDeserializer<>(Arrays.asList("numberOfClusters","l","sigma"), delegateGson);
JsonDeserializer<DynamicSpectralClusteringCliParameters> desMarkov = new StrictJsonDeserializer<>(Arrays.asList("max_residual","gamma_exp","loop_gain","zero_max"), delegateGson); JsonDeserializer<DynamicMarkovCliParameters> desMarkov = new StrictJsonDeserializer<>(Arrays.asList("max_residual","gamma_exp","loop_gain","zero_max"), delegateGson);
JsonDeserializer<DynamicSpectralClusteringCliParameters> desDBScan = new StrictJsonDeserializer<>(Arrays.asList("min_pts","radius"), delegateGson); JsonDeserializer<DynamicDBScanCliParameters> desDBScan = new StrictJsonDeserializer<>(Arrays.asList("min_pts","radius"), delegateGson);
JsonDeserializer<DynamicAffinityPropagationCliParameters> desAff = new StrictJsonDeserializer<>(Collections.emptyList(), delegateGson);
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder()
.registerTypeAdapter(DynamicSpectralClusteringCliParameters.class, desSpectral) .registerTypeAdapter(DynamicSpectralClusteringCliParameters.class, desSpectral)
.registerTypeAdapter(DynamicMarkovCliParameters.class, desMarkov) .registerTypeAdapter(DynamicMarkovCliParameters.class, desMarkov)
.registerTypeAdapter(DynamicDBScanCliParameters.class, desDBScan) .registerTypeAdapter(DynamicDBScanCliParameters.class, desDBScan)
.registerTypeAdapter(DynamicAffinityPropagationCliParameters.class, desAff)
.registerTypeAdapter(CliParameters.class, desCliParameters) .registerTypeAdapter(CliParameters.class, desCliParameters)
.registerTypeAdapter(ClusteringParameters.class, desClustering) .registerTypeAdapter(ClusteringParameters.class, desClustering)
.create(); .create();
......
package de.monticore.lang.monticar.generator.middleware.cli; package de.monticore.lang.monticar.generator.middleware.cli;
import de.monticore.lang.monticar.generator.middleware.cli.algorithms.AlgorithmCliParameters; import de.monticore.lang.monticar.generator.middleware.cli.algorithms.AlgorithmCliParameters;
import de.monticore.lang.monticar.generator.middleware.cli.algorithms.SpectralClusteringCliParameters;
import de.monticore.lang.monticar.generator.middleware.cli.algorithms.dynamic.DynamicAlgorithmCliParameters; import de.monticore.lang.monticar.generator.middleware.cli.algorithms.dynamic.DynamicAlgorithmCliParameters;
import de.monticore.lang.monticar.generator.middleware.cli.algorithms.dynamic.DynamicParameter; import de.monticore.lang.monticar.generator.middleware.cli.algorithms.dynamic.DynamicParameter;
import de.monticore.lang.monticar.generator.middleware.cli.algorithms.dynamic.DynamicSpectralClusteringCliParameters; import de.monticore.lang.monticar.generator.middleware.cli.algorithms.dynamic.DynamicSpectralClusteringCliParameters;
import de.monticore.lang.monticar.generator.middleware.cli.algorithms.dynamic.ListParameter; import de.monticore.lang.monticar.generator.middleware.cli.algorithms.dynamic.ListParameter;
import de.monticore.lang.monticar.generator.middleware.clustering.qualityMetric.Metric;
import de.monticore.lang.monticar.generator.middleware.clustering.qualityMetric.MetricType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -18,6 +19,7 @@ public class ClusteringParameters { ...@@ -18,6 +19,7 @@ public class ClusteringParameters {
private Integer flattenLevel; private Integer flattenLevel;
private ResultChoosingStrategy chooseBy = ResultChoosingStrategy.bestWithFittingN; private ResultChoosingStrategy chooseBy = ResultChoosingStrategy.bestWithFittingN;
private List<DynamicAlgorithmCliParameters> algorithmParameters = new ArrayList<>(); private List<DynamicAlgorithmCliParameters> algorithmParameters = new ArrayList<>();
private MetricType metric;
public ClusteringParameters() { public ClusteringParameters() {
} }
...@@ -54,4 +56,12 @@ public class ClusteringParameters { ...@@ -54,4 +56,12 @@ public class ClusteringParameters {
public Optional<Integer> getFlattenLevel() { public Optional<Integer> getFlattenLevel() {
return Optional.ofNullable(flattenLevel); return Optional.ofNullable(flattenLevel);
} }
public Metric getMetric() {
if(metric == null){
return MetricType.CommunicationCost.toMetric();
}else{
return metric.toMetric();
}
}
} }
...@@ -2,6 +2,8 @@ package de.monticore.lang.monticar.generator.middleware.cli.algorithms; ...@@ -2,6 +2,8 @@ package de.monticore.lang.monticar.generator.middleware.cli.algorithms;
import de.monticore.lang.monticar.generator.middleware.clustering.ClusteringAlgorithm; import de.monticore.lang.monticar.generator.middleware.clustering.ClusteringAlgorithm;
import java.util.Optional;
public abstract class AlgorithmCliParameters { public abstract class AlgorithmCliParameters {
public static final String TYPE_SPECTRAL_CLUSTERING = "SpectralClustering"; public static final String TYPE_SPECTRAL_CLUSTERING = "SpectralClustering";
public static final String TYPE_UNKOWN = "Unkown"; public static final String TYPE_UNKOWN = "Unkown";
...@@ -22,4 +24,8 @@ public abstract class AlgorithmCliParameters { ...@@ -22,4 +24,8 @@ public abstract class AlgorithmCliParameters {
public abstract Object[] asAlgorithmArgs(); public abstract Object[] asAlgorithmArgs();
public abstract boolean isValid(); public abstract boolean isValid();
public Optional<Integer> expectedClusterCount(){
return Optional.empty();
}
} }
...@@ -68,6 +68,11 @@ public class SpectralClusteringCliParameters extends AlgorithmCliParameters { ...@@ -68,6 +68,11 @@ public class SpectralClusteringCliParameters extends AlgorithmCliParameters {
return numberOfClusters != null; return numberOfClusters != null;
} }
@Override
public Optional<Integer> expectedClusterCount() {
return Optional.of(getNumberOfClusters().get());
}
public Optional<Integer> getNumberOfClusters() { public Optional<Integer> getNumberOfClusters() {
return Optional.ofNullable(numberOfClusters); return Optional.ofNullable(numberOfClusters);
} }
......
...@@ -7,12 +7,12 @@ import java.util.Set; ...@@ -7,12 +7,12 @@ import java.util.Set;
// product if for clustering factory // product if for clustering factory
public interface ClusteringAlgorithm { public interface ClusteringAlgorithm {
List<Set<EMAComponentInstanceSymbol>> cluster(EMAComponentInstanceSymbol component, Object... args); List<Set<EMAComponentInstanceSymbol>> cluster(ClusteringInput clusteringInput, Object... args);
//TODO: add arguments as typed state of the algorithms(instead of untyped) //TODO: add arguments as typed state of the algorithms(instead of untyped)
default List<Set<EMAComponentInstanceSymbol>> clusterWithState(EMAComponentInstanceSymbol component){ default List<Set<EMAComponentInstanceSymbol>> clusterWithState(ClusteringInput clusteringInput){
Object[] args = getArgs(); Object[] args = getArgs();
return cluster(component, args); return cluster(clusteringInput, args);
} }
default Object[] getArgs(){ default Object[] getArgs(){
......
package de.monticore.lang.monticar.generator.middleware.clustering;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.middleware.helpers.ComponentHelper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ClusteringInput {
private EMAComponentInstanceSymbol instanceSymbol;
private double[][] adjacencyMatrix;
private boolean initAdjMatrix = false;
private double[][] distanceMatrix;
private boolean initDistMatrix = false;
private List<EMAComponentInstanceSymbol> subcompsOrderedByName;
private boolean initSubcomposOrderedByName = false;
private Map<String, Integer> labelsForSubcomps;
private boolean initLabelsForSubcomps = false;
public ClusteringInput(EMAComponentInstanceSymbol instanceSymbol) {
this.instanceSymbol = instanceSymbol;
}
public EMAComponentInstanceSymbol getComponent() {
return instanceSymbol;
}
public double[][] getAdjacencyMatrix(){
if(!initAdjMatrix){
initAdjMatrix = true;
adjacencyMatrix = AutomaticClusteringHelper.guaranteedConnectedAdjacencyMatrix(getSubcompsOrderedByName(), ComponentHelper.getInnerConnectors(instanceSymbol),getLabelsForSubcomps());
}
return getCopyOf(adjacencyMatrix);
}
public double[][] getDistanceMatrix(){
if(!initDistMatrix){
initDistMatrix = true;
distanceMatrix = AutomaticClusteringHelper.getDistanceMatrix(getAdjacencyMatrix());
}
return getCopyOf(distanceMatrix);
}
public List<EMAComponentInstanceSymbol> getSubcompsOrderedByName(){
if(!initSubcomposOrderedByName){
initSubcomposOrderedByName = true;
subcompsOrderedByName = ComponentHelper.getSubcompsOrderedByName(instanceSymbol);
}
return new ArrayList<>(subcompsOrderedByName);
}
public Map<String, Integer> getLabelsForSubcomps(){
if(!initLabelsForSubcomps){
initLabelsForSubcomps = true;
labelsForSubcomps = ComponentHelper.getLabelsForSubcomps(subcompsOrderedByName);
}
return new HashMap<>(labelsForSubcomps);
}
private double[][] getCopyOf(double[][] old){
double[][] res = new double[old.length][old[0].length];
for (int i = 0; i < old.length; i++) {
if (old[i].length >= 0) System.arraycopy(old[i], 0, res[i], 0, old[i].length);
}
return res;
}
}
...@@ -6,6 +6,7 @@ import com.google.gson.JsonParser; ...@@ -6,6 +6,7 @@ import com.google.gson.JsonParser;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol; import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.FileContent; import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.middleware.cli.algorithms.AlgorithmCliParameters; import de.monticore.lang.monticar.generator.middleware.cli.algorithms.AlgorithmCliParameters;
import de.monticore.lang.monticar.generator.middleware.clustering.qualityMetric.Metric;
import de.monticore.lang.monticar.generator.middleware.clustering.visualization.ModelVisualizer; import de.monticore.lang.monticar.generator.middleware.clustering.visualization.ModelVisualizer;
import de.monticore.lang.monticar.generator.middleware.impls.MiddlewareTagGenImpl; import de.monticore.lang.monticar.generator.middleware.impls.MiddlewareTagGenImpl;
import de.se_rwth.commons.logging.Log; import de.se_rwth.commons.logging.Log;
...@@ -15,46 +16,83 @@ import java.io.File; ...@@ -15,46 +16,83 @@ import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Set; import java.util.Set;
public class ClusteringResult { public class ClusteringResult {
Double score = null; private ClusteringInput clusteringInput;
private EMAComponentInstanceSymbol component;
private AlgorithmCliParameters parameters; private AlgorithmCliParameters parameters;
private List<Set<EMAComponentInstanceSymbol>> clustering; private List<Set<EMAComponentInstanceSymbol>> clustering;
private long durration; private long duration;
private int componentNumber; private int componentNumber;
private boolean valid;
private Metric metric;
private ClusteringResult(EMAComponentInstanceSymbol component, AlgorithmCliParameters parameters, private ClusteringResult(ClusteringInput clusteringInput, AlgorithmCliParameters parameters,
List<Set<EMAComponentInstanceSymbol>> clustering, long durration, int componentNumber) { List<Set<EMAComponentInstanceSymbol>> clustering, long duration, int componentNumber, boolean valid, Metric metric) {
this.component = component; this.clusteringInput = clusteringInput;
this.parameters = parameters; this.parameters = parameters;
this.clustering = clustering; this.clustering = clustering;
this.durration = durration; this.duration = duration;
this.componentNumber = componentNumber; this.componentNumber = componentNumber;
this.valid = valid;
this.metric = metric;
} }
public static ClusteringResult fromParameters(EMAComponentInstanceSymbol component, AlgorithmCliParameters parameters){ public static ClusteringResult fromParameters(ClusteringInput clusteringInput, AlgorithmCliParameters parameters, Metric metric) {
List<Set<EMAComponentInstanceSymbol>> res;
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
List<Set<EMAComponentInstanceSymbol>> res = parameters.asClusteringAlgorithm().clusterWithState(component);
try {
res = parameters.asClusteringAlgorithm().clusterWithState(clusteringInput);
} catch (Exception e) {
Log.warn("Marking this result as invalid. Error clustering the component.", e);
return new ClusteringResult(clusteringInput, parameters, new ArrayList<>(), -1, clusteringInput.getComponent().getSubComponents().size(), false, metric);
}
long endTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis();
boolean curValid = true;
int clustersBefore = res.size();
res.removeIf(Set::isEmpty);
if (clustersBefore != res.size()) {
Log.warn("Removed " + (clustersBefore - res.size()) + " empty clusters for algorithm " + parameters.toString());
}
Optional<Integer> expClusters = parameters.expectedClusterCount();
if(expClusters.isPresent() && !expClusters.get().equals(res.size())){
curValid = false;
Log.warn("Marking this result as invalid. The actual number of clusters(" + res.size() + ") does not equal the expected number(" + expClusters.get() +")");
}
int componentNumber = 0; int componentNumber = 0;
for (Set<EMAComponentInstanceSymbol> cluster : res) { for (Set<EMAComponentInstanceSymbol> cluster : res) {
componentNumber += cluster.size(); componentNumber += cluster.size();
} }
return new ClusteringResult(component, parameters, res, endTime - startTime, componentNumber); return new ClusteringResult(clusteringInput, parameters, res, endTime - startTime, componentNumber, curValid, metric);
}
public Metric getMetric() {
return metric;
}
public void setMetric(Metric metric){
this.metric = metric;
} }
public double getScore(){ public double getScore(){
if(score == null){ return metric.getScore(this);
score = AutomaticClusteringHelper.getTypeCostHeuristic(component, clustering);
}
return score;
} }
public EMAComponentInstanceSymbol getComponent() { public EMAComponentInstanceSymbol getComponent() {
return component; return clusteringInput.getComponent();
}
public ClusteringInput getClusteringInput() {
return clusteringInput;
} }
public AlgorithmCliParameters getParameters() { public AlgorithmCliParameters getParameters() {
...@@ -69,8 +107,8 @@ public class ClusteringResult { ...@@ -69,8 +107,8 @@ public class ClusteringResult {
return clustering.size(); return clustering.size();
} }
private long getDurration() { private long getDuration() {
return this.durration; return this.duration;
} }
public int getComponentNumber() { public int getComponentNumber() {
...@@ -87,17 +125,17 @@ public class ClusteringResult { ...@@ -87,17 +125,17 @@ public class ClusteringResult {
String prefix = "//Algorithm: " + this.getParameters().toString() + "\n" + String prefix = "//Algorithm: " + this.getParameters().toString() + "\n" +
"//Number of clusters: " + this.getNumberOfClusters() + "\n" + "//Number of clusters: " + this.getNumberOfClusters() + "\n" +
"//Score: " + this.getScore() + "\n" + "//Score: " + this.getScore() + "\n" +
"//Durration in ms: " + this.getDurration() + "\n"; "//Durration in ms: " + this.getDuration() + "\n";
String content = MiddlewareTagGenImpl.getFileContent(component, this.clustering); String content = MiddlewareTagGenImpl.getFileContent(clusteringInput.getComponent(), this.clustering);
res.setFileContent(prefix + content); res.setFileContent(prefix + content);
return res; return res;
} }
//TODO: refactor to File? //TODO: refactor to File?
public void saveVisualization(String path, String fileName){ public void saveVisualization(String path, String fileName){
Graph g = ModelVisualizer.buildGraph(component, parameters.toString()); Graph g = ModelVisualizer.buildGraph(clusteringInput.getComponent(), parameters.toString());
ModelVisualizer.visualizeClustering(g, clustering, component); ModelVisualizer.visualizeClustering(g, clustering, clusteringInput.getComponent());
ModelVisualizer.saveGraphAsImage(g, path, fileName); ModelVisualizer.saveGraphAsImage(g, path, fileName);
} }
...@@ -133,9 +171,16 @@ public class ClusteringResult { ...@@ -133,9 +171,16 @@ public class ClusteringResult {
result.addProperty("Algorithm", this.getParameters().toString()); result.addProperty("Algorithm", this.getParameters().toString());
result.addProperty("NumberOfClusters", this.getNumberOfClusters()); result.addProperty("NumberOfClusters", this.getNumberOfClusters());
result.addProperty("Score", this.getScore()); result.addProperty("Score", this.getScore());
result.addProperty("DurationInMs", this.getDurration()); result.addProperty("DurationInMs", this.getDuration());
result.addProperty("ComponentNumber", this.getComponentNumber()); result.addProperty("ComponentNumber", this.getComponentNumber());
return result; return result;
} }
public boolean isValid() {
return valid;
}
public void setValid(boolean valid) {
this.valid = valid;
}
} }
\ No newline at end of file
package de.monticore.lang.monticar.generator.middleware.clustering; package de.monticore.lang.monticar.generator.middleware.clustering;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.FileContent; import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.middleware.cli.algorithms.AlgorithmCliParameters;
import de.monticore.lang.monticar.generator.middleware.clustering.qualityMetric.Metric;
import de.se_rwth.commons.logging.Log; import de.se_rwth.commons.logging.Log;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -14,6 +17,24 @@ public class ClusteringResultList extends ArrayList<ClusteringResult> { ...@@ -14,6 +17,24 @@ public class ClusteringResultList extends ArrayList<ClusteringResult> {
super(); super();
} }
public static ClusteringResultList fromParametersList(EMAComponentInstanceSymbol emaComponentInstance, List<AlgorithmCliParameters> algoParams, Metric metric) {
ClusteringResultList res = new ClusteringResultList();
ClusteringInput clusteringInput = new ClusteringInput(emaComponentInstance);
//create AdjacencyMatrix to make execution speed comparision fairer
clusteringInput.getAdjacencyMatrix();
for (int i = 0; i < algoParams.size(); i++) {
System.out.println("Clustering with algorithm " + (i + 1) + "/" + algoParams.size() + ": " + algoParams.get(i).toString());
ClusteringResult result = ClusteringResult.fromParameters(clusteringInput, algoParams.get(i), metric);
if (result.isValid()) {
res.add(result);
} else {
Log.warn("Ignoring the result! It is invalid!");
}
}
return res;
}
public Optional<ClusteringResult> getBestResultWithFittingN(int n){ public Optional<ClusteringResult> getBestResultWithFittingN(int n){
ClusteringResultList filteredList = new ClusteringResultList(); ClusteringResultList filteredList = new ClusteringResultList();
for(ClusteringResult c : this){ for(ClusteringResult c : this){
...@@ -28,8 +49,16 @@ public class ClusteringResultList extends ArrayList<ClusteringResult> { ...@@ -28,8 +49,16 @@ public class ClusteringResultList extends ArrayList<ClusteringResult> {
} }
public Optional<ClusteringResult> getBestResultOverall(){ public Optional<ClusteringResult> getBestResultOverall(){
this.sort(Comparator.comparing(ClusteringResult::getScore)); if(this.isEmpty()){
return this.size() == 0 ? Optional.empty() : Optional.of(this.get(0)); return Optional.empty();
}
ClusteringResultList copiedList = new ClusteringResultList();
copiedList.addAll(this);
copiedList.sort(Comparator.comparing(ClusteringResult::getScore));
int index = copiedList.get(0).getMetric().higherIsBetter() ? copiedList.size() - 1 : 0;
return Optional.of(copiedList.get(index));
} }
public List<FileContent> getAllTagFiles(String baseName){ public List<FileContent> getAllTagFiles(String baseName){
......
...@@ -3,9 +3,8 @@ package de.monticore.lang.monticar.generator.middleware.clustering.algorithms; ...@@ -3,9 +3,8 @@ package de.monticore.lang.monticar.generator.middleware.clustering.algorithms;
import com.clust4j.algo.AffinityPropagation; import com.clust4j.algo.AffinityPropagation;
import com.clust4j.algo.AffinityPropagationParameters; import com.clust4j.algo.AffinityPropagationParameters;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol; import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.middleware.clustering.AutomaticClusteringHelper;
import de.monticore.lang.monticar.generator.middleware.clustering.ClusteringAlgorithm; import de.monticore.lang.monticar.generator.middleware.clustering.ClusteringAlgorithm;
import de.monticore.lang.monticar.generator.middleware.helpers.ComponentHelper; import de.monticore.lang.monticar.generator.middleware.clustering.ClusteringInput;