Exemplo n.º 1
0
    def log_likelihood(self, p):
        r"""Returns the log of the likelihood for the stored data given
        parameters ``p``.  The likelihood is computed in time
        proportional to :math:`\mathcal{O}(N)`, where :math:`N` is the
        number of data samples.

        """
        p = self.to_params(p)

        alphas, betas = self._alphas_betas(p)
        bc = self._banded_covariance(p)

        ys = self.ys.copy() - p['mu']
        ys[1:] = ys[1:] - alphas*ys[0:-1]

        dts = self.ts.reshape((-1, 1)) - self.ts.reshape((1, -1))
        tau = np.exp(p['lntau'])
        nu = self._inv_logit(p['logitnu'])
        sigma = np.exp(p['lnsigma'])
        full_cov = sigma*sigma*((1-nu)*np.exp(-np.abs(dts)/tau) + nu)

        llow = sl.cholesky_banded(bc, lower=True)

        logdet = np.sum(np.log(llow[0, :]))

        return -0.5*self.ts.shape[0]*np.log(2.0*np.pi) - logdet - 0.5*np.dot(ys, sl.cho_solve_banded((llow, True), ys))
    def posterior_cov(self):
        r"""
        Posterior covariance of the states conditional on the data

        Notes
        -----
        **Warning**: the matrix computed when accessing this property can be
        extremely large: it is shaped `(nobs * k_states, nobs * k_states)`. In
        most cases, it is better to use the `posterior_cov_inv_chol_sparse`
        property if possible, which holds in sparse diagonal banded storage
        the Cholesky factor of the inverse of the posterior covariance matrix.

        .. math::

            Var[\alpha \mid Y^n ]

        This posterior covariance matrix is *not* identical to the
        `smoothed_state_cov` attribute produced by the Kalman smoother, because
        it additionally contains all cross-covariance terms. Instead,
        `smoothed_state_cov` contains the `(k_states, k_states)` block
        diagonal entries of this posterior covariance matrix.
        """
        if self._posterior_cov is None:
            from scipy.linalg import cho_solve_banded
            inv_chol = self.posterior_cov_inv_chol_sparse
            self._posterior_cov = cho_solve_banded((inv_chol, True),
                                                   np.eye(inv_chol.shape[1]))
        return self._posterior_cov
Exemplo n.º 3
0
def cholesky_solve(a, bb):
    """Solve the equation :math:`A x = b` where `a` is a *lower*
    Cholesky-banded matrix.

    In the :class:`~pydl.pydlutils.bspline.Bspline` machinery, `a` needs to
    be padded.  This function should only used with the output of
    :func:`~pydl.pydlutils.bspline.cholesky_band`, to ensure the proper
    padding on `a`.  Otherwise the computation is delegated to
    :func:`scipy.linalg.cho_solve_banded`.

    Parameters
    ----------
    a : :class:`numpy.ndarray`
        *Lower* Cholesky decomposition of :math:`A` in :math:`A x = b`.
    bb : :class:`numpy.ndarray`
        :math:`b` in :math:`A x = b`.

    Returns
    -------
    :class:`numpy.ndarray`
        The solution, padded to be the same shape as `bb`.
    """
    bw = a.shape[0]
    n = bb.shape[0] - bw
    x = np.zeros(bb.shape, dtype=bb.dtype)
    x[0:n] = cho_solve_banded((a[:, 0:n], True), bb[0:n])
    return x
Exemplo n.º 4
0
 def _step(self):
     self.x = cho_solve_banded(
         (self.c, False),
         self.y + sum(self.ρ[i] * self.D[i].T @ (self.α[i] + self.u[i])
                      for i in range(self.r)),
         check_finite=False,
     )
     for i in range(self.r):
         Dx = self.D[i] @ self.x
         for j in range(self.x.shape[1]):
             self.α[i][:, j] = ptv.tv1_1d(Dx[:, j] - self.u[i][:, j],
                                          self.λ[i] / self.ρ[i])
         self.u[i] += self.α[i] - Dx
