package i5.las2peer.services.ocd.metrics;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.math3.linear.ArrayRealVector;
import i5.las2peer.services.ocd.algorithms.utils.OcdAlgorithmException;
import i5.las2peer.services.ocd.algorithms.utils.Similarities;
import i5.las2peer.services.ocd.algorithms.utils.Termmatrix;
import i5.las2peer.services.ocd.graphs.Cover;
import i5.las2peer.services.ocd.graphs.CustomGraph;
import i5.las2peer.services.ocd.graphs.GraphType;
import y.base.Node;
import y.base.NodeCursor;
/**
* Implements the newman modularity combined with the cosine similarity of each of the nodes.
* The influence of the similarity can be maintained by the weighting factor.
* The bigger the factor is chosen, the less is the influence of the similarity.
* If the weighting factor is equal to 1, the algorithm will behave like the normal newman modularity.
* @author Sabrina
*
*/
public class NewmanModularityCombined implements StatisticalMeasure {
private double alpha = 0.5;
public static final String ALPHA_NAME = "weightingFactor";
@Override
public void setParameters(Map<String, String> parameters) {
if(parameters.containsKey(ALPHA_NAME)){
alpha = Double.parseDouble(parameters.get(ALPHA_NAME));
if(alpha < 0 || alpha > 1){
throw new IllegalArgumentException();
}
parameters.remove(ALPHA_NAME);
}
if(parameters.size() > 0) {
throw new IllegalArgumentException();
}
}
@Override
public Map<String, String> getParameters() {
Map<String, String> param = new HashMap<String, String>();
param.put(ALPHA_NAME, Double.toString(alpha));
return param;
}
@Override
public Set<GraphType> compatibleGraphTypes() {
Set<GraphType> compatibleTypes = new HashSet<GraphType>();
compatibleTypes.add(GraphType.DIRECTED);
compatibleTypes.add(GraphType.ZERO_WEIGHTS);
compatibleTypes.add(GraphType.CONTENT_LINKED);
return compatibleTypes;
}
@Override
public double measure(Cover cover) throws InterruptedException, OcdAlgorithmException {
double metricValue = 0;
Similarities sim = new Similarities();
CustomGraph graph = cover.getGraph();
Termmatrix t = new Termmatrix(graph);
NodeCursor nodesA = graph.nodes();
NodeCursor nodesB = graph.nodes();
Node nodeA;
Node nodeB;
int indexA;
int indexB;
double iteration = 0;
while(nodesA.ok()) {
nodeA = nodesA.node();
nodesB.toFirst();
indexA = t.getNodeIdList().indexOf(nodeA);
while(nodesB.ok()) {
nodeB = nodesB.node();
indexB = t.getNodeIdList().indexOf(nodeB);
if(indexB > indexA){
int coMembership = 0;
for(Integer comId: cover.getCommunityIndices(nodeA)){
if(cover.getCommunityIndices(nodeB).contains(comId)){
//coMembership += (cover.getBelongingFactor(nodeA, comId) * cover.getBelongingFactor(nodeB, comId));
coMembership = 1;
break;
}
}
iteration++;
metricValue +=
(alpha * linkStrength(cover, nodeA, nodeB) + ( 1- alpha) * sim.cosineSim((ArrayRealVector)t.getMatrix().getRowVector(indexA), (ArrayRealVector)t.getMatrix().getRowVector(indexB))) * coMembership;
}
nodesB.next();
}
nodesA.next();
}
return metricValue/iteration;
}
private double linkStrength(Cover cover, Node nodeA, Node nodeB){
double cont = 0;
double edgeCont = 0;
double degreeProd;
//double coMembership = 0;
double adjacencyEntry = 0;
if(cover.getGraph().containsEdge(nodeA, nodeB)){
adjacencyEntry = 1;
}
if(cover.getGraph().edgeCount() != 0){
degreeProd = nodeA.inDegree() * nodeB.inDegree();
edgeCont = (adjacencyEntry - (degreeProd / (cover.getGraph().edgeCount() * 2)));
}
cont = edgeCont /* * coMembership*/;
if(cover.getGraph().edgeCount() != 0){
cont /= (cover.getGraph().edgeCount() * 2);
}
return cont;
}
}