"""
Dynamic topology
================

This example shows how to generate a topology, an event schedule and a traffic
matrix.

In this specific example we create a Waxman topology and create an event
schedule listing random link failures and restores and generate a static
traffic matrix.

This scenario could be used to assess the performance of a routing algorithm
in case of frequent link failures.
"""
import fnss
import random

# generate a Waxman1 topology with 200 nodes
topology = fnss.waxman_1_topology(n=200, alpha=0.4, beta=0.1, L=1)

# assign constant weight (1) to all links
fnss.set_weights_constant(topology, 1)


# set delay equal to 1 ms to all links
fnss.set_delays_constant(topology, 1, 'ms')

# set varying capacities among 10, 100 and 1000 Mbps proprtionally to edge
# betweenness centrality
fnss.set_capacities_edge_betweenness(topology, [10, 100, 1000], 'Mbps')

    
# now create a static traffic matrix assuming all nodes are both origins
# and destinations of traffic
traffic_matrix = fnss.static_traffic_matrix(topology, mean=2, stddev=0.2, max_u=0.5)

# This is the event generator function, which generates link failure events
def rand_failure(links):
    link = random.choice(links)
    return {'link': link, 'action': 'down'}

# Create schedule of link failures
event_schedule = fnss.poisson_process_event_schedule(
                        avg_interval=0.5,               # 0.5 min = 30 sec
                        t_start=0,                      # starts at 0
                        duration= 60,                   # 2 hours
                        t_unit='min',                   # minutes
                        event_generator= rand_failure,  # event gen function
                        links=topology.edges(),         # 'links' argument
                        )

# Now let's create a schedule with link restoration events
# We assume that the duration of a failure is exponentially distributed with
# average 1 minute.
restore_schedule = fnss.EventSchedule(t_start=0, t_unit='min')
for failure_time, event in event_schedule:
    link = event['link']
    restore_time = failure_time + random.expovariate(1)
    restore_schedule.add(time=restore_time, 
                         event={'link': link, 'action': 'up'},
                         absolute_time=True
                         )

# Now merge failure and restoration schedules
# After merging events are still chronologically sorted
event_schedule.add_schedule(restore_schedule)

# Note: there are several ways to create this link failure-restoration schedule
# This method has been used to illustrate a variety of functions and methods
# that FNSS provides to manipulate event schedules

# Write topology, event schedule and traffic matrix to files
fnss.write_topology(topology, 'topology.xml')
fnss.write_event_schedule(event_schedule, 'event_schedule.xml')
fnss.write_traffic_matrix(traffic_matrix, 'traffic_matrix.xml')