Exemplo n.º 5
0
    def test_lower_real(self):
        # Symmetric positive definite banded matrix `a`
        a = array([[4.0, 1.0, 0.0, 0.0], [1.0, 4.0, 0.5, 0.0], [0.0, 0.5, 4.0, 0.2], [0.0, 0.0, 0.2, 4.0]])
        # Banded storage form of `a`.
        ab = array([[4.0, 4.0, 4.0, 4.0], [1.0, 0.5, 0.2, -1.0]])
        c = cholesky_banded(ab, lower=True)
        lfac = zeros_like(a)
        lfac[list(range(4)), list(range(4))] = c[0]
        lfac[(1, 2, 3), (0, 1, 2)] = c[1, :3]
        assert_array_almost_equal(a, dot(lfac, lfac.T))

        b = array([0.0, 0.5, 4.2, 4.2])
        x = cho_solve_banded((c, True), b)
        assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
Exemplo n.º 6
0
    def test_lower_complex(self):
        # Hermitian positive definite banded matrix `a`
        a = array([[4.0, 1.0, 0.0, 0.0], [1.0, 4.0, 0.5, 0.0], [0.0, 0.5, 4.0, -0.2j], [0.0, 0.0, 0.2j, 4.0]])
        # Banded storage form of `a`.
        ab = array([[4.0, 4.0, 4.0, 4.0], [1.0, 0.5, 0.2j, -1.0]])
        c = cholesky_banded(ab, lower=True)
        lfac = zeros_like(a)
        lfac[list(range(4)), list(range(4))] = c[0]
        lfac[(1, 2, 3), (0, 1, 2)] = c[1, :3]
        assert_array_almost_equal(a, dot(lfac, lfac.conj().T))

        b = array([0.0, 0.5j, 3.8j, 3.8])
        x = cho_solve_banded((c, True), b)
        assert_array_almost_equal(x, [0.0, 0.0, 1.0j, 1.0])
Exemplo n.º 7
0
    def Binvprod(self, x):
        """Computes the product B^(-1) * x via the Cholesky factor.

        Using the band Cholesky factorization of B, the matrix-vector
        product y is computed using scipy.linalg.cho_solve_banded to
        solve B * y = x.

        Argument:
            x: Vector to multiply.

        Returns:
            Matrix-vector product B^(-1) * x.
        """
        return la.cho_solve_banded((self.sqrtBdata, True), x)
Exemplo n.º 8
0
    def test_upper_real(self):
        # Symmetric positive definite banded matrix `a`
        a = array([[4.0, 1.0, 0.0, 0.0], [1.0, 4.0, 0.5, 0.0], [0.0, 0.5, 4.0, 0.2], [0.0, 0.0, 0.2, 4.0]])
        # Banded storage form of `a`.
        ab = array([[-1.0, 1.0, 0.5, 0.2], [4.0, 4.0, 4.0, 4.0]])
        c = cholesky_banded(ab, lower=False)
        ufac = zeros_like(a)
        ufac[list(range(4)), list(range(4))] = c[-1]
        ufac[(0, 1, 2), (1, 2, 3)] = c[0, 1:]
        assert_array_almost_equal(a, dot(ufac.T, ufac))

        b = array([0.0, 0.5, 4.2, 4.2])
        x = cho_solve_banded((c, False), b)
        assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
Exemplo n.º 9
0
    def test_lower_complex(self):
        # Hermitian positive definite banded matrix `a`
        a = array([[4.0, 1.0, 0.0, 0.0], [1.0, 4.0, 0.5, 0.0],
                   [0.0, 0.5, 4.0, -0.2j], [0.0, 0.0, 0.2j, 4.0]])
        # Banded storage form of `a`.
        ab = array([[4.0, 4.0, 4.0, 4.0], [1.0, 0.5, 0.2j, -1.0]])
        c = cholesky_banded(ab, lower=True)
        lfac = zeros_like(a)
        lfac[list(range(4)), list(range(4))] = c[0]
        lfac[(1, 2, 3), (0, 1, 2)] = c[1, :3]
        assert_array_almost_equal(a, dot(lfac, lfac.conj().T))

        b = array([0.0, 0.5j, 3.8j, 3.8])
        x = cho_solve_banded((c, True), b)
        assert_array_almost_equal(x, [0.0, 0.0, 1.0j, 1.0])
