def cry(self, theta, q_control, q_target): """ Apply Controlled-RY (cry) Gate. Args: self (QuantumCircuit): The circuit to apply the ch gate on. theta (float): The rotation angle. q_control ((QuantumRegister, int)): The control qubit. q_target ((QuantumRegister, int)): The target qubit. """ if not is_qubit(q_control): raise AquaError('A qubit is expected for the control.') if not self.has_register(q_control[0]): raise AquaError('The control qubit is expected to be part of the circuit.') if not is_qubit(q_target): raise AquaError('A qubit is expected for the target.') if not self.has_register(q_target[0]): raise AquaError('The target qubit is expected to be part of the circuit.') if q_control == q_target: raise AquaError('The control and target need to be different qubits.') self.u3(theta / 2, 0, 0, q_target) self.cx(q_control, q_target) self.u3(-theta / 2, 0, 0, q_target) self.cx(q_control, q_target) return self
def ch(self, q_control, q_target): """ Apply Controlled-Hadamard (ch) Gate. Note that this implementation of the ch uses a single cx gate, which is more efficient than what's currently provided in Terra. Args: self (QuantumCircuit): The circuit to apply the ch gate on. q_control ((QuantumRegister, int)): The control qubit. q_target ((QuantumRegister, int)): The target qubit. """ if not is_qubit(q_control): raise AquaError('A qubit is expected for the control.') if not self.has_register(q_control[0]): raise AquaError( 'The control qubit is expected to be part of the circuit.') if not is_qubit(q_target): raise AquaError('A qubit is expected for the target.') if not self.has_register(q_target[0]): raise AquaError( 'The target qubit is expected to be part of the circuit.') if q_control == q_target: raise AquaError('The control and target need to be different qubits.') self.u3(-7 / 4 * pi, 0, 0, q_target) self.cx(q_control, q_target) self.u3(7 / 4 * pi, 0, 0, q_target) return self
def rcccx(self, q_control_1, q_control_2, q_control_3, q_target): """ Apply 3-Control Relative-Phase Toffoli gate from q_control_1, q_control_2, and q_control_3 to q_target. The implementation is based on https://arxiv.org/pdf/1508.03273.pdf Figure 4 Args: self (QuantumCircuit): The QuantumCircuit object to apply the rcccx gate on. q_control_1 (tuple(QuantumRegister, int)): The 1st control qubit. q_control_2 (tuple(QuantumRegister, int)): The 2nd control qubit. q_control_3 (tuple(QuantumRegister, int)): The 3rd control qubit. q_target (tuple(QuantumRegister, int)): The target qubit. """ if not is_qubit(q_control_1): raise AquaError('A qubit is expected for the first control.') if not self.has_register(q_control_1[0]): raise AquaError( 'The first control qubit is expected to be part of the circuit.') if not is_qubit(q_control_2): raise AquaError('A qubit is expected for the second control.') if not self.has_register(q_control_2[0]): raise AquaError( 'The second control qubit is expected to be part of the circuit.') if not is_qubit(q_target): raise AquaError('A qubit is expected for the target.') if not self.has_register(q_target[0]): raise AquaError( 'The target qubit is expected to be part of the circuit.') self._check_dups([q_control_1, q_control_2, q_control_3, q_target]) _apply_rcccx(self, q_control_1, q_control_2, q_control_3, q_target)
def mct(self, q_controls, q_target, q_ancilla, mode='basic'): """ Apply Multiple-Control Toffoli operation Args: q_controls: The list of control qubits q_target: The target qubit q_ancilla: The list of ancillary qubits mode (string): The implementation mode to use """ if len(q_controls) == 1: # cx self.cx(q_controls[0], q_target) elif len(q_controls) == 2: # ccx self.ccx(q_controls[0], q_controls[1], q_target) else: # check controls if isinstance(q_controls, QuantumRegister): control_qubits = [qb for qb in q_controls] elif isinstance(q_controls, list): control_qubits = q_controls else: raise AquaError( 'MCT needs a list of qubits or a quantum register for controls.' ) # check target if is_qubit(q_target): target_qubit = q_target else: raise AquaError('MCT needs a single qubit as target.') # check ancilla if q_ancilla is None: ancillary_qubits = [] elif isinstance(q_ancilla, QuantumRegister): ancillary_qubits = [qb for qb in q_ancilla] elif isinstance(q_ancilla, list): ancillary_qubits = q_ancilla else: raise AquaError( 'MCT needs None or a list of qubits or a quantum register for ancilla.' ) all_qubits = control_qubits + [target_qubit] + ancillary_qubits self._check_qargs(all_qubits) self._check_dups(all_qubits) if mode == 'basic': _ccx_v_chain(self, control_qubits, target_qubit, ancillary_qubits) elif mode == 'advanced': _multicx(self, [*control_qubits, target_qubit], ancillary_qubits[0] if ancillary_qubits else None) elif mode == 'noancilla': _multicx_noancilla(self, [*control_qubits, target_qubit]) else: raise AquaError( 'Unrecognized mode for building MCT circuit: {}.'.format(mode))
def mcry(self, theta, q_controls, q_target, q_ancillae): """ Apply Multiple-Control RY (mcry) Gate. Args: self (QuantumCircuit): The circuit to apply the ch gate on. theta (float): The rotation angle. q_controls (QuantumRegister | (QuantumRegister, int)): The control qubits. q_target ((QuantumRegister, int)): The target qubit. q_ancillae (QuantumRegister | (QuantumRegister, int)): The ancillary qubits. """ # check controls if isinstance(q_controls, QuantumRegister): control_qubits = [qb for qb in q_controls] elif isinstance(q_controls, list): control_qubits = q_controls else: raise AquaError( 'The mcry gate needs a list of qubits or a quantum register for controls.' ) # check target if is_qubit(q_target): target_qubit = q_target else: raise AquaError('The mcry gate needs a single qubit as target.') # check ancilla if q_ancillae is None: ancillary_qubits = [] elif isinstance(q_ancillae, QuantumRegister): ancillary_qubits = [qb for qb in q_ancillae] elif isinstance(q_ancillae, list): ancillary_qubits = q_ancillae else: raise AquaError( 'The mcry gate needs None or a list of qubits or a quantum register for ancilla.' ) all_qubits = control_qubits + [target_qubit] + ancillary_qubits self._check_qargs(all_qubits) self._check_dups(all_qubits) self.u3(theta / 2, 0, 0, q_target) self.mct(q_controls, q_target, q_ancillae) self.u3(-theta / 2, 0, 0, q_target) self.mct(q_controls, q_target, q_ancillae) return self