Example #1
0
def p_b_wins():
	# Equal to P(b<a).
	T=6; distrb3 = scipy.array([[p_x_tries(x, T, payoff(T)) for x in xs]])
	T=7; distrb6 = scipy.array([[p_x_tries(x, T, payoff(T)) for x in xs]])
	T=3; distrb7 = scipy.array([[p_x_tries(x, T, payoff(T)) for x in xs]])

	table36 = scipy.fliplr(scipy.dot(distrb3.T, distrb6))
	distr36 = scipy.zeros((1, 2*MAX_X)) # First element should be 0.
	for offseti, offset in enumerate(xrange(-(MAX_X-1), MAX_X)):
		distr36[0,-offseti-1] = scipy.trace(table36, offset)
	del table36
	distr36 = distr36[:,:MAX_X]
	assert distr36[0,0] == 0

	table367 = scipy.fliplr(scipy.dot(distr36.T, distrb7))
	del distr36
	distr367 = scipy.zeros((1, 2*MAX_X)) # First two elements should be 0.
	for offseti, offset in enumerate(xrange(-(MAX_X-1), MAX_X)):
		distr367[0,-offseti-1] = scipy.trace(table367, offset)
	del table367
	distr367 = distr367[:,:MAX_X]
	assert distr367[0,0] == 0 and distr367[0,1] == 0

	#pylab.bar(xs, distr367[0,:]); pylab.show()
	m = scipy.dot(distra.T, distr367)
	p = 0.
	for offseti, offset in enumerate(xrange(-(MAX_X-1), 0)):
		p += scipy.trace(m, offset)

	return p
Example #2
0
def _qfunc_pure(psi, alpha_vec):
    """
    Calculate the Q-function for a pure state.
    """
    n = np.prod(psi.shape)

    # Gengyan: maximun number to use factorial()
    nmax = 170

    if isinstance(psi, Qobj):
        psi = psi.full().flatten()
    else:
        psi = psi.T

    if n < nmax:
        qvec = abs(
            polyval(
                fliplr([psi / sqrt(factorial(arange(n)))])[0],
                conjugate(alpha_vec)))**2 * exp(-abs(alpha_vec)**2)
    else:
        # Gengyan: for m < nmax, use factorial()
        qvec = polyval(
            fliplr([psi[0:nmax] / sqrt(factorial(arange(nmax)))])[0],
            conjugate(alpha_vec)) * exp(-abs(alpha_vec)**2 / 2)
        # Gengyan: for m >= nmax, use Stirling's approximation
        for m in range(nmax, n):
            qvec += (conjugate(alpha_vec)/sqrt(m))**m*psi[m] * \
                exp((m-abs(alpha_vec)**2)/2)*(2*pi*m)**(-0.25)
        qvec = abs(qvec)**2

    return np.real(qvec) / pi
Example #3
0
def Suffle(n=1,a=25214903917,c=11,mod=2**48,seed=1):
    NumberofCards=52
    final=PRNG(n*NumberofCards,a,c,mod,seed)
    index=sp.zeros((n,NumberofCards))
    for x in range(n):
        index[x,:]=final[(x)*NumberofCards:(x+1)*NumberofCards].argsort()
    return sp.fliplr(index).astype(int)
Example #4
0
def p_b_wins(strategy, scorea = 0):
	# Equal to P(b<a).
	Ts = strategy.Ts
	targets = strategy.targets
	distr = None
	for T, target, i in zip(Ts, targets, itertools.count()):
		distrT = scipy.array([[p_x_tries(x, T, target) for x in xs]])
		if distr is not None:
			table = scipy.fliplr(scipy.dot(distr.T, distrT))
			distr = scipy.zeros((1, 2*MAX_X))
			for offseti, offset in enumerate(xrange(-(MAX_X-1), MAX_X)):
				distr[0, -offseti-1] = scipy.trace(table, offset)
			distr = distr[:,:MAX_X]
		else:
			distr = distrT
		assert distr[0,:i].sum() == 0

	E = (xs * distr[0,:]).sum()
	#pylab.bar(xs, distr[0,:]); pylab.show()
	distra = scipy.array([[p_x_tries(x, 1, 100 - scorea) for x in xs]])
	m = scipy.dot(distra.T, distr)
	p = 0.
	for offseti, offset in enumerate(xrange(-(MAX_X-1), 0)):
		p += scipy.trace(m, offset)

	return p
