diff --git a/src/eva2/server/go/operators/cluster/ClusteringDensityBased.java b/src/eva2/server/go/operators/cluster/ClusteringDensityBased.java index 987b29c6..20a64317 100644 --- a/src/eva2/server/go/operators/cluster/ClusteringDensityBased.java +++ b/src/eva2/server/go/operators/cluster/ClusteringDensityBased.java @@ -146,7 +146,7 @@ public class ClusteringDensityBased implements InterfaceClustering, java.io.Seri } } - /** This method allows you to decied if two species converge. + /** This method allows you to decide if two species converge. * @param species1 The first species. * @param species2 The second species. * @return True if species converge, else False. diff --git a/src/eva2/server/go/operators/cluster/ClusteringHierarchical.java b/src/eva2/server/go/operators/cluster/ClusteringHierarchical.java new file mode 100644 index 00000000..31c168eb --- /dev/null +++ b/src/eva2/server/go/operators/cluster/ClusteringHierarchical.java @@ -0,0 +1,221 @@ +package eva2.server.go.operators.cluster; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Vector; + +import eva2.gui.BeanInspector; +import eva2.gui.GenericObjectEditor; +import eva2.server.go.individuals.AbstractEAIndividual; +import eva2.server.go.individuals.AbstractEAIndividualComparator; +import eva2.server.go.operators.distancemetric.InterfaceDistanceMetric; +import eva2.server.go.operators.distancemetric.PhenotypeMetric; +import eva2.server.go.populations.Population; + +/** + * Hierarchical clustering after Preuss et al., "Counteracting Genetic Drift and Disruptive Recombination + * in (mu+,lambda)-EA on Multimodal Fitness Landscapes", GECCO '05. + * + * A tree is produced by assigning each individual the closest individual with better fitness. + * Connections with a distance above a certain threshold are cut. After that, each interconnected subtree forms a cluster. + * In the paper, the threshold is deduced as 2*d_p for d_p: the mean distance in the population. + * + * @author mkron + * + */ +public class ClusteringHierarchical implements InterfaceClustering, Serializable { + + private InterfaceDistanceMetric metric = new PhenotypeMetric(); + private double absoluteDistThreshold = 0.5; + private boolean thresholdMultipleOfMeanDist = false; + private double meanDistFactor = 2.; // recommended setting + private double currentMeanDistance = -1.; + private int minimumGroupSize = 3; + + private int[] uplink; + private double[] uplinkDist; + private AbstractEAIndividualComparator comparator = new AbstractEAIndividualComparator(); + private Vector[] children; +// private boolean[] clustered; +// private boolean m_TestConvergingSpeciesOnBestOnly = true; + private boolean TRACE = true; + + public ClusteringHierarchical() { + } + + public ClusteringHierarchical(ClusteringHierarchical clusteringHierarchical) { + } + + public void hideHideable() { + setAdaptiveThreshold(isAdaptiveThreshold()); + } + + /** This method allows you to make a deep clone of + * the object + * @return the deep clone + */ + public Object clone() { + return (Object) new ClusteringHierarchical(this); + } + + public boolean belongsToSpecies(AbstractEAIndividual indy, + Population species) { + // TODO Auto-generated method stub + return false; + } + + public Population[] cluster(Population pop) { + if (pop.isEmpty()) return new Population[]{pop.cloneWithoutInds()}; + ArrayList sorted = pop.getSorted(comparator); + if (uplink==null || (uplink.length!=pop.size())) uplink = new int[pop.size()]; // parent index of all indys + if (uplinkDist==null || (uplinkDist.length!=pop.size())) uplinkDist = new double[pop.size()]; // parent distance for all indys + if (children==null || (children.length!=pop.size())) children = new Vector[pop.size()]; // list of children for all indies + else if (children.length==pop.size()) for (int i=0; i=1; i--) { // start with worst indies + // search for closest indy which is better + uplink[i]=-1; + uplinkDist[i] = -1; + for (int j=i-1; j>=0; j--) { // look at all which are better + // if the j-th indy is closer, reset the index + double curDist = metric.distance(sorted.get(i), sorted.get(j)); + if (uplinkDist[i]<0 || (curDist < uplinkDist[i])) { + uplink[i] = j; + uplinkDist[i] = curDist; + } + } + // the closest best for indy i is now known. connect them in the graph. + if (children[uplink[i]]==null) children[uplink[i]]=new Vector(); + children[uplink[i]].add(i); + } + + // now go through indies starting with best. + // Add all children which are closer than threshold and recursively their children to a cluster. + // Mark them as clustered and start with the next best unclustered. + int current = 0; // top indy is first + boolean[] clustered = new boolean[pop.size()]; + LinkedList allClusters = new LinkedList(); + while (current finalClusts = new ArrayList(allClusters.size()); + finalClusts.add(pop.cloneWithoutInds()); + for (Population clust : allClusters) { + if (clust.size() sorted, Population currentClust) { + if (children[current]!=null && (children[current].size()>0)) { + for (int i=0; i