MATLAB Tutorial 4 – Créer et appeler des fonctions

matlab fonctions blog ingenieursUne introduction à la création de ses propres fonctions, à leur sauvegarde dans leur répertoire, et l’appel de ces fonctions dans le script principal.

Scripts et fonctions

Il est possible d’enregistrer une séquence d’instructions dans un fichier (appelé un M-file  ) et de les faire exécuter par MATLAB. Un tel fichier doit obligatoirement avoir une extension de la forme .m (d’où le nom M-file) pour être considéré par MATLABcomme un fichier d’instructions. On distingue 2 types de M-file, les fichiers de scripts et les fichiers de fonctions. Un script est un ensemble d’instructions MATLAB qui joue le rôle de programme principal. Si le script est écrit dans le fichier de nom nom.m on l’exécute dans la fenêtre MATLAB en tapant nom. Même si l’on ne souhaite pas à proprement parler écrire de programme, utiliser un script est très utile. Il est en effet beaucoup plus simple de modifier des instructions dans un fichier à l’aide d’un éditeur de texte que de retaper un ensemble d’instructions MATLAB dans la fenêtre de commande.


Les fichiers de fonctions ont deux rôles. Ils permettent à l’utilisateur de définir des fonctions qui ne figurent pas parmi les fonctions incorporées de MATLAB (<< built-in functions >>) et de les utiliser de la même manière que ces dernières (ces fonctions sont nommées fonctions utilisateur).   Ils sont également un élément important dans la programmation d’applications où les fonctions jouent le rôle des fonctions et procédures des langages de programmation usuels.
On définit la fonction fonc de la manière suivante:

function [vars1,, varsm] = fonc(vare_1,, varen)

séquence d’instructions

  • vars1, …, varsm sont les variables de sortie de la fonction;
  • vare1, …, varen sont les variables d’entrée de la fonction;
  • séquence d’instructions est le corps de la fonction.

Le fichier doit impérativement commencer par le mot-clé function. Suit entre crochets les variables de sortie de la fonction, le symbole =, le nom de la fonction et enfin les variables d’entrée entre parenthèses. Si la fonction ne possède qu’une seule variable de sortie, les crochets sont inutiles. Il est impératif que la fonction ayant pour nom fonc soit enregistrée dans un fichier de nom fonc.m sans quoi cette fonction ne sera pas << visible >> par MATLAB.
Dans l’exemple qui suit, on définit une fonction modulo qui calcule la valeur de a modulo n en prenant pour système de résidus {1, 2, …, n} au lieu de {0, 1, …, n-1} (système de résidus considéré par la fonction incorporée mod). Les lignes qui suivent doivent être enregistrées dans un fichier de nom modulo.m.

function [r,q] = modulo(a,n)

% Calcule la valeur de a modulo n en prenant pour systeme de residus
% 1, … , n au lieu de 0, … , n-1.
%
% appel : [r,q] = modulo(a,n)
%
% Arguments de sortie :
%  r : le residu
%  q : le quotient

q = floor(a./n);
r = a – n*q;

% si le reste de la division entiere vaut 0, le residu vaut par convention n
if r == 0, r = n; end

Les lignes précédées du symbole % sont des lignes de commentaire. Les lignes de commentaire situées entre la ligne function … et la 1-ere ligne d’instructions sont affichées si l’on demande de l’aide sur la fonction modulo.

>> help modulo

Calcule la valeur de a modulo n en prenant pour systeme de residus
1, … , n au lieu de 0, … , n-1.

appel : [r,q] = modulo(a,n)

Arguments de sortie :
r : le residu
q : le quotient

>>

L’appel d’une fonction utilisateur s’effectue de la même façon que l’appel de n’importe quelle fonction MATLAB:

>> b = 10 ; m = 4;
>> [r,q] = modulo(b,m)
r =
2
q =
2
>> modulo(10,5)
ans =
5
>>

