HIOM example¶
Description¶
This example will be slightly more complex, as it involves different schemes and update functions to model the spread of opinion polarization within and across individuals.
Code¶
import networkx as nx
import random
import numpy as np
import matplotlib.pyplot as plt
from ndlib.models.ContinuousModel import ContinuousModel
from ndlib.models.compartments.NodeStochastic import NodeStochastic
import ndlib.models.ModelConfig as mc
################### MODEL SPECIFICATIONS ###################
constants = {
'dt': 0.01,
'A_min': -0.5,
'A_star': 1,
's_O': 0.01,
's_I': 0,
'd_A': 0,
'p': 1,
'r_min': 0,
't_O': np.inf,
}
def initial_I(node, graph, status, constants):
return np.random.normal(0, 0.3)
def initial_O(node, graph, status, constants):
return np.random.normal(0, 0.2)
initial_status = {
'I': initial_I,
'O': initial_O,
'A': 1
}
def update_I(node, graph, status, attributes, constants):
nb = np.random.choice(graph.neighbors(node))
if abs(status[node]['O'] - status[nb]['O']) > constants['t_O']:
return status[node]['I'] # Do nothing
else:
# Update information
r = constants['r_min'] + (1 - constants['r_min']) / (1 + np.exp(-1 * constants['p'] * (status[node]['A'] - status[nb]['A'])))
inf = r * status[node]['I'] + (1-r) * status[nb]['I'] + np.random.normal(0, constants['s_I'])
# Update attention
status[node]['A'] = status[node]['A'] + constants['d_A'] * (2 * constants['A_star'] - status[node]['A'])
status[nb]['A'] = status[nb]['A'] + constants['d_A'] * (2 * constants['A_star'] - status[nb]['A'])
return inf
return
def update_A(node, graph, status, attributes, constants):
return status[node]['A'] - 2 * constants['d_A'] * status[node]['A']/len(graph.nodes)
def update_O(node, graph, status, attributes, constants):
noise = np.random.normal(0, constants['s_O'])
x = status[node]['O'] - constants['dt'] * (status[node]['O']**3 - (status[node]['A'] + constants['A_min']) * status[node]['O'] - status[node]['I']) + noise
return x
def shrink_I(node, graph, status, attributes, constants):
return status[node]['I'] * 0.999
def shrink_A(node, graph, status, attributes, constants):
return status[node]['A'] * 0.999
def sample_attention_weighted(graph, status):
probs = []
A = [stat['A'] for stat in list(status.values())]
factor = 1.0/sum(A)
for a in A:
probs.append(a * factor)
return np.random.choice(graph.nodes, size=1, replace=False, p=probs)
schemes = [
{
'name': 'random agent',
'function': sample_attention_weighted,
},
{
'name': 'all',
'function': lambda graph, status: graph.nodes,
},
{
'name': 'shrink I',
'function': lambda graph, status: graph.nodes,
'lower': 5000
},
{
'name': 'shrink A',
'function': lambda graph, status: graph.nodes,
'lower': 10000
},
]
################### MODEL CONFIGURATION ###################
# Network definition
g = nx.watts_strogatz_graph(400, 2, 0.02)
# Visualization config
visualization_config = {
'layout': 'fr',
'plot_interval': 100,
'plot_variable': 'O',
'variable_limits': {
'A': [0, 1]
},
'cmin': -1,
'cmax': 1,
'color_scale': 'RdBu',
'plot_output': './HIOM.gif',
'plot_title': 'HIERARCHICAL ISING OPINION MODEL',
}
# Model definition
HIOM = ContinuousModel(g, constants=constants, iteration_schemes=schemes)
HIOM.add_status('I')
HIOM.add_status('A')
HIOM.add_status('O')
# Compartments
condition = NodeStochastic(1)
# Rules
HIOM.add_rule('I', update_I, condition, ['random agent'])
HIOM.add_rule('A', update_A, condition, ['all'])
HIOM.add_rule('O', update_O, condition, ['all'])
HIOM.add_rule('I', shrink_I, condition, ['shrink I'])
HIOM.add_rule('A', shrink_A, condition, ['shrink A'])
# Configuration
config = mc.Configuration()
HIOM.set_initial_status(initial_status, config)
HIOM.configure_visualization(visualization_config)
################### SIMULATION ###################
iterations = HIOM.iteration_bunch(15000, node_status=True)
trends = HIOM.build_trends(iterations)
################### VISUALIZATION ###################
HIOM.plot(trends, len(iterations), delta=True)
HIOM.visualize(iterations)