/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package it.cnr.iasi.giant.util;

import java.util.ArrayList;
import java.util.HashMap;
import net.sf.javaml.clustering.evaluation.ClusterEvaluation;
import net.sf.javaml.clustering.evaluation.SumOfSquaredErrors;
import net.sf.javaml.core.Dataset;

/**
 *
 * @author Fabio Cumbo
 * @info GIANT
 * @version v1.0
 * @organization IASI-CNR : Istituto di Analisi dei Sistemi ed Informatica 
 *                  "Antonio Ruberti" - Consiglio Nazionale delle Ricerche
 * 
 */
public class ClusterValidation {
    
    public ClusterValidation() {}
    
    public double getSSE(Dataset[] clusters) {
        ClusterEvaluation sse= new SumOfSquaredErrors();
        return sse.score(clusters);
    }
    
    public double getValidation(HashMap<Integer, ArrayList<Integer>> clusters, int[][] distanceMatrix) {
        //double[][] meanMatrix = new double[distanceMatrix.length][distanceMatrix.length];
        double[][] localCentroids = new double[clusters.keySet().size()][distanceMatrix.length];
        double[] globalCentroid = new double[distanceMatrix.length];
        for (int clusterNum: clusters.keySet()) {
            ArrayList<Integer> cluster = clusters.get(clusterNum);
            for (int column=0; column<distanceMatrix.length; column++) {
                int sumColumn = 0;
                for (int clusterRow=0; clusterRow<cluster.size(); clusterRow++) {
                    sumColumn += distanceMatrix[clusterRow][column];
                }
                double sumColumnMean = sumColumn / cluster.size();
                /*for (int clusterRow=0; clusterRow<cluster.size(); clusterRow++) {
                    meanMatrix[clusterRow][column] = sumColumnMean;
                }*/
                localCentroids[clusterNum][column] = sumColumnMean;
            }
        }
        for (int distMatColumn=0; distMatColumn<distanceMatrix.length; distMatColumn++) {
            int sumMatrixCol = 0;
            for (int distMatRow=0; distMatRow<distanceMatrix.length; distMatRow++) {
                sumMatrixCol += distanceMatrix[distMatRow][distMatColumn];
            }
            globalCentroid[distMatColumn] = (sumMatrixCol / distanceMatrix.length);
        }
        
        double varianceClusterCentroid = 0;
        double varianceNetworkCentroid = 0;
        for (int k=0; k<clusters.keySet().size(); k++) {
            for (int i=0; i<clusters.get(k).size(); i++) {
                //varianceClusterCentroid += (euclideanDist(distanceMatrix[i], localCentroids[k])) / clusters.get(k).size();
                //varianceNetworkCentroid += (euclideanDist(localCentroids[k], globalCentroid)) / clusters.get(k).size();
                varianceClusterCentroid += (variance(distanceMatrix[i], localCentroids[k]));
                varianceNetworkCentroid += (variance(localCentroids[k], globalCentroid));
            }
        }
        
        return varianceClusterCentroid / varianceNetworkCentroid;
    }
    
    /*private double euclideanDist(double[] vector1, double[] vector2) {
        if(vector1.length != vector2.length){
            throw new NumberFormatException();
        }
        double result = 0;
        double d;
        for (int i = 0; i < vector1.length; i++) {
            d = (vector1[i] - vector2[i]);
            result += ( d * d ); //power of 2
        }
        return (float) Math.sqrt(result);
    }*/
    
    private double variance(int[] vector1, double[] vector2) {
        if(vector1.length != vector2.length){
            throw new NumberFormatException();
        }
        double result = 0;
        double d;
        for (int i = 0; i < vector1.length; i++) {
            d = (vector1[i] - vector2[i]);
            result += ( d * d ); //power of 2
        }
        return (result / vector1.length);
    }
    
    private double variance(double[] vector1, double[] vector2) {
        if(vector1.length != vector2.length){
            throw new NumberFormatException();
        }
        double result = 0;
        double d;
        for (int i = 0; i < vector1.length; i++) {
            d = (vector1[i] - vector2[i]);
            result += ( d * d ); //power of 2
        }
        return (result / vector1.length);
    }
    
}
