iqm-benchmarks 1.12__tar.gz → 2.0__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.

Potentially problematic release.


This version of iqm-benchmarks might be problematic. Click here for more details.

Files changed (86) hide show
  1. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/CHANGELOG.rst +7 -0
  2. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/PKG-INFO +1 -1
  3. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/__init__.py +1 -0
  4. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/benchmark_definition.py +15 -12
  5. iqm_benchmarks-2.0/src/iqm/benchmarks/circuit_containers.py +221 -0
  6. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/compressive_gst/compressive_gst.py +11 -4
  7. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/entanglement/ghz.py +101 -89
  8. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/optimization/qscore.py +1 -1
  9. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/quantum_volume/clops.py +13 -32
  10. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/quantum_volume/quantum_volume.py +18 -19
  11. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/randomized_benchmarking/clifford_rb/clifford_rb.py +23 -14
  12. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/randomized_benchmarking/interleaved_rb/interleaved_rb.py +48 -30
  13. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/randomized_benchmarking/mirror_rb/mirror_rb.py +14 -31
  14. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/randomized_benchmarking/randomized_benchmarking_common.py +2 -1
  15. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/readout_mitigation.py +2 -1
  16. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/utils.py +2 -1
  17. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm_benchmarks.egg-info/PKG-INFO +1 -1
  18. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm_benchmarks.egg-info/SOURCES.txt +3 -1
  19. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/mGST/qiskit_interface.py +1 -1
  20. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/tests/test_ghz.py +10 -11
  21. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/tests/test_gst.py +2 -2
  22. iqm_benchmarks-2.0/tests/unit/test_benchmark_circuit.py +56 -0
  23. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/.github/workflows/main.yml +0 -0
  24. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/.github/workflows/publish.yml +0 -0
  25. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/.github/workflows/tag_and_release.yml +0 -0
  26. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/.gitignore +0 -0
  27. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/LICENSE +0 -0
  28. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/README.md +0 -0
  29. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/benchmark_runner.py +0 -0
  30. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/docs/API.rst +0 -0
  31. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/docs/Makefile +0 -0
  32. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/docs/_static/images/favicon.ico +0 -0
  33. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/docs/_templates/autosummary-class-template.rst +0 -0
  34. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/docs/_templates/autosummary-module-template.rst +0 -0
  35. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/docs/changelog.rst +0 -0
  36. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/docs/conf.py +0 -0
  37. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/docs/index.rst +0 -0
  38. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/docs/license.rst +0 -0
  39. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/docs/readme.md +0 -0
  40. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/examples/example_clifford_rb.ipynb +0 -0
  41. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/examples/example_clops.ipynb +0 -0
  42. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/examples/example_experiment_all.ipynb +0 -0
  43. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/examples/example_ghz.ipynb +0 -0
  44. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/examples/example_gst.ipynb +0 -0
  45. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/examples/example_interleaved_rb.ipynb +0 -0
  46. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/examples/example_mirror_rb.ipynb +0 -0
  47. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/examples/example_qscore.ipynb +0 -0
  48. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/examples/example_quantum_volume.ipynb +0 -0
  49. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/examples/generate_2qubit_cliffords.ipynb +0 -0
  50. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/examples/how_to_make_your_own_benchmark.ipynb +0 -0
  51. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/pyproject.toml +0 -0
  52. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/scheduled_experiments/adonis/__init__.py +0 -0
  53. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/scheduled_experiments/adonis/weekly.py +0 -0
  54. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/setup.cfg +0 -0
  55. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/benchmark.py +0 -0
  56. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/benchmark_experiment.py +0 -0
  57. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/compressive_gst/__init__.py +0 -0
  58. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/compressive_gst/gst_analysis.py +0 -0
  59. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/entanglement/__init__.py +0 -0
  60. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/logging_config.py +0 -0
  61. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/optimization/__init__.py +0 -0
  62. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/quantum_volume/__init__.py +0 -0
  63. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/randomized_benchmarking/__init__.py +0 -0
  64. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/randomized_benchmarking/clifford_1q.pkl +0 -0
  65. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/randomized_benchmarking/clifford_2q.pkl +0 -0
  66. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/randomized_benchmarking/clifford_rb/__init__.py +0 -0
  67. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/randomized_benchmarking/interleaved_rb/__init__.py +0 -0
  68. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/randomized_benchmarking/mirror_rb/__init__.py +0 -0
  69. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm/benchmarks/randomized_benchmarking/multi_lmfit.py +0 -0
  70. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm_benchmarks.egg-info/dependency_links.txt +0 -0
  71. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm_benchmarks.egg-info/requires.txt +0 -0
  72. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/iqm_benchmarks.egg-info/top_level.txt +0 -0
  73. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/mGST/LICENSE +0 -0
  74. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/mGST/README.md +0 -0
  75. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/mGST/additional_fns.py +0 -0
  76. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/mGST/algorithm.py +0 -0
  77. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/mGST/compatibility.py +0 -0
  78. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/mGST/low_level_jit.py +0 -0
  79. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/mGST/optimization.py +0 -0
  80. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/mGST/reporting/figure_gen.py +0 -0
  81. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/src/mGST/reporting/reporting.py +0 -0
  82. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/tag-from-pipeline.sh +0 -0
  83. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/tests/test_qscore.py +0 -0
  84. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/tests/test_qv.py +0 -0
  85. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/tests/test_rb.py +0 -0
  86. {iqm_benchmarks-1.12 → iqm_benchmarks-2.0}/tox.ini +0 -0
