Page 1 sur 1

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

Publié : sam. déc. 11, 2010 9:27 pm
par alb
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;
}
:;

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

Publié : dim. déc. 12, 2010 10:34 pm
par alb
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))

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

Publié : lun. déc. 13, 2010 8:03 am
par parisse
D'un autre cote, s'il s'agit de faire faire de l'algorithmique, c'est aussi interessant de montrer la decomposition d'un '+'.

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

Publié : jeu. déc. 16, 2010 6:31 pm
par alb
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 ?

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

Publié : jeu. déc. 16, 2010 7:21 pm
par parisse
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.

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

Publié : jeu. déc. 16, 2010 8:51 pm
par alb
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