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

import it.cnr.iasi.giant.frame.MCLInitFrame;
import it.cnr.iasi.giant.io.IOWriter;
import it.cnr.iasi.giant.util.Helper;
import java.util.ArrayList;
import java.util.HashMap;
import net.sf.javaml.clustering.mcl.MarkovClustering;
import net.sf.javaml.clustering.mcl.SparseMatrix;

/**
 *
 * @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 MCLThread extends Thread {
        
    @Override
    public void run() {
        SparseMatrix matrix = new SparseMatrix(NetworkLoaderThread.getAdjMatrix());
        matrix = matrix.transpose();
        double maxResidual = 0.001;
        double gammaExp = 2.0;
        double loopGain = 0.;
        double zeroMax = 0.001;
        MarkovClustering mcl = new MarkovClustering();
        
        MCLInitFrame.appendInConsole("MCL: starting MCL algorithm at " + Helper.getCurrentTime());
        MCLInitFrame.appendInConsole("---------------------------------------------------------");
        MCLInitFrame.appendInConsole("MCL: computing...");
        
        matrix = mcl.run(matrix, maxResidual, gammaExp, loopGain, zeroMax);
        
        HashMap<Integer, ArrayList<String>> clusters = new HashMap<Integer, ArrayList<String>>();
        
        //print(matrix, "result");
        
        //each row I is a cluster; if column J value not equals to 0 => the node J is in the cluster I
        
        matrix = matrix.transpose();
        double[][] dense = matrix.getDense();
        int count = 0;
        /*for (int i=0; i<matrix.getSize()[0]; i++) {
            ArrayList<String> tmp = new ArrayList<String>();
            for (int j=0; j<matrix.getSize()[1]; j++) {
                if (matrix.get(i, j)>0.0)
                    tmp.add(NetworkLoaderThread.getNodesMap().get(j));
            }
            if (tmp.size()>0) {
                clusters.put(count, tmp);
                count++;
            }
        }*/
        //int countDoubleNodes = 0;
        ArrayList<String> alreadyClustered = new ArrayList<String>();
        for (int i=0; i<dense.length; i++) {
            ArrayList<String> tmp = new ArrayList<String>();
            for (int j=0; j<dense[0].length; j++) {
                if (dense[i][j]>0.0) {
                    String node = NetworkLoaderThread.getNodesMap().get(j);
                    if (!alreadyClustered.contains(node)) {
                        tmp.add(node);
                        alreadyClustered.add(node);
                    }
                    /*else {
                        countDoubleNodes++;
                    }*/
                }
            }
            if (tmp.size()>0) {
                clusters.put(count, tmp);
                count++;
            }
        }
        //System.err.println("DUPLICATI: " + countDoubleNodes);
        
        IOWriter writer = new IOWriter();
        String filePath = writer.writeTmpClusterFile(clusters);
        
        if (!clusters.isEmpty() && !filePath.equals("NULL")) {
            ClusterLoaderThread.setClusterFileName("MCL-POWERED");
            ClusterLoaderThread.setClusterFilePath(filePath);
            ClusterLoaderThread.setClusters(clusters);
            
            MCLInitFrame.appendInConsole("MCL: completed at " + Helper.getCurrentTime());
            MCLInitFrame.appendInConsole("CLUSTERS: " + clusters.size());
            for (int t=0; t<clusters.size(); t++)
                MCLInitFrame.appendInConsole("cluster " + (t+1) + "  -  size: " + clusters.get(t).size());
            MCLInitFrame.appendInConsole("---------------------------------------------------------");
        }
        else {
            MCLInitFrame.appendInConsole("INTERNAL ERROR: please retry...");
            MCLInitFrame.appendInConsole("---------------------------------------------------------");
        }
    }
    
}
