2525
2626random .seed (45 )
2727
28+
2829class HistoryTemp (TypedDict , total = False ):
2930 """Type for history dictionaries."""
31+
3032 scores : list [int ]
31- layout_init : dict [int | str , tuple [int , int ] | list [tuple [int , int ]]]
32- layout_final : dict [int | str , tuple [int , int ] | list [tuple [int , int ]]]
33+ layout_init : dict [int | str , Any ] # tuple[int, int] | list[tuple[int, int]]]
34+ layout_final : dict [int | str , Any ] # tuple[int, int] | list[tuple[int, int]]]
3335
3436
3537def save_to_file (path : str , data : Any ) -> None : # noqa: ANN401
@@ -55,7 +57,7 @@ def __init__(
5557 free_rows : list [str ] | None = None ,
5658 t : int | None = None ,
5759 optimize_factories : bool = False ,
58- custom_layout : list [list [tuple [int ,int ]] | nx .Graph ] | None = None ,
60+ custom_layout : list [list [tuple [int , int ]] | nx .Graph ] | None = None ,
5961 routing : str = "static" ,
6062 ) -> None :
6163 """Initializes the Hill Climbing with Random Restarts algorithm.
@@ -133,7 +135,7 @@ def __init__(
133135 elif layout_type == "hex" :
134136 data_qubit_locs = lat .gen_layout_hex ()
135137 elif layout_type == "custom" :
136- if custom_layout is not None : # only for mypy
138+ if custom_layout is not None : # only for mypy
137139 data_qubit_locs = custom_layout [0 ]
138140 self .lat .G = custom_layout [1 ]
139141 else :
@@ -148,7 +150,9 @@ def __init__(
148150 num for tup in self .circuit for num in (tup if isinstance (tup , tuple ) else (tup ,))
149151 ]
150152 else :
151- flattened_qubit_labels = [num for tup in self .circuit if isinstance (tup , tuple ) for num in tup ] #isinstance only added for mypy
153+ flattened_qubit_labels = [
154+ num for tup in self .circuit if isinstance (tup , tuple ) for num in tup
155+ ] # isinstance only added for mypy
152156 self .q = max (flattened_qubit_labels ) + 1
153157 if self .q < len (self .data_qubit_locs ):
154158 self .data_qubit_locs = self .data_qubit_locs [: self .q ] # cut-off unnecessary qubit spots.
@@ -234,16 +238,22 @@ def add_left_g(g: nx.Graph) -> nx.Graph:
234238
235239 return g
236240
237- def evaluate_solution (self , layout : dict [int | str , tuple [int , int ] | list [tuple [int ,int ]]]) -> int :
241+ def evaluate_solution (self , layout : dict [int | str , tuple [int , int ] | list [tuple [int , int ]]]) -> int :
238242 """Evaluates the layout=solution according to self.metric."""
239243 terminal_pairs = translate_layout_circuit (self .circuit , layout )
240- factory_positions : list [tuple [int ,int ]]
241- #if type(layout["factory_positions"]) is list[tuple[int,int]] or list:
242- factory_positions = layout ["factory_positions" ]
243- #else:
244+ # factory_positions: list[tuple[int, int]]
245+ # if type(layout["factory_positions"]) is list[tuple[int,int]] or list:
246+ factory_positions_temp = layout ["factory_positions" ]
247+ if isinstance (factory_positions_temp , list ):
248+ factory_positions : list [tuple [int , int ]] = factory_positions_temp
249+ else :
250+ msg = "`layout['factory_positions']` must be of type list[tuple[int,int]] but this is not even a list."
251+ raise TypeError (msg )
252+
253+ # else:
244254 # msg = f"factory positions of layout must be list[tuple[int,int]]. But you got {type(layout['factory_positions'])}"
245255 # raise TypeError(msg)
246- router : ShortestFirstRouter | ShortestFirstRouterTGatesDyn | ShortestFirstRouterTGates
256+ router : ShortestFirstRouter | ShortestFirstRouterTGatesDyn | ShortestFirstRouterTGates
247257 if any (type (el ) is int for el in self .circuit ):
248258 if self .t is not None :
249259 if self .routing == "static" :
@@ -258,7 +268,7 @@ def evaluate_solution(self, layout: dict[int | str, tuple[int, int] | list[tuple
258268 router .G = self .lat .G .copy ()
259269 else : # if not custom, update self.lat.G by the router's G because m,n might differ from initial values.
260270 self .lat .G = router .G # also add to self
261- if self .free_rows is not None : # for mypy # noqa: SIM102
271+ if self .free_rows is not None : # for mypy # noqa: SIM102
262272 if "left" in self .free_rows :
263273 router .G = self .add_left_g (router .G )
264274 self .lat .G = router .G # also add to self
@@ -281,15 +291,15 @@ def evaluate_solution(self, layout: dict[int | str, tuple[int, int] | list[tuple
281291 cost : int
282292 if self .metric == "crossing" :
283293 if self .optimize_factories and any (type (el ) is int for el in self .circuit ):
284- router = cast ("ShortestFirstRouterTGates | ShortestFirstRouterTGatesDyn" , router )
294+ router = cast ("ShortestFirstRouterTGates | ShortestFirstRouterTGatesDyn" , router )
285295 cost = np .sum (router .count_crossings_per_layer (t_crossings = True ))
286296 elif self .optimize_factories is False and any (type (el ) is int for el in self .circuit ):
287- router = cast ("ShortestFirstRouterTGates | ShortestFirstRouterTGatesDyn" , router )
297+ router = cast ("ShortestFirstRouterTGates | ShortestFirstRouterTGatesDyn" , router )
288298 cost = np .sum (router .count_crossings_per_layer (t_crossings = False ))
289299 else :
290300 cost = np .sum (router .count_crossings_per_layer ())
291301 elif self .metric == "distance" :
292- router = cast ("ShortestFirstRouter" , router )
302+ router = cast ("ShortestFirstRouter" , router )
293303 distances = router .measure_terminal_pair_distances ()
294304 cost = np .sum (distances )
295305 if any (type (el ) is int for el in self .circuit ):
@@ -298,14 +308,14 @@ def evaluate_solution(self, layout: dict[int | str, tuple[int, int] | list[tuple
298308 if self .routing == "static" :
299309 vdp_layers = router .find_total_vdp_layers ()
300310 elif self .routing == "dynamic" :
301- router = cast ("ShortestFirstRouterTGatesDyn" , router )
311+ router = cast ("ShortestFirstRouterTGatesDyn" , router )
302312 vdp_layers = router .find_total_vdp_layers_dyn ()
303313 cost = len (vdp_layers )
304314 return cost
305315
306- def gen_random_qubit_assignment (self ) -> dict [int | str , tuple [int , int ] | list [tuple [int ,int ]]]:
316+ def gen_random_qubit_assignment (self ) -> dict [int | str , tuple [int , int ] | list [tuple [int , int ]]]:
307317 """Yields a random qubit assignment given the `data_qubit_locs`."""
308- layout : dict [int | str , tuple [int , int ] | list [tuple [int ,int ]]] = {}
318+ layout : dict [int | str , tuple [int , int ] | list [tuple [int , int ]]] = {}
309319 perm = list (range (self .q ))
310320 random .shuffle (perm )
311321 for i , j in zip (
@@ -323,7 +333,9 @@ def gen_random_qubit_assignment(self) -> dict[int | str, tuple[int, int] | list[
323333
324334 return layout
325335
326- def gen_neighborhood (self , layout : dict [int | str , tuple [int , int ] | list [tuple [int ,int ]]]) -> list [dict [int | str , tuple [int , int ] | list [tuple [int ,int ]]]]:
336+ def gen_neighborhood (
337+ self , layout : dict [int | str , tuple [int , int ] | list [tuple [int , int ]]]
338+ ) -> list [dict [int | str , tuple [int , int ] | list [tuple [int , int ]]]]:
327339 """Creates the Neighborhood of a given layout by going through each terminal pair and swapping their positions.
328340
329341 If there are no T gates, there will be l=len(terminal_pairs) elements in the neighborhood.
@@ -364,12 +376,9 @@ def gen_neighborhood(self, layout: dict[int | str, tuple[int, int] | list[tuple[
364376
365377 return neighborhood
366378
367- def _parallel_hill_climbing (self , restart : int ) -> tuple [
368- int ,
369- dict [int | str , tuple [int , int ] | list [tuple [int ,int ]]],
370- int ,
371- HistoryTemp
372- ]:
379+ def _parallel_hill_climbing (
380+ self , restart : int
381+ ) -> tuple [int , dict [int | str , tuple [int , int ] | list [tuple [int , int ]]], int , HistoryTemp ]:
373382 """Helper method for parallel execution of hill climbing restarts.
374383
375384 Args:
@@ -408,7 +417,9 @@ def _parallel_hill_climbing(self, restart: int) -> tuple[
408417 history_temp .update ({"layout_final" : current_solution .copy ()})
409418 return restart , current_solution , current_score , history_temp
410419
411- def run (self , prefix : str , suffix : str , parallel : bool , processes : int = 8 ) -> tuple [dict [int | str , tuple [int , int ] | list [tuple [int , int ]]], int , int , dict [int ,HistoryTemp ]]:
420+ def run (
421+ self , prefix : str , suffix : str , parallel : bool , processes : int = 8
422+ ) -> tuple [dict [int | str , tuple [int , int ] | list [tuple [int , int ]]], int , int , dict [int , HistoryTemp ]]:
412423 """Executes the Hill Climbing algorithm with random restarts.
413424
414425 Args:
@@ -495,7 +506,10 @@ def run(self, prefix: str, suffix: str, parallel: bool, processes: int = 8) -> t
495506 return best_solution , best_score , best_rep , score_history
496507
497508 def plot_history (
498- self , score_history : HistoryTemp , filename : str = "./hc_history_plot.pdf" , size : tuple [float , float ] = (5 , 5 )
509+ self ,
510+ score_history : dict [int , HistoryTemp ],
511+ filename : str = "./hc_history_plot.pdf" ,
512+ size : tuple [float , float ] = (5 , 5 ),
499513 ) -> None :
500514 """Plots the scores for each restart and iteration.
501515
0 commit comments