|
> Die naheliegende Erweiterung von Plus durch > Plus[x_CI,y_CI] := CI[(Identity@@x) + (Identity@@y)] > fuehrt jedoch zu enormen Rechenzeiten (Out[13] im Vergleich zu Out[8]+Out[9]). > Warum wird Mathematica durch die Umdefinition von Plus derart aus > dem Tritt gebracht? Da Plus assoziativ und kommutativ ist (Attribute Flat und Orderless), muß Mathematica in einer Summe mit vielen Termen jedes mögliche Paar bilden und dann untersuchen, ob die Regel anwendbar ist. Das führt zu einer exponentiell wachsenden Rechenzeit. In diesem Fall ist die äußere Summe (der Monome in Z), auf die die Regel ja gar nie anwendbar ist, der Grund für die lange Rechenzeit. Als Sie Ihre eigene Funktion "plus" definierten, haben Sie sie nicht als assoziativ und kommutativ deklariert; Ihre Regel plus[x_CI, y_CI] := CI[(Identity@@x) + (Identity@@y)]; wird also nur auf die Terme mit genau zwei Summanden angewendet, die in den Koeffizienten der Potenzen von z vorkommen, was in Ihrem Beispiel genügt. > Warum passiert das nicht auch bei der Umdefinition von Times (In[4])? Weil in Ihrem Beispiel keine Produkte mit vielen Faktoren vorkommen, sondern jeweils nur Produkte mit drei Faktoren. > Was ist grundsaetzlich bei der Definition von Funktionen mit Pattern > zu beachten um kurze Rechenzeiten zu erreichen? Kapitel 6 meines Buches "Programming in Mathematica, 3rd ed." handelt von solchen Fragestellungen. Generell sind Regeln der Form a_ + b_ := zu vermeiden, oder anders ausgedrückt: wenn Sie versucht sind, Unprotect[etwas] zu benutzen, empfiehlt es sich, nach Alternativen zu suchen. Sie erreichen eine wesentliche Verbesserung, wenn Sie dafür sorgen, daß Ihre Regel nur angewendet wird, wenn die Summanden tatsächlich vom Typ "CI" sind, also die Regel für Plus an das Symbol CI anhängen: CI/:Plus[x_CI,y_CI] := CI[(Identity@@x) + (Identity@@y)] Regel für Times wie vorhin: Times[x_CI,y_n] := CI[(Identity@@x) (Identity@@y)]; dann: In[6]:= Timing[ Collect[f g, z] ] 3 8 6 12 Out[6]= {0.01 Second, z CI[4] + z CI[6] + z CI[10] + z CI[14] + 4 9 10 11 5 > z CI[17] + z CI[18] + z CI[19] + z CI[21] + z CI[23]} Noch etwas verbessert, schlage ich folgende Regeln vor (die auch kein Unprotect[Times, Plus] mehr benötigen!) CI/:Times[CI[x_],n[y_]] := CI[x y]; CI/:Plus[CI[x_], CI[y_]] := CI[x + y] Alternativ können Sie statt Collect[f g, z] mittels CoefficientList[f g, z] eine Liste l der Koeffizienten erhalten, auf die Sie dann gezielt Ihre Vereinfachungsregeln mittels l /. {regeln..} anwenden können. Dann wandeln Sie die Liste l mittels Plus @@ (l . z^Range[0,Length[l]-1]) in ein Polynom um, wenn Sie es in dieser Form brauchen. Roman Mäder ----------------------------------------------------------------------- MathConsult Dr. R. Mäder Samstagernstrasse 58a Mathematik- und Informatik-Beratung CH-8832 Wollerau T: +41-1-687 4050 mailto:maeder@XXXXXXX.ch F: +41-1-687 4054 http://www.mathconsult.ch/ ----------------------------------------------------------------------- |