The loop is as follows:
for j = 1:20
sigma = (y<0) - (y>=0);
x0 = x;
out_angle = out_angle - sigma*lut(j);
x = x-(y.*sigma)*poweroftwo;
y = y+(x0.*sigma)*poweroftwo;
poweroftwo = poweroftwo/2;
end
out_angle, x,y and sigma are matrices of dim m*n. lut is an array of size 20. poweroftwo is a scalar with initial value 1. Is it possible to vectorize this code and avoid the for loop?
A lot of informaiton is missing for the vectorization of this loop. Just have a look at the line
out_angle = out_angle - sigma*lut(j);
After vectorization you would like to have an expression similar to
out_angle(j) = out_angle(j-1) - sigma*lut(j);
You immediately see that the current out_angle depends on the previously computed value. This also means that out_angle can only be computed sequentially except if you can
come up with an explicit representation of out_angle.
out_angle(j) = out_angle(j-1) - sigma*lut(j)
= out_angle(j-2) - sigma*lut(j-1) - sigma*lut(j)
= out_angle(j-3) - sigma*lut(j-2) - sigma*lut(j-1) - sigma*lut(j)
= ...
= out_angle(0) - sum_{k = 0}^j (sigma*lut(k))
The thing gets more complicated as sigma also depends on j, i.e. actually you have
sigma(j) and thus
out_angle(j) = out_angle(0) - sum_{k = 0}^j (sigma(k)*lut(k))
Unfortunately you also have only an implicit expression for sigma which you have to
resolve in the same manner. You can probably think a bit about the structure behind sigma. This is a variable, which is 1, where y is negative and -1 where y is positive
or zero, i.e. it is something like
sigma = -mySign(y)
where mySign acts like the sign function but gives 1 for a zero argument.
If you can find an explicit representation for sigma, you can insert it into the explicit representation of out_angle above. After that you can (most likely) vectorize the code.
Related
I want to find the maximum value using the second derivative of the the expression when x is between 0 and 1. In other words I am taking the derivative of cox(x^2) twice to get the second derivative resulting in - 2*sin(x^2) - 4*x^2*cos(x^2), then I want to evaluate this second derivative at x = 0 to x = 1, and display the maximum value of the populated values.
I have:
syms x
f = cos(x^2);
secondD = diff(diff(f));
for i = 0:1
y = max(secondD(i))
end
Can someone help?
You can do it easily by subs and double:
syms x
f = cos(x^2);
secondD = diff(diff(f));
% instead of the for loop
epsilon = 0.01;
specified_range = 0:epsilon:1;
[max_val, max_ind] = max(double(subs(secondD, specified_range)));
Please note that it is a numerical approach to find the maximum and the returned answer is not completely correct all the time. However, by increasing the epsilon, you can expect a better result in general (again in some cases it is not completely correct).
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.
I am trying to apply Newton's method in Matlab, and I wrote a script:
syms f(x)
f(x) = x^2-4
g = diff(f)
x_1=1 %initial point
while f(['x_' num2str(i+1)])<0.001;% tolerance
for i=1:1000 %it should be stopped when tolerance is reached
['x_' num2str(i+1)]=['x_' num2str(i)]-f(['x_' num2str(i)])/g(['x_' num2str(i)])
end
end
I am getting this error:
Error: An array for multiple LHS assignment cannot contain M_STRING.
Newton's Method formula is x_(n+1)= x_n-f(x_n)/df(x_n) that goes until f(x_n) value gets closer to zero.
All of the main pieces are present in the code present. However, there are some problems.
The main problem is assuming string concatenation makes a variable in the workspace; it does not. The primary culprit is this line is this one
['x_' num2str(i+1)]=['x_' num2str(i)]-f(['x_' num2str(i)])/g(['x_' num2str(i)])
['x_' num2str(i+1)] is a string, and the MATLAB language does not support assignment to character arrays (which is my interpretation of An array for multiple LHS assignment cannot contain M_STRING.).
My answer, those others' may vary, would be
Convert the symbolic functions to handles via matlabFunction (since Netwon's Method is almost always a numerical implementation, symbolic functions should be dropper once the result of their usage is completed)
Replace the string creations with a double array for x (much, much cleaner, faster, and overall better code).
Put a if-test with a break in the for-loop versus the current construction.
My suggestions, implemented, would look like this:
syms f(x)
f(x) = x^2-4;
g = diff(f);
f = matlabFunction(f);
g = matlabFunction(g);
nmax = 1000;
tol = 0.001;% tolerance
x = zeros(1, nmax);
x(1) = 1; %initial point
fk = f(x(1));
for k = 1:nmax
if (abs(fk) < tol)
break;
end
x(k+1) = x(k) - f(x(k))/g(x(k));
fk = f(x(k));
end
I have the following problem:
max CEQ(w) s.t. w in (0,1) and I don't know anything about CEQ(w) except that is given by a fixed point equation of the form CEQ(w) = F(CEQ(w)). If I fix a w, I can solve the fixed point equation using the fzero function and obtain a value for CEQ. If I choose a different w, I get another value for CEQ. Thus, I could loop over all possible values of w and then choose the one that gives the highest CEQ. This seems bad programming though and I was wondering whether I can do this more efficient in MATLAB: I want to model the solution to my fixed point equation as a function of w but I don't know how to implement it.
To be more precise, here is a sample code:
clear all
clc
NoDraws = 1000000;
T_hat = 12;
mu = 0.0058;
variance = 0.0017;
rf = 0.0036;
sim_returns(:,T_hat/12) = T_hat*mu + sqrt(T_hat*variance)*randn(NoDraws,1);
A = 5;
kappa=1;
l=0;
theta = 1 - l*(kappa^(1-A) - 1) *(kappa>1);
CEQ_DA_0 = 1.1;
CEQ_opt = -1000;
w_opt = 0;
W_T = #(w) (1-w)*exp(rf*T_hat) + w*exp(rf*T_hat + sim_returns(:,T_hat/12));
for w=0.01:0.01:0.99
W=W_T(w);
fp = #(CEQ) theta*CEQ^(1-A)/(1-A) - mean( W.^(1-A)/(1-A)) + l*mean( ((kappa*CEQ)^(1-A)/(1-A) - W.^(1-A)/(1-A)) .* (W < kappa*CEQ));
CEQ_DA = fzero(fp,CEQ_DA_0);
if CEQ_DA > CEQ_opt
CEQ_opt = CEQ_DA;
w_opt = w;
end
end
That is, in the loop, I fix a w, solve the fixed point equation and store the value for CEQ. If some other w gives a bigger value for CEQ, the current optimal w gets replaced by that new w. what I would like to have (instead of the loop part) is something like this:
fp = #(CEQ,w) theta*CEQ^(1-A)/(1-A) - mean( W_T(w).^(1-A)/(1-A)) + l*mean( ((kappa*CEQ)^(1-A)/(1-A) - W_T(w).^(1-A)/(1-A)) .* (W_T(w) < kappa*CEQ));
CEQ_DA = #(w) fzero(fp,CEQ_DA_0);
[w_opt, fval]=fminbnd(CEQ_DA,0,1);
Your proposed solution is very close. In words, you're defining fp as a function of two arguments, and would like CEQ_DA to be a function of w, which solves fp for CEQ, with that given w. The only issue is that fzero doesn't know which parameter of fp to solve over, because it can't match anonymous function parameters and fp parameters by name.
The answer is yet one more anonymous function inside the fzero, to turn fp(CEP,w) into fp_w(CEP), which will be solveable for CEQ
CEQ_DA = #(w) fzero(#(CEQ) fp(CEQ, w),CEQ_DA_0);
I'm trying to write a Non-Local Means filter for an assignment. I've written the code in two ways, but the method I'd expect to be quicker is much slower than the other method.
Method 1: (This method is slower)
for i = 1:size(I,1)
tic
sprintf('%d/%d',i,size(I,1))
for j = 1:size(I,2)
w = exp((-abs(I-I(i,j))^2)/(h^2));
Z = sum(sum(w));
w = w/Z;
sumV = w .* I;
NL(i,j) = sum(sum(sumV));
end
toc
end
Method 2: (This method is faster)
for i = 1:size(I,1)
tic
sprintf('%d/%d',i,size(I,1))
for j = 1:size(I,2)
Z = 0;
for k = 1:size(I,1)
for l = 1:size(I,2)
w = exp((-abs(I(i,j)-I(k,l))^2)/(h^2));
Z = Z + w;
end
end
sumV = 0;
for k = 1:size(I,1)
for l = 1:size(I,2)
w = exp((-abs(I(i,j)-I(k,l))^2)/(h^2));
w = w/Z;
sumV = sumV + w * I(k,l);
end
end
NL(i,j) = sumV;
end
toc
end
I really thought that MATLAB would be optimized for Matrix operations. Is there reason it isn't in this code? The difference is pretty large. For a 512x512 image, with h = 0.05, one iteration of the outer loop takes 24-28 seconds for Method 1 and 10-12 seconds for Method 2.
The two methods are not doing the same thing. In Method 2, the term abs(I(i,j)-I(k,l)) in the w= expression is being squared, which is fine because the term is just a single numeric value.
However, in Method 1, the term abs(I-I(i,j)) is actually a matrix (The numeric value I(i,j) is being subtracted from every element in the matrix I, returning a matrix again). So, when this term is squared with the ^ operator, matrix multiplication is happening. My guess, based on Method 2, is that this is not what you intended. If instead, you want to square each element in that matrix, then use the .^ operator, as in abs(I-I(i,j)).^2
Matrix multiplication is a much more computation intensive operation, which is likely why Method 1 takes so much longer.
My guess is that you have not preassigned NL, that both methods are in the same function (or are scripts and you didn't clear NL between function runs). This would have slowed the first method by quite a bit.
Try the following: Create a function for both methods. Run each method once. Then use the profiler to see where each function spends most of its time.
A much faster implementation (Vectorized) could be achieved using im2col:
Create a Vector out of each neighborhood.
Using predefined indices calculate the distance between each patch.
Sum over the values and the weights using sum function.
This method will work with no loop at all.