Ejemplo n.º 1
0
    def get_csd(unitary_mats):
        """
        This function does a CS (cosine-sine) decomposition (by calling the LAPACK function cuncsd.f. The old C++
        Qubiter called zggsvd.f instead) of each unitary matrix in the list of arrays unitary_mats. This function is
        called by the constructor of the class Node and is fundamental for decomposing a unitary matrix into
        multiplexors and diagonal unitaries.

        Parameters
        ----------
        unitary_mats : list(np.ndarray)

        Returns
        -------
        list(np.ndarray), list(np.ndarray), list(np.ndarray)

        """
        block_size = unitary_mats[0].shape[0]
        num_mats = len(unitary_mats)
        for mat in unitary_mats:
            assert mat.shape == (block_size, block_size)
        if block_size == 1:
            left_mats = None
            right_mats = None
            vec = np.array([unitary_mats[k][0, 0] for k in range(0, num_mats)])
            vec1 = vec[0] * np.ones((num_mats, ))
            if np.linalg.norm(vec - vec1) < 1e-6:
                central_mats = None
            else:
                c_vec = np.real(vec)
                s_vec = np.imag(vec)
                central_mats = np.arctan2(s_vec, c_vec)
        else:
            # Henning Dekant constructed a python wrapper for LAPACK's cuncsd.f
            # via the python application f2py. Thanks Henning!

            # In[2]: import cuncsd
            # In[3]: print(cuncsd.cuncsd.__doc__)
            # x11,x12,x21,x22,theta,u1,u2,v1t,v2t,work,rwork,iwork,info =
            # cuncsd(p,x11,x12,x21,x22,lwork,lrwork,
            # [jobu1,jobu2,jobv1t,jobv2t,trans,signs,m,q,
            # ldx11,ldx12,ldx21,ldx22,ldu1,ldu2,ldv1t,ldv2t,credit])
            #
            # Wrapper for ``cuncsd``.
            #
            # Parameters
            # ----------
            # p : input int
            # x11 : input rank-2 array('F') with bounds (p,p)
            # x12 : input rank-2 array('F') with bounds (p,p)
            # x21 : input rank-2 array('F') with bounds (p,p)
            # x22 : input rank-2 array('F') with bounds (p,p)
            # lwork : input int
            # lrwork : input int
            #
            # Other Parameters
            # ----------------
            # jobu1 : input string(len=1), optional
            #     Default: 'Y'
            # jobu2 : input string(len=1), optional
            #     Default: 'Y'
            # jobv1t : input string(len=1), optional
            #     Default: 'Y'
            # jobv2t : input string(len=1), optional
            #     Default: 'Y'
            # trans : input string(len=1), optional
            #     Default: 'T'
            # signs : input string(len=1), optional
            #     Default: 'O'
            # m : input int, optional
            #     Default: 2*p
            # q : input int, optional
            #     Default: p
            # ldx11 : input int, optional
            #     Default: p
            # ldx12 : input int, optional
            #     Default: p
            # ldx21 : input int, optional
            #     Default: p
            # ldx22 : input int, optional
            #     Default: p
            # ldu1 : input int, optional
            #     Default: p
            # ldu2 : input int, optional
            #     Default: p
            # ldv1t : input int, optional
            #     Default: p
            # ldv2t : input int, optional
            #     Default: p
            # credit : input int, optional
            #     Default: 0
            #
            # Returns
            # -------
            # x11 : rank-2 array('F') with bounds (p,p)
            # x12 : rank-2 array('F') with bounds (p,p)
            # x21 : rank-2 array('F') with bounds (p,p)
            # x22 : rank-2 array('F') with bounds (p,p)
            # theta : rank-1 array('f') with bounds (p)
            # u1 : rank-2 array('F') with bounds (p,p)
            # u2 : rank-2 array('F') with bounds (p,p)
            # v1t : rank-2 array('F') with bounds (p,p)
            # v2t : rank-2 array('F') with bounds (p,p)
            # work : rank-1 array('F') with bounds (abs(lwork))
            # rwork : rank-1 array('f') with bounds (abs(lrwork))
            # iwork : rank-1 array('i') with bounds (p)
            # info : int

            left_mats = []
            central_mats = []
            right_mats = []

            for mat in unitary_mats:
                dim = mat.shape[0]
                assert dim % 2 == 0
                hdim = dim >> 1  # half dimension

                p = hdim
                # x11 = np.copy(mat[0:hdim, 0:hdim], 'C')
                # x12 = np.copy(mat[0:hdim, hdim:dim], 'C')
                # x21 = np.copy(mat[hdim:dim, 0:hdim], 'C')
                # x22 = np.copy(mat[hdim:dim, hdim:dim], 'C')

                x11 = mat[0:hdim, 0:hdim]
                x12 = mat[0:hdim, hdim:dim]
                x21 = mat[hdim:dim, 0:hdim]
                x22 = mat[hdim:dim, hdim:dim]

                # print('mat\n', mat)
                # print('x11\n', x11)
                # print('x12\n', x12)
                # print('x21\n', x21)
                # print('x22\n', x22)
                x11, x12, x21, x22, theta, u1, u2, v1t, v2t, \
                work, rwork, iwork, info = \
                    csd.cuncsd(p, x11, x12, x21, x22, lwork=-1, lrwork=-1,
                               trans='F')
                # print('x11\n', x11)
                # print('x12\n', x12)
                # print('x21\n', x21)
                # print('x22\n', x22)

                lw = math.ceil(work[0].real)
                lrw = math.ceil(rwork[0].real)
                # print("work query:", lw)
                # print("rwork query:", lrw)
                x11, x12, x21, x22, theta, u1, u2, v1t, v2t, \
                work, rwork, iwork, info = \
                    csd.cuncsd(p, x11, x12, x21, x22, lwork=lw, lrwork=lrw,
                               trans='F')
                # print('info', info)
                # print('u1 continguous', u1.flags.contiguous)
                # u1 = np.ascontiguousarray(u1)
                # u2 = np.ascontiguousarray(u2)
                # v1t = np.ascontiguousarray(v1t)
                # v2t = np.ascontiguousarray(v2t)
                # print('u1 continguous', u1.flags.contiguous)

                left_mats.append(u1)
                left_mats.append(u2)
                central_mats.append(theta)
                right_mats.append(v1t)
                right_mats.append(v2t)
        return left_mats, central_mats, right_mats