Example #5
0
    def generator(self,samples=None):
        """Generator to only hold batch_size of data in memory

        TODO:
            * Trim images -> Or do this with a cropping layer in keras

        Args:
            samples (Dataframe): Dataframe containing sample info.
            batch_size (int): Batch size for the training
        """

        print("="*50)
        print(" Generate batch data")
        print("-"*50)

        im_output_flip = True
        path = self._path
        batch_size = self._batchsize
        num_samples = len(samples)
        num_samples_flipped = 0
        print(" Batch size = {}, Sample Size = {}".format(batch_size,num_samples))

        while 1: # Loop forever so the generator never terminates
          sklearn.utils.shuffle(samples) # Wow, this work for pandas DataFrames !!!
          for offset in range(0, num_samples, batch_size):
            batch_samples = samples[offset:offset+batch_size]

            images = []
            angles = []

            for index, batch_sample in batch_samples.iterrows():
              # name = './IMG/'+batch_sample[0].split('/')[-1] # Add if becessart
              im_col = batch_sample["im_sel"]
              image = cv2.imread(os.path.join(path, batch_sample[im_col].lstrip()))
              image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

              if batch_sample['im_flip']:
                if im_output_flip:
                  logger.info('Saving first flipped image')
                  print('Saving first flipped image')
                  plt.imsave('examples/im_flip_original.png',image)
                image = sp.fliplr(image)
                if im_output_flip:
                  plt.imsave('examples/im_flip_flipped.png',image)
                  im_output_flip = False

              angle = float(batch_sample['steering'])
              images.append(image)
              angles.append(angle)

            # trim image to only see section with road
            X_train = sp.array(images)
            y_train = sp.array(angles)
            yield sklearn.utils.shuffle(X_train, y_train)
Example #6
0
def _qfunc_pure(psi, alpha_mat):
    """
    Calculate the Q-function for a pure state.
    """
    n = prod(psi.shape)
    if isinstance(psi, Qobj):
        psi = array(psi.trans().full())[0,:]
    else:
        psi = psi.T

    qmat1 = abs(polyval(fliplr([psi/sqrt(factorial(arange(0, n)))])[0], conjugate(alpha_mat))) ** 2;
    qmat1 = real(qmat1) * exp(-abs(alpha_mat)**2) / pi;

    return qmat1
Example #7
0
def _qfunc_pure(psi, alpha_mat):
    """
    Calculate the Q-function for a pure state.
    """
    n = np.prod(psi.shape)
    if isinstance(psi, Qobj):
        psi = psi.full().flatten()
    else:
        psi = psi.T

    qmat = abs(polyval(fliplr([psi / sqrt(factorial(arange(n)))])[0],
                       conjugate(alpha_mat))) ** 2

    return real(qmat) * exp(-abs(alpha_mat) ** 2) / pi
Example #8
0
File: pca.py Project: Yevgnen/prml
    def _eig_decomposition(self, A, largest=True):
        n_features = A.shape[0]

        if (largest):
            eig_range = (n_features - self.n_components, n_features - 1)
        else:
            eig_range = (0, self.n_components - 1)

        eigvals, eigvecs = spla.eigh(A, eigvals=eig_range)

        if (largest):
            eigvals = eigvals[::-1]
            eigvecs = sp.fliplr(eigvecs)

        return eigvals, eigvecs
