Comment puis-je obtenir la solution d’une équation compliquée?
Introduction
Mise à jour 6/2014
À l’origine, j’ai trouvé trois solutions; maintenant c’est six. Je pensais savoir qu’il y en avait trois car la rationalisation de l’équation aboutit à un polynôme de degré 24 et NSolve
trouve 24 racines puis élimine les racines qui n’étaient pas des zéros de l’équation d’origine. Il s’avère que l’équation était gênante du point de vue des numériques et j’en ai manqué trois.
Autres modifications:
-
Il semble plus naturel d’utiliser
Rationalize
pour convertir les coefficients en nombres exacts dans ce cas queSetPrecision
. -
De même, j’ai remplacé
First @ eq
parSubtract @@ eq
.
Rationaliser l’équation
Il faut garder à l’esprit que selon la documentation sur NSolve
NSolve
traite principalement des équations linéaires et polynomiales.
L’équation de l’OP est une équation algébrique qui peut être transformée en une équation polynomiale, que NSolve
peut alors résoudre facilement. Puisque NSolve
ne le fait pas tout seul, nous devons rationaliser “à la main.”La rationalisation a tendance à introduire des solutions étrangères, nous devons donc vérifier les réponses renvoyées par NSolve
. Les coefficients un peu désagréables de eq
rendent les choses plus difficiles, car en rationalisant eq
, l’erreur d’arrondi conduit à ce que certaines des racines carrées ne s’annulent pas comme elles le devraient. Nous pouvons résoudre ce problème en définissant la précision de eq
sur Infinity
.
On peut trouver les racines carrées dans une expression expr
avec
DeleteDuplicates @ Cases, Infinity]
Puis pour chaque racine carrée, on peut multiplier expr
par l’expression avec la racine carrée remplacée par son négatif et simplifier.
Ci-dessous est le résultat de l’application de la méthode à la fonction obtenue en remplaçant Equal
dans eq
par Subtract
par Apply
(@@
). Nous pouvons résoudre l’équation exactement.
eqExact = Rationalize;rationalized = Simplify @ Fold &, eqExact, DeleteDuplicates@Cases, Infinity]];rootsRatExact = Solve;rootsRat = NSolve(* 24 roots {{ζ -> -24559.6 + 24559.6 I}, <<22>>, {ζ -> 24559.6 - 24559.7 I}}*)
Il existe des différences significatives entre les deux solutions:
(ζ /. rootsRat) - (ζ /. rootsRatExact) // Abs // Max(* 3.15226*10^-10*)
Sélection des racines de l’équation donnée
Mise à jour: Voici où j’ai manqué quelques zéros.
J’ai utilisé Pick
pour sélectionner des racines pour lesquelles l’équation d’origine eq
a une petite valeur, inférieure à un petit seuil, disons 10^-1
. Nous pourrons vérifier plus tard que chacune est une racine, mais je n’ai pas vérifié d’autres racines. Les racines originales étaient:
rootsEq = Pick < 10^-1 /. rootsRat](* {{ζ -> -3.78042 - 5.50655 I}, {ζ -> -3.20562 + 5.39914 I}, {ζ -> 6.98478 + 0.493405 I}}*)
Ceux-ci correspondent aux racines 7, 9 et 20 dans rootsRat
:
Position < 10^-1 &)](* {{7}, {9}, {20}}*)
Si je vérifie l’équation exacte pour les zéros avec PossibleZeroQ
, j’obtiens plus de racines:
Position(* {{1}, {7}, {9}, {14}, {20}, {21}}*)
prend une éternité sur ces racines potentielles, ou du moins plus longtemps que je n’étais prêt à attendre.]
Fait intéressant, ces racines supplémentaires sont liées aux différences entre les résultats renvoyés par NSolve
et Solve
:
Position, _?Positive](* {{1}, {2}, {3}, {14}, {21}, {22}, {23}, {24}}*)
Laissons nos nouvelles racines être les suivantes et nous pouvons les vérifier ci-dessous:
rootsEqNew = Pick];rootsEqNew // N(* {{ζ -> -24559.6 + 24559.6 I}, {ζ -> -3.78042 - 5.50655 I}, {ζ -> -3.20562 + 5.39914 I}, {ζ -> -0.0832786 - 722.827 I}, {ζ -> 6.98478 + 0.493405 I}, {ζ -> 722.642 - 0.100823 I}}*)
Vérifie
Au début, at ne semble pas trop beau pour les nouveaux ajouts:
eqExact /. rootsEqNew // N(* { 0. + 9.7614*10^12 I, (* {1} *) -1.49012*10^-8 + 3.91155*10^-8 I, (* {7} *) -1.39698*10^-8 - 3.63216*10^-8 I, (* {9} *) -2. + 1536. I, (* {14} *) 1.49012*10^-8 + 1.11759*10^-8 I, (* {20} *) 0. + 1024. I} (* {21} *)*)
Le problème réside dans l’évaluation de l’équation avec la précision de la machine.
N(* N::meprec warning about $MaxExtraPrecision being reached *)(* {0``69.62973568978663 + 0``69.69302870899077 I, 0``90.5174054423328 + 0``90.55817837498498 I, 0``90.50250822096415 + 0``90.54414468499085 I, 0``80.1824915073549 + 0``79.76650578675965 I, 0``90.47483650216002 + 0``90.49782363232914 I, 0``80.17292602755023 + 0``79.76710897249409 I}*)
L’avertissement ne semble pas significatif. L’augmentation de $MaxExtraPrecision
à 2000
produit toujours l’avertissement et les zéros avec des précisions autour de 2020
à 2040
. S’ils sont des zéros, N
produira probablement toujours l’avertissement, car ne peut pas avoir de
Precision
(autre que MachinePrecision
).