Skip to content

Commit

Permalink
Clustering: added some convenience functions. (#15)
Browse files Browse the repository at this point in the history
* Clustering: support not assigning nodes to a cluster by using negative indices.

* Remove support for missing clusters.

* Corrected coding style.

* Further corrected code style.

* Minor improvements code style

Co-authored-by: Nees Jan van Eck <[email protected]>
  • Loading branch information
vtraag and neesjanvaneck authored Dec 7, 2020
1 parent 15370fd commit 42fdd9e
Showing 1 changed file with 106 additions and 16 deletions.
122 changes: 106 additions & 16 deletions src/main/java/nl/cwts/networkanalysis/Clustering.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,8 @@ public static Clustering load(String filename) throws ClassNotFoundException, IO
ObjectInputStream objectInputStream;

objectInputStream = new ObjectInputStream(new FileInputStream(filename));

clustering = (Clustering)objectInputStream.readObject();

objectInputStream.close();

return clustering;
}

Expand Down Expand Up @@ -125,9 +122,7 @@ public void save(String filename) throws IOException
ObjectOutputStream objectOutputStream;

objectOutputStream = new ObjectOutputStream(new FileOutputStream(filename));

objectOutputStream.writeObject(this);

objectOutputStream.close();
}

Expand All @@ -152,6 +147,49 @@ public int getNClusters()
}

/**
* Returns whether cluster is empty or not.
*
* @return Cluster is empty for each cluster
*/
public boolean[] getClusterIsNotEmpty()
{
boolean[] clusterIsNotEmpty;
int c, i;

clusterIsNotEmpty = new boolean[nClusters];
for (i = 0; i < nNodes; i++)
{
c = clusters[i];
if (!clusterIsNotEmpty[c])
clusterIsNotEmpty[c] = true;
}
return clusterIsNotEmpty;
}

/**
* @return Number of non-empty clusters.
* @see #getClusterIsNotEmpty()
*/
public int getNNonEmptyClusters()
{
boolean[] clusterIsNotEmpty;
int c, i, nNonEmptyClusters;

clusterIsNotEmpty = new boolean[nClusters];
nNonEmptyClusters = 0;
for (i = 0; i < nNodes; i++)
{
c = clusters[i];
if (!clusterIsNotEmpty[c])
{
clusterIsNotEmpty[c] = true;
nNonEmptyClusters += 1;
}
}
return nNonEmptyClusters;
}

/**
* Returns the cluster of each node.
*
* @return Cluster of each node
Expand Down Expand Up @@ -250,17 +288,41 @@ public void initSingletonClusters()
*/
public void removeEmptyClusters()
{
boolean[] nonEmptyClusters;
removeEmptyClustersLargerThan(0);
}

/**
* Removes empty clusters and relabels clusters to follow consecutive
* numbering only for clusters larger than the specified minimum number of
* clusters.
*
* <p>
* Each empty cluster larger that {@code minimumCluster} is reassigned to
* the lowest available cluster, in the order of the existing clusters. For
* example, if {@code minimumCluster = 5} and cluster 2 and 7 are empty,
* then cluster 8 is relabeled to 7 (and 9 to 8, etc...), but clusters 0-4
* remain as they are.
* </p>
*
* @param minimumCluster Minimum cluster to start relabeling from.
*/
public void removeEmptyClustersLargerThan(int minimumCluster)
{
boolean[] clusterIsNotEmpty;
int i, j;
int[] newClusters;

nonEmptyClusters = new boolean[nClusters];
clusterIsNotEmpty = getClusterIsNotEmpty();

// Do not relabel until minimumCluster
newClusters = new int[nClusters];
for (i = 0; i < nNodes; i++)
nonEmptyClusters[clusters[i]] = true;
i = 0;
for (j = 0; j < nClusters; j++)
if (nonEmptyClusters[j])
for (j = 0; j < minimumCluster; j++)
newClusters[j] = j;

// Relabel starting from minimumCluster
i = j;
for ( ; j < nClusters; j++)
if (clusterIsNotEmpty[j])
{
newClusters[j] = i;
i++;
Expand All @@ -270,6 +332,36 @@ public void removeEmptyClusters()
clusters[i] = newClusters[clusters[i]];
}

/**
* Determine the total node weight of all nodes per cluster.
*
* @param network Network with node weights.
* @return Total node weight per cluster.
* @see #getClusterWeights(double[] nodeWeight)
*/
public double[] getClusterWeights(Network network)
{
return getClusterWeights(network.nodeWeights);
}

/**
* Determine the total node weight of all nodes per cluster.
*
* @param nodeWeights Array of node weights.
* @return Total node weight per cluster.
*/
public double[] getClusterWeights(double[] nodeWeights)
{
double[] clusterWeight;
int i;

clusterWeight = new double[nClusters];
for (i = 0; i < nNodes; i++)
clusterWeight[this.clusters[i]] += nodeWeights[i];

return clusterWeight;
}

/**
* Orders the clusters in decreasing order of their number of nodes.
*
Expand All @@ -296,7 +388,6 @@ public void orderClustersByWeight(double[] nodeWeights)
{
class Cluster implements Comparable<Cluster>
{

int cluster;
double weight;

Expand All @@ -317,9 +408,8 @@ public int compareTo(Cluster cluster)
int i;
int[] newClusters;

clusterWeights = new double[nClusters];
for (i = 0; i < nNodes; i++)
clusterWeights[this.clusters[i]] += nodeWeights[i];
clusterWeights = getClusterWeights(nodeWeights);

clusters = new Cluster[nClusters];
for (i = 0; i < nClusters; i++)
clusters[i] = new Cluster(i, clusterWeights[i]);
Expand Down

0 comments on commit 42fdd9e

Please sign in to comment.