Exemplo n.º 10
0
    def test_upper_complex(self):
        # Hermitian positive definite banded matrix `a`
        a = array([[4.0, 1.0, 0.0, 0.0], [1.0, 4.0, 0.5, 0.0],
                   [0.0, 0.5, 4.0, -0.2j], [0.0, 0.0, 0.2j, 4.0]])
        # Banded storage form of `a`.
        ab = array([[-1.0, 1.0, 0.5, -0.2j], [4.0, 4.0, 4.0, 4.0]])
        c = cholesky_banded(ab, lower=False)
        ufac = zeros_like(a)
        ufac[range(4), range(4)] = c[-1]
        ufac[(0, 1, 2), (1, 2, 3)] = c[0, 1:]
        assert_array_almost_equal(a, dot(ufac.conj().T, ufac))

        b = array([0.0, 0.5, 4.0 - 0.2j, 0.2j + 4.0])
        x = cho_solve_banded((c, False), b)
        assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
Exemplo n.º 11
0
    def Qinvprod(self, x, i):
        """Product of the inverse of Q[i] with a vector x.

        The model error covariance matrix Q[i] is assumed to be a
        band matrix accessible from sqrtQdata[i], which is stored in
        lower form.

        Arguments:
            x: The vector to multiply.
            i: Index indicating which model error covariance to use.

        Returns:
            Product of the inverse of Q[i] with x.
        """
        return la.cho_solve_banded((self.sqrtQdata[i], True), x)
Exemplo n.º 12
0
    def test_upper_real(self):
        # Symmetric positive definite banded matrix `a`
        a = array([[4.0, 1.0, 0.0, 0.0], [1.0, 4.0, 0.5, 0.0],
                   [0.0, 0.5, 4.0, 0.2], [0.0, 0.0, 0.2, 4.0]])
        # Banded storage form of `a`.
        ab = array([[-1.0, 1.0, 0.5, 0.2], [4.0, 4.0, 4.0, 4.0]])
        c = cholesky_banded(ab, lower=False)
        ufac = zeros_like(a)
        ufac[list(range(4)), list(range(4))] = c[-1]
        ufac[(0, 1, 2), (1, 2, 3)] = c[0, 1:]
        assert_array_almost_equal(a, dot(ufac.T, ufac))

        b = array([0.0, 0.5, 4.2, 4.2])
        x = cho_solve_banded((c, False), b)
        assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
Exemplo n.º 13
0
    def test_lower_real(self):
        # Symmetric positive definite banded matrix `a`
        a = array([[4.0, 1.0, 0.0, 0.0], [1.0, 4.0, 0.5, 0.0],
                   [0.0, 0.5, 4.0, 0.2], [0.0, 0.0, 0.2, 4.0]])
        # Banded storage form of `a`.
        ab = array([[4.0, 4.0, 4.0, 4.0], [1.0, 0.5, 0.2, -1.0]])
        c = cholesky_banded(ab, lower=True)
        lfac = zeros_like(a)
        lfac[list(range(4)), list(range(4))] = c[0]
        lfac[(1, 2, 3), (0, 1, 2)] = c[1, :3]
        assert_array_almost_equal(a, dot(lfac, lfac.T))

        b = array([0.0, 0.5, 4.2, 4.2])
        x = cho_solve_banded((c, True), b)
        assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
Exemplo n.º 14
0
    def test_upper_complex(self):
        # Hermitian positive definite banded matrix `a`
        a = array([[4.0, 1.0,  0.0,  0.0],
                    [1.0, 4.0,  0.5,  0.0],
                    [0.0, 0.5,  4.0, -0.2j],
                    [0.0, 0.0,  0.2j, 4.0]])
        # Banded storage form of `a`.
        ab = array([[-1.0, 1.0, 0.5, -0.2j],
                     [4.0, 4.0, 4.0,  4.0]])
        c = cholesky_banded(ab, lower=False)
        ufac = zeros_like(a)
        ufac[range(4),range(4)] = c[-1]
        ufac[(0,1,2),(1,2,3)] = c[0,1:]
        assert_array_almost_equal(a, dot(ufac.conj().T, ufac))

        b = array([0.0, 0.5, 4.0-0.2j, 0.2j + 4.0])
        x = cho_solve_banded((c, False), b)
        assert_array_almost_equal(x, [0.0, 0.0, 1.0, 1.0])
    def test_posterior_cov(self):
        # Test the values from the Cython results
        inv_chol = np.array(self._sim_cfa.posterior_cov_inv_chol, copy=True)
        actual = cho_solve_banded((inv_chol, True), np.eye(inv_chol.shape[1]))

        for t in range(self.mod.nobs):
            tm = t * self.mod.k_states
            t1m = tm + self.mod.k_states
            assert_allclose(actual[tm:t1m, tm:t1m],
                            self.res.smoothed_state_cov[..., t],
                            atol=self.cov_atol)

        # Test the values from the CFASimulationSmoother wrapper results
        actual = self.sim_cfa.posterior_cov

        for t in range(self.mod.nobs):
            tm = t * self.mod.k_states
            t1m = tm + self.mod.k_states
            assert_allclose(actual[tm:t1m, tm:t1m],
                            self.res.smoothed_state_cov[..., t],
                            atol=self.cov_atol)
