Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
calibration_records.py
Go to the documentation of this file.
1 from __future__ import annotations
2 
3 from copy import deepcopy
4 from functools import lru_cache
5 
6 import numpy as np
7 from qiskit import QuantumCircuit
8 from qiskit_aer import AerSimulator
9 from qiskit_aer.noise import (
10  amplitude_damping_error,
11  depolarizing_error,
12  phase_damping_error,
13 )
14 
15 from benchmarks.density_matrix.partitioned_runtime.common import (
16  PHASE3_RUNTIME_DENSITY_TOL,
17  PHASE3_RUNTIME_ENERGY_TOL,
18  build_density_comparison_metrics,
19  density_energy,
20  execute_partitioned_with_reference,
21 )
22 from benchmarks.density_matrix.planner_calibration.signals import (
23  PLANNER_CALIBRATION_DENSITY_AWARE_OBJECTIVE_NAME,
24  apply_density_scores_and_rankings,
25  build_density_signal_record,
26 )
27 from benchmarks.density_matrix.planner_calibration.case_selection import (
28  PLANNER_CALIBRATION_CASE_KIND_CONTINUITY,
29  PLANNER_CALIBRATION_CASE_KIND_MICROCASE,
30  iter_planner_calibration_candidate_cases,
31 )
32 from squander.partitioning.noisy_runtime import PHASE3_RUNTIME_PATH_BASELINE
33 
34 PLANNER_CALIBRATION_CALIBRATION_RECORD_SCHEMA_VERSION = "phase3_planner_calibration_record_v1"
35 PLANNER_CALIBRATION_REFERENCE_BACKEND = "qiskit_aer_density_matrix"
36 PLANNER_CALIBRATION_EXTERNAL_REFERENCE_CONTINUITY_QUBITS = (4,)
37 
38 
39 def _flatten_members(descriptor_set):
40  return tuple(
41  member for partition in descriptor_set.partitions for member in partition.members
42  )
43 
44 
45 def _member_parameter_value(parameters: np.ndarray, descriptor_set, member) -> float:
46  op = descriptor_set.operations[member.canonical_operation_index]
47  return float(parameters[op.param_start])
48 
49 
51  qc: QuantumCircuit, descriptor_set, member, parameters: np.ndarray
52 ) -> None:
53  op = descriptor_set.operations[member.canonical_operation_index]
54  if op.kind == "gate":
55  if op.name == "U3":
56  theta, phi, lam = parameters[op.param_start : op.param_start + 3]
57  qiskit_theta = np.fmod(2.0 * float(theta), 4.0 * np.pi)
58  qiskit_phi = np.fmod(float(phi), 2.0 * np.pi)
59  qiskit_lambda = np.fmod(float(lam), 2.0 * np.pi)
60  qc.u(qiskit_theta, qiskit_phi, qiskit_lambda, op.target_qbit)
61  return
62  if op.name == "CNOT":
63  qc.cx(op.control_qbit, op.target_qbit)
64  return
65  raise ValueError(
66  "Unsupported Qiskit gate '{}' for planner calibration reference".format(op.name)
67  )
68 
69  if op.kind == "noise":
70  value = (
71  float(op.fixed_value)
72  if op.fixed_value is not None
73  else _member_parameter_value(parameters, descriptor_set, member)
74  )
75  if op.name == "local_depolarizing":
76  qc.append(depolarizing_error(value, 1), [op.target_qbit])
77  return
78  if op.name == "amplitude_damping":
79  qc.append(amplitude_damping_error(value), [op.target_qbit])
80  return
81  if op.name == "phase_damping":
82  qc.append(phase_damping_error(value), [op.target_qbit])
83  return
84  raise ValueError(
85  "Unsupported Qiskit noise '{}' for planner calibration reference".format(op.name)
86  )
87 
88  raise ValueError(
89  "Unsupported descriptor member kind '{}' for planner calibration reference".format(
90  op.kind
91  )
92  )
93 
94 
96  descriptor_set,
97  parameters: np.ndarray,
98 ) -> np.ndarray:
99  qc = QuantumCircuit(descriptor_set.qbit_num)
100  for member in _flatten_members(descriptor_set):
101  _apply_member_to_qiskit(qc, descriptor_set, member, parameters)
102  qc.save_density_matrix()
103  simulator = AerSimulator(method="density_matrix")
104  result = simulator.run(qc, shots=1).result()
105  return np.asarray(result.data()["density_matrix"])
106 
107 
108 def _requires_external_reference(metadata: dict) -> bool:
109  return metadata["case_kind"] == PLANNER_CALIBRATION_CASE_KIND_MICROCASE or (
110  metadata["case_kind"] == PLANNER_CALIBRATION_CASE_KIND_CONTINUITY
111  and metadata["qbit_num"] in PLANNER_CALIBRATION_EXTERNAL_REFERENCE_CONTINUITY_QUBITS
112  )
113 
114 
116  metadata: dict,
117  descriptor_set,
118  parameters: np.ndarray,
119  *,
120  hamiltonian=None,
121 ) -> dict:
122  runtime_result, reference_density, density_metrics = execute_partitioned_with_reference(
123  descriptor_set, parameters, allow_fusion=False
124  )
126  metadata,
127  descriptor_set,
128  runtime_result,
129  density_metrics,
130  )
131  record["record_schema_version"] = PLANNER_CALIBRATION_CALIBRATION_RECORD_SCHEMA_VERSION
132  record["density_aware_objective_name"] = PLANNER_CALIBRATION_DENSITY_AWARE_OBJECTIVE_NAME
133  record["trace_deviation"] = runtime_result.trace_deviation
134  record["rho_is_valid"] = runtime_result.rho_is_valid
135  record["rho_is_valid_tol"] = 1e-10
136  record["runtime_path"] = PHASE3_RUNTIME_PATH_BASELINE
137 
138  internal_density_pass = (
139  record["frobenius_norm_diff"] <= PHASE3_RUNTIME_DENSITY_TOL
140  and record["max_abs_diff"] <= PHASE3_RUNTIME_DENSITY_TOL
141  and runtime_result.trace_deviation <= PHASE3_RUNTIME_DENSITY_TOL
142  and runtime_result.rho_is_valid
143  )
144 
145  continuity_energy_error = None
146  continuity_energy_pass = True
147  if hamiltonian is not None:
148  runtime_energy_real, _ = density_energy(
149  hamiltonian, runtime_result.density_matrix_numpy()
150  )
151  reference_energy_real, _ = density_energy(
152  hamiltonian, np.asarray(reference_density.to_numpy())
153  )
154  continuity_energy_error = float(abs(runtime_energy_real - reference_energy_real))
155  continuity_energy_pass = continuity_energy_error <= PHASE3_RUNTIME_ENERGY_TOL
156 
157  record["continuity_energy_error"] = continuity_energy_error
158  record["continuity_energy_pass"] = continuity_energy_pass
159  record["internal_correctness_pass"] = internal_density_pass and continuity_energy_pass
160 
161  external_reference_required = _requires_external_reference(metadata)
162  record["external_reference_required"] = external_reference_required
163  record["reference_backend"] = (
164  PLANNER_CALIBRATION_REFERENCE_BACKEND if external_reference_required else None
165  )
166  if external_reference_required:
167  aer_density = execute_qiskit_density_reference(descriptor_set, parameters)
168  external_metrics = build_density_comparison_metrics(
169  runtime_result.density_matrix, aer_density
170  )
171  external_energy_error = None
172  if hamiltonian is not None:
173  runtime_energy_real, _ = density_energy(
174  hamiltonian, runtime_result.density_matrix_numpy()
175  )
176  aer_energy_real, _ = density_energy(hamiltonian, aer_density)
177  external_energy_error = float(abs(runtime_energy_real - aer_energy_real))
178  external_reference_pass = (
179  external_metrics["frobenius_norm_diff"] <= PHASE3_RUNTIME_DENSITY_TOL
180  and external_metrics["max_abs_diff"] <= PHASE3_RUNTIME_DENSITY_TOL
181  and (
182  external_energy_error is None
183  or external_energy_error <= PHASE3_RUNTIME_ENERGY_TOL
184  )
185  )
186  record["external_frobenius_norm_diff"] = external_metrics["frobenius_norm_diff"]
187  record["external_max_abs_diff"] = external_metrics["max_abs_diff"]
188  record["external_energy_error"] = external_energy_error
189  record["external_reference_pass"] = external_reference_pass
190  else:
191  record["external_frobenius_norm_diff"] = None
192  record["external_max_abs_diff"] = None
193  record["external_energy_error"] = None
194  record["external_reference_pass"] = True
195 
196  record["counted_calibration_case"] = (
197  record["internal_correctness_pass"] and record["external_reference_pass"]
198  )
199  return record
200 
201 
202 @lru_cache(maxsize=1)
204  records = [
206  metadata,
207  descriptor_set,
208  parameters,
209  hamiltonian=hamiltonian,
210  )
211  for metadata, descriptor_set, parameters, hamiltonian in iter_planner_calibration_candidate_cases()
212  ]
213  return tuple(apply_density_scores_and_rankings(records))
214 
215 
def _build_planner_calibration_calibration_records_cached()
def apply_density_scores_and_rankings
Definition: signals.py:100
def build_planner_calibration_calibration_records()
def build_planner_calibration_calibration_record
def _flatten_members(descriptor_set)
def build_density_comparison_metrics
def execute_partitioned_with_reference
def build_density_signal_record
Definition: signals.py:38