package i5.las2peer.services.ocd.algorithms;
import i5.las2peer.services.ocd.algorithms.utils.OcdAlgorithmException;
import i5.las2peer.services.ocd.graphs.Cover;
import i5.las2peer.services.ocd.graphs.CoverCreationLog;
import i5.las2peer.services.ocd.graphs.CoverCreationType;
import i5.las2peer.services.ocd.graphs.CustomGraph;
import i5.las2peer.services.ocd.graphs.GraphProcessor;
import i5.las2peer.services.ocd.metrics.ExecutionTime;
import i5.las2peer.services.ocd.utils.ExecutionStatus;
import i5.las2peer.services.ocd.utils.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.la4j.matrix.Matrix;
import org.la4j.matrix.sparse.CCSMatrix;
import y.base.Node;
/**
* Manages the execution of an OcdAlgorithm.
* @author Sebastian
*
*/
public class OcdAlgorithmExecutor {
/**
* Calculates a cover by executing an ocd algorithm on a graph.
* The algorithm is run on each weakly connected component seperately.
* Small components are automatically considered to be one community.
* @param graph The graph.
* @param algorithm The algorithm.
* @param componentNodeCountFilter Weakly connected components of a size
* lower than the filter will automatically be considered a single community.
* @return A cover of the graph calculated by the algorithm.
* @throws OcdAlgorithmException In case of an algorithm failure.
* @throws InterruptedException In case of an algorithm interrupt.
*/
public Cover execute(CustomGraph graph, OcdAlgorithm algorithm, int componentNodeCountFilter) throws OcdAlgorithmException, InterruptedException {
CustomGraph graphCopy = new CustomGraph(graph);
GraphProcessor processor = new GraphProcessor();
processor.makeCompatible(graphCopy, algorithm.compatibleGraphTypes());
if(algorithm.getAlgorithmType().toString().equalsIgnoreCase(CoverCreationType.WORD_CLUSTERING_REF_ALGORITHM.toString())||algorithm.getAlgorithmType().toString().equalsIgnoreCase(CoverCreationType.COST_FUNC_OPT_CLUSTERING_ALGORITHM.toString())){
ExecutionTime executionTime = new ExecutionTime();
Cover cover = algorithm.detectOverlappingCommunities(graph);
cover.setCreationMethod(new CoverCreationLog(algorithm.getAlgorithmType(), algorithm.getParameters(), algorithm.compatibleGraphTypes()));
cover.getCreationMethod().setStatus(ExecutionStatus.COMPLETED);
executionTime.setCoverExecutionTime(cover);
return cover;
}else{
List<Pair<CustomGraph, Map<Node, Node>>> components;
List<Pair<Cover, Map<Node, Node>>> componentCovers;
components = processor.divideIntoConnectedComponents(graphCopy);
ExecutionTime executionTime = new ExecutionTime();
componentCovers = calculateComponentCovers(components, algorithm, componentNodeCountFilter, executionTime);
Cover coverCopy = processor.mergeComponentCovers(graphCopy, componentCovers);
Cover cover = new Cover(graph, coverCopy.getMemberships());
cover.setCreationMethod(coverCopy.getCreationMethod());
cover.getCreationMethod().setStatus(ExecutionStatus.COMPLETED);
executionTime.setCoverExecutionTime(cover);
return cover;
}
}
/*
* Calculates the cover of each connected component.
* @param components The connected components each with a node mapping from the component nodes to the original graph nodes.
* @param algorithm The algorithm to calculate the covers with.
* @param componentNodeCountFilter Components of a size lower than the filter will automatically be considered a single community.
* @param executionTime The execution time metric corresponding the algorithm execution.
* @return The covers of the connected components each with a node mapping from the component nodes to the original graph nodes.
* @throws OcdAlgorithmException In case of an algorithm failure.
* @throws InterruptedException In case of an algorithm interrupt.
*/
private List<Pair<Cover, Map<Node, Node>>> calculateComponentCovers(List<Pair<CustomGraph, Map<Node, Node>>> components,
OcdAlgorithm algorithm, int componentNodeCountFilter, ExecutionTime executionTime) throws OcdAlgorithmException, InterruptedException {
List<Pair<Cover, Map<Node, Node>>> componentCovers = new ArrayList<Pair<Cover, Map<Node, Node>>>();
CustomGraph component;
Cover componentCover;
for(Pair<CustomGraph, Map<Node, Node>> pair : components) {
component = pair.getFirst();
if(component.nodeCount() < componentNodeCountFilter) {
componentCover = computeSingleCommunityCover(component, algorithm);
}
else {
executionTime.start();
componentCover = algorithm.detectOverlappingCommunities(component);
componentCover.setCreationMethod(new CoverCreationLog(algorithm.getAlgorithmType(), algorithm.getParameters(), algorithm.compatibleGraphTypes()));
componentCover.getCreationMethod().setStatus(ExecutionStatus.COMPLETED);
executionTime.stop();
}
componentCovers.add(new Pair<Cover, Map<Node, Node>>(componentCover, pair.getSecond()));
}
return componentCovers;
}
/*
* Calculates a cover consisting of a single community.
* @param graph The graph to create the cover for.
* @param algorithm The algorithm used for setting the log entry.
* @return The cover.
*/
private Cover computeSingleCommunityCover(CustomGraph graph, OcdAlgorithm algorithm) {
Matrix memberships = new CCSMatrix(graph.nodeCount(), 1);
memberships.assign(1);
Cover cover = new Cover (graph, memberships);
cover.setCreationMethod(new CoverCreationLog(algorithm.getAlgorithmType(), algorithm.getParameters(), algorithm.compatibleGraphTypes()));
cover.getCreationMethod().setStatus(ExecutionStatus.COMPLETED);
return cover;
}
}