public ArrayList<Integer> cluster(){

        int number_of_clusters = 3;//(int)Math.ceil(this.p.len/4);
        int its = 100;

        Dataset data = new DefaultDataset();
        data.addAll(Arrays.asList(instances));
        Dataset[] best_clusters = null;
        double best_score = 999999999999.0;

        for (int niter=0; niter<5; niter++) {

            Clusterer km = new KMeans(number_of_clusters, its);
                  //  new CosineSimilarity());
            System.out.println("Clustering...");
            Dataset[] clusters = km.cluster(data);
            System.out.println("End Clustering");

            ClusterEvaluation sse = new SumOfSquaredErrors();
            double score = sse.score(clusters);
            System.out.println("Score = "+score);
            System.out.println("");

            if (score<best_score){
                best_score = score;
                best_clusters = clusters;
            }

        }

        ArrayList<Integer> fpages = new ArrayList<Integer>();
        ArrayList<Double> averages = new ArrayList<Double>();

        System.out.println("Running Clustering with:");
        System.out.println("Number of clusters = "+number_of_clusters);
        System.out.println("Iterations = "+its);
        System.out.println("Distance Measure = Cosine Similarity");
        System.out.println("Best Score = "+best_score);
        System.out.println("");

        System.out.println("Clusters found: " + best_clusters.length);

        for (int i=0;i<number_of_clusters;i++){

            System.out.println("");
            System.out.println("");
            System.out.println(" ========== Cluster #"+(i+1)+" size: "
                    +best_clusters[i].size()+" ========== ");
            System.out.println("");
            double tot = 0;
            for (int j=0;j<best_clusters[i].size();j++) {
                Integer page = (Integer)best_clusters[i].get(j).classValue();
                int key = p.pagenumbers.indexOf(page);
                tot += p.percent_color.get(key);
                System.out.print((page+1)+" ");
            }
            double aver = tot/best_clusters[i].size();
            System.out.println("\nAverage = "+aver);
            averages.add(aver);
        }

        // Selecting the most suitabble pages from the clusters found
        int target = (int)(p.pagenumbers.size()*saving);
        int tot = 0;

        while (tot < target){
            int select = max_douArrayList(averages);
            int projection = Math.abs(target - tot + best_clusters[select].size());
            if (( projection > (target - tot)) && (tot > 0))
                break;
            for (int i=0; i<best_clusters[select].size(); i++){
                fpages.add((Integer)best_clusters[select].get(i).classValue());
                tot += 1;
            }
            averages.set(select, -1.0);
        }

        return fpages;

    }