public static double getSilhouette(Dataset trainingSet, ArrayList<ArrayList<Integer>> clusters, double[][] distance, int VERBOSE) {
		int logFlag = Constants.LOG_SILHOUETTE;
		/** initial phase **/
		// build an inverted index of cluster assg, i.e., clusterAssignment[objectNo] = clusterId;
		int[] clusterAssignment = new int[trainingSet.size()];
		for (int i=0; i<clusters.size(); i++) {
			for (int j=0; j<clusters.get(i).size(); j++){
				clusterAssignment[clusters.get(i).get(j)] = i;	
			}			
		}
	
		
		/** compute silhouette(i) **/
		//ArrayList<Double> silh = new ArrayList<Double> ();
		double sumSilh = 0.0;
		for (int i=0; i<trainingSet.size(); i++) {
			// compute a(i)
			double ai = (sumRowAgainstColumn(distance, i, clusters.get(clusterAssignment[i])) + 0.0)/ (clusters.get(clusterAssignment[i]).size() + 0.0);
			Util.logPrintln(VERBOSE, logFlag, "item "+i+", ai:"+ai+", clusterId: "+clusterAssignment[i]+", fellow-cluster: "+ clusters.get(clusterAssignment[i]));
			
			// compute b(i)
			// average dissimilarity with other clusters
			double minBi = Double.MAX_VALUE;
			for (int j=0; j<clusters.size(); j++) {
				if (j!=clusterAssignment[i]) {
					double bis = (sumRowAgainstColumn(distance, i, clusters.get(j)) + 0.0 ) / clusters.get(j).size();
					if ( bis < minBi ) minBi = bis; 
				}
			}
			
			Double maxAiBi = Math.max(ai, minBi);
			double silh = ( (minBi - ai) / maxAiBi);
			sumSilh += silh;
			Util.logPrintln(VERBOSE, logFlag, ai+","+minBi + ", " + (minBi - ai) +"," + silh);
						
		}
		
		double silhouette = sumSilh / trainingSet.size();
		Util.logPrintln(VERBOSE, logFlag, "silhouette: "+silhouette);
		return silhouette;
		
	}