iqm-benchmarks 1.11__py3-none-any.whl → 2.0__py3-none-any.whl

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.

@@ -28,7 +28,7 @@ import networkx
28
28
  from networkx import Graph, all_pairs_shortest_path, is_connected, minimum_spanning_tree
29
29
  import numpy as np
30
30
  import pycurl
31
- from qiskit import QuantumCircuit, transpile
31
+ from qiskit import QuantumRegister, transpile
32
32
  from qiskit.quantum_info import random_clifford
33
33
  from qiskit.transpiler import CouplingMap
34
34
  from qiskit_aer import Aer
@@ -44,6 +44,7 @@ from iqm.benchmarks.benchmark_definition import (
44
44
  BenchmarkRunResult,
45
45
  add_counts_to_dataset,
46
46
  )
47
+ from iqm.benchmarks.circuit_containers import BenchmarkCircuit, CircuitGroup, Circuits
47
48
  from iqm.benchmarks.logging_config import qcvv_logger
48
49
  from iqm.benchmarks.readout_mitigation import apply_readout_error_mitigation
49
50
  from iqm.benchmarks.utils import (
@@ -55,6 +56,7 @@ from iqm.benchmarks.utils import (
55
56
  timeit,
56
57
  xrvariable_to_counts,
57
58
  )
59
+ from iqm.qiskit_iqm import IQMCircuit as QuantumCircuit
58
60
  from iqm.qiskit_iqm.iqm_backend import IQMBackendBase
59
61
 
60
62
 
@@ -94,16 +96,13 @@ def append_rms(
94
96
  rm_circ.compose(rand_clifford, qubits=[q], inplace=True)
95
97
 
96
98
  rm_circ.measure_active()
97
- # if backend is not None and backend.name != "IQMNdonisBackend" and optimize_sqg:
98
- # rm_circuits.append(optimize_single_qubit_gates(rm_circ))
99
- # else:
100
99
  rm_circuits.append(transpile(rm_circ, basis_gates=backend.operation_names))
101
100
 
102
101
  return rm_circuits
103
102
 
104
103
 
105
104
  def fidelity_ghz_randomized_measurements(
106
- dataset: xr.Dataset, qubit_layout, ideal_probabilities: List[Dict[str, int]], num_qubits: int
105
+ dataset: xr.Dataset, qubit_layout, ideal_probabilities: List[Dict[str, int]], num_qubits: int, circuits: Circuits
107
106
  ) -> tuple[dict[str, Any], dict[str, Any]]:
108
107
  """
109
108
  Estimates GHZ state fidelity through cross-correlations of RMs.
@@ -113,7 +112,8 @@ def fidelity_ghz_randomized_measurements(
113
112
  dataset (xr.Dataset):
114
113
  qubit_layout: List[int]: The subset of system-qubits used in the protocol
115
114
  ideal_probabilities (List[Dict[str, int]]):
116
- num_qubits (int):
115
+ num_qubits (int): Number of qubits
116
+ circuits (Circuits): Instance of `Circuits` containing transpiled circuits
117
117
  Returns:
118
118
  values: dict[str, Any]
119
119
  The fidelities
@@ -125,7 +125,7 @@ def fidelity_ghz_randomized_measurements(
125
125
  fid_rm = []
126
126
 
127
127
  # Loop through RMs and add each contribution
128
- num_rms = len(dataset.attrs["transpiled_circuits"][f"{idx}"])
128
+ num_rms = len(circuits["transpiled_circuits"][f"{idx}_native_ghz"].circuits)
129
129
  for u in range(num_rms):
130
130
  # Probability estimates for noisy measurements
131
131
  probabilities_sample = {}
@@ -168,7 +168,7 @@ def fidelity_ghz_randomized_measurements(
168
168
  return values, uncertainties
169
169
 
170
170
 
171
- def fidelity_ghz_coherences(dataset: xr.Dataset, qubit_layout: List[int]) -> list[Any]:
171
+ def fidelity_ghz_coherences(dataset: xr.Dataset, qubit_layout: List[int], circuits: Circuits) -> list[Any]:
172
172
  """
173
173
  Estimates the GHZ state fidelity based on the multiple quantum coherences method based on [Mooney, 2021]
174
174
 
@@ -177,6 +177,8 @@ def fidelity_ghz_coherences(dataset: xr.Dataset, qubit_layout: List[int]) -> lis
177
177
  An xarray dataset containing the measurement data
178
178
  qubit_layout: List[int]
179
179
  The subset of system-qubits used in the protocol
180
+ circuits: Circuits
181
+ Instance of `Circuits` containing transpiled circuits
180
182
 
181
183
  Returns:
182
184
  dict[str, dict[str, Any]]: The ghz fidelity or, if rem=True, fidelity and readout error mitigated fidelity
@@ -185,9 +187,9 @@ def fidelity_ghz_coherences(dataset: xr.Dataset, qubit_layout: List[int]) -> lis
185
187
  num_qubits = len(qubit_layout)
186
188
  phases = [np.pi * i / (num_qubits + 1) for i in range(2 * num_qubits + 2)]
187
189
  idx = BenchmarkObservationIdentifier(qubit_layout).string_identifier
188
- transpiled_circuits = dataset.attrs["transpiled_circuits"][idx]
190
+ transpiled_circuits = circuits["transpiled_circuits"]
189
191
  num_shots = dataset.attrs["shots"]
190
- num_circuits = len(transpiled_circuits)
192
+ num_circuits = len(transpiled_circuits[f"{qubit_layout}_native_ghz"].circuits)
191
193
 
192
194
  # Computing the phase acquired by the |11...1> component for each interval
193
195
  complex_coefficients = np.exp(1j * num_qubits * np.array(phases))
@@ -250,45 +252,50 @@ def fidelity_analysis(run: BenchmarkRunResult) -> BenchmarkAnalysisResult:
250
252
 
251
253
  observation_list: list[BenchmarkObservation] = []
252
254
  for qubit_layout in qubit_layouts:
253
- if routine == "randomized_measurements":
254
- ideal_simulator = Aer.get_backend("statevector_simulator")
255
- ideal_probabilities = []
256
- idx = BenchmarkObservationIdentifier(qubit_layout).string_identifier
257
- all_circuits = run.dataset.attrs["transpiled_circuits"][idx]
258
- for qc in all_circuits:
259
- qc_copy = qc.copy()
260
- qc_copy.remove_final_measurements()
261
- deflated_qc = reduce_to_active_qubits(qc_copy, backend_name)
262
- ideal_probabilities.append(dict(sorted(ideal_simulator.run(deflated_qc).result().get_counts().items())))
263
- values, uncertainties = fidelity_ghz_randomized_measurements(
264
- dataset, qubit_layout, ideal_probabilities, len(qubit_layout)
265
- )
266
- observation_list.extend(
267
- [
268
- BenchmarkObservation(
269
- name=key,
270
- identifier=BenchmarkObservationIdentifier(qubit_layout),
271
- value=value,
272
- uncertainty=uncertainties[key],
273
- )
274
- for key, value in values.items()
275
- ]
276
- )
277
- else: # default routine == "coherences":
278
- fidelity = fidelity_ghz_coherences(dataset, qubit_layout)
279
- observation_list.extend(
280
- [
281
- BenchmarkObservation(
282
- name="fidelity", identifier=BenchmarkObservationIdentifier(qubit_layout), value=fidelity[0]
283
- )
284
- ]
285
- )
286
- if len(fidelity) > 1:
287
- observation_list.append(
288
- BenchmarkObservation(
289
- name="fidelity_rem", identifier=BenchmarkObservationIdentifier(qubit_layout), value=fidelity[1]
255
+ match routine:
256
+ case "randomized_measurements":
257
+ ideal_simulator = Aer.get_backend("statevector_simulator")
258
+ ideal_probabilities = []
259
+ idx = BenchmarkObservationIdentifier(qubit_layout).string_identifier
260
+ all_circuits = run.circuits["transpiled_circuits"][f"{idx}_native_ghz"].circuits
261
+ for qc in all_circuits:
262
+ qc_copy = qc.copy()
263
+ qc_copy.remove_final_measurements()
264
+ deflated_qc = reduce_to_active_qubits(qc_copy, backend_name)
265
+ ideal_probabilities.append(
266
+ dict(sorted(ideal_simulator.run(deflated_qc).result().get_counts().items()))
290
267
  )
268
+ values, uncertainties = fidelity_ghz_randomized_measurements(
269
+ dataset, qubit_layout, ideal_probabilities, len(qubit_layout), run.circuits
291
270
  )
271
+ observation_list.extend(
272
+ [
273
+ BenchmarkObservation(
274
+ name=key,
275
+ identifier=BenchmarkObservationIdentifier(qubit_layout),
276
+ value=value,
277
+ uncertainty=uncertainties[key],
278
+ )
279
+ for key, value in values.items()
280
+ ]
281
+ )
282
+ case "coherences":
283
+ fidelity = fidelity_ghz_coherences(dataset, qubit_layout, run.circuits)
284
+ observation_list.extend(
285
+ [
286
+ BenchmarkObservation(
287
+ name="fidelity", identifier=BenchmarkObservationIdentifier(qubit_layout), value=fidelity[0]
288
+ )
289
+ ]
290
+ )
291
+ if len(fidelity) > 1:
292
+ observation_list.append(
293
+ BenchmarkObservation(
294
+ name="fidelity_rem",
295
+ identifier=BenchmarkObservationIdentifier(qubit_layout),
296
+ value=fidelity[1],
297
+ )
298
+ )
292
299
  plots = {"All layout fidelities": plot_fidelities(observation_list, qubit_layouts)}
293
300
  return BenchmarkAnalysisResult(dataset=dataset, observations=observation_list, plots=plots)
294
301
 
@@ -304,7 +311,8 @@ def generate_ghz_linear(num_qubits: int) -> QuantumCircuit:
304
311
  A quantum circuit generating a GHZ state of n qubits
305
312
  """
306
313
  s = int(num_qubits / 2)
307
- qc = QuantumCircuit(num_qubits)
314
+ quantum_register = QuantumRegister(num_qubits)
315
+ qc = QuantumCircuit(quantum_register, name="GHZ_linear")
308
316
  qc.h(s)
309
317
 
310
318
  for m in range(s, 0, -1):
@@ -325,7 +333,8 @@ def generate_ghz_log_cruz(num_qubits: int) -> QuantumCircuit:
325
333
  Returns:
326
334
  A quantum circuit generating a GHZ state of n qubits
327
335
  """
328
- qc = QuantumCircuit(num_qubits)
336
+ quantum_register = QuantumRegister(num_qubits)
337
+ qc = QuantumCircuit(quantum_register, name="GHZ_log_Cruz")
329
338
  qc.h(0)
330
339
 
331
340
  for m in range(num_qubits):
@@ -346,7 +355,8 @@ def generate_ghz_log_mooney(num_qubits: int) -> QuantumCircuit:
346
355
  Returns:
347
356
  A quantum circuit generating a GHZ state of n qubits
348
357
  """
349
- qc = QuantumCircuit(num_qubits)
358
+ quantum_register = QuantumRegister(num_qubits)
359
+ qc = QuantumCircuit(quantum_register, name="GHZ_log_Mooney")
350
360
  qc.h(0)
351
361
 
352
362
  aux_n = int(np.ceil(np.log2(num_qubits)))
@@ -389,7 +399,8 @@ def generate_ghz_spanning_tree(
389
399
  participating_qubits = set(qubit for pair in cx_map[: n_state - 1] for qubit in pair)
390
400
 
391
401
  relabeling = {idx_old: idx_new for idx_new, idx_old in enumerate(participating_qubits)}
392
- qc = QuantumCircuit(n_state, name="ghz")
402
+ n_state_register = QuantumRegister(n_state)
403
+ qc = QuantumCircuit(n_state_register, name="ghz")
393
404
  qc.h([relabeling[cx_map[0][0]]])
394
405
  for _, pair in zip(np.arange(n_state - 1), cx_map):
395
406
  relabeled_pair = [relabeling[pair[0]], relabeling[pair[1]]]
@@ -594,7 +605,6 @@ class GHZBenchmark(Benchmark):
594
605
  super().__init__(backend, configuration)
595
606
 
596
607
  self.state_generation_routine = configuration.state_generation_routine
597
- # self.choose_qubits_routine = configuration.choose_qubits_routine
598
608
  if configuration.custom_qubits_array:
599
609
  self.custom_qubits_array = configuration.custom_qubits_array
600
610
  else:
@@ -606,7 +616,6 @@ class GHZBenchmark(Benchmark):
606
616
  if any(np.max(configuration.qubit_counts) > [len(layout) for layout in self.custom_qubits_array]):
607
617
  raise ValueError("The maximum given qubit count is larger than the size of the smallest qubit layout.")
608
618
  self.qubit_counts = configuration.qubit_counts
609
- # self.layout_idx_mapping = {str(qubit_layout): idx for idx, qubit_layout in enumerate(self.custom_qubits_array)}
610
619
 
611
620
  self.qiskit_optim_level = configuration.qiskit_optim_level
612
621
  self.optimize_sqg = configuration.optimize_sqg
@@ -617,11 +626,7 @@ class GHZBenchmark(Benchmark):
617
626
  self.cal_url = configuration.cal_url
618
627
  self.timestamp = strftime("%Y%m%d-%H%M%S")
619
628
 
620
- # @staticmethod
621
- # def name() -> str:
622
- # return "ghz"
623
-
624
- def generate_native_ghz(self, qubit_layout: List[int], qubit_count: int, routine: str) -> QuantumCircuit:
629
+ def generate_native_ghz(self, qubit_layout: List[int], qubit_count: int, routine: str) -> CircuitGroup:
625
630
  """
626
631
  Generate a circuit preparing a GHZ state,
627
632
  according to a given routine and transpiled to the native gate set and topology.
@@ -638,13 +643,13 @@ class GHZBenchmark(Benchmark):
638
643
  Returns:
639
644
  QuantumCircuit implementing GHZ native state
640
645
  """
641
- # num_qubits = len(qubit_layout)
646
+ circuit_group = CircuitGroup(name=f"{qubit_layout}_native_ghz")
642
647
  fixed_coupling_map = set_coupling_map(qubit_layout, self.backend, "fixed")
643
- idx = BenchmarkObservationIdentifier(qubit_layout).string_identifier
644
648
  ghz_native_transpiled: List[QuantumCircuit]
649
+
645
650
  if routine == "naive":
646
- ghz = generate_ghz_linear(qubit_count)
647
- self.untranspiled_circuits[idx].update({qubit_count: ghz})
651
+ ghz: QuantumCircuit = generate_ghz_linear(qubit_count)
652
+ circuit_group.add_circuit(ghz)
648
653
  ghz_native_transpiled, _ = perform_backend_transpilation(
649
654
  [ghz],
650
655
  self.backend,
@@ -661,7 +666,7 @@ class GHZBenchmark(Benchmark):
661
666
  else:
662
667
  graph = get_edges(self.backend.coupling_map, qubit_layout)
663
668
  ghz, _ = generate_ghz_spanning_tree(graph, qubit_layout, qubit_count)
664
- self.untranspiled_circuits[idx].update({qubit_count: ghz})
669
+ circuit_group.add_circuit(ghz)
665
670
  ghz_native_transpiled, _ = perform_backend_transpilation(
666
671
  [ghz],
667
672
  self.backend,
@@ -685,12 +690,13 @@ class GHZBenchmark(Benchmark):
685
690
  if ghz_native_transpiled[0].depth() == ghz_native_transpiled[1].depth():
686
691
  index_min_2q = np.argmin([c.count_ops()["cz"] for c in ghz_native_transpiled])
687
692
  final_ghz = ghz_native_transpiled[index_min_2q]
688
- self.untranspiled_circuits[idx].update({qubit_count: ghz_log[index_min_2q]})
693
+ circuit_group.add_circuit(ghz_log[index_min_2q])
689
694
  else:
690
695
  index_min_depth = np.argmin([c.depth() for c in ghz_native_transpiled])
691
696
  final_ghz = ghz_native_transpiled[index_min_depth]
692
- self.untranspiled_circuits[idx].update({qubit_count: ghz_log[index_min_depth]})
693
- return final_ghz[0]
697
+ circuit_group.add_circuit([ghz_log[index_min_depth]])
698
+ self.circuits["untranspiled_circuits"].circuit_groups.append(circuit_group)
699
+ return CircuitGroup(name=f"{qubit_layout}_native_ghz", circuits=[final_ghz[0]])
694
700
 
695
701
  def generate_coherence_meas_circuits(self, qubit_layout: List[int], qubit_count: int) -> List[QuantumCircuit]:
696
702
  """
@@ -708,9 +714,9 @@ class GHZBenchmark(Benchmark):
708
714
  """
709
715
 
710
716
  idx = BenchmarkObservationIdentifier(qubit_layout).string_identifier
711
- qc = self.untranspiled_circuits[idx][qubit_count]
712
- qc_list = [qc.copy()]
717
+ qc_list = self.circuits["untranspiled_circuits"][f"{qubit_layout}_native_ghz"].circuits
713
718
 
719
+ qc = qc_list[0].copy()
714
720
  qc.remove_final_measurements()
715
721
  qc_inv = qc.inverse()
716
722
  phases = [np.pi * i / (qubit_count + 1) for i in range(2 * qubit_count + 2)]
@@ -733,10 +739,11 @@ class GHZBenchmark(Benchmark):
733
739
  qiskit_optim_level=self.qiskit_optim_level,
734
740
  optimize_sqg=self.optimize_sqg,
735
741
  )
736
- self.untranspiled_circuits[idx].update({qubit_count: qc_list})
742
+ circuit_group = CircuitGroup(name=idx, circuits=qc_list)
743
+ self.circuits["untranspiled_circuits"].circuit_groups.append(circuit_group)
737
744
  return qc_list_transpiled
738
745
 
739
- def generate_readout_circuit(self, qubit_layout, qubit_count):
746
+ def generate_readout_circuit(self, qubit_layout: List[int], qubit_count: int) -> CircuitGroup:
740
747
  """
741
748
  A wrapper for the creation of different circuits to estimate the fidelity
742
749
 
@@ -752,22 +759,23 @@ class GHZBenchmark(Benchmark):
752
759
  A list of transpiled quantum circuits to be measured
753
760
  """
754
761
  # Generate the list of circuits
755
- idx = BenchmarkObservationIdentifier(qubit_layout).string_identifier
756
- self.untranspiled_circuits[idx] = {}
757
- self.transpiled_circuits[idx] = {}
758
762
 
759
763
  qcvv_logger.info(f"Now generating a {len(qubit_layout)}-qubit GHZ state on qubits {qubit_layout}")
760
- transpiled_ghz = self.generate_native_ghz(qubit_layout, qubit_count, self.state_generation_routine)
761
-
762
- if self.fidelity_routine == "randomized_measurements":
763
- all_circuits_list, _ = append_rms(transpiled_ghz, cast(int, self.num_RMs), self.backend)
764
- elif self.fidelity_routine == "coherences":
765
- all_circuits_list = self.generate_coherence_meas_circuits(qubit_layout, qubit_count)
766
- else:
767
- all_circuits_list = transpiled_ghz
764
+ transpiled_ghz_group: CircuitGroup = self.generate_native_ghz(
765
+ qubit_layout, qubit_count, self.state_generation_routine
766
+ )
768
767
 
769
- self.transpiled_circuits.update({idx: all_circuits_list})
770
- return all_circuits_list
768
+ match self.fidelity_routine:
769
+ case "randomized_measurements":
770
+ all_circuits_list, _ = append_rms(
771
+ transpiled_ghz_group.circuits[0], cast(int, self.num_RMs), self.backend
772
+ )
773
+ transpiled_ghz_group.circuits = all_circuits_list
774
+ case "coherences":
775
+ all_circuits_list = self.generate_coherence_meas_circuits(qubit_layout, qubit_count)
776
+ transpiled_ghz_group.circuits = all_circuits_list
777
+ self.circuits["transpiled_circuits"].circuit_groups.append(transpiled_ghz_group)
778
+ return transpiled_ghz_group
771
779
 
772
780
  def add_configuration_to_dataset(self, dataset: xr.Dataset): # CHECK
773
781
  """
@@ -785,8 +793,7 @@ class GHZBenchmark(Benchmark):
785
793
  else:
786
794
  dataset.attrs[key] = value
787
795
  dataset.attrs[f"backend_name"] = self.backend.name
788
- dataset.attrs[f"untranspiled_circuits"] = self.untranspiled_circuits
789
- dataset.attrs[f"transpiled_circuits"] = self.transpiled_circuits
796
+ dataset.attrs["fidelity_routine"] = self.fidelity_routine
790
797
 
791
798
  def execute(self, backend) -> xr.Dataset:
792
799
  """
@@ -797,13 +804,17 @@ class GHZBenchmark(Benchmark):
797
804
 
798
805
  # Submit all
799
806
  all_jobs: Dict = {}
807
+
808
+ self.circuits = Circuits()
809
+ self.circuits.benchmark_circuits.append(BenchmarkCircuit(name="transpiled_circuits"))
810
+ self.circuits.benchmark_circuits.append(BenchmarkCircuit(name="untranspiled_circuits"))
800
811
  for qubit_layout in aux_custom_qubits_array:
801
812
  Id = BenchmarkObservationIdentifier(qubit_layout)
802
813
  idx = Id.string_identifier
803
814
  # for qubit_count in self.qubit_counts[idx]:
804
815
  qubit_count = len(qubit_layout)
805
- circuits = self.generate_readout_circuit(qubit_layout, qubit_count)
806
- transpiled_circuit_dict = {tuple(qubit_layout): circuits}
816
+ circuit_group: CircuitGroup = self.generate_readout_circuit(qubit_layout, qubit_count)
817
+ transpiled_circuit_dict = {tuple(qubit_layout): circuit_group.circuits}
807
818
  all_jobs[idx], _ = submit_execute(
808
819
  transpiled_circuit_dict,
809
820
  backend,
@@ -811,6 +822,7 @@ class GHZBenchmark(Benchmark):
811
822
  self.calset_id,
812
823
  max_gates_per_batch=self.max_gates_per_batch,
813
824
  )
825
+
814
826
  # Retrieve all
815
827
  qcvv_logger.info(f"Retrieving counts and adding counts to dataset...")
816
828
  for qubit_layout in aux_custom_qubits_array:
@@ -822,8 +834,8 @@ class GHZBenchmark(Benchmark):
822
834
  dataset, _ = add_counts_to_dataset(counts, idx, dataset)
823
835
  if self.rem:
824
836
  qcvv_logger.info(f"Applying readout error mitigation")
825
- circuits = self.transpiled_circuits[idx]
826
- rem_results, _ = apply_readout_error_mitigation(backend, circuits, counts, self.mit_shots)
837
+ circuit_group = self.circuits["transpiled_circuits"][f"{idx}_native_ghz"]
838
+ rem_results, _ = apply_readout_error_mitigation(backend, circuit_group.circuits, counts, self.mit_shots)
827
839
  rem_results_dist = [counts_mit.nearest_probability_distribution() for counts_mit in rem_results]
828
840
  dataset, _ = add_counts_to_dataset(rem_results_dist, f"{idx}_rem", dataset)
829
841
 
@@ -17,20 +17,21 @@ Q-score benchmark
17
17
  """
18
18
 
19
19
  import itertools
20
+ import logging
20
21
  from time import strftime
21
- from typing import Callable, Dict, List, Optional, Tuple, Type
22
+ from typing import Callable, Dict, List, Literal, Optional, Tuple, Type
22
23
 
23
24
  from matplotlib.figure import Figure
24
25
  import matplotlib.pyplot as plt
25
26
  from networkx import Graph
26
27
  import networkx as nx
27
28
  import numpy as np
28
- from qiskit import QuantumCircuit
29
29
  from scipy.optimize import basinhopping, minimize
30
30
 
31
31
  from iqm.benchmarks.benchmark import BenchmarkBase, BenchmarkConfigurationBase
32
32
  from iqm.benchmarks.logging_config import qcvv_logger
33
33
  from iqm.benchmarks.utils import perform_backend_transpilation, retrieve_all_counts, submit_execute, timeit
34
+ from iqm.qiskit_iqm import IQMCircuit as QuantumCircuit
34
35
  from iqm.qiskit_iqm.iqm_backend import IQMBackendBase
35
36
 
36
37
 
@@ -209,6 +210,7 @@ class QScoreBenchmark(BenchmarkBase):
209
210
 
210
211
  else:
211
212
  coupling_map = self.backend.coupling_map.reduce(qubit_set)
213
+ qcvv_logger.setLevel(logging.WARNING)
212
214
  transpiled_qc_list, _ = perform_backend_transpilation(
213
215
  [qc],
214
216
  backend=self.backend,
@@ -230,6 +232,7 @@ class QScoreBenchmark(BenchmarkBase):
230
232
  )
231
233
 
232
234
  counts = retrieve_all_counts(jobs)[0][0]
235
+ qcvv_logger.setLevel(logging.INFO)
233
236
 
234
237
  return self.compute_expectation_value(counts, graph)
235
238
 
@@ -595,7 +598,7 @@ class QScoreBenchmark(BenchmarkBase):
595
598
 
596
599
  for i in range(self.num_instances):
597
600
  graph = nx.generators.erdos_renyi_graph(num_nodes, 0.5, seed=seed)
598
- print(f"graph: {graph}")
601
+ qcvv_logger.debug(f"graph: {graph}")
599
602
  self.graph_physical = graph.copy()
600
603
  self.virtual_nodes = []
601
604
  if self.use_virtual_node:
@@ -619,14 +622,14 @@ class QScoreBenchmark(BenchmarkBase):
619
622
  if graph.number_of_edges() == 0:
620
623
  cut_sizes.append(0)
621
624
  seed += 1
622
- qcvv_logger.info(f"Graph {i+1}/{self.num_instances} had no edges: cut size = 0.")
625
+ qcvv_logger.debug(f"Graph {i+1}/{self.num_instances} had no edges: cut size = 0.")
623
626
  continue
624
627
 
625
628
  # Choose the qubit layout
626
629
  qubit_set = []
627
630
  if self.choose_qubits_routine.lower() == "naive":
628
631
  qubit_set = self.choose_qubits_naive(num_nodes)
629
- elif self.choose_qubits_routine.lower() == "custom" or self.choose_qubits_routine.lower() == "mapomatic":
632
+ elif self.choose_qubits_routine.lower() == "custom":
630
633
  qubit_set = self.choose_qubits_custom(num_nodes)
631
634
  else:
632
635
  raise ValueError('choose_qubits_routine must either be "naive" or "custom".')
@@ -634,7 +637,7 @@ class QScoreBenchmark(BenchmarkBase):
634
637
  # Solve the maximum cut size with QAOA
635
638
  cut_sizes.append(self.run_QAOA(graph, qubit_set))
636
639
  seed += 1
637
- qcvv_logger.info(f"Solved the MaxCut on graph {i+1}/{self.num_instances}.")
640
+ qcvv_logger.debug(f"Solved the MaxCut on graph {i+1}/{self.num_instances}.")
638
641
 
639
642
  average_cut_size = np.mean(cut_sizes) - num_nodes * (num_nodes - 1) / 8
640
643
  average_best_cut_size = 0.178 * pow(num_nodes, 3 / 2)
@@ -677,7 +680,7 @@ class QScoreBenchmark(BenchmarkBase):
677
680
  list_of_cut_sizes = []
678
681
 
679
682
  for num_nodes in range(self.min_num_nodes, max_num_nodes + 1):
680
- qcvv_logger.info(f"Executing on {self.num_instances} random graphs with {num_nodes} nodes.")
683
+ qcvv_logger.debug(f"Executing on {self.num_instances} random graphs with {num_nodes} nodes.")
681
684
  is_successful, approximation_ratio, cut_sizes = self.execute_single_benchmark(num_nodes)[0:3]
682
685
  approximation_ratios.append(approximation_ratio)
683
686
 
@@ -711,7 +714,7 @@ class QScoreConfiguration(BenchmarkConfigurationBase):
711
714
  max_num_nodes: Optional[int] = None
712
715
  use_virtual_node: bool = True
713
716
  use_classically_optimized_angles: bool = True
714
- choose_qubits_routine: str = "naive"
717
+ choose_qubits_routine: Literal["naive", "custom"] = "naive"
715
718
  min_num_qubits: int = 2 # If choose_qubits_routine is "naive"
716
719
  custom_qubits_array: Optional[list[list[int]]] = None
717
720
  qiskit_optim_level: int = 3
@@ -25,13 +25,13 @@ import matplotlib as mpl
25
25
  from matplotlib.figure import Figure
26
26
  import matplotlib.pyplot as plt
27
27
  import numpy as np
28
- from qiskit import QuantumCircuit
29
28
  from qiskit.circuit import ParameterVector
30
29
  import xarray as xr
31
30
 
32
31
  from iqm.benchmarks import Benchmark
33
32
  from iqm.benchmarks.benchmark import BenchmarkConfigurationBase
34
33
  from iqm.benchmarks.benchmark_definition import BenchmarkAnalysisResult, BenchmarkRunResult
34
+ from iqm.benchmarks.circuit_containers import BenchmarkCircuit, CircuitGroup, Circuits
35
35
  from iqm.benchmarks.logging_config import qcvv_logger
36
36
  from iqm.benchmarks.utils import (
37
37
  count_2q_layers,
@@ -44,6 +44,7 @@ from iqm.benchmarks.utils import (
44
44
  submit_execute,
45
45
  timeit,
46
46
  )
47
+ from iqm.qiskit_iqm import IQMCircuit as QuantumCircuit
47
48
  from iqm.qiskit_iqm.iqm_backend import IQMBackendBase
48
49
  from iqm.qiskit_iqm.iqm_transpilation import optimize_single_qubit_gates
49
50
 
@@ -251,9 +252,10 @@ def clops_analysis(run: BenchmarkRunResult) -> BenchmarkAnalysisResult:
251
252
  all_times_retrieve = dataset.attrs["all_times_retrieve"]
252
253
 
253
254
  transpiled_qc_list = []
254
- for _, value in dataset.attrs["transpiled_circuits"].items():
255
- for _, transpiled_circuit in value.items():
256
- transpiled_qc_list.extend(transpiled_circuit)
255
+ for group in run.circuits["transpiled_circuits"].circuit_groups:
256
+ transpiled_qc_list.extend(group.circuits)
257
+ # for _, value in dataset.attrs["transpiled_circuits"].items():
258
+ # for _, transpiled_circuit in value.items():
257
259
 
258
260
  # CLOPS_V
259
261
  clops_v: float = num_circuits * num_updates * num_shots * depth / clops_time
@@ -387,26 +389,6 @@ class CLOPSBenchmark(Benchmark):
387
389
  dataset.attrs["u_per_layer"] = self.u_per_layer
388
390
  dataset.attrs["num_parameters"] = self.num_parameters
389
391
 
390
- def add_all_circuits_to_dataset(self, dataset: xr.Dataset):
391
- """Adds all generated circuits during execution to the dataset variable
392
-
393
- Args:
394
- dataset (xr.Dataset): The xarray dataset
395
-
396
- Returns:
397
-
398
- """
399
- qcvv_logger.info(f"Adding all circuits to the dataset")
400
- for key, circuit in zip(
401
- ["transpiled_circuits", "untranspiled_circuits"], [self.transpiled_circuits, self.untranspiled_circuits]
402
- ):
403
- dictionary = {}
404
- for outer_key, outer_value in circuit.items():
405
- dictionary[str(outer_key)] = {
406
- str(inner_key): inner_values for inner_key, inner_values in outer_value.items()
407
- }
408
- dataset.attrs[key] = dictionary
409
-
410
392
  def append_parameterized_unitary(
411
393
  self,
412
394
  qc: QuantumCircuit,
@@ -593,8 +575,6 @@ class CLOPSBenchmark(Benchmark):
593
575
  Dict[str, QuantumCircuit]: a dictionary of quantum circuits with keys being str(qubit layout)
594
576
  """
595
577
  # Generate the list of QV circuits
596
- self.untranspiled_circuits = {}
597
- self.transpiled_circuits = {}
598
578
 
599
579
  qc_list, self.time_circuit_generate = self.generate_circuit_list()
600
580
 
@@ -622,11 +602,9 @@ class CLOPSBenchmark(Benchmark):
622
602
  # Sort circuits according to their final measurement mappings
623
603
  (sorted_transpiled_qc_list, _), self.time_sort_batches = sort_batches_by_final_layout(transpiled_qc_list)
624
604
 
625
- self.untranspiled_circuits.update({str(self.qubits): {str(self.qubits): qc_list}})
626
- self.transpiled_circuits.update(
627
- {str(self.qubits): {str(key): value for key, value in sorted_transpiled_qc_list.items()}}
628
- )
629
- # self.transpiled_circuits[str(self.qubits)].update(sorted_transpiled_qc_list)
605
+ self.untranspiled_circuits.circuit_groups.append(CircuitGroup(name=self.qubits, circuits=qc_list))
606
+ for key in sorted_transpiled_qc_list.keys():
607
+ self.transpiled_circuits.circuit_groups.append(CircuitGroup(name=f"{self.qubits}_{key}", circuits=qc_list))
630
608
 
631
609
  return sorted_transpiled_qc_list
632
610
 
@@ -635,6 +613,9 @@ class CLOPSBenchmark(Benchmark):
635
613
 
636
614
  self.execution_timestamp = strftime("%Y-%m-%d_%H:%M:%S")
637
615
 
616
+ self.circuits = Circuits()
617
+ self.transpiled_circuits = BenchmarkCircuit(name="transpiled_circuits")
618
+ self.untranspiled_circuits = BenchmarkCircuit(name="untranspiled_circuits")
638
619
  dataset = xr.Dataset()
639
620
  self.add_all_meta_to_dataset(dataset)
640
621
 
@@ -691,7 +672,7 @@ class CLOPSBenchmark(Benchmark):
691
672
  }
692
673
  )
693
674
 
694
- self.add_all_circuits_to_dataset(dataset)
675
+ self.circuits = Circuits([self.transpiled_circuits, self.untranspiled_circuits])
695
676
 
696
677
  return dataset
697
678