Add path traversal with infection

This commit is contained in:
Marcin Kostrzewski 2022-06-16 22:05:00 +02:00
parent b6706489da
commit 255420e622

View File

@ -25,10 +25,14 @@ class Edge:
def as_tuple(self): def as_tuple(self):
return self.node_a, self.node_b, {'weight': self.weight} return self.node_a, self.node_b, {'weight': self.weight}
def has_node(self, node: Node) -> bool:
return self.node_a is node or self.node_b is node
class Graph: class Graph:
def __init__(self): def __init__(self, use_weights=False):
self.edges = [] self.edges = []
self.use_weights = use_weights
def add_edge(self, edge: Edge): def add_edge(self, edge: Edge):
self.edges.append(edge) self.edges.append(edge)
@ -43,6 +47,31 @@ class Graph:
nodes.add(edge.node_b) nodes.add(edge.node_b)
return nodes return nodes
def get_adjacent_nodes(self, node: Node) -> [(Node, int)]:
"""
:param node: Node to search for
:return: An array of tuples (node, weight)
"""
edges_with_node = filter(lambda ed: ed.has_node(node), self.edges)
nodes = set()
for e in edges_with_node:
if e.node_a is node:
nodes.add((e.node_b, e.weight))
else:
nodes.add((e.node_a, e.weight))
return nodes
def infect_step(self):
infected_nodes = list(filter(lambda n: n.is_infected, self.get_nodes()))
for node in infected_nodes:
adjacent_nodes = self.get_adjacent_nodes(node)
if self.use_weights:
to_be_infected = random.choices([n[0] for n in adjacent_nodes], weights=[n[1] for n in adjacent_nodes])[0]
else:
to_be_infected = random.choice([n[0] for n in adjacent_nodes])
to_be_infected.is_infected = True
def update(num, layout, g_repr, ax, our_graph: Graph): def update(num, layout, g_repr, ax, our_graph: Graph):
""" """
@ -50,9 +79,6 @@ def update(num, layout, g_repr, ax, our_graph: Graph):
""" """
ax.clear() ax.clear()
for n in our_graph.get_nodes():
n.is_infected = bool(random.getrandbits(1))
colors = ['red' if n.is_infected else 'blue' for n in g_repr] colors = ['red' if n.is_infected else 'blue' for n in g_repr]
sizes = [50 if n.is_infected else 1 for n in g_repr] sizes = [50 if n.is_infected else 1 for n in g_repr]
nx.draw( nx.draw(
@ -67,6 +93,8 @@ def update(num, layout, g_repr, ax, our_graph: Graph):
linewidths=40, linewidths=40,
) )
our_graph.infect_step()
def do_graph_animation(output_file_name: str, in_graph: Graph, frame_count: int, layout): def do_graph_animation(output_file_name: str, in_graph: Graph, frame_count: int, layout):
g_repr = nx.Graph() g_repr = nx.Graph()
@ -80,7 +108,7 @@ def do_graph_animation(output_file_name: str, in_graph: Graph, frame_count: int,
fig.set_figheight(15) fig.set_figheight(15)
anim = animation.FuncAnimation( anim = animation.FuncAnimation(
fig, update, frames=frame_count, fargs=(layout, g_repr, ax, in_graph) fig, update, frames=frame_count, interval=500, fargs=(layout, g_repr, ax, in_graph)
) )
anim.save(output_file_name) anim.save(output_file_name)
@ -88,9 +116,10 @@ def do_graph_animation(output_file_name: str, in_graph: Graph, frame_count: int,
plt.show() plt.show()
def bus_network(n=30) -> Graph: def bus_network(n=30, infected_idx=0) -> Graph:
network = Graph() network = Graph()
nodes = [Node() for _ in range(n)] nodes = [Node() for _ in range(n)]
nodes[infected_idx].is_infected = True
edges = [Edge(nodes[i], nodes[i + 1], 1.0) for i in range(n - 1)] edges = [Edge(nodes[i], nodes[i + 1], 1.0) for i in range(n - 1)]
network.add_edges(edges) network.add_edges(edges)
@ -100,6 +129,7 @@ def bus_network(n=30) -> Graph:
def ring_network(n=30) -> Graph: def ring_network(n=30) -> Graph:
network = Graph() network = Graph()
nodes = [Node() for _ in range(n)] nodes = [Node() for _ in range(n)]
nodes[0].is_infected = True
edges = [Edge(nodes[i], nodes[i + 1], 1.0) for i in range(n - 1)] edges = [Edge(nodes[i], nodes[i + 1], 1.0) for i in range(n - 1)]
end_edge = Edge(nodes[n - 1], nodes[0], 1.0) end_edge = Edge(nodes[n - 1], nodes[0], 1.0)
edges.append(end_edge) edges.append(end_edge)
@ -126,10 +156,10 @@ def main():
do_graph_animation('test.gif', network, 5, nx.spring_layout) do_graph_animation('test.gif', network, 5, nx.spring_layout)
bus = bus_network() bus = bus_network()
do_graph_animation('bus.gif', bus, 5, nx.spiral_layout) do_graph_animation('bus.gif', bus, 20, nx.spiral_layout)
ring = ring_network() ring = ring_network()
do_graph_animation('ring.gif', ring, 5, nx.circular_layout) do_graph_animation('ring.gif', ring, 20, nx.circular_layout)
if __name__ == "__main__": if __name__ == "__main__":