Hjelpesiden til FindRoot
sier:
«som standard, FindRoot bruker Newtons metode (Newton-Raphson) for å løse et ikke-lineært system»
(eller en ikke-lineær ligning antar jeg). Likevel er det noe skjult for meg i FindRoot
kommandoen. Tenk på funksjonen
f[x]:=Exp[1 - x] - 1,
hvis Newton-iterasjonsfunksjon er
Nf[x_]:=E^(-1 + x) (-1 + E^(1 - x)) + x
Itererer med denne funksjonen ved hjelp av NestList
du får verdisekvensen produsert etter Newtons metode. Newton-metoden for store verdier av den første gjetningen presenterer langsom konvergens for dette problemet. Tar vi $ 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} *)
der vi kan se langsom konvergens. Et plott av funksjonen Nf[x]
hjelper til å forstå oppførselen til metoden. Men å ta
Module[{s = 0, e = 0}, {FindRoot[f[x], {x, 10.}, StepMonitor :> s++, EvaluationMonitor :> e++], "Steps" -> s, "Evaluations" -> e}]
gir
{{x -> 1.}, "Steps" -> 7, "Evaluations" -> 11}
trenger bare 7 trinn for å få løsningen $ x = 1 $. Hvorfor gir FindRoot
dette resultatet ?. Åpenbart bruker FindRoot
ikke Newtons standardmetode, ikke sant? Kan noen hjelpe meg? Takk.
Kommentarer
- Se her og her
Svar
Som standard FindRoot
bruker "LineSearch"
metoden for trinnkontroll som beskrevet i veiledningen tutorial/UnconstrainedOptimizationLineSearchMethods
. Standardinnstillingene er
FindRoot[Exp[1 - x] - 1, {x, 10.}, Method -> {"Newton", "StepControl" -> {"LineSearch", "CurvatureFactor" -> Automatic, "DecreaseFactor" -> 1/10000, "MaxRelativeStepSize" -> 10, Method -> Automatic}}]
For å få Newtons metode mer eller mindre nøyaktig, bruk ingen trinnkontroll. Imidlertid FindRoot
begrenser fremdeles den maksimale trinnstørrelsen (det første trinnet i saken nedenfor er avkortet 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 ønsket nøyaktighet eller presisjon innen 100 iterasjoner. >>
(* {{x -> -1.07713}, "Steps" -> 100, "Evaluations" -> 101} *)
Du kan bruke alternativene
StepMonitor :> Print[{x}], EvaluationMonitor :> Print[x]
for å overvåke trinnene og evalueringene. Eller du kan bruk FindRootPlot
i "Optimization`UnconstrainedProblems`"
-pakken. (Se nøye etter de gule prikkene som angir en evaluering som ikke er et trinn.)
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
- Sagt på en annen måte:
FindRoot[]
bruker en dempet versjon av Newton-Raphson, for uten demping vil dårlige valg av startverdier oftere resultere i divergens. Dempingen gjør at iterasjonene er mindre sannsynlige å gå vill.