Exemplo n.º 16
0
def drawFrame(i):
    #print ''
    print 'i:',i
    gridT = np.reshape(T[0], (Nx, Ny))
    #print 'gridT:', shape(gridT)
    #print gridT
    #print 'x:',shape(x)
    #print 'y:',shape(y)
    z = im.zoom(gridT, szmul, order=3)
    extent = (xi, xf, yf, yi)
    ax.imshow(z, extent=extent, cmap=paleta, interpolation="nearest", vmin=0.0, vmax=vmax)
    c1 = ax.contour(x,y,z, levels=np.arange(0.0, vmax, vmax/50.0), colors='k', vmin=0.0, vmax=vmax)
    c2 = ax.contourf(x,y,z, levels=np.arange(0.0, vmax, vmax/50.0), cmap=paleta, vmin=0.0, vmax=vmax)
    
    # calculando os valores para o próximo frame da animação
    vecB = calcNextTimeResultVec(i)
    #print vecB
    #vecR = la.solve(matA, vecB)
    #print 'choFacA:', choFacA
    vecR = la.cho_solve_banded((choA, False), vecB)
    #vecR = la.cho_solve(choFacA, vecB)
    vecR = list(vecR.flat)
    #print 'vecR:', vecR
    T[0] = vecR
Exemplo n.º 17
0
 def test_cho_solve_banded(self):
     x = array([[0, -1, -1], [2, 2, 2]])
     xcho = cholesky_banded(x)
     assert_no_overwrite(lambda b: cho_solve_banded((xcho, False), b),
                         [(3,)])
