Implementing my own FFT in MATLAB giving wrong results - matlab

I'm trying to implement my own fft in MATLAB the following way:
function z=FastFourierTransform(x)
N=length(x);
if N <= 1
z = x;
else
range = (0:N/2-1);
e = exp(-2i*pi/N).^range;
odd = FastFourierTransform(x(1:2:N-1));
even = e.*FastFourierTransform(x(2:2:N));
z = [even + odd, even - odd];
end
return
Turns out, there seems to be somthing wrong with it since it does not give the same result as the built in function provided by MATLAB.
I'm calling the function the following way:
N = 128;
x = 32*pi*(1:N)'/N;
u = cos(x/16).*(1+sin(x/16));
actualSolution = fft(u);
actualSolution
mySolution = FastFourierTransform(u)';
mySolution
actualSolution
mySolution
The numbers are always the same but they sometimes differ in their sign.

You have swapped odd and even.
Using this line to compute z will produce the correct FFT:
z = [odd + even, odd - even];
My guess is that the source of confusion is that Matlab uses 1-based indices, and the pseudocode you used to implement the function uses 0-based indices.

Related

Metropolis-Hastings in matlab

I am trying to use the Metropolis Hastings algorithm with a random walk sampler to simulate samples from a function $$ in matlab, but something is wrong with my code. The proposal density is the uniform PDF on the ellipse 2s^2 + 3t^2 ≤ 1/4. Can I use the acceptance rejection method to sample from the proposal density?
N=5000;
alpha = #(x1,x2,y1,y2) (min(1,f(y1,y2)/f(x1,x2)));
X = zeros(2,N);
accept = false;
n = 0;
while n < 5000
accept = false;
while ~accept
s = 1-rand*(2);
t = 1-rand*(2);
val = 2*s^2 + 3*t^2;
% check acceptance
accept = val <= 1/4;
end
% and then draw uniformly distributed points checking that u< alpha?
u = rand();
c = u < alpha(X(1,i-1),X(2,i-1),X(1,i-1)+s,X(2,i-1)+t);
X(1,i) = c*s + X(1,i-1);
X(2,i) = c*t + X(2,i-1);
n = n+1;
end
figure;
plot(X(1,:), X(2,:), 'r+');
You may just want to use the native implementation of matlab mhsample.
Regarding your code, there are a few things missing:
- function alpha,
- loop variable i (it might be just n but it is not suited for indexing since it starts at zero).
And you should always allocate memory in matlab if you want to fill it dynamically, i.e. X in your case.
To expand on the suggestions by #max, the code appears to work if you change the i indices to n and replace
n = 0;
with
n = 2;
X(:,1) = [.1,.1];
It would probably be better to assign X(:,1) to random values within your accept region (using the same code you use later), and/or include a burn-in period.
Depending upon what you are going to do with this, it may also make things cleaner to evaluate the argument to sin in the f function to keep it within 0 to 2 pi (likely by shifting the value by 2 pi if it exceeds those bounds)

How to resolve MATLAB trapz function error?

I am working on an assignment that requires me to use the trapz function in MATLAB in order to evaluate an integral. I believe I have written the code correctly, but the program returns answers that are wildly incorrect. I am attempting to find the integral of e^(-x^2) from 0 to 1.
x = linspace(0,1,2000);
y = zeros(1,2000);
for iCnt = 1:2000
y(iCnt) = e.^(-(x(iCnt)^2));
end
a = trapz(y);
disp(a);
This code currently returns
1.4929e+03
What am I doing incorrectly?
You need to just specify also the x values:
x = linspace(0,1,2000);
y = exp(-x.^2);
a = trapz(x,y)
a =
0.7468
More details:
First of all, in MATLAB you can use vectors to avoid for-loops for performing operation on arrays (vectors). So the whole four lines of code
y = zeros(1,2000);
for iCnt = 1:2000
y(iCnt) = exp(-(x(iCnt)^2));
end
will be translated to one line:
y = exp(-x.^2)
You defined x = linspace(0,1,2000) it means that you need to calculate the integral of the given function in range [0 1]. So there is a mistake in the way you calculate y which returns it to be in range [1 2000] and that is why you got the big number as the result.
In addition, in MATLAB you should use exp there is not function as e in MATLAB.
Also, if you plot the function in the range, you will see that the result makes sense because the whole page has an area of 1x1.

Two functions in Matlab to approximate integral - not enough input arguments?

