33from concurrent .futures import ProcessPoolExecutor as Pool
44from importlib import reload
55from time import sleep
6+ from typing import Callable , Optional , Any , Dict , List
67
78from netqasm .logging .glob import get_netqasm_logger
89from netqasm .logging .output import (reset_struct_loggers ,
@@ -59,44 +60,70 @@ def reset(save_loggers=False):
5960 reload (logging )
6061
6162
62- def check_sim_backend (sim_backend ):
63+ def check_sim_backend (sim_backend : SimBackend ):
6364 if sim_backend in [SimBackend .PROJECTQ , SimBackend .QUTIP ]:
6465 assert has_module .main (sim_backend .value ), f"To use { sim_backend } as backend you need to install the package"
6566
6667
67- def run_sim_backend (node_names , sim_backend ):
68+ def run_sim_backend (node_names : List [ str ] , sim_backend : SimBackend , network_config_file : str ):
6869 logger .debug ("Starting simulaqron sim_backend process with nodes %s" , node_names )
69- check_sim_backend (sim_backend = sim_backend )
70+ check_sim_backend (sim_backend )
7071 simulaqron_settings .sim_backend = sim_backend .value
71- network = Network (name = "default" , nodes = node_names , force = True , new = True )
72+ network = Network (name = "default" , nodes = node_names , network_config_file = network_config_file , force = True , new = True )
7273 network .start ()
7374 return network
7475
7576
7677def run_applications (
7778 app_instance : ApplicationInstance ,
78- num_rounds = 1 ,
79- network_cfg = None ,
80- log_cfg = None ,
81- results_file = None ,
82- formalism = Formalism .KET ,
83- post_function = None ,
84- flavour = None ,
85- enable_logging = True ,
86- hardware = None ,
87- use_app_config = True , # whether to give app_config as argument to app's main()
88- ):
79+ num_rounds : int = 1 ,
80+ network_cfg : str = None , # WARNING - The type of this argument *cannot* be harmonized
81+ nv_cfg : Any = None , # Unused; it's here for harmonization with squidasm "simulate_application"
82+ log_cfg : LogConfig = None ,
83+ formalism : Formalism = Formalism .KET ,
84+ use_app_config : bool = True ,
85+ post_function : Optional [Callable ] = None ,
86+ enable_logging : bool = True ,
87+ hardware : Any = None , # Unused; it's here for harmonization with squidasm "simulate_application"
88+ ) -> List [Dict [str , Any ]]:
8989 """Executes functions containing application scripts,
9090
9191 Parameters
9292 ----------
93- applications : dict
93+ app_instance : ApplicationInstance
9494 Keys should be names of nodes
9595 Values should be the functions
96+ num_rounds : int
97+ Number executions for this simulation
98+ network_cfg:
99+ Path of the network configuration file.
100+ nv_cfg: Any
101+ Unused argument. Any parameter given here will be ignored.
102+ log_cfg: LogConfig
103+ Configuration for the logging.
104+ formalism: Formalism
105+ Qubit formalism to use for the simulation. On this value depends
106+ The SimulaQron backend to use.
107+ use_app_config: bool
108+ Whether to give app_config as argument to app's main()
109+ post_function: Optional[Callable]
110+ Function to execute after all rounds have been executed.
111+ enable_logging: bool
112+ Whether to enable logging.
113+ hardware: Any
114+ Unused argument. Any parameter given here will be ignored.
115+
116+ Returns
117+ -------
118+ List[Dict[str, Any]]
119+ List of dictionaries describing the application names and the simulation results.
120+ The i-th entry of the list will correspond to the i-th execution round of the
121+ simulation.
96122 """
97123 # app_names = [app_cfg.app_name for app_cfg in app_cfgs]
98- app_names = [program .party for program in app_instance .app .programs ]
99- sim_backend = _SIMULAQRON_BACKENDS [formalism ]
124+ app_names : List [str ] = [program .party for program in app_instance .app .programs ]
125+ sim_backend : SimBackend = _SIMULAQRON_BACKENDS [formalism ]
126+ timed_log_dir : str = ""
100127
101128 if enable_logging :
102129 log_cfg = LogConfig () if log_cfg is None else log_cfg
@@ -112,54 +139,59 @@ def run_applications(
112139 app_instance .logging_cfg .log_subroutines_dir = timed_log_dir
113140 app_instance .logging_cfg .comm_log_dir = timed_log_dir
114141
115- with Pool (len (app_names )) as executor :
116- # Start the backend process
117- network = run_sim_backend (app_names , sim_backend = sim_backend )
118-
119- # Start the application processes
120- app_futures = []
121-
122- programs = app_instance .app .programs
123- for program in programs :
124- inputs = app_instance .program_inputs [program .party ]
125- if use_app_config :
126- app_cfg = AppConfig (
127- app_name = program .party ,
128- node_name = program .party , # node name should be same as app name
129- main_func = program .entry ,
130- log_config = app_instance .logging_cfg ,
131- inputs = inputs ,
132- )
133- inputs ["app_config" ] = app_cfg
134- future = executor .submit (program .entry , ** inputs )
135- app_futures .append (future )
136-
137- # for app_cfg in app_cfgs:
138- # inputs = app_cfg.inputs
139- # if use_app_config:
140- # inputs['app_config'] = app_cfg
141- # future = executor.submit(app_cfg.main_func, **inputs)
142- # app_futures.append(future)
143-
144- # Join the application processes and the backend
145- names = [f'app_{ app_name } ' for app_name in app_names ]
146- results = {}
147- for future , name in as_completed (app_futures , names = names ):
148- results [name ] = future .result ()
149- # if results_file is not None:
150- # save_results(results=results, results_file=results_file)
151- if enable_logging :
152- assert timed_log_dir is not None
153- path = os .path .join (timed_log_dir , "results.yaml" )
154- dump_yaml (data = results , file_path = path )
155-
156- network .stop ()
142+ results : List [Dict [str , Any ]] = []
143+
144+ for _ in range (num_rounds ):
145+ with Pool (len (app_names )) as executor :
146+ # Start the backend process
147+ network = run_sim_backend (app_names , sim_backend , network_cfg )
148+
149+ # Start the application processes
150+ app_futures = []
151+
152+ programs = app_instance .app .programs
153+ for program in programs :
154+ inputs = app_instance .program_inputs [program .party ]
155+ if use_app_config :
156+ app_cfg = AppConfig (
157+ app_name = program .party ,
158+ node_name = program .party , # node name should be same as app name
159+ main_func = program .entry ,
160+ log_config = app_instance .logging_cfg ,
161+ inputs = inputs ,
162+ )
163+ inputs ["app_config" ] = app_cfg
164+ future = executor .submit (program .entry , ** inputs )
165+ app_futures .append (future )
166+
167+ # for app_cfg in app_cfgs:
168+ # inputs = app_cfg.inputs
169+ # if use_app_config:
170+ # inputs['app_config'] = app_cfg
171+ # future = executor.submit(app_cfg.main_func, **inputs)
172+ # app_futures.append(future)
173+
174+ # Join the application processes and the backend
175+ names = [f'app_{ app_name } ' for app_name in app_names ]
176+ result = {}
177+ for future , name in as_completed (app_futures , names = names ):
178+ result [name ] = future .result ()
179+ # if results_file is not None:
180+ # save_results(results=results, results_file=results_file)
181+ if enable_logging :
182+ assert timed_log_dir is not None
183+ path = os .path .join (timed_log_dir , "results.yaml" )
184+ dump_yaml (data = result , file_path = path )
185+
186+ results .append (result )
187+ network .stop ()
188+
189+ reset (save_loggers = True )
157190
158191 if enable_logging :
159192 process_logs .make_last_log (log_dir = timed_log_dir )
160193
161- reset (save_loggers = True )
162- return [results ]
194+ return results
163195
164196
165197def save_results (results , results_file ):
0 commit comments