Exemplo n.º 18
0
def make_lsq_spline(x, y, t, k=3, w=None, axis=0, check_finite=True):
    r"""Compute the (coefficients of) an LSQ B-spline.

    The result is a linear combination

    .. math::

            S(x) = \sum_j c_j B_j(x; t)

    of the B-spline basis elements, :math:`B_j(x; t)`, which minimizes

    .. math::

        \sum_{j} \left( w_j \times (S(x_j) - y_j) \right)^2

    Parameters
    ----------
    x : array_like, shape (m,)
        Abscissas.
    y : array_like, shape (m, ...)
        Ordinates.
    t : array_like, shape (n + k + 1,).
        Knots.
        Knots and data points must satisfy Schoenberg-Whitney conditions.
    k : int, optional
        B-spline degree. Default is cubic, k=3.
    w : array_like, shape (n,), optional
        Weights for spline fitting. Must be positive. If ``None``,
        then weights are all equal.
        Default is ``None``.
    axis : int, optional
        Interpolation axis. Default is zero.
    check_finite : bool, optional
        Whether to check that the input arrays contain only finite numbers.
        Disabling may give a performance gain, but may result in problems
        (crashes, non-termination) if the inputs do contain infinities or NaNs.
        Default is True.

    Returns
    -------
    b : a BSpline object of the degree `k` with knots `t`.

    Notes
    -----

    The number of data points must be larger than the spline degree `k`.

    Knots `t` must satisfy the Schoenberg-Whitney conditions,
    i.e., there must be a subset of data points ``x[j]`` such that
    ``t[j] < x[j] < t[j+k+1]``, for ``j=0, 1,...,n-k-2``.

    Examples
    --------
    Generate some noisy data:

    >>> x = np.linspace(-3, 3, 50)
    >>> y = np.exp(-x**2) + 0.1 * np.random.randn(50)

    Now fit a smoothing cubic spline with a pre-defined internal knots.
    Here we make the knot vector (k+1)-regular by adding boundary knots:

    >>> from scipy.interpolate import make_lsq_spline, BSpline
    >>> t = [-1, 0, 1]
    >>> k = 3
    >>> t = np.r_[(x[0],)*(k+1),
    ...           t,
    ...           (x[-1],)*(k+1)]
    >>> spl = make_lsq_spline(x, y, t, k)

    For comparison, we also construct an interpolating spline for the same
    set of data:

    >>> from scipy.interpolate import make_interp_spline
    >>> spl_i = make_interp_spline(x, y)

    Plot both:

    >>> import matplotlib.pyplot as plt
    >>> xs = np.linspace(-3, 3, 100)
    >>> plt.plot(x, y, 'ro', ms=5)
    >>> plt.plot(xs, spl(xs), 'g-', lw=3, label='LSQ spline')
    >>> plt.plot(xs, spl_i(xs), 'b-', lw=3, alpha=0.7, label='interp spline')
    >>> plt.legend(loc='best')
    >>> plt.show()

    **NaN handling**: If the input arrays contain ``nan`` values, the result is
    not useful since the underlying spline fitting routines cannot deal with
    ``nan``. A workaround is to use zero weights for not-a-number data points:

    >>> y[8] = np.nan
    >>> w = np.isnan(y)
    >>> y[w] = 0.
    >>> tck = make_lsq_spline(x, y, t, w=~w)

    Notice the need to replace a ``nan`` by a numerical value (precise value
    does not matter as long as the corresponding weight is zero.)

    See Also
    --------
    BSpline : base class representing the B-spline objects
    make_interp_spline : a similar factory function for interpolating splines
    LSQUnivariateSpline : a FITPACK-based spline fitting routine
    splrep : a FITPACK-based fitting routine

    """
    x = _as_float_array(x, check_finite)
    y = _as_float_array(y, check_finite)
    t = _as_float_array(t, check_finite)
    if w is not None:
        w = _as_float_array(w, check_finite)
    else:
        w = np.ones_like(x)
    k = operator.index(k)

    if not -y.ndim <= axis < y.ndim:
        raise ValueError("axis {} is out of bounds".format(axis))
    if axis < 0:
        axis += y.ndim

    y = np.rollaxis(y, axis)    # now internally interp axis is zero

    if x.ndim != 1 or np.any(x[1:] - x[:-1] <= 0):
        raise ValueError("Expect x to be a 1-D sorted array_like.")
    if x.shape[0] < k+1:
        raise ValueError("Need more x points.")
    if k < 0:
        raise ValueError("Expect non-negative k.")
    if t.ndim != 1 or np.any(t[1:] - t[:-1] < 0):
        raise ValueError("Expect t to be a 1-D sorted array_like.")
    if x.size != y.shape[0]:
        raise ValueError('x & y are incompatible.')
    if k > 0 and np.any((x < t[k]) | (x > t[-k])):
        raise ValueError('Out of bounds w/ x = %s.' % x)
    if x.size != w.size:
        raise ValueError('Incompatible weights.')

    # number of coefficients
    n = t.size - k - 1

    # construct A.T @ A and rhs with A the collocation matrix, and
    # rhs = A.T @ y for solving the LSQ problem  ``A.T @ A @ c = A.T @ y``
    lower = True
    extradim = prod(y.shape[1:])
    ab = np.zeros((k+1, n), dtype=np.float_, order='F')
    rhs = np.zeros((n, extradim), dtype=y.dtype, order='F')
    _bspl._norm_eq_lsq(x, t, k,
                      y.reshape(-1, extradim),
                      w,
                      ab, rhs)
    rhs = rhs.reshape((n,) + y.shape[1:])

    # have observation matrix & rhs, can solve the LSQ problem
    cho_decomp = cholesky_banded(ab, overwrite_ab=True, lower=lower,
                                 check_finite=check_finite)
    c = cho_solve_banded((cho_decomp, lower), rhs, overwrite_b=True,
                         check_finite=check_finite)

    c = np.ascontiguousarray(c)
    return BSpline.construct_fast(t, c, k, axis=axis)
