Example #1
0
    def test_df_arith_2d_array_collike_broadcasts(self,
                                                  all_arithmetic_operators):
        # GH#23000
        opname = all_arithmetic_operators

        arr = np.arange(6).reshape(3, 2)
        df = pd.DataFrame(arr, columns=[True, False], index=['A', 'B', 'C'])

        collike = arr[:, [1]]  # shape --> (nrows, 1)
        assert collike.shape == (df.shape[0], 1)

        exvals = {True: getattr(df[True], opname)(collike.squeeze()),
                  False: getattr(df[False], opname)(collike.squeeze())}

        dtype = None
        if opname in ['__rmod__', '__rfloordiv__']:
            # Series ops may return mixed int/float dtypes in cases where
            #   DataFrame op will return all-float.  So we upcast `expected`
            dtype = np.common_type(*[x.values for x in exvals.values()])

        expected = pd.DataFrame(exvals, columns=df.columns, index=df.index,
                                dtype=dtype)

        result = getattr(df, opname)(collike)
        tm.assert_frame_equal(result, expected)
Example #2
0
def minmax_normalize(samples, out=None):
    """Min-max normalization of a function evaluated on the unit sphere

    Normalizes samples to ``(samples - min(samples)) / (max(samples) -
    min(samples))`` for each unit sphere.

    Parameters
    ----------
    samples : ndarray (..., N)
        N samples on a unit sphere for each point, stored along the last axis
        of the array.
    out : ndrray (..., N), optional
        An array to store the normalized samples.

    Returns
    -------
    out : ndarray, (..., N)
        Normalized samples.

    """
    if out is None:
        dtype = np.common_type(np.empty(0, 'float32'), samples)
        out = np.array(samples, dtype=dtype, copy=True)
    else:
        out[:] = samples

    sample_mins = np.min(samples, -1)[..., None]
    sample_maxes = np.max(samples, -1)[..., None]
    out -= sample_mins
    out /= (sample_maxes - sample_mins)
    return out
Example #3
0
def poly_outer_product(left, right):
  left, right = numpy.asarray(left), numpy.asarray(right)
  nleft, nright = left.ndim-1, right.ndim-1
  pshape = left.shape[1:] if not nright else right.shape[1:] if not nleft else (max(left.shape[1:])+max(right.shape[1:])-1,) * (nleft + nright)
  outer = numpy.zeros((left.shape[0], right.shape[0], *pshape), dtype=numpy.common_type(left, right))
  a = slice(None)
  outer[(a,a,*(map(slice, left.shape[1:]+right.shape[1:])))] = left[(a,None)+(a,)*nleft+(None,)*nright]*right[(None,a)+(None,)*nleft+(a,)*nright]
  return types.frozenarray(outer.reshape(left.shape[0] * right.shape[0], *pshape), copy=False)
Example #4
0
 def _get_shared_type_and_fill_value(data1, data2, fill1=None, fill2=None) :
     """
     Figure out a shared type that can be used when adding or subtracting
     the two data sets given (accounting for possible overflow)
     Also returns a fill value that can be used.
     """
     
     # figure out the shared type
     type_to_return = data1.dtype
     changed_type   = False
     if data1.dtype is not data2.dtype:
         type_to_return = np.common_type(data1, data2)
         changed_type   = True
     
     # make sure we're using a type that has negative values in it
     if type_to_return in DiffInfoObject.POSITIVE_UPCASTS :
         type_to_return = DiffInfoObject.POSITIVE_UPCASTS[type_to_return]
         changed_type = True
     
     # upcast the type if we think we'll need more space for subtracting
     if type_to_return in DiffInfoObject.DATATYPE_UPCASTS :
         type_to_return = DiffInfoObject.DATATYPE_UPCASTS[type_to_return]
         changed_type = True
     
     if changed_type :
         LOG.debug('To prevent overflow, difference data will be upcast from ('
                   + str(data1.dtype) + '/' + str(data2.dtype) + ') to: ' + str(type_to_return))
     
     # figure out the fill value
     fill_value_to_return = None
     
     # if both of the old fill values exist and are the same, use them
     if (fill1 is not None) and (fill1 == fill2) :
         
         fill_value_to_return = fill1
         if changed_type :
             fill_value_to_return = type_to_return(fill_value_to_return)
         
     else: 
         
         # if we're looking at float or complex data, use a nan
         if (np.issubdtype(type_to_return, np.float) or
             np.issubdtype(type_to_return, np.complex)) :
             fill_value_to_return = np.nan
         
         # if we're looking at int data, use the minimum value
         elif np.issubdtype(type_to_return, np.int) :
             fill_value_to_return = np.iinfo(type_to_return).min
         
         # if we're looking at unsigned data, use the maximum value
         elif ((type_to_return is np.uint8)  or
               (type_to_return is np.uint16) or
               (type_to_return is np.uint32) or
               (type_to_return is np.uint64)) :
             fill_value_to_return = np.iinfo(type_to_return).max
     
     return type_to_return, fill_value_to_return
Example #5
0
def _normalize_scalar_dtype(s, arrs):
    # cast python scalars to an appropriate numpy dtype
    if isinstance(s, (int, float, complex)):
        ndarrs = [_a for _a in arrs if hasattr(_a, 'dtype')]
        flt_arrs = [_a for _a in ndarrs if _a.dtype.kind in 'fc']
        int_arrs = [_a for _a in ndarrs if _a.dtype.kind in 'i']
        if flt_arrs and isinstance(s, (int, float, complex)):
            s = np.asarray(s).astype(np.common_type(*flt_arrs))
        elif int_arrs and isinstance(s, (int, )):
            s = np.asarray(s).astype(max([_a.dtype for _a in int_arrs]))
    return s
def as_series(alist, trim=True):
    """Return arguments as a list of 1d arrays.

    The return type will always be an array of double, complex double. or
    object.

    Parameters
    ----------
    [a1, a2,...] : list of array_like.
        The arrays must have no more than one dimension when converted.
    trim : boolean
        When True, trailing zeros are removed from the inputs.
        When False, the inputs are passed through intact.

    Returns
    -------
    [a1, a2,...] : list of 1d-arrays
        A copy of the input data as a 1d-arrays.

    Raises
    ------
    ValueError :
        Raised when an input can not be coverted to 1-d array or the
        resulting array is empty.

    """
    arrays = [np.array(a, ndmin=1, copy=0) for a in alist]
    if min([a.size for a in arrays]) == 0:
        raise ValueError("Coefficient array is empty")
    if max([a.ndim for a in arrays]) > 1:
        raise ValueError("Coefficient array is not 1-d")
    if trim:
        arrays = [trimseq(a) for a in arrays]

    if any([a.dtype == np.dtype(object) for a in arrays]):
        ret = []
        for a in arrays:
            if a.dtype != np.dtype(object):
                tmp = np.empty(len(a), dtype=np.dtype(object))
                tmp[:] = a[:]
                ret.append(tmp)
            else:
                ret.append(a.copy())
    else:
        try:
            dtype = np.common_type(*arrays)
        except:
            raise ValueError("Coefficient arrays have no common type")
        ret = [np.array(a, copy=1, dtype=dtype) for a in arrays]
    return ret
Example #7
0
def nulp_diff(x, y, dtype=None):
    """For each item in x and y, return the number of representable floating
    points between them.

    Parameters
    ----------
    x : array_like
        first input array
    y : array_like
        second input array

    Returns
    -------
    nulp: array_like
        number of representable floating point numbers between each item in x
        and y.

    Examples
    --------
    # By definition, epsilon is the smallest number such as 1 + eps != 1, so
    # there should be exactly one ULP between 1 and 1 + eps
    >>> nulp_diff(1, 1 + np.finfo(x.dtype).eps)
    1.0
    """
    import numpy as np
    if dtype:
        x = np.array(x, dtype=dtype)
        y = np.array(y, dtype=dtype)
    else:
        x = np.array(x)
        y = np.array(y)

    t = np.common_type(x, y)
    if np.iscomplexobj(x) or np.iscomplexobj(y):
        raise NotImplementedError("_nulp not implemented for complex array")

    x = np.array(x, dtype=t)
    y = np.array(y, dtype=t)

    if not x.shape == y.shape:
        raise ValueError("x and y do not have the same shape: %s - %s" % \
                         (x.shape, y.shape))

    def _diff(rx, ry, vdt):
        diff = np.array(rx-ry, dtype=vdt)
        return np.abs(diff)

    rx = integer_repr(x)
    ry = integer_repr(y)
    return _diff(rx, ry, t)
def matrixmultiply(a, b):
    if len(b.shape) == 1:
        b_is_vector = True
        b = b[:,newaxis]
    else:
        b_is_vector = False
    assert_(a.shape[1] == b.shape[0])
    c = zeros((a.shape[0], b.shape[1]), common_type(a, b))
    for i in xrange(a.shape[0]):
        for j in xrange(b.shape[1]):
            s = 0
            for k in xrange(a.shape[1]):
                s += a[i,k] * b[k, j]
            c[i,j] = s
    if b_is_vector:
        c = c.reshape((a.shape[0],))
    return c
Example #9
0
def matrixmultiply(a, b):
    if len(b.shape) == 1:
        b_is_vector = True
        b = b[:,newaxis]
    else:
        b_is_vector = False
    assert_equal(a.shape[1], b.shape[0])
    c = zeros((a.shape[0], b.shape[1]), common_type(a, b))
    for i in xrange(a.shape[0]):
        for j in xrange(b.shape[1]):
            s = 0
            for k in xrange(a.shape[1]):
                s += a[i,k] * b[k, j]
            c[i,j] = s
    if b_is_vector:
        c = c.reshape((a.shape[0],))
    return c
