def _observable_to_instruction(observable: Observable, target_list: List[int]): return [ Instruction(gate, target_list) for gate in observable.basis_rotation_gates ]
def test_apply_multipe_noise_1QubitNoise_2(circuit_2qubit, noise_1qubit, noise_1qubit_2): circ = circuit_2qubit.apply_gate_noise(noise_1qubit, target_gates=[Gate.X],).apply_gate_noise( noise_1qubit_2, target_qubits=[0], ) expected = ( Circuit() .add_instruction(Instruction(Gate.X(), 0)) .add_instruction(Instruction(noise_1qubit_2, 0)) .add_instruction(Instruction(noise_1qubit, 0)) .add_instruction(Instruction(Gate.Y(), 1)) .add_instruction(Instruction(Gate.X(), 0)) .add_instruction(Instruction(noise_1qubit_2, 0)) .add_instruction(Instruction(noise_1qubit, 0)) .add_instruction(Instruction(Gate.X(), 1)) .add_instruction(Instruction(noise_1qubit, 1)) .add_instruction(Instruction(Gate.CNot(), [0, 1])) .add_instruction(Instruction(noise_1qubit_2, 0)) ) assert circ == expected
def add_instruction( self, instruction: Instruction, target: QubitSetInput = None, target_mapping: Dict[QubitInput, QubitInput] = {}, ) -> Circuit: """ Add an instruction to `self`, returns `self` for chaining ability. Args: instruction (Instruction): `Instruction` to add into `self`. target (int, Qubit, or iterable of int / Qubit, optional): Target qubits for the `instruction`. If a single qubit gate, an instruction is created for every index in `target`. Default = `None`. target_mapping (dictionary[int or Qubit, int or Qubit], optional): A dictionary of qubit mappings to apply to the `instruction.target`. Key is the qubit in `instruction.target` and the value is what the key will be changed to. Default = `{}`. Returns: Circuit: self Raises: TypeError: If both `target_mapping` and `target` are supplied. Examples: >>> instr = Instruction(Gate.CNot(), [0, 1]) >>> circ = Circuit().add_instruction(instr) >>> print(circ.instructions[0]) Instruction('operator': 'CNOT', 'target': QubitSet(Qubit(0), Qubit(1))) >>> instr = Instruction(Gate.CNot(), [0, 1]) >>> circ = Circuit().add_instruction(instr, target_mapping={0: 10, 1: 11}) >>> print(circ.instructions[0]) Instruction('operator': 'CNOT', 'target': QubitSet(Qubit(10), Qubit(11))) >>> instr = Instruction(Gate.CNot(), [0, 1]) >>> circ = Circuit().add_instruction(instr, target=[10, 11]) >>> print(circ.instructions[0]) Instruction('operator': 'CNOT', 'target': QubitSet(Qubit(10), Qubit(11))) >>> instr = Instruction(Gate.H(), 0) >>> circ = Circuit().add_instruction(instr, target=[10, 11]) >>> print(circ.instructions[0]) Instruction('operator': 'H', 'target': QubitSet(Qubit(10),)) >>> print(circ.instructions[1]) Instruction('operator': 'H', 'target': QubitSet(Qubit(11),)) """ if target_mapping and target is not None: raise TypeError( "Only one of 'target_mapping' or 'target' can be supplied.") if not target_mapping and not target: # Nothing has been supplied, add instruction instructions_to_add = [instruction] elif target_mapping: # Target mapping has been supplied, copy instruction instructions_to_add = [ instruction.copy(target_mapping=target_mapping) ] elif hasattr(instruction.operator, "qubit_count") and instruction.operator.qubit_count == 1: # single qubit operator with target, add an instruction for each target instructions_to_add = [ instruction.copy(target=qubit) for qubit in target ] else: # non single qubit operator with target, add instruction with target instructions_to_add = [instruction.copy(target=target)] self._moments.add(instructions_to_add) return self
def test_apply_noise_to_gates_2QubitNoise_2( circuit_3qubit, noise_2qubit, noise_1qubit, noise_1qubit_2 ): circ = apply_noise_to_gates( circuit_3qubit, [noise_1qubit, noise_2qubit, noise_1qubit_2], target_gates=[Gate.CZ], target_qubits=QubitSet([1, 2]), ) expected = ( Circuit() .add_instruction(Instruction(Gate.X(), 0)) .add_instruction(Instruction(Gate.Y(), 1)) .add_instruction(Instruction(Gate.CNot(), [0, 1])) .add_instruction(Instruction(Gate.Z(), 2)) .add_instruction(Instruction(Gate.CZ(), [2, 1])) .add_instruction(Instruction(noise_1qubit, 1)) .add_instruction(Instruction(noise_1qubit, 2)) .add_instruction(Instruction(noise_2qubit, [2, 1])) .add_instruction(Instruction(noise_1qubit_2, 1)) .add_instruction(Instruction(noise_1qubit_2, 2)) .add_instruction(Instruction(Gate.CNot(), [0, 2])) .add_instruction(Instruction(Gate.CZ(), [1, 2])) .add_instruction(Instruction(noise_1qubit, 1)) .add_instruction(Instruction(noise_1qubit, 2)) .add_instruction(Instruction(noise_2qubit, [1, 2])) .add_instruction(Instruction(noise_1qubit_2, 1)) .add_instruction(Instruction(noise_1qubit_2, 2)) ) assert circ == expected
def add_verbatim_box( self, verbatim_circuit: Circuit, target: QubitSetInput = None, target_mapping: Dict[QubitInput, QubitInput] = None, ) -> Circuit: """ Add a verbatim `circuit` to self, that is, ensures that `circuit` is not modified in any way by the compiler. Args: verbatim_circuit (Circuit): Circuit to add into self. target (int, Qubit, or iterable of int / Qubit, optional): Target qubits for the supplied circuit. This is a macro over `target_mapping`; `target` is converted to a `target_mapping` by zipping together a sorted `circuit.qubits` and `target`. Default = `None`. target_mapping (dictionary[int or Qubit, int or Qubit], optional): A dictionary of qubit mappings to apply to the qubits of `circuit.instructions`. Key is the qubit to map, and the value is what to change it to. Default = `None`. Returns: Circuit: self Raises: TypeError: If both `target_mapping` and `target` are supplied. ValueError: If `circuit` has result types attached Examples: >>> widget = Circuit().h(0).h(1) >>> circ = Circuit().add_verbatim_box(widget) >>> print(list(circ.instructions)) [Instruction('operator': StartVerbatimBox, 'target': QubitSet([])), Instruction('operator': H('qubit_count': 1), 'target': QubitSet([Qubit(0)])), Instruction('operator': H('qubit_count': 1), 'target': QubitSet([Qubit(1)])), Instruction('operator': EndVerbatimBox, 'target': QubitSet([]))] >>> widget = Circuit().h(0).cnot(0, 1) >>> circ = Circuit().add_verbatim_box(widget, target_mapping={0: 10, 1: 11}) >>> print(list(circ.instructions)) [Instruction('operator': StartVerbatimBox, 'target': QubitSet([])), Instruction('operator': H('qubit_count': 1), 'target': QubitSet([Qubit(10)])), Instruction('operator': H('qubit_count': 1), 'target': QubitSet([Qubit(11)])), Instruction('operator': EndVerbatimBox, 'target': QubitSet([]))] >>> widget = Circuit().h(0).cnot(0, 1) >>> circ = Circuit().add_verbatim_box(widget, target=[10, 11]) >>> print(list(circ.instructions)) [Instruction('operator': StartVerbatimBox, 'target': QubitSet([])), Instruction('operator': H('qubit_count': 1), 'target': QubitSet([Qubit(10)])), Instruction('operator': H('qubit_count': 1), 'target': QubitSet([Qubit(11)])), Instruction('operator': EndVerbatimBox, 'target': QubitSet([]))] """ if target_mapping and target is not None: raise TypeError("Only one of 'target_mapping' or 'target' can be supplied.") elif target is not None: keys = sorted(verbatim_circuit.qubits) values = target target_mapping = dict(zip(keys, values)) if verbatim_circuit.result_types: raise ValueError("Verbatim subcircuit is not measured and cannot have result types") if verbatim_circuit.instructions: self.add_instruction(Instruction(compiler_directives.StartVerbatimBox())) for instruction in verbatim_circuit.instructions: self.add_instruction(instruction, target_mapping=target_mapping) self.add_instruction(Instruction(compiler_directives.EndVerbatimBox())) self._has_compiler_directives = True return self