Hjälpsidan för FindRoot
säger:
”som standard, FindRoot använder Newtons metod (Newton-Raphson) för att lösa ett icke-linjärt system”
(eller en icke-linjär ekvation antar jag). Ändå finns det något dolt för mig i kommandot FindRoot
. Tänk på funktionen
f[x]:=Exp[1 - x] - 1,
vars Newton-iterationsfunktion är
Nf[x_]:=E^(-1 + x) (-1 + E^(1 - x)) + x
Itererar med den här funktionen med NestList
du får sekvensen av värden som produceras med Newtons metod. Newton-metoden för stora värden för den första gissningen presenterar långsam konvergens för detta problem. Tar $ 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} *)
där vi kan se långsam konvergens. En plot av funktionen Nf[x]
hjälper till att förstå metodens beteende. Men att ta
Module[{s = 0, e = 0}, {FindRoot[f[x], {x, 10.}, StepMonitor :> s++, EvaluationMonitor :> e++], "Steps" -> s, "Evaluations" -> e}]
producerar
{{x -> 1.}, "Steps" -> 7, "Evaluations" -> 11}
behöver bara sju steg för att få lösningen $ x = 1 $. Varför FindRoot
ger detta resultat ?. Det är uppenbart att FindRoot
inte använder Newtons standardmetod, eller hur? Kan någon hjälpa mig? Tack.
Kommentarer
- Se här och här
Svar
Som standard FindRoot
använder "LineSearch"
metoden för stegkontroll som beskrivs i självstudien tutorial/UnconstrainedOptimizationLineSearchMethods
. Standardinställningarna är
FindRoot[Exp[1 - x] - 1, {x, 10.}, Method -> {"Newton", "StepControl" -> {"LineSearch", "CurvatureFactor" -> Automatic, "DecreaseFactor" -> 1/10000, "MaxRelativeStepSize" -> 10, Method -> Automatic}}]
För att få Newtons metod mer eller mindre exakt, använd ingen stegkontroll. FindRoot
begränsar fortfarande den maximala stegstorleken (det första steget i fallet nedan trunkeras till 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: Det gick inte att konvergera till önskad noggrannhet eller precision inom 100 iterationer. >>
(* {{x -> -1.07713}, "Steps" -> 100, "Evaluations" -> 101} *)
Du kan använda alternativen
StepMonitor :> Print[{x}], EvaluationMonitor :> Print[x]
för att övervaka stegen och utvärderingarna. Eller så kan du använd FindRootPlot
i paketet "Optimization`UnconstrainedProblems`"
. (Titta noga efter de gula prickarna som anger en utvärdering som inte är ett steg.)
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ätt på ett annat sätt:
FindRoot[]
använder en dämpad version av Newton-Raphson, för utan dämpning kommer dåliga val av startvärden oftare att leda till divergens. Dämpningen gör att iterationerna blir mindre benägna.