@@ -2,6 +2,13 @@
2
2
  Changelog
3
3
  =========
4
4
 
5
+ Version 2.0
6
+ ===========
7
+ * Adds `Circuits`, `BenchmarkCircuit` and `CircuitGroup` as a way to easily store and interact with multiple quantum circuits.
8
+ * `BenchmarkRunResult` now takes a `circuits` argument, expecting an instance of `Circuits`. `QuantumCircuit` instances can now exist there instead of inside xarray Datasets. All analysis methods should also expect to use an instance of `BenchmarkRunResult`.
9
+ * Ported all of the benchmarks subclassing from `Benchmark` to use the new containers.
10
+ * Updates the usage of `qiskit.QuantumCircuit` to `iqm.qiskit_iqm.IQMCircuit` in many places.
11
+
5
12
  Version 1.12
6
13
  ===========
7
14
  * Miscellaneous small bugs fixed.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iqm-benchmarks
3
- Version: 1.12
3
+ Version: 2.0
4
4
  Summary: A package for implementation of Quantum Characterization, Verification and Validation (QCVV) techniques on IQM's hardware at gate level abstraction
5
5
  Author-email: IQM Finland Oy <developers@meetiqm.com>, Aniket Rath <aniket.rath@meetiqm.com>, Jami Rönkkö <jami@meetiqm.com>, Pedro Figueroa Romero <pedro.romero@meetiqm.com>, Vicente Pina Canelles <vicente.pina@meetiqm.com>, Raphael Brieger <raphael.brieger@meetiqm.com>, Stefan Seegerer <stefan.seegerer@meetiqm.com>
6
6
  Project-URL: Homepage, https://github.com/iqm-finland/iqm-benchmarks
@@ -25,6 +25,7 @@ from .benchmark_definition import (
25
25
  BenchmarkObservationIdentifier,
26
26
  BenchmarkRunResult,
27
27
  )
28
+ from .circuit_containers import BenchmarkCircuit, CircuitGroup, Circuits
28
29
  from .entanglement.ghz import GHZBenchmark, GHZConfiguration
29
30
  from .quantum_volume.clops import CLOPSBenchmark, CLOPSConfiguration
30
31
  from .quantum_volume.quantum_volume import QuantumVolumeBenchmark, QuantumVolumeConfiguration
@@ -21,7 +21,7 @@ import copy
21
21
  from copy import deepcopy
22
22
  from dataclasses import dataclass, field
23
23
  import functools
24
- from typing import Any, Dict, List, Optional, Union
24
+ from typing import Any, Callable, Dict, List, Optional, Union
25
25
  import uuid
26
26
 
27
27
  from matplotlib.figure import Figure
@@ -29,6 +29,7 @@ import matplotlib.pyplot as plt
29
29
  import xarray as xr
30
30
 
31
31
  from iqm.benchmarks.benchmark import BenchmarkConfigurationBase
