Help me make this small inner loop faster - more efficient notation or functions?

I have some code which runs this inner loop a LOT of times for different values of Ri and Ii:
z = complex(Ri,Ii);
for (k=1:50)
e1 = eval(formula);
e2 = eval(derivative);
z = z - e1/e2 / (1 - (e1*eval(derivative2))/(2*power(e2,2.0)));
g = power(real(z),2)+power(imag(z),2);
if (k>1 && abs(g-gprev)<epsilon)
break;
end
gprev = g;
end
Formula is a string expression involving "z" (input by user at run-time, so can't be hardcoded) and derivative is it's symbolic derivative. I know eval() is supposed to be subs() but that seems to make it way slower. Is there anything I should be doing in terms of choosing better functions or notation that would help speed this up?

 Accepted Answer

Using eval is not only not necessary, it will cause problems.
I would do something like this instead:
z = complex(rand,rand);
Deriv = @(f,x) (f(x+1E-8)-f(x))/1E-8;
Formula_str = 'exp(-x)*cos(x)';
Formula = str2func(['@(x) ' vectorize(Formula_str)]);
Derivative = Deriv(Formula,z);
e1 = Formula(z);
e2 = Derivative;
Use the str2func function to create an executable anonymous functon from the input string. The ‘Deriv’ function is a reliable way of calculating derivatives of anonymous functions.
This has the advantage of running correctly, and avoids the Symbolic Math Toolbox that is likely not necessary here. It is also likely faster, although I didn’t time it.

4 Comments

Aha! Thanks. Question: can
Formula = str2func(['@(x) ' vectorize(Formula_str)]);
be put outside the loop? The creation of the function doesn't need to happen inside, right - can be done just once? The next line,
Derivative = Deriv(Formula,z);
is real calculations with current value of z (not symbolic) so needs to be inside the loop?
My pleasure!
This assignment:
Formula = str2func(['@(x) ' vectorize(Formula_str)]);
should be put before the loop (obviously after the inputdlg or input statement that creates what I call ‘Function_str’), unless the inputdlg or input call occurs within the loop. It creates the anonymous function ‘Formula’ that can be used anywhere after that.
This assignment:
Derivative = Deriv(Formula,z);
belongs wherever ‘Formula’ and the current value of ‘z’ both exist together, since it specifically calculaltes the value of the derivative at ‘z’.
.
Ok this works great. 2 remaining problems:
1) the 2nd derivative:
z=complex(rand,rand);
Deriv = @(f,z) (f(z+1E-8)-f(z))/1E-8;
Formula_str='cos(z)';
FormulaF = str2func(['@(z) ' vectorize(Formula_str)]);
Derivative=Deriv(FormulaF,z);
Derivative2=Deriv(Deriv(FormulaF,z),z);
gives
Array indices must be positive integers or logical values.
Error in test>@(f,z)(f(z+1E-8)-f(z))/1E-8 (line 3)
Deriv = @(f,z) (f(z+1E-8)-f(z))/1E-8;
Error in test (line 7)
Derivative2=Deriv(Deriv(FormulaF,z),z);
I'm doing something wrong with the notation. How would you do the 2nd derivative?
2) my function also has a parameter 't': for example,
sin(z)+z*t+1
the derivative will be taken with respect to z, but t has to remain in the function. It's choking when I add the t to the function string because it says "undefined function or variable 't'. Using this notation, where would I add it? I did this:
z = complex(rand,rand);
t = complex(rand,rand);
Deriv = @(f,z) (f(z+1E-8,t)-f(z,t))/1E-8;
Formula_str = 'cos(z)+t';
Formula = str2func(['@(z,t) ' vectorize(Formula_str)]);
Derivative = Deriv(Formula,z);
e1 = Formula(z,t);
e2 = Derivative
and it seems to work; am I missing anything?
thanks!!
How would you do the 2nd derivative?
I didn’t realise you want it as well. It’s different:
Deriv2 = @(f,x) (f(x+1E-6) - 2*f(x) + f(x-1E-6))/1E-12;
and changing ‘Deriv’ to a central difference as well:
Deriv = @(f,x) (f(x+1E-6)-f(x-1E-6))/2E-6;
I’m slightly lost with respect to what you are doing.
Try this:
z = complex(rand,rand);
t = complex(rand,rand);
Deriv = @(f,x) (f(x+1E-6,t)-f(x-1E-6,t))/2E-6;
Deriv2 = @(f,x) (f(x+1E-6,t) - 2*f(x,t) + f(x-1E-6,t))/1E-12;
Formula_str = 'cos(z)+t';
Formula = str2func(['@(z,t) ' vectorize(Formula_str)]);
Derivative = Deriv(Formula,z);
Derivative2 = Deriv2(Formula,z);
e1 = Formula(z,t);
e2 = Derivative;
e3 = Derivative2
That runs without error.

Sign in to comment.

More Answers (0)

Categories

Find more on Function Creation in Help Center and File Exchange

Products

Release

R2018b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!