How to Create Autocorrelation Function without any buit-in functions like xcorr - matlab

I want to auto-correlate a random noise vector with out any built-in MATLAB functions.
My auto correlation equation that is given is:
Rxx[L] = ∑ from n = 1 to N-1 [x(n)*x(n+L)]
L = [0:200]
I have written the code below but the plot Rxx vs L plot is not what I am expecting.
I am expecting my plot to start at some maximum at L = 0 or L = 1 since MATLAB starts its index at 1. Then exponentially decrease and saturates at a min of zero.
clc
clear all
randn('seed',2496132);
n = randn(1,1024);
upperbound = numel(n)-1;
for L = 1:200
for j = 1 : upperbound
n1(j) = n(j)+L;
Rxx(j) = (n(j)*n1(j));
end
Rxx_sum(L) = sum(Rxx);
Rxx = 0;
end
plot([1:200], Rxx_sum)

You have error in inner loop: you need to use n1(j) = n(j+L); instead n1(j) = n(j)+L;. E.g. you need add L to index instead value.
Second error is following: if you want to use upperbound = numel(n)-1 than you should use L equal to 0 or 1 only. E.g. you outer loop will be
for L = 0:1
...
Rxx_sum(L+1) = sum(Rxx);
...
Instead of this you can also correct upperbound value:
upperbound = numel(n) - maxL;
There maxL is maximal value of L that will used in next loop.
One more tip: it is possible to increase calculation speed if you replace inner loop with scalar product, e.g.
for L = 1:200
Rxx_sum(L) = n(1:upperbound) * n(1+L:upperbound+L)';
end

I ended up fixing my script with the help of the above code.
clc
clear all
randn('seed',2496132);
z = randn(1,1024);
n = [z zeros(1,200)];
upperbound = numel(z)-1;
for L = 0:200
for j = 1 : upperbound
Rxx(j) = (n(j)*n(j+L));
>end
Rxx_sum(L+1) = sum(Rxx);
Rxx = 0;
end
plot([0:200],Rxx_sum)

Related

How to calculate the expected value of a function with random normally distributed X?

I am trying to calculate on MatLab the Expectation for the function e^X where X ~ N(mu,sigma^2). In my example, mu = 0 and sigma = 1.
function [E] = expectedval(m,s)
%find E(e^x) with X~N(mu,sigma)
% mu = 0 , sigma = 1
X = normrnd(m,s);
f=exp(X);
mean(f)
So by the end I can run expectedval(0,1) to get my solution. The code runs with no issue, but I would like to compile a histogram to analyse the data with several runs. How may I collect this data with some sort of loop?
I'd appreciate any improvement ideas or suggestions!
Actually, your function just creates one random value for the given mean and variance... so there's actually no point in calculating a mean. On the top of that, the output E value is not assigned before the function finishes. The function can therefore be rewritten as follows:
function E = expectedval(m,s)
X = normrnd(m,s);
E = exp(X);
end
If you want to draw a sample from the normal distribution, and use the mean to compute the correct expected value, you can rewrite it as follows instead:
function E = expectedval(m,s,n)
X = normrnd(m,s,[n 1]);
f = exp(X);
E = mean(f);
end
And here is an example on how to run your function many times with different parameters, collecting the output on each iteration:
m = 0:4;
m_len = numel(m);
s = 1:0.25:2;
s_len = numel(s);
n = 100;
data = NaN(m_len*s_len,1);
data_off = 1;
for s = 1:s_len
for m = 1:m_len
data(data_off) = expectedval(m,s,n);
data_off = data_off + 1;
end
end

MATLAB - Finding Zero of Sum of Functions by Iteration

