问题
I would like to apply loop over a function. I have the following "mother" code:
v = 1;
fun = @root;
x0 = [0,0]
options = optimset('MaxFunEvals',100000,'MaxIter', 10000 );
x = fsolve(fun,x0, options)
In addition, I have the following function in a separate file:
function D = root(x)
v = 1;
D(1) = x(1) + x(2) + v - 2;
D(2) = x(1) - x(2) + v - 1.8;
end
Now, I would like to find roots when v = sort(rand(1,1000)). In other words, I would like to iterate over function for each values of v.
回答1:
You will need to modify root to accept an additional variable (v) and then change the function handle to root to an anonymous function which feeds in the v that you want
function D = root(x, v)
D(1) = x(1) + x(2) + v - 2;
D(2) = x(1) - x(2) + v - 1.8;
end
% Creates a function handle to root using a specific value of v
fun = @(x)root(x, v(k))
回答2:
Just in case that equation is your actual equation (and not a dummy example): that equation is linear, meaning, you can solve it for all v with a simple mldivide:
v = sort(rand(1,1000));
x = [1 1; 1 -1] \ bsxfun(@plus, -v, [2; 1.8])
And, in case those are not your actual equations, you don't need to loop, you can vectorize the whole thing:
function x = solver()
options = optimset('Display' , 'off',...
'MaxFunEvals', 1e5,...
'MaxIter' , 1e4);
v = sort(rand(1, 1000));
x0 = repmat([0 0], numel(v), 1);
x = fsolve(@(x)root(x,v'), x0, options);
end
function D = root(x,v)
D = [x(:,1) + x(:,2) + v - 2
x(:,1) - x(:,2) + v - 1.8];
end
This may or may not be faster than looping, it depends on your actual equations.
It may be slower because fsolve will need to compute a Jacobian of 2000×2000 (4M elements), instead of 2×2, 1000 times (4k elements).
But, it may be faster because the startup cost of fsolve can be large, meaning, the overhead of many calls may in fact outweigh the cost of computing the larger Jacobian.
In any case, providing the Jacobian as a second output will speed everything up rather enormously:
function solver()
options = optimset('Display' , 'off',...
'MaxFunEvals', 1e5,...
'MaxIter' , 1e4,...
'Jacobian' , 'on');
v = sort(rand(1, 1000));
x0 = repmat([1 1], numel(v), 1);
x = fsolve(@(x)root(x,v'), x0, options);
end
function [D, J] = root(x,v)
% Jacobian is constant:
persistent J_out
if isempty(J_out)
one = speye(numel(v));
J_out = [+one +one
+one -one];
end
% Function values at x
D = [x(:,1) + x(:,2) + v - 2
x(:,1) - x(:,2) + v - 1.8];
% Jacobian at x:
J = J_out;
end
回答3:
vvec = sort(rand(1,2));
x0 = [0,0];
for v = vvec,
fun = @(x) root(v, x);
options = optimset('MaxFunEvals',100000,'MaxIter', 10000 );
x = fsolve(fun, x0, options);
end
with function definition:
function D = root(v, x)
D(1) = x(1) + x(2) + v - 2;
D(2) = x(1) - x(2) + v - 1.8;
end
来源:https://stackoverflow.com/questions/41635918/how-to-iterate-over-functions