diff --git a/azure-quantum/azure/quantum/qiskit/backends/__init__.py b/azure-quantum/azure/quantum/qiskit/backends/__init__.py index 4b6cfd6e0..83395c31b 100644 --- a/azure-quantum/azure/quantum/qiskit/backends/__init__.py +++ b/azure-quantum/azure/quantum/qiskit/backends/__init__.py @@ -10,6 +10,8 @@ IonQSimulatorBackend, IonQQPUQirBackend, IonQAriaQirBackend, + IonQForteBackend, + IonQForteQirBackend, IonQSimulatorQirBackend, ) diff --git a/azure-quantum/azure/quantum/qiskit/backends/ionq.py b/azure-quantum/azure/quantum/qiskit/backends/ionq.py index 6c74a539a..80b2876b1 100644 --- a/azure-quantum/azure/quantum/qiskit/backends/ionq.py +++ b/azure-quantum/azure/quantum/qiskit/backends/ionq.py @@ -30,13 +30,16 @@ "IonQQPUBackend", "IonQSimulatorBackend", "IonQAriaBackend", + "IonQForteBackend", "IonQQirBackend", "IonQSimulatorQirBackend", "IonQSimulatorNativeBackend", "IonQQPUQirBackend", "IonQQPUNativeBackend", "IonQAriaQirBackend", + "IonQForteQirBackend", "IonQAriaNativeBackend", + "IonQForteNativeBackend", ] @@ -159,6 +162,38 @@ def __init__(self, name: str, provider: "AzureQuantumProvider", **kwargs): super().__init__(configuration=configuration, provider=provider, **kwargs) +class IonQForteQirBackend(IonQQirBackendBase): + backend_names = ("ionq.qpu.forte-1",) + + def __init__(self, name: str, provider: "AzureQuantumProvider", **kwargs): + """Base class for interfacing with an IonQ Forte QPU backend""" + + default_config = BackendConfiguration.from_dict( + { + "backend_name": name, + "backend_version": __version__, + "simulator": False, + "local": False, + "coupling_map": None, + "description": "IonQ Forte QPU on Azure Quantum", + "basis_gates": ionq_basis_gates, + "memory": False, + "n_qubits": 35, + "conditional": False, + "max_shots": 10000, + "max_experiments": 1, + "open_pulse": False, + "gates": [{"name": "TODO", "parameters": [], "qasm_def": "TODO"}], + "azure": self._azure_config(), + } + ) + logger.info("Initializing IonQForteQirBackend") + configuration: BackendConfiguration = kwargs.pop( + "configuration", default_config + ) + super().__init__(configuration=configuration, provider=provider, **kwargs) + + class IonQBackend(AzureBackend): """Base class for interfacing with an IonQ backend in Azure Quantum""" @@ -348,6 +383,39 @@ def __init__(self, name: str, provider: "AzureQuantumProvider", **kwargs): super().__init__(configuration=configuration, provider=provider, **kwargs) +class IonQForteBackend(IonQBackend): + backend_names = ("ionq.qpu.forte-1",) + + def __init__(self, name: str, provider: "AzureQuantumProvider", **kwargs): + """Base class for interfacing with an IonQ Forte QPU backend""" + gateset = kwargs.pop("gateset", "qis") + default_config = BackendConfiguration.from_dict( + { + "backend_name": name, + "backend_version": __version__, + "simulator": False, + "local": False, + "coupling_map": None, + "description": "IonQ Forte QPU on Azure Quantum", + "basis_gates": GATESET_MAP[gateset], + "memory": False, + "n_qubits": 35, + "conditional": False, + "max_shots": 10000, + "max_experiments": 1, + "open_pulse": False, + "gates": [{"name": "TODO", "parameters": [], "qasm_def": "TODO"}], + "azure": self._azure_config(), + "gateset": gateset, + } + ) + logger.info("Initializing IonQForteBackend") + configuration: BackendConfiguration = kwargs.pop( + "configuration", default_config + ) + super().__init__(configuration=configuration, provider=provider, **kwargs) + + class IonQAriaNativeBackend(IonQAriaBackend): def __init__(self, name: str, provider: "AzureQuantumProvider", **kwargs): if "gateset" not in kwargs: @@ -362,3 +430,19 @@ def _azure_config(self) -> Dict[str, str]: } ) return config + + +class IonQForteNativeBackend(IonQForteBackend): + def __init__(self, name: str, provider: "AzureQuantumProvider", **kwargs): + if "gateset" not in kwargs: + kwargs["gateset"] = "native" + super().__init__(name, provider, **kwargs) + + def _azure_config(self) -> Dict[str, str]: + config = super()._azure_config() + config.update( + { + "is_default": False, + } + ) + return config diff --git a/azure-quantum/azure/quantum/target/ionq.py b/azure-quantum/azure/quantum/target/ionq.py index 276e1030b..bba2324eb 100644 --- a/azure-quantum/azure/quantum/target/ionq.py +++ b/azure-quantum/azure/quantum/target/ionq.py @@ -13,21 +13,24 @@ "ionq.simulator" : 0.0, "ionq.qpu" : 0.00003, "ionq.qpu.aria-1" : 0.0002205, - "ionq.qpu.aria-2" : 0.0002205 + "ionq.qpu.aria-2" : 0.0002205, + "ionq.qpu.forte-1" : 0.0002205 } COST_2QUBIT_GATE_MAP = { "ionq.simulator" : 0.0, "ionq.qpu" : 0.0003, "ionq.qpu.aria-1" : 0.00098, - "ionq.qpu.aria-2" : 0.00098 + "ionq.qpu.aria-2" : 0.00098, + "ionq.qpu.forte-1" : 0.00098 } MIN_PRICE_MAP = { "ionq.simulator" : 0.0, "ionq.qpu" : 1.0, "ionq.qpu.aria-1" : 97.5, - "ionq.qpu.aria-2" : 97.5 + "ionq.qpu.aria-2" : 97.5, + "ionq.qpu.forte-1" : 97.5 } def int_to_bitstring(k: int, num_qubits: int, measured_qubit_ids: List[int]): @@ -43,7 +46,8 @@ class IonQ(Target): "ionq.qpu", "ionq.simulator", "ionq.qpu.aria-1", - "ionq.qpu.aria-2" + "ionq.qpu.aria-2", + "ionq.qpu.forte-1" ) def __init__( diff --git a/azure-quantum/tests/unit/test_qiskit.py b/azure-quantum/tests/unit/test_qiskit.py index 9b3b3e514..27527e197 100644 --- a/azure-quantum/tests/unit/test_qiskit.py +++ b/azure-quantum/tests/unit/test_qiskit.py @@ -590,6 +590,26 @@ def test_ionq_aria2_has_qis_gateset_target(self): provider = DummyProvider() provider.get_backend("ionq.qpu.aria-2", gateset="qis") + @pytest.mark.ionq + def test_ionq_forte1_has_default(self): + provider = DummyProvider() + provider.get_backend("ionq.qpu.forte-1") + + @pytest.mark.ionq + def test_ionq_forte1_has_qir_target(self): + provider = DummyProvider() + provider.get_backend("ionq.qpu.forte-1", input_data_format="qir.v1") + + @pytest.mark.ionq + def test_ionq_forte1_has_native_gateset_target(self): + provider = DummyProvider() + provider.get_backend("ionq.qpu.forte-1", gateset="native") + + @pytest.mark.ionq + def test_ionq_forte1_has_qis_gateset_target(self): + provider = DummyProvider() + provider.get_backend("ionq.qpu.forte-1", gateset="qis") + # The following test is skipped until we can use a workspace # with this target available as part of the E2E tests. # @pytest.mark.ionq