1

I am following this example called Virus on Network from the Mesa library which creates network graphs using Networkx.

Here is its function screening a node's neighbors to try to infect them with a virus.

def try_to_infect_neighbors(self):
    neighbors_nodes = self.model.grid.get_neighbors(self.pos, include_center=False)
    susceptible_neighbors = [agent for agent in self.model.grid.get_cell_list_contents(neighbors_nodes) if
                             agent.state is State.SUSCEPTIBLE]
    for a in susceptible_neighbors:
        if self.random.random() < self.virus_spread_chance:
            a.state = State.INFECTED

However, I like to get the distance between a node and its neighbor. And here is another example called Sugarscape from Mesa that seems to do just that.

So I modified the code into:

def try_to_infect_neighbors(self):
    neighbors_nodes = self.model.grid.get_neighbors(self.pos, include_center=False)
    susceptible_neighbors = [agent for agent in self.model.grid.get_cell_list_contents(neighbors_nodes) if
                             agent.state is State.SUSCEPTIBLE]                         
    for a in susceptible_neighbors:

        print('Self position:', self.pos, 'Neightbor position:', neighbor_agent.pos)
        # Output: Self position: 52 Neightbor position: 13
        neightbor_distance = get_distance(self.pos, neighbor_agent.pos)
        # TypeError: 'int' object is not iterable
        print(neightbor_distance)

        if neightbor_distance <= 1:
            if self.random.random() < self.virus_spread_chance:
                a.state = State.INFECTED

def get_distance(pos_1, pos_2):
    """ Get the distance between two point
    Args:
        pos_1, pos_2: Coordinate tuples for both points.
    """
    x1, y1 = pos_1
    x2, y2 = pos_2
    dx = x1 - x2
    dy = y1 - y2
    return math.sqrt(dx**2 + dy**2)

In the Sugarscape example, a.pos gives a tuple of x and y locations. But in the Virus on Network, a.pos gives the agent's ID. How can I access agent's x and y location in the Virus on Network example? I tried searching for them from within a.model.G and a.model.grid via the variables: self.G = nx.erdos_renyi_graph(n=self.num_nodes, p=prob) and self.grid = NetworkGrid(self.G), but I couldn't identify them and am thinking it shouldn't be that hidden.

KubiK888
  • 4,377
  • 14
  • 61
  • 115
  • The virus model does not have (x,y) coordinates assigned to the agents (see implementation of [`NetworkGrid`](https://github.com/projectmesa/mesa/blob/bb56278d6dfbc20ecd38b5b9cfe3c3ca8ff7811a/mesa/space.py#L834)). You could either simply add random weights as distance to the graph or place the nodes of the graph to a 2D plane (e.g. via a drawing algorithm, and use this). Would this solve your problem? – Sparky05 Apr 09 '20 at 12:55
  • How do you place the nodes on a graph? A working example will be great. – KubiK888 Apr 09 '20 at 16:17
  • And also, can you please explain how I can assign weight onto node connections? – KubiK888 Apr 09 '20 at 22:33

1 Answers1

1

Here is some code to add edge weights or get random node positions (maybe you want to scale them).

import networkx as nx
import random

num_nodes = 10
prob = .25

G = nx.erdos_renyi_graph(n=num_nodes, p=prob)

# you need to add this in the __init__ of VirusOnNetwork
for u, v in G.edges():
    # add random weights between 0 and 10
    G[u][v]["weight"] = random.random() * 10
    # you can access these weights in the same way (G[from_node][target_node]["weight"]

print(G.edges(data=True))
# [(0, 5, {'weight': 2.3337749464751454}), (0, 9, {'weight': 6.127630949347937}), (1, 4, {'weight': 9.048896640242369}), (2, 4, {'weight': 1.4236964132196228}), (2, 6, {'weight': 4.749936581386136}), (2, 9, {'weight': 2.037644705935693}), (3, 5, {'weight': 2.296192134297448}), (3, 7, {'weight': 1.5250362478641677}), (3, 9, {'weight': 7.362866019415747}), (4, 6, {'weight': 7.365668938333058}), (5, 6, {'weight': 1.1855367672698724}), (5, 8, {'weight': 3.219373770451519}), (7, 9, {'weight': 4.025563800958256})]


# alternative node positions
# you can store them in the graph or as separate attribute of your model
pos = nx.random_layout(G)

print(pos)
#{0: array([0.8604371 , 0.19834588], dtype=float32), 1: array([0.13099413, 0.97313595], dtype=float32), 2: array([0.30455875, 0.8844262 ], dtype=float32), 3: array([0.575425, 0.517468], dtype=float32), 4: array([0.7437008 , 0.89525336], dtype=float32), 5: array([0.9664812 , 0.21694745], dtype=float32), 6: array([0.89979964, 0.33603832], dtype=float32), 7: array([0.7894464, 0.7614578], dtype=float32), 8: array([0.44350627, 0.9081728 ], dtype=float32), 9: array([0.8049214 , 0.20761919], dtype=float32)}

# you can use this position for visualisation with networkx
nx.draw(G, pos)
KubiK888
  • 4,377
  • 14
  • 61
  • 115
Sparky05
  • 4,692
  • 1
  • 10
  • 27
  • Once you generate the x and y position got each node, is it possible to remap or redraw the erdos_renyi_graph, so that it will correspond to the some x and y axes? If not, is there an alternative graph I can do that along with the network connection information? – KubiK888 Apr 10 '20 at 19:24
  • What do you mean with redraw? Do you mean only the visualisation? or do you mean sampling new edges? – Sparky05 Apr 10 '20 at 19:53
  • What I means is from my original post, you mentioned and it seems to be the case that `networkgrid` doesn't have x and y coordinates assigned to the agent. But my code has been built on this display scheme and I really like the way it shows the nodes and edges. In your answer, looks like you are assigning some random x and y as pos to each node. So I wonder if I were to display that as a network graph, how I can display that in a way it will show the newly assigned x and y position. For example, considering the most lower left corner as position (0, 0). – KubiK888 Apr 10 '20 at 20:03
  • The server of your example (https://github.com/projectmesa/mesa/blob/master/examples/virus_on_network/virus_on_network/server.py) does not use the networkx drawing, but instead some javascript. Then you would need to modify that and the corresponding js file (https://github.com/projectmesa/mesa/blob/bb56278d6dfbc20ecd38b5b9cfe3c3ca8ff7811a/mesa/visualization/templates/js/NetworkModule_sigma.js) – Sparky05 Apr 10 '20 at 21:06