Source code for qlauncher.routines.cirq

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