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
Related
I'm having trouble with implementing double integral in Matlab.
Unlike other double integrals, I need the result of the first (inside) integral to be an expression of the second variable, before going through the second (outside) integral, as it must be powered by k.
For example:
In the example above, I need the result of the inside integral to be expressed as 2y, so that I can calculate (2y)^k, before doing the second (outside) integral.
Does anyone know how to do this in Matlab?
I don't like doing things symbolically, because 99.9% of all problems don't have a closed form solution at all. For 99.9% of the problems that do have a closed-form solution, that solution is unwieldy and hardly useful at all. That may be because of my specific discipline, but I'm going to assume that your problem falls in one of those 99.9% sets, so I'll present the most obvious numerical way to do this.
And that is, integrate a function which calls integral itself:
function dbl_int()
f = #(x,y) 2.*x.*y + 1;
k = 1;
x_limits = [0 1];
y_limits = [1 2];
val = integral(#(y) integrand(f, y, k, x_limits), ...
y_limits(1), y_limits(2));
end
function val = integrand(f, y, k, x_limits)
val = zeros(size(y));
for ii = 1:numel(y)
val(ii) = integral(#(x) f(x,y(ii)), ...
x_limits(1), x_limits(2));
end
val = val.^k;
end
When I type help gmres in MATLAB I get the following example:
n = 21; A = gallery('wilk',n); b = sum(A,2);
tol = 1e-12; maxit = 15;
x1 = gmres(#(x)afun(x,n),b,10,tol,maxit,#(x)mfun(x,n));
where the two functions are:
function y = afun(x,n)
y = [0; x(1:n-1)] + [((n-1)/2:-1:0)'; (1:(n-1)/2)'].*x+[x(2:n); 0];
end
and
function y = mfun(r,n)
y = r ./ [((n-1)/2:-1:1)'; 1; (1:(n-1)/2)'];
end
I tested it and it works great. My question is in both those functions what is the value for x since we never give it one?
Also shouldn't the call to gmres be written like this: (y in the #handle)
x1 = gmres(#(y)afun(x,n),b,10,tol,maxit,#(y)mfun(x,n));
Function handles are one way to parametrize functions in MATLAB. From the documentation page, we find the following example:
b = 2;
c = 3.5;
cubicpoly = #(x) x^3 + b*x + c;
x = fzero(cubicpoly,0)
which results in:
x =
-1.0945
So what's happening here? fzero is a so-called function function, that takes function handles as inputs, and performs operations on them -- in this case, finds the root of the given function. Practically, this means that fzero decides which values for the input argument x to cubicpoly to try in order to find the root. This means the user just provides a function - no need to give the inputs - and fzero will query the function with different values for x to eventually find the root.
The function you ask about, gmres, operates in a similar manner. What this means is that you merely need to provide a function that takes an appropriate number of input arguments, and gmres will take care of calling it with appropriate inputs to produce its output.
Finally, let's consider your suggestion of calling gmres as follows:
x1 = gmres(#(y)afun(x,n),b,10,tol,maxit,#(y)mfun(x,n));
This might work, or then again it might not -- it depends whether you have a variable called x in the workspace of the function eventually calling either afun or mfun. Notice that now the function handles take one input, y, but its value is nowhere used in the expression of the function defined. This means it will not have any effect on the output.
Consider the following example to illustrate what happens:
f = #(y)2*x+1; % define a function handle
f(1) % error! Undefined function or variable 'x'!
% the following this works, and g will now use x from the workspace
x = 42;
g = #(y)2*x+1; % define a function handle that knows about x
g(1)
g(2)
g(3) % ...but the result will be independent of y as it's not used.
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.
We have an equation similar to the Fredholm integral equation of second kind.
To solve this equation we have been given an iterative solution that is guaranteed to converge for our specific equation. Now our only problem consists in implementing this iterative prodedure in MATLAB.
For now, the problematic part of our code looks like this:
function delta = delta(x,a,P,H,E,c,c0,w)
delt = #(x)delta_a(x,a,P,H,E,c0,w);
for i=1:500
delt = #(x)delt(x) - 1/E.*integral(#(xi)((c(1)-c(2)*delt(xi))*ms(xi,x,a,P,H,w)),0,a-0.001);
end
delta=delt;
end
delta_a is a function of x, and represent the initial value of the iteration. ms is a function of x and xi.
As you might see we want delt to depend on both x (before the integral) and xi (inside of the integral) in the iteration. Unfortunately this way of writing the code (with the function handle) does not give us a numerical value, as we wish. We can't either write delt as two different functions, one of x and one of xi, since xi is not defined (until integral defines it). So, how can we make sure that delt depends on xi inside of the integral, and still get a numerical value out of the iteration?
Do any of you have any suggestions to how we might solve this?
Using numerical integration
Explanation of the input parameters: x is a vector of numerical values, all the rest are constants. A problem with my code is that the input parameter x is not being used (I guess this means that x is being treated as a symbol).
It looks like you can do a nesting of anonymous functions in MATLAB:
f =
#(x)2*x
>> ff = #(x) f(f(x))
ff =
#(x)f(f(x))
>> ff(2)
ans =
8
>> f = ff;
>> f(2)
ans =
8
Also it is possible to rebind the pointers to the functions.
Thus, you can set up your iteration like
delta_old = #(x) delta_a(x)
for i=1:500
delta_new = #(x) delta_old(x) - integral(#(xi),delta_old(xi))
delta_old = delta_new
end
plus the inclusion of your parameters...
You may want to consider to solve a discretized version of your problem.
Let K be the matrix which discretizes your Fredholm kernel k(t,s), e.g.
K(i,j) = int_a^b K(x_i, s) l_j(s) ds
where l_j(s) is, for instance, the j-th lagrange interpolant associated to the interpolation nodes (x_i) = x_1,x_2,...,x_n.
Then, solving your Picard iterations is as simple as doing
phi_n+1 = f + K*phi_n
i.e.
for i = 1:N
phi = f + K*phi
end
where phi_n and f are the nodal values of phi and f on the (x_i).
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.