简体   繁体   English

在 Matlab 或 Octave 中使用 fzero,避免 for 循环和复杂的解决方案

[英]Using fzero in Matlab or Octave, avoiding for loop and complex solutions

I'm using fzero function to solve a non-linear equation depending on one parameter and I'm not satisfied with my method.我正在使用 fzero 函数根据一个参数求解非线性方程,但我对我的方法不满意。 I have these issues:我有这些问题:

1) Can for loop for the parameter be avoided ? 1) 可以避免参数的 for 循环吗?

2) In order to avoid complex solutions I first have to pre-compute valid interval for fzero. 2)为了避免复杂的解决方案,我首先必须预先计算 fzero 的有效间隔。 Is there is a better solution here ?这里有更好的解决方案吗?

If I reduce the parameter step size the execution time becomes slow.如果我减小参数步长,执行时间就会变慢。 If I don't pre-compute the interval I get an error "Function values at interval endpoints must be finite and real."如果我不预先计算间隔,我会收到错误消息“间隔端点处的函数值必须是有限且真实的”。 in Matlab and "fzero: not a valid initial bracketing" in Octave.在 Matlab 和 Octave 中的“fzero:不是有效的初始括号”。

Here is the code这是代码

% solve y = 90-asind(n*(sind(90-asind(sind(a0)/n)-y)))

% set the equation paramaters
n=1.48; a0=0:0.1:60;

% loop over a0
for i = 1:size(a0,2)

  % for each a0 find where the argument of outer asind() 
  % will not give complex solutions, i.e. argument is between 1 and -1 

  fun1 = @(y) n*(sind(90-asind(sind(a0(i))/n)-y))-0.999;
  y1 = fzero(fun1,[0 90]);  
  fun2 = @(y) n*(sind(90-asind(sind(a0(i))/n)-y))+0.999;
  y2 = fzero(fun2,[0 90]);


  % use y1, y2 as limits in fzero interval

  fun3 = @(y) 90-asind(n*(sind(90-asind(sind(a0(i))/n)-y)))-y;
  y(i) = fzero(fun3, [y1 y2]);

end

% plot the result
figure; plot(y); grid minor;
xlabel('Incident ray angle [Deg]');
ylabel('Lens surface tangent angle');

With Matlab, I obtained the plot below with the following simplified loop.使用 Matlab,我通过以下简化循环获得了下面的图。

for i = 1:size(a0,2)
  fun3 = @(y) sind(90-y) - n*(sind(90-asind(sind(a0(i))/n)-y));
  y(i) = fzero(fun3, [0,90]);
end

The difference is in the form of equation: I replaced 90-y = asind(something) with sin(90-y) = something.区别在于等式的形式:我用 sin(90-y) = something 替换了 90-y = asind(something)。 When "something" is greater than 1 in absolute value, the former version throws an error due to complex value of asind.当“something”的绝对值大于1时,由于asind的复数值,前一个版本会抛出错误。 The latter proceeds normally, recognizing that this is not a solution (sin(90-y) can't be equal to something that is greater than 1).后者正常进行,认识到这不是一个解(sin(90-y) 不能等于大于 1 的值)。

No precomputing of the bracket was necessary, [0,90] simply worked.不需要对括号进行预计算,[0,90] 简单有效。 Another change I made was in the plot: plot(a0,y) instead of plot(y) , to get the correct horizontal axis.我所做的另一个更改是在绘图中: plot(a0,y)而不是plot(y) ,以获得正确的水平轴。

And you can't avoid for loop here, nor should you worry about it.并且您无法避免这里的for循环,您也不应该担心它。 Vectorization means eliminating loops where the content is a low-level operation that can be done en masse by operating on some C array.矢量化装置消除了环路,其中内容是可以由在一些C阵列操作来完成集体一个低级操作。 But fzero is totally not that.fzero完全不是那样。 If the code takes long to run, it's because solving a bunch of equations takes long, not because there's a for loop.如果代码需要很长时间才能运行,那是因为求解一堆方程需要很长时间,而不是因为存在for循环。

阴谋

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM