diff --git a/examples/path_requests_run.py b/examples/path_requests_run.py index fc27508b..c64f6a99 100755 --- a/examples/path_requests_run.py +++ b/examples/path_requests_run.py @@ -180,21 +180,10 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist): # TODO change all these req, dsjct, res lists into dict ! path_res_list = [] - - # # Build the network once using the default power defined in SI in eqpt config - # # power density : db2linp(ower_dbm": 0)/power_dbm": 0 * nb channels as defined by - # # spacing, f_min and f_max - # p_db = equipment['SI']['default'].power_dbm - - # p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,\ - # equipment['SI']['default'].f_max, equipment['SI']['default'].spacing)) - # build_network(network, equipment, p_db, p_total_db) - # TODO : get the designed power to set it when it is not an input - # pathreq.power to be adapted for i,pathreq in enumerate(pathreqlist): # use the power specified in requests but might be different from the one specified for design - # TODO: set the power as an optional parameter for requests definition + # the power is an optional parameter for requests definition # if optional, use the one defines in eqt_config.json p_db = lin2db(pathreq.power*1e3) p_total_db = p_db + lin2db(pathreq.nb_channel) @@ -211,13 +200,18 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist): total_path = propagate(total_path,pathreq,equipment, show=False) else: total_path,mode = propagate_and_optimize_mode(total_path,pathreq,equipment, show=False) - pathreq.baud_rate = mode['baud_rate'] - pathreq.tsp_mode = mode['format'] - pathreq.format = mode['format'] - pathreq.OSNR = mode['OSNR'] - pathreq.bit_rate = mode['bit_rate'] - else: - total_path = [] + # if no baudrate satisfies spacing, no mode is returned and an empty path is returned + # a warning is shown in the propagate_and_optimize_mode + if mode is not None : + # propagate_and_optimize_mode function returns the mode with the highest bitrate + # that passes. if no mode passes, then it returns an empty path + pathreq.baud_rate = mode['baud_rate'] + pathreq.tsp_mode = mode['format'] + pathreq.format = mode['format'] + pathreq.OSNR = mode['OSNR'] + pathreq.bit_rate = mode['bit_rate'] + else : + total_path = [] # we record the last tranceiver object in order to have th whole # information about spectrum. Important Note: since transceivers # attached to roadms are actually logical elements to simulate @@ -301,7 +295,7 @@ if __name__ == '__main__': network = load_network(args.network_filename,equipment) # Build the network once using the default power defined in SI in eqpt config - # power density : db2linp(ower_dbm": 0)/power_dbm": 0 * nb channels as defined by + # TODO power density : db2linp(ower_dbm": 0)/power_dbm": 0 * nb channels as defined by # spacing, f_min and f_max p_db = equipment['SI']['default'].power_dbm diff --git a/gnpy/core/request.py b/gnpy/core/request.py index 0c7f9188..0969b3a4 100644 --- a/gnpy/core/request.py +++ b/gnpy/core/request.py @@ -121,7 +121,9 @@ class Result_element(Element): else: hop_type.append('not recorded') else: - mode = 'no mode' + # TODO differentiate empty path in case not feasible because of tsp or not feasible because + # ther is no path connecting the nodes (whatever the tsp) + mode = 'not feasible with this transponder' hop_type = ' - '.join([path_request.tsp,mode]) self.hop_type = hop_type uid = property(lambda self: repr(self)) @@ -400,28 +402,42 @@ def propagate_and_optimize_mode(path, req, equipment, show=False): baudrate_to_explore = list(set([m['baud_rate'] for m in equipment['Transceiver'][req.tsp].mode if float(m['baud_rate'])+12.5e9< req.spacing])) baudrate_to_explore = sorted(baudrate_to_explore, reverse=True) - found_a_feasible_mode = False - for b in baudrate_to_explore : - modes_to_explore = [m for m in equipment['Transceiver'][req.tsp].mode - if m['baud_rate'] == b] - modes_to_explore = sorted(modes_to_explore, - key = lambda x: x['bit_rate'], reverse=True) - # step2 : computes propagation for each baudrate: stop and select the first that passes - found_a_feasible_mode = False - # TODO : the case of roll of is not included: for now use SI one - si = create_input_spectral_information( - req.frequency['min'], equipment['SI']['default'].roll_off, - b, req.power, req.spacing, req.nb_channel) - for el in path: - si = el(si) - if show : - print(el) - for m in modes_to_explore : - if round(mean(path[-1].snr+lin2db(b/(12.5e9))),2) > m['OSNR'] : - found_a_feasible_mode = True - return path, m - # if no feasible path were found - return found_a_feasible_mode + if baudrate_to_explore : + # at least 1 baudrate can be tested wrt spacing + for b in baudrate_to_explore : + modes_to_explore = [m for m in equipment['Transceiver'][req.tsp].mode + if m['baud_rate'] == b] + modes_to_explore = sorted(modes_to_explore, + key = lambda x: x['bit_rate'], reverse=True) + # step2 : computes propagation for each baudrate: stop and select the first that passes + found_a_feasible_mode = False + # TODO : the case of roll of is not included: for now use SI one + # TODO : if the loop in mode optimization does not have a feasible path, then bugs + si = create_input_spectral_information( + req.frequency['min'], equipment['SI']['default'].roll_off, + b, req.power, req.spacing, req.nb_channel) + for el in path: + si = el(si) + if show : + print(el) + for m in modes_to_explore : + if round(mean(path[-1].snr+lin2db(b/(12.5e9))),2) > m['OSNR'] : + found_a_feasible_mode = True + return path, m + else: + mode = m + # only get to this point if no budrate/mode staisfies OSNR requirement + # returns the last propagated path and mode + msg = f'Warning! Request {req.request_id}: no mode satisfies path SNR requirement.\n' + print(msg) + logger.info(msg) + return [],None + else : + # no baudrate satisfying spacing + msg = f'Warning! Request {req.request_id}: no baudrate satisfies spacing requirement.\n' + print(msg) + logger.info(msg) + return path, None def jsontocsv(json_data,equipment,fileout): @@ -453,7 +469,7 @@ def jsontocsv(json_data,equipment,fileout): # find the min acceptable OSNR, baud rate from the eqpt library based on tsp (tupe) and mode (format) # loading equipment already tests the existence of tsp type and mode: - if mode !='no mode' : + if mode !='not feasible with this transponder' : [minosnr, baud_rate, bit_rate, cost] = next([m['OSNR'] , m['baud_rate'] , m['bit_rate'], m['cost']] for m in equipment['Transceiver'][tsp].mode if m['format']==mode) # else: @@ -471,9 +487,9 @@ def jsontocsv(json_data,equipment,fileout): path_bandwidth = next(e['accumulative-value'] for e in p['path-properties']['path-metric'] if e['metric-type'] == 'path_bandwidth') if isinstance(output_snr, str): - isok = '' - nb_tsp = '' - pthbdbw = '' + isok = False + nb_tsp = 0 + pthbdbw = round(path_bandwidth*1e-9,2) rosnr = '' rsnr = '' rsnrb = '' diff --git a/service-template.json b/service-template.json index fd23b58f..8d7a1d77 100644 --- a/service-template.json +++ b/service-template.json @@ -19,7 +19,8 @@ ], "spacing": null, "max-nb-of-channel": null, - "output-power": null + "output-power": null, + "path_bandwidth": null } }, "optimizations": { diff --git a/tests/test_disjunction.py b/tests/test_disjunction.py index 1bb6877e..286851b4 100644 --- a/tests/test_disjunction.py +++ b/tests/test_disjunction.py @@ -96,4 +96,12 @@ def test_does_not_loop_back(net,eqpt,serv): test = False break - assert test \ No newline at end of file + assert test + + # TODO : test that identical requests are correctly agregated + # and reproduce disjunction vector as well as route constraints + # check that requests with different parameters are not aggregated + + # check that the total agregated bandwidth is the same after aggregation + + # \ No newline at end of file