1515import pickle
1616from itertools import combinations
1717from pathlib import Path
18- from typing import TYPE_CHECKING , Dict , NewType , Set , Tuple
18+ from typing import TYPE_CHECKING , Dict , NewType , Optional , Set , Tuple
1919
2020if TYPE_CHECKING : # pragma: no cover
21+ from collections .abc import Iterable
22+
2123 from matplotlib import figure
22- from qiskit .providers import Backend
24+ from qiskit .providers import BackendV1
25+ from typing_extensions import TypeAlias
2326
2427 from mqt .qmap import Architecture
2528
2629
30+ import contextlib
31+
2732import rustworkx as rx
33+ import rustworkx .visualization as rxviz
34+
35+ with contextlib .suppress (TypeError ):
36+ Graph : TypeAlias = rx .PyGraph [int , Optional [int ]]
37+
2838
2939PartialOrder = NewType ("PartialOrder" , Dict [Tuple [int , int ], Set [Tuple [int , int ]]])
3040
@@ -40,7 +50,7 @@ class SubarchitectureOrder:
4050
4151 def __init__ (self ) -> None :
4252 """Initialize a partial order."""
43- self .arch : rx . PyGraph = rx .PyGraph ()
53+ self .arch : Graph = rx .PyGraph ()
4454 self .subarch_order : PartialOrder = PartialOrder ({})
4555 self .desirable_subarchitectures : PartialOrder = PartialOrder ({})
4656 self .isomorphisms : dict [tuple [int , int ], dict [tuple [int , int ], dict [int , int ]]] = {}
@@ -50,7 +60,7 @@ def __init__(self) -> None:
5060 self .__compute_desirable_subarchitectures ()
5161
5262 @classmethod
53- def from_retworkx_graph (cls , graph : rx . PyGraph ) -> SubarchitectureOrder :
63+ def from_retworkx_graph (cls , graph : Graph ) -> SubarchitectureOrder :
5464 """Construct the partial order from retworkx graph.
5565
5666 Args:
@@ -68,24 +78,24 @@ def from_retworkx_graph(cls, graph: rx.PyGraph) -> SubarchitectureOrder:
6878 return so
6979
7080 @classmethod
71- def from_coupling_map (cls , coupling_map : set [ tuple [ int , int ]] | list [tuple [int , int ]]) -> SubarchitectureOrder :
81+ def from_coupling_map (cls , coupling_map : Iterable [tuple [int , int ]]) -> SubarchitectureOrder :
7282 """Construct partial order from coupling map defined as set of tuples of connected qubits.
7383
7484 Args:
75- coupling_map: Set or list of tuples of connected qubits.
85+ coupling_map: Iterable of tuples of connected qubits.
7686
7787 Returns:
7888 The resulting partial order.
7989 """
8090 num_nodes = max (max (int (u ), int (v )) for u , v in coupling_map )
81- graph = rx .PyGraph ()
91+ graph : Graph = rx .PyGraph ()
8292 graph .add_nodes_from (list (range (num_nodes + 1 )))
83- graph .add_edges_from_no_data ([ tuple ( edge ) for edge in coupling_map ] )
93+ graph .add_edges_from_no_data (list ( coupling_map ) )
8494
8595 return cls .from_retworkx_graph (graph )
8696
8797 @classmethod
88- def from_backend (cls , backend : Backend ) -> SubarchitectureOrder :
98+ def from_backend (cls , backend : BackendV1 ) -> SubarchitectureOrder :
8999 """Construct the partial order from a coupling map defined as a Qiskit backend.
90100
91101 Args:
@@ -144,7 +154,7 @@ def from_string(cls, name: str) -> SubarchitectureOrder:
144154 return cls .from_library (lib_path )
145155 return SubarchitectureOrder ()
146156
147- def optimal_candidates (self , nqubits : int ) -> list [rx . PyGraph ]:
157+ def optimal_candidates (self , nqubits : int ) -> list [Graph ]:
148158 """Return optimal subarchitecture candidate.
149159
150160 Args:
@@ -176,7 +186,7 @@ def optimal_candidates(self, nqubits: int) -> list[rx.PyGraph]:
176186
177187 return [self .sgs [n ][i ] for (n , i ) in opt_cands ]
178188
179- def covering (self , nqubits : int , size : int ) -> list [rx . PyGraph ]:
189+ def covering (self , nqubits : int , size : int ) -> list [Graph ]:
180190 """Return covering for nqubit circuits.
181191
182192 Args:
@@ -218,7 +228,7 @@ def store_library(self, lib_name: str | Path) -> None:
218228 with path .open ("wb" ) as f :
219229 pickle .dump (self , f )
220230
221- def draw_subarchitecture (self , subarchitecture : rx . PyGraph | tuple [int , int ]) -> figure .Figure :
231+ def draw_subarchitecture (self , subarchitecture : Graph | tuple [int , int ]) -> figure .Figure :
222232 """Create a matplotlib figure showing subarchitecture within the entire architecture.
223233
224234 Nodes that are part of the subarchitecture are drawn yellow.
@@ -235,9 +245,9 @@ def draw_subarchitecture(self, subarchitecture: rx.PyGraph | tuple[int, int]) ->
235245 colors = [SubarchitectureOrder .inactive_color for _ in range (self .arch .num_nodes ())]
236246 for node in subarchitecture .nodes ():
237247 colors [node ] = SubarchitectureOrder .active_color
238- return rx . visualization . mpl_draw (subarchitecture , node_color = colors )
248+ return rxviz . mpl_draw (self . arch , node_color = colors ) # type: ignore[no-untyped-call]
239249
240- def draw_subarchitectures (self , subarchitectures : list [rx . PyGraph ] | list [tuple [int , int ]]) -> list [figure .Figure ]:
250+ def draw_subarchitectures (self , subarchitectures : list [Graph ] | list [tuple [int , int ]]) -> list [figure .Figure ]:
241251 """Create matplotlib figures showing subarchitectures within the entire architecture.
242252
243253 For each subarchitecture one figure is drawn.
@@ -254,15 +264,15 @@ def draw_subarchitectures(self, subarchitectures: list[rx.PyGraph] | list[tuple[
254264
255265 def __compute_subarchs (self ) -> None :
256266 """Compute all subarchitectures of the architecture."""
257- self .sgs : list [list [rx . PyGraph ]] = [[] for i in range (self .arch .num_nodes () + 1 )]
267+ self .sgs : list [list [Graph ]] = [[] for i in range (self .arch .num_nodes () + 1 )]
258268
259269 for i in range (1 , self .arch .num_nodes () + 1 ):
260270 node_combinations = combinations (range (self .arch .num_nodes ()), i )
261271 for sg in (self .arch .subgraph (selected_nodes ) for selected_nodes in node_combinations ):
262- if rx .is_connected (sg ):
272+ if rx .is_connected (sg ): # type: ignore[attr-defined]
263273 new_class = True
264274 for g in self .sgs [i ]:
265- if rx .is_isomorphic (g , sg ):
275+ if rx .is_isomorphic (g , sg ): # type: ignore[attr-defined]
266276 new_class = False
267277 break
268278 if new_class :
@@ -279,7 +289,7 @@ def __compute_subarch_order(self) -> None:
279289 for n , sgs_n in enumerate (self .sgs [:- 1 ]):
280290 for i , sg in enumerate (sgs_n ):
281291 for j , parent_sg in enumerate (self .sgs [n + 1 ]):
282- matcher = rx .graph_vf2_mapping (parent_sg , sg , subgraph = True )
292+ matcher = rx .graph_vf2_mapping (parent_sg , sg , subgraph = True ) # type: ignore[attr-defined]
283293 for iso in matcher :
284294 self .subarch_order [(n , i )].add ((n + 1 , j ))
285295 iso_rev = {}
@@ -354,8 +364,8 @@ def __path_order_less(self, n: int, i: int, n_prime: int, i_prime: int) -> bool:
354364 if v is w :
355365 continue
356366 if (
357- rx .dijkstra_shortest_path_lengths (lhs , v , lambda _x : 1 , goal = w )[w ]
358- > rx .dijkstra_shortest_path_lengths (rhs , iso [v ], lambda _x : 1 , goal = iso [w ])[iso [w ]]
367+ rx .dijkstra_shortest_path_lengths (lhs , v , lambda _x : 1 , goal = w )[w ] # type: ignore[attr-defined]
368+ > rx .dijkstra_shortest_path_lengths (rhs , iso [v ], lambda _x : 1 , goal = iso [w ])[iso [w ]] # type: ignore[attr-defined]
359369 ):
360370 return True
361371 return False
0 commit comments