32
+ from iqm.benchmarks.circuit_containers import BenchmarkCircuit, Circuits
32
33
  from iqm.benchmarks.utils import get_iqm_backend, timeit
33
34
  from iqm.qiskit_iqm.iqm_backend import IQMBackendBase
34
35
  from iqm.qiskit_iqm.iqm_provider import IQMBackend, IQMFacadeBackend
@@ -81,6 +82,7 @@ class BenchmarkRunResult:
81
82
  """
82
83
 
83
84
  dataset: xr.Dataset
85
+ circuits: Circuits
84
86
 
85
87
 
86
88
  @dataclass
@@ -94,6 +96,7 @@ class BenchmarkAnalysisResult:
94
96
  """
95
97
 
96
98
  dataset: xr.Dataset
99
+ circuits: Optional[Circuits] = field(default=None)
97
100
  plots: dict[str, Figure] = field(default_factory=lambda: ({}))
98
101
  observations: list[BenchmarkObservation] = field(default_factory=lambda: [])
99
102
 
@@ -122,14 +125,14 @@ class BenchmarkAnalysisResult:
122
125
  Args:
123
126
  run: A run for which analysis result is created.
124
127
  """
125
- return cls(dataset=run.dataset)
128
+ return cls(dataset=run.dataset, circuits=Circuits)
126
129
 
127
130
 
128
- def default_analysis_function(result: BenchmarkAnalysisResult) -> BenchmarkAnalysisResult:
131
+ def default_analysis_function(result: BenchmarkRunResult) -> BenchmarkAnalysisResult:
129
132
  """
130
133
  The default analysis that only pass the result through.
131
134
  """
132
- return result
135
+ return BenchmarkAnalysisResult.from_run_result(result)
133
136
 
134
137
 
135
138
  def merge_datasets_dac(datasets: List[xr.Dataset]) -> xr.Dataset:
@@ -208,18 +211,19 @@ class Benchmark(ABC):
208
211
  accept ``AnalysisResult`` as its input and return the final result.
209
212
  """
210
213
 
211
- analysis_function = staticmethod(default_analysis_function)
214
+ analysis_function: Callable[[BenchmarkRunResult], BenchmarkAnalysisResult] = staticmethod(default_analysis_function)
212
215
  default_options: dict[str, Any] | None = None
213
216
  options: dict[str, Any] | None = None
214
- # name: str = "unnamed_benchmark"
215
217
 
216
- def __init__(self, backend: Union[str, IQMBackendBase], configuration: "BenchmarkConfigurationBase", **kwargs):
218
+ def __init__(self, backend: Union[str, IQMBackendBase], configuration: BenchmarkConfigurationBase, **kwargs):
217
219
 
218
220
  # Ported from BenchmarkBase # CHECK
219
221
  self.configuration = configuration
220
222
  self.serializable_configuration = deepcopy(self.configuration)
221
223
  self.serializable_configuration.benchmark = self.name
222
224
 
225
+ self.circuits = Circuits()
226
+
223
227
  if isinstance(backend, str):
224
228
  self.backend = get_iqm_backend(backend)
225
229
  else:
@@ -233,8 +237,8 @@ class Benchmark(ABC):
233
237
  self.routing_method = self.configuration.routing_method
234
238
  self.physical_layout = self.configuration.physical_layout
235
239
 
236
- self.untranspiled_circuits: Dict[str, Dict[int, list]] = {}
237
- self.transpiled_circuits: Dict[str, Dict[int, list]] = {}
240
+ self.transpiled_circuits: BenchmarkCircuit
241
+ self.untranspiled_circuits: BenchmarkCircuit
238
242
 
239
243
  # From exa_support MR
240
244
  self.options = copy.copy(self.default_options) if self.default_options else {}
@@ -278,7 +282,7 @@ class Benchmark(ABC):
278
282
  self.backend.run, calibration_set_id=calibration_set_id
279
283
  ) # type: ignore
280
284
  dataset = self.execute(backend_for_execute)
281
- run = BenchmarkRunResult(dataset)
285
+ run = BenchmarkRunResult(dataset, self.circuits)
282
286
  self.runs.append(run)
283
287
  return run
284
288
 
