@@ -78,8 +78,7 @@ class VF2PostLayout(AnalysisPass):
7878 * ``">2q gates in basis"``: If VF2PostLayout can't work with the basis of the circuit.
7979
8080 By default, this pass will construct a heuristic scoring map based on
81- the error rates in the provided ``target`` (or ``properties`` if ``target``
82- is not provided). However, analysis passes can be run prior to this pass
81+ the error rates in the provided ``target``. However, analysis passes can be run prior to this pass
8382 and set ``vf2_avg_error_map`` in the property set with a :class:`~.ErrorMap`
8483 instance. If a value is ``NaN`` that is treated as an ideal edge
8584 For example if an error map is created as::
@@ -102,8 +101,6 @@ class VF2PostLayout(AnalysisPass):
102101 def __init__ (
103102 self ,
104103 target = None ,
105- coupling_map = None ,
106- properties = None ,
107104 seed = None ,
108105 call_limit = None ,
109106 time_limit = None ,
@@ -114,12 +111,6 @@ def __init__(
114111
115112 Args:
116113 target (Target): A target representing the backend device to run ``VF2PostLayout`` on.
117- If specified it will supersede a set value for ``properties`` and
118- ``coupling_map``.
119- coupling_map (CouplingMap): Directed graph representing a coupling map.
120- properties (BackendProperties): The backend properties for the backend. If
121- :meth:`~qiskit.providers.models.BackendProperties.readout_error` is available
122- it is used to score the layout.
123114 seed (int): Sets the seed of the PRNG. -1 Means no node shuffling.
124115 call_limit (int): The number of state visits to attempt in each execution of
125116 VF2.
@@ -138,12 +129,10 @@ def __init__(
138129 a layout. A value of ``0`` (the default) means 'unlimited'.
139130
140131 Raises:
141- TypeError: At runtime, if neither ``coupling_map`` or `` target`` are provided.
132+ TypeError: At runtime, if `` target`` isn't provided.
142133 """
143134 super ().__init__ ()
144135 self .target = target
145- self .coupling_map = coupling_map
146- self .properties = properties
147136 self .call_limit = call_limit
148137 self .time_limit = time_limit
149138 self .max_trials = max_trials
@@ -153,16 +142,12 @@ def __init__(
153142
154143 def run (self , dag ):
155144 """run the layout method"""
156- if self .target is None and (self .coupling_map is None or self .properties is None ):
157- raise TranspilerError (
158- "A target must be specified or a coupling map and properties must be provided"
159- )
145+ if self .target is None :
146+ raise TranspilerError ("A target must be specified or a coupling map must be provided" )
160147 if not self .strict_direction :
161148 self .avg_error_map = self .property_set ["vf2_avg_error_map" ]
162149 if self .avg_error_map is None :
163- self .avg_error_map = vf2_utils .build_average_error_map (
164- self .target , self .properties , self .coupling_map
165- )
150+ self .avg_error_map = vf2_utils .build_average_error_map (self .target , None )
166151
167152 result = vf2_utils .build_interaction_graph (dag , self .strict_direction )
168153 if result is None :
@@ -172,67 +157,62 @@ def run(self, dag):
172157 scoring_bit_list = vf2_utils .build_bit_list (im_graph , im_graph_node_map )
173158 scoring_edge_list = vf2_utils .build_edge_list (im_graph )
174159
175- if self .target is not None :
176- # If qargs is None then target is global and ideal so no
177- # scoring is needed
178- if self .target .qargs is None :
179- return
180- if self .strict_direction :
181- cm_graph = PyDiGraph (multigraph = False )
182- else :
183- cm_graph = PyGraph (multigraph = False )
184- # If None is present in qargs there are globally defined ideal operations
185- # we should add these to all entries based on the number of qubits, so we
186- # treat that as a valid operation even if there is no scoring for the
187- # strict direction case
188- global_ops = None
189- if None in self .target .qargs :
190- global_ops = {1 : [], 2 : []}
191- for op in self .target .operation_names_for_qargs (None ):
192- operation = self .target .operation_for_name (op )
193- # If operation is a class this is a variable width ideal instruction
194- # so we treat it as available on both 1 and 2 qubits
195- if inspect .isclass (operation ):
196- global_ops [1 ].append (op )
197- global_ops [2 ].append (op )
198- else :
199- num_qubits = operation .num_qubits
200- if num_qubits in global_ops :
201- global_ops [num_qubits ].append (op )
202- op_names = []
203- for i in range (self .target .num_qubits ):
204- try :
205- entry = set (self .target .operation_names_for_qargs ((i ,)))
206- except KeyError :
207- entry = set ()
208- if global_ops is not None :
209- entry .update (global_ops [1 ])
210- op_names .append (entry )
211- cm_graph .add_nodes_from (op_names )
212- for qargs in self .target .qargs :
213- len_args = len (qargs )
214- # If qargs == 1 we already populated it and if qargs > 2 there are no instructions
215- # using those in the circuit because we'd have already returned by this point
216- if len_args == 2 :
217- ops = set (self .target .operation_names_for_qargs (qargs ))
218- if global_ops is not None :
219- ops .update (global_ops [2 ])
220- cm_graph .add_edge (qargs [0 ], qargs [1 ], ops )
221- cm_nodes = list (cm_graph .node_indexes ())
222- # Filter qubits without any supported operations. If they
223- # don't support any operations, they're not valid for layout selection.
224- # This is only needed in the undirected case because in strict direction
225- # mode the node matcher will not match since none of the circuit ops
226- # will match the cmap ops.
227- if not self .strict_direction :
228- has_operations = set (itertools .chain .from_iterable (self .target .qargs ))
229- to_remove = set (cm_graph .node_indices ()).difference (has_operations )
230- if to_remove :
231- cm_graph .remove_nodes_from (list (to_remove ))
160+ # If qargs is None then target is global and ideal so no
161+ # scoring is needed
162+ if self .target .qargs is None :
163+ return
164+ if self .strict_direction :
165+ cm_graph = PyDiGraph (multigraph = False )
232166 else :
233- cm_graph , cm_nodes = vf2_utils .shuffle_coupling_graph (
234- self .coupling_map , self .seed , self .strict_direction
235- )
167+ cm_graph = PyGraph (multigraph = False )
168+ # If None is present in qargs there are globally defined ideal operations
169+ # we should add these to all entries based on the number of qubits, so we
170+ # treat that as a valid operation even if there is no scoring for the
171+ # strict direction case
172+ global_ops = None
173+ if None in self .target .qargs :
174+ global_ops = {1 : [], 2 : []}
175+ for op in self .target .operation_names_for_qargs (None ):
176+ operation = self .target .operation_for_name (op )
177+ # If operation is a class this is a variable width ideal instruction
178+ # so we treat it as available on both 1 and 2 qubits
179+ if inspect .isclass (operation ):
180+ global_ops [1 ].append (op )
181+ global_ops [2 ].append (op )
182+ else :
183+ num_qubits = operation .num_qubits
184+ if num_qubits in global_ops :
185+ global_ops [num_qubits ].append (op )
186+ op_names = []
187+ for i in range (self .target .num_qubits ):
188+ try :
189+ entry = set (self .target .operation_names_for_qargs ((i ,)))
190+ except KeyError :
191+ entry = set ()
192+ if global_ops is not None :
193+ entry .update (global_ops [1 ])
194+ op_names .append (entry )
195+ cm_graph .add_nodes_from (op_names )
196+ for qargs in self .target .qargs :
197+ len_args = len (qargs )
198+ # If qargs == 1 we already populated it and if qargs > 2 there are no instructions
199+ # using those in the circuit because we'd have already returned by this point
200+ if len_args == 2 :
201+ ops = set (self .target .operation_names_for_qargs (qargs ))
202+ if global_ops is not None :
203+ ops .update (global_ops [2 ])
204+ cm_graph .add_edge (qargs [0 ], qargs [1 ], ops )
205+ cm_nodes = list (cm_graph .node_indexes ())
206+ # Filter qubits without any supported operations. If they
207+ # don't support any operations, they're not valid for layout selection.
208+ # This is only needed in the undirected case because in strict direction
209+ # mode the node matcher will not match since none of the circuit ops
210+ # will match the cmap ops.
211+ if not self .strict_direction :
212+ has_operations = set (itertools .chain .from_iterable (self .target .qargs ))
213+ to_remove = set (cm_graph .node_indices ()).difference (has_operations )
214+ if to_remove :
215+ cm_graph .remove_nodes_from (list (to_remove ))
236216
237217 logger .debug ("Running VF2 to find post transpile mappings" )
238218 if self .target and self .strict_direction :
0 commit comments