Matlab4n00bz: Ou comment faire de Matlab votre meilleur ami. Version 1.0 Vincent Schellekens et Florimond Houssiau August 2014 Table des matières 1 Avant de commencer, un peu d’informatique. . . 1.1 Matlab , c’est quoi ? . . . . . . . . . . . . . . . . 1.2 Comment écrire du code en Matlab . . . . . . . 1.2.1 Fichiers : scripts et fonctions . . . . . . . 1.2.2 Commande interactive . . . . . . . . . . . 1.3 Concept clé : la vectorisation . . . . . . . . . . . 1.4 Alternatives gratuites à Matlab . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 4 4 4 5 5 2 Concepts de base : variables, fonctions, syntaxe, . . . 2.1 Le code, c’est quoi ? . . . . . . . . . . . . . . . . . . . . 2.2 Variables et opérations . . . . . . . . . . . . . . . . . . . 2.2.1 Les variables . . . . . . . . . . . . . . . . . . . . 2.2.2 Opérateurs . . . . . . . . . . . . . . . . . . . . . 2.3 Boucles et instructions conditionnelles . . . . . . . . . . 2.3.1 Les conditions . . . . . . . . . . . . . . . . . . . 2.3.2 Les instructions conditionnelles : if et else . . . . 2.3.3 La boucle while . . . . . . . . . . . . . . . . . . . 2.3.4 La boucle for . . . . . . . . . . . . . . . . . . . . 2.4 Les fonctions . . . . . . . . . . . . . . . . . . . . . . . . 2.4.1 Syntaxe des fonctions . . . . . . . . . . . . . . . 2.4.2 Plusieurs valeurs de sortie, plusieurs arguments . 2.4.3 Fonctions utiles de Matlab . . . . . . . . . . . . 2.5 Débugger votre code Matlab . . . . . . . . . . . . . . . 2.5.1 Le point-virgule . . . . . . . . . . . . . . . . . . . 2.5.2 Quelques fonctions pour afficher vos résultats . . 2.5.3 Mesurer le temps d’exécution du code . . . . . . 2.5.4 Programmer défensivement . . . . . . . . . . . . 2.6 Un petit commentaire sur l’utilisation de commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 6 7 7 8 9 9 10 10 11 11 12 12 14 14 15 15 15 15 16 3 Opérations sur les vecteurs 3.1 Créer ses propres vecteurs . . . . . . . . 3.1.1 Syntaxe propre aux vecteurs . . 3.1.2 Fonctions de création de vecteurs 3.1.3 Adjonction de vecteurs . . . . . . 3.2 Manipuler des vecteurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 18 18 18 19 19 . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 20 21 22 22 22 24 24 . . . . . . . . . . . . . . . . . . de niveau. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 25 27 28 28 28 28 5 Les superpouvoirs de Matlab : ode45, le calcul symbolique, . . . 5.1 Résoudre des équations différentielles ordinaires plus vite que son ombre 5.1.1 Que fait vraiment ode45 ? . . . . . . . . . . . . . . . . . . . . . . 5.1.2 Quels arguments donner à ode45 ? . . . . . . . . . . . . . . . . . 5.1.3 Comment utiliser les valeurs de retour ? . . . . . . . . . . . . . . 5.1.4 Un exemple : le pendule amorti . . . . . . . . . . . . . . . . . . . 5.2 Calculer symboliquement mieux que vous . . . . . . . . . . . . . . . . . 5.3 S’amuser avec Matlab . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3.1 Les petites blagues de Matlab . . . . . . . . . . . . . . . . . . . 5.3.2 Oubliez Steam : jouer avec Matlab . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 29 29 30 30 31 32 33 33 33 3.3 3.2.1 Accès aux éléments . . . . . . . . 3.2.2 Opérations sur un vecteur . . . . 3.2.3 Opérations entre vecteurs . . . . 3.2.4 Opérations élément par élément . Les vecteurs Like A Boss . . . . . . . . . 3.3.1 La vectorisation . . . . . . . . . 3.3.2 La préallocation . . . . . . . . . 3.3.3 Les matrices creuses . . . . . . . . . . . . . . . . . . . . . . . 4 Dessiner des graphes 4.1 Créer le graphe de base (titre, axes...) . . . 4.2 Plein d’options pour faire joli . . . . . . . . 4.3 Exporter votre chef-d’oeuvre . . . . . . . . 4.4 A trois variables : les surfaces et les courbes 4.4.1 Les courbes de niveau : contourf . . 4.4.2 Les courbes 3-D : surf et plot3 . . . . . . . . . . . . 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introduction Ce document est destiné aux étudiants de deuxième année en ingénieur civil et ingénieur civil architecte suivant le cours de Méthodes Numériques. Son objectif est de présenter et d’expliquer les principaux concepts et fonctionnalités du logiciel Matlab , d’abord pour le cours, mais aussi pour le projet 3 et plus généralement, pour l’apprentissage personnel. Ce document n’est pas un guide exhaustif à Matlab. Il contient essentiellement ce que nous avons jugé important de savoir pour réussir le cours, et en particulier réussir les devoirs hebdomadaires. Le premier chapitre décrit le logiciel Matlab de manière plus pratique, et est présent à titre strictement indicatif. Le chapitre 2 introduit la syntaxe du langage Matlab, et est indispensable à quiconque n’a jamais écrit de code auparavant. Le chapitre 3 se concentre sur l’emploi omniprésent des vecteurs dans Matlab, et est certainement le plus important du document. Le chapitre 4 explique comment afficher les données en traçant de beaux graphes. Enfin, le chapitre 5 expose les fonctionnalités les plus puissantes de Matlab, pour ceux qui voudraient aller plus loin, et faire des choses vraiment utiles avec le logiciel. . . Ceci n’est pas un syllabus officiel, et il n’est pas obligé de tout lire ! Au contraire, si vous n’avez pas le temps de tout lire, concentrez vous sur les chapitres 2 et 3, qui contiennent les éléments les plus importants sur les bonnes pratiques en Matlab. Si vous avez des remarques concernant le document, si vous y repérez une erreur (il y en a certainement), n’hésitez surtout pas à nous contacter par mail (vincent.schellekens@student.uclouvain.be ou florimond.houssiau@student.uclouvain.be), ou en personne. Le document est actuellement hébergé sur ShareLatex, mais devrait être migré sous GitHub bientot, ce qui rendra la distribution et la correction plus aisées. Bonne lecture ! 1 Avant de commencer, un peu d’informatique. . . Parce que oui, Matlab , avant tout, c’est de l’informatique. N’ayez pas peur, cette section ne se penche pas sur toutes ces choses scabreuses que sont les pointeurs, la récursion terminale et le polymorphisme, mais plutôt sur les quelques petites choses qu’il est bon de savoir sur votre (futur) logiciel favori. Cette partie ne fait pas partie de la matière d’examination. Attention, certaines sections de ce chapitre pré-supposent des notions d’informatique : si vous ne comprenez pas de quoi il s’agit, ne vous inquiétez pas, tout sera expliqué en temps utile dans la suite du document. 1.1 Matlab , c’est quoi ? Matlab , c’est deux choses : 1. un langage de programmation développé par la firme MathWorks 2. un logiciel, développé par cette même firme, qui exécute les fichiers de code Matlab Le langage Matlab est interprété, c’est à dire que le code n’est jamais transformé en langage machine, mais plutot lu par un logiciel (dans ce cas, le logiciel Matlab 1 ). Cela rend l’exécution d’un code Matlab relativement lente, par rapport par exemple à celle d’un langage compilé, comme le C, et dans une certaine mesure le Java. Pour pallier cet inconvénient, Matlab est doté d’un nombre important de fonctions toute faites, fournies pré-compilées (en langage machine) avec le logiciel : ces fonctions, qui s’occupent notament de la gestion des vecteurs, offrent donc pratiquement les mêmes performances que si on avait écrit le code en C, par exemple. Par conséquent, pour rendre un code Matlab efficace, il faut employer au maximum ces fonctions (ou en tout cas, éviter au maximum d’implémenter les opérations vectorielles à la main, on en reparlera), ce qui est une bonne et une mauvaise nouvelle. Bonne nouvelle : les codes Matlab sont relativement courts. Mauvaise 1. ça porte à confusion, certes, mais Matlab est interprété par Matlab . . . 3 nouvelle : il faut connaitre ces fonctions. . . (Rassurez vous, il n’y en a pas tant que ça à connaitre pour s’en sortir correctement). La documentation du langage Matlab se trouve sur le site /www.mathworks.nl/help/matlab/index. html. Autrement, comme dirait Monsieur Legat, Google est votre ami. 1.2 Comment écrire du code en Matlab Matlab supporte deux manières d’écrire du code : les fichiers et la commande interactive. 1.2.1 Fichiers : scripts et fonctions Le logiciel Matlab contient un éditeur de texte assez puissant, qui repère certaines erreurs et comportements à éviter, offre une complétion de texte assez efficace, et colorise le texte en accord avec la syntaxe. Les fichiers de code Matlab ont pour extension .m. Il existe deux types de fichier : les scripts et les fonctions. Les scripts contiennent du code exécutable : en lançant un script (en appuyant sur la flèche verte, par exemple), le code s’exécute tel quel. Il est interdit de définir des fonctions à l’intérieur d’un script, ainsi que de spécifier des arguments 2 ce rend les scripts très limités. Ils sont utiles pour des codes assez courts destinés par exemple à tester une fonction. Les fichiers de fonction ne contiennent que des définitions de fonctions (voir chapitre 2.4 sur les fonctions) : il est interdit d’écrire du code qui ne soit pas compris entre function ... et le end respectif. Chaque fichier peut contenir la définition de plusieurs fonctions, mais seule celle portant le même nom que le fichier ne sera utilisable de l’extérieur. La plus grande majorité des projets en Matlab utilisent exclusivement des fichiers de fonction, de par leur grande flexibilité. 1.2.2 Commande interactive Un des atouts de Matlab , qui le distingue particulièrement de Java, est la possibilité d’entrer du code de manière interactive dans une commande (qui est normalement la première chose qu’on voit lorsque Matlab se lance). Cette commande permet notamment de : — tester une de vos fonctions avec plein d’arguments différents (pour voir si ça marche) — réaliser des petits calculs pour lesquels il est inutile de faire un fichier (par exemple, résoudre un système linéaire) — naviguer dans les dossiers via les opérateurs ls et cd (utile dans certains cas) — consulter la documentation : en tapant help nom_de_la_fonction, la documentation liée est affichée — tester les fonctions de la doc pour essayer de comprendre ce qu’elles font (parce que lire la doc, ça prend du temps) La commande garde en mémoire toutes les variables définies lors de son utilisation ou de l’emploi d’un script (les variables définies dans une fonction, par contre, disparaissent à la fin de l’exécution de celle-ci). A titre d’exemple, voici comment calculer facilement la moyenne et la moyenne des carrés des sinus de tous les entiers entre 1 et 1000 compris (une tache courante de la vie de tous les jours) : 1 2 3 4 5 6 EDU > > x = 1:1000; % on prend tous les entiers de 1 a 1000 EDU > > y = sin ( x ) ; EDU > > disp ( mean ( y ) ) ; % disp = display = afficher 8.1397 e -004 EDU > > disp ( mean ( y .^2) ) ; 0.5002 2. Concrètement, le script s’exécute dans l’environnement actuel de la commande interactive : il est dont possible de référencer une variable, qu’on espère définie dans l’environnement. C’est toutefois une mauvaise pratique : il vaut mieux faire appel aux fonctions ! 4 1.3 Concept clé : la vectorisation Le concept le plus important du langage Matlab est la vectorisation : l’emploi extensif de vecteurs. Toutes les opérations sur les vecteurs sont gérées par le langage de manière très efficace. Il faut donc à tout prix éviter de coder par soi-même ces opérations. A titre d’exemple, implémentons le produit scalaire entre deux vecteurs, nommés x (vecteur ligne) et y (vecteur colonne). Ce code s’implémente naivement comme suit : 1 2 3 4 res = 0; for i = 1: length ( x ) res = res + x ( i ) * y ( i ) ; end En employant les fonctionnalités natives de Matlab, cela devient simplement : 1 res = x * y ; En mesurant les performances des deux codes écrits ci-dessus, on constate rapidement que le deuxième code est, pour des vecteurs de grande taille, au moins 10 fois plus rapide 3 ! En outre, la majorité des fonctions mathématiques de base de Matlab (comme, par exemple, sin, cos, exp, . . .) admettent comme argument des vecteurs. Ainsi, pour calculer le sinus de chaque élément d’un vecteur x, et stocker le résultat dans un vecteur y, on utilisera simplement : 1 y = sin ( x ) ; Ce qui combine les avantages d’être à la fois plus rapide et beaucoup plus lisible ! Nous aborderons encore l’importance de la vectorisation dans un chapitre futur. En attendant, retenez surtout ceci : Tant que possible, il faut éviter la boucle for ! 1.4 Alternatives gratuites à Matlab Le logiciel Matlab est un logiciel propriétaire, ce qui signifie, hélas, qu’il est payant 4 . Toutefois, des alternatives open-source (donc ouvertes, sures et gratuites) existent. Evidemment, ce n’est jamais aussi bien que l’original, et souvent pas tout à fait compatible (de nombreuses fonctions n’existent que chez Matlab ) mais elles ont tout de même leurs mérites. La plus connue de toutes, et la plus proche du logiciel développé par MathWorks, est Octave (http: //www.gnu.org/software/octave/). La plus grande majorité des fonctionnalités du langage Matlab sont présentes (il est tout à fait possible de suivre le cours de Méthodes Numériques avec Octave, à condition de s’assurer de la compatibilité sur les machines des salles info, juste pour être sur !), de manière généralement assez performante. Par contre, Octave est très loin du logiciel Matlab : il ne s’agit que d’une commande interactive ! Il faut donc utiliser un autre éditeur de texte (comme par exemple Vim 5 , Nano 6 , ou Notepad++ 7 ). Une autre possibilité est d’utiliser Freemat (http://freemat.sourceforge.net/), qui se veut un clone (assez moche) de Matlab, beaucoup moins puissant, mais doté de l’ensemble des fonctionnalités de base du langage et du logiciel. L’éditeur de texte est assez basique (pas de complétion, par exemple), mais tout fonctionne bien. Il présente toutefois un très grand avantage par rapport à notre logiciel favori : Freemat est très léger, et se lance donc très vite. Ce qui vous permet d’éviter de devoir lancer Matlab pour un bête système matriciel (surtout sur des machines un peu vieilles, sur lesquelles Matlab prend des plombes à se lancer, et pompe pas mal de mémoire). Malheureusement, il manque à Freemat des fonctions nécessaires 3. Pour un vecteur de 1000000 éléments (ce qui n’est pas si rare que ça !), le code vectoriel est près de 100 fois plus rapide ! 4. Enfin, en théorie... On sait tous que ce n’est pas forcément le cas. . . Blague à part, nous vous recommandons fortement d’avoir une version légale de Matlab quand vous aurez des travaux importants à rendre (mémoire...). Puis bon, l’amende vaut 100 fois la license étudiante, de quoi réfléchir. 5. Editeur à la ligne de commande particulièrement puissant, mais très dur à utiliser au début : http://www.vim.org 6. Autre éditeur à la commande, plus simple à utiliser que Vim : http://www.nano-editor.org/ 7. IDE (presque) universel, beaucoup plus simple que les deux autres :http://notepad-plus-plus.org/ 5 pour le cours de Méthodes Numériques (notamment contourf), et sa syntaxe n’est pas tout à fait compatible avec notre bon vieux Matlab . . . Il existe plein d’autres programmes (Scilab, Sage, . . .), plus ou moins proches de Matlab , plus ou moins bons (et pour être honnête, on n’a pas tout testé ;-), donc à vous de voir. . . Reste que Matlab n’est pas trop trop cher (pour rire, allez comparer avec Mathematica, ou SolidWorks), mais pour des ordis pas super puissants (par exemple, si vous avez un petit ordi d’appoint), les deux programmes ci-dessus devraient suffire pour le cours. 2 Concepts de base : variables, fonctions, syntaxe, . . . Cette section s’adresse à tout ceux qui ne savent pas trop ce que c’est, le code informatique (par exemple, les ARCH), ou qui ont un peu oublié (INFO 1, c’était il y a au moins 8 mois !), et va vous apprendre tout ce qu’il faut savoir pour écrire et comprendre du code Matlab. 2.1 Le code, c’est quoi ? Cette sous-section s’adresse aux étudiants qui n’ont jamais programmé de leur vie et qui ne savent pas trop ce que c’est, écrire du code, à part taper très vite sur un clavier et écrire plein de choses bizarres à l’écran qui sont incompréhensibles pour le commun des mortels. Certains d’entre vous ont peut-être une haute estime de leur ordinateur. Après tout, celui-ci peut effectuer de nombreuses tâches que nous serions bien incapables d’effectuer, et peut par exemple en même temps télécharger les épisodes de votre série favorite, ainsi que jouer de la musique, afficher ce document et vous faire part des avis de vos amis sur votre photo de profil. Et tout cela, en même temps ! Ce qui laisse à supposer que votre ordinateur est un être absolument génial. Hé bien, ce n’est pas le cas. Au contraire même, votre ordinateur n’est qu’un ensemble de circuits électroniques dénués de la moindre capacité d’interprétation ou once d’intelligence. Un ordinateur est en fait une simple machine qui fait exactement ce qu’on lui dit : rien de plus, rien de moins. Mais dans quel langage parle l’ordinateur ? La réponse est simple, et pas très utile : en binaire (représenté par des courants électriques et des charges de condensateurs). Heureusement, l’époque oú l’on écrivait les programmes en binaire est révolue, et on peut désormais employer des langages de programmation, qui sont compréhensibles par les humains, et peuvent être traduits de manière non-ambigües en langage machine (le binaire). Matlab est un langage de programmation (c’est aussi le nom du programme qui traduit le langage Matlab en langage machine). Le principe d’un ordinateur est très simple : un être doté d’une intelligence supérieur (le programmeur, c’est-à-dire, vous) va donner toute une série d’instruction (le code, écrit en un certain language, ici Matlab ) à l’ordinateur pour qu’il effectue une certaine tâche. Comme, nous l’avons dit, l’ordinateur est stupide, il faudra être extrêmement précis durant l’écriture de la susnommée séquence d’instructions, de sorte à ce qu’aucune ambiguïté ne soit possible pour le pauvre ordinateur qui ne possède aucune capacité d’interprétation. Tour l’art d’écrire du code constiste donc à expliquer à l’ordinateur ce qui est attendu de lui, de manière à ce qu’il puisse ensuite (durant l’éxécution) effectuer la tâche souhaitée avec brio. Les trois premières sections de ce chapitre introduisent les concepts nécessaires à l’écriture d’un code Matlab qui fonctionne. Par contre, si vous n’êtes pas assez clair ou que vous faites quelque chose que vous n’avez pas le droit de faire, Matlab vous insultera gentiment avec des messages (en rouge pour faire peur) du genre : Figure 1 – Un gentil message d’erreur de Matlab . A votre avis, d’ou vient l’erreur 8 ? 8. Comme vous le signale plus ou moins explicitement Matlab , les vecteurs ne sont pas compatibles pour le produit matriciel : 6 La mauvaise nouvelle, c’est que quand Matlab vous insulte, c’est une bonne nouvelle. Les erreurs les plus dures à corriger sont celles qui n’entrainent pas de messages d’erreur. . . C’est l’objet de la dernière section de ce chapitre, qui vous expliquera comment faire pour que votre code fonctionne (enfin) comme vous le voulez ! 2.2 2.2.1 Variables et opérations Les variables Le concept le plus important de toute la programmation (non non, nous n’exagérons pas) est sans aucun doute celui de variable. Une variable est l’équivalent (grosso modo) d’une adresse dans la mémoire de l’ordinateur, à laquelle se trouve une donnée : il s’agit d’un lien vers une donnée. Une variable porte un nom, appelé identifiant (par exemple x), et une valeur (par exemple 42). Pour créer une variable, on utilise le symbole = : 1 x = 42 % creation d ’ une variable x initialisee a 42 Contrairement à Java, il n’est pas nécessaire (ni même permis) de déclarer des variables. Ce qui signifie que les variables sont crées à l’initialisation, c’est à dire quand on leur assigne une valeur pour la première fois. Il est tout-à-fait possible de modifier la valeur d’une variable : cela se fait également avec le symbole =. Pour accéder à une variable définie, il suffit d’utiliser l’identifiant. En fait, on peut toujours substituer l’identifiant à sa valeur. Par exemple, pour assigner à y le double de x, on écrira : 1 y = 2 * x Attention, la variable y dans le code ci-dessous n’est pas liée à x : si on change la valeur de x après, la valeur de y reste inchangée. C’est la valeur de la variable x au moment de l’instruction qui est utilisée. Ceci est vrai partout : si on change la valeur d’une variable, cela n’a aucun effet sur les autres variables. Ceci permet de faire quelque chose d’extrêmement intéressant : modifier une variable en fonction d’ellemême ! Par exemple, pour incrémenter (augmenter d’une unité la valeur) d’une variable x, on utilisera le code : 1 x = x + 1; % ligne de code ultra - courante Types de données Les variables peuvent contenir des données de différents types. En Matlab , les types les plus courants sont : 1. Les nombres : soit entiers (1, 2, -1, . . . ), soit à virgule (1.2, 3.14159, -1e-4, . . . ) 2. les matrices : appelées vecteurs, il s’agit juste de tableaux de nombres Les booléens de Java n’existent pas : on utilise ici des nombres (0 = false, 1 = true). Idem pour les chaines de caractères, qui sont des tableaux de nombres (mais cela ne rentre pas dans le cadre de ce document). La syntaxe pour créer des nombres est très simple, puisque très proche de la notation habituelle. Le signe moins se note par un tiret -, et la virgule séparant partie entière des décimales par un point . (notation américaine). La notation scientifique s’utilise comme ceci : <chiffre>.<décimales>e<exposant>. Ainsi, pour écrire 4.2 · 10−9 , on utilisera 4.2e-9. √ Le nombre imaginaire i = −1 se note simplement i ou j, mais Matlab préfère une notation un peu différente : 1i, afin d’éviter une confusion possible avec une variable i déjà existante (i est un nom courant pour une variable, en particulier dans les itérations). Matlab supporte deux valeurs particulières pour les nombres : Inf (l’infini, éventuellement négatif si on met un tiret devant) et NaN (Not a Number, résultat de la division de l’infini par l’infini, le plus souvent). il s’agit de deux vecteurs lignes ! Cette erreur est sans aucun doute la plus courante (si vous la rencontrez, transposez (’) intelligemment vos vecteurs, ça marche toujours bien). 7 La constante π est également définie par Matlab , sous le symbole pi. La constante e ne bénéficie par du même privilège, mais peut être obtenue avec exp(1) (la valeur de l’exponentielle en 1). Nous aborderons la syntaxe propre aux vecteurs dans le prochain chapitre. Les commentaires : Vous l’avez sans doute remarqué, les codes de ce document contiennent souvent un % suivi de texte en vert. C’est ce qu’on appelle un commentaire, autrement dit du texte qui sera totalement ignoré par Matlab lors de l’exécution du code. Les commentaires permettent d’expliquer ce que vous faites, et de faciliter la compréhension du code. Il est impératif de mettre des commentaires lorsque vous remettez du code pour un cours, ou un projet. . . Nous y reviendrons dans la section 2.6. 2.2.2 Opérateurs Nous savons à présent comment créer et stocker de l’information, sous forme de variables. Voyons à présent comment manipuler cette information. Comme en maths, il existe ce qu’on appelle des opérateurs, comme l’addition ou la multiplication. Le tableau 1 présente les opérateurs les plus courantes : Symbole + * / ˆ Effet Addition Soustraction Multiplication Division Exposant Exemple 42 + 42 = 84 42 - 42 = 0 42 * 42 = 1764 42 / 42 = 1 42 ˆ 42 = 1.5013e+68 Table 1 – Opérateurs principaux de Matlab Avec ces opérateurs, il est déjà possible de se servir de Matlab comme d’une très puissante calculatrice de bureau : 1 2 3 4 5 6 7 8 9 10 11 EDU > > 123456789 ^ 9 ans = 6.6625 e +72 EDU > > 72 /0.000212121 ans = 3.3943 e +05 EDU > > (1+2 i ) ^ 10 ans = 2.3700 e +02 - 3.1160 e +03 i A quoi sert le point-virgule ? En Matlab, le point-virgule détient deux roles. Premièrement, il permet de séparer les instructions, et est en cela équivalent à un retour à la ligne (il est possible d’écrire plusieurs instructions en une ligne en Matlab, mais ça rend en général le code illisible). Deuxièmement, il permet de réguler l’affichage des variables. Lorsqu’on assigne une valeur à une variable (éventuellement nouvelle), en omettant le point-vigule (x = 42), Matlab affiche la valeur assignée. L’usage d’un pointvirgule permet de supprimer cet affichage. La plupart du temps, il faut impérativement utiliser le pointvirgule (en particulier quand vous manipulez des grosses matrices. . . ) ! 8 2.3 Boucles et instructions conditionnelles Le véritable intérêt d’un ordinateur par rapport à un humain, outre sa vitesse de calcul des opérations, est sa capacité à exécuter la même opération un nombre important de fois. Cela se fait grace aux boucles et aux instructions conditionnelles. 2.3.1 Les conditions Les instructions conditionnelles et les boucles reposent le plus souvent sur l’évaluation d’une condition. Une condition est une valeur, la plupart du temps dépendant de variables, qui est soit vraie, soit fausse. En Matlab , il n’existe pas de booléens, autrement dit de valeur spécifique pour vrai ou faux : un nombre est vrai s’il est différent de zéro, et un vecteur est vrai s’il ne contient aucun zéro (mais c’est moins important). En pratique, on définit les conditions à l’aide des opérateurs logiques, qui retournent 0 ou 1 : A == B A > (resp. <) B A >= (resp. <=) B A ~= B ~A A && B A || B égalité : vrai si A et B sont égaux. ordre : vrai si A est plus grand (resp. petit) que B. ordre et égalité : vrai si A est plus grand (resp. petit) ou égal à B. différence : vrai si A est différent deB. NON logique : vrai si A est faux. ET logique : vrai si A et B sont vrais. OU logique : vrai si A ou B est vrai. Table 2 – Opérateurs logiques de Matlab Attention, notez que si A et B dont des vecteurs de même dimension 9 dans les opérations ci-dessus, le résultat est un vecteur dont l’élément i correspond au résultat de A(i) <opération> B(i). L’exemple ci-dessous illustre ces opérations : 1 2 3 4 5 6 7 8 9 10 11 EDU > > pi > 3 ans = 1 EDU > > [1 2 3] ~= [0 2 2] ans = 1 0 1 EDU > > [1 2 3] >= 2 ans = 0 1 1 L’égalité entre nombres réels : il faut faire extrêmement attention lorsqu’on utilise == entre deux nombres réels (dits à virgule flottante). Pour des raisons informatiques, les nombres à virgule ne sont pas parfaitement stockés dans la mémoire. Ainsi, deux expressions qui sont mathématiquement équivalente, comme 0.3 et 0.1 + 0.1 + 0.1 sont différentes dans Matlab (faites le test !). Une solution est d’employer des inégalités quand c’est possible. La vraie solution académique est de vérifier que la différence des valeurs à comparer est inférieure en valeur absolue à une certaine tolérance : 1 abs ( A - B ) < tol ; % tol = 1e -6 , par exemple 9. B peut éventuellement être un scalaire. 9 2.3.2 Les instructions conditionnelles : if et else Une instruction conditionnelle est l’équivalent d’un si dans le code : si une certaine condition est vraie, alors fais ceci ; sinon, fais cela. La syntaxe est élémentaire : 1 2 3 4 5 6 7 if condition1 % (1) faire quelque chose elseif condition2 % (2) faire autre chose else % (3) dernier recours end L’instruction (1) ne sera exécutée que si condition1 est vrai. Si condition1 est fausse, alors le code continue dans l’instruction conditionnelle, et évalue condition2. Si celle-ci est vraie, alors l’instruction (2) est exécutée. Sinon, l’instruction (3) est exécutée. Il est possible de mettre plusieurs instructions elseif à la suite. L’instruction else finale n’est pas obligatoire, pas plus que les elseif. Notez que les clauses sont exclusives : elles ne peuvent jamais s’exécuter en même temps. Voici, pour illustrer les instructions conditionnelles, un code assignant à la variable M le maximum entre A et B : 1 2 3 4 5 if A > B M = A; else M = B; end Petite note sur l’indentation Le code à l’intérieur d’une instruction conditionnelle est indenté : on a ajouté des espaces (ou une tabulation) devant le code, pour bien faire comprendre que ce code est à l’intérieur d’une partie du code total. Cette pratique augmente grandement la lisiblité du code, et est presque obligatoire ! 2.3.3 La boucle while Une boucle est un mécanisme extrêmement important en programmation. Elle se compose de deux éléments : 1. Une série d’instructions, qui seront exécutées à chaque itération de la boucle. 2. Une condition d’arrêt régissant la boucle : celle-ci se termine lorsque la condition devient fausse. Cela se traduit simplement dans la syntaxe de la boucle while : 1 2 3 while condition % instructions end Cette boucle est très utile pour les méthodes itératives. Boucles infinies : si la condition d’arrêt est toujours vraie, alors la boucle peut ne jamais s’arrêter (en pratique, il suffit d’appuyer sur Control + C dans la commande interactive pendant l’exécution du code pour interrompre celle-ci). Les boucles infinies sont évidemment très ennuyantes, et parfois très difficiles à dépister. Voici deux exemples de boucles infinies, l’une évidente, l’autre moins : 10 1 2 3 4 5 6 7 while 1 end % 1 est toujours vrai ! a = 0.1; while a ~=1.0 a = a + 0.1; end La seconde boucle infinie résulte du problème concernant l’égalité entre réels, que nous avons abordé plus haut. Une bonne pratique pour éviter les boucles infinies est d’utiliser une variable contenant le nombre d’itérations effectuées, et vérifier que ce nombre est inférieur à une certaine valeur : 1 2 3 4 5 n = 0; while conditon && n < NMAX % NMAX = 1000 , par exemple % instructions n = n + 1; end 2.3.4 La boucle for La boucle for est l’autre mécanisme de boucles de Matlab . Elle est très différente de la boucle while, et est beaucoup plus simple. Elle se limite à une opération très simple : parcourir un vecteur. La syntaxe est élémentaire : 1 2 3 for x = vecteur % instructions , ou x prend successivement la valeur des elements du vecteur end La boucle for est en fait équivalente à cette boucle while : 1 2 3 4 5 6 i = 1; while i <= length ( vecteur ) x = vecteur ( i ) ; % instructions i = i + 1; end Cette boucle permet très facilement de réaliser des opérations sur les vecteurs. Malheureusement, elle n’est pas toujours optimale, et il est souvent plus efficace de manipuler directement les vecteurs plutot que de les traiter élément par élément. Nous aborderons la syntaxe propre aux vecteurs dans le prochain chapitre : dans un premier temps, savoir manipuler la boucle for est amplement suffisant. 2.4 Les fonctions Une fonction, en Matlab , est en quelque sorte l’équivalent d’une fonction mathématique : une entité qui, pour une certaine entrée (les arguments), sort des valeurs (les valeurs de retour). Tout comme les variables, les fonctions portent un nom. 11 2.4.1 Syntaxe des fonctions Quand vous créez une nouvelle fonction avec le logiciel Matlab , vous obtenez déjà un gentil code de base qui révèle directement la syntaxe à respecter. Vous devriez avoir un truc du genre : 1 2 3 4 5 function [ output_args ] = Untitled ( input_args ) % UNTITLED Summary of this function goes here % Detailed explanation goes here end Une fonction commence toujours par le mot-clé function et finit toujours par end. Après function on met le nom de la/des variable(s) retournée(s), séparées par une virgule. Suit ensuite le signe = puis le nom de la fonction suivie à son tour du nom des variables d’entrée, séparées par une virgule. Cet ensemble forme la définition de la fonction. Pour finir, il y a un paragraphe de commentaires qui donne des explications sur l’utilisation de la fonction (un peu comme le mode d’emploi). Ce texte n’est pas indispensable en théorie pour que la fonction fonctionne correctement, mais il est quand même recommandé de l’écrire : il s’agit de la documentation sur votre fonction (plus de détails là-dessus dans la section 2.6 sur les commentaires). Tout le code compris entre la définition de la fonction et le end final est le code de la fonction : il est exécuté à chaque appel de la fonction. Un appel de fonction est l’utilisation de cette fonction : cela se fait en adjoignant des parenthèses contenant √ les valeurs que vous voulez donner aux arguments au nom de la fonction. Par exemple, pour calculer 2, on appelle la fonction sqrt avec l’argument 2 : result = sqrt(2). Tout le code de la fonction est exécuté à chaque appel : contrairement à de nombreux langages de programmation, l’exécution ne s’arrête pas lorsqu’on assigne une valeur de retour (il n’y pas vraiment de return en Matlab ). Les valeurs de retour doivent être créées (ce sont des variables) lors de l’exécution. A titre d’exemple, voici une fonction qui prend en argument deux nombres (ou vecteurs) et les additionne : 1 2 3 4 function [ C ] = addition ( A , B ) % ADDITION retourne la somme de A et B C = A + B; end Un appel à cette fonction pourrait se faire comme ceci : 1 R = addition (1 , 2) ; Il est de bonne pratique d’indenter le code à l’intérieur des fonctions, pour augmenter la lisibilité. 2.4.2 Plusieurs valeurs de sortie, plusieurs arguments Il est possible de fournir plusieurs valeurs de sortie à la fonction : cela se fait en définissant plusieurs identifiants de variables, séparés par des virgules, entre les crochets suivant function. Par exemple, on pourrait modifier la fonction addition pour qu’elle retourne en plus le produit des deux nombres : 1 2 3 4 5 function [ C , D ] = addition ( A , B ) % ADDITION retourne la somme et le produit de A et B C = A + B; D = A * B; end Pour récupérer plusieurs valeurs de sortie, il faut utiliser des crochets autour des identifiants des variables de sortie : 1 [ Somme , Produit ] = addition ( 1 , 2 ) ; 12 Si on emploie pas assez d’arguments à l’entrée, et que l’argument est utilisé par le code de la fonction (s’il ne l’est pas, c’est anormal !), Matlab soulève une erreur. De même, si on essaye de récupérer une valeur de sortie qui n’est pas définie par la fonction (par exemple, si le programmeur s’est trompé), Matlab soulève également une erreur. Des arguments spéciaux : les options De nombreuses fonctions de Matlab prennent comme argument des options, c’est à dire des arguments facultatifs composés d’un nom (une chaine de caractère) et une valeur (notez donc qu’il s’agit de deux arguments distincts). Par exemple, la fonction plot (qui dessine des graphes, voir chapitre 4) permet de spécifier le style des lignes avec l’option LineStyle, de la manière suivante : 1 plot (x , y , ’ LineStyle ’ , ’ -- ’) ; Pour aller plus loin Il est possible de savoir quel est le nombre d’arguments fournis à l’entrée et le nombre de valeurs de retour demandées lors d’un appel à la fonction, via les variables nargin et nargout. Ceci sort un peu du cadre de ce document, et est fourni à titre strictement indicatif. Notez que de très nombreuses fonctions Matlab emploient ces techniques pour plus de flexibilité. Nous allons modifier la fonction addition de sorte que : — Elle accepte de n’avoir qu’un seul argument. Elle calcule alors le double et le carré de son argument. — Elle ne calcule pas le produit si on ne récupère pas explicitement cette valeur. Le code de la fonction devient donc : 1 2 3 4 5 6 7 8 9 10 11 function [ C , D ] = addition ( A , B ) % ADDITION retourne la somme de A et B % si B n ’ est pas fourni , la fonction considere que B = A if nargin == 1 B = A end C = A + B; if nargout == 2 D = A * B; end end Voici quatre appels différents à cette nouvelle fonction, tous valides : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 EDU > > S = S = 7 EDU > > [S , S = 7 P = 12 EDU > > S = S = 10 EDU > > [S , S = 10 addition (3 , 4) P ] = addition (3 , 4) addition (5) P ] = addition (5) 13 15 16 P = 25 Et les appels récursifs ? Matlab ne supporte pas la récursion terminale. Les appels récursifs (lorsque la fonction s’appelle elle-même) sont à éviter tant que possible. Fonctions utiles de Matlab 2.4.3 Pour conclure cette section sur les fonctions, voici une petite liste de fonctions qui vous seront utiles dans le cadre du cours de Méthodes Numériques, et/ou par la suite. Les explications fournies pour chaque fonction sont très courtes, et décrivent un seul des comportements possibles de la fonction. Pour plus d’information, nous vons invitons à consulter la documentation (help nom_de_la_fonction dans la commande interactive). Identifiant cos(X), sin(X), tan(X) sqrt(X) abs(X) acos(X), atan(X) asin(X), polyfit(X, Y, N) polyval(P, X) spline(X, Y, t) roots(P) fzero(FUN, X0) [V, D] = eigs(A, K) ode45(ODEFUN, TSPAN, Y0) Description Les fonctions trigonométriques classiques. Leur argument peut être un vecteur de complexes. La racine carrée (SQuare RooT ). Son argument peut être un vecteur de complexes, éventuellement négatifs. La valeur absolue. Pour les complexes, ceci calcule la norme de chaque complexe (à ne pas confondre avec norm(X) qui retourne la norme totale du vecteur !). L’inverse des fonctions trigonométriques. Leur argument peut être un vecteur de complexes (notez que Matlab manipule très facilement les complexes, et donc utiliser des valeurs sortant des domaines réels de ces fonctions ne provoque pas d’erreur : essayez acos(2)). Retourne les coefficients d’un polynome de degré N passant au mieux (au sens des moindres carrés) par les points (X, Y). Si N < length(X), le polynome retourné passe exactement par les points. retourne la valeur du polynome représenté par les coefficients P en les points X. retourne la valeur de l’interpolation par splines cubiques des points (X, Y) en les abscisses t Retourne un vecteur contenant toutes les racines complexes du polynome représenté les coefficients P. Les racines multiples sont présentes plusieurs fois, de sorte que la taille du vecteur est toujours le degré du polynome moins un. Retourne une racine de la fonction FUN (passée en argument sous forme de function handle : mettez un @ devant le nom), en commençant la recherche à partir de l’abscisse X0. Recherche de valeurs propres (eigenvalues) : la matrice D contient les K plus grandes valeurs propres de A dans sa diagonale, et V contient K vecteurs propres correspondants à ces valeurs propres. Résolution d’équations différentielles ordinaires. Son utilisation est décrite dans le chapitre 5.1. Table 3 – Quelques fonctions utiles de Matlab 2.5 Débugger votre code Matlab Vous découvrirez malheureusement vite qu’un code Matlab ne fonctionne quasi jamais (correctement) du premier coup, même pour le meilleur des informaticiens ! Une fois que vous aurez constaté avec consternation que votre joli code ne donne pas le résultat attendu, il va falloir se mettre à la recherche des erreurs de 14 programmation commises, communément appelées bugs. La mauvaise nouvelle, c’est qu’un code est parfois long et complexe et il est difficile de trouver ou se cachent ses failles en regardant juste le résultat final du code. La bonne nouvelle, c’est que le logiciel Matlab offre de nombreux outils permettant de faciliter la recherche de bugs. 2.5.1 Le point-virgule D’habitude, toutes les lignes Matlab se terminent par un point-virgule ( ;). Pourtant, ces points-virgules (semicolon en anglais) ne sont pas indispensables au bon fonctionnement du programme 10 : elles permettent par contre de masquer le résultat de l’opération. Si vous enlevez ce point-virgule, Matlab affichera le résultat numérique de l’opération concernée dans la console. Souvent, tous ces résultats intermédiaires ne nous intéressent pas (d’où l’habitude de mettre un pointvirgule à la fin de chaque instruction). Mais dans une traque au bugs, on peut utiliser ces résultats intermédiaires pour vérifier le bon fonctionnement de chaque petit bout de code étape par étape (plutôt que de devoir vérifier le fonctionnement de tout le code d’un coup), ce qui permet de localiser rapidement l’emplacement du bug. Attention toutefois de ne pas oublier de remettre les point-virgules que vous avez supprimé avant de rendre votre code. . . 2.5.2 Quelques fonctions pour afficher vos résultats Afficher le résultat de chaque calcul effectué par Matlab c’est bien, mais ce n’est pas toujours la valeur que l’on souhaite vérifier (et en plus, c’est un peu moche comme manière de procéder). Bonne nouvelle, Matlab regorge de fonctions diverses permettant de vérifier le bon déroulement d’une suite de calculs. Une fonction qui est extrêmement utile est disp. Comme son nom l’indique très bien, disp(var) affiche le contenu de la variable var. Comme on travaille souvent avec des matrices assez grandes, il est parfois difficile de conclure quelque chose en faisant un simple disp sur ladite matrice : 3 tonnes de chiffres qui se suivent peuvent être compliqués à interpréter. Pour de telles matrices, on peut utiliser spy. spy affiche dans une jolie petite image la matrice de la manière suivante : les entrées non-nulles sont représentées par un petit point, tandis que les entrées nulles restent une case blanche. Ce qui permet de rapidement visualiser quelles entrées de la matrice sont non-nulles, et comprendre ce qui s’y passe. 2.5.3 Mesurer le temps d’exécution du code Parfois, il arrive que vous finissiez votre code, que celui-ci marche et soit paré à toute entrée vicieuse. . . à ce moment, vous vous demanderez sans doute ce que vous allez faire de votre vie maintenant que tout est fini. . . Mais j’ai une bonne nouvelle pour vous ! Une fois votre code terminé, vous pourrez améliorer les performances de celui-ci pour le rendre encore plus rapide ! Alléchant n’est-il pas ? Blague à part, les performances temporelles d’un programme sont un critère important et il est donc important de rendre votre programme le plus rapide possible ! Pour cela, il faut savoir mesurer le temps d’exécution de votre code pour voir comment ce temps évolue avec les modifications que vous apportez à votre code. Pour cela, Matlab possède une fonction (en fait, deux fonctions) pour chronométrer votre temps et battre tous les records : tic et toc. Quand Matlab rencontre l’instruction tic, il lance un chronomètre. Quand il rencontre toc, il arrête le chronomètre et renvoie le temps écoulé entre tic et toc. 2.5.4 Programmer défensivement Programmer défensivement, c’est écrire du code tel qu’il est protégé des attaques des utilisateurs. Les attaques, ce sont des arguments invalides : un vecteur colonne à la place d’un vecteur ligne, un entier négatif au lieu d’un entier positif. . . 10. Rien à voir donc avec les points-virgules indiquant la fin d’une instruction en Java ou en C par exemple. 15 Un code est dit robuste si, lorsqu’on lui fournit un argument invalide, le code ne crashe pas, autrement dit, agit de manière controlée. En Matlab, le plus simple est d’ajouter des clauses if au début du code, vérifiant la validité des arguments. S’ils ne le sont pas, il suffit d’employer la fonction de base error, assortie d’une chaine de caractères informant l’utilisateur de l’erreur qu’il a commise. Si c’est possible, ce peut être une bonne idée de corriger l’erreur : l’exemple le plus simple est l’emploi d’un vecteur ligne à la place d’un vecteur colonne, résolu par une simple transposition. Notez que, pour vérifier si un vecteur ligne ou colonne, il existe deux fonctions : isline et iscolumn. 2.6 Un petit commentaire sur l’utilisation de commentaires Ecrire du code qui fonctionne, c’est bien. Mais écrire du code qui fonctionne et qui est compréhensible facilement, c’est mieux, surtout quand ce code va être lu, par exemple par un correcteur. . . Il existe un certain nombre de réflexes qui rendent votre code plus agréable à lire, et permettent de rendre votre tuteur/tutrice plus heureux/heureuse. Les commentaires : partout, toujours Un code sans commentaire est un code incompréhensible. Les commentaires doivent accompagner le code, expliquer de manière simple ce qu’il fait, décrire le role des différentes variables et fonctions définies. Attention qu’il ne faut pas verser dans l’excès ! Trop de commentaires rend le code illisible, parce que trop chargé. En particulier, évitez de mettre un commentaire entre chaque instruction : groupez les instructions et les commentaires, afin de permettre une visualisation plus facile de l’exécution. Les commentaires décrivant une fonction, qui suivent directement la signature de la fonction (son nom), sont obligatoires. Il s’agit du seul moyen pour celui qui utilise votre fonction de comprendre ce qu’elle fait. Ces commentaires doivent décrire le role de la fonction, quels arguments sont attendus (par exemple, deux vecteurs de même taille et un entier positif), et quelles seront le ou les valeur(s) de sortie. Nommez vos variables convenablement Le nom (l’identifiant) d’une variable doit permettre de comprendre facilement ce que représente cette variable. Un nom de variable comme var, ou fonction est donc à proscrire ! Aussi, il vaut mieux, en général, éviter les noms de variables en un seul caractère, mais en Matlab, cela ne cause pas de réel problème, les codes étant relativement courts. Aussi, les noms de variable comme currentIterationNumber peuvent paraitre une bonne idée sur papier, mais sont en pratique beaucoup trop lourds. Comme pour les commentaires, il faut trouver un juste milieu entre trop court et trop long. Toutefois, en Matlab, les codes sont souvent fortement liés à des formules mathématiques : les variables correspondent donc à des variables mathématiques. Utiliser comme identifiant le nom de la variable mathématique (u, x, theta, . . . ) est une bonne pratique, car cela facilite le parallèle entre les formules et le code. N’oubliez pas, cependant, de préciser à quoi correspondent les variables par des commentaires. Ainsi, pour l’angle d’un pendule, par exemple, il vaut mieux employer theta, plutot que a ou angleDuPendule. Bien nommer ses variables est le plus souvent une simple question de bon sens ! L’indentation : son absence est un crime Pour rappel, indenter du code consiste à mettre des espaces (ou des tabulations) devant les lignes de code se trouvant dans un bloc de code (if, while, function, for, . . . ). L’indentation permet de distinguer immédiatement le code appartenant au bloc, et facilite énormément la lecture du code ! Comme l’éditeur de Matlab indente automatiquement le code, vous n’avez donc aucune excuse pour ne pas indenter votre code ! Aérez votre code Les espaces, en Matlab, ne changent rien : ainsi, x=0 ; est strictement équivalent à x = 0 ; . Ajouter des espaces permet d’aérer le code, donc augmenter la lisibilité, sans rendre le code plus difficile à comprendre. 16 Les lignes vides ne modifient pas le comportement du code, et permettent de diviser le code en paragraphes, pour simplifier la lecture. Par exemple, il est intelligent de regrouper les déclarations de variables, en les séparant des opérations. Aussi, même si Matlab le permet, évitez d’écrire plusieurs instructions en une ligne (en les séparant par des point-virgules) : cela rend le code assez difficile à lire. N’oubliez pas vos point-virgules . . . Vérifiez toujours que vous n’avez pas oublié des point-virgules quand vous assignez une valeur à une variable : sauf si explicitement précisé, vos fonctions ne doivent jamais afficher quoi que ce soit lorsque vous les lancez (à part éventuellement un warning). Un petit exemple Voici, pour vous convaincre que ces règles sont essentielles (et devraient être un réflexe !). Essayez de comprendre le code suivant, qui est écrit de la façon la plus illisible possible : 1 2 3 4 5 6 7 8 9 function [ res ] = fonction1 ( x1 , x2 , x3 ) a = x2 * x2 ; b =4* x1 * x3 ; if a == b res =[ - x2 /(2* x1 ) ] else v = sqrt (a - b ) res =[( - x2 - v ) /(2* x1 ) ,( - x2 + v ) /(2* x1 ) ] end end Et voici le code corrigé, en tenant en compte les règles : 1 2 3 4 5 6 7 8 9 10 11 12 function [ x0 ] = polynome2roots (a , b , c ) % trouve les racines du polynome a * x ^2 + b * x + c % ceci retourne un vecteur contenant les racines distinctes rho = b * b - 4* a * c ; % si racine double : une seule valeur if rho == 0 x0 = [ - b /(2 * a ) ]; else sqrho = sqrt ( rho ) ; % calcul unique de la racine de rho x0 = [ ( - b - sqrho ) /(2* a ) , ( - b + sqrho ) /(2* a ) ]; end end Plus clair, n’est-ce-pas ? 3 Opérations sur les vecteurs Les vecteurs, c’est un des plus gros points forts de Matlab : il est très facile 11 de créer et manipuler ceux-ci (et pour cause ! Matlab est l’acronyme de Matrix Laboratory). Nous ne vous feront pas l’affront de vous rappeler ce qu’est un vecteur en mathématiques, mais avec Matlab , le mot "vecteur" désigne uniquement les structures de données (en d’autres mots, les matrices). Plus concrètement, on peut voir un vecteur comme comme un tableau à deux dimensions de nombres. Comme pour les variables classiques (qu’on peut voir comme les plus petits vecteurs possibles), il n’est pas nécessaire de déclarer un vecteur 12 , il sera crée automatiquement la première fois qu’on lui assigne une valeur. 11. Essayez un peu de traduire un code Matlab en C, par exemple. Le nombre de lignes de codes est multiplié par 10. . . 12. Même si il convient parfois de faire de la pré-allocation, on y reviendra. 17 3.1 3.1.1 Créer ses propres vecteurs Syntaxe propre aux vecteurs Matlab propose une syntaxe simple pour créer des vecteurs, qui se compose de trois (en fait, quatre) symboles : 1. les crochets [ ] : ils délimitent le début et la fin du vecteur 2. la virgule , : elle sépare les éléments d’une ligne 3. le point-virgule ; : il sépare les différentes lignes Ainsi, pour créer la matrice (de la vie de tous les jours) π 217.3 √1 A = 2 42 i −1 1042 6.626 · 10−34 On utilisera le code : 1 A = [1 , pi , 2^17.3; sqrt (2) , 42 , 1 i ; -1 , 1 e42 , 6.626 e -34] La syntaxe est même plus simple que ça : la virgule est en fait facultative. On peut tout à fait la remplacer par un espace, ce qui augmente la lisibilité du code dans certains cas. Il est aussi possible d’effectuer un retour à la ligne (touche ENTER) à la place de mettre un point-virgule. 3.1.2 Fonctions de création de vecteurs Cette manière de faire fonctionne bien pour des petits vecteurs (par exemple, si vous voulez résoudre un petit système linéaire). Toutefois, elle s’avère très vite fastidieuse si vous devez manipuler des vecteurs plus grands (et donc, plus intéressants). Imaginez créer une matrice unité de taille 20 fois 20. . . De plus, il arrive souvent qu’on ne puisse déterminer la taille d’un vecteur que lors de l’exécution du code. Par exemple, cette syntaxe de permet pas de créer une fonction retournant une matrice unité de taille n passée en argument. Heureusement, Matlab offre une solution à ce problème : un ensemble de fonctions permettant de créer des vecteurs particuliers. Ces fonctions sont très largement utilisées et il n’y pas d’autre solution que de les mémoriser. . . Voici, en vrac, une série de fonctions qui vous seront éventuellement utiles (surtout les trois premières) 13 : Fonction linspace(a, b, n) zeros(l, c) ones(l, c) eye(l, c) diag(V, k) magic(n) rand(m, n) Valeur de retour Vecteur ligne dont les n éléments sont répartis linéairement entre a et b inclus Matrice l × c remplie de zéros. Matrice l × c remplie de uns. Matrice l × c dont la diagonale est remplie de uns (matrice unité si l=c). Si V est un vecteur de taille n, une matrice n + k × n + k dont la ki`eme diagonale est le vecteur V. Un carré magique de taille n × n Matrice m × n rempli de nombres aléatoires entre 0 et 1. Table 4 – Fonctions essentielles pour créer des vecteurs Notez qu’il existe une syntaxe alternative à linspace : [a : dx : b], qui génère un vecteur contenant toutes b les valeurs a + i · dx, 0 ≤ i ≤ dx (autrement dit, toutes les valeurs entre a et b séparées de dx). Faites attention que si l’écart entre a et b n’est pas un multiple de dx, b ne sera pas inclus dans le vecteur. La valeur 13. Un carré magique de taille n est une matrice n×n contenant exactement une fois tous les nombres de 1 à n2 , dont la somme de chaque ligne, colonne ou diagonale est toujours la même. Hé oui, c’est magique. Essayez un peu magic(20000). 18 par défaut de dx est 1, ce qui permet très facilement de créer des vecteurs de nombres entiers (par exemple, 1:5 contient les entiers entre 1 et 5 inclus). Les crochets sont facultatifs, ici, mais il est recommandé de les ajouter. 3.1.3 Adjonction de vecteurs Un dernier outil pour créer des vecteurs est l’adjonction de vecteurs. Ceci est similaire aux opérations par blocs en mathématiques : on peut représenter une matrice par les différentes sous-matrices qui la composent. Le bonne nouvelle, c’est que la syntaxe est exactement la même que pour la création de matrices : des virgules pour séparer les blocs horizontalement, et des point-virgules pour les séparer verticalement. Voici un exemple : 1 2 3 4 A B C R = = = = [2 , [4; [5 , [1 , 3]; % 7]; % 6; 8 , A; B, vecteur ligne vecteur colonne 9]; % matrice carree C ]; % adjonction La mauvaise nouvelle, c’est qu’il faut prendre beaucoup de précautions quant aux dimensions des vecteurs concernés. Ça parait simple, mais les erreurs sont très fréquentes, et les insultes de Matlab qui s’ensuivent ne sont pas très explicites. Si on échange A et B dans la dernière ligne du code ci-dessus, Matlab nous dit ceci : 3.2 3.2.1 Manipuler des vecteurs Accès aux éléments L’accès aux éléments d’un vecteur est une opération extrêmement courante, et la syntaxe qui l’implémente est à la fois simple et très puissante. Par accéder à un élément, on entend lire la valeur d’un élément, ou d’un sous-groupe d’éléments, d’un vecteur, mais également la modifier. Tout d’abord, pour accéder au i e`me élément d’un vecteur à une dimension (indifféremment ligne ou colonne), il suffit d’adjoindre une paire de parenthèses contenant l’indice de l’élément à l’identifiant du vecteur : x(i). Ceci est appelé un accès en lecture. Attention, contrairement à la plupart des langages de programmation, Matlab numérote ses vecteurs à partir de 1, et non de 0. Le premier élément est donc celui d’indice 1, et le dernier d’indice égal à la longueur du vecteur. Pour assigner la valeur du ie`me élément d’un vecteur x à 42, on emploiera le code : 1 x ( i ) = 42; Nous appelerons ceci un accès en écriture. Notez que cette syntaxe est la même que celle utilisée pour assigner une valeur à une variable. On peut en fait traiter les éléments d’un vecteur comme des variables. Accès aux éléments. . . pas dans le vecteur ! Lorsqu’on tente d’accéder en lecture à un élément dont l’indice est plus grand que la taille du vecteur, Matlab soulève une erreur : Index exceeds matrix dimensions. Par contre, si on accède en écriture à un élément, il n’y a pas de problème : Matlab agrandit le vecteur, ajoutant des zéros entre la fin du vecteur et l’emplacement désiré (qui sera lui assigné à la valeur demandée). Cette pratique permet de créer plus simplement des vecteurs via des boucles mais est toutefois à éviter, pour des raisons que nous aborderons plus loin. 19 Cette syntaxe fonctionne également avec les matrices, mais de manière plus obscure, et rarement utile. Les éléments d’une matrice sont numérotés en partant du haut à gauche, en descendant le long de la première colonne, puis de la deuxième, et ainsi de suite : 1 4 7 2 5 8 3 6 9 Pour les matrices, on peut accéder à un élément en spécifiant simplement sa ligne et sa colonne, séparées d’une virgule. C’est la forme d’accès la plus utilisée sur les matrices. Elle est illustrée par le code ci-dessous : 1 2 3 4 5 6 7 EDU > > EDU > > EDU > > EDU > > A = eye (3) ; A (1 , 2) = 42; A (3 , 1) = -1; disp ( A ) % affichage de A 1 42 0 0 1 0 -1 0 1 Une forme d’accès plus sophistiquée consiste à accéder à des sous-matrices à l’intérieur des matrices (des groupes d’éléments). Cela se fait en utilisant des vecteurs d’indice. En d’autres termes, si x est un vecteur de nombres entiers, alors A(x) retourne un vecteur contenant les éléments de A aux indices spécifiés par x. Employer un vecteur x quelconque n’est que rarement utile, et en pratique on emploie souvent des vecteurs de la forme a:b, avec a le premier indice et b le dernier. Cela permet d’obtenir tous les éléments d’indice compris entre a et b. Notez qu’on peut également employer cette forme d’accès sur les lignes et les colonnes d’une matrice. 1 2 3 4 5 6 7 8 9 10 11 12 EDU > > A = eye (3) ; EDU > > B = [1 2 3 4 5]; EDU > > disp ( B (2:4) ) ; 2 3 4 EDU > > disp ( A (2:3 , 1:2) ) 0 1 0 0 EDU > > disp ( A (2:3 , 1) ) 0 0 Enfin, il existe une syntaxe spéciale pour deux situations : 1. L’accès à tous les éléments de i au dernier : A( i:end ) 2. L’accès à tous les éléments : deux points A(:) (équivalent à A( 1:end ) ) Cette syntaxe permet d’accéder facilement à une colonne ou une ligne d’une matrice : 1 2 A ( i , : ) % acces a la ligne i A ( : , i ) % acces a la colonne i 3.2.2 Opérations sur un vecteur Opérations spéciales Des multiples opérations sur un seul vecteur que Matlab supporte, trois sont particulièrement utiles : 20 — A’ : la transposition. Les matrices de mauvaise dimension causent très souvent des erreurs en Matlab , et la plupart du temps une simple transposition suffit à résoudre les problêmes. D’ou l’emploi d’une syntaxe facile : le guillemet. — inv(A) : l’inversion. Bien qu’à éviter pour résoudre les systèmes en Matlab , l’inversion reste une opération capitale. Attention que si la matrice n’est pas inversible, Matlab affiche un Warning et renvoie une valeur absurde. — reshape(A, M, N) : changement de forme d’une matrice. Ceci permet de passer d’une matrice à un vecteur, et inversément, et sera utile pour le cours de méthodes numériques. La matrice résultante comprendra M lignes et N colonnes. Dimension d’un vecteur A ce stade, on peut s’intéresser à la façon de récuperer la dimension d’un vecteur. Deux fonctions sont à notre disposition : size et length. size retourne deux valeurs : le nombre de lignes et de colonnes du vecteur passé en argument. On peut donc récupérer le nombre de lignes de A en faisant x = size(A) pour stocker la taille de A dans le vecteur x, puis en écrivant x(1). length devrait être utilisée exclusivement sur les vecteurs à une dimension (des vecteurs lignes ou colonne) : il donne le nombre d’éléments d’un tel vecteur à une dimension. Mais si on donne à length un vecteur à plusieurs dimensions, il retournera le nombre de lignes de ce vecteur. C’est pourquoi nous vous conseillons d’utiliser length pour les vecteurs à une dimension et size sinon. En conclusion, voici un petit bout de code qui montre le comportement de ces deux fonctions. 1 2 3 4 5 6 7 8 9 10 >> A = [[1 5 3];[7 8 9];[2 8 9];[2 3 2]] ; >> B = 8:11 ; >> disp ( size ( A ) ) % 4 lignes et 3 colonnes 4 3 >> disp ( size ( B ) ) % La valeur retournee est un VECTEUR 1 4 >> disp ( length ( A ) ) % !! A est a 2 dimensions = > pas ideal 4 >> disp ( length ( B ) ) % Il s ’ agit du nombre de colonnes de B ! 4 Fonctions agrégatives On désigne par fonctions agrégatives toutes les fonctions qui, pour un vecteur à une dimension en argument, sortent un nombre. Les plus utiles sont illustrées dans le code suivant : 1 2 3 4 max ( X ) ; min ( X ) ; mean ( X ) ; sum ( X ) ; % % % % maximum des elements minimum des elements moyenne des elements somme des elements Si on donne une matrice en argument à ces fonctions, elles retournent un vecteur ligne contenant le résultat de l’opération sur chaque colonne. Pour faire la somme de tous les éléments d’une matrice, il faut donc faire sum( sum( A ) ). 3.2.3 Opérations entre vecteurs En général, c’est ici que beaucoup d’erreurs vont apparaître, et pour cause : les vecteurs impliqués dans l’opération courante n’ont pas les bonnes dimensions. Ca parait idiot, mais c’est sans aucun doute l’erreur la plus courante sur Matlab. Faites donc toujours bien attention à la compabilité entre vecteurs avec l’opérations que vous utilisez (un bout de papier et un crayon font parfois des miracles pour ça). Voici les opérations de base entre vecteurs supportées par Matlab. La dernière commande est l’une des plus utiles de Matlab : elle permet de résoudre un système linéaire A*x = b. 21 1 2 3 4 5 A + B; A - B; A * B; x = A\b; % % % % % addition de A et B ( etonnant non ?) ! A et B doivent avoir la meme taille multiplication MATRICIELLE entre A et B il faut que # col de A = # lin de B x est une colonne contenant la solution de A * x = b Petite note sur A\b : Cet opérateur est sans aucun doute celui que vous utiliserez le plus souvent sur Matlab . . . Mais que fait-il vraiment ? x = A\b résoud l’équation A * x = b de la manière la plus efficace possible. Toutefois, cela n’est vrai que si le système admet une et une seule solution ! Il est en cela équivalent à x = inv(A) * b, qui est à éviter à tout prix. Pourquoi ? Tout d’abord, c’est contre-efficace : il faut faire plus d’opérations en inversant puis en multipliant qu’en résolvant. Ensuite, inverser une matrice est numériquement instable, et conduit à des erreurs. Enfin, pas de résolution si la matrice n’est pas inversible ! En utilisant A\b, Matlab se comporte intelligemment si le système n’est pas régulier. Si le système n’admet pas de solution, Matlab le résoud au sens des moindres carrés (Ce qui est bien souvent ce que l’on recherche) ! Par contre, si le système admet plusieurs solutions, Matlab vous affiche un Warning : Matrix is singular to working precision, et vous sort un vecteur rempli de NaN (ou avec quelques nombres, s’ils sont les mêmes pour toutes les solutions). . . 3.2.4 Opérations élément par élément Parfois, on aimerait effectuer une opération entre les éléments de deux vecteurs plutôt qu’entre les deux vecteurs : par exemple, on souhaite multiplier le premier élément d’un vecteur avec le premier élément d’un autre vecteur, puis le second élément du premier vecteur avec le second élément du deuxième, etc. . . Cela est possible avec Matlab en utilisant les element-wise operations, les opérations "élément par élément". Attention, il faut bien sûr que les deux vecteurs soient de même dimension. Ces opérations s’obtiennent facilement en rajoutant un point devant le symbole de l’opération. Quelques exemples : 1 2 3 4 5 x = [1 3 5]; y = [2 0 1]; x .* y ; y ./ x ; x .^ y ; x .^2; 3.3 % % % % % quelques vecteurs pour s ’ amuser calcule [1*2 3*0 5*1] = [2 0 5] [2 0 0.2] [1 1 5] ( exposant element par element ) [1 9 25] : cela fonctionne aussi ! Les vecteurs Like A Boss Pour employer Matlab de la manière la plus efficace (avec des codes les plus rapides) possible, il est essentiel de savoir utiliser les vecteurs correctement. C’est l’objectif de cette section : apprendre à employer les vecteurs Like A Boss. 3.3.1 La vectorisation La première étape pour apprendre à employer Matlab correctement est de penser en termes de vecteurs. L’emploi extensif de vecteurs s’appelle la vectorisation, et se base sur 4 concepts clés : 1. toutes les fonctions à une variable prennent en argument un vecteur (sqrt, exp, sin, . . . ) 2. l’emploi des fonctions agrégatives (sum, mean, . . . ) 3. l’emploi du produit matriciel et des opérations élément par élément 4. l’emploi de fonctions de création de vecteurs pour générer efficacement des vecteurs 22 Plus simplement, il existe une règle (presque) d’or : employer le moins possible de boucle for. Bien souvent, une boucle for a pour but de parcourir les éléments d’un vecteur, ce qui est une opération assez lente qui peut la plupart du temps (mais pas toujours) se remplacer par une ou plusieurs opérations vectorielles. Les codes vectorisés sont souvent plus courts, et presque toujours plus rapides, mais en général, plus compliqués à écrire et à comprendre. Ecrire du code vectoriel demande une certaine pratique. Pour illustrer cette idée, voici quelques exemples de codes Matlab résolvant une tache plus ou moins simple, le code de gauche étant l’implémentation naive, et celui de droite l’implémentation vectorisée. Calculer le sinus des éléments d’un vecteur X 1 2 3 4 Y = zeros ( size ( X ) ) ; for i = 1: length ( X ) Y ( i ) = sin ( X ( i ) ) ; end 1 Y = sin ( X ) ; Calculer la racine carrée de la moyenne du carré des éléments d’un vecteur X Une opération courante (si, si !) : il s’agit du RMS en électricté 1 2 3 4 5 Y = 0; % resultat for elem = X Y = Y + elem * elem ; end Y = sqrt ( Y / length ( X ) ) ; 1 Y = sqrt ( mean ( X .^ 2 ) ) ; Calculer la valeur maximale d’un polynome sur un vecteur X d’abscisses Pour l’exemple, nous choisirons le polynome x3 + 2x + 1. 1 2 3 4 5 6 7 Y = - Inf ; % maximum actuel for elem = X val = ( elem ^3 + 2* elem + 1) ; if val > Y Y = val ; end end 1 Y = max ( X .^3 + 2* X + 1 ) ; Créer une matrice N × N tridiagonale de 1, avec des 2 sur la diagonale Un exemple un peu sophistiqué qui repose sur l’emploi de diag. Ici, la vectorisation n’est pas absolument nécessaire, puisque la création d’un vecteur n’est en général pas une opération critique (puisque réalisée une seule fois). 1 2 3 4 5 6 7 8 A = zeros (N , N ) ; A (1 , 1) = 2; A (N , N ) = 2; for i = 2: N -1 A (i , i ) = 2; A (i -1 , i -1) = 1; A ( i +1 , i +1) = 1; end 1 2 23 D = diag ( ones (1 , N -1) , 1) ; A = diag ( ones (1 , N ) *2) + D + D ’ ; Calculer le sin(n * X), pour n = 1..N, et X un vecteur colonne Le résultat sera donc une matrice. Ce genre de problèmes peut paraitre absurde et tordu, et pourtant, vous serez amenés à faire pire dans le cadre du cours. . . 1 2 3 4 5 6 res = zeros ( length ( X ) , N ) ; for i = 1: length ( X ) for j = 1: N res (i , j ) = sin ( X ( i ) * j ) ; end end 3.3.2 1 Y = sin ( X * [1: N ] ) ; La préallocation Comme mentionné plus haut dans ce chapitre, Matlab supporte un accès en écriture aux éléments d’un vecteurs avec un indice supérieur à la taille du vecteur : le vecteur est alors agrandi en ajoutant des zéros jusqu’à la position désirée, qui est elle assignée à la valeur spécifiée. Cela permet relativement facilement de créer des vecteurs. Voici, par exemple, une fonction équivalente à [1:N] qui se base sur cette technique : 1 2 3 4 5 6 7 8 function X = entiers ( N ) X = []; i = 1; while i <= N X(i) = i; i = i + 1; end end Malheureusement, cette technique est à éviter à tout prix ! D’ailleurs, l’éditeur Matlab souligne en orange le code X(i) = i, et nous informe que : Variable ’X’ appears to change size on every loop iteration. Consider preallocating for speed. En d’autres termes, le vecteur change de taille à chaque itération, ce qui est précisément ce que l’on cherche à faire. Pourquoi Matlab se plaint-il ? C’est une question de performance. Le code dans sa version actuelle est terriblement lent, et peut être optimisé facilement. La raison de ce manque d’efficacité est en fait bêtement informatique : lorsque Matlab augmente la taille d’un vecteur, il se passe un véritable déménagement en mémoire. Matlab cherche en mémoire un bloc vide de la taille du nouveau vecteur, et y copie alors tout le contenu de l’ancien vecteur (en y adjoignant la nouvelle valeur). Et ceci, à chaque opération. Autrement dit, Matlab doit chercher de la place et copier son vecteur N fois de suite, ce qui prend de plus en plus de temps, lorsque la taille du vecteur augmente ! La solution est très simple : préalloquer, autrement dit définir au préalable un vecteur de la même taille que le vecteur de sortie. Les valeurs contenues à l’origine dans le vecteur ne sont d’aucune importance, puisqu’elles seront de toute façon supprimées. En général, on utilise la fonction zeros pour créer une matrice pleine de zéros de bonne dimension. Pour améliorer le code ci-dessus, il suffit donc de remplacer X = [ ] par X = zeros(1, N), et le tour est joué ! En mesurant les performances des deux programmes, on s’aperçoit que le code avec préallocation est au moins dix fois plus rapide que l’autre (parfois même cent fois plus !), ce qui représente un gain considérable ! 3.3.3 Les matrices creuses L’emploi de matrices creuses permet d’améliorer les performances de certains programmes de manière vraiment importante, mais uniquement dans certaines circonstances. Tout d’abord, expliquons ce qu’est une matrice creuse : il s’agit d’une matrice contenant beaucoup de zéros, donc assez peu d’éléments réellement importants. De telles matrices apparaissent dans de nombreux problèmes en sciences de l’ingénieur. 24 Matlab permet de stocker ces matrices sous une forme plus avantageuse, avec l’emploi de la fonction sparse. Cette fonction prend en argument une matrice, et retourne cette matrice sous forme creuse (sparse en Anglais). Voici un exemple : 1 2 3 4 5 6 EDU > > A = [0 0 0 1; 0 1 0 0; 2 0 0 0]; EDU > > sparse ( A ) ans = (3 ,1) 2 (2 ,2) 1 (1 ,4) 1 Quel est l’intérêt d’utiliser des matrices creuses ? Accélérer la résolution de systèmes linéaires. Il existe des algorithmes très rapide pour cette opération sur des matrices creuses (algorithmes qui sont évidemment supportés par Matlab). Cela a un prix, évidemment : assigner des éléments dans une matrice creuse est une opération couteuse, plus couteuse que d’assigner dans une simple matrice. Aussi, l’opération sparse est relativement lente pour de grandes matrices. Un bon compromis est de créer la matrice sous forme classique, et de la transformer en matrice creuse une fois que la création de la matrice est terminée. Le gain de temps total, sur des matrices de grande taille, est alors considérable. Les matrices creuses sont un sujet assez complexe, qui sort du cadre de ce document. Toutefois, l’emploi de la fonction sparse avant la résolution de systèmes linéaires est en général amplement suffisant pour la plupart des taches classiques. 4 Dessiner des graphes Vous voilà donc maître des fonctionnalités principales de Matlab , et vous avez écrit un super code performant qui marche à merveille... et qui vous donne une tonne de chiffres à virgule flottante absolument indigestes et impossibles à interpréter ! Heureusement, il est très simple de créer des graphes avec Matlab. 4.1 Créer le graphe de base (titre, axes...) Le code suivant permet de créer un graphe contenant les informations essentielles. Analysons celui-ci ligne par ligne. 14 1 2 3 4 5 6 7 8 9 figure () ; % Nouvelle figure plot (x , y ) % Le graphe en question hold on ; % On va rajouter un deuxieme graphe par - dessus plot (x ,z , ’g ’) % On precise ici la couleur souhaitee title ( ’ Population ␣ mondiale ␣ de ␣ Koalas ␣ et ␣ de ␣ Pelicans ␣ en ␣ fonction ␣ de ␣ la ␣ temperature ’) xlabel ( ’ Temperature ␣ [ K ] ’) ylabel ( ’ Population ␣ animale ␣ en ␣ millions ␣ [/] ’) legend ( ’ koalas ’ , ’ pelicans ’) hold off ; % Pour les graphes suivants 14. Vous aurez remarqué que la population de pélicans peut être négative : il s’agit d’anti-pélicans. Leurs collisions fréquentes avec les pélicans normaux dégage une quantité énorme d’énergie, énergie qu’absorbent les koalas (des vrais). Ce phénomène explique la croissance golbale de koalas, qui oscille en fonction de l’oscillation de la population de pélicans. 25 4 5 x 10 Population mondiale de Koalas et de Pelicans en fonction de la temperature koalas pelicans Population animale en millions [/] 4 3 2 1 0 −1 260 280 300 320 Temperature [K] 340 360 380 Figure 2 – Le résultat du code d’exemple. Ligne 1 : création de la figure Avant de pouvoir dessiner votre graphe, il faut indiquer à Matlab que vous souhaitez placer celle-ci dans une nouvelle fenêtre. Si vous ne le précisez pas, Matlab prendra la dernière fenêtre ouverte 15 , écrasant un éventuel graphe important dedans... Nous vous recommandons donc de toujours créer une nouvelle figure avant chaque nouveau graphe. Vous pouvez éventuellement donner en argument de cette fonction un numéro associé à la fenêtre. Vous pourrez plus tard revenir à cette fenêtre en retapant la même commande avec le même numéro, et modifier ainsi plusieurs fenêtres à tour de rôle. Ligne 2 : le graphe Il s’agit de la commande la plus importante (en effet, pour les minimalistes, il est possible de créer un graphe avec uniquement cette ligne de code) : on plot les valeurs contenues dans y (les ordonnées) en fonction de celles contenues dans le vecteur x (les abscisses). En fait, Matlab ne fait que tracer les points contenus dans les vecteurs en les reliant ensuite un à un par une droite. Il est donc important que les éléments contenus dans le vecteur abscisse soient ordonnés : sinon Matlab va tout mélanger. Ligne 3 et 9 : la commande hold On souhaite parfois afficher plusieurs couples de données sur un même graphe, ce qui est possible grâce à la commande hold 16 . Celle-ci, une fois activée par une commande hold on, indique à Matlab que tous les plot suivant se feront par-dessus le dernier plot réalisé, sans l’effacer. On arrête ensuite le hold avec hold off. Notons aussi qu’on a rajouté ici une couleur au second plot, pour différencier les deux courbes. On verra cela en détail dans la sous-section suivante. Ligne 5, 6 et 7 : Le titre, les axes Cela devrait être assez explicite, ce sont les commandes pour mettre un titre au graphe et pour commenter les axes (attention à ne pas oublier d’en profiter pour donner les unités !). Ligne 8 : la légende Dans le cas de plusieurs courbes sur un seul graphe comme ici, il est quand même relativement pratique de savoir à quelles données correspond chaque courbe : cette commande-ci permet de rajouter le cadre en haut à droite 17 qui permet de différencier les courbes. On lui donne en argument les noms à donner aux courbes dans l’ordre dans lequel elles ont été plottées. 15. Si aucune fenêtre pouvant accueillir des graphes n’est ouverte, Matlab en créera une nouvelle. 16. Il est aussi possible d’afficher plusieurs groupes de données en un seul plot en écrivant par exemple plot(x,y,x,z). 17. Si la position ne convient pas (par exemple, ici, elle gêne la lecture de la courbe de la population de koalas), il est possible de changer sa position en rajoutant des arguments. Voir la doc pour plus d’informations. 26 4.2 Plein d’options pour faire joli Une fois votre graphe de base crée, vous avez à votre disposition une tonne d’option pour modifier son apparence comme bon vous semble. Une simple recherche sur la doc permet de trouver rapidement ce que vous recherchez, mais voici un aperçu (loin d’être exhaustif) des possiblités. La fonction plot est extrêmement riche, et possède de très nombreuses options. Les deux dernières lignes illustrent l’usage de cette fonction avec des options permettant de modifier l’apparence des courbes. Nous vous invitons à consulter la documentation (http://www.mathworks.nl/help/matlab/ref/plot. html) pour plus d’informations. 1 2 3 4 5 6 7 8 9 10 11 xlim ([0 10]) ; % Change les limites du graphe : ici on affiche uniquement les abscisses entre 0 et 10 ylim ([ -10 10]) ; % On affiche que les ordonnees entre -10 et 10 loglog (x , y ) ; % Equivalent a plot , mais x et y seront affiches en echelle logarithmique semilogx (x , y ) ; % Ici , seul x sera en echelle logarithmique semilogy (x , y ) ; % A vous de decouvrir stem (x , y ) ; % graphe en batonnets ( pour donnees discretes ) plot (x ,y , ’ Color ’ , ’r ’) ; % On donne une couleur au plot , ici rouge ( Red ) = > ’r ’ plot (x ,y , ’ LineStyle ’ , ’ -- ’) ; % Le trait de la courbe dessinee sera en pointilles Une dernière option est assez utile et est assez particulière : parfois, on souhaite avoir plusieurs graphes l’un à côté de l’autre (pour les comparer par exemple). La commande subplot est parfaite pour ça : elle permet de créer un "quadrillage" (non visible), dont chaque case peut accueilir un graphe. Elle prend en entrée 3 arguments : le nombre de lignes du quadrillage, le nombre de colonnes et l’emplacement dans le quadrillage ou le prochain plot sera effectué (les "cases" sont numérotées de gauche à droite puis de haut en bas). Un exemple vaut mieux qu’un long discours : 1 2 3 4 5 6 7 8 9 x = linspace (0 , 1 , 1000) ; figure () ; subplot (3 ,2 , 1) ; % 3 lignes , 2 colonnes , case 1 plot (x , x .^2) ; subplot (3 ,2 , 4) ; % case 4 ( deuxieme ligne deuxieme colonne ) plot (x , x .^3) ; subplot (3 ,2 , 5) ; % case 5 (3 eme ligne , 1 ere colonne ) plot (x , sqrt ( x ) ) ; title ( ’ Exemple ␣ ultra ␣ stupide ’) ; % ATTENTION : le title ne s ’ applique qu ’ au subplot courant ! 27 1 0.5 0 0 0.5 1 1 0.5 0 0 0.5 1 Exemple ultra stupide 1 0.5 0 0 0.5 1 Figure 3 – Le résultat du code d’exemple. 4.3 Exporter votre chef-d’oeuvre Dans la fenêtre créée lors d’une commande figure ou plot, vous avez à votre disposition des tas de jolis boutons rigolos qui permettent de faire plein de manipulations diverses sur votre figure (par exemple, zoomer sur une partie intéressante) que nous vous laissons explorer (vous devriez vous en rendre compte petit à petit, le logiciel Matlab possède (à l’instar du language Matlab) des milliards d’options, et quand on pense commencer à connaître, on découvre un nouveau menu avec dix mille nouveaux boutons. . . il serait extrêmement fastidieux d’en faire le tour). Il est extrêmement pratique de pouvoir sauver l’image d’un graphe (pour le mettre dans votre joli rapport par exemple), ce qui se fait bêtement via "File > Save As", ou vous choisirez votre format préféré (Dans ce document, nous utilisons le format EPS, qui s’intègre très bien dans les documents LATEX). 4.4 A trois variables : les surfaces et les courbes de niveau. Deux dimensions, c’est bien pour afficher des fonctions à une variable. Trois dimensions, c’est mieux pour les fonctions à deux variables. Matlab propose plusieurs façons de visualiser un tel type de données tridimensionnel. 4.4.1 Les courbes de niveau : contourf Sans surprise, cette fonction permet de créer une représentation type "courbes de niveau" de données à deux variables (les données seront donc stockées dans une matrice plutôt que dans un vecteur unidimensionnel). contourf(x,y,z,k) crée, à la manière d’un plot, une nouvelle fenêtre avec k courbes de niveau des données contenues dans z (une matrice n ∗ m) en fonction des variables x (de taille m : l’axe x correspond donc aux colonnes de z) et y (de taille n). 4.4.2 Les courbes 3-D : surf et plot3 Il existe aussi des fonctions pour avoir un véritable graphe en 3 dimensions. 28 surf(x,y,z) permet de créer la surface 18 formée par la donnée z en fonction des variables x et y. Son fonctionnement est tout à fait similaire à celui de contourf, le résultat final sera juste en trois dimensions plutôt que deux. plot3(x,y,z) quant à elle fonctionne de manière très similaire à plot (d’où le nom) mais avec une variable en plus. Concrètement, Matlab relie dans une image 3D les points de l’espace (x(1), y(1), z(1)), (x(2), y(2), z(2))... Les superpouvoirs de Matlab : ode45, le calcul symbolique, . . . 5 Maintenant que vous êtes devenus des Dieux du calcul numérique, que les vecteurs et les graphes n’ont plus de secret pour vous, il est temps de vous dévoiler les superpouvoirs de Matlab , les arcanes ultimes qui vont rendre votre vie plus facile (surtout si vous avez à résoudre régulièrement des équations différentielles ordinaires). Ce chapitre est présent à titre strictement indicatif, pour les étudiants qui voudraient en savoir plus. 5.1 Résoudre des équations différentielles ordinaires plus vite que son ombre Bien que le cours de méthodes numériques soit essentiellement destiné à, précisément, résoudre des EDO, on s’aperçoit surtout très vite que ce n’est pas si simple que ça (d’ailleurs, on fait toujours Euler Explicite quand doit résoudre des EDO, parce que c’est la seule méthode vraiment super facile à implémenter et à retenir). Heureusement, Matlab contient un outil formidable de résolution d’EDO : la sacro-sainte fonction ode45 (pour Ordinary Differential Equations 45 ). C’est en tapant help ode45 dans la commande qu’on se dit vite que l’outil doit en effet être très puissant, vu la quantité de texte qui s’affiche. La page de la documentation (http://www.mathworks.nl/help/matlab/ ref/ode45.html) est encore plus complète, et plus agréable à lire. Nous nous limiterons dans ce texte à un usage assez limité (mais déjà plus que suffisant, je vous rassure !) de la fonction, qui permet de faire vraiment plein de choses. Pour ceux que ça intéresse, ode45 utilise une méthode explicite adaptative appelée méthode de Dormand-Prince 19 (Ce n’est pas une blague !), de la famille des méthodes de Runge-Kutta (d’ou le 45 : on combine ici une méthode d’ordre 4 et une méthode d’ordre 5). 5.1.1 Que fait vraiment ode45 ? ode45 résoud l’équation différentielle ordinaire classique u (t) = f(t, u(t)), pour une fonction f et une condition initiale donnée, sur un intervalle de temps donné. Attention, la fonction f peut être vectorielle, c’est-à-dire de R × Rn −→ Rn (concrètement, elle accepte comme arguments un scalaire, le temps, et un vecteur, et retourne un vecteur). La fonction retourne deux vecteurs, appelés TOUT et YOUT dans l’aide de Matlab , qui contiennent respectivement les temps et les valeurs de la solution en ces temps (notez que ce deuxième vecteur est. . . une matrice, puisqu’il contient une liste de valeurs vectorielles). Le nombre de temps dépend entre autres de la stiffness (raideur) du problème. Il est possible d’obliger à Matlab de ne retourner les valeurs qu’en certains temps spécifiés. Précision des résultats : ode45 possède deux options, RelTol et AbsTol, qui définissent les tolérances d’erreur commise respectivement relativement (10−3 par défaut) et absolument sur chaque composante du vecteur de retour (un vecteur aux composantes initialisées à 10−6 par défaut). Les réglages par défaut sont un bon compromis entre efficacité et précision, et il n’est pas, en général, nécessaire ou recommandé de les modifier. 18. D’où le nom surf (rien à voir avec le sport donc). 19. Kids, don’t try this at home : http://en.wikipedia.org/wiki/Dormand%E2%80%93Prince_method 29 5.1.2 Quels arguments donner à ode45 ? Dans sa version la plus simple, la fonction admet trois arguments : 1. ODEFUN La fonction f(t, x) de l’EDO. Celle-ci doit être passée en argument sous forme d’une function handle. En pratique, il suffit de mettre une arobase (@) devant le nom de la fonction, et le tour est joué. Il est aussi possible d’utiliser des fonctions anonymes, de la forme @(< arguments >) < expression >. Par exemple, une fonction a deux arguments calculant le cosinus du premier et le sinus du deuxième s’écrirait : 1 @ (x , y ) [ cos ( x ) sin ( y ) ] Attention, si l’argument x de la fonction est un vecteur (autrement dit, si la solution est une fonction à valeur vectorielles), la valeur retournée doit être un vecteur de même taille ! 2. TSPAN L’intervalle de temps sur lequel résoudre l’EDO. Cet argument peut prendre deux formes : 1. un vecteur a deux éléments contenant le début et la fin de l’intervalle, le plus petit élément étant considéré comme le début. Ainsi, [0, 1] et [1; 0] donnent les mêmes résultats. ode45 retourne alors la valeur de la solution en des points compris dans cet intervalle et en les bornes. C’est la méthode la plus efficace. 2. un vecteur contenant plus de deux éléments. Les valeurs de la solution sont alors calculées exclusivement en ces points (la fonction ne retourne pas de points intermédiaires). C’est donc l’équivalent de l’évaluation de la solution en une série de temps donnés. 3. Y0 La solution initiale, autrement dit la valeur de la solution en le plus petit point de l’intervalle. Si la solution est une fonction à valeur vectorielle, alors cette solution initiale doit être un vecteur de même taille que la solution (évidemment), et que le second argument et la valeur de retour de ODEFUN. 5.1.3 Comment utiliser les valeurs de retour ? Si vous ne récupérez pas explicitement la valeur de retour d’ode45 (si vous ne définissez pas une variable égale à la sortie), la fonction dessine automatiquement la solution en fonction du temps dans la dernière figure créée (ou en crée une au besoin) ! Ce comportement par défaut est extrêmement pratique, et est suffisant, dans la plupart des cas. Si vous désirez récupérer explicitement les temps et valeurs de la solution en ces temps, il faut utiliser deux valeurs de retour (appelées TOUT et YOUT dans la documentation) : 1 [ TOUT , YOUT ] = ode45 (...) ; Format de YOUT : En raison du caractère vectoriel de la solution, YOUT est une matrice. Chaque colonne de la matrice correspond au valeurs d’une composante de la solution en fonction du temps. Pour accéder à la valeur de (toutes les composantes de) la solution en l’instant t, qui correspond au ni`eme élément de TOUT, on utilise donc le code : 1 y_en_t = YOUT (n ,:) ; Il est intéressant de noter que ces deux lignes sont équivalentes (ou ODEFUN, TSPAN et Y0 ont été correctement définis au préalable), à l’exception que la seconde stocke les valeurs de retour dans les vecteurs t et y : 1 2 ode45 ( ODEFUN , TSPAN , Y0 ) ; % comportement par defaut [t , y ] = ode45 ( ODEFUN , TSPAN , Y0 ) ; plot (t , y ) ; hold on ; plot (t , y , ’o ’) ; 30 Si on stocke la valeur de retour dans une seule variable, la fonction retourne une structure, qui contient beaucoup plus d’informations (comme le nombre de pas), mais ceci dépasse du cadre de ce document. 5.1.4 Un exemple : le pendule amorti Afin de terminer cette section sur ode45, utilisons cette fonction pour résoudre une des équations les plus célèbres de la mécanique, celle du pendule amorti : θ (t) = − g · θ(t) − λθ (t) L Le coefficient λ correspond au coefficient de frottement dans l’air, g est l’accélération de la pesanteur et L la longueur de la corde du pendule. Notre but est de réaliser une fonction qui affiche θ(t), pour un temps correspondant à 4 périodes (en faisant l’approximation qu’une période est de durée 2π Lg ), pour une position initiale correspondant à un angle initial de 90◦ à droite et une vitesse initiale nulle. Les paramètres de cette fonction correspondront aux trois paramètres de l’équation. Tout d’abord, il faut transformer l’équation actuelle du second ordre en équation vectorielle du premier ordre. Cela se fait en posant u1 = θ et u2 = θ . On a alors : u (t) = u2 (t) 1 u2 (t) = − Lg u1 (t) − λ · u2 (t) u1 (0) = π/2 u2 (0) = 0 La fonction ODEFUN s’écrit donc, si g, lambda et L sont définis dans son environnement 20 : 1 2 3 function dudt = odefun (t , u ) dudt = [ u (2) ; -g / L * u (1) - lambda * u (2) ]; end On peut donc écrire le code de la fonction pendulum comme ceci : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function pendulum (g , L , lambda ) % fonction qui trace la solution a l ’ equation du pendule % arguments : ( gravite , longueur , frottement ) function dudt = ODEFUN (t , u ) % acces aux arguments possible ici dudt = [ u (2) ; -g / L * u (1) - lambda * u (2) ]; end TSPAN = [0 , 4 * 2* pi * sqrt ( L / g ) ]; % de 0 a 4 periodes Y0 = [ pi /2 , 0]; % vitesse initiale nulle [t , u ] = ode45 ( @ODEFUN , TSPAN , Y0 ) ; % on affiche uniquement la position ( pas la vitesse angulaire ) plot (t , u (: ,1) ) ; hold on ; xlim ( TSPAN ) ; title ( ’ angle ␣ du ␣ pendule ␣ en ␣ fonction ␣ du ␣ temps ’) ; end La figure 4 ci-dessous montre un exemple d’exécution. 20. Matlab supporte les variables contextuelles : toutes les variables définies avant une fonction dans le même bloc de code sont accessibles depuis cette fonction. 31 angle du pendule en fonction du temps 2 1.5 1 0.5 0 −0.5 −1 −1.5 0 1 2 3 4 5 6 7 8 Figure 4 – Résultat pour pendulum(9.81, 1, 0.8) ; 5.2 Calculer symboliquement mieux que vous Le calcul symbolique, c’est l’ordinateur au service du mathématicien : pas pour l’aider dans ce qu’il ne sait pas faire (par exemple, mille itérations de Runge-Kutta 4), mais dans ce qu’il sait très bien faire, autrement dit, faire de l’analyse. En d’autres termes, manipuler des fonctions exactes, analytiques (avec une formule, comme en maths), afin de pouvoir les dériver et les intégrer de façon analytique. L’idée essentielle est de définir une ou plusieurs variables symboliques, variables qui ne prendront pas une seule valeur comme c’était le cas jusqu’à présent : il s’agira de variables au sens mathématique, pouvant prendre toutes les valeurs réelles. On les définit en faisant syms <variable>. Toute variable définie en fonction d’une variable symbolique est une variable symbolique (y = 2 * x). Ensuite, on peut traiter la variable déclarée symbolique (ici x) telle quelle dans tous les calculs possibles et imaginables. Avant d’aller plus loin, il faut préciser que le calcul symbolique de Matlab a ses limites. Il n’a pas la meilleure réputation dans le monde académique pour multiples raisons, dont par exemple sa lenteur. Si, par exemple, vous devez employer la dérivée d’une fonction complexe dans votre code, il vaut mieux la calculer à part et copier le résultat dans le code plutot que de la calculer à chaque appel de la fonction. . . De plus, si vous cherchez un logiciel spécialisé dans le calcul symbolique, il vaut mieux se tourner vers Mathematica 21 ou Maple 22 . De toute façon, il vaut mieux faire les calculs à la main quand ils sont faisables en plus, cela permet d’avoir un double-check. Voici un exemple d’usage du calcul symbolique : 1 2 3 EDU > > syms x EDU > > disp ( sqrt ( 4* x ^2 ) ) 2*( x ^2) ^(1/2) % le calcul symbolique dans toute sa splendeur Pour calculer la dérivée d’une fonction (par exemple la terrible fonction f (x) = x2 ), il suffit d’utiliser diff : 21. http ://www.wolfram.com/mathematica/ 22. http ://www.maplesoft.com/ 32 1 2 EDU > > disp ( diff ( x ^2) ) 2* x % qui l ’ eut cru ? Plus sérieusement, vous l’aurez deviné, diff(fonction,variable) permet de dériver l’expression fournie en premier argument par rapport à la variable fournie en second (non donnée dans l’exemple mais il n’y avait qu’une variable donc Matlab a deviné tout seul comme un grand). Il est également possible d’intégrer symboliquement, toujours aussi facilement : 1 2 EDU > > disp ( int ( x ^2) x ^3/3 Il existe beaucoup d’options qui s’ouvrent à vous, même si la différenciation et l’intégration sont les opérations les plus courantes. Matlab factorise, simplifie, et bien d’autres choses encore. Comme cela sort légèrement du cadre du cours, à vous de découvrir tout cela par vous-mêmes. 5.3 S’amuser avec Matlab Matlab, à l’instar de nombreux logiciels (en particulier le moteur de recherche Google) possède des Easter Eggs, autrement dit des petites blagues, qui font souvent référence à la culture populaire. . . Les Easter Eggs changent d’une version à l’autre, donc il est possible que quelques unes de ces perles ne fonctionnent pas chez vous (hélas). Nous remercions Antoine de Comité de nous avoir initié aux fonctionnalités ludiques de Matlab. 5.3.1 Les petites blagues de Matlab Les fonctions sans arguments Quelques unes des fonctions de base de Matlab (qui sont utiles en vrai) ont un comportement spécial si on ne leur donne pas d’arguments. . . En particulier, essayez avec spy (oui oui, le spy qui affiche les matrices !) et image. Dans la catégorie image, penny vous montre un cent américain en 3D ! Pour un logo Matlab en 3D, essayez surf(membrane), ou plus simplement logo. Un peu d’aide philosophique La fonction why vous fournit des excuses. Elle sélectionne une excuse aléatoire, sauf si vous spécifiez un numéro. De la musique ! Les instructions successives load handel et sound(y, Fs) ; jouent un célèbrissime morceau de musique (c’est mon Easter Egg préféré, personnellement). 5.3.2 Oubliez Steam : jouer avec Matlab Derrière ce titre un peu racoleur, se cache une réalité : Matlab regorge de petits jeux cachés. Bon, d’accord, ça ne vaut pas un Zelda ou un League of Legends, mais il y a peut-être moyen de tenter de s’amuser ! Les jeux stars de votre nouvelle console de jeux sont au nombre de trois : xpbombs, life et fifteen ! Bon amusement ! (Plus sérieusement, il parait qu’il est possible de développer un jeu en Matlab, mais bon, franchement, est-ce que ça en vaut la peine ? ;-) 33
© Copyright 2024 Paperzz