Curve fitting of complex variable in Matlab - matlab

I want to solve the following system of equations shown in the image below,
The matrix system
where the component of the matrix A is complex numbers with the angle (theta) runs from 0 to 2*pi which has m divisions, and n = 9. The known value z = x + iy. Suppose the x and y of matrix z is
z =
0 1.0148
0.1736 0.9848
0.3420 0.9397
0.5047 0.8742
0.6748 0.8042
0.8419 0.7065
0.9919 0.5727
1.1049 0.4022
1.1757 0.2073
1.1999 0
1.1757 -0.2073
1.1049 -0.4022
0.9919 -0.5727
0.8419 -0.7065
0.6748 -0.8042
0.5047 -0.8742
0.3420 -0.9397
0.1736 -0.9848
0 -1.0148
How do you solve them iteratively? Notice that the value of the first component of the desired constants must equal 1. I am working with Matlab.

You can apply simple multilinear regression for complex valued data.
Step 1. Get the matrix ready for linear regression
Your linear system
written without matrices, becomes
that rearranged yelds
If you rewrite it with matrices you get
Step 2. Apply multiple linear regression
Let the system above be
where
Now you can apply linear regression, that returns the best fit for α when
where
is the conjugate transpose.
In MATLAB
Y = Z - A(:,1); % Calculate Y subtracting the first col of A from Z
R = A(:,:); R(:,1) = []; % Calculate R as an exact copy of A, just without first column
Rs = ctranspose(R); % Calculate R-star (conjugate transpose of R)
alpha = (Rs*R)^(-1)*Rs*Y; % Finally apply multiple linear regression
alpha = cat(1, 1, alpha); % Add alpha1 back, whose value is 1
or, if you prefer built-ins, have a look at regress function:
Y = Z - A(:,1); % Calculate Y subtracting the first col of A from Z
R = A(:,:); R(:,1) = []; % Calculate R as an exact copy of A, just without first column
alpha = regress(Y, R); % Finally apply multiple linear regression
alpha = cat(1, 1, alpha); % Add alpha1 back, whose value is 1

Related

Rotate discrete dataset Octave

I have a discrete dataset, X=[x1,x2,..,x12] & Y=[y1,y2,...,y12]. X ranges from [-25, 0] and Y ranges from [1e-6, 1e0]. X does not increase uniformly - as x approaches a value of 0, data sampling density increases from increments of 2.5 to increments of 1. Each x value is units of cm. I cannot get a good fit to the data from fitting a function (I've tried quite a few). I'm left with the discrete data. My need is to sweep the X, Y data completly around the Z axis and put the resulting swept data values into a matrix Z of size (51, 51). I've tried using the cylinder function, [u,v,w] = cylinder(Y) thinking I could extract the data or create a matrix Z from [u, v, w]. I can't seem to sort that out. surf(u,v,w) plots almost correctly - the scaling on the (u, v) axes ranges from [-1, 1] instead of [-25, 25]. This is, I assume, because I'm using cylinder(Y). When I try [u,v,w] = cylinder(X,Y) I get, error: linspace: N must be a scalar. It seems like there should be a better way then my approach of using cylinder to take the X & Y data, interpolate between points (to fill Z where data isn't), rotate it, and put the result into a matrix Z. Any suggestions are welcome. I'm using Octave 6.3.0. Thank you in advance.
Create a matrix R containing distance from origin values.
Use for loops and single value interpolation to cover the R space.
Place the interpolated values into the matrix Z.
% Original data X = [-25,-22.5,...,0]; size(X) = 1 12
% Original data Y = [1e-6, 1.3e-6,...,1] size(Y) = 1 12
u = [-range(X):1:range(X)]; v = [-range(X):1:range(X)]';
R = -sqrt(u.^2.+v.^2);
Z = zeros( 2 .* range(X) + 1);
for i = 1:size(R,1)
for j = 1:size(R,2)
if R(i,j) < min(X); Z(i,j) = 0; endif
if R(i,j) >= min(X); Z(i,j) = interp1(X,Y,R(i,j)); endif
endfor
endfor

Which function allow me to calculate cumulative variance over a vector?

