-
Notifications
You must be signed in to change notification settings - Fork 0
Network Simulation Tutorial
milad edited this page May 10, 2026
·
2 revisions
Complete guide to simulating fake news and information spread on social networks.
- What is Network Simulation?
- Network Types
- How Spread Works
- Code Examples
- Visualizing Networks
- Real-World Applications
- Advanced Usage
- Common Pitfalls
Unlike compartmental models (SIR/SEIR) that assume random mixing, network simulation models contact patterns between individuals.
| Concept | Description |
|---|---|
| Nodes | Individuals or entities in the network |
| Edges | Connections between nodes (friendships, followers) |
| Spread | Information/disease travels along edges |
| Network Topology | Structure of connections |
| Scenario | Compartmental Model | Network Model |
|---|---|---|
| Homogeneous mixing | β Good | β Overkill |
| Social structure matters | β Poor | β Essential |
| Super-spreaders | β Can't model | β Can capture |
| Contact tracing | β Not possible | β Possible |
| Fake news spread | β Not realistic | β Highly realistic |
Properties: Power-law degree distribution (few highly connected nodes, many poorly connected).
from sir_simulator.core_models.network_model import SocialNetworkSimulator
sim = SocialNetworkSimulator(num_nodes=200, network_type='scale_free')Characteristics:
- Few "hubs" with many connections
- Realistic for social media (influencers)
- Robust to random failures, vulnerable to targeted attacks
Real-world examples:
- Twitter followers
- Facebook friendships
- Citation networks
Properties: High clustering + short path lengths.
sim = SocialNetworkSimulator(num_nodes=200, network_type='small_world')Characteristics:
- "Six degrees of separation"
- Friends have mutual friends
- Realistic for social circles
Real-world examples:
- Acquaintance networks
- Collaboration networks
- Neural networks
Properties: Random connections with uniform probability.
sim = SocialNetworkSimulator(num_nodes=200, network_type='random')Characteristics:
- No structure, completely random
- Limited realism
- Good baseline for comparison
Real-world examples:
- Airline routes (somewhat)
- Random encounters
The spread follows the same logic as SIR but on a graph:
| Stage | State | Description |
|---|---|---|
| S | Susceptible | Node has not seen the information |
| I | Infected (Spreader) | Node actively spreading information |
| R | Recovered | Node has seen it and stopped spreading |
- Initial infection: Random nodes start infected (spreaders)
-
Spread step: Each infected node tries to infect neighbors with probability
transmission_prob -
Recovery: Each infected node recovers with probability
recovery_prob -
Stop: Process ends when no infected nodes remain or
max_stepsreached
| Value | Meaning |
|---|---|
| 0.0 - 0.2 | Low virality (unlikely to be shared) |
| 0.2 - 0.5 | Medium virality |
| 0.5 - 0.8 | High virality (going viral) |
| 0.8 - 1.0 | Extremely viral (everyone shares) |
| Value | Meaning |
|---|---|
| 0.0 - 0.1 | People keep sharing for a long time |
| 0.1 - 0.3 | Moderate sharing duration |
| 0.3 - 0.5 | Quick loss of interest |
| 0.5 - 1.0 | Very short attention span |
from sir_simulator.core_models.network_model import SocialNetworkSimulator
# Create network
sim = SocialNetworkSimulator(num_nodes=200, network_type='scale_free')
# Get network stats
stats = sim.get_network_stats()
print(f"Nodes: {stats['nodes']}")
print(f"Edges: {stats['edges']}")
print(f"Avg degree: {stats['avg_degree']:.2f}")
# Run spread simulation
df = sim.simulate_spread(
transmission_prob=0.3, # 30% chance to spread
recovery_prob=0.1, # 10% chance to recover per step
initial_infected=5, # Start with 5 spreaders
max_steps=50 # Maximum 50 steps
)
print(df.tail())# Find peak spread
peak_spreaders = df['infected'].max()
peak_step = df[df['infected'] == peak_spreaders]['step'].values[0]
print(f"Peak spreaders: {peak_spreaders} at step {peak_step}")
# Calculate final reach
final_reach = df['recovered'].iloc[-1] + df['infected'].iloc[-1]
if final_reach == 0 and len(df) > 1:
final_reach = df['recovered'].iloc[-2]
reach_percentage = (final_reach / sim.num_nodes) * 100
print(f"Final reach: {final_reach}/{sim.num_nodes} ({reach_percentage:.1f}%)")
# How long did spread last?
total_steps = len(df) - 1 # -1 because step 0 is initial
print(f"Spread lasted {total_steps} steps")import numpy as np
import matplotlib.pyplot as plt
transmission_probs = [0.1, 0.3, 0.5, 0.7]
colors = ['blue', 'green', 'orange', 'red']
plt.figure(figsize=(10, 6))
for prob, color in zip(transmission_probs, colors):
sim = SocialNetworkSimulator(num_nodes=200, network_type='scale_free')
df = sim.simulate_spread(transmission_prob=prob, recovery_prob=0.1, max_steps=50)
plt.plot(df['step'], df['infected'], label=f'Transmission={prob}', color=color)
plt.xlabel('Step', fontsize=12)
plt.ylabel('Number of Spreaders', fontsize=12)
plt.title('Network Simulation - Effect of Transmission Probability', fontsize=14)
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()import matplotlib.pyplot as plt
network_types = ['scale_free', 'small_world', 'random']
colors = ['red', 'blue', 'green']
linestyles = ['-', '--', ':']
plt.figure(figsize=(12, 6))
for net_type, color, ls in zip(network_types, colors, linestyles):
sim = SocialNetworkSimulator(num_nodes=200, network_type=net_type)
df = sim.simulate_spread(transmission_prob=0.3, recovery_prob=0.1, max_steps=50)
plt.plot(df['step'], df['infected'], label=net_type, color=color, linestyle=ls, linewidth=2)
plt.xlabel('Step', fontsize=12)
plt.ylabel('Number of Spreaders', fontsize=12)
plt.title('Network Simulation - Effect of Network Topology', fontsize=14)
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()sim = SocialNetworkSimulator(num_nodes=50, network_type='scale_free')
sim.visualize_network(show_labels=False)import matplotlib.pyplot as plt
import networkx as nx
sim = SocialNetworkSimulator(num_nodes=100, network_type='small_world')
sim.simulate_spread(transmission_prob=0.3, recovery_prob=0.1, max_steps=20)
# Visualize with custom styling
plt.figure(figsize=(12, 10))
pos = nx.spring_layout(sim.graph, seed=42, k=2)
# Node colors based on state
node_colors = []
for node in sim.graph.nodes():
if node in sim.I:
node_colors.append('red') # Infected (spreader)
elif node in sim.R:
node_colors.append('green') # Recovered
else:
node_colors.append('blue') # Susceptible
# Draw network
nx.draw(sim.graph, pos, node_color=node_colors, node_size=100,
with_labels=False, edge_color='gray', alpha=0.6)
# Add legend
legend_elements = [
plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='blue', markersize=10, label='Susceptible'),
plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='red', markersize=10, label='Spreader'),
plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='green', markersize=10, label='Recovered')
]
plt.legend(handles=legend_elements, loc='upper right')
plt.title(f'Network State at Step {len(sim.history)-1}', fontsize=14)
plt.axis('off')
plt.show()Network simulation can help identify:
- Super-spreaders - Nodes that cause rapid spread
- Critical connections - Edges that enable spread between communities
- Intervention points - Where to fact-check or block
For actual diseases, network models capture:
- Household spread - Family members infect each other
- School spread - Children infect classmates
- Workplace spread - Coworker transmission
- Super-spreader events - Concerts, conferences, weddings
Business applications:
- Viral marketing - Identify influential customers
- Product adoption - Simulate how new products spread
- Influencer identification - Find key opinion leaders
import numpy as np
def find_superspreaders(sim, num_top=5):
"""Find nodes that cause the most spread"""
from collections import Counter
spread_counts = Counter()
# Run simulation multiple times with different initial seeds
for _ in range(20):
df = sim.simulate_spread(transmission_prob=0.3, recovery_prob=0.1, max_steps=30)
# Track which nodes spread
for node in sim.I:
spread_counts[node] += 1
top_spreaders = spread_counts.most_common(num_top)
print(f"Top {num_top} super-spreaders:")
for node, count in top_spreaders:
degree = sim.graph.degree(node)
print(f" Node {node}: appeared in {count}/20 runs, degree={degree}")
return top_spreaders
sim = SocialNetworkSimulator(num_nodes=200, network_type='scale_free')
superspreaders = find_superspreaders(sim)def test_node_removal(sim, node_to_remove):
"""Test spread without a specific node"""
# Original spread
df_original = sim.simulate_spread(transmission_prob=0.3, recovery_prob=0.1)
original_reach = df_original['recovered'].max() + df_original['infected'].max()
# Remove node and test spread
sim.graph.remove_node(node_to_remove)
sim.num_nodes -= 1
df_removed = sim.simulate_spread(transmission_prob=0.3, recovery_prob=0.1)
removed_reach = df_removed['recovered'].max() + df_removed['infected'].max()
reduction = (original_reach - removed_reach) / original_reach * 100
print(f"Removing node {node_to_remove} reduces reach by {reduction:.1f}%")
return reduction| Nodes | Performance |
|---|---|
| < 500 | Fast |
| 500 - 2000 | Moderate |
| 2000 - 10000 | Slow |
| > 10000 | Memory issues possible |
# Good - fast
sim = SocialNetworkSimulator(num_nodes=200)
# May be slow
sim = SocialNetworkSimulator(num_nodes=5000)# Realistic
sim.simulate_spread(transmission_prob=0.3, recovery_prob=0.1)
# Unrealistic - almost everyone gets infected
sim.simulate_spread(transmission_prob=0.99, recovery_prob=0.01)# Too short - spread not complete
sim.simulate_spread(transmission_prob=0.3, recovery_prob=0.1, max_steps=10)
# Better - allow time for spread
sim.simulate_spread(transmission_prob=0.3, recovery_prob=0.1, max_steps=100)| Concept | Summary |
|---|---|
| Network Types | Scale-free, Small-world, Random |
| Spread Logic | SIR model on graph |
| Key Parameters | Transmission prob, Recovery prob |
| Super-spreaders | High-degree nodes in scale-free networks |
| Best for | Social media, targeted interventions |
- ML Prediction Tutorial - Forecast future spread
- Scenario Comparison Tutorial - Intervention strategies