コード例 #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()
コード例 #2
0
def bicgstab(A,
             b,
             x0=None,
             eps=1e-8,
             maxit=1000,
             eps_round=1e-10,
             ext_info=False):
    """ Solves the system :math:`Ax=b` using the Bi-Conjugate Gradient Stabilized method using Tensor Train format.
    
    :param TTmat A: Tensor train matrix
    :param TTvec b: Right hand side
    
    :param TTvec x0: [default == :py:func:`TensorToolbox.core.zerosvec`] initial guess of solution ``x``
    :param float eps: [default == 1e-8] stop criteria for Bi-CGSTAB iterations
    :param int maxit: [default == 1000] maximum number of iterations for Bi-CGSTAB
    :param float eps_round: [default == 1e-10] accuracy for Tensor Train rounding operations
    :param bool ext_info: [default == False] whehter of not to have additional info returned

    :return: tuple :py:data:`(x,conv,info)`
       
       * :py:data:`x` (TTvec): solution of the linear system if converged or last iterate if not converged
       * :py:data:`conv` (bool): True -> converged, False -> Not converged / Zero Inner Product exeception
       * :py:data:`info` (dict): ``iter`` -> total number of iterations; ``r`` -> last residual in TT format; ``rho`` -> last value of dot(r0,r) must be bigger than np.spacing(1); ``r0v`` -> last value of dot(r0,v) must be bigger than np.spacing(1)
    
    """

    logger = logging.getLogger(__name__)
    logger.propagate = False
    ch = logging.StreamHandler()
    formatter = logging.Formatter(
        "%(asctime)s %(levelname)s:%(name)s: %(message)s", "%Y-%m-%d %H:%M:%S")
    ch.setFormatter(formatter)
    logger.addHandler(ch)

    from TensorToolbox.core import TTvec
    from TensorToolbox.core import zerosvec
    from TensorToolbox.core import TTmat

    if not A.init or not b.init:
        raise NameError(
            "TensorToolbox.multilinalg.cg: TT not initialized correctly")
    if not (isinstance(A, TTmat) and isinstance(b, TTvec)
            and not isinstance(b, TTmat)):
        raise NameError(
            "TensorToolbox.multilinalg.cg: Conjugate gradient not implemented for the input types"
        )

    if x0 == None:
        x0 = zerosvec(len(b.shape()), b.shape())
    elif not isinstance(x0, TTvec) or b.shape() != x0.shape():
        raise NameError(
            "TensorToolbox.multilinalg.cg: Initial guess must be in TT format and have the same shape of b"
        )

    # Bi-CGSTAB init
    x = x0
    i = 0
    r = (b - dot(A, x)).rounding(eps_round)
    r0 = r.copy()
    delta_0 = norm(r0, 2)
    delta_new = delta_0
    rho_old = 1.
    alpha = 1.
    omega = 1.
    v = zerosvec(len(b.shape()), b.shape())
    p = zerosvec(len(b.shape()), b.shape())
    while i < maxit and delta_new > eps**2. * delta_0:
        i += 1

        rho_new = dot(r0, r)

        if np.abs(rho_new) < np.spacing(1):  # Break computations
            conv = False
            if ext_info:
                info = {'iter': i, 'r': r, 'rho': rho_new, 'r0v': r0v}
                return (x, conv, info)
            else:
                return (x, conv)

        beta = (rho_new / rho_old) * (alpha / omega)
        p = r + (p - v * omega) * beta
        p.rounding(eps_round)
        v = dot(A, p).rounding(eps_round)
        r0v = dot(r0, v)

        if np.abs(r0v) < np.spacing(1):  # Break computations
            conv = False
            if ext_info:
                info = {'iter': i, 'r': r, 'rho': rho_new, 'r0v': r0v}
                return (x, conv, info)
            else:
                return (x, conv)

        alpha = rho_new / r0v
        s = r - v * alpha
        s.rounding(eps_round)

        if norm(
                s, 2
        ) <= eps**2. * delta_0:  # Convergence already reached, update and break loop
            x = x + p * alpha
            conv = True
            if ext_info:
                info = {'iter': i, 's': r, 'rho': rho_new, 'r0v': r0v}
                return (x, conv, info)
            else:
                return (x, conv)

        t = dot(A, s).rounding(eps_round)
        omega = dot(t, s) / norm(t, 2)
        x = x + p * alpha + s * omega
        x.rounding(eps_round)
        # The exit was here, but we can postpone it ...
        r = s - t * omega
        r.rounding(eps_round)

        # Update new -> old
        delta_new = norm(r, 2)
        rho_old = rho_new

        logger.info("Bi-CGSTAB: err=%e" % (delta_new))

    conv = (i < maxit)
    if ext_info:
        info = {'iter': i, 'r': r, 'rho': rho_new, 'r0v': r0v}
        return (x, conv, info)
    else:
        return (x, conv)
