Skip to content

Commit

Permalink
Merge branch 'net_abstraction' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
GiulioRossetti committed Jun 22, 2019
2 parents 4676a20 + 47681f1 commit e210e53
Show file tree
Hide file tree
Showing 29 changed files with 677 additions and 478 deletions.
2 changes: 1 addition & 1 deletion ndlib/models/CompositeModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def iteration(self, node_status=True):
return {"iteration": 0, "status": {},
"node_count": node_count.copy(), "status_delta": status_delta.copy()}

for u in self.graph.nodes():
for u in self.graph.nodes:
u_status = self.status[u]
for i in range(0, self.compartment_progressive):

Expand Down
14 changes: 7 additions & 7 deletions ndlib/models/DiffusionModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import past.builtins
import future.utils
import six
from netdispatch import AGraph

__author__ = "Giulio Rossetti"
__license__ = "BSD-2-Clause"
Expand Down Expand Up @@ -52,8 +53,8 @@ def __init__(self, graph):
}

self.actual_iteration = 0
self.graph = graph
self.status = {n: 0 for n in self.graph.nodes()}
self.graph = AGraph(graph)
self.status = {n: 0 for n in self.graph.nodes}
self.initial_status = {}

def __validate_configuration(self, configuration):
Expand Down Expand Up @@ -99,13 +100,13 @@ def __validate_configuration(self, configuration):
if len(onp) > 0:
for param in onp:
if param not in ndp:
for nid in self.graph.nodes():
for nid in self.graph.nodes:
configuration.add_node_configuration(param, nid, self.parameters['nodes'][param]['default'])

if len(oep) > 0:
for param in oep:
if param not in edp:
for eid in self.graph.edges():
for eid in self.graph.edges:
configuration.add_edge_configuration(param, eid, self.parameters['edges'][param]['default'])

# Checking initial simulation status
Expand All @@ -128,15 +129,15 @@ def set_initial_status(self, configuration):
# Set additional node information

for param, node_to_value in future.utils.iteritems(nodes_cfg):
if len(node_to_value) < len(self.graph.nodes()):
if len(node_to_value) < len(self.graph.nodes):
raise ConfigurationException({"message": "Not all nodes have a configuration specified"})

self.params['nodes'][param] = node_to_value

edges_cfg = configuration.get_edges_configuration()
# Set additional edges information
for param, edge_to_values in future.utils.iteritems(edges_cfg):
if len(edge_to_values) == len(self.graph.edges()):
if len(edge_to_values) == len(self.graph.edges):
self.params['edges'][param] = {}
for e in edge_to_values:
self.params['edges'][param][e] = edge_to_values[e]
Expand Down Expand Up @@ -227,7 +228,6 @@ def reset(self, infected_nodes=None):
if 'fraction_infected' in self.params['model']:
for n in self.status:
self.status[n] = 0

number_of_initial_infected = len(self.graph.nodes()) * float(self.params['model']['fraction_infected'])
available_nodes = [n for n in self.status if self.status[n] == 0]
sampled_nodes = np.random.choice(available_nodes, int(number_of_initial_infected), replace=False)
Expand Down
115 changes: 115 additions & 0 deletions ndlib/models/DynamicDiffusionModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import networkx as nx
from ndlib.models.DiffusionModel import DiffusionModel
import six
import warnings
import numpy as np
import future.utils

__author__ = "Giulio Rossetti"
__license__ = "BSD-2-Clause"
Expand Down Expand Up @@ -85,4 +88,116 @@ def execute_iterations(self, node_status=True):
system_status.append(its)
return system_status

def set_initial_status(self, configuration):
"""
Set the initial model configuration
:param configuration: a ```ndlib.models.ModelConfig.Configuration``` object
"""

self.__validate_configuration(configuration)

nodes_cfg = configuration.get_nodes_configuration()
# Set additional node information

for param, node_to_value in future.utils.iteritems(nodes_cfg):
if len(node_to_value) < len(self.graph.nodes()):
raise ConfigurationException({"message": "Not all nodes have a configuration specified"})

self.params['nodes'][param] = node_to_value

edges_cfg = configuration.get_edges_configuration()
# Set additional edges information
for param, edge_to_values in future.utils.iteritems(edges_cfg):
if len(edge_to_values) == len(self.graph.edges()):
self.params['edges'][param] = {}
for e in edge_to_values:
self.params['edges'][param][e] = edge_to_values[e]

# Set initial status
model_status = configuration.get_model_configuration()

for param, nodes in future.utils.iteritems(model_status):
self.params['status'][param] = nodes
for node in nodes:
self.status[node] = self.available_statuses[param]

# Set model additional information
model_params = configuration.get_model_parameters()
for param, val in future.utils.iteritems(model_params):
self.params['model'][param] = val

# Handle initial infection
if 'Infected' not in self.params['status']:
if 'percentage_infected' in self.params['model']:
number_of_initial_infected = len(self.graph.nodes()) * float(self.params['model']['percentage_infected'])
if number_of_initial_infected < 1:
warnings.warn('Graph with less than 100 nodes: a single node will be set as infected')
number_of_initial_infected = 1

