Skip to content

🎨 Update of IonQ and Rigetti Devices #570

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
May 25, 2025
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8f97eea
🎨 WIP for IonQ Device handling
nquetschlich May 22, 2025
ea45fa2
Merge branch 'main' into update_ionq_devices
nquetschlich May 22, 2025
33a23f5
handled linter warnings
nquetschlich May 22, 2025
60575ae
♻️ refactored module structrue
nquetschlich May 23, 2025
a0799c1
♻️ refactored ionq handling
nquetschlich May 23, 2025
9831391
♻️ refactored gateset handling
nquetschlich May 23, 2025
1031198
♻️ refactored the IonQ gate definitions
nquetschlich May 23, 2025
c44b965
✨ introduced the new IonQ gates also to the native gates level
nquetschlich May 23, 2025
0a2e568
💡 added copyrights
nquetschlich May 23, 2025
64b96d3
🎨 improved ionq gateset handling
nquetschlich May 23, 2025
8d54a14
🎨 simplified gate definition
nquetschlich May 23, 2025
3ac576f
update Rigetti Device and Gateset accordingly to IonQ one
nquetschlich May 23, 2025
e6279f7
✅ added test to increase coverage
nquetschlich May 23, 2025
58b8de4
🚨
nquetschlich May 23, 2025
a27e24f
🎨 renamed custom rigetti gates
nquetschlich May 23, 2025
bc53846
🔥 removed unnecessary array definition fur custom gates
nquetschlich May 23, 2025
d9e8084
🎨 improved equivalence handling
nquetschlich May 23, 2025
b13e824
🎨 use relative imports instead of absolute ones
nquetschlich May 23, 2025
db651b3
🎨 renamed custom rigetti gates
nquetschlich May 23, 2025
e300c9b
🎨 adjusted the naming scheme of devices
nquetschlich May 23, 2025
f1666f4
🎨 removed tests that used an internal method
nquetschlich May 23, 2025
2eda174
🔥 removed unnecessary equivalence
nquetschlich May 23, 2025
371a77e
✨ added a rx decomposition
nquetschlich May 23, 2025
4c5666e
✨ improved the equivalence adding logic
nquetschlich May 23, 2025
9645895
✨ removed comment
nquetschlich May 23, 2025
f2b5fee
Merge branch 'main' into update_ionq_devices
nquetschlich May 24, 2025
4b1f0ee
Merge branch 'main' into update_ionq_devices
nquetschlich May 25, 2025
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
13 changes: 13 additions & 0 deletions src/mqt/bench/benchmark_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@

from dataclasses import dataclass

from qiskit.circuit import SessionEquivalenceLibrary

from .targets.gatesets import ionq, rigetti


