Beispiel #1
0
def QTTzerosvec(d, N, base):
    """ Returns the rank-1 multidimensional vector of zeros in Quantics Tensor Train format
    
    Args:
       d (int): number of dimensions
       N (int or list): If int then uniform sizes are used for all the dimensions, if list of int then len(N) == d and each dimension will use different size
       base (int): QTT base
    
    Returns:
       QTTvec The rank-1 multidim vector of zeros in Tensor Train format
    """
    from TensorToolbox.core import Candecomp
    from TensorToolbox.core import zerosvec

    if isint(N):
        N = [N for i in range(d)]

    for sizedim in N:
        if np.remainder(math.log(sizedim) / math.log(base),
                        1.0) > np.spacing(1):
            raise NameError(
                "TensorToolbox.QTTvec.QTTzerosvec: base is not a valid base of N"
            )

    L = int(np.around(math.log(np.prod(N)) / math.log(base)))

    tt = zerosvec(L, [base for i in range(L)])

    return QTTvec(tt.TT, global_shape=N).build()
def eye(d, N):
    """ Returns the multidimensional identity operator in Tensor Train format
    
    Args:
       d (int): number of dimensions
       N (int or list): If int then uniform sizes are used for all the dimensions, if list of int then len(N) == d and each dimension will use different size
    
    Returns:
       TTmat The multidim identity matrix in Tensor Train format

    Note:
       TODO: improve construction avoiding passage through Candecomp
    """
    from TensorToolbox.core import Candecomp
    if isint(N):
        If = np.eye(N).flatten().reshape((1, N**2))
        CPtmp = [If for i in range(d)]
    elif isinstance(N, list):
        CPtmp = [
            np.eye(N[i]).flatten().reshape((1, N[i]**2)) for i in range(d)
        ]

    CP_id = Candecomp(CPtmp)
    TT_id = TTmat(CP_id, nrows=N, ncols=N, is_sparse=[True] * d).build()
    return TT_id
