graphe par morceaux/fonction args

Discussion sur l'enseignement de l'algorithmique avec Xcas au lycee
alb
Messages : 1320
Inscription : ven. août 28, 2009 3:34 pm

Re: graphe par morceaux/fonction args

Message par alb » sam. oct. 23, 2010 11:02 am

J'ai essayé de tracer le graphe exact de piecewise en repère orthonormé (à cause des demi-cercles) en tenant compte:
1)des discontinuités
2)des exclusions éventuelles (symbolisées par des demi-cercles)
2)de la non dérivabilité éventuelle aux bornes (cas où diff renvoie undef ou inf)
Voici donc le programme que j'ai testé en modifiant dans tous les sens ceci:
f(x):=piecewise(x<-5,2*sqrt(-x-5),x<=0,1-sqrt(-x),x<4,2*sqrt(x)-1,x<=6,4-x/4,x<=8,x-8,4-2*sqrt(x-6));
Graphe_piecewise();
Il est fort possible que des erreurs apparaissent sur d'autres exemples mais j'en ai appris un peu plus sur Xcas.

Code : Tout sélectionner

Rayon():={
//détermination du rayon des demi-cercles
//on cherche la longueur minimale des segments
//en excluant les extrémités
  local k,X1,Y1,X2,Y2,L,T,s;
  L:=NULL;
  T:=f(x);
  s:=size(f(x));
  si s=3 alors
    return 2;//modifier 2 ?
  fsi;
  si s>=4 alors 
    pour k de 1 jusque (s-3)/2 faire
      X1:=T[2k-1][1];
      X2:=T[2k+1][1];
      Y1:=subst(T[2k+2],x=X1);
      Y2:=subst(T[2k+2],x=X2);
      L:=L,longueur(point(X1,Y1),point(X2,Y2));
    fpour;
    si s<8 alors return min(L)/10;sinon return min(L)/5;fsi;
    //modifier 8,10,5 ?
  fsi;
}
:;

Demi_cercle_gauche(a,E,b):={
  local R,m,A,C;
  R:=Rayon();
  m:=evalf(subst(diff(E,x),x=a));
  A:=point(a,subst(E,x=a));
  //tester si m=undef ou m=inf
  si type(m)!=DOM_IDENT et type(m)!=DOM_SYMBOLIC alors
    C:=point(a-R/sqrt(1+m^2),subst(E,x=a)-R*m/sqrt(1+m^2));
    return plot(E,x=a..b),cercle(C,R,-pi/2+arctan(m),pi/2+arctan(m));sinon 
      si subst(E,x=a)-subst(E,x=b)<0 alors
        m:=inf;
        C:=point(a,subst(E,x=a)-R);
        return plot(E,x=a..b),cercle(C,R,-pi/2+arctan(m),pi/2+arctan(m));sinon
        m:=inf;
        C:=point(a,subst(E,x=a)+R);
        return plot(E,x=a..b),cercle(C,R,-pi/2-arctan(m),pi/2-arctan(m));
      fsi;   
  fsi;
}
:;

Demi_cercle_droite(a,E,b):={
  local R,m,B,C;
  R:=Rayon();
  m:=evalf(subst(diff(E,x),x=b));
  B:=point(b,subst(E,x=b));
  //tester si m=undef ou m=inf
  si type(m)!=DOM_IDENT et type(m)!=DOM_SYMBOLIC alors
  C:=point(b+R/sqrt(1+m^2),subst(E,x=b)+R*m/sqrt(1+m^2));
  return plot(E,x=a..b),cercle(C,R,pi/2+arctan(m),3*pi/2+arctan(m));sinon
    si subst(E,x=a)-subst(E,x=b)>0 alors
        m:=inf;
        C:=point(b,subst(E,x=b)-R);
        return plot(E,x=a..b),cercle(C,R,-pi/2+arctan(m),pi/2+arctan(m));sinon
        m:=inf;
        C:=point(b,subst(E,x=b)+R);
        return plot(E,x=a..b),cercle(C,R,-pi/2-arctan(m),pi/2-arctan(m));
      fsi;   
  fsi; 
}
:;

