8
votes

La fonction de coefficient est lente

S'il vous plaît considérer:

{4.93, Null}


9 commentaires

Peut-être coefficient S algorithme de la vitesse de l'espace pour pouvoir travailler sur des expressions avec une forme expansée extrêmement longue? BTW Votre ordinateur est 4,5 fois plus rapide que le mien.


@Szabolcs je suppose que cela a du sens; Je vais essayer de le tester. J'espère espérer un processus de sélection de méthode plus intelligent si c'est le cas. Si vous utilisez la version 8, pouvez-vous également essayer le test dans la version 7? Je soupçonne que au moins certaines choses sont plus lentes dans 8.


Je n'ai pas de V7 Installer à portée de main maintenant ..


@Szabolcs Il est également 4 fois plus lent sur le mien (V8), alors je suppose que c'est une différence de version.


@Szabolcs Je peux confirmer votre hypothèse, à l'aide de ce que coefficient est beaucoup plus efficace de mémoire sur (1 + x) ^ 50000 . Y a-t-il quelque chose de raisonnable que je puisse faire pour faire une fonction généralisée qui appelle coefficient plus rapidement? Existe-t-il une sorte de formulaire semi-élargi, ou méthode qui me donnerait un équilibre entre ces options?


Avec une situation d'expression plus grande est encore pire. Avec expr = somme [x ^ i, {i, 30}] ^ 20; il y a un facteur de 670 entre eux. Je ne remarque pas beaucoup de différence en ce qui concerne l'utilisation de la mémoire, mais le moniteur système n'est pas très sensible.


@Sjoerd merci d'avoir testé. Veuillez essayer avec l'échantillon: (1 + x) ^ 50000 ou similaire.


Avez-vous vu l'autre différence de version étrange (entre 8.0.x et 8.0.4), Ici ? La solution de Belisarius ne fonctionne pas comme - est sur 8.0.4, apparemment en raison d'une modification de Radon []


A obtenu 20% à 30% des résultats plus lents sur 8.0.4 par rapport à 7,0,1 (mais toujours la moitié de la vitesse de M.Wizard ...)


4 Réponses :


12
votes

Voici un piratage qui peut permettre à votre code d'être rapide, mais je ne le garantis pas de toujours fonctionner correctement: xxx

en l'utilisant, nous obtenons: < Pré> xxx

L'idée est que, coefficient utilise binomial en interne pour estimer le nombre de termes, puis élargir (appels développer ) Si le nombre de termes est inférieur à 1000 , que vous pouvez vérifier à l'aide de TRACE [..., TRACELInnernal-> true] . Et quand il ne se développe pas, il calcule beaucoup de sommes de grandes listes de coefficients dominées par les zéros, ce qui est apparemment plus lent que l'expansion, pour une gamme d'expressions. Ce que je fais, c'est d'imbécile binomial dans le retour d'un petit nombre ( 10 ), mais j'ai également essayé de le faire de telle sorte qu'il n'affecte que le binomial appelé interne par coefficient : xxx

Je ne peux cependant pas garantir qu'il n'y a pas d'exemples où binomial ailleurs Dans le code sera calculé de manière incorrecte.

EDIT

Bien sûr, une alternative plus sûre qui existe toujours est de redéfinir le coefficient Utilisation de Villegas - Gayley Trick, élargissement d'une expression à l'intérieur et l'appelant à nouveau: xxx

edit 2

Ma première suggestion a eu un avantage que nous avons défini une macro modifié les propriétés des fonctions localement, mais inconvénient qu'il était dangereux. Ma deuxième suggestion est plus sûre mais modifie coefficient globalement, il sera donc toujours développer jusqu'à ce que nous supprimions cette définition. Nous pouvons avoir le meilleur des deux mondes à l'aide de Interne`inhéritedblock , qui crée une copie locale d'une fonction donnée. Voici le code: xxx

L'utilisation est similaire au premier cas: xxx

le coefficient principal La fonction reste non affectée cependant: xxx


2 commentaires