Exemplo n.º 19
0
def l2appr(n_dim, K, vec_timestamps, vec_obs, numObs, knots, weight):

    #  CONSTRUCTS THE (WEIGHTED DISCRETE) L2-APPROXIMATION BY SPLINES OF ORDER
    #  K WITH KNOT SEQUENCE T(1), .., T(N+K) TO GIVEN DATA POINTS
    #  (TAU(I),GTAU(I)), I=1,...,NTAU. THE B-SPLINE COEFFICIENTS
    #   B C O E F  OF THE APPROXIMATING SPLINE ARE DETERMINED FROM THE
    #  NORMAL EQUATIONS USING CHOLESKY'S METHOD.

    # n_dim : dimension of the B-spline space
    # K : order
    # numObs : number of data points
    # number of knots = n_dim + K

    bcoeff = np.asarray([0.0 for i in range(n_dim)])
    biatx = np.asarray([0.0 for i in range(K)])
    Q = np.zeros((K, n_dim))

    left_py = K - 1
    leftmk_py = -1  # left - K
    # Note that left cors. to the index of the knot just left of x, by Dr. Watson's notes indices.
    # The knots t run from t_1 to t_{n_dim+K}.
    # The python vector t will, however, go from 0 to n_dim+K-1.
    # t_1 is stored at location t[0].
    # t_2 is stored at location t[1].
    # t_K is stored at location t[K-1]
    # t[i] is stored at location t[i-1].
    # If we identify an index 'left' st. t[left] < x < t[left+1], then
    # x is actually in between t_{left} and t_{left+1}
    for ll in range(0, numObs):
        #        print 'll =', ll, 'x_ll =', vec_timestamps[ll],
        #        print 'knots[left_py]', knots[left_py], 'vec_timestamps[ll] >= knots[left_py]', vec_timestamps[ll] >= knots[left_py]
        # corner case
        if (left_py == n_dim - 1) or (vec_timestamps[ll] < knots[left_py + 1]):
            # we want: vec_timestamps(ll) \in (knots(left_fort) , knots(left_fort+1))
            # i.e., vec_timestamps(ll) \in (knots(left_py - 1) , knots(left_py))
            # call bsplvb directly
            left_fort = left_py + 1
            biatx[0:K + 1] = bsplvb(knots, K, 1, vec_timestamps[ll], left_fort)
        else:
            # Locate left st. vec_timestamps(ll) \in (knots(left_fort) , knots(left_fort+1))
            # i.e., vec_timestamps(ll) \in (knots(left_py - 1) , knots(left_py))
            while (vec_timestamps[ll] >= knots[left_py + 1]):
                left_py += 1
                leftmk_py += 1
            # now call bsplvb
            left_fort = left_py + 1
            biatx[0:K + 1] = bsplvb(knots, K, 1, vec_timestamps[ll], left_fort)

        # BIATX(MM-1)   (originally, BIATX(MM) in Fortran)
        # CONTAINS THE VALUE OF B(LEFT-K+MM), MM = 1,2,...,K,  AT TAU(LL).
        # HENCE, WITH DW := BIATX(MM-1)*WEIGHT(LL), (originally, BIATX(MM)*WEIGHT(LL) in Fortran)
        # THE NUMBER DW*GTAU(LL)
        # IS A SUMMAND IN THE INNER PRODUCT
        # (B(LEFT-K+MM),G) WHICH GOES INTO BCOEF(LEFT-K+MM-1)  (originally, BCOEF(LEFT-K+MM) in Fortran)
        # AND THE NUMBER BIATX(JJ)*DW IS A SUMMAND IN THE INNER PRODUCT
        # (B(LEFT-K+JJ),B(LEFT-K+MM)), INTO Q(JJ-MM+1,LEFT-K+MM)
        # SINCE (LEFT-K+JJ) - (LEFT-K+MM) + 1 = JJ - MM + 1 .

        # Solving:             min || Ax - b ||
        # So, we solve:       A^tA x = A^t b
        #
        # Entries of A^t A:
        #
        #                  ---
        #                  \
        # [AtA]_{ij} =          B_i(x_l) * B_j(x_j) * w(l)
        #                  /
        #                  ---
        #                  i,j=
        #
        # AtA is a symmetric banded matrix due to local support of B-splines.
        # No point storing (or even calculating) all entries.
        # Only nonzero entries are calculated.
        #
        # Entries of A^t b:
        #
        for mm in range(1, K + 1):
            dw = biatx[mm - 1] * weight[ll]
            j = (leftmk_py + 1) + mm
            # The rhs < A^t, b >
            bcoeff[j - 1] = dw * vec_obs[ll] + bcoeff[j - 1]
            i = 1
            for jj in range(mm, K + 1):
                Q[i - 1, j - 1] = biatx[jj - 1] * dw + Q[
                    i - 1, j - 1]  # j is fixed for currnt x_ll and current mm.
                # only i and jj are incrementing.
                # Q[*, j-1] is getting filled.
                # Then mm increments. j will also increment.
                # Q[*, j_old+1] will get filled.
                #
                # Then next x_ll comes in.
                # Suppose x_ll is in the same knot interval.
                # mm will still run from 1 to K.
                # j, by formula, will again take same values as previous loop.
                # So same columns of Q will get updated.
                # i will also take same values as previous ll-loop.
                # So, same rows of Q will update.
                # Essentially, for fixed [left, left+1), same entries
                # of Q will update.
                #
                # Suppose x_ll is in a different interval.
                # i.e., left is different, say, left_new = left_old+1
                # Then, j takes 1 higher values than prevoius ll-loops.
                # Meaning, a new (1 up) set of columns is filled.
                # mm and K are always same. So each row is filled again,
                # just in a different column.
                # That's the story of 'matrix filling' here.
                # Figure out the actual working of bandedness etc. -- TODO.
                i += 1


