Skip to content
Snippets Groups Projects
network.py 2.38 KiB
from itertools import combinations

import networkx as nx

from .core import TickProcess

from .packet import PacketGenerator
from .node import NodeFactory
from .routers import types as routers
from .traces import types as traces

class Network:
    ''''''
    def __init__(self, env,
                 packets=None,
                 node_factory=None,
                 community=None,
                 trace=None):
        ''''''
        self.env = env

        # contact trace
        if trace is None:
            trace = traces['random']()
        self.trace = trace
        self.trace.start(env, network=self)

        # community detection
        self.community = community
        if community is not None:
            self.community.start(env, network=self)

        # packet generation
        if packets is None:
            packets = {}
        self.packets = PacketGenerator(**packets)
        self.packets.start(env, network=self)

        # create node network
        if node_factory is None:
            node_factory = NodeFactory(tick_rate=1, router=routers['direct'])
        self.nodes = [
            node_factory(self, nid)
            for nid in range(self.trace.nodes)
        ]
        self.links = [
            (a, b)
            for a, b in combinations(self.nodes, 2)
        ]

        # set up networkx graph
        self.graph = nx.Graph()
        self.graph.add_nodes_from(self.nodes)
        self.graph.add_edges_from([
            (a, b, { 'state': False })
            for a, b in self.links
        ])

    def set_link(self, a, b, state):
        if isinstance(a, int):
            a = self.nodes[a]

        if isinstance(b, int):
            b = self.nodes[b]

        edge = self[a][b]
        if edge['state'] == state:
            return

        if state is None:
            state = not edge['state']
        edge['state'] = state

        if self.community:
            self.community.set_link(a, b, state, self.env.now)

        if state:
            a.route_packets()
            b.route_packets()

    def toggle_link(self, a, b):
        self.set_link(a, b, None)

    def send_link(self, a, b, packet):
        ''''''
        if self.graph[a][b]['state']:
            # TODO: transfer delay
            b.recv(packet)
        else:
            raise Exception('Nodes {} and {} not connected'.format(a, b))

    def __getitem__(self, node):
        ''''''
        return self.graph[node]