/*
* Copyright (C) 2015 Adrien Guille <adrien.guille@univ-lyon2.fr>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main.java.fr.ericlab.sondy.algo.eventdetection.edcow;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import no.uib.cipr.matrix.DenseVector;
import no.uib.cipr.matrix.VectorEntry;
import ch.epfl.lis.jmod.Jmod;
import ch.epfl.lis.jmod.JmodNetwork;
import ch.epfl.lis.jmod.JmodSettings;
import ch.epfl.lis.jmod.modularity.community.Community;
import ch.epfl.lis.jmod.modularity.community.RootCommunity;
import ch.epfl.lis.networks.Edge;
import ch.epfl.lis.networks.EdgeFactory;
import ch.epfl.lis.networks.NetworkException;
import ch.epfl.lis.networks.Node;
import ch.epfl.lis.networks.NodeFactory;
import ch.epfl.lis.networks.Structure;
////////////////////////////////////////////////////////////////////////////////
// This file is part of SONDY. //
// //
// SONDY is free software: you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation, either version 3 of the License, or //
// (at your option) any later version. //
// //
// SONDY is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with SONDY. If not, see <http://www.gnu.org/licenses/>. //
////////////////////////////////////////////////////////////////////////////////
/**
* @author Yue HE, Falitokiniaina RABEARISON, Département Informatique et Statistiques, Université Lumière Lyon 2
* @author Adrien GUILLE, Laboratoire ERIC, Université Lumière Lyon 2
*/
public class EDCoWModularityDetection {
List<Node> nodeList;
ArrayList<Community> arrayCommunities;
Structure<Node, Edge<Node>> structure;
LinkedList<EDCoWEvent> events;
float startSlice;
float endSlice;
// Add two arguments : start and end index of the frequency array
public EDCoWModularityDetection(LinkedList<EDCoWKeyword> keywords, double[][] correlations, float startDay, float endDay) throws NetworkException, Exception{
this.startSlice = startDay;
this.endSlice = endDay;
// instantiate structure
NodeFactory<Node> nodeFactory = new NodeFactory<>(new Node());
EdgeFactory<Edge<Node>> edgeFactory = new EdgeFactory<>(new Edge<Node>());
structure = new Structure<>(nodeFactory, edgeFactory);
// Adding weighted edges between keywords
for(int i = 0; i < keywords.size(); i++){
for(int j = i; j < keywords.size(); j++){
if(i != j && correlations[i][j] > 0.1){
if(!structure.containsNode(keywords.get(i).getKeyWord()))
structure.addNode(keywords.get(i).getKeyWord());
if(!structure.containsNode(keywords.get(j).getKeyWord()))
structure.addNode(keywords.get(j).getKeyWord());
structure.addEdge(new Edge(structure.getNode(keywords.get(i).getKeyWord()),structure.getNode(keywords.get(j).getKeyWord()),correlations[i][j]));
}
}
}
nodeList = structure.getNodesOrderedByNames();
System.out.println("Structure between slices "+startSlice+" and "+endSlice+": "+structure.getSize()+" nodes and " + structure.getNumEdges()+" edges");
if(structure.getNumEdges()>0){
// instantiate JmodNetwork
JmodNetwork network = new JmodNetwork(structure);
JmodSettings settings = JmodSettings.getInstance();
settings.setUseMovingVertex(true);
settings.setUseGlobalMovingVertex(true);
// run modularity detection
Jmod jmod = new Jmod();
jmod.runModularityDetection(network);
events = new LinkedList<>();
RootCommunity rc = jmod.getRootCommunity();
arrayCommunities = rc.getIndivisibleCommunities();
}
}
public double computeEdgesWeight(Community c, List<Node> nodeList){
double totalWeight =0;
if(c.getChild1() == null){
DenseVector nodesC = c.getVertexIndexes();
for(VectorEntry ve : nodesC){
int id = (int)ve.get();
Set<Edge<Node>> edges = structure.getEdges(nodeList.get(id));
for(Edge e:edges){
if(e.getSource().equals(nodeList.get(id)))
totalWeight += e.getWeight();
}
}
}else{
computeEdgesWeight(c.getChild1(),nodeList);
computeEdgesWeight(c.getChild2(),nodeList);
}
return totalWeight;
}
public void saveEventFromCommunity(Community c){
DenseVector nodesC = c.getVertexIndexes();
if(nodesC.size() > 1){
EDCoWEvent event = new EDCoWEvent();
for(VectorEntry ve : nodesC){
int id = (int)ve.get();
String keyword = nodeList.get(id).getName();
event.keywords.add(keyword);
}
event.setEpsylon(computeE(c));
event.setStartSlice(startSlice);
event.setEndSlice(endSlice);
events.add(event);
}
}
public void explore(Community c){
if(c.getChild1() == null){
DenseVector nodesC = c.getVertexIndexes();
EDCoWEvent event = new EDCoWEvent();
for(VectorEntry ve : nodesC){
int id = (int)ve.get();
event.keywords.add(nodeList.get(id).getName());
event.setEpsylon(computeE(c));
event.setStartSlice(startSlice);
event.setEndSlice(endSlice);
}
events.add(event);
}else{
explore(c.getChild1());
explore(c.getChild2());
}
}
public ArrayList<Community> getCommunitiesFiltered(double thresholdE) {
ArrayList<Community> ComFiltered = new ArrayList<>();
for(Community c:arrayCommunities){
double tempComE= computeE(c);
if(tempComE>thresholdE) ComFiltered.add(c);
}
return ComFiltered;
}
private double computeE(Community c) {
int n = c.getCommunitySize();
double totalWeight = computeEdgesWeight(c,nodeList);
double e = totalWeight * (Math.exp(1.5*n)/2*n);
return e;
}
public ArrayList<Community> getArrayCommunities(){
return arrayCommunities;
}
public List<Node> getNodeList() {
return nodeList;
}
public LinkedList<EDCoWEvent> getEvents(){
return events;
}
}