#       Get the CHOLESKY FACTORIZATION FOR banded matrix Q, THEN USE
#       IT TO SOLVE THE NORMAL EQUATIONS
#         C*X = BCOEF
#       FOR X , AND STORE X IN BCOEF
#    print 'In l2appr'
#    print  'n_dim =', n_dim
#    with open("ltr_python_output.csv", "a") as fh:
#        fh.write('writing Q:' + '\n')
#        for i in range(K):
#            fh.write('  '.join([str(Q[i, col]) for col in range(n_dim)] ) + '\n ')
#    fh.close()
    cb = la.cholesky_banded(Q,
                            overwrite_ab=False,
                            lower=True,
                            check_finite=True)
    bcoeff = la.cho_solve_banded((cb, True),
                                 bcoeff,
                                 overwrite_b=True,
                                 check_finite=True)

    return bcoeff
Exemplo n.º 20
0
def make_lsq_spline(x, y, t, k=3, w=None, axis=0, check_finite=True):
    r"""Compute the (coefficients of) an LSQ B-spline.

    The result is a linear combination

    .. math::

            S(x) = \sum_j c_j B_j(x; t)

    of the B-spline basis elements, :math:`B_j(x; t)`, which minimizes

    .. math::

        \sum_{j} \left( w_j \times (S(x_j) - y_j) \right)^2

    Parameters
    ----------
    x : array_like, shape (m,)
        Abscissas.
    y : array_like, shape (m, ...)
        Ordinates.
    t : array_like, shape (n + k + 1,).
        Knots.
        Knots and data points must satisfy Schoenberg-Whitney conditions.
    k : int, optional
        B-spline degree. Default is cubic, k=3.
    w : array_like, shape (n,), optional
        Weights for spline fitting. Must be positive. If ``None``,
        then weights are all equal.
        Default is ``None``.
    axis : int, optional
        Interpolation axis. Default is zero.
    check_finite : bool, optional
        Whether to check that the input arrays contain only finite numbers.
        Disabling may give a performance gain, but may result in problems
        (crashes, non-termination) if the inputs do contain infinities or NaNs.
        Default is True.

    Returns
    -------
    b : a BSpline object of the degree `k` with knots `t`.

    Notes
    -----

    The number of data points must be larger than the spline degree `k`.

    Knots `t` must satisfy the Schoenberg-Whitney conditions,
    i.e., there must be a subset of data points ``x[j]`` such that
    ``t[j] < x[j] < t[j+k+1]``, for ``j=0, 1,...,n-k-2``.

    Examples
    --------
    Generate some noisy data:

    >>> x = np.linspace(-3, 3, 50)
    >>> y = np.exp(-x**2) + 0.1 * np.random.randn(50)

    Now fit a smoothing cubic spline with a pre-defined internal knots.
    Here we make the knot vector (k+1)-regular by adding boundary knots:

    >>> from scipy.interpolate import make_lsq_spline, BSpline
    >>> t = [-1, 0, 1]
    >>> k = 3
    >>> t = np.r_[(x[0],)*(k+1),
    ...           t,
    ...           (x[-1],)*(k+1)]
    >>> spl = make_lsq_spline(x, y, t, k)

    For comparison, we also construct an interpolating spline for the same
    set of data:

    >>> from scipy.interpolate import make_interp_spline
    >>> spl_i = make_interp_spline(x, y)

    Plot both:

    >>> import matplotlib.pyplot as plt
    >>> xs = np.linspace(-3, 3, 100)
    >>> plt.plot(x, y, 'ro', ms=5)
    >>> plt.plot(xs, spl(xs), 'g-', lw=3, label='LSQ spline')
    >>> plt.plot(xs, spl_i(xs), 'b-', lw=3, alpha=0.7, label='interp spline')
    >>> plt.legend(loc='best')
    >>> plt.show()

    **NaN handling**: If the input arrays contain ``nan`` values, the result is
    not useful since the underlying spline fitting routines cannot deal with
    ``nan``. A workaround is to use zero weights for not-a-number data points:

    >>> y[8] = np.nan
    >>> w = np.isnan(y)
    >>> y[w] = 0.
    >>> tck = make_lsq_spline(x, y, t, w=~w)

    Notice the need to replace a ``nan`` by a numerical value (precise value
    does not matter as long as the corresponding weight is zero.)

    See Also
    --------
    BSpline : base class representing the B-spline objects
    make_interp_spline : a similar factory function for interpolating splines
    LSQUnivariateSpline : a FITPACK-based spline fitting routine
    splrep : a FITPACK-based fitting routine

    """
    x = _as_float_array(x, check_finite)
    y = _as_float_array(y, check_finite)
    t = _as_float_array(t, check_finite)
    if w is not None:
        w = _as_float_array(w, check_finite)
    else:
        w = np.ones_like(x)
    k = operator.index(k)

    axis = normalize_axis_index(axis, y.ndim)

    y = np.rollaxis(y, axis)  # now internally interp axis is zero

    if x.ndim != 1 or np.any(x[1:] - x[:-1] <= 0):
        raise ValueError("Expect x to be a 1-D sorted array_like.")
    if x.shape[0] < k + 1:
        raise ValueError("Need more x points.")
    if k < 0:
        raise ValueError("Expect non-negative k.")
    if t.ndim != 1 or np.any(t[1:] - t[:-1] < 0):
        raise ValueError("Expect t to be a 1-D sorted array_like.")
    if x.size != y.shape[0]:
        raise ValueError('x & y are incompatible.')
    if k > 0 and np.any((x < t[k]) | (x > t[-k])):
        raise ValueError('Out of bounds w/ x = %s.' % x)
    if x.size != w.size:
        raise ValueError('Incompatible weights.')

    # number of coefficients
    n = t.size - k - 1

    # construct A.T @ A and rhs with A the collocation matrix, and
    # rhs = A.T @ y for solving the LSQ problem  ``A.T @ A @ c = A.T @ y``
    lower = True
    extradim = prod(y.shape[1:])
    ab = np.zeros((k + 1, n), dtype=np.float_, order='F')
    rhs = np.zeros((n, extradim), dtype=y.dtype, order='F')
    _bspl._norm_eq_lsq(x, t, k, y.reshape(-1, extradim), w, ab, rhs)
    rhs = rhs.reshape((n, ) + y.shape[1:])

    # have observation matrix & rhs, can solve the LSQ problem
    cho_decomp = cholesky_banded(ab,
                                 overwrite_ab=True,
                                 lower=lower,
                                 check_finite=check_finite)
    c = cho_solve_banded((cho_decomp, lower),
                         rhs,
                         overwrite_b=True,
                         check_finite=check_finite)

    c = np.ascontiguousarray(c)
    return BSpline.construct_fast(t, c, k, axis=axis)
Exemplo n.º 21
0
 def test_cho_solve_banded(self):
     x = array([[0, -1, -1], [2, 2, 2]])
     xcho = cholesky_banded(x)
     assert_no_overwrite(lambda b: cho_solve_banded((xcho, False), b),
                         [(3,)])
Exemplo n.º 22
0
 def linear_map(self, x):
     if not self.banded:
         return cho_solve(self._cholesky, x)
     else:
         return cho_solve_banded(self._cholesky, x)
Exemplo n.º 23
0
 def linear_map(self, x):
     if not self.banded:
         return cho_solve(self._cholesky, x)
     else:
         return cho_solve_banded(self._cholesky, x)