1# Copyright 2020 The Cirq Developers 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14from typing import List, Dict, Sequence, Any 15 16import cirq 17import cirq_pasqal 18 19 20class PasqalNoiseModel(cirq.devices.NoiseModel): 21 """A noise model for Pasqal neutral atom device""" 22 23 def __init__(self, device: cirq.devices.Device): 24 self.noise_op_dict = self.get_default_noise_dict() 25 if not isinstance(device, cirq_pasqal.PasqalDevice): 26 raise TypeError( 27 "The noise model varies between Pasqal's devices. " 28 "Please specify the one you intend to execute the " 29 "circuit on." 30 ) 31 self.device = device 32 33 def get_default_noise_dict(self) -> Dict[str, Any]: 34 """Returns the current noise parameters""" 35 default_noise_dict = { 36 str(cirq.ops.YPowGate()): cirq.ops.depolarize(1e-2), 37 str(cirq.ops.ZPowGate()): cirq.ops.depolarize(1e-2), 38 str(cirq.ops.XPowGate()): cirq.ops.depolarize(1e-2), 39 str(cirq.ops.PhasedXPowGate(phase_exponent=0)): cirq.ops.depolarize(1e-2), 40 str(cirq.ops.HPowGate(exponent=1)): cirq.ops.depolarize(1e-2), 41 str(cirq.ops.CNotPowGate(exponent=1)): cirq.ops.depolarize(3e-2), 42 str(cirq.ops.CZPowGate(exponent=1)): cirq.ops.depolarize(3e-2), 43 str(cirq.ops.CCXPowGate(exponent=1)): cirq.ops.depolarize(8e-2), 44 str(cirq.ops.CCZPowGate(exponent=1)): cirq.ops.depolarize(8e-2), 45 } 46 return default_noise_dict 47 48 def noisy_moment( 49 self, moment: cirq.ops.Moment, system_qubits: Sequence[cirq.ops.Qid] 50 ) -> List[cirq.ops.Operation]: 51 """Returns a list of noisy moments. 52 The model includes 53 - Depolarizing noise with gate-dependent strength 54 Args: 55 moment: ideal moment 56 system_qubits: List of qubits 57 Returns: 58 List of ideal and noisy moments 59 """ 60 noise_list = [] 61 for op in moment: 62 op_str = self.get_op_string(op) 63 noise_op = self.noise_op_dict.get(op_str, cirq.ops.depolarize(5e-2)) 64 for qubit in op.qubits: 65 noise_list.append(noise_op.on(qubit)) 66 return list(moment) + noise_list 67 68 # TODO(#3388) Add documentation for Raises. 69 # pylint: disable=missing-raises-doc 70 def get_op_string(self, cirq_op: cirq.ops.Operation) -> str: 71 """Find the string representation for a given operation. 72 73 Args: 74 cirq_op: one cirq operation. 75 76 Returns: 77 String representing the gate operations. 78 """ 79 if not self.device.is_pasqal_device_op(cirq_op) or isinstance( 80 cirq_op.gate, cirq.ops.MeasurementGate 81 ): 82 raise ValueError('Got unknown operation:', cirq_op) 83 84 return str(cirq_op.gate) 85 86 # pylint: enable=missing-raises-doc 87