gnpy.topology

Tracking request for spectrum and their spectrum_assignment.

gnpy.topology.request

This module contains path request functionality.

This functionality allows the user to provide a JSON request file in accordance with a Yang model for requesting path computations and returns path results in terms of path and feasibility

See: draft-ietf-teas-yang-path-computation-01.txt

class gnpy.topology.request.Disjunction(**params)

Bases: object

the class that contains all attributes related to disjunction constraints

class gnpy.topology.request.PathRequest(**params)

Bases: object

the class that contains all attributes related to a request

class gnpy.topology.request.ResultElement(path_request, computed_path, reversed_computed_path=None)

Bases: object

property detailed_path_json

a function that builds path object for normal and blocking cases

property json
property path_properties

a function that returns the path properties (metrics, crossed elements) into a dict

property pathresult

create the result dictionnary (response for a request)

property uid
gnpy.topology.request._get_srce_dest_trx(path_route_objects, emitter_index, receiver_index)
gnpy.topology.request._jsontoparams(path_response, trx_type, trx_mode, equipment)

Determine optical params from transponder type and trx_mode and reads the path_properties and metrics

It supports the no-mode case. It returns a tuple of values corresponding to csv fields jsontoparamsfields + cost

gnpy.topology.request._jsontopath_metric(path_metric)

Reads the accupulated values of metrics in the json dict

returns the values in the required unit and format for CSV export

gnpy.topology.request._penalty_msg(total_path, msg, min_ind)

formatting helper for reporting unfeasible paths

The penalty info are optional, so this checks that penalty exists before creating a message.

gnpy.topology.request.compare_reqs(req1, req2, disjlist)

compare two requests: returns True or False

gnpy.topology.request.compute_constrained_path(network, req)
gnpy.topology.request.compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list)
gnpy.topology.request.compute_path_with_disjunction(network, equipment, pathreqlist, pathlist, redesign=False)

use a list but a dictionnary might be helpful to find path based on request_id

TODO change all these req, dsjct, res lists into dict !

gnpy.topology.request.compute_spectrum_slot_vs_bandwidth(bandwidth, spacing, bit_rate, slot_width=12500000000.0)

Compute the number of required wavelengths and the M value (number of consumed slots)

Each wavelength consumes one spacing, and the result is rounded up to consume a natural number of slots.

>>> compute_spectrum_slot_vs_bandwidth(400e9, 50e9, 200e9)
(2, 8)
gnpy.topology.request.correct_json_route_list(network, pathreqlist)

all names in list should be exact name in the network, and there is no ambiguity

This function only checks that list is correct, warns user if the name is incorrect and suppresses the constraint it it is loose or raises an error if it is strict

gnpy.topology.request.deduplicate_disjunctions(disjn)

clean disjunctions to remove possible repetition

gnpy.topology.request.explicit_path(node_list, source, destination, network)

if list of nodes leads to adjacent oms, then means that the path is explicit, and no need to compute the function returns the explicit path (including source and destination ROADMs)

gnpy.topology.request.filter_si(path: list, equipment: dict, si: SpectralInformation) SpectralInformation

Filter spectral information based on the amplifiers common range

gnpy.topology.request.find_elements_common_range(el_list: list, equipment: dict) List[dict]

Find the common frequency range of amps of a given list of elements (for example an OMS or a path) If there are no amplifiers in the path, then use the SI

gnpy.topology.request.find_reversed_path(pth)

select of intermediate roadms and find the path between them note that this function may not give an exact result in case of multiple links between two adjacent nodes.

gnpy.topology.request.get_penalty_from_receiver(receiver, impairment)

Read penalty if impairment is in the list

gnpy.topology.request.is_adjacent(oms1, oms2)

oms1’s egress ROADM is oms2’s ingress ROADM

gnpy.topology.request.isdisjoint(pth1, pth2)

returns 0 if disjoint

gnpy.topology.request.ispart(ptha, pthb)

the functions takes two paths a and b and retrns True if all a elements are part of b and in the same order

gnpy.topology.request.jsontocsv(json_data, equipment, fileout)

Reads json path result file in accordance with: Yang model for requesting Path Computation draft-ietf-teas-yang-path-computation-01.txt. and write results in an CSV file

gnpy.topology.request.penalty_msg(receiver, msg, min_ind, required_osnr, system_margins)

Returns a message that contains complementary reasons for blocking Reason can be that lowest GSNR is below threshold, or that accumulated impairment adds a lot of penalty This message is intended to help identifying causes of blocking

gnpy.topology.request.propagate(path, req, equipment)

propagates signals in each element according to initial spectrum set by user Spectrum is specified in request through f_min, f_max and spacing, or initial_spectrum and amps frequency band on the path is used to filter out frequencies