I need to calculate the cumulative variance of a vector. I have tried to build and script, but this script takes too much time to calculate the cumulative variance of my vectors of size 1*100000. Do you know if there exists a faster way to find this cumulative variance?
This is the code I am using
%%Creation of the rand vectors. ans calculation of the variances
d=100000; %dimension of the vectors
nv=6 %quantity of vectors
for j=1:nv;
VItimeseries(:,j)=rand(d,1); % Final matrix with vectors
end
%% script to calculate the cumulative variance in the columns of my matrix
VectorVarianza=0;
VectoFinalVar=0;
VectorFinalTotalVAriances=zeros(d,nv);
for k=1:nv %number of columns
for j=1:numel(VItimeseries(:,k)) %size of the rows
Vector=VItimeseries(:,k);
VectorVarianza(1:j)= Vector(1:j); % Vector to calculate the variance...
...Independently
VectorFinalVar(j,k)= var(VectorVarianza);%Calculation of variances
end
VectorFinalTotalVAriances(:,k)=VectorFinalVar(:,k)% construction of the...
...Final Vector with the cumulative variances
end
Looping over the n elements of x, and within the loop computing the variance of all elements up to i using var(x(1:i)) amounts to an algorithm O(n2). This is inherently expensive.
Sample variance (what var computes) is defined as sum((x-mean(x)).^2) / (n-1), with n = length(x). This can be rewritten as (sum(x.^2) - sum(x).^2 / n) / (n-1). This formula allows us to accumulate sum(x) and sum(x.^2) within a single loop, then compute the variance later. It also allows us to compute the cumulative variance in O(n).
For a vector x, we'd have the following loop:
x = randn(100,1); % some data
v = zeros(size(x)); % cumulative variance
s = x(1); % running sum of x
s2 = x(1).^2; % running sum of square of x
for ii = 2:numel(x) % loop starts at 2, for ii=1 we cannot compute variance
s = s + x(ii);
s2 = s2 + x(ii).^2;
v(ii) = (s2 - s.^2 / ii) / (ii-1);
end
We can avoid the explicit loop by using cumsum:
s = cumsum(x);
s2 = cumsum(x.^2);
n = (1:numel(x)).';
v = (s2 - s.^2 ./ n) ./ (n-1); % v(1) will be NaN, rather than 0 as in the first version
v(1) = 0; % so we set it to 0 explicitly here
The code in the OP computes the cumulative variance for each column of a matrix. The code above can be trivially adapted to do the same:
s = cumsum(VItimeseries,1); % cumulative sum explicitly along columns
s2 = cumsum(VItimeseries.^2,1);
n = (1:size(VItimeseries,1)).'; % use number of rows, rather than `numel`.
v = (s2 - s.^2 ./ n) ./ (n-1);
v(1,:) = 0; % fill first row with zeros, not just first element

Double integral of the equation in Matlab

How to implement this equation
in Matlab,
where: A and B are mxm matrices.
for example:
A = [3.45 32.54 78.2; 8.4 33.1 4.66; 68.2 9.336 33.87 ]
B = [6.45 36.54 28.24; 85.4 323.1 74.66; 98.2 93.336 38.55 ]
my code:
f1 = #(A) (abs(A) ).^2;
f2 = #(B) (abs(B) ).^2;
Q = integral2( f1, 0, 1, 0, 1) * integral2(f2, 0, 1, 0, 1);
But when i run the code I got the error "Too many input arguments.".
What is the problem in the code?
After clarification of your question, let me change my post.
What you are after is numerical integration of a function that was already sampled on a fixed grid, and the function values are stored in matrices A and B that are two dimensional M by M. I suppose that you have the associated gridpoints as well, suppose they are denoted xc and yc. Then, if you have sufficiently fine sampling of a smooth function, the integral approaches:
xc = linspace(0,1,M);
yc = linspace(0,1,M);
Q = trapz(xc,trapz(yc, abs(A).^2)) * trapz(xc,trapz(yc, abs(B).^2 ));
To test that, I made a simple example that evaluates the surface of a circle, i.e.
so to do that with trapezoidal method with N samples for r and M samples for phi, we have,
r = 2; % Pick a value for r
M = 100; % Pick M samples for the angular coordinate from 0 to 2*pi
N = 101; % Pick N samples for the radial coordinate from 0 to r
phic = linspace(0,2*pi,M); % take M samples uniformly for example
rc = linspace(0,r,N); % take N samples uniformly for example
integrand = repmat(rc,M,1); % Make MxN matrix, phi along rows, r along columns
I = trapz(rc, trapz(phic, integrand));
So for the case r=2, it gives indeed 4*pi.

MATLAB: What's wrong with my quatrotate script?

