def mcu1(self, theta, control_qubits, target_qubit): """ Apply Multiple-Controlled U1 gate Args: self (QuantumCircuit): The QuantumCircuit object to apply the mcu1 gate on. theta (float): angle theta control_qubits (list of Qubit): The list of control qubits target_qubit (Qubit): The target qubit """ if isinstance(target_qubit, QuantumRegister) and len(target_qubit) == 1: target_qubit = target_qubit[0] temp = [] self._check_qargs(control_qubits) temp += control_qubits self._check_qargs([target_qubit]) temp.append(target_qubit) self._check_dups(temp) n_c = len(control_qubits) if n_c == 1: # cu1 apply_cu1(self, theta, control_qubits[0], target_qubit) else: _apply_mcu1(self, theta, control_qubits, target_qubit)
def _apply_mcu1(circuit, theta, ctls, tgt, global_phase=0): """Apply multi-controlled u1 gate from ctls to tgt with angle theta.""" n = len(ctls) gray_code = list(GrayCode(n).generate_gray()) last_pattern = None theta_angle = theta * (1 / (2**(n - 1))) gp_angle = angle(global_phase) * (1 / (2**(n - 1))) for pattern in gray_code: if '1' not in pattern: continue if last_pattern is None: last_pattern = pattern # find left most set bit lm_pos = list(pattern).index('1') # find changed bit comp = [i != j for i, j in zip(pattern, last_pattern)] if True in comp: pos = comp.index(True) else: pos = None if pos is not None: if pos != lm_pos: circuit.cx(ctls[pos], ctls[lm_pos]) else: indices = [i for i, x in enumerate(pattern) if x == '1'] for idx in indices[1:]: circuit.cx(ctls[idx], ctls[lm_pos]) # check parity if pattern.count('1') % 2 == 0: # inverse apply_cu1(circuit, -theta_angle, ctls[lm_pos], tgt) if global_phase: circuit.u1(-gp_angle, ctls[lm_pos]) else: apply_cu1(circuit, theta_angle, ctls[lm_pos], tgt) if global_phase: circuit.u1(gp_angle, ctls[lm_pos]) last_pattern = pattern