"""
Provides predefined contagion functions for use in the hypercontagion library.
"""
import random
# built-in functions
[docs]def collective_contagion(node, status, edge):
"""Collective contagion function.
Parameters
----------
node : hashable
node ID
status : dict
keys are node IDs and values are their statuses.
edge : iterable
hyperedge
Returns
-------
int
0 if no transmission can occur, 1 if it can.
"""
for i in set(edge).difference({node}):
if status[i] != "I":
return 0
return 1
[docs]def individual_contagion(node, status, edge):
"""Individual contagion function.
Parameters
----------
node : hashable
node ID
status : dict
keys are node IDs and values are their statuses.
edge : iterable
hyperedge
Returns
-------
int
0 if no transmission can occur, 1 if it can.
"""
for i in set(edge).difference({node}):
if status[i] == "I":
return 1
return 0
[docs]def threshold(node, status, edge, threshold=0.5):
"""Threshold contagion process.
Contagion may spread if greater than a specified fraction
of hyperedge neighbors are infected.
Parameters
----------
node : hashable
node ID
status : dict
keys are node IDs and values are their statuses.
edge : iterable of hashables
nodes in the hyperedge
threshold : float, default: 0.5
the critical fraction of hyperedge neighbors above
which contagion spreads.
Returns
-------
int
0 if no transmission can occur, 1 if it can.
"""
neighbors = set(edge).difference({node})
try:
c = sum([status[i] == "I" for i in neighbors]) / len(neighbors)
except:
c = 0
if c < threshold:
return 0
elif c >= threshold:
return 1
[docs]def majority_vote(node, status, edge):
"""Majority vote contagion process.
Contagion may spread if the majority of a node's
hyperedge neighbors are infected. If it's a tie,
the result is random.
Parameters
----------
node : hashable
node ID
status : dict
keys are node IDs and values are their statuses.
edge : iterable of hashables
nodes in the hyperedge
Returns
-------
int
0 if no transmission can occur, 1 if it can.
"""
neighbors = set(edge).difference({node})
try:
c = sum([status[i] == "I" for i in neighbors]) / len(neighbors)
except:
c = 0
if c < 0.5:
return 0
elif c > 0.5:
return 1
else:
return random.choice([0, 1])
[docs]def size_dependent(node, status, edge):
return sum([status[i] == "I" for i in set(edge).difference({node})])