コード例 #3
0
def gmres(A,
          b,
          x0=None,
          eps=1e-8,
          maxit=1000,
          restart=1000,
          eps_round=1e-10,
          ext_info=False):
    """ Solves the system :math:`Ax=b` using the Generalized Minimum Residual method with Modified Gram-Schmidt iterations using Tensor Train format.
    
    :param TTmat A: Tensor train matrix
    :param TTvec b: Right hand side
    
    :param TTvec x0: [default == :py:func:`TensorToolbox.core.zerosvec`] initial guess of solution ``x``
    :param float eps: [default == 1e-8] stop criteria for GMRES iterations
    :param int maxit: [default == 1000] maximum number of iterations for GMRES
    :param int restart: [default == 1000] restart constant for GMRES (nothing is implemented to retain information, i.e. Hessemberg and Krylov space are reset)
    :param float eps_round: [default == 1e-10] accuracy for Tensor Train rounding operations
    :param bool ext_info: [default == False] whehter of not to have additional info returned

    :return: tuple :py:data:`(x,conv,info)`
       
       * :py:data:`x` (TTvec): solution of the linear system if converged or last iterate if not converged
       * :py:data:`conv` (bool): True -> converged, False -> Not converged / Zero Inner Product exeception
       * :py:data:`info` (dict): ``iter`` -> total number of iterations; ``TT_r`` -> last residual in TT format; ``res`` -> norm of last residual; ``err`` -> residual history per iteration
    
    :note: not optimized for symmetric A
    """

    logger = logging.getLogger(__name__)
    logger.propagate = False
    ch = logging.StreamHandler()
    formatter = logging.Formatter(
        "%(asctime)s %(levelname)s:%(name)s: %(message)s", "%Y-%m-%d %H:%M:%S")
    ch.setFormatter(formatter)
    logger.addHandler(ch)

    from TensorToolbox.core import TTvec, TTmat, zerosvec

    if not A.init or not b.init:
        raise NameError(
            "TensorToolbox.multilinalg.cg: TT not initialized correctly")
    if not (isinstance(A, TTmat) and isinstance(b, TTvec)
            and not isinstance(b, TTmat)):
        raise NameError(
            "TensorToolbox.multilinalg.cg: Conjugate gradient not implemented for the input types"
        )

    if x0 == None:
        x0 = zerosvec(len(b.shape()), b.shape())
    elif not isinstance(x0, TTvec) or b.shape() != x0.shape():
        raise NameError(
            "TensorToolbox.multilinalg.cg: Initial guess must be in TT format and have the same shape of b"
        )

    logger.info("GMRES: Starting")

    # Iterate
    x = x0.copy()
    counter = 0
    j = restart
    err = []
    while counter < maxit:
        if j == restart:
            if counter > 0:
                # Compute y_m: Solve y_m = H^-1 g_m
                y = npla.solve(H[:-1, :], g[:-1])
                # Compute
                for i in range(restart):
                    x += v[i] * y[i]
                    x.rounding(eps_round)

            Q = np.eye(restart + 1)
            H = np.zeros((restart + 1, restart))
            g = np.zeros((restart + 1))
            r = (b - dot(A, x)).rounding(eps_round)
            g[0] = norm(r, 2)  # beta
            v = [r * 1. / g[0]]
            j = 0

        w = dot(A, v[j]).rounding(eps_round)
        for i in range(j + 1):
            H[i, j] = dot(w, v[i])
            w -= v[i] * H[i, j]
            w.rounding(eps_round)
        H[j + 1, j] = norm(w, 2)
        if np.abs(H[j + 1, j]) < np.spacing(1):
            # lucky break
            break
        v.append(w * 1. / H[j + 1, j])

        # Apply old givens rotations to the new column
        H[:j + 2, j] = np.dot(Q[:j + 2, :j + 2], H[:j + 2, j])
        # New Givens rotation
        omega = np.eye((j + 2))
        c = H[j, j] / np.sqrt(H[j, j]**2. + H[j + 1, j]**2.)
        s = H[j + 1, j] / np.sqrt(H[j, j]**2. + H[j + 1, j]**2.)
        omega[j, j] = c
        omega[j + 1, j + 1] = c
        omega[j, j + 1] = s
        omega[j + 1, j] = -s
        # Apply to the Q, H and g
        Q[:j + 2, :j + 2] = np.dot(omega, Q[:j + 2, :j + 2])
        H[:j + 2, :j + 1] = np.dot(omega, H[:j + 2, :j + 1])
        g[j + 1] = -s * g[j]
        g[j] *= c
        err.append(np.abs(g[j + 1]))

        if isinstance(x, TTvec):
            logger.info("GMRES: err=%e ranks=%s" % (err[-1], x.ranks()))
        elif isinstance(x, np.ndarray):
            logger.info("GMRES: err=%e" % (err[-1]))

        if err[-1] < eps:
            # convergent break
            break

        counter += 1
        j += 1

    conv = (counter < maxit)

    # Compute y_j: Solve H y_j = g_j
    y = npla.solve(H[:j + 1, :j + 1], g[:j + 1])
    # Compute solution
    for i in range(j + 1):
        x += v[i] * y[i]
        x.rounding(eps_round)

    r = (b - dot(A, x)).rounding(eps_round)

    logger.info("GMRES: Done ")

    if ext_info:
        info = {'iter': counter, 'TT_r': r, 'res': norm(r, 2), 'err': err}
        return (x, conv, info)
    else:
        return (x, conv)