@@ -299,6 +303,5 @@ class Benchmark(ABC):
299
303
  the ``analysis_function`` field.
300
304
  """
301
305
  run = self.runs[run_index]
302
- result = BenchmarkAnalysisResult.from_run_result(run)
303
- updated_result = self.analysis_function(result)
306
+ updated_result = self.analysis_function(run)
304
307
  return updated_result
@@ -0,0 +1,221 @@
1
+ # Copyright 2024 IQM Benchmarks developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ This module contains classes to easily interact with quantum circuits
17
+ """
18
+
19
+ from dataclasses import dataclass, field
20
+ from typing import List, Optional, TypeAlias
21
+
22
+ from qiskit.circuit import Qubit
23
+
24
+ from iqm.qiskit_iqm.iqm_circuit import IQMCircuit
25
+
26
+
27
+ QubitLayout: TypeAlias = tuple[Qubit, ...]
28
+ QubitLayouts: TypeAlias = tuple[QubitLayout, ...]
29
+ QubitLayoutIndices: TypeAlias = tuple[tuple[int, ...], ...]
30
+
31
+
32
+ # pylint: disable=protected-access
33
+ @dataclass
34
+ class CircuitGroup:
35
+ """Group of `IQMCircuits`. It represents a list of circuits with a common purpose, typically executed in a batch.
36
+
37
+ Attributes:
38
+ circuits: List of `IQMCircuit`.
39
+ name: Name of the group.
40
+ """
41
+
42
+ circuits: List[IQMCircuit] = field(default_factory=list)
43
+ name: Optional[str] = field(default="")
44
+
45
+ @property
46
+ def qubit_layouts_by_index(self) -> QubitLayoutIndices:
47
+ """The qubit layouts contained in all the circuits, where the qubits are represented by an integer.
48
+
49
+ Returns:
50
+ All qubit layouts.
51
+ """
52
+ return tuple(tuple(int(qubit._index) for qubit in layout) for layout in self.qubit_layouts)
53
+
54
+ @property
55
+ def qubit_layouts(self) -> QubitLayouts:
56
+ """The qubit layouts contained in all the circuits, where the qubits are represented by an instance of `Qubit`.
57
+
58
+ Returns:
59
+ All qubit layouts.
60
+ """
61
+ qubit_layouts = tuple(map(lambda x: tuple(x._data.active_bits()[0]), self.circuits))
62
+ return qubit_layouts
63
+
64
+ @property
65
+ def qubits(self) -> set[Qubit]:
66
+ """The set of active qubits in all of the circuits
67
+
68
+ Returns:
69
+ A set of `Qubit`
70
+ """
71
+ qubit_set = set()
72
+ for circuit in self.circuits:
73
+ for qubit in circuit._data.active_bits()[0]:
74
+ qubit_set.add(qubit)
75
+ return qubit_set
76
+
77
+ def __setitem__(self, key: str, value: IQMCircuit) -> None:
78
+ value.name = key
79
+ return self.add_circuit(value)
80
+
81
+ def add_circuit(self, circuit: IQMCircuit):
82
+ """Adds a circuit to the internal list
83
+
84
+ Args:
85
+ circuit: Circuit to add.
86
+ """
87
+ self.circuits.append(circuit)
88
+
89
+ @property
90
+ def circuit_names(self) -> list[str]:
91
+ """Name of all the circuits contained in the group as a string
92
+
93
+ Returns:
94
+ List of strings
95
+ """
96
+ benchmark_circuit_names = list(map(lambda x: x.name, self.circuits))
97
+ return benchmark_circuit_names
98
+
99
+ def get_circuits_by_name(self, name: str) -> Optional[IQMCircuit]:
100
+ """Returns a list of the internal circuits that share the same name
101
+
102
+ Args:
103
+ name: Name of the circuit to return as a string
104
+
105
+ Returns:
106
+ The circuit with the desired name as a string, or None if they are not found.
107
+ """
108
+ benchmark_circuit_names = filter(lambda x: x.name == name, self.circuits)
109
+ return next(benchmark_circuit_names, None)
110
+
111
+ def __getitem__(self, key: str) -> Optional[IQMCircuit]:
112
+ return self.get_circuits_by_name(key)
113
+
114
+
115
+ @dataclass
116
+ class BenchmarkCircuit:
117
+ """A class grouping a list of `CircuitGroup` into a single purpose. This can typically represent, for example,
118
+ all of the transpiled circuits that are executed.
119
+
120
+ Attributes:
121
+ name: Name of the `BenchmarkCircuit`.
122
+ circuit_groups: List of `CircuitGroup` contained inside
123
+
124
+ """
125
+
126
+ name: str
127
+ circuit_groups: List[CircuitGroup] = field(default_factory=list)
128
+
129
+ def get_circuit_group_by_name(self, name: str) -> Optional[CircuitGroup]:
130
+ """Gets a `CircuitGroup` by name.
131
+
132
+ Args:
133
+ name: name of the group.
134
+
135
+ Returns:
136
+ The desired `CircuitGroup`, or None if it does not exist.
137
+
138
+ """
139
+ benchmark_circuit_names = filter(lambda x: x.name == name, self.circuit_groups)
140
+ next_value = next(benchmark_circuit_names, None)
141
+ return next_value
142
+
143
+ @property
144
+ def groups(self) -> List[CircuitGroup]:
145
+ """The circuit groups inside."""
146
+ return self.circuit_groups
147
+
148
+ @property
149
+ def group_names(self) -> List[str | None]:
150
+ """Names of all the contained `CircuitGroup`."""
151
+ return list(map(lambda x: x.name, self.circuit_groups)) if len(self.circuit_groups) > 0 else []
152
+
153
+ @property
154
+ def qubit_indices(self) -> set[int]:
155
+ """Set of all the qubits used in all the `CircuitGroup`, represented as an integer."""
156
+ qubit_set = set()
157
+ for circuit in self.circuit_groups:
158
+ for qubit_index in map(lambda x: x._index, circuit.qubits):
159
+ qubit_set.add(qubit_index)
160
+ return qubit_set
161
+
162
+ @property
163
+ def qubits(self) -> set[Qubit]:
164
+ """Set of all the qubits used in all the `CircuitGroup`, represented as an instance of `Qubit`."""
165
+ qubit_set: set[Qubit] = set()
166
+ for qubit in map(lambda x: x.qubits, self.circuit_groups):
167
+ qubit_set = qubit_set.union(qubit)
168
+ return qubit_set
169
+
170
+ @property
171
+ def qubit_layouts_by_index(self) -> set[QubitLayoutIndices]:
172
+ """Set of all the qubit layouts used, where the qubits are represented as an integer."""
173
+ layout_set = set()
174
+ for layout in map(lambda x: x.qubit_layouts_by_index, self.circuit_groups):
175
+ layout_set.add(layout)
176
+ return layout_set
177
+
178
+ @property
179
+ def qubit_layouts(self) -> set[QubitLayouts]:
180
+ """Set of all the qubit layouts used, where the qubits are represented as an instance of `Qubit`."""
181
+ layout_set = set()
182
+ for layout in map(lambda x: x.qubit_layouts, self.circuit_groups):
183
+ layout_set.add(layout)
184
+ return layout_set
185
+
186
+ def __setitem__(self, key: str, value: CircuitGroup) -> None:
187
+ value.name = key
188
+ return self.circuit_groups.append(value)
189
+
190
+ def __getitem__(self, key: str) -> CircuitGroup | None:
191
+ return self.get_circuit_group_by_name(key)
192
+
193
+
194
+ @dataclass
195
+ class Circuits:
196
+ """Container for all the `BenchmarkCircuit` that are generated in a single benchmark execution.
197
+
198
+ Attributes:
199
+ benchmark_circuits: List of `BenchmarkCircuit` contained.
200
+ """
201
+
202
+ benchmark_circuits: List[BenchmarkCircuit] = field(default_factory=list)
203
+
204
+ def __setitem__(self, key: str, value: BenchmarkCircuit) -> None:
205
+ value.name = key
206
+ return self.benchmark_circuits.append(value)
207
+
208
+ def __getitem__(self, key: str) -> BenchmarkCircuit | None:
209
+ return self.get_benchmark_circuits_by_name(key)
210
+
211
+ def get_benchmark_circuits_by_name(self, name: str) -> Optional[BenchmarkCircuit]:
212
+ """Returned the `BenchmarkCircuit` by name.
213
+
214
+ Args:
215
+ name: Name of the requested `BenchmarkCircuit` as a string
216
+
217
+ Returns:
218
+ The requested `BenchmarkCircuit` if it exists, None otherwise
219
+ """
220
+ benchmark_circuit_names = filter(lambda x: x.name == name, self.benchmark_circuits)
221
+ return next(benchmark_circuit_names, None)
@@ -30,12 +30,12 @@ The full benchmark executes the following steps:
30
30
  from typing import Any, Dict, List, Tuple, Type, Union
