Aufgrund einer Wartung wird GitLab am 28.09. zwischen 10:00 und 11:00 Uhr kurzzeitig nicht zur Verfügung stehen. / Due to maintenance, GitLab will be temporarily unavailable on 28.09. between 10:00 and 11:00 am.

Commit 5f161a2f authored by Michael Günther Beyer's avatar Michael Günther Beyer

model and clustering visualization

parent 72354611
......@@ -79,6 +79,11 @@
<artifactId>smile-core</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>com.github.haifengl</groupId>
<artifactId>smile-plot</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
......
package de.monticore.lang.monticar.generator.middleware.clustering.visualization;
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.helpers.ComponentHelper;
import de.monticore.lang.monticar.generator.order.simulator.AbstractSymtab;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.monticore.symboltable.CommonSymbol;
import org.graphstream.graph.Edge;
import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;
import org.graphstream.graph.implementations.SingleGraph;
import org.graphstream.stream.file.FileSinkImages;
import smile.plot.Palette;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class ModelVisualizer {
private static FileSinkImages.OutputType imgType = FileSinkImages.OutputType.PNG;
private static FileSinkImages.Resolutions imgRes = FileSinkImages.Resolutions.XGA;
private static Integer stdNodeSize = 12;
private static Integer minNodeSize = 10;
private static Integer maxNodeSize = 20;
public static Integer getStdNodeSize() {
return stdNodeSize;
}
public static void setStdNodeSize(Integer size) {
stdNodeSize = size;
}
public static Integer getMinNodeSize() {
return minNodeSize;
}
public static void setMaxNodeSize(Integer size) {
maxNodeSize = size;
}
public static Integer getMaxNodeSize() {
return maxNodeSize;
}
public static void setMinNodeSize(Integer size) {
minNodeSize = size;
}
public static FileSinkImages.OutputType getImgType() {
return imgType;
}
public static void setImgType(FileSinkImages.OutputType type) {
imgType = type;
}
public static FileSinkImages.Resolutions getImgResolution() {
return imgRes;
}
public static void setImgType(FileSinkImages.Resolutions res) {
imgRes = res;
}
public static Integer calcNodeSize(Integer maxClustNum, Integer clustNum) {
if (clustNum==1) {
return getMinNodeSize();
} else if (clustNum==maxClustNum) {
return getMaxNodeSize();
} else {
return getMinNodeSize() + ( clustNum * (getMaxNodeSize()-getMinNodeSize()) / (maxClustNum + 1) );
}
}
public static EMAComponentInstanceSymbol loadModel(String modelPath, String modelName) {
TaggingResolver taggingResolver = AbstractSymtab.createSymTabAndTaggingResolver(modelPath);
return taggingResolver.<EMAComponentInstanceSymbol>resolve(modelName, EMAComponentInstanceSymbol.KIND).orElse(null);
}
public static Graph buildGraph(EMAComponentInstanceSymbol componentInstanceSymbol, String modelName) {
Graph graph = new SingleGraph(modelName);
List<EMAComponentInstanceSymbol> subcompsOrderedByName = ComponentHelper.getSubcompsOrderedByName(componentInstanceSymbol);
Map<String, Integer> labelsForSubcomps = ComponentHelper.getLabelsForSubcomps(subcompsOrderedByName);
Map<Integer, String> subcompsLabels = ComponentHelper.getSubcompsLabels(subcompsOrderedByName);
double[][] adjMatrix = AutomaticClusteringHelper.createAdjacencyMatrix(subcompsOrderedByName,
ComponentHelper.getInnerConnectors(componentInstanceSymbol),
labelsForSubcomps);
Node node;
Edge edge;
String subCompLabel;
for(int i = 0; i < adjMatrix[0].length; i++) {
node= graph.addNode(Integer.toString(i));
subCompLabel= subcompsLabels.get(Integer.parseInt(node.getId()));
subCompLabel= subCompLabel.substring(subCompLabel.lastIndexOf('.') + 1);
node.addAttribute("ui.label", node.getId() + " (" + subCompLabel + ")");
node.setAttribute("ui.style", "size: "+getStdNodeSize()+"px;");
}
for(int i = 0; i < adjMatrix[0].length; i++) {
for(int j = i; j < adjMatrix[0].length; j++) {
if (adjMatrix[i][j] > 0) {
edge= graph.addEdge(i + "-" + j, Integer.toString(i), Integer.toString(j));
edge.addAttribute("ui.label", adjMatrix[i][j]);
}
}
}
return graph;
}
public static void visualizeClustering(Graph graph, List<Set<EMAComponentInstanceSymbol>> clusters, EMAComponentInstanceSymbol componentInstanceSymbol) {
List<EMAComponentInstanceSymbol> subcompsOrderedByName = ComponentHelper.getSubcompsOrderedByName(componentInstanceSymbol);
Map<String, Integer> labelsForSubcomps = ComponentHelper.getLabelsForSubcomps(subcompsOrderedByName);
Map<Integer, String> subcompsLabels = ComponentHelper.getSubcompsLabels(subcompsOrderedByName);
double[][] adjMatrix = AutomaticClusteringHelper.createAdjacencyMatrix(subcompsOrderedByName,
ComponentHelper.getInnerConnectors(componentInstanceSymbol),
labelsForSubcomps);
Node n;
Edge e;
String nodeName;
String nodeId;
Integer colR, colG, colB;
Integer size;
Set<EMAComponentInstanceSymbol> cluster;
List<String> clusterNames;
for(int i = 0; i < clusters.size(); i++) {
cluster = clusters.get(i);
colR= Palette.rainbow(clusters.size())[i].getRed();
colB= Palette.rainbow(clusters.size())[i].getGreen();
colG= Palette.rainbow(clusters.size())[i].getBlue();
size= calcNodeSize(clusters.size(), i+1);
clusterNames = cluster.stream().map(CommonSymbol::getFullName).collect(Collectors.toList());
for(int j = 0; j < clusterNames.size(); j++) {
nodeId= labelsForSubcomps.get(clusterNames.get(j)).toString();
if (nodeId!=null) {
n= graph.getNode(nodeId);
n.setAttribute("ui.style", "fill-mode: plain; fill-color: rgb("+colR+","+colG+","+colB+"); size: "+size+"px;");
// find "cutting" edges and re-color (or delete) them
for(int k = 0; k < adjMatrix[Integer.parseInt(nodeId)].length; k++) {
if (adjMatrix[Integer.parseInt(nodeId)][k] > 0) {
// target node k is not in current cluster
nodeName= subcompsLabels.get(k);
if (!clusterNames.contains(nodeName)) {
e= graph.getEdge(Integer.parseInt(nodeId)+"-"+k);
// if (e!=null) graph.removeEdge(e);
if (e!=null) e.setAttribute("ui.style", "fill-mode: plain; fill-color: #F0F0F0;");
}
}
}
}
}
}
}
public static void saveGraphAsImage(Graph graph, String imgPath, String imgName) {
FileSinkImages img = new FileSinkImages(getImgType(), getImgResolution());
img.setStyleSheet("graph { padding: 100px; }");
img.setLayoutPolicy(FileSinkImages.LayoutPolicy.COMPUTED_FULLY_AT_NEW_IMAGE);
try {
img.writeAll(graph, imgPath + imgName + "." + getImgType().name().toLowerCase());
} catch (IOException e) {
System.out.println("Couldn't create image file " + imgPath + imgName + "." + getImgType().name().toLowerCase() + "\n" + e.getMessage());
};
}
public static void viewGraph(Graph graph) {
SimpleModelViewer viewer = new SimpleModelViewer(graph);
viewer.run();
}
}
package de.monticore.lang.monticar.generator.middleware.clustering;
package de.monticore.lang.monticar.generator.middleware.clustering.visualization;
import org.graphstream.graph.Graph;
import org.graphstream.ui.view.Viewer;
......
......@@ -7,6 +7,8 @@ import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instance
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAPortInstanceSymbol;
import de.monticore.lang.monticar.generator.middleware.clustering.*;
import de.monticore.lang.monticar.generator.middleware.clustering.algorithms.*;
import de.monticore.lang.monticar.generator.middleware.clustering.visualization.ModelVisualizer;
import de.monticore.lang.monticar.generator.middleware.clustering.visualization.SimpleModelViewer;
import de.monticore.lang.monticar.generator.middleware.helpers.ComponentHelper;
import de.monticore.lang.monticar.generator.middleware.impls.CPPGenImpl;
import de.monticore.lang.monticar.generator.middleware.impls.RosCppGenImpl;
......@@ -29,6 +31,7 @@ import org.junit.Assert;
import org.junit.Test;
import smile.clustering.DBSCAN;
import smile.clustering.SpectralClustering;
import smile.plot.Palette;
import java.io.IOException;
import java.util.*;
......@@ -431,53 +434,19 @@ public class AutomaticClusteringTest extends AbstractSymtabTest{
@Test
public void testClusteringAlgorithms(){
TaggingResolver taggingResolver = AbstractSymtabTest.createSymTabAndTaggingResolver(TEST_PATH);
//String modelName= "clustering.unambiguousCluster";
String modelName= "clustering.midSizeDemoCluster";
EMAComponentInstanceSymbol componentInstanceSymbol = taggingResolver.<EMAComponentInstanceSymbol>resolve(modelName, EMAComponentInstanceSymbol.KIND).orElse(null);
EMAComponentInstanceSymbol componentInstanceSymbol = ModelVisualizer.loadModel(TEST_PATH, modelName);
assertNotNull(componentInstanceSymbol);
// get stuff together for adjmatrix
List<EMAComponentInstanceSymbol> subcompsOrderedByName = ComponentHelper.getSubcompsOrderedByName(componentInstanceSymbol);
Map<String, Integer> labelsForSubcomps = ComponentHelper.getLabelsForSubcomps(subcompsOrderedByName);
Map<Integer, String> subcompsLabels = ComponentHelper.getSubcompsLabels(subcompsOrderedByName);
double[][] adjMatrix = AutomaticClusteringHelper.createAdjacencyMatrix(subcompsOrderedByName,
ComponentHelper.getInnerConnectors(componentInstanceSymbol),
labelsForSubcomps);
// build a graph from this stuff
Graph graph = new SingleGraph(modelName);
Node node= null;
Edge edge= null;
String subCompLabel= null;
for(int i = 0; i < adjMatrix[0].length; i++) {
node= graph.addNode(Integer.toString(i));
subCompLabel= subcompsLabels.get(Integer.parseInt(node.getId()));
subCompLabel= subCompLabel.substring(subCompLabel.lastIndexOf('.') + 1);
node.addAttribute("ui.label", node.getId() + " (" + subCompLabel + ")");
}
for(int i = 0; i < adjMatrix[0].length; i++) {
for(int j = i; j < adjMatrix[0].length; j++) {
if (adjMatrix[i][j] > 0) {
edge= graph.addEdge(i + "-" + j, Integer.toString(i), Integer.toString(j));
edge.addAttribute("ui.label", adjMatrix[i][j]);
}
}
}
Graph graph = ModelVisualizer.buildGraph(componentInstanceSymbol, modelName);
FileSinkImages img = new FileSinkImages(FileSinkImages.OutputType.PNG, FileSinkImages.Resolutions.XGA);
img.setStyleSheet("graph { padding: 100px; }");
img.setLayoutPolicy(FileSinkImages.LayoutPolicy.COMPUTED_FULLY_AT_NEW_IMAGE);
try { img.writeAll(graph, TEST_PATH_PNG + modelName + ".png"); } catch (IOException e) { System.out.println("Couldn't create image file "+TEST_PATH_PNG + modelName + ".png"+
"\n"+e.getMessage()); };
/*
SimpleModelViewer viewer= new SimpleModelViewer(graph);
viewer.run();
*/
ModelVisualizer.saveGraphAsImage(graph, TEST_PATH_PNG, modelName);
// ModelVisualizer.viewGraph(graph);
Object[] params;
for(ClusteringKind kind : ClusteringKind.values()){
......@@ -503,240 +472,163 @@ public class AutomaticClusteringTest extends AbstractSymtabTest{
String algoNameShort= algoName.substring(algoName.lastIndexOf(".")+1);
System.out.println(algoName);
TaggingResolver taggingResolver = AbstractSymtabTest.createSymTabAndTaggingResolver(TEST_PATH);
componentInstanceSymbol = taggingResolver.<EMAComponentInstanceSymbol>resolve(modelName, EMAComponentInstanceSymbol.KIND).orElse(null);
assertNotNull(componentInstanceSymbol);
List<Set<EMAComponentInstanceSymbol>> clusters = null;
if (params != null) clusters = algorithm.cluster(componentInstanceSymbol, params); else
clusters = algorithm.cluster(componentInstanceSymbol);
double colorIncrement= 1.0/clusters.size();
double sizeIncrement= Math.ceil(50/clusters.size());
double color= 0;
double size= 10;
// get stuff together for adjmatrix
List<EMAComponentInstanceSymbol> subcompsOrderedByName = ComponentHelper.getSubcompsOrderedByName(componentInstanceSymbol);
Map<String, Integer> labelsForSubcomps = ComponentHelper.getLabelsForSubcomps(subcompsOrderedByName);
Map<Integer, String> subcompsLabels = ComponentHelper.getSubcompsLabels(subcompsOrderedByName);
double[][] adjMatrix = AutomaticClusteringHelper.createAdjacencyMatrix(subcompsOrderedByName,
ComponentHelper.getInnerConnectors(componentInstanceSymbol),
labelsForSubcomps);
// build a graph from this stuff
Graph graph = new SingleGraph(algoNameShort);
Node node= null;
Edge edge= null;
String subCompLabel= null;
for(int i = 0; i < adjMatrix[0].length; i++) {
node= graph.addNode(Integer.toString(i));
subCompLabel= subcompsLabels.get(Integer.parseInt(node.getId()));
subCompLabel= subCompLabel.substring(subCompLabel.lastIndexOf('.') + 1);
node.addAttribute("ui.label", node.getId() + " (" + subCompLabel + ")");
}
for(int i = 0; i < adjMatrix[0].length; i++) {
for(int j = i; j < adjMatrix[0].length; j++) {
if (adjMatrix[i][j] > 0) {
edge= graph.addEdge(i + "-" + j, Integer.toString(i), Integer.toString(j));
edge.addAttribute("ui.label", adjMatrix[i][j]);
Graph graph = ModelVisualizer.buildGraph(componentInstanceSymbol, algoNameShort);
ModelVisualizer.visualizeClustering(graph, clusters, componentInstanceSymbol);
ModelVisualizer.saveGraphAsImage(graph, TEST_PATH_PNG, modelName + "/" + graph.getId());
// ModelVisualizer.viewGraph(graph);
if (modelName=="clustering.midSizeDemoCluster") {
if (algorithm instanceof AffinityPropagationAlgorithm) {
assertTrue(clusters.get(0).size() > 0 &&
clusters.get(1).size() > 0 &&
clusters.get(2).size() > 0
);
Set<EMAComponentInstanceSymbol> cluster1 = clusters.get(0);
Set<EMAComponentInstanceSymbol> cluster2 = clusters.get(1);
Set<EMAComponentInstanceSymbol> cluster3 = clusters.get(2);
assertTrue((cluster1.size() == 3 && cluster2.size() == 1 && cluster3.size() == 3) ||
(cluster1.size() == 3 && cluster2.size() == 3 && cluster3.size() == 1) ||
(cluster1.size() == 1 && cluster2.size() == 3 && cluster3.size() == 3)
);
List<String> cluster1Names = cluster1.stream()
.map(CommonSymbol::getFullName)
.collect(Collectors.toList());
List<String> cluster2Names = cluster2.stream()
.map(CommonSymbol::getFullName)
.collect(Collectors.toList());
List<String> cluster3Names = cluster3.stream()
.map(CommonSymbol::getFullName)
.collect(Collectors.toList());
// cut-off point should be at comp1 or comp4, so those nodes should form a cluster of their own
if (cluster1.size() == 1) {
if (cluster1Names.get(0).endsWith("comp1")) assertTrue(cluster1Names.contains(modelName + ".comp1"));
if (cluster1Names.get(0).endsWith("comp4")) assertTrue(cluster1Names.contains(modelName + ".comp4"));
} else if (cluster2.size() == 1) {
if (cluster2Names.get(0).endsWith("comp1")) assertTrue(cluster2Names.contains(modelName + ".comp1"));
if (cluster2Names.get(0).endsWith("comp4")) assertTrue(cluster2Names.contains(modelName + ".comp4"));
} else if (cluster3.size() == 1) {
if (cluster3Names.get(0).endsWith("comp1")) assertTrue(cluster3Names.contains(modelName + ".comp1"));
if (cluster3Names.get(0).endsWith("comp4")) assertTrue(cluster3Names.contains(modelName + ".comp4"));
}
}
}
// style (colorize + resize) nodes for clusters
Node n;
Edge e;
String nodeName;
String nodeId;
Set<EMAComponentInstanceSymbol> cluster;
List<String> clusterNames;
for(int i = 0; i < clusters.size(); i++) {
cluster = clusters.get(i);
clusterNames = cluster.stream().map(CommonSymbol::getFullName).collect(Collectors.toList());
for(int j = 0; j < clusterNames.size(); j++) {
nodeId= null;
nodeId= labelsForSubcomps.get(clusterNames.get(j)).toString();
if (nodeId!=null) {
n= graph.getNode(nodeId);
n.setAttribute("ui.style", "fill-mode: dyn-plain; fill-color: red, black; size: " + size + "px;");
n.setAttribute("ui.color", color);
// find cutting edges and delete or re-color them
for(int k = 0; k < adjMatrix[Integer.parseInt(nodeId)].length; k++) {
if (adjMatrix[Integer.parseInt(nodeId)][k] > 0) {
// target node k is not in current cluster
nodeName= subcompsLabels.get(k);
if (!clusterNames.contains(nodeName)) {
e= null;
e= graph.getEdge(Integer.parseInt(nodeId)+"-"+k);
//graph.removeEdge(e);
if (e!=null) e.setAttribute("ui.style", "fill-mode: plain; fill-color: #F0F0F0;");
}
}
} else {
assertTrue(clusters.size() == 2);
Set<EMAComponentInstanceSymbol> cluster1 = clusters.get(0);
Set<EMAComponentInstanceSymbol> cluster2 = clusters.get(1);
assertTrue((cluster1.size() == 3 && cluster2.size() == 4) ||
(cluster2.size() == 3 && cluster1.size() == 4)
);
List<String> cluster1Names = cluster1.stream()
.map(CommonSymbol::getFullName)
.collect(Collectors.toList());
List<String> cluster2Names = cluster2.stream()
.map(CommonSymbol::getFullName)
.collect(Collectors.toList());
if (cluster1.size() == 4) {
if (cluster1Names.get(0).endsWith("comp0") ||
cluster1Names.get(0).endsWith("comp1") ||
cluster1Names.get(0).endsWith("comp2") ||
cluster1Names.get(0).endsWith("comp3")
) {
assertTrue(cluster1Names.contains(modelName + ".comp0"));
assertTrue(cluster1Names.contains(modelName + ".comp1"));
assertTrue(cluster1Names.contains(modelName + ".comp2"));
assertTrue(cluster1Names.contains(modelName + ".comp3"));
assertTrue(cluster2Names.contains(modelName + ".comp4"));
assertTrue(cluster2Names.contains(modelName + ".comp5"));
assertTrue(cluster2Names.contains(modelName + ".comp6"));
}
} else if (cluster1.size() == 3) {
if (cluster1Names.get(0).endsWith("comp4") ||
cluster1Names.get(0).endsWith("comp5") ||
cluster1Names.get(0).endsWith("comp6")
) {
assertTrue(cluster2Names.contains(modelName + ".comp0"));
assertTrue(cluster2Names.contains(modelName + ".comp1"));
assertTrue(cluster2Names.contains(modelName + ".comp2"));
assertTrue(cluster2Names.contains(modelName + ".comp3"));
assertTrue(cluster1Names.contains(modelName + ".comp4"));
assertTrue(cluster1Names.contains(modelName + ".comp5"));
assertTrue(cluster1Names.contains(modelName + ".comp6"));
}
}
}
color= color + colorIncrement;
size= size + sizeIncrement;
}
FileSinkImages img = new FileSinkImages(FileSinkImages.OutputType.PNG, FileSinkImages.Resolutions.XGA);
img.setStyleSheet("graph { padding: 100px; }");
img.setLayoutPolicy(FileSinkImages.LayoutPolicy.COMPUTED_FULLY_AT_NEW_IMAGE);
try { img.writeAll(graph, TEST_PATH_PNG + modelName + "/" + graph.getId() + ".png"); } catch (IOException ex) { System.out.println("Couldn't create image file "+TEST_PATH_PNG + graph.getId() + ".png"+
"\n"+ex.getMessage()); };
/*
SimpleModelViewer viewer= new SimpleModelViewer(graph);
viewer.run();
*/
if (modelName=="clustering.midSizeDemoCluster") {
if (algorithm instanceof AffinityPropagationAlgorithm) {
assertTrue(clusters.get(0).size() > 0 &&
clusters.get(1).size() > 0 &&
clusters.get(2).size() > 0
);
Set<EMAComponentInstanceSymbol> cluster1 = clusters.get(0);
Set<EMAComponentInstanceSymbol> cluster2 = clusters.get(1);
Set<EMAComponentInstanceSymbol> cluster3 = clusters.get(2);
assertTrue((cluster1.size() == 3 && cluster2.size() == 1 && cluster3.size() == 3) ||
(cluster1.size() == 3 && cluster2.size() == 3 && cluster3.size() == 1) ||
(cluster1.size() == 1 && cluster2.size() == 3 && cluster3.size() == 3)
);
List<String> cluster1Names = cluster1.stream()
.map(CommonSymbol::getFullName)
.collect(Collectors.toList());
List<String> cluster2Names = cluster2.stream()
.map(CommonSymbol::getFullName)
.collect(Collectors.toList());
List<String> cluster3Names = cluster3.stream()
.map(CommonSymbol::getFullName)
.collect(Collectors.toList());
// cut-off point should be at comp1 or comp4, so those nodes should form a cluster of their own
if (cluster1.size() == 1) {
if (cluster1Names.get(0).endsWith("comp1")) assertTrue(cluster1Names.contains(modelName + ".comp1"));
if (cluster1Names.get(0).endsWith("comp4")) assertTrue(cluster1Names.contains(modelName + ".comp4"));
} else if (cluster2.size() == 1) {
if (cluster2Names.get(0).endsWith("comp1")) assertTrue(cluster2Names.contains(modelName + ".comp1"));
if (cluster2Names.get(0).endsWith("comp4")) assertTrue(cluster2Names.contains(modelName + ".comp4"));
} else if (cluster3.size() == 1) {
if (cluster3Names.get(0).endsWith("comp1")) assertTrue(cluster3Names.contains(modelName + ".comp1"));
if (cluster3Names.get(0).endsWith("comp4")) assertTrue(cluster3Names.contains(modelName + ".comp4"));
}
} else {
assertTrue(clusters.size() == 2);
Set<EMAComponentInstanceSymbol> cluster1 = clusters.get(0);
Set<EMAComponentInstanceSymbol> cluster2 = clusters.get(1);
assertTrue((cluster1.size() == 3 && cluster2.size() == 4) ||
(cluster2.size() == 3 && cluster1.size() == 4)
);
List<String> cluster1Names = cluster1.stream()
.map(CommonSymbol::getFullName)
.collect(Collectors.toList());
List<String> cluster2Names = cluster2.stream()
.map(CommonSymbol::getFullName)
.collect(Collectors.toList());
if (cluster1.size() == 4) {
if (cluster1Names.get(0).endsWith("comp0") ||
cluster1Names.get(0).endsWith("comp1") ||
cluster1Names.get(0).endsWith("comp2") ||
cluster1Names.get(0).endsWith("comp3")
) {
assertTrue(cluster1Names.contains(modelName + ".comp0"));
assertTrue(cluster1Names.contains(modelName + ".comp1"));
assertTrue(cluster1Names.contains(modelName + ".comp2"));
assertTrue(cluster1Names.contains(modelName + ".comp3"));
assertTrue(cluster2Names.contains(modelName + ".comp4"));
assertTrue(cluster2Names.contains(modelName + ".comp5"));
assertTrue(cluster2Names.contains(modelName + ".comp6"));
}
} else if (cluster1.size() == 3) {
if (cluster1Names.get(0).endsWith("comp4") ||
cluster1Names.get(0).endsWith("comp5") ||
cluster1Names.get(0).endsWith("comp6")
) {
assertTrue(cluster2Names.contains(modelName + ".comp0"));
assertTrue(cluster2Names.contains(modelName + ".comp1"));
assertTrue(cluster2Names.contains(modelName + ".comp2"));
assertTrue(cluster2Names.contains(modelName + ".comp3"));
assertTrue(cluster1Names.contains(modelName + ".comp4"));
assertTrue(cluster1Names.contains(modelName + ".comp5"));
assertTrue(cluster1Names.contains(modelName + ".comp6"));
}
}
}
}
if (modelName=="clustering.unambiguousCluster") {
if (algorithm instanceof SpectralClusteringAlgorithm) {
if (modelName=="clustering.unambiguousCluster") {
if (algorithm instanceof SpectralClusteringAlgorithm) {
assertTrue(clusters.size() == 2);
assertTrue(clusters.size() == 2);
Set<EMAComponentInstanceSymbol> cluster1 = clusters.get(0);
Set<EMAComponentInstanceSymbol> cluster2 = clusters.get(1);
assertTrue(cluster1.size() == 2);
assertTrue(cluster2.size() == 2);
Set<EMAComponentInstanceSymbol>