Was ist in Ihrer Mathematica-Werkzeugtasche? [geschlossen]

152

Wir alle wissen, dass Mathematica großartig ist, aber es fehlt oft auch an kritischer Funktionalität. Welche externen Pakete / Tools / Ressourcen verwenden Sie mit Mathematica?

Ich werde diesen Hauptbeitrag bearbeiten (und auch andere dazu einladen), um Ressourcen aufzunehmen, die sich auf die allgemeine Anwendbarkeit in der wissenschaftlichen Forschung konzentrieren und die so vielen Menschen wie möglich nützlich sein werden. Fühlen Sie sich frei, irgendetwas beizutragen, auch kleine Code-Schnipsel (wie ich es unten für eine Timing-Routine getan habe).

Außerdem sind undokumentierte und nützliche Funktionen in Mathematica 7 und darüber hinaus, die Sie selbst gefunden oder von einem Papier / einer Website ausgegraben haben, sehr willkommen.

Bitte geben Sie eine kurze Beschreibung oder einen Kommentar dazu an, warum etwas großartig ist oder welches Dienstprogramm es bietet. Wenn Sie mit Affiliate-Links auf Bücher bei Amazon verlinken, erwähnen Sie dies bitte, indem Sie beispielsweise Ihren Namen hinter den Link setzen.


Pakete:

  1. LevelSchemeist ein Paket, das die Fähigkeit von Mathematica, gut aussehende Diagramme zu erstellen, erheblich erweitert. Ich benutze es, wenn nicht für irgendetwas anderes, dann für die viel, viel verbesserte Kontrolle über Rahmen- / Achsen-Ticks. Die neueste Version heißt SciDraw und wird noch in diesem Jahr veröffentlicht.
  2. David Park's Presentation Package(50 US-Dollar - keine Gebühr für Updates)
  3. Das grassmannOpsPaket von Jeremy Michelson bietet Ressourcen für die Durchführung von Algebra und Kalkül mit Grassmann-Variablen und -Operatoren, die nicht triviale Kommutierungsbeziehungen haben.
  4. John Browns GrassmannAlgebraPaket und Buch für die Arbeit mit Grassmann- und Clifford-Algebren.
  5. RISC (Forschungsinstitut für symbolische Berechnung) bietet eine Vielzahl von Paketen für Mathematica (und andere Sprachen) zum Download an. Insbesondere ist es Theorema für automatisierte Theorembeweisen, und die Vielzahl der Pakete für die symbolische Summe, Differenzengleichungen, usw. auf der Software - Seite der Algorithmic Kombinatorik Gruppe .

Werkzeuge:

  1. MASHist Daniel Reeves 'exzellentes Perl- Skript, das im Wesentlichen Skriptunterstützung für Mathematica v7 bietet. (Jetzt ab Mathematica 8 mit der -scriptOption eingebaut .)
  2. Ein alternate Mathematica shellmit einer GNU-Readline-Eingabe (mit Python, nur * nix)
  3. Mit dem ColourMaths-Paket können Sie Teile eines Ausdrucks visuell auswählen und bearbeiten. http://www.dbaileyconsultancy.co.uk/colour_maths/colour_maths.html

Ressourcen:

  1. Wolframs eigenes Repository MathSourcebietet viele nützliche, wenn auch schmale Notizbücher für verschiedene Anwendungen. Schauen Sie sich auch die anderen Abschnitte an, wie z

  2. Das Mathematica Wikibook .

Bücher:

  1. Mathematica-Programmierung: Eine erweiterte Einführung von Leonid Shifrin ( web, pdf) ist ein Muss, wenn Sie mehr als For- Schleifen in Mathematica ausführen möchten . Wir haben das Vergnügen, Leonidhier Fragen beantworten zu können.
  2. Quantenmethoden mit Mathematica von James F. Feagin ( amazon )
  3. Das Mathematica-Buch von Stephen Wolfram ( amazon ) ( web)
  4. Schaums Umriss ( amazon )
  5. Mathematica in Aktion von Stan Wagon ( Amazon ) - 600 Seiten mit tollen Beispielen und bis zu Mathematica Version 7. Visualisierungstechniken sind besonders gut, einige davon finden Sie auf der des Autors Demonstrations Page.
  6. Mathematica Programming Fundamentals von Richard Gaylord ( pdf) - Eine gute, prägnante Einführung in das meiste, was Sie über Mathematica-Programmierung wissen müssen.
  7. Mathematica Cookbook von Sal Mangano veröffentlicht von O'Reilly 2010 832 Seiten. - Geschrieben im bekannten O'Reilly-Kochbuchstil: Problem - Lösung. Für Zwischenprodukte.
  8. Differentialgleichungen mit Mathematica, 3. Aufl. Elsevier 2004 Amsterdam von Martha L. Abell, James P. Braselton - 893 Seiten Für Anfänger lernen Sie gleichzeitig, DEs und Mathematica zu lösen.

Undokumentierte (oder kaum dokumentierte) Funktionen:

  1. So passen Sie Mathematica-Tastaturkürzel an Siehe this question.
  2. Untersuchen von Mustern und Funktionen, die von Mathematicas eigenen Funktionen verwendet werden. Sehenthis answer
  3. Wie kann eine konsistente Größe für GraphPlots in Mathematica erreicht werden? Siehe this question.
  4. Erstellen von Dokumenten und Präsentationen mit Mathematica. Siehe this question.
Dr. belisarius
quelle
2
Mathematica 8 bietet eine viel bessere Integration von Shell-Skripten. wolfram.com/mathematica/new-in-8/mathematica-shell-scripts
Joshua Martell
2
+1 für LevelScheme. Manchmal ist es etwas langsam. Aber es hat eine vernünftige Methode zum Erstellen von Häkchen, und es ist dann viel einfacher, journalwürdige Layouts für Grafiken Gridoder ähnliches zu erstellen .
Rcollyer
2
Wie von Alexey in den Kommentaren zu dieser Frage stackoverflow.com/questions/5152551/… vorgeschlagen, habe ich die Umbenennung des Tags für Mathematica hier vorgeschlagen: meta.stackexchange.com/questions/81152/… . Bitte schauen Sie vorbei und stimmen Sie ab, wenn Sie damit einverstanden sind. Ich poste es hier, weil diese Frage hier viele Favoriten in der Mma-Community hat.
Dr. Belisarius
1
Alles in allem sollte diese Frage aus all den üblichen Gründen ein Community-Wiki sein: Sie hat keine richtige Antwort und ist eher eine Liste als alles andere. Ich entschuldige mich bei allen, die von dieser Frage einen guten Ruf erlangt haben.
rcollyer
2
Diese Antworten auf diese Frage sind konstruktiv, sie sollte wieder geöffnet werden.
MR

Antworten:

29

Ich habe erwähne dies vor, aber das Werkzeug , das ich am nützlichsten ist eine Anwendung von finden Reapund Sowwelche ahmt / erweitert das Verhalten GatherBy:

