Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup #2

Merged
merged 7 commits into from
Nov 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ It requires 6 arguments in this order.
Example:

```bash
$ java −jar SACT−1.0−SNAPSHOT.jar ./exp1.csv ./res.csv 3 1 1 2
$ java −jar SACT−1.1−SNAPSHOT.jar ./exp1.csv ./res.csv 3 1 1 2
```

It will print the created clusters in the console as well as create a csv file with the clusters.
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>com.kkoutsilis</groupId>
<artifactId>SACT</artifactId>
<version>1.0-SNAPSHOT</version>
<version>1.1-SNAPSHOT</version>

<name>SACT</name>

Expand Down
31 changes: 19 additions & 12 deletions src/main/java/com/kkoutsilis/App.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package com.kkoutsilis;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.kkoutsilis.algorithms.ClusteringAlgorithm;
import com.kkoutsilis.algorithms.HCNN;
import com.kkoutsilis.graphs.Graph;
Expand All @@ -8,18 +14,18 @@
import com.kkoutsilis.utilities.CsvHandler;
import com.kkoutsilis.utilities.NearestNeighbour;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* @author kkoutsilis
*/
public class App {
public static void main(String[] args) throws Exception {
String inputFilePath = args[0];
String outputFilePath = args[1];
int k = Integer.parseInt(args[2]);
int fistNearestNeighbourAlgorithm = Integer.parseInt(args[3]);
int secondNearestNeighbourAlgorithm = Integer.parseInt(args[4]);
int n = Integer.parseInt(args[5]);
final Logger logger = Logger.getLogger(App.class.getName());
final String inputFilePath = args[0];
final String outputFilePath = args[1];
final int k = Integer.parseInt(args[2]);
final int fistNearestNeighbourAlgorithm = Integer.parseInt(args[3]);
final int secondNearestNeighbourAlgorithm = Integer.parseInt(args[4]);
final int n = Integer.parseInt(args[5]);

long startTime = System.nanoTime();

Expand Down Expand Up @@ -70,9 +76,10 @@ public static void main(String[] args) throws Exception {
s.forEach(v -> System.out.print(v.getLabel() + " "));
System.out.println();
}
System.out.println("Clustering execution time in milliseconds: " + elapsedTime / 1000000);
logger.log(Level.INFO,
() -> "Clustering execution time in milliseconds: " + elapsedTime / 1000000);

SilhouetteCoefficient quality = new SilhouetteCoefficient(result, graph);
System.out.printf("Silhouette Coefficient: %.03f", quality.calculate());
logger.log(Level.INFO, () -> String.format("Silhouette Coefficient: %.03f", quality.calculate()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import java.util.List;
import java.util.Set;

/**
* @author kkoutsilis
*/
public interface ClusteringAlgorithm {
List<Set<Vertex>> fit() throws Exception;
}
123 changes: 60 additions & 63 deletions src/main/java/com/kkoutsilis/algorithms/HCNN.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,23 @@
import com.kkoutsilis.utilities.Distance;

import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
* @author kkoutsilis
*/
public class HCNN implements ClusteringAlgorithm {
private Graph graph;
private List<Integer> indexes;
private List<Vertex> G;
private List<Vertex> data;
private int n;
private Map<Vertex, Set<Vertex>> fistNnAlgorithm;
private Map<Vertex, Set<Vertex>> secondNnAlgorithm;
private final Logger logger = Logger.getLogger(HCNN.class.getName());

public HCNN() {
}

public HCNN(Graph graph, int n, Map<Vertex, Set<Vertex>> fistNnAlgorithm, Map<Vertex, Set<Vertex>> secondNnAlgorithm) {
public HCNN(Graph graph, int n, Map<Vertex, Set<Vertex>> fistNnAlgorithm,
Map<Vertex, Set<Vertex>> secondNnAlgorithm) {
this.graph = graph;
this.n = n;
this.fistNnAlgorithm = fistNnAlgorithm;
Expand All @@ -32,76 +35,71 @@ public HCNN(Graph graph, int n, Map<Vertex, Set<Vertex>> fistNnAlgorithm, Map<Ve
for (int i = 0; i < this.graph.getVertices().size(); i++) {
this.indexes.add(i);
}
this.G = new ArrayList<>(this.graph.getVertices().keySet());
this.data = new ArrayList<>(this.graph.getVertices().keySet());
}

@Override
public List<Set<Vertex>> fit() throws Exception {
this.logger.log(Level.INFO, "Fitting...");
ClustersAndOutliers clustersAndOutliers = this.initializeClustering();
List<Set<Vertex>> C = clustersAndOutliers.getClusters();
Set<Vertex> D = clustersAndOutliers.getOutliers();
List<Set<Vertex>> clusters = clustersAndOutliers.getClusters();
Set<Vertex> outliers = clustersAndOutliers.getOutliers();

while (C.size() > this.n) {
int L = C.size();
// line 4
float tmax = 0;
for (int i = 0; i < L; i++) {
for (int j = i + 1; j < L; j++) {
float similarity = sim(C.get(i), C.get(j));
if (tmax < similarity) {
tmax = similarity;
while (clusters.size() > this.n) {
int l = clusters.size();
float tMax = 0;
for (int i = 0; i < l; i++) {
for (int j = i + 1; j < l; j++) {
float similarity = sim(clusters.get(i), clusters.get(j));
if (tMax < similarity) {
tMax = similarity;
}
}
}
// line 5
if (tmax == 0) {
if (tMax == 0) {
break;
}
// line 7
Set<MSP> msp = new LinkedHashSet<>();
for (int i = 0; i < L; i++) {
for (int j = i + 1; j < L; j++) {
float similarity = sim(C.get(i), C.get(j));
if (similarity == tmax) {
for (int i = 0; i < l; i++) {
for (int j = i + 1; j < l; j++) {
float similarity = sim(clusters.get(i), clusters.get(j));
if (similarity == tMax) {
msp.add(new MSP(i, j));
}
}
}
// line 8-10
DisjointSets DS = new DisjointSets();
for (Set<Vertex> vertices : C) {
DS.makeSet(vertices);
DisjointSets disjointSets = new DisjointSets();
for (Set<Vertex> vertices : clusters) {
disjointSets.makeSet(vertices);
}
// line 11-12
for (MSP msp1 : msp) {
int i = msp1.getI();
int j = msp1.getJ();
DS.union(C.get(i), C.get(j));
disjointSets.union(clusters.get(i), clusters.get(j));
}
// line 13-16
for (int i = 0; i < L; i++) {
int index = DS.findSet(C.get(i));
Set<Vertex> repr = DS.getRepresentative(index).getHead().getData();
if (repr != C.get(i)) {
repr.addAll(C.get(i));
C.set(i, Collections.emptySet());
for (int i = 0; i < l; i++) {
int index = disjointSets.findSet(clusters.get(i));
Set<Vertex> repr = disjointSets.getRepresentative(index).getHead().getData();
if (repr != clusters.get(i)) {
repr.addAll(clusters.get(i));
clusters.set(i, Collections.emptySet());
}
}
// line 17-20
List<Set<Vertex>> Ctemp = new ArrayList<>(C);
C = new ArrayList<>();
for (Set<Vertex> c : Ctemp) {
List<Set<Vertex>> tempClusters = new ArrayList<>(clusters);
clusters = new ArrayList<>();
for (Set<Vertex> c : tempClusters) {
if (!c.isEmpty()) {
C.add(c);
clusters.add(c);
}
}
}
C = assignOutliers(C, D);
clusters = assignOutliers(clusters, outliers);

return C;
return clusters;
}

private List<Set<Vertex>> assignOutliers(List<Set<Vertex>> clusters, Set<Vertex> outliers) {
this.logger.log(Level.INFO, "Assigning outliers...");
float[] label = new float[this.indexes.size() + 1];
Set<Vertex> loners = new HashSet<>();
for (int i = 0; i <= this.indexes.size(); i++) {
Expand Down Expand Up @@ -150,7 +148,7 @@ private List<Set<Vertex>> assignOutliers(List<Set<Vertex>> clusters, Set<Vertex>
}

private ClustersAndOutliers initializeClustering() {
// initializing
this.logger.log(Level.INFO, "Initializing clusters...");
int nOfIndexes = this.indexes.size();
CorePair[] corePairs = new CorePair[nOfIndexes];
int[] label = new int[nOfIndexes];
Expand All @@ -162,8 +160,7 @@ private ClustersAndOutliers initializeClustering() {
Set<Vertex> outliers = new LinkedHashSet<>();
float[][] structSimZ = new float[nOfIndexes][nOfIndexes];

// lines 2-7
for (Vertex i : this.G) {
for (Vertex i : this.data) {
Set<Vertex> Q = this.fistNnAlgorithm.get(i);
Set<Vertex> tmp = new HashSet<>(this.fistNnAlgorithm.get(i));
for (Vertex j : tmp) {
Expand All @@ -174,12 +171,11 @@ private ClustersAndOutliers initializeClustering() {
}
}

// line 8
List<PairSim> pairSims = new ArrayList<>();
for (int i = 0; i < nOfIndexes; i++) {
for (int j = i + 1; j < nOfIndexes; j++) {
Vertex vI = this.G.get(i);
Vertex vJ = this.G.get(j);
Vertex vI = this.data.get(i);
Vertex vJ = this.data.get(j);
float structSim = z(vI, vJ);
if (structSim > 0) {
pairSims.add(new PairSim(vI.getLabel(), vJ.getLabel(), structSim));
Expand All @@ -195,14 +191,14 @@ private ClustersAndOutliers initializeClustering() {
int j = pairSim.getJ() - 1;
if (label[i] == 0 && label[j] == 0) {
last += 1;
label[i] = label[j] = last;// Not sure about that, line 14
label[i] = label[j] = last;
corePairs[last] = new CorePair(i, j);
Vertex vI = this.G.get(i);
Vertex vJ = this.G.get(j);
Vertex vI = this.data.get(i);
Vertex vJ = this.data.get(j);
Set<Vertex> union = new LinkedHashSet<>(fistNnAlgorithm.get(vI));
union.addAll(this.fistNnAlgorithm.get(vJ));
for (Vertex u : union) {
int ui = this.G.indexOf(u); // wrong ??
int ui = this.data.indexOf(u);
if (label[ui] == 0) {
label[ui] = last;
}
Expand All @@ -211,14 +207,14 @@ private ClustersAndOutliers initializeClustering() {
int h = corePair.getI();
int k = corePair.getJ();

Vertex vuI = this.G.get(ui);
Vertex vuI = this.data.get(ui);
float max = z(vuI, vI);
float temp = z(vuI, vJ);
if (max < temp) {
max = temp;
}
Vertex vH = this.G.get(h);
Vertex vK = this.G.get(k);
Vertex vH = this.data.get(h);
Vertex vK = this.data.get(k);

float min = z(vuI, vH);
temp = z(vuI, vK);
Expand All @@ -234,21 +230,20 @@ private ClustersAndOutliers initializeClustering() {
}
}

// line 23-28
List<Set<Vertex>> clusters = new ArrayList<>();
for (int i : this.indexes) {
for (int i = 0; i <= this.indexes.size(); i++) {
clusters.add(new HashSet<>());
}
for (int i : this.indexes) {
Vertex vI = this.G.get(i);
Vertex vI = this.data.get(i);
if (label[i] > 0) {
clusters.get(label[i]).add(vI);
}
if (label[i] == 0) {
outliers.add(vI);
}
}
clusters.removeIf(Set::isEmpty); // Not the best but it works for now.
clusters.removeIf(Set::isEmpty); // Not the best but works for now.
return new ClustersAndOutliers(clusters, outliers);

}
Expand Down Expand Up @@ -292,6 +287,8 @@ private int link(Set<Vertex> clusterA, Set<Vertex> clusterB) {
}

private float sim(Set<Vertex> clusterA, Set<Vertex> clusterB) {
return ((float) conn(clusterA, clusterB) / (float) (clusterA.size() * clusterB.size())) * ((float) link(clusterA, clusterB) / (float) clusterA.size()) * ((float) link(clusterB, clusterA) / (float) clusterB.size());
return ((float) conn(clusterA, clusterB) / (float) (clusterA.size() * clusterB.size()))
* ((float) link(clusterA, clusterB) / (float) clusterA.size())
* ((float) link(clusterB, clusterA) / (float) clusterB.size());
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.kkoutsilis.algorithms.helpers;


import com.kkoutsilis.graphs.Vertex;

import java.util.List;
import java.util.Set;

/**
* @author kkoutsilis
*/
public class ClustersAndOutliers {
private List<Set<Vertex>> clusters;
private Set<Vertex> outliers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import java.util.Objects;

/**
* @author kkoutsilis
*/
public class CorePair {
private int i;
private int j;
Expand Down Expand Up @@ -38,8 +41,10 @@ public void setPair(int i, int j) {

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CorePair)) return false;
if (this == o)
return true;
if (!(o instanceof CorePair))
return false;
CorePair corePair = (CorePair) o;
return getI() == corePair.getI() && getJ() == corePair.getJ();
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/kkoutsilis/algorithms/helpers/MSP.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.kkoutsilis.algorithms.helpers;

/**
* @author kkoutsilis
*/
public class MSP {
private int i;
private int j;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import java.util.Objects;

/**
* @author kkoutsilis
*/
public class PairSim {
private int i;
private int j;
Expand Down Expand Up @@ -48,8 +51,10 @@ public void setPairSim(int i, int j, float similarity) {

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PairSim)) return false;
if (this == o)
return true;
if (!(o instanceof PairSim))
return false;
PairSim pairSim = (PairSim) o;
return getI() == pairSim.getI() && getJ() == pairSim.getJ() && getSimilarity() == pairSim.getSimilarity();
}
Expand Down
Loading