TomasVercettiЦитата: В 5-7 версиях вложенные функции типа FindRoot[NIntegrate[]] могли выдавать ошибки (а могли и нет) типа NIntegrate::inumr, которые связаны с тем, что внутренняя функция рассчитвается (Evaluate) в первый раз перед расчётом внешней. Т.е., с символьными аргументами, так как численные значения внешней функции ещё не подставлены (нормальный порядок расчёта) При этом всё рассчитывалось нормально. В 8й версии при наличии таких ошибок FindRoot работает некорректно в принципе (ещё одно сообщение).
Полное «решение» проблемы — позволить внутренней (и, для вызова из других функций, внешней) функции быть рассчитываемой только с численными значениями. Например, InternalF[x_?NumericQ, y_?NumericQ]:=NIntegrate[x y z, {z,0,1}], WrappingF[x_?NumericQ]:=FindRoot[InternalF[x,y],{y,0,1}].
Только что прочитал
объяснение сути проблемы:
1)
FindRoot имеет атрибут
HoldAll, поэтому неверно думать, что выполнение первого аргумента
до присвоения числового значения локальной переменной (в данном случае
y) является просто отражением стандартной последовательности выполнения выражения (The Standard Evaluation Sequence; см. в документации страницу
tutorial/Evaluation).
2) В
Mathematica 6 у некоторых числовых функций появилась недокументированная опция
Evaluated. Она не заменяет отсутствующие
Hold*-атрибуты функции, т.е. не предотвращает предварительное выполнение аргументов функции перед выполнением самой функции, но предотвращает выполнение аргумента
самой функцией до того момента, когда локальной переменной будет присвоено конкретное значение. В
Mathematica 5.x вместо этой опции вроде бы была другая, но заставить работать ее мне не удалось.
Пример использования:
In[1]:= FindRoot[NIntegrate[Exp[a x], {x, 0, 1}] == 2, {a, 1}
, Evaluated -> False]
Out[1]= {a -> 1.25643}
(никаких сообщений об ошибке!)
Эта опция есть и у ряда других числовых функций:
In[2]:= Options[#, Evaluated] & /@ {ContourPlot, ContourPlot3D,
DensityPlot, FindRoot, ParametricPlot, ParametricPlot3D, Plot,
Plot3D, RegionPlot, RegionPlot3D}
Out[2]= {{Evaluated -> Automatic}, {Evaluated ->
Automatic}, {Evaluated -> Automatic}, {Evaluated ->
True}, {Evaluated -> Automatic}, {Evaluated ->
Automatic}, {Evaluated -> Automatic}, {Evaluated ->
Automatic}, {Evaluated -> Automatic}, {Evaluated -> Automatic}}
Использование этой недокументированной опции позволяет добиться заметного прироста скорости выполнения по сравнению с документированными методами:
In[1]:= ClearSystemCache[];
FindRoot[NIntegrate[Exp[a x], {x, 0, 1}] == 2, {a, 100},
Evaluated -> False] // Timing
Clear[internalF]; ClearSystemCache[];
internalF[a_?NumberQ] := NIntegrate[Exp[a x], {x, 0, 1}]
FindRoot[internalF[a] == 2, {a, 100}] // Timing
Clear[internalF]; ClearSystemCache[];
internalF[a : (_Real | _Integer)] := NIntegrate[Exp[a x], {x, 0, 1}]
FindRoot[internalF[a] == 2, {a, 100}] // Timing
Clear[internalF]; ClearSystemCache[];
internalF[a_?NumericQ] := NIntegrate[Exp[a x], {x, 0, 1}]
FindRoot[internalF[a] == 2, {a, 100}] // Timing
Clear[internalF]; ClearSystemCache[];
internalF[a_ /; NumericQ[a]] := NIntegrate[Exp[a x], {x, 0, 1}]
FindRoot[internalF[a] == 2, {a, 100}] // Timing
Out[2]= {1.342, {a -> 1.25643}}
Out[5]= {1.993, {a -> 1.25643}}
Out[8]= {1.983, {a -> 1.25643}}
Out[11]= {1.973, {a -> 1.25643}}
Out[14]= {2.023, {a -> 1.25643}}