• Aucun résultat trouvé

Structures de données et efficacité

Dans le document Calcul mathématique avec Sage (Page 159-162)

Corps finis et théorie élémentaire des 6

7.7 Structures de données et efficacité

Concluons ce chapitre avec quelques remarques de goût un peu plus informatique.

Représentation dense et représentation creuse. Un même objet ma-thématique — le polynôme p, à coefficients dans A — peut se coder sur ordinateur de façons très différentes. Si le résultat mathématique d’une opé-ration surpest bien sûr indépendant de la représentation, il en va autrement du comportement des objetsSage correspondants. Le choix de la représen-tation influe sur les opérations possibles, la forme exacte de leurs résultats, et particulièrement l’efficacité des calculs.

Il existe deux façons principales de représenter les polynômes. En re-présentationdense, les coefficients de p =Pni=0pixi sont stockés dans un tableau [p0, . . . , pn] indexé par les exposants. Une représentationcreuse ne stocke que les coefficients non nuls : le polynôme est codé par un ensemble de paires exposant-coefficient (i, pi), regroupées dans une liste, ou mieux, dans un dictionnaire indexé par les exposants (voir §4.3.9).

Pour des polynômes qui sont effectivement denses, c’est-à-dire dont la plupart des coefficients sont non nuls, la représentation dense occupe moins de mémoire et permet des calculs plus rapides. Elle économise le stockage des exposants et des structures de données internes du dictionnaire : ne reste que le strict nécessaire, les coefficients. De plus, l’accès à un élément ou l’itération sur les éléments sont plus rapides dans un tableau que dans un dictionnaire.

Inversement, la représentation creuse permet de calculer efficacement sur des polynômes qui ne tiendraient même pas en mémoire en représentation dense :

sage: R = PolynomialRing(ZZ, 'x', sparse=True)

sage: p = R.cyclotomic_polynomial(2^50); p, p.derivative() (x^562949953421312 + 1, 562949953421312*x^562949953421311)

Comme l’illustre l’exemple précédent, la représentation est une carac-téristique de l’anneau de polynômes, que l’on choisit à sa construction. Le polynôme « dense »x∈Q[x] et le polynôme « creux »x∈Q[x] n’ont donc pas le même9 parent. La représentation par défaut des polynômes à une indéterminée est dense. L’option sparse=True de PolynomialRing sert à construire un anneau de polynômes creux.

Certains détails de représentation varient de plus suivant la nature des coefficients des polynômes. Il en va de même du code utilisé pour effectuer les opérations fondamentales. Sageoffre en effet, outre une implémentation générique des polynômes qui fonctionne sur tout anneau commutatif, plu-sieurs variantes optimisées pour un type particulier de coefficients. Celles-ci

9. Pourtant,QQ['x'] == PolynomialRing(QQ, 'x', sparse=True)renvoie vrai : les deux parents sontégaux, car ils représentent le même objet mathématique. Naturellement, le test correspondant avecisrenvoie faux.

BR

OUILLON

apportent quelques fonctionnalités supplémentaires, et surtout sont considé-rablement plus efficaces que la version générique. Elles s’appuient pour cela sur des bibliothèques externes spécialisées, par exempleflint ountl dans le cas deZ[x].

Pour mener à bien de très gros calculs, il est crucial de travailler autant que possible dans des anneaux de polynômes disposant d’implémentations efficaces. La page d’aide affichée par p?pour un polynômepindique quelle implémentation il utilise. Le choix de l’implémentation découle le plus souvent de ceux de l’anneau de base et de la représentation. L’optionimplementation dePolynomialRing permet de préciser une implémentation quand il reste plusieurs possibilités.

Expressions symboliques. Les expressions symboliques décrites dans les chapitres1 et 2 (c’est-à-dire les éléments deSR) fournissent une troisième représentation des polynômes. Elles constituent un choix naturel quand un calcul mêle polynômes et expressions plus complexes, comme c’est souvent le cas en analyse. Mais la souplesse de représentation qu’elles offrent est parfois utile même dans un contexte plus algébrique. Par exemple, le polynôme (x+ 1)1010, une fois développé, est dense, mais il n’est pas nécessaire (ni souhaitable !) de le développer pour le dériver ou l’évaluer numériquement.

Attention cependant : contrairement aux polynômes algébriques, les polynômes symboliques ne sont pas rattachés à un anneau de coefficients particulier et ne sont pas manipulés sous forme canonique. Un même po-lynôme a un grand nombre d’écritures différentes, entre lesquelles c’est à l’utilisateur d’expliciter les conversions nécessaires. Dans le même ordre d’idées, le domaine SR regroupe toutes les expressions symboliques, sans distinction entre les polynômes et les autres, mais on peut tester explicite-ment si une expression symboliquefest polynomiale en une variablexpar f.is_polynomial(x).

Un peu de théorie. Pour tirer le meilleur parti des opérations rapides sur les polynômes, il est bon d’avoir une idée de leur complexité algorithmique.

En voici pour finir un bref aperçu, à l’intention du lecteur connaissant un peu d’algorithmique. Nous nous limitons au cas des polynômes denses.

Additions, soustractions et autres manipulations directes des coefficients se font facilement en temps linéaire en les degrés des polynômes en jeu. Leur rapidité en pratique dépend donc essentiellement de la possibilité d’accéder rapidement aux coefficients, et donc de la structure de données.

L’opération cruciale est la multiplication. En effet, non seulement c’est une opération arithmétique de base, mais on dispose de plus d’algorithmes pour toutes sortes d’opérations plus complexes dont la complexité dépend essentiellement de celle de la multiplication. Par exemple, on peut calcu-ler la division euclidienne de deux polynômes de degré au plus n pour le

BR

OUILLON

coût de O(1) multiplications, ou encore leur pgcd pour celui de O(logn) multiplications.

Bonne nouvelle : on sait multiplier les polynômes en temps presque linéaire.

Précisément, la meilleure complexité connue sur un anneau quelconque est deO(nlognlog logn) opérations dans l’anneau de base. Elle repose sur des généralisations du célèbre algorithme de Schönhage-Strassen, qui atteint la même complexité pour la multiplication d’entiers. En comparaison, la méthode que l’on utilise à la main pour multiplier les polynômes demande un nombre d’opérations de l’ordre den2.

Les algorithmes de multiplication rapide sont compétitifs en pratique pour les polynômes de degré suffisamment grand, de même que les méthodes qui en dérivent pour la division. Les bibliothèques sur lesquelles s’appuie Sagepour certains types de coefficients font appel à ce genre d’algorithmes avancés : c’est ainsi queSageest capable de travailler efficacement avec des polynômes de degré astronomique sur certains anneaux de coefficients.

BR

OUILLON

William Stein

Dans le document Calcul mathématique avec Sage (Page 159-162)