« Introduction à Maple/Procédures » : différence entre les versions

Une page de Wikiversité, la communauté pédagogique libre.
Contenu supprimé Contenu ajouté
passage au geshi
Ligne 2 : Ligne 2 :
| titre = Procédures
| titre = Procédures
| idfaculté = informatique
| idfaculté = informatique
| leçon = [[Introduction à Maple]]
| leçon = [[../]]
| numero = 6
| numero = 6
| précédent = [[Introduction à Maple/Listes, tableaux, matrices|Listes, tableaux, matrices]]
| précédent = [[../Listes, tableaux, matrices/]]
| suivant = [[../Bibliothèques de fonctions|Bibliothèques de fonctions]]
| suivant = [[../Bibliothèques de fonctions/]]
| niveau = 13
| niveau = 13
}}
}}
Ligne 19 : Ligne 19 :
Pour l'utiliser, on pourra écrire :
Pour l'utiliser, on pourra écrire :


<source lang="text">
:<code>MoudreCafe(T, V) ;</code>
MoudreCafe(T, V) ;
</source>


Enfin, une procédure peut se comporter comme une fonction : elle peut retourner une (ou plusieurs) valeur(s) lorsqu'elle est appelée. La différence tient surtout au fait qu'une procédure permet de faire beaucoup plus de choses qu'une fonction. En contrepartie, il ne faut pas espérer dériver, tracer… une procédure.
Enfin, une procédure peut se comporter comme une fonction : elle peut retourner une (ou plusieurs) valeur(s) lorsqu'elle est appelée. La différence tient surtout au fait qu'une procédure permet de faire beaucoup plus de choses qu'une fonction. En contrepartie, il ne faut pas espérer dériver, tracer… une procédure.
Ligne 35 : Ligne 37 :
Voici l'exemple complet :
Voici l'exemple complet :


<source lang="text">
:<code>MaProcedure := proc(a,b,c)</code>
:<code> x := a+b+c;</code>
MaProcedure := proc(a,b,c)
x := a+b+c;
:<code>end proc;</code>
end proc;
</source>


Cette procédure prend trois arguments et retourne la somme des trois. En effet, une procédure retourne par défaut le dernier calcul effectué ou la dernière évaluation faite. Ici, l'affectation à la variable <code>x</code> sera retournée. Par exemple :
Cette procédure prend trois arguments et retourne la somme des trois. En effet, une procédure retourne par défaut le dernier calcul effectué ou la dernière évaluation faite. Ici, l'affectation à la variable <code>x</code> sera retournée. Par exemple :



:<code>MaProcedure(1,2,3);</code> retourne <code>6</code> ;
:<code>MaProcedure(1,2,3);</code> retourne <code>6</code> ;
Ligne 50 : Ligne 55 :
Exemple d'illustration :
Exemple d'illustration :


<source lang="text">
:<code>retourner := proc(x);</code>
retourner := proc(x);
:<code> for i from 1 to x do</code>
for i from 1 to x do
:<code> return(i);</code>
return(i);
:<code> od;</code>
od;
:<code>end proc;</code>
end proc;
</source>


Cette procédure inutile, ne retourne que la valeur 1 car c'est lors de la première itération de la boucle <code>for</code>, c'est-à-dire quand <code>i</code> possède la valeur 1, que le programme va retourner <code>i</code> et s'interrompre. Aucune autre itération ne sera effectuée, quelque-soit la valeur de <code>x</code> (pourvu tout de même qu'elle soit supérieure ou égale à 1).
Cette procédure inutile, ne retourne que la valeur 1 car c'est lors de la première itération de la boucle <code>for</code>, c'est-à-dire quand <code>i</code> possède la valeur 1, que le programme va retourner <code>i</code> et s'interrompre. Aucune autre itération ne sera effectuée, quelque-soit la valeur de <code>x</code> (pourvu tout de même qu'elle soit supérieure ou égale à 1).
Ligne 62 : Ligne 69 :
On peut utiliser des variables dans les procédures Maple (elles sont dites « locales », ce sont par exemples les variables muettes des <code>for</code>). Pour cela, il n'est en pratique rien besoin de faire. Pour plus de clarté cependant, on prendra l'habitude de les préciser en début de code, avec le mot-clé <code>local</code>. Exemple :
On peut utiliser des variables dans les procédures Maple (elles sont dites « locales », ce sont par exemples les variables muettes des <code>for</code>). Pour cela, il n'est en pratique rien besoin de faire. Pour plus de clarté cependant, on prendra l'habitude de les préciser en début de code, avec le mot-clé <code>local</code>. Exemple :


<source lang="text">
:<code>MaProcedure := proc(a,b,c)</code>
MaProcedure := proc(a,b,c)
:<code> local x;</code>
local x;
:<code> …</code>
</source>


On peut également utiliser des variables accessibles depuis l'extérieur des procédures (dites « globales »), bien que cela soit moins courant. On utilise alors le mot-clé <code>global</code>.
On peut également utiliser des variables accessibles depuis l'extérieur des procédures (dites « globales »), bien que cela soit moins courant. On utilise alors le mot-clé <code>global</code>.
Ligne 72 : Ligne 81 :
Nous voudrions pouvoir exécuter une certaine opération si un nombre ''x'' est positif, et une autre opération s'il est négatif. Comment faire ? La réponse : utiliser des conditions. Voici la syntaxe Maple qui convient :
Nous voudrions pouvoir exécuter une certaine opération si un nombre ''x'' est positif, et une autre opération s'il est négatif. Comment faire ? La réponse : utiliser des conditions. Voici la syntaxe Maple qui convient :


<source lang="text">
:<code>if ''condition'' then</code>
:<code> ''code si condition vraie''</code>
if ''condition'' then
''code si condition vraie''
:<code>fi; </code>
fi;
</source>


La ''condition'' doit être une expression booléenne (vraie ou fausse), par exemple :
La ''condition'' doit être une expression booléenne (vraie ou fausse), par exemple :


<source lang="text">
* <code>x > 3</code>
x > 3
* <code>(x > 3) and (x < 1)</code>
(x > 3) and (x < 1)
* <code>x = 12</code>
x = 12
</source>


Si on essaie d'utiliser une expression ouverte (par exemple, x + 3) Maple retourne une erreur. Notre code s'exécute ici uniquement si la condition est vraie. Si elle est fausse, rien n'est fait. Un petit raffinement :
Si on essaie d'utiliser une expression ouverte (par exemple, x + 3) Maple retourne une erreur. Notre code s'exécute ici uniquement si la condition est vraie. Si elle est fausse, rien n'est fait. Un petit raffinement :


<source lang="text">
:<code>if ''condition'' then</code>
:<code> ''code si condition vraie''</code>
if ''condition'' then
''code si condition vraie''
:<code>else
else
:<code> ''code si condition fausse''</code>
''code si condition fausse''
:<code>fi; </code>
fi;
</source>


{{Attention
{{Attention|Avec_fond=oui|En anglais, ''if… then… else…'' signifie littéralement ''si… alors… sinon…''.}}
| Avec_fond = oui
| En anglais, ''if… then… else…'' signifie littéralement ''si… alors… sinon…''.
}}


Exemple :
Exemple :


<source lang="text">
:<code>Majeur := proc(age)</code>
Majeur := proc(age)
:<code>if age >= 18 then</code>
if age >= 18 then
:<code> "oui";</code>
"oui";
:<code>else</code>
else
:<code> "non";</code>
"non";
:<code>fi;</code>
fi;
:<code>end proc;</code>
end proc;
</source>


