Strona pomocy FindRoot
zawiera:
„FindRoot domyślnie używa metody Newtona (Newton-Raphson) do rozwiązania systemu nieliniowego”
(lub nieliniowe równanie, jak przypuszczam). Niemniej jednak w poleceniu FindRoot
jest coś ukrytego. Rozważmy funkcję
f[x]:=Exp[1 - x] - 1,
którego funkcją iteracyjną Newtona jest
Nf[x_]:=E^(-1 + x) (-1 + E^(1 - x)) + x
Iterując tą funkcją używając NestList
otrzymujesz sekwencja wartości uzyskanych metodą Newtona. Metoda Newtona dla dużych wartości początkowego przypuszczenia przedstawia powolną zbieżność dla tego problemu. Biorąc $ x_0 = 10 $ otrzymujemy:
NestList[Nf, 10., 8] (* {10., -8092.08, -8091.08, -8090.08, -8089.08, -8088.08, -8087.08, -8086.08, -8085.08} *)
gdzie możemy zobaczyć powolna konwergencja. Wykres funkcji Nf[x]
pomaga zrozumieć zachowanie metody. Ale biorąc
Module[{s = 0, e = 0}, {FindRoot[f[x], {x, 10.}, StepMonitor :> s++, EvaluationMonitor :> e++], "Steps" -> s, "Evaluations" -> e}]
daje
{{x -> 1.}, "Steps" -> 7, "Evaluations" -> 11}
wystarczy 7 kroków, aby uzyskać rozwiązanie $ x = 1 $. Dlaczego FindRoot
daje taki wynik ?. Oczywiście FindRoot
nie używa standardowej metody Newtona, prawda? Czy ktoś może mi pomóc? Dzięki.
Komentarze
- Zobacz tutaj i tutaj
Odpowiedź
Domyślnie FindRoot
używa metody "LineSearch"
, zgodnie z opisem w samouczku tutorial/UnconstrainedOptimizationLineSearchMethods
. Domyślne ustawienia to
FindRoot[Exp[1 - x] - 1, {x, 10.}, Method -> {"Newton", "StepControl" -> {"LineSearch", "CurvatureFactor" -> Automatic, "DecreaseFactor" -> 1/10000, "MaxRelativeStepSize" -> 10, Method -> Automatic}}]
Aby uzyskać mniej więcej dokładną metodę Newtona, nie używaj sterowania krokowego. Jednak FindRoot
nadal ogranicza maksymalny rozmiar kroku (pierwszy krok w poniższym przypadku jest obcięty do x == -100.
):
Module[{s = 0, e = 0}, {FindRoot[Exp[1 - x] - 1, {x, 10.}, Method -> {"Newton", "StepControl" -> None}, StepMonitor :> s++, EvaluationMonitor :> e++], "Steps" -> s, "Evaluations" -> e}]
FindRoot :: cvmit: Nie udało się uzyskać zbieżności z żądaną dokładnością lub precyzją w ciągu 100 iteracji. >>
(* {{x -> -1.07713}, "Steps" -> 100, "Evaluations" -> 101} *)
Możesz użyć opcji
StepMonitor :> Print[{x}], EvaluationMonitor :> Print[x]
, aby monitorować kroki i oceny. Możesz też użyj FindRootPlot
w pakiecie "Optimization`UnconstrainedProblems`"
. (Poszukaj żółtych kropek oznaczających ocenę, która nie jest krokiem).
Needs["Optimization`UnconstrainedProblems`"] FindRootPlot[Exp[1 - x] - 1, {x, 10.}, PlotRange -> All]
FindRootPlot[Exp[1 - x] - 1, {x, 10.}, Method -> {"Newton", "StepControl" -> None}, PlotRange -> All]
Komentarze
- Inaczej mówiąc:
FindRoot[]
używa tłumionej wersji Newtona-Raphsona, ponieważ bez tłumienia, zły wybór wartości początkowych częściej będzie skutkował rozbieżnością. Tłumienie sprawia, że iteracje są mniej podatne na oszukiwanie.