I have an eigenvalue problem in the form
At the moment I'm using scipy.linalg.eig. The strategy I use is conceptually similar to the Campbel diagram used to identify the natural frequencies of a rotor whose stiffness and damping are function of the rotating velocity. This is:
vary the value of that I use to compute from 0 to a certain maximum value (or loop to infinity)
Compute the eigenvalues of for each value of
Now for each eigenvalue (eg. the lowest one) "intersect" the function with the bisector
Search for the intersection where the eigenvalue is equal to the value of used to compute the matrix. Store it and the associated eigenvector.
This however is slow, tedious and, most importantly, it is required to "follow" the eigenvalues when changes. When two eigenvalues "swap" order (the second becomes the third for example), you need to properly identify this to avoid errors.
Is there a better way of solving this?
Related
I need to integrate a certain function that I have specified as discrete values for discrete arguments (I want to count the area under the graph I get).
I.e., from the earlier part of the code I have the literal:
args=[a1, a2, a3, a3]
valuses=[v1, v2, v3, v4]
where value v1 corresponds to a1, etc. If it's important, I have args set in advance with a specific discretization width, and I count values with a ready-made function.
I am attaching a figure.
And putting this function, which gave me a 'values' array, into integrate.quad() gives me an error:
IntegrationWarning: The maximum number of subdivisions (50) has been achieved. If increasing the limit yields no improvement it is advised to analyze
the integrand in order to determine the difficulties. If the position of a
local difficulty can be determined (singularity, discontinuity) one will
probably gain from splitting up the interval and calling the integrator on the subranges. Perhaps a special-purpose integrator should be used.
How can I integrate this? I'm mulling over the scipy documentation, but I can't seem to put it together. Because, after all, args themselves are already discretized by a finite number.
I am guessing that before passing the integral to quad you did some kind of interpolation on it. In general this is a misguided approach.
Integration and interpolation is very closely related. An integral requires you to compute the area under the curve and thus you must know the value of the function at any given point. Hence, starting from a set of data it is natural to want to interpolate it first. Yet the quad routine does not know that you started with a limited set of data, it just assumes that the function you gave it is "perfect" and it will do its best to compute the area under it! However the interpolated function is just a guess on what the values are between given points and thus integrating an interpolated function is a waste of time.
As MB-F said, in the discrete case you should simply sum up the points while multiplying them by the step size between them. You can do this the naïve way by pretending that the function is just rectangles. Or you can do what MB-F suggested which pretend that all the data points are connected with straight lines. Going one step further is pretending that the line connecting the data points is smooth (often true for physical systems) and use simpson integration implemented by scipy
Since you only have a discrete approximation of the function, integration reduces to summation.
As a simple approximation of an integral, try this:
midpoints = (values[:-1] + values[1:]) / 2
steps = np.diff(args)
area = np.sum(midpoints * steps)
(Assuming args and values are numpy arrays and the function is value = f(arg).)
That approach sums the areas of all trapezoids between adjacent data points (Wikipedia).
I am writing a program in Python that uses numpy.linalg.eigh to diagonalize a Hermitian matrix (a Hamiltonian). I diagonalize many such matrices and use the resultant eigenvector matrices for multiple unitary transformations of some other matrix. By "eigenvector matrix", I mean a matrix whose columns are the eigenvectors of the original matrix.
Unfortunately, I am hitting a potential problem because of the eigenvector sign ambiguity (i.e., eigenvectors are only defined up to a constant and normalization still does not fix the sign of an eigenvector). Specifically, the result I am calculating depends on the interference patterns produced by the successive unitary transformations. Thus, I anticipate that the sign ambiguity will become a problem.
My question:
What is the best way (or the industry standard) to enforce a particular sign convention for the eigenvectors?
I have thought of/come across the following:
Ensure the first coefficient of each eigenvector is positive. Problem: some of these coefficients are zero or within numerical error of zero.
Ensure the first coefficient of largest magnitude is positive. Problem: some of the eigenvectors have multiple coefficients with the same magnitude within numerical error. Numerical error then "randomly" determines which coefficient is "bigger."
Ensure the sum of the coefficients is positive. Problem: some coefficients are equal in magnitude but opposite in sign, leaving the sign still ambiguous/determined by numerical error. (I also see other problems with this approach).
Add a small number (such as 1E-16) to the eigenvector, ensure that the first coefficient is positive, then subtract the number. Problem: Maybe none important for me, but this makes me uneasy as I am not sure what problems it may cause.
(Inspired by Eigenshuffle and Sign correction in SVD and PCA) Pick a reference vector and ensure that the dot product of every eigenvector with this vector is positive. Problem: How to pick the vector? A random vector increases the likelihood that no eigenvectors are orthogonal to it (within numerical error), but there is no guarantee. Alternatively, one could choose a set of random vectors (all with positive coefficients) to increase the likelihood that the vector space is "spanned" well-enough.
I have tried to find what is the "standard" convention but I have a hard time finding anything particularly useful, particularly in Python. There is a solution for SVD (Sign correction in SVD and PCA), but I don't have any data vectors to compare to. There is Eigenshuffle (which is for Matlab and I am using Python), but my matrices are not usually successive small modifications of each other (though some are).
I am leaning toward solution 5 at it seems pretty intuitive; we are simply ensuring that all eigenvectors are in the same high-dimensional "quadrant". Also, having two or three random reference vectors with positive coefficients should cover almost all eigenvectors with very high probability, assuming the dimensionality of the system is not too big (my system has a dimensionality of 9).
I read slide about top-k algorithms which are Fagin Algorithm (FA), Threshold Algorithm (TA) and No random access algorithm (NRA). Those algorithms are good because we do not need to see all values, we just need to set a threshold or compute lower bound and upper bound.
Slide = http://alumni.cs.ucr.edu/~skulhari/Top-k-Query.pdf
Now, I have large of data points and I want to get the top-k points (subset) which diversity maximum, means that the distances among points in the top-k (subset) are maximum. I know that this problem is NP-Hard. The algorithm such as Brute force is not feasible for this case due to the dataset is large.
In here, I just want to know, is it possible to get subset/top-k points without computing all distances among all pair points like in FA/TA/NRA algorithm?
I am using scipy.sparse.linalg.eigs to calculate the eigenvalues of a large sparse matrix, which is a Jacobian for a vector function (the Jacobian size is 1200x1200). The method raises ArpackNoConvergence every once in a while, and I think it happens especially when the real part of the eigenvalues become small in magnitude (but still negative). How can I set this method to be able to calculate those eigenvalues without crashing?
My current setup is:
eigs = sparse.linalg.eigs(jacobian(state),k=1,which='LR',return_eigenvectors=False)[0]
What I would like to achieve is to find when the real part of one of the eigenvalues crosses zero (and thus the state is unstable linearly).
I need to numerically compute the eigenvalues and eigenfunctions of the radial Schrodinger Equation in the case of a 3D and 2D Coulomb potential. The differential equation contains both the first and second derivative of R(r).
The problem is that scipy.integrate.ode or scipy.integrate.odeint require "initial values" for the function and its first derivative - every example I've seen online uses a differential equation in t, so that specifying the initial conditions of the system is trivial and arbitrary.
Since I am considering an ODE in space, not time, I should note that "initial conditions" should be more accurately called "boundary conditions". For my case, however, the function R(r) must only be finite at the origin, but there is no specific value it must take at r=0. Furthermore the derivative of the radial wavefunction, R', is physically meaningless and so constraining (or especially specifying) its value at the origin is nonsensical. The only definite boundary conditions present in the system is that the function must exponentially decay to zero for very large r.
In this case I am considering, instead of making the linspace count up from zero to some large number, make it count backwards from a large value to zero, for which I can set my "initial condition at r -> infinity" such that R and R' are zero.
Anyone else have this issue, and what workaround did you find for it?
Thank you!