gnpy.topology.request.propagate_and_optimize_mode(path, req, equipment)
gnpy.topology.request.read_property(path_metric, metric_type)

Return the accumulative-value of a metric_type if it exists else return an empty string

gnpy.topology.request.remove_candidate(candidates, allpaths, rqst, pth)

filter duplicate candidates

gnpy.topology.request.requests_aggregation(pathreqlist, disjlist)

this function aggregates requests so that if several requests exist between same source and destination and with same transponder type If transponder mode is defined and identical, then also agregates demands.

gnpy.topology.spectrum_assignment

This module contains the Oms and Bitmap classes and methods to select and assign spectrum. The spectrum_selection() function identifies the free slots and select_candidate() selects the candidate spectrum according to strategy: for example first fit oms records its elements, and elements are updated with an oms to have element/oms correspondace

class gnpy.topology.spectrum_assignment.Bitmap(f_min, f_max, grid, guardband=25000000000.0, bitmap=None)

Bases: object

records the spectrum occupation

geti(nvalue)

converts the local index into n (itu grid)

getn(i)

converts the n (itu grid) into a local index

insert_left(newbitmap)

insert bitmap on the left to align oms bitmaps if their start frequencies are different

insert_right(newbitmap)

insert bitmap on the right to align oms bitmaps if their stop frequencies are different

class gnpy.topology.spectrum_assignment.BitmapValue(*values)

Bases: Enum

Bitmap allowed values

FREE = 1
OCCUPIED = 0
UNUSABLE = 'u'
class gnpy.topology.spectrum_assignment.OMS(**params)

Bases: object

OMS class is the logical container that represent a link between two adjacent ROADMs and records the crossed elements and the occupied spectrum

add_element(elem: Roadm | Transceiver | Edfa | Multiband_amplifier | Fiber | RamanFiber | Fused)

records oms elements

add_service(service_id: str, nb_wl: int)

record service and mark spectrum as occupied

assign_spectrum(nvalue: int, mvalue: int)

change oms spectrum to mark spectrum assigned

update_spectrum(f_min: float, f_max: float, guardband=25000000000.0, existing_spectrum: List[str | int] | None = None, grid: float = 6250000000.0)

Updates spectrum with an existing bitmap. Frequencies expressed in Hz.

Use ITU-T G694.1 Flexible DWDM grid definition For the flexible DWDM grid, the allowed frequency slots have a nominal central frequency (in THz) defined by: 193.1 + n × 0.00625 where n is a positive or negative integer including 0 and 0.00625 is the nominal central frequency granularity in THz and a slot width defined by: 12.5 × m where m is a positive integer and 12.5 is the slot width granularity in GHz. Any combination of frequency slots is allowed as long as no two frequency slots overlap. If bitmap is not None, then use it: Bitmap checks its consistency with f_min f_max else a brand new bitmap is created

class gnpy.topology.spectrum_assignment.OMSParams(oms_id, el_id_list, el_list)

Bases: tuple

_asdict()

Return a new dict which maps field names to their values.

_field_defaults = {}
_fields = ('oms_id', 'el_id_list', 'el_list')
classmethod _make(iterable)

Make a new OMSParams object from a sequence or iterable

_replace(**kwds)

Return a new OMSParams object replacing specified fields with new values

el_id_list

Alias for field number 1

el_list

Alias for field number 2

oms_id

Alias for field number 0

gnpy.topology.spectrum_assignment.aggregate_oms_bitmap(path_oms: List[int], oms_list: List[OMS]) OMS

Returns an OMS class with spectral occupation union of all oms spectral occupation in the path

this is usefull to find an and to and free set of slots on the path

gnpy.topology.spectrum_assignment.align_grids(oms_list: List[OMS]) List[OMS]

Used to apply same grid to all oms : same starting n, stop n and slot size.Out of grid slots are set to 0.

gnpy.topology.spectrum_assignment.bitmap_sum(band1: List[BitmapValue], band2: List[BitmapValue]) List[BitmapValue]

mark occupied bitmap by 0 if the slot is occupied in band1 or in band2

gnpy.topology.spectrum_assignment.build_oms_list(network: DiGraph, equipment: dict) List[OMS]

initialization of OMS list in the network

an oms is build reading all intermediate nodes between two adjacent ROADMs each element within the list is being added an oms and oms_id to record the oms it belongs to. the function supports different spectrum width and supposes that the whole network works with the min range among OMSs

gnpy.topology.spectrum_assignment.build_path_oms_id_list(pth: List[Roadm | Transceiver | Edfa | Multiband_amplifier | Fiber | RamanFiber | Fused]) List[int]

Returns the list of oms_id composing the path pth

