package DDMT.Nodes;
/*
 * P2PKmeans.java
 *
 * Created on 21:09, August 4th, 2004
 */

/** Main function of P2P K-means algorithm.
 * @author Kun Liu
 * @version 1.1
 */

import java.lang.*;
import java.io.*;
import java.math.*;
import java.util.*;

public class Kmeans
{
    DataSite centralData;
    public int dimension;
    public Kmeans(int numClusters,String DataFileName, int d)
    {
        this.dimension = d;
        boolean notDone = true;
        double gamma = 0.1;
        centralData = new DataSite(numClusters, gamma, DataFileName);
        
        DataPoint [] initialCentroids = new DataPoint[numClusters];
        double [] temp = new double[this.dimension];
        Vector centroids = new Vector();
        
        Random rand = new Random();
        rand.setSeed(1000);
        do
        {
            System.out.println("In K-means");
            
            for (int i=0;i<numClusters;i++)
            {
            	for (int j=0;j<this.dimension;j++)
              	   temp[j] = 2.0*rand.nextDouble()-1.0;
              
                initialCentroids[i] = new DataPoint(temp);
            }
            
            centralData.setCentroidsV(initialCentroids);
            centralData.simpleKmeans();

            centroids = centralData.getCentroids();

            int here = 0;
            for (int i=0;i<numClusters;i++)
            {
                if (centralData.numPointsPerCluster[i]==0)
                {
                    here = 1;
                    break;
                }
            }

            if (here==1)
                notDone = true;
            else
                notDone = false;
                                   
            centralData.printClusters();
        }
        while(notDone);
        this.WriteFile("c:\\ReferenceCentroids.txt", this.MakeString(centroids));
        
    }
    
    public Kmeans(int numClusters,Vector PointList, double gamma,int TimeStamp, int d)
    {
        this.dimension = d;
        boolean notDone = true;
        ArrayList Alist = new ArrayList();
        Vector centroids = new Vector();
        
        for (int i=0;i<PointList.size();i++)
        {
            Point dp = (Point)PointList.elementAt(i);
            DataPoint p = new DataPoint(this.dimension);
            for (int j=0;j<this.dimension;j++)
                p.DataArray[j] = dp.x[j];
            
            p.membership =   dp.membership;
            Alist.add(p);
        }
        centralData = new DataSite(numClusters, gamma, Alist);

        DataPoint [] initialCentroids = new DataPoint[numClusters];
        double [] temp = new double[this.dimension];
        
        Random rand = new Random();
        rand.setSeed(1000);
        do
        {
//            System.out.println("In K-means");
            
            for (int i=0;i<numClusters;i++)
            {
            	for (int j=0;j<this.dimension;j++)
              	   temp[j] = 2.0*rand.nextDouble()-1.0;
              
                initialCentroids[i] = new DataPoint(temp);
            }
            
            centralData.setCentroidsV(initialCentroids);
            centralData.simpleKmeans();

            centroids = centralData.getCentroids();

            int here = 0;
            for (int i=0;i<numClusters;i++)
            {
                if (centralData.numPointsPerCluster[i]==0)
                {
                    here = 1;
                    break;
                }
            }

            if (here==1)
                notDone = true;
            else
                notDone = false;
                                  
            centralData.printClusters();
        }
        while(notDone);
        this.WriteFile("c:\\centroids.txt", this.MakeString(centroids));
        
    }
    
    public Vector ReturnData()
    {
        return centralData.getDataPoint();
    }
    
    public Vector ReturnCentroids()
    {
        return centralData.getCentroids();
    }
    
    public String MakeString(Vector Pts)
    {
        String Data = "";
        Pts = this.SortCentroids(Pts);
        for (int i=0;i<Pts.size();i++)
        {
            Point dp = (Point)Pts.elementAt(i);
            for (int j=0;j<this.dimension;j++)
                Data = Data.concat(Double.toString(dp.x[j])+"\t");
            Data = Data.concat(Integer.toString(dp.membership)+"\n");
        }
        return Data;
    }
    
    public static void WriteFile(String filename,String fileData)
    {
	try 
	{
            BufferedWriter out = new BufferedWriter(new FileWriter(filename));
                    
            out.write(fileData);
            out.close();
        }
	catch (IOException e) 
	{
		System.out.println("Writing exception");
        }
    }
    
    public Vector SortCentroids(Vector Centroids)
    {
     //   AppendFile("c:\\Tempori.txt",this.MakeString(Data));
        // sort by x
        for (int i=0;i<Centroids.size();i++)
        {
            int min = i;
            for (int j=i+1;j<Centroids.size();j++)
            {
                Point a = (Point)Centroids.elementAt(min);
                Point b = (Point)Centroids.elementAt(j);
                if (b.x[0]<a.x[0])
                {
                    min = j;
                }
            }
            if (min!=i)
            {
             //   Point t = (Point)Data.elementAt(i);
            //    System.out.println(t.x+" -");
                //swap min and i
                Point temp = (Point)Centroids.elementAt(min);
            //    System.out.println(temp.x);
                Centroids.set(min, (Point)Centroids.elementAt(i));
                Centroids.set(i, temp);
            }
        }
     //   AppendFile("c:\\Tempnew.txt",this.MakeString(Data));
    //    System.exit(0);
        return Centroids;
    }
    
    public static void main (String [] args)
    {
        String FileName = "c:\\centralData.txt";
        int NumClusters = 1;
        int NumCentralPoints = 1000;
        double NoiseProb = 0.1;
        int dimension = 5;
        DataGen dg = new DataGen(dimension,NoiseProb,NumClusters,NumCentralPoints,FileName);
        Kmeans km = new Kmeans(NumClusters,FileName,dimension);
        System.out.println("Execution Complete");
       // this.WriteFile(filename
    }// main function
}
 // class

