Un essai de réduction d'une combinaison de ln

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

Un essai de réduction d'une combinaison de ln

Message par alb » sam. déc. 11, 2010 9:27 pm

Une tentative très empirique de réduction d'une combinaison linéaire à coefficients rationnels de ln.
Je suis preneur de toute remarque ou exemple qui invaliderait ce programme d'amateur.
Un exemple qui marche:
E:=-2/3*ln(2010/58)-2*ln(154/256)-ln(145)+ln(123)+5*ln(45)+1/2*ln(289/125);
Simplog(E);
c'est parfois un peu plus réduit que tsimplify(E);

Code : Tout sélectionner

Ln_entier(N):={
local L,s;
L:=ifactors(N);
s:=size(L);
return sum(L[2k+1]*ln(L[2k]),k,0,s/2-1);
}
:;

Ln(N):={
si type(N)==DOM_INT alors return Ln_entier(N) sinon
  si type(N)==DOM_RAT alors return Ln_entier(numer(N))-Ln_entier(denom(N)) sinon
    return ln(N)
  fsi;
fsi;
}
:;

Simplog(E):={ //simplifier une combinaison linéaire de ln à coeff rat
local s,L;
si sommet(E)=='+' alors
L:=simplifier(op(E));
s:=size(L);
pour k de 0 jusque s-1 faire
  si sommet(L[k])=='ln' alors L[k]=<Ln(op(L[k])) sinon //pour ln(A)
    si sommet(op(L[k]))=='ln' alors L[k]=<-Ln(op(op(L[k]))) sinon //pour -ln(A)
      si sommet(op(L[k])[0])=='ln' alors L[k]=<op(L[k])[1]*Ln(op(op(L[k])[0])) sinon //pour ln(A)/B
        si sommet(op(op(L[k])[0]))=='ln' alors L[k]=<-op(L[k])[1]*Ln(op(op(op(L[k])[0]))) //pour -ln(A)/B
        fsi;
      fsi;
    fsi;
  fsi;
fpour;
return tsimplify(sum(L[k],k,0,s-1));
fsi;
L:=simplifier(E); //si un seul terme dans la somme
si sommet(L)=='ln' alors return Ln(op(L)) sinon //pour ln(A)
  si sommet(L)==neg alors return -Ln(op(op(L))) sinon //pour -ln(A)
    si sommet(L)=='*' alors return expand(op(L)[1]*Ln(op(op(L)[0]))) sinon //pour ln(A)/B
      return "la simplification n'a pas été réalisée" 
    fsi;
  fsi;
fsi;
}
:;

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

Re: Un essai de réduction d'une combinaison de ln

Message par alb » dim. déc. 12, 2010 10:34 pm

J'ai l'impression d'avoir utilisé un couteau suisse pour tailler une allumette.
En partant du constat suivant non avéré:
simplify transforme toute combinaison linéaire à coefficients rationnels de ln de rationnels en l'une des 3 formes suivantes:
ou ln(A) ou -ln(A) ou ln(A)/B
on peut alors en sortant moins d'outils de la boîte utiliser le programme suivant compréhensible par un élève de terminale:

Code : Tout sélectionner

Ln_entier(N):={//simplifier ln(entier)
local L,s;
L:=ifactors(N);
s:=size(L);
return sum(L[2k+1]*ln(L[2k]),k,0,s/2-1);
}
:;

Ln(N):={//simplifier ln(rationnel)
si type(N)==DOM_INT alors return Ln_entier(N) sinon
  si type(N)==DOM_RAT alors return Ln_entier(numer(N))-Ln_entier(denom(N)) sinon
    return ln(N)
  fsi;
fsi;
}
:;

Simplog(E):={ //simplifier une combinaison linéaire de ln à coeff rat
local L;
L:=simplifier(E);
si sommet(L)=='ln' alors return Ln(op(L)) sinon //pour ln(A)
  si sommet(L)==neg alors return -Ln(op(op(L))) sinon //pour -ln(A)
    si sommet(L)=='*' alors return expand(op(L)[1]*Ln(op(op(L)[0]))) sinon //pour ln(A)/B
      return "la simplification n'a pas été réalisée" 
    fsi;
  fsi;
fsi;
}
:;
Exemple:
E:=8/5*ln(125/289)-2/3*ln(1024/81);Simplog(E); (mieux que tsimplify(E))

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

Re: Un essai de réduction d'une combinaison de ln

Message par parisse » lun. déc. 13, 2010 8:03 am

D'un autre cote, s'il s'agit de faire faire de l'algorithmique, c'est aussi interessant de montrer la decomposition d'un '+'.

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

Re: Un essai de réduction d'une combinaison de ln

