openquantum-sdk-qiskit 0.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. openquantum_sdk_qiskit-0.2.4/PKG-INFO +157 -0
  2. openquantum_sdk_qiskit-0.2.4/README.md +145 -0
  3. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit/__init__.py +19 -0
  4. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit/_qasm.py +29 -0
  5. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit/backend_data.py +274 -0
  6. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit/oq_backend.py +192 -0
  7. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit/oq_estimator.py +64 -0
  8. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit/oq_sampler.py +156 -0
  9. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit/oq_service.py +608 -0
  10. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit/oq_target.py +339 -0
  11. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit.egg-info/PKG-INFO +157 -0
  12. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit.egg-info/SOURCES.txt +25 -0
  13. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit.egg-info/dependency_links.txt +1 -0
  14. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit.egg-info/requires.txt +2 -0
  15. openquantum_sdk_qiskit-0.2.4/openquantum_sdk_qiskit.egg-info/top_level.txt +2 -0
  16. openquantum_sdk_qiskit-0.2.4/pyproject.toml +23 -0
  17. openquantum_sdk_qiskit-0.2.4/setup.cfg +4 -0
  18. openquantum_sdk_qiskit-0.2.4/tests/test_auth_login.py +58 -0
  19. openquantum_sdk_qiskit-0.2.4/tests/test_qiskit_adapter.py +361 -0
  20. openquantum_sdk_qiskit-0.2.4/tests/test_qiskit_backend.py +47 -0
  21. openquantum_sdk_qiskit-0.2.4/tests/test_qiskit_estimator.py +27 -0
  22. openquantum_sdk_qiskit-0.2.4/tests/test_qiskit_sampler.py +73 -0
  23. openquantum_sdk_qiskit-0.2.4/tests/test_qiskit_service.py +26 -0
  24. openquantum_sdk_qiskit-0.2.4/tests/test_sampler_v2_mapping.py +258 -0
  25. openquantum_sdk_qiskit-0.2.4/tests/test_service_and_backend.py +74 -0
  26. openquantum_sdk_qiskit-0.2.4/tests/test_service_backend_and_sampler_integration.py +183 -0
  27. openquantum_sdk_qiskit-0.2.4/tests/test_service_backends_filters.py +70 -0
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.4
2
+ Name: openquantum-sdk-qiskit
3
+ Version: 0.2.4
4
+ Summary: Qiskit Python SDK for Open Quantum
5
+ Classifier: Programming Language :: Python :: 3
6
+ Classifier: License :: OSI Approved :: Apache Software License
7
+ Classifier: Operating System :: OS Independent
8
+ Requires-Python: >=3.9
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: openquantum-sdk>=0.3.3
11
+ Requires-Dist: qiskit>=2.0.0
12
+
13
+ # openquantum-sdk-qiskit
14
+
15
+ Qiskit 2.x addon for the Open Quantum SDK.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ # Plugin (and core SDK)
21
+ pip install openquantum-sdk-qiskit
22
+
23
+ # or via extras:
24
+ pip install "openquantum-sdk[qiskit]"
25
+ ```
26
+
27
+ ## Authentication
28
+
29
+ The OpenQuantum Qiskit Service uses **saved accounts** for authentication.
30
+
31
+ ### Option 1: Saved Account (Recommended)
32
+
33
+ Save your credentials once using the `ClientCredentials` model from the core SDK. This is the recommended, secure, one-time setup.
34
+
35
+ ```python
36
+ from openquantum_sdk.auth import ClientCredentials
37
+ from openquantum_sdk.qiskit import OpenQuantumService
38
+
39
+ OpenQuantumService.save_account(
40
+ name="default", # The name to refer to this account later
41
+ creds=ClientCredentials(client_id="s_...", client_secret="e460c8..."),
42
+ use_keyring=True, # Recommended for secure storage
43
+ )
44
+
45
+ # Then, load it automatically:
46
+ svc = OpenQuantumService()
47
+ ```
48
+
49
+ ### Option 2: Direct in Code
50
+
51
+ You can also pass the credentials directly when instantiating the service.
52
+
53
+ ```python
54
+ from openquantum_sdk.qiskit import OpenQuantumService
55
+ from openquantum_sdk.auth import ClientCredentials
56
+
57
+ creds=ClientCredentials(client_id="s_...", client_secret="e460c8...")
58
+
59
+ svc = OpenQuantumService(creds=creds)
60
+ ```
61
+
62
+ ## Quickstart: SamplerV2
63
+
64
+ ```python
65
+ # 1) Imports — just change import path from qiskit.* to openquantum.qiskit for SamplerV2 and EstimatorV2
66
+ from openquantum_sdk.qiskit import OpenQuantumService, SamplerV2, list_backends, get_backend
67
+
68
+ # Qiskit tools
69
+ from qiskit import QuantumCircuit, transpile
70
+ from qiskit.visualization import plot_histogram
71
+
72
+ # 2) Auth — load saved account
73
+ svc = OpenQuantumService() # auto-loads saved account by default
74
+
75
+ # 3) Discover backends (client-side filters, optional)
76
+ bks = list_backends(service = svc, name="ankaa", device_type="QPU", online=True)
77
+ print(bks)
78
+
79
+ # 4) Select a backend (by id, name, or short code)
80
+ backend = get_backend("rigetti:ankaa-3")
81
+
82
+ # 5) Build a circuit, transpile against the backend if desired
83
+ qc = QuantumCircuit(2)
84
+ qc.h(0)
85
+ qc.cx(0, 1)
86
+ qc.measure_all()
87
+
88
+ tqc = transpile(
89
+ qc,
90
+ backend=backend,
91
+ optimization_level=1,
92
+ )
93
+
94
+ # 6) Create a Sampler and **run**
95
+
96
+ CONFIG = {
97
+ "backend_class_id": "rigetti:ankaa-3", # UUID or short code
98
+ "job_subcategory_id": "phys:hds", # Short code for Hamiltonian Dynamics Simulation
99
+ "name": "bell-demo", # optional job name prefix
100
+ }
101
+
102
+ sampler = SamplerV2(
103
+ backend=backend,
104
+ scheduler=svc.scheduler,
105
+ config=CONFIG,
106
+ export_format="qasm3",
107
+ )
108
+
109
+ # Run a job (circuit, pub for params, shots)
110
+ job = sampler.run([(tqc, None, 1000)])
111
+ result = job.result()
112
+ counts = result[0].data.meas.get_counts()
113
+ print(counts)
114
+
115
+ # 7) Plot
116
+ plot_histogram(counts)
117
+ ```
118
+
119
+ ## EstimatorV2 Quickstart
120
+
121
+ ```python
122
+ # Import EstimatorV2
123
+ from openquantum_sdk.qiskit import EstimatorV2
124
+ from qiskit.quantum_info import SparsePauliOp
125
+ # Create an Estimator
126
+ est = EstimatorV2(
127
+ backend=backend,
128
+ scheduler=svc.scheduler,
129
+ config=CONFIG
130
+ )
131
+ layout = tqc.layout
132
+ obs = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)]).apply_layout(layout) # Define observations for estimator to evaluate
133
+ # Run (circuit, observables)
134
+ job = est.run([(tqc, obs)])
135
+ result = job.result()
136
+ print(f"Expectation value: {result[0].data.evs}")
137
+ ```
138
+
139
+ ## API Reference
140
+
141
+ ## API Reference
142
+
143
+ ### `OpenQuantumService` Helpers
144
+
145
+ | Method | Description |
146
+ |--------|-------------|
147
+ | `OpenQuantumService()` | Main client for auth, discovery, and factory creation. |
148
+ | `save_account(...)` | Securely save credentials for auto-loading. |
149
+ | `list_backends(...)` | Discover available **BackendV2** objects (with client-side filters). |
150
+ | `get_backend(...)` | Retrieve a single **BackendV2** object. |
151
+
152
+ ### Qiskit Primitives
153
+
154
+ | Class | Description |
155
+ |-------|-------------|
156
+ | `SamplerV2` | Qiskit 2.x Sampler compatible primitive that submits jobs to the Open Quantum platform. |
157
+ | `EstimatorV2` | Qiskit 2.x Estimator compatible primitive that submits jobs to the Open Quantum platform. |
@@ -0,0 +1,145 @@
1
+ # openquantum-sdk-qiskit
2
+
3
+ Qiskit 2.x addon for the Open Quantum SDK.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # Plugin (and core SDK)
9
+ pip install openquantum-sdk-qiskit
10
+
11
+ # or via extras:
12
+ pip install "openquantum-sdk[qiskit]"
13
+ ```
14
+
15
+ ## Authentication
16
+
17
+ The OpenQuantum Qiskit Service uses **saved accounts** for authentication.
18
+
19
+ ### Option 1: Saved Account (Recommended)
20
+
21
+ Save your credentials once using the `ClientCredentials` model from the core SDK. This is the recommended, secure, one-time setup.
22
+
23
+ ```python
24
+ from openquantum_sdk.auth import ClientCredentials
25
+ from openquantum_sdk.qiskit import OpenQuantumService
26
+
27
+ OpenQuantumService.save_account(
28
+ name="default", # The name to refer to this account later
29
+ creds=ClientCredentials(client_id="s_...", client_secret="e460c8..."),
30
+ use_keyring=True, # Recommended for secure storage
31
+ )
32
+
33
+ # Then, load it automatically:
34
+ svc = OpenQuantumService()
35
+ ```
36
+
37
+ ### Option 2: Direct in Code
38
+
39
+ You can also pass the credentials directly when instantiating the service.
40
+
41
+ ```python
42
+ from openquantum_sdk.qiskit import OpenQuantumService
43
+ from openquantum_sdk.auth import ClientCredentials
44
+
45
+ creds=ClientCredentials(client_id="s_...", client_secret="e460c8...")
46
+
47
+ svc = OpenQuantumService(creds=creds)
48
+ ```
49
+
50
+ ## Quickstart: SamplerV2
51
+
52
+ ```python
53
+ # 1) Imports — just change import path from qiskit.* to openquantum.qiskit for SamplerV2 and EstimatorV2
54
+ from openquantum_sdk.qiskit import OpenQuantumService, SamplerV2, list_backends, get_backend
55
+
56
+ # Qiskit tools
57
+ from qiskit import QuantumCircuit, transpile
58
+ from qiskit.visualization import plot_histogram
59
+
60
+ # 2) Auth — load saved account
61
+ svc = OpenQuantumService() # auto-loads saved account by default
62
+
63
+ # 3) Discover backends (client-side filters, optional)
64
+ bks = list_backends(service = svc, name="ankaa", device_type="QPU", online=True)
65
+ print(bks)
66
+
67
+ # 4) Select a backend (by id, name, or short code)
68
+ backend = get_backend("rigetti:ankaa-3")
69
+
70
+ # 5) Build a circuit, transpile against the backend if desired
71
+ qc = QuantumCircuit(2)
72
+ qc.h(0)
73
+ qc.cx(0, 1)
74
+ qc.measure_all()
75
+
76
+ tqc = transpile(
77
+ qc,
78
+ backend=backend,
79
+ optimization_level=1,
80
+ )
81
+
82
+ # 6) Create a Sampler and **run**
83
+
84
+ CONFIG = {
85
+ "backend_class_id": "rigetti:ankaa-3", # UUID or short code
86
+ "job_subcategory_id": "phys:hds", # Short code for Hamiltonian Dynamics Simulation
87
+ "name": "bell-demo", # optional job name prefix
88
+ }
89
+
90
+ sampler = SamplerV2(
91
+ backend=backend,
92
+ scheduler=svc.scheduler,
93
+ config=CONFIG,
94
+ export_format="qasm3",
95
+ )
96
+
97
+ # Run a job (circuit, pub for params, shots)
98
+ job = sampler.run([(tqc, None, 1000)])
99
+ result = job.result()
100
+ counts = result[0].data.meas.get_counts()
101
+ print(counts)
102
+
103
+ # 7) Plot
104
+ plot_histogram(counts)
105
+ ```
106
+
107
+ ## EstimatorV2 Quickstart
108
+
109
+ ```python
110
+ # Import EstimatorV2
111
+ from openquantum_sdk.qiskit import EstimatorV2
112
+ from qiskit.quantum_info import SparsePauliOp
113
+ # Create an Estimator
114
+ est = EstimatorV2(
115
+ backend=backend,
116
+ scheduler=svc.scheduler,
117
+ config=CONFIG
118
+ )
119
+ layout = tqc.layout
120
+ obs = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)]).apply_layout(layout) # Define observations for estimator to evaluate
121
+ # Run (circuit, observables)
122
+ job = est.run([(tqc, obs)])
123
+ result = job.result()
124
+ print(f"Expectation value: {result[0].data.evs}")
125
+ ```
126
+
127
+ ## API Reference
128
+
129
+ ## API Reference
130
+
131
+ ### `OpenQuantumService` Helpers
132
+
133
+ | Method | Description |
134
+ |--------|-------------|
135
+ | `OpenQuantumService()` | Main client for auth, discovery, and factory creation. |
136
+ | `save_account(...)` | Securely save credentials for auto-loading. |
137
+ | `list_backends(...)` | Discover available **BackendV2** objects (with client-side filters). |
138
+ | `get_backend(...)` | Retrieve a single **BackendV2** object. |
139
+
140
+ ### Qiskit Primitives
141
+
142
+ | Class | Description |
143
+ |-------|-------------|
144
+ | `SamplerV2` | Qiskit 2.x Sampler compatible primitive that submits jobs to the Open Quantum platform. |
145
+ | `EstimatorV2` | Qiskit 2.x Estimator compatible primitive that submits jobs to the Open Quantum platform. |
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ from .oq_service import OpenQuantumService
4
+ from .oq_backend import OpenQuantumBackend
5
+ from .oq_sampler import OQSampler
6
+ from .oq_estimator import OQEstimator
7
+
8
+ SamplerV2 = OQSampler
9
+ EstimatorV2 = OQEstimator
10
+
11
+ __version__ = "0.2.4"
12
+ __all__ = [
13
+ "OpenQuantumService",
14
+ "OpenQuantumBackend",
15
+ "OQSampler",
16
+ "SamplerV2",
17
+ "OQEstimator",
18
+ "EstimatorV2",
19
+ ]
@@ -0,0 +1,29 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+
6
+ def export_circuit_to_qasm(circuit: Any, fmt: str) -> bytes:
7
+ f = (fmt or "qasm3").lower()
8
+ if f == "qasm3":
9
+ try:
10
+ import qiskit.qasm3 as qasm3
11
+ except Exception as e:
12
+ raise RuntimeError(
13
+ "Qiskit qasm3 exporter is required. Install: pip install 'openquantum-sdk[qiskit]'"
14
+ ) from e
15
+ qasm = qasm3.dumps(circuit)
16
+ return qasm.encode("utf-8")
17
+ if f == "qasm2":
18
+ try:
19
+ from qiskit import qasm2
20
+
21
+ qasm = qasm2.dumps(circuit)
22
+ return qasm.encode("utf-8")
23
+ except Exception:
24
+ try:
25
+ qasm = circuit.qasm()
26
+ return qasm.encode("utf-8")
27
+ except Exception as e:
28
+ raise RuntimeError("Failed to export circuit to OpenQASM 2.") from e
29
+ raise ValueError("export_format must be 'qasm2' or 'qasm3'")
@@ -0,0 +1,274 @@
1
+
2
+ from typing import List, Dict
3
+
4
+
5
+ def adj_to_edges(adj: Dict[str, List[str]], shift: int = 0) -> List[List[int]]:
6
+ edges = []
7
+ seen = set()
8
+ for u_str, neighbors in adj.items():
9
+ u = int(u_str) - shift
10
+ for v_str in neighbors:
11
+ v = int(v_str) - shift
12
+ if u < v:
13
+ pair = (u, v)
14
+ else:
15
+ pair = (v, u)
16
+ if pair not in seen:
17
+ edges.append([pair[0], pair[1]])
18
+ seen.add(pair)
19
+ return sorted(edges)
20
+
21
+
22
+ def fully_connected(n: int) -> List[List[int]]:
23
+ edges = []
24
+ for i in range(n):
25
+ for j in range(i + 1, n):
26
+ edges.append([i, j])
27
+ return edges
28
+
29
+
30
+ # --- Rigetti Ankaa-3 ---
31
+ RIGETTI_ADJ = {
32
+ '0': ['1', '7'], '1': ['0', '2', '8'], '2': ['1', '3', '9'], '3': ['2', '4', '10'],
33
+ '4': ['3', '5', '11'], '5': ['4', '6', '12'], '6': ['5', '13'], '7': ['0', '8', '14'],
34
+ '8': ['1', '7', '9', '15'], '9': ['2', '8', '10', '16'], '10': ['3', '9', '11', '17'],
35
+ '11': ['4', '10', '12', '18'], '12': ['5', '11', '13', '19'], '13': ['6', '12', '20'],
36
+ '14': ['7', '15', '21'], '15': ['8', '14', '16', '22'], '16': ['9', '15', '17', '23'],
37
+ '17': ['10', '16', '18', '24'], '18': ['11', '17', '19', '25'], '19': ['12', '18', '20', '26'],
38
+ '20': ['13', '19', '27'], '21': ['14', '22', '28'], '22': ['15', '21', '23', '29'],
39
+ '23': ['16', '22', '24', '30'], '24': ['17', '23', '25', '31'], '25': ['18', '24', '26', '32'],
40
+ '26': ['19', '25', '27', '33'], '27': ['20', '26'], '28': ['21', '29', '35'],
41
+ '29': ['22', '28', '30', '36'], '30': ['23', '29', '31', '37'], '31': ['24', '30', '32', '38'],
42
+ '32': ['25', '31', '33', '39'], '33': ['26', '32', '34', '40'], '34': ['33', '41'],
43
+ '35': ['28', '36'], '36': ['29', '35', '37', '43'], '37': ['30', '36', '38', '44'],
44
+ '38': ['31', '37', '39', '45'], '39': ['32', '38', '40', '46'], '40': ['33', '39', '41', '47'],
45
+ '41': ['34', '40'], '43': ['36', '50'], '44': ['37', '45', '51'], '45': ['38', '44', '46', '52'],
46
+ '46': ['39', '45', '47', '53'], '47': ['40', '46', '54'], '49': ['50', '56'],
47
+ '50': ['43', '49', '51', '57'], '51': ['44', '50', '52', '58'], '52': ['45', '51', '53', '59'],
48
+ '53': ['46', '52', '54', '60'], '54': ['47', '53', '55', '61'], '55': ['54', '62'],
49
+ '56': ['49', '57', '63'], '57': ['50', '56', '58', '64'], '58': ['51', '57', '59', '65'],
50
+ '59': ['52', '58', '60', '66'], '60': ['53', '59', '61', '67'], '61': ['54', '60', '62', '68'],
51
+ '62': ['55', '61', '69'], '63': ['56', '64', '70'], '64': ['57', '63', '65', '71'],
52
+ '65': ['58', '64', '66', '72'], '66': ['59', '65', '73'], '67': ['60', '68', '74'],
53
+ '68': ['61', '67', '69', '75'], '69': ['62', '68', '76'], '70': ['63', '71', '77'],
54
+ '71': ['64', '70', '72', '78'], '72': ['65', '71', '73', '79'], '73': ['66', '72', '74', '80'],
55
+ '74': ['67', '73', '75', '81'], '75': ['68', '74', '76', '82'], '76': ['69', '75', '83'],
56
+ '77': ['70', '78'], '78': ['71', '77', '79'], '79': ['72', '78', '80'],
57
+ '80': ['73', '79', '81'], '81': ['74', '80', '82'], '82': ['75', '81', '83'],
58
+ '83': ['76', '82']
59
+ }
60
+
61
+ RIGETTI_ANKAA_3_CAPS = {
62
+ "version": 1,
63
+ "n_qubits": 84,
64
+ "timing": {
65
+ "dt": 1e-9, # Placeholder
66
+ "durations": []
67
+ },
68
+ "native_ops": [
69
+ {"name": "rx", "arity": 1, "params": ["theta"]},
70
+ {"name": "rz", "arity": 1, "params": ["phi"]},
71
+ {"name": "iswap", "arity": 2},
72
+ {"name": "measure", "arity": 1}
73
+ ],
74
+ "supported_ops": [
75
+ {"name": "cz", "arity": 2}, {"name": "xy", "arity": 2}, {"name": "ccnot", "arity": 3},
76
+ {"name": "cnot", "arity": 2}, {"name": "cphaseshift", "arity": 2}, {"name": "cswap", "arity": 3},
77
+ {"name": "h", "arity": 1}, {"name": "i", "arity": 1}, {"name": "iswap", "arity": 2},
78
+ {"name": "phaseshift", "arity": 1}, {"name": "pswap", "arity": 2}, {"name": "rx", "arity": 1},
79
+ {"name": "ry", "arity": 1}, {"name": "rz", "arity": 1}, {"name": "s", "arity": 1},
80
+ {"name": "si", "arity": 1}, {"name": "swap", "arity": 2}, {"name": "t", "arity": 1},
81
+ {"name": "ti", "arity": 1}, {"name": "x", "arity": 1}, {"name": "y", "arity": 1},
82
+ {"name": "z", "arity": 1}
83
+ ],
84
+ "topology": {
85
+ "directed_edges": False,
86
+ "coupling_map": adj_to_edges(RIGETTI_ADJ, shift=0)
87
+ },
88
+ "noise": {},
89
+ "qubit_properties": [],
90
+ "limits": {"max_circuits": 1024},
91
+ "features": ["measure"]
92
+ }
93
+
94
+ # --- IonQ Aria-1 ---
95
+ IONQ_ARIA_1_CAPS = {
96
+ "version": 1,
97
+ "n_qubits": 25,
98
+ "timing": {"dt": None, "durations": []},
99
+ "native_ops": [
100
+ {"name": "gpi", "arity": 1, "params": ["phi"]},
101
+ {"name": "gpi2", "arity": 1, "params": ["phi"]},
102
+ {"name": "ms", "arity": 2, "params": ["phi0", "phi1"]},
103
+ {"name": "measure", "arity": 1}
104
+ ],
105
+ "supported_ops": [
106
+ {"name": "x", "arity": 1}, {"name": "y", "arity": 1}, {"name": "z", "arity": 1},
107
+ {"name": "h", "arity": 1}, {"name": "s", "arity": 1}, {"name": "si", "arity": 1},
108
+ {"name": "t", "arity": 1}, {"name": "ti", "arity": 1}, {"name": "v", "arity": 1},
109
+ {"name": "vi", "arity": 1}, {"name": "rx", "arity": 1}, {"name": "ry", "arity": 1},
110
+ {"name": "rz", "arity": 1}, {"name": "cnot", "arity": 2}, {"name": "swap", "arity": 2},
111
+ {"name": "xx", "arity": 2}, {"name": "yy", "arity": 2}, {"name": "zz", "arity": 2}
112
+ ],
113
+ "topology": {
114
+ "directed_edges": False,
115
+ "coupling_map": fully_connected(25)
116
+ },
117
+ "noise": {},
118
+ "limits": {"max_circuits": 1024},
119
+ "features": ["measure"]
120
+ }
121
+
122
+ # --- IonQ Forte-1 ---
123
+ IONQ_FORTE_1_CAPS = {
124
+ "version": 1,
125
+ "n_qubits": 36,
126
+ "timing": {"dt": None, "durations": []},
127
+ "native_ops": [
128
+ {"name": "gpi", "arity": 1, "params": ["phi"]},
129
+ {"name": "gpi2", "arity": 1, "params": ["phi"]},
130
+ {"name": "zz", "arity": 2, "params": ["phi0", "phi1"]},
131
+ {"name": "measure", "arity": 1}
132
+ ],
133
+ "supported_ops": [
134
+ {"name": "x", "arity": 1}, {"name": "y", "arity": 1}, {"name": "z", "arity": 1},
135
+ {"name": "h", "arity": 1}, {"name": "s", "arity": 1}, {"name": "si", "arity": 1},
136
+ {"name": "t", "arity": 1}, {"name": "ti", "arity": 1}, {"name": "v", "arity": 1},
137
+ {"name": "vi", "arity": 1}, {"name": "rx", "arity": 1}, {"name": "ry", "arity": 1},
138
+ {"name": "rz", "arity": 1}, {"name": "cnot", "arity": 2}, {"name": "swap", "arity": 2},
139
+ {"name": "xx", "arity": 2}, {"name": "yy", "arity": 2}
140
+ ],
141
+ "topology": {
142
+ "directed_edges": False,
143
+ "coupling_map": fully_connected(36)
144
+ },
145
+ "noise": {},
146
+ "limits": {"max_circuits": 1024, "min_shots": 100, "max_shots": 5000},
147
+ "features": ["measure"]
148
+ }
149
+
150
+ # --- IQM Emerald ---
151
+ IQM_EMERALD_ADJ = {
152
+ '1': ['2', '5'], '2': ['1', '6'], '5': ['1', '4', '6', '11'], '6': ['2', '5', '7', '12'],
153
+ '3': ['4', '9'], '4': ['3', '5', '10'], '9': ['3', '8', '10', '17'], '10': ['4', '9', '11'],
154
+ '11': ['5', '10', '12', '19'], '7': ['6'], '12': ['6', '11', '13', '20'], '8': ['9', '16'],
155
+ '16': ['8', '15', '17', '24'], '17': ['9', '16', '18', '25'], '19': ['11', '18', '20', '27'],
156
+ '13': ['12', '14', '21'], '20': ['12', '19', '21', '28'], '14': ['13', '22'],
157
+ '21': ['13', '20', '22', '29'], '22': ['14', '21', '30'], '15': ['16', '23'],
158
+ '23': ['15', '24'], '24': ['16', '23', '25', '32'], '18': ['17', '19', '26'],
159
+ '25': ['17', '24', '26', '33'], '26': ['18', '25', '27', '34'], '27': ['19', '26', '28', '35'],
160
+ '28': ['20', '27', '29', '36'], '29': ['21', '28', '30', '37'], '30': ['22', '29', '31'],
161
+ '32': ['24', '33'], '33': ['25', '32', '34', '41'], '34': ['26', '33', '35', '42'],
162
+ '35': ['27', '34', '36', '43'], '36': ['28', '35', '37', '44'], '37': ['29', '36', '38', '45'],
163
+ '31': ['30', '39'], '39': ['31', '38'], '41': ['33', '40', '42', '47'],
164
+ '42': ['34', '41', '43', '48'], '43': ['35', '42'], '44': ['36', '45', '50'],
165
+ '38': ['37', '39', '46'], '45': ['37', '44', '46', '51'], '46': ['38', '45'],
166
+ '40': ['41'], '47': ['41', '48'], '48': ['42', '47', '49', '52'], '50': ['44', '51', '54'],
167
+ '51': ['45', '50'], '49': ['48', '53'], '52': ['48', '53'], '53': ['49', '52', '54'],
168
+ '54': ['50', '53']
169
+ }
170
+
171
+ IQM_EMERALD_CAPS = {
172
+ "version": 1,
173
+ "n_qubits": 54,
174
+ "timing": {"dt": None, "durations": []},
175
+ "native_ops": [
176
+ {"name": "cz", "arity": 2},
177
+ {"name": "prx", "arity": 1, "params": ["theta", "phi"]},
178
+ {"name": "measure", "arity": 1}
179
+ ],
180
+ "supported_ops": [
181
+ {"name": "ccnot", "arity": 3}, {"name": "cnot", "arity": 2}, {"name": "cphaseshift", "arity": 2},
182
+ {"name": "cswap", "arity": 3}, {"name": "swap", "arity": 2}, {"name": "iswap", "arity": 2},
183
+ {"name": "ecr", "arity": 2}, {"name": "cy", "arity": 2}, {"name": "cz", "arity": 2},
184
+ {"name": "xy", "arity": 2}, {"name": "xx", "arity": 2}, {"name": "yy", "arity": 2},
185
+ {"name": "zz", "arity": 2}, {"name": "h", "arity": 1}, {"name": "i", "arity": 1},
186
+ {"name": "rx", "arity": 1}, {"name": "ry", "arity": 1}, {"name": "rz", "arity": 1},
187
+ {"name": "s", "arity": 1}, {"name": "si", "arity": 1}, {"name": "t", "arity": 1},
188
+ {"name": "ti", "arity": 1}, {"name": "v", "arity": 1}, {"name": "vi", "arity": 1},
189
+ {"name": "x", "arity": 1}, {"name": "y", "arity": 1}, {"name": "z", "arity": 1},
190
+ {"name": "prx", "arity": 1}, {"name": "cc_prx", "arity": 2}, {"name": "measure_ff", "arity": 1}
191
+ ],
192
+ "topology": {
193
+ "directed_edges": False,
194
+ "coupling_map": adj_to_edges(IQM_EMERALD_ADJ, shift=1) # 1-based to 0-based
195
+ },
196
+ "noise": {},
197
+ "limits": {"max_circuits": 1024},
198
+ "features": ["measure"]
199
+ }
200
+
201
+ # --- IQM Garnet ---
202
+ IQM_GARNET_ADJ = {
203
+ '1': ['2', '4'], '2': ['1', '5'], '4': ['1', '3', '5', '9'], '5': ['2', '4', '6', '10'],
204
+ '3': ['4', '8'], '8': ['3', '9', '13'], '9': ['4', '8', '10', '14'], '6': ['5', '7', '11'],
205
+ '10': ['5', '9', '11', '15'], '7': ['6', '12'], '11': ['6', '10', '12', '16'],
206
+ '12': ['7', '11', '17'], '13': ['8', '14'], '14': ['9', '13', '15', '18'],
207
+ '15': ['10', '14', '16', '19'], '16': ['11', '15', '17', '20'], '17': ['12', '16'],
208
+ '18': ['14', '19'], '19': ['15', '18', '20'], '20': ['16', '19']
209
+ }
210
+
211
+ IQM_GARNET_CAPS = {
212
+ "version": 1,
213
+ "n_qubits": 20,
214
+ "timing": {"dt": None, "durations": []},
215
+ "native_ops": [
216
+ {"name": "cz", "arity": 2},
217
+ {"name": "prx", "arity": 1, "params": ["theta", "phi"]},
218
+ {"name": "measure", "arity": 1}
219
+ ],
220
+ "supported_ops": [
221
+ {"name": "ccnot", "arity": 3}, {"name": "cnot", "arity": 2}, {"name": "cphaseshift", "arity": 2},
222
+ {"name": "cswap", "arity": 3}, {"name": "swap", "arity": 2}, {"name": "iswap", "arity": 2},
223
+ {"name": "ecr", "arity": 2}, {"name": "cy", "arity": 2}, {"name": "cz", "arity": 2},
224
+ {"name": "xy", "arity": 2}, {"name": "xx", "arity": 2}, {"name": "yy", "arity": 2},
225
+ {"name": "zz", "arity": 2}, {"name": "h", "arity": 1}, {"name": "i", "arity": 1},
226
+ {"name": "rx", "arity": 1}, {"name": "ry", "arity": 1}, {"name": "rz", "arity": 1},
227
+ {"name": "s", "arity": 1}, {"name": "si", "arity": 1}, {"name": "t", "arity": 1},
228
+ {"name": "ti", "arity": 1}, {"name": "v", "arity": 1}, {"name": "vi", "arity": 1},
229
+ {"name": "x", "arity": 1}, {"name": "y", "arity": 1}, {"name": "z", "arity": 1},
230
+ {"name": "prx", "arity": 1}, {"name": "cc_prx", "arity": 2}, {"name": "measure_ff", "arity": 1}
231
+ ],
232
+ "topology": {
233
+ "directed_edges": False,
234
+ "coupling_map": adj_to_edges(IQM_GARNET_ADJ, shift=1) # 1-based to 0-based
235
+ },
236
+ "noise": {},
237
+ "limits": {"max_circuits": 1024},
238
+ "features": ["measure"]
239
+ }
240
+
241
+ # --- AQT IBEX Q1 ---
242
+ AQT_IBEX_Q1_CAPS = {
243
+ "version": 1,
244
+ "n_qubits": 12,
245
+ "timing": {"dt": None, "durations": []},
246
+ "native_ops": [
247
+ {"name": "prx", "arity": 1, "params": ["theta", "phi"]},
248
+ {"name": "xx", "arity": 2, "params": ["theta"]},
249
+ {"name": "rz", "arity": 1, "params": ["phi"]},
250
+ {"name": "measure", "arity": 1}
251
+ ],
252
+
253
+ "supported_ops": [
254
+ {"name": "ccnot", "arity": 3}, {"name": "cnot", "arity": 2}, {"name": "cphaseshift", "arity": 2},
255
+ {"name": "cphaseshift00", "arity": 2}, {"name": "cphaseshift01", "arity": 2}, {"name": "cphaseshift10", "arity": 2},
256
+ {"name": "cswap", "arity": 3}, {"name": "swap", "arity": 2}, {"name": "iswap", "arity": 2},
257
+ {"name": "pswap", "arity": 2}, {"name": "ecr", "arity": 2}, {"name": "cy", "arity": 2},
258
+ {"name": "cz", "arity": 2}, {"name": "xy", "arity": 2}, {"name": "xx", "arity": 2},
259
+ {"name": "yy", "arity": 2}, {"name": "zz", "arity": 2}, {"name": "h", "arity": 1},
260
+ {"name": "i", "arity": 1}, {"name": "phaseshift", "arity": 1}, {"name": "rx", "arity": 1},
261
+ {"name": "ry", "arity": 1}, {"name": "rz", "arity": 1}, {"name": "s", "arity": 1},
262
+ {"name": "si", "arity": 1}, {"name": "t", "arity": 1}, {"name": "ti", "arity": 1},
263
+ {"name": "v", "arity": 1}, {"name": "vi", "arity": 1}, {"name": "x", "arity": 1},
264
+ {"name": "y", "arity": 1}, {"name": "z", "arity": 1}, {"name": "prx", "arity": 1}
265
+ ],
266
+
267
+ "topology": {
268
+ "directed_edges": False,
269
+ "coupling_map": fully_connected(12)
270
+ },
271
+ "noise": {},
272
+ "limits": {"max_circuits": 1024, "max_shots": 2000, "min_shots": 1},
273
+ "features": ["measure"]
274
+ }