Example #9
0
def _qfunc_pure(psi, alpha_mat):
    """
    Calculate the Q-function for a pure state.
    """
    n = prod(psi.shape)
    if isinstance(psi, Qobj):
        psi = array(psi.trans().full())[0, :]
    else:
        psi = psi.T

    qmat1 = abs(
        polyval(
            fliplr([psi / sqrt(factorial(arange(0, n)))])[0],
            conjugate(alpha_mat)))**2
    qmat1 = real(qmat1) * exp(-abs(alpha_mat)**2) / pi

    return qmat1
Example #10
0
        color_Lab = KamiSolve.rgb2CIELAB(color[::-1])

        #gw = color.dot(BGR_weights)
        #color = color/gw
        #color = scipy.append(color,gw/100)
        
        #dist_list = [scipy.linalg.norm(color-mi) for mi in m]
        #dist_list = [abs(scipy.exp(1j*color_hsl[0]*pi/180)-scipy.exp(1j*mi[0]*pi/180)) + abs(color_hsl[1]-mi[1]) for mi in m]
        dist_list = [scipy.linalg.norm(color_Lab-mi) for mi in m]
        
        min_index, min_value = min(enumerate(dist_list), key=operator.itemgetter(1))
        #color_board[p] = [color,min_index]
        #color_board[p] = [color_hsl,min_index]
        color_board[p] = [color_Lab,min_index]

kami = scipy.fliplr(kami.reshape(-1,3)).reshape(kami.shape)
plt.imshow(kami)
plt.figure()
KamiSolve.show_color_board(color_board)

m = KamiSolve.k_means(color_board,k)
plt.figure()
KamiSolve.show_color_board(color_board)

plt.show()

c = [ [], [], [], [] ]
for i in color_board:
    c[color_board[i][1]].append(i)
while [] in c:
    c.remove([])
Example #11
0
 def define_mask(self):
     csmask0 = sp.flipud(sp.fliplr(self.omask))
     csmask = np.zeros((self.ny+4*self.dy, self.nx+4*self.dx)).astype(np.bool)
     csmask[self.dy:self.dy+self.ny,self.dx:self.dx+self.nx] = csmask0
     self.csmask = csmask
