Beispiel #1
0
	def analyse():
		pts = mesh.points		
		for p, neigh in it:
			# decide a local coordinate system
			u,v,w = dirbase(normals[p])
			# get neighboors contributions
			b = np.empty(len(neigh))
			a = np.empty((len(neigh), 14))
			for i,n in enumerate(neigh):
				e = pts[n] - pts[p]
				b[i] = dot(e,w)
				eu = dot(e,u)
				ev = dot(e,v)
				# these are the monoms to compose to build a polynom approximating the surface until 4th-order derivatives
				a[i] = (	eu**2, ev**2, eu*ev,
							eu, ev,
							eu**3, eu**2*ev, eu*ev**2, ev**3,
							eu**4, eu**3*ev, eu**2*ev**2, eu*ev**3, ev**4,
							)

			# least squares resulution, the complexity is roughly the same as inverting a mat3
			(au, av, auv, *_), residuals, *_ = np.linalg.lstsq(a, b)
			# diagonalize the curve tensor to get the principal curvatures
			diag, transfer = np.linalg.eigh(mat2(2*au, auv, 
													auv, 2*av))
			yield 1/np.max(np.abs(diag)), p
Beispiel #2
0
		def __init__(self, scene, sch):
			ctx = scene.ctx
			
			# set display params
			self.annotation = sch.annotation
			
			# load the ressources
			self.shaders, self.shader_ident = scene.ressource('scheme', self.load)
			
			# switch to array indexed spaces
			self.spaces = np.empty((self.max_spaces, 4,4), 'f4')
			self.spacegens = list(sch.spaces)
			if len(self.spacegens) > self.max_spaces:		
				print('warning: the number of local spaces exceeds the arbitrary build-in limit of {}'.format(self.max_spaces))
			
			self.components = [(space,scene.display(obj))	for space,obj in sch.components]
			
			
			self.nidents = max(v[5] for v in sch.vertices)+1
			self.box = boundingbox(fvec3(v[1]) for v in sch.vertices if self.spacegens[v[0]] is world)
			
			# prepare the buffer of vertices
			vertices = np.empty(len(sch.vertices), 'u1, 3f4, 3f4, 4u1, f4, u2, u1')
			for i,v in enumerate(sch.vertices):
				vertices[i] = (
					*v[:3],
					u8vec4(v[3]*255), 
					*v[4:]
					)			
			self.vb_vertices = ctx.buffer(vertices)
			verticesdef = [(self.vb_vertices, 'u1 3f4 3f4 4f1 f4 u2 u1', 
								'space', 
								'v_position', 
								'v_normal', 
								'v_color', 
								'v_layer', 
								'v_ident', 
								'v_flags')]
			
			# prepare the rending commands
			ident_triangles = []
			ident_lines = []
			self.vas = {}
			self.vai_triangles = None
			self.vai_lines = None
			for shname,batch in sch.primitives.items():
				if not batch:	continue
				if shname not in self.shaders:	raise KeyError('no shader for name {}'.format(repr(shname)))
				
				prim, shader = self.shaders[shname]
				vb_indices = ctx.buffer(np.array(batch, 'u4'))
				self.vas[shname] = (prim, ctx.vertex_array(shader, verticesdef, vb_indices, skip_errors=True))
				if prim == mgl.LINES:			ident_triangles.extend(batch)
				elif prim == mgl.TRIANGLES:		ident_lines.extend(batch)
			
			if ident_triangles:	self.vai_triangles	= ctx.vertex_array(self.shader_ident, verticesdef, ctx.buffer(np.array(ident_triangles, 'u4')), skip_errors=True)
			if ident_lines:		self.vai_lines 		= ctx.vertex_array(self.shader_ident, verticesdef, ctx.buffer(np.array(ident_lines, 'u4')), skip_errors=True)
Beispiel #3
0
	def init(self):
		w,h = self.width(), self.height()
		ctx = self.scene.ctx
		assert ctx, 'context is not initialized'

		# self.fb_frame is already created and sized by Qt
		self.fb_screen = ctx.detect_framebuffer(self.defaultFramebufferObject())
		self.fb_ident = ctx.simple_framebuffer((w,h), components=3, dtype='f1')
		self.targets = [ ('screen', self.fb_screen, self.setup_screen), 
						 ('ident', self.fb_ident, self.setup_ident)]
		self.map_ident = np.empty((h,w), dtype='u2')
		self.map_depth = np.empty((h,w), dtype='f4')
Beispiel #4
0
    def init(self, size):
        w, h = size

        ctx = self.scene.ctx
        assert ctx, 'context is not initialized'

        # self.fb_frame is already created and sized by Qt
        self.fb_screen = ctx.simple_framebuffer(size)
        self.fb_ident = ctx.simple_framebuffer(size, components=3, dtype='f1')
        self.targets = [('screen', self.fb_screen, self.setup_screen),
                        ('ident', self.fb_ident, self.setup_ident)]
        self.map_ident = np.empty((h, w), dtype='u2')
        self.map_depth = np.empty((h, w), dtype='f4')
Beispiel #5
0
  def build_sparse_crank_nicolson(s):
    """(internal) Set up the sparse matrices for the Crank-Nicolson method. """

    A = sparse.lil_matrix((s.n, s.n))
    C = sparse.lil_matrix((s.n, s.n))

    for j in xrange(0, s.n):
      xd = j+1+s.xs
      ssxx = (s.sigma * xd) ** 2

      A[j,j] = 1.0 - 0.5*s.dt*(ssxx + s.r)
      C[j,j] = 1.0 + 0.5*s.dt*(ssxx + s.r)
      
      if j > 0:
        A[j,j-1] = 0.25*s.dt*(+ssxx - s.r*xd)
        C[j,j-1] = 0.25*s.dt*(-ssxx + s.r*xd)
      if j < s.n-1:
        A[j,j+1] = 0.25*s.dt*(+ssxx + s.r*xd)
        C[j,j+1] = 0.25*s.dt*(-ssxx - s.r*xd)

    s.A = A.tocsr()
    s.C = linsolve.splu(C)              # perform sparse LU decomposition

    # Buffer to store right-hand side of the linear system Cu = v
    s.v = empty((n, ))
