Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion qiskit_ionq/ionq_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ def __init__(

# Target (basis & connectivity)
self._target = self._make_target()
# Track noise_model for native simulator target caching
self._cached_noise_model: str | None = None

# Apply initial options if any
if initial_options:
Expand All @@ -141,6 +143,11 @@ def _default_options(cls) -> Options:

@property
def target(self) -> Target | None:
if self._simulator and self._gateset == "native":
current_noise_model = getattr(self.options, "noise_model", "ideal")
if self._cached_noise_model != current_noise_model:
self._target = self._make_target()
self._cached_noise_model = current_noise_model
return self._target

@property
Expand Down Expand Up @@ -321,7 +328,14 @@ def _make_target(self) -> Target:
tgt.add_instruction(gate)

# 2q native
if "forte" in self.name.lower():
noise_model = getattr(self.options, "noise_model", "ideal")
name_lower = self.name.lower()
name_is_forte = "forte-" in name_lower or name_lower.endswith("forte")
noise_model_is_forte = isinstance(noise_model, str) and (
noise_model.lower().startswith("forte")
)
use_zz = name_is_forte or noise_model_is_forte
if use_zz:
theta = Parameter("θ")
tgt.add_instruction(ZZGate(theta))
else:
Expand Down
46 changes: 45 additions & 1 deletion test/ionq_backend/test_base_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from unittest import mock

import pytest
from qiskit import QuantumCircuit
from qiskit import QuantumCircuit, transpile

from qiskit_ionq import exceptions, ionq_client, ionq_job
from qiskit_ionq.helpers import get_user_agent
Expand Down Expand Up @@ -314,3 +314,47 @@ def test_backend_memory(
job = ionq_job.IonQJob(mock_backend, job_id)
with pytest.raises(AttributeError):
job.get_memory() # pylint: disable=no-member


def test_simulator_native_target_respects_noise_model(provider):
"""Test that simulator native target uses ZZ gate for Forte noise models.

Args:
provider: A test IonQProvider.
"""
sim_backend = provider.get_backend("ionq_simulator", gateset="native")

target_ops = [op.name for op in sim_backend.target.operations]
assert "ms" in target_ops
assert "zz" not in target_ops

sim_backend.set_options(noise_model="forte-1")
target_ops = [op.name for op in sim_backend.target.operations]
assert "zz" in target_ops
assert "ms" not in target_ops

sim_backend.set_options(noise_model="aria-1")
target_ops = [op.name for op in sim_backend.target.operations]
assert "ms" in target_ops
assert "zz" not in target_ops


def test_forte_noise_model_transpiles_rzz_to_zz(provider):
"""Test that rzz gates transpile to zz (not ms) with Forte noise model.

Regression test for issue #210.

Args:
provider: A test IonQProvider.
"""
native_simulator = provider.get_backend("ionq_simulator", gateset="native")
native_simulator.set_options(noise_model="forte-1")

qc = QuantumCircuit(2)
qc.rzz(1, 0, 1)

transpiled_qc = transpile(qc, backend=native_simulator, optimization_level=3)
ops = transpiled_qc.count_ops()

assert "zz" in ops
assert "ms" not in ops
Loading