gnpy.topology.spectrum_assignment.compute_n_m(required_m: int, rq: PathRequest, path_oms: List[int], oms_list: List[OMS], per_channel_m: int, policy: str = 'first_fit') Tuple[list, list, int]

based on requested path_bandwidth fill in M=None values with uint values, using per_channel_m and center frequency, with first fit strategy. The function checks the available spectrum but check consistencies among M values of the request, but not with other requests. For example, if request is for 32 slots corresponding to 8 x 4 slots of 32Gbauds channels, the following frequency slots will result in the following assignment

N = 0, 8, 16, 32 -> 0, 8, 16, 32 M = 8, None, 8, None -> 8, 8, 8, 8

N = 0, 8, 16, 32 -> 0, , 16 M = None, None, 8, None -> 24, , 8

gnpy.topology.spectrum_assignment.create_oms_bitmap(oms: OMS, equipment: dict, f_min: float, f_max: float, grid: float) List[BitmapValue]

Create the bitmap window corresponding to the common frequency range on the OMS. f_min is the min central frequency but if the channel is 50GHz witdth it occupies 4 slots around this central frequency. We took the convention that central frequency is relative index 0 -4 -3 -2 -1 0 1 2 3 ___________ ^__________ so that the channel occupies index(f_min) - 4 to index(f_min) + 3 on the occupation bitmap

Parameters:
  • oms – oms object containing the list of elements with their own spectral occupation

  • equipment – equipment library

  • f_max (f_min,) – central frequency range in Hz

gnpy.topology.spectrum_assignment.determine_slot_numbers(test_oms: OMS, requested_n: int, required_m: int, per_channel_m: int) int

determines max availability around requested_n. requested_n should not be None

gnpy.topology.spectrum_assignment.find_network_freq_range(network: DiGraph) Tuple[float, float]

Find the lowest freq from amps and highest freq among all amps to determine the resulting bitmap

gnpy.topology.spectrum_assignment.frequency_to_n(freq: float, grid: float = 6250000000.0) int

converts frequency into the n value (ITU grid)

reference to Recommendation G.694.1 (02/12), Figure I.3 https://www.itu.int/rec/T-REC-G.694.1-201202-I/en

>>> frequency_to_n(193.1375e12)
6
>>> frequency_to_n(193.225e12)
20
gnpy.topology.spectrum_assignment.m_to_freq(nvalue: int, mvalue: int, grid: float = 6250000000.0) Tuple[float, float]

converts m into frequency range

spectrum(13,7) is (193137500000000.0, 193225000000000.0) reference to Recommendation G.694.1 (02/12), Figure I.3 https://www.itu.int/rec/T-REC-G.694.1-201202-I/en

>>> fstart, fstop = m_to_freq(13, 7)
>>> fstart
193137500000000.0
>>> fstop
193225000000000.0
gnpy.topology.spectrum_assignment.mvalue_to_slots(nvalue: int, mvalue: int) Tuple[int, int]

convert center n an m into start and stop n

gnpy.topology.spectrum_assignment.nvalue_to_frequency(nvalue: int, grid: float = 6250000000.0) float

converts n value into a frequency

reference to Recommendation G.694.1 (02/12), Table 1 https://www.itu.int/rec/T-REC-G.694.1-201202-I/en

>>> nvalue_to_frequency(6)
193137500000000.0
>>> nvalue_to_frequency(-1, 0.1e12)
193000000000000.0
gnpy.topology.spectrum_assignment.pth_assign_spectrum(pths: List[Roadm | Transceiver | Edfa | Multiband_amplifier | Fiber | RamanFiber | Fused], rqs: List[PathRequest], oms_list: List[OMS], rpths: List[Roadm | Transceiver | Edfa | Multiband_amplifier | Fiber | RamanFiber | Fused], policy='first_fit')

basic first fit assignment

if reversed path are provided, means that occupation is bidir

gnpy.topology.spectrum_assignment.reversed_oms(oms_list: List[OMS])

identifies reversed OMS

only applicable for non parallel OMS

gnpy.topology.spectrum_assignment.select_candidate(candidates: List[Tuple[int, int, int]], policy: str) Tuple[int, int, int]

selects a candidate among all available spectrum

gnpy.topology.spectrum_assignment.slots_to_m(startn: int, stopn: int) Tuple[int, int]

converts the start and stop n values to the center n and m value

reference to Recommendation G.694.1 (02/12), Figure I.3 https://www.itu.int/rec/T-REC-G.694.1-201202-I/en

>>> nval, mval = slots_to_m(6, 20)
>>> nval
13
>>> mval
7
gnpy.topology.spectrum_assignment.spectrum_selection(test_oms: OMS, requested_m: int, requested_n: int | None = None, policy: str = 'first_fit') Tuple[int, int, int] | Tuple[None, None, None]

Collects spectrum availability and call the select_candidate function