Ici, <code>"oui"</code> et <code>"non"</code> sont des chaines de caractères qui sont évaluées, donc retournées lors de la sortie de la procédure (car aucune autre valeur n'est évaluée par la suite).
Ici, <code>"oui"</code> et <code>"non"</code> sont des chaines de caractères qui sont évaluées, donc retournées lors de la sortie de la procédure (car aucune autre valeur n'est évaluée par la suite).
Ligne 115 : Ligne 135 :
Il est parfois nécessaire de répéter des instructions un nombre ''déterminé'' de fois. On peut pour cela utiliser l'instruction <code>for</code>, de la manière suivante :
Il est parfois nécessaire de répéter des instructions un nombre ''déterminé'' de fois. On peut pour cela utiliser l'instruction <code>for</code>, de la manière suivante :


<source lang="text">
:<code>for ''variable'' from ''debut'' to ''fin'' do</code>
for ''variable'' from ''debut'' to ''fin'' do
:<code>''code à répéter''</code>
''code à répéter''
:<code>od; </code>
od;
</source>


Écrire le code ci-dessus revient exactement à écrire la chose suivante:
Écrire le code ci-dessus revient exactement à écrire la chose suivante:


<source lang="text">
:<code>variable = début;</code>
variable = début;
:<code>''code à répéter''</code>
''code à répéter''
:<code>variable = début + 1;</code>
variable = début + 1;
:<code>''code à répéter''</code>
''code à répéter''
:<code>variable = début +2;</code>
variable = début +2;
:<code>''code à répéter''</code>
''code à répéter''
:<code>…</code>
:<code>variable = fin;</code>
variable = fin;
:<code>''code à répéter''</code>
''code à répéter''
</source>


Utiliser <code>for</code> permet donc de condenser les choses. Voici un exemple clarifiant les choses :
Utiliser <code>for</code> permet donc de condenser les choses. Voici un exemple clarifiant les choses :


<source lang="text">
:<code>x := NULL;</code>
x := NULL;
:<code>for i from 1 to 10 do</code>
for i from 1 to 10 do
:<code> x := x, i;</code>
x := x, i;
:<code>od;</code>
od;
:<code>[x];</code>
[x];
</source>


Étudions ce code ligne par ligne :
Étudions ce code ligne par ligne :
Ligne 199 : Ligne 225 :
Pour calculer la factorielle de ''n'', nous calculons la factorielle de ''n-1''. Pour celle-ci, il nous faut (''n-2'')! ''etc.'' Voici le code associé :
Pour calculer la factorielle de ''n'', nous calculons la factorielle de ''n-1''. Pour celle-ci, il nous faut (''n-2'')! ''etc.'' Voici le code associé :


<source lang="text">
:<code>factorielle := proc(n)</code>
factorielle := proc(n)
:<code> if n = 0 then</code>
if n = 0 then
:<code> 1;</code>
1;
:<code> else</code>
else
:<code> (n * factorielle(n-1));</code>
(n * factorielle(n-1))
:<code> fi;</code>
fi;
:<code>end;</code>
end;
</source>


Lorsqu'on exécute <code>factorielle(6)</code>, Maple affiche le bon résultat : <code>720</code>.
Lorsqu'on exécute <code>factorielle(6)</code>, Maple affiche le bon résultat : <code>720</code>.
Ligne 229 : Ligne 257 :
{{Bas de page
{{Bas de page
| idfaculté = informatique
| idfaculté = informatique
| leçon = [[Introduction à Maple]]
| leçon = [[../]]
| précédent = [[Introduction à Maple/Listes, tableaux, matrices|Listes, tableaux, matrices]]
| précédent = [[../Listes, tableaux, matrices/]]
| suivant = [[../Bibliothèques de fonctions|Bibliothèques de fonctions]]
| suivant = [[../Bibliothèques de fonctions/]]
}}
}}



Version du 7 avril 2009 à 08:59

Début de la boite de navigation du chapitre
Procédures
Icône de la faculté
Chapitre no {{{numéro}}}
Leçon : Introduction à Maple
Chap. préc. :Listes, tableaux, matrices
Chap. suiv. :Bibliothèques de fonctions
fin de la boite de navigation du chapitre
En raison de limitations techniques, la typographie souhaitable du titre, « Introduction à Maple : Procédures
Introduction à Maple/Procédures
 », n'a pu être restituée correctement ci-dessus.

Introduction

Toutes les opérations que nous avons réalisé jusqu'ici concernaient des opérations élémentaires (pas nécessairement simples). Pour exécuter trente fois ces opérations, nous pourrions les écrire trente fois à la suite. Cela est toutefois assez pénible et improductif : Maple dispose de quelques capacités de programmation, que nous abordons dans ce chapitre.

Les procédures (proc)

Utiliser les procédures

Une « procédure » est une opération (potentiellement très longue est complexe), repérée par son nom. Par exemple : MoudreCafe. On peut demander à Maple d'exécuter cette opération, sans avoir à se soucier de son contenu précis. Une procédure peut également nécessiter une ou plusieurs informations de départ (les arguments) pour se faire : la température T, le volume V du café dans notre exemple.

Pour l'utiliser, on pourra écrire :

MoudreCafe(T, V) ;

Enfin, une procédure peut se comporter comme une fonction : elle peut retourner une (ou plusieurs) valeur(s) lorsqu'elle est appelée. La différence tient surtout au fait qu'une procédure permet de faire beaucoup plus de choses qu'une fonction. En contrepartie, il ne faut pas espérer dériver, tracer… une procédure.

Définir une procédure

Une procédure Maple se découpe en trois parties : l'entête, le corps et le retour.

  • L'entête (MaProcedure := proc(a, b, c)) fournit les informations utiles pour utiliser la procédure : son nom (MaProcedure) et ses arguments (ici, a, b et c).
  • Le corps (x := a + b + c) indique au logiciel les actions à réaliser.
  • Enfin, la fin de la procédure retourne éventuellement un résultat spécifique. Une procédure Maple se termine toujours par end proc ou end.

Voici l'exemple complet :

MaProcedure := proc(a,b,c)
    x := a+b+c;
end proc;

Cette procédure prend trois arguments et retourne la somme des trois. En effet, une procédure retourne par défaut le dernier calcul effectué ou la dernière évaluation faite. Ici, l'affectation à la variable x sera retournée. Par exemple :


MaProcedure(1,2,3); retourne 6 ;
MaProcedure(x,x,x); retourne 3x.

Si on ne veut pas que la procédure retourne une valeur (par exemple si elle agit sur des variables globales ou qu'elle affiche déjà une suite de chiffres à l'aide de la fonction print()), on mettra en fin de programme NULL; ce qui aura pour effet d'évaluer cette variable intrinsèque à Maple et comme son nom l'indique, "rien" ne sera retourné par la procédure.

La commande return(x) permet aussi de faire retourner un résultat (ici x), mais son utilisation est particulière, car elle interrompt le programme. On ne l'utilise donc qu'en cas de sortie particulière, inattendue, d'une procédure. Dans l'exemple cité plus haut, il n'est pas nécessaire d'utiliser la fonction return().

Exemple d'illustration :

retourner := proc(x);
   for i from 1 to x do
     return(i);
   od;
end proc;

Cette procédure inutile, ne retourne que la valeur 1 car c'est lors de la première itération de la boucle for, c'est-à-dire quand i possède la valeur 1, que le programme va retourner i et s'interrompre. Aucune autre itération ne sera effectuée, quelque-soit la valeur de x (pourvu tout de même qu'elle soit supérieure ou égale à 1).

Les variables

On peut utiliser des variables dans les procédures Maple (elles sont dites « locales », ce sont par exemples les variables muettes des for). Pour cela, il n'est en pratique rien besoin de faire. Pour plus de clarté cependant, on prendra l'habitude de les préciser en début de code, avec le mot-clé local. Exemple :

MaProcedure := proc(a,b,c)
    local x;
    …

On peut également utiliser des variables accessibles depuis l'extérieur des procédures (dites « globales »), bien que cela soit moins courant. On utilise alors le mot-clé global.

Les conditions (if… then… else)

Nous voudrions pouvoir exécuter une certaine opération si un nombre x est positif, et une autre opération s'il est négatif. Comment faire ? La réponse : utiliser des conditions. Voici la syntaxe Maple qui convient :

if ''condition'' then
    ''code si condition vraie''
fi;

La condition doit être une expression booléenne (vraie ou fausse), par exemple :

x > 3
(x > 3) and (x < 1)
x = 12

Si on essaie d'utiliser une expression ouverte (par exemple, x + 3) Maple retourne une erreur. Notre code s'exécute ici uniquement si la condition est vraie. Si elle est fausse, rien n'est fait. Un petit raffinement :

if ''condition'' then
    ''code si condition vraie''
else
    ''code si condition fausse''
fi;
Panneau d’avertissement En anglais, if… then… else… signifie littéralement si… alors… sinon….

Exemple :

Majeur := proc(age)
if age >= 18 then
    "oui";
else
    "non";
fi;
end proc;

Ici, "oui" et "non" sont des chaines de caractères qui sont évaluées, donc retournées lors de la sortie de la procédure (car aucune autre valeur n'est évaluée par la suite).

Ce programme répond de la manière suivante :

Majeur(32); réponse : oui
Majeur(24); réponse : oui
Majeur(18); réponse : oui
Majeur(17); réponse : non

Les boucles

Boucles déterminées (for)

Il est parfois nécessaire de répéter des instructions un nombre déterminé de fois. On peut pour cela utiliser l'instruction for, de la manière suivante :

for ''variable'' from ''debut'' to ''fin'' do
''code à répéter''
od;

Écrire le code ci-dessus revient exactement à écrire la chose suivante:

variable = début;
''code à répéter''
variable = début + 1;
''code à répéter''
variable = début +2;
''code à répéter''
…
variable = fin;
''code à répéter''

Utiliser for permet donc de condenser les choses. Voici un exemple clarifiant les choses :

x := NULL;
for i from 1 to 10 do
 x := x, i;
od;
[x];

Étudions ce code ligne par ligne :

  • on crée une liste vide, nommée x
  • on ajoute « 1 » à la liste;
  • on ajoute « 2 » à la liste;
  • on ajoute « 10 » à la liste;
  • on retourne la liste.

Remarquez que i prend toutes les valeurs entre 1 et 10. Le programme ci-dessus retourne donc [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. Exercice rapide : adapter le code précédent pour afficher la liste des 1000 premiers entiers non nuls.

L'instruction for ne peut être utilisée que lorsqu'on connait a priori le nombre de répétitions.

Remarque : on peut avoir besoin que l'indice aille de 2 en 2, ou de 3 en 3. Il suffit de rajouter cette option dans la déclaration de la boucle : for k from 1 to 1 by 2 do en remplaçant 2 par le pas souhaité.

Boucles indéterminées (do while)

Lorsqu'on ne sait pas, a priori, combien de fois nous souhaitons répéter les instructions, il est quand même possible de s'en sortir. Il faut cependant savoir quand arrêter, sans quoi le programme restera bloqué, exécutant les mêmes instructions ad vitam æternam. On fixe donc une condition, par exemple « x < 5 ». Tant que cette condition est vérifiée, la boucle s'exécute.

Panneau d’avertissement Il faut que, dans la boucle, une instruction modifie x : si ce n'est pas le cas, la condition peut être toujours vraie, et le programme boucle pour toujours.

On utilise, pour de telles boucles indéterminées, la structure do while … od, de la manière suivante :

while (condition) do
    ''code à répéter''
    ''code qui modifie l'état de la condition''
od;

Voici un exemple d'utilisation :

x := 5;
while (x>2) do
    y := x+12;
    x := x-1;
od;

Remarquez que, dans ce cas précis, on aurait pu faire exactement la même chose avec for… Utiliser while dans ce cas n'est vraiment pas utile, mais c'est un exemple.

L'utilisation de while do … od est souvent évitable. On peut également l'utiliser pour optimiser un peu le code, mais dans la majorité des cas simples, il est rarement nécessaire ou utile.

Exercice rapide : reprendre l'exemple de la section précédente avec un while do au lieu du for.

Programmation récursive

Une procédure Maple peut tout à fait s'appeler elle-même, pour résoudre des problèmes de manière récursive. En particulier, les algorithmes de tri les plus efficaces utilisent cette méthode. Pour illustrer cela, nous allons écrire un algorithme qui calcule la (très classique) factorielle d'un entier n.

Partons des constats suivants :

  • lorsque n est strictement positif ;

Pour calculer la factorielle de n, nous calculons la factorielle de n-1. Pour celle-ci, il nous faut (n-2)! etc. Voici le code associé :

factorielle := proc(n)
  if n = 0 then
    1;
  else
    (n * factorielle(n-1))
  fi;
end;

Lorsqu'on exécute factorielle(6), Maple affiche le bon résultat : 720.

Ce type d'utilisation de la récursivité d'une fonction permet de voir tout de suite quel a été l'algorithme qui a engendré la création de cette procédure, cependant ce genre d'opération est gourmand en ressources pour Maple, car à chaque nouvel appel de la procédure factorielle, il doit garder en mémoire le résultat précédent de la procédure qui n'est pas finie, pour finalement fermer toutes les procédures lorsqu'il est arrivé à la fin de la récursivité. Cette méthode est donc à utiliser judicieusement ou à défaut, on peut utiliser les boucles for et while vues précédemment.

Remarque : on peut cependant améliorer l'efficacité de la récursivité en demandant à Maple de se souvenir des valeurs précédemment calculées en ajoutant option remember dans l'entête de la procédure.

Quelques exemples

Résumé

Au cours de ce chapitre, nous avons appris à réaliser les opérations suivantes :

  • définir une procédure avec proc ;
  • définir des variables avec local ;
  • poser des conditions, avec if … then … else … fi ;
  • former des boucles avec for ou while ;
  • réaliser des procédures récursives.

Ces points sont au cœur de l'utilisation pratique de Maple : en effet, les capacités de calcul sont bien souvent employées dans de telles procédures. Dans le chapitre prochain, nous verrons comment étendre les capacités de Maple, en prenant en compte les bibliothèques de fonctions.