Mathematica-Regelersetzungsspeicher

  • Zuerst stelle ich die spezifische Programmierfrage vor und gebe dann weitere Hintergrundinformationen an.

    Wenn ein Ausdruck in Mathematica angegeben ist, sagen Sie f=3x+7y dort sind zwei gebräuchliche Möglichkeiten, Informationen durch x und y zu ersetzen. Die erste ist die Verwendung der Regel /.. Etwas wie

      t=f/.{x->0,y->0};
     

    würde den Wert von t gleich 0.

    Und der andere ist eine allgemeinere Ersetzung für x und y, wo immer sie auftauchen, wie

      x=0; y=0;
     t=f;
     

    Dadurch wird auch der Wert von t gleich 0. Der Unterschied bei der Speichernutzung wird jedoch bei komplizierteren Polynomen deutlich. Ich habe eine Textdatei mit einem komplizierten Polynom zu MediaFire hochgeladen: http://www.mediafire.com/?0ea3mhtqmc8c3r2 (es handelt sich um etwa 4 MB, und ich weiß nicht, wie man es besser teilt). Wenn Sie es herunterladen und anschließend in Mathematica laden, wie ich es demonstrieren werde, können Sie den erheblichen Speicherverlust selbst sehen:

    Substitutionsmethode

      In[1]:= << "/home/username/Downloads/p";
     In[2]:= MaxMemoryUsed[]
     Out[2]= 79833424
     In[3]:= MemoryInUse[]
     Out[3]= 76373112
     In[4]:= t = p /. {x -> 0, y -> 0, z -> 0};
     In[5]:= MaxMemoryUsed[]
     Out[5]= 152124264
     In[6]:= MemoryInUse[]
     Out[6]= 112876080
     

    Allgemeine Zuweisungsmethode

     [pre>  In[1]:= << "/home/username/Downloads/p";
     In[2]:= MaxMemoryUsed[]
     Out[2]= 79831632
     In[3]:= MemoryInUse[]
     Out[3]= 75415960
     In[4]:= x = 0; y = 0; z = 0;
     In[5]:= MaxMemoryUsed[]
     Out[5]= 79831632
     In[6]:= MemoryInUse[]
     Out[6]= 75420744
     In[7]:= t = p;
     In[8]:= MaxMemoryUsed[]
     Out[8]= 112888664
     In[9]:= MemoryInUse[]
     Out[9]= 112875336
     

    Wie Sie sehen, wurden während des Ersetzungsvorgangs etwa 40 MB zusätzlicher Speicher für die Ersetzung verwendet. Die Substitutionsmethode dauert auch viel länger als die allgemeine Methode. Der Unterschied zwischen den beiden Methoden wird um ein Vielfaches größer (einige GB), wenn die Komplexität des Polynoms zunimmt und der verfügbare RAM maximal ausgenutzt wird. Das Problem ist, dass ich für mein Programm x, y, z im Allgemeinen nicht gleich Null setzen kann.

    Dies scheint eine Ineffizienz der Art zu sein, in der Mathematica Substitutionen durchführt. Ich würde mich über Anregungen freuen, um dieses Problem zu umgehen.


    Weiterer Hintergrund

    Der Grund, warum ich die allgemeine Methode nicht einfach anwenden kann, ist der, dass der nächste Schritt erfordert, dass ich

    08 March 2012
    Szabolcs
3 answers
  • Auch wenn ich nicht erklären kann, warum es einen Unterschied zwischen den beiden Methoden gibt, möchte ich vorschlagen,

     t = Block[{x=0, y=0}, p];
     

    Block setzt einen Wert nur vorübergehend auf x und y und vermeidet die Verwendung von Clear.

    Einige mehr Dinge, die für Sie nützlich sein können:

    1. Wenn Sie mit der Arbeit beginnen, verwenden Sie $HistoryLength = 0, um zu vermeiden, dass Sie sich an vergangene Ergebnisse erinnern und Speicherplatz verschwenden (beachten Sie das Mathematica erinnert sich manchmal an volle Ergebnisse, auch wenn die Eingabe mit einem Semikolon beendet wurde!)

    2. Verwenden Sie gelegentlich Share[]. Es scheint, dass dies mit Ihrem Polynom viel mehr als in anderen Fällen hilft. Nach dem Einlesen des Polynoms werden sofort 60 MB für mich freigegeben.

    07 March 2012
    Szabolcs
  • Ich habe dieses Problem auf sehr einfache Weise gelöst, wie ich es hier zeigen werde:

      In[1]:= f = 3 x + 7 y
     Out[1]= 3 x + 7 y
     In[2]:= x = 0;
     In[3]:= t = f
     Out[3]= 7 y
     In[4]:= Clear[x];
     In[5]:= t
     Out[5]= 7 y
     In[6]:= f
     Out[6]= 3 x + 7 y
     

    Nun wundere ich mich nur, warum der Ersetzungsbefehl von Mathematica diese Methode nicht für Ersetzungen verwendet. Ich bin sicher, dass es Situationen gibt, in denen kompliziertere Substitutionsregeln mit diesem Ansatz möglicherweise fehlschlagen. In diesem Fall sollten jedoch einige Heuristiken bestimmen, ob diese viel schnellere und weniger RAM-intensive Methode anwendbar ist, und sie gegebenenfalls anwenden.

    06 March 2012
    process91
  • Das grundlegende Problem ist Folgendes:

     expr /. x->1
     

    Mathematica muss das gesamte System untersuchen Ausdrucksbaum, um zu bestimmen, welche Teile ersetzt werden können. Nachdem alle diese Teile ersetzt wurden, wird das Ergebnis ausgewertet. Vergleichen Sie dies mit einem Block -Ansatz:

     Block[{x=1}, expr]
     

    In diesem Fall setzt Mathematica x=1 und wertet dann expr aus. Wenn x während der Bewertung von expr angetroffen wird, wird es zu 1 ausgewertet. Im Gegensatz zur Verwendung von ReplaceAll sucht Mathematica nicht nach Teilen, die mit x. Daher überrascht es nicht, dass der Block -Prozess viel schneller sein kann.

    Hier sind drei weitere Beobachtungen:

    Bewertung

    Beim Ansatz Block wird x nur durch 1 ersetzt. ], wenn der Evaluator auf x trifft. Hier ist ein Beispiel, in dem der Block dem Evaluator niemals x :

     Hold[x] /. x->1
    Block[{x=1}, Hold[x]]
     

    Halten Sie [1]

    Halten Sie [x]

    Regeln mit Mustern

    Wenn die LHS der Regel ein Muster und kein Literal ist, dann ist der naive Block Ansatz funktioniert nicht.

     {x[1], x[2.2]} /. x[_Integer] -> 1
    Block[{x[_Integer]=1}, {x[1], x[2.2]}]
     

    {1, x [2.2] }

    Block :: lvset: Lokale Variablenspezifikation {x [_Integer] = 1} enthält x [_Integer] = 1, was eine Zuweisung zu x [_Integer] ist; Es sind nur Zuweisungen zu Symbolen zulässig.

    Block [{x [_Integer] =

    16 April 2018
    Carl Woll