How to iterate over functions?

南笙酒味 提交于 2020-01-06 21:23:48

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!