Remarques:

  1. Il n’y a pas de mot-clé (par exemple end) pour indiquer la fin de la fonction. La fonction est supposée se terminer à la fin du fichier. Il est toutefois possible de provoquer un retour au programme appelant dans le corps de la fonction grâce à la commande return.
  2. On ne peut écrire qu’une seule fonction par fichier (qui doit porter le nom de cette fonction). Toutefois dans la version 5 de MATLAB existe la notion de << sous-fonction >>. Une sous-fonction est une fonction écrite dans le même fichier qu’une autre fonction (dite principale) et qui ne sera utilisable que par cette fonction principale (une sous-fonction ne peut pas être appelée par un autre sous-programme que la fonction principale).
  3. Si le fichier ne commence pas par le mot-clé function on a tout simplement écrit un script!

La gestion des variables d’entrée et de sortie est très souple sous MATLAB. Si l’on n’est intéressé que par le résidu et pas par le quotient, on peut se contenter de ne mettre qu’une seule variable de sortie, v = modulo(10,4). Dans cet appel la variable vcontiendra le résidu (la première variable de sortie). Par contre, même si l’on ne souhaite recueillir que le quotient, on est obligé d’effectuer un appel de la forme [r,q] = modulo(10,4) et donc de définir une variable inutile. Aussi, d’une manière générale, il est bon de ranger les variables de sortie par ordre << d’importance >>. Il est également possible d’appeler une fonction donnée avec moins de variables d’entrée que le nombre indiqué pour la définition de la fonction (il faut bien entendu que le corps de la fonction soit programmé de sorte de prévoir cette éventualité). Il existe deux fonctions MATLAB utiles pour gérer cette situation: nargin qui retourne le nombre de variables d’entrée utilisés lors de l’appel et nargout qui retourne le nombre de variables de sortie prévues lors de l’appel. Voici un petit exemple venant illustrer ces possibilités.

function [A,rang] = matale(T,m,n)

% Construit une matrice A de m lignes et n colonnes ayant des elements
% entiers generes de maniere aleatoire entre 0 et T.
% Calcule le rang de la matrice si l’appel est effectue avec 2 arguments
% de sortie.
% Si la matrice est carree, le parametre n peut etre omis.
%
% Appels:
%       [A,r] = Matale(T,m,n)
%       [A,r] = Matale(T,m)
%           A = Matale(T,m,n)
%           A = Matale(T,m)

if nargin == 2
A = fix(T*rand(m));
else
A = fix(T*rand(m,n));
end

if nargout == 2
rang = rank(A);
end

Dans cet exemple, on gère les variables d’entrée de la fonction de sorte de ne pas avoir besoin de donner lors de l’appel le nombre de lignes et de colonnes si la matrice est carrée. On gère aussi les variables de sortie afin de ne pas calculer le rang de la matrice si aucune variable de sortie pour le résultat n’est prévue lors de l’appel.

>> [A,r] = matale(20,3,4)
A =
16    13    13    10
10    16     7    14
4     0    16     8
r =
3
>> [A,r] = matale(20,3)
A =
12     0    18
5    14     9
3     8     8
r =
3
>> A = matale(20,3)
A =
8     7     2
17    16     4
1     0     3
>>
Un point important concerne la gestion des variables entre le programme principal (ou le workspace) et les fonctions de l’utilisateur. Toutes les variables définies à l’intérieur d’une fonction sont des variables locales à cette fonction. La communication avec des variables du programme principal (ou du workspace) ou avec des variables d’autres fonctions se fait uniquement par les variables d’entrée et sortie de la fonction. Une alternative existe toutefois: il est possible de déclarer certaines variables comme desvariables globales . Une variable globale peut être partagée entre un programme principal et plusieurs fonctions sans qu’il soit besoin de la spécifier parmi les variables d’entrée-sortie des différentes fonctions. On déclare une variable globale grâce au mot clé global. Par exemple pour déclarer la variable numex globale on écrit global numex. Attention, la déclaration global numex doit être reprise dans chaque fonction utilisant numex comme variable.

Opérateurs de comparaison et opérateurs logiques

Les opérateurs de comparaison sont:

==  : égal à (x == y)
> : strictement plus grand que (x > y)
< : strictement plus petit que (x < y)
>= : plus grand ou égal à (x >= y)
<= : plus petit ou égal à (x <= y)
~ =  : différent de (x ~ = y)

Les opérateurs logiques sont:

: et (x & y)
: ou (x | y)
~ : non (~ x)

Les opérateurs de comparaison et les opérateurs logiques sont utilisés essentiellement dans les instructions de contrôle.

