Skip to content

Commit

Permalink
Reconstruction algorithm - sbrp
Browse files Browse the repository at this point in the history
  • Loading branch information
edytafraszczak committed Jul 4, 2024
1 parent bd88000 commit cd20ac9
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 6 deletions.
26 changes: 23 additions & 3 deletions src/nsdlib/algorithms/algorithms_utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from functools import lru_cache
from typing import Dict, Set, List, Union

from netcenlib.common import nx_cached
from netcenlib.common.nx_cached import MAX_SIZE
from networkx import Graph
from typing import Dict, Set, List, Union

from nsdlib.algorithms import node_evaluation, outbreaks_detection
from nsdlib.algorithms import node_evaluation, outbreaks_detection, \
reconstruction
from nsdlib.common.models import SourceDetectionEvaluation, NODE_TYPE
from nsdlib.taxonomies import (
NodeEvaluationAlgorithm,
Expand All @@ -32,6 +32,15 @@ def evaluate_nodes(
return getattr(node_evaluation, function_name)(network, *args, **kwargs)


def reconstruct_propagation(
G: Graph, IG: Graph,
reconstruction_alg: PropagationReconstructionAlgorithm, *args, **kwargs
):
"""Reconstruct the propagation of a given network."""
function_name = f"{reconstruction_alg.value.lower()}"
return getattr(reconstruction, function_name)(G, IG, *args, **kwargs)


@lru_cache(maxsize=MAX_SIZE)
def identify_outbreaks_cached(
network: Graph, outbreaks_alg: OutbreaksDetectionAlgorithm, *args, **kwargs
Expand All @@ -48,10 +57,20 @@ def evaluate_nodes_cached(
return evaluate_nodes(network, evaluation_alg, *args, **kwargs)


@lru_cache(maxsize=MAX_SIZE)
def reconstruct_propagation_cached(
G: Graph, IG: Graph,
reconstruction_alg: PropagationReconstructionAlgorithm, *args, **kwargs
):
"""Reconstruct the propagation of a given network."""
return reconstruct_propagation(G, IG, reconstruction_alg, *args, **kwargs)


def compute_error_distances(
G: Graph, not_detected_sources: Set[int],
invalid_detected_sources: Set[int]
) -> Dict[NODE_TYPE, float]:
"""Compute the error distances for the source detection evaluation."""
if not_detected_sources and invalid_detected_sources:
return {source:
min(
Expand All @@ -73,6 +92,7 @@ def compute_source_detection_evaluation(
real_sources: List[NODE_TYPE],
detected_sources: Union[NODE_TYPE, List[NODE_TYPE]]
) -> SourceDetectionEvaluation:
"""Compute the evaluation of the source detection."""
detected_sources = (
detected_sources if isinstance(detected_sources, list) else [
detected_sources]
Expand Down
8 changes: 7 additions & 1 deletion src/nsdlib/algorithms/node_evaluation/dynamic_age.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@


def dynamic_age(network: Graph) -> Dict[int, float]:
"""Dynamic age source detection method."""
"""Dynamic age source detection method.
References
----------
- [1] V. Fioriti i M. Chinnici, „Predicting the sources of an outbreak with a spectral technique”, ArXiv12112333 Math-Ph Physicsphysics, lis. 2012, Dostęp: 6 maj 2021. [Online]. Dostępne na: http://arxiv.org/abs/1211.2333
"""
A = nx.adjacency_matrix(network).todense().A
dynamicAges = {node: 0 for node in network.nodes}
lamda_max = max(np.linalg.eigvals(A)).real
Expand Down
12 changes: 11 additions & 1 deletion src/nsdlib/algorithms/node_evaluation/jordan_center.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@


def jordan_center(network: Graph) -> Dict[int, float]:
"""Jordan center source detection method."""
"""Jordan center node evaluation method.
References
----------
- [1] L. Ying and K. Zhu,
"On the Universality of Jordan Centers for Estimating Infection Sources in Tree Networks"
IEEE Transactions of Information Theory, 2017
- [2] L. Ying and K. Zhu,
"Diffusion Source Localization in Large Networks"
Synthesis Lectures on Communication Networks, 2018
"""
scores = ncl.eccentricity_centrality(network)
return {v: 1 / scores.get(v) for v in network.nodes}
12 changes: 11 additions & 1 deletion src/nsdlib/algorithms/node_evaluation/net_sleuth.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,18 @@


def net_sleuth(network: Graph) -> Dict[int, float]:
"""Netsleuth source detection method."""
"""NetSleuth source evaluation method.
References
----------
- [1] B. A. Prakash, J. Vreeken, C. Faloutsos,
"Efficiently spotting the starting points of an epidemic in a large graph"
Knowledge and Information Systems, 2013
https://link.springer.com/article/10.1007/s10115-013-0671-5
- [2] L. Ying and K. Zhu,
"Diffusion Source Localization in Large Networks"
Synthesis Lectures on Communication Networks, 2018
"""
L = nx.laplacian_matrix(network).toarray()
eigenvalues, eigenvectors = np.linalg.eig(L)
largest_eigenvalue = max(eigenvalues)
Expand Down
2 changes: 2 additions & 0 deletions src/nsdlib/algorithms/reconstruction/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

from nsdlib.algorithms.reconstruction.sbrp import sbrp
37 changes: 37 additions & 0 deletions src/nsdlib/algorithms/reconstruction/sbrp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from networkx import Graph

from nsdlib.algorithms.reconstruction.utils import init_extended_network, \
compute_neighbors_probability, NODE_INFECTION_PROBABILITY_ATTR, \
remove_invalid_nodes


def sbrp(G: Graph, IG: Graph,
reconstruction_threshold=0.5,
max_iterations: int = 1) -> Graph:
"""SbRP graph reconstruction algorithm.
@param G: Network
@param IG: Infected network
@param reconstruction_threshold: Reconstruction threshold
@return: Extended network
References
----------
- [1] W. Zang, P. Zhang, C. Zhou, i L. Guo, „Discovering Multiple Diffusion Source Nodes in Social Networks”, Procedia Comput. Sci., t. 29, s. 443–452, 2014, doi: 10.1016/j.procs.2014.05.040.
- [2] W. Zang, P. Zhang, C. Zhou, i L. Guo, „Locating multiple sources in social networks under the SIR model: A divide-and-conquer approach”, J. Comput. Sci., t. 10, s. 278–287, wrz. 2015, doi: 10.1016/j.jocs.2015.05.002.
"""
EG = init_extended_network(G=G, IG=IG)
iter = 1
nodes = [1]
while iter < max_iterations and nodes:
iter += 1
for node in IG:
for neighbour in G.neighbors(node):
if neighbour in IG:
continue
EG.nodes[neighbour][
NODE_INFECTION_PROBABILITY_ATTR] = compute_neighbors_probability(
G=EG, node=neighbour)

remove_invalid_nodes(EG, reconstruction_threshold)
return EG
71 changes: 71 additions & 0 deletions src/nsdlib/algorithms/reconstruction/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import operator
from functools import reduce

import networkx as nx
from networkx import Graph

from nsdlib.common.models import NODE_TYPE

NODE_INFECTION_PROBABILITY_ATTR = "INFECTION_PROBABILITY"


def init_extended_network(G: Graph, IG: Graph) -> Graph:
"""
Initialize extended network.
@param G: Network
@param IG: Infected network
@return: Extended network
"""
EG = G.copy()
nx.set_node_attributes(
EG,
{
node: {NODE_INFECTION_PROBABILITY_ATTR: 1.0 if node in IG else 0.0}
for node in G
},
)
return EG


def compute_neighbors_probability(node: NODE_TYPE, G: Graph) -> float:
"""
Compute probability of infection for a given node.
@param node: Node
@param G: Graph
@return: Probability of infection for a given node
"""
neighbors_probability = [
G.nodes[node][NODE_INFECTION_PROBABILITY_ATTR] for node in
nx.neighbors(G, node)
]
return reduce(
operator.mul,
neighbors_probability,
1,
)


def remove_invalid_nodes(EG: Graph, threshold: float) -> Graph:
"""
Remove nodes with infection probability lower than threshold.
@param EG: Extended network
@param threshold: Infection probability threshold
@return: Extended network with removed nodes that have infection probability lower than threshold
"""
nodes_to_remove = []
for node in EG.nodes(data=True):
data = node[1]
infection_probability = data[NODE_INFECTION_PROBABILITY_ATTR]
if infection_probability < threshold:
nodes_to_remove.append(node[0])

EG.remove_nodes_from(nodes_to_remove)
EG.remove_nodes_from(list(nx.isolates(EG)))

return EG
1 change: 1 addition & 0 deletions src/nsdlib/source_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@


class SourceDetector:
"""Source detection generic algorithm."""
def __init__(self, config: SourceDetectionConfig):
self.config = config

Expand Down

0 comments on commit cd20ac9

Please sign in to comment.