available_nodes = [n for n in self.status if self.status[n] == 0]
sampled_nodes = np.random.choice(available_nodes, int(number_of_initial_infected), replace=False)
for k in sampled_nodes:
self.status[k] = self.available_statuses['Infected']

self.initial_status = self.status

def __validate_configuration(self, configuration):
"""
Validate the consistency of a Configuration object for the specific model
:param configuration: a Configuration object instance
"""
if "Infected" not in self.available_statuses:
raise ConfigurationException("'Infected' status not defined.")

# Checking mandatory parameters
omp = set([k for k in self.parameters['model'].keys() if not self.parameters['model'][k]['optional']])
onp = set([k for k in self.parameters['nodes'].keys() if not self.parameters['nodes'][k]['optional']])
oep = set([k for k in self.parameters['edges'].keys() if not self.parameters['edges'][k]['optional']])

mdp = set(configuration.get_model_parameters().keys())
ndp = set(configuration.get_nodes_configuration().keys())
edp = set(configuration.get_edges_configuration().keys())

if len(omp) > 0:
if len(omp & mdp) != len(omp):
raise ConfigurationException({"message": "Missing mandatory model parameter(s)", "parameters": omp-mdp})

if len(onp) > 0:
if len(onp & ndp) != len(onp):
raise ConfigurationException({"message": "Missing mandatory node parameter(s)", "parameters": onp-ndp})

if len(oep) > 0:
if len(oep & edp) != len(oep):
raise ConfigurationException({"message": "Missing mandatory edge parameter(s)", "parameters": oep-edp})

# Checking optional parameters
omp = set([k for k in self.parameters['model'].keys() if self.parameters['model'][k]['optional']])
onp = set([k for k in self.parameters['nodes'].keys() if self.parameters['nodes'][k]['optional']])
oep = set([k for k in self.parameters['edges'].keys() if self.parameters['edges'][k]['optional']])

if len(omp) > 0:
for param in omp:
if param not in mdp:
configuration.add_model_parameter(param, self.parameters['model'][param]['default'])

if len(onp) > 0:
for param in onp:
if param not in ndp:
for nid in self.graph.nodes():
configuration.add_node_configuration(param, nid, self.parameters['nodes'][param]['default'])

if len(oep) > 0:
for param in oep:
if param not in edp:
for eid in self.graph.edges():
configuration.add_edge_configuration(param, eid, self.parameters['edges'][param]['default'])

# Checking initial simulation status
sts = set(configuration.get_model_configuration().keys())
if self.discrete_state and "Infected" not in sts and "percentage_infected" not in mdp:
warnings.warn('Initial infection missing: a random sample of 5% of graph nodes will be set as infected')
self.params['model']["percentage_infected"] = 0.05

iteration_bunch = execute_snapshots
2 changes: 1 addition & 1 deletion ndlib/models/compartments/EdgeCategoricalAttribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def execute(self, node, graph, status, status_map, *args, **kwargs):
if isinstance(graph, nx.DiGraph):
neighbors = list(graph.predecessors(node))

edge_attr = nx.get_edge_attributes(graph, self.attribute)
edge_attr = graph.get_edge_attributes(self.attribute)