Example #12
0
def rdmd(A,
         dt=1,
         k=None,
         p=10,
         q=2,
         sdist='uniform',
         return_amplitudes=False,
         return_vandermonde=False,
         order=True):
    """
    Randomized Dynamic Mode Decomposition.

    Dynamic Mode Decomposition (DMD) is a data processing algorithm which
    allows to decompose a matrix `A` in space and time. The matrix `A` is 
    decomposed as `A = F * B * V`, where the columns of `F` contain the dynamic modes.
    The modes are ordered corresponding to the amplitudes stored in the diagonal 
    matrix `B`. `V` is a Vandermonde matrix describing the temporal evolution.


    Parameters
    ----------
    A : array_like
        Real/complex input matrix  `a` with dimensions `(m, n)`.
    
    dt : scalar or array_like  
        Factor specifying the time difference between the observations.  
    
    k : int
        If `k < (n-1)` low-rank Dynamic Mode Decomposition is computed.
    
    p : int, optional
        Oversampling paramater.         
    
    sdist : str `{'uniform', 'normal'}`  
        Specify the distribution of the sensing matrix `S`. 
    
    
    return_amplitudes : bool `{True, False}` 
        True: return amplitudes in addition to dynamic modes. 
    
    return_vandermonde : bool `{True, False}`
        True: return Vandermonde matrix in addition to dynamic modes and amplitudes.     
    
    order :  bool `{True, False}`
        True: return modes sorted.


    Returns
    -------
    F : array_like
        Matrix containing the dynamic modes of shape `(m, n-1)`  or `(m, k)`.
    
    b : array_like, if `return_amplitudes=True`
        1-D array containing the amplitudes of length `min(n-1, k)`.
    
    V : array_like, if `return_vandermonde=True`
        Vandermonde matrix of shape `(n-1, n-1)`  or `(k, n-1)`.

    omega : array_like
        Time scaled eigenvalues: `ln(l)/dt`. 


    Notes
    -----
    
    
    References
    ----------
  

    
    Examples
    --------



    
    """

    #Shape of A
    m, n = A.shape
    dat_type = A.dtype
    if dat_type == sci.float32:
        isreal = True
        real_type = sci.float32
        fT = rT
    elif dat_type == sci.float64:
        isreal = True
        real_type = sci.float64
        fT = rT
    elif dat_type == sci.complex64:
        isreal = False
        real_type = sci.float32
        fT = cT
    elif dat_type == sci.complex128:
        isreal = False
        real_type = sci.float64
        fT = cT
    else:
        raise ValueError('A.dtype is not supported')

    if k > min(m, n):
        k = min(m, n)
    if k is None:
        raise ValueError('Target rank needs to be specified.')

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Generate a random test matrix Omega
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if sdist == 'uniform':
        Omega = np.array(sci.random.uniform(-1, 1, size=(n, k + p)),
                         dtype=dat_type)
        if isreal == False:
            Omega += 1j * sci.array(sci.random.uniform(-1, 1, size=(n, k + p)),
                                    dtype=real_type)

    elif sdist == 'normal':
        Omega = np.array(sci.random.standard_normal(size=(n, k + p)),
                         dtype=dat_type)
        if isreal == False:
            Omega += 1j * sci.array(
                sci.random.standard_normal(size=(n, k + p)), dtype=real_type)

    else:
        raise ValueError('Sampling distribution is not supported.')

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Build sample matrix Y : Y = A * Omega
    #Note: Y should approximate the range of A
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Y = A.dot(Omega)
    del (Omega)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Orthogonalize Y using economic QR decomposition: Y=QR
    #If q > 0 perfrom q subspace iterations
    #Note: check_finite=False may give a performance gain
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    s = 1  #control parameter for number of orthogonalizations
    if q > 0:
        for i in np.arange(1, q + 1):
            if ((2 * i - 2) % s == 0):
                Y, _ = sci.linalg.qr(Y,
                                     mode='economic',
                                     check_finite=False,
                                     overwrite_a=True)

            if ((2 * i - 1) % s == 0):
                Z, _ = sci.linalg.qr(fT(A).dot(Y),
                                     mode='economic',
                                     check_finite=False,
                                     overwrite_a=True)

            Y = A.dot(Z)
        #End for
    #End if

    Q, _ = sci.linalg.qr(Y,
                         mode='economic',
                         check_finite=False,
                         overwrite_a=True)
    del (Y)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Project the data matrix a into a lower dimensional subspace
    #B = Q.T * A
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    B = fT(Q).dot(A)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Split data into lef and right snapshot sequence
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    X = B[:, 0:(n - 1)]  #pointer
    Y = B[:, 1:n]  #pointer

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Singular Value Decomposition
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    U, s, Vh = sci.linalg.svd(X,
                              compute_uv=True,
                              full_matrices=False,
                              overwrite_a=False,
                              check_finite=True)
    U = U[:, 0:k]
    s = s[0:k]
    Vh = Vh[0:k, :]

    #EndIf

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Solve the LS problem to find estimate for M using the pseudo-inverse
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #real: M = U.T * Y * Vt.T * S**-1
    #complex: M = U.H * Y * Vt.H * S**-1
    #Let G = Y * Vt.H * S**-1, hence M = M * G
    Vscaled = fT(Vh) * s**-1
    G = np.dot(Y, Vscaled)
    M = np.dot(fT(U), G)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Eigen Decomposition
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    l, W = sci.linalg.eig(M, right=True, overwrite_a=True)

    omega = np.log(l) / dt

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Order
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if order == True:
        sort_idx = sci.argsort(np.abs(omega))
        W = W[:, sort_idx]
        l = l[sort_idx]
        omega = omega[sort_idx]

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Compute DMD Modes
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    F = Q.dot(U.dot(W))

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Compute amplitueds b using least-squares: Fb=x1
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if return_amplitudes == True:
        b, _, _, _ = sci.linalg.lstsq(F, A[:, 0])

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Compute Vandermonde matrix (CPU)
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if return_vandermonde == True:
        V = sci.fliplr(sci.vander(l, N=n))

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Return
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    if return_amplitudes == True and return_vandermonde == True:
        return F, b, V, omega
    elif return_amplitudes == True and return_vandermonde == False:
        return F, b, omega
    else:
        return F, omega
