def test_multi_control_u1(self):
        """Test the matrix representation of the controlled and controlled-controlled U1 gate."""
        import qiskit.circuit.library.standard_gates.u1 as u1

        num_ctrl = 3
        # U1 gate params
        theta = 0.2

        # cnu1 gate
        u1gate = u1.U1Gate(theta)
        cnu1 = u1gate.control(num_ctrl)
        width = cnu1.num_qubits
        qr = QuantumRegister(width)
        qcnu1 = QuantumCircuit(qr)
        qcnu1.append(cnu1, qr, [])

        # U1 gate
        qu1 = QuantumCircuit(1)
        qu1.u1(theta, 0)

        # CU1 gate
        qcu1 = QuantumCircuit(2)
        qcu1.cu1(theta, 0, 1)

        # c-cu1 gate
        width = 3
        qr = QuantumRegister(width)
        qc_cu1 = QuantumCircuit(qr)
        cu1gate = u1.CU1Gate(theta)
        c_cu1 = cu1gate.control(1)
        qc_cu1.append(c_cu1, qr, [])

        job = execute([qcnu1, qu1, qcu1, qc_cu1], BasicAer.get_backend('unitary_simulator'),
                      basis_gates=['u1', 'u2', 'u3', 'id', 'cx'])
        result = job.result()

        # Circuit unitaries
        mat_cnu1 = result.get_unitary(0)
        # trace out ancillae

        mat_u1 = result.get_unitary(1)
        mat_cu1 = result.get_unitary(2)
        mat_c_cu1 = result.get_unitary(3)

        # Target Controlled-U1 unitary
        target_cnu1 = _compute_control_matrix(mat_u1, num_ctrl)
        target_cu1 = np.kron(mat_u1, np.diag([0, 1])) + np.kron(np.eye(2), np.diag([1, 0]))
        target_c_cu1 = np.kron(mat_cu1, np.diag([0, 1])) + np.kron(np.eye(4), np.diag([1, 0]))

        tests = [('check unitary of u1.control against tensored unitary of u1',
                  target_cu1, mat_cu1),
                 ('check unitary of cu1.control against tensored unitary of cu1',
                  target_c_cu1, mat_c_cu1),
                 ('check unitary of cnu1 against tensored unitary of u1',
                  target_cnu1, mat_cnu1)]
        for itest in tests:
            info, target, decomp = itest[0], itest[1], itest[2]
            with self.subTest(i=info):
                self.log.info(info)
                self.assertTrue(matrix_equal(target, decomp, ignore_phase=True))
class TestSingleControlledRotationGates(QiskitTestCase):
    """Test the controlled rotation gates controlled on one qubit."""
    import qiskit.circuit.library.standard_gates.u1 as u1
    import qiskit.circuit.library.standard_gates.rx as rx
    import qiskit.circuit.library.standard_gates.ry as ry
    import qiskit.circuit.library.standard_gates.rz as rz

    num_ctrl = 2
    num_target = 1

    theta = pi / 2
    gu1 = u1.U1Gate(theta)
    grx = rx.RXGate(theta)
    gry = ry.RYGate(theta)
    grz = rz.RZGate(theta)

    ugu1 = ac._unroll_gate(gu1, ['u1', 'u3', 'cx'])
    ugrx = ac._unroll_gate(grx, ['u1', 'u3', 'cx'])
    ugry = ac._unroll_gate(gry, ['u1', 'u3', 'cx'])
    ugrz = ac._unroll_gate(grz, ['u1', 'u3', 'cx'])
    ugrz.params = grz.params

    cgu1 = ugu1.control(num_ctrl)
    cgrx = ugrx.control(num_ctrl)
    cgry = ugry.control(num_ctrl)
    cgrz = ugrz.control(num_ctrl)

    @data((gu1, cgu1), (grx, cgrx), (gry, cgry), (grz, cgrz))
    @unpack
    def test_single_controlled_rotation_gates(self, gate, cgate):
        """Test the controlled rotation gates controlled on one qubit."""
        if gate.name == 'rz':
            iden = Operator.from_label('I')
            zgen = Operator.from_label('Z')
            op_mat = (np.cos(0.5 * self.theta) * iden -
                      1j * np.sin(0.5 * self.theta) * zgen).data
        else:
            op_mat = Operator(gate).data
        ref_mat = Operator(cgate).data
        cop_mat = _compute_control_matrix(op_mat, self.num_ctrl)
        self.assertTrue(matrix_equal(cop_mat, ref_mat, ignore_phase=True))
        cqc = QuantumCircuit(self.num_ctrl + self.num_target)
        cqc.append(cgate, cqc.qregs[0])
        dag = circuit_to_dag(cqc)
        unroller = Unroller(['u3', 'cx'])
        uqc = dag_to_circuit(unroller.run(dag))
        self.log.info('%s gate count: %d', cgate.name, uqc.size())
        self.log.info('\n%s', str(uqc))
        # these limits could be changed
        if gate.name == 'ry':
            self.assertTrue(uqc.size() <= 32)
        elif gate.name == 'rz':
            self.assertTrue(uqc.size() <= 40)
        else:
            self.assertTrue(uqc.size() <= 20)

    def test_composite(self):
        """Test composite gate count."""
        qreg = QuantumRegister(self.num_ctrl + self.num_target)
        qc = QuantumCircuit(qreg, name='composite')
        qc.append(self.grx.control(self.num_ctrl), qreg)
        qc.append(self.gry.control(self.num_ctrl), qreg)
        qc.append(self.gry, qreg[0:self.gry.num_qubits])
        qc.append(self.grz.control(self.num_ctrl), qreg)

        dag = circuit_to_dag(qc)
        unroller = Unroller(['u3', 'cx'])
        uqc = dag_to_circuit(unroller.run(dag))
        self.log.info('%s gate count: %d', uqc.name, uqc.size())
        self.assertTrue(uqc.size() <= 93)  # this limit could be changed