import igraph as ig
import numpy as np
import time
import multiprocessing as mp


f2 = open("screen.out", 'w')
f = open("result.dat", "w")

# Calculating the efficiency of a given network
def eff_global(g, weights):

        N = g.vcount()
        eff = 0.0
        sp = g.shortest_paths(weights=weights)
        for l in sp:
                for ll in l:
                        if ll != 0.0:
                                # the eff of each edge is simply 1.0/(shortest path)
                                eff += 1.0/float(ll)

        E = eff / (float(N)*(float(N)-1.0))
        return E


def vuln_for_each_node(g, weights, k, E):
        g_copy = g.copy()
        # delete edges connected to node k
        del_list = []
        for target_vertex_id in range(g_copy.vcount()):
                try:
                        del_list.append(g_copy.get_eid(k,target_vertex_id))
                except:
                        pass
        g_copy.delete_edges(del_list)

        # compute the efficiency of the network after removing the edges that incide on node k
        Ek = eff_global(g_copy, weights)

        # Vulnerability index
        Vk = (E - Ek)/E
        del del_list

        return Vk



def vulnerability(g, weights, procs = 1, f2=None):
        x=time.time()
        f2.write("Calculating global efficiency\n")
        # Global efficiency of the original network
        E = eff_global(g, weights)
        f2.write(f"Time to calculate: {time.time()-x} seconds\n")


        # For each node, remove its adjacency edges, compute the global efficiency of the remaining network,
        # and its associated Vulnerability index

        # Parallel version
        # Number of subprocesses
        f2.write("Starting the parallelization\n")
        pool = mp.Pool(procs)
        argss = [(g, weights, k, E) for k in range(g.vcount())]
        vuln = pool.starmap(vuln_for_each_node, argss)

        return vuln



f2.write("Reading the network\n")
g = ig.Graph.Read_Edgelist("edgelist.dat")
f2.write("Network read\n")
x = time.time()
f2.write(f"Starting the vulnerability calculation\n")
vul = vulnerability(g, None, 4, f2)
f2.write(f"End of calculation: {(time.time()-x)/60/60} hours\n")

f.write(f"no\tvul\n")
for i in range(len(vul)):
        f.write(f"{i}\t{vul[i]}\n")
