Source code for uxsim.scenario_reader_writer

"""
Scenario reader and writer using toml.
"""

import functools
import inspect
from collections import defaultdict as ddict
import dill as pickle

[docs] def demand_info_record(func): """ A decorator to record arguments of `World.addVehicle`, `World.adddemand`, etc used in secenario definition in World object. """ @functools.wraps(func) def wrapper(self, *args, **kwargs): # 関数名を取得 func_name = func.__name__ # 引数の情報を取得 bound_args = inspect.signature(func).bind(self, *args, **kwargs) bound_args.apply_defaults() # self引数を除外 arg_dict = dict(list(bound_args.arguments.items())[1:]) # direct_call=Trueが含まれている場合のみ保存 if arg_dict.get('direct_call') == True: # direct_callを除いた引数を保存 arg_dict_to_save = {k: v for k, v in arg_dict.items() if k != 'direct_call'} #arg_dict_to_save["] = func_name # 関数名と引数をdict_func_argsに格納 self.demand_info[func_name].append(arg_dict_to_save) # 元の関数を呼び出す return func(self, *args, **kwargs) return wrapper
[docs] def instance_to_arg_dict(instance): """ Convert an instance's attributes to a dictionary of constructor arguments. This function inspects an object instance and creates a dictionary of arguments that could be used to recreate the instance. It uses the signature of the class's __init__ method to determine which attributes to include. Parameters ---------- instance : object The instance to convert to a dictionary of arguments. Returns ------- dict A dictionary where keys are parameter names and values are the corresponding attribute values from the instance. Notes ----- - Parameters with default values are omitted if the instance's value matches the default. - The 'self' parameter is always ignored. - The 'W' parameter, if present, is removed from the resulting dictionary. - Attributes of type 'Node' or 'Link' are replaced with their 'name' attribute. """ # クラスの__init__メソッドのシグネチャを取得 signature = inspect.signature(instance.__class__.__init__) # インスタンス変数を取得 instance_vars = vars(instance) # 引数リストを作成 args = {} for param_name, param in signature.parameters.items(): if param_name == 'self': continue value = instance_vars.get(param_name, param.default) if value == param.default: continue args[param_name] = value for param in list(args): if param == "W": del args[param] elif str(type(args[param])) == "<class 'uxsim.uxsim.Node'>": args[param] = args[param].name elif str(type(args[param])) == "<class 'uxsim.uxsim.Link'>": args[param] = args[param].name return args
[docs] def save_scenario(W, fname, network=True, demand=True): """ Save scenario data to a file. This function saves various components of a scenario, including meta data, network information (nodes and links), and demand information, to a file using pickle serialization. Parameters ---------- W : World The world to be saved fname : str The file name or path where the scenario data will be saved. network : bool, optional If True, save network information (nodes and links). Default is True. demand : bool, optional If True, save demand information. Default is True. Notes ----- The function uses the pickle module to serialize the data. The saved file will be in binary format. The saved data structure is a dictionary containing: - 'meta_data': Meta data from W.meta_data - 'Nodes' and 'Links': Network information (if network=True) - Demand information from W.demand_info (if demand=True) """ out = {"meta_data": W.meta_data} if network: nodes = [] for n in W.NODES: nodes.append(instance_to_arg_dict(n)) links = [] for l in W.LINKS: links.append(instance_to_arg_dict(l)) network = { "Nodes": nodes, "Links": links } out = out | network if demand: out = out | dict(W.demand_info) # from pprint import pprint # pprint(out) with open(fname, "wb") as f: pickle.dump(out, f)
[docs] def load_scenario(W, fname, network=True, demand=True): """ Load scenario data from a file. This function loads various components of a scenario, including meta data, network information (nodes and links), and demand information, from a file created by the save_scenario function. Parameters ---------- W : World The world to which the scenario data will be loaded. fname : str The file name or path from which the scenario data will be loaded. network : bool, optional If True, load network information (nodes and links). Default is True. demand : bool, optional If True, load demand information. Default is True. """ with open(fname, "rb") as f: dat = pickle.load(f) # from pprint import pprint # pprint(dat) print(f"loading scenario from '{fname}'") if dat["meta_data"]: if type(dat["meta_data"]) is dict: for key in dat["meta_data"]: print("", key, ":", dat["meta_data"][key]) else: print("", dat["meta_data"]) if network: for n in dat["Nodes"]: W.addNode(**n) for l in dat["Links"]: W.addLink(**l) print(" Number of loaded nodes:", len(dat["Nodes"])) print(" Number of loaded links:", len(dat["Links"])) if demand: for demand_type in dat: if demand_type == 'adddemand': for dem in dat[demand_type]: W.adddemand(**dem) print(f" Number of loaded `{demand_type}`s:", len( dat[demand_type])) elif demand_type == 'adddemand_point2point': for dem in dat[demand_type]: W.adddemand_point2point(**dem) print(f" Number of loaded `{demand_type}`s:", len( dat[demand_type])) if demand_type == 'adddemand_area2area': for dem in dat[demand_type]: W.adddemand_area2area(**dem) print(f" Number of loaded `{demand_type}`s:", len( dat[demand_type]))