def test_config_from_backend_v2(self): """Test from_backend() with a BackendV2 instance.""" backend = FakeAlmadenV2() config = PassManagerConfig.from_backend(backend) self.assertEqual(config.basis_gates, backend.operation_names) self.assertEqual(config.inst_map, backend.instruction_schedule_map) self.assertEqual(config.coupling_map.get_edges(), backend.coupling_map.get_edges())
def test_default_pass_manager_two(self): """Test default_pass_manager.run(circuitS). circuit1 and circuit2: qr0:-[H]--.------------ -> 1 | qr1:-----(+)--.-------- -> 2 | qr2:---------(+)--.---- -> 3 | qr3:-------------(+)--- -> 5 device: 0 - 1 - 2 - 3 - 4 - 5 - 6 | | | | | | 13 - 12 - 11 - 10 - 9 - 8 - 7 """ qr = QuantumRegister(4, "qr") circuit1 = QuantumCircuit(qr) circuit1.h(qr[0]) circuit1.cx(qr[0], qr[1]) circuit1.cx(qr[1], qr[2]) circuit1.cx(qr[2], qr[3]) circuit2 = QuantumCircuit(qr) circuit2.cx(qr[1], qr[2]) circuit2.cx(qr[0], qr[1]) circuit2.cx(qr[2], qr[3]) coupling_map = FakeMelbourne().configuration().coupling_map initial_layout = [None, qr[0], qr[1], qr[2], None, qr[3]] pass_manager = level_1_pass_manager( PassManagerConfig.from_backend( FakeMelbourne(), initial_layout=Layout.from_qubit_list(initial_layout), seed_transpiler=42, )) new_circuits = pass_manager.run([circuit1, circuit2]) for new_circuit in new_circuits: bit_indices = { bit: idx for idx, bit in enumerate(new_circuit.qregs[0]) } for gate, qargs, _ in new_circuit.data: if isinstance(gate, CXGate): self.assertIn([bit_indices[x] for x in qargs], coupling_map)
def test_config_from_backend(self): """Test from_backend() with a valid backend. `FakeAlmaden` is used in this testcase. This backend has `defaults` attribute that contains an instruction schedule map. """ backend = FakeAlmaden() config = PassManagerConfig.from_backend(backend) self.assertEqual(config.basis_gates, backend.configuration().basis_gates) self.assertEqual(config.inst_map, backend.defaults().instruction_schedule_map) self.assertEqual( str(config.coupling_map), str(CouplingMap(backend.configuration().coupling_map)))
def test_from_backend_and_user(self): """Test from_backend() with a backend and user options. `FakeMelbourne` is used in this testcase. This backend does not have `defaults` attribute and thus not provide an instruction schedule map. """ qr = QuantumRegister(4, "qr") initial_layout = [None, qr[0], qr[1], qr[2], None, qr[3]] backend = FakeMelbourne() config = PassManagerConfig.from_backend(backend, basis_gates=["user_gate"], initial_layout=initial_layout) self.assertEqual(config.basis_gates, ["user_gate"]) self.assertNotEqual(config.basis_gates, backend.configuration().basis_gates) self.assertIsNone(config.inst_map) self.assertEqual( str(config.coupling_map), str(CouplingMap(backend.configuration().coupling_map))) self.assertEqual(config.initial_layout, initial_layout)
def test_str(self): """Test string output.""" pm_config = PassManagerConfig.from_backend(FakeArmonk()) # For testing remove instruction schedule map it's str output is non-deterministic # based on hash seed pm_config.inst_map = None str_out = str(pm_config) expected = """Pass Manager Config: initial_layout: None basis_gates: ['id', 'rz', 'sx', 'x'] inst_map: None coupling_map: layout_method: None routing_method: None translation_method: None scheduling_method: None instruction_durations: id(0,): 7.111111111111111e-08 s rz(0,): 0.0 s sx(0,): 7.111111111111111e-08 s x(0,): 7.111111111111111e-08 s measure(0,): 4.977777777777777e-06 s backend_properties: {'backend_name': 'ibmq_armonk', 'backend_version': '2.4.3', 'gates': [{'gate': 'id', 'name': 'id0', 'parameters': [{'date': datetime.datetime(2021, 3, 15, 0, 38, 15, tzinfo=tzoffset(None, -14400)), 'name': 'gate_error', 'unit': '', 'value': 0.00019769550670970334}, {'date': datetime.datetime(2021, 3, 15, 0, 40, 24, tzinfo=tzoffset(None, -14400)), 'name': 'gate_length', 'unit': 'ns', 'value': 71.11111111111111}], 'qubits': [0]}, {'gate': 'rz', 'name': 'rz0', 'parameters': [{'date': datetime.datetime(2021, 3, 15, 0, 40, 24, tzinfo=tzoffset(None, -14400)), 'name': 'gate_error', 'unit': '', 'value': 0}, {'date': datetime.datetime(2021, 3, 15, 0, 40, 24, tzinfo=tzoffset(None, -14400)), 'name': 'gate_length', 'unit': 'ns', 'value': 0}], 'qubits': [0]}, {'gate': 'sx', 'name': 'sx0', 'parameters': [{'date': datetime.datetime(2021, 3, 15, 0, 38, 15, tzinfo=tzoffset(None, -14400)), 'name': 'gate_error', 'unit': '', 'value': 0.00019769550670970334}, {'date': datetime.datetime(2021, 3, 15, 0, 40, 24, tzinfo=tzoffset(None, -14400)), 'name': 'gate_length', 'unit': 'ns', 'value': 71.11111111111111}], 'qubits': [0]}, {'gate': 'x', 'name': 'x0', 'parameters': [{'date': datetime.datetime(2021, 3, 15, 0, 38, 15, tzinfo=tzoffset(None, -14400)), 'name': 'gate_error', 'unit': '', 'value': 0.00019769550670970334}, {'date': datetime.datetime(2021, 3, 15, 0, 40, 24, tzinfo=tzoffset(None, -14400)), 'name': 'gate_length', 'unit': 'ns', 'value': 71.11111111111111}], 'qubits': [0]}], 'general': [], 'last_update_date': datetime.datetime(2021, 3, 15, 0, 40, 24, tzinfo=tzoffset(None, -14400)), 'qubits': [[{'date': datetime.datetime(2021, 3, 15, 0, 36, 17, tzinfo=tzoffset(None, -14400)), 'name': 'T1', 'unit': 'us', 'value': 182.6611165336624}, {'date': datetime.datetime(2021, 3, 14, 0, 33, 45, tzinfo=tzoffset(None, -18000)), 'name': 'T2', 'unit': 'us', 'value': 237.8589220110257}, {'date': datetime.datetime(2021, 3, 15, 0, 40, 24, tzinfo=tzoffset(None, -14400)), 'name': 'frequency', 'unit': 'GHz', 'value': 4.971852852405576}, {'date': datetime.datetime(2021, 3, 15, 0, 40, 24, tzinfo=tzoffset(None, -14400)), 'name': 'anharmonicity', 'unit': 'GHz', 'value': -0.34719293148282626}, {'date': datetime.datetime(2021, 3, 15, 0, 35, 20, tzinfo=tzoffset(None, -14400)), 'name': 'readout_error', 'unit': '', 'value': 0.02400000000000002}, {'date': datetime.datetime(2021, 3, 15, 0, 35, 20, tzinfo=tzoffset(None, -14400)), 'name': 'prob_meas0_prep1', 'unit': '', 'value': 0.0234}, {'date': datetime.datetime(2021, 3, 15, 0, 35, 20, tzinfo=tzoffset(None, -14400)), 'name': 'prob_meas1_prep0', 'unit': '', 'value': 0.024599999999999955}, {'date': datetime.datetime(2021, 3, 15, 0, 35, 20, tzinfo=tzoffset(None, -14400)), 'name': 'readout_length', 'unit': 'ns', 'value': 4977.777777777777}]]} approximation_degree: None seed_transpiler: None timing_constraints: None unitary_synthesis_method: default unitary_synthesis_plugin_config: None target: None """ self.assertEqual(str_out, expected)
def test_invalid_user_option(self): """Test from_backend() with an invalid user option.""" with self.assertRaises(TypeError): PassManagerConfig.from_backend(FakeMelbourne(), invalid_option=None)
def test_invalid_backend(self): """Test from_backend() with an invalid backend.""" with self.assertRaises(AttributeError): PassManagerConfig.from_backend(Backend())
def generate_preset_pass_manager( optimization_level, backend=None, target=None, basis_gates=None, inst_map=None, coupling_map=None, instruction_durations=None, backend_properties=None, timing_constraints=None, initial_layout=None, layout_method=None, routing_method=None, translation_method=None, scheduling_method=None, approximation_degree=None, seed_transpiler=None, unitary_synthesis_method="default", unitary_synthesis_plugin_config=None, ): """Generate a preset :class:`~.PassManager` This function is used to quickly generate a preset pass manager. A preset pass manager are the default pass managers used by the :func:`~.transpile` function. This function provides a convenient and simple method to construct a standalone :class:`~.PassManager` object that mirrors what the transpile Args: optimization_level (int): The optimization level to generate a :class:`~.PassManager` for. This can be 0, 1, 2, or 3. Higher levels generate more optimized circuits, at the expense of longer transpilation time: * 0: no optimization * 1: light optimization * 2: heavy optimization * 3: even heavier optimization backend (Backend): An optional backend object which can be used as the source of the default values for the ``basis_gates``, ``inst_map``, ``couplig_map``, ``backend_properties``, ``instruction_durations``, ``timing_constraints``, and ``target``. If any of those other arguments are specified in addition to ``backend`` they will take precedence over the value contained in the backend. target (Target): The :class:`~.Target` representing a backend compilation target. The following attributes will be inferred from this argument if they are not set: ``coupling_map``, ``basis_gates``, ``instruction_durations``, ``inst_map``, ``timing_constraints`` and ``backend_properties``. basis_gates (list): List of basis gate names to unroll to (e.g: ``['u1', 'u2', 'u3', 'cx']``). inst_map (InstructionScheduleMap): Mapping object that maps gate to schedules. If any user defined calibration is found in the map and this is used in a circuit, transpiler attaches the custom gate definition to the circuit. This enables one to flexibly override the low-level instruction implementation. coupling_map (CouplingMap): Directed graph represented a coupling map. instruction_durations (InstructionDurations): Dictionary of duration (in dt) for each instruction. timing_constraints (TimingConstraints): Hardware time alignment restrictions. initial_layout (Layout): Initial position of virtual qubits on physical qubits. layout_method (str): The :class:`~.Pass` to use for choosing initial qubit placement. Valid choices are ``'trivial'``, ``'dense'``, ``'noise_adaptive'``, and, ``'sabre'`` repsenting :class:`~.TrivialLayout`, :class:`~DenseLayout`, :class:`~.NoiseAdaptiveLayout`, :class:`~.SabreLayout` respectively. routing_method (str): The pass to use for routing qubits on the architecture. Valid choices are ``'basic'``, ``'lookahead'``, ``'stochastic'``, ``'sabre'``, and ``'none'`` representing :class:`~.BasicSwap`, :class:`~.LookaheadSwap`, :class:`~.StochasticSwap`, :class:`~.SabreSwap`, and erroring if routing is required respectively. translation_method (str): The method to use for translating gates to basis gates. Valid choices ``'unroller'``, ``'translator'``, ``'synthesis'`` representing :class:`~.Unroller`, :class:`~.BasisTranslator`, and :class:`~.UnitarySynthesis` respectively. scheduling_method (str): The pass to use for scheduling instructions. Valid choices are ``'alap'`` and ``'asap'``. backend_properties (BackendProperties): Properties returned by a backend, including information on gate errors, readout errors, qubit coherence times, etc. approximation_degree (float): Heuristic dial used for circuit approximation (1.0=no approximation, 0.0=maximal approximation). seed_transpiler (int): Sets random seed for the stochastic parts of the transpiler. unitary_synthesis_method (str): The name of the unitary synthesis method to use. By default 'default' is used, which is the only method included with qiskit. If you have installed any unitary synthesis plugins you can use the name exported by the plugin. unitary_synthesis_plugin_config (dict): An optional configuration dictionary that will be passed directly to the unitary synthesis plugin. By default this setting will have no effect as the default unitary synthesis method does not take custom configuration. This should only be necessary when a unitary synthesis plugin is specified with the ``unitary_synthesis`` argument. As this is custom for each unitary synthesis plugin refer to the plugin documentation for how to use this option. Returns: StagedPassManager: The preset pass manager for the given options Raises: ValueError: if an invalid value for ``optimization_level`` is passed in. """ if target is not None: if coupling_map is None: coupling_map = target.build_coupling_map() if basis_gates is None: basis_gates = target.operation_names if instruction_durations is None: instruction_durations = target.durations() if inst_map is None: inst_map = target.instruction_schedule_map() if timing_constraints is None: timing_constraints = target.timing_constraints() if backend_properties is None: backend_properties = target_to_backend_properties(target) pm_options = dict( target=target, basis_gates=basis_gates, inst_map=inst_map, coupling_map=coupling_map, instruction_durations=instruction_durations, backend_properties=backend_properties, timing_constraints=timing_constraints, layout_method=layout_method, routing_method=routing_method, translation_method=translation_method, scheduling_method=scheduling_method, approximation_degree=approximation_degree, seed_transpiler=seed_transpiler, unitary_synthesis_method=unitary_synthesis_method, unitary_synthesis_plugin_config=unitary_synthesis_plugin_config, initial_layout=initial_layout, ) if backend is not None: pm_config = PassManagerConfig.from_backend(backend, **pm_options) else: pm_config = PassManagerConfig(**pm_options) if optimization_level == 0: pm = level_0_pass_manager(pm_config) elif optimization_level == 1: pm = level_1_pass_manager(pm_config) elif optimization_level == 2: pm = level_2_pass_manager(pm_config) elif optimization_level == 3: pm = level_3_pass_manager(pm_config) else: raise ValueError(f"Invalid optimization level {optimization_level}") return pm