Example #10
0
def random_MPS(L, d, chimax, func=randmat.standard_normal_complex, bc='finite', form='B'):
    site = Site(charges.LegCharge.from_trivial(d))
    chi = [chimax] * (L + 1)
    if bc == 'finite':
        for i in range(L // 2 + 1):
            chi[i] = chi[L - i] = min(chi[i], d**i)
    Bs = []
    for i in range(L):
        B = func((d, chi[i], chi[i + 1]))
        B /= np.sqrt(chi[i + 1]) * d
        Bs.append(B)
    dtype = np.common_type(*Bs)
    psi = MPS.from_Bflat([site] * L, Bs, bc=bc, dtype=dtype, form=None)
    if form is not None:
        psi.canonical_form()
        psi.convert_form(form)
    return psi
Example #11
0
def dot_generalized(a, b):
    a = asarray(a)
    if a.ndim >= 3:
        if a.ndim == b.ndim:
            # matrix x matrix
            new_shape = a.shape[:-1] + b.shape[-1:]
        elif a.ndim == b.ndim + 1:
            # matrix x vector
            new_shape = a.shape[:-1]
        else:
            raise ValueError("Not implemented...")
        r = np.empty(new_shape, dtype=np.common_type(a, b))
        for c in itertools.product(*map(range, a.shape[:-2])):
            r[c] = dot(a[c], b[c])
        return r
    else:
        return dot(a, b)
Example #12
0
def ising_H(J,g):
    if len(J)<len(g):
        J=np.array(list(J)+[0.0])
    J=np.array(J)
    g=np.array(g)
    diage=np.zeros(len(g)+len(J)-1,dtype=np.common_type(J,g))
    diage[::2]=g
    diage[1::2]=J[:-1]
    rete=0.5j*(np.diag(diage,1)-np.diag(diage,-1))
    if len(g)>1:
        rete[0,-1]+=-0.5j*J[-1]
        rete[-1,0]+=0.5j*J[-1]
    reto=0.5j*(np.diag(diage,1)-np.diag(diage,-1))
    if len(g)>1:
        reto[0,-1]+=0.5j*J[-1]
        reto[-1,0]+=-0.5j*J[-1]
    return (rete*4,reto*4)
Example #13
0
def dot_generalized(a, b):
    a = asarray(a)
    if a.ndim >= 3:
        if a.ndim == b.ndim:
            # matrix x matrix
            new_shape = a.shape[:-1] + b.shape[-1:]
        elif a.ndim == b.ndim + 1:
            # matrix x vector
            new_shape = a.shape[:-1]
        else:
            raise ValueError("Not implemented...")
        r = np.empty(new_shape, dtype=np.common_type(a, b))
        for c in itertools.product(*map(range, a.shape[:-2])):
            r[c] = dot(a[c], b[c])
        return r
    else:
        return dot(a, b)
Example #14
0
    def evaluate(self, points):
        """Evaluate the estimated pdf on a set of points.
        Parameters
        ----------
        points : (# of dimensions, # of points)-array
            Alternatively, a (# of dimensions,) vector can be passed in and
            treated as a single point.
        Returns
        -------
        values : (# of points,)-array
            The values at each point.
        Raises
        ------
        ValueError : if the dimensionality of the input points is different than
                     the dimensionality of the KDE.
        """
        #points = atleast_2d(asarray(points))

        d, m = points.shape
        '''
        if d != self.d:
            if d == 1 and m == self.d:
                # points was passed in as a row vector
                points = reshape(points, (self.d, 1))
                m = 1
            else:
                msg = "points have dimension %s, dataset has dimension %s" % (d,
                    self.d)
                raise ValueError(msg)
        '''
        output_dtype = np.common_type(self.covariance, points)
        itemsize = np.dtype(output_dtype).itemsize
        if itemsize == 4:
            spec = 'float'
        elif itemsize == 8:
            spec = 'double'
        elif itemsize in (12, 16):
            spec = 'long double'
        else:
            raise TypeError('%s has unexpected item size %d' %
                            (output_dtype, itemsize))
        result = gaussian_kernel_estimate[spec](self.dataset.T,
                                                self.weights[:,
                                                             None], points.T,
                                                self.inv_cov, output_dtype)
        return result[:, 0]
Example #15
0
def sparse_transform(m, *args):
    """
    Performs a sparse transform of a dense tensor.
    Args:
        m (ndarray): a tensor to transform;
        *args: alternating indexes and bases to transform into;

    Returns:
        The transformed tensor.
    """
    result = m
    for i, (index, basis) in enumerate(zip(args[::2], args[1::2])):

        if len(basis.shape) != 2:
            raise ValueError(
                "Transform {:d} is not a matrix: shape = {}".format(
                    i, repr(basis.shape)))
        if result.shape[index] != basis.shape[0]:
            raise ValueError(
                "Dimension mismatch of transform {:d}: m.shape[{:d}] = {:d} != basis.shape[0] = {:d}"
                .format(
                    i,
                    index,
                    result.shape[index],
                    basis.shape[0],
                ))
        if "getcol" not in dir(basis):
            raise ValueError(
                "No 'getcol' in the transform matrix {:d}: not a CSC sparse matrix?"
            )

        result_shape = result.shape[:index] + (
            basis.shape[1], ) + result.shape[index + 1:]
        new_result = numpy.zeros(result_shape,
                                 numpy.common_type(*(args[1::2] + (m, ))))
        for b2 in range(basis.shape[1]):
            slice_b2 = (slice(None), ) * index + (b2, )
            col = basis.getcol(b2)
            for b1 in col.nonzero()[0]:
                slice_b1 = (slice(None), ) * index + (b1, )
                new_result[slice_b2] += col[b1, 0] * result[slice_b1]
        result = new_result

    return result
Example #16
0
def get_sparse_ov_transform(oo, vv):
    """
    Retrieves a sparse `ovov` transform out of sparse `oo` and `vv` transforms.
    Args:
        oo (ndarray): the transformation in the occupied space;
        vv (ndarray): the transformation in the virtual space;

    Returns:
        The resulting matrix representing the sparse transform in the `ov` space.
    """
    i, a = oo.shape
    j, b = vv.shape

    # If the input is dense the result is simply
    # return (oo[:, numpy.newaxis, :, numpy.newaxis] * vv[numpy.newaxis, :, numpy.newaxis, :]).reshape(i*j, a*b)

    result_data = numpy.zeros(oo.nnz * vv.nnz, dtype=numpy.common_type(oo, vv))
    result_indices = numpy.zeros(len(result_data), dtype=int)
    result_indptr = numpy.zeros(a * b + 1, dtype=int)

    ptr_counter = 0
    for i_a in range(a):
        oo_col = oo.getcol(i_a)
        assert tuple(oo_col.indptr.tolist()) == (0, len(oo_col.data))
        i_i, oo_col_v = oo_col.indices, oo_col.data
        for i_b in range(b):
            vv_col = vv.getcol(i_b)
            assert tuple(vv_col.indptr.tolist()) == (0, len(vv_col.data))
            i_j, vv_col_v = vv_col.indices, vv_col.data

            data_length = len(i_i) * len(i_j)
            result_indices[ptr_counter:ptr_counter +
                           data_length] = ((i_i * j)[:, numpy.newaxis] +
                                           i_j[numpy.newaxis, :]).reshape(-1)
            result_data[ptr_counter:ptr_counter +
                        data_length] = (oo_col_v[:, numpy.newaxis] *
                                        vv_col_v[numpy.newaxis, :]).reshape(-1)
            result_indptr[i_a * b + i_b] = ptr_counter

            ptr_counter += data_length

    result_indptr[-1] = ptr_counter
    return sparse.csc_matrix((result_data, result_indices, result_indptr))
Example #17
0
File: gdos.py Project: mzszym/oedes
 def _nevaluate(self, a, b, **tasks):
     if np.any(a != self.a):
         raise ValueError('a is different than precalculated')
     if np.asarray(a).shape == (0,):
         assert np.asarray(b).shape in [(), (0,)]
         b = np.zeros(0, dtype=np.common_type(a, b))
     result = {}
     if tasks.pop('need_value', False):
         result['value'] = self.spline(b)
     if tasks.pop('need_db', False):
         result['db'] = self.spline(b, 1)
     if tasks.pop('need_d2bb', False):
         result['d2bb'] = self.spline(b, 2)
     if tasks.pop('need_da', False):
         result['da'] = self.daspline(b)
     if tasks.pop('need_d2ab', False):
         result['d2ab'] = self.daspline(b, 1)
     if any(tasks.values()):
         raise NotImplementedError()
     return result
Example #18
0
def ising_H(L, J, g, h):
    r'''
        Construct a dense Hamiltonian of a spin 1/2 Ising ring with parameters given by the arrays J,g,h.
        H=\sum_i J_i s^z_{i+1}s^z_{i} + \sum_i h_i s^z_i + \sum_i g_i s^x_i
        (s^x, s^z are Pauli matrices)
        length is taken from the size of h, J can be either the same length
        (open boundary condition) or one element shorter (periodic boundary conditions).
    '''
    J = np.array(J)
    g = np.array(g)
    h = np.array(h)
    ret = np.zeros((2**L, 2**L), dtype=np.common_type(J, g, h, np.array(1.0)))
    for i, Jv in enumerate(J[:L - 1]):
        ret += Jv * kron([ID] * i + [SZ] + [SZ] + [ID] * (L - i - 2))
    if len(J) == L and L > 1:
        ret += J[-1] * kron([SZ] + [ID] * (L - 2) + [SZ])
    for i, hv in enumerate(h):
        ret += hv * kron([ID] * i + [SZ] + [ID] * (L - i - 1))
    for i, gv in enumerate(g):
        ret += gv * kron([ID] * i + [SX] + [ID] * (L - i - 1))
    return ret
Example #19
0
def fftwconvolve_1d(in1, in2):
    '''
    This code taken from:
    https://stackoverflow.com/questions/32028979/speed-up-for-loop-in-convolution-for-numpy-3d-array
    and the resulting output is the full discrete linear convolution of the 
    inputs (i.e. This returns the convolution at each point of overlap), 
    which includes additional terms at the start and end of the array such 
    that if A has size N and B has size M when covolved the size is N+M-1. 
    At the end-points of the convolution, the signals do not overlap 
    completely, and boundary effects may be seen. 
     
    Args:
        in1 (array): ?
        in2 (array): ?
        
    Returns:
        array (array): Linear convolution of inputs.
    '''

    outlen = in1.shape[-1] + in2.shape[-1] - 1
    origlen = in1.shape[-1]
    n = next_fast_len(outlen)
    tr1 = pyfftw.interfaces.numpy_fft.rfft(in1, n)
    tr2 = pyfftw.interfaces.numpy_fft.rfft(in2, n)
    sh = np.broadcast(tr1, tr2).shape
    dt = np.common_type(tr1, tr2)
    pr = pyfftw.n_byte_align_empty(sh, 16, dt)
    np.multiply(tr1, tr2, out=pr)
    out = pyfftw.interfaces.numpy_fft.irfft(pr, n)

    # Find the central indices of the resulting array
    index_low = int(outlen / 2.) - int(np.floor(origlen / 2))
    index_high = int(outlen / 2.) + int(np.ceil(origlen / 2))

    # Return an array the same length as the input.
    # Boundary effects are still visible and when overlap is not
    # complete zero values are assumed I believe.
    return out[..., index_low:index_high].copy()
Example #20
0
def heisenberg_H(L, Jx, Jy, Jz, hx, hy, hz):
    assert len(hy) == L
    assert len(hz) == L
    assert len(Jx) == len(Jy)
    assert len(Jx) == len(Jz)
    Jx, Jy, Jz, hx, hy, hz = np.array(Jx), np.array(Jy), np.array(
        Jz), np.array(hx), np.array(hy), np.array(hz),
    ret = np.zeros((2**L, 2**L),
                   dtype=np.common_type(Jx, Jy, Jz, hx, hy, hz,
                                        np.array(1.0j)))
    for i, Jxi, Jyi, Jzi in zip(range(L - 1), Jx[:L - 1], Jy[:L - 1],
                                Jz[:L - 1]):
        ret += Jxi * kron([ID] * i + [SX] + [SX] + [ID] * (L - i - 2))
        ret += Jyi * kron([ID] * i + [SY] + [SY] + [ID] * (L - i - 2))
        ret += Jzi * kron([ID] * i + [SZ] + [SZ] + [ID] * (L - i - 2))
    if len(Jx) == L and L > 1:
        ret += Jx[-1] * kron([SX] + [ID] * (L - 2) + [SX])
        ret += Jy[-1] * kron([SY] + [ID] * (L - 2) + [SY])
        ret += Jz[-1] * kron([SZ] + [ID] * (L - 2) + [SZ])
    for i, hxi, hyi, hzi in zip(range(L), hx, hy, hz):
        ret += hxi * kron([ID] * i + [SX] + [ID] * (L - i - 1))
        ret += hyi * kron([ID] * i + [SY] + [ID] * (L - i - 1))
        ret += hzi * kron([ID] * i + [SZ] + [ID] * (L - i - 1))
    return ret
Example #21
0
def convert_r2c_gen_schur(s, t, q=None, z=None):
    """Convert a real generallzed Schur form (with possibly 2x2 blocks on the
    diagonal) into a complex Schur form that is completely triangular.  If the
    input is already completely triagonal (real or complex), the input is
    returned unchanged.

    This function guarantees that in the case of a 2x2 block at rows and
    columns i and i+1, the converted, complex Schur form will contain the
    generalized eigenvalue with the positive imaginary part in s[i,i] and
    t[i,i], and the one with the negative imaginary part in s[i+1,i+1] and
    t[i+1,i+1].  This ensures that the list of eigenvalues (more precisely,
    their order) returned originally from gen_schur() is still valid for the
    newly formed complex Schur form.

    Parameters
    ----------
    s : array, shape (M, M)
    t : array, shape (M, M)
        Real generalized Schur form of the original matrix
    q : array, shape (M, M), optional
    z : array, shape (M, M), optional
        Schur transformation matrix. Default: None

    Returns
    -------
    s : array, shape (M, M)
    t : array, shape (M, M)
        Complex generalized Schur form of the original matrix,
        completely triagonal
    q : array, shape (M, M)
    z : array, shape (M, M)
        Schur transformation matrices corresponding to the complex
        form. `q` or `z` are only computed if they are provided (not
        None) on input.

    Raises
    ------
    LinAlgError
        If it fails to convert a 2x2 block into complex form (unlikely).
    """

    s, t, q, z = lapack.prepare_for_lapack(True, s, t, q, z)
    # Note: overwrite=True does not mean much here, the arrays are all copied

    if (s.ndim != 2 or t.ndim != 2 or (q is not None and q.ndim != 2)
            or (z is not None and z.ndim != 2)):
        raise ValueError("Expect matrices as input")

    if ((s.shape[0] != s.shape[1] or t.shape[0] != t.shape[1]
         or s.shape[0] != t.shape[0])
            or (q is not None and
                (q.shape[0] != q.shape[1] or s.shape[0] != q.shape[0]))
            or (z is not None and
                (z.shape[0] != z.shape[1] or s.shape[0] != z.shape[0]))):
        raise ValueError("Invalid Schur decomposition as input")

    # First, find the positions of 2x2-blocks.
    blockpos = np.diagonal(s, -1).nonzero()[0]

    # Check if there are actually any 2x2-blocks.
    if not blockpos.size:
        s2 = s
        t2 = t
        q2 = q
        z2 = z
    else:
        s2 = s.astype(np.common_type(s, np.array([], np.complex64)))
        t2 = t.astype(np.common_type(t, np.array([], np.complex64)))
        if q is not None:
            q2 = q.astype(np.common_type(q, np.array([], np.complex64)))
        if z is not None:
            z2 = z.astype(np.common_type(z, np.array([], np.complex64)))

    for i in blockpos:
        # In the following, we use gen_schur on individual 2x2 blocks (that are
        # promoted to complex form) to compute the complex generalized Schur
        # form. If necessary, order_gen_schur is used to ensure the desired
        # order of eigenvalues.

        sb, tb, qb, zb, alphab, betab = gen_schur(s2[i:i + 2, i:i + 2],
                                                  t2[i:i + 2, i:i + 2])

        # Ensure order of eigenvalues. (betab is positive)
        if alphab[0].imag < alphab[1].imag:
            sb, tb, qb, zb, alphab, betab = order_gen_schur([False, True], sb,
                                                            tb, qb, zb)

        s2[i:i + 2, i:i + 2] = sb
        t2[i:i + 2, i:i + 2] = tb

        s2[:i, i:i + 2] = np.dot(s2[:i, i:i + 2], zb)
        s2[i:i + 2, i + 2:] = np.dot(qb.T.conj(), s2[i:i + 2, i + 2:])
        t2[:i, i:i + 2] = np.dot(t2[:i, i:i + 2], zb)
        t2[i:i + 2, i + 2:] = np.dot(qb.T.conj(), t2[i:i + 2, i + 2:])

        if q is not None:
            q2[:, i:i + 2] = np.dot(q[:, i:i + 2], qb)
        if z is not None:
            z2[:, i:i + 2] = np.dot(z[:, i:i + 2], zb)

    if q is not None and z is not None:
        return s2, t2, q2, z2
    elif q is not None:
        return s2, t2, q2
    elif z is not None:
        return s2, t2, z2
    else:
        return s2, t2
Example #22
0
def vq(obs, code_book):
    """
    Assign codes from a code book to observations.

    Assigns a code from a code book to each observation. Each
    observation vector in the 'M' by 'N' `obs` array is compared with the
    centroids in the code book and assigned the code of the closest
    centroid.

    The features in `obs` should have unit variance, which can be
    achieved by passing them through the whiten function.  The code
    book can be created with the k-means algorithm or a different
    encoding algorithm.

    Parameters
    ----------
    obs : ndarray
        Each row of the 'M' x 'N' array is an observation.  The columns are
        the "features" seen during each observation. The features must be
        whitened first using the whiten function or something equivalent.
    code_book : ndarray
        The code book is usually generated using the k-means algorithm.
        Each row of the array holds a different code, and the columns are
        the features of the code.

         >>> #              f0    f1    f2   f3
         >>> code_book = [
         ...             [  1.,   2.,   3.,   4.],  #c0
         ...             [  1.,   2.,   3.,   4.],  #c1
         ...             [  1.,   2.,   3.,   4.]]  #c2

    Returns
    -------
    code : ndarray
        A length M array holding the code book index for each observation.
    dist : ndarray
        The distortion (distance) between the observation and its nearest
        code.

    Examples
    --------
    >>> from numpy import array
    >>> from scipy.cluster.vq import vq
    >>> code_book = array([[1.,1.,1.],
    ...                    [2.,2.,2.]])
    >>> features  = array([[  1.9,2.3,1.7],
    ...                    [  1.5,2.5,2.2],
    ...                    [  0.8,0.6,1.7]])
    >>> vq(features,code_book)
    (array([1, 1, 0],'i'), array([ 0.43588989,  0.73484692,  0.83066239]))

    """
    ct = common_type(obs, code_book)

    # avoid copying when dtype is the same
    # should be replaced with c_obs = astype(ct, copy=False)
    # when we get to numpy 1.7.0
    if obs.dtype != ct:
        c_obs = obs.astype(ct)
    else:
        c_obs = obs

    if code_book.dtype != ct:
        c_code_book = code_book.astype(ct)
    else:
        c_code_book = code_book

    if ct in (single, double):
        results = _vq.vq(c_obs, c_code_book)
    else:
        results = py_vq(obs, code_book)
    return results
Example #23
0
def arma_acovf(ar, ma, nobs=10, sigma2=1, dtype=None):
    """
    Theoretical autocovariance function of ARMA process

    Parameters
    ----------
    ar : array_like, 1d
        coefficient for autoregressive lag polynomial, including zero lag
    ma : array_like, 1d
        coefficient for moving-average lag polynomial, including zero lag
    nobs : int
        number of terms (lags plus zero lag) to include in returned acovf
    sigma2 : float
        Variance of the innovation term.

    Returns
    -------
    acovf : array
        autocovariance of ARMA process given by ar, ma

    See Also
    --------
    arma_acf
    acovf

    References
    ----------
    Brockwell, Peter J., and Richard A. Davis. 2009.
    Time Series: Theory and Methods. 2nd ed. 1991.
    New York, NY: Springer.

    """
    if dtype is None:
        dtype = np.common_type(np.array(ar), np.array(ma), np.array(sigma2))

    p = len(ar) - 1
    q = len(ma) - 1
    m = max(p, q) + 1

    if sigma2.real < 0:
        raise ValueError('Must have positive innovation variance.')

    # Short-circuit for trivial corner-case
    if p == q == 0:
        out = np.zeros(nobs, dtype=dtype)
        out[0] = sigma2
        return out

    # Get the moving average representation coefficients that we need
    ma_coeffs = arma2ma(ar, ma, lags=m)

    # Solve for the first m autocovariances via the linear system
    # described by (BD, eq. 3.3.8)
    A = np.zeros((m, m), dtype=dtype)
    b = np.zeros((m, 1), dtype=dtype)
    # We need a zero-right-padded version of ar params
    tmp_ar = np.zeros(m, dtype=dtype)
    tmp_ar[:p + 1] = ar
    for k in range(m):
        A[k, :(k + 1)] = tmp_ar[:(k + 1)][::-1]
        A[k, 1:m - k] += tmp_ar[(k + 1):m]
        b[k] = sigma2 * np.dot(ma[k:q + 1], ma_coeffs[:max((q + 1 - k), 0)])
    acovf = np.zeros(max(nobs, m), dtype=dtype)
    acovf[:m] = np.linalg.solve(A, b)[:, 0]

    # Iteratively apply (BD, eq. 3.3.9) to solve for remaining autocovariances
    if nobs > m:
        zi = signal.lfiltic([1], ar, acovf[:m:][::-1])
        acovf[m:] = signal.lfilter([1], ar, np.zeros(nobs - m, dtype=dtype),
                                   zi=zi)[0]

    return acovf[:nobs]
Example #24
0
    def diags(diagonals, offsets, shape=None, format=None, dtype=None):
        """
Note: copied from scipy.sparse.construct

Construct a sparse matrix from diagonals.

.. versionadded:: 0.11

Parameters
----------
diagonals : sequence of array_like
Sequence of arrays containing the matrix diagonals,
corresponding to `offsets`.
offsets : sequence of int
Diagonals to set:
- k = 0 the main diagonal
- k > 0 the k-th upper diagonal
- k < 0 the k-th lower diagonal
shape : tuple of int, optional
Shape of the result. If omitted, a square matrix large enough
to contain the diagonals is returned.
format : {"dia", "csr", "csc", "lil", ...}, optional
Matrix format of the result. By default (format=None) an
appropriate sparse matrix format is returned. This choice is
subject to change.
dtype : dtype, optional
Data type of the matrix.

See Also
--------
spdiags : construct matrix from diagonals

Notes
-----
This function differs from `spdiags` in the way it handles
off-diagonals.

The result from `diags` is the sparse equivalent of::

np.diag(diagonals[0], offsets[0])
+ ...
+ np.diag(diagonals[k], offsets[k])

Repeated diagonal offsets are disallowed.

Examples
--------
>>> diagonals = [[1,2,3,4], [1,2,3], [1,2]]
>>> diags(diagonals, [0, -1, 2]).todense()
matrix([[1., 0., 1., 0.],
[1., 2., 0., 2.],
[0., 2., 3., 0.],
[0., 0., 3., 4.]])

Broadcasting of scalars is supported (but shape needs to be
specified):

>>> diags([1, -2, 1], [-1, 0, 1], shape=(4, 4)).todense()
matrix([[-2., 1., 0., 0.],
[ 1., -2., 1., 0.],
[ 0., 1., -2., 1.],
[ 0., 0., 1., -2.]])


If only one diagonal is wanted (as in `numpy.diag`), the following
works as well:

>>> diags([1, 2, 3], 1).todense()
matrix([[ 0., 1., 0., 0.],
[ 0., 0., 2., 0.],
[ 0., 0., 0., 3.],
[ 0., 0., 0., 0.]])
"""
        # if offsets is not a sequence, assume that there's only one diagonal
        try:
            iter(offsets)
        except TypeError:
            # now check that there's actually only one diagonal
            try:
                iter(diagonals[0])
            except TypeError:
                diagonals = [np.atleast_1d(diagonals)]
            else:
                raise ValueError("Different number of diagonals and offsets.")
        else:
            diagonals = list(map(np.atleast_1d, diagonals))
        offsets = np.atleast_1d(offsets)
    
        # Basic check
        if len(diagonals) != len(offsets):
            raise ValueError("Different number of diagonals and offsets.")
    
        # Determine shape, if omitted
        if shape is None:
            m = len(diagonals[0]) + abs(int(offsets[0]))
            shape = (m, m)
    
        # Determine data type, if omitted
        if dtype is None:
            dtype = np.common_type(*diagonals)
    
        # Construct data array
        m, n = shape
    
        M = max([min(m + offset, n - offset) + max(0, offset)
                 for offset in offsets])
        M = max(0, M)
        data_arr = np.zeros((len(offsets), M), dtype=dtype)
    
        for j, diagonal in enumerate(diagonals):
            offset = offsets[j]
            k = max(0, offset)
            length = min(m + offset, n - offset)
            if length <= 0:
                raise ValueError("Offset %d (index %d) out of bounds" % (offset, j))
            try:
                data_arr[j, k:k+length] = diagonal
            except ValueError:
                if len(diagonal) != length and len(diagonal) != 1:
                    raise ValueError(
                        "Diagonal length (index %d: %d at offset %d) does not "
                        "agree with matrix size (%d, %d)." % (
                        j, len(diagonal), offset, m, n))
                raise
    
        return dia_matrix((data_arr, offsets), shape=(m, n)).asformat(format)
Example #25
0
def as_series(alist, trim=True) :
    """
    Return argument as a list of 1-d arrays.

    The returned list contains array(s) of dtype double, complex double, or
    object.  A 1-d argument of shape ``(N,)`` is parsed into ``N`` arrays of
    size one; a 2-d argument of shape ``(M,N)`` is parsed into ``M`` arrays
    of size ``N`` (i.e., is "parsed by row"); and a higher dimensional array
    raises a Value Error if it is not first reshaped into either a 1-d or 2-d
    array.

    Parameters
    ----------
    a : array_like
        A 1- or 2-d array_like
    trim : boolean, optional
        When True, trailing zeros are removed from the inputs.
        When False, the inputs are passed through intact.

    Returns
    -------
    [a1, a2,...] : list of 1-D arrays
        A copy of the input data as a list of 1-d arrays.

    Raises
    ------
    ValueError :
        Raised when `as_series` cannot convert its input to 1-d arrays, or at
        least one of the resulting arrays is empty.

    Examples
    --------
    >>> from numpy import polynomial as P
    >>> a = np.arange(4)
    >>> P.as_series(a)
    [array([ 0.]), array([ 1.]), array([ 2.]), array([ 3.])]
    >>> b = np.arange(6).reshape((2,3))
    >>> P.as_series(b)
    [array([ 0.,  1.,  2.]), array([ 3.,  4.,  5.])]

    """
    arrays = [np.array(a, ndmin=1, copy=0) for a in alist]
    if min([a.size for a in arrays]) == 0 :
        raise ValueError("Coefficient array is empty")
    if any([a.ndim != 1 for a in arrays]) :
        raise ValueError("Coefficient array is not 1-d")
    if trim :
        arrays = [trimseq(a) for a in arrays]

    if any([a.dtype == np.dtype(object) for a in arrays]) :
        ret = []
        for a in arrays :
            if a.dtype != np.dtype(object) :
                tmp = np.empty(len(a), dtype=np.dtype(object))
                tmp[:] = a[:]
                ret.append(tmp)
            else :
                ret.append(a.copy())
    else :
        try :
            dtype = np.common_type(*arrays)
        except :
            raise ValueError("Coefficient arrays have no common type")
        ret = [np.array(a, copy=1, dtype=dtype) for a in arrays]
    return ret
Example #26
0
def true_divide(
    x1: PolyLike,
    x2: PolyLike,
    out: Optional[ndpoly] = None,
    where: numpy.typing.ArrayLike = True,
    **kwargs: Any,
) -> ndpoly:
    """
    Return true division of the inputs, element-wise.

    Instead of the Python traditional 'floor division', this returns a true
    division.  True division adjusts the output type to present the best
    answer, regardless of input types.

    Args:
        x1:
            Dividend array.
        x2:
            Divisor array. If ``x1.shape != x2.shape``, they must be
            broadcastable to a common shape (which becomes the shape of the
            output).
        out:
            A location into which the result is stored. If provided, it must
            have a shape that the inputs broadcast to. If not provided or
            `None`, a freshly-allocated array is returned. A tuple (possible
            only as a keyword argument) must have length equal to the number of
            outputs.
        where:
            This condition is broadcast over the input. At locations where the
            condition is True, the `out` array will be set to the ufunc result.
            Elsewhere, the `out` array will retain its original value. Note
            that if an uninitialized `out` array is created via the default
            ``out=None``, locations within it where the condition is False will
            remain uninitialized.
        kwargs:
            Keyword args passed to numpy.ufunc.

    Returns:
        This is a scalar if both `x1` and `x2` are scalars.

    Raises:
        numpoly.baseclass.FeatureNotSupported:
            If `x2` contains indeterminants, numerical division is no longer
            possible and an error is raised instead. For polynomial
            division see ``numpoly.poly_divide``.

    Examples:
        >>> q0q1q2 = numpoly.variable(3)
        >>> numpoly.true_divide(q0q1q2, 4)
        polynomial([0.25*q0, 0.25*q1, 0.25*q2])
        >>> numpoly.true_divide(q0q1q2, [1, 2, 4])
        polynomial([q0, 0.5*q1, 0.25*q2])

    """
    x1, x2 = numpoly.align_polynomials(x1, x2)
    if not x2.isconstant():
        raise numpoly.FeatureNotSupported(DIVIDE_ERROR_MSG)
    x2 = x2.tonumpy()
    if out is None:
        out_ = numpoly.ndpoly(
            exponents=x1.exponents,
            shape=x1.shape,
            names=x1.indeterminants,
            dtype=numpy.common_type(x1, numpy.array(1.)),
        )
    else:
        assert len(out) == 1
        out_ = out[0]
    assert isinstance(out_, numpoly.ndpoly)
    for key in x1.keys:
        out_[key] = 0
        numpy.true_divide(x1.values[key],
                          x2,
                          out=out_.values[key],
                          where=numpy.asarray(where),
                          **kwargs)
    if out is None:
        out_ = numpoly.clean_attributes(out_)
    return out_
Example #27
0
File: vq.py Project: gwang-cv/scipy
def vq(obs, code_book, check_finite=True):
    """
    Assign codes from a code book to observations.

    Assigns a code from a code book to each observation. Each
    observation vector in the 'M' by 'N' `obs` array is compared with the
    centroids in the code book and assigned the code of the closest
    centroid.

    The features in `obs` should have unit variance, which can be
    achieved by passing them through the whiten function.  The code
    book can be created with the k-means algorithm or a different
    encoding algorithm.

    Parameters
    ----------
    obs : ndarray
        Each row of the 'M' x 'N' array is an observation.  The columns are
        the "features" seen during each observation. The features must be
        whitened first using the whiten function or something equivalent.
    code_book : ndarray
        The code book is usually generated using the k-means algorithm.
        Each row of the array holds a different code, and the columns are
        the features of the code.

         >>> #              f0    f1    f2   f3
         >>> code_book = [
         ...             [  1.,   2.,   3.,   4.],  #c0
         ...             [  1.,   2.,   3.,   4.],  #c1
         ...             [  1.,   2.,   3.,   4.]]  #c2

    check_finite : bool, optional
        Whether to check that the input matrices 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: True

    Returns
    -------
    code : ndarray
        A length M array holding the code book index for each observation.
    dist : ndarray
        The distortion (distance) between the observation and its nearest
        code.

    Examples
    --------
    >>> from numpy import array
    >>> from scipy.cluster.vq import vq
    >>> code_book = array([[1.,1.,1.],
    ...                    [2.,2.,2.]])
    >>> features  = array([[  1.9,2.3,1.7],
    ...                    [  1.5,2.5,2.2],
    ...                    [  0.8,0.6,1.7]])
    >>> vq(features,code_book)
    (array([1, 1, 0],'i'), array([ 0.43588989,  0.73484692,  0.83066239]))

    """
    obs = _asarray_validated(obs, check_finite=check_finite)
    code_book = _asarray_validated(code_book, check_finite=check_finite)
    ct = common_type(obs, code_book)

    c_obs = obs.astype(ct, copy=False)

    if code_book.dtype != ct:
        c_code_book = code_book.astype(ct)
    else:
        c_code_book = code_book

    if ct in (single, double):
        results = _vq.vq(c_obs, c_code_book)
    else:
        results = py_vq(obs, code_book)
    return results
Example #28
0
def matvec(cc, vector, k):
    '''2ph operators are of the form s_{ij}^{ b}, i.e. 'jb' indices are coupled.'''
    # Ref: Nooijen and Snijders, J. Chem. Phys. 102, 1681 (1995) Eqs.(8)-(9)
    if not cc.imds.made_ip_imds:
        cc.imds.make_ip(cc.ip_partition)
    imds = cc.imds

    vector = mask_frozen(cc, vector, k, const=0.0)
    r1, r2 = vector_to_amplitudes(cc, vector, k)

    t1, t2 = cc.t1, cc.t2
    nkpts = cc.nkpts
    kconserv = cc.khelper.kconserv

    # 1h-1h block
    Hr1 = -einsum('ki,k->i', imds.Loo[k], r1)
    # 1h-2h1p block
    for kl in range(nkpts):
        Hr1 += 2. * einsum('ld,ild->i', imds.Fov[kl], r2[k, kl])
        Hr1 += -einsum('ld,lid->i', imds.Fov[kl], r2[kl, k])
        for kk in range(nkpts):
            kd = kconserv[kk, k, kl]
            Hr1 += -2. * einsum('klid,kld->i', imds.Wooov[kk, kl, k], r2[kk, kl])
            Hr1 += einsum('lkid,kld->i', imds.Wooov[kl, kk, k], r2[kk, kl])

    Hr2 = np.zeros(r2.shape, dtype=np.common_type(imds.Wovoo[0, 0, 0], r1))
    # 2h1p-1h block
    for ki in range(nkpts):
        for kj in range(nkpts):
            kb = kconserv[ki, k, kj]
            Hr2[ki, kj] -= einsum('kbij,k->ijb', imds.Wovoo[k, kb, ki], r1)
    # 2h1p-2h1p block
    if cc.ip_partition == 'mp':
        nkpts, nocc, nvir = cc.t1.shape
        fock = cc.eris.fock
        foo = fock[:, :nocc, :nocc]
        fvv = fock[:, nocc:, nocc:]
        for ki in range(nkpts):
            for kj in range(nkpts):
                kb = kconserv[ki, k, kj]
                Hr2[ki, kj] += einsum('bd,ijd->ijb', fvv[kb], r2[ki, kj])
                Hr2[ki, kj] -= einsum('li,ljb->ijb', foo[ki], r2[ki, kj])
                Hr2[ki, kj] -= einsum('lj,ilb->ijb', foo[kj], r2[ki, kj])
    elif cc.ip_partition == 'full':
        Hr2 += cc._ipccsd_diag_matrix2 * r2
    else:
        for ki in range(nkpts):
            for kj in range(nkpts):
                kb = kconserv[ki, k, kj]
                Hr2[ki, kj] += einsum('bd,ijd->ijb', imds.Lvv[kb], r2[ki, kj])
                Hr2[ki, kj] -= einsum('li,ljb->ijb', imds.Loo[ki], r2[ki, kj])
                Hr2[ki, kj] -= einsum('lj,ilb->ijb', imds.Loo[kj], r2[ki, kj])
                for kl in range(nkpts):
                    kk = kconserv[ki, kl, kj]
                    Hr2[ki, kj] += einsum('klij,klb->ijb', imds.Woooo[kk, kl, ki], r2[kk, kl])
                    kd = kconserv[kl, kj, kb]
                    Hr2[ki, kj] += 2. * einsum('lbdj,ild->ijb', imds.Wovvo[kl, kb, kd], r2[ki, kl])
                    Hr2[ki, kj] += -einsum('lbdj,lid->ijb', imds.Wovvo[kl, kb, kd], r2[kl, ki])
                    Hr2[ki, kj] += -einsum('lbjd,ild->ijb', imds.Wovov[kl, kb, kj], r2[ki, kl])  # typo in Ref
                    kd = kconserv[kl, ki, kb]
                    Hr2[ki, kj] += -einsum('lbid,ljd->ijb', imds.Wovov[kl, kb, ki], r2[kl, kj])
        tmp = (2. * einsum('xyklcd,xykld->c', imds.Woovv[:, :, k], r2[:, :])
               - einsum('yxlkcd,xykld->c', imds.Woovv[:, :, k], r2[:, :]))
        Hr2[:, :] += -einsum('c,xyijcb->xyijb', tmp, t2[:, :, k])

    return mask_frozen(cc, amplitudes_to_vector(cc, Hr1, Hr2, k), k, const=0.0)
Example #29
0
def as_series(alist, trim=True):
    """
    Return argument as a list of 1-d arrays.

    The returned list contains array(s) of dtype double, complex double, or
    object.  A 1-d argument of shape ``(N,)`` is parsed into ``N`` arrays of
    size one; a 2-d argument of shape ``(M,N)`` is parsed into ``M`` arrays
    of size ``N`` (i.e., is "parsed by row"); and a higher dimensional array
    raises a Value Error if it is not first reshaped into either a 1-d or 2-d
    array.

    Parameters
    ----------
    alist : array_like
        A 1- or 2-d array_like
    trim : boolean, optional
        When True, trailing zeros are removed from the inputs.
        When False, the inputs are passed through intact.

    Returns
    -------
    [a1, a2,...] : list of 1-D arrays
        A copy of the input data as a list of 1-d arrays.

    Raises
    ------
    ValueError
        Raised when `as_series` cannot convert its input to 1-d arrays, or at
        least one of the resulting arrays is empty.

    Examples
    --------
    >>> from numpy.polynomial import polyutils as pu
    >>> a = np.arange(4)
    >>> pu.as_series(a)
    [array([0.]), array([1.]), array([2.]), array([3.])]
    >>> b = np.arange(6).reshape((2,3))
    >>> pu.as_series(b)
    [array([0., 1., 2.]), array([3., 4., 5.])]

    >>> pu.as_series((1, np.arange(3), np.arange(2, dtype=np.float16)))
    [array([1.]), array([0., 1., 2.]), array([0., 1.])]

    >>> pu.as_series([2, [1.1, 0.]])
    [array([2.]), array([1.1])]

    >>> pu.as_series([2, [1.1, 0.]], trim=False)
    [array([2.]), array([1.1, 0. ])]

    """
    arrays = [np.array(a, ndmin=1, copy=False) for a in alist]
    if min([a.size for a in arrays]) == 0:
        raise ValueError("Coefficient array is empty")
    if any(a.ndim != 1 for a in arrays):
        raise ValueError("Coefficient array is not 1-d")
    if trim:
        arrays = [trimseq(a) for a in arrays]

    if any(a.dtype == np.dtype(object) for a in arrays):
        ret = []
        for a in arrays:
            if a.dtype != np.dtype(object):
                tmp = np.empty(len(a), dtype=np.dtype(object))
                tmp[:] = a[:]
                ret.append(tmp)
            else:
                ret.append(a.copy())
    else:
        try:
            dtype = np.common_type(*arrays)
        except Exception as e:
            raise ValueError("Coefficient arrays have no common type") from e
        ret = [np.array(a, copy=True, dtype=dtype) for a in arrays]
    return ret
Example #30
0
def unified_eigenproblem(a, b=None, tol=1e6):
    """A helper routine for modes(), that wraps eigenproblems.

    This routine wraps the regular and general eigenproblems that can arise
    in a unfied way.

    Parameters
    ----------
    a : numpy array
        The matrix on the left hand side of a regular or generalized eigenvalue
        problem.
    b : numpy array or None
        The matrix on the right hand side of the generalized eigenvalue problem.
    tol : float
        The tolerance for separating eigenvalues with absolute value 1 from the
        rest.

    Returns
    -------
    ev : numpy array
        An array of eigenvalues (can contain NaNs and Infs, but those
        are not accessed in `modes()`) The number of eigenvalues equals
        twice the number of nonzero singular values of
        `h_hop` (so `2*h_cell.shape[0]` if `h_hop` is invertible).
    evanselect : numpy integer array
        Index array of right-decaying modes.
    propselect : numpy integer array
        Index array of propagating modes (both left and right).
    vec_gen(select) : function
        A function that computes the eigenvectors chosen by the array select.
    ord_schur(select) : function
        A function that computes the unitary matrix (corresponding to the right
        eigenvector space) of the (general) Schur decomposition reordered such
        that the eigenvalues chosen by the array select are in the top left
        block.
    """
    if b is None:
        eps = np.finfo(a.dtype).eps * tol
        t, z, ev = kla.schur(a)

        # Right-decaying modes.
        select = abs(ev) > 1 + eps
        # Propagating modes.
        propselect = abs(abs(ev) - 1) < eps

        vec_gen = lambda x: kla.evecs_from_schur(t, z, select=x)
        ord_schur = lambda x: kla.order_schur(x, t, z, calc_ev=False)[1]

    else:
        eps = np.finfo(np.common_type(a, b)).eps * tol
        s, t, z, alpha, beta = kla.gen_schur(a, b, calc_q=False)

        # Right-decaying modes.
        select = abs(alpha) > (1 + eps) * abs(beta)
        # Propagating modes.
        propselect = (abs(abs(alpha) - abs(beta)) < eps * abs(beta))

        with np.errstate(divide='ignore', invalid='ignore'):
            ev = alpha / beta
        # Note: the division is OK here, since we later only access
        #       eigenvalues close to the unit circle

        vec_gen = lambda x: kla.evecs_from_gen_schur(s, t, z=z, select=x)
        ord_schur = lambda x: kla.order_gen_schur(x, s, t, z=z,
                                                  calc_ev=False)[2]

    return ev, select, propselect, vec_gen, ord_schur
        def lstsq(a,
                  b,
                  cond=None,
                  overwrite_a=False,
                  overwrite_b=False,
                  check_finite=True,
                  lapack_driver=None):
            """
            Compute least-squares solution to equation Ax = b.
            Compute a vector x such that the 2-norm ``|b - A x|`` is minimized.

            This code was adapted from the Scipy distribution: https://github.com/scipy/scipy/blob/v1.2.1/scipy/linalg/basic.py#L1047-L1264

            Parameters
            ----------
            a : (M, N) array_like
                Left hand side matrix (2-D array).
            b : (M,) or (M, K) array_like
                Right hand side matrix or vector (1-D or 2-D array).
            cond : float, optional
                Cutoff for 'small' singular values; used to determine effective
                rank of a. Singular values smaller than
                ``rcond * largest_singular_value`` are considered zero.
            overwrite_a : bool, optional
                Discard data in `a` (may enhance performance). Default is False.
            overwrite_b : bool, optional
                Discard data in `b` (may enhance performance). Default is False.
            check_finite : bool, optional
                Whether to check that the input matrices 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.
            lapack_driver : str, optional
                Which LAPACK driver is used to solve the least-squares problem.
                Options are ``'gelsd'``, ``'gelsy'``, ``'gelss'``. Default
                (``'gelsd'``) is a good choice.  However, ``'gelsy'`` can be slightly
                faster on many problems.  ``'gelss'`` was used historically.  It is
                generally slow but uses less memory.
                .. versionadded:: 0.17.0
            Returns
            -------
            x : (N,) or (N, K) ndarray
                Least-squares solution.  Return shape matches shape of `b`.
            residues : (0,) or () or (K,) ndarray
                Sums of residues, squared 2-norm for each column in ``b - a x``.
                If rank of matrix a is ``< N`` or ``N > M``, or ``'gelsy'`` is used,
                this is a length zero array. If b was 1-D, this is a () shape array
                (numpy scalar), otherwise the shape is (K,).
            rank : int
                Effective rank of matrix `a`.
            s : (min(M,N),) ndarray or None
                Singular values of `a`. The condition number of a is
                ``abs(s[0] / s[-1])``. None is returned when ``'gelsy'`` is used.
            Raises
            ------
            LinAlgError
                If computation does not converge.
            ValueError
                When parameters are wrong.
            See Also
            --------
            optimize.nnls : linear least squares with non-negativity constraint
            Examples
            --------
            >>> from scipy.linalg import lstsq
            >>> import matplotlib.pyplot as plt
            Suppose we have the following data:
            >>> x = np.array([1, 2.5, 3.5, 4, 5, 7, 8.5])
            >>> y = np.array([0.3, 1.1, 1.5, 2.0, 3.2, 6.6, 8.6])
            We want to fit a quadratic polynomial of the form ``y = a + b*x**2``
            to this data.  We first form the "design matrix" M, with a constant
            column of 1s and a column containing ``x**2``:
            >>> M = x[:, np.newaxis]**[0, 2]
            >>> M
            array([[  1.  ,   1.  ],
                   [  1.  ,   6.25],
                   [  1.  ,  12.25],
                   [  1.  ,  16.  ],
                   [  1.  ,  25.  ],
                   [  1.  ,  49.  ],
                   [  1.  ,  72.25]])
            We want to find the least-squares solution to ``M.dot(p) = y``,
            where ``p`` is a vector with length 2 that holds the parameters
            ``a`` and ``b``.
            >>> p, res, rnk, s = lstsq(M, y)
            >>> p
            array([ 0.20925829,  0.12013861])
            Plot the data and the fitted curve.
            >>> plt.plot(x, y, 'o', label='data')
            >>> xx = np.linspace(0, 9, 101)
            >>> yy = p[0] + p[1]*xx**2
            >>> plt.plot(xx, yy, label='least squares fit, $y = a + bx^2$')
            >>> plt.xlabel('x')
            >>> plt.ylabel('y')
            >>> plt.legend(framealpha=1, shadow=True)
            >>> plt.grid(alpha=0.25)
            >>> plt.show()
            """

            a1 = _asarray_validated(a, check_finite=check_finite)
            b1 = _asarray_validated(b, check_finite=check_finite)
            if len(a1.shape) != 2:
                raise ValueError('expected matrix')
            m, n = a1.shape

            if len(b1.shape) == 2:
                nrhs = b1.shape[1]
            else:
                nrhs = 1
            if m != b1.shape[0]:
                raise ValueError('incompatible dimensions')
            if m == 0 or n == 0:  # Zero-sized problem, confuses LAPACK
                x = np.zeros((n, ) + b1.shape[1:],
                             dtype=np.common_type(a1, b1))
                if n == 0:
                    residues = np.linalg.norm(b1, axis=0)**2
                else:
                    residues = np.empty((0, ))
                return x, residues, 0, np.empty((0, ))

            driver = lapack_driver
            if driver is None:
                global default_lapack_driver
                driver = default_lapack_driver
            if driver not in ('gelsd', 'gelsy', 'gelss'):
                raise ValueError('LAPACK driver "%s" is not found' % driver)

            lapack_func, lapack_lwork = get_lapack_funcs(
                (driver, '%s_lwork' % driver), (a1, b1))
            real_data = True if (lapack_func.dtype.kind == 'f') else False

            if m < n:
                # need to extend b matrix as it will be filled with
                # a larger solution matrix
                if len(b1.shape) == 2:
                    b2 = np.zeros((n, nrhs), dtype=lapack_func.dtype)
                    b2[:m, :] = b1
                else:
                    b2 = np.zeros(n, dtype=lapack_func.dtype)
                    b2[:m] = b1
                b1 = b2

            overwrite_a = overwrite_a or _datacopied(a1, a)
            overwrite_b = overwrite_b or _datacopied(b1, b)

            if cond is None:
                cond = np.finfo(lapack_func.dtype).eps

            a1_wrk = np.copy(a1)
            b1_wrk = np.copy(b1)
            lwork, iwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
            x_check, s_check, rank_check, info = lapack_func(
                a1_wrk, b1_wrk, lwork, iwork, cond, False, False)

            driver = 'gelss'
            if driver in ('gelss', 'gelsd'):
                if driver == 'gelss':
                    if not context:
                        a1_wrk = np.copy(a1)
                        b1_wrk = np.copy(b1)
                        lwork, iwork = _compute_lwork(lapack_lwork, m, n, nrhs,
                                                      cond)
                        x, s, rank, info = lapack_func(a1_wrk, b1_wrk, lwork,
                                                       iwork, cond, False,
                                                       False)
                    else:
                        try:
                            # Check that we aren't dealing with an underconstrained problem ...
                            if m < n:
                                pkg.log.error(
                                    Exception(
                                        "Underconstrained problems not yet supported by Magma."
                                    ))

                            # Initialize
                            a1_trans = np.copy(a1, order='F')
                            a1_gpu = gpuarray.to_gpu(a1_trans)

                            # Note that the result for 'x' gets written to the vector inputted for b
                            x_trans = np.copy(b1, order='F')
                            x_gpu = gpuarray.to_gpu(x_trans)

                            # Init singular-value decomposition (SVD) output & buffer arrays
                            s = np.zeros(min(m, n), np.float32)
                            u = np.zeros((m, m), np.float32)
                            vh = np.zeros((n, n), np.float32)

                            # Query and allocate optimal workspace
                            # n.b.: - the result for 'x' gets written to the input vector for b, so we just label b->x
                            #       - assume magma variables lda=ldb=m throughout here
                            lwork_SVD = magma.magma_sgesvd_buffersize(
                                'A', 'A', m, n, a1_trans.ctypes.data, m,
                                s.ctypes.data, u.ctypes.data, m,
                                vh.ctypes.data, n)

                            # For some reason, magma_sgels_buffersize() does not return the right value for large problems, so
                            # we compute the values used for the validation check (see Magma SGELS documentation) directly and use that
                            #lwork_LS = magma.magma_sgels_buffersize('n', m, n, nrhs, a1_trans.ctypes.data, m, x_trans.ctypes.data, m)
                            nb = magma.magma_get_sgeqrf_nb(m, n)
                            check = (m - n + nb) * (nrhs + nb) + nrhs * nb
                            lwork_LS = check

                            # Allocate workspaces
                            hwork_SVD = np.zeros(lwork_SVD,
                                                 np.float32,
                                                 order='F')
                            hwork_LS = np.zeros(lwork_LS, np.float32)

                            # Compute SVD
                            timer.start("SVD")
                            magma.magma_sgesvd('A', 'A', m, n,
                                               a1_trans.ctypes.data, m,
                                               s.ctypes.data, u.ctypes.data, m,
                                               vh.ctypes.data, n,
                                               hwork_SVD.ctypes.data,
                                               lwork_SVD)
                            timer.stop("SVD")

                            # Note, the use of s_i>rcond here; this is meant to select
                            # values that are effectively non-zero.  Results will depend
                            # somewhat on the choice for this value.  This criterion was
                            # adopted from that utilized by scipy.linalg.basic.lstsq()
                            rcond = np.finfo(lapack_func.dtype).eps * s[0]
                            rank = sum(1 for s_i in s if s_i > rcond)

                            # Run LS solver
                            timer.start("LS")
                            magma.magma_sgels_gpu('n', m, n, nrhs,
                                                  a1_gpu.gpudata, m,
                                                  x_gpu.gpudata, m,
                                                  hwork_LS.ctypes.data,
                                                  lwork_LS)
                            timer.stop("LS")

                            # Unload result from GPU
                            x = x_gpu.get()

                        except magma.MagmaError as e:
                            info = e._status
                        else:
                            info = 0

                elif driver == 'gelsd':
                    if real_data:
                        if not context:
                            raise Exception(
                                "For some reason, the CUDA implementation of fit() is being called when context is False."
                            )
                        else:
                            raise Exception(
                                "gelsd not supported using Cuda yet")
                    else:  # complex data
                        raise LinAlgError(
                            "driver=%s not yet supported for complex data" %
                            (driver))
                if info > 0:
                    raise LinAlgError(
                        "SVD did not converge in Linear Least Squares")
                if info < 0:
                    raise ValueError(
                        'illegal value in %d-th argument of internal %s' %
                        (-info, lapack_driver))
                resids = np.asarray([], dtype=x.dtype)
                if m > n:
                    x1 = x[:n]
                    if rank == n:
                        resids = np.sum(np.abs(x[n:])**2, axis=0)
                    x = x1

            elif driver == 'gelsy':
                raise LinAlgError("driver=%s not yet supported" % (driver))

            #pkg.log.close("Done", time_elapsed=True)
            return x, resids, rank, s
Example #32
0
 def _matvec(self, vec):
     v = np.array(np.ravel(vec), dtype=np.common_type(vec, self.diag))
     fwht(v)
     v *= self.diag / v.shape[0]
     fwht(v)
     return v
Example #33
0
def divide(x1, x2, out=None, where=True, **kwargs):
    """
    Return a true division of the inputs, element-wise.

    Instead of the Python traditional 'floor division', this returns a true
    division.  True division adjusts the output type to present the best
    answer, regardless of input types.

    Args:
        x1 (numpoly.ndpoly):
            Dividend array.
        x2 (numpoly.ndpoly):
            Divisor array. If ``x1.shape != x2.shape``, they must be
            broadcastable to a commo n shape (which becomes the shape of the
            output).
        out (Optional[numpy.ndarray]):
            A location into which the result is stored. If provided, it must
            have a shape that the inputs broadcast to. If not provided or
            `None`, a freshly-allocated array is returned. A tuple (possible
            only as a keyword argument) must have length equal to the number of
            outputs.
        where (Optional[numpy.ndarray]):
            This condition is broadcast over the input. At locations where the
            condition is True, the `out` array will be set to the ufunc result.
            Elsewhere, the `out` array will retain its original value. Note
            that if an uninitialized `out` array is created via the default
            ``out=None``, locations within it where the condition is False will
            remain uninitialized.
        kwargs:
            Keyword args passed to numpy.ufunc.

    Returns:
        (numpoly.ndpoly):
            This is a scalar if both `x1` and `x2` are scalars.

    Examples:
        >>> xyz = numpoly.symbols("x y z")
        >>> numpoly.divide(xyz, 4)
        polynomial([0.25*x, 0.25*y, 0.25*z])
        >>> numpoly.divide(xyz, [1, 2, 4])
        polynomial([x, 0.5*y, 0.25*z])
        >>> numpoly.divide([1, 2, 4], xyz)
        Traceback (most recent call last):
            ...
        ValueError: only constant polynomials can be converted to array.

    """
    x1, x2 = numpoly.align_polynomials(x1, x2)
    x2 = x2.tonumpy()
    no_output = out is None
    if no_output:
        out = numpoly.ndpoly(
            exponents=x1.exponents,
            shape=x1.shape,
            names=x1.indeterminants,
            dtype=numpy.common_type(x1, numpy.array(1.)),
        )
    elif not isinstance(out, numpy.ndarray):
        assert len(out) == 1, "only one output"
        out = out[0]
    for key in x1.keys:
        out[key] = 0
        numpy.true_divide(x1[key], x2, out=out[key], where=where, **kwargs)
    if no_output:
        out = numpoly.clean_attributes(out)
    return out
Example #34
0
def vq(obs, code_book):
    """
    Assign codes from a code book to observations.

    Assigns a code from a code book to each observation. Each
    observation vector in the 'M' by 'N' `obs` array is compared with the
    centroids in the code book and assigned the code of the closest
    centroid.

    The features in `obs` should have unit variance, which can be
    acheived by passing them through the whiten function.  The code
    book can be created with the k-means algorithm or a different
    encoding algorithm.

    Parameters
    ----------
    obs : ndarray
        Each row of the 'N' x 'M' array is an observation.  The columns are
        the "features" seen during each observation. The features must be
        whitened first using the whiten function or something equivalent.
    code_book : ndarray
        The code book is usually generated using the k-means algorithm.
        Each row of the array holds a different code, and the columns are
        the features of the code.

         >>> #              f0    f1    f2   f3
         >>> code_book = [
         ...             [  1.,   2.,   3.,   4.],  #c0
         ...             [  1.,   2.,   3.,   4.],  #c1
         ...             [  1.,   2.,   3.,   4.]]) #c2

    Returns
    -------
    code : ndarray
        A length N array holding the code book index for each observation.
    dist : ndarray
        The distortion (distance) between the observation and its nearest
        code.

    Notes
    -----
    This currently forces 32-bit math precision for speed.  Anyone know
    of a situation where this undermines the accuracy of the algorithm?

    Examples
    --------
    >>> from numpy import array
    >>> from scipy.cluster.vq import vq
    >>> code_book = array([[1.,1.,1.],
    ...                    [2.,2.,2.]])
    >>> features  = array([[  1.9,2.3,1.7],
    ...                    [  1.5,2.5,2.2],
    ...                    [  0.8,0.6,1.7]])
    >>> vq(features,code_book)
    (array([1, 1, 0],'i'), array([ 0.43588989,  0.73484692,  0.83066239]))

    """
    try:
        import _vq
        ct = common_type(obs, code_book)
        c_obs = obs.astype(ct)
        c_code_book = code_book.astype(ct)
        if ct is single:
            results = _vq.vq(c_obs, c_code_book)
        elif ct is double:
            results = _vq.vq(c_obs, c_code_book)
        else:
            results = py_vq(obs, code_book)
    except ImportError:
        results = py_vq(obs, code_book)
    return results
Example #35
0
def make_proper_modes(lmbdainv, psi, extract, tol=1e6, *, particle_hole=None,
                      time_reversal=None, chiral=None):
    """
    Find, normalize and sort the propagating eigenmodes.

    Special care is taken of the case of degenerate k-values, where the
    numerically computed modes are typically a superposition of the real
    modes. In this case, also the proper (orthogonal) modes are computed.
    """
    vel_eps = np.finfo(psi.dtype).eps * tol

    nmodes = psi.shape[1]
    n = len(psi) // 2

    # Array for the velocities.
    velocities = np.empty(nmodes, dtype=float)

    # Array of indices to sort modes at a TRIM by PHS.
    TRIM_PHS_sort = np.zeros(nmodes, dtype=int)

    # Calculate the full wave function in real space.
    full_psi = extract(psi, lmbdainv)

    # Find clusters of nearby eigenvalues. Since the eigenvalues occupy the
    # unit circle, special care has to be taken to not introduce a cut at
    # lambda = -1.
    eps = np.finfo(lmbdainv.dtype).eps * tol
    angles = np.angle(lmbdainv)
    sort_order = np.resize(np.argsort(angles), (2 * len(angles,)))
    boundaries = np.argwhere(np.abs(np.diff(lmbdainv[sort_order]))
                             > eps).flatten() + 1

    # Detect the singular case of all eigenvalues equal.
    if boundaries.shape == (0,) and len(angles):
        boundaries = np.array([0, len(angles)])

    for interval in zip(boundaries[:-1], boundaries[1:]):
        if interval[1] > boundaries[0] + len(angles):
            break

        indx = sort_order[interval[0] : interval[1]]

        # If there is a degenerate eigenvalue with several different
        # eigenvectors, the numerical routines return some arbitrary
        # overlap of the real, physical solutions. In order
        # to figure out the correct wave function, we need to
        # have the full, not the projected wave functions
        # (at least to our current knowledge).

        # Finding the true modes is done in two steps:

        # 1. The true transversal modes should be orthogonal to each other, as
        # they share the same Bloch momentum (note that transversal modes with
        # different Bloch momenta k1 and k2 need not be orthogonal, the full
        # modes are orthogonal because of the longitudinal dependence e^{i k1
        # x} and e^{i k2 x}).  The modes with the same k are therefore
        # orthogonalized. Moreover for the velocity to have a proper value the
        # modes should also be normalized.

        q, r = la.qr(full_psi[:, indx], mode='economic')

        # If the eigenvectors were purely real up to this stage,
        # they will typically become complex after the rotation.
        if psi.dtype != np.common_type(psi, r):
            psi = psi.astype(np.common_type(psi, r))
        if full_psi.dtype != np.common_type(full_psi, q):
            full_psi = full_psi.astype(np.common_type(psi, q))

        full_psi[:, indx] = q
        psi[:, indx] = la.solve(r.T, psi[:, indx].T).T

        # 2. Moving infinitesimally away from the degeneracy
        # point, the modes should diagonalize the velocity
        # operator (i.e. when they are non-degenerate any more)
        # The modes are therefore rotated properly such that they
        # diagonalize the velocity operator.
        # Note that step 2. does not give a unique result if there are
        # two modes with the same velocity, or if the modes stay
        # degenerate even for a range of Bloch momenta (and hence
        # must have the same velocity). However, this does not matter,
        # since we are happy with any superposition in this case.

        vel_op = -1j * dot(psi[n:, indx].T.conj(), psi[:n, indx])
        vel_op = vel_op + vel_op.T.conj()
        vel_vals, rot = la.eigh(vel_op)

        # If the eigenvectors were purely real up to this stage,
        # they will typically become complex after the rotation.

        if psi.dtype != np.common_type(psi, rot):
            psi = psi.astype(np.common_type(psi, rot))
        if full_psi.dtype != np.common_type(full_psi, rot):
            full_psi = full_psi.astype(np.common_type(psi, rot))

        psi[:, indx] = dot(psi[:, indx], rot)
        full_psi[:, indx] = dot(full_psi[:, indx], rot)
        velocities[indx] = vel_vals

        # With particle-hole symmetry, treat TRIMs individually.
        # Particle-hole conserves velocity.
        # If P^2 = 1, we can pick modes at a TRIM as particle-hole eigenstates.
        # If P^2 = -1, a mode at a TRIM and its particle-hole partner are
        # orthogonal, and we pick modes such that they are related by
        # particle-hole symmetry.

        # At a TRIM, propagating translation eigenvalues are +1 or -1.
        if (particle_hole is not None and
            (np.abs(np.abs(lmbdainv[indx].real) - 1) < eps).all()):
            assert not len(indx) % 2
            # Set the eigenvalues to the exact TRIM values.
            if (np.abs(lmbdainv[indx].real - 1) < eps).all():
                lmbdainv[indx] = 1
            else:
            # Momenta are the negative arguments of the translation eigenvalues,
            # as computed below using np.angle. np.angle of -1 is pi, so this
            # assigns k = -pi to modes with translation eigenvalue -1.
                lmbdainv[indx] = -1

            # Original wave functions
            orig_wf = full_psi[:, indx]

            # Modes are already sorted by velocity in ascending order, as
            # returned by la.eigh above. The first half is thus incident,
            # and the second half outgoing.
            # Here we work within a subspace of modes with a fixed velocity.
            # Mostly, this is done to ensure that modes of different velocities
            # are not mixed when particle-hole partners are constructed for
            # P^2 = -1. First, we identify which modes have the same velocity.
            # In each such subspace of modes, we construct wave functions that
            # are particle-hole partners.
            vels = velocities[indx]
            # Velocities are sorted in ascending order. Find the indices of the
            # last instance of each unique velocity.
            inds = [ind+1 for ind, vel in enumerate(vels[:-1])
                    if np.abs(vel-vels[ind+1])>vel_eps]
            inds = [0] + inds + [len(vels)]
            inds = zip(inds[:-1], inds[1:])
            # Now possess an iterator over tuples, where each tuple (i,j)
            # contains the starting and final indices i and j of a submatrix
            # of the modes matrix, such that all modes in the submatrix
            # have the same velocity.

            # Iterate over all submatrices of modes with the same velocity.
            new_wf = []
            TRIM_sorts = []
            for ind_tuple in inds:
                # Pick out wave functions that have a given velocity
                wfs = orig_wf[:, slice(*ind_tuple)]
                # Make particle-hole symmetric modes
                new_modes, TRIM_sort = phs_symmetrization(wfs, particle_hole)
                new_wf.append(new_modes)
                # Store sorting indices of the TRIM modes with the given
                # velocity.
                TRIM_sorts.append(TRIM_sort)
            # Gather into a matrix of modes
            new_wf = np.hstack(new_wf)
            # Store the sort order of all modes at the TRIM.
            # Used later with np.lexsort when the ordering
            # of modes is done.
            TRIM_PHS_sort[indx] = np.hstack(TRIM_sorts)
            # Replace the old modes.
            full_psi[:, indx] = new_wf
            # For both cases P^2 = +-1, must rotate wave functions in the
            # singular value basis. Find the rotation from new basis to old.
            rot = new_wf.T.conj().dot(orig_wf)
            # Rotate the wave functions in the singular value basis
            psi[:, indx] = psi[:, indx].dot(rot.T.conj())

        # Ensure proper usage of chiral symmetry.
        if chiral is not None and time_reversal is None:
            out_orig = full_psi[:, indx[len(indx)//2:]]
            out = chiral.dot(full_psi[:, indx[:len(indx)//2]])
            rot = out_orig.T.conj().dot(out)
            full_psi[:, indx[len(indx)//2:]] = out
            psi[:, indx[len(indx)//2:]] = psi[:, indx[len(indx)//2:]].dot(rot)

    if np.any(abs(velocities) < vel_eps):
        raise RuntimeError("Found a mode with zero or close to zero velocity.")
    if 2 * np.sum(velocities < 0) != len(velocities):
        raise RuntimeError("Numbers of left- and right-propagating "
                           "modes differ, possibly due to a numerical "
                           "instability.")

    momenta = -np.angle(lmbdainv)
    # Sort the modes. The modes are sorted first by velocity and momentum,
    # and finally TRIM modes are properly ordered.
    order = np.lexsort([TRIM_PHS_sort, velocities,
                        -np.sign(velocities) * momenta, np.sign(velocities)])

    # TODO: Remove the check once we depend on numpy>=1.8.
    if not len(order):
        order = slice(None)
    velocities = velocities[order]
    momenta = momenta[order]
    full_psi = full_psi[:, order]
    psi = psi[:, order]

    # Use particle-hole symmetry to relate modes that propagate in the
    # same direction but at opposite momenta.
    # Modes are sorted by velocity (first incident, then outgoing).
    # Incident modes are then sorted by momentum in ascending order,
    # and outgoing modes in descending order.
    # Adopted convention is to get modes with negative k (both in and out)
    # by applying particle-hole operator to modes with positive k.
    if particle_hole is not None:
        N = nmodes//2  # Number of incident or outgoing modes.
        # With particle-hole symmetry, N must be an even number.
        # Incident modes
        positive_k = (np.pi - eps > momenta[:N]) * (momenta[:N] > eps)
        # Original wave functions with negative values of k
        orig_neg_k = full_psi[:, :N][:, positive_k[::-1]]
        # For incident modes, ordering of wfs by momentum as returned by kwant
        # is [-k2, -k1, k1, k2], if k2, k1 > 0 and k2 > k1.
        # To maintain this ordering with ki and -ki as particle-hole partners,
        # reverse the order of the product at the end.
        wf_neg_k = particle_hole.dot((full_psi[:, :N][:, positive_k]).conj())[:, ::-1]
        rot = orig_neg_k.T.conj().dot(wf_neg_k)
        full_psi[:, :N][:, positive_k[::-1]] = wf_neg_k
        psi[:, :N][:, positive_k[::-1]] = psi[:, :N][:, positive_k[::-1]].dot(rot)

        # Outgoing modes
        positive_k = (np.pi - eps > momenta[N:]) * (momenta[N:] > eps)
        # Original wave functions with negative values of k
        orig_neg_k = full_psi[:, N:][:, positive_k[::-1]]
        # For outgoing modes, ordering of wfs by momentum as returned by kwant
        # is like [k2, k1, -k1, -k2], if k2, k1 > 0 and k2 > k1.
        # Reverse order with [::-1] at the end to match momenta of opposite sign.
        wf_neg_k = particle_hole.dot(full_psi[:, N:][:, positive_k].conj())[:, ::-1]
        rot = orig_neg_k.T.conj().dot(wf_neg_k)
        full_psi[:, N:][:, positive_k[::-1]] = wf_neg_k
        psi[:, N:][:, positive_k[::-1]] = psi[:, N:][:, positive_k[::-1]].dot(rot)

    # Modes are ordered by velocity.
    # Use time-reversal symmetry to relate modes of opposite velocity.
    if time_reversal is not None:
        # Note: within this function, nmodes refers to the total number
        # of propagating modes, not either left or right movers.
        out_orig = full_psi[:, nmodes//2:]
        out = time_reversal.dot(full_psi[:, :nmodes//2].conj())
        rot = out_orig.T.conj().dot(out)
        full_psi[:, nmodes//2:] = out
        psi[:, nmodes//2:] = psi[:, nmodes//2:].dot(rot)

    norm = np.sqrt(abs(velocities))
    full_psi = full_psi / norm
    psi = psi / norm

    return psi, PropagatingModes(full_psi, velocities, momenta)
Example #36
0
def make_proper_modes(lmbdainv, psi, extract, tol=1e6):
    """
    Find, normalize and sort the propagating eigenmodes.

    Special care is taken of the case of degenerate k-values, where the
    numerically computed modes are typically a superposition of the real
    modes. In this case, also the proper (orthogonal) modes are computed.
    """
    vel_eps = np.finfo(psi.dtype).eps * tol

    nmodes = psi.shape[1]
    n = len(psi) // 2

    # Array for the velocities.
    velocities = np.empty(nmodes, dtype=float)

    # Calculate the full wave function in real space.
    full_psi = extract(psi, lmbdainv)

    # Find clusters of nearby eigenvalues. Since the eigenvalues occupy the
    # unit circle, special care has to be taken to not introduce a cut at
    # lambda = -1.
    eps = np.finfo(lmbdainv.dtype).eps * tol
    angles = np.angle(lmbdainv)
    sort_order = np.resize(np.argsort(angles), (2 * len(angles,)))
    boundaries = np.argwhere(np.abs(np.diff(lmbdainv[sort_order]))
                             > eps).flatten() + 1

    # Detect the singular case of all eigenvalues equal.
    if boundaries.shape == (0,) and len(angles):
        boundaries = np.array([0, len(angles)])

    for interval in izip(boundaries[:-1], boundaries[1:]):
        if interval[1] > boundaries[0] + len(angles):
            break

        indx = sort_order[interval[0] : interval[1]]

        # If there is a degenerate eigenvalue with several different
        # eigenvectors, the numerical routines return some arbitrary
        # overlap of the real, physical solutions. In order
        # to figure out the correct wave function, we need to
        # have the full, not the projected wave functions
        # (at least to our current knowledge).

        # Finding the true modes is done in two steps:

        # 1. The true transversal modes should be orthogonal to each other, as
        # they share the same Bloch momentum (note that transversal modes with
        # different Bloch momenta k1 and k2 need not be orthogonal, the full
        # modes are orthogonal because of the longitudinal dependence e^{i k1
        # x} and e^{i k2 x}).  The modes with the same k are therefore
        # orthogonalized. Moreover for the velocity to have a proper value the
        # modes should also be normalized.

        q, r = la.qr(full_psi[:, indx], mode='economic')

        # If the eigenvectors were purely real up to this stage,
        # they will typically become complex after the rotation.
        if psi.dtype != np.common_type(psi, r):
            psi = psi.astype(np.common_type(psi, r))
        if full_psi.dtype != np.common_type(full_psi, q):
            full_psi = full_psi.astype(np.common_type(psi, q))

        full_psi[:, indx] = q
        psi[:, indx] = la.solve(r.T, psi[:, indx].T).T

        # 2. Moving infinitesimally away from the degeneracy
        # point, the modes should diagonalize the velocity
        # operator (i.e. when they are non-degenerate any more)
        # The modes are therefore rotated properly such that they
        # diagonalize the velocity operator.
        # Note that step 2. does not give a unique result if there are
        # two modes with the same velocity, or if the modes stay
        # degenerate even for a range of Bloch momenta (and hence
        # must have the same velocity). However, this does not matter,
        # since we are happy with any superposition in this case.

        vel_op = -1j * dot(psi[n:, indx].T.conj(), psi[:n, indx])
        vel_op = vel_op + vel_op.T.conj()
        vel_vals, rot = la.eigh(vel_op)

        # If the eigenvectors were purely real up to this stage,
        # they will typically become complex after the rotation.

        if psi.dtype != np.common_type(psi, rot):
            psi = psi.astype(np.common_type(psi, rot))
        if full_psi.dtype != np.common_type(full_psi, rot):
            full_psi = full_psi.astype(np.common_type(psi, rot))

        psi[:, indx] = dot(psi[:, indx], rot)
        full_psi[:, indx] = dot(full_psi[:, indx], rot)
        velocities[indx] = vel_vals

    if np.any(abs(velocities) < vel_eps):
        raise RuntimeError("Found a mode with zero or close to zero velocity.")
    if 2 * np.sum(velocities < 0) != len(velocities):
        raise RuntimeError("Numbers of left- and right-propagating "
                           "modes differ, possibly due to a numerical "
                           "instability.")
    momenta = -np.angle(lmbdainv)
    order = np.lexsort([velocities, -np.sign(velocities) * momenta,
                        np.sign(velocities)])

    # TODO: Remove the check once we depende on numpy>=1.8.
    if not len(order):
        order = slice(None)
    velocities = velocities[order]
    norm = np.sqrt(abs(velocities))
    full_psi = full_psi[:, order] / norm
    psi = psi[:, order] / norm
    momenta = momenta[order]

    return psi, PropagatingModes(full_psi, velocities, momenta)
Example #37
0
    def evaluate(self, points):
        """
        Evaluate the estimated pdf on a set of points.

        Parameters
        ----------
        points : (# of dimensions, # of points)-array
            Alternatively, a (# of dimensions,) vector can be passed in and
            treated as a single point.

        Returns
        -------
        values : (# of points,)-array
            The values at each point.

        Raises
        ------
        ValueError : if the dimensionality of the input points is different than
                     the dimensionality of the KDE.

        """
        points = atleast_2d(asarray(points))

        d, m = points.shape
        if d != self.d:
            if d == 1 and m == self.d:
                # points was passed in as a row vector
                points = reshape(points, (self.d, 1))
                m = 1
            else:
                raise ValueError(
                    f"points have dimension {d}, dataset has dimension {self.d}"
                )

        output_dtype = np.common_type(self.covariance, points)

        if True:
            # result = gaussian_kernel_estimate_vectorized(points=self.dataset.T,
            #                                              values=self.weights[:, None],
            #                                              xi=points.T,
            #                                              precision=self.inv_cov,
            #                                              dtype=output_dtype,
            #                                              gpu=self._gpu)

            result = gaussian_kernel_estimate_vectorized_whitened(
                whitening=self.whitening,
                whitened_points=self.whitened_points,
                values=self.weights[:, None],
                xi=points.T,
                norm=self.normalization_constant,
                dtype=output_dtype,
                gpu=self._gpu)

            return result
        else:
            result = gaussian_kernel_estimate(points=self.dataset.T,
                                              values=self.weights[:, None],
                                              xi=points.T,
                                              precision=self.inv_cov,
                                              dtype=output_dtype)
            return result[:, 0]
Example #38
0
def vq(obs, code_book):
    """
    Assign codes from a code book to observations.

    Assigns a code from a code book to each observation. Each
    observation vector in the 'M' by 'N' `obs` array is compared with the
    centroids in the code book and assigned the code of the closest
    centroid.

    The features in `obs` should have unit variance, which can be
    achieved by passing them through the whiten function.  The code
    book can be created with the k-means algorithm or a different
    encoding algorithm.

    Parameters
    ----------
    obs : ndarray
        Each row of the 'M' x 'N' array is an observation.  The columns are
        the "features" seen during each observation. The features must be
        whitened first using the whiten function or something equivalent.
    code_book : ndarray
        The code book is usually generated using the k-means algorithm.
        Each row of the array holds a different code, and the columns are
        the features of the code.

         >>> #              f0    f1    f2   f3
         >>> code_book = [
         ...             [  1.,   2.,   3.,   4.],  #c0
         ...             [  1.,   2.,   3.,   4.],  #c1
         ...             [  1.,   2.,   3.,   4.]]  #c2

    Returns
    -------
    code : ndarray
        A length M array holding the code book index for each observation.
    dist : ndarray
        The distortion (distance) between the observation and its nearest
        code.

    Examples
    --------
    >>> from numpy import array
    >>> from scipy.cluster.vq import vq
    >>> code_book = array([[1.,1.,1.],
    ...                    [2.,2.,2.]])
    >>> features  = array([[  1.9,2.3,1.7],
    ...                    [  1.5,2.5,2.2],
    ...                    [  0.8,0.6,1.7]])
    >>> vq(features,code_book)
    (array([1, 1, 0],'i'), array([ 0.43588989,  0.73484692,  0.83066239]))

    """
    try:
        from . import _vq
        ct = common_type(obs, code_book)

        # avoid copying when dtype is the same
        # should be replaced with c_obs = astype(ct, copy=False)
        # when we get to numpy 1.7.0
        if obs.dtype != ct:
            c_obs = obs.astype(ct)
        else:
            c_obs = obs

        if code_book.dtype != ct:
            c_code_book = code_book.astype(ct)
        else:
            c_code_book = code_book

        if ct in (single, double):
            results = _vq.vq(c_obs, c_code_book)
        else:
            results = py_vq(obs, code_book)
    except ImportError:
        results = py_vq(obs, code_book)
    return results
Example #39
0
def prepare_for_fortran(overwrite, *args):
    """Convert arrays to Fortran format.

    This function takes a number of array objects in `args` and converts them
    to a format that can be directly passed to a Fortran function (Fortran
    contiguous NumPy array). If the arrays have different data type, they
    converted arrays are cast to a common compatible data type (one of NumPy's
    `float32`, `float64`, `complex64`, `complex128` data types).

    If `overwrite` is ``False``, an NumPy array that would already be in the
    correct format (Fortran contiguous, right data type) is neverthelessed
    copied. (Hence, overwrite = True does not imply that acting on the
    converted array in the return values will overwrite the original array in
    all cases -- it does only so if the original array was already in the
    correct format. The conversions require copying. In fact, that's the same
    behavior as in SciPy, it's just not explicitly stated there)

    If an argument is ``None``, it is just passed through and not used to
    determine the proper data type.

    `prepare_for_lapack` returns a character indicating the proper
    data type in LAPACK style ('s', 'd', 'c', 'z') and a list of
    properly converted arrays.
    """

    # Make sure we have NumPy arrays
    mats = [None] * len(args)
    for i in range(len(args)):
        if args[i] is not None:
            arr = np.asanyarray(args[i])
            if not np.issubdtype(arr.dtype, np.number):
                raise ValueError("Argument cannot be interpreted "
                                 "as a numeric array")

            mats[i] = (arr, arr is not args[i] or overwrite)
        else:
            mats[i] = (None, True)

    # First figure out common dtype
    # Note: The return type of common_type is guaranteed to be a floating point
    #       kind.
    dtype = np.common_type(*[arr for arr, ovwrt in mats if arr is not None])

    if dtype == np.float32:
        lapacktype = 's'
    elif dtype == np.float64:
        lapacktype = 'd'
    elif dtype == np.complex64:
        lapacktype = 'c'
    elif dtype == np.complex128:
        lapacktype = 'z'
    else:
        raise AssertionError("Unexpected data type from common_type")

    ret = [lapacktype]
    for npmat, ovwrt in mats:
        # Now make sure that the array is contiguous, and copy if necessary.
        if npmat is not None:
            if npmat.ndim == 2:
                if not npmat.flags["F_CONTIGUOUS"]:
                    npmat = np.asfortranarray(npmat, dtype=dtype)
                elif npmat.dtype != dtype:
                    npmat = npmat.astype(dtype)
                elif not ovwrt:
                    # ugly here: copy makes always C-array, no way to tell it
                    # to make a Fortran array.
                    npmat = np.asfortranarray(npmat.copy())
            elif npmat.ndim == 1:
                if not npmat.flags["C_CONTIGUOUS"]:
                    npmat = np.ascontiguousarray(npmat, dtype=dtype)
                elif npmat.dtype != dtype:
                    npmat = npmat.astype(dtype)
                elif not ovwrt:
                    npmat = np.asfortranarray(npmat.copy())
            else:
                raise ValueError("Dimensionality of array is not 1 or 2")

        ret.append(npmat)

    return tuple(ret)
Example #40
0
File: vq.py Project: ssps12/scipy
def vq(obs, code_book, check_finite=True):
    """
    Assign codes from a code book to observations.

    Assigns a code from a code book to each observation. Each
    observation vector in the 'M' by 'N' `obs` array is compared with the
    centroids in the code book and assigned the code of the closest
    centroid.

    The features in `obs` should have unit variance, which can be
    achieved by passing them through the whiten function. The code
    book can be created with the k-means algorithm or a different
    encoding algorithm.

    Parameters
    ----------
    obs : ndarray
        Each row of the 'M' x 'N' array is an observation. The columns are
        the "features" seen during each observation. The features must be
        whitened first using the whiten function or something equivalent.
    code_book : ndarray
        The code book is usually generated using the k-means algorithm.
        Each row of the array holds a different code, and the columns are
        the features of the code.

         >>> #              f0    f1    f2   f3
         >>> code_book = [
         ...             [  1.,   2.,   3.,   4.],  #c0
         ...             [  1.,   2.,   3.,   4.],  #c1
         ...             [  1.,   2.,   3.,   4.]]  #c2

    check_finite : bool, optional
        Whether to check that the input matrices 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: True

    Returns
    -------
    code : ndarray
        A length M array holding the code book index for each observation.
    dist : ndarray
        The distortion (distance) between the observation and its nearest
        code.

    Examples
    --------
    >>> from numpy import array
    >>> from scipy.cluster.vq import vq
    >>> code_book = array([[1.,1.,1.],
    ...                    [2.,2.,2.]])
    >>> features  = array([[  1.9,2.3,1.7],
    ...                    [  1.5,2.5,2.2],
    ...                    [  0.8,0.6,1.7]])
    >>> vq(features,code_book)
    (array([1, 1, 0],'i'), array([ 0.43588989,  0.73484692,  0.83066239]))

    """
    obs = _asarray_validated(obs, check_finite=check_finite)
    code_book = _asarray_validated(code_book, check_finite=check_finite)
    ct = np.common_type(obs, code_book)

    c_obs = obs.astype(ct, copy=False)
    c_code_book = code_book.astype(ct, copy=False)

    if np.issubdtype(ct, np.float64) or np.issubdtype(ct, np.float32):
        return _vq.vq(c_obs, c_code_book)
    return py_vq(obs, code_book, check_finite=False)
Example #41
0
def convert_r2c_gen_schur(s, t, q=None, z=None):
    """Convert a real generallzed Schur form (with possibly 2x2 blocks on the
    diagonal) into a complex Schur form that is completely triangular.  If the
    input is already completely triagonal (real or complex), the input is
    returned unchanged.

    This function guarantees that in the case of a 2x2 block at rows and
    columns i and i+1, the converted, complex Schur form will contain the
    generalized eigenvalue with the positive imaginary part in s[i,i] and
    t[i,i], and the one with the negative imaginary part in s[i+1,i+1] and
    t[i+1,i+1].  This ensures that the list of eigenvalues (more precisely,
    their order) returned originally from gen_schur() is still valid for the
    newly formed complex Schur form.

    Parameters
    ----------
    s : array, shape (M, M)
    t : array, shape (M, M)
        Real generalized Schur form of the original matrix
    q : array, shape (M, M), optional
    z : array, shape (M, M), optional
        Schur transformation matrix. Default: None

    Returns
    -------
    s : array, shape (M, M)
    t : array, shape (M, M)
        Complex generalized Schur form of the original matrix,
        completely triagonal
    q : array, shape (M, M)
    z : array, shape (M, M)
        Schur transformation matrices corresponding to the complex
        form. `q` or `z` are only computed if they are provided (not
        None) on input.

    Raises
    ------
    LinAlgError
        If it fails to convert a 2x2 block into complex form (unlikely).
    """

    ltype, s, t, q, z = lapack.prepare_for_lapack(True, s, t, q, z)
    # Note: overwrite=True does not mean much here, the arrays are all copied

    if (s.ndim != 2 or t.ndim != 2 or
        (q is not None and q.ndim != 2) or
        (z is not None and z.ndim != 2)):
        raise ValueError("Expect matrices as input")

    if ((s.shape[0] != s.shape[1] or t.shape[0] != t.shape[1] or
         s.shape[0] != t.shape[0]) or
        (q is not None and (q.shape[0] != q.shape[1] or
                            s.shape[0] != q.shape[0])) or
        (z is not None and (z.shape[0] != z.shape[1] or
                            s.shape[0] != z.shape[0]))):
        raise ValueError("Invalid Schur decomposition as input")

    # First, find the positions of 2x2-blocks.
    blockpos = np.diagonal(s, -1).nonzero()[0]

    # Check if there are actually any 2x2-blocks.
    if not blockpos.size:
        s2 = s
        t2 = t
        q2 = q
        z2 = z
    else:
        s2 = s.astype(np.common_type(s, np.array([], np.complex64)))
        t2 = t.astype(np.common_type(t, np.array([], np.complex64)))
        if q is not None:
            q2 = q.astype(np.common_type(q, np.array([], np.complex64)))
        if z is not None:
            z2 = z.astype(np.common_type(z, np.array([], np.complex64)))

    for i in blockpos:
        # In the following, we use gen_schur on individual 2x2 blocks (that are
        # promoted to complex form) to compute the complex generalized Schur
        # form. If necessary, order_gen_schur is used to ensure the desired
        # order of eigenvalues.

        sb, tb, qb, zb, alphab, betab = gen_schur(s2[i:i+2, i:i+2],
                                                  t2[i:i+2, i:i+2])

        # Ensure order of eigenvalues. (betab is positive)
        if alphab[0].imag < alphab[1].imag:
            sb, tb, qb, zb, alphab, betab = order_gen_schur([False, True],
                                                            sb, tb, qb, zb)

        s2[i:i+2, i:i+2] = sb
        t2[i:i+2, i:i+2] = tb

        s2[:i, i:i+2] = np.dot(s2[:i, i:i+2], zb)
        s2[i:i+2, i+2:] = np.dot(qb.T.conj(), s2[i:i+2, i+2:])
        t2[:i, i:i+2] = np.dot(t2[:i, i:i+2], zb)
        t2[i:i+2, i+2:] = np.dot(qb.T.conj(), t2[i:i+2, i+2:])

        if q is not None:
            q2[:, i:i+2] = np.dot(q[:, i:i+2], qb)
        if z is not None:
            z2[:, i:i+2] = np.dot(z[:, i:i+2], zb)

    if q is not None and z is not None:
        return s2, t2, q2, z2
    elif q is not None:
        return s2, t2, q2
    elif z is not None:
        return s2, t2, z2
    else:
        return s2, t2
Example #42
0
def prepare_for_fortran(overwrite, *args):
    """Convert arrays to Fortran format.

    This function takes a number of array objects in `args` and converts them
    to a format that can be directly passed to a Fortran function (Fortran
    contiguous NumPy array). If the arrays have different data type, they
    converted arrays are cast to a common compatible data type (one of NumPy's
    `float32`, `float64`, `complex64`, `complex128` data types).

    If `overwrite` is ``False``, an NumPy array that would already be in the
    correct format (Fortran contiguous, right data type) is neverthelessed
    copied. (Hence, overwrite = True does not imply that acting on the
    converted array in the return values will overwrite the original array in
    all cases -- it does only so if the original array was already in the
    correct format. The conversions require copying. In fact, that's the same
    behavior as in SciPy, it's just not explicitly stated there)

    If an argument is ``None``, it is just passed through and not used to
    determine the proper data type.

    `prepare_for_lapack` returns a character indicating the proper
    data type in LAPACK style ('s', 'd', 'c', 'z') and a list of
    properly converted arrays.
    """

    # Make sure we have NumPy arrays
    mats = [None]*len(args)
    for i in range(len(args)):
        if args[i] is not None:
            arr = np.asanyarray(args[i])
            if not np.issubdtype(arr.dtype, np.number):
                raise ValueError("Argument cannot be interpreted "
                                 "as a numeric array")

            mats[i] = (arr, arr is not args[i] or overwrite)
        else:
            mats[i] = (None, True)

    # First figure out common dtype
    # Note: The return type of common_type is guaranteed to be a floating point
    #       kind.
    dtype = np.common_type(*[arr for arr, ovwrt in mats if arr is not None])

    if dtype == np.float32:
        lapacktype = 's'
    elif dtype == np.float64:
        lapacktype = 'd'
    elif dtype == np.complex64:
        lapacktype = 'c'
    elif dtype == np.complex128:
        lapacktype = 'z'
    else:
        raise AssertionError("Unexpected data type from common_type")

    ret = [ lapacktype ]
    for npmat, ovwrt in mats:
        # Now make sure that the array is contiguous, and copy if necessary.
        if npmat is not None:
            if npmat.ndim == 2:
                if not npmat.flags["F_CONTIGUOUS"]:
                    npmat = np.asfortranarray(npmat, dtype = dtype)
                elif npmat.dtype != dtype:
                    npmat = npmat.astype(dtype)
                elif not ovwrt:
                    # ugly here: copy makes always C-array, no way to tell it
                    # to make a Fortran array.
                    npmat = np.asfortranarray(npmat.copy())
            elif npmat.ndim == 1:
                if not npmat.flags["C_CONTIGUOUS"]:
                    npmat = np.ascontiguousarray(npmat, dtype = dtype)
                elif npmat.dtype != dtype:
                    npmat = npmat.astype(dtype)
                elif not ovwrt:
                    npmat = np.asfortranarray(npmat.copy())
            else:
                raise ValueError("Dimensionality of array is not 1 or 2")

        ret.append(npmat)

    return tuple(ret)
Example #43
0
def convert_r2c_schur(t, q):
    """Convert a real Schur form (with possibly 2x2 blocks on the diagonal)
    into a complex Schur form that is completely triangular.

    This function is equivalent to the scipy.linalg.rsf2csf pendant (though the
    implementation is different), but there is additionally the guarantee that
    in the case of a 2x2 block at rows and columns i and i+1, t[i, i] will
    contain the eigenvalue with the positive part, and t[i+1, i+1] the one with
    the negative part.  This ensures that the list of eigenvalues (more
    precisely, their order) returned originally from schur() is still valid for
    the newly formed complex Schur form.

    Parameters
    ----------
    t : array, shape (M, M)
        Real Schur form of the original matrix
    q : array, shape (M, M)
        Schur transformation matrix

    Returns
    -------
    t : array, shape (M, M)
        Complex Schur form of the original matrix
    q : array, shape (M, M)
        Schur transformation matrix corresponding to the complex form
    """

    # First find the positions of 2x2-blocks
    blockpos = np.diagonal(t, -1).nonzero()[0]

    # Check if there are actually any 2x2-blocks
    if not blockpos.size:
        return (t, q)
    else:
        t2 = t.astype(np.common_type(t, np.array([], np.complex64)))
        q2 = q.astype(np.common_type(q, np.array([], np.complex64)))

    for i in blockpos:
        # Bringing a 2x2 block to complex triangular form is relatively simple:
        # the 2x2 blocks are guaranteed to be of the form [[a, b], [c, a]],
        # where b*c < 0. The eigenvalues of this matrix are a +/- i sqrt(-b*c),
        # the corresponding eigenvectors are [ +/- sqrt(-b*c), c].  The Schur
        # form can be achieved by a unitary 2x2 matrix with one of the
        # eigenvectors in the first column, and the second column an orthogonal
        # vector.

        a = t[i, i]
        b = t[i, i+1]
        c = t[i+1, i]

        x = 1j * sqrt(-b * c)
        y = c
        norm = sqrt(-b * c + c * c)

        U = np.array([[x / norm, -y / norm], [y / norm, -x / norm]])

        t2[i, i] = a + x
        t2[i+1, i] = 0
        t2[i, i+1] = -b - c
        t2[i+1, i+1] = a - x

        t2[:i, i:i+2] = np.dot(t2[:i, i:i+2], U)
        t2[i:i+2, i+2:] = np.dot(np.conj(U.T), t2[i:i+2, i+2:])

        q2[:, i:i+2] = np.dot(q2[:, i:i+2], U)

    return t2, q2
Example #44
0
def arma_acovf(ar, ma, nobs=10, sigma2=1, dtype=None):
    """
    Theoretical autocovariances of stationary ARMA processes

    Parameters
    ----------
    ar : array_like, 1d
        The coefficients for autoregressive lag polynomial, including zero lag.
    ma : array_like, 1d
        The coefficients for moving-average lag polynomial, including zero lag.
    nobs : int
        The number of terms (lags plus zero lag) to include in returned acovf.
    sigma2 : float
        Variance of the innovation term.

    Returns
    -------
    ndarray
        The autocovariance of ARMA process given by ar, ma.

    See Also
    --------
    arma_acf : Autocorrelation function for ARMA processes.
    acovf : Sample autocovariance estimation.

    References
    ----------
    .. [*] Brockwell, Peter J., and Richard A. Davis. 2009. Time Series:
        Theory and Methods. 2nd ed. 1991. New York, NY: Springer.
    """
    if dtype is None:
        dtype = np.common_type(np.array(ar), np.array(ma), np.array(sigma2))

    p = len(ar) - 1
    q = len(ma) - 1
    m = max(p, q) + 1

    if sigma2.real < 0:
        raise ValueError("Must have positive innovation variance.")

    # Short-circuit for trivial corner-case
    if p == q == 0:
        out = np.zeros(nobs, dtype=dtype)
        out[0] = sigma2
        return out
    elif p > 0 and np.max(np.abs(np.roots(ar))) >= 1:
        raise ValueError(NONSTATIONARY_ERROR)

    # Get the moving average representation coefficients that we need
    ma_coeffs = arma2ma(ar, ma, lags=m)

    # Solve for the first m autocovariances via the linear system
    # described by (BD, eq. 3.3.8)
    A = np.zeros((m, m), dtype=dtype)
    b = np.zeros((m, 1), dtype=dtype)
    # We need a zero-right-padded version of ar params
    tmp_ar = np.zeros(m, dtype=dtype)
    tmp_ar[: p + 1] = ar
    for k in range(m):
        A[k, : (k + 1)] = tmp_ar[: (k + 1)][::-1]
        A[k, 1 : m - k] += tmp_ar[(k + 1) : m]
        b[k] = sigma2 * np.dot(ma[k : q + 1], ma_coeffs[: max((q + 1 - k), 0)])
    acovf = np.zeros(max(nobs, m), dtype=dtype)
    try:
        acovf[:m] = np.linalg.solve(A, b)[:, 0]
    except np.linalg.LinAlgError:
        raise ValueError(NONSTATIONARY_ERROR)

    # Iteratively apply (BD, eq. 3.3.9) to solve for remaining autocovariances
    if nobs > m:
        zi = signal.lfiltic([1], ar, acovf[:m:][::-1])
        acovf[m:] = signal.lfilter(
            [1], ar, np.zeros(nobs - m, dtype=dtype), zi=zi
        )[0]

    return acovf[:nobs]
Example #45
0
 def test_array_function_common_type(self, xp):
     return numpy.common_type(xp.arange(2, dtype='f8'),
                              xp.arange(2, dtype='f4'))
Example #46
0
File: vq.py Project: b-t-g/Sim
def vq(obs, code_book):
    """
    Assign codes from a code book to observations.

    Assigns a code from a code book to each observation. Each
    observation vector in the 'M' by 'N' `obs` array is compared with the
    centroids in the code book and assigned the code of the closest
    centroid.

    The features in `obs` should have unit variance, which can be
    acheived by passing them through the whiten function.  The code
    book can be created with the k-means algorithm or a different
    encoding algorithm.

    Parameters
    ----------
    obs : ndarray
        Each row of the 'N' x 'M' array is an observation.  The columns are
        the "features" seen during each observation. The features must be
        whitened first using the whiten function or something equivalent.
    code_book : ndarray
        The code book is usually generated using the k-means algorithm.
        Each row of the array holds a different code, and the columns are
        the features of the code.

         >>> #              f0    f1    f2   f3
         >>> code_book = [
         ...             [  1.,   2.,   3.,   4.],  #c0
         ...             [  1.,   2.,   3.,   4.],  #c1
         ...             [  1.,   2.,   3.,   4.]]) #c2

    Returns
    -------
    code : ndarray
        A length N array holding the code book index for each observation.
    dist : ndarray
        The distortion (distance) between the observation and its nearest
        code.

    Notes
    -----
    This currently forces 32-bit math precision for speed.  Anyone know
    of a situation where this undermines the accuracy of the algorithm?

    Examples
    --------
    >>> from numpy import array
    >>> from scipy.cluster.vq import vq
    >>> code_book = array([[1.,1.,1.],
    ...                    [2.,2.,2.]])
    >>> features  = array([[  1.9,2.3,1.7],
    ...                    [  1.5,2.5,2.2],
    ...                    [  0.8,0.6,1.7]])
    >>> vq(features,code_book)
    (array([1, 1, 0],'i'), array([ 0.43588989,  0.73484692,  0.83066239]))

    """
    try:
        from . import _vq
        ct = common_type(obs, code_book)
        c_obs = obs.astype(ct)
        c_code_book = code_book.astype(ct)
        if ct is single:
            results = _vq.vq(c_obs, c_code_book)
        elif ct is double:
            results = _vq.vq(c_obs, c_code_book)
        else:
            results = py_vq(obs, code_book)
    except ImportError:
        results = py_vq(obs, code_book)
    return results
Example #47
0
 def upcasted_fn(a, b):
     if a.dtype == b.dtype:
         return fn(a, b)
     else:
         common = np.common_type(a, b)
         return fn(a.astype(common), b.astype(common))
Example #48
0
def matvec(cc, vector, k):
    # Ref: Nooijen and Bartlett, J. Chem. Phys. 102, 3629 (1994) Eqs.(30)-(31)
    if not cc.imds.made_ea_imds:
        cc.imds.make_ea(cc.ea_partition)
    imds = cc.imds

    vector = mask_frozen(cc, vector, k, const=0.0)
    r1, r2 = vector_to_amplitudes(cc, vector, k)

    t1, t2 = cc.t1, cc.t2
    nkpts = cc.nkpts
    kconserv = cc.khelper.kconserv

    # Eq. (30)
    # 1p-1p block
    Hr1 = einsum('ac,c->a', imds.Lvv[k], r1)
    # 1p-2p1h block
    for kl in range(nkpts):
        Hr1 += 2. * einsum('ld,lad->a', imds.Fov[kl], r2[kl, k])
        Hr1 += -einsum('ld,lda->a', imds.Fov[kl], r2[kl, kl])
        for kc in range(nkpts):
            kd = kconserv[k, kc, kl]
            Hr1 += 2. * einsum('alcd,lcd->a', imds.Wvovv[k, kl, kc], r2[kl,
                                                                        kc])
            Hr1 += -einsum('aldc,lcd->a', imds.Wvovv[k, kl, kd], r2[kl, kc])

    # Eq. (31)
    # 2p1h-1p block
    Hr2 = np.zeros(r2.shape, dtype=np.common_type(imds.Wvvvo[0, 0, 0], r1))
    for kj in range(nkpts):
        for ka in range(nkpts):
            kb = kconserv[k, ka, kj]
            Hr2[kj, ka] += einsum('abcj,c->jab', imds.Wvvvo[ka, kb, k], r1)

    # 2p1h-2p1h block
    if cc.ea_partition == 'mp':
        nkpts, nocc, nvir = cc.t1.shape
        fock = cc.eris.fock
        foo = fock[:, :nocc, :nocc]
        fvv = fock[:, nocc:, nocc:]
        for kj in range(nkpts):
            for ka in range(nkpts):
                kb = kconserv[k, ka, kj]
                Hr2[kj, ka] -= einsum('lj,lab->jab', foo[kj], r2[kj, ka])
                Hr2[kj, ka] += einsum('ac,jcb->jab', fvv[ka], r2[kj, ka])
                Hr2[kj, ka] += einsum('bd,jad->jab', fvv[kb], r2[kj, ka])
    elif cc.ea_partition == 'full':
        Hr2 += cc._eaccsd_diag_matrix2 * r2
    else:
        for kj in range(nkpts):
            for ka in range(nkpts):
                kb = kconserv[k, ka, kj]
                Hr2[kj, ka] -= einsum('lj,lab->jab', imds.Loo[kj], r2[kj, ka])
                Hr2[kj, ka] += einsum('ac,jcb->jab', imds.Lvv[ka], r2[kj, ka])
                Hr2[kj, ka] += einsum('bd,jad->jab', imds.Lvv[kb], r2[kj, ka])
                for kd in range(nkpts):
                    kc = kconserv[ka, kd, kb]
                    Hr2[kj, ka] += einsum('abcd,jcd->jab',
                                          imds.Wvvvv[ka, kb, kc], r2[kj, kc])
                    kl = kconserv[kd, kb, kj]
                    Hr2[kj, ka] += 2. * einsum(
                        'lbdj,lad->jab', imds.Wovvo[kl, kb, kd], r2[kl, ka])
                    # imds.Wvovo[kb,kl,kd,kj] <= imds.Wovov[kl,kb,kj,kd].transpose(1,0,3,2)
                    Hr2[kj, ka] += -einsum(
                        'bldj,lad->jab', imds.Wovov[kl, kb, kj].transpose(
                            1, 0, 3, 2), r2[kl, ka])
                    # imds.Wvoov[kb,kl,kj,kd] <= imds.Wovvo[kl,kb,kd,kj].transpose(1,0,3,2)
                    Hr2[kj, ka] += -einsum(
                        'bljd,lda->jab', imds.Wovvo[kl, kb, kd].transpose(
                            1, 0, 3, 2), r2[kl, kd])
                    kl = kconserv[kd, ka, kj]
                    # imds.Wvovo[ka,kl,kd,kj] <= imds.Wovov[kl,ka,kj,kd].transpose(1,0,3,2)
                    Hr2[kj, ka] += -einsum(
                        'aldj,ldb->jab', imds.Wovov[kl, ka, kj].transpose(
                            1, 0, 3, 2), r2[kl, kd])
        tmp = (2. * einsum('xyklcd,xylcd->k', imds.Woovv[k, :, :], r2[:, :]) -
               einsum('xylkcd,xylcd->k', imds.Woovv[:, k, :], r2[:, :]))
        Hr2[:, :] += -einsum('k,xykjab->xyjab', tmp, t2[k, :, :])

    return mask_frozen(cc, amplitudes_to_vector(cc, Hr1, Hr2, k), k, const=0.0)
Example #49
0
def setup_linsys(h_cell, h_hop, tol=1e6, stabilization=None):
    """Make an eigenvalue problem for eigenvectors of translation operator.

    Parameters
    ----------
    h_cell : numpy array with shape (n, n)
        Hamiltonian of a single lead unit cell.
    h_hop : numpy array with shape (n, m), m <= n
        Hopping Hamiltonian from a cell to the next one.
    tol : float
        Numbers are considered zero when they are smaller than `tol` times
        the machine precision.
    stabilization : sequence of 2 booleans or None
        Which steps of the eigenvalue problem stabilization to perform. If the
        value is `None`, then Kwant chooses the fastest (and least stable)
        algorithm that is expected to be sufficient.  For any other value,
        Kwant forms the eigenvalue problem in the basis of the hopping singular
        values.  The first element set to `True` forces Kwant to add an
        anti-Hermitian term to the cell Hamiltonian before inverting. If it is
        set to `False`, the extra term will only be added if the cell
        Hamiltonian isn't invertible. The second element set to `True` forces
        Kwant to solve a generalized eigenvalue problem, and not to reduce it
        to the regular one.  If it is `False`, reduction to a regular problem
        is performed if possible.

    Returns
    -------
    linsys : namedtuple
        A named tuple containing `matrices` a matrix pencil defining
        the eigenproblem, `v` a hermitian conjugate of the last matrix in
        the hopping singular value decomposition, and functions for
        extracting the wave function in the unit cell from the wave function
        in the basis of the nonzero singular exponents of the hopping.

    Notes
    -----
    The lead problem with degenerate hopping is rather complicated, and the
    details of the algorithm will be published elsewhere.

    """
    n = h_cell.shape[0]
    m = h_hop.shape[1]
    if stabilization is not None:
        stabilization = list(stabilization)

    if not complex_any(h_hop):
        # Inter-cell hopping is zero.  The current algorithm is not suited to
        # treat this extremely singular case.
        raise ValueError("Inter-cell hopping is exactly zero.")

    # If both h and t are real, it may be possible to use the real eigenproblem.
    if (not np.any(h_hop.imag)) and (not np.any(h_cell.imag)):
        h_hop = h_hop.real
        h_cell = h_cell.real

    eps = np.finfo(np.common_type(h_cell, h_hop)).eps * tol

    # First check if the hopping matrix has singular values close to 0.
    # (Close to zero is defined here as |x| < eps * tol * s[0] , where
    # s[0] is the largest singular value.)

    u, s, vh = la.svd(h_hop)
    assert m == vh.shape[1], "Corrupt output of svd."
    n_nonsing = np.sum(s > eps * s[0])

    if (n_nonsing == n and stabilization is None):
        # The hopping matrix is well-conditioned and can be safely inverted.
        # Hence the regular transfer matrix may be used.
        hop_inv = la.inv(h_hop)

        A = np.zeros((2*n, 2*n), dtype=np.common_type(h_cell, h_hop))
        A[:n, :n] = dot(hop_inv, -h_cell)
        A[:n, n:] = -hop_inv
        A[n:, :n] = h_hop.T.conj()

        # The function that can extract the full wave function psi from the
        # projected one. Here it is almost trivial, but used for simplifying
        # the logic.

        def extract_wf(psi, lmbdainv):
            return np.copy(psi[:n])

        matrices = (A, None)
        v_out = None
    else:
        if stabilization is None:
            stabilization = [None, False]

        # The hopping matrix has eigenvalues close to 0 - those
        # need to be eliminated.

        # Recast the svd of h_hop = u s v^dagger such that
        # u, v are matrices with shape n x n_nonsing.
        u = u[:, :n_nonsing]
        s = s[:n_nonsing]
        u = u * np.sqrt(s)
        # pad v with zeros if necessary
        v = np.zeros((n, n_nonsing), dtype=vh.dtype)
        v[:vh.shape[1]] = vh[:n_nonsing].T.conj()
        v = v * np.sqrt(s)

        # Eliminating the zero eigenvalues requires inverting the on-site
        # Hamiltonian, possibly including a self-energy-like term.  The
        # self-energy-like term stabilizes the inversion, but the most stable
        # choice is inherently complex. This can be disadvantageous if the
        # Hamiltonian is real, since staying in real arithmetics can be
        # significantly faster.  The strategy here is to add a complex
        # self-energy-like term always if the original Hamiltonian is complex,
        # and check for invertibility first if it is real

        matrices_real = issubclass(np.common_type(h_cell, h_hop), np.floating)
        add_imaginary = stabilization[0] or ((stabilization[0] is None) and
                                             not matrices_real)
        # Check if there is a chance we will not need to add an imaginary term.
        if not add_imaginary:
            h = h_cell
            sol = kla.lu_factor(h)
            rcond = kla.rcond_from_lu(sol, npl.norm(h, 1))

            if rcond < eps:
                need_to_stabilize = True
            else:
                need_to_stabilize = False

        if add_imaginary or need_to_stabilize:
            need_to_stabilize = True
            # Matrices are complex or need self-energy-like term to be
            # stabilized.
            temp = dot(u, u.T.conj()) + dot(v, v.T.conj())
            h = h_cell + 1j * temp

            sol = kla.lu_factor(h)
            rcond = kla.rcond_from_lu(sol, npl.norm(h, 1))

            # If the condition number of the stabilized h is
            # still bad, there is nothing we can do.
            if rcond < eps:
                raise RuntimeError("Flat band encountered at the requested "
                                   "energy, result is badly defined.")

        # The function that can extract the full wave function psi from
        # the projected one (v^dagger psi lambda^-1, s u^dagger psi).

        def extract_wf(psi, lmbdainv):
            wf = -dot(u, psi[: n_nonsing] * lmbdainv) - dot(v, psi[n_nonsing:])
            if need_to_stabilize:
                wf += 1j * (dot(v, psi[: n_nonsing]) +
                            dot(u, psi[n_nonsing:] * lmbdainv))
            return kla.lu_solve(sol, wf)

        # Setup the generalized eigenvalue problem.

        A = np.zeros((2 * n_nonsing, 2 * n_nonsing), np.common_type(h, h_hop))
        B = np.zeros((2 * n_nonsing, 2 * n_nonsing), np.common_type(h, h_hop))

        begin, end = slice(n_nonsing), slice(n_nonsing, None)

        A[end, begin] = np.identity(n_nonsing)
        temp = kla.lu_solve(sol, v)
        temp2 = dot(u.T.conj(), temp)
        if need_to_stabilize:
            A[begin, begin] = -1j * temp2
        A[begin, end] = temp2
        temp2 = dot(v.T.conj(), temp)
        if need_to_stabilize:
            A[end, begin] -= 1j *temp2
        A[end, end] = temp2

        B[begin, end] = -np.identity(n_nonsing)
        temp = kla.lu_solve(sol, u)
        temp2 = dot(u.T.conj(), temp)
        B[begin, begin] = -temp2
        if need_to_stabilize:
            B[begin, end] += 1j * temp2
        temp2 = dot(v.T.conj(), temp)
        B[end, begin] = -temp2
        if need_to_stabilize:
            B[end, end] = 1j * temp2

        v_out = v[:m]

        # Solving a generalized eigenproblem is about twice as expensive
        # as solving a regular eigenvalue problem.
        # Computing the LU factorization is negligible compared to both
        # (approximately 1/30th of a regular eigenvalue problem).
        # Because of this, it makes sense to try to reduce
        # the generalized eigenvalue problem to a regular one, provided
        # the matrix B can be safely inverted.

        lu_b = kla.lu_factor(B)
        if not stabilization[1]:
            rcond = kla.rcond_from_lu(lu_b, npl.norm(B, 1))
            # A more stringent condition is used here since errors can
            # accumulate from here to the eigenvalue calculation later.
            stabilization[1] = rcond > eps * tol

        if stabilization[1]:
            matrices = (kla.lu_solve(lu_b, A), None)
        else:
            matrices = (A, B)
    return Linsys(matrices, v_out, extract_wf)
Example #50
0
def convert_r2c_schur(t, q):
    """Convert a real Schur form (with possibly 2x2 blocks on the diagonal)
    into a complex Schur form that is completely triangular.

    This function is equivalent to the scipy.linalg.rsf2csf pendant (though the
    implementation is different), but there is additionally the guarantee that
    in the case of a 2x2 block at rows and columns i and i+1, t[i, i] will
    contain the eigenvalue with the positive part, and t[i+1, i+1] the one with
    the negative part.  This ensures that the list of eigenvalues (more
    precisely, their order) returned originally from schur() is still valid for
    the newly formed complex Schur form.

    Parameters
    ----------
    t : array, shape (M, M)
        Real Schur form of the original matrix
    q : array, shape (M, M)
        Schur transformation matrix

    Returns
    -------
    t : array, shape (M, M)
        Complex Schur form of the original matrix
    q : array, shape (M, M)
        Schur transformation matrix corresponding to the complex form
    """

    # First find the positions of 2x2-blocks
    blockpos = np.diagonal(t, -1).nonzero()[0]

    # Check if there are actually any 2x2-blocks
    if not blockpos.size:
        return (t, q)
    else:
        t2 = t.astype(np.common_type(t, np.array([], np.complex64)))
        q2 = q.astype(np.common_type(q, np.array([], np.complex64)))

    for i in blockpos:
        # Bringing a 2x2 block to complex triangular form is relatively simple:
        # the 2x2 blocks are guaranteed to be of the form [[a, b], [c, a]],
        # where b*c < 0. The eigenvalues of this matrix are a +/- i sqrt(-b*c),
        # the corresponding eigenvectors are [ +/- sqrt(-b*c), c].  The Schur
        # form can be achieved by a unitary 2x2 matrix with one of the
        # eigenvectors in the first column, and the second column an orthogonal
        # vector.

        a = t[i, i]
        b = t[i, i + 1]
        c = t[i + 1, i]

        x = 1j * sqrt(-b * c)
        y = c
        norm = sqrt(-b * c + c * c)

        U = np.array([[x / norm, -y / norm], [y / norm, -x / norm]])

        t2[i, i] = a + x
        t2[i + 1, i] = 0
        t2[i, i + 1] = -b - c
        t2[i + 1, i + 1] = a - x

        t2[:i, i:i + 2] = np.dot(t2[:i, i:i + 2], U)
        t2[i:i + 2, i + 2:] = np.dot(np.conj(U.T), t2[i:i + 2, i + 2:])

        q2[:, i:i + 2] = np.dot(q2[:, i:i + 2], U)

    return t2, q2
Example #51
0
def floor_divide(x1, x2, out=None, where=True, **kwargs):
    """
    Return the largest integer smaller or equal to the division of the inputs.

    It is equivalent to the Python ``//`` operator and pairs with the
    Python ``%`` (`remainder`), function so that ``a = a % b + b * (a // b)``
    up to roundoff.

    Args:
        x1 (numpoly.ndpoly):
            Numerator.
        x2 (numpoly.ndpoly):
            Denominator. If ``x1.shape != x2.shape``, they must be
            broadcastable to a common shape (which becomes the shape of the
            output).
        out (Optional[numpy.ndarray]):
            A location into which the result is stored. If provided, it must
            have a shape that the inputs broadcast to. If not provided or
            `None`, a freshly-allocated array is returned. A tuple (possible
            only as a keyword argument) must have length equal to the number of
            outputs.
        where (Optional[numpy.ndarray]):
            This condition is broadcast over the input. At locations where the
            condition is True, the `out` array will be set to the ufunc result.
            Elsewhere, the `out` array will retain its original value.
            Note that if an uninitialized `out` array is created via the default
            ``out=None``, locations within it where the condition is False will
            remain uninitialized.
        kwargs:
            Keyword args passed to numpy.ufunc.

    Returns:
        (numpoly.ndpoly):
            This is a scalar if both `x1` and `x2` are scalars.

    Examples:
        >>> xyz = [1, 2, 4]*numpoly.symbols("x y z")
        >>> numpoly.floor_divide(xyz, 2.)
        polynomial([0.0, y, 2.0*z])
        >>> numpoly.floor_divide(xyz, [1, 2, 4])
        polynomial([x, y, z])
        >>> numpoly.floor_divide([1, 2, 4], xyz)
        Traceback (most recent call last):
            ...
        ValueError: only constant polynomials can be converted to array.

    """
    x1, x2 = numpoly.align_polynomials(x1, x2)
    x2 = x2.tonumpy()
    no_output = out is None
    if no_output:
        out = numpoly.ndpoly(
            exponents=x1.exponents,
            shape=x1.shape,
            names=x1.indeterminants,
            dtype=numpy.common_type(x1, numpy.array(1.)),
        )
    for key in x1.keys:
        numpy.floor_divide(x1[key], x2, out=out[key], where=where, **kwargs)
    if no_output:
        out = numpoly.clean_attributes(out)
    return out
Example #52
0
def diags(diagonals, offsets, shape=None, format=None, dtype=None):
    """
    Construct a sparse matrix from diagonals.

    .. versionadded:: 0.11

    Parameters
    ----------
    diagonals : sequence of array_like
        Sequence of arrays containing the matrix diagonals,
        corresponding to `offsets`.
    offsets  : sequence of int
        Diagonals to set:
          - k = 0  the main diagonal
          - k > 0  the k-th upper diagonal
          - k < 0  the k-th lower diagonal
    shape : tuple of int, optional
        Shape of the result. If omitted, a square matrix large enough
        to contain the diagonals is returned.
    format : {"dia", "csr", "csc", "lil", ...}, optional
        Matrix format of the result.  By default (format=None) an
        appropriate sparse matrix format is returned.  This choice is
        subject to change.
    dtype : dtype, optional
        Data type of the matrix.

    See Also
    --------
    spdiags : construct matrix from diagonals

    Notes
    -----
    This function differs from `spdiags` in the way it handles
    off-diagonals.

    The result from `diags` is the sparse equivalent of::

        np.diag(diagonals[0], offsets[0])
        + ...
        + np.diag(diagonals[k], offsets[k])

    Repeated diagonal offsets are disallowed.

    Examples
    --------
    >>> diagonals = [[1,2,3,4], [1,2,3], [1,2]]
    >>> diags(diagonals, [0, -1, 2]).todense()
    matrix([[1, 0, 1, 0],
            [1, 2, 0, 2],
            [0, 2, 3, 0],
            [0, 0, 3, 4]])

    Broadcasting of scalars is supported (but shape needs to be
    specified):

    >>> diags([1, -2, 1], [-1, 0, 1], shape=(4, 4)).todense()
    matrix([[-2.,  1.,  0.,  0.],
            [ 1., -2.,  1.,  0.],
            [ 0.,  1., -2.,  1.],
            [ 0.,  0.,  1., -2.]])


    If only one diagonal is wanted (as in `numpy.diag`), the following
    works as well:

    >>> diags([1, 2, 3], 1).todense()
    matrix([[ 0.,  1.,  0.,  0.],
            [ 0.,  0.,  2.,  0.],
            [ 0.,  0.,  0.,  3.],
            [ 0.,  0.,  0.,  0.]])
    """
    # if offsets is not a sequence, assume that there's only one diagonal
    try:
        iter(offsets)
    except TypeError:
        # now check that there's actually only one diagonal
        try:
            iter(diagonals[0])
        except TypeError:
            diagonals = [np.atleast_1d(diagonals)]
        else:
            raise ValueError("Different number of diagonals and offsets.")
    else:
        diagonals = list(map(np.atleast_1d, diagonals))
    offsets = np.atleast_1d(offsets)

    # Basic check
    if len(diagonals) != len(offsets):
        raise ValueError("Different number of diagonals and offsets.")

    # Determine shape, if omitted
    if shape is None:
        m = len(diagonals[0]) + abs(int(offsets[0]))
        shape = (m, m)

    # Determine data type, if omitted
    if dtype is None:
        dtype = np.common_type(*diagonals)

    # Construct data array
    m, n = shape

    M = max(
        [min(m + offset, n - offset) + max(0, offset) for offset in offsets])
    M = max(0, M)
    data_arr = np.zeros((len(offsets), M), dtype=dtype)

    for j, diagonal in enumerate(diagonals):
        offset = offsets[j]
        k = max(0, offset)
        length = min(m + offset, n - offset)
        if length <= 0:
            raise ValueError("Offset %d (index %d) out of bounds" %
                             (offset, j))
        try:
            data_arr[j, k:k + length] = diagonal
        except ValueError:
            if len(diagonal) != length and len(diagonal) != 1:
                raise ValueError(
                    "Diagonal length (index %d: %d at offset %d) does not "
                    "agree with matrix size (%d, %d)." %
                    (j, len(diagonal), offset, m, n))
            raise

    return dia_matrix((data_arr, offsets), shape=(m, n)).asformat(format)
Example #53
0
def vq(obs, code_book):
    """ Vector Quantization: assign features sets to codes in a code book.

    Vector quantization determines which code in the code book best represents
    an observation of a target.  The features of each observation are compared
    to each code in the book, and assigned the one closest to it.  The
    observations are contained in the obs array. These features should be
    "whitened," or nomalized by the standard deviation of all the features
    before being quantized.  The code book can be created using the kmeans
    algorithm or something similar.

    :Parameters:
        obs : ndarray
            Each row of the array is an observation.  The columns are the
            "features" seen during each observation The features must be
            whitened first using the whiten function or something equivalent.
        code_book : ndarray.
            The code book is usually generated using the kmeans algorithm.
            Each row of the array holds a different code, and the columns are
            the features of the code.

            ::

                            #   f0    f1    f2   f3
                code_book = [[  1.,   2.,   3.,   4.],  #c0
                             [  1.,   2.,   3.,   4.],  #c1
                             [  1.,   2.,   3.,   4.]]) #c2

    :Returns:
        code : ndarray
            If obs is a NxM array, then a length N array is returned that holds
            the selected code book index for each observation.
        dist : ndarray
            The distortion (distance) between the observation and its nearest
            code

    Notes
    -----
    This currently forces 32 bit math precision for speed.  Anyone know
    of a situation where this undermines the accuracy of the algorithm?

    Examples
    --------
    >>> from numpy import array
    >>> from scipy.cluster.vq import vq
    >>> code_book = array([[1.,1.,1.],
    ...                    [2.,2.,2.]])
    >>> features  = array([[  1.9,2.3,1.7],
    ...                    [  1.5,2.5,2.2],
    ...                    [  0.8,0.6,1.7]])
    >>> vq(features,code_book)
    (array([1, 1, 0],'i'), array([ 0.43588989,  0.73484692,  0.83066239]))

    """
    try:
        import _vq
        ct = common_type(obs, code_book)
        c_obs = obs.astype(ct)
        c_code_book = code_book.astype(ct)
        if ct is single:
            results = _vq.vq(c_obs, c_code_book)
        elif ct is double:
            results = _vq.vq(c_obs, c_code_book)
        else:
            results = py_vq(obs, code_book)
    except ImportError:
        results = py_vq(obs, code_book)
    return results