PROGRAM Lissajou;

{
Epreuve informatique de l'Ecole Polytechnique           92.158
--------------------------------------------------------------

1° 	Dans En, espace Euclidien de dimension n muni d'une distance d, on
considère la trajectoire d'un point mobile Mt dont les coordonnées
(m1, m2 ....  mn) sont des fonctions périodiques du temps t :

                        mi=sin(wi.t)   1<=i<=n
 	

où les wi  sont des constantes réelles quelconques, appelées "coefficients".

Etudier les propriétés de cette trajectoire à l'aide d'un programme Pascal.
Quel est le domaine décrit par le point M lorsque t varie de 0 à +infini ?
Illustrer graphiquement dans le cas où n=2.


2° 	Soit f(x) une application de En dans R et un nombre réel T>0.
On considère la moyenne des valeurs prises par f(M) lorsque M décrit l'arc
paramétré défini par 0<t<T :

Ecrire un programme Pascal qui cherche une approximation de la limite Foo
de F(T) quand T tend vers +infini, dans le cas particulier où la fonction f
est égale à la distance du point M à l'origine : f(M)=d(M0 ,M).

Reporter sur un graphique le nuage des points ayant Foo pour ordonnée et
n pour abscisse pour différents choix des coefficients wi. Qu'observe-t-on ?


3° 	Soit d(A,Mt) la distance qui sépare  Mt d'un point fixe A.
Ecrire un programme Pascal pour étudier les variations de cette distance en
fonction de t. On s'intéresse en particulier aux extrema sur l'intervalle
[0,T] :

                        inf[d(A,Mt)] 	et   sup[d(A,Mt)]

Ecrire un programme qui cherche, pour différentes positions du point A et
différentes combinaisons des coefficients wi la limite de ces deux extrema
lorsque T tend vers +infini.

Comparer les résultats obtenus avec ceux d'un raisonnement géométrique.

4 	Dans les cas où la limite inférieure précédemment calculée est nulle, écrire un
programme Pascal qui pour une suite de réels dn>0 de plus en plus petits fournis comme
paramètre,
recherche la plus petite valeur positive de t vérifiant d(A, Mt)<dn

                                         - - -

Applications numériques suggérées :
                     i
1er cas  : 	wi=pi  		2ème cas :   wi=2+i
Point fixe :	A=(ai)		ai=l		1<=i<=n   où  l réel.

+------------------------------------------------------------+
¦              Imprimer tous les résultats                   ¦
¦     en indiquant chaque fois à quoi ils correspondent      ¦
+------------------------------------------------------------+


                             -=-=-}

uses
  crt, modubase;

Const
     Escape=#27;
     maxn=30;


Var
    Ch         : Char ;
    n          : integer;
    x1,x2,y1,y2 : real;
    cas         : integer;

Type
    Myreal = {real }   extended          ;
    Vecteur=  array[1..maxn] of real;
    Points = record
                 x:vecteur;
             end;





Var
   Omega:vecteur;
   O:Points;

Procedure Genere(Var M:points;t:real);
Var
   i:integer;
begin
     for i:=1 to n do
         M.x[i]:=sin(omega[i]*t);
end

Procedure Joindre(M1,M2:points);
begin
     with M1 do Deplace(x[1],x[2]);
     with M2 do Trace  (x[1],x[2]);
end ;





Function Distance(M1,M2:points):MyReal;
Var
   i:integer;
   d:Myreal;
begin
     d:=0;
     for i:=1 to n do
         d:=d+sqr(M1.x[i]-M2.x[i]);
     distance:=sqrt(d);
end ;

Procedure Choix_omega(cas:integer);
Var
   i:integer;
begin
     for i:=1 to n do
         case cas of
         1:omega[i]:=puiss(pi,i);
         2:omega[i]:=2+i;
         3:omega[i]:=1;
         end; {esac}
end;


Function f(M:points):MyReal;
Var
   i:integer;
   z:real;
begin
     case cas of
     1:f:=distance(O,M);
     2:begin
            z:=0;
            for i:=1 to n do
                z:=z+sqr(omega[i])*(1-sqr(M.x[i]));
            f:=sqrt(z);
       end;
     3:begin
            z:=1;
            for i:=1 to n do
                z:=z*(1-sqr(M.x[i]));
            f:=sqrt(z);
       end;
     end; {esac}
end ;






Procedure Init(hx1,hx2,hy1,hy2:real);
Var
   O:Points;
begin
     x1:=hx1;
     x2:=hx2;
     y1:=hy1;
     y2:=hy2;
      Initgraphique;
      Fenetre(x1,x2,y1,y2);
      Couleur(Bleu);
      Croix(0,0);
      Ecris('o');
      Deplace(0,0);
      Trace(0,1);
      Ecris('y');
      Deplace(0,0);
      Trace(x2*0.9,0);
      Ecris('x');
end;


Procedure Trace_courbe(t1,t2:real;c:integer);
Const
     npas=50000;
     nstat=1000;
Var
   t:real;
   pas : Real;
   O,M1,M2: points;
begin
     n:=2;           {rappel}
     Deplace(x1,y2*0.9);Ecris('Lissajou');
     pas:=(t2-t1)/npas;
     genere(O,0);
     t:=t1;
     Genere(M2,t);
     repeat
           Couleur(c);
           t:=t+pas;
           M1:=M2;
           Genere(M2,t);
           Joindre(O,M2);     {  Point(M2.x[1],M2.x[2]);}
           if random<(1/2000) then
              c:=trunc(random*32);

     until KeyPressed;
     Ch:=ReadKey;
end;

Procedure barre(b:real);
begin
     Couleur(vert);
     Deplace(0,b);
     Trace(x2,b)
end;


Procedure Histogramme(ca:integer;nom:string);
Const
     npas=1000;
     nclasse=100;
Var
   tpas,coeff:real;
   i:integer;
   t:real;
   y:real;
   d:real;
   M,M1,M2:Points;
   stats:array[0..nclasse] of integer;
begin
     for i:=0 to nclasse do
         stats[i]:=0;
     coeff:=nclasse/n;
     Init(-1,200,-0.2,2);
     cas:=ca;
     Couleur(brillant);
     Deplace(x1,y2*0.95);
     Ecris('HISTOGRAMME : '+nom);
     Deplace(x1,y2*0.90);
     Ecris('n=');EcrisEntier(n);
     for i:=1 to n do
          Barre(sqrt(i));

     Couleur(brillant);
     tpas:=x2/npas;
     t:=0;
     M2.x[1]:=t;
     M2.x[2]:=0;
     repeat
           t:=t+tpas;
           Genere(M,t);
           M1:=M2;
           M2.x[1]:=t;
           y:=f(M);
           M2.x[2]:=y;

           Joindre(M1,M2);
           i:=trunc(y*coeff);
           inc(stats[i]);
           Point(stats[i]/100,y);


     until KeyPressed;
     Ch:=readKey;
end;

Procedure Minmax(A:Points;nom:string)
Const
     npas=10000;
     nclasse=100;
Var
   mini,maxi:real;
   tpas,coeff:real;
   i,mask:integer;
   t:real;
   y:real;
   d:real;
   M,M1,M2,B:Points;
   stats:array[0..nclasse] of integer;
begin
     cas:=1;   {distance}
     Init(-1,2000,-0.2,2*sqrt(n));
     Couleur(brillant);

     Deplace(x1,y2*0.95);
     Ecris('MIN-MAX : '+nom);
     Deplace(x1,y2*0.90);
     Ecris('n=');EcrisEntier(n);
     Couleur(vert);
     Barre(1);
     y:=0;
     for mask:=0 to trunc(puiss(2,n)-0.99) do
         begin
              for i:=1 to n do
              begin
                   if (mask shr (i-1))=0 then
                      B.x[i]:=1
                   else
                      B.x[i]:=-1;
              end;
              if distance(A,B)>y then
                 y:=distance(A,B);
         end;
     Barre(y);

     Couleur(brillant);
     mini:=1;
     maxi:=1;

     tpas:=x2/npas;
     t:=0;
     M2.x[1]:=t;
     M2.x[2]:=0;
     repeat
           t:=t+tpas;
           Genere(M,t);
           M1:=M2;
           M2.x[1]:=t;
           y:=distance(A,M);
           M2.x[2]:=y;
           if y>maxi then
              begin
                   maxi:=y;
                   deplace(0,y);
                   trace(t,y);
              end;
           if y<mini then
              begin
                   mini:=y;
                   deplace(0,y);
                   trace(t,y);
              end;
           Couleur(brillant);
           Joindre(M1,M2);

     until KeyPressed;
     Ch:=readKey;
end;

Procedure Approche(A:Points);
Const
     npas=100;
     nclasse=100;
Var
   mini,maxi:real;
   tpas,coeff:real;
   i,mask:integer;
   t:real;
   y,z,v:real;
   d:real;
   M,M1,M2,B:Points;
begin
     v:=0;
     for i:=1 to n do
         v:=v+sqr(omega[i])*(1-sqr(A.x[i]));
     v:=sqrt(v);          { vitesse maxi }
     WriteLN('Vitesse en A : v=',v:12:9);

     mini:=1;
     tpas:=1/v;
     t:=0;
     repeat
           t:=t+tpas;
           Genere(M,t);
           y:=distance(A,M);
           if y<mini then
              begin  { si s'éloigne}
                   Write('.');
                   z:=0;
                   for i:=1 to n do
                       begin
                            z:=z+(M.x[i]-A.x[i])*omega[i]*cos(omega[i]*t);
                       end;
                   if z>0 then
                          begin
                               mini:=y;
                               WriteLN;
                               Write('d(A,Mt)=',y:12:7,' pour t=',t:15  :8);
                               Write(' v*t*d=',v*t*y:12:5);
                               tpas:=0.3*y/v;
                          end;
              end;
     until KeyPressed;
     Ch:=ReadKey
     WriteLN;
end;


Procedure Moyenne(ca:integer;nom:string);
Const
     npas=2000;
Var
   tpas:real;
   np:longint
   i,j:integer;
   t:real;
   z:real;
   M,M1,M2:Points;
begin
     cas:=ca;
     cas:=1;   {distance}
     Init(-1,maxn,-0.2,4);
     Couleur(brillant);
     Deplace(x1,y2*0.95);
     Ecris('MOYENNE de la distance M°M');
     Deplace(x1,y2*0.85);Ecris('cas n°1 : wi= Pi puissance i');
     Deplace(x1,y2*0.80);Ecris('cas n°2 : wi= 2+i');
     Deplace(x1,y2*0.75);Ecris('cas n°3 : wi= 1');

     for j:=1 to 3 do
         Barre(j);

     for j:=1 to 3 do
         begin
              M2.x[1]:=0;
              M2.x[2]:=0;

              For n:=1 to maxn do
                begin
                     choix_omega(j);
                     tpas:=x2/npas;
                     tpas:=sqrt(2);
                     t:=0;
                     z:=0;
                     np:=0;
                     repeat
                           Inc(np);
                           t:=t+tpas;
                           Genere(M,t);
                           z:=z+f(M);
                     until np>npas;
                     M1:=M2;
                     M2.x[1]:=n;
                     M2.x[2]:=z/np;
                     Couleur(Brillant);
                     Joindre(M1,M2);
                     Couleur(Vert);
                     EcrisReel(M2.x[2]);

                end;  {for j:=1 to 2}
     end;
     Pause;
end;

Procedure Presentation;
Var
   i:integer;
Begin
      Efface;
      WriteLN(' ========== Figures de LISSAJOU ================');
      WriteLN('                                        ');
      WriteLN('                                        ');
      WriteLN('   (1) Tracé de la figure               ');
      WriteLN('   (2) Tracé d''histogrammes            ');
      WriteLN('   (3) Valeurs moyennes                 ');
      WriteLN('   (4) Extrema de f(Mt)                 ');
      WriteLN('   (5) d(A,Mt)<delta                    ');
      WriteLN('                              ');
      Write('   Tapez votre Choix  :  ');
      For i:=1 to maxn do
          O.x[i]:=0;


end;




procedure Question1;
Var
   i:integer;

begin
     Efface;
     Writeln('+---------------------- Question n°1 -------------------------------+');
     Writeln('¦                                                                   ¦');
     Writeln('¦   Tracé de la figure                                              ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('+-------------------------------------------------------------------+');
     Randomize;
     n:=2;
     Repeat
          Init(-1.2,1.2,-1.2,1.2);

           for i:=1 to n do
               omega[i]:=random;

           Trace_courbe(0,1000,Brillant);
           Modetexte;
     until false;
end;


procedure Question2;
Var
   i:integer;
   A:Points;
begin
     Randomize;
     Repeat;
     ModeTexte;
     Efface;
     Writeln('+---------------------- Question n°2 -------------------------------+');
     Writeln('¦                                                                   ¦');
     Writeln('¦   Tracé d''un histogramme                                          ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦    (1) Distance OM                                                ¦');
     Writeln('¦    (2) Vitesse                                                    ¦');
     Writeln('¦    (3) sqrt( (1-sqr(x1))(1-sqr(x2))...(1-sqr(xn)))                ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('+-------------------------------------------------------------------+');
     Writeln;
     Writeln('Choisissez une option');
     Writeln;
     n:=3;
     for i:=1 to n do
         omega[i]:=random;

             repeat
              Read(Ch)
              until Ch in ['0'..'3'];
          case ch of
               '1':  Histogramme(1,' Distance OM ');
               '2':  Histogramme(2,' Vitesse');
               '3':  Histogramme(3,' sqrt( (1-sqr(x1))(1-sqr(x2))...(1-sqr(xn)))');
          end; {esac}

     until ch='0';
end;

procedure Question3;
Var
   i:integer;
   A,B:Points;
begin
     Randomize;
     Efface;
     Writeln('+---------------------- Question n°3 -------------------------------+');
     Writeln('¦                                                                   ¦');
     Writeln('¦   Calcul de valeur moyenne de distance M°M                        ¦');
     Writeln('¦    en fonction de M et des omega                                  ¦');
     Writeln('¦                                                                   ¦');
     Writeln('+-------------------------------------------------------------------+');
     Pause;
     Moyenne(1,' Distance OM ');

end;



procedure Question4;
Var
   i:integer;
   A:Points;
begin
     Randomize;
     ModeTexte;
     Efface;
     Writeln('+---------------------- Question n°4 -------------------------------+');
     Writeln('¦                                                                   ¦');
     Writeln('¦   Extrema de d(A,Mt)                                         ¦');
     Writeln('¦                                                                   ¦');
     Writeln('+-------------------------------------------------------------------+');
     Writeln;
     n:=3;
     for i:=1 to n do
         begin
              omega[i]:=random;
              A.x[i]:=random;
         end;

     Minmax(A,'Extrema de d(A,Mt)');
     Pause;


end;


procedure Question5;
Var
   i:integer;
   A,M:Points;
   Delta:real;
   t:real;
   lambda:real;
begin
     Randomize;
     ModeTexte;
     Efface;
     Writeln('+---------------------- Question n°5 -------------------------------+');
     Writeln('¦                                                                   ¦');
     Writeln('¦            d(A,Mt)<delta                                          ¦');
     Writeln('¦                                                                   ¦');
     Writeln('+-------------------------------------------------------------------+');
     Writeln;


     n:=1;

     Repeat
           Inc(n);
           WriteLN('=================================================');
           Write('n=',n,'  A=(');
           lambda:=random;
           for i:=1 to n do
               begin
                    A.x[i]:=lambda;
                    Write(A.x[i]:10:7,',');
               end;
           WriteLN(')');
           Write('omega=(');
           for i:=1 to n do
               begin
                    omega[i]:=puiss(pi,i);
                    Write(omega[i]:10:7,',');
               end;
           WriteLN(')');
           Approche(A);
     until false;


end;


Begin
     while true do
     begin

          Presentation;
          Repeat
              Read(Ch)
          until Ch in ['0'..'5'];
          case ch of
               '1':  Question1;
               '2':  Question2;
               '3' : Question3;
               '4' : Question4;
               '5' : Question5;
               '0' : Halt
          end;
     Pause;
  end;
end.