Instructions de contrôle

Les instructions de contrôle sous MATLAB sont très proches de celles existant dans d’autres langages de programmation.

Boucle FOR : parcours d’un intervalle

Une première possibilité pour exécuter une séquence d’instructions de manière répétée consiste à effectuer une boucle pour les valeurs d’un indice, incrémenté à chaque itération, variant entre deux bornes données. Ce processus est mis en oeuvre par laboucle for.

Syntaxe :

forindice=borne_inf:borne_sup

séquence d’instructions

end

 

      indice est une variable appelée l’

indice de la boucle

      ;

borne_inf etborne_sup sont deux constantes réelles (appelées paramètres de la boucle);

séquence d’instructions est le traitement à effectuer pour les valeurs d’indices variant entre borne_inf et borne_sup avec un incrément de 1. On parle du corps de la boucle.
Interprétation :
Si borne_inf est plus petit ou égal àborne_sup, le traitement séquence d’instructions est exécuté borne_sup – borne_inf fois, pour les valeurs de la variable indice égales à borne_inf, borne_inf+1, …, borne_sup. Si borne_inf est strictement plus grand queborne_sup, on passe à l’instruction qui suit immédiatement l’instruction de fin de boucle (end).
Remarque :
L’indice de boucle ne prend pas nécessairement des valeurs entières. D’autre part il n’est pas nécessaire que l’indice de la boucle apparaisse dans le corps de la boucle; par contre il est interdit de modifier sa valeur s’il apparaît. Il est possible d’imbriquer des boucles mais elles ne doivent pas se recouvrir. On peut utiliser un incrément (pas) autre que 1 (valeur par défaut). La syntaxe est alors borne_inf: pas : borne_sup. Le pas peut être négatif. Attention à bien gérer la borne supérieure! Voici un exemple (idiot) venant illustrer les possibilités de variations de l’indice de la boucle

>> for r=1.1:-0.1:0.75
disp([‘r = ‘, num2str(r)]);
end
r = 1.1
r = 1
r = 0.9
r = 0.8
>>

Voici un exemple d’utilisation d’une boucle pour calculer n! (le lecteur attentif sait calculer n! plus simplement … par exemple en exécutant prod([1:n])).

>> n = 4;
>> nfac = 1;
>> for k = 1:n
nfac = nfac*k;
end
>> nfac
nfac =
24
>>

Boucle WHILE : tant que . . . faire

Une seconde possibilité pour exécuter une séquence d’instructions de manière répétée consiste à effectuer une boucle tant qu’une condition reste vérifiée. On arrête de boucler dès que cette condition n’est plus satisfaite. Ce processus est mis en oeuvre par laboucle while.

Syntaxe :

whileexpression logique

séquence d’instructions

end

  • expression logique est une expression dont le résultat peut être vrai ou faux;
  • séquence d’instructions est le traitement à effectuer tant que expression logique est vraie.