コード例 #4
0
def cg(A, b, x0=None, eps=1e-8, maxit=1000, eps_round=1e-10, ext_info=False):
    """ Solves the system :math:`Ax=b` using the Conjugate Gradient method in Tensor Train format.
    
    :param TTmat A: Tensor train matrix
    :param TTvec/ndarray b: Right hand side
    
    :param TTvec/ndarray x0: [default == :py:func:`TensorToolbox.core.zerosvec`] initial guess of solution ``x``
    :param float eps: [default == 1e-8] stop criteria for Bi-CGSTAB iterations
    :param int maxit: [default == 1000] maximum number of iterations for Bi-CGSTAB
    :param float eps_round: [default == 1e-10] accuracy for Tensor Train rounding operations
    :param bool ext_info: [default == False] whehter of not to have additional info returned

    :return: tuple :py:data:`(x,conv,info)`
       
       * :py:data:`x` (TTvec): solution of the linear system if converged or last iterate if not converged
       * :py:data:`conv` (bool): True -> converged, False -> Not converged / Zero Inner Product exeception
       * :py:data:`info` (dict): ``iter`` -> total number of iterations; ``r`` -> last residual in TT format; ``res`` -> residual history
    
    """

    logger = logging.getLogger(__name__)
    logger.propagate = False
    ch = logging.StreamHandler()
    formatter = logging.Formatter(
        "%(asctime)s %(levelname)s:%(name)s: %(message)s", "%Y-%m-%d %H:%M:%S")
    ch.setFormatter(formatter)
    logger.addHandler(ch)

    from TensorToolbox.core import TTvec, TTmat, zerosvec

    if isinstance(A, TTmat):
        if not A.init:
            raise NameError(
                "TensorToolbox.multilinalg.cg: TT not initialized correctly")

        if isinstance(b, TTvec) and not isinstance(b, TTmat): is_tt = True
        elif isinstance(b, np.ndarray): is_tt = False
        else:
            raise NameError("TensorToolbox.multilinalg.cg: invalid type of b")

        if is_tt:
            if not b.init:
                raise NameError(
                    "TensorToolbox.multilinalg.cg: TT not initialized correctly"
                )

        if x0 == None:
            if is_tt:
                x0 = zerosvec(len(b.shape()), b.shape())
            else:
                x0 = np.zeros(b.shape)
        else:
            if is_tt:
                if not isinstance(x0, TTvec) or b.shape() != x0.shape():
                    raise NameError(
                        "TensorToolbox.multilinalg.cg: Initial guess must be in TT format and have the same shape of b"
                    )
            else:
                if not isinstance(x0, np.ndarray) or b.shape != x0.shape:
                    raise NameError(
                        "TensorToolbox.multilinalg.cg: Initial guess must be in ndarray format and have the same shape of b"
                    )

        # CG init
        x = x0
        i = 0
        r = (b - dot(A, x))
        if is_tt: r.rounding(eps_round)
        d = r
        res = [dot(r, r)]
        delta_0 = res[-1]
        while i < maxit and res[-1] > eps:  # * delta_0:
            q = dot(A, d)
            if is_tt: q.rounding(eps_round)
            alpha = res[-1] / dot(d, q)
            x += d * alpha
            if is_tt: x.rounding(eps_round)
            if i % 5 == 0:
                r = (b - dot(A, x))
                if is_tt: r.rounding(eps_round)
            else:
                r -= q * alpha
                if is_tt: r.rounding(eps_round)
            delta_old = res[-1]
            res.append(dot(r, r))
            beta = res[-1] / delta_old

            d *= beta
            d += r
            if is_tt: d.rounding(eps_round)

            if isinstance(x, TTvec):
                logger.info("CG: err=%e ranks=%s" % (res[-1], x.ranks()))
            elif isinstance(x, np.ndarray):
                logger.info("CG: err=%e " % (res[-1]))

            i += 1

        conv = (i < maxit)
        if ext_info:
            info = {'iter': i, 'r': r, 'res': res}
            return (x, conv, info)
        else:
            return (x, conv)

    else:
        raise NameError(
            "TensorToolbox.multilinalg.cg: Conjugate gradient not implemented for the input types"
        )