def _dec_mcg_up_diag(self): """ Call to create a circuit with gates that implement the MCG up to a diagonal gate. Remark: The qubits the gate acts on are ordered in the following way: q=[q_target,q_controls,q_ancilla_zero,q_ancilla_dirty] """ diag = np.ones(2 ** (self.num_controls + 1)).tolist() q = QuantumRegister(self.num_qubits) circuit = QuantumCircuit(q) (q_target, q_controls, q_ancillas_zero, q_ancillas_dirty) = self._define_qubit_role(q) # ToDo: Keep this threshold updated such that the lowest gate count is achieved: # ToDo: we implement the MCG with a UCG up to diagonal if the number of controls is # ToDo: smaller than the threshold. threshold = float("inf") if self.num_controls < threshold: # Implement the MCG as a UCG (up to diagonal) gate_list = [np.eye(2, 2) for i in range(2 ** self.num_controls)] gate_list[-1] = self.params[0] ucg = UCG(gate_list, up_to_diagonal=True) circuit.append(ucg, [q_target] + q_controls) diag = ucg._get_diagonal() # else: # ToDo: Use the best decomposition for MCGs up to diagonal gates here # ToDo: (with all available ancillas) return circuit, diag
def _append_ucg_up_to_diagonal(self, circ, q, single_qubit_gates, control_labels, target_label): (q_input, q_ancillas_for_output, q_ancillas_zero, q_ancillas_dirty) = \ self._define_qubit_role(q) n = int(np.log2(self.params[0].shape[0])) qubits = q_input + q_ancillas_for_output # Note that we have to reverse the control labels, since controls are provided by # increasing qubit number toa UCG by convention control_qubits = _reverse_qubit_oder( _get_qubits_by_label(control_labels, qubits, n)) target_qubit = _get_qubits_by_label([target_label], qubits, n)[0] ucg = UCG(single_qubit_gates, up_to_diagonal=True) circ.append(ucg, [target_qubit] + control_qubits) return ucg._get_diagonal()
def test_ucg(self): """Test uniformly controlled gates.""" for squs, up_to_diagonal in itertools.product(squs_list, up_to_diagonal_list): with self.subTest(single_qubit_unitaries=squs, up_to_diagonal=up_to_diagonal): num_con = int(np.log2(len(squs))) q = QuantumRegister(num_con + 1) qc = QuantumCircuit(q) qc.ucg(squs, q[1:], q[0], up_to_diagonal=up_to_diagonal) # Decompose the gate qc = transpile(qc, basis_gates=['u1', 'u3', 'u2', 'cx', 'id']) # Simulate the decomposed gate simulator = BasicAer.get_backend('unitary_simulator') result = execute(qc, simulator).result() unitary = result.get_unitary(qc) if up_to_diagonal: ucg = UCG(squs, up_to_diagonal=up_to_diagonal) unitary = np.dot(np.diagflat(ucg._get_diagonal()), unitary) unitary_desired = _get_ucg_matrix(squs) self.assertTrue( matrix_equal(unitary_desired, unitary, ignore_phase=True))
def _multiplexed_control(gate, control: Union[AllOneControl, Qubits], target: Qubits): # TODO: Now not considering the order because this is being controlled by # the all 1s sequence. if isinstance(control, Qubits): control = AllOneControl(control) control_qubits = tuple(chain( *(value.qiskit_qubits for value in control.values))) control_patterns_count = 2 ** len(control_qubits) gate_list = [ IdGate().to_matrix() for _ in range(control_patterns_count - 1)] + [gate.to_matrix()] bp.__ALLOCATIONS__[-1].circuit.append( UCG(gate_list, False), (target.qiskit_qubits, ) + control_qubits)