def apply_noise_to_moments( circuit: Circuit, noise: Iterable[Type[Noise]], target_qubits: QubitSet, position: str ) -> Circuit: """ Apply initialization/readout noise to the circuit. When `noise.qubit_count` == 1, `noise` is added to all qubits in `target_qubits`. When `noise.qubit_count` > 1, `noise.qubit_count` must be the same as the length of `target_qubits`. Args: circuit (Circuit): A ciruit where `noise` is applied to. noise (Iterable[Type[Noise]]): Noise channel(s) to be applied to the circuit. target_qubits (QubitSet): Index or indices of qubits. `noise` is applied to. Returns: Circuit: modified circuit. """ noise_instructions = [] for noise_channel in noise: if noise_channel.qubit_count == 1: new = [Instruction(noise_channel, qubit) for qubit in target_qubits] noise_instructions = noise_instructions + new else: noise_instructions.append(Instruction(noise_channel, target_qubits)) new_moments = Moments() if position == "initialization": for noise in noise_instructions: new_moments.add_noise(noise, "initialization_noise") # add existing instructions for moment_key in circuit.moments: instruction = circuit.moments[moment_key] # if the instruction is noise instruction if isinstance(instruction.operator, Noise): new_moments.add_noise(instruction, moment_key.moment_type, moment_key.noise_index) # if the instruction is a gate instruction else: new_moments.add([instruction], moment_key.noise_index) if position == "readout": for noise in noise_instructions: new_moments.add_noise(noise, "readout_noise") circuit._moments = new_moments return circuit
def apply_noise_to_gates( circuit: Circuit, noise: Iterable[Type[Noise]], target_gates: Union[Iterable[Type[Gate]], np.ndarray], target_qubits: QubitSet, ) -> Circuit: """Apply noise after target gates in target qubits. When `noise.qubit_count` == 1, `noise` is applied to target_qubits after `target_gates`. When `noise.qubit_count` > 1, all elements in `target_gates`, if is given, must have the same number of qubits as `noise.qubit_count`. Args: circuit (Circuit): A ciruit where `noise` is applied to. noise (Iterable[Type[Noise]]): Noise channel(s) to be applied to the circuit. target_gates (Union[Iterable[Type[Gate]], np.ndarray]): List of gates, or a unitary matrix which `noise` is applied to. target_qubits (QubitSet): Index or indices of qubits which `noise` is applied to. Returns: Circuit: modified circuit. Raises: Warning: If `noise` is multi-qubit noise while there is no gate with the same number of qubits in `target_qubits` or in the whole circuit when `target_qubits` is not given. If no `target_gates` exist in `target_qubits` or in the whole circuit when `target_qubits` is not given. """ new_moments = Moments() noise_applied = False for moment_key in circuit.moments: instruction = circuit.moments[moment_key] # add the instruction to new_moments if it is noise instruction if isinstance(instruction.operator, Noise): new_moments.add_noise(instruction, moment_key.moment_type, moment_key.noise_index) # if the instruction is a gate instruction else: new_noise_instruction = [] noise_index = moment_key.noise_index if isinstance(target_gates, np.ndarray): if (instruction.operator.name == "Unitary") and ( np.array_equiv(instruction.operator._matrix, target_gates) ): intersection = list(set(instruction.target) & set(target_qubits)) ( new_noise_instruction, noise_index, noise_applied, ) = _apply_noise_to_gates_helper( noise, target_qubits, instruction, noise_index, intersection, noise_applied, new_noise_instruction, ) elif (target_gates is None) or ( instruction.operator.name in [g.__name__ for g in target_gates] ): intersection = list(set(instruction.target) & set(target_qubits)) new_noise_instruction, noise_index, noise_applied = _apply_noise_to_gates_helper( noise, target_qubits, instruction, noise_index, intersection, noise_applied, new_noise_instruction, ) # add the gate and gate noise instructions to new_moments new_moments.add([instruction], noise_index=noise_index) for instruction, noise_index in new_noise_instruction: new_moments.add_noise(instruction, "gate_noise", noise_index) no_noise_applied_warning(noise_applied) circuit._moments = new_moments return circuit