package com.rapidminer.operator.learner.clustering.clusterer;
import java.util.Iterator;
import java.util.Vector;
import com.rapidminer.example.Example;
import com.rapidminer.example.ExampleSet;
import com.rapidminer.operator.IOContainer;
import com.rapidminer.operator.OperatorDescription;
import com.rapidminer.operator.OperatorException;
import com.rapidminer.operator.learner.clustering.ClusterModel;
import com.rapidminer.operator.learner.clustering.DefaultCluster;
import com.rapidminer.operator.learner.clustering.FlatClusterModel;
import com.rapidminer.operator.learner.clustering.FlatCrispClusterModel;
import com.rapidminer.operator.learner.clustering.IdUtils;
/**
* Aggregates several clusterings into one. The strategy of this
* operator is based on correlation clustering.
*
* @author Michael Huber
* @see com.rapidminer.operator.learner.clustering.clusterer.DBScanClustering
* @see com.rapidminer.operator.learner.clustering.clusterer.uncertain.DBScanEAClustering
* @see com.rapidminer.operator.learner.clustering.clusterer.uncertain.FDBScanClustering
*/
public class ClusteringAggregation extends AbstractFlatClusterer {
private Vector<FlatCrispClusterModel> clusteringModels;
public ClusteringAggregation(OperatorDescription description) {
super(description);
}
public ClusterModel createClusterModel(ExampleSet es)
throws OperatorException {
clusteringModels = new Vector<FlatCrispClusterModel>();
IOContainer ioc = getInput();
while(ioc.contains(ClusterModel.class)) {
clusteringModels.add(ioc.get(FlatCrispClusterModel.class));
ioc.remove(FlatCrispClusterModel.class);
}
FlatCrispClusterModel result = new FlatCrispClusterModel();
double edge;
int uClusterId, vClusterId;
int clusterCount = 0;
//Durchlaufen aller Paar-Kombinationen der Objekte u,v
for (Example u: es) {
for (Example v: es) {
String uid = IdUtils.getIdFromExample(u);
String vid = IdUtils.getIdFromExample(v);
//Berechnung der Wahrscheinlichkeit, zusammengeclustert zu werden
edge = 0;
for(int i = 0; i < clusteringModels.size(); i++) {
uClusterId = getClusterId(uid, clusteringModels.get(i));
vClusterId = getClusterId(vid, clusteringModels.get(i));
if(uClusterId == vClusterId) { //hier wird Noise auch als Cluster gesehen
edge++;
}
}
edge = edge / clusteringModels.size();
//logNote("(" + uid + ";" + vid + ") = " + edge);
if(edge > 0.5) {
if(!containsId(uid, result) && !containsId(vid, result)) {
//beide in neues Cluster einf�gen
result.addCluster(new DefaultCluster(String.valueOf(clusterCount)));
((DefaultCluster) result.getClusterAt(clusterCount)).addObject(uid);
((DefaultCluster) result.getClusterAt(clusterCount)).addObject(vid);
clusterCount++;
} else if((containsId(uid, result) && !containsId(vid, result)) ||
(!containsId(uid, result) && containsId(vid, result))) {
//ein Objekt ist bereits im ClusterModel result, das andere nicht
String a = uid;
String b = vid;
if(containsId(vid, result)) {
a = vid;
b = uid;
}
//das nicht enthaltene Objekt zum Cluster des anderen hinzuf�gen
((DefaultCluster) result.getClusterAt(getClusterId(a, result))).addObject(b);
} else if (containsId(uid, result) && containsId(vid, result)) {//also wenn beide bereits drin sind UND sie sich in verschiedenen Clustern befinden
if(getClusterId(uid, result) != getClusterId(vid, result)) {
//beide Cluster mergen!
DefaultCluster uCluster = (DefaultCluster)result.getClusterAt(getClusterId(uid, result));
DefaultCluster vCluster = (DefaultCluster)result.getClusterAt(getClusterId(vid, result));
String tempId;
Iterator<String> it = vCluster.getObjects();
while(it.hasNext()) {
tempId = it.next();
//vCluster.removeObject(tempId);
uCluster.addObject(tempId);
}
result.removeCluster(vCluster);
resetClusterIds(result);
clusterCount--; //weil es jetzt eines weniger gibt...
}
//TODO: Bei L�schen eines Clusters Bezeichnungen erneuern
//(die darin gef�hrte Nummererierung stimmt nicht mehr)
}
}
}
}
return result;
}
private void resetClusterIds(FlatClusterModel cm) {
for(int i = 0; i < cm.getNumberOfClusters(); i++) {
//TODO: resetClusterIds(FlatClusterModel cm)
//Die Klasse Cluster bietet keine M�glichkeit im Nachhinein die Bezeichner zu �ndern.
}
}
private int getClusterId(String id, FlatClusterModel cm) {
for(int i = 0; i < cm.getNumberOfClusters(); i++) {
if(cm.getClusterAt(i).contains(id))
return i;
}
return 0;
}
private boolean containsId(String id, FlatClusterModel cm) {
for(int i = 0; i < cm.getNumberOfClusters(); i++) {
if(cm.getClusterAt(i).contains(id))
return true;
}
return false;
}
public Class[] getInputClasses() {
return new Class[] { ExampleSet.class, ClusterModel.class };
}
}