+1 Pour le travail et l'analyse d'ingénierie inverse, mais n'est-ce pas vraiment identique à l'expansion manuelle en premier, mais dangereux? Ou est-ce encore plus efficace de mémoire que cela (c'est-à-dire la décision interne de se développer ou non de se développer à l'ensemble de l'expression ou des pièces uniquement)?


@Szabolcs Je viens de modifier pour ajouter l'autre possibilité (expansion) avant de voir votre commentaire. C'est probablement la même mémoire - sage, et lorsque le coefficient se développe, il élargit toute expression (autant que je puisse dire). Ma première solution est plus pour une illustration. Je vais ajouter le second à partir de Gayley - Villegas Trick sous peu.



10
votes

coefficient code> ne se développera pas à moins qu'il ne le juge absolument nécessaire de le faire. Cela évite effectivement des explosions de la mémoire. Je crois que cela a été de cette façon depuis la version 3 (je pense que je travaillais autour de 1995 environ).

Cela peut également être plus rapide pour éviter l'expansion. Voici un exemple simple. P>

Coefficient[Expand[expr], x, 234]; // Timing


0 commentaires

9
votes
expr = Sum[x^i, {i, 15}]^30; 

scoeff[ex_, var_, n_] /; PolynomialQ[ex, var] := 
   ex + O[var]^(n + 1) /. 
    Verbatim[SeriesData][_, 0, c_List, nmin_, nmax_, 1] :> 
     If[nmax - nmin != Length[c], 0, c[[-1]]]; 

Timing[scoeff[expr, x, 234]]
seems quite fast, too.

6 commentaires

+1. Il est en fait plusieurs fois plus rapide pour les expressions plus grandes, que des solutions basées sur l'élargissement d'une expression. De plus, il est considérablement plus rapide pour les coefficients à index plus petits, car il semble effectivement ne développer que la partie d'expression jusqu'à un terme déterminé (puissance).


SeriesData est vraiment très joliment mis en œuvre à Mathematica. Donc, tout ce que l'on peut faire avec SeriesData est flamboyant rapide (encore plus rapide que la forme ( Nikhef.nl/~Forme)).


Rolf Mertig, je suis obligé d'accepter cette réponse, car il est concis et efficace. Cependant, je ne comprends pas vraiment. Voulez-vous s'il vous plaît expliquer cela dans les termes les plus simples possibles?


Spécifiquement, je ne comprends pas: ex + o [var] ^ (n + 1)


C'est juste une expansion de Taylor qui a du sens ici puisque les puissances supérieures de X ne sont pas nécessaires. L'accélération provient du fait que SeriesData est implémentée efficacement dans Mathematica. Voir aussi: référence.wolfram.com/mathematica/ref/o.html


Merci. Pardonnez-moi pour l'ONU-Accepter votre réponse, mais je pense avoir trouvé une méthode plus facile, inspirée par la vôtre. J'attendrai l'examen par les pairs sur cette réponse.



1
votes

Après une certaine expérimentation après la réponse de Rolf Mertig, cela semble être la méthode la plus rapide sur le type d'expression telle que somme [x ^ i, {i, 15}] ^ 30 : Xxx


4 commentaires

Notez que cela répond quelque peu une question différente de ce que vous avez demandé à l'origine: Vous avez posé des questions sur les raisons pour lesquelles coefficient est lent (accent sur coefficient et "pourquoi lentement"), pas ce que sont substituts rapides possibles pour cela.


@Leonid très bon point. J'avais oublié cela après avoir lu les diverses réponses. Je suppose que la réponse de Daniel est la plus directe; Devrais-je accepter ça? Aussi, que pensez-vous de cette méthode? Y a-t-il des problèmes évidents avec cela?


Désolé, je ne peux pas vous conseiller sur quelle réponse vous acceptez - c'est entièrement à vous de vous. La réponse de Daniel est très bonne, brève et au point. Quant à la méthode - je ne vois pas de problèmes évidents, mais hélas n'ont pas de temps en ce moment pour jouer avec elle.


@Leonid vous sonnez assez diplomatique. D'accord.