Right, I'm really pretty new to the concept of vectorization but I'm trying to get head round it. Currently, I'm trying to adapt some of the code that I wrote to implement canny edge detection into a vectorized form and what I don't understand is why this:
for r=1:fsize
for c=1:fsize
mask(r,c) = mask(r,c)/Z;
end
end
produces a different result to this:
mask(r:fsize,c:fsize) = mask(r:fsize,c:fsize)/Z;
When my understanding is that they should do the same thing?
What is r, what is c in the second solution? Probably you need element-wise division ./:
mask = mask./Z;
If this does not solve your problem, please provide input data to reproduce.
for r=1:fsize
for c=1:fsize
mask(r,c) = mask(r,c)/Z;
end
end
Is equivalent to
mask(1:fsize, 1:fsize) = mask(1:fsize, 1:fsize) / Z;
Note - 1:fsize not c:fsize.
This is assuming that Z is a constant. It would be marginally faster to do * (1 / Z) - doing the division just once, and then multiplying...
Related
I'd like to declare first of all, that I'm a mathematician. This might be a stupid stupid question; but I've gone through all the matlab tutorials--they've gotten me nowhere. I imagine I could code this in C (it'd be exhausting); but I need matlab for this particular function. And I don't get exactly how to do it.
Here is the pasted Matlab code of where I'm running into trouble:
function y = TAU(z,n)
y=0;
for i =[1,n]
y(z) = log(beta(z+1,i) + y(z+1)) - beta(z,i);
end
end
(beta is an arbitrary "float" to "float" function with an index i.)
I'm having trouble declaring y as a function, in which we call the function at a different argument. I want to define y_n(z) with something something y_{n-1}(z+1). This is all done in a recursive process to create the function. I really feel like I'm missing something stupid.
As a default function it assigns y to be an array (or whatever you call the default index assignment). But I don't want an array. I want y to be assigned as a "function" class (i.e. takes "float" to "float"). And then I'm defining a sequence of y_n : "float" to "float". So that z to z+1 is a map on "float" to "float".
I don't know if I'm asking too much of matlab...
Help a poor mathematician who hasn't coded since the glory days of X-box mods.
...Please don't tell me I have to go back to Pari-GP/C drawing boards over something so stupid.
Please help!
EDIT: At rahnema1 & mimocha's request, I'll describe the math, and of what I am trying to do with my program. I can't see how to implement latex in here. So I'll write the latex code in a generator and upload a picture. I'm not so sure if there even is a work around to what I want to do.
As to the expected output. We'd want,
beta(z+1,i) + TAU(z+1,i) = exp(beta(z,i) + TAU(z,i+1))
And we want to grow i to a fixed value n. Again, I haven't programmed in forever, so I apologize if I'm speaking a little nonsensically.
EDIT2:
So, as #rahnema1 suggests; I should produce a reproducible example. In order to do this, I'll write the code for my beta function. It's surprisingly simple. This is for the case where the "multiplier" variable is set to log(2); but you don't need to worry about any of that.
function f = beta(z,n)
f=0;
for i = 0:n-1
f = exp(f)/(1+exp(log(2)*(n-i-z)));
end
end
This will work fine for z a float no greater than 4. Once you make z larger it'll start to overflow. So for example, if you put in,
beta(2,100)
1.4242
beta(3,100)
3.3235
beta(3,100) - exp(beta(2,100))/(1/4+1)
0
The significance of the 100, is simply how many iterations we perform; it converges fast so even setting this to 15 or so will still produce the same numerical accuracy. Now, the expected output I want for TAU is pretty straight forward,
TAU(z,1) = log(beta(z+1,1)) - beta(z,1)
TAU(z,2) = log(beta(z+1,2) + TAU(z+1,1)) - beta(z,2)
TAU(z,3) = log(beta(z+1,3) + TAU(z+1,2)) - beta(z,3)
...
TAU(z,n) = log(beta(z+1,n) + TAU(z+1,n-1)) -beta(z,n)
I hope this helps. I feel like there should be an easy way to program this sequence, and I must be missing something obvious; but maybe it's just not possible in Matlab.
At mimocha's suggestion, I'll look into tail-end recursion. I hope to god I don't have to go back to Pari-gp; but it looks like I may have to. Not looking forward to doing a deep dive on that language, lol.
Thanks, again!
Is this what you are looking for?
function out = tau(z,n)
% Ends recursion when n == 1
if n == 1
out = log(beta(z+1,1)) - beta(z,1);
return
end
out = log(beta(z+1,n) + tau(z+1,n-1)) - beta(z,n);
end
function f = beta(z,n)
f = 0;
for i = 0:n-1
f = exp(f) / (1 + exp(log(2)*(n-i-z)));
end
end
This is basically your code from the most recent edit, but I've added a simple catch in the tau function. I tried running your code and noticed that n gets decremented infinitely (no exit condition).
With the modification, the code runs successfully on my laptop for smaller integer values of n, where 1e5 > n >= 1; and for floating values of z, real and complex. So the code will unfortunately break for floating values of n, since I don't know what values to return for, say, tau(1,0) or tau(1,0.9). This should easily be fixable if you know the math though.
However, many of the values I get are NaNs or Infs. So I'm not sure if your original problem was Out of memory error (infinite recursion), or values blowing up to infinity / NaN (numerical stability issue).
Here is a quick 100x100 grid calculation I made with this code.
Then I tested on negative values of z, and found the imaginary part of the output to looks kinda cool.
Not to mention I'm slightly geeking out over the fact that pi is showing up in the imaginary part as well :)
tau(-0.3,2) == -1.45179335740446147085 +3.14159265358979311600i
Incredibly simple question, but I think I'm unable to come up with the correct terminology to google search it.
If I have a snippet of code that relies on three independent variables:
code(x,y,z)
That produces two values, i.e.:
output1, output2
How do I go about iterating like so (pseudocode):
for x
for y
for z
code(x,y,z)
end
end
end
And have data I can parse to generate 3D graphs such as
surf(x,y,output1)
A naive solution I came up with was just to create a bin of n length and then iterating one variable n times to come up with a 2D graph, i.e:
x_axis = zeros(1,25)
for m = 1:25
xm = x + 1
x_axis(m) = xm
code(x,y,z)
Even a referral to some documentation would be extremely helpful.
Thanks!
Brute force approach:
for x=[1:50]
for y=[1:50]
for z=[1:50]
result(y,x,z)=code(x,y,z);
end
end
end
More paradigmatic approach (in MATLAB) is to meshgrid it, and pump those in.
[XX,YY,ZZ]=meshgrid([1:50],[1:50],[1:50]);
result=code(XX,YY,ZZ);
this is likely a few lines of code but I cannot figure it out...
I need to perform a convolution operation of experimental data with an analytical function which is singular at the beginning of the integration range. So if I use "conv" it won't work...
I have two experimental vectors, phi(time) and time
then want to calculate T(t)
T = \int_{0}^{t}\phi \left ( t-\tau \right )\frac{\textup{d}\tau}{\tau ^{1/2}}
So the the singularity at tau = 0 makes "conv" not work. I've been fiddling with anonymous functions and using quadgk to handle the singularity and the like, but can't make anything work. I would have bet anything that this is a solved problem but can't find anything like it. Any help is very much appreciated.
EDIT: solved it this way:
function T = TCalc(time, power)
warning off MATLAB:quadgk:NonFiniteValue %suppress warning at the zero point
T=zeros(size(time));
for par = 1:numel(time)
T(par) = s1(time(par));
end
function y = r1(t)
y = interp1q(time,power,t');%notice that t is transposed! to make interp1q work.
y = y';
end
function y = s1(tfin)
y = quadgk(#(t) (r1(tfin-t))./t.^(0.5),0,tfin,'RelTol',1.e-2);
end
end
I guess, the inelegant trick here is to make Matlab think the experimental data is an analytical function by passing through interp1, and using quadgk to tolerate a singularity at the limit of integration. About one second for 1000-point vectors. Ignoring or setting the tau = 0 point to a small value doesn't work, it still perceives a singularity and the result is wrong.
After having learned basic programming in Java, I have found that the most difficult part of transitioning to MatLab for my current algorithm course, is to avoid loops. I know that there are plenty of smart ways to vectorize operations in MatLab, but my mind is so "stuck" in loop-thinking, that I am finding it hard to intuitively see how I may vectorize code. Once I am shown how it can be done, it makes sense to me, but I just don't see it that easily myself. Currently I have the following code for finding the barycentric weights used in Lagrangian interpolation:
function w = barycentric_weights(x);
% The function is used to find the weights of the
% barycentric formula based on a given grid as input.
n = length(x);
w = zeros(1,n);
% Calculating the weights
for i = 1:n
prod = 1;
for j = 1:n
if i ~= j
prod = prod*(x(i) - x(j));
end
end
w(i) = prod;
end
w = 1./w;
I am pretty sure there must be a smarter way to do this in MatLab, but I just can't think of it. If anyone has any tips I will be very grateful :). And the only way I'll ever learn all the vectorizing tricks in MatLab is to see how they are used in various scenarios such as above.
One has to be creative in matlab to avoid for loop:
[X,Y] =meshgrid(x,x)
Z = X - Y
w =1./prod(Z+eye(length(x)))
Kristian, there are a lot of ways to vectorize code. You've already gotten two. (And I agree with shakinfree: you should always consider 1) how long it takes to run in non-vectorized form (so you'll have an idea of how much time you might save by vectorizing); 2) how long it might take you to vectorize (so you'll have a better sense of whether or not it's worth your time; 3) how many times you will call it (again: is it worth doing); and 3) readability. As shakinfree suggests, you don't want to come back to your code a year from now and scratch your head about what you've implemented. At least make sure you've commented well.
But at a meta-level, when you decide that you need to improve runtime performance by vectorizing, first start with small (3x1 ?) array and make sure you understand exactly what's happening for each iteration. Then, spend some time reading this document, and following relevant links:
http://www.mathworks.com/help/releases/R2012b/symbolic/code-performance.html
It will help you determine when and how to vectorize.
Happy MATLABbing!
Brett
I can see the appeal of vectorization, but I often ask myself how much time it actually saves when I go back to the code a month later and have to decipher all that repmat gibberish. I think your current code is clean and clear and I wouldn't mess with it unless performance is really critical. But to answer your question here is my best effort:
function w = barycentric_weights_vectorized(x)
n = length(x);
w = 1./prod(eye(n) + repmat(x,n,1) - repmat(x',1,n),1);
end
Hope that helps!
And I am assuming x is a row vector here.
I have been looking at this code for a while now, and cannot figure out why matlab is not calculating correctly. Does anyone see anything that I may be doing wrong with this code?
((1-EU_P2par3(:,1))*US_P2par3(:,1))+((1-EU_P2par3(:,2))*US_P2par3(:,2))+((1-EU_P2par3(:,3))*US_P2par3(:,3))+((1-EU_P2par3(:,4))*US_P2par3(:,4))+((1-EU_P2par3(:,5))*US_P2par3(:,5))+((1-EU_P2par3(:,6)*US_P2par3(:,6)))+((1-EU_P2par3(:,7))*US_P2par3(:,7))
Thanks for all the help!
In cases like this, good code formatting is your friend. Using an ellipsis (i.e. ..., the line continuation symbol) to create a multi-line statement can help greatly...
It looks like you have a parenthesis in the wrong place. Your code looks like this:
result = ((1-EU_P2par3(:,1))*US_P2par3(:,1))+...
((1-EU_P2par3(:,2))*US_P2par3(:,2))+...
((1-EU_P2par3(:,3))*US_P2par3(:,3))+...
((1-EU_P2par3(:,4))*US_P2par3(:,4))+...
((1-EU_P2par3(:,5))*US_P2par3(:,5))+...
((1-EU_P2par3(:,6)*US_P2par3(:,6)))+... %# Notice something here?
((1-EU_P2par3(:,7))*US_P2par3(:,7));
And you probably want this:
result = ((1-EU_P2par3(:,1))*US_P2par3(:,1))+...
((1-EU_P2par3(:,2))*US_P2par3(:,2))+...
((1-EU_P2par3(:,3))*US_P2par3(:,3))+...
((1-EU_P2par3(:,4))*US_P2par3(:,4))+...
((1-EU_P2par3(:,5))*US_P2par3(:,5))+...
((1-EU_P2par3(:,6))*US_P2par3(:,6))+... %# Notice the change?
((1-EU_P2par3(:,7))*US_P2par3(:,7));
EDIT:
In addition, as Darren mentions in his answer, you will likely have to use the element-wise multiplication operator .* instead of the matrix multiplication operator *. Explanations of the arithmetic operators can be found here.
Also, your calculation can be greatly simplified by vectorizing it using the function SUM, like so:
result = sum((1-EU_P2par3(:,1:7)).*US_P2par3(:,1:7),2);
Try the following example.
xy = rand(10,2);
a = xy(:,1)*xy(:,2);
% ??? Error using ==> mtimes
% Inner matrix dimensions must agree.
a = xy(:,1).*xy(:,2);
The error arises when you attempt to multiply vectors together. You must use the .* operator to get element-wise multiplication
Hope that helps