Pagina de ajutor a FindRoot
spune:
„implicit, FindRoot folosește metoda Newton (Newton-Raphson) pentru a rezolva un sistem neliniar”
(sau presupun o ecuație neliniară). Cu toate acestea, există ceva ascuns pentru mine în comanda FindRoot
. Luați în considerare funcția
f[x]:=Exp[1 - x] - 1,
a cărei funcție de iterație Newton este
Nf[x_]:=E^(-1 + x) (-1 + E^(1 - x)) + x
Iterând cu această funcție folosind NestList
pe care îl obțineți succesiunea valorilor produse prin metoda lui Newton. Metoda Newton pentru valori mari ale presupunerii inițiale prezintă convergență lentă pentru această problemă. Luând $ x_0 = 10 $ obținem:
NestList[Nf, 10., 8] (* {10., -8092.08, -8091.08, -8090.08, -8089.08, -8088.08, -8087.08, -8086.08, -8085.08} *)
unde putem vedea convergență lentă. Un grafic al funcției Nf[x]
ajută la înțelegerea comportamentului metodei. Dar luând
Module[{s = 0, e = 0}, {FindRoot[f[x], {x, 10.}, StepMonitor :> s++, EvaluationMonitor :> e++], "Steps" -> s, "Evaluations" -> e}]
produce
{{x -> 1.}, "Steps" -> 7, "Evaluations" -> 11}
fiind nevoie doar de 7 pași pentru a obține soluția $ x = 1 $. De ce FindRoot
produce acest rezultat ?. Evident, FindRoot
nu folosește metoda standard Newton, nu-i așa? Ma poate ajuta cineva? Mulțumesc.
Comentarii
- Consultați aici și aici
Răspuns
În mod implicit FindRoot
folosește metoda "LineSearch"
de control pas, așa cum este descris în tutorial tutorial/UnconstrainedOptimizationLineSearchMethods
. Setările implicite sunt
FindRoot[Exp[1 - x] - 1, {x, 10.}, Method -> {"Newton", "StepControl" -> {"LineSearch", "CurvatureFactor" -> Automatic, "DecreaseFactor" -> 1/10000, "MaxRelativeStepSize" -> 10, Method -> Automatic}}]
Pentru a obține metoda lui Newton mai mult sau mai puțin exact, nu utilizați nici un control de pași. Cu toate acestea, FindRoot
limitează în continuare dimensiunea maximă a pasului (primul pas în cazul de mai jos este trunchiat la 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: Nu s-a reușit să convergem la precizia solicitată sau precizia în 100 de iterații. >>
(* {{x -> -1.07713}, "Steps" -> 100, "Evaluations" -> 101} *)
Puteți utiliza opțiunile
StepMonitor :> Print[{x}], EvaluationMonitor :> Print[x]
pentru a monitoriza pașii și evaluările. Sau puteți utilizați FindRootPlot
în pachetul "Optimization`UnconstrainedProblems`"
. (Căutați cu atenție punctele galbene care denotă o evaluare care nu este un pas.)
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]
Comentarii
- Cu alte cuvinte:
FindRoot[]
folosește o versiune amortizată a Newton-Raphson, pentru că fără amortizare, alegerile rele ale valorilor de pornire vor duce mai des la divergență. Împiedicarea face ca iterațiile să devină mai puțin probabil să se dezlănțuiască.