@dataclass
class QiskitSettings:
Expand Down Expand Up @@ -276,6 +280,10 @@ def get_native_gates_level(
qc = pm.run(compiled_for_sk.remove_final_measurements(inplace=False))
qc.measure_all()

if "rigetti" in target.description:
rigetti.add_equivalences(SessionEquivalenceLibrary)
elif "ionq" in target.description:
ionq.add_equivalences(SessionEquivalenceLibrary)
pm = generate_preset_pass_manager(optimization_level=opt_level, target=target, seed_transpiler=10)
pm.layout = None
pm.routing = None
Expand Down Expand Up @@ -360,6 +368,11 @@ def get_mapped_level(
if file_precheck and path.is_file():
return True

if "rigetti" in device.description:
rigetti.add_equivalences(SessionEquivalenceLibrary)
elif "ionq" in device.description:
ionq.add_equivalences(SessionEquivalenceLibrary)

compiled = transpile(
qc,
target=device,
Expand Down
8 changes: 4 additions & 4 deletions src/mqt/bench/targets/devices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ def get_available_devices() -> list[Target]:
get_ibm_target("ibm_eagle_127"),
get_ibm_target("ibm_heron_133"),
get_ibm_target("ibm_heron_156"),
get_ionq_target("ionq_harmony"),
get_ionq_target("ionq_aria1"),
get_ionq_target("ionq_forte_36"),
get_ionq_target("ionq_aria_25"),
get_iqm_target("iqm_crystal_5"),
get_iqm_target("iqm_crystal_20"),
get_iqm_target("iqm_crystal_54"),
get_quantinuum_target("quantinuum_h2"),
get_rigetti_target("rigetti_aspen_m3"),
get_quantinuum_target("quantinuum_h2_56"),
get_rigetti_target("rigetti_ankaa_84"),
]


Expand Down
69 changes: 41 additions & 28 deletions src/mqt/bench/targets/devices/ionq.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,54 +11,59 @@
from __future__ import annotations

from qiskit.circuit import Parameter
from qiskit.circuit.library import Measure, RXGate, RXXGate, RYGate, RZGate
from qiskit.circuit.library import Measure, RZGate
from qiskit.transpiler import InstructionProperties, Target

from ..gatesets.ionq import GPI2Gate, GPIGate, MSGate, ZZGate


def get_ionq_target(device_name: str) -> Target:
"""Get the target device for a given IonQ device name."""
if device_name == "ionq_aria1":
return get_ionq_aria1_target()
if device_name == "ionq_harmony":
return get_ionq_harmony_target()
if device_name == "ionq_aria_25":
return get_ionq_aria_25()
if device_name == "ionq_forte_36":
return get_ionq_forte_36()
msg = f"Unknown IonQ device: '{device_name}'"
raise ValueError(msg)


def get_ionq_aria1_target() -> Target:
"""Get the target device for IonQ Aria1."""
def get_ionq_aria_25() -> Target:
"""Get the target device for IonQ Aria 1."""
num_qubits = 25
return _build_ionq_target(
num_qubits=num_qubits,
description="ionq_aria1",
description="ionq_aria_25",
entangling_gate="MS",
oneq_duration=135e-6,
twoq_duration=600e-6,
readout_duration=300e-6,
oneq_fidelity=0.9829,
twoq_fidelity=0.996,
spam_fidelity=0.9993,
oneq_fidelity=0.9998,
twoq_fidelity=0.98720,
spam_fidelity=0.99370,
)


def get_ionq_harmony_target() -> Target:
"""Get the target device for IonQ Harmony."""
num_qubits = 11
def get_ionq_forte_36() -> Target:
"""Get the target device for IonQ Forte 1."""
num_qubits = 36
return _build_ionq_target(
num_qubits=num_qubits,
description="ionq_harmony",
oneq_duration=10e-6,
twoq_duration=200e-6,
readout_duration=130e-6,
oneq_fidelity=0.9985,
twoq_fidelity=0.9614,
spam_fidelity=0.99752,
description="ionq_forte_36",
entangling_gate="ZZ",
oneq_duration=130e-6,
twoq_duration=970e-6,
readout_duration=150e-6,
oneq_fidelity=0.9998,
twoq_fidelity=0.9932,
spam_fidelity=0.9959,
)


def _build_ionq_target(
*,
num_qubits: int,
description: str,
entangling_gate: str,
oneq_duration: float,
twoq_duration: float,
readout_duration: float,
Expand All @@ -71,21 +76,19 @@

theta = Parameter("theta")
phi = Parameter("phi")
lam = Parameter("lambda")
alpha = Parameter("alpha")

# === Add single-qubit gates ===
singleq_props = {
(q,): InstructionProperties(duration=oneq_duration, error=1 - oneq_fidelity) for q in range(num_qubits)
}
rz_props = {(q,): InstructionProperties(duration=0.0, error=0.0) for q in range(num_qubits)}
rz_props = {(q,): InstructionProperties(duration=0, error=0) for q in range(num_qubits)}
measure_props = {
(q,): InstructionProperties(duration=readout_duration, error=1 - spam_fidelity) for q in range(num_qubits)
}

target.add_instruction(RXGate(theta), singleq_props)
target.add_instruction(RYGate(phi), singleq_props)
target.add_instruction(RZGate(lam), rz_props)
target.add_instruction(RZGate(theta), rz_props)
target.add_instruction(GPIGate(theta), singleq_props)
target.add_instruction(GPI2Gate(phi), singleq_props)
target.add_instruction(Measure(), measure_props)

# === Add two-qubit gates ===
Expand All @@ -94,5 +97,15 @@
(q1, q2): InstructionProperties(duration=twoq_duration, error=1 - twoq_fidelity) for q1, q2 in connectivity
}

target.add_instruction(RXXGate(alpha), twoq_props)
if entangling_gate == "MS":
alpha = Parameter("alpha")
beta = Parameter("beta")
gamma = Parameter("gamma")
target.add_instruction(MSGate(alpha, beta, gamma), twoq_props)
elif entangling_gate == "ZZ":
alpha = Parameter("alpha")
target.add_instruction(ZZGate(alpha), twoq_props)
else:
msg = f"Unknown entangling gate: '{entangling_gate}'."
raise ValueError(msg)

Check warning on line 110 in src/mqt/bench/targets/devices/ionq.py

View check run for this annotation

Codecov / codecov/patch

src/mqt/bench/targets/devices/ionq.py#L109-L110

Added lines #L109 - L110 were not covered by tests
return target
8 changes: 4 additions & 4 deletions src/mqt/bench/targets/devices/quantinuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@

def get_quantinuum_target(device_name: str) -> Target:
"""Get a hardcoded Quantinuum target device by name."""
if device_name == "quantinuum_h2":
return get_quantinuum_h2_target()
if device_name == "quantinuum_h2_56":
return get_quantinuum_h2_56()
msg = f"Unknown Quantinuum device: '{device_name}'."
raise ValueError(msg)


def get_quantinuum_h2_target() -> Target:
def get_quantinuum_h2_56() -> Target:
"""Get the target device for Quantinuum H2."""
num_qubits = 56
return _build_quantinuum_target(
name="quantinuum_h2",
name="quantinuum_h2_56",
num_qubits=num_qubits,
oneq_error=0.00003,
twoq_error=0.0015,
Expand Down
Loading
Loading