Message par alb » jeu. déc. 16, 2010 6:31 pm

J'ai modifié le programme ainsi:

Code : Tout sélectionner

Ln_entier(N):={
local L,s;
L:=ifactors(N);
s:=size(L);
return sum(L[2k+1]*ln(L[2k]),k,0,s/2-1);
}
:;

Ln(N):={
si type(N)==DOM_INT alors return Ln_entier(N) sinon
  si type(N)==DOM_RAT alors return Ln_entier(numer(N))-Ln_entier(denom(N)) sinon
    return ln(N)
  fsi;
fsi;
}
:;

Simplog(E):={ //simplifier une combinaison linéaire de ln à coeff rat
local s,L;
L:=100+E;//pour que L soit une somme d'au moins deux termes
L:=expand(lnexpand(L));
L:=simplifier(op(L));
s:=size(L);
pour k de 0 jusque s-1 faire
  si sommet(L[k])=='ln' alors L[k]=<Ln(op(L[k])) sinon //pour ln(A)
    si sommet(op(L[k]))=='ln' alors L[k]=<-Ln(op(op(L[k]))) sinon //pour -ln(A)
      si sommet(op(L[k])[0])=='ln' alors L[k]=<op(L[k])[1]*Ln(op(op(L[k])[0])) sinon //pour ln(A)/B
        si sommet(op(op(L[k])[0]))=='ln' alors L[k]=<-op(L[k])[1]*Ln(op(op(op(L[k])[0]))) //pour -ln(A)/B
        fsi;
      fsi;
    fsi;
  fsi;
fpour;
return tsimplify(sum(L[k],k,0,s-1)-100);
}
:;
Pour le tester j'ai pris une somme au hasard:

Code : Tout sélectionner

E:=sum((k+2)/(k+1)*(-1)^(k+1)*ln((k+1)^(k+3)),k,0,n)
que je veux donc décomposer en somme de rat*ln(premier) pour des valeurs de n
Je fais:

Code : Tout sélectionner

A:=Simplog(E);B:=tsimplify(E);simplifier(A-B)
Pour n autour de 30 j'ai simplifier(A-B) qui donne 0 en 1 à 2 secondes
Pour n autour de 50 j'ai simplifier(A-B) qui donne 0 en 60 secondes environ
Pour n=70 simplifier(A-B) donne un résultat qui n'est pas 0 en 420 secondes environ
Pour n=73 xcas se ferme sur Simplog(E)
Pour d'autres valeurs comme 75 ou 80 Simplog(E) donne "Error in PARI subsystem Error: Bad Argument Value"
NB: tsimplify(E) marche pour toutes ces valeurs de n y compris n quelconque.
Est-ce le programme qui est en cause ?

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

Re: Un essai de réduction d'une combinaison de ln

Message par parisse » jeu. déc. 16, 2010 7:21 pm

Je viens de tester pour n=70 et n=73, c'est très long (10 minutes), mais ça renvoie bien 0 chez moi (test fait avec la version en ligne de commande sous linux lancé depuis gdb pour pouvoir attraper un segfault et l'analyser). Il faut pas mal de mémoire (plus de 300M), peut-etre est-ce pour cela que ça plante chez vous. Je ne suis pas très étonné car l'algorithme de simplification des ln par simplify n'est vraiment pas fait pour ce type d'expressions.

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

Re: Un essai de réduction d'une combinaison de ln

Message par alb » jeu. déc. 16, 2010 8:51 pm

0.9.1 sous linux.
Nouvel essai pour n=70, 421 secondes avec deux pics à 280M. Réponse:

Code : Tout sélectionner

(66285050370*ln(1/Integer_too_large_for_display)+438155417700*ln(1/Integer_too_large_for_display)+423789666300*ln(1/Integer_too_large_for_display)+385838352900*ln(1/Integer_too_large_for_display)+2930971615*ln(1/Integer_too_large_for_display)+253442839650*ln(1/Integer_too_large_for_display)+28694827*ln(1/Integer_too_large_for_display)+78336877710*ln(1/Integer_too_large_for_display)+78336877710*ln(Integer_too_large_for_display)+253442839650*ln(Integer_too_large_for_display)+28694827*ln(Integer_too_large_for_display)+438155417700*ln(Integer_too_large_for_display)+66285050370*ln(Integer_too_large_for_display)+423789666300*ln(Integer_too_large_for_display)+385838352900*ln(Integer_too_large_for_display)+2930971615*ln(Integer_too_large_for_display))/25851169644300
Ensuite chaque tentative donne la même chose:
un crash à 73
au delà Error in PARI subsystem Error: Bad Argument Value

Répondre