Mathématice, intégration des Tice dans l'enseignement des mathématiques  
Sommaire > N°16 - Septembre 2009 > Le dossier du numéro > Faire de la programmation avec CaRMetal en (...)

Faire de la programmation avec CaRMetal en Seconde
où on montre qu’un logiciel de géométrie dynamique peut servir à faire autre chose que de la géométrie
Moteur de recherche
Mis en ligne le 25 septembre 2009, par Alain Busser

On peut parler d’instrumentalisation de CaRMetal à propos de cette nouvelle fonctionnalité du logiciel, celui-ci étant muni d’un véritable éditeur javascript avec des instructions spécifiques d’entrée-sortie, une gestion efficace des messages d’erreur, et un retour en arrière, qui fait de CaRMetal un outil de programmation. Et, surprenamment, un bon.

C’est en me livrant au classique exercice de comparaison de langages de programmation, dont le résultat est téléchargeable au bas de cet article que le chronomètre m’a révélé la puissance de cet outil : 30 secondes pour écrire et tester un petit programme : Si 30 secondes m’ont suffi à moi, prof, pour préparer le corrigé, je peux espérer qu’une heure me suffira pour aider mes élèves à déboguer, les mêmes fonctionnalités devant être utiles dans les deux cas...

Une petite remarque historique tout d’abord : La possibilité de créer des figures complexes avec un logiciel de géométrie dynamique existait déjà auparavant. Je connais trois exemples :

  • DrGeo avec le langage Scheme ;
  • Kig avec le langage Python (langage) ; ces deux logiciels figurent sur la distribution libre RoxMaths ;
  • et depuis peu, Cinderella qui a son propre langage de script, et qui n’est pas un logiciel libre.

CaRMetal 3.0 se télécharge en cliquant sur le lien téléchargement dans la page suivante. C’est la version 3.0 qui possède le fameux éditeur en ligne. Pour l’ouvrir, on clique sur Javascript>ouvrir l’éditeur de script.


Entrée et sortie de données ; affectation

Pour entrer une donnée dans le programme, il suffit de cliquer sur "Input()" dans la partie droite de l’éditeur, et la première ligne de programme apparaît, sous la forme d’un exemple complet, qu’il suffit de modifier par exemple pour changer le nom de la variable et le texte de la question. De façon analogue, pour afficher le contenu d’une variable, on clique sur "Println()"" et on adapte la nouvelle ligne de programme apparue. La sortie se fait dans une fenêtre spécialement créée par CaRMetal ou moment où il en a besoin.

Il faut distinguer deux manières d’affecter une variable : Au moment où on crée celle-ci, on peut déjà lui affecter une valeur de départ qui montre à Javascript de quel type elle est (texte, nombre, booléen etc.) ce qu’on fait par "var x=1" ; et dans le corps du programme, on peut modifier la valeur de la variable sans avoir à la créer ; dans le cas de Javascript cela se fait par "x=1", notation très répandue mais malheureuse [1].

Or CaRMetal permet d’illustrer géométriquement la distinction entre ces deux manières d’affecter une valeur à une variable (ou plutôt deux variables : une abscisse et une ordonnée) : On peut créer un point par "Point()", et le bouger par Move()".

Pour simuler le mouvement d’un projectile [2], on entre le script suivant :

a=Point(0,0);
for (n=0; n<=100; n++){
        x=n/100;
        y=4*x*(1-x);
        Move(a,x,y);
        Pause(10);       
}

Remarque : On peut copier-coller ce code entre la présente page, et l’éditeur de script de CaRMetal.

Le seul point délicat est en fait la création du point : Quand on écrit "a=Point(0,0)", l’éditeur crée une chaîne de caractères et la met dans la variable a. En plus il crée le point et lui affecte les coordonnées (0,0). On peut suggérer un nom pour le point mais ici on a laissé CaRMetal s’en occuper, il a choisi P1. Donc dorénavant a contient le texte "P1". Et donc lorsqu’on écrit "Move(a,x,y)" au moment où x=0,1 et y=0,04, CaRMetal va voir Move(P1,0.1,0.04) et va donc déplacer P1 comme on le souhaitait.

Seules les lignes qui commencent par x= et y= ont été écrites au clavier, les autres ont été obtenues en cliquant sur des options du menu à droite. Donc l’exemple a été très vite écrit sans faute de syntaxe genre oubli de point-virgule ou non concordance de parenthèses. Si j’ai l’air d’insister là-dessus, c’est parce que c’est la raison essentielle pour laquelle j’ai choisi cet outil pour faire manipuler mes futurs élèves de Seconde : C’est en forgeant avec la souris que je suis devenu forgeron... En y réfléchissant, on pouvait raccourcir le code à coup de javascript :

a=Point(0,0);
for (x=0; x<=1; x+=0.01){
        y=4*x*(1-x);
        Move(a,x,y);
        Pause(10);       
}

Mais la production de code court n’est pas une priorité dans l’enseignement de la programmation.


Boucles à nombres prédéfinis d’exécution

Ce pour quoi ce langage de script a été conçu, c’est sans doute pour réaliser des figures complexes de façon automatique (plutôt qu’inciter un utilisateur à appliquer 1000 fois la même macro, autant confier ce travail à javascript). Dans l’exemple ci-dessous, on considère un triangle représenté en bleu dont les murs sont des miroirs, et un point M, en noir. De M on fait partir un rayon laser (il paraît que les mathématiciens appellent ça une "demi-droite") qui heurte le premier miroir en N. Les segments qui constituent le triangle ont été nommés par CaRMetal s1, s2 et s3, et N a été choisi sur s3.

copie d’écran de la figure initiale

Pour représenter la trajectoire du rayon laser, on écrit le script suivant :

m="M";
n="N";
for (i=0; i<100; i++){
        d1=Perpendicular("s3",m);SetHide(d1,true);
        p=Intersection(d1,"s3");SetHide(p,true);
        q=Symmetry(p,m);SetHide(q,true);
        r=Ray(q,n);SetHide(r,true);
        s=Intersection(r,"s2");SetHide(s,true);
        u=Vector(n,s);
        m=n;
        n=s;
        d1=Perpendicular("s2",m);SetHide(d1,true);
        p=Intersection(d1,"s2");SetHide(p,true);
        q=Symmetry(p,m);SetHide(q,true);
        r=Ray(q,n);SetHide(r,true);
        s=Intersection(r,"s1");SetHide(s,true);
        u=Vector(n,s);
        m=n;
        n=s;
        d1=Perpendicular("s1",m);SetHide(d1,true);
        p=Intersection(d1,"s1");SetHide(p,true);
        q=Symmetry(p,m);SetHide(q,true);
        r=Ray(q,n);SetHide(r,true);
        s=Intersection(r,"s3");SetHide(s,true);
        u=Vector(n,s);
        m=n;
        n=s;
}

Dans la boucle effectuée 100 fois, on effectue trois fois la même suite d’opérations : On nomme m et n les extrémités du vecteur, on construit le symétrique q de m par rapport à s3 (en plusieurs étapes, CaRMetal n’ayant pour l’instant pas d’instruction "réflexion" en javascript, c’est très intéressant pour des élèves de Seconde), puis la demi-droite de sommet q passant par n, qui coupe s2 en s, et enfin le vecteur allant de n à s ; ensuite on refait tout ça en remplaçant m et n par les points nouvellement construits, et en appliquant une permutation circulaire à s1, s2 et s3.

Le script construit la figure suivante, manipulable à la souris (on peut bouger M, N et les sommets du triangle) :

La figure ci-dessus est clairement améliorable puisque la réflexion du rayon laser sur le segment s2 ne l’amène pas forcément à croiser le triangle en s1 mais parfois en s3 à nouveau. On peut au moins manipuler la figure en cherchant quand la trajectoire devient intéressante. Je suggère d’essayer avec un triangle presque équilatéral mais si le triangle est vraiment équilatéral, la trajectoire est moins intéressante. Pourquoi ? Le problème étudié, appelé billard triangulaire, est nettement plus complexe que prévu... Mais le cas du billard elliptique donne de très jolies enveloppes de droites : les caustiques.

Un autre exemple de ce qu’on peut faire avec ça est le fichier sur l’attracteur de Hénon, remarquable par la brièveté du script qui l’a engendré.

Une force des langages objet est que les boucles ne sont pas forcément effectuées lorsque la variable n évolue dans un nombre ordinal mais aussi lorsque la variable n évolue dans un ensemble fini quelconque. On peut s’en servir pour étudier les propriétés de certaines fonctions sur les solutions d’une équation (théorie de Galois, en bonne place dans les modes d’emploi de Maple et de Maxima) ou pour faire de la géométrie finie, entre autres...

Dans le cas présent (classe de Seconde), on peut placer sur un cercle trigonométrique des angles "remarquables" tout simplement en les énumérant. Et en plus on peut les rendre magnétiques et leur attacher un point M. Sur la figure suivante :

copie d’écran de la figure initiale

on exécute le script suivant :

SetMagneticRay("M",2000);
angrem=[0,30,45,60,90,120,135,150,180,210,225,240,270,300,315,330];
for (n in angrem){
        t=Math.PI*angrem[n]/180;
        x=Math.cos(t);
        y=Math.sin(t);
        a=Point(x,y);
        SetShowName(a,true);
        SetAlias(a,angrem[n]+"°");
        AddMagneticObject("M",a);
}

Ce qui donne le fichier suivant :


tests et boucles avec condition d’arrêt

Les tests s’écrivent en JavaScript de façon très classique : if...else... sauf que l’usage d’accolades évite le recours au "fi" ou "endif" habituel. Un exemple d’utilisation est la construction du triangle de Sierpinski avec un système de fonctions itérées ; l’avantage du triangle de Sierpinski est qu’il n’est pas nécessaire d’utiliser le vocabulaire des homothéties en
Seconde, puisque les rapports des homothéties étant égaux à $\frac{1}{2}$, on peut ne parler que de milieux : L’exécution du code suivant sur une figure CaRMetal ne contenant que trois points A, B et C

m=Point(Math.random(),Math.random());
SetHide(m,true);
for (i=0; i<2000; i++){
   t=3*Math.random();
   if (t<1){
       n=MidPoint(m,"A");col="green";
   } else if (t<2){
       n=MidPoint(m,"B");col="blue";
   } else {
       n=MidPoint(m,"C");col="red";
   }
   SetPointType(n,"point");SetColor(n,col);
   m=n;
}

produit la figure suivante :

Copie d’écran car la figure, longue à charger, bloque la page SPIP
On téléchargera la figure en fin d’article.

boucles à sortie conditionnelle

La possibilité de quitter une boucle selon le résultat d’un test a été promue par le groupe créateur d’Algol (langage) comme une des briques de la programmation structurée. On peut la simuler dans une boucle, avec break, mais un langage de programmation qui possède les deux variantes (while et until) toutes faites est incontestablement un atout maître en Seconde (parce qu’il donne de bonnes habitudes de programmation, et que c’est en Seconde que ces habitudes peuvent être prises). L’éditeur de CaRMetal possède la boucle "while" qui va être utilisée dans l’exemple suivant, inspiré par Monique Gironce, et qui vise à mesurer le temps d’évasion d’une particule brownienne en trois dimensions :

Un robot évolue dans l’espace grâce à six petites rétrofusées disposées aux sommets d’un octaèdre régulier (ou au centre de ses faces, en effet ce robot est cubique). Las, un bogue fait que le mouvement du robot se fait au hasard parallèlement aux axes de coordonnées, dans un sens erratique à chaque allumage d’une rétrofusée, d’une distance constante (ici 0,1 unité de longueur). On cherche à savoir à quel moment ce pauvre robot réussira à s’éloigner d’une distance donnée (ici 2 unités) de son point de départ.

Pour commencer, on va représenter une trajectoire du robot, cette fois-ci sur un fichier 3D de CaRMetal. Un tel fichier est fourni avec des macros spécifiques à la 3D, et avec un repère OXYZ (4 points) de l’espace. Pour représenter le point de coordonnées x, y et z, on va écrire les coordonnées de sa projection plane dans le langage de CaRMetal (traitement de chaînes de caractères). Et dans l’écriture des coordonnées, il y a x, y et z qui sont des nombres ! Précéder leurs noms du caractère "underscore" (sous le 8 du clavier) permet à CaRMetal de récupérer les valeurs de ces nombres, de les convertir en chaînes de caractères et de les insérer au bon endroit dans le texte. La détermination du temps de sortie se fait avec la fameuse boucle "while" dont la condition d’arrêt est que $x^2+y^2+z^2\geqslant R$ (le robot est sorti de la sphère de rayon $\sqrt{R}$). Le script est alors le suivant [3] :

R=4; h=0.1;
x=0; y=0;z=0;
a=Point("x(O)+_x*(x(X)-x(O))+_y*(x(Y)-x(O))+_z*(x(Z)-x(O))",
"y(O)+_x*(y(X)-y(O))+_y*(y(Y)-y(O))+_z*(y(Z)-y(O))");
SetHide(a,true);
while (x*x+y*y+z*z<R){
        t=3*Math.random();
        s=Math.floor(2*Math.random())*2-1;
        if (t<1){
                x+=s*h;
                x=Math.round(10000*x)/10000;
        }
        else{
                if (t>2){
                        z+=s*h;
                        z=Math.round(10000*z)/10000;
                }
                else{
                        y+=s*h;
                        y=Math.round(10000*y)/10000;
                }
        }
        b=Point("x(O)+_x*(x(X)-x(O))+_y*(x(Y)-x(O))+_z*(x(Z)-x(O))",
        "y(O)+_x*(y(X)-y(O))+_y*(y(Y)-y(O))+_z*(y(Z)-y(O))");
        SetHide(b,true);
        r=Segment(a,b);
        a=b;
}

En faisant marcher ce script deux fois sur la même figure 3D, on obtient la figure suivante (elle aussi peut-être longue à charger) :

C’est avec la souris, clic-droit enfoncé, qu’on peut faire tourner la figure. En bas de cette page, un fichier avec 4 traces de marche aléatoires est téléchargeable. Il n’a pas été inclus dans le corps de l’article pour ne pas allonger exagérément le temps d’ouverture de celui-ci. La modification du fichier pour déterminer le temps mis à sortir de la boucle est laissée en exercice.


Conclusion

L’outil JavaScript de CaRMetal, à l’origine vraisemblablement destiné à produire des figures complexes de façon automatique, se révèle à l’usage franchement performant pour faire produire par les élèves de Seconde, des CarScripts illustrant des notions d’algorithmique dans un contexte géométrique, donc graphique. Et quel que soit le jugement qu’on porte sur le langage JavaScript, la présence de plusieurs outils de développement performants (celui décrit dans cet autre article du présent numéro et celui de CaRMetal, au moins) incite à choisir le langage pour bénéficier de ces outils.

L’IREM de La Réunion a, cette année, un groupe de travail sur l’algorithmique avec les CarScripts de CarMetal. Dans cette page, on trouvera déjà un premier document de 56 pages de prise en main de cet outil, ainsi que des articles sur les premières utilisations concrètes en classe de seconde.

Cette rubrique est également consacrée, sans le dire, à une utilisation des CarScripts, qui servent essentiellement à tracer des graduations sur des courbes, ce qui est déjà pas mal ! La rubrique en question est en cours de rédaction, elle devrait se remplir progressivement au cours de l’année 2009-2010.

Ndlr : Sur le même thème, voir aussi les deux articles de prise en main d’Yves Martin sur le site de l’IREM de La Réunion.
http://www.reunion.iufm.fr/recherche/irem/spip.php?article186 (partie 1) et
http://www.reunion.iufm.fr/recherche/irem/spip.php?article210 (partie 2)


notes

[1pour incrémenter n, on peut écrire n=n+1 ce qui heurte mon œil d’algébriste ; on peut lui préférer la notation n+=1, voire mieux : n++

[2pour faire simple, on va lui donner une vitesse constante, il est possible d’améliorer le réalisme.

[3il a fallu remplacer x, y et z par leurs arrondis au dix-millième sinon ça ne marchait pas, et ce débogage a été facilité par la souplesse de la console JavaScript de CaRMetal.

Documents associés à l'article
  CercleAvecAngles   |   (CarMetal - 4.4 ko)
  Sierpinski2000pts   |   (CarMetal - 213.5 ko)
  MouvBrownien2traces   |   (CarMetal - 329 ko)
  Brownien3D4traces   |   (CarMetal - 773.7 ko) Attention figure longue à ouvrir (1500 segments)
     |   (CarMetal - 50.6 ko)
Réagir à cet article
Vous souhaitez compléter cet article pour un numéro futur, réagir à son contenu, demander des précisions à l'auteur ou au comité de rédaction...
À lire aussi ici
MathémaTICE est un projet
en collaboration avec
Suivre la vie du site Flux RSS 2.0  |  Espace de rédaction  |  Nous contacter  |  Site réalisé avec: SPIP  |  N° ISSN 2109-9197