【问题标题】:How to iterate over functions?如何迭代函数?
【发布时间】:2017-05-28 21:39:50
【问题描述】:

我想对一个函数应用循环。我有以下“母亲”代码:

v = 1;
fun = @root;
x0 = [0,0]
options = optimset('MaxFunEvals',100000,'MaxIter', 10000 );
x = fsolve(fun,x0, options)

另外,我在一个单独的文件中有以下函数:

function D = root(x)
 v = 1;
 D(1) = x(1) + x(2) + v - 2;
 D(2) = x(1) - x(2) + v - 1.8;
end

现在,我想在v = sort(rand(1,1000)) 时找到根。换句话说,我想为v 的每个值迭代函数。

【问题讨论】:

  • ...你知道这些是线性方程,对吧?你不需要fsolve 来解决这些问题,事实上,这会很慢而且很可能不准确......root 是一个例子,还是你的 real 函数来解决?

标签: matlab function for-loop iteration


【解决方案1】:

以防万一该方程式是您的实际方程式(而不是虚拟示例):该方程式是线性,这意味着您可以解决所有v用一个简单的mldivide

v = sort(rand(1,1000));
x = [1 1; 1 -1] \ bsxfun(@plus, -v, [2; 1.8])

而且,如果这些不是你的实际方程,你不需要循环,你可以向量化整个事情:

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

这可能会也可能不会比循环更快,这取决于您的实际方程式。

它可能会更慢,因为fsolve 需要计算 2000×2000(4M 元素)的雅可比行列式,而不是 2×2、1000 次(4k 元素)。

但是,它可能会更快,因为fsolve 的启动成本可能很大,这意味着许多调用的开销实际上可能超过计算更大的雅可比行列式的成本。

无论如何,提供雅可比矩阵作为第二个输出将大大加快一切:

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

【讨论】:

    【解决方案2】:
    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
    

    带函数定义:

    function D = root(v, x)
     D(1) = x(1) + x(2) + v - 2;
     D(2) = x(1) - x(2) + v - 1.8;
    end
    

    【讨论】:

      【解决方案3】:

      您将需要修改 root 以接受附加变量 (v),然后将函数句柄更改为 root 为匿名函数,该函数提供您想要的 v

      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))
      

      【讨论】:

        猜你喜欢
        • 2011-02-24
        • 2020-07-04
        • 2021-10-28
        • 2021-12-09
        • 2022-01-12
        • 2010-12-14
        • 1970-01-01
        • 2018-09-12
        相关资源
        最近更新 更多