if self.trigger is not None:
triggered = [v for v in neighbors if status[v] == status_map[self.trigger] and
Expand Down
2 changes: 1 addition & 1 deletion ndlib/models/compartments/EdgeNumericalAttribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def execute(self, node, graph, status, status_map, *args, **kwargs):
if isinstance(graph, nx.DiGraph):
neighbors = list(graph.predecessors(node))

edge_attr = nx.get_edge_attributes(graph, self.attribute)
edge_attr = graph.get_edge_attributes(self.attribute)

triggered = []

Expand Down
9 changes: 7 additions & 2 deletions ndlib/models/compartments/EdgeStochastic.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from ndlib.models.compartments.Compartment import Compartiment, ConfigurationException
import numpy as np
import networkx as nx

__author__ = 'Giulio Rossetti'
__license__ = "BSD-2-Clause"
Expand All @@ -18,7 +17,13 @@ def __init__(self, threshold=None, triggering_status=None, **kwargs):

def execute(self, node, graph, status, status_map, params, *args, **kwargs):
neighbors = list(graph.neighbors(node))
if isinstance(graph, nx.DiGraph):

try:
directed = graph.directed
except AttributeError:
directed = graph.is_directed()

if directed:
neighbors = list(graph.predecessors(node))

threshold = float(1)/len(neighbors)
Expand Down
8 changes: 6 additions & 2 deletions ndlib/models/compartments/NodeStochastic.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from ndlib.models.compartments.Compartment import Compartiment
import numpy as np
import networkx as nx

__author__ = 'Giulio Rossetti'
__license__ = "BSD-2-Clause"
Expand All @@ -16,7 +15,12 @@ def __init__(self, rate, triggering_status=None, **kwargs):

def execute(self, node, graph, status, status_map, *args, **kwargs):
neighbors = graph.neighbors(node)
if isinstance(graph, nx.DiGraph):
try:
directed = graph.directed
except AttributeError:
directed = graph.is_directed()

if directed:
neighbors = graph.predecessors(node)

p = np.random.random_sample()
Expand Down
9 changes: 7 additions & 2 deletions ndlib/models/compartments/NodeThreshold.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from ndlib.models.compartments.Compartment import Compartiment, ConfigurationException
import networkx as nx

__author__ = 'Giulio Rossetti'
__license__ = "BSD-2-Clause"
Expand All @@ -16,7 +15,13 @@ def __init__(self, threshold=None, triggering_status=None, **kwargs):
def execute(self, node, graph, status, status_map, params, *args, **kwargs):
neighbors = list(graph.neighbors(node))
test = False
if isinstance(graph, nx.DiGraph):

try:
directed = graph.directed
except AttributeError:
directed = graph.is_directed()

if directed:
neighbors = list(graph.predecessors(node))

if self.trigger is None:
Expand Down
9 changes: 4 additions & 5 deletions ndlib/models/epidemics/GeneralisedThresholdModel.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from ..DiffusionModel import DiffusionModel
import networkx as nx
import future.utils
import random
import queue
Expand Down Expand Up @@ -70,10 +69,10 @@ def iteration(self, node_status=True):
return 0, actual_status

gamma = float(self.params['model']['mu']) * float(self.actual_iteration) / float(self.params['model']['tau'])
list_node = self.graph.nodes()
list_node = self.graph.nodes
start = min(list_node)
stop = max(list_node)
number_node_susceptible = len(self.graph.nodes()) - sum(self.status.values())
number_node_susceptible = len(self.graph.nodes) - sum(self.status.values())

while gamma >= 1 and number_node_susceptible >= 1:
random_index = random.randrange(start, stop+1, 1)
Expand All @@ -82,12 +81,12 @@ def iteration(self, node_status=True):
gamma -= 1
number_node_susceptible -= 1

for u in self.graph.nodes():
for u in self.graph.nodes:
if actual_status[u] == 1:
continue

neighbors = list(self.graph.neighbors(u))
if isinstance(self.graph, nx.DiGraph):
if self.graph.directed:
neighbors = list(self.graph.predecessors(u))

infected = 0
Expand Down
5 changes: 2 additions & 3 deletions ndlib/models/epidemics/IndependentCascadesModel.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from ..DiffusionModel import DiffusionModel
import numpy as np
import future.utils
import networkx as nx

__author__ = 'Giulio Rossetti'
__license__ = "BSD-2-Clause"
Expand Down Expand Up @@ -62,7 +61,7 @@ def iteration(self, node_status=True):
return {"iteration": 0, "status": {},
"node_count": node_count.copy(), "status_delta": status_delta.copy()}

for u in self.graph.nodes():
for u in self.graph.nodes:
if self.status[u] != 1:
continue

Expand All @@ -80,7 +79,7 @@ def iteration(self, node_status=True):
if 'threshold' in self.params['edges']:
if key in self.params['edges']['threshold']:
threshold = self.params['edges']['threshold'][key]
elif (v, u) in self.params['edges']['threshold'] and not nx.is_directed(self.graph):
elif (v, u) in self.params['edges']['threshold'] and not self.graph.directed:
threshold = self.params['edges']['threshold'][(v, u)]

flip = np.random.random_sample()
Expand Down
5 changes: 2 additions & 3 deletions ndlib/models/epidemics/KerteszThresholdModel.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from ..DiffusionModel import DiffusionModel
import networkx as nx
import numpy as np
from scipy import stats
import future.utils
Expand Down Expand Up @@ -96,7 +95,7 @@ def iteration(self, node_status=True):
return {"iteration": 0, "status": {},
"node_count": node_count.copy(), "status_delta": status_delta.copy()}

for node in self.graph.nodes():
for node in self.graph.nodes:
if self.status[node] == 0:
if self.params['model']['adopter_rate'] > 0:
xk = (0, 1)
Expand All @@ -112,7 +111,7 @@ def iteration(self, node_status=True):
if len(neighbors) == 0:
continue

if isinstance(self.graph, nx.DiGraph):
if self.graph.directed:
neighbors = self.graph.predecessors(node)

infected = 0
Expand Down
5 changes: 2 additions & 3 deletions ndlib/models/epidemics/ProfileModel.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from ..DiffusionModel import DiffusionModel
import networkx as nx
import numpy as np
import future.utils
from scipy import stats
Expand Down Expand Up @@ -76,7 +75,7 @@ def iteration(self, node_status=True):
return {"iteration": 0, "status": {},
"node_count": node_count.copy(), "status_delta": status_delta.copy()}

for u in self.graph.nodes():
for u in self.graph.nodes:
if actual_status[u] != 0:
continue

Expand All @@ -91,7 +90,7 @@ def iteration(self, node_status=True):
continue

neighbors = self.graph.neighbors(u)
if isinstance(self.graph, nx.DiGraph):
if self.graph.directed:
neighbors = self.graph.predecessors(u)

infected = 0
Expand Down

0 comments on commit e210e53

Please sign in to comment.