I want to write a function that approximates integrals with the trapezoidal rule.
I first defined a function in one file:
function[y] = integrand(x)
y = x*exp(-x^2); %This will be integrand I want to approximate
end
Then I wrote my function that approximates definite integrals with lower bound a and upper bound b (also in another file):
function [result] = trapez(integrand,a,b,k)
sum = 0;
h = (b-a)/k; %split up the interval in equidistant spaces
for j = 1:k
x_j = a + j*h; %this are the points in the interval
sum = sum + ((x_j - x_(j-1))/2) * (integrand(x_(j-1)) + integrand(x_j));
end
result = sum
end
But when I want to call this function from the command window, using result = trapez(integrand,0,1,10) for example, I always get an error 'not enough input arguments'. I don't know what I'm doing wrong?
There are numerous issues with your code:
x_(j-1) is not defined, and is not really a valid Matlab syntax (assuming you want that to be a variable).
By calling trapez(integrand,0,1,10) you're actually calling integrand function with no input arguments. If you want to pass a handle, use #integrand instead. But in this case there's no need to pass it at all.
You should avoid variable names that coincide with Matlab functions, such as sum. This can easily lead to issues which are difficult to debug, if you also try to use sum as a function.
Here's a working version (note also a better code style):
function res = trapez(a, b, k)
res = 0;
h = (b-a)/k; % split up the interval in equidistant spaces
for j = 1:k
x_j1 = a + (j-1)*h;
x_j = a + j*h; % this are the points in the interval
res = res+ ((x_j - x_j1)/2) * (integrand(x_j1) + integrand(x_j));
end
end
function y = integrand(x)
y = x*exp(-x^2); % This will be integrand I want to approximate
end
And the way to call it is: result = trapez(0, 1, 10);
Your integrandfunction requires an input argument x, which you are not supplying in your command line function call

Why is this for loop giving me an error?

So I am trying to go through a for loop that will increment .1 every time and will do this until the another variable h is less than or equal to zero. Then I am suppose to graph this h variable along another variable x. The code that I wrote looks like this:
O = 20;
v = 200;
g = 32.2;
for t = 0:.1:12
% Calculate the height
h(t) = (v)*(t)*(sin(O))-(1/2)*(g)*(t^2);
% Calculate the horizontal location
x(t) = (v)*(t)*cos(O);
if t > 0 && h <= 0
break
end
end
The Error that I keep getting when running this code says "Attempted to access h(0); index must be a positive integer or logical." I don't understand what exactly is going on in order for this to happen. So my question is why is this happening and is there a way I can solve it, Thank you in advance.
You're using t as your loop variable as well as your indexing variable. This doesn't work, because you'll try to access h(0), h(0.1), h(0.2), etc, which doesn't make sense. As the error says, you can only access variables using integers. You could replace your code with the following:
t = 0:0.1:12;
for i = 1:length(t)
% use t(i) instead of t now
end
I will also point out that you don't need to use a for loop to do this. MATLAB is optimised for acting on matrices (and vectors), and will in general run faster on vectorised functions rather than for loops. For instance, your equation for h could be replaced with the following:
O = 20;
v = 200;
g = 32.2;
t = 0:0.1:12;
h = v * t * sin(O) - 0.5 * g * t.^2;
The only difference is that you have to use the element-wise square (.^2) rather than the normal square (^2). This means that MATLAB will square each element of the vector t, rather than multiplying the vector t by itself.
In short:
As the error says, t needs to be an integer or logical.
But your t is t=0:0.1:12, therefore a decimal value.
O = 20;
v = 200;
g = 32.2;
for t = 0:.1:12
% Calculate the height
idx_t = 1:numel(t);
h(idx_t) = (v)*(t)*(sin(O))-(1/2)*(g)*(t^2);
% Calculate the horizontal location
x(idx_t) = (v)*(t)*cos(O);
if t > 0 && h <= 0
break
end
end
Look this question's answer for more options: Subscript indices must either be real positive integers or logical error

Compute the convolution of two arrays in MATLAB

I am trying to generate an array from some starting values using this formula in MATLAB:
yt = a0 + ∑i=1p (ai ⋅ yt-i), t ≥ p
p is some small number compared to T (max t). I have been able to make this using two for cycles but it is really slow. Is there some easy way to do it?
First p values of y are provided and vector a (its length is p+1) is provided too...
This is what I have so far, but now when I tried it, it doesn't work 100% (I think it's because of indexing from 1 in MATLAB):
y1 = zeros(T+1, 1);
y1(1:p) = y(1:p);
for t = p+1:T+1
value = a1(1);
for j = 2:p+1
value = value + a1(j)*y1(t-j+1);
end
y1(t) = value;
end
EDIT: I solved it, I am just not used to Matlab indexing from 1...
This statement
if(p>=t)
looks odd inside a loop whose index expression is
for t = p+1:T+1
which seems to guarantee that t>p for the entire duration of the loop. Is that what you meant to write ?
EDIT in response to comment
Inside a loop indexed with this statement
for j = 2:p
how does the reference you make to a(j) ever call for a(0) ?
y1 = zeros(T+1, 1);
y1(1:p) = y(1:p);
for t = p+1:T+1
value = a1(1);
for j = 2:p+1
value = value + a1(j)*y1(t-j+1);
end
y1(t) = value;
end