Hjælpesiden til FindRoot
siger:
“som standard, FindRoot bruger Newtons metode (Newton-Raphson) til at løse et ikke-lineært system”
(eller en ikke-lineær ligning antager jeg). Ikke desto mindre er der noget skjult for mig i kommandoen FindRoot
. Overvej funktionen
f[x]:=Exp[1 - x] - 1,
hvis Newton-iterationsfunktion er
Nf[x_]:=E^(-1 + x) (-1 + E^(1 - x)) + x
Itererer med denne funktion ved hjælp af NestList
du får rækkefølgen af værdier produceret efter Newtons metode. Newton-metoden til store værdier af det første gæt præsenterer langsom konvergens for dette problem. At tage $ x_0 = 10 $ får vi:
NestList[Nf, 10., 8] (* {10., -8092.08, -8091.08, -8090.08, -8089.08, -8088.08, -8087.08, -8086.08, -8085.08} *)
hvor vi kan se langsom konvergens. Et plot af funktionen Nf[x]
hjælper med at forstå metodens opførsel. Men at tage
Module[{s = 0, e = 0}, {FindRoot[f[x], {x, 10.}, StepMonitor :> s++, EvaluationMonitor :> e++], "Steps" -> s, "Evaluations" -> e}]
producerer
{{x -> 1.}, "Steps" -> 7, "Evaluations" -> 11}
behøver kun 7 trin for at få løsningen $ x = 1 $. Hvorfor FindRoot
giver dette resultat ?. Det er klart, at FindRoot
ikke bruger Newtons standardmetode, er det ikke? Kan nogen hjælpe mig? Tak.
Kommentarer
- Se her og her
Svar
Som standard FindRoot
bruger "LineSearch"
metoden til trinkontrol som beskrevet i vejledningen tutorial/UnconstrainedOptimizationLineSearchMethods
. Standardindstillingerne er
FindRoot[Exp[1 - x] - 1, {x, 10.}, Method -> {"Newton", "StepControl" -> {"LineSearch", "CurvatureFactor" -> Automatic, "DecreaseFactor" -> 1/10000, "MaxRelativeStepSize" -> 10, Method -> Automatic}}]
For at få Newtons metode mere eller mindre nøjagtigt skal du ikke bruge nogen trinkontrol. FindRoot
begrænser stadig den maksimale trinstørrelse (det første trin i nedenstående tilfælde er afkortet til 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: Kunne ikke konvergere til den ønskede nøjagtighed eller præcision inden for 100 iterationer. >>
(* {{x -> -1.07713}, "Steps" -> 100, "Evaluations" -> 101} *)
Du kan bruge indstillingerne
StepMonitor :> Print[{x}], EvaluationMonitor :> Print[x]
til at overvåge trinene og evalueringerne. Eller du kan brug FindRootPlot
i "Optimization`UnconstrainedProblems`"
-pakken. (Se nøje efter de gule prikker, der angiver en evaluering, der ikke er et trin.)
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]
Kommentarer
- Sæt det på en anden måde:
FindRoot[]
bruger en dæmpet version af Newton-Raphson, for uden dæmpning vil dårlige valg af startværdier oftere resultere i divergens. Dæmpningen gør gentagelserne mindre tilbøjelige til at blive vilde.