TP Maple : Tortue topologique

Ce TP était l'occasion d'avoir une vision dynamique de problèmes géométriques, de découvrir quelques notions de topologie algébrique, de géométrie différentielle, de cheminement aléatoire sans en avoir l'air, et tout ça avec une petite tortue : de grandes choses à partir d'outils basiques, une nouvelle vision de problèmes connus, la main à la pâte mathématique, travailler pendant deux heures comme un apprenti chercheur...que du bonheur. Remarque : personne n'a parlé dans la première partie de la notion importante, celle de rayon de courbure... Sinon, pour le théorème qu'il fallait démontrer, quelques éléments :

  • si la tortue revient dans sa position d'origine, sa rotation totale est un multiple de 360 degrés (elle peut avoir fait n'importe quoi avant mais elle ne fait pas de saut dans l'espace-temps);
  • le problème réciproque est primordial pour la tortue : elle n'a pas de vision globale du problème ! Comment peut-elle savoir que le chemin qu'elle a parcouru est fermé ? En additionnant ses changements de direction. Une première étape est de montrer avec des outils géométriques de collège que les sommets construits avec poly1 sont cocycliques. Ensuite, il n'y a qu'une corde de longueur donnée et de direction donnée dans le cercle circonscrit (la 2e corde est à exclure) donc si la tortue sait faire des additions et des soustractions, elle peut avoir un résultat global à partir de renseignements locaux.

Point n'est besoin d'effectuer deux pages de calculs pour ça...

Voici quelques procédures Maple utiles :

Maple
pos := [0,0]:
dir := 0.:
chemin := plottools[point](pos, color=pink,symbol=box):
 
tourne := proc(angle)
global dir,chemin;
    dir := dir + evalf(Pi)*angle/180.;
end:
 
avance := proc(long)
global pos,dir,chemin;
local pos0;
      pos0 := pos;
    pos := pos + [long*cos(dir),long*sin(dir)];
    chemin := chemin,plot([pos0,pos],color=green);
end:
 
saute := proc(long)
global pos,dir,chemin;
    pos := pos + [long*cos(dir),long*sin(dir)];
end:
 
efface := proc()
global pos,dir,chemin;
    pos := [0,0]:
    dir := 0:
    chemin := plottools[point](pos, color=pink,symbol=box):
end:
 
affiche := proc()
global chemin;
    chemin := chemin,plottools[point](pos, color=red,symbol=diamond):
    plots[display](chemin,scaling=constrained,axes=none);
end:
 
 
carre := proc(cote)
local k;
    for k from 1 to 4 do
        avance(cote);
        tourne(90);
    od;
end: 
 
 
efface():
carre(0.5):
tourne(45):
carre(0.5):
efface():
 
cercle := proc(r,a)
local k;
    for k from 1 to floor(360/a) do 
        avance(r);
        tourne(a);
    od;
end:
 
arc := proc(r,deg)
local k;
    for k from 1 to deg do 
        avance(r);
        tourne(1);
    od;
end:
 
efface():
seq(cercle(k,k),k=1..8):
affiche();
 
 
efface():
for k from 1 to 9 do arc(1,360); tourne(40); od:
affiche();
 
poly1 := proc(cote,angle,nb)
local k;
    for k from 1 to nb do
        avance(cote);
        tourne(angle);
    od;
end:
 
efface():
poly1(1,108,10):affiche();
 
poly2 := proc(cote,angle,facteur,nb)
local k;
    for k from 1 to nb do
        avance(cote);
        tourne(angle);
        avance(cote);
        tourne(facteur*angle);
    od;
end:   
 
efface():poly2(1,144,2,20):affiche();
 
poly_spirale := proc(cote,angle,inc,nb)
    if nb = 0 then NULL;
    else
        avance(cote);
        tourne(angle); 
        poly_spirale(cote + inc,angle,inc,nb - 1)
    fi;
end:
 
efface():poly_spirale(100,91,1,100):affiche();
 
poly_spirale_2 := proc(cote,angle,inc,nb)
    if nb = 0 then NULL;
    else
        avance(cote);
        tourne(angle); 
        poly_spirale_2(cote,angle + inc,inc,nb - 1)
    fi;
end:
 
efface():poly_spirale_2(10,0,7,500):affiche();
 
efface():poly_spirale_2(10,1,70,500):affiche();
 
poly3_1 := proc(cote,angle,total)
    if angle = 0 then 
        RETURN(`ligne droite`)
    elif floor(angle) < angle then
        RETURN(`l'angle doit être un entier`)
    elif irem(total,360) > 0 or total = 0 then 
        avance(cote);
        tourne(angle);
        poly3_1(cote,angle,total + angle);
    else chemin;
    fi;
end:  
 
poly3 := proc(cote,angle)
    poly3_1(cote,angle,0)
end:
 
poly4 := proc(cote,angle)
local total;
    if angle = 0 then 
        ERROR(`ligne droite`)
    elif floor(angle) < angle then
        ERROR(`l'angle doit être un entier`)
    else
        total := 0;
        while irem(total,360) > 0 or total = 0 do 
            avance(cote);
            tourne(angle);
            total := total + angle;
        od;
    fi;
end: 
 
 
efface():poly2(1,70,2,10):affiche():
 
ellipse := proc(s,e)
local n;
    for n from 0 to 360 do
        tourne(n); avance(s);tourne(-n);
        tourne(-n);avance(s*e);tourne(n);
    od:
end:
 
efface():ellipse(2,2):affiche():
 
 
efface():poly1(1,144,10):affiche():
 
ciseaux := proc(distance,phase)
    tourne(phase);
    avance(distance);
    tourne(-2*phase);
    avance(distance);
    tourne(phase);
end:
 
efface():ciseaux(1,120):ciseaux(1,10):affiche();
 
random_move := proc(d1,d2,a1,a2,n)
local random_dir,random_avance,k;
    random_dir := rand(d1..d2);
    random_avance := rand(a1..a2);
    for k from 1 to n do
        tourne(random_dir());
        avance(random_avance());
    od:
end:
 
efface():random_move(-100,100,-100,100,1000):
affiche();
 
proie := [200,200]:
 
distance := proc(c1,c2)
    RETURN(((c2[1]-c1[1])^2 + (c2[2]-c1[2])^2)) 
end:
 
chasse := proc(d,a,o,n)
global chemin;
local random_dir,random_avance,random_odeur,k,dist,new_dist;
    chemin := chemin, plottools[point](proie,
                                       color=blue,symbol=circle):
    random_dir := rand(-d..d);
    random_avance := rand(1..a);
    dist := distance(pos,proie);
    for k from 1 to n do
        avance(random_avance());
        tourne(random_dir()); 
        new_dist := distance(pos,proie);
        if new_dist > dist then tourne(o); fi;
        dist := new_dist;
    od;
end:
 
 
efface():chasse(60,5,90,200):affiche();

courtesy of webmatter.de