SelectEquivalents[x_List,f_:Identity, g_:Identity, h_:(#2&)]:=
   Reap[Sow[g[#],{f[#]}]&/@x, _, h][[2]];

Auf diese Weise kann ich Listen nach beliebigen Kriterien gruppieren und dabei transformieren. So funktioniert es: Eine Kriterienfunktion ( f) markiert jedes Element in der Liste, jedes Element wird dann von einer zweiten bereitgestellten Funktion ( g) transformiert und die spezifische Ausgabe wird von einer dritten Funktion ( h) gesteuert . Die Funktion hakzeptiert zwei Argumente: ein Tag und eine Liste der gesammelten Elemente mit diesem Tag. Die Artikel behalten ihre ursprüngliche Reihenfolge bei. Wenn Sie also festlegen, erhalten h = #1&Sie eine unsortierte Union, wie in den Beispielen für Reap. Es kann jedoch für die Sekundärverarbeitung verwendet werden.

Als Beispiel für seine Nützlichkeit habe ich mit Wannier90 gearbeitet, das den räumlich abhängigen Hamilton-Operator wie folgt in eine Datei ausgibt, in der jede Zeile ein anderes Element in der Matrix ist

rx ry rz i j Re[Hij] Im[Hij]

Um diese Liste in eine Reihe von Matrizen umzuwandeln, habe ich alle Unterlisten zusammengestellt, die dieselbe Koordinate enthalten, die Elementinformationen in eine Regel umgewandelt (dh {i, j} -> Re [Hij] + I Im [Hij]) und verwandelte dann die gesammelten Regeln in ein SparseArrayAll mit dem einen Liner:

SelectEquivalents[hamlst, 
      #[[;; 3]] &, 
      #[[{4, 5}]] -> (Complex @@ #[[6 ;;]]) &, 
      {#1, SparseArray[#2]} &]

Ehrlich gesagt, das ist mein Schweizer Taschenmesser und es macht komplexe Dinge sehr einfach. Die meisten meiner anderen Tools sind etwas domänenspezifisch, daher werde ich sie wahrscheinlich nicht veröffentlichen. Die meisten, wenn nicht alle, beziehen sich jedoch auf sie SelectEquivalents.

Bearbeiten : Es ahmt nicht vollständig GatherBynach, da es nicht mehrere Ebenen des Ausdrucks so einfach wie GatherBymöglich gruppieren kann. Funktioniert jedoch Mapfür das meiste, was ich brauche, einwandfrei.

Beispiel : @Yaroslav Bulatov hat um ein in sich geschlossenes Beispiel gebeten. Hier ist eine aus meiner Forschung, die stark vereinfacht wurde. Nehmen wir also an, wir haben eine Reihe von Punkten in einer Ebene

In[1] := pts = {{-1, -1, 0}, {-1, 0, 0}, {-1, 1, 0}, {0, -1, 0}, {0, 0, 0}, 
 {0, 1, 0}, {1, -1, 0}, {1, 0, 0}, {1, 1, 0}}

und wir möchten die Anzahl der Punkte durch eine Reihe von Symmetrieoperationen reduzieren. (Für Neugierige generieren wir die kleine Gruppe jedes Punktes.) In diesem Beispiel verwenden wir eine vierfache Rotationsachse um die z-Achse

In[2] := rots = RotationTransform[#, {0, 0, 1}] & /@ (Pi/2 Range[0, 3]);

Mit können SelectEquivalentswir die Punkte, die denselben Satz von Bildern erzeugen, unter diesen Operationen gruppieren, dh sie sind äquivalent

In[3] := SelectEquivalents[ pts, Union[Through[rots[#] ] ]& ] (*<-- Note Union*)
Out[3]:= {{{-1, -1, 0}, {-1, 1, 0}, {1, -1, 0}, {1, 1, 0}},
          {{-1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {1, 0, 0}},
          {{0,0,0}}}

Dies erzeugt 3 Unterlisten mit den entsprechenden Punkten. (Beachten Sie, dass dies Unionhier unbedingt erforderlich ist, da dadurch sichergestellt wird, dass von jedem Punkt das gleiche Bild erzeugt wird. Ursprünglich habe ich es verwendet Sort, aber wenn ein Punkt auf einer Symmetrieachse liegt, ist er unter der Drehung um diese Achse unveränderlich und ergibt ein zusätzliches Bild von sich So., Unionbeseitigt diese zusätzlichen Bilder. Außerdem GatherBywürde das gleiche Ergebnis.) in diesem Fall sind die Punkte bereits in einer Form , die ich benutze, aber ich brauche nur einen repräsentativen Punkt aus jeder Gruppe und mir würde eine Zählung gefallen der äquivalenten Punkte. Da ich nicht jeden Punkt transformieren muss, verwende ich dieIdentityFunktion in der zweiten Position. Für die dritte Funktion müssen wir vorsichtig sein. Das erste Argument, das an es übergeben wird, sind die Bilder der Punkte unter den Rotationen, die für den Punkt {0,0,0}eine Liste von vier identischen Elementen sind, und deren Verwendung würde die Zählung beeinträchtigen. Das zweite Argument ist jedoch nur eine Liste aller Elemente, die dieses Tag haben, sodass es nur enthält {0,0,0}. In Code,

In[4] := SelectEquivalents[pts,  
             Union[Through[rots[#]]]&, #&, {#2[[1]], Length[#2]}& ]
Out[4]:= {{{-1, -1, 0}, 4}, {{-1, 0, 0}, 4}, {{0, 0, 0}, 1}}

Beachten Sie, dass dieser letzte Schritt genauso einfach von ausgeführt werden kann

In[5] := {#[[1]], Length[#]}& /@ Out[3]

Mit diesem und dem weniger vollständigen Beispiel oben ist jedoch leicht zu erkennen, wie sehr komplexe Transformationen mit einem Minimum an Code möglich sind.

rcollyer
quelle
Der ursprüngliche Fortran77-Code wurde am Erntedankfest 1996 umstrukturiert und ist daher seit vielen Jahren als Truthahn bekannt. F :: Sehr schöne Grafiken übrigens. Erinnerte mich an das Monster von Falicov ...
Dr. belisarius
@ Belisarius, ich hatte die Geschichte nicht gelesen, das ist lustig. Ich habe gerade angefangen, Wannier90 zu verwenden, aber es ist einer der am besten organisierten und gut geschriebenen FortranCodes, die ich gesehen habe. Fortran
Lässt
Ich frage mich, ob Sie ein in sich geschlossenes Beispiel für SelectEquivalents in Aktion hinzufügen könnten
Yaroslav Bulatov
@ Jaroslaw Bulatow, auf Anfrage ein Beispiel hinzugefügt. Lassen Sie mich wissen, ob das hilft. Wenn nicht, werden wir sehen, was wir tun können.
Rcollyer
Sie erhalten das Häkchen bei dieser "Frage" für den interessantesten Code-Snippet-Beitrag.
Timo
57

Eines der schönen Dinge an der Mathematica-Notebook-Oberfläche ist, dass sie Ausdrücke in jeder Sprache auswerten kann , nicht nur in Mathematica. Als einfaches Beispiel sollten Sie einen neuen Shell- Eingabezelltyp erstellen , der den enthaltenen Ausdruck zur Auswertung an die Betriebssystem-Shell übergibt.

Definieren Sie zunächst eine Funktion, die die Auswertung eines Textbefehls an die externe Shell delegiert:

shellEvaluate[cmd_, _] := Import["!"~~cmd, "Text"]

Das zweite Argument wird aus Gründen benötigt und ignoriert, die später ersichtlich werden. Als nächstes wollen wir einen neuen Stil namens Shell erstellen :

  1. Öffnen Sie ein neues Notizbuch.
  2. Wählen Sie den Menüpunkt Format / Stylesheet bearbeiten ...
  3. Im Dialogfeld neben Geben Sie einen Stilnamen ein: Typ Shell.
  4. Wählen Sie die Zellenklammer neben dem neuen Stil aus.
  5. Wählen Sie den Menüpunkt Zelle / Ausdruck anzeigen
  6. Überschreiben Sie den Zellausdruck mit dem unten angegebenen Text in Schritt 6 .
  7. Wählen Sie erneut den Menüpunkt Zelle / Ausdruck anzeigen
  8. Schließen Sie den Dialog.

Verwenden Sie den folgenden Zellausdruck als Text für Schritt 6 :

Cell[StyleData["Shell"],
 CellFrame->{{0, 0}, {0.5, 0.5}},
 CellMargins->{{66, 4}, {0, 8}},
 Evaluatable->True,
 StripStyleOnPaste->True,
 CellEvaluationFunction->shellEvaluate,
 CellFrameLabels->{{None, "Shell"}, {None, None}},
 Hyphenation->False,
 AutoQuoteCharacters->{},
 PasteAutoQuoteCharacters->{},
 LanguageCategory->"Formula",
 ScriptLevel->1,
 MenuSortingValue->1800,
 FontFamily->"Courier"]

Der größte Teil dieses Ausdrucks wurde direkt aus dem integrierten Programmstil kopiert . Die wichtigsten Änderungen sind folgende Zeilen:

 Evaluatable->True,
 CellEvaluationFunction->shellEvaluate,
 CellFrameLabels->{{None, "Shell"}, {None, None}},

EvaluatableAktiviert die SHIFT + ENTER-Funktionalität für die Zelle. Bei der Auswertung wird die CellEvaluationFunctionÜbergabe des Zelleninhalts und des Inhaltstyps als Argumente aufgerufen (wobei shellEvaluatedas letztere Argument ignoriert wird). CellFrameLabelsist nur eine nette Sache, mit der der Benutzer erkennen kann, dass diese Zelle ungewöhnlich ist.

Mit all dem können wir nun einen Shell-Ausdruck eingeben und auswerten:

  1. Erstellen Sie in dem in den obigen Schritten erstellten Notizbuch eine leere Zelle und wählen Sie die Zellenklammer aus.
  2. Wählen Sie den Menüpunkt Format / Style / Shell .
  3. Geben Sie einen gültigen Betriebssystem-Shell-Befehl in die Zelle ein (z. B. 'ls' unter Unix oder 'dir' unter Windows).
  4. Drücken Sie UMSCHALT + EINGABETASTE.

Es ist am besten, diesen definierten Stil in einem zentral angeordneten Stylesheet beizubehalten. Darüber hinaus lassen sich Bewertungsfunktionen wie Decubs am shellEvaluatebesten mit DeclarePackage in definieren init.m. Die Einzelheiten dieser beiden Aktivitäten gehen über den Rahmen dieser Antwort hinaus.

Mit dieser Funktion können Notizbücher erstellt werden, die Eingabeausdrücke in einer beliebigen Syntax von Interesse enthalten. Die Bewertungsfunktion kann in reiner Mathematica geschrieben sein oder einen oder alle Teile der Bewertung an eine externe Agentur delegieren. Seien Sie sich bewusst , dass es andere Haken sind , die Auswertung beziehen sich auf die Zelle, wie CellEpilog, CellPrologund CellDynamicExpression.

Ein gängiges Muster besteht darin, den Text des Eingabeausdrucks in eine temporäre Datei zu schreiben, die Datei in einer bestimmten Sprache zu kompilieren, das Programm auszuführen und die Ausgabe für die endgültige Anzeige in der Ausgabezelle zu erfassen. Es gibt viele Details zu beachten, wenn eine vollständige Lösung dieser Art implementiert wird (z. B. die korrekte Erfassung von Fehlermeldungen), aber man muss die Tatsache zu schätzen wissen, dass dies nicht nur möglich, sondern auch praktisch ist.

Persönlich gesehen sind es Funktionen wie diese, die die Notebook-Oberfläche zum Zentrum meines Programmieruniversums machen.

Aktualisieren

Die folgende Hilfsfunktion ist nützlich, um solche Zellen zu erstellen:

evaluatableCell[label_String, evaluationFunction_] :=
  ( CellPrint[
      TextCell[
        ""
      , "Program"
      , Evaluatable -> True
      , CellEvaluationFunction -> (evaluationFunction[#]&)
      , CellFrameLabels -> {{None, label}, {None, None}}
      , CellGroupingRules -> "InputGrouping"
      ]
    ]
  ; SelectionMove[EvaluationNotebook[], All, EvaluationCell]
  ; NotebookDelete[]
  ; SelectionMove[EvaluationNotebook[], Next, CellContents]
  )

Es wird folgendermaßen verwendet:

shellCell[] := evaluatableCell["shell", Import["!"~~#, "Text"] &]

Wenn dies shellCell[]ausgewertet wird, wird die Eingabezelle gelöscht und durch eine neue Eingabezelle ersetzt, die ihren Inhalt als Shell-Befehl auswertet.

WReach
quelle
3
@ WReach +100! Ich wünschte, ich wüsste das früher! Das ist zumindest für mich sehr nützlich. Danke für das Teilen!
Leonid Shifrin
Das sieht ziemlich schick aus! CellEvaluationFunctionkönnte auch für Low-Level-Syntax-Hacking verwendet werden, denke ich.
Mr.Wizard
@Leonid Zumindest für das FrontEnd, ist CellEvaluationFunctionder Haken, den Sie gesucht haben?
Mr.Wizard
2
Darüber hinaus gibt es eine weitere CellOption, die sich auf die Bewertung von Zellen bezieht - Evaluator -> "EvaluatorName". Die Bedeutung von "EvaluatorName"kann über das Dialogfeld Evaluation :: Kernel Configuration Options ... konfiguriert werden . Ich weiß immer noch nicht, ob es möglich ist, es programmgesteuert zu konfigurieren ... Diese Technik ermöglicht es, verschiedene MathKernels in verschiedenen Cells in einem Notebook zu verwenden. Diese MathKernels können aus verschiedenen Versionen von Mathematica installiert sein.
Alexey Popkov
1
@Szabolcs Alle meine eigenen Anwendungen dieser Technik umfassen entweder einen stdin _ / _ stdout- Ansatz wie oben dargestellt oder eine in sich geschlossene Remoteanforderung wie eine SQL-Abfrage oder eine HTTP-Operation. Sie können versuchen, eine Python REPL-Webanwendung (wie diese ) einzurichten und mit ihr zu interagieren Import, oder einen externen Python-Prozess starten und über seine Streams kommunizieren (z. B. mit einem Java ProcessBuilder ). Ich bin sicher, es gibt einen besseren Mathematica-Weg - klingt nach einer guten SO-Frage :)
WReach
36

Todd Gayley (Wolfram Research) hat mir gerade einen netten Hack geschickt, mit dem integrierte Funktionen mit beliebigem Code "umbrochen" werden können. Ich habe das Gefühl, dass ich dieses nützliche Instrument teilen muss. Das Folgende ist Todd's Antwort auf meine question.

Ein bisschen interessante (?) Geschichte: Diese Art von Hack zum "Umwickeln" einer eingebauten Funktion wurde um 1994 von Robby Villegas und mir, ironischerweise für die Funktion Message, in einem Paket namens ErrorHelp erfunden, das ich für das Mathematica Journal geschrieben habe damals. Es wurde seitdem von vielen Menschen oft benutzt. Es ist ein Trick eines Insiders, aber ich denke, es ist fair zu sagen, dass es die kanonische Methode geworden ist, Ihren eigenen Code in die Definition einer integrierten Funktion einzufügen. Es erledigt die Arbeit gut. Sie können die Variable $ inMsg natürlich in einen beliebigen privaten Kontext stellen.

Unprotect[Message];

Message[args___] := Block[{$inMsg = True, result},
   "some code here";
   result = Message[args];
   "some code here";
   result] /; ! TrueQ[$inMsg]

Protect[Message];
Alexey Popkov
quelle
@ Alexander Ich habe Schwierigkeiten, dies zu verstehen. Können Sie erklären, wie das funktioniert? Sollte es nicht irgendwo eine Unprotect [Nachricht] geben? Und enthält dieses Beispiel nicht eine unendliche Rekursion? Und, ! TrueQ [$ inMsg] macht das Sinn, wenn $ inMsg innerhalb des Blockbereichs definiert und außerhalb von Block undefiniert ist?
Sjoerd C. de Vries
9
@Sjoerd Soweit ich weiß, muss das Unprotectin der Tat sein, wurde einfach weggelassen . Der Punkt von Block(dynamisches Scoping) und $inMsgist genau, um eine unendliche Rekursion zu verhindern. Da $inMsgaußerhalb undefiniert ist (dies ist eine wichtige Anforderung), wird zunächst TrueQausgewertet Falseund wir geben den Funktionskörper ein. Wenn wir jedoch den Funktionsaufruf im Körper haben, wird die Bedingung ausgewertet False(da die Variable durch Block neu definiert wurde). Daher stimmt die benutzerdefinierte Regel nicht überein, und stattdessen wird die integrierte Regel verwendet.
Leonid Shifrin
1
@Leonid Danke, ich verstehe es jetzt. Sehr schlau!
Sjoerd C. de Vries
1
Ich habe gerade festgestellt, dass diese Technik von Robby Villegas von Wolfram Research auf der Entwicklerkonferenz 1999 diskutiert wurde. Siehe das hier veröffentlichte Notizbuch "Arbeiten mit nicht bewerteten Ausdrücken" . In diesem Notizbuch beschreibt Robby Villegas diesen Trick im Unterabschnitt "Mein Blocktrick zum Überfüllen von Aufrufen für integrierte Funktionen".
Alexey Popkov
1
@ Mr.Wizard Dies ist nicht die einzige Möglichkeit, dies zu tun. Ich habe lange Zeit eine Version verwendet, in der Sie die DownValueszur Laufzeit neu definieren. Sie können sich diesen Beitrag groups.google.com/group/comp.soft-sys.math.mathematica/… als Beispiel ansehen ( SetDelayedNeudefinition). . Meine Methode ist jedoch weniger elegant, weniger robust, fehleranfälliger und macht die Implementierung der Rekursion weniger trivial. In den meisten Situationen gewinnt die von @Alexey beschriebene Methode zweifellos.
Leonid Shifrin
25

Dies ist keine vollständige Ressource, daher werfe ich sie hier im Abschnitt "Antworten", aber ich habe sie als sehr nützlich empfunden, wenn ich Geschwindigkeitsprobleme herausgefunden habe (was leider einen großen Teil der Mathematik-Programmierung ausmacht).

timeAvg[func_] := Module[
{x = 0, y = 0, timeLimit = 0.1, p, q, iterTimes = Power[10, Range[0, 10]]},
Catch[
 If[(x = First[Timing[(y++; Do[func, {#}]);]]) > timeLimit,
    Throw[{x, y}]
    ] & /@ iterTimes
 ] /. {p_, q_} :> p/iterTimes[[q]]
];
Attributes[timeAvg] = {HoldAll};

Nutzung ist dann einfach timeAvg@funcYouWantToTest.

EDIT: Mr. Wizard hat eine einfachere Version zur Verfügung gestellt , die weg tut mit Throwund Catchund ist ein wenig einfacher zu parsen:

SetAttributes[timeAvg, HoldFirst]
timeAvg[func_] := Do[If[# > 0.3, Return[#/5^i]] & @@ 
                     Timing @ Do[func, {5^i}]
                     ,{i, 0, 15}]

EDIT: Hier ist eine Version von acl (von hier übernommen ):

timeIt::usage = "timeIt[expr] gives the time taken to execute expr, \
  repeating as many times as necessary to achieve a total time of 1s";

SetAttributes[timeIt, HoldAll]
timeIt[expr_] := Module[{t = Timing[expr;][[1]], tries = 1},
  While[t < 1., tries *= 2; t = Timing[Do[expr, {tries}];][[1]];]; 
  t/tries]
Timo
quelle
Wieder getan und wieder ... Zeit, in meine eigene Tasche einzutreten. tnx!
Dr. Belisarius
1
Ein Problem mit diesem Code (naja, vielleicht ist dies der Standpunkt eines Perfektionisten) ist, dass wir etwas fangen können, das wir nicht geworfen haben, und dies als falsches Timing-Ergebnis interpretieren können. Beide Catchund Throwsollten mit eindeutigen Ausnahme-Tags verwendet worden sein.
Leonid Shifrin
2
Timo, ich bin froh, dass dir meine Wiedergabe genug gefällt, um sie aufzunehmen. Danke, dass du mir auch Anerkennung gegeben hast. Ich bin gespannt, wie Sie meinen Code neu formatiert haben. Ich befolge keine bestimmten Richtlinien in meinem eigenen Code, außer es mir leicht zu machen, mich selbst zu lesen. Gibt es eine Denkschule hinter Ihrer Neuformatierung oder ist es nur eine Präferenz? Mathematica fördert aufgrund der Art und Weise, wie Eingaben zurückfließen, keine präzise Code-Formatierung, aber das Posten von Code hier veranlasst mich, darüber nachzudenken. Übrigens, ich denke du meinst " Throwund Catch" anstatt " Reapund Sow".
Mr.Wizard
1
@Simon, Mr.Wizard, ich verwende diese Methode, um unterschiedliche Versionen kleinerer Funktionen zeitlich festzulegen, die häufig aufgerufen werden. Nicht unbedingt in einer Schleifenstruktur, aber sicherlich in Konstrukten, die MMA optimiert. In diesem Zusammenhang ist das Timing der Ausführung einer Schleife sinnvoll und die Leistung liegt nahe an der realen Anwendung. Für das Timing großer komplexer Funktionen (möglicherweise sogar ganzer Initialisierungszellen) liefert die Methode von Simon ein besseres Ergebnis. Alles in allem interessiere ich mich mehr für relative Werte und beide Methoden sollten dort funktionieren.
Timo
3
Es gibt jetzt das RepeatedTimingzu tun.
Masterxilo
20

Internal`InheritedBlock

Ich habe kürzlich Internal`InheritedBlockaus dieser Botschaft von Daniel Lichtblau in der offiziellen Newsgroup erfahren, dass es so nützliche Funktionen gibt .

Soweit ich weiß, Internal`InheritedBlockkann eine Kopie einer ausgehenden Funktion innerhalb des BlockGültigkeitsbereichs übergeben werden:

In[1]:= Internal`InheritedBlock[{Message},
Print[Attributes[Message]];
Unprotect[Message];
Message[x___]:=Print[{{x},Stack[]}];
Sin[1,1]
]
Sin[1,1]
During evaluation of In[1]:= {HoldFirst,Protected}
During evaluation of In[1]:= {{Sin::argx,Sin,2},{Internal`InheritedBlock,CompoundExpression,Sin,Print,List}}
Out[1]= Sin[1,1]
During evaluation of In[1]:= Sin::argx: Sin called with 2 arguments; 1 argument is expected. >>
Out[2]= Sin[1,1]

Ich denke, diese Funktion kann für alle sehr nützlich sein, die eingebaute Funktionen vorübergehend ändern müssen!

Vergleich mit Block

Definieren wir eine Funktion:

a := Print[b]

Nun möchten wir eine Kopie dieser Funktion in den BlockBereich übergeben. Die naive Prüfung gibt nicht das, was wir wollen:

In[2]:= Block[{a = a}, OwnValues[a]]

During evaluation of In[9]:= b

Out[2]= {HoldPattern[a] :> Null}

Versuchen Sie nun, die verzögerte Definition im ersten Argument von zu verwenden Block(es ist auch eine undokumentierte Funktion):

In[3]:= Block[{a := a}, OwnValues[a]]
Block[{a := a}, a]

Out[3]= {HoldPattern[a] :> a}

During evaluation of In[3]:= b

Wir sehen, dass in diesem Fall afunktioniert, aber wir haben keine Kopie des Originals ainnerhalb des BlockBereichs.

Versuchen wir jetzt Internal`InheritedBlock:

In[5]:= Internal`InheritedBlock[{a}, OwnValues[a]]

Out[5]= {HoldPattern[a] :> Print[b]}

Wir haben eine Kopie der ursprünglichen Definition für ainnerhalb des BlockGültigkeitsbereichs und können sie nach unseren Wünschen ändern, ohne die globale Definition für zu beeinflussen a!

Alexey Popkov
quelle
+1 Sehr praktisch! Ein weiteres Werkzeug in der Tasche und 10 Punkte näher am Bearbeitungsrecht für Sie.
Mr.Wizard
Für mich erscheint dies als eine Variante der frühen oder späten oder keiner und vollständigen Bewertung.
user2432923
19

Mathematica ist ein scharfes Werkzeug, aber es kann Sie mit seinem etwas untypisierten Verhalten und den Lawinen kryptischer Diagnosemeldungen schneiden . Eine Möglichkeit, damit umzugehen, besteht darin, Funktionen zu definieren, die dieser Redewendung folgen:

ClearAll@zot
SetAttributes[zot, ...]
zot[a_] := ...
zot[b_ /; ...] := ...
zot[___] := (Message[zot::invalidArguments]; Abort[])

Das ist eine Menge Boilerplate, die ich häufig überspringen möchte. Besonders beim Prototyping, was in Mathematica häufig vorkommt. Also benutze ich ein Makro namens define, das es mir ermöglicht, diszipliniert zu bleiben, mit viel weniger Boilerplate.

Eine grundlegende Verwendung von defineist wie folgt:

define[
  fact[0] = 1
; fact[n_ /; n > 0] := n * fact[n-1]
]

fact[5]

120

Auf den ersten Blick sieht es nicht nach viel aus, aber es gibt einige versteckte Vorteile. Der erste Dienst, der definebereitgestellt wird, besteht darin, dass er automatisch ClearAllauf das zu definierende Symbol angewendet wird. Dies stellt sicher, dass keine Restdefinitionen vorhanden sind - ein häufiges Ereignis bei der anfänglichen Entwicklung einer Funktion.

Der zweite Dienst besteht darin, dass die zu definierende Funktion automatisch "geschlossen" wird. Damit meine ich, dass die Funktion eine Nachricht ausgibt und abbricht, wenn sie mit einer Argumentliste aufgerufen wird, die nicht mit einer der Definitionen übereinstimmt:

fact[-1]

define::badargs: There is no definition for 'fact' applicable to fact[-1].
$Aborted

Dies ist der primäre Wert von define, der eine sehr häufige Fehlerklasse abfängt.

Ein weiterer Vorteil ist die übersichtliche Möglichkeit, Attribute für die zu definierende Funktion anzugeben. Machen wir die Funktion Listable:

define[
  fact[0] = 1
; fact[n_ /; n > 0] := n * fact[n-1]
, Listable
]

fact[{3, 5, 8}]

{6, 120, 40320}

Akzeptiert zusätzlich zu allen normalen Attributen defineein zusätzliches Attribut namens Open. Dies verhindert define, dass der Funktion die Gesamtfehlerdefinition hinzugefügt wird:

define[
  successor[x_ /; x > 0] := x + 1
, Open
]

successor /@ {1, "hi"}

{2, successor["hi"]}

Für eine Funktion können mehrere Attribute definiert werden:

define[
  flatHold[x___] := Hold[x]
, {Flat, HoldAll}
]

flatHold[flatHold[1+1, flatHold[2+3]], 4+5]

Hold[1 + 1, 2 + 3, 4 + 5]

Hier ist ohne weiteres die Definition von define:

ClearAll@define
SetAttributes[define, HoldAll]
define[body_, attribute_Symbol] := define[body, {attribute}]
define[body:(_Set|_SetDelayed), attributes_List:{}] := define[CompoundExpression[body], attributes]
define[body:CompoundExpression[((Set|SetDelayed)[name_Symbol[___], _])..], attributes_List:{}] :=
  ( ClearAll@name
  ; SetAttributes[name, DeleteCases[attributes, Open]]
  ; If[!MemberQ[attributes, Open]
    , def:name[___] := (Message[define::badargs, name, Defer@def]; Abort[])
    ]
  ; body
  ;
  )
def:define[___] := (Message[define::malformed, Defer@def]; Abort[])

define::badargs = "There is no definition for '``' applicable to ``.";
define::malformed = "Malformed definition: ``";

Die gezeigte Implementierung unterstützt weder Aufwärtswerte noch Currying noch allgemeinere Muster als die einfache Funktionsdefinition. Es bleibt jedoch nützlich.

WReach
quelle
2
+1 - das ist wirklich nützliches Zeug. Ich habe ähnliche Tools verwendet. Makros (sowie Introspektion und andere Meta-Programmiertechniken) können sehr leistungsfähig sein, scheinen jedoch in der Mathematica-Community allgemein unterbewertet zu sein, oder zumindest war dies bisher mein Eindruck.
Leonid Shifrin
Ich habe gerade etwas Ähnliches definiert. +1 für CompoundExpression-Unterstützung für mehrere Definitionen, Abort [] (scheint besser als noch mehr Nachrichten) und Open (schön für z. B. Konstruktoren).
Masterxilo
16

Beginnen Sie, ohne dass ein leeres Notizbuch geöffnet ist

Es störte mich, Mathematica mit einem leeren Notizbuch beginnen zu lassen. Ich könnte dieses Notizbuch mit einem Skript schließen, aber es würde immer noch kurz aufblitzen. Mein Hack ist es, eine Datei zu erstellen, die Folgendes Invisible.nbenthält:

Notebook[{},Visible->False]

Und füge dies zu meinem hinzu Kernel\init.m:

If[Length[Notebooks["Invisible*"]] > 0, 
  NotebookClose[Notebooks["Invisible*"][[1]]]
]

SetOptions[$FrontEnd,
  Options[$FrontEnd, NotebooksMenu] /. 
    HoldPattern["Invisible.nb" -> {__}] :> Sequence[]
]

Ich starte jetzt Mathematica durch Öffnen Invisible.nb

Es mag einen besseren Weg geben, aber das hat mir gut getan.


Kundenspezifisch FoldundFoldList

Fold[f, x] wird gleichgesetzt gemacht zu Fold[f, First@x, Rest@x]

Ich glaube übrigens, dass dies seinen Weg in eine zukünftige Version von Mathematica finden könnte.

Überraschung! Dies wurde implementiert, ist jedoch derzeit nicht dokumentiert. Ich bin informiert, dass es 2011 von Oliver Ruebenkoenig implementiert wurde, anscheinend nicht lange nachdem ich dies gepostet habe. Danke Oliver Ruebenkoenig!

Unprotect[Fold, FoldList]

Fold[f_, h_[a_, b__]] := Fold[f, Unevaluated @ a, h @ b]
FoldList[f_, h_[a_, b__]] := FoldList[f, Unevaluated @ a, h @ b]

(* Faysal's recommendation to modify SyntaxInformation *)
SyntaxInformation[Fold]     = {"ArgumentsPattern" -> {_, _, _.}};
SyntaxInformation[FoldList] = {"ArgumentsPattern" -> {_, _., {__}}};

Protect[Fold, FoldList]

Aktualisiert, um dies zu ermöglichen:

SetAttributes[f, HoldAll]
Fold[f, Hold[1 + 1, 2/2, 3^3]]
f[f[1 + 1, 2/2], 3^3]

"Dynamische Partition"

Eine neue Version dieser Funktion finden Sie in Mathematica.SE Post # 7512 .

Häufig möchte ich eine Liste nach einer Längenfolge aufteilen.

Pseudocode-Beispiel:

partition[{1,2,3,4,5,6}, {2,3,1}]

Ausgabe: {{1,2}, {3,4,5}, {6}}

Ich habe mir das ausgedacht:

dynP[l_, p_] := 
 MapThread[l[[# ;; #2]] &, {{0} ~Join~ Most@# + 1, #} &@Accumulate@p]

Was ich dann damit abgeschlossen habe, einschließlich Argumenttests:

dynamicPartition[l_List, p : {_Integer?NonNegative ..}] :=
  dynP[l, p] /; Length@l >= Tr@p

dynamicPartition[l_List, p : {_Integer?NonNegative ..}, All] :=
  dynP[l, p] ~Append~ Drop[l, Tr@p] /; Length@l >= Tr@p

dynamicPartition[l_List, p : {_Integer?NonNegative ..}, n__ | {n__}] :=
  dynP[l, p] ~Join~ Partition[l ~Drop~ Tr@p, n] /; Length@l >= Tr@p

Das dritte Argument steuert, was mit Elementen außerhalb der Split-Spezifikation geschieht.


Szabolcs 'Mathematica-Tricks

Die von mir am häufigsten verwendete ist die Tabelle zum Einfügen tabellarischer Daten

CreatePalette@
 Column@{Button["TSV", 
    Module[{data, strip}, 
     data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]];
     strip[s_String] := 
      StringReplace[s, RegularExpression["^\\s*(.*?)\\s*$"] -> "$1"];
     strip[e_] := e;
     If[Head[data] === String, 
      NotebookWrite[InputNotebook[], 
       ToBoxes@Map[strip, ImportString[data, "TSV"], {2}]]]]], 
   Button["CSV", 
    Module[{data, strip}, 
     data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]];
     strip[s_String] := 
      StringReplace[s, RegularExpression["^\\s*(.*?)\\s*$"] -> "$1"];
     strip[e_] := e;
     If[Head[data] === String, 
      NotebookWrite[InputNotebook[], 
       ToBoxes@Map[strip, ImportString[data, "CSV"], {2}]]]]], 
   Button["Table", 
    Module[{data}, data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]];
     If[Head[data] === String, 
      NotebookWrite[InputNotebook[], 
       ToBoxes@ImportString[data, "Table"]]]]]}

Ändern Sie externe Daten von innen Compile

Kürzlich hat Daniel Lichtblau diese Methode gezeigt, die ich noch nie gesehen hatte. Meiner Meinung nach erweitert es den Nutzen von erheblichCompile

ll = {2., 3., 4.};
c = Compile[{{x}, {y}}, ll[[1]] = x; y];

c[4.5, 5.6]

ll

(* Out[1] = 5.6  *)

(* Out[2] = {4.5, 3., 4.}  *)
Mr.Wizard
quelle
3
+1 Eine gute Sammlung! In Bezug auf die externen Änderungen von innen Compile- mein ganzer Beitrag hier: stackoverflow.com/questions/5246330/… - sollte diese Möglichkeit in einer nicht trivialen Umgebung demonstrieren (es gab bereits eine kürzere und schnellere Lösung für das fragliche Problem) . IMO, der größte Gewinn hierbei ist die Möglichkeit, Pass-by-Reference zu emulieren und große kompilierte Funktionen in besser verwaltbare und wiederverwendbare Blöcke zu unterteilen.
Leonid Shifrin
1
Sie können auch die Syntaxinformationen von Fold und FoldList in Ihrer neuen Definition anpassen: SyntaxInformation [Fold] = {"ArgumentsPattern" -> {_ , . , _}}; SyntaxInformation [FoldList] = {"ArgumentsPattern" -> {_, _., {_ }}};
Faysou
14

Allgemeine PDF / EMF-Exportprobleme und -lösungen

1) Es ist völlig unerwartet und nicht dokumentiert, aber Mathematica exportiert und speichert Grafiken in PDF- und EPS-Formaten unter Verwendung einer Reihe von Stildefinitionen, die sich von denen unterscheiden, die für die Anzeige von Notebooks auf dem Bildschirm verwendet werden. Standardmäßig werden Notebooks auf dem Bildschirm in der Stilumgebung "Arbeiten" angezeigt (dies ist der Standardwert für die ScreenStyleEvironmentglobale $FrontEndOption), sie werden jedoch in der "Printout"Stilumgebung gedruckt (dies ist der Standardwert für die PrintingStyleEnvironmentglobale $FrontEndOption). Wenn man Grafiken in Rasterformaten wie GIF und PNG oder im EMF-Format exportiert, generiert Mathematica Grafiken, die genau so aussehen, wie sie in Notebook aussehen. Es scheint, dass die"Working"In diesem Fall wird die Stilumgebung zum Rendern verwendet. Dies ist jedoch nicht der Fall, wenn Sie etwas im PDF- oder EPS-Format exportieren / speichern! In diesem Fall "Printout"wird standardmäßig die Stilumgebung verwendet , die sich stark von der Stilumgebung "Arbeiten" unterscheidet. Zunächst wird die "Printout"Stilumgebung Magnificationauf 80% festgelegt . Zweitens werden eigene Werte für die Schriftgrößen verschiedener Stile verwendet. Dies führt zu inkonsistenten Änderungen der Schriftgröße in der generierten PDF-Datei im Vergleich zur ursprünglichen Bildschirmdarstellung. Letzteres kann als FontSize-Schwankungen bezeichnet werden, die sehr ärgerlich sind. Glücklicherweise kann dies vermieden werden, indem die PrintingStyleEnvironmentglobale $FrontEndOption auf "Arbeiten" gesetzt wird :

SetOptions[$FrontEnd, PrintingStyleEnvironment -> "Working"]

2) Das häufigste Problem beim Exportieren in das EMF-Format besteht darin, dass die meisten Programme (nicht nur Mathematica ) eine Datei generieren, die in der Standardgröße gut aussieht, aber beim Vergrößern hässlich wird. Dies liegt daran, dass Metadateien mit der Genauigkeit der Bildschirmauflösung abgetastet werden . Die Qualität der generierten EMF-Datei kann verbessert werden, indem Magnifydas ursprüngliche grafische Objekt verwendet wird, sodass die Genauigkeit der Abtastung der ursprünglichen Grafiken viel präziser wird. Vergleichen Sie zwei Dateien:

graphics1 = 
  First@ImportString[
    ExportString[Style["a", FontFamily -> "Times"], "PDF"], "PDF"];
graphics2 = Magnify[graphics1, 10];
Export["C:\\test1.emf", graphics1]
Export["C:\\test2.emf", graphics2]

Wenn Sie diese Dateien in Microsoft Word einfügen und vergrößern, sehen Sie, dass das erste "a" einen Sägezahn aufweist, während das zweite nicht (getestet mit Mathematica 6).

Ein anderer Weg ImageResolutionwurde von Chris Degnen vorgeschlagen (diese Option wirkt sich zumindest ab Mathematica 8 aus):

Export["C:\\test1.emf", graphics1]
Export["C:\\test2.emf", graphics1, ImageResolution -> 300]

3) In Mathematica gibt es drei Möglichkeiten, Grafiken in Metadateien umzuwandeln: über Exportbis "EMF"(dringend empfohlen: Erzeugt Metadateien mit höchstmöglicher Qualität), über den Save selection As...Menüpunkt ( erzeugt eine viel weniger genaue Zahl , nicht empfohlen) und über den Edit ► Copy As ► MetafileMenüpunkt ( ich empfehle dringend gegen diese Route ).

Alexey Popkov
quelle
13

Auf vielfachen Wunsch wird der Code zum Generieren des Top-10-SO-Antwort-Plots (mit Ausnahme von Anmerkungen ) mithilfe der SO-API erstellt .

Geben Sie hier die Bildbeschreibung ein

getRepChanges[userID_Integer] :=
 Module[{totalChanges},
  totalChanges = 
   "total" /. 
    Import["http://api.stackoverflow.com/1.1/users/" <> 
      ToString[userID] <> "/reputation?fromdate=0&pagesize=10&page=1",
      "JSON"];
  Join @@ Table[
    "rep_changes" /. 
     Import["http://api.stackoverflow.com/1.1/users/" <> 
       ToString[userID] <> 
       "/reputation?fromdate=0&pagesize=10&page=" <> ToString[page], 
      "JSON"],
    {page, 1, Ceiling[totalChanges/10]}
    ]
  ]

topAnswerers = ({"display_name", 
      "user_id"} /. #) & /@ ("user" /. ("top_users" /. 
      Import["http://api.stackoverflow.com/1.1/tags/mathematica/top-\
answerers/all-time", "JSON"]))

repChangesTopUsers =
  Monitor[Table[
    repChange = 
     ReleaseHold[(Hold[{DateList[
              "on_date" + AbsoluteTime["January 1, 1970"]], 
             "positive_rep" - "negative_rep"}] /. #) & /@ 
        getRepChanges[userID]] // Sort;
    accRepChange = {repChange[[All, 1]], 
       Accumulate[repChange[[All, 2]]]}\[Transpose],
    {userID, topAnswerers[[All, 2]]}
    ], userID];

pl = DateListLogPlot[
  Tooltip @@@ 
   Take[({repChangesTopUsers, topAnswerers[[All, 1]]}\[Transpose]), 
    10], Joined -> True, Mesh -> None, ImageSize -> 1000, 
  PlotRange -> {All, {10, All}}, 
  BaseStyle -> {FontFamily -> "Arial-Bold", FontSize -> 16}, 
  DateTicksFormat -> {"MonthNameShort", " ", "Year"}, 
  GridLines -> {True, None}, 
  FrameLabel -> (Style[#, FontSize -> 18] & /@ {"Date", "Reputation", 
      "Top-10 answerers", ""})]
Sjoerd C. de Vries
quelle
1
Brett stellte eine Frage nach fast genau diesem Code. Vielleicht ist es dort am besten geeignet, mit ein oder zwei Anpassungen, um der Frage zu entsprechen. Ich wäre tatsächlich eine Wiederholung wert, im Gegensatz zu dieser Frage.
Rcollyer
@rcollyer ist richtig. Dies ist "Community Wiki"
Dr. belisarius
@ Belisarius Ich habe es gerade in der Antwort auf Bretts Frage kopiert ...
Sjoerd C. de Vries
@Sjoerd Dein Plot hier wird nicht automatisch aktualisiert.
Dr. Belisarius
@belisarius Eigentlich hatte ich gehofft, dass Sie diese Aufgabe übernehmen würden ... ;-)
Sjoerd C. de Vries
13

Caching-Ausdrücke

Ich finde diese Funktionen sehr hilfreich, um jeden Ausdruck zwischenzuspeichern. Das Interessante an diesen beiden Funktionen ist, dass der gehaltene Ausdruck selbst als Schlüssel für die Hashtabelle / das Symbol Cache oder CacheIndex verwendet wird, verglichen mit der bekannten Memoisierung in Mathematica, bei der Sie das Ergebnis nur zwischenspeichern können, wenn die Funktion wie f definiert ist [x_]: = f [x] = ... Sie können also jeden Teil eines Codes zwischenspeichern. Dies ist nützlich, wenn eine Funktion mehrmals aufgerufen werden soll, aber nur einige Teile des Codes nicht neu berechnet werden dürfen.

Um einen Ausdruck unabhängig von seinen Argumenten zwischenzuspeichern.

SetAttributes[Cache, HoldFirst];
c:Cache[expr_] := c = expr;

Ex: Cache[Pause[5]; 6]
Cache[Pause[5]; 6]

Beim zweiten Mal gibt der Ausdruck 6 zurück, ohne zu warten.

Zwischenspeichern eines Ausdrucks mithilfe eines Alias-Ausdrucks, der von einem Argument des zwischengespeicherten Ausdrucks abhängen kann.

SetAttributes[CacheIndex, HoldRest];
c:CacheIndex[index_,expr_] := c = expr;

Ex: CacheIndex[{"f",2},x=2;y=4;x+y]

Wenn die Berechnung von expr einige Zeit in Anspruch nimmt, ist es viel schneller, {"f", 2} auszuwerten, um beispielsweise das zwischengespeicherte Ergebnis abzurufen.

Eine Variation dieser Funktionen für einen lokalisierten Cache (dh der Cache-Speicher wird automatisch außerhalb des Blockkonstrukts freigegeben) finden Sie in diesem Beitrag. Vermeiden Sie wiederholte Aufrufe der Interpolation

Zwischengespeicherte Werte löschen

So löschen Sie zwischengespeicherte Werte, wenn Sie die Anzahl der Definitionen einer Funktion nicht kennen. Ich bin der Meinung, dass Definitionen irgendwo in ihren Argumenten ein Leerzeichen haben.

DeleteCachedValues[f_] := 
       DownValues[f] = Select[DownValues[f], !FreeQ[Hold@#,Pattern]&];

Löschen zwischengespeicherter Werte, wenn Sie die Anzahl der Definitionen einer Funktion kennen (geht etwas schneller).

DeleteCachedValues[f_,nrules_] := 
       DownValues[f] = Extract[DownValues[f], List /@ Range[-nrules, -1]];

Dies nutzt die Tatsache, dass Definitionen einer Funktion am Ende ihrer DownValues-Liste stehen und zwischengespeicherte Werte vor.

Verwenden von Symbolen zum Speichern von Daten und objektähnlichen Funktionen

Auch hier gibt es interessante Funktionen zur Verwendung von Symbolen wie Objekten.

Es ist bereits bekannt, dass Sie Daten in Symbolen speichern und mit DownValues ​​schnell darauf zugreifen können

mysymbol["property"]=2;

Sie können mit diesen Funktionen auf die Liste der Schlüssel (oder Eigenschaften) eines Symbols zugreifen, basierend auf den Dreeves, die in einem Beitrag auf dieser Site eingereicht wurden:

SetAttributes[RemoveHead, {HoldAll}];
RemoveHead[h_[args___]] := {args};
NKeys[symbol_] := RemoveHead @@@ DownValues[symbol(*,Sort->False*)][[All,1]];
Keys[symbol_] := NKeys[symbol] /. {x_} :> x;

Ich benutze diese Funktion häufig, um alle Informationen anzuzeigen, die in den DownValues ​​eines Symbols enthalten sind:

PrintSymbol[symbol_] :=
  Module[{symbolKeys},
    symbolKeys = Keys[symbol];
    TableForm@Transpose[{symbolKeys, symbol /@ symbolKeys}]
  ];

Schließlich gibt es hier eine einfache Möglichkeit, ein Symbol zu erstellen, das sich in der objektorientierten Programmierung wie ein Objekt verhält (es gibt nur das grundlegendste Verhalten von OOP wieder, aber ich finde die Syntax elegant):

Options[NewObject]={y->2};
NewObject[OptionsPattern[]]:=
  Module[{newObject},
    newObject["y"]=OptionValue[y];

    function[newObject,x_] ^:= newObject["y"]+x;
    newObject /: newObject.function2[x_] := 2 newObject["y"]+x;

    newObject
  ];

Eigenschaften werden als DownValues ​​und Methoden als verzögerte Upvalues ​​in dem von Module erstellten Symbol gespeichert, das zurückgegeben wird. Ich habe die Syntax für function2 gefunden, die die übliche OO-Syntax für Funktionen in der Tree-Datenstruktur in Mathematica ist .

Eine Liste der vorhandenen Wertetypen für jedes Symbol finden Sie unter http://reference.wolfram.com/mathematica/tutorial/PatternsAndTransformationRules.html und http://www.verbeia.com/mathematica/tips/HTMLLinks/Tricks_Misc_4.html .

Versuchen Sie dies zum Beispiel

x = NewObject[y -> 3];
function[x, 4]
x.function2[5]

Sie können weiter gehen , wenn Sie Objektvererbung mit einem Paket emulieren wollen genannt InheritRules hier http://library.wolfram.com/infocenter/MathSource/671/

Sie können die Funktionsdefinition auch nicht in newObject, sondern in einem Typensymbol speichern. Wenn NewObject also anstelle von newObject den Typ [newObject] zurückgibt, können Sie Funktion und Funktion2 außerhalb von NewObject (und nicht innerhalb) wie folgt definieren und dieselbe Verwendung wie zuvor verwenden .

function[type[object_], x_] ^:= object["y"] + x;
type /: type[object_].function2[x_] := 2 object["y"]+x;

Verwenden Sie UpValues ​​[Typ], um zu sehen, dass Funktion und Funktion2 im Typensymbol definiert sind.

Weitere Ideen zu dieser letzten Syntax finden Sie hier https://mathematica.stackexchange.com/a/999/66 .

Verbesserte Version von SelectEquivalents

@rcollyer: Vielen Dank, dass Sie SelectEquivalents an die Oberfläche gebracht haben. Es ist eine erstaunliche Funktion. Hier ist eine verbesserte Version von SelectEquivalents, die oben aufgeführt ist und mehr Möglichkeiten und Optionen bietet. Dies erleichtert die Verwendung.

Options[SelectEquivalents] = 
   {
      TagElement->Identity,
      TransformElement->Identity,
      TransformResults->(#2&) (*#1=tag,#2 list of elements corresponding to tag*),
      MapLevel->1,
      TagPattern->_,
      FinalFunction->Identity
   };

SelectEquivalents[x_List,OptionsPattern[]] := 
   With[
      {
         tagElement=OptionValue@TagElement,
         transformElement=OptionValue@TransformElement,
         transformResults=OptionValue@TransformResults,
         mapLevel=OptionValue@MapLevel,
         tagPattern=OptionValue@TagPattern,
         finalFunction=OptionValue@FinalFunction
      }
      ,
      finalFunction[
         Reap[
            Map[
               Sow[
                  transformElement@#
                  ,
                  {tagElement@#}
               ]&
               , 
               x
               , 
               {mapLevel}
            ] 
            , 
            tagPattern
            , 
            transformResults
         ][[2]]
      ]
   ];

Hier sind Beispiele, wie diese Version verwendet werden kann:

Verwenden von Mathematica Gather / Collect richtig

Wie würden Sie eine PivotTable-Funktion in Mathematica ausführen?

Mathematica schneller 2D-Binning-Algorithmus

Interne Tasche

Daniel Lichtblau beschreibt hier eine interessante interne Datenstruktur für wachsende Listen.

Implementierung eines Quadtree in Mathematica

Debugging-Funktionen

Diese beiden Beiträge verweisen auf nützliche Funktionen zum Debuggen:

Wie debugge ich beim Schreiben kleiner oder großer Codes mit Mathematica? Werkbank? mma debugger? oder etwas anderes? (Zeig es)

/programming/5459735/the-clearest-way-to-represent-mathematicas-evaluation-sequence/5527117#5527117 (TraceView)

Hier ist eine weitere Funktion, die auf Reap und Sow basiert, um Ausdrücke aus verschiedenen Teilen eines Programms zu extrahieren und in einem Symbol zu speichern.

SetAttributes[ReapTags,HoldFirst];
ReapTags[expr_]:=
   Module[{elements},
      Reap[expr,_,(elements[#1]=#2/.{x_}:>x)&];
      elements
   ];

Hier ist ein Beispiel

ftest[]:=((*some code*)Sow[1,"x"];(*some code*)Sow[2,"x"];(*some code*)Sow[3,"y"]);
s=ReapTags[ftest[]];
Keys[s]
s["x"]
PrintSymbol[s] (*Keys and PrintSymbol are defined above*)

Andere Ressourcen

Hier ist eine Liste interessanter Links für Lernzwecke:

Eine Sammlung von Mathematica-Lernressourcen

Hier aktualisiert: https://mathematica.stackexchange.com/a/259/66

faysou
quelle
Verwandte: " Der beste Weg, um eine Funktion mit Speicher zu konstruieren ". WReach hat dort ein erstaunliches Beispiel für eine einfache Funktion gegeben, die sich nicht nur ihre Werte merkt, sondern sie auch in eine Datei schreibt und beim Neustart rückwärts liest.
Alexey Popkov
1
Verwandte: " Mathematica: So löschen Sie den Cache für ein Symbol, dh nicht gesetzte musterfreie DownValues ". Diese Frage zeigt, wie der Cache mithilfe der Standardnotiz f[x_] := f[x] = some codegelöscht wird.
Simon
7
+1 Es gibt eine nette Notation, die es unnötig macht, die linke Seite der Definition in einer Caching-Funktion zu wiederholen, z c:Cache[expr_] := c = expr.
WReach
Schöne Variante von SelectEquivalents. Ich denke, ich würde TagOnElementals zweiten Parameter voreingestellt bleiben, Identityda er der am häufigsten verwendete ist. Ich glaube auch nicht, dass ich aufgenommen habe FinalOp, da es innerhalb behandelt werden kann OpOnTaggedElems. Ich würde auch die Optionsnamen kürzen, da ihre Länge das Tippen umständlich macht. Versuchen Sie TagFunction, TransformElement, TransformResults, und TagPatternstattdessen. Beides TagPatternund MapLevelsind großartige Ergänzungen der Funktionalität und insgesamt ein gutes Umschreiben.
Collyer
Vielen Dank für Ihren Kommentar rcollyer. Ich habe es berücksichtigt und auch die Lesbarkeit des Codes verbessert. Ich behalte FinalFunction, weil es mit dem Ergebnis von Reap arbeitet, zum Beispiel, wenn Sie Ihr Endergebnis nach Tags sortieren möchten, wenn Sie sie behalten.
Faysou
12

Meine Dienstprogrammfunktionen (ich habe diese in MASH integriert, was in der Frage erwähnt wird):

pr = WriteString["stdout", ##]&;            (* More                           *)
prn = pr[##, "\n"]&;                        (*  convenient                    *)
perr = WriteString["stderr", ##]&;          (*   print                        *)
perrn = perr[##, "\n"]&;                    (*    statements.                 *)
re = RegularExpression;                     (* I wish mathematica             *)
eval = ToExpression[cat[##]]&;              (*  weren't so damn               *)
EOF = EndOfFile;                            (*   verbose!                     *)
read[] := InputString[""];                  (* Grab a line from stdin.        *)
doList[f_, test_] :=                        (* Accumulate list of what f[]    *)
  Most@NestWhileList[f[]&, f[], test];      (*  returns while test is true.   *)
readList[] := doList[read, #=!=EOF&];       (* Slurp list'o'lines from stdin. *)
cat = StringJoin@@(ToString/@{##})&;        (* Like sprintf/strout in C/C++.  *)
system = Run@cat@##&;                       (* System call.                   *)
backtick = Import[cat["!", ##], "Text"]&;   (* System call; returns stdout.   *)
slurp = Import[#, "Text"]&;                 (* Fetch contents of file as str. *)
                                            (* ABOVE: mma-scripting related.  *)
keys[f_, i_:1] :=                           (* BELOW: general utilities.      *)
  DownValues[f, Sort->False][[All,1,1,i]];  (* Keys of a hash/dictionary.     *)
SetAttributes[each, HoldAll];               (* each[pattern, list, body]      *)
each[pat_, lst_, bod_] := ReleaseHold[      (*  converts pattern to body for  *)
  Hold[Cases[Evaluate@lst, pat:>bod];]];    (*   each element of list.        *)
some[f_, l_List] := True ===                (* Whether f applied to some      *)
  Scan[If[f[#], Return[True]]&, l];         (*  element of list is True.      *)
every[f_, l_List] := Null ===               (* Similarly, And @@ f/@l         *)
  Scan[If[!f[#], Return[False]]&, l];       (*  (but with lazy evaluation).   *)
träumt
quelle
11

Ein Trick, den ich verwendet habe, mit dem Sie die Art und Weise emulieren können, wie die meisten integrierten Funktionen mit schlechten Argumenten arbeiten (indem Sie eine Nachricht senden und dann das gesamte Formular ohne Bewertung zurückgeben), nutzt eine Eigenart der Funktionsweise aus, Conditionwenn sie in einer Definition verwendet werden. Wenn foosollte nur mit einem Argument arbeiten:

foo[x_] := x + 1;
expr : foo[___] /; (Message[foo::argx, foo, Length@Unevaluated[expr], 1]; 
                    False) := Null; (* never reached *)

Wenn Sie komplexere Anforderungen haben, können Sie die Argumentvalidierung und Nachrichtengenerierung leicht als unabhängige Funktion herausrechnen. Sie können aufwändigere Dinge tun, indem Sie Nebenwirkungen verwenden, die Conditionüber das Generieren von Nachrichten hinausgehen. Meiner Meinung nach fallen die meisten jedoch in die Kategorie "Sleazy Hack" und sollten nach Möglichkeit vermieden werden.

Wenn Sie in der Kategorie "Metaprogrammierung" eine Mathematica package ( .m) -Datei haben, können Sie das "HeldExpressions"Element verwenden , um alle Ausdrücke in der eingeschlossenen Datei abzurufen HoldComplete. Dies macht das Aufspüren viel einfacher als die Verwendung textbasierter Suchvorgänge. Leider gibt es keine einfache Möglichkeit, dasselbe mit einem Notebook zu tun, aber Sie können alle Eingabeausdrücke wie folgt abrufen:

inputExpressionsFromNotebookFile[nb_String] :=
 Cases[Get[nb],
  Cell[BoxData[boxes_], "Input", ___] :>
   MakeExpression[StripBoxes[boxes], StandardForm],
  Infinity]

Zuletzt können Sie die Tatsache verwenden, dass Modulelexikalische Abschlüsse emuliert werden, um das Äquivalent von Referenztypen zu erstellen. Hier ist ein einfacher Stapel (der Conditionals Bonus eine Variation des Tricks zur Fehlerbehandlung verwendet):

ClearAll[MakeStack, StackInstance, EmptyQ, Pop, Push, Peek]
 With[{emptyStack = Unique["empty"]},
  Attributes[StackInstance] = HoldFirst;
  MakeStack[] :=
   Module[{backing = emptyStack},
    StackInstance[backing]];

  StackInstance::empty = "stack is empty";

  EmptyQ[StackInstance[backing_]] := (backing === emptyStack);

  HoldPattern[
    Pop[instance : StackInstance[backing_]]] /;
    ! EmptyQ[instance] || (Message[StackInstance::empty]; False) :=
   (backing = Last@backing; instance);

  HoldPattern[Push[instance : StackInstance[backing_], new_]] :=
   (backing = {new, backing}; instance);

  HoldPattern[Peek[instance : StackInstance[backing_]]] /;
    ! EmptyQ[instance] || (Message[StackInstance::empty]; False) :=
   First@backing]

Jetzt können Sie die Elemente einer Liste in umgekehrter Reihenfolge unnötig verschlungen drucken!

With[{stack = MakeStack[], list},
 Do[Push[stack, elt], {elt, list}];

 While[!EmptyQ[stack],
  Print[Peek@stack];
  Pop@stack]]
Pillsy
quelle
1
+1 für HeldExpressionsElement in Paketen, war sich dessen nicht bewusst. Normalerweise habe ich als String importiert und dann ToExpressionmit HoldCompleteals letztes Argument verwendet. In Bezug auf die Verwendung Conditionfür Nachrichten - dies ist seit mindestens 1994 eine Standardtechnik beim Schreiben von Paketen. In Bezug auf die Persistenz durch ModuleVars - habe ich vor einiger Zeit einen langen Beitrag dazu in Mathgroup verfasst: groups.google.com/group/comp.soft- sys.math.mathematica /… (mein dritter Beitrag in diesem Thread), dies ist in die gleiche Richtung und enthält Links zu einigen nicht trivialen Anwendungsbeispielen.
Leonid Shifrin
@Leonid Shifrin: Ich habe das ConditionDing als Überlieferung aufgegriffen , wahrscheinlich von einem Kollegen, aber nicht bemerkt , dass es eine Standardtechnik ist. Der Link zur Verwendung von ModuleSymbolen als Referenztypen ist interessant!
Pillsy
+1, daran habe ich nie gedacht. Je mehr ich über diese Sprache lerne, desto mächtiger scheint sie zu sein.
Collyer
@Pillsy was ist der Zweck, einen Stapel auf diese Weise zu machen?
Mr.Wizard
@ Mr.Wizard: Ich habe gerade eine der einfachsten veränderlichen Datenstrukturen ausgewählt, die ich mir vorstellen kann, um die Technik zu veranschaulichen.
Pillsy
11

Drucksystem-Symboldefinitionen ohne vorangestellten Kontext

Die folgende contextFreeDefinition[]Funktion versucht, die Definition eines Symbols ohne den häufigsten vorangestellten Kontext zu drucken. Die Definition kann dann in die Workbench kopiert und zur besseren Lesbarkeit formatiert werden (auswählen, Rechtsklick, Quelle -> Format)

Clear[commonestContexts, contextFreeDefinition]

commonestContexts[sym_Symbol, n_: 1] := Quiet[
  Commonest[
   Cases[Level[DownValues[sym], {-1}, HoldComplete], 
    s_Symbol /; FreeQ[$ContextPath, Context[s]] :> Context[s]], n],
  Commonest::dstlms]

contextFreeDefinition::contexts = "Not showing the following contexts: `1`";

contextFreeDefinition[sym_Symbol, contexts_List] := 
 (If[contexts =!= {}, Message[contextFreeDefinition::contexts, contexts]];
  Internal`InheritedBlock[{sym}, ClearAttributes[sym, ReadProtected];
   Block[{$ContextPath = Join[$ContextPath, contexts]}, 
    Print@InputForm[FullDefinition[sym]]]])

contextFreeDefinition[sym_Symbol, context_String] := 
 contextFreeDefinition[sym, {context}]

contextFreeDefinition[sym_Symbol] := 
 contextFreeDefinition[sym, commonestContexts[sym]]

withRules []

Vorsichtsmaßnahme: Diese Funktion lokalisiert Variablen nicht auf die gleiche Weise Withund Moduletut dies auch. Dies bedeutet, dass verschachtelte Lokalisierungskonstrukte nicht wie erwartet funktionieren. withRules[{a -> 1, b -> 2}, With[{a=3}, b_ :> b]] wird ersetzen aund bin der verschachtelten Withund Rule, während Withdies nicht tut.

Dies ist eine Variante With, die Regeln anstelle von =und verwendet :=:

ClearAll[withRules]
SetAttributes[withRules, HoldAll]
withRules[rules_, expr_] :=
  Internal`InheritedBlock[
    {Rule, RuleDelayed},
    SetAttributes[{Rule, RuleDelayed}, HoldFirst];
    Unevaluated[expr] /. rules
  ]

Ich fand dies nützlich, wenn ich Code bereinigte, der während des Experimentierens geschrieben wurde, und Variablen lokalisierte. Gelegentlich erhalte ich Parameterlisten in Form von {par1 -> 1.1, par2 -> 2.2}. Mit withRulesParameter können Werte einfach in Code eingefügt werden, der zuvor mit globalen Variablen geschrieben wurde.

Die Verwendung ist wie folgt With:

withRules[
  {a -> 1, b -> 2},
  a+b
]

Antialiasing 3D-Grafiken

Dies ist eine sehr einfache Technik für Antialias-3D-Grafiken, auch wenn Ihre Grafikhardware dies nicht nativ unterstützt.

antialias[g_, n_: 3] := 
  ImageResize[Rasterize[g, "Image", ImageResolution -> n 72], Scaled[1/n]]

Hier ist ein Beispiel:

Mathematica-Grafiken Mathematica-Grafiken

Beachten Sie, dass ein großer Wert für noder eine große Bildgröße dazu neigt, Grafik-Treiberfehler aufzudecken oder Artefakte einzuführen.


Notebook Diff-Funktionalität

Die Notebook-Diff-Funktionalität ist im <<AuthorTools`Paket und (zumindest in Version 8) im undokumentierten NotebookTools`Kontext verfügbar . Dies ist eine kleine Benutzeroberfläche, um zwei derzeit geöffnete Notebooks zu unterscheiden:

PaletteNotebook@DynamicModule[
  {nb1, nb2}, 
  Dynamic@Column[
    {PopupMenu[Dynamic[nb1], 
      Thread[Notebooks[] -> NotebookTools`NotebookName /@ Notebooks[]]], 
     PopupMenu[Dynamic[nb2], 
      Thread[Notebooks[] -> NotebookTools`NotebookName /@ Notebooks[]]], 
     Button["Show differences", 
      CreateDocument@NotebookTools`NotebookDiff[nb1, nb2]]}]
  ]

Mathematica-Grafiken

Szabolcs
quelle
Alles wäre schön, aber dies lokalisiert Variablen nicht wirklich , wie Sie sehen können, indem Sie say a = 3; b = 4;vor Ihrem Beispielaufruf zuweisen und dann aufrufen withRules. Sie können es speichern, indem Sie stattdessen Folgendes verwenden : SetAttributes[withRules, HoldAll];withRules[rules_, expr_] := Unevaluated[expr] /. Unevaluated[rules]. Die Unterschiede in Bezug auf die Semantik von Withdamals: 1. Die Seiten von Regeln werden jetzt nicht ausgewertet. 2. Löst withRulesdie Namenskonflikte mit Konstrukten mit innerem Gültigkeitsbereich nicht wie Withfolgt auf. Der letzte ist ziemlich ernst - je nach Fall gut oder schlecht.
Leonid Shifrin
@Leonid Sie haben völlig Recht, anscheinend habe ich nie gelernt, den Code vor dem Posten richtig zu überprüfen. Wenn ich dies verwende, ordne ich den Variablen praktisch nie Werte zu, aber das ist ein ziemlich ernstes Problem, Sie haben Recht. Was denkst du über die korrigierte Version? (Es ist mir eigentlich egal, Withob verschachtelte s nicht behandelt werden . Dies funktioniert auch nicht immer mit den eingebauten Lokalisierungskonstrukten, z With[{a=1}, Block[{a=2}, a]]. B. Glauben Sie, dass es einen guten Grund gibt, warum die verschachtelten Blocknicht dort lokalisiert sind, wie verschachtelt Withund Module?)
Szabolcs
@Leonid habe ich nicht einfach benutzt, Unevaluated[rules]weil ich x -> 1+1die RHS auswerten wollte .
Szabolcs
@Leonid Sie haben tatsächlich Recht, das Problem der verschachtelten Lokalisierung kann sehr schwerwiegend sein. Ich denke, verschachtelte Withs sind leicht zu erkennen und zu vermeiden, Muster jedoch nicht: With[{a = 1}, a_ -> a]Lokalisiert das Innere, awährend withRulesdies nicht der Fall ist. Wissen Sie, ob es eine Möglichkeit gibt, auf den internen Lokalisierungsmechanismus von Mathematica zuzugreifen und neue Konstrukte (ähnlich Rule) zu erstellen, die ebenfalls lokalisieren? Ich werde diese Antwort wahrscheinlich später löschen, da sie eher gefährlich als nützlich ist, aber ich würde gerne zuerst ein bisschen mehr damit spielen.
Szabolcs
Ich finde deine Verwendung InheritedBlockziemlich cool und löst das Problem sehr elegant. Bei den Scoping-Konflikten treten normalerweise Bindungen für das lexikalische Scoping zur "lexikalischen Bindungszeit" auf, dh vor der Laufzeit, während das dynamische Scoping zur Laufzeit gebunden wird, was dies möglicherweise erklärt. Sie können dies dem ähnlichen Fall für gegenüberstellen Module, der eine konstruktive Verwendung ermöglicht (siehe z . B. hier stackoverflow.com/questions/7394113/… ). Das Problem ist, dass Blockein Symbol benötigt wird, um ...
Leonid Shifrin
9

Rekursive reine Funktionen ( #0) scheinen eine der dunkleren Ecken der Sprache zu sein. Hier sind einige nicht triviale Beispiele für ihre Verwendung, bei denen dies wirklich nützlich ist (nicht, dass sie ohne sie nicht möglich sind). Das Folgende ist eine ziemlich präzise und relativ schnelle Funktion, um verbundene Komponenten in einem Diagramm zu finden, wenn eine Liste von Kanten als Eckpunktpaare angegeben wird:

ClearAll[setNew, componentsBFLS];
setNew[x_, x_] := Null;
setNew[lhs_, rhs_]:=lhs:=Function[Null, (#1 := #0[##]); #2, HoldFirst][lhs, rhs];

componentsBFLS[lst_List] := Module[{f}, setNew @@@ Map[f, lst, {2}];
   GatherBy[Tally[Flatten@lst][[All, 1]], f]];

Was hier passiert, ist, dass wir zuerst ein Dummy-Symbol auf jede der Scheitelpunktnummern abbilden und dann einen Weg einrichten, der bei einem gegebenen Scheitelpunktpaar {f[5],f[10]}dann f[5]ausgewertet wird f[10]. Die rekursive reine Funktion wird als Pfadkompressor verwendet (um die Memoisierung so einzurichten, dass f[1]=f[3],f[3]=f[4],f[4]=f[2], ...gespeicherte Werte anstelle von langen Ketten korrigiert werden, wenn eine neue "Wurzel" der Komponente entdeckt wird. Dies führt zu einer erheblichen Beschleunigung. Da wir Zuweisungen verwenden, muss es HoldAll sein, was dieses Konstrukt noch dunkler und attraktiver macht. Diese Funktion ist das Ergebnis einer Online- und Offline-Diskussion in der Mathgroup, an der Fred Simons, Szabolcs Horvat, DrMajorBob und Ihre Mitarbeiter beteiligt sind. Beispiel:

In[13]:= largeTest=RandomInteger[{1,80000},{40000,2}];

In[14]:= componentsBFLS[largeTest]//Short//Timing
Out[14]= {0.828,{{33686,62711,64315,11760,35384,45604,10212,52552,63986,  
     <<8>>,40962,7294,63002,38018,46533,26503,43515,73143,5932},<<10522>>}}

Es ist sicherlich viel langsamer als ein eingebautes, aber für die Größe des Codes ziemlich schnell noch IMO.

Ein weiteres Beispiel: Hier ist eine rekursive Realisierung von Select, basierend auf verknüpften Listen und rekursiven reinen Funktionen:

selLLNaive[x_List, test_] :=
  Flatten[If[TrueQ[test[#1]],
     {#1, If[#2 === {}, {}, #0 @@ #2]},
     If[#2 === {}, {}, #0 @@ #2]] & @@ Fold[{#2, #1} &, {}, Reverse[x]]];

Beispielsweise,

In[5]:= Block[
         {$RecursionLimit= Infinity},
         selLLNaive[Range[3000],EvenQ]]//Short//Timing

Out[5]= {0.047,{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,
 <<1470>>,2972,2974,2976,2978,2980,2982,2984,2986,2988,2990,
  2992,2994,2996,2998,3000}}

Es ist jedoch nicht richtig rekursiv und wird den Stapel für größere Listen sprengen (den Kernel zum Absturz bringen). Hier ist die schwanzrekursive Version:

selLLTailRec[x_List, test_] :=
Flatten[
 If[Last[#1] === {},
  If[TrueQ[test[First[#1]]],
   {#2, First[#1]}, #2],
  (* else *)
  #0[Last[#1],
   If[TrueQ[test[First[#1]]], {#2, First[#1]}, #2]
   ]] &[Fold[{#2, #1} &, {}, Reverse[x]], {}]];

Beispielsweise,

In[6]:= Block[{$IterationLimit= Infinity},
       selLLTailRec[Range[500000],EvenQ]]//Short//Timing
Out[6]= {2.39,{2,4,6,8,10,12,14,16,18,20,22,
       <<249978>>,499980,499982,499984,499986,499988,499990,499992,
        499994,499996,499998,500000}} 
Leonid Shifrin
quelle
Die Funktion für angeschlossene Komponenten ist immer noch ein Favorit von mir :-)
Szabolcs
@Szabolcs Ja, es ist ziemlich cool. Sie und Fred haben das meiste getan, Bobby und ich haben nur ein paar Verfeinerungen hinzugefügt, IIRC.
Leonid Shifrin
8

Dies ist ein Rezept aus Stan Wagons Buch ... verwenden Sie es, wenn sich das eingebaute Diagramm aufgrund mangelnder Präzision unregelmäßig verhält

Options[PrecisePlot] = {PrecisionGoal -> 6};
PrecisePlot[f_, {x_, a_, b_}, opts___] := Module[{g, pg},
   pg = PrecisionGoal /. {opts} /. Options[PrecisePlot];
   SetAttributes[g, NumericFunction];
   g[z_?InexactNumberQ] := Evaluate[f /. x -> z];
   Plot[N[g[SetPrecision[y, \[Infinity]]], pg], {y, a, b},
    Evaluate[Sequence @@ FilterRules[{opts}, Options[Plot]]]]];

Ich verwende oft den folgenden Trick von Kristjan Kannike, wenn ich ein "wörterbuchartiges" Verhalten von Mathematicas Abwärtswerten benötige

index[downvalue_, 
   dict_] := (downvalue[[1]] /. HoldPattern[dict[x_]] -> x) // 
   ReleaseHold;
value[downvalue_] := downvalue[[-1]];
indices[dict_] := 
  Map[#[[1]] /. {HoldPattern[dict[x_]] -> x} &, DownValues[dict]] // 
   ReleaseHold;
values[dict_] := Map[#[[-1]] &, DownValues[dict]];
items[dict_] := Map[{index[#, dict], value[#]} &, DownValues[dict]];
indexQ[dict_, index_] := 
  If[MatchQ[dict[index], HoldPattern[dict[index]]], False, True];

(* Usage example: *)
(* Count number of times each subexpression occurs in an expression *)
expr = Cos[x + Cos[Cos[x] + Sin[x]]] + Cos[Cos[x] + Sin[x]]
Map[(counts[#] = If[indexQ[counts, #], counts[#] + 1, 1]; #) &, expr, Infinity];
items[counts]

Wenn die Bewertungsergebnisse verwirrend sind, ist es manchmal hilfreich, Bewertungsschritte in eine Textdatei zu kopieren

SetAttributes[recordSteps, HoldAll];
recordSteps[expr_] :=
 Block[{$Output = List@OpenWrite["~/temp/msgStream.m"]}, 
  TracePrint[Unevaluated[expr], _?(FreeQ[#, Off] &), 
   TraceInternal -> True];
  Close /@ $Output;
  Thread[Union@
    Cases[ReadList["~/temp/msgStream.m", HoldComplete[Expression]], 
     symb_Symbol /; 
       AtomQ@Unevaluated@symb && 
        Context@Unevaluated@symb === "System`" :> 
      HoldComplete@symb, {0, Infinity}, Heads -> True], HoldComplete]
  ]

(* Usage example: *)
(* puts steps of evaluation of 1+2+Sin[5]) into ~/temp/msgStream.m *)
recordSteps[1+2+Sin[5]]
Jaroslaw Bulatow
quelle
Ein Verwendungsbeispiel wäre toll. Versuchen Sie, eine zu posten, wenn Sie Zeit haben.
Dr. Belisarius
Kennst du Kristjan? Ich habe mit ihm in derselben Gruppe in Helsinki gearbeitet. Netter Kerl, kleine Welt.
Timo
Nein, fand seinen Code im Web. Eigentlich habe ich versucht, ihm eine E-Mail zu schicken, um einen kleinen Fehler im Code zu beheben, aber die E-Mail auf seiner Webseite funktioniert nicht mehr
Yaroslav Bulatov
8

Es ist möglich, MathKernel im Batch-Modus auszuführen, indem Sie undokumentierte Befehlszeilenoptionen verwenden -batchinputund-batchoutput :

math -batchinput -batchoutput < input.m > outputfile.txt

(Wo input.mist die Batch-Eingabedatei, die mit dem Zeilenumbruchzeichen endet, outputfile.txtist die Datei, in die die Ausgabe umgeleitet wird).

In Mathematica v.> = 6 verfügt der MathKernel über eine undokumentierte Befehlszeilenoption:

-noicon

Hiermit wird gesteuert, ob der MathKernel ein sichtbares Symbol in der Taskleiste hat (zumindest unter Windows).

Das FrontEnd (zumindest ab Version 5) verfügt über eine undokumentierte Befehlszeilenoption

-b

Dadurch wird der Begrüßungsbildschirm deaktiviert und das Mathematica FrontEnd kann viel schneller ausgeführt werden

und Option

-directlaunch

die deaktiviert den Mechanismus, startet die jüngste Mathematica - Version installiert statt startet die Version , die mit .nb Dateien in der Systemregistrierung.

Ein anderer Weg , dies wahrscheinlich zu tun ist :

Anstatt die Binärdatei Mathematica.exe im Installationsverzeichnis zu starten, starten Sie die Binärdatei Mathematica.exe unter SystemFiles \ FrontEnd \ Binaries \ Windows. Ersteres ist ein einfaches Startprogramm, das sich nach Kräften bemüht, Anforderungen zum Öffnen von Notizbüchern auf das Ausführen von Kopien der Benutzeroberfläche umzuleiten. Letzteres ist die Binärdatei der Benutzeroberfläche.

Es ist praktisch, die letzte Befehlszeilenoption mit der Einstellung der globalen FrontEnd-Option zu kombinieren, VersionedPreferences->True die das Teilen von Einstellungen zwischen verschiedenen installierten Mathematica- Versionen deaktiviert :

SetOptions[$FrontEnd, VersionedPreferences -> True]

(Das Obige sollte in der neuesten installierten Mathematica- Version ausgewertet werden .)

In Mathematica 8 wird dies im Dialogfeld "Einstellungen" im Bereich "System" unter der Einstellung "Versionsspezifische Front-End-Einstellungen erstellen und verwalten" gesteuert .

Es ist möglich, eine unvollständige Liste der Befehlszeilenoptionen des FrontEnd zu erhalten, indem Sie einen undokumentierten Schlüssel -h(den Code für Windows) verwenden:

SetDirectory[$InstallationDirectory <> 
   "\\SystemFiles\\FrontEnd\\Binaries\\Windows\\"];
Import["!Mathematica -h", "Text"]

gibt:

Usage:  Mathematica [options] [files]
Valid options:
    -h (--help):  prints help message
    -cleanStart (--cleanStart):  removes existing preferences upon startup
    -clean (--clean):  removes existing preferences upon startup
    -nogui (--nogui):  starts in a mode which is initially hidden
    -server (--server):  starts in a mode which disables user interaction
    -activate (--activate):  makes application frontmost upon startup
    -topDirectory (--topDirectory):  specifies the directory to search for resources and initialization files
    -preferencesDirectory (--preferencesDirectory):  specifies the directory to search for user AddOns and preference files
    -password (--password):  specifies the password contents
    -pwfile (--pwfile):  specifies the path for the password file
    -pwpath (--pwpath):  specifies the directory to search for the password file
    -b (--b):  launches without the splash screen
    -min (--min):  launches as minimized

Weitere Optionen sind:

-directLaunch:  force this FE to start
-32:  force the 32-bit FE to start
-matchingkernel:  sets the frontend to use the kernel of matching bitness
-Embedding:  specifies that this instance is being used to host content out of process

Gibt es andere potenziell nützliche Befehlszeilenoptionen für MathKernel und FrontEnd? Bitte teilen Sie, wenn Sie wissen.

Verwandte Frage .

Alexey Popkov
quelle
"passende Bissigkeit?" Was bedeutet das?
Mr.Wizard
@ Mr.Wizard Wahrscheinlich hat diese Option nur unter 64-Bit-Systemen in Kombination mit der Option einen Sinn -32und bedeutet, dass die Bittigkeit des vom FrontEnd verwendeten MathKernels mit der Bitterkeit des Betriebssystems (64-Bit) übereinstimmt. In anderen Fällen scheint diese Option nichts zu ändern.
Alexey Popkov
7

Meine Lieblings-Hacks sind kleine Code-generierende Makros, mit denen Sie eine Reihe von Standard-Boilerplate-Befehlen durch einen kurzen ersetzen können. Alternativ können Sie Befehle zum Öffnen / Erstellen von Notizbüchern erstellen.

Folgendes verwende ich seit einiger Zeit in meinem täglichen Mathematica-Workflow. Ich habe Folgendes oft ausgeführt:

  1. Stellen Sie sicher, dass ein Notizbuch einen privaten Kontext hat, laden Sie die benötigten Pakete und speichern Sie sie automatisch.
  2. Nachdem ich eine Weile mit diesem Notizbuch gearbeitet habe, möchte ich einige Scratch-Berechnungen in einem separaten Notizbuch mit eigenem privaten Kontext durchführen und gleichzeitig auf Definitionen zugreifen, die ich im "Haupt" -Notizbuch verwendet habe. Da ich den privaten Kontext eingerichtet habe, muss $ ContextPath manuell angepasst werden

All dies immer und immer wieder von Hand zu tun, ist ein Schmerz, also lasst uns automatisieren! Zunächst ein Dienstprogrammcode:

(* Credit goes to Sasha for SelfDestruct[] *)
SetAttributes[SelfDestruct, HoldAllComplete];
SelfDestruct[e_] := (If[$FrontEnd =!= $Failed,
   SelectionMove[EvaluationNotebook[], All, EvaluationCell]; 
   NotebookDelete[]]; e)

writeAndEval[nb_,boxExpr_]:=(
    NotebookWrite[nb,  CellGroupData[{Cell[BoxData[boxExpr],"Input"]}]];
    SelectionMove[nb, Previous, Cell]; 
    SelectionMove[nb, Next, Cell];
    SelectionEvaluate[nb];
)

ExposeContexts::badargs = 
  "Exposed contexts should be given as a list of strings.";
ExposeContexts[list___] := 
 Module[{ctList}, ctList = Flatten@List@list; 
  If[! MemberQ[ctList, Except[_String]],AppendTo[$ContextPath, #] & /@ ctList, 
   Message[ExposeContexts::badargs]];
  $ContextPath = DeleteDuplicates[$ContextPath];
  $ContextPath]

    Autosave[x:(True|False)] := SetOptions[EvaluationNotebook[],NotebookAutoSave->x];

Erstellen wir nun ein Makro, das die folgenden Zellen in das Notizbuch einfügt:

SetOptions[EvaluationNotebook[], CellContext -> Notebook]
Needs["LVAutils`"]
Autosave[True]

Und hier ist das Makro:

MyPrivatize[exposedCtxts : ({__String} | Null) : Null]:=
  SelfDestruct@Module[{contBox,lvaBox,expCtxtBox,assembledStatements,strList},
    contBox = MakeBoxes[SetOptions[EvaluationNotebook[], CellContext -> Notebook]];
    lvaBox = MakeBoxes[Needs["LVAutils`"]];

    assembledStatements = {lvaBox,MakeBoxes[Autosave[True]],"(*********)"};
    assembledStatements = Riffle[assembledStatements,"\[IndentingNewLine]"]//RowBox;
    writeAndEval[InputNotebook[],contBox];
    writeAndEval[InputNotebook[],assembledStatements];
    If[exposedCtxts =!= Null,
       strList = Riffle[("\"" <> # <> "\"") & /@ exposedCtxts, ","];
       expCtxtBox = RowBox[{"ExposeContexts", "[", RowBox[{"{", RowBox[strList], "}"}], "]"}];
       writeAndEval[InputNotebook[],expCtxtBox];
      ]
 ]

Wenn ich jetzt MyPrivatize[]tippe, wird der private Kontext erstellt und mein Standardpaket geladen. Jetzt erstellen wir einen Befehl, der ein neues Notizbuch mit einem eigenen privaten Kontext öffnet (damit Sie dort mit wilder Hingabe hacken können, ohne die Definitionen zu verfälschen), aber Zugriff auf Ihre aktuellen Kontexte hat.

SpawnScratch[] := SelfDestruct@Module[{nb,boxExpr,strList},
    strList = Riffle[("\"" <> # <> "\"") & /@ $ContextPath, ","];
    boxExpr = RowBox[{"MyPrivatize", "[",
        RowBox[{"{", RowBox[strList], "}"}], "]"}];
    nb = CreateDocument[];
    writeAndEval[nb,boxExpr];
]

Das Coole daran ist, dass SelfDestructder Befehl beim Ausführen keine Spuren im aktuellen Notizbuch hinterlässt - was gut ist, da es sonst nur zu Unordnung kommen würde.

Für zusätzliche Stilpunkte können Sie Keyword-Trigger für diese Makros erstellen InputAutoReplacements, aber ich überlasse dies dem Leser als Übung.

Leo Alekseyev
quelle
7

PutAppend mit PageWidth -> Infinity

In Mathematica ist die Verwendung des PutAppendBefehls die einfachste Möglichkeit, eine laufende Protokolldatei mit Ergebnissen von Zwischenberechnungen zu verwalten. Die Standardeinstellung wird jedoch PageWith->78beim Exportieren von Ausdrücken in eine Datei verwendet. Daher kann nicht garantiert werden, dass jede Zwischenausgabe nur eine Zeile im Protokoll enthält.

PutAppendhat selbst keine Optionen, aber die Verfolgung seiner Auswertungen zeigt, dass es auf der OpenAppendFunktion basiert, die über die PageWithOption verfügt, und ermöglicht, den Standardwert durch den folgenden SetOptionsBefehl zu ändern :

In[2]:= Trace[x>>>"log.txt",TraceInternal->True]
Out[2]= {x>>>log.txt,{OpenAppend[log.txt,CharacterEncoding->PrintableASCII],OutputStream[log.txt,15]},Null}

So können wir immer PutAppendnur eine Zeile anhängen, indem wir Folgendes einstellen:

SetOptions[OpenAppend, PageWidth -> Infinity]

AKTUALISIEREN

In Version 10 wurde ein Fehler eingeführt (in Version 11.3 behoben): SetOptionsDas Verhalten von OpenWriteund wird nicht mehr beeinflusst OpenAppend.

Eine Problemumgehung besteht darin, eine eigene Version von PutAppendmit expliziter PageWidth -> InfinityOption zu implementieren :

Clear[myPutAppend]
myPutAppend[expr_, pathtofile_String] :=
 (Write[#, expr]; Close[#];) &[OpenAppend[pathtofile, PageWidth -> Infinity]]

Beachten Sie, dass wir es auch WriteStringwie in dieser Antwort gezeigt implementieren können. In diesem Fall ist es jedoch erforderlich, den Ausdruck vorab in das entsprechende InputFormVia umzuwandeln ToString[expr, InputForm].

Alexey Popkov
quelle
6

Ich habe gerade eines meiner Pakete nach Aufnahme durchsucht und einige von mir definierte Nachrichten gefunden, die Wunder wirken : Debug::<some name>. Standardmäßig sind sie deaktiviert, daher entsteht kein großer Overhead. Aber ich kann meinen Code mit ihnen verunreinigen und sie einschalten, wenn ich genau herausfinden muss, wie sich ein bisschen Code verhält.

rcollyer
quelle
Aus der Hilfe> Seit Version 2.0 (veröffentlicht 1991) wurde Debug von Trace abgelöst.
Dr. Belisarius
1
@ Belisarius, du hast den Punkt verpasst. Es ist weder das Debugnoch TraceFunktionen; Es handelt sich um eine Reihe von Nachrichten, mit denen ich meinen Code verunreinigen kann, um sie nach Belieben ein- und auszuschalten. Ihnen wird das Wort vorangestellt Debug, genauso wie einer usageNachricht der Name der Funktion vorangestellt wird. Es bietet die gleiche Funktionalität wie das Platzieren einer Reihe von coutAnweisungen in C ++ - Code.
Rcollyer
1
Oh Entschuldigung. Ich war verwirrt, weil ich nie den Kindergarten abgeschlossen habe, weil ich nicht gelernt habe "Hauptstädte sind für Länder": D
Dr. belisarius
6

Eines der Dinge, die mich an den integrierten Scoping-Konstrukten stören, ist, dass sie alle lokalen Variablendefinitionen gleichzeitig auswerten, sodass Sie beispielsweise nicht schreiben können

With[{a = 5, b = 2 * a},
    ...
]

Vor einiger Zeit habe ich mir ein Makro namens WithNest ausgedacht, mit dem Sie dies tun können. Ich finde es praktisch, da Sie damit variable Bindungen lokal halten können, ohne etwas Ähnliches tun zu müssen

Module[{a = 5,b},
    b = 2 * a;
    ...
]

Am Ende war der beste Weg, dies zu tun, die Verwendung eines speziellen Symbols, um das Durchblättern der Liste der Bindungen zu erleichtern, und ich habe die Definition in ein eigenes Paket eingefügt, um dieses Symbol verborgen zu halten. Vielleicht hat jemand eine einfachere Lösung für dieses Problem?

Wenn Sie es ausprobieren möchten, fügen Sie Folgendes in eine Datei mit dem Namen ein Scoping.m:

BeginPackage["Scoping`"];

WithNest::usage=
"WithNest[{var1=val1,var2=val2,...},body] works just like With, except that
values are evaluated in order and later values have access to earlier ones.
For example, val2 can use var1 in its definition.";

Begin["`Private`"];

(* Set up a custom symbol that works just like Hold. *)
SetAttributes[WithNestHold,HoldAll];

(* The user-facing call.  Give a list of bindings and a body that's not
our custom symbol, and we start a recursive call by using the custom
symbol. *)
WithNest[bindings_List,body:Except[_WithNestHold]]:=
WithNest[bindings,WithNestHold[body]];

(* Base case of recursive definition *)
WithNest[{},WithNestHold[body_]]:=body;

WithNest[{bindings___,a_},WithNestHold[body_]]:=
WithNest[
{bindings},
WithNestHold[With[List@a,body]]];

SyntaxInformation[WithNest]={"ArgumentsPattern"->{{__},_}};
SetAttributes[WithNest,{HoldAll,Protected}];

End[];

EndPackage[];
DGrady
quelle
Janus hat eine Version davon gepostet und verweist auf Ihre Frage in MathGroup: stackoverflow.com/questions/4190845/custom-notation-question/…
Mr.Wizard
Vielen Dank für den Hinweis! Es ist schon eine Weile her, dass ich mir dieses Zeug angesehen habe, und es ist interessant, all diese anderen Ansätze zu sehen.
DGrady
5

Dieser wurde von Alberto Di Lullo geschrieben (der nicht auf Stack Overflow zu sein scheint).

CopyToClipboard, für Mathematica 7 (in Mathematica 8 ist es eingebaut)

CopyToClipboard[expr_] := 
  Module[{nb}, 
   nb = CreateDocument[Null, Visible -> False, WindowSelected -> True];
   NotebookWrite[nb, Cell[OutputFormData@expr], All];
   FrontEndExecute[FrontEndToken[nb, "Copy"]];
   NotebookClose@nb];

Ursprünglicher Beitrag: http://forums.wolfram.com/mathgroup/archive/2010/Jun/msg00148.html

Ich habe diese Routine nützlich gefunden, um große reelle Zahlen in gewöhnlicher Dezimalform in die Zwischenablage zu kopieren. Z.BCopyToClipboard["123456789.12345"]

Cell[OutputFormData@expr] entfernt ordentlich die Anführungszeichen.

Chris Degnen
quelle
5

Dieser Code erstellt eine Palette, die die Auswahl als Bild in Stack Exchange hochlädt. Unter Windows wird eine zusätzliche Schaltfläche bereitgestellt, mit der die Auswahl genauer wiedergegeben werden kann.

Kopieren Sie den Code in eine Notizbuchzelle und werten Sie ihn aus. Nehmen Sie dann die Palette aus der Ausgabe heraus und installieren Sie sie mitPalettes -> Install Palette...

Wenn Sie Probleme damit haben, schreiben Sie hier einen Kommentar. Laden Sie die Notebook - Version hier .


Begin["SOUploader`"];

Global`palette = PaletteNotebook@DynamicModule[{},

   Column[{
     Button["Upload to SE",
      With[{img = rasterizeSelection1[]},
       If[img === $Failed, Beep[], uploadWithPreview[img]]],
      Appearance -> "Palette"],

     If[$OperatingSystem === "Windows",

      Button["Upload to SE (pp)",
       With[{img = rasterizeSelection2[]},
        If[img === $Failed, Beep[], uploadWithPreview[img]]],
       Appearance -> "Palette"],

      Unevaluated@Sequence[]
      ]
     }],

   (* Init start *)
   Initialization :>
    (

     stackImage::httperr = "Server returned respose code: `1`";
     stackImage::err = "Server returner error: `1`";

     stackImage[g_] :=
      Module[
       {getVal, url, client, method, data, partSource, part, entity,
        code, response, error, result},

       getVal[res_, key_String] :=
        With[{k = "var " <> key <> " = "},
         StringTrim[

          First@StringCases[
            First@Select[res, StringMatchQ[#, k ~~ ___] &],
            k ~~ v___ ~~ ";" :> v],
          "'"]
         ];

       data = ExportString[g, "PNG"];

       JLink`JavaBlock[
        url = "http://stackoverflow.com/upload/image";
        client =
         JLink`JavaNew["org.apache.commons.httpclient.HttpClient"];
        method =
         JLink`JavaNew[
          "org.apache.commons.httpclient.methods.PostMethod", url];
        partSource =
         JLink`JavaNew[
          "org.apache.commons.httpclient.methods.multipart.\
ByteArrayPartSource", "mmagraphics.png",
          JLink`MakeJavaObject[data]@toCharArray[]];
        part =
         JLink`JavaNew[
          "org.apache.commons.httpclient.methods.multipart.FilePart",
          "name", partSource];
        part@setContentType["image/png"];
        entity =
         JLink`JavaNew[
          "org.apache.commons.httpclient.methods.multipart.\
MultipartRequestEntity", {part}, method@getParams[]];
        method@setRequestEntity[entity];
        code = client@executeMethod[method];
        response = method@getResponseBodyAsString[];
        ];

       If[code =!= 200, Message[stackImage::httperr, code];
        Return[$Failed]];
       response = StringTrim /@ StringSplit[response, "\n"];

       error = getVal[response, "error"];
       result = getVal[response, "result"];
       If[StringMatchQ[result, "http*"],
        result,
        Message[stackImage::err, error]; $Failed]
       ];

     stackMarkdown[g_] :=
      "![Mathematica graphics](" <> stackImage[g] <> ")";

     stackCopyMarkdown[g_] := Module[{nb, markdown},
       markdown = Check[stackMarkdown[g], $Failed];
       If[markdown =!= $Failed,
        nb = NotebookCreate[Visible -> False];
        NotebookWrite[nb, Cell[markdown, "Text"]];
        SelectionMove[nb, All, Notebook];
        FrontEndTokenExecute[nb, "Copy"];
        NotebookClose[nb];
        ]
       ];

     (* Returns available vertical screen space,
     taking into account screen elements like the taskbar and menu *)


     screenHeight[] := -Subtract @@
        Part[ScreenRectangle /. Options[$FrontEnd, ScreenRectangle],
         2];

     uploadWithPreview[img_Image] :=
      CreateDialog[
       Column[{
         Style["Upload image to the Stack Exchange network?", Bold],
         Pane[

          Image[img, Magnification -> 1], {Automatic,
           Min[screenHeight[] - 140, 1 + ImageDimensions[img][[2]]]},
          Scrollbars -> Automatic, AppearanceElements -> {},
          ImageMargins -> 0
          ],
         Item[
          ChoiceButtons[{"Upload and copy MarkDown"}, \
{stackCopyMarkdown[img]; DialogReturn[]}], Alignment -> Right]
         }],
       WindowTitle -> "Upload image to Stack Exchange?"
       ];

     (* Multiplatform, fixed-width version.
        The default max width is 650 to fit Stack Exchange *)
     rasterizeSelection1[maxWidth_: 650] :=
      Module[{target, selection, image},
       selection = NotebookRead[SelectedNotebook[]];
       If[MemberQ[Hold[{}, $Failed, NotebookRead[$Failed]], selection],

        $Failed, (* There was nothing selected *)

        target =
         CreateDocument[{}, WindowSelected -> False, Visible -> False,
           WindowSize -> maxWidth];
        NotebookWrite[target, selection];
        image = Rasterize[target, "Image"];
        NotebookClose[target];
        image
        ]
       ];

     (* Windows-only pixel perfect version *)
     rasterizeSelection2[] :=
      If[
       MemberQ[Hold[{}, $Failed, NotebookRead[$Failed]],
        NotebookRead[SelectedNotebook[]]],

       $Failed, (* There was nothing selected *)

       Module[{tag},
        FrontEndExecute[
         FrontEndToken[FrontEnd`SelectedNotebook[], "CopySpecial",
          "MGF"]];
        Catch[
         NotebookGet@ClipboardNotebook[] /.
          r_RasterBox :>
           Block[{},
            Throw[Image[First[r], "Byte", ColorSpace -> "RGB"], tag] /;
              True];
         $Failed,
         tag
         ]
        ]
       ];
     )
   (* Init end *)
   ]

End[];
Szabolcs
quelle
4

Ich bin sicher, dass viele Leute auf die Situation gestoßen sind, in der sie einige Dinge ausführen, und festgestellt haben, dass dies nicht nur das Programm blockiert, sondern auch die letzten 10 Minuten nicht gespeichert hat!

BEARBEITEN

Nachdem ich einige Zeit darunter gelitten hatte, fand ich eines Tages heraus, dass man das automatische Speichern aus dem Mathematica- Code heraus erstellen kann . Ich denke, dass mir die Verwendung eines solchen automatischen Speicherns in der Vergangenheit sehr geholfen hat, und ich hatte immer das Gefühl, dass die Möglichkeit selbst etwas ist, von dem nicht viele Menschen wissen, dass sie es können.

Der ursprüngliche Code, den ich verwendet habe, befindet sich unten. Dank der Kommentare habe ich herausgefunden, dass es problematisch ist und dass es viel besser ist, es auf alternative Weise mit ScheduledTask(was nur in Mathematica 8 funktioniert ) zu tun .

Code dafür finden Sie in dieser Antwort von Sjoerd C. de Vries (Da ich nicht sicher bin, ob es in Ordnung ist, ihn hierher zu kopieren, lasse ich ihn nur als Link.)


Die folgende Lösung verwendet Dynamic. Das Notebook wird alle 60 Sekunden gespeichert , aber anscheinend nur, wenn seine Zelle sichtbar ist . Ich lasse es hier nur aus Fertigstellungsgründen. (und für Benutzer von Mathematica 6 und 7)

/BEARBEITEN

Um es zu lösen, verwende ich diesen Code am Anfang eines Notizbuchs:

Dynamic[Refresh[NotebookSave[]; DateString[], UpdateInterval -> 60]]

Dies spart Ihre Arbeit alle 60 Sekunden.
Ich bevorzuge es, NotebookAutoSave[]weil es gespeichert wird, bevor die Eingabe verarbeitet wird, und weil einige Dateien mehr Text als Eingabe sind.

Ich habe es ursprünglich hier gefunden: http://en.wikipedia.org/wiki/Talk:Mathematica#Criticisms

Beachten Sie, dass nach dem Ausführen dieser Zeile das Speichern auch dann erfolgt, wenn Sie Ihre Datei schließen und erneut öffnen (solange die dynamische Aktualisierung aktiviert ist).

Da es in Mathematica kein Rückgängigmachen gibt , sollten Sie darauf achten, nicht alle Inhalte zu löschen, da diese durch das Speichern irreversibel werden (vorsichtshalber entferne ich diesen Code von jedem fertigen Notizbuch).

tsvikas
quelle
Sie können es auch unter einem anderen Namen speichern (z. B. indem Sie die aktuelle Uhrzeit und das aktuelle Datum an das Ende des Dateinamens anhängen) und möglicherweise in einem bestimmten Verzeichnis (z. B. "Backups"). Dies wäre wie eine primitive Form der Versionierung.
Acl
Sie können so etwas tun NotebookSave[SelectedNotebook[], "work-" <> IntegerString[i] <> ".nb"]; i++, aber ich denke, dass jede Art von Verweis auf den aktuellen Notizbuchnamen rekursiv wird.
Tsvikas
2
Ich dachte, DynamicObjekte werden nur aktualisiert, wenn sie sichtbar sind, daher wäre ich mir nicht sicher, ob diese Methode funktionieren würde, wenn Sie beispielsweise das DynamicObjekt aus dem sichtbaren Bereich scrollen . Andererseits habe ich es nicht versucht. Auf jeden Fall habe ich es nur als Vorschlag angeboten.
Acl
1
Sie können dies mit testen Dynamic[Refresh[i++, UpdateInterval -> 1, TrackedSymbols -> {}]]. Scrollen Sie die inkrementierende Zahl aus dem Blickfeld, warten Sie eine Minute, scrollen Sie zurück und sehen Sie, dass die Zahl nicht um 60 erhöht wird. Info UpdateInterval: Dies wird normalerweise verwendet, wenn dies möglich ist. Wenn Ihr Code jedoch Variablen enthält, die sich ändern, löst diese Änderung eine neue Aktualisierung vor dem aus Intervall endet. Versuchen Sie die obige Zeile ohneTrackedSymbols
Sjoerd C. de Vries
1
@ j0ker5 Versuchen Sie meinen obigen Code und Sie können sehen, dass UpdateInterval nicht immer erzwingt, dass Aktualisierungen mit dem angegebenen Intervall angeordnet werden. Dieser Code zeigt auch, dass Dynamic nur funktioniert, wenn die Zelle, in der es enthalten ist, im Frontend sichtbar ist . Es hört wirklich auf, sobald es außer Sicht ist. Die Leute sollten diesem Code wirklich nicht vertrauen, um ihre Dateien zu speichern, weil dies nicht der Fall ist. Es ist gefährlich
Sjoerd C. de Vries
3

Ich finde es sehr nützlich, wenn ich Pakete entwickle, um diese Tastenkombination zu meiner SystemFiles/FrontEnd/TextResources/Windows/KeyEventTranslations.trDatei hinzuzufügen .

(* Evaluate Initialization Cells: Real useful for reloading library changes. *)

Item[KeyEvent["i", Modifiers -> {Control, Command}],
    FrontEndExecute[
        FrontEndToken[
            SelectedNotebook[],
            "EvaluateInitialization"]]],

Als nächstes Packagename.mmache ich für jedes ein PackagenameTest.nbNotizbuch zum Testen und die ersten 2 Zellen des Testnotizbuchs werden als Initialisierungszellen festgelegt. In die erste Zelle habe ich gesetzt

Needs["PackageManipulations`"]

um die sehr nützliche PackageManipulations- Bibliothek zu laden, die von Leonid geschrieben wurde. Die zweite Zelle enthält

PackageRemove["Packagename`Private`"]
PackageRemove["Packagename`"]
PackageReload["Packagename`"]

die alle das eigentliche Paket neu laden. Beachten Sie, dass die ersten beiden Zeilen nur für Removealle Symbole gelten, da ich die Kontexte so sauber wie möglich halten möchte.

Dann wird der Workflow zum Schreiben und Testen eines Pakets ungefähr so.

  1. Speichern Sie die Änderungen in Packagename.m.
  2. Geh zu PackagenameTest.nbund mach CTRL + ALT + i.

Dies führt dazu, dass die Initialisierungszellen das Paket neu laden, was das Testen sehr einfach macht.

Nixeagle
quelle
1

Die folgende Funktion format[expr_]kann verwendet werden, um unformatierte mathematicaAusdrücke einzurücken / zu formatieren , die sich über eine Seite erstrecken

indent[str_String, ob_String, cb_String, delim_String] := 
  Module[{ind, indent, f, tab}, ind = 0; tab = "    ";
   indent[i_, tab_, nl_] := nl <> Nest[tab <> ToString[#] &, "", i];
   f[c_] := (indent[ind, "", " "] <> c <> indent[++ind, tab, "\n"]) /;StringMatchQ[ob, ___ ~~ c ~~ ___];
   f[c_] := (indent[--ind, "", " "] <> c <> indent[ind, tab, "\n"]) /;StringMatchQ[cb, ___ ~~ c ~~ ___];
   f[c_] := (c <> indent[ind, tab, "\n"]) /;StringMatchQ[delim, ___ ~~ c ~~ ___];
   f[c_] := c;
   f /@ Characters@str // StringJoin];
format[expr_] := indent[expr // InputForm // ToString, "[({", "])}", ";"];

(*    
format[Hold@Module[{ind, indent, f, tab}, ind = 0; tab = "    ";
 indent[i_, tab_, nl_] := nl <> Nest[tab <> ToString[#] &, "", i];
 f[c_] := (indent[ind, "", " "] <> c <> indent[++ind, tab, "\n"]) /;StringMatchQ[ob, ___ ~~ c ~~ ___];
 f[c_] := (indent[--ind, "", " "] <> c <> indent[ind, tab, "\n"]) /;StringMatchQ[cb, ___ ~~ c ~~ ___];
 f[c_] := (c <> indent[ind, tab, "\n"]) /;StringMatchQ[delim, ___ ~~ c ~~ ___];
 f[c_] := c;
 f /@ Characters@str // StringJoin]]
*)

Ref: /codegolf/3088/indent-a-string-using-given-parentheses

Prashant Bhate
quelle
Wofür verwenden Sie dies in der Praxis? Die Ausgabe ist etwas zu "lustig" , um gelesen zu werden, wenn sie auf Ihren Code oder auf Daten (Listen, format@RandomInteger[10,{3,3}]) angewendet wird : pastebin.com/nUT54Emq Da Sie bereits über die Grundlagen verfügen und daran interessiert sind, können Sie den Code verbessern eine sinnvoll lesbare Formatierung erstellen? Dann wäre der nächste Schritt, eine Schaltfläche zum Einfügen zu erstellen, die eine Eingabezelle mit gut eingerücktem Mathematica-Code erstellt (vorzugsweise Kommentare beibehalten !!). Siehe auch meine verwandte Frage .
Szabolcs