31
31
 
32
32
  import numpy as np
33
- from qiskit import QuantumCircuit
34
33
  from qiskit.circuit.library import CZGate, RGate
35
34
  import xarray as xr
36
35
 
37
36
  from iqm.benchmarks.benchmark import BenchmarkConfigurationBase
38
37
  from iqm.benchmarks.benchmark_definition import Benchmark, add_counts_to_dataset
38
+ from iqm.benchmarks.circuit_containers import BenchmarkCircuit, CircuitGroup, Circuits
39
39
  from iqm.benchmarks.compressive_gst.gst_analysis import mgst_analysis
40
40
  from iqm.benchmarks.logging_config import qcvv_logger
41
41
  from iqm.benchmarks.utils import (
@@ -45,6 +45,7 @@ from iqm.benchmarks.utils import (
45
45
  submit_execute,
46
46
  timeit,
47
47
  )
48
+ from iqm.qiskit_iqm import IQMCircuit as QuantumCircuit
48
49
  from iqm.qiskit_iqm.iqm_backend import IQMBackendBase
49
50
  from mGST import additional_fns, qiskit_interface
50
51
  from mGST.qiskit_interface import add_idle_gates, remove_idle_wires
@@ -156,8 +157,10 @@ class CompressiveGST(Benchmark):
156
157
  drop_final_rz=False,
157
158
  )