My version of MATLAB doesn't have the quatrotate function included, so I wrote my own using the equation MathWorks provide here. Trouble is, I don't get the same answers they get in their example in my function, or when I hand calculate it.
Under their example if I input the following I should get an n vector [-1 1 1]:
q = [1 0 1 0]; r = [1 1 1]; n = quatrotate(q, r)
n =
-1.0000 1.0000 1.0000
In my function, and by hand, I get:
[-3 1 1]
What am I missing here? The more I search the more confused I get. As far as I can tell the answer should be [-3 1 1].
Here is the function I wrote:
function [n] = quatrotate(q,r)
%Rotate a given acceleration vector by a given quaternion
%
%Inputs:
% q: A matrix containing a set of quaternion vectors of the
% form q = [w,x,y,z]
% r: A matrix containing a set of linear acceleration vectors
% of the form r= [i,j,k] (also known as [x,y,z])
%
% Outputs:
% n: The solved matrix containing the rotated vector of each linear
% acceleration component
%
%This assumes that the quaternion is normalised (sqw + sqx + sqy + sqz =1),
%if not it should be normalised before doing the conversion.
%To normalise divide qx, qy, qz and qw by n where n=sqrt(qx2 + qy2 + qz2 + qw2)
for k = 1:size(q,1)
rot=[(1-2.*q(k,3).^2-2.*q(k,4).^2) 2.*(q(k,2).*q(k,3)+q(k,1).*q(k,4))...
2.*(q(k,2).*q(k,4)-q(k,1).*q(k,3));2.*(q(k,2).*q(k,3)-q(k,1).*q(k,4))...
(1-2.*q(k,2).^2-2.*q(k,4).^2) 2.*(q(k,3).*q(k,4)+q(k,1).*q(k,2));...
2.*(q(k,2).*q(k,4)+q(k,1).*q(k,3)) 2.*(q(k,3).*q(k,4)-q(k,1).*q(k,2))...
(1-2.*q(k,2).^2-2.*q(k,3).^2)];
n(k,:) = rot*r(k,:)';
end
Thanks in advance!
first of all you need to calculate the modulus of the given Quaternion q:
for index = size(q,1):-1:1
mod(index,:) = norm(q(index,:),2);
end
Then normalize it:
qn = q./(mod* ones(1,4));
Now calculate the Direct Cosine Matrix using these formulae:
dcm = zeros(3,3,size(qn,1));
dcm(1,1,:) = qn(:,1).^2 + qn(:,2).^2 - qn(:,3).^2 - qn(:,4).^2;
dcm(1,2,:) = 2.*(qn(:,2).*qn(:,3) + qn(:,1).*qn(:,4));
dcm(1,3,:) = 2.*(qn(:,2).*qn(:,4) - qn(:,1).*qn(:,3));
dcm(2,1,:) = 2.*(qn(:,2).*qn(:,3) - qn(:,1).*qn(:,4));
dcm(2,2,:) = qn(:,1).^2 - qn(:,2).^2 + qn(:,3).^2 - qn(:,4).^2;
dcm(2,3,:) = 2.*(qn(:,3).*qn(:,4) + qn(:,1).*qn(:,2));
dcm(3,1,:) = 2.*(qn(:,2).*qn(:,4) + qn(:,1).*qn(:,3));
dcm(3,2,:) = 2.*(qn(:,3).*qn(:,4) - qn(:,1).*qn(:,2));
dcm(3,3,:) = qn(:,1).^2 - qn(:,2).^2 - qn(:,3).^2 + qn(:,4).^2;
According to MATLAB documents, the rotation of a vector r by the calculated dcm can be found as follows:
if ( size(q,1) == 1 )
% Q is 1-by-4
qout = (dcm*r')';
elseif (size(r,1) == 1)
% R is 1-by-3
for i = size(q,1):-1:1
qout(i,:) = (dcm(:,:,i)*r')';
end
else
% Q is M-by-4 and R is M-by-3
for i = size(q,1):-1:1
qout(i,:) = (dcm(:,:,i)*r(i,:)')';
end
end
Well first of all, in order for quatrotate to work, you need to use a unit quaternion (i.e. length of 1).
Second of all, I see that you are using the matrix provided by the MATLAB page. I've recently derived that matrix myself and found that the MATLAB page has the wrong matrix.
According to this (page 45), rotating a vector by a quaternion is
p' = p + 2w(v × p)+2(v × (v × p))
Where,
p' is the output vector after rotation,
p is the starting vector to be rotated,
w is the first coefficient in the quaternion,
v is the vector of [second coefficent, third coefficient, fourth coefficient] of the quaternion,
× is the cross product operand.
I encourage you to go to the link and derive the matrix yourself. You will see that the matrix provided on the MATLAB page has the wrong additions and subtractions.
This is what's said on the MATLAB page:
Here's my derivation (here the quaternion is [q0, q1, q2, q3] and the vector is [x, y, z]):
First row:
Second row:
Third row:
Here you can see that the signs are incorrect on MATLAB's website. I've emailed them about the error and is waiting to hear back.

Computing an ODE in Matlab

Given a system of the form y' = A*y(t) with solution y(t) = e^(tA)*y(0), where e^A is the matrix exponential (i.e. sum from n=0 to infinity of A^n/n!), how would I use matlab to compute the solution given the values of matrix A and the initial values for y?
That is, given A = [-2.1, 1.6; -3.1, 2.6], y(0) = [1;2], how would I solve for y(t) = [y1; y2] on t = [0:5] in matlab?
I try to use something like
t = 0:5
[y1; y2] = expm(A.*t).*[1;2]
and I'm finding errors in computing the multiplication due to dimensions not agreeing.
Please note that matrix exponential is defined for square matrices. Your attempt to multiply the attenuation coefs with the time vector doesn't give you what you'd want (which should be a 3D matrix that should be exponentiated slice by slice).
One of the simple ways would be this:
A = [-2.1, 1.6; -3.1, 2.6];
t = 0:5;
n = numel(t); %'number of samples'
y = NaN(2, n);
y(:,1) = [1;2];
for k =2:n
y(:,k) = expm(t(k)*A) * y(:,1);
end;
figure();
plot(t, y(1,:), t, y(2,:));
Please note that in MATLAB array are indexed from 1.