I am trying to sum a function and then attempting to find the root of said function. That is, for example, take:
Consider that I have a matrix,X, and vector,t, of values: X(2*n+1,n+1), t(n+1)
for j = 1:n+1
sum = 0;
for i = 1:2*j+1
f = #(g)exp[-exp[X(i,j)+g]*(t(j+1)-t(j))];
sum = sum + f;
end
fzero(sum,0)
end
That is,
I want to evaluate at
j = 1
f = #(g)exp[-exp[X(1,1)+g]*(t(j+1)-t(j))]
fzero(f,0)
j = 2
f = #(g)exp[-exp[X(1,2)+g]*(t(j+1)-t(j))] + exp[-exp[X(2,2)+g]*(t(j+1)-t(j))] + exp[-exp[X(3,2)+g]*(t(j+1)-t(j))]
fzero(f,0)
j = 3
etc...
However, I have no idea how to actually implement this in practice.
Any help is appreciated!
PS - I do not have the symbolic toolbox in Matlab.
I suggest making use of matlab's array operations:
zerovec = zeros(1,n+1); %preallocate
for k = 1:n+1
f = #(y) sum(exp(-exp(X(1:2*k+1,k)+y)*(t(k+1)-t(k))));
zerovec(k) = fzero(f,0);
end
However, note that the sum of exponentials will never be zero, unless the exponent is complex. Which fzero will never find, so the question is a bit of a moot point.
Another solution is to write a function:
function [ sum ] = func(j,g,t,X)
sum = 0;
for i = 0:2*j
f = exp(-exp(X(i+1,j+1)+g)*(t(j+3)-t(j+2)));
sum = sum + f;
end
end
Then loop your solver
for j=0:n
fun = #(g)func(j,g,t,X);
fzero(fun,0)
end

Matrices in Matlab

I'm running a script calling a function and within the function it takes a value from the matrix. Matlab seems to be thinking that the value is still a matrix and is asking for a . when its squared. I should be getting a single value out of my matrix. Any help would be appreciated!
Output
Error using ^
Inputs must be a scalar and a square matrix.
To compute elementwise POWER, use POWER (.^) instead.
Error in ls_error (line 11)
partialSum = (vi - yi)^2;
This is the script i'm running
Exp1H1 = 35.6;
Exp1H2 = 24.7;
Exp2H1 = 46.8;
Exp2H2 = 37.8;
Exp3H1 = 45.7;
Exp3H2 = 36.4;
Exp4H1 = 47.7;
Exp4H2 = 39.2;
Radius = 3.75;
L = 10;
ArrayOfHeightDiff = [(Exp1H1-Exp1H2),(Exp2H1-Exp2H2),(Exp3H1-Exp3H2), (Exp4H1-Exp4H2)];
dhdl = ArrayOfHeightDiff./L
ArrayOfDarcys = [0.29,0.25,0.26,0.23];
v_meas = ((ArrayOfDarcys.*1000)./60)./(pi*Radius^2)
K = [-0.3 : 0.1 : 0.5];
for ii = 1 : 1 : length(K)
ExportSum = ls_error(dhdl, v_meas, K)
ExportSum(1,ii) = ExportSum
end
This is the function
function [ExportSum] = ls_error(dhdl, v_meas, K)
total = 0;
L = length(dhdl);
for ii = 1 : 1 : L
dhdl1 = dhdl(1,ii);
vi = v_meas(1,ii);
yi = 1*K* dhdl1;
partialSum = (vi - yi)^2;
total = total + partialSum;
end
ExportSum = total;
end
In the following code, you create a 1xN vector K, and pass it into ls_error:
K = [-0.3 : 0.1 : 0.5];
for ii = 1 : 1 : length(K)
ExportSum = ls_error(dhdl, v_meas, K)
ExportSum(1,ii) = ExportSum
end
You then use this vector Kand multiply it by two scalars, which will produce a 1xN vector:
yi = 1*K* dhdl1;
partialSum = (vi - yi)^2;
The partialSum calculation is then giving you the error, as you can't perform a scalar square on a vector.
From your code, what I think you meant to do was this:
for ii = 1 : 1 : length(K)
ExportSum = ls_error(dhdl, v_meas, K(ii))
ExportSum(1,ii) = ExportSum
end
Where instead of passing in the entire vector K, you just want to pass in the iith element to use within the calculation of ExportSum which you return.
As a further note, once this bug is solved, it may be worth looking at vectorising your Matlab function (i.e. deliberately passing it the entire vector of K and computing all of the ExportSums at once using vector arithmetic instead of inside a loop), which will hugely speed up your code. It can be complicated, but will likely give you a huge decrease in execution time.
In the calling script you define K as a vector. Therefore, in the function yi is a vector too. Hence the error in (vi - yi)^2.

