Is there any way to reduce total execution time for the function `getSilhouetteIndex`

? P.S. I am using `weka SimpleKMeans`

for getting kmeans and `ceval`

.

`private double getSilhouetteIndex(List<ITSPoI> _POIs, SimpleKMeans kmeans, ClusterEvaluation ceval) { double si_index = 0; double[] ca = ceval.getClusterAssignments(); double[] d_arr = new double[ca.length]; List<Double> si_indexes = new ArrayList<Double>(); for (int i=0; i<ca.length; i++) { // STEP 1. Compute the average distance between the i-th PoI and all other points of a given cluster double a = averageDist(_POIs,ca,i,1); // STEP 2. Compute the average distance between the i-th PoI and all PoIs of other clusters for (int j=0; j<ca.length; j++) { double d = averageDist(_POIs,ca,j,2); d_arr[j] = d; } // STEP 3. Compute the the distance from the i-th PoI to its nearest cluster to which it does not belong double b = d_arr[0]; for (Double _d : d_arr) { if (_d < b) b = _d; } // STEP 4. Compute the Silhouette index for the i-th PoI double si = (b - a)/Math.max(a,b); si_indexes.add(si); } // STEP 5. Compute the average index over all observations double sum = 0; for(Double _si : si_indexes) { sum += _si; } si_index = sum/si_indexes.size(); return si_index; } private double averageDist(List<ITSPoI> _POIs, double[] ca, int id, int calc) { double avgDist = 0; List<ITSPoI> clusterPOIs = new ArrayList<ITSPoI>(); // Distances inside the cluster if (calc == 1) { for (int i = 0; i<ca.length; i++) { if (ca[i] == ca[id]) clusterPOIs.add(_POIs.get(i)); } } // Distances outside the cluster else { for (int i = 0; i<ca.length; i++) { if (ca[i] != ca[id]) clusterPOIs.add(_POIs.get(i)); } } double latx, lonx, laty, lony; double[] dist = new double[clusterPOIs.size()]; latx = _POIs.get(id).getLat(); lonx = _POIs.get(id).getLon(); for (int i=0; i<clusterPOIs.size(); i++) { laty = clusterPOIs.get(i).getLat(); lony = clusterPOIs.get(i).getLon(); dist[i] = distanceGeo(latx,lonx,laty,lony); } double sum = 0; for(Double d : dist) { sum += d; } avgDist = sum/dist.length; return avgDist; } private double distanceGeo(double lat1, double lon1, double lat2, double lon2) { if (lat1 == lat2 && lon1 == lon2) { return 0; } else { double theta = lon1 - lon2; double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta)); dist = Math.acos(dist); dist = rad2deg(dist); dist = dist * 60 * 1.1515; dist = dist * 1.609344; return dist; } } `