Program MIRA;

{ Epreuve informatique de l'Ecole Polytechnique ............ 94.278

Source : Philippe MINÉ décembre 1993

 Le chaos esthétique de MIRA
in "18. les attracteurs étranges et le chaos"
   Pages 198 et suivantes ......


   1) cas où b=1 .

      C'est le plus intéressant.
      La descendance du point M0 est quasi cyclique pour  0<a<1
      Pour    -1<a<0, elle tend à diverger.

      Les descendances sont symétriques par rapport à l'axe 0x.

      La famille (xi,yi) et la famille (xi,-yi) sont confondues.
      Donc tout cycle contient au moins un point (x0,0) sur l'axe Ox.

      Cycles d'ordre 2 : apparemment aucun

      Cycles d'ordre 3  : quand a proche de -0,5 : x0 voisin de -1

      Cycles d'ordre 4 : à trouver ...

      Cycles d'ordre 5 pour a= 0,271 :   x0=6,1 environ
                               et aussi  x0= -7 environ
             mais aussi pour a=-0,8   avec x0=11 environ

      Cycle d'ordre 6 pour a voisin de 0,45
           exemple : si a=0,428  :   x0= 6 environ,
                                  ou x0= -3,5 environ


      Cycles d'ordre supérieur :
             - quelques-uns aux alentours de a=-0,66
             - abondants pour valeurs positives de a
             - le plus souvent d'ordre impair


                                  }


Uses crt, modubase ;

Type
    Points = record
           x,y :real;
    end;
    Myreal = Double;

var
   n1,n2,nmax,cas:integer;
   a,b:MyReal;
   m,m0,m1,M2,Mini:Points;
   Ch:char;
   c:integer;
   pas : MyReal;
   xini : MyReal;
   xinipas : MyReal;
   choisir: Boolean;

   sizeY:MyReal;
Const
     size=10;
     eps=1e-6;
     Escape=#27;


Type
    Claviers = record
     Touche     : Char;
     Enter      : Boolean;
     Escape     : Boolean;
     BackSpace  : Boolean;
     SpaceBar   : Boolean;    
     Up         : Boolean;
     Down       : Boolean;
     Left       : Boolean;
     Right      : Boolean;
     Home       : Boolean;
     Fin        : Boolean;
     PageUp     : Boolean;
     PageDown   : Boolean;
     Insert     : Boolean;
     Suppr      : Boolean;
     Ctrl_Left  : Boolean;
     Ctrl_Right : Boolean;
    end;


var
   Clavier:Claviers;

Procedure Lire_Clavier;
Const
     Clavier_vide:Claviers=(Touche    :#00;
                            Enter     : False;
                            Escape    : False;
                            BackSpace : False;
                            SpaceBar  : False;
                            Up        : False;
                            Down      : False;
                            Left      : False;
                            Right     : False;
                            Home      : False;
                            Fin       : False;
                            PageUp    : False;
                            PageDown  : False;
                            Insert    : False;
                            Suppr     : False;
                            Ctrl_Left : False;
                            Ctrl_Right: False);
begin
  Clavier:=Clavier_vide;
  With Clavier do
   begin
     repeat
     until Keypressed;
     Touche := Readkey;
    If Touche=#00 then
        begin
             Touche  :=ReadKey;
             Up           :=Touche=#72;
             Down         :=Touche=#80;
             Left         :=Touche=#75;
             Right        :=Touche=#77;
             Home         :=Touche=#71;
             Fin          :=Touche=#79;
             PageUp       :=Touche=#73;
             PageDown     :=Touche=#81;
             Insert       :=Touche=#82;
             Suppr        :=Touche=#83;
             Ctrl_Left    :=Touche=#115;
             Ctrl_Right   :=Touche=#116;
             Touche:=#00;
        end
    else
        begin
             Enter    := Touche= #13;
             Escape   := Touche= #27;
             BackSpace:= Touche= #08;
             SpaceBar := Touche= ' ';
             Touche:=Upcase(Touche);
        end;
   end;   {  With Clavier }