Interprétation :
Tant que expression logique est vraie le traitement séquence d’instructionsest exécuté sous forme d’une boucle. Lorsque expression logique devient faux, on passe à l’instruction qui suit immédiatement l’instruction de fin de boucle (end).
Remarque :
expression logique est en général le résultat d’un test (par exemple i < Imax) ou le résultat d’une fonction logique (par exemple all(x)). Il est impératif que le traitement de la séquence d’instructions agisse sur le résultat de expression logique sans quoi on boucle indéfiniment (-:.
Voici comment calculer n! avec une boucle while:

>> n = 4;
>> k = 1; nfac = 1;
>> while k <= n
nfac = nfac*k;
k = k+1;
end
>> nfac
nfac =
24
>>

L’instruction conditionnée IF

On a parfois besoin d’exécuter une séquence d’instructions seulement dans le cas où une condition donnée est vérifiée au préalable. Différentes formes d’instruction conditionnée existent sous MATLAB.
L’instruction conditionnée la plus simple a la forme suivante:

Syntaxe :

ifexpression logique

séquence d’instructions

end

  • expression logique est une expression dont le résultat peut être vrai ou faux;
  • séquence d’instructions est le traitement à effectuer si expression logique est vraie.

Interprétation:
la séquence d’instructions n’est exécutée que si le résultat de l’évaluation de l’expression logique est vraie (c’est-à-dire vaut 1). Dans le cas contraire on exécute l’instruction qui suit le mot clé end. Dans le cas où l’expression logique est vraie, après exécution de la séquence d’instructions on reprend le programme à l’instruction qui suit le mot clé end.
Remarque :
Contrairement à certains langages de programmation, il n’y a pas de mot clé << then >> dans cette instruction conditionnée. Notez également que la marque de fin de bloc conditionné est le mot clé end et non pas<< endif >>.
Il existe une séquence conditionnée sous forme d’alternatives:

Syntaxe :

if expression logique

séquence d’instructions 1

else

séquence d’instructions 2

end

  • expression logique est une expression dont le résultat peut être vrai ou faux;
  • séquence d’instructions 1 est la séquence d’instructions à exécuter dans le cas où expression logique est vraie et séquence d’instructions 2 est la séquence d’instructions à exécuter dans le cas où expression logique est faux.

Interprétation :
Si expression logique est vraie la séquence d’instructions 1 est exécutée, sinon c’est la séquence d’instructions 2 qui est exécutée. Le déroulement du programme reprend ensuite à la première instruction suivant le mot clé end.
Il est bien entendu possible d’imbriquer des séquences d’instructions conditionnées (au sens où la séquence d’instruction conditionnée contient des séquences d’instructions conditionnée). Pour une meilleure lisibilité, il est recommandé d’utiliser des indentations afin de mettre en évidence l’imbrication des séquences d’instructions conditionnées.
Il est possible d’effectuer un choix en cascade:

Syntaxe :

if expression logique 1

séquence d’instructions 1

elseif expression logique 2

séquence d’instructions 2

elseif expression logique N

séquence d’instructions N

else

séquence d’instructions par défaut

end

 

Interprétation :
Si expression logique 1 est vraie la séquence d’instructions 1 est exécutée et le programme reprend ensuite à la première instruction suivant le mot clé end, sinon si expression logique 2 est vraie la séquence d’instructions 2 est exécutée et le programme reprend ensuite à la première instruction suivant le mot clé end, etc. Si aucune des expressions logiques 1 à N n’est vraie alors séquence d’instructions par défaut est exécutée.
Remarque :
Attention à ne pas laisser d’espace entre else et if; le mot clé est elseif.
On utilise fréquemment un choix en cascade lors d’initialisation de données. Par exemple, on initialise une matrice A en fonction de la valeur d’une variable numex (numéro d’exemple) de la manière suivante:

if numex == 1
A = ones(n);
elseif numex == 2
A = magic(n);
elseif numex == 3 | numex == 4
A = rand(n);
else
error(‘numero d »exemple non prevu …’);
end

Choix ventilé, l’instruction switch

Une alternative à l’utilisation d’une séquence d’instructions conditionnées pour effectuer un choix en cascade existe. Il s’agit de l’instruction switch.
Syntaxe :

switch var

casecst1,

séquence d’instructions 1

casecst2,

séquence d’instructions 2

casecstN,

séquence d’instructions N

otherwise

séquence d’instructions par défaut

end

  • var est une variable numérique ou une variable chaîne de caractères;
  • cst1, …, cstN, sont des constantes numérique ou des constantes chaîne de caractères;
  • séquence d’instructions i est la séquence d’instructions à exécuter si le contenu de la variable var est égal à la constante csti (var==csti).

Interprétation :
Si la variable var est égale à l’une des constantes cst1, …, cstN, (par exemple csti) alors la séquence d’instructions correspondante (ici séquence d’instructions i) est exécutée. Le programme reprend ensuite à la première instruction suivant le mot-clé end. Si la variable var n’est égale à aucune des constantes la séquence d’instructions par défaut est exécutée.
Remarque :
La variable var doit bien entendu être du même type que les constantes cst1, …, cstN.
Il n’est pas nécessaire de prévoir un cas par défaut (bien que cela soit préférable). S’il n’y a pas de cas par défaut et si la variable var n’est égale à aucune des constantes, alors le programme continue à la première instruction suivant le mot-clé end.
Il est possible de regrouper plusieurs << cas >> si la séquence d’instructions à exécuter est la même pour ces différents cas. La syntaxe est alors,

case{ cstk , cstl , …}

séquence d’instructions commune

 

Reprenons l’exemple où l’on souhaite initialiser une matrice A en fonction de la valeur prise par une variable numérique numex (numéro d’exemple). En utilisant un choix ventilé on obtient:

function  A = initA(n,numex)

switch numex
case 1,
A = ones(n)
case 2,
A = magic(n);
case {3,4},
A = rand(n);
otherwise
error(‘numero d »exemple non prevu …’);
end

Voici un exemple de choix ventilé portant sur une variable de type chaîne de caractères.

rep = input(‘Votre reponse (oui, non, chepas) :’);

switch rep
case {‘oui’,’o’},
disp(‘bravo …’);
case {‘non’,’n’}
disp(‘perdu …’);
case ‘chepas’
disp(‘c »est pourtant facile …’);
end

Interruption d’une boucle de contrôle

Il est possible de provoquer une sortie prématurée d’une boucle de contrôle. L’instruction break permet de sortir d’une boucle for ou d’une boucle while. L’exécution se poursuit alors séquentiellement à partir de l’instruction suivant le mot clé endfermant la boucle. En cas de boucles imbriquées, on interrompt seulement l’exécution de la boucle intérieure contenant l’instruction break. L’instruction return provoque un retour au programme appelant (ou au clavier). Les instructions suivant le return ne sont donc pas exécutées. L’instruction return est souvent utilisée conjointement avec une instruction conditionnée par exemple pour tester dans le corps d’une fonction si les paramètres d’entrée ont les valeurs attendues.
L’instruction errorpermet d’arrêter un programme et d’afficher un message d’erreur. La syntaxe est error(‘ message d »erreur ‘). L’instruction warning permet d’afficher un message de mise en garde sans suspendre l’exécution du programme. La syntaxe est warning(‘ message de mise en garde ‘). Il est possible d’indiquer à MATLAB de ne pas afficher les messages de mise en garde d’un programme en tapant warning off dans la fenêtre de commandes. On rétablit l’affichage en tapant warning on.
On peut ainsi améliorer la fonction matale de la manière suivante:

function [A,rang] = matale(T,m,n)
% Construit une matrice A de m lignes et n colonnes ayant des elements
% entiers generes de maniere aleatoire entre 0 et T.
% Calcule le rang de la matrice si l’appel est effectue avec 2 arguments
% de sortie.
% Si la matrice est carree, le parametre n peut etre omis.
%
% Appels:
%       [A,r] = Matale(T,m,n)
%       [A,r] = Matale(T,m)
%           A = Matale(T,m,n)
%           A = Matale(T,m)

% si la fonction est appelee avec un nombre d’arguments d’entree
% different de 2 ou 3, on arrete tout …
if nargin ~= 2 &  nargin ~= 3,
error(‘ La fonction matale doit avoir 2 ou 3 arguments d »entree ‘);
end

if nargin == 2
A = fix(T*rand(m));
else
A = fix(T*rand(m,n));
end

if nargout == 2
rang = rank(A);
if nargin == 2,
rangx = m;
else
rangx = min([m,n]);
end
if rang ~= rangx, warning(‘ Le rang n »est pas maximum ‘); end;
end

On obtient alors les messages suivants:>> A = matale(3);
??? Error using ==> matale
La fonction matale doit avoir 2 ou 3 arguments d’entree

>> A = matale(20,3)
A =
8    18     8
12    14    18
15     3    18
>> [A,r] = matale(20,3)

Warning:  Le rang n’est pas maximum
> In /home0/maths/balac/DOCMATLAB/matale.m at line 34
A =
1     4     3
10    15    11
3    12     9
r =
2
>>

La commande pause permet d’interrompre l’exécution du programme. L’exécution normale reprend dès que l’utilisateur enfonce une touche du clavier. L’instruction pause(n) suspend l’exécution du programme pendant n secondes.

Un exemple complet

Une technique de construction de carrés magiques d’ordre impair a été proposée par Manuel Moschopoulos au début du XIV siècle. Cette technique est décrite dans [Histoire d’Algorithmes, du caillou à la puce, J.L. Chabert éditeur, Belin 1994].
Notons l(x) le numéro de la ligne et c(x) le numéro de la colonne du carré sur lequel se trouve l’entier x. Partant d’un carré d’ordre impair n=2k+1, la technique de Moschopoulos peut se formuler comme suit:

  • Initialisation de l’algorithme en plaçant l’unité dans la case immédiatement au dessous de la case centrale, autrement dit à l’intersection de la (k+1) éme colonne et de la (k+2) ème ligne:

l(1) = k + 2
c(1) = k + 1

  • Connaissant la position (l(x), c(x)) de l’entier x, on place l’entier x+1 suivant les règles suivantes:
      si

x

      n’est pas un multiple de

n

    , alors

l(x+1) = 1 + l(x) modulo(n)
c(x+1) = 1 + c(x) modulo(n)

      si

x

      est un multiple de

n

      , alors

l(x+1) = 2 + l(x) modulo(n)
c(x+1) = c(x) modulo(n)
Dans ces règles pour la prise du modulo, le système de résidus que l’on considère est 1, 2, …, n et non pas 0, 1, …, n-1.
La fonction magik met en oeuvre la méthode de Moschopoulos.

function M = magik(n)
%
% Calcule le carre magique d’ordre n selon la methode
% de Moschopoulous.
%
% Entree:
%  n : ordre du carre (entier impair)
% Sortie:
%  M : le carre magique
%

if rem(n,2) == 0,
msg = [‘la methode de Moschopoulous ne construit que des carres’ …
,’ d »ordre impair’];
error(msg)
end

k = (n-1)/2;
l(1) = k+2;
c(1) = k+1;
M(l(1),c(1)) = 1;

for x = 2:n.^2
[l(x),c(x)] = pos(x-1,l(x-1),c(x-1),n);
M(l(x),c(x)) = x;
% ou plus simplement M(pos(x,l(x-1),c(x-1))) = x;
end

La fonction utilise la fonction pos. Cette dernière fonction peut soit être écrite à la suite de la fonction magik si l’on dispose de la version 5 de MATLAB (dans ce cas il s’agira d’une sous-fonction qui ne sera visible que de la fonction magik) soit être sauvegardée dans un fichier pos.m.

function [ly,cy] = pos(x,lx,cx,n)
%
% Retourne la position (indice de ligne ly et indice de colonne cy)
% dans le carre magique d’ordre n de l’entier y = x+1 selon la
% regle de Moschopoulous.
%
% Entree:
%  n : ordre du carre (entier impair)
%  x : l’entier considere
% lx : indice de ligne de l’entier x dans le carre magique
% cx : indice de colonne de l’entier x dans le carre magique
%
% Sortie:
%  ly : indice de ligne de l’entier y=x+1 dans le carre magique
%  cy : indice de colonne de l’entier y=x+1 dans le carre magique
%

if rem(x,n) == 0
ly = modulo(2+lx,n);
cy = modulo(cx,n);
else
ly = modulo(1+lx,n);
cy = modulo(1+cx,n);
end
Voici quelques exemples d’utilisation de la fonction magik. On vérifie que la somme des éléments des différentes lignes ainsi que la somme des éléments des différentes colonnes sont bien constantes. Pour calculer la somme des éléments diagonaux c’est un peu plus compliqué. On remarque que le carré magique construit diffère du carré magique retourné par la fonction MATLAB incorporée magic.

>> magik(4)
??? Error using ==> magik
la methode de Moschopoulous ne construit que des carres d’ordre impair
>> magik(5)
ans =
11    24     7    20     3
4    12    25     8    16
17     5    13    21     9
10    18     1    14    22
23     6    19     2    15
>> sum(magik(5),1)
ans =
65    65    65    65    65
>>  sum(magik(5),2)
ans =
65
65
65
65
65
>> magic(5)
ans =
17    24     1     8    15
23     5     7    14    16
4     6    13    20    22
10    12    19    21     3
11    18    25     2     9

Source Stephane Balac et ChE McMaster

Termes de recherche :appel fonction matlab,programme avec plusieurs fonctions sous matlab,comment creer une fonction matlab,comment construire des sous programmes dans matlab,comment appeler une fonction sur matlab,calcule resdus dun matrice en Matlab,appelle des fonctions sous matlab,appeler une fonction matlab,utilisation de fonction magic avec Matlab,appeler une fonction avec interpreted matlab fcn

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.