Ejemplo n.º 2
0
    def cs_decomp(unitary_mats):
        """
        This function does a CS (cosine-sine) decomposition (by calling the
        LAPACK function cuncsd.f. The old C++ Qubiter called zggsvd.f
        instead) of each unitary matrix in the list of arrays unitary_mats.
        This function is called by the constructor of the class Node and is
        fundamental for decomposing a unitary matrix into multiplexors and
        diagonal unitaries.

        Parameters
        ----------
        unitary_mats : list(np.ndarray)

        Returns
        -------
        list(np.ndarray), list(np.ndarray), list(np.ndarray)

        """
        block_size = unitary_mats[0].shape[0]
        num_mats = len(unitary_mats)
        for mat in unitary_mats:
            assert mat.shape == (block_size, block_size)
        if block_size == 1:
            left_mats = None
            right_mats = None
            vec = np.array([unitary_mats[k][0, 0]
                            for k in range(0, num_mats)])
            vec1 = vec[0]*np.ones((num_mats,))
            if np.linalg.norm(vec-vec1) < 1e-6:
                central_mats = None
            else:
                c_vec = np.real(vec)
                s_vec = np.imag(vec)
                central_mats = np.arctan2(s_vec, c_vec)
        else:
            # Henning Dekant constructed a python wrapper for LAPACK's cuncsd.f
            # via the python application f2py. Thanks Henning!

            # In[2]: import cuncsd
            # In[3]: print(cuncsd.cuncsd.__doc__)
            # x11,x12,x21,x22,theta,u1,u2,v1t,v2t,work,rwork,iwork,info =
            # cuncsd(p,x11,x12,x21,x22,lwork,lrwork,
            # [jobu1,jobu2,jobv1t,jobv2t,trans,signs,m,q,
            # ldx11,ldx12,ldx21,ldx22,ldu1,ldu2,ldv1t,ldv2t,credit])
            #
            # Wrapper for ``cuncsd``.
            #
            # Parameters
            # ----------
            # p : input int
            # x11 : input rank-2 array('F') with bounds (p,p)
            # x12 : input rank-2 array('F') with bounds (p,p)
            # x21 : input rank-2 array('F') with bounds (p,p)
            # x22 : input rank-2 array('F') with bounds (p,p)
            # lwork : input int
            # lrwork : input int
            #
            # Other Parameters
            # ----------------
            # jobu1 : input string(len=1), optional
            #     Default: 'Y'
            # jobu2 : input string(len=1), optional
            #     Default: 'Y'
            # jobv1t : input string(len=1), optional
            #     Default: 'Y'
            # jobv2t : input string(len=1), optional
            #     Default: 'Y'
            # trans : input string(len=1), optional
            #     Default: 'T'
            # signs : input string(len=1), optional
            #     Default: 'O'
            # m : input int, optional
            #     Default: 2*p
            # q : input int, optional
            #     Default: p
            # ldx11 : input int, optional
            #     Default: p
            # ldx12 : input int, optional
            #     Default: p
            # ldx21 : input int, optional
            #     Default: p
            # ldx22 : input int, optional
            #     Default: p
            # ldu1 : input int, optional
            #     Default: p
            # ldu2 : input int, optional
            #     Default: p
            # ldv1t : input int, optional
            #     Default: p
            # ldv2t : input int, optional
            #     Default: p
            # credit : input int, optional
            #     Default: 0
            #
            # Returns
            # -------
            # x11 : rank-2 array('F') with bounds (p,p)
            # x12 : rank-2 array('F') with bounds (p,p)
            # x21 : rank-2 array('F') with bounds (p,p)
            # x22 : rank-2 array('F') with bounds (p,p)
            # theta : rank-1 array('f') with bounds (p)
            # u1 : rank-2 array('F') with bounds (p,p)
            # u2 : rank-2 array('F') with bounds (p,p)
            # v1t : rank-2 array('F') with bounds (p,p)
            # v2t : rank-2 array('F') with bounds (p,p)
            # work : rank-1 array('F') with bounds (abs(lwork))
            # rwork : rank-1 array('f') with bounds (abs(lrwork))
            # iwork : rank-1 array('i') with bounds (p)
            # info : int

            left_mats = []
            central_mats = []
            right_mats = []

            for mat in unitary_mats:
                dim = mat.shape[0]
                assert dim % 2 == 0
                hdim = dim >> 1  # half dimension

                p = hdim
                # x11 = np.copy(mat[0:hdim, 0:hdim], 'C')
                # x12 = np.copy(mat[0:hdim, hdim:dim], 'C')
                # x21 = np.copy(mat[hdim:dim, 0:hdim], 'C')
                # x22 = np.copy(mat[hdim:dim, hdim:dim], 'C')

                x11 = mat[0:hdim, 0:hdim]
                x12 = mat[0:hdim, hdim:dim]
                x21 = mat[hdim:dim, 0:hdim]
                x22 = mat[hdim:dim, hdim:dim]

                # print('mat\n', mat)
                # print('x11\n', x11)
                # print('x12\n', x12)
                # print('x21\n', x21)
                # print('x22\n', x22)
                x11, x12, x21, x22, theta, u1, u2, v1t, v2t,\
                    work, rwork, iwork, info =\
                        csd.cuncsd(p, x11, x12, x21, x22, lwork=-1, lrwork=-1,
                                      trans='F')
                # print('x11\n', x11)
                # print('x12\n', x12)
                # print('x21\n', x21)
                # print('x22\n', x22)

                lw = math.ceil(work[0].real)
                lrw = math.ceil(rwork[0].real)
                # print("work query:", lw)
                # print("rwork query:", lrw)
                x11, x12, x21, x22, theta, u1, u2, v1t, v2t,\
                    work, rwork, iwork, info =\
                        csd.cuncsd(p, x11, x12, x21, x22, lwork=lw, lrwork=lrw,
                                      trans='F')
                # print('info', info)
                # print('u1 continguous', u1.flags.contiguous)
                # u1 = np.ascontiguousarray(u1)
                # u2 = np.ascontiguousarray(u2)
                # v1t = np.ascontiguousarray(v1t)
                # v2t = np.ascontiguousarray(v2t)
                # print('u1 continguous', u1.flags.contiguous)

                left_mats.append(u1)
                left_mats.append(u2)
                central_mats.append(theta)
                right_mats.append(v1t)
                right_mats.append(v2t)
        return left_mats, central_mats, right_mats