package edu.claflin.finder.algo.clustering;

import static edu.claflin.finder.Global.getLogger;

import java.util.ArrayList;

import edu.claflin.finder.algo.ArgumentsBundle;
import edu.claflin.finder.algo.clustering.struct.leading_eigenvector_struct.LeadingEigenvectorCaller;
import edu.claflin.finder.log.LogLevel;
import edu.claflin.finder.logic.Graph;

/**
 * Leading Eigenvector Algorithm for Community Detection, following Mark Newman's "Finding community structure in networks
 * using the eigenvectors of matrices".
 * Uses JAMA to calculate leading eigenvectors and eigenvalues.
 * 
 * For more information see "Finding community structure in networks using the eigenvectors of matrices" by Mark Newman
 * 
 * There are also detailed comments and descriptions in:
 * 	edu.claflin.finder.algo.clustering.struct.leading_eigenvector_struct.LeadingEigenvectorAlgorithm.java
 * 
 * @author Samuel Perez
 *
 */
public class LeadingEigenvector extends ClusteringAlgorithm
{

	public LeadingEigenvector(ArgumentsBundle args)
	{
		super(args);

		if (getLogger() != null)
		{
			getLogger().logInfo(LogLevel.DEBUG, "Community detection with the leading eigenvector algorithm initialized..");
		}

	}

	@Override
	public String toString()
	{
		return "Leading Eigenvector Algorithm";
	}

	/**
	 * Performs community detection using Mark Newman's Leading Eigenvector algorithm
	 * on a given Graph object, returning the clustering the highest approximated modularity.
	 *
	 * @param graph the Graph on which community detection will be performed
	 * @return the list of Graphs representing the clustering with the highest
	 *         approximated modularity
	 */
	@Override
	public ArrayList<Graph> process(Graph graph)
	{
		if (getLogger() != null)
		{
			getLogger().logAlgo(LogLevel.NORMAL,
					"Leading Eigenvector: Searching Graph: " + graph.getName() + "\nRunning Algorithm");
		}

		if (graph.getNodeCount() <= 1)
		{
			return new ArrayList<Graph>();
		}

		LeadingEigenvectorCaller leigen = new LeadingEigenvectorCaller(graph);

		if (getLogger() != null)
		{
			getLogger().logAlgo(LogLevel.NORMAL,
					"Leading Eigenvector: Algorithm done. Getting Clustering with Maximum Modularity");
		}
		
		Communities communities = new Communities(leigen.getCommunities(), graph, isWeighted());
		
		ArrayList<Graph> result = new ArrayList<>();

		if (communities != null)
		{
			result = this.buildCommunityGraphs(communities.getList(), graph, "Leading Eigenvector");
		}

		return cull(result);
	}

}