Source code for quantum_launcher.routines.cirq_routines
1"""
2Routine file for Cirq library
3"""
4from typing import Literal
5from collections.abc import Sequence
6
7from quantum_launcher.base import Backend
8from quantum_launcher.base.translator import Translation
9from quantum_launcher.import_management import DependencyError
10try:
11 import cirq
12 from cirq.sim.sparse_simulator import Simulator
13except ImportError as e:
14 raise DependencyError(e, install_hint='cirq') from e
15try:
16 import qiskit
17 from qiskit.primitives import Sampler
18 from qiskit.primitives.base.sampler_result import SamplerResult
19 from qiskit.result import QuasiDistribution
20 from qiskit_algorithms.optimizers import COBYLA
21except ImportError as e:
22 raise DependencyError(e, install_hint='qiskit') from e
23
24
25class _CirqRunner:
26 simulator = Simulator()
27 repetitions = 1024
28
29 @classmethod
30 def calculate_circuit(cls, circuit: qiskit.QuantumCircuit) -> dict:
31 circuit = circuit.measure_all(inplace=False)
32 cirq_circ = Translation.get_translation(circuit, 'cirq')
33 result = cls.simulator.run(cirq_circ, repetitions=cls.repetitions)
34 return cls._result_to_dist(result)
35
36 @classmethod
37 def _result_to_dist(cls, result) -> dict:
38 return cirq_result_to_probabilities(result)
39
40
[docs]
41class CirqSampler(Sampler):
42 """ Sampler adapter for Cirq """
43
44 def _call(self, circuits: Sequence[int], parameter_values: Sequence[Sequence[float]], **run_options) -> SamplerResult:
45 bound_circuits = []
46 for i, value in zip(circuits, parameter_values):
47 bound_circuits.append(
48 self._circuits[i]
49 if len(value) == 0
50 else self._circuits[i].assign_parameters(dict(zip(self._parameters[i], value)))
51 )
52 distributions = [_CirqRunner.calculate_circuit(circuit) for circuit in bound_circuits]
53 quasi_dists = list(map(QuasiDistribution, distributions))
54 return SamplerResult(quasi_dists, [{} for _ in range(len(parameter_values))])
55
56
[docs]
57class CirqBackend(Backend):
58 """
59
60 Args:
61 Backend (_type_): _description_
62 """
63
64 def __init__(self, name: Literal['local_simulator'] = 'local_simulator'):
65 self.sampler = self.samplerV1 = CirqSampler()
66 self.optimizer = COBYLA()
67 super().__init__(name)
68
69
[docs]
70def cirq_result_to_probabilities(
71 result: cirq.Result,
72 integer_keys: bool = False
73) -> dict:
74 measurements = result.measurements
75
76 sorted_keys = list(measurements.keys())
77
78 bitstrings = []
79 num_shots = len(measurements[sorted_keys[0]])
80
81 for shot_index in range(num_shots):
82 bits = []
83 for key in sorted_keys:
84 bits.extend(str(b) for b in measurements[key][shot_index])
85
86 bitstring = "".join(bits)
87 bitstrings.append(bitstring)
88
89 counts = {}
90 for bs in bitstrings:
91 counts[bs] = counts.get(bs, 0) + 1
92
93 total_shots = sum(counts.values())
94 if integer_keys:
95 prob_dict = {int(k, 2): v / total_shots for k, v in counts.items()}
96 else:
97 prob_dict = {k: v / total_shots for k, v in counts.items()}
98
99 return prob_dict