How to vectorize a matlab script converting a 3d matrix to a single vector?

I am writing a graphical representation of numerical stability of differential operators and I am having trouble removing a nested for loop. The code loops through all entries in the X,Y, plane and calculates the stability value for each point. This is done by finding the roots of a polynomial of a size dependent on an input variable (length of input vector results in a polynomial 3d matrix of size(m,n,(lenght of input vector)). The main nested for loop is as follows.
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
The full code of an example numerical method (Trapezoidal Rule) is as follows. Any and all help is appreciated.
alpha = [-1 1];
beta = [.5 .5];
Wind = 2;
Wsize = 500;
if numel(Wind) == 1
Wind(4) = Wind(1);
Wind(3) = -Wind(1);
Wind(2) = Wind(4);
Wind(1) = Wind(3);
end
if numel(Wsize) == 1
Wsize(2) = Wsize;
end
z1 = linspace(Wind(1),Wind(2),Wsize(1));
z2 = linspace(Wind(3),Wind(4),Wsize(2));
[Z1,Z2] = meshgrid(z1,z2);
z = Z1+1i*Z2;
p = zeros(Wsize(2),Wsize(1),length(alpha));
for n = length(alpha):-1:1
p(:,:,(length(alpha)-n+1)) = alpha(n)-z*beta(n);
end
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
figure()
surf(Z1,Z2,z,'EdgeColor','None');
caxis([0 2])
cmap = jet(255);
cmap((127:129),:) = 0;
colormap(cmap)
view(2);
title(['Alpha Values (',num2str(alpha),') Beta Values (',num2str(beta),')'])
EDIT::
I was able to remove one of the for loops using the reshape command. So;
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
has now become
gg = reshape(p,[numel(p)/length(alpha) length(alpha)]);
r = zeros(numel(p)/length(alpha),1);
for n = 1:numel(p)/length(alpha)
temp = roots(gg(n,:));
if isempty(temp),temp = 0;end
r(n,1) = max(abs(temp));
end
z = reshape(r,[Wsize(2),Wsize(1)]);
This might be one for loop, but I am still going through the same number of elements. Is there a way to use the roots command on all of my rows at the same time?

Multiplying a vector by random numbers while keeping the sum the same (MATLAB)

I'm trying to multiply (element wise) a vector V of length N by a randomly generated number in the range (a,b), while keeping the sum of the vector equal to a total amount, E. I want to do this in MATLAB, but I'm not sure how. Getting random numbers between a certain range I know how to do:
minrand = 0;
maxrand = 1;
randfac = (maxrand-minrand).*rand(1,N) + minrand;
But yeah, beyond that I'm pretty clueless. I guess the random numbers can't really be generated like this, because if we call the random numbers the vector R, then I want that
R_1*V1 + R_2*V2 .... + R_N*V_N = E. So I guess it's a big equation. Is there any way to solve it, while putting constraints on the max and min values of R?
You can pick pairs of two elements (in all combinations) and add and subtract an equal random number.
% Make up a random vector
N=10;
randfac = 10*rand(1,N);
%OP Answer here: Given randfac with sum E re-randomize it
E = sum(randfac);
minrand = 0;
maxrand = 2;
disp(randfac)
% v = [6.4685 2.9652 6.6567 1.6153 7.3581 0.0237 7.1025
% 3.2381 1.9176 1.3561]
disp(sum(randfac))
% E = 38.7019
r = minrand + (maxrand-minrand)*rand(N*N,1);
k = 1;
for i=1:N
for j=1:N
randfac(i) = randfac(i)-r(k);
randfac(j) = randfac(j)+r(k);
k = k + 1;
end
end
disp(randfac)
% v = [5.4905 0.7051 4.7646 1.3479 9.3722 -1.4222 7.9275
% 7.5777 1.7549 1.1836]
disp(sum(randfac))
% E = 38.7019
Just divide the vector with the sum and multiply with the target E.
randfac = (maxrand-minrand).*rand(1,N) + minrand;
randfac = E*randfac/sum(randfac);
as long as the operator is linear, the result is going to retain it's randomness. Below is some sample code:
minrand = 0;
maxrand = 1;
N = 1000; %size
v = (maxrand-minrand).*rand(1,N) + minrand;
E = 100; %Target sum
A = sum(v);
randfac = (E/A)*v;
disp(sum(randfac))
% 100.0000
First of all with random numbers in the interval of [a b] you can't guarantee that you will have the same summation (same E). For example if [a b]=[1 2] of course the E will increase.
Here is an idea, I don't know how random is this!
For even N I randomize V then divide it in two rows and multiply one of them with random numbers in [a b] but the second column will be multiplied to a vector to hold the summation fixed.
N = 10;
V = randi(100,[1 N]);
E = sum(V);
idx = randperm(N);
Vr = V(idx);
[~,ridx] = sort(idx);
Vr = reshape(Vr,[2 N/2]);
a = 1;
b = 3;
r1 = (b - a).*rand(1,N/2) + a;
r2 = (sum(Vr) - r1.*Vr(1,:))./Vr(2,:);
r = reshape([r1;r2],1,[]);
r = r(ridx);
Enew = sum(V.*r);
The example results are,
V = [12 82 25 51 81 51 31 87 6 74];
r = [2.8018 0.7363 1.9281 0.5451 1.9387 -0.4909 1.3076 0.8904 2.9236 0.8440];
with E = 500 as well as Enew.
I'm simply assigning one random number to a pair (It can be considered as half random!).
Okay, I have found a way to somewhat do this, but it is not elegant and there are probably better solutions. Starting with an initial vector e, for which sum(e) = E, I can randomize its values and end up with an e for which sum(e) is in the range [(1-threshold)E,(1+thresholdE)]. It is computationally expensive, and not pretty.
The idea is to first multiply e by random numbers in a certain range. Then, I will check what the sum is. If it is too big, I will decrease the value of the random numbers smaller than half of the range until the sum is no longer too big. If it is too small, I do the converse, and iterate until the sum is within the desired range.
e = somepredefinedvector
minrand = 0;
maxrand = 2;
randfac = (maxrand-minrand).*rand(1,N) + minrand;
e = randfac.*e;
threshold = 0.001;
while sum(e) < (1-threshold)*E || sum(e) > (1+threshold)*E
if sum(e) > (1+threshold)*E
for j = 1:N
if randfac(j) > (maxrand-minrand)/2
e(j) = e(j)/randfac(j);
randfac(j) = ((maxrand-minrand)/2-minrand).*rand(1,1) + minrand;
e(j) = randfac(j)*e(j);
end
if sum(e) > (1-threshold)*E && sum(e) < (1+threshold)*E
break
end
end
elseif sum(e) < (1-threshold)*E
for j = 1:N
if randfac(j) < (maxrand-minrand)/2
e(j) = e(j)/randfac(j);
randfac(j) = (maxrand-(maxrand-minrand)/2).*rand(1,1) + (maxrand-minrand)/2;
e(j) = randfac(j)*e(j);
end
if sum(e) > (1-threshold)*E && sum(e) < (1+threshold)*E
break
end
end
end
end