Graphe_piecewise():={
  local T,s,L,k;
  affichage(epaisseur_ligne_3);
  T:=f(x);L:=NULL;
  s:=size(f(x));
  si s=3 alors
    si simplifier(subst(T[2],x=T[1][1])-subst(T[3],x=T[1][1]))!=0 et T[1][0]=='>' alors
      L:=L,Demi_cercle_droite(T[1][1]-5,T[2],T[1][1]);
    fsi;
    si simplifier(subst(T[2],x=T[1][1])-subst(T[3],x=T[1][1]))!=0 et T[1][0]=='>=' alors 
      L:=L,Demi_cercle_gauche(T[1][1],T[3],T[1][1]+5);
    fsi;
    return L:=L,plot(T[2],x=T[1][1]-5..T[1][1]),plot(T[3],x=T[1][1]..T[1][1]+5);
  fsi;
  si s>=4 alors
    si simplifier(subst(T[2],x=T[1][1])-subst(T[4],x=T[1][1]))!=0 et T[1][0]=='>' alors
      L:=L,Demi_cercle_droite(T[1][1]-5,T[2],T[1][1]);
    fsi;
    si simplifier(subst(T[s-1],x=T[s-2][1])-subst(T[s],x=T[s-2][1]))!=0 et T[s-2][0]=='>=' alors 
      L:=L,Demi_cercle_gauche(T[s-2][1],T[s],T[s-2][1]+5);
    fsi;
    si simplifier(subst(T[s-1],x=T[s-2][1])-subst(T[s],x=T[s-2][1]))!=0 et T[s-2][0]=='>' alors
      L:=L,Demi_cercle_droite(T[s-4][1],T[s-1],T[s-2][1]);
    fsi;
    L:=L,plot(T[2],x=T[1][1]-5..T[1][1]),
      plot(T[s],x=T[s-2][1]..T[s-2][1]+5);
    pour k de 2 jusque (s-1)/2 faire
      si simplifier(subst(T[2k-2],x=T[2k-3][1])-subst(T[2k],x=T[2k-3][1]))!=0 et T[2k-3][0]=='>=' alors
        L:=L,Demi_cercle_gauche(T[2k-3][1],T[2k],T[2k-1][1]);
      fsi;
      si k!=(s-1)/2 alors 
        si simplifier(subst(T[2k],x=T[2k-1][1])-subst(T[2k+2],x=T[2k-1][1]))!=0 et T[2k-1][0]=='>' alors
          L:=L,Demi_cercle_droite(T[2k-3][1],T[2k],T[2k-1][1]);
        fsi;
      fsi;
      L:=L,plot(T[2k],x=T[2k-3][1]..T[2k-1][1]);
    fpour;
    return L;
  fsi;
}
:;

alb
Messages : 1320
Inscription : ven. août 28, 2009 3:34 pm

Re: graphe par morceaux/fonction args

Message par alb » lun. oct. 25, 2010 9:05 pm

Dans la série cherchons la petite bête, ce constat:
solve(3*sqrt(x+1)-2>3) renvoie sans erreur [x>(16/9)] mais
f(x):=piecewise(x<0,1,x<8,3*sqrt(x+1)-2,-x+15);solve(f(x)>3) renvoie "Gen [int] Error: Bad Argument Type"

parisse
Messages : 5731
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Re: graphe par morceaux/fonction args

Message par parisse » mar. oct. 26, 2010 7:20 am

en effet, merci pour l'info, je suis en train de tester un correctif. On va bien finir par arriver à le débugguer cet xcas!!!

alb
Messages : 1320
Inscription : ven. août 28, 2009 3:34 pm

Re: graphe par morceaux/fonction args

Message par alb » ven. nov. 26, 2010 9:50 pm

Au moins deux cas où mon programme ne marche pas (demi-cercles mal orientés):
f(x):=piecewise(x<=-2,undef,x<2,3+sqrt(4-x^2),x<5,2,x<=8,x-3,undef);Graphe_piecewise();
et
f(x):=piecewise(x<=-2,undef,x<2,3-sqrt(4-x^2),x<5,2,x<=8,x-3,undef);Graphe_piecewise();
C'est beaucoup mieux si on remplace les fonctions Demi_cercle par ceci:

Code : Tout sélectionner

Demi_cercle_gauche(a,E,b):={
  local R,m,A,C;
  R:=Rayon();
  m:=evalf(subst(diff(E,x),x=a));
  A:=point(a,subst(E,x=a));
  //tester si m=undef ou m=inf
  si type(m)!=DOM_IDENT et type(m)!=DOM_SYMBOLIC alors
    C:=point(a-R/sqrt(1+m^2),subst(E,x=a)-R*m/sqrt(1+m^2));
    return plot(E,x=a..b),cercle(C,R,-pi/2+arctan(m),pi/2+arctan(m));sinon 
      si subst(E,x=a)-subst(E,x=a+0.001)<0 alors
        m:=inf;
        C:=point(a,subst(E,x=a)-R);
        return plot(E,x=a..b),cercle(C,R,-pi/2+arctan(m),pi/2+arctan(m));sinon
        m:=inf;
        C:=point(a,subst(E,x=a)+R);
        return plot(E,x=a..b),cercle(C,R,-pi/2-arctan(m),pi/2-arctan(m));
      fsi;   
  fsi;
}
:;

Demi_cercle_droite(a,E,b):={
  local R,m,B,C;
  R:=Rayon();
  m:=evalf(subst(diff(E,x),x=b));
  B:=point(b,subst(E,x=b));
  //tester si m=undef ou m=inf
  si type(m)!=DOM_IDENT et type(m)!=DOM_SYMBOLIC alors
  C:=point(b+R/sqrt(1+m^2),subst(E,x=b)+R*m/sqrt(1+m^2));
  return plot(E,x=a..b),cercle(C,R,pi/2+arctan(m),3*pi/2+arctan(m));sinon
    si subst(E,x=b-0.001)-subst(E,x=b)>0 alors
        m:=inf;
        C:=point(b,subst(E,x=b)-R);
        return plot(E,x=a..b),cercle(C,R,-pi/2+arctan(m),pi/2+arctan(m));sinon
        m:=inf;
        C:=point(b,subst(E,x=b)+R);
        return plot(E,x=a..b),cercle(C,R,-pi/2-arctan(m),pi/2-arctan(m));
      fsi;   
  fsi; 
}
:;

Répondre