Beispiel #6
0
def fftfreq(n, d=1.0):
    """
    Return the Discrete Fourier Transform sample frequencies.

    The returned float array `f` contains the frequency bin centers in cycles
    per unit of the sample spacing (with zero at the start).  For instance, if
    the sample spacing is in seconds, then the frequency unit is cycles/second.

    Given a window length `n` and a sample spacing `d`::

      f = [0, 1, ...,   n/2-1,     -n/2, ..., -1] / (d*n)   if n is even
      f = [0, 1, ..., (n-1)/2, -(n-1)/2, ..., -1] / (d*n)   if n is odd

    Parameters
    ----------
    n : int
        Window length.
    d : scalar, optional
        Sample spacing (inverse of the sampling rate). Defaults to 1.

    Returns
    -------
    f : ndarray
        Array of length `n` containing the sample frequencies.
    """
    if not isinstance(n, integer_types):
        raise ValueError("n should be an integer")
    val = 1.0 / (n * d)
    results = empty(n, int)
    N = (n - 1) // 2 + 1
    p1 = arange(0, N, dtype=int)
    results[:N] = p1
    p2 = arange(-(n // 2), 0, dtype=int)
    results[N:] = p2
    return results * val
Beispiel #7
0
    def build_sparse_crank_nicolson(self, s):
        """(internal) Set up the sparse matrices for the Crank-Nicolson method. """

        A = sparse.lil_matrix((s.n, s.n))
        C = sparse.lil_matrix((s.n, s.n))

        for j in range(0, s.n):
            xd = j + 1 + s.xs
            ssxx = (s.sigma * xd)**2

            A[j, j] = 1.0 - 0.5 * s.dt * (ssxx + s.r)
            C[j, j] = 1.0 + 0.5 * s.dt * (ssxx + s.r)

            if j > 0:
                A[j, j - 1] = 0.25 * s.dt * (+ssxx - s.r * xd)
                C[j, j - 1] = 0.25 * s.dt * (-ssxx + s.r * xd)
            if j < s.n - 1:
                A[j, j + 1] = 0.25 * s.dt * (+ssxx + s.r * xd)
                C[j, j + 1] = 0.25 * s.dt * (-ssxx - s.r * xd)

        s.A = A.tocsr()
        s.C = linsolve.splu(
            sparse.lil_matrix.tocsc(C))  # perform sparse LU decomposition

        # Buffer to store right-hand side of the linear system Cu = v
        s.v = empty((self.n, ))
Beispiel #8
0
  def __init__(self, r, sigma, T, Bl, Bu, Fl, Fu, Fp, m, n):
    """Initialize the finite-difference solver.

     Parameters:
      r     - interest rate
      sigma - volatility
      T     - maturity time
      Bl    - stock price on lower boundary
      Bu    - stock price on upper boundary
      Fl    - value of option on lower boundary
      Fu    - value of option on upper boundary
      Fp    - pay-off at maturity
      m     - number of time steps to take when discretizing PDE
      n     - number of points in x (stock price) domain
              when discretizing PDE;  does not include the boundary points
    """

    self.r  = r;  self.sigma = sigma;  self.T  = T

    self.Bl = Bl;        self.Bu = Bu
    self.Fl = Fl;        self.Fu = Fu

    self.m  = m;         self.n  = n
    
    # Step sizes
    self.dt = float(T)/m
    self.dx = float(Bu-Bl)/(n+1)
    self.xs = Bl/self.dx

    # Grid that will eventually contain the finite-difference solution
    self.u = empty((m+1, n))
    self.u[0,:] = Fp                # initial condition
Beispiel #9
0
def fftfreq(n, d=1.0):
    if not isinstance(n, integer_types):
        raise ValueError("n should be an integer")
    val = 1.0 / (n * d)
    results = empty(n, int)
    N = (n - 1) // 2 + 1
    p1 = arange(0, N, dtype=int)
    results[:N] = p1
    p2 = arange(-(n // 2), 0, dtype=int)
    results[N:] = p2
    return results * val
Beispiel #10
0
		def load(scene):
			n = 101
			h = n//2
			pts = np.empty((n,n), dtype='f4, f4, f2')
			for i in range(n):
				for j in range(n):
					pts[i,j] = (i-h, j-h, (1+min(digitfit(i), digitfit(j))))
			
			shader = scene.ctx.program(
						vertex_shader=open(ressourcedir+'/shaders/viewgrid.vert').read(),
						fragment_shader=open(ressourcedir+'/shaders/viewgrid.frag').read(),
						)
			vb = scene.ctx.buffer(pts)
			va = scene.ctx.vertex_array(shader, [(vb, '2f4 f2', 'v_position', 'v_opacity')])
			return shader, va
Beispiel #11
0
def sqrt_ginv(a, rcond=1e-15):
    a, wrap = _makearray(a)
    rcond = asarray(rcond)
    if _is_empty_2d(a):
        m, n = a.shape[-2:]
        res = empty(a.shape[:-2] + (n, m), dtype=a.dtype)
        return wrap(res)
    a = a.conjugate()
    u, s, vt = svd(a, full_matrices=False)
    # discard small singular values
    cutoff = rcond[..., newaxis] * amax(s, axis=-1, keepdims=True)
    large = s > cutoff
    s = divide(1, s**0.5, where=large, out=s)
    s[~large] = 0 
    res = matmul(transpose(vt), multiply(s[..., newaxis], transpose(u)))
    return wrap(res)
Beispiel #12
0
def fftfreq(n, d=1.0):
    """
    Return the Discrete Fourier Transform sample frequencies.

    The returned float array `f` contains the frequency bin centers in cycles 
    per unit of the sample spacing (with zero at the start).  For instance, if 
    the sample spacing is in seconds, then the frequency unit is cycles/second.

    Given a window length `n` and a sample spacing `d`::

      f = [0, 1, ...,   n/2-1,     -n/2, ..., -1] / (d*n)   if n is even
      f = [0, 1, ..., (n-1)/2, -(n-1)/2, ..., -1] / (d*n)   if n is odd

    Parameters
    ----------
    n : int
        Window length.
    d : scalar, optional
        Sample spacing (inverse of the sampling rate). Defaults to 1.
        
    Returns
    -------
    f : ndarray
        Array of length `n` containing the sample frequencies.

    Examples
    --------
    >>> signal = np.array([-2, 8, 6, 4, 1, 0, 3, 5], dtype=float)
    >>> fourier = np.fft.fft(signal)
    >>> n = signal.size
    >>> timestep = 0.1
    >>> freq = np.fft.fftfreq(n, d=timestep)
    >>> freq
    array([ 0.  ,  1.25,  2.5 ,  3.75, -5.  , -3.75, -2.5 , -1.25])

    """
    if not (isinstance(n,types.IntType) or isinstance(n, integer)):
        raise ValueError("n should be an integer")
    val = 1.0 / (n * d)
    results = empty(n, int)
    N = (n-1)//2 + 1
    p1 = arange(0, N, dtype=int)
    results[:N] = p1
    p2 = arange(-(n//2), 0, dtype=int)
    results[N:] = p2
    return results * val
Beispiel #13
0
def fftfreq(n, d=1.0):
    """
    Return the Discrete Fourier Transform sample frequencies.

    The returned float array `f` contains the frequency bin centers in cycles
    per unit of the sample spacing (with zero at the start).  For instance, if
    the sample spacing is in seconds, then the frequency unit is cycles/second.

    Given a window length `n` and a sample spacing `d`::

      f = [0, 1, ...,   n/2-1,     -n/2, ..., -1] / (d*n)   if n is even
      f = [0, 1, ..., (n-1)/2, -(n-1)/2, ..., -1] / (d*n)   if n is odd

    Parameters
    ----------
    n : int
        Window length.
    d : scalar, optional
        Sample spacing (inverse of the sampling rate). Defaults to 1.

    Returns
    -------
    f : ndarray
        Array of length `n` containing the sample frequencies.

    Examples
    --------
    >>> signal = np.array([-2, 8, 6, 4, 1, 0, 3, 5], dtype=float)
    >>> fourier = np.fft.fft(signal)
    >>> n = signal.size
    >>> timestep = 0.1
    >>> freq = np.fft.fftfreq(n, d=timestep)
    >>> freq
    array([ 0.  ,  1.25,  2.5 ,  3.75, -5.  , -3.75, -2.5 , -1.25])

    """
    if not (isinstance(n, int) or isinstance(n, integer)):
        raise ValueError("n should be an integer")
    val = 1.0 / (n * d)
    results = empty(n, int)
    N = (n - 1) // 2 + 1
    p1 = arange(0, N, dtype=int)
    results[:N] = p1
    p2 = arange(-(n // 2), 0, dtype=int)
    results[N:] = p2
    return results * val
Beispiel #14
0
def fftfreq(n,d=1.0):
    """
    Discrete Fourier Transform sample frequencies.

    The returned float array contains the frequency bins in
    cycles/unit (with zero at the start) given a window length `n` and a
    sample spacing `d`.
    ::

      f = [0,1,...,n/2-1,-n/2,...,-1]/(d*n)         if n is even
      f = [0,1,...,(n-1)/2,-(n-1)/2,...,-1]/(d*n)   if n is odd

    Parameters
    ----------
    n : int
        Window length.
    d : scalar
        Sample spacing.

    Returns
    -------
    out : ndarray, shape(`n`,)
        Sample frequencies.

    Examples
    --------
    >>> signal = np.array([-2.,  8., -6.,  4.,  1., 0.,  3.,  5.])
    >>> fourier = np.fft.fft(signal)
    >>> n = len(signal)
    >>> timestep = 0.1
    >>> freq = np.fft.fftfreq(n, d=timestep)
    >>> freq
    array([ 0.  ,  1.25,  2.5 ,  3.75, -5.  , -3.75, -2.5 , -1.25])

    """
    assert isinstance(n,types.IntType) or isinstance(n, integer)
    val = 1.0/(n*d)
    results = empty(n, int)
    N = (n-1)//2 + 1
    p1 = arange(0,N,dtype=int)
    results[:N] = p1
    p2 = arange(-(n//2),0,dtype=int)
    results[N:] = p2
    return results * val
Beispiel #15
0
    def __init__(self, r, sigma, T, Bl, Bu, Fl, Fu, Fp, m, n, isAmericanOpt):

        super().__init__()
        """Initialize the finite-difference solver.

         Parameters:
          r     - interest rate
          sigma - volatility
          T     - maturity time
          Bl    - stock price on lower boundary
          Bu    - stock price on upper boundary
          Fl    - value of option on lower boundary
          Fu    - value of option on upper boundary
          Fp    - pay-off at maturity
          m     - number of time steps to take when discretizing PDE
          n     - number of points in x (stock price) domain
                  when discretizing PDE;  does not include the boundary points
        """

        self.r = r
        self.sigma = sigma
        self.T = T

        self.Bl = Bl
        self.Bu = Bu
        self.Fl = Fl
        self.Fu = Fu

        self.m = m
        self.n = n

        # Step sizes
        self.dt = float(T) / m
        self.dx = float(Bu - Bl) / (n + 1)
        self.xs = Bl / self.dx

        # Grid that will eventually contain the finite-difference solution
        self.u = empty((m + 1, n))
        self.u[0, :] = Fp  # initial condition
        self.isAmerican = isAmericanOpt
        self.intrinsicValue = self.u[0, :]
Beispiel #16
0
 def __init__(self, r, sigma, T, Smin, Smax, Fl, Fu, Fp, m, n):
 
     self.r  = r
     self.sigma = sigma
     self.T  = T
 
     self.Smin = Smin
     self.Smax = Smax
     self.Fl = Fl
     self.Fu = Fu
 
     self.m  = m
     self.n  = n
     
     # Step sizes
     self.dt = float(T)/m
     self.dx = float(Smax-Smin)/(n+1)
     self.xs = Smin/self.dx
 
     self.u = empty((m+1, n))
     self.u[0,:] = Fp
Beispiel #17
0
def fftfreq(n,d=1.0):
    """ fftfreq(n, d=1.0) -> f

    DFT sample frequencies

    The returned float array contains the frequency bins in
    cycles/unit (with zero at the start) given a window length n and a
    sample spacing d:

      f = [0,1,...,n/2-1,-n/2,...,-1]/(d*n)         if n is even
      f = [0,1,...,(n-1)/2,-(n-1)/2,...,-1]/(d*n)   if n is odd
    """
    assert isinstance(n,types.IntType) or isinstance(n, integer)
    val = 1.0/(n*d)
    results = empty(n, int)
    N = (n-1)//2 + 1
    p1 = arange(0,N,dtype=int)
    results[:N] = p1
    p2 = arange(-(n//2),0,dtype=int)
    results[N:] = p2
    return results * val
Beispiel #18
0
  def build_sparse_implicit(s):
    """(internal) Set up the sparse matrix system for the implicit method."""

    C = sparse.lil_matrix((s.n, s.n))

    for j in xrange(0, s.n):
      xd = j+1+s.xs
      ssxx = (s.sigma * xd) ** 2
      
      C[j,j] = 1.0 + s.dt*(ssxx + s.r)

      if j > 0:
        C[j,j-1] = 0.5*s.dt*(-ssxx + s.r*xd)
      if j < s.n-1:
        C[j,j+1] = 0.5*s.dt*(-ssxx - s.r*xd) 

    # Store matrix with sparse LU decomposition already performed
    s.C = linsolve.splu(C)

    # Buffer to store right-hand side of the linear system Cu = v
    s.v = empty((n, ))
Beispiel #19
0
    def build_sparse_implicit(self, s):
        """(internal) Set up the sparse matrix system for the implicit method."""

        C = sparse.lil_matrix((s.n, s.n))

        for j in range(0, s.n):
            xd = j + 1 + s.xs
            ssxx = (s.sigma * xd)**2

            C[j, j] = 1.0 + s.dt * (ssxx + s.r)

            if j > 0:
                C[j, j - 1] = 0.5 * s.dt * (-ssxx + s.r * xd)
            if j < s.n - 1:
                C[j, j + 1] = 0.5 * s.dt * (-ssxx - s.r * xd)

                # Store matrix with sparse LU decomposition already performed
        s.C = linsolve.splu(sparse.lil_matrix.tocsc(C))

        # Buffer to store right-hand side of the linear system Cu = v
        s.v = empty((n, ))
Beispiel #20
0
def fftfreq(n, d=1.0):
    """ fftfreq(n, d=1.0) -> f

    DFT sample frequencies

    The returned float array contains the frequency bins in
    cycles/unit (with zero at the start) given a window length n and a
    sample spacing d:

      f = [0,1,...,n/2-1,-n/2,...,-1]/(d*n)         if n is even
      f = [0,1,...,(n-1)/2,-(n-1)/2,...,-1]/(d*n)   if n is odd
    """
    assert isinstance(n, types.IntType) or isinstance(n, integer)
    val = 1.0 / (n * d)
    results = empty(n, int)
    N = (n - 1) // 2 + 1
    p1 = arange(0, N, dtype=int)
    results[:N] = p1
    p2 = arange(-(n // 2), 0, dtype=int)
    results[N:] = p2
    return results * val
Beispiel #21
0
 def build(self):
 
     A = sparse.lil_matrix((self.n, self.n))
     C = sparse.lil_matrix((self.n, self.n))
 
     for j in xrange(0, self.n):
         xd = j+1+self.xs
         ssxx = (self.sigma * xd) ** 2
     
         A[j,j] = 1.0 - 0.5*self.dt*(ssxx + self.r)
         C[j,j] = 1.0 + 0.5*self.dt*(ssxx + self.r)
         
         if j > 0:
             A[j,j-1] = 0.25*self.dt*(+ssxx - self.r*xd)
             C[j,j-1] = 0.25*self.dt*(-ssxx + self.r*xd)
         if j < self.n-1:
             A[j,j+1] = 0.25*self.dt*(+ssxx + self.r*xd)
             C[j,j+1] = 0.25*self.dt*(-ssxx - self.r*xd)
 
     self.A = A.tocsr()
     self.C = linsolve.splu(C)  # sparse LU decomposition
 
     # Buffer to store right-hand side of the linear system Cu = v
     self.v = empty((n, ))
Beispiel #22
0
def svd(a, full_matrices=1, compute_uv=1):
    """
    Singular Value Decomposition.

    Factorizes the matrix `a` into two unitary matrices, ``U`` and ``Vh``,
    and a 1-dimensional array of singular values, ``s`` (real, non-negative),
    such that ``a == U S Vh``, where ``S`` is the diagonal
    matrix ``np.diag(s)``.

    Parameters
    ----------
    a : array_like, shape (M, N)
        Matrix to decompose
    full_matrices : boolean, optional
        If True (default), ``U`` and ``Vh`` are shaped
        ``(M,M)`` and ``(N,N)``.  Otherwise, the shapes are
        ``(M,K)`` and ``(K,N)``, where ``K = min(M,N)``.
    compute_uv : boolean
        Whether to compute ``U`` and ``Vh`` in addition to ``s``.
        True by default.

    Returns
    -------
    U : ndarray, shape (M, M) or (M, K) depending on `full_matrices`
        Unitary matrix.
    s :  ndarray, shape (K,) where ``K = min(M, N)``
        The singular values, sorted so that ``s[i] >= s[i+1]``.
    Vh : ndarray, shape (N,N) or (K,N) depending on `full_matrices`
        Unitary matrix.

    Raises
    ------
    LinAlgError
        If SVD computation does not converge.

    Notes
    -----
    If `a` is a matrix (in contrast to an ndarray), then so are all
    the return values.

    Examples
    --------
    >>> a = np.random.randn(9, 6) + 1j*np.random.randn(9, 6)
    >>> U, s, Vh = np.linalg.svd(a)
    >>> U.shape, Vh.shape, s.shape
    ((9, 9), (6, 6), (6,))

    >>> U, s, Vh = np.linalg.svd(a, full_matrices=False)
    >>> U.shape, Vh.shape, s.shape
    ((9, 6), (6, 6), (6,))
    >>> S = np.diag(s)
    >>> np.allclose(a, np.dot(U, np.dot(S, Vh)))
    True

    >>> s2 = np.linalg.svd(a, compute_uv=False)
    >>> np.allclose(s, s2)
    True

    """
    a, wrap = _makearray(a)
    _assertRank2(a)
    _assertNonEmpty(a)
    m, n = a.shape
    t, result_t = _commonType(a)
    real_t = _linalgRealType(t)
    a = _fastCopyAndTranspose(t, a)
    s = zeros((min(n, m), ), real_t)
    if compute_uv:
        if full_matrices:
            nu = m
            nvt = n
            option = 'A'
        else:
            nu = min(n, m)
            nvt = min(n, m)
            option = 'S'
        u = zeros((nu, m), t)
        vt = zeros((n, nvt), t)
    else:
        option = 'N'
        nu = 1
        nvt = 1
        u = empty((1, 1), t)
        vt = empty((1, 1), t)

    iwork = zeros((8 * min(m, n), ), fortran_int)
    if isComplexType(t):
        lapack_routine = lapack_lite.zgesdd
        rwork = zeros((5 * min(m, n) * min(m, n) + 5 * min(m, n), ), real_t)
        lwork = 1
        work = zeros((lwork, ), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt, work,
                                 -1, rwork, iwork, 0)
        lwork = int(abs(work[0]))
        work = zeros((lwork, ), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt, work,
                                 lwork, rwork, iwork, 0)
    else:
        lapack_routine = lapack_lite.dgesdd
        lwork = 1
        work = zeros((lwork, ), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt, work,
                                 -1, iwork, 0)
        lwork = int(work[0])
        work = zeros((lwork, ), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt, work,
                                 lwork, iwork, 0)
    if results['info'] > 0:
        raise LinAlgError, 'SVD did not converge'
    s = s.astype(_realType(result_t))
    if compute_uv:
        u = u.transpose().astype(result_t)
        vt = vt.transpose().astype(result_t)
        return wrap(u), s, wrap(vt)
    else:
        return s
Beispiel #23
0
def svd(a, full_matrices=1, compute_uv=1):
    """Singular Value Decomposition.

    Factorizes the matrix a into two unitary matrices U and Vh and
    an 1d-array s of singular values (real, non-negative) such that
    a == U S Vh  if S is an suitably shaped matrix of zeros whose
    main diagonal is s.

    Parameters
    ----------
    a : array-like, shape (M, N)
        Matrix to decompose
    full_matrices : boolean
        If true,  U, Vh are shaped  (M,M), (N,N)
        If false, the shapes are    (M,K), (K,N) where K = min(M,N)
    compute_uv : boolean
        Whether to compute U and Vh in addition to s

    Returns
    -------
    U:  array, shape (M,M) or (M,K) depending on full_matrices
    s:  array, shape (K,)
        The singular values, sorted so that s[i] >= s[i+1]
        K = min(M, N)
    Vh: array, shape (N,N) or (K,N) depending on full_matrices

    If a is a matrix, so are all the return values.

    Raises LinAlgError if SVD computation does not converge

    Examples
    --------
    >>> a = random.randn(9, 6) + 1j*random.randn(9, 6)
    >>> U, s, Vh = linalg.svd(a)
    >>> U.shape, Vh.shape, s.shape
    ((9, 9), (6, 6), (6,))

    >>> U, s, Vh = linalg.svd(a, full_matrices=False)
    >>> U.shape, Vh.shape, s.shape
    ((9, 6), (6, 6), (6,))
    >>> S = diag(s)
    >>> allclose(a, dot(U, dot(S, Vh)))
    True

    >>> s2 = linalg.svd(a, compute_uv=False)
    >>> allclose(s, s2)
    True
    """
    a, wrap = _makearray(a)
    _assertRank2(a)
    _assertNonEmpty(a)
    m, n = a.shape
    t, result_t = _commonType(a)
    real_t = _linalgRealType(t)
    a = _fastCopyAndTranspose(t, a)
    s = zeros((min(n, m),), real_t)
    if compute_uv:
        if full_matrices:
            nu = m
            nvt = n
            option = 'A'
        else:
            nu = min(n, m)
            nvt = min(n, m)
            option = 'S'
        u = zeros((nu, m), t)
        vt = zeros((n, nvt), t)
    else:
        option = 'N'
        nu = 1
        nvt = 1
        u = empty((1, 1), t)
        vt = empty((1, 1), t)

    iwork = zeros((8*min(m, n),), fortran_int)
    if isComplexType(t):
        lapack_routine = lapack_lite.zgesdd
        rwork = zeros((5*min(m, n)*min(m, n) + 5*min(m, n),), real_t)
        lwork = 1
        work = zeros((lwork,), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt,
                                 work, -1, rwork, iwork, 0)
        lwork = int(abs(work[0]))
        work = zeros((lwork,), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt,
                                 work, lwork, rwork, iwork, 0)
    else:
        lapack_routine = lapack_lite.dgesdd
        lwork = 1
        work = zeros((lwork,), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt,
                                 work, -1, iwork, 0)
        lwork = int(work[0])
        work = zeros((lwork,), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt,
                                 work, lwork, iwork, 0)
    if results['info'] > 0:
        raise LinAlgError, 'SVD did not converge'
    s = s.astype(_realType(result_t))
    if compute_uv:
        u = u.transpose().astype(result_t)
        vt = vt.transpose().astype(result_t)
        return wrap(u), s, wrap(vt)
    else:
        return s
Beispiel #24
0
def svd_zgesvd(a, full_matrices=1, compute_uv=1):
    """
    Singular Value Decomposition of a complex matrix.

    Factorizes the matrix `a` into two unitary matrices, ``U`` and ``Vh``,
    and a 1-dimensional array of singular values, ``s`` (real, non-negative),
    such that ``a == U S Vh``, where ``S`` is the diagonal
    matrix ``np.diag(s)``.

    Parameters
    ----------
    a : array_like, shape (M, N)
        Matrix to decompose
    full_matrices : boolean, optional
        If True (default), ``U`` and ``Vh`` are shaped
        ``(M,M)`` and ``(N,N)``.  Otherwise, the shapes are
        ``(M,K)`` and ``(K,N)``, where ``K = min(M,N)``.
    compute_uv : boolean
        Whether to compute ``U`` and ``Vh`` in addition to ``s``.
        True by default.

    Returns
    -------
    U : ndarray, shape (M, M) or (M, K) depending on `full_matrices`
        Unitary matrix.
    s :  ndarray, shape (K,) where ``K = min(M, N)``
        The singular values, sorted so that ``s[i] >= s[i+1]``.
    Vh : ndarray, shape (N,N) or (K,N) depending on `full_matrices`
        Unitary matrix.

    Raises
    ------
    LinAlgError
        If SVD computation fails. 
        For details see zgesvd.f and dbdsqr.f of LAPACK
    """
    a, wrap = _makearray(a)
    _assertRank2(a)
    _assertNonEmpty(a)
    m, n = a.shape
    t, result_t = _commonType(a)
    real_t = _linalgRealType(t)
    real_t = _linalgRealType(t)
    a = _fastCopyAndTranspose(t, a)
    s = zeros((min(n, m),), real_t)

    if compute_uv:
        if full_matrices:
            nu = m
            nvt = n
            option = "A"
        else:
            nu = min(n, m)
            nvt = min(n, m)
            option = "S"
        u = zeros((nu, m), t)
        vt = zeros((n, nvt), t)
    else:
        option = "N"
        nu = 1
        nvt = 1
        u = empty((1, 1), t)
        vt = empty((1, 1), t)

    lapack_routine = lib.zgesvd_

    lwork = 1
    work = zeros((lwork,), t)
    INFO = c_int(0)
    m = c_int(m)
    n = c_int(n)
    nvt = c_int(nvt)
    lwork = c_int(-1)
    K = min(a.shape)
    rwork = zeros((5 * K,), real_t)
    lapack_routine(option, option, m, n, a, m, s, u, m, vt, nvt, work, lwork, rwork, INFO)
    if INFO.value < 0:
        raise Exception("%d-th argument had an illegal value" % INFO.value)

    lwork = int(work[0].real)
    work = zeros((lwork,), t)
    lwork = c_int(lwork)
    rwork = zeros((5 * K,), real_t)

    lapack_routine(option, option, m, n, a, m, s, u, m, vt, nvt, work, lwork, rwork, INFO)

    if INFO.value > 0:
        raise Exception("Error during factorization: %d" % INFO.value)
    #        raise LinAlgError, 'SVD did not converge'
    s = s.astype(_realType(result_t))

    if compute_uv:
        u = u.transpose().astype(result_t)
        vt = vt.transpose().astype(result_t)
        return wrap(u), s, wrap(vt)
    else:
        return s
Beispiel #25
0
def glmarray(array, dtype='f4'):
    ''' create a numpy array from a list of glm vec '''
    buff = np.empty((len(array), len(array[0])), dtype=dtype)
    for i, e in enumerate(array):
        buff[i][:] = e
    return buff
b1c0, c1 = C.shape; cost1 = a0 * b1c0 * (a1b0 + c1); cost2 = a1b0 * c1 * (a0 + b1c0); if cost1 < cost2: return dot(dot(A, B), C); else: return dot(A, dot(B, C)); def _multi_dot_matrix_chain_order(arrays, return_costs=False): n = len(arrays); p = [a.shape[0] for a in arrays] + [arrays[-1].shape[1]]; m = zeros((n, n), dtype=double); s = empty((n, n), dtype=intp); for l in range(1, n): for i in range(n - l): j = i + l; m[i, j] = Inf; for k in range(i, j): q = m[i, k] + m[k+1, j] + p[i]*p[k+1]*p[j+1]; if q < m[i, j]: m[i, j] = q; s[i, j] = k; if i == j: return arrays[i]; else: return dot(_multi_dot(arrays, order, i, order[i, j]),; _multi_dot(arrays, order, order[i, j] + 1, j))
__all__ = ['matrix_power', 'solve', 'tensorsolve', 'tensorinv', 'inv',
'cholesky', 'eigvals', 'eigvalsh', 'pinv', 'slogdet', 'det',
'svd', 'eig', 'eigh', 'lstsq', 'norm', 'qr', 'cond', 'matrix_rank',
'LinAlgError', 'multi_dot']; import functools
import operator
import warnings; from numpy.core import (
array, asarray, zeros, empty, empty_like, intc, single, double,
csingle, cdouble, inexact, complexfloating, newaxis, all, Inf, dot,
add, multiply, sqrt, fastCopyAndTranspose, sum, isfinite,
finfo, errstate, geterrobj, moveaxis, amin, amax, product, abs,
atleast_2d, intp, asanyarray, object_, matmul,
swapaxes, divide, count_nonzero, isnan, sign
); from numpy.core.multiarray import normalize_axis_index; from numpy.core.overrides import set_module; from numpy.core import overrides; from numpy.lib.twodim_base import triu, eye; from numpy.linalg import lapack_lite, _umath_linalg; array_function_dispatch = functools.partial(
overrides.array_function_dispatch, module='numpy.linalg'); _N = b'N'; _V = b'V'; _A = b'A'; _S = b'S'; _L = b'L' fortran_int = intc @set_module('numpy.linalg') class LinAlgError(Exception): def _determine_error_states(): errobj = geterrobj() bufsize = errobj[0] with errstate(invalid='call', over='ignore', divide='ignore', under='ignore'): invalid_call_errmask = geterrobj()[1] return [bufsize, invalid_call_errmask, None]; _linalg_error_extobj = _determine_error_states(); del _determine_error_states; def _raise_linalgerror_singular(err, flag): raise LinAlgError("Singular matrix"); def _raise_linalgerror_nonposdef(err, flag): raise LinAlgError("Matrix is not positive definite"); def _raise_linalgerror_eigenvalues_nonconvergence(err, flag): raise LinAlgError("Eigenvalues did not converge"); def _raise_linalgerror_svd_nonconvergence(err, flag): raise LinAlgError("SVD did not converge"); def _raise_linalgerror_lstsq(err, flag): raise LinAlgError("SVD did not converge in Linear Least Squares"); def get_linalg_error_extobj(callback): extobj = list(_linalg_error_extobj); extobj[2] = callback; return extobj; def _makearray(a): new = asarray(a); wrap = getattr(a, "__array_prepare__", new.__array_wrap__); return new, wrap; def isComplexType(t): return issubclass(t, complexfloating); _real_types_map = {single: single,; double: double,; csingle: single,; cdouble: double}; _complex_types_map = {single: csingle,; double: cdouble,; csingle: csingle,; cdouble: cdouble}; def _realType(t, default=double): return _real_types_map.get(t, default); def _complexType(t, default=cdouble): return _complex_types_map.get(t, default); def _linalgRealType(t): """Cast the type t to either double or cdouble."""; return double; def _commonType(*arrays): result_type = single; is_complex = False; for a in arrays: if issubclass(a.dtype.type, inexact): if isComplexType(a.dtype.type): is_complex = True; rt = _realType(a.dtype.type, default=None); if rt is None: raise TypeError("array type %s is unsupported in linalg" %; (a.dtype.name,)); else: rt = double; if rt is double: result_type = double; if is_complex: t = cdouble; result_type = _complex_types_map[result_type]; else: t = double; return t, result_type;  _fastCT = fastCopyAndTranspose; def _to_native_byte_order(*arrays): ret = []; for arr in arrays: if arr.dtype.byteorder not in ('=', '|'): ret.append(asarray(arr, dtype=arr.dtype.newbyteorder('='))); else: ret.append(arr); if len(ret) == 1: return ret[0]; else: return ret; def _fastCopyAndTranspose(type, *arrays): cast_arrays = (); for a in arrays: if a.dtype.type is type: cast_arrays = cast_arrays + (_fastCT(a),); else: cast_arrays = cast_arrays + (_fastCT(a.astype(type)),); if len(cast_arrays) == 1: return cast_arrays[0]; else: return cast_arrays; def _assert_2d(*arrays): for a in arrays: if a.ndim != 2: raise LinAlgError('%d-dimensional array given. Array must be '; 'two-dimensional' % a.ndim); def _assert_stacked_2d(*arrays): for a in arrays: if a.ndim < 2: raise LinAlgError('%d-dimensional array given. Array must be '; 'at least two-dimensional' % a.ndim); def _assert_stacked_square(*arrays): for a in arrays: m, n = a.shape[-2:]; if m != n: raise LinAlgError('Last 2 dimensions of the array must be square'); def _assert_finite(*arrays): for a in arrays: if not isfinite(a).all(): raise LinAlgError("Array must not contain infs or NaNs"); def _is_empty_2d(arr): return arr.size == 0 and product(arr.shape[-2:]) == 0; def transpose(a): a, wrap = _makearray(a); b = asarray(b); an = a.ndim; if axes is not None: allaxes = list(range(0, an)); for k in axes: allaxes.remove(k); allaxes.insert(an, k); a = a.transpose(allaxes); oldshape = a.shape[-(an-b.ndim):]; prod = 1; for k in oldshape: prod *= k; a = a.reshape(-1, prod); b = b.ravel(); res = wrap(solve(a, b)); res.shape = oldshape; return res; def _solve_dispatcher(a, b): return (a, b); @array_function_dispatch(_solve_dispatcher); def solve(a, b):  a, _ = _makearray(a); _assert_stacked_2d(a); _assert_stacked_square(a); b, wrap = _makearray(b); t, result_t = _commonType(a, b); if b.ndim == a.ndim - 1: gufunc = _umath_linalg.solve1; else: gufunc = _umath_linalg.solve; signature = 'DD->D' if isComplexType(t) else 'dd->d'; extobj = get_linalg_error_extobj(_raise_linalgerror_singular); r = gufunc(a, b, signature=signature, extobj=extobj); return wrap(r.astype(result_t, copy=False)); def _tensorinv_dispatcher(a, ind=None): return (a,); @array_function_dispatch(_tensorinv_dispatcher); def tensorinv(a, ind=2): a = asarray(a); oldshape = a.shape; prod = 1; if ind > 0: invshape = oldshape[ind:] + oldshape[:ind]; for k in oldshape[ind:]: prod *= k; else: raise ValueError("Invalid ind argument."); a = a.reshape(prod, -1); ia = inv(a); return ia.reshape(*invshape); def _unary_dispatcher(a): return (a,); @array_function_dispatch(_unary_dispatcher); def inv(a): a, wrap = _makearray(a); _assert_stacked_2d(a); _assert_stacked_square(a); t, result_t = _commonType(a); signature = 'D->D' if isComplexType(t) else 'd->d'; extobj = get_linalg_error_extobj(_raise_linalgerror_singular); ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj); return wrap(ainv.astype(result_t, copy=False)); def _matrix_power_dispatcher(a, n): return (a,); @array_function_dispatch(_matrix_power_dispatcher); def matrix_power(a, n): a = asanyarray(a); _assert_stacked_2d(a); _assert_stacked_square(a); try: n = operator.index(n); except TypeError: raise TypeError("exponent must be an integer"); if a.dtype != object: fmatmul = matmul; elif a.ndim == 2: fmatmul = dot; else: raise NotImplementedError(; "matrix_power not supported for stacks of object arrays"); if n == 0: a = empty_like(a); a[...] = eye(a.shape[-2], dtype=a.dtype); return a; elif n < 0: a = inv(a); n = abs(n); if n == 1: return a; elif n == 2: return fmatmul(a, a); elif n == 3: return fmatmul(fmatmul(a, a), a); z = result = None; while n > 0: z = a if z is None else fmatmul(z, z); n, bit = divmod(n, 2); if bit: result = z if result is None else fmatmul(result, z); return result; @array_function_dispatch(_unary_dispatcher); def cholesky(a): extobj = get_linalg_error_extobj(_raise_linalgerror_nonposdef); gufunc = _umath_linalg.cholesky_lo; a, wrap = _makearray(a); _assert_stacked_2d(a); _assert_stacked_square(a); t, result_t = _commonType(a); signature = 'D->D' if isComplexType(t) else 'd->d'; r = gufunc(a, signature=signature, extobj=extobj); return wrap(r.astype(result_t, copy=False)); def _qr_dispatcher(a, mode=None): return (a,); @array_function_dispatch(_qr_dispatcher); def qr(a, mode='reduced'): if mode not in ('reduced', 'complete',x 'r', 'raw'): if mode in ('f', 'full'): msg = "".join((; "The 'full' option is deprecated in favor of 'reduced'.\n",; "For backward compatibility let mode default.")); warnings.warn(msg, DeprecationWarning, stacklevel=3); mode = 'reduced'; elif mode in ('e', 'economic'): msg = "The 'economic' option is deprecated."; warnings.warn(msg, DeprecationWarning, stacklevel=3); mode = 'economic'; else: raise ValueError("Unrecognized mode '%s'" % mode); a, wrap = _makearray(a); _assert_2d(a); m, n = a.shape; t, result_t = _commonType(a); a = _fastCopyAndTranspose(t, a); a = _to_native_byte_order(a); mn = min(m, n); tau = zeros((mn,), t); if isComplexType(t): lapack_routine = lapack_lite.zgeqrf; routine_name = 'zgeqrf'; else: lapack_routine = lapack_lite.dgeqrf; routine_name = 'dgeqrf'; lwork = 1; work = zeros((lwork,), t); results = lapack_routine(m, n, a, max(1, m), tau, work, -1, 0); if results['info'] != 0: raise LinAlgError('%s returns %d' % (routine_name, results['info'])); lwork = max(1, n, int(abs(work[0]))); work = zeros((lwork,), t); results = lapack_routine(m, n, a, max(1, m), tau, work, lwork, 0); if results['info'] != 0: raise LinAlgError('%s returns %d' % (routine_name, results['info'])); if mode == 'r': r = _fastCopyAndTranspose(result_t, a[:, :mn]); return wrap(triu(r)); if mode == 'raw': return a, tau; if mode == 'economic': if t != result_t : a = a.astype(result_t, copy=False); return wrap(a.T); if mode == 'complete' and m > n: mc = m; q = empty((m, m), t); else: mc = mn; q = empty((n, m), t); q[:n] = a; if isComplexType(t): lapack_routine = lapack_lite.zungqr; routine_name = 'zungqr'; else: lapack_routine = lapack_lite.dorgqr; routine_name = 'dorgqr'; lwork = 1; work = zeros((lwork,), t); results = lapack_routine(m, mc, mn, q, max(1, m), tau, work, -1, 0); if results['info'] != 0: raise LinAlgError('%s returns %d' % (routine_name, results['info'])); lwork = max(1, n, int(abs(work[0]))); work = zeros((lwork,), t); results = lapack_routine(m, mc, mn, q, max(1, m), tau, work, lwork, 0); if results['info'] != 0: raise LinAlgError('%s returns %d' % (routine_name, results['info'])); q = _fastCopyAndTranspose(result_t, q[:mc]); r = _fastCopyAndTranspose(result_t, a[:, :mc]); return wrap(q), wrap(triu(r)); @array_function_dispatch(_unary_dispatcher); def eigvals(a): a, wrap = _makearray(a); _assert_stacked_2d(a); _assert_stacked_square(a); _assert_finite(a); t, result_t = _commonType(a); extobj = get_linalg_error_extobj(; _raise_linalgerror_eigenvalues_nonconvergence); signature = 'D->D' if isComplexType(t) else 'd->D'; w = _umath_linalg.eigvals(a, signature=signature, extobj=extobj); if not isComplexType(t): if all(w.imag == 0): w = w.real; result_t = _realType(result_t); else: result_t = _complexType(result_t); return w.astype(result_t, copy=False); def _eigvalsh_dispatcher(a, UPLO=None): return (a,); @array_function_dispatch(_eigvalsh_dispatcher); def eigvalsh(a, UPLO='L'): UPLO = UPLO.upper(); if UPLO not in ('L', 'U'): raise ValueError("UPLO argument must be 'L' or 'U'"); extobj = get_linalg_error_extobj(; _raise_linalgerror_eigenvalues_nonconvergence); if UPLO == 'L': gufunc = _umath_linalg.eigvalsh_lo; else: gufunc = _umath_linalg.eigvalsh_up; a, wrap = _makearray(a); _assert_stacked_2d(a); _assert_stacked_square(a); t, result_t = _commonType(a); signature = 'D->d' if isComplexType(t) else 'd->d'; w = gufunc(a, signature=signature, extobj=extobj); return w.astype(_realType(result_t), copy=False); def _convertarray(a): t, result_t = _commonType(a); a = _fastCT(a.astype(t)); return a, t, result_t; def eig(a): a, wrap = _makearray(a); _assert_stacked_2d(a); _assert_stacked_square(a); _assert_finite(a); t, result_t = _commonType(a); extobj = get_linalg_error_extobj(; _raise_linalgerror_eigenvalues_nonconvergence); signature = 'D->DD' if isComplexType(t) else 'd->DD'; w, vt = _umath_linalg.eig(a, signature=signature, extobj=extobj); if not isComplexType(t) and all(w.imag == 0.0): w = w.real; vt = vt.real; result_t = _realType(result_t); else: result_t = _complexType(result_t); vt = vt.astype(result_t, copy=False); return w.astype(result_t, copy=False), wrap(vt); @array_function_dispatch(_eigvalsh_dispatcher); def eigh(a, UPLO='L'): UPLO = UPLO.upper(); if UPLO not in ('L', 'U'): raise ValueError("UPLO argument must be 'L' or 'U'"); a, wrap = _makearray(a); _assert_stacked_2d(a); _assert_stacked_square(a); t, result_t = _commonType(a); extobj = get_linalg_error_extobj(; _raise_linalgerror_eigenvalues_nonconvergence); if UPLO == 'L': gufunc = _umath_linalg.eigh_lo; else: gufunc = _umath_linalg.eigh_up; signature = 'D->dD' if isComplexType(t) else 'd->dd'; w, vt = gufunc(a, signature=signature, extobj=extobj); w = w.astype(_realType(result_t), copy=False); vt = vt.astype(result_t, copy=False); return w, wrap(vt); def _svd_dispatcher(a, full_matrices=None, compute_uv=None, hermitian=None): return (a,); @array_function_dispatch(_svd_dispatcher); def svd(a, full_matrices=True, compute_uv=True, hermitian=False): a, wrap = _makearray(a); if hermitian: if compute_uv: s, u = eigh(a); s = s[..., ::-1]; u = u[..., ::-1]; vt = transpose(u * sign(s)[..., None, :]).conjugate(); s = abs(s); return wrap(u), s, wrap(vt); else: s = eigvalsh(a); s = s[..., ::-1]; s = abs(s); return s; _assert_stacked_2d(a); t, result_t = _commonType(a); extobj = get_linalg_error_extobj(_raise_linalgerror_svd_nonconvergence); m, n = a.shape[-2:]; if compute_uv: if full_matrices: if m < n: gufunc = _umath_linalg.svd_m_f; else: gufunc = _umath_linalg.svd_n_f; else: if m < n: gufunc = _umath_linalg.svd_m_s; else: gufunc = _umath_linalg.svd_n_s; signature = 'D->DdD' if isComplexType(t) else 'd->ddd'; u, s, vh = gufunc(a, signature=signature, extobj=extobj); u = u.astype(result_t, copy=False); s = s.astype(_realType(result_t), copy=False); vh = vh.astype(result_t, copy=False); return wrap(u), s, wrap(vh); else: if m < n: gufunc = _umath_linalg.svd_m; else: gufunc = _umath_linalg.svd_n; signature = 'D->d' if isComplexType(t) else 'd->d'; s = gufunc(a, signature=signature, extobj=extobj); s = s.astype(_realType(result_t), copy=False); return s; def _cond_dispatcher(x, p=None): return (x,); @array_function_dispatch(_cond_dispatcher); def cond(x, p=None): x = asarray(x); if _is_empty_2d(x): raise LinAlgError("cond is not defined on empty arrays"); if p is None or p == 2 or p == -2: s = svd(x, compute_uv=False); with errstate(all='ignore'): if p == -2: r = s[..., -1] / s[..., 0]; else: r = s[..., 0] / s[..., -1]; else: _assert_stacked_2d(x); _assert_stacked_square(x); t, result_t = _commonType(x); signature = 'D->D' if isComplexType(t) else 'd->d'; with errstate(all='ignore'): invx = _umath_linalg.inv(x, signature=signature); r = norm(x, p, axis=(-2, -1)) * norm(invx, p, axis=(-2, -1)); r = r.astype(result_t, copy=False); r = asarray(r); nan_mask = isnan(r); if nan_mask.any(): nan_mask &= ~isnan(x).any(axis=(-2, -1)); if r.ndim > 0: r[nan_mask] = Inf; elif nan_mask: r[()] = Inf; if r.ndim == 0: r = r[()]; return r; def _matrix_rank_dispatcher(M, tol=None, hermitian=None): return (M,); @array_function_dispatch(_matrix_rank_dispatcher); def matrix_rank(M, tol=None, hermitian=False): M = asarray(M); if M.ndim < 2: return int(not all(M==0)); S = svd(M, compute_uv=False, hermitian=hermitian); if tol is None: tol = S.max(axis=-1, keepdims=True) * max(M.shape[-2:]) * finfo(S.dtype).eps; else: tol = asarray(tol)[..., newaxis]; return count_nonzero(S > tol, axis=-1); def pinv(a, rcond=1e-15, hermitian=False): a, wrap = _makearray(a); rcond = asarray(rcond); if _is_empty_2d(a): m, n = a.shape[-2:]; res = empty(a.shape[:-2] + (n, m), dtype=a.dtype); return wrap(res); a = a.conjugate(); u, s, vt = svd(a, full_matrices=False, hermitian=hermitian); cutoff = rcond[..., newaxis] * amax(s, axis=-1, keepdims=True); large = s > cutoff; s = divide(1, s, where=large, out=s); s[~large] = 0; res = matmul(transpose(vt), multiply(s[..., newaxis], transpose(u))); return wrap(res); def slogdet(a): a = asarray(a); _assert_stacked_2d(a); _assert_stacked_square(a); t, result_t = _commonType(a); real_t = _realType(result_t); signature = 'D->Dd' if isComplexType(t) else 'd->dd'; sign, logdet = _umath_linalg.slogdet(a, signature=signature); sign = sign.astype(result_t, copy=False); logdet = logdet.astype(real_t, copy=False); return sign, logdet; @array_function_dispatch(_unary_dispatcher); def det(a): a = asarray(a); _assert_stacked_2d(a); _assert_stacked_square(a); t, result_t = _commonType(a); signature = 'D->D' if isComplexType(t) else 'd->d'; r = _umath_linalg.det(a, signature=signature); r = r.astype(result_t, copy=False); return r; def lstsq(a, b, rcond="warn"): a, _ = _makearray(a); b, wrap = _makearray(b); is_1d = b.ndim == 1; if is_1d: b = b[:, newaxis]; _assert_2d(a, b); m, n = a.shape[-2:]; m2, n_rhs = b.shape[-2:]; if m != m2: raise LinAlgError('Incompatible dimensions'); t, result_t = _commonType(a, b); real_t = _linalgRealType(t); result_real_t = _realType(result_t); if rcond == "warn": warnings.warn("`rcond` parameter will change to the default of "; "machine precision times ``max(M, N)`` where M and N "; "are the input matrix dimensions.\n"; "To use the future default and silence this warning "; "we advise to pass `rcond=None`, to keep using the old, "; "explicitly pass `rcond=-1`.",; FutureWarning, stacklevel=3); rcond = -1; if rcond is None: rcond = finfo(t).eps * max(n, m); if m <= n: gufunc = _umath_linalg.lstsq_m; else: gufunc = _umath_linalg.lstsq_n; signature = 'DDd->Ddid' if isComplexType(t) else 'ddd->ddid'; extobj = get_linalg_error_extobj(_raise_linalgerror_lstsq); if n_rhs == 0: b = zeros(b.shape[:-2] + (m, n_rhs + 1), dtype=b.dtype); x, resids, rank, s = gufunc(a, b, rcond, signature=signature, extobj=extobj); if m == 0: x[...] = 0; if n_rhs == 0: x = x[..., :n_rhs]; resids = resids[..., :n_rhs]; if is_1d: x = x.squeeze(axis=-1); if rank != n or m <= n: resids = array([], result_real_t); s = s.astype(result_real_t, copy=False); resids = resids.astype(result_real_t, copy=False); x = x.astype(result_t, copy=True); return wrap(x), wrap(resids), rank, s; def _multi_svd_norm(x, row_axis, col_axis, op): y = moveaxis(x, (row_axis, col_axis), (-2, -1)); result = op(svd(y, compute_uv=False), axis=-1); return result; def _norm_dispatcher(x, ord=None, axis=None, keepdims=None): return (x,); @array_function_dispatch(_norm_dispatcher); def norm(x, ord=None, axis=None, keepdims=False): x = asarray(x); if not issubclass(x.dtype.type, (inexact, object_)): x = x.astype(float); if axis is None: ndim = x.ndim; if ((ord is None) or; (ord in ('f', 'fro') and ndim == 2) or; (ord == 2 and ndim == 1)): x = x.ravel(order='K'); if isComplexType(x.dtype.type): sqnorm = dot(x.real, x.real) + dot(x.imag, x.imag); else: sqnorm = dot(x, x); ret = sqrt(sqnorm); if keepdims: ret = ret.reshape(ndim*[1]); return ret; nd = x.ndim; if axis is None: axis = tuple(range(nd)); elif not isinstance(axis, tuple): try: axis = int(axis); except Exception: raise TypeError("'axis' must be None, an integer or a tuple of integers"); axis = (axis,); if len(axis) == 1: if ord == Inf: return abs(x).max(axis=axis, keepdims=keepdims); elif ord == -Inf: return abs(x).min(axis=axis, keepdims=keepdims); elif ord == 0: return (x != 0).astype(x.real.dtype).sum(axis=axis, keepdims=keepdims); elif ord == 1: return add.reduce(abs(x), axis=axis, keepdims=keepdims); elif ord is None or ord == 2: s = (x.conj() * x).real; return sqrt(add.reduce(s, axis=axis, keepdims=keepdims)); else: try: ord + 1; except TypeError: raise ValueError("Invalid norm order for vectors."); absx = abs(x); absx **= ord; ret = add.reduce(absx, axis=axis, keepdims=keepdims); ret **= (1 / ord); return ret; elif len(axis) == 2: row_axis, col_axis = axis; row_axis = normalize_axis_index(row_axis, nd); col_axis = normalize_axis_index(col_axis, nd); if row_axis == col_axis: raise ValueError('Duplicate axes given.'); if ord == 2: ret =_multi_svd_norm(x, row_axis, col_axis, amax); elif ord == -2: ret = _multi_svd_norm(x, row_axis, col_axis, amin); elif ord == 1: if col_axis > row_axis: col_axis -= 1; ret = add.reduce(abs(x), axis=row_axis).max(axis=col_axis); elif ord == Inf: if row_axis > col_axis: row_axis -= 1; ret = add.reduce(abs(x), axis=col_axis).max(axis=row_axis); elif ord == -1: if col_axis > row_axis: col_axis -= 1; ret = add.reduce(abs(x), axis=row_axis).min(axis=col_axis); elif ord == -Inf: if row_axis > col_axis: row_axis -= 1; ret = add.reduce(abs(x), axis=col_axis).min(axis=row_axis); elif ord in [None, 'fro', 'f']: ret = sqrt(add.reduce((x.conj() * x).real, axis=axis)); elif ord == 'nuc': ret = _multi_svd_norm(x, row_axis, col_axis, sum); else: raise ValueError("Invalid norm order for matrices."); if keepdims: ret_shape = list(x.shape); ret_shape[axis[0]] = 1; ret_shape[axis[1]] = 1; ret = ret.reshape(ret_shape); return ret; else: raise ValueError("Improper number of dimensions to norm."); def multi_dot(arrays): n = len(arrays); if n < 2: raise ValueError("Expecting at least two arrays."); elif n == 2: return dot(arrays[0], arrays[1]); arrays = [asanyarray(a) for a in arrays]; ndim_first, ndim_last = arrays[0].ndim, arrays[-1].ndim; if arrays[0].ndim == 1: arrays[0] = atleast_2d(arrays[0]); if arrays[-1].ndim == 1: arrays[-1] = atleast_2d(arrays[-1]).T; _assert_2d(*arrays)
if n == 3: result = _multi_dot_three(arrays[0], arrays[1], arrays[2])
else: order = _multi_dot_matrix_chain_order(arrays)
result = _multi_dot(arrays, order, 0, n - 1)
if ndim_first == 1 and ndim_last == 1: return result[0, 0]
elif ndim_first == 1 or ndim_last == 1: return result.ravel()
else: return result; def _multi_dot_three(A, B, C): a0, a1b0 = A.shape
b1c0, c1 = C.shape; cost1 = a0 * b1c0 * (a1b0 + c1); cost2 = a1b0 * c1 * (a0 + b1c0); if cost1 < cost2: return dot(dot(A, B), C); else: return dot(A, dot(B, C)); def _multi_dot_matrix_chain_order(arrays, return_costs=False): n = len(arrays); p = [a.shape[0] for a in arrays] + [arrays[-1].shape[1]]; m = zeros((n, n), dtype=double); s = empty((n, n), dtype=intp); for l in range(1, n): for i in range(n - l): j = i + l; m[i, j] = Inf; for k in range(i, j): q = m[i, k] + m[k+1, j] + p[i]*p[k+1]*p[j+1]; if q < m[i, j]: m[i, j] = q; s[i, j] = k; if i == j: return arrays[i]; else: return dot(_multi_dot(arrays, order, i, order[i, j]),; _multi_dot(arrays, order, order[i, j] + 1, j))
Beispiel #28
0
def svd(a, full_matrices=1, compute_uv=1):
    """Singular Value Decomposition.

    u,s,vh = svd(a)

    If a is an M x N array, then the svd produces a factoring of the array
    into two unitary (orthogonal) 2-d arrays u (MxM) and vh (NxN) and a
    min(M,N)-length array of singular values such that

                     a == dot(u,dot(S,vh))

    where S is an MxN array of zeros whose main diagonal is s.

    if compute_uv == 0, then return only the singular values
    if full_matrices == 0, then only part of either u or vh is
                           returned so that it is MxN
    """
    a, wrap = _makearray(a)
    _assertRank2(a)
    m, n = a.shape
    t, result_t = _commonType(a)
    real_t = _linalgRealType(t)
    a = _fastCopyAndTranspose(t, a)
    s = zeros((min(n, m),), real_t)
    if compute_uv:
        if full_matrices:
            nu = m
            nvt = n
            option = 'A'
        else:
            nu = min(n, m)
            nvt = min(n, m)
            option = 'S'
        u = zeros((nu, m), t)
        vt = zeros((n, nvt), t)
    else:
        option = 'N'
        nu = 1
        nvt = 1
        u = empty((1, 1), t)
        vt = empty((1, 1), t)

    iwork = zeros((8*min(m, n),), fortran_int)
    if isComplexType(t):
        lapack_routine = lapack_lite.zgesdd
        rwork = zeros((5*min(m, n)*min(m, n) + 5*min(m, n),), real_t)
        lwork = 1
        work = zeros((lwork,), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt,
                                 work, -1, rwork, iwork, 0)
        lwork = int(abs(work[0]))
        work = zeros((lwork,), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt,
                                 work, lwork, rwork, iwork, 0)
    else:
        lapack_routine = lapack_lite.dgesdd
        lwork = 1
        work = zeros((lwork,), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt,
                                 work, -1, iwork, 0)
        lwork = int(work[0])
        work = zeros((lwork,), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt,
                                 work, lwork, iwork, 0)
    if results['info'] > 0:
        raise LinAlgError, 'SVD did not converge'
    s = s.astype(_realType(result_t))
    if compute_uv:
        u = u.transpose().astype(result_t)
        vt = vt.transpose().astype(result_t)
        return wrap(u), s, wrap(vt)
    else:
        return s
Beispiel #29
0
 def test_deprecated(self):
     # NumPy 1.13.0, 2017-04-26
     assert_warns(DeprecationWarning, ufl.fix, [1, 2], y=nx.empty(2))
     assert_warns(DeprecationWarning, ufl.isposinf, [1, 2], y=nx.empty(2))
     assert_warns(DeprecationWarning, ufl.isneginf, [1, 2], y=nx.empty(2))
Beispiel #30
0
def svd(a, full_matrices=1, compute_uv=1):
    """
    Singular Value Decomposition.

    Factorizes the matrix `a` into two unitary matrices, ``U`` and ``Vh``,
    and a 1-dimensional array of singular values, ``s`` (real, non-negative),
    such that ``a == U S Vh``, where ``S`` is the diagonal
    matrix ``np.diag(s)``.

    Parameters
    ----------
    a : array_like, shape (M, N)
        Matrix to decompose
    full_matrices : boolean, optional
        If True (default), ``U`` and ``Vh`` are shaped
        ``(M,M)`` and ``(N,N)``.  Otherwise, the shapes are
        ``(M,K)`` and ``(K,N)``, where ``K = min(M,N)``.
    compute_uv : boolean
        Whether to compute ``U`` and ``Vh`` in addition to ``s``.
        True by default.

    Returns
    -------
    U : ndarray, shape (M, M) or (M, K) depending on `full_matrices`
        Unitary matrix.
    s :  ndarray, shape (K,) where ``K = min(M, N)``
        The singular values, sorted so that ``s[i] >= s[i+1]``.
    Vh : ndarray, shape (N,N) or (K,N) depending on `full_matrices`
        Unitary matrix.

    Raises
    ------
    LinAlgError
        If SVD computation does not converge.

    Notes
    -----
    If `a` is a matrix (in contrast to an ndarray), then so are all
    the return values.

    Examples
    --------
    >>> a = np.random.randn(9, 6) + 1j*np.random.randn(9, 6)
    >>> U, s, Vh = np.linalg.svd(a)
    >>> U.shape, Vh.shape, s.shape
    ((9, 9), (6, 6), (6,))

    >>> U, s, Vh = np.linalg.svd(a, full_matrices=False)
    >>> U.shape, Vh.shape, s.shape
    ((9, 6), (6, 6), (6,))
    >>> S = np.diag(s)
    >>> np.allclose(a, np.dot(U, np.dot(S, Vh)))
    True

    >>> s2 = np.linalg.svd(a, compute_uv=False)
    >>> np.allclose(s, s2)
    True

    """
    a, wrap = _makearray(a)
    _assertRank2(a)
    _assertNonEmpty(a)
    m, n = a.shape
    t, result_t = _commonType(a)
    real_t = _linalgRealType(t)
    a = _fastCopyAndTranspose(t, a)
    s = zeros((min(n, m),), real_t)
    if compute_uv:
        if full_matrices:
            nu = m
            nvt = n
            option = 'A'
        else:
            nu = min(n, m)
            nvt = min(n, m)
            option = 'S'
        u = zeros((nu, m), t)
        vt = zeros((n, nvt), t)
    else:
        option = 'N'
        nu = 1
        nvt = 1
        u = empty((1, 1), t)
        vt = empty((1, 1), t)

    iwork = zeros((8*min(m, n),), fortran_int)
    if isComplexType(t):
        lapack_routine = lapack_lite.zgesdd
        rwork = zeros((5*min(m, n)*min(m, n) + 5*min(m, n),), real_t)
        lwork = 1
        work = zeros((lwork,), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt,
                                 work, -1, rwork, iwork, 0)
        lwork = int(abs(work[0]))
        work = zeros((lwork,), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt,
                                 work, lwork, rwork, iwork, 0)
    else:
        lapack_routine = lapack_lite.dgesdd
        lwork = 1
        work = zeros((lwork,), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt,
                                 work, -1, iwork, 0)
        lwork = int(work[0])
        work = zeros((lwork,), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt,
                                 work, lwork, iwork, 0)
    if results['info'] > 0:
        raise LinAlgError, 'SVD did not converge'
    s = s.astype(_realType(result_t))
    if compute_uv:
        u = u.transpose().astype(result_t)
        vt = vt.transpose().astype(result_t)
        return wrap(u), s, wrap(vt)
    else:
        return s
Beispiel #31
0
 def test_deprecated(self):
     # NumPy 1.13.0, 2017-04-26
     assert_warns(DeprecationWarning, ufl.fix, [1, 2], y=nx.empty(2))
     assert_warns(DeprecationWarning, ufl.isposinf, [1, 2], y=nx.empty(2))
     assert_warns(DeprecationWarning, ufl.isneginf, [1, 2], y=nx.empty(2))
Beispiel #32
0
def svd(a, full_matrices=1, compute_uv=1):
    """Singular Value Decomposition.

    Factorizes the matrix a into two unitary matrices U and Vh and
    an 1d-array s of singular values (real, non-negative) such that
    a == U S Vh  if S is an suitably shaped matrix of zeros whose
    main diagonal is s.

    Parameters
    ----------
    a : array-like, shape (M, N)
        Matrix to decompose
    full_matrices : boolean
        If true,  U, Vh are shaped  (M,M), (N,N)
        If false, the shapes are    (M,K), (K,N) where K = min(M,N)
    compute_uv : boolean
        Whether to compute U and Vh in addition to s

    Returns
    -------
    U:  array, shape (M,M) or (M,K) depending on full_matrices
    s:  array, shape (K,)
        The singular values, sorted so that s[i] >= s[i+1]
        K = min(M, N)
    Vh: array, shape (N,N) or (K,N) depending on full_matrices

    If a is a matrix, so are all the return values.

    Raises LinAlgError if SVD computation does not converge

    Examples
    --------
    >>> a = random.randn(9, 6) + 1j*random.randn(9, 6)
    >>> U, s, Vh = linalg.svd(a)
    >>> U.shape, Vh.shape, s.shape
    ((9, 9), (6, 6), (6,))

    >>> U, s, Vh = linalg.svd(a, full_matrices=False)
    >>> U.shape, Vh.shape, s.shape
    ((9, 6), (6, 6), (6,))
    >>> S = diag(s)
    >>> allclose(a, dot(U, dot(S, Vh)))
    True

    >>> s2 = linalg.svd(a, compute_uv=False)
    >>> allclose(s, s2)
    True
    """
    a, wrap = _makearray(a)
    _assertRank2(a)
    _assertNonEmpty(a)
    m, n = a.shape
    t, result_t = _commonType(a)
    real_t = _linalgRealType(t)
    a = _fastCopyAndTranspose(t, a)
    s = zeros((min(n, m), ), real_t)
    if compute_uv:
        if full_matrices:
            nu = m
            nvt = n
            option = 'A'
        else:
            nu = min(n, m)
            nvt = min(n, m)
            option = 'S'
        u = zeros((nu, m), t)
        vt = zeros((n, nvt), t)
    else:
        option = 'N'
        nu = 1
        nvt = 1
        u = empty((1, 1), t)
        vt = empty((1, 1), t)

    iwork = zeros((8 * min(m, n), ), fortran_int)
    if isComplexType(t):
        lapack_routine = lapack_lite.zgesdd
        rwork = zeros((5 * min(m, n) * min(m, n) + 5 * min(m, n), ), real_t)
        lwork = 1
        work = zeros((lwork, ), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt, work,
                                 -1, rwork, iwork, 0)
        lwork = int(abs(work[0]))
        work = zeros((lwork, ), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt, work,
                                 lwork, rwork, iwork, 0)
    else:
        lapack_routine = lapack_lite.dgesdd
        lwork = 1
        work = zeros((lwork, ), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt, work,
                                 -1, iwork, 0)
        lwork = int(work[0])
        work = zeros((lwork, ), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt, work,
                                 lwork, iwork, 0)
    if results['info'] > 0:
        raise LinAlgError, 'SVD did not converge'
    s = s.astype(_realType(result_t))
    if compute_uv:
        u = u.transpose().astype(result_t)
        vt = vt.transpose().astype(result_t)
        return wrap(u), s, wrap(vt)
    else:
        return s
Beispiel #33
0
def svd(a, full_matrices=1, compute_uv=1):
    """Singular Value Decomposition.

    u,s,vh = svd(a)

    If a is an M x N array, then the svd produces a factoring of the array
    into two unitary (orthogonal) 2-d arrays u (MxM) and vh (NxN) and a
    min(M,N)-length array of singular values such that

                     a == dot(u,dot(S,vh))

    where S is an MxN array of zeros whose main diagonal is s.

    if compute_uv == 0, then return only the singular values
    if full_matrices == 0, then only part of either u or vh is
                           returned so that it is MxN
    """
    a, wrap = _makearray(a)
    _assertRank2(a)
    _assertNonEmpty(a)
    m, n = a.shape
    t, result_t = _commonType(a)
    real_t = _linalgRealType(t)
    a = _fastCopyAndTranspose(t, a)
    s = zeros((min(n, m), ), real_t)
    if compute_uv:
        if full_matrices:
            nu = m
            nvt = n
            option = 'A'
        else:
            nu = min(n, m)
            nvt = min(n, m)
            option = 'S'
        u = zeros((nu, m), t)
        vt = zeros((n, nvt), t)
    else:
        option = 'N'
        nu = 1
        nvt = 1
        u = empty((1, 1), t)
        vt = empty((1, 1), t)

    iwork = zeros((8 * min(m, n), ), fortran_int)
    if isComplexType(t):
        lapack_routine = lapack_lite.zgesdd
        rwork = zeros((5 * min(m, n) * min(m, n) + 5 * min(m, n), ), real_t)
        lwork = 1
        work = zeros((lwork, ), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt, work,
                                 -1, rwork, iwork, 0)
        lwork = int(abs(work[0]))
        work = zeros((lwork, ), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt, work,
                                 lwork, rwork, iwork, 0)
    else:
        lapack_routine = lapack_lite.dgesdd
        lwork = 1
        work = zeros((lwork, ), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt, work,
                                 -1, iwork, 0)
        lwork = int(work[0])
        work = zeros((lwork, ), t)
        results = lapack_routine(option, m, n, a, m, s, u, m, vt, nvt, work,
                                 lwork, iwork, 0)
    if results['info'] > 0:
        raise LinAlgError, 'SVD did not converge'
    s = s.astype(_realType(result_t))
    if compute_uv:
        u = u.transpose().astype(result_t)
        vt = vt.transpose().astype(result_t)
        return wrap(u), s, wrap(vt)
    else:
        return s
def svd_dgesvd(a, full_matrices=1, compute_uv=1):
    """
    Singular Value Decomposition.

    Factorizes the matrix `a` into two unitary matrices, ``U`` and ``Vh``,
    and a 1-dimensional array of singular values, ``s`` (real, non-negative),
    such that ``a == U S Vh``, where ``S`` is the diagonal
    matrix ``np.diag(s)``.

    Parameters
    ----------
    a : array_like, shape (M, N)
        Matrix to decompose
    full_matrices : boolean, optional
        If True (default), ``U`` and ``Vh`` are shaped
        ``(M,M)`` and ``(N,N)``.  Otherwise, the shapes are
        ``(M,K)`` and ``(K,N)``, where ``K = min(M,N)``.
    compute_uv : boolean
        Whether to compute ``U`` and ``Vh`` in addition to ``s``.
        True by default.

    Returns
    -------
    U : ndarray, shape (M, M) or (M, K) depending on `full_matrices`
        Unitary matrix.
    s :  ndarray, shape (K,) where ``K = min(M, N)``
        The singular values, sorted so that ``s[i] >= s[i+1]``.
    Vh : ndarray, shape (N,N) or (K,N) depending on `full_matrices`
        Unitary matrix.

    Raises
    ------
    LinAlgError
        If SVD computation fails. 
        For details see dgesvd.f and dbdsqr.f of LAPACK
    """
    a, wrap = _makearray(a)
    _assertRank2(a)
    _assertNonEmpty(a)
    m, n = a.shape
    t, result_t = _commonType(a)
    real_t = _linalgRealType(t)
    a = _fastCopyAndTranspose(t, a)
    s = zeros((min(n, m),), real_t)

    if compute_uv:
        if full_matrices:
            nu = m
            nvt = n
            option = 'A'
        else:
            nu = min(n, m)
            nvt = min(n, m)
            option = 'S'
        u = zeros((nu, m), t)
        vt = zeros((n, nvt), t)
    else:
        option = 'N'
        nu = 1
        nvt = 1
        u = empty((1, 1), t)
        vt = empty((1, 1), t)

    lapack_routine = lib.dgesvd_

    lwork = 1
    work = zeros((lwork,), t)
    INFO = c_int(0)
    m = c_int(m)
    n = c_int(n)
    nvt = c_int(nvt)
    lwork = c_int(-1)
    lapack_routine(option, option, m, n, a, m, s, u, m, vt, nvt,
                                work, lwork, INFO)
    if INFO.value < 0:
        raise Exception('%d-th argument had an illegal value' % INFO.value)

    lwork = int(work[0])
    work = zeros((lwork,), t)
    lwork = c_int(lwork)
    lapack_routine(option, option, m, n, a, m, s, u, m, vt, nvt,
                                work, lwork, INFO)
    if INFO.value > 0:
        raise Exception('Error during factorization: %d' % INFO.value)
#        raise LinAlgError, 'SVD did not converge'
    s = s.astype(_realType(result_t))
    if compute_uv:
        u = u.transpose().astype(result_t)
        vt = vt.transpose().astype(result_t)
        return wrap(u), s, wrap(vt)
    else:
        return s
Beispiel #35
0
def mesh_curvatures(mesh, conn=None, normals=None, propagate=2):
	''' compute the curvature around a point in a mesh/web/wire
	
		Parameters:
		
			mesh:			the surface/line to search
			conn:			a point-to-point connectivity (computed if not provided)
			normals:		the vertex normals (computed if not provided)
			propagate(int):	the maximum propagation rank for points to pick for the regression
	
		Returns:	
			
			`[(tuple, mat3)]`
			
			where the `tuple` contains the curvature in each of the column directions in the `mat3`. The `mat3` has the principal directions of curvature
	'''
	pts = mesh.points
		
	# propagate though the mesh and return seen points
	def propagate_pp(conn, start, maxrank):
		front = deque((0,s) for s in start)
		seen = set()
		while front:
			rank, p = front.popleft()
			if p in seen:	continue
			seen.add(p)
			if rank < maxrank:
				for n in conn[p]:
					if n not in seen:	
						front.append((rank+1, n))
		return seen
	
	if isinstance(mesh, Mesh):		
		if not conn:	conn = connpp(mesh.faces)
		if not normals:	normals = mesh.vertexnormals()
		it = ( (p, propagate_pp(conn, [p], propagate))   for p in range(len(mesh.points)) )
	elif isinstance(mesh, Web):	
		if not conn:	conn = connpp(mesh.edges)
		if not normals:	
			normals = [vec3(0)  for p in mesh.points]
			for e in mesh.edges:
				d = pts[e[0]] - pts[e[1]]
				normals[e[0]] += d
				normals[e[1]] -= d
			for i,n in enumerate(normals):
				normals[i] = normalize(n)
		it = ( (p, propagate_pp(conn, [p], propagate))   for p in range(len(mesh.points)) )
	elif isinstance(mesh, Wire):
		if not normals:	normals = mesh.vertexnormals()
		it = ( (mesh.indices[i], mesh.indices[i-propagate:i+propagate])   for i in range(len(mesh.indices)) )
	else:
		raise TypeError('bad input shape type')
	
	curvatures = [None]*len(pts)
	
	for p, neigh in it:
		# decide a local coordinate system
		u,v,w = dirbase(normals[p])
		# get neighboors contributions
		b = np.empty(len(neigh))
		a = np.empty((len(neigh), 14))
		for i,n in enumerate(neigh):
			e = pts[n] - pts[p]
			b[i] = dot(e,w)
			eu = dot(e,u)
			ev = dot(e,v)
			# these are the monoms to compose to build a polynom approximating the surface until 4th-order derivatives
			a[i] = (	eu**2, ev**2, eu*ev,  # what we want to get
						# the others terms are only present to catch the surface regularities and not disturb the curvature terms
						eu, ev,
						eu**3, eu**2*ev, eu*ev**2, ev**3,
						eu**4, eu**3*ev, eu**2*ev**2, eu*ev**3, ev**4,
						)

		# least squares resulution, the complexity is roughly the same as inverting a mat3
		(au, av, auv, *_), residuals, *_ = np.linalg.lstsq(a, b, rcond=None)
		# diagonalize the curve tensor to get the principal curvatures
		diag, transfer = np.linalg.eigh(mat2(2*au, auv, 
												auv, 2*av))
		curvatures[p] = diag, mat3(u,v,w) * mat3(mat2(transfer))
		
	return curvatures