public code v1
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>flintstones.group</groupId>
|
||||
<artifactId>flintstones.bundles</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>flintstones.clustering.agglomerative</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
<name>[bundle] Aglomerative Clustering</name>
|
||||
<organization>
|
||||
<name>Sinbad2</name>
|
||||
</organization>
|
||||
</project>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>flintstones.clustering.agglomerative</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
<filteredResources>
|
||||
<filter>
|
||||
<id>1779484362535</id>
|
||||
<name></name>
|
||||
<type>30</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.core.resources.regexFilterMatcher</id>
|
||||
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
</filteredResources>
|
||||
</projectDescription>
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@@ -0,0 +1,7 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
||||
@@ -0,0 +1,4 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
||||
@@ -0,0 +1,12 @@
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Aglomerative Clustering
|
||||
Bundle-SymbolicName: flintstones.clustering.agglomerative
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: Sinbad2
|
||||
Automatic-Module-Name: flintstones.clustering.aglomerative
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Export-Package: flintstones.clustering.agglomerative,
|
||||
flintstones.clustering.agglomerative.exception,
|
||||
flintstones.clustering.agglomerative.function
|
||||
Require-Bundle: flintstones.entity.problemelement
|
||||
@@ -0,0 +1,4 @@
|
||||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
package flintstones.clustering.agglomerative;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* The Cluster class will contain a set of values and elements belonging to the cluster, along with the
|
||||
* parents of that cluster (or null if none) and the distance between parents (0 if none).
|
||||
*/
|
||||
public class AgglomerativeCluster implements Comparable<AgglomerativeCluster> {
|
||||
private double[] values;
|
||||
private Object[] elements;
|
||||
/**
|
||||
* An array containing the parent clusters.
|
||||
*/
|
||||
private AgglomerativeCluster[] parents;
|
||||
private double distance;
|
||||
|
||||
public AgglomerativeCluster(double values, Object elements, AgglomerativeCluster[] parents, double distance) {
|
||||
this.values = new double[]{values};
|
||||
this.elements = new Object[] {elements};
|
||||
this.parents = parents;
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
public AgglomerativeCluster(double[] values, Object[] elements, AgglomerativeCluster[] parents, double distance) {
|
||||
this.values = values;
|
||||
this.elements = elements;
|
||||
this.parents = parents;
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Cluster{" +
|
||||
"values=" + Arrays.toString(values) +
|
||||
"elements=" + Arrays.toString(elements) +
|
||||
//", parents=" + Arrays.toString(parents) +
|
||||
//", distance=" + distance +
|
||||
'}';
|
||||
}
|
||||
|
||||
public double[] getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public void setValues(double values[]) {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public Object[] getElements() {
|
||||
return elements;
|
||||
}
|
||||
|
||||
public void setElements(Object elements[]) {
|
||||
this.elements = elements;
|
||||
}
|
||||
|
||||
public AgglomerativeCluster[] getParents() {
|
||||
return parents;
|
||||
}
|
||||
|
||||
public void setParents(AgglomerativeCluster[] parents) {
|
||||
this.parents = parents;
|
||||
}
|
||||
|
||||
public double getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public void setDistance(double distance) {
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given two clusters, merge the values into a new one. Also sets
|
||||
* the new cluster parents and distance between parents.
|
||||
* @param c1 the first cluster we want to merge
|
||||
* @param c2 the second cluster we want to merge
|
||||
* @param distance the distance between the two clusters we want to merge
|
||||
* @return the new cluster
|
||||
*/
|
||||
public static AgglomerativeCluster mergeClusters(AgglomerativeCluster c1, AgglomerativeCluster c2, double distance) {
|
||||
int length = c1.getValues().length + c2.getValues().length;
|
||||
|
||||
double[] combinedArray = new double[length];
|
||||
System.arraycopy(c1.getValues(), 0, combinedArray, 0, c1.getValues().length);
|
||||
System.arraycopy(c2.getValues(), 0, combinedArray, c1.getValues().length, c2.getValues().length);
|
||||
|
||||
Object[] combinedElementsArray = new Object[length];
|
||||
System.arraycopy(c1.getElements(), 0, combinedElementsArray, 0, c1.getValues().length);
|
||||
System.arraycopy(c2.getElements(), 0, combinedElementsArray, c1.getValues().length, c2.getValues().length);
|
||||
|
||||
//Order values and elements
|
||||
boolean swapped = true;
|
||||
int j = 0;
|
||||
double tmpValue;
|
||||
Object tmpElement;
|
||||
while (swapped) {
|
||||
swapped = false;
|
||||
j++;
|
||||
for (int i = 0; i < combinedArray.length - j; i++) {
|
||||
if (combinedArray[i] > combinedArray[i + 1]) {
|
||||
tmpValue = combinedArray[i];
|
||||
combinedArray[i] = combinedArray[i + 1];
|
||||
combinedArray[i + 1] = tmpValue;
|
||||
|
||||
tmpElement = combinedElementsArray[i];
|
||||
combinedElementsArray[i] = combinedElementsArray[i + 1];
|
||||
combinedElementsArray[i + 1] = tmpElement;
|
||||
|
||||
swapped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new AgglomerativeCluster(combinedArray, combinedElementsArray, new AgglomerativeCluster[]{c1, c2}, distance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(AgglomerativeCluster o) {
|
||||
return Double.valueOf(this.values[0]).compareTo(o.getValues()[0]);
|
||||
}
|
||||
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
package flintstones.clustering.agglomerative;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import flintstones.clustering.agglomerative.exception.InvalidClusterException;
|
||||
|
||||
public class AgglomerativeClustering {
|
||||
|
||||
private AgglomerativeClustering() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an agglomeration given an array of doubles
|
||||
* @param clusters array containing the clusters
|
||||
* @param clustersAmount amount of clusters we want to end up with
|
||||
* @param linkageCriterion the criteria that will be used to perform the agglomeration of two clusters
|
||||
* @return a list of agglomerated clusters
|
||||
* @throws InvalidClusterException if the clusters array are empty
|
||||
*/
|
||||
public static List<AgglomerativeCluster> process(Double[] clusters, Object[] elements, int clustersAmount, LinkageCriterion linkageCriterion) throws InvalidClusterException {
|
||||
|
||||
if (clusters == null) {
|
||||
throw new NullPointerException("Clusters were null");
|
||||
}
|
||||
|
||||
List<AgglomerativeCluster> tempClusters = new ArrayList<>();
|
||||
int e = 0;
|
||||
for (double cluster : clusters) {
|
||||
tempClusters.add(new AgglomerativeCluster(cluster, elements[e], null, 0));
|
||||
e++;
|
||||
}
|
||||
|
||||
return process(tempClusters, clustersAmount, linkageCriterion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an agglomeration given an list of Cluster
|
||||
* @param agglomerativeClusters non-empty list containing Cluster objects
|
||||
* @param clustersAmount amount of clusters we want to end up with
|
||||
* @param linkageCriterion the criteria that will be used to perform the agglomeration of two clusters
|
||||
* @return a list of agglomerated clusters
|
||||
* @throws InvalidClusterException if the clusters array are empty
|
||||
*/
|
||||
public static List<AgglomerativeCluster> process(List<AgglomerativeCluster> agglomerativeClusters, int clustersAmount, LinkageCriterion linkageCriterion) throws InvalidClusterException {
|
||||
|
||||
if (agglomerativeClusters == null) {
|
||||
throw new NullPointerException("Clusters were null");
|
||||
} else if (agglomerativeClusters.isEmpty()) {
|
||||
throw new InvalidClusterException("Cluster values were less than 1");
|
||||
}
|
||||
|
||||
while (clustersAmount != agglomerativeClusters.size()) {
|
||||
AgglomerativeCluster newCluster = agglomerate(agglomerativeClusters, linkageCriterion);
|
||||
agglomerativeClusters.remove(newCluster.getParents()[0]);
|
||||
agglomerativeClusters.remove(newCluster.getParents()[1]);
|
||||
agglomerativeClusters.add(newCluster);
|
||||
}
|
||||
|
||||
Collections.sort(agglomerativeClusters);
|
||||
|
||||
return agglomerativeClusters;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will perform an agglomeration given a list of clusters
|
||||
* following the specified linkage criteria.
|
||||
* @param agglomerativeClusters the list of clusters
|
||||
* @param linkageCriterion the linkage criterion we want to use
|
||||
* @return a merged cluster
|
||||
*/
|
||||
private static AgglomerativeCluster agglomerate(List<AgglomerativeCluster> agglomerativeClusters, LinkageCriterion linkageCriterion) {
|
||||
double distance = Double.POSITIVE_INFINITY;
|
||||
|
||||
// To store the position in array of he closest pair.
|
||||
int[] closestPair = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE};
|
||||
|
||||
for (int i = 0; i < agglomerativeClusters.size(); i++) {
|
||||
for (int j = 0; j < agglomerativeClusters.size(); j++) {
|
||||
// Do not calculate distance if i == j. It means they're the same item and distance will be 0.
|
||||
if (j != i) {
|
||||
double tempDistance = linkageCriterion.calculate(agglomerativeClusters.get(i), agglomerativeClusters.get(j));
|
||||
if (tempDistance < distance) {
|
||||
distance = tempDistance;
|
||||
closestPair[0] = i;
|
||||
closestPair[1] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AgglomerativeCluster c1 = agglomerativeClusters.get(closestPair[0]);
|
||||
AgglomerativeCluster c2 = agglomerativeClusters.get(closestPair[1]);
|
||||
return AgglomerativeCluster.mergeClusters(c1, c2, distance);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package flintstones.clustering.agglomerative;
|
||||
|
||||
public interface LinkageCriterion {
|
||||
double calculate(AgglomerativeCluster c1, AgglomerativeCluster c2);
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package flintstones.clustering.agglomerative;
|
||||
|
||||
import flintstones.clustering.agglomerative.function.DistanceFunction;
|
||||
|
||||
public class SingleLinkageCriterion implements LinkageCriterion {
|
||||
private DistanceFunction distanceFunction = null;
|
||||
|
||||
public SingleLinkageCriterion(DistanceFunction distanceFunction) {
|
||||
this.distanceFunction = distanceFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given two clusters with 1 or more points, return the distance between the closest
|
||||
* from both clusters.
|
||||
* @param c1 The first cluster we are comparing
|
||||
* @param c2 The second cluster we are comparing
|
||||
* @return the minimum distance between two clusters
|
||||
*/
|
||||
@Override
|
||||
public double calculate(AgglomerativeCluster c1, AgglomerativeCluster c2) {
|
||||
double[] cluster1Values = c1.getValues();
|
||||
double[] cluster2Values = c2.getValues();
|
||||
double distance = Double.POSITIVE_INFINITY;
|
||||
for (int i = 0; i < cluster1Values.length; i++) {
|
||||
for (int j = 0; j < cluster2Values.length; j++) {
|
||||
double tempDistance = distanceFunction.calculate(cluster1Values[i], cluster2Values[j]);
|
||||
if (tempDistance < distance)
|
||||
distance = tempDistance;
|
||||
}
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package flintstones.clustering.agglomerative.exception;
|
||||
|
||||
/**
|
||||
* Exception to be throw if the values of the clusters are not valid.
|
||||
* For example: empty cluster.
|
||||
*/
|
||||
public class InvalidClusterException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public InvalidClusterException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package flintstones.clustering.agglomerative.function;
|
||||
|
||||
public interface DistanceFunction {
|
||||
double calculate(double value1, double value2);
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package flintstones.clustering.agglomerative.function;
|
||||
|
||||
public class EuclideanDistance implements DistanceFunction{
|
||||
|
||||
/**
|
||||
* Given two points, calculate a distance between them.
|
||||
* @param value1 the first value of the Euclidean distance formula
|
||||
* @param value2 the second value of the Euclidean distance formula
|
||||
* @return the distance between two points
|
||||
*/
|
||||
@Override
|
||||
public double calculate(double value1, double value2) {
|
||||
return Math.sqrt(Math.pow(value1 - value2, 2));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user