def randmat(d, nrows, ncols):
    """ Returns the rank-1 multidimensional random matrix in Tensor Train format
    
    Args:
       d (int): number of dimensions
       nrows (int or list): If int then uniform sizes are used for all the dimensions, if list of int then len(nrows) == d and each dimension will use different size
       ncols (int or list): If int then uniform sizes are used for all the dimensions, if list of int then len(ncols) == d and each dimension will use different size
    
    Returns:
       TTmat The rank-1 multidim random matrix in Tensor Train format
    """
    import numpy.random as npr
    from TensorToolbox.core import Candecomp

    if isint(nrows): nrows = [nrows for i in range(d)]
    if isint(ncols): ncols = [ncols for i in range(d)]
    CPtmp = [
        npr.random(nrows[i] * ncols[i]).reshape((1, nrows[i] * ncols[i])) + 0.5
        for i in range(d)
    ]
    CP_rand = Candecomp(CPtmp)
    TT_rand = TTmat(CP_rand, nrows, ncols).build()
    return TT_rand
    def build(self,
              eps=1e-10,
              method='svd',
              rs=None,
              fix_rank=False,
              Jinit=None,
              delta=1e-4,
              maxit=100,
              mv_eps=1e-6,
              mv_maxit=100,
              max_ranks=None,
              kickrank=2):
        """ Common interface for the construction of the approximation.

        :param float eps: [default == 1e-10] For method=='svd': precision with which to approximate the input tensor. For method=='ttcross': TT-rounding tolerance for rank-check.
        :param string method: 'svd' use singular value decomposition to construct the TT representation :cite:`Oseledets2011`, 'ttcross' use low rank skeleton approximation to construct the TT representation :cite:`Oseledets2010`, 'ttdmrg' uses Tensor Train Renormalization Cross to construct the TT representation :cite:`Savostyanov2011,Savostyanov2013`, 'ttdmrgcross' uses 'ttdmrg' with 'ttcross' approximation of supercores
        :param list rs: list of integer ranks of different cores. If ``None`` then the incremental TTcross approach will be used. (method=='ttcross')
        :param bool fix_rank: determines whether the rank is allowed to be increased (method=='ttcross')
        :param list Jinit: list of list of integers containing the r starting columns in the lowrankapprox routine for each core. If ``None`` then pick them randomly. (method=='ttcross')
        :param float delta: accuracy parameter in the TT-cross routine (method=='ttcross'). It is the relative error in Frobenious norm between two successive iterations.
        :param int maxit: maximum number of iterations in the lowrankapprox routine (method=='ttcross')
        :param float mv_eps: accuracy parameter for each usage of the maxvol algorithm (method=='ttcross')
        :param int mv_maxit: maximum number of iterations in the maxvol routine (method=='ttcross')
        :param bool fix_rank: Whether the rank is allowed to increase
        :param list max_ranks: Maximum ranks to be used to limit the trunaction rank due to ``eps``. The first and last elements of the list must be ``1``, e.g. ``[1,...,1]``. Default: ``None``.
        :param int kickrank: rank overshooting for 'ttdmrg'
        """

        nrows = self.full_nrows
        ncols = self.full_ncols

        if isint(nrows) and isint(ncols):
            nrows = [nrows]
            ncols = [ncols]

        if len(nrows) != len(ncols):
            raise NameError(
                "TensorToolbox.QTTmat.__init__: len(nrows)!=len(ncols)")

        self.full_nrows = nrows
        self.full_ncols = ncols

        if isinstance(self.A, np.ndarray):

            for i, sizedim in enumerate(self.A.shape):
                if sizedim != self.full_nrows[i] * self.full_ncols[i]:
                    raise NameError(
                        "TensorToolbox.QTTmat.__init__: Array dimension not consistent with nrows and ncols"
                    )
                if np.remainder(np.log(sizedim) / np.log(self.basemat),
                                1.0) > np.spacing(1):
                    raise NameError(
                        "TensorToolbox.QTTmat.__init__: base is not a valid base of A.size"
                    )

            self.L = int(np.log(self.A.size) / np.log(self.basemat))

            # Prepare interleaved idxs (wtf!!!)
            Ls = [
                int(
                    np.log(self.full_nrows[i] * self.full_ncols[i]) /
                    np.log(self.basemat)) for i in range(self.ndims())
            ]
            idxs = []
            for j in range(self.ndims()):
                offset = np.sum(2 * Ls[:j], dtype=int)
                for i in range(Ls[j]):
                    idxs.append(offset + i)
                    idxs.append(offset + Ls[j] + i)

            # Fold, re-order and reshape
            self.A = np.reshape(self.A, [self.base for i in range(2 * self.L)])
            self.A = np.transpose(self.A, axes=idxs)
            self.A = np.reshape(self.A, [self.basemat for i in range(self.L)])

            super(QTTmat, self).build(eps=eps,
                                      method=method,
                                      rs=rs,
                                      fix_rank=fix_rank,
                                      Jinit=Jinit,
                                      delta=delta,
                                      maxit=maxit,
                                      mv_eps=mv_eps,
                                      mv_maxit=mv_maxit,
                                      max_ranks=max_ranks,
                                      kickrank=kickrank)

        elif isinstance(self.A, list):

            super(QTTmat, self).build(eps=eps,
                                      method=method,
                                      rs=rs,
                                      fix_rank=fix_rank,
                                      Jinit=Jinit,
                                      delta=delta,
                                      maxit=maxit,
                                      mv_eps=mv_eps,
                                      mv_maxit=mv_maxit,
                                      max_ranks=max_ranks,
                                      kickrank=kickrank)

            # Check that unfolded nrows,ncols are consistent with the dimension of A
            if np.prod(self.shape()) != np.prod(self.full_nrows) * np.prod(
                    self.full_ncols):
                self.init = False
                raise NameError(
                    "TensorToolbox.QTTmat.__init__: unfolded nrows,ncols not consistent with shape of A"
                )
            for nrow, ncol in zip(self.full_nrows, self.full_ncols):
                if np.remainder(
                        np.log(nrow * ncol) / np.log(self.basemat),
                        1.0) > np.spacing(1):
                    self.init = False
                    raise NameError(
                        "TensorToolbox.QTTmat.__init__: base is not a valid base for the selected nrows,ncols"
                    )

            self.L = len(self.shape())

        return self
    def build(self,
              eps=1e-10,
              method='svd',
              rs=None,
              fix_rank=False,
              Jinit=None,
              delta=1e-4,
              maxit=100,
              mv_eps=1e-6,
              mv_maxit=100,
              max_ranks=None,
              kickrank=2):
        """ Common interface for the construction of the approximation.

        :param float eps: [default == 1e-10] For method=='svd': precision with which to approximate the input tensor. For method=='ttcross': TT-rounding tolerance for rank-check.
        :param string method: 'svd' use singular value decomposition to construct the TT representation :cite:`Oseledets2011`, 'ttcross' use low rank skeleton approximation to construct the TT representation :cite:`Oseledets2010`, 'ttdmrg' uses Tensor Train Renormalization Cross to construct the TT representation :cite:`Savostyanov2011,Savostyanov2013`, 'ttdmrgcross' uses 'ttdmrg' with 'ttcross' approximation of supercores
        :param list rs: list of integer ranks of different cores. If ``None`` then the incremental TTcross approach will be used. (method=='ttcross')
        :param bool fix_rank: determines whether the rank is allowed to be increased (method=='ttcross')
        :param list Jinit: list of list of integers containing the r starting columns in the lowrankapprox routine for each core. If ``None`` then pick them randomly. (method=='ttcross')
        :param float delta: accuracy parameter in the TT-cross routine (method=='ttcross'). It is the relative error in Frobenious norm between two successive iterations.
        :param int maxit: maximum number of iterations in the lowrankapprox routine (method=='ttcross')
        :param float mv_eps: accuracy parameter for each usage of the maxvol algorithm (method=='ttcross')
        :param int mv_maxit: maximum number of iterations in the maxvol routine (method=='ttcross')
        :param bool fix_rank: Whether the rank is allowed to increase
        :param list max_ranks: Maximum ranks to be used to limit the trunaction rank due to ``eps``. The first and last elements of the list must be ``1``, e.g. ``[1,...,1]``. Default: ``None``.
        :param int kickrank: rank overshooting for 'ttdmrg'
        """

        nrows = self.nrows
        ncols = self.ncols
        is_sparse = self.is_sparse

        self.nrows = []
        self.ncols = []
        self.is_sparse = []
        self.sparse_TT = []

        if isinstance(self.A, list) and np.all(
            [(isinstance(self.A[i], scsp.csr_matrix)
              or isinstance(self.A[i], scsp.csc_matrix)
              or isinstance(self.A[i], scsp.dia_matrix))
             for i in range(len(self.A))]):
            if self.sparse_ranks == None:
                raise AttributeError(
                    "The parameter sparse_ranks must be defined for only-sparse initialization"
                )

            if len(self.sparse_ranks) - 1 != len(self.A):
                raise AttributeError(
                    "The condition len(sparse_ranks)-1 == len(A) must hold.")

            self.sparse_only = True
            self.sparse_TT = self.A

            if isint(nrows) and isin(ncols):
                d = len(self.sparse_TT)
                self.nrows = [nrows for i in range(d)]
                self.ncols = [ncols for i in range(d)]
            elif isinstance(nrows, list) and isinstance(ncols, list):
                self.nrows = nrows
                self.ncols = ncols
            else:
                self.init = False
                raise TypeError(
                    "tensor.TTmat.__init__: types of nrows and ncols are inconsistent."
                )

            self.is_sparse = [True] * len(self.sparse_TT)
            self.TT = [None] * len(self.sparse_TT)

            self.init = True

        elif isinstance(self.A, list) and np.any(
            [(isinstance(self.A[i], scsp.csr_matrix)
              or isinstance(self.A[i], scsp.csc_matrix)
              or isinstance(self.A[i], scsp.dia_matrix))
             for i in range(len(self.A))]):
            raise TypeError(
                "Mixed sparse/full initialization not implemented yet")
        else:
            self.sparse_only = False
            super(TTmat, self).build(eps=eps,
                                     method=method,
                                     rs=rs,
                                     fix_rank=fix_rank,
                                     Jinit=Jinit,
                                     delta=delta,
                                     maxit=maxit,
                                     mv_eps=mv_eps,
                                     mv_maxit=mv_maxit,
                                     max_ranks=max_ranks,
                                     kickrank=kickrank)
            if isint(nrows) and isint(ncols):
                d = len(self.TT)
                self.nrows = [nrows for i in range(d)]
                self.ncols = [ncols for i in range(d)]
            elif isinstance(nrows, list) and isinstance(ncols, list):
                self.nrows = nrows
                self.ncols = ncols
            else:
                self.init = False
                raise TypeError(
                    "tensor.TTmat.__init__: types of nrows and ncols are inconsistent."
                )

            if is_sparse == None:
                self.is_sparse = [False] * len(self.TT)
            elif len(is_sparse) != len(self.TT):
                raise TypeError(
                    "tensor.TTmat.__init__: parameter is_sparse must be of length d=A.ndims."
                )
            else:
                self.is_sparse = is_sparse

            for i, (is_sp, Ai) in enumerate(zip(self.is_sparse, self.TT)):
                if is_sp:
                    Ai_rsh = np.reshape(Ai, (Ai.shape[0], self.nrows[i],
                                             self.ncols[i], Ai.shape[2]))
                    Ai_rsh = np.transpose(Ai_rsh, axes=(0, 3, 1, 2))
                    Ai_rsh = np.reshape(Ai_rsh, (Ai.shape[0] * Ai.shape[2] *
                                                 self.nrows[i], self.ncols[i]))
                    self.sparse_TT.append(scsp.csr_matrix(Ai_rsh))
                else:
                    self.sparse_TT.append(None)

            # Check that all the mode sizes are equal to rows*cols
            for i, msize in enumerate(self.shape()):
                if msize != self.nrows[i] * self.ncols[i]:
                    self.init = False
                    raise NameError(
                        "tensor.TTmat.__init__: the %d-th TT mode size must be equal to nrows[%d]*ncols[%d]"
                        % (i, i, i))

        return self