Aide à la résolution d'une équation

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

Aide à la résolution d'une équation

Message par alb » jeu. mars 24, 2011 10:03 am

J'ai utilisé la version 0.9.1 en test du 23 mars.

Code : Tout sélectionner

ResG(E):={ 
//résolution graphique de E=0
//commencer par ResG(E) dans un niveau et Resoudre(E) dans un autre
local s,a,b,h;
s:=size(resoudre(E));
si s==0 alors 
  si plot(E)!=[] alors
    retourne plot(E)
  sinon 
    retourne plot(E,x=-100..100)
  fsi;
fsi;
si s==1 alors
  si simplifier(E)=0 alors
    retourne plot(0,x=-20..20,affichage=bleu+epaisseur_ligne_4),
    legende([50,100],"Elementary my dear Watson !");
  fsi;
  a:=resoudre(E)[0]-10;b:=resoudre(E)[0]+10;
sinon
  a:=min(resoudre(E));b:=max(resoudre(E));
  h:=(b-a)/10;
  a:=min(resoudre(E))-h;b:=max(resoudre(E))+h;
fsi;
retourne plot(E,x=a..b);
}
:;
LmoinsM(L,M):={
//liste L privée des éléments de la liste (ou de l'ensemble) M
local temp,k;
purge(k);
temp:=L;
pour k de 0 jusque size(M)-1 faire
  temp:=remove(x->simplifier(x-M[k])==0,temp);
fpour;
retourne temp;
}
:;
Resoudre(E):={ //E est une expression. On résout E=0. Le résultat est une liste
local rep,a,C,sol,temp,temp2,j,k,enl,rep2;
saisir_chaine("Faut-il imposer des conditions (o/n) ?",rep);
si rep=="n" alors 
  si simplifier(E)=0 alors
    retourne [x];
  sinon
    retourne simplifier(resoudre(E=0))
  fsi;
fsi;
si rep=="o" alors
  saisir("expressions sur lesquelles \n portent les conditions, \n séparées par des virgules",C);
  choosebox("les expressions doivent être",["non nulles","positives","strictement positives"],a);
  si a==1 alors    
    C:=[C];
    sol:=[];
    pour j de 0 jusque size(C)-1 faire
      //sol:=concat(sol,solve(C[j]));
      sol:=sol union solve(C[j]);//union pour éviter les répétitions
    fpour;
    si size(sol)==0 alors 
      afficher("la(les) condition(s) est(sont) vérifiée(s) pour tout x");
      afficher("les solutions possibles sont "+simplifier(resoudre(E=0)));
      retourne simplifier(resoudre(E=0));
    sinon
      temp:="Attention: x doit être différent de "+simplifier(sol[0]);
      pour k de 1 jusque size(sol)-1 faire
        temp:=temp+",de "+simplifier(sol[k]);
      fpour;
      afficher(cat(temp));
      afficher("les solutions possibles sont "+simplifier(resoudre(E=0)));
      retourne LmoinsM(simplifier(resoudre(E=0)),sol);
    fsi;
  sinon
    C:=[C];
    sol:=NULL;
    si a==2 alors
      pour j de 0 jusque size(C)-1 faire
        si solve(C[j]>=0)!=[x] alors
          sol:=sol,solve(C[j]>=0);
        fsi;
      fpour;
    fsi;
    si a==3 alors
      pour j de 0 jusque size(C)-1 faire
        si solve(C[j]>0)!=[x] alors
          sol:=sol,solve(C[j]>0);
        fsi;
      fpour;
    fsi;
    si size(sol)==0 alors 
      afficher("la(les) condition(s) est(sont) vérifiée(s) pour tout x");
      afficher("les solutions possibles sont "+simplifier(resoudre(E=0)));
      retourne simplifier(resoudre(E=0));
    sinon
      Digits:=4;
      temp:="Attention: x doit vérifier "+simplifier(sol[0]);
      pour k de 1 jusque size(sol)-1 faire
        temp:=temp+" et "+simplifier(sol[k]);
      fpour;
      temp2:="ou approximativement "+evalf(sol[0]);
      pour k de 1 jusque size(sol)-1 faire
        temp2:=temp2+" et "+evalf(sol[k]);
      fpour;
      afficher(cat(temp));
      afficher(cat(temp2));
      afficher("les solutions possibles sont "+simplifier(resoudre(E=0)));
      afficher("ou approximativement "+evalf(resoudre(E=0)));
      saisir_chaine("voulez vous enlever des solutions(o/n)",rep2);
      si rep2=="n" alors 
        retourne simplifier(resoudre(E=0));
      fsi;
      si rep2=="o" alors
        saisir("indiquer les solutions à enlever, \n séparées par des virgules",enl);
        retourne LmoinsM(simplifier(resoudre(E=0)),[enl]);
      fsi;
    fsi;
  fsi;
fsi;
}
Testons avec un exemple simple souvent rencontré sur le forum:
E:=(x+3)*ln(x) puis ResG(E) puis Resoudre(E)

Prenons un exemple moins évident.
On veut résoudre l'équation ln(x^2-13*x+30)+ln(28)=ln(-x^2+10*x+200)+ln(x+5)
1/ niveau 1:
E:=ln(x^2-13*x+30)-ln(-x^2+10*x+200)-ln(x+5)+ln(28)
2/ niveau 2:
ResG(E)
autoscale si nécessaire.
En principe le graphique donne au plus les solutions possibles de l'équation E=0 et donc leur approximation.
Dans cet exemple on voit 2 solutions alors que solve(E) en fournit 3.
3/ niveau 3:
Resoudre(E)
-fenêtre 1: si on répond non on aura pour cet exemple 3 solutions, on compare avec le graphique.
si on répond oui:
-fenêtre 2: l'élève note les expressions ou bien il les aura sélectionnées dans la réponse du niveau 1 et copiées/collées dans un niveau 2b avant exécution sous la forme d'une séquence (expressions séparées par des virgules) qu'il copie pour la coller ultérieurement dans la fenêtre 2
-fenêtre 3: l'élève choisit l'une des 3 options
C'est ici que se situe le gros défaut de la fonction Resoudre:ce choix est exclusif. En cas d'équation
nécessitant plusieurs options,on peut:
--soit construire une fonction qui permet de choisir plus d'une option (bon courage :-))
--soit faire un choix pertinent et réfléchir au moment d'enlever des solutions.
-fenêtre 4: l'élève compare les solutions possibles (renvoyées en fait par resoudre ou solve) avec les
conditions de validité si nécessaire en utilisant les approximations (zone bleue)
s'il décide d'enlever des solutions alors
-fenêtre 5: on peut saisir les solutions à enlever sous leurs diverses représentations,
essayez par exemple (-1/2)*(39+sqrt(1481))

Remarque générale sur les saisies:
Chez moi le focus alterne aléatoirement de la fenêtre de saisie à celle de xcas
et si l'on tape un peu trop vite c'est le plantage assuré. Très gênant.

Un détail: pour choosebox le texte est sous la liste de choix, le contraire ne serait-il pas mieux ?

J'ai essayé pas mal d'exemples tous plus tordus les uns que les autres,
mais il est probable que des bugs vont apparaître.
Toute remarque est la bienvenue.

Répondre