end;

Procedure Move(var M:Points);
Var
   SavetextAttr:Byte;
begin
  With M do
     With clavier do
      begin
         SavetextAttr:=TextAttr;
         couleur(-Brillant);
         repeat
           repeat
                   Deplace(-10,SizeY*0.70);
                   Ecris('x0=');Ecrisreel(x);
                   Ecris('  y0=');Ecrisreel(y);



            Delay(10);
            Croix(x,y);
            Delay(10);
            Croix(x,y);
           until Keypressed;
           Lire_clavier;
           if left  then x:=x-pas;
           if right then x:=x+pas;
           if Up    then y:=y+pas;
           If Down  then y:=y-pas;
           case Touche of
                '+'  : pas:=pas*2;
                '-'  : pas:=pas/2;
           end; { case }
         until Enter;
         TextAttr:=SaveTextAttr;
    end ;  { with }
end;

Function f(x:MyReal):MyReal;
begin
     f:=a*x+2*(1-a)*sqr(x)/(1+sqr(x));
end;

Function distance(M1,M2:Points):MyReal;
begin
     distance:=sqrt(sqr(M1.x-M2.x)+sqr(M1.y-M2.y));
end;

Procedure ChoixCouleur(M1,M2:Points);
begin
     Couleur(-9-Trunc(distance(M1,M2)/4));
end;
                   
Procedure Next(var M:points);
Var
   x0:MyReal;
begin
     With M do
          begin
               x0:=x;
               x:=b*y+f(x);
               y:=-x0+f(x);
          end;
end;




Procedure ShowF(Xmin,Xmax,Ymin:Integer);
Var
   x:MyReal;
   i:integer;
Const
   DeltaX=0.1;
begin
    {Utiliser ForceGraphique(3,1) si EGA WONDER sur moniteur monochrome}
  Efface;
  IsoFenetre(Xmin,XMax,Ymin);
  SizeY:=-Ymin*1.5;
  Couleur(Bleu);
  X_Axe(0,0,1);
  Y_Axe(0,0,1);
                           {Tracé de la courbe}
  Couleur(Brillant);
  Deplace(Xmin,SizeY*0.95);
  Ecris('*** Chaos esthétique de MIRA ***');
  Deplace(Xmin,SizeY*0.90);
  Ecris('Fonction F(x)=a*x+2*(1-a)*sqr(x)/(1+sqr(x))');
  Deplace(Xmin,SizeY*0.85);
  Ecris('x[n+1]:=b*y[n]+F(x[n])');
  Deplace(Xmin,SizeY*0.80);
  Ecris('y[n+1]:=-x[n]+F(x[n+1])');
  Deplace(Xmin,SizeY*0.75);
  Ecris('a=');Ecrisreel(a);
  Ecris('  b=');Ecrisreel(b);
  Couleur(Brillant);
  x:=Xmin;
  Deplace(x,f(x));
  repeat
        Trace(x,f(x));
        x:=x+Deltax;
  until x>xmax;
end;

Procedure Point_cyclique(k : integer; a1, x,y: MyReal );
const
  nbiter=100;
var
   i,j,u:integer;
   M,moyenne:POints;
begin
        Modegraphique;
        a:=a1;
        b:=1;
        ShowF(-size,size,-Trunc(size*0.66));
        Couleur(Brillant);
        Croix(1,0);
        Croix(0,0);
         M.x:=x;
         M.y:=y;
        u:=0;
        repeat
         inc(u);
         Couleur(-(15 and u));
         with M do
          begin
               Croix(M.x,M.y);
               Deplace(-10,SizeY*0.70);
                   Ecris('x0=');Ecrisreel(x);
                   Ecris('  y0=');Ecrisreel(y);
          end;

     with moyenne do
      begin
           x:=0;
           y:=0;
           for i:=1 to nbiter do
            begin
               for j:=1 to k do
                  begin
                   Next(M);
                   Point(M.x,M.y);
                  end;
               x:=x+M.x;
               y:=y+M.y;
            end;
           x:=x/nbiter;
           y:=y/nbiter;
       end;
      M:=Moyenne;


      until Keypressed;
      Ch:=readkey;
      Modetexte;
      WriteLN('a=',a:7:3,'    Cycle d''ordre k=',k);
      WriteLN('x0=',x:20:15,'    y0=',y:20:15);
      With Moyenne do
           WriteLN('x =',x:20:15,'    y =',y:20:15);
      PAuse;





