How it is possible to calculate only one eigenvector for one eigenvalue lambda=1 on C++ as efficiently as possible - lapack

С++ have a very efficient algorithm to calculate eigenvalues and eigenvectors in MKL library with function dgeev. But it calculates all Eigenvalues, and all left and rirhgt eigenvectors.
DGEEV Example Program Results
Eigenvalues ( 2.86, 10.76) ( 2.86,-10.76) ( -0.69, 4.70) ( -0.69,
-4.70) -10.46
Left eigenvectors ( 0.04, 0.29) ( 0.04, -0.29) ( -0.13, -0.33) (
-0.13, 0.33) 0.04 ( 0.62, 0.00) ( 0.62, 0.00) ( 0.69, 0.00) ( 0.69, 0.00) 0.56 ( -0.04, -0.58) ( -0.04, 0.58) ( -0.39,
-0.07) ( -0.39, 0.07) -0.13 ( 0.28, 0.01) ( 0.28, -0.01) ( -0.02, -0.19) ( -0.02, 0.19) -0.80 ( -0.04, 0.34) ( -0.04, -0.34) ( -0.40, 0.22) ( -0.40, -0.22) 0.18
Right eigenvectors ( 0.11, 0.17) ( 0.11, -0.17) ( 0.73, 0.00) (
0.73, 0.00) 0.46 ( 0.41, -0.26) ( 0.41, 0.26) ( -0.03, -0.02) ( -0.03, 0.02) 0.34 ( 0.10, -0.51) ( 0.10, 0.51) ( 0.19, -0.29) ( 0.19, 0.29) 0.31 ( 0.40, -0.09) ( 0.40, 0.09) ( -0.08,
-0.08) ( -0.08, 0.08) -0.74 ( 0.54, 0.00) ( 0.54, 0.00) ( -0.29, -0.49) ( -0.29, 0.49) 0.16
For large matrices it takes a lot of time. Especially if you need to calculate eigenvectors for a large number of matrices.
So the main question is how can I calculate the only one eigenvector for real matrix only for one eigenvalue lambda = 1 as fast as possible?
Or how I can solve the system of linear equations A-E=0, where A is a real matrix, E - Identity matrix.
The eigenvector 100% exist and it consists only real numbers.

You can't really solve B x = 0 with B = A - I. This equation has infinitely many solutions if A has a unit eigenvalue.
For the simplest solution, put x(n) = 1 for arbitrary n, say n = N. Then use first N-1 equations to find x(1:N-1). Effectively, you'll have to solve B' x' = r for x' = x(1:N-1), where B' = B(1:N-1, 1:N-1), and r = -B(1:N-1,N). This can easily be done using MKL/LAPACK ?gesv routine specifying appropriate values for matrix sizes and leading dimensions.
Note that depending on A, B' can also be singular. Then you'll have to fix more x_n components. In the extreme case, when A = I, all x_ns are arbitrary.

Related

Add the constraint of normalization coefficient for matlab curve fitting

I want to use a custom model to fit some data. The syntax I used is fit(). The mathematical model I used has the form of this:
a*exp(-x*b)+c*exp(-y*d)+e*exp(-z*f)
where a,b,c,d,e,f are the parametres I will estimate and x,y,z are independent variables. (The actual mathematical formula is more complicated but something nonlinear like this.)
How can I add the constraint of a+c+e=1 (and a,c,e must be positive or 0) when fitting the curve? I know how to set the lower and upper bound but don't know how to add this normalization coefficient constraint to the fitting. Is it possible to do this when using the fit() method?
I think I already posted this somewhere, but can't find it right now.
As it is a non-linear fit, there is no big deal in transforming the parameters. say we chose the continuously differentiable and monotonic function:
a = f(s) = 1/2 ( 1 + s / sqrt( 1 + s^2 ) )
so for s in (-inf, inf) on gets a in (0,1). Actually, with some simple shifting and scaling we could get any a in ( u, v ).
Now we can do the same for b, but with the additional restriction a + b + c = 1 we know that at most c = 0 and b must definitively be smaller than 1 - f(s) = 1/2 ( 1 - s / sqrt( 1 + s^2 ) ). Now, hence, is the time for scaling and we can set:
b = g(t, s) = 1/2 ( 1 - s / sqrt( 1 + s^2 ) ) 1/2 ( 1 + t / sqrt( 1 + t^2 ) )
again with t in (-inf, inf). The first part is the scaling due to the already set value for a, the second part repeats the procedure from above.
Finally, cis simply 1- f(s) - g(t, s)
Eventually, the fit function with parameters s and t looks like:
+ 0.50 * ( 1 + s / sqrt( 1 + s^2 ) ) * exp( -x * b )
+ 0.25 * ( 1 - s / sqrt( 1 + s^2 ) ) * ( 1 + t / sqrt( 1 + t^2 ) ) * exp( -y * d )
+ (
+1.00
-0.50 * ( 1 + s / sqrt( 1 + s^2 )
-0.25 * ( 1 - s / sqrt( 1 + s^2 ) ) * ( 1 + t / sqrt( 1 + t^2 ) )
) * exp( -z * f )
Getting results for s and t provides a, b and c via error propagation

PyTorch RoI pooling implementation deviation

I am trying to implement ROI pooling by PyTorch. Here's the minimal demo.
import torch
import torch.nn as nn
import torch.nn.functional as F
def roi_pooling(feature_map, rois, size=(7, 7)):
"""
:param feature_map: (1, C, H, W)
:param rois: (1, N, 4) N refers to bbox num, 4 represent (ltx, lty, w, h)
:param size: output size
:return: (1, C, size[0], size[1])
"""
output = []
rois_num = rois.size(1)
for i in range(rois_num):
roi = rois[0][i]
x, y, w, h = roi
output.append(F.adaptive_max_pool2d(feature_map[:, :, y:y+h, x:x+w], size))
return torch.cat(output)
if __name__ == '__main__':
test_tensor = torch.tensor([
[0.88, 0.44, 0.14, 0.16, 0.37, 0.77, 0.96, 0.27],
[0.19, 0.45, 0.57, 0.16, 0.63, 0.29, 0.71, 0.70],
[0.66, 0.26, 0.82, 0.64, 0.54, 0.73, 0.59, 0.26],
[0.85, 0.34, 0.76, 0.84, 0.29, 0.75, 0.62, 0.25],
[0.32, 0.74, 0.21, 0.39, 0.34, 0.03, 0.33, 0.48],
[0.20, 0.14, 0.16, 0.13, 0.73, 0.65, 0.96, 0.32],
[0.19, 0.69, 0.09, 0.86, 0.88, 0.07, 0.01, 0.48],
[0.83, 0.24, 0.97, 0.04, 0.24, 0.35, 0.50, 0.91]
])
test_tensor = test_tensor.view(1, 1, 8, 8)
rois = torch.tensor([[0, 3, 7, 5]])
rois = rois.view(1, -1, 4)
output = roi_pooling(test_tensor, rois, (2, 2))
print(output)
I implement this by referencing this website: https://deepsense.ai/region-of-interest-pooling-explained/. And the test_tensor and RoI also comes from the website's example. However, as the website display, the output should be
[ [0.85, 0.84], [0.97, 0.96] ]
instead of my demo's output:
[ [0.85, 0.96], [0.97, 0.96] ]
So, what's the exact problem of my code? Is the coordinate split phase wrong?

2d interpolation table (Matlab)

I have a table( w, alfa, eta ):
w = [0, 0.5, 1]
alfa = [0, 0.3, 0.6, 0.9]
eta(0,0.3) = 0.23
eta(0.5,0) = 0.18
eta(0.5,0.6) = 0.65
eta(1,0.9) = 0.47
where, eta = f(w,alfa)
How can I interpolate the data to obtain all values ​​in this table?
I try griddata, interp2 etc but i can't do it.
It seems like griddata should do the work in your case. However, you should notice that your inputs requires extrapolation as well as interpolation.
>> [xout yout] = meshgrid( w, alfa ); % output points
>> w_in = [ 0, 0.5, 0.5, 1 ];
>> a_in = [ 0.3, 0, 0.6, 0.9 ];
>> e_in = [ 0.23, 0.18, 0.65, 0.47 ];
>> eta_out = griddata( w_in, a_in, e_in, xout, yout, 'linear' )

Solving non linear equations related to distance

I want to solve a set of non linear equations in matlab. I mean lets say I have two points defined by (lat1,lon1) and (lat2,lon2). Now I want to find a point lat3,lon3 such that it is at a distance of 20km from both of the points. It is given by the intersection of the circles with radius 20km drawn with points (lat1,lon1) and (lat2,lon2) as center.
However, I am a bit confused about how to solve this equation.
I have the function to calculate the distance between two points in matlab
function [ distance ] = calculateDistance( latitude1,longitude1,latitude2,longitude2 )
radius = 6371;
dLat = degtorad(latitude2-latitude1);
dLon = degtorad(longitude2-longitude1);
a = sin(dLat/2) * sin(dLat/2) + cos(degtorad(latitude1)) * cos(degtorad(latitude2)) * sin(dLon/2) * sin(dLon/2);
c = 2 * atan2(sqrt(a), sqrt(1-a));
distance = radius * c;
end
and I am trying to use the solve function of matlab available at
http://www.mathworks.com/help/toolbox/symbolic/solve.html
However when I define
syms lat3 lon3
and try to get the equations to pass to the solve function it throws the error that
atan2 only accepts arguments of type sym.
How can I over this?
If you have to solve only that particular question, you do not need any equation solving functions of Matlab. You can simply use Pythagoras' formula:
If your points are (0,0) and (1,0) and the radius is x, then the two points which are x away from both (0,0) and (1,0) are
(0.5, sqrt (x^2 - 0.25) ) and (0.5, - sqrt (x^2 - 0.25)).
Now if your points are (a,b) and (c,d), then the distance of the two points is
dist = sqrt ( (c-a)^2 + (d-b)^2 ).
Ok, now we take a coordinate system where the origin is (a,b) and the unit is dist and the horizontal axis goes through (c,d). In this coordinate system, the points in question are
(0.5, +/- sqrt ( (r/dist)^2 - 0.25 ) ).
Now, to get to the original coordinate system, we have to multiply by dist, getting
(0.5 * dist, +/- sqrt ( r^2 - 0.25 * dist^2 ) ),
then rotate with the matrix rotating (dist, 0) to (c-a, d-b), which is
cos alpha -sin alpha
sin alpha cos alpha
where alpha = arccos ( (d-b) / dist), i.e. the matrix
(d-b) / dist -(c-a) / dist
(c-a) / dist (d-b) / dist
which gives
(0.5 (d-b) -/+ (c-a) sqrt (r^2 / dist^2 - 0.25),
0.5 (c-a) +/- (d-b) sqrt (r^2 / dist^2 - 0.25)
and finally add (a,b), yielding
(a + 0.5 (d-b) -/+ (c-a) sqrt (r^2 /dist^2 - 0.25),
b + 0.5 (c-a) +/- (d-b) sqrt (r^2 /dist^2 - 0.25) )
These are the points you are looking for. Probably I have made a mistake somewhere, but the direction should be clear, I hope.

Matlab: how to calculate the definite integral of a function over multiple limits?

Assume:
z = [0.4 0.5 0.75]'
function y = myfunct(x)
y = quad(#sin, 0, x)
I'd like to calculate the definite integral of sin(x) from 0 to 0.4, to 0.5, and 0.75, using:
myfunct(z)
However, Matlab returns:
??? Error using ==> quad at 70
The limits of integration must be scalars.
I'd be thankful for any constructive suggestions.
You can use the arrayfun function in recent versions of MATLAB:
z = [0.4 0.5 0.75]';
y = arrayfun(#(upperLim)(quad(#sin,0,upperLim)),z);
You can also use quadv to do this. BUT, instead of making a vector of integration limits, make an array valued function so that when you integrate each element, the range of integration will be 0 to 1.
To be more specific, you want to integrate sin(x) from x = 0 to z. This is the same as integrating sin(u z)*z from u = 0 to 1 (u-substitution). Make an array function
F = #(u) [sin( .4 * u) * .4, sin( .5 * u ) * .5, sin( .75 * u ) * .75 ];
Then do
quadv(F,0,1)