158
159
  # Saving raw and transpiled circuits in a consistent format with other benchmarks
159
- self.untranspiled_circuits.update({str(qubits): raw_qc_list})
160
- self.transpiled_circuits.update({str(qubits): transpiled_qc_list})
160
+ self.transpiled_circuits.circuit_groups.append(CircuitGroup(name=str(qubits), circuits=raw_qc_list))
161
+ self.untranspiled_circuits.circuit_groups.append(
162
+ CircuitGroup(name=str(qubits), circuits=transpiled_qc_list)
163
+ )
161
164
 
162
165
  def add_configuration_to_dataset(self, dataset): # CHECK
163
166
  """
@@ -186,13 +189,16 @@ class CompressiveGST(Benchmark):
186
189
  dataset = xr.Dataset()
187
190
  qcvv_logger.info(f"Now generating {self.configuration.num_circuits} random GST circuits...")
188
191
 
192
+ self.circuits = Circuits()
193
+ self.transpiled_circuits = BenchmarkCircuit(name="transpiled_circuits")
194
+ self.untranspiled_circuits = BenchmarkCircuit(name="untranspiled_circuits")
189
195
  # Generate circuits
190
196
  self.generate_meas_circuits()
191
197
 
192
198
  # Submit all
193
199
  all_jobs: Dict = {}
194
200
  for qubit_layout in self.qubit_layouts:
195
- transpiled_circuit_dict = {tuple(qubit_layout): self.transpiled_circuits[str(qubit_layout)]}
201
+ transpiled_circuit_dict = {tuple(qubit_layout): self.transpiled_circuits[str(qubit_layout)].circuits}
196
202
  all_jobs[str(qubit_layout)], _ = submit_execute(
197
203
  transpiled_circuit_dict,
198
204
  backend,
@@ -207,6 +213,7 @@ class CompressiveGST(Benchmark):
207
213
  dataset, _ = add_counts_to_dataset(counts, str(qubit_layout), dataset)
208
214
 
209
215
  self.add_configuration_to_dataset(dataset)
216
+ self.circuits.benchmark_circuits = [self.transpiled_circuits, self.untranspiled_circuits]
210
217
  return dataset
211
218
 
212
219