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