package edu.nd.nina.snap.cascades;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;
import edu.nd.nina.DirectedGraph;
import edu.nd.nina.UndirectedGraph;
import edu.nd.nina.alg.ConnectivityInspector;
import edu.nd.nina.experimental.isomorphism.IntegerVertexFactory;
import edu.nd.nina.generate.RandomGraphGenerator;
import edu.nd.nina.graph.DefaultDirectedGraph;
import edu.nd.nina.graph.DefaultEdge;
import edu.nd.nina.graph.SimpleGraph;
import edu.nd.nina.graph.UndirectedSubgraph;
import edu.nd.nina.math.Randoms;
import edu.nd.nina.structs.Pair;
public class Cascades {
private static Randoms r;
private Integer seed = 0;
public Cascades() {
r = new Randoms(seed);
}
/**
* simulate SI model cascade using infection probability Beta until the
* cascade reaches size CascSz
*
* @param g
* @param Beta
* @param CascSz
* @param NIdInfTmH
* @return
*/
DirectedGraph<Integer, DefaultEdge> runSICascade(UndirectedSubgraph<Integer, DefaultEdge> g,
final double Beta, final int CascSz,
Hashtable<Integer, Integer> NIdInfTmH) {
DirectedGraph<Integer, DefaultEdge> Casc = new DefaultDirectedGraph<Integer, DefaultEdge>(
DefaultEdge.class);
final int StartId = g.randomVertex(r);
Casc.addVertex(StartId);
NIdInfTmH.put(StartId, NIdInfTmH.size());
for (int X = 0; X < 10 * CascSz; X++) {
Integer[] CascNIdV = new Integer[Casc.vertexSet().size()];
Casc.vertexSet().toArray(CascNIdV);
for (Integer v : CascNIdV) {
for (DefaultEdge e : g.edgesOf(v)) {
if (Casc.containsVertex(g.getEdgeTarget(e))) {
continue;
}
if (r.GetUniDev() < Beta) {
Integer t = g.getEdgeTarget(e);
if (t.equals(v)) {
t = g.getEdgeSource(e);
}
Casc.addVertex(t);
NIdInfTmH.put(t, NIdInfTmH.size());
Casc.addEdge(v, t);
if (Casc.vertexSet().size() == CascSz) {
return Casc;
}
}
}
}
}
return Casc;
}
/**
* network cascade: add spurious edges for more details see
* "Correcting for Missing Data in Information Cascades" by E. Sadikov, M.
* Medina, J. Leskovec, H. Garcia-Molina. WSDM, 2011
*
* @param g
* @param Casc
* @param NIdTmH
* @return
*/
DirectedGraph<Integer, DefaultEdge> addSpuriousEdges(
final UndirectedSubgraph<Integer, DefaultEdge> g,
final DirectedGraph<Integer, DefaultEdge> Casc,
Hashtable<Integer, Integer> NIdTmH) {
Vector<Pair<Integer, Integer>> EdgeV = new Vector<Pair<Integer, Integer>>();
for (Integer GNI : Casc.vertexSet()) {
final int Tm = NIdTmH.get(GNI);
for (DefaultEdge e : g.edgesOf(GNI)) {
Integer dst = g.getEdgeTarget(e);
if (dst.equals(GNI)) {
dst = g.getEdgeSource(e);
}
if (NIdTmH.containsKey(dst)
&& Tm < NIdTmH.get(dst)
&& !Casc.containsEdge(GNI, dst)) {
EdgeV.add(new Pair<Integer, Integer>(GNI, dst));
}
}
}
DirectedGraph<Integer, DefaultEdge> NetCasc = new DefaultDirectedGraph<Integer, DefaultEdge>(
DefaultEdge.class);
//copy Casc to NetCasc
for(Integer v : Casc.vertexSet()){
NetCasc.addVertex(v);
}
for(DefaultEdge e : Casc.edgeSet()){
NetCasc.addEdge(Casc.getEdgeSource(e), Casc.getEdgeTarget(e));
}
for (int e = 0; e < EdgeV.size(); e++) {
NetCasc.addEdge(EdgeV.get(e).p1, EdgeV.get(e).p2);
}
return NetCasc;
}
public static void main(String[] args) {
Long exeTm = System.currentTimeMillis();
try {
final String InFNm = "demo"; // Input undirected graph
final String OutFNm = "influence_demo"; // Output file name prefix
final double Beta = 0.1; // Beta (infection (i.e., cascade
// propagation) probability)
// load
System.out.printf("Loading %s...", InFNm);
UndirectedGraph<Integer, DefaultEdge> ug = new SimpleGraph<Integer, DefaultEdge>(DefaultEdge.class);
if (InFNm == "demo") {
RandomGraphGenerator<Integer, DefaultEdge> rgg = new RandomGraphGenerator<Integer, DefaultEdge>(
100, 200);
Map<String, Integer> resultMap = new HashMap<String, Integer>();
rgg.generateGraph(ug, new IntegerVertexFactory(), resultMap);
} else {
// Graph = TSnap::LoadEdgeList<PUNGraph>(InFNm);
}
System.out.printf("nodes:%d edges:%d\n", ug.vertexSet().size(), ug
.edgeSet().size());
// Simulate SI model
UndirectedSubgraph<Integer, DefaultEdge> g = ConnectivityInspector.getMaxWcc(ug);
boolean DivByM = true;
Cascades c = new Cascades();
CascadeStatistics cascStat = new CascadeStatistics();
System.out.printf("\nGraph:%s -- Beta: %g\n", OutFNm, Beta);
for (int Run = 0; Run < 10; Run++) { // number of runs
Hashtable<Integer, Integer> NIdInfTmH = new Hashtable<Integer, Integer>();
// incluence cascade
DirectedGraph<Integer, DefaultEdge> InfCasc = c.runSICascade(g, Beta,
100, NIdInfTmH);
// min cascade size
if (InfCasc.vertexSet().size() < 10) {
System.out.printf(".");
continue;
}
// network cascade
DirectedGraph<Integer, DefaultEdge> NetCasc = c.addSpuriousEdges(g,
InfCasc, NIdInfTmH);
// sample the cascade
cascStat.sampleCascade(InfCasc, NetCasc, NIdInfTmH, 0.1, 10,
DivByM, r); // div-by-M
System.out.printf(".");
}
cascStat.plotAll(String
.format("%s-B%03d", OutFNm, (int)( 100 * Beta)), String
.format("%s N=%d E=%d Beta=%g", OutFNm, g.vertexSet()
.size(), g.edgeSet().size(), Beta), DivByM);
} catch (Exception e) {
System.err.printf("\nrun time: %s (%s)\n",
System.currentTimeMillis() - exeTm,
System.currentTimeMillis());
e.printStackTrace();
}
}
}