Search code examples
rgraphigraphcomplex-networks

set the starting node for spreading a virus in a network


I'm working on finding influential nodes in complex networks using R programming. I want to use degree centrality which means the number of neighbors a node has in a graph. I have a graph and the degree centrality of each node. Now I want to know how many nodes will be infected within a specified time when we start to spread the virus from each node. according to my studies I should use SIR(susceptible, infected, recovered) epidemic model which I found in "igraph" package, the problem is that I can't specify the starting node. It seems that this functions works based on SIR equations:

s'= -(beta)SI
I' = (beta)SI - (gamma)I
R' = (gamma)I

where beta is infection parameter and gamma is recovery parameter. here is the igraph SIR code:

function (graph, beta, gamma, no.sim = 100) 
{
if (!is_igraph(graph)) {
    stop("Not a graph object")
}
beta <- as.numeric(beta)
gamma <- as.numeric(gamma)
no.sim <- as.integer(no.sim)
on.exit(.Call("R_igraph_finalizer", PACKAGE = "igraph"))
res <- .Call("R_igraph_sir", graph, beta, gamma, no.sim, 
    PACKAGE = "igraph")
class(res) <- "sir"
res
}

It seems that most of the work is being done in "R_igraph_sir" but I cant find such a function in that package. Is there any way to set the starting node?


Solution

  • It seems like you'd like to have a SIR model where you are able to set the initially infected node by monkeypatching the existing R code. Since the R package is compiled from C code this might be tough depending on your programming experience and in general monkeypatching isn't recommended, if nothing else then because you will lose your code the minute you update your igraph package.

    Instead you can relatively easily implement this yourself using the igraph package. Below is an untested implementation in python that should be easibly ported to R.

    The first step infects any node in the graph adjacent to an infected node with a probability of beta

    After infection stage any infected node can be removed from the graph with a probability of gamma

    After the given number of timesteps you find the number of effected nodes as the size of the infected_nodes array. This won't count removed nodes, so if you want the total number of infected over the entire simulation you put in a counter that increments each time you infect a node

    infected_nodes = []
    # Set the infection rate
    beta = 0.1
    # Set the removal rate
    gamma = 0.1
    # Set how many timesteps you want to pass through
    n_timesteps = 100
    # Start from the node you have chosen using edge centrality
    infected_nodes.append(chosen_node)
    for _ in n_timesteps:
        # Infection stage
        for node in infected_nodes:
            for neighbor in igraph.neighborhood(graph, node):
                # random.random simply returns a number between [0,1)
                if random.random() < beta:
                    infected_nodes.append(neighbor)
        # Removal stage
        infected_survivors = []
        for node in infected_nodes:
            if random.random() < gamma:
                graph = igraph.delete_vertices(graph, node)
            else:
                infected_survivors.append(node)
        infected_nodes = infected_survivors
    

    Some aberdabeis:

    • This assumes every node visits all their neighbors at each timestep. If you only want each node to be able to infect n neighbors per turn you will need to take a size n random sample of the neighbors instead of iterating over all of them.
    • In the removal stage it is possible to remove newly infected nodes, meaning that there is a chance that a node will not have the opportunity to infect its neighbors. If this is not realistic in your case you will have to store newly infected nodes in a separate array and add them to the infected nodes at the beginning of the infection stage
    • This will obviously be slower than C implementation provided by the R package