Example #13
0
    if dict_fn.split('.')[-1] == 'pickle':
        with open(dict_fn, 'rb') as fid:
            d = pickle.load(fid)
    else:
        d = sio.loadmat(dict_fn)
        d['n_words'] = len(d['w_sizes'])
    if d['n_words'] > max_dict_words:
        d['n_words'] = max_dict_words
        d['w_sizes'] = d['w_sizes'][:max_dict_words]
        d['l_words'] = d['l_words'][:max_dict_words]
    word_sizes = sorted(np.unique([s[0] for s in d['w_sizes']]))
    d["l_word_sizes"] = [[s,s] for s in word_sizes]
    max_word_size = np.max(word_sizes)
    d['l_words'] = d['l_words'][:,:,:max_word_size,:max_word_size]
    for i,ws in enumerate(word_sizes):
        d['l_words'][i,:,:ws,:ws] = flipud(fliplr(d['l_words'][i,:,:ws,:ws]))
    print 'Using dictionary with %d words with sizes %s.' % (d['n_words'], d["l_word_sizes"])
else:
    d = None

p       = legacy.params.ventral_2(d)
padding_value = p['model']['preprocessing']['pad_value']
img_new_size = p['model']['preprocessing']['img_base_size']
if s2_is_rbf:
    p['model']['s2']['function'] = 'extract_s2_rbf'
    p['model']['s2']['sigma'] = s2_rbf_sigma

n_scales = p['model']['preprocessing']['n_scales']
scaling_factor = p['model']['preprocessing']['scaling_factor']

# init the cuda kernels
Example #14
0
 def define_mask(self):
     csmask0 = sp.flipud(sp.fliplr(self.omask))
     csmask = np.zeros((self.ny+4*self.dy, self.nx+4*self.dx)).astype(np.bool)
     csmask[self.dy:self.dy+self.ny,self.dx:self.dx+self.nx] = csmask0
     self.csmask = csmask
 def flip_frame(frame):    
     return sp.fliplr(frame)
Example #16
0
if patch_size[0] % 2 == 0 or patch_size[1] % 2 == 0:
    print("patch_size should be even")
    exit(1)    


key = 0
for filename in os.listdir(args.input_dir):
    img = cv2.imread(args.input_dir+"/"+filename)
    # img = cv2.cvtColor(img, cv2.cv.CV_BGR2GRAY)
    if img.shape == (100, 130, 3):
        first_resized = cv2.resize(img, (65, 50))
        resized = cv2.resize(first_resized, (130, 100))
        cv2.imwrite(args.resized_dir+"/"+filename+".png", resized)

        # 折り返し画像
        large_width = scipy.concatenate((scipy.fliplr(resized), resized, scipy.fliplr(resized)), axis=1)
        large = scipy.concatenate((scipy.flipud(large_width), large_width, scipy.flipud(large_width)), axis=0)

        h, w, d = resized.shape
        xys = [(x, y) for x in xrange(w) for y in xrange(h)]
        random.shuffle(xys)
        for original_x, original_y in xys:
            key += 1
            x, y = original_x + w, original_y + h
            subimg = large[y-patch_size[1]/2:y+patch_size[1]/2+1, x-patch_size[0]/2:x+patch_size[0]/2+1]
            #cv2.imshow("test", img)
            #cv2.waitKey(-1)
            target_filename="{}_{}_{}.png".format(filename, original_x, original_y)
            cv2.imwrite(args.output_dir+"/"+target_filename, subimg)
            label = map(lambda item: float(item)/256, img[original_y, original_x].tolist())
            print(" ".join(map(str, [key, target_filename]+label)))
Example #17
0
 def flip_frame(frame):    
     return sp.fliplr(frame)
Example #18
0
def rdmd_single(A,
                dt=1,
                k=None,
                p=10,
                l=None,
                sdist='uniform',
                return_amplitudes=False,
                return_vandermonde=False,
                order=True):
    """
    Randomized Dynamic Mode Decomposition Single-View.

    Dynamic Mode Decomposition (DMD) is a data processing algorithm which
    allows to decompose a matrix `A` in space and time. The matrix `A` is 
    decomposed as `A = F * B * V`, where the columns of `F` contain the dynamic modes.
    The modes are ordered corresponding to the amplitudes stored in the diagonal 
    matrix `B`. `V` is a Vandermonde matrix describing the temporal evolution.

    This algorithms implements a single pass algorithm. 
     
    
    Parameters
    ----------
    A : array_like
        Real/complex input matrix  `a` with dimensions `(m, n)`.
    
    dt : scalar or array_like  
        Factor specifying the time difference between the observations.  
    
    k : int
        If `k < (n-1)` low-rank Dynamic Mode Decomposition is computed.
    
    p : integer, default: `p=10`.
        Parameter to control oversampling of column space.
        
    l : integer, default: `l=2*p`.
        Parameter to control oversampling of row space.         
    
    sdist : str `{'uniform', 'normal', 'orthogonal'}`, default: `sdist='uniform'`.
        'uniform' : Random test matrices with uniform distributed elements.
        
        'normal' : Random test matrices with normal distributed elements.     

        'orthogonal' : Orthogonalized random test matrices with uniform distributed elements.     

    return_amplitudes : bool `{True, False}` 
        True: return amplitudes in addition to dynamic modes. 
    
    return_vandermonde : bool `{True, False}`
        True: return Vandermonde matrix in addition to dynamic modes and amplitudes.     
    
    order :  bool `{True, False}`
        True: return modes sorted.


    Returns
    -------
    F : array_like
        Matrix containing the dynamic modes of shape `(m, n-1)`  or `(m, k)`.
    
    b : array_like, if `return_amplitudes=True`
        1-D array containing the amplitudes of length `min(n-1, k)`.
    
    V : array_like, if `return_vandermonde=True`
        Vandermonde matrix of shape `(n-1, n-1)`  or `(k, n-1)`.

    omega : array_like
        Time scaled eigenvalues: `ln(l)/dt`. 


    Notes
    -----   
    * Add option for sparse random test matrices.
    
    * Modify algorithm to allow for the streaming model. 
    

    References
    ----------
    Tropp, Joel A., et al.
    "Randomized single-view algorithms for low-rank matrix approximation" (2016). 
    (available at `arXiv <https://arxiv.org/abs/1609.00048>`_).


    Examples
    --------


    
    """

    # Shape of input matrix
    m, n = A.shape
    dat_type = A.dtype

    if dat_type == sci.float32:
        isreal = True
        real_type = sci.float32
        fT = rT
    elif dat_type == sci.float64:
        isreal = True
        real_type = sci.float64
        fT = rT
    elif dat_type == sci.complex64:
        isreal = False
        real_type = sci.float32
        fT = cT
    elif dat_type == sci.complex128:
        isreal = False
        real_type = sci.float64
        fT = cT
    else:
        raise ValueError("A.dtype is not supported")

    if l is None:
        l = 2 * p

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Generate a random test matrix Omega
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if sdist == 'uniform':
        Omega = np.array(sci.random.uniform(-1, 1, size=(n, k + p)),
                         dtype=dat_type)
        Psi = np.array(sci.random.uniform(-1, 1, size=(k + l, m)),
                       dtype=dat_type)
        if isreal == False:
            Omega += 1j * sci.array(sci.random.uniform(-1, 1, size=(n, k + p)),
                                    dtype=real_type)
            Psi += 1j * sci.array(sci.random.uniform(-1, 1, size=(k + l, m)),
                                  dtype=real_type)

    elif sdist == 'normal':
        Omega = np.array(sci.random.standard_normal(size=(n, k + p)),
                         dtype=dat_type)
        Psi = np.array(sci.random.standard_normal(size=(k + l, m)),
                       dtype=dat_type)
        if isreal == False:
            Omega += 1j * sci.array(
                sci.random.standard_normal(size=(n, k + p)), dtype=real_type)
            Psi += 1j * sci.array(sci.random.standard_normal(size=(k + l, m)),
                                  dtype=real_type)

    elif sdist == 'orthogonal':
        Omega = np.array(sci.random.standard_normal(size=(n, k + p)),
                         dtype=dat_type)
        Psi = np.array(sci.random.standard_normal(size=(k + l, m)),
                       dtype=dat_type)
        if isreal == False:
            Omega += 1j * sci.array(
                sci.random.standard_normal(size=(n, k + p)), dtype=real_type)
            Psi += 1j * sci.array(sci.random.standard_normal(size=(k + l, m)),
                                  dtype=real_type)

        Omega, _ = sci.linalg.qr(Omega,
                                 mode='economic',
                                 check_finite=False,
                                 overwrite_a=True)
        Psi, _ = sci.linalg.qr(Psi.T,
                               mode='economic',
                               check_finite=False,
                               overwrite_a=True)
        Psi = Psi.T

    else:
        raise ValueError('Sampling distribution is not supported.')

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Build sample matrix Y = A * Omega and W = Psi * A
    #Note: Y should approximate the column space and W the row space of A
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Y = A.dot(Omega)
    W = Psi.dot(A)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Orthogonalize Y using economic QR decomposition: Y=QR
    #Note: check_finite=False may give a performance gain
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Q, _ = sci.linalg.qr(Y,
                         mode='economic',
                         check_finite=False,
                         overwrite_a=True)

    U, T = sci.linalg.qr(Psi.dot(Q),
                         mode='economic',
                         check_finite=False,
                         overwrite_a=False)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Form a smaller matrix
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    B = sci.linalg.solve(a=T, b=fT(U).dot(W))

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Split data into lef and right snapshot sequence
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    X = B[:, 0:(n - 1)]  #pointer
    Y = B[:, 1:n]  #pointer

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Singular Value Decomposition
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    U, s, Vh = sci.linalg.svd(X,
                              compute_uv=True,
                              full_matrices=False,
                              overwrite_a=False,
                              check_finite=True)
    U = U[:, 0:k]
    s = s[0:k]
    Vh = Vh[0:k, :]

    #EndIf

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Solve the LS problem to find estimate for M using the pseudo-inverse
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #real: M = U.T * Y * Vt.T * S**-1
    #complex: M = U.H * Y * Vt.H * S**-1
    #Let G = Y * Vt.H * S**-1, hence M = M * G
    Vscaled = fT(Vh) * s**-1
    G = np.dot(Y, Vscaled)
    M = np.dot(fT(U), G)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Eigen Decomposition
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    l, W = sci.linalg.eig(M, right=True, overwrite_a=True)

    omega = np.log(l) / dt

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Order
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if order == True:
        sort_idx = np.argsort(np.abs(omega))
        W = W[:, sort_idx]
        l = l[sort_idx]
        omega = omega[sort_idx]

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Compute DMD Modes
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    F = Q.dot(U.dot(W))

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Compute amplitueds b using least-squares: Fb=x1
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if return_amplitudes == True:
        b, _, _, _ = sci.linalg.lstsq(F, A[:, 0])

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Compute Vandermonde matrix (CPU)
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if return_vandermonde == True:
        V = sci.fliplr(np.vander(l, N=n))

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Return
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    if return_amplitudes == True and return_vandermonde == True:
        return F, b, V, omega
    elif return_amplitudes == True and return_vandermonde == False:
        return F, b, omega
    else:
        return F, omega