def __init__(self): """ .. code-block:: text 1 ↙ ↑ 0 ← 2 ← 3 ↑ ↙ 4 """ cmap = [[1, 0], [2, 0], [2, 1], [3, 2], [3, 4], [4, 2]] configuration = QasmBackendConfiguration( backend_name="fake_tenerife", backend_version="0.0.0", n_qubits=5, basis_gates=["u1", "u2", "u3", "cx", "id"], simulator=False, local=True, conditional=False, open_pulse=False, memory=False, max_shots=65536, max_experiments=900, gates=[GateConfig(name="TODO", parameters=[], qasm_def="TODO")], coupling_map=cmap, ) super().__init__(configuration)
def test_deprecate_id_instruction(self): """Test replacement of 'id' Instructions with 'Delay' instructions.""" circuit_with_id = QuantumCircuit(2) circuit_with_id.id(0) circuit_with_id.id(0) circuit_with_id.id(1) config = QasmBackendConfiguration( basis_gates=["id"], supported_instructions=["delay"], dt=0.25, backend_name="test", backend_version="0.0", n_qubits=1, gates=[], local=False, simulator=False, conditional=False, open_pulse=False, memory=False, max_shots=1, coupling_map=[], ) with patch.object(self.backend, "configuration", return_value=config): with self.assertWarnsRegex(DeprecationWarning, r"'id' instruction"): mutated_circuit = self.backend._deprecate_id_instruction( circuit_with_id) self.assertEqual(mutated_circuit[0].count_ops(), {"delay": 3}) self.assertEqual(circuit_with_id.count_ops(), {"id": 3})
def __init__(self): """ 00 ↔ 01 ↔ 02 ↔ 03 ↔ 04 ↕ ↕ 05 ↔ 06 ↔ 07 ↔ 08 ↔ 09 ↕ ↕ ↕ 10 ↔ 11 ↔ 12 ↔ 13 ↔ 14 ↕ ↕ 15 ↔ 16 ↔ 17 ↔ 18 ↔ 19 """ cmap = [[0, 1], [1, 0], [1, 2], [1, 6], [2, 1], [2, 3], [3, 2], [3, 4], [3, 8], [4, 3], [5, 6], [5, 10], [6, 1], [6, 5], [6, 7], [7, 6], [7, 8], [7, 12], [8, 3], [8, 7], [8, 9], [9, 8], [9, 14], [10, 5], [10, 11], [11, 10], [11, 12], [11, 16], [12, 7], [12, 11], [12, 13], [13, 12], [13, 14], [13, 18], [14, 9], [14, 13], [15, 16], [16, 11], [16, 15], [16, 17], [17, 16], [17, 18], [18, 13], [18, 17], [18, 19], [19, 18]] configuration = QasmBackendConfiguration( backend_name='fake_boeblingen', backend_version='0.0.0', n_qubits=20, basis_gates=['u1', 'u2', 'u3', 'cx', 'id'], simulator=False, local=True, conditional=False, open_pulse=False, memory=True, max_shots=8192, gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')], coupling_map=cmap, ) super().__init__(configuration)
def __init__(self): cmap = [[0, 1], [0, 5], [1, 0], [1, 2], [2, 1], [2, 3], [3, 2], [3, 4], [4, 3], [4, 9], [5, 0], [5, 6], [5, 10], [6, 5], [6, 7], [7, 6], [7, 8], [7, 12], [8, 7], [8, 9], [9, 4], [9, 8], [9, 14], [10, 5], [10, 11], [10, 15], [11, 10], [11, 12], [12, 7], [12, 11], [12, 13], [13, 12], [13, 14], [14, 9], [14, 13], [14, 19], [15, 10], [15, 16], [16, 15], [16, 17], [17, 16], [17, 18], [18, 17], [18, 19], [19, 14], [19, 18]] configuration = QasmBackendConfiguration( backend_name='fake_poughkeepsie', backend_version='0.0.0', n_qubits=20, basis_gates=['u1', 'u2', 'u3', 'cx', 'id'], simulator=False, local=True, conditional=False, open_pulse=False, memory=True, max_shots=8192, gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')], coupling_map=cmap, ) super().__init__(configuration)
def __init__( self, t2hahn=None, frequency=None, initialization_error=None, readout0to1=None, readout1to0=None, ): """ Initialize the T2Hahn backend """ configuration = QasmBackendConfiguration( backend_name="T2Hahn_simulator", backend_version="0", n_qubits=int(1e6), basis_gates=["barrier", "rx", "delay", "measure"], gates=[], local=True, simulator=True, conditional=False, open_pulse=False, memory=False, max_shots=int(1e6), coupling_map=None, ) self._t2hahn = t2hahn self._frequency = frequency self._initialization_error = initialization_error self._readout0to1 = readout0to1 self._readout1to0 = readout1to0 self._rng = np.random.default_rng(seed=SEED) super().__init__(configuration)
def __init__(self, t1, initial_prob1=None, readout0to1=None, readout1to0=None): """ Initialize the T1 backend """ configuration = QasmBackendConfiguration( backend_name="t1_simulator", backend_version="0", n_qubits=int(1e6), basis_gates=["barrier", "x", "delay", "measure"], gates=[], local=True, simulator=True, conditional=False, open_pulse=False, memory=False, max_shots=int(1e6), coupling_map=None, ) self._t1 = t1 self._initial_prob1 = initial_prob1 self._readout0to1 = readout0to1 self._readout1to0 = readout1to0 self._rng = np.random.default_rng(0) super().__init__(configuration)
def __init__(self): """ 1 / | 0 - 2 - 3 | / 4 """ cmap = [[1, 0], [2, 0], [2, 1], [3, 2], [3, 4], [4, 2]] configuration = QasmBackendConfiguration( backend_name='fake_tenerife', backend_version='0.0.0', n_qubits=5, basis_gates=['u1', 'u2', 'u3', 'cx', 'id'], simulator=False, local=True, conditional=False, open_pulse=False, memory=False, max_shots=65536, gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')], coupling_map=cmap, ) super().__init__(configuration)
def __init__( self, p0=None, initial_prob_plus=None, readout0to1=None, readout1to0=None, ): """ Initialize the T2Ramsey backend """ configuration = QasmBackendConfiguration( backend_name="T2Ramsey_simulator", backend_version="0", n_qubits=int(1e6), basis_gates=["barrier", "h", "p", "delay", "measure"], gates=[], local=True, simulator=True, conditional=False, open_pulse=False, memory=False, max_shots=int(1e6), coupling_map=None, ) self._t2ramsey = p0["T2star"] self._a_param = p0["A"] self._freq = p0["f"] self._phi = p0["phi"] self._b_param = p0["B"] self._initial_prob_plus = initial_prob_plus self._readout0to1 = readout0to1 self._readout1to0 = readout1to0 self._rng = np.random.default_rng(0) super().__init__(configuration)
def __init__(self): """ 1 → 2 → 3 → 4 ← 5 ← 6 → 7 ← 8 ↓ ↑ ↓ ↓ ↑ ↓ ↓ ↑ 0 ← 15 → 14 ← 13 ← 12 → 11 → 10 ← 9 """ cmap = [[1, 0], [1, 2], [2, 3], [3, 4], [3, 14], [5, 4], [6, 5], [6, 7], [6, 11], [7, 10], [8, 7], [9, 8], [9, 10], [11, 10], [12, 5], [12, 11], [12, 13], [13, 4], [13, 14], [15, 0], [15, 2], [15, 14]] configuration = QasmBackendConfiguration( backend_name='fake_rueschlikon', backend_version='0.0.0', n_qubits=16, basis_gates=['u1', 'u2', 'u3', 'cx', 'id'], simulator=False, local=True, conditional=False, open_pulse=False, memory=False, max_shots=65536, max_experiments=900, gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')], coupling_map=cmap, ) super().__init__(configuration)
def __init__(self): """ 0 ↔ 1 ↔ 3 ↔ 4 ↕ 2 """ cmap = [[0, 1], [1, 0], [1, 2], [1, 3], [2, 1], [3, 1], [3, 4], [4, 3]] configuration = QasmBackendConfiguration( backend_name='fake_ourense', backend_version='0.0.0', n_qubits=5, basis_gates=['u1', 'u2', 'u3', 'cx', 'id'], simulator=False, local=True, conditional=False, open_pulse=False, memory=False, max_shots=65536, max_experiments=900, gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')], coupling_map=cmap, ) super().__init__(configuration)
def __init__(self, t1, initial_prob1=None, readout0to1=None, readout1to0=None, dt_factor=None): """ Initialize the T1 backend """ dt_factor_in_ns = dt_factor * 1e9 if dt_factor is not None else None configuration = QasmBackendConfiguration( backend_name="t1_simulator", backend_version="0", n_qubits=int(1e6), basis_gates=["barrier", "x", "delay", "measure"], gates=[], local=True, simulator=True, conditional=False, open_pulse=False, memory=False, max_shots=int(1e6), coupling_map=None, dt=dt_factor_in_ns, ) self._t1 = t1 self._initial_prob1 = initial_prob1 self._readout0to1 = readout0to1 self._readout1to0 = readout1to0 self._dt_factor = dt_factor super().__init__(configuration)
def __init__(self): """ 0 ← 1 → 2 → 3 ← 4 ← 5 → 6 ↑ ↑ ↑ ↓ ↓ ↓ 13 → 12 ← 11 → 10 ← 9 → 8 ← 7 """ cmap = [[1, 0], [1, 2], [2, 3], [4, 3], [4, 10], [5, 4], [5, 6], [5, 9], [6, 8], [7, 8], [9, 8], [9, 10], [11, 3], [11, 10], [11, 12], [12, 2], [13, 1], [13, 12]] configuration = QasmBackendConfiguration( backend_name='fake_melbourne', backend_version='0.0.0', n_qubits=14, basis_gates=['u1', 'u2', 'u3', 'cx', 'id'], simulator=False, local=True, conditional=False, open_pulse=False, memory=False, max_shots=65536, max_experiments=900, gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')], coupling_map=cmap, ) super().__init__(configuration)
def __init__(self): """ 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 | | | | | | | | 0 - 15 - 14 - 13 - 12 - 11 - 10 - 9 """ cmap = [[1, 0], [1, 2], [2, 3], [3, 4], [3, 14], [5, 4], [6, 5], [6, 7], [6, 11], [7, 10], [8, 7], [9, 8], [9, 10], [11, 10], [12, 5], [12, 11], [12, 13], [13, 4], [13, 14], [15, 0], [15, 2], [15, 14]] configuration = QasmBackendConfiguration( backend_name='fake_rueschlikon', backend_version='0.0.0', n_qubits=16, basis_gates=['u1', 'u2', 'u3', 'cx', 'id'], simulator=False, local=True, conditional=False, open_pulse=False, memory=False, max_shots=65536, gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')], coupling_map=cmap, ) super().__init__(configuration)
def __init__(self): """ 0 - 1 - 2 - 3 - 4 - 5 - 6 | | | | | | 13 - 12 - 11 - 10 - 9 - 8 - 7 """ cmap = [[1, 0], [1, 2], [2, 3], [4, 3], [4, 10], [5, 4], [5, 6], [5, 9], [6, 8], [7, 8], [9, 8], [9, 10], [11, 3], [11, 10], [11, 12], [12, 2], [13, 1], [13, 12]] configuration = QasmBackendConfiguration( backend_name='fake_melbourne', backend_version='0.0.0', n_qubits=14, basis_gates=['u1', 'u2', 'u3', 'cx', 'id'], simulator=False, local=True, conditional=False, open_pulse=False, memory=False, max_shots=65536, gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')], coupling_map=cmap, ) super().__init__(configuration)
def __init__( self, t1=None, t2ramsey=None, freq=None, initial_prob1=None, readout0to1=None, readout1to0=None, ): """ Initialize the Tphi backend """ self._configuration = QasmBackendConfiguration( backend_name="tphi_simulator", backend_version="0", n_qubits=int(1e6), basis_gates=["barrier", "h", "p", "delay", "measure", "x"], gates=[], local=True, simulator=True, conditional=False, open_pulse=False, memory=False, max_shots=int(1e6), coupling_map=None, ) self._t1 = [t1] self._t2ramsey = t2ramsey self._freq = freq self._initial_prob1 = initial_prob1 self._readout0to1 = readout0to1 self._readout1to0 = readout1to0 self._internal_backends = {} super().__init__(self._configuration) self._internal_backends["T1"] = T1Backend(self._t1, self._initial_prob1, self._readout0to1, self._readout1to0) if self._initial_prob1 is None: self._initial_prob_plus = None else: self._initial_prob_plus = 0.5 # temporary self._p0 = { "A": [0.5], "T2star": [t2ramsey], "f": [freq], "phi": [0.0], "B": [0.5], } self._internal_backends["T2*"] = T2RamseyBackend( self._p0, self._initial_prob_plus, self._readout0to1, self._readout1to0)
def __init__(self): """ .. code-block:: text 1 → 2 → 3 → 4 ← 5 ← 6 → 7 ← 8 ↓ ↑ ↓ ↓ ↑ ↓ ↓ ↑ 0 ← 15 → 14 ← 13 ← 12 → 11 → 10 ← 9 """ cmap = [ [1, 0], [1, 2], [2, 3], [3, 4], [3, 14], [5, 4], [6, 5], [6, 7], [6, 11], [7, 10], [8, 7], [9, 8], [9, 10], [11, 10], [12, 5], [12, 11], [12, 13], [13, 4], [13, 14], [15, 0], [15, 2], [15, 14], ] configuration = QasmBackendConfiguration( backend_name="fake_rueschlikon", backend_version="0.0.0", n_qubits=16, basis_gates=["u1", "u2", "u3", "cx", "id"], simulator=False, local=True, conditional=False, open_pulse=False, memory=False, max_shots=65536, max_experiments=900, gates=[GateConfig(name="TODO", parameters=[], qasm_def="TODO")], coupling_map=cmap, ) super().__init__(configuration)
def __init__(self): """ .. code-block:: text 0 ← 1 → 2 → 3 ← 4 ← 5 → 6 ↑ ↑ ↑ ↓ ↓ ↓ 13 → 12 ← 11 → 10 ← 9 → 8 ← 7 """ cmap = [ [1, 0], [1, 2], [2, 3], [4, 3], [4, 10], [5, 4], [5, 6], [5, 9], [6, 8], [7, 8], [9, 8], [9, 10], [11, 3], [11, 10], [11, 12], [12, 2], [13, 1], [13, 12], ] configuration = QasmBackendConfiguration( backend_name="fake_melbourne", backend_version="0.0.0", n_qubits=14, basis_gates=["u1", "u2", "u3", "cx", "id"], simulator=False, local=True, conditional=False, open_pulse=False, memory=False, max_shots=65536, max_experiments=900, gates=[GateConfig(name="TODO", parameters=[], qasm_def="TODO")], coupling_map=cmap, ) super().__init__(configuration)
def __init__(self, max_experiments=None): configuration = QasmBackendConfiguration( backend_name="dummy_backend", backend_version="0", n_qubits=int(1e6), basis_gates=["barrier", "x", "delay", "measure"], gates=[], local=True, simulator=True, conditional=False, open_pulse=False, memory=False, max_shots=int(1e6), max_experiments=max_experiments, coupling_map=None, ) super().__init__(configuration)
def convert_to_qiskit_hardware(self): configuration = QasmBackendConfiguration( backend_name=self.name, backend_version="0.0.0", n_qubits=self.num_qubits, basis_gates=["u1", "u2", "u3", "cx", "id"], # TODO check gate sets simulator=False, local=True, conditional=False, open_pulse=False, memory=False, max_shots=65536, gates=[GateConfig(name="TODO", parameters=[], qasm_def="TODO")], coupling_map=self.qubit_connectivity.get_coupling_map(), ) hardware = FakeBackend(configuration) return hardware
def __init__(self): configuration = QasmBackendConfiguration( backend_name='fake_qasm_simulator', backend_version='0.0.0', n_qubits=5, basis_gates=['u1', 'u2', 'u3', 'cx', 'id', 'unitary'], coupling_map=None, simulator=True, local=True, conditional=True, open_pulse=False, memory=True, max_shots=65536, gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')] ) super().__init__(configuration)
def __init__(self): """ 0 = 1 = 2 = 3 4 || || || || X || 5 = 6 = 7 = 8 = 9 || X || || X || 10 = 11 = 12 = 13 = 14 || || X || X || 15 = 16 = 17 18 19 """ cmap = [[0, 1], [0, 5], [1, 0], [1, 2], [1, 6], [2, 1], [2, 3], [2, 6], [3, 2], [3, 8], [3, 9], [4, 8], [4, 9], [5, 0], [5, 6], [5, 10], [5, 11], [6, 1], [6, 2], [6, 5], [6, 7], [6, 10], [6, 11], [7, 1], [7, 6], [7, 8], [7, 12], [7, 13], [8, 3], [8, 4], [8, 7], [8, 9], [8, 12], [8, 13], [9, 3], [9, 4], [9, 8], [10, 5], [10, 6], [10, 11], [10, 15], [11, 5], [11, 6], [11, 10], [11, 12], [11, 16], [11, 17], [12, 7], [12, 8], [12, 11], [12, 13], [12, 16], [13, 7], [13, 8], [13, 12], [13, 14], [13, 18], [13, 19], [14, 13], [14, 18], [14, 19], [15, 10], [15, 16], [16, 11], [16, 12], [16, 15], [16, 17], [17, 11], [17, 16], [18, 13], [18, 14], [19, 13], [19, 14]] configuration = QasmBackendConfiguration( backend_name='fake_tokyo', backend_version='0.0.0', n_qubits=20, basis_gates=['u1', 'u2', 'u3', 'cx', 'id'], simulator=False, local=True, conditional=False, open_pulse=False, memory=False, max_shots=65536, gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')], coupling_map=cmap, ) super().__init__(configuration)
def from_name(cls, backend_name: str, provider: 'accountprovider.AccountProvider', credentials: Credentials, api: AccountClient) -> 'IBMQRetiredBackend': """Return a retired backend from its name.""" configuration = QasmBackendConfiguration( backend_name=backend_name, backend_version='0.0.0', n_qubits=1, basis_gates=[], simulator=False, local=False, conditional=False, open_pulse=False, memory=False, max_shots=1, gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')], coupling_map=[[0, 1]], ) return cls(configuration, provider, credentials, api)
def test_backend_default_configuration(self): simulator = QuantumInspireBackend(Mock(), Mock()) configuration = simulator.configuration() expected_configuration = QasmBackendConfiguration( backend_name='qi_simulator', backend_version=quantum_inspire_version, n_qubits=26, basis_gates=['x', 'y', 'z', 'h', 'rx', 'ry', 'rz', 's', 'sdg', 't', 'tdg', 'cx', 'ccx', 'u1', 'u2', 'u3', 'id', 'swap', 'cz', 'snapshot'], gates=[GateConfig(name='NotUsed', parameters=['NaN'], qasm_def='NaN')], conditional=True, simulator=True, local=False, memory=True, open_pulse=False, max_shots=1024, max_experiments=1, coupling_map=None ) self.assertDictEqual(configuration.to_dict(), expected_configuration.to_dict())
def __init__(self): configuration = QasmBackendConfiguration( backend_name="fake_qasm_simulator", backend_version="0.0.0", n_qubits=5, basis_gates=["u1", "u2", "u3", "cx", "id", "unitary"], coupling_map=None, simulator=True, local=True, conditional=True, open_pulse=False, memory=True, max_shots=65536, gates=[GateConfig(name="TODO", parameters=[], qasm_def="TODO")], dt=1.3333, dtm=10.5, qubit_lo_range=[[4.95, 5.05], [4.95, 5.05], [4.95, 5.05], [4.95, 5.05], [4.95, 5.05]], meas_lo_range=[[6.65, 6.75], [6.65, 6.75], [6.65, 6.75], [6.65, 6.75], [6.65, 6.75]], ) super().__init__(configuration)
def __init__(self): cmap = [[0, 5], [0, 1], [1, 2], [1, 0], [2, 3], [2, 1], [3, 4], [3, 2], [4, 6], [4, 3], [5, 9], [5, 0], [6, 13], [6, 4], [7, 16], [7, 8], [8, 9], [8, 7], [9, 10], [9, 8], [9, 5], [10, 11], [10, 9], [11, 17], [11, 12], [11, 10], [12, 13], [12, 11], [13, 14], [13, 12], [13, 6], [14, 15], [14, 13], [15, 18], [15, 14], [16, 19], [16, 7], [17, 23], [17, 11], [18, 27], [18, 15], [19, 20], [19, 16], [20, 21], [20, 19], [21, 28], [21, 22], [21, 20], [22, 23], [22, 21], [23, 24], [23, 22], [23, 17], [24, 25], [24, 23], [25, 29], [25, 26], [25, 24], [26, 27], [26, 25], [27, 26], [27, 18], [28, 32], [28, 21], [29, 36], [29, 25], [30, 39], [30, 31], [31, 32], [31, 30], [32, 33], [32, 31], [32, 28], [33, 34], [33, 32], [34, 40], [34, 35], [34, 33], [35, 36], [35, 34], [36, 37], [36, 35], [36, 29], [37, 38], [37, 36], [38, 41], [38, 37], [39, 42], [39, 30], [40, 46], [40, 34], [41, 50], [41, 38], [42, 43], [42, 39], [43, 44], [43, 42], [44, 51], [44, 45], [44, 43], [45, 46], [45, 44], [46, 47], [46, 45], [46, 40], [47, 48], [47, 46], [48, 52], [48, 49], [48, 47], [49, 50], [49, 48], [50, 49], [50, 41], [51, 44], [52, 48]] configuration = QasmBackendConfiguration( backend_name='fake_rochester', backend_version='0.0.0', n_qubits=53, basis_gates=['u1', 'u2', 'u3', 'cx', 'id'], simulator=False, local=True, conditional=False, open_pulse=False, memory=True, max_shots=8192, max_experiments=900, gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')], coupling_map=cmap, ) super().__init__(configuration)
def from_name( cls, backend_name: str, provider: "ibm_provider.IBMProvider", api: AccountClient, ) -> "IBMRetiredBackend": """Return a retired backend from its name.""" configuration = QasmBackendConfiguration( backend_name=backend_name, backend_version="0.0.0", online_date="2019-10-16T04:00:00Z", n_qubits=1, basis_gates=[], simulator=False, local=False, conditional=False, open_pulse=False, memory=False, max_shots=1, gates=[GateConfig(name="TODO", parameters=[], qasm_def="TODO")], coupling_map=[[0, 1]], max_experiments=300, ) return cls(configuration, provider, api)
def __init__(self, backend: Backend, comp_pass: Optional[BasePass] = None): """Create a new :py:class:`TketBackend` from a :py:class:`Backend`. :param backend: The device or simulator to wrap up :type backend: Backend :param comp_pass: The (optional) tket compilation pass to apply to each circuit before submitting to the :py:class:`Backend`, defaults to None :type comp_pass: Optional[BasePass], optional """ config = QasmBackendConfiguration( backend_name=("statevector_" if backend.supports_state else "") + "pytket/" + str(type(backend)), backend_version="0.0.1", n_qubits=len(backend.device.nodes) if backend.device else 40, basis_gates=_extract_basis_gates(backend), gates=[], local=False, simulator=False, conditional=not any( ( type(pred) == NoClassicalControlPredicate for pred in backend.required_predicates ) ), open_pulse=False, memory=backend.supports_shots, max_shots=10000, coupling_map=[[n.index[0], m.index[0]] for n, m in backend.device.coupling] if backend.device else None, max_experiments=10000, ) super().__init__(configuration=config, provider=None) self._backend = backend self._comp_pass = comp_pass
class QuantumInspireBackend(BaseBackend): # type: ignore DEFAULT_CONFIGURATION = QasmBackendConfiguration( backend_name='qi_simulator', backend_version=quantum_inspire_version, n_qubits=26, basis_gates=[ 'x', 'y', 'z', 'h', 'rx', 'ry', 'rz', 's', 'sdg', 't', 'tdg', 'cx', 'ccx', 'u1', 'u2', 'u3', 'id', 'swap', 'cz', 'snapshot' ], gates=[GateConfig(name='NotUsed', parameters=['NaN'], qasm_def='NaN')], local=False, simulator=True, conditional=True, open_pulse=False, memory=True, max_shots=1024, max_experiments=1, coupling_map=None) def __init__( self, api: QuantumInspireAPI, provider: Any, configuration: Optional[QasmBackendConfiguration] = None) -> None: """ Python implementation of a quantum simulator using Quantum Inspire API. Args: api: The interface instance to the Quantum Inspire API. provider: Provider for this backend. configuration: The configuration of the quantum inspire backend. The configuration must implement the fields given by the QiSimulatorPy.DEFAULT_CONFIGURATION. All configuration fields are listed in the table below. The table rows with an asterisk specify fields which can have a custom value and are allowed to be changed according to the description column. | key | description |----------------------------|------------------------------------------------------------------------- | backend_name (str)* | The name of the quantum inspire backend. The API can list the name of | | each available backend using the function api.list_backend_types(). One | | of the listed names must be used. | backend_version (str) | Backend version in the form X.Y.Z. | n_qubits (int) | Number of qubits. | basis_gates (list(str)) | A list of basis gates to compile to. | gates (GateConfig) | List of basis gates on the backend. Not used. | local (bool) | Indicates whether the system is running locally or remotely. | simulator (bool) | Specifies whether the backend is a simulator or a quantum system. | conditional (bool) | Backend supports conditional operations. | open_pulse (bool) | Backend supports open pulse. False. | memory (bool) | Backend supports memory. True. | max_shots (int) | Maximum number of shots supported. | max_experiments (int) | Optional: Maximum number of experiments (circuits) per job. | coupling_map (list(tuple)) | Define the edges. """ super().__init__( configuration=(configuration or QuantumInspireBackend.DEFAULT_CONFIGURATION), provider=provider) self.__backend: Dict[str, Any] = api.get_backend_type_by_name(self.name()) self.__api: QuantumInspireAPI = api @property def backend_name(self) -> str: return self.name() # type: ignore def run(self, qobj: QasmQobj) -> QIJob: """ Submits a quantum job to the Quantum Inspire platform. Args: qobj: The quantum job with the Qiskit algorithm and quantum inspire backend. Returns: A job that has been submitted. """ self.__validate_number_of_shots(qobj) number_of_shots = qobj.config.shots identifier = uuid.uuid1() project_name = 'qi-sdk-project-{}'.format(identifier) project = self.__api.create_project(project_name, number_of_shots, self.__backend) experiments = qobj.experiments job = QIJob(self, str(project['id']), self.__api) for experiment in experiments: self.__validate_number_of_clbits(experiment) full_state_projection = self.__validate_full_state_projection( experiment) if not full_state_projection: QuantumInspireBackend.__validate_unsupported_measurements( experiment) self._submit_experiment( experiment, number_of_shots, project=project, full_state_projection=full_state_projection) job.experiments = experiments return job def retrieve_job(self, job_id: str) -> QIJob: """ Retrieve a specified job by its job_id. Args: job_id: The job id. Returns: The job that has been retrieved. Raises: QisKitBackendError: If job not found or error occurs during retrieval of the job. """ try: self.__api.get_project(int(job_id)) except (ErrorMessage, ValueError): raise QisKitBackendError( "Could not retrieve job with job_id '{}' ".format(job_id)) return QIJob(self, job_id, self.__api) @staticmethod def _generate_cqasm(experiment: QasmQobjExperiment, full_state_projection: bool = True) -> str: """ Generates the cQASM from the Qiskit experiment. Args: experiment: The experiment that contains instructions to be converted to cQASM. full_state_projection: When False, the experiment is not suitable for full state projection Returns: The cQASM code that can be sent to the Quantum Inspire API. """ parser = CircuitToString(full_state_projection) number_of_qubits = experiment.header.n_qubits instructions = experiment.instructions with io.StringIO() as stream: stream.write('version 1.0\n') stream.write('# cQASM generated by QI backend for Qiskit\n') stream.write('qubits %d\n' % number_of_qubits) for instruction in instructions: parser.parse(stream, instruction) return stream.getvalue() def _submit_experiment( self, experiment: QasmQobjExperiment, number_of_shots: int, project: Optional[Dict[str, Any]] = None, full_state_projection: bool = True) -> QuantumInspireJob: compiled_qasm = self._generate_cqasm( experiment, full_state_projection=full_state_projection) measurements = self._collect_measurements(experiment) user_data = { 'name': experiment.header.name, 'memory_slots': experiment.header.memory_slots, 'creg_sizes': experiment.header.creg_sizes, 'measurements': measurements } job_id = self.__api.execute_qasm_async( compiled_qasm, backend_type=self.__backend, number_of_shots=number_of_shots, project=project, job_name=experiment.header.name, user_data=json.dumps(user_data), full_state_projection=full_state_projection) return job_id def get_experiment_results(self, qi_job: QIJob) -> List[ExperimentResult]: """ Get results from experiments from the Quantum-inspire platform. Args: qi_job: A job that has already been submitted and which execution is completed. Raises: QisKitBackendError: If an error occurred during execution by the backend. Returns: A list of experiment results; containing the data, execution time, status, etc. """ jobs = self.__api.get_jobs_from_project(int(qi_job.job_id())) results = [self.__api.get_result_from_job(job['id']) for job in jobs] experiment_results = [] for result, job in zip(results, jobs): if not result.get('histogram', {}): raise QisKitBackendError( 'Result from backend contains no histogram data!\n{}'. format(result.get('raw_text'))) user_data = json.loads(str(job.get('user_data'))) measurements = user_data.pop('measurements') histogram_obj, memory_data = self.__convert_result_data( result, measurements) full_state_histogram_obj = self.__convert_histogram( result, measurements) experiment_result_data = ExperimentResultData(counts=histogram_obj, memory=memory_data) experiment_result_data.probabilities = full_state_histogram_obj header = QobjExperimentHeader.from_dict(user_data) experiment_result_dictionary = { 'name': job.get('name'), 'seed': 42, 'shots': job.get('number_of_shots'), 'data': experiment_result_data, 'status': 'DONE', 'success': True, 'time_taken': result.get('execution_time_in_seconds'), 'header': header } experiment_results.append( ExperimentResult(**experiment_result_dictionary)) return experiment_results def __validate_number_of_shots(self, job: QasmQobj) -> None: """ Checks whether the number of shots has a valid value. Args: job: The quantum job with the Qiskit algorithm and quantum inspire backend. Raises: QisKitBackendError: When the value is not correct. """ number_of_shots = job.config.shots if number_of_shots < 1 or number_of_shots > self.__backend[ 'max_number_of_shots']: raise QisKitBackendError( 'Invalid shots (number_of_shots={})'.format(number_of_shots)) def __validate_number_of_clbits(self, experiment: QasmQobjExperiment) -> None: """ Checks whether the number of classical bits has a value cQASM can support. 1. When number of classical bits is less than 1 an error is raised. 2. When binary controlled gates are used and the number of classical registers > number of classical registers an error is raised. When using binary controlled gates in Qiskit, we can have something like: q = QuantumRegister(2) c = ClassicalRegister(4) circuit = QuantumCircuit(q, c) circuit.h(q[0]).c_if(c, 15) Because cQASM has the same number of classical registers as qubits (2 in this case), this circuit cannot be translated to valid cQASM. Args: experiment: The experiment with gate operations and header. Raises: QisKitBackendError: When the value is not correct. """ number_of_clbits = experiment.header.memory_slots if number_of_clbits < 1: raise QisKitBackendError( "Invalid amount of classical bits ({})!".format( number_of_clbits)) if BaseBackend.configuration(self).conditional: number_of_qubits = experiment.header.n_qubits if number_of_clbits > number_of_qubits: # no problem when there are no conditional gate operations for instruction in experiment.instructions: if hasattr(instruction, 'conditional'): raise QisKitBackendError( "Number of classical bits must be less than or equal to the" " number of qubits when using conditional gate operations" ) @staticmethod def __validate_full_state_projection( experiment: QasmQobjExperiment) -> bool: """ FSP (Full State Projection) can be used when no measurements are found in the circuit or when no other gates are found after measurements. Args: experiment: The experiment with gate operations and header. Returns: True when FSP can be used, otherwise False. """ fsp = True measurement_found = False for instruction in experiment.instructions: if instruction.name == 'measure': measurement_found = True elif measurement_found: fsp = False return fsp @staticmethod def __validate_unsupported_measurements( experiment: QasmQobjExperiment) -> None: """ When using non-FSP (not full state projection) certain measurements cannot be handled correctly because cQASM isn't as flexible as Qiskit in measuring to specific classical bits. Therefore some Qiskit constructions are not supported in QI: 1. When a quantum register is measured to different classical registers 2. When a classical register is used for the measurement of more than one quantum register Args: experiment: The experiment with gate operations and header. Raises: QisKitBackendError: When the circuit contains an invalid non-FSP measurement """ measurements: List[List[int]] = [] for instruction in experiment.instructions: if instruction.name == 'measure': for q, m in measurements: if q == instruction.qubits[ 0] and m != instruction.memory[0]: raise QisKitBackendError( 'Measurement of qubit {} to different classical registers ' 'is not supported'.format(q)) if q != instruction.qubits[0] and m == instruction.memory[ 0]: raise QisKitBackendError( 'Measurement of different qubits to the same classical register {0} ' 'is not supported'.format(m)) measurements.append( [instruction.qubits[0], instruction.memory[0]]) @staticmethod def _collect_measurements( experiment: QasmQobjExperiment) -> Dict[str, Any]: """ Determines the measured qubits and classical bits. The full-state measured qubits is returned when no measurements are present in the compiled circuit. Args: experiment: The experiment with gate operations and header. Returns: The dict contains measurements, which is a list of lists, for each measurement the list contains a list of [qubit_index, classical_bit_index], which represents the measurement of a qubit to a classical bit, and the second field in the dict is the number of classical bits (int). """ header = experiment.header number_of_qubits = header.n_qubits number_of_clbits = header.memory_slots operations = experiment.instructions measurements = [[ number_of_qubits - 1 - m.qubits[0], number_of_clbits - 1 - m.memory[0] ] for m in operations if m.name == 'measure'] if not measurements: measurements = [[index, index] for index in range(number_of_qubits)] return { 'measurements': measurements, 'number_of_clbits': number_of_clbits } @staticmethod def __qubit_to_classical_hex(qubit_register: str, measurements: Dict[str, Any], number_of_qubits: int) -> str: """ This function converts the qubit register data to the hexadecimal representation of the classical state. Args: qubit_register: The measured value of the qubits represented as int. measurements: The dictionary contains a measured qubits/classical bits map (list) and the number of classical bits (int). number_of_qubits: Number of qubits used in the algorithm. Returns: The hexadecimal value of the classical state. """ qubit_state = ('{0:0{1}b}'.format(int(qubit_register), number_of_qubits)) classical_state = ['0'] * measurements['number_of_clbits'] for q, c in measurements['measurements']: classical_state[c] = qubit_state[q] classical_state_str = ''.join(classical_state) classical_state_hex = hex(int(classical_state_str, 2)) return classical_state_hex @staticmethod def __convert_histogram(result: Dict[str, Any], measurements: Dict[str, Any]) -> Dict[str, float]: """ The quantum inspire backend always uses full state projection. The SDK user can measure not all qubits and change the combined classical bits. This function converts the result to a histogram output that represents the probabilities measured with the classical bits. Args: result: The result output from the quantum inspire backend with full- state projection histogram output. measurements: The dictionary contains a measured qubits/classical bits map (list) and the number of classical bits (int). Returns: The resulting full state histogram with probabilities. """ output_histogram_probabilities: Dict[str, float] = defaultdict(lambda: 0) number_of_qubits = result['number_of_qubits'] state_probability: Dict[str, float] = result['histogram'] for qubit_register, probability in state_probability.items(): classical_state_hex = QuantumInspireBackend.__qubit_to_classical_hex( qubit_register, measurements, number_of_qubits) output_histogram_probabilities[classical_state_hex] += probability sorted_histogram_probabilities: List[Tuple[str, float]] = sorted( output_histogram_probabilities.items(), key=lambda kv: int(kv[0], 16)) return dict(sorted_histogram_probabilities) def __convert_result_data( self, result: Dict[str, Any], measurements: Dict[str, Any]) -> Tuple[Dict[str, int], List[str]]: """ The quantum inspire backend returns the single shot values as raw data. This function converts this list of single shot values to hexadecimal memory data according the Qiskit spec. From this memory data the counts histogram is constructed by counting the single shot values. Note: When shots = 1, the backend returns an empty list as raw_data. This is a special case. In this case the resulting memory data consists of 1 value and the count histogram consists of 1 instance of this value. To determine this value a random float is generated in the range [0, 1). With this random number the value from this probabilities histogram is taken where the added probabilities is greater this random number. Example: probability histogram is {[0x0, 0.2], [0x3, 0.4], [0x5, 0.1], [0x6, 0.3]}. When random is in the range [0, 0.2) the first value of the probability histogram is taken (0x0). When random is in the range [0.2, 0.6) the second value of the probability histogram is taken (0x3). When random is in the range [0.6, 0.7) the third value of the probability histogram is taken (0x5). When random is in the range [0.7, 1) the last value of the probability histogram is taken (0x6). Args: result: The result output from the quantum inspire backend with full- state projection histogram output. measurements: The dictionary contains a measured qubits/classical bits map (list) and the number of classical bits (int). Returns: The result consists of two formats for the result. The first result is the histogram with count data, the second result is a list with converted hexadecimal memory values for each shot. """ memory_data = [] histogram_data: Dict[str, int] = defaultdict(lambda: 0) number_of_qubits: int = result['number_of_qubits'] raw_data = self.__api.get_raw_data_from_result(result['id']) if raw_data: for raw_qubit_register in raw_data: classical_state_hex = QuantumInspireBackend.__qubit_to_classical_hex( str(raw_qubit_register), measurements, number_of_qubits) memory_data.append(classical_state_hex) histogram_data = { elem: count for elem, count in Counter(memory_data).items() } else: state_probabilities = result['histogram'] random_probability = np.random.rand() sum_probability = 0.0 for qubit_register, probability in state_probabilities.items(): sum_probability += probability if random_probability < sum_probability: classical_state_hex = QuantumInspireBackend.__qubit_to_classical_hex( qubit_register, measurements, number_of_qubits) memory_data.append(classical_state_hex) histogram_data[classical_state_hex] = 1 break sorted_histogram_data: List[Tuple[str, int]] = sorted( histogram_data.items(), key=lambda kv: int(kv[0], 16)) histogram_obj = OrderedDict(sorted_histogram_data) return dict(histogram_obj), memory_data
def aws_device_2_configuration( aws_device: AwsDevice) -> QasmBackendConfiguration: configuration: QasmBackendConfiguration properties: DeviceCapabilities = aws_device.properties basis_gates_aws: List[str] = [] result_types_aws: List[ResultType] = [] if DeviceActionType.JAQCD in properties.action: # noinspection PyTypeChecker action_properties: JaqcdDeviceActionProperties = properties.action[ DeviceActionType.JAQCD] basis_gates_aws = action_properties.supportedOperations result_types_aws = action_properties.supportedResultTypes # Basics num_qubits = 0 backend_name = aws_device.name backend_version = aws_device.arn max_shots = properties.service.shotsRange[1] connectivity: dict = {} is_fully_connected = False is_simulator = False native_gate_set = ['u1', 'u2', 'u3', 'cx', 'id'] # use the qiskit / IBMQ default if hasattr(properties, 'paradigm'): if isinstance(properties.paradigm, GateModelQpuParadigmProperties): num_qubits = properties.paradigm.qubitCount connectivity = properties.paradigm.connectivity.connectivityGraph is_fully_connected = properties.paradigm.connectivity.fullyConnected # TODO: one day we will get data here and then do nifty things. # native_gate_set = properties.paradigm.nativeGateSet # if len(native_gate_set) == 0: # native_gate_set = [] if isinstance(properties.paradigm, GateModelSimulatorParadigmProperties): num_qubits = properties.paradigm.qubitCount is_simulator = True is_fully_connected = True basis_gates = [_known_maps.get(g, g) for g in native_gate_set] basis_gates = [ b for b in basis_gates if b ] # FIXME: print out as warning any that cannot be translated. gates = [gate_name_2_gate_config(g) for g in basis_gates] # Coupling # We need to map any arbitrary qubit numbering to a canonical mapping from_device_2_canonical = dict([ (q, i) for i, q in enumerate(connectivity.keys()) ]) from_canonical_2_device = dict([ (i, q) for i, q in enumerate(connectivity.keys()) ]) if is_fully_connected: coupling = [[ q1, q2 ] for q1, q2 in itertools.product(range(num_qubits), range(num_qubits)) if q1 != q2] else: # CouplingMap() coupling = [[int(k), int(c)] for k, connections in apply_coupling_map( connectivity, from_device_2_canonical).items() for c in connections] # Add coupling information coupling_map_1 = [[q] for q in set([q for q_list in coupling for q in q_list])] coupling_map_2 = get_gate_coupling( apply_coupling_map(connectivity, from_device_2_canonical), 2) # TODO: for another time maybe # coupling_map_3 = get_gate_coupling(connectivity, 3) for gate in gates: if gate.name in _native_two_qubit_gates: gate.coupling_map = coupling_map_2 else: gate.coupling_map = coupling_map_1 configuration: QasmBackendConfiguration = QasmBackendConfiguration( backend_name=backend_name, backend_version= '1.0.0', # TODO: there is no such thing as version, what to do instead? n_qubits=num_qubits, basis_gates=basis_gates, gates=gates, local=False, simulator=is_simulator, conditional=False, open_pulse=False, memory=False, max_shots=max_shots, coupling_map=coupling, max_experiments=None, coupling_device_2_canonical=from_device_2_canonical, coupling_canonical_2_device=from_canonical_2_device) return configuration
def __init__(self): """ .. code-block:: text 00 ↔ 01 ↔ 02 ↔ 03 ↔ 04 ↕ ↕ 05 ↔ 06 ↔ 07 ↔ 08 ↔ 09 ↕ ↕ ↕ 10 ↔ 11 ↔ 12 ↔ 13 ↔ 14 ↕ ↕ 15 ↔ 16 ↔ 17 ↔ 18 ↔ 19 """ cmap = [ [0, 1], [0, 5], [1, 0], [1, 2], [2, 1], [2, 3], [3, 2], [3, 4], [4, 3], [4, 9], [5, 0], [5, 6], [5, 10], [6, 5], [6, 7], [7, 6], [7, 8], [7, 12], [8, 7], [8, 9], [9, 4], [9, 8], [9, 14], [10, 5], [10, 11], [10, 15], [11, 10], [11, 12], [12, 7], [12, 11], [12, 13], [13, 12], [13, 14], [14, 9], [14, 13], [14, 19], [15, 10], [15, 16], [16, 15], [16, 17], [17, 16], [17, 18], [18, 17], [18, 19], [19, 14], [19, 18], ] configuration = QasmBackendConfiguration( backend_name="fake_poughkeepsie", backend_version="0.0.0", n_qubits=20, basis_gates=["u1", "u2", "u3", "cx", "id"], simulator=False, local=True, conditional=False, open_pulse=False, memory=True, max_shots=8192, max_experiments=900, gates=[GateConfig(name="TODO", parameters=[], qasm_def="TODO")], coupling_map=cmap, ) super().__init__(configuration)