end;



begin
  InitGraphique;
  Randomize;
  ModeTexte;
  ClrScr;
  WriteLN('Chaos esthétique de MIRA');
  WriteLN;
  WriteLN('Fonction F(x)=a*x+2*(1-a)*sqr(x)/(1+sqr(x))');
  WriteLN('x[n+1]:=b*y[n]+F(x[n])');
  WriteLN('y[n+1]:=-x[n]+F(x[n+1])');
  WriteLN;
  WriteLN('Les points fixes permanents sont : ');
  WriteLN('           O=(0,0)    et  M1=(1,0)    ');
  WriteLN;
  WriteLN('cas n°1 :  a quelconque     ,  b=1   ');
  WriteLN('cas n°2 :  a quelconque     ,  b légèrement inférieur à 1 ');
  WriteLN;
  WriteLN;


  Point_cyclique(50,0.7,3,0);
  Point_cyclique(4,-0.1,-1,3);


  Point_cyclique(4,-0.01,8,5.2);
  Point_cyclique(3,-0.7,-1.36,0);
  Point_cyclique(8,0.7,8.6,2);
  Point_cyclique(9,0.7,-1.5,0);
  Point_cyclique(25,0.7,5.2,0);
  Modetexte;

  cas:=1;


  Write('cas :');
  {ReadLN(cas);}
  repeat
        Write(' Choix du point de départ manuel automatique (M/A): ');
        ReadLN(Ch);
        Ch:=Upcase(Ch);
  until Ch in ['A','M'];
  Choisir:=Ch='M';
  With Mini do
       begin
             x:=0;
             y:=0;
       end;


  repeat
        pas:=0.1;
     {   a:=2*(random-0.5);
        a:=0.5;}

        a:=2*(random-0.5);
        Modetexte;
        Write('a=');
        ReadLN(a);


        cas:=1;

        Modegraphique;


        case cas of
        1:b:=1;
        2:b:=1-0.1*random;
        end; { case }
        ShowF(-size,size,-Trunc(size*0.66));
        Couleur(Brillant);
        Croix(1,0);
        Croix(0,0);
        n1:=0;
        xinipas:=0.1;
        repeat
              Ch:=' ';
              Inc(n1);
              c:=(15-n1) and 15;
              Couleur(c);
              M0.x:=size*(random-0.5);
              M0.y:=size*(random-0.5);
              M0:=Mini;
              if choisir then
               begin
                  Move(Mini)
               end
              else
                With Mini do
                  begin
                       x:=x-xinipas;
                       x:=20*(random-0.5);
                       y:=20*(random-0.5);
                  end;
              M0:=Mini;
              Couleur(c);
              With M0 do
                begin
                   Croix(x,y);
                   Deplace(-10,SizeY*0.70);
                   Ecris('x0=');Ecrisreel(x);
                   Ecris('  y0=');Ecrisreel(y);
                end;
              Couleur(Brillant);
              M:=M0;
              with M do
              begin
              n2:=0;
              Deplace(x,y);
              repeat
                  Inc(n2);
                  M1:=M;
                  next(M);
                  Couleur(-c);
                  if choisir then
                     begin
                          Trace(x,y);
                          Delay(100);
                          With M1 do
                               Deplace(x,y);
                          Trace(x,y);
                     end;
                  Couleur(c);
                  Point(x,y);
              until (n2>1000) or KeyPressed;
              if Keypressed then
                 Ch:=UpCase(ReadKey);
              Case Ch of
              'M':Choisir:=True;
              'A':Choisir:=False;
              end;
        end;
   until Ch=Escape;
until false;
end.

