Apa yang ada di tas alat Mathematica Anda? [Tutup]

152

Kita semua tahu bahwa Mathematica hebat, tetapi juga sering tidak memiliki fungsi kritis. Paket / alat / sumber daya eksternal apa yang Anda gunakan dengan Mathematica?

Saya akan mengedit (dan mengundang orang lain untuk melakukannya juga) posting utama ini untuk memasukkan sumber daya yang berfokus pada penerapan umum dalam penelitian ilmiah dan yang mungkin berguna bagi banyak orang. Jangan ragu untuk menyumbang apa pun, bahkan cuplikan kode kecil (seperti yang saya lakukan di bawah ini untuk rutinitas waktu).

Juga, fitur tidak berdokumen dan berguna di Mathematica 7 dan di luar Anda menemukan diri Anda, atau menggali dari beberapa kertas / situs dipersilahkan.

Harap sertakan deskripsi atau komentar singkat tentang mengapa sesuatu itu hebat atau utilitas apa yang disediakannya. Jika Anda menautkan ke buku-buku di Amazon dengan tautan afiliasi, harap sebutkan, misalnya, dengan meletakkan nama Anda setelah tautan.


Paket:

  1. LevelSchemeadalah paket yang sangat memperluas kemampuan Mathematica untuk menghasilkan plot yang terlihat bagus. Saya menggunakannya jika bukan untuk hal lain maka untuk kontrol, jauh lebih baik atas bingkai / kutu kapak. Versi terbarunya disebut SciDraw, dan akan dirilis sekitar tahun ini.
  2. David Park's Presentation Package(US $ 50 - tidak ada biaya untuk pembaruan)
  3. Paket Jeremy Michelson grassmannOpsmenyediakan sumber daya untuk melakukan aljabar dan kalkulus dengan variabel dan operator Grassmann yang memiliki hubungan pergantian non trivial.
  4. GrassmannAlgebraPaket dan buku John Brown untuk bekerja dengan aljabar Grassmann dan Clifford.
  5. RISC (Research Institute for Symbolic Computation) memiliki beragam paket untuk Mathematica (dan bahasa lain) yang tersedia untuk diunduh. Secara khusus, ada Teorema untuk pembuktian teorema otomatis, dan banyak paket untuk penjumlahan simbolik, persamaan perbedaan, dll . Di halaman perangkat lunak kelompok Algorithmic Combinatorics group .

Alat:

  1. MASHadalah skrip Perl yang sangat bagus dari Daniel Reeves yang pada dasarnya menyediakan dukungan scripting untuk Mathematica v7. (Sekarang dibangun pada Mathematica 8 dengan -scriptopsi.)
  2. Sebuah alternate Mathematica shelldengan input readline GNU (menggunakan python, * nix saja)
  3. Paket ColourMaths memungkinkan Anda memilih bagian ekspresi secara visual dan memanipulasinya. http://www.dbaileyconsultancy.co.uk/colour_maths/colour_maths.html

Sumber:

  1. Repositori Wolfram sendiri MathSourcememiliki banyak notebook yang berguna jika sempit untuk berbagai aplikasi. Periksa juga bagian lain seperti

  2. The Mathematica Wikibook .

Buku:

  1. Pemrograman Mathematica: pengantar tingkat lanjut oleh Leonid Shifrin ( web, pdf) adalah harus dibaca jika Anda ingin melakukan apa pun lebih dari Untuk loop di Mathematica. Kami merasa senang memiliki Leoniddirinya sendiri menjawab pertanyaan di sini.
  2. Metode Quantum dengan Mathematica oleh James F. Feagin ( amazon )
  3. Buku The Mathematica oleh Stephen Wolfram ( amazon ) ( web)
  4. Garis Besar Schaum ( amazon )
  5. Mathematica in Action oleh Stan Wagon ( amazon ) - 600 halaman contoh rapi dan naik ke Mathematica versi 7. Teknik visualisasi sangat baik, Anda dapat melihat beberapa di antaranya ada di penulis Demonstrations Page.
  6. Dasar-Dasar Pemrograman Mathematica oleh Richard Gaylord ( pdf) - Pengantar singkat yang bagus untuk sebagian besar dari apa yang perlu Anda ketahui tentang pemrograman Mathematica.
  7. Cookbook Mathematica oleh Sal Mangano diterbitkan oleh O'Reilly 2010 832 halaman. - Ditulis dengan gaya O'Reilly Cookbook yang terkenal: Masalah - Solusi. Untuk perantara.
  8. Persamaan Diferensial dengan Mathematica, 3rd Ed. Elsevier 2004 Amsterdam oleh Martha L. Abell, James P. Braselton - 893 halaman Untuk pemula, belajar memecahkan DE dan Mathematica secara bersamaan.

Fitur tidak berdokumen (atau jarang didokumentasikan):

  1. Bagaimana cara menyesuaikan pintasan keyboard Mathematica. Lihat this question.
  2. Cara memeriksa pola dan fungsi yang digunakan oleh fungsi Mathematica sendiri. Lihatthis answer
  3. Bagaimana cara mencapai ukuran yang konsisten untuk GraphPlots di Mathematica? Lihat this question.
  4. Cara membuat dokumen dan presentasi dengan Mathematica. Lihat this question.
Dr. belisarius
sumber
2
Mathematica 8 keluar dengan integrasi skrip shell yang jauh lebih baik. wolfram.com/mathematica/new-in-8/mathematica-shell-scripts
Joshua Martell
2
+1, untuk LevelScheme. Agak lambat, terkadang. Tapi, ia memiliki metode yang waras untuk membuat tanda centang, dan jauh lebih mudah untuk membuat tata letak jurnal yang layak untuk grafik Grid, atau apa pun yang seperti itu.
rcollyer
2
Seperti yang diusulkan oleh Alexey dalam komentar tentang pertanyaan ini stackoverflow.com/questions/5152551/... , saya mengusulkan tag nama untuk Mathematica di sini: meta.stackexchange.com/questions/81152/… . Silakan melihat dan mendukung jika Anda setuju. Saya mempostingnya di sini karena pertanyaan ini memiliki banyak favorit di komunitas Mma di sini.
Dr. belisarius
1
Semua, pertanyaan ini benar-benar harus menjadi wiki komunitas karena semua alasan yang biasa: ia tidak memiliki jawaban yang benar dan lebih merupakan daftar daripada yang lainnya. Saya minta maaf kepada semua yang telah mendapat untung dengan reputasi baik dari pertanyaan ini.
rcollyer
2
Jawaban atas pertanyaan ini konstruktif, harus dibuka kembali.
MR

Jawaban:

29

Saya telah menyebutkan ini sebelumnya, tetapi alat yang saya temukan paling berguna adalah aplikasi Reapdan Sowyang meniru / memperluas perilaku GatherBy:

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

Ini memungkinkan saya untuk mengelompokkan daftar berdasarkan kriteria apa pun dan mengubahnya dalam proses. Cara kerjanya adalah bahwa fungsi kriteria ( f) menandai setiap item dalam daftar, setiap item kemudian diubah oleh fungsi yang disediakan kedua ( g), dan output spesifik dikontrol oleh fungsi ketiga ( h). Fungsi hmenerima dua argumen: tag dan daftar item yang dikumpulkan yang memiliki tag itu. Item mempertahankan pesanan aslinya, jadi jika Anda mengatur h = #1&maka Anda mendapatkan yang tidak disortir Union, seperti dalam contoh untuk Reap. Tapi, itu bisa digunakan untuk pemrosesan sekunder.

Sebagai contoh utilitasnya, saya telah bekerja dengan Wannier90 yang menampilkan Hamiltonian yang bergantung secara spasial ke dalam file di mana setiap baris adalah elemen yang berbeda dalam matriks, sebagai berikut

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

Untuk mengubah daftar itu menjadi seperangkat matriks, saya mengumpulkan semua sublists yang berisi koordinat yang sama, mengubah informasi elemen menjadi aturan (yaitu {i, j} -> Re [Hij] + I Im [Hij]), dan kemudian mengubah aturan yang terkumpul menjadi SparseArraysemua dengan liner satu:

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

Jujur, ini adalah Pisau Tentara Swiss saya, dan itu membuat hal-hal rumit sangat sederhana. Sebagian besar alat saya yang lain agak spesifik domain, jadi saya mungkin tidak akan mempostingnya. Namun, sebagian besar, jika tidak semua, referensi dari mereka SelectEquivalents.

Sunting : ini tidak sepenuhnya meniru GatherBybahwa ia tidak dapat mengelompokkan beberapa level ekspresi sesederhana yang GatherBybisa. Namun, Mapberfungsi dengan baik untuk sebagian besar yang saya butuhkan.

Contoh : @Yaroslav Bulatov telah meminta contoh yang lengkap. Ini satu dari penelitian saya yang sangat disederhanakan. Jadi, katakanlah kita memiliki satu set poin di pesawat

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}}

dan kami ingin mengurangi jumlah poin dengan serangkaian operasi simetri. (Untuk yang penasaran, kami menghasilkan grup kecil dari setiap titik.) Untuk contoh ini, mari kita gunakan sumbu rotasi empat kali lipat tentang sumbu z

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

Menggunakan SelectEquivalentskami dapat mengelompokkan poin yang menghasilkan set gambar yang sama di bawah operasi ini, yaitu mereka setara, menggunakan berikut ini

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}}}

yang menghasilkan 3 sublists yang berisi poin yang setara. (Catatan, Unionsangat penting di sini karena memastikan bahwa gambar yang sama dihasilkan oleh setiap titik. Awalnya, saya menggunakan Sort, tetapi jika suatu titik terletak pada sumbu simetri, itu tidak berubah di bawah rotasi tentang sumbu yang memberikan gambar ekstra dari dirinya sendiri. Jadi, Unionhilangkan gambar-gambar ekstra ini. Juga, GatherByakan menghasilkan hasil yang sama.) Dalam hal ini, poin sudah dalam bentuk yang akan saya gunakan, tetapi saya hanya perlu titik perwakilan dari setiap pengelompokan dan saya ingin menghitung dari poin yang setara. Karena, saya tidak perlu mengubah setiap titik, saya menggunakanIdentityberfungsi di posisi kedua. Untuk fungsi ketiga, kita harus berhati-hati. Argumen pertama yang diteruskan adalah gambar dari titik-titik di bawah rotasi yang untuk titik tersebut {0,0,0}adalah daftar empat elemen yang identik, dan menggunakannya akan membuang hitungan. Namun, argumen kedua hanyalah daftar semua elemen yang memiliki tag itu, jadi hanya akan berisi {0,0,0}. Dalam kode,

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}}

Perhatikan, langkah terakhir ini bisa dengan mudah dilakukan

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

Tapi, mudah dengan ini dan contoh yang kurang lengkap di atas untuk melihat bagaimana transformasi yang sangat kompleks dimungkinkan dengan kode minimum.

rcollyer
sumber
Kode Fortran77 asli direstrukturisasi pada Hari Thanksgiving 1996, dan karenanya selama bertahun-tahun dikenal sebagai turkey.f ...: D Grafis BTW yang sangat bagus. Ingat saya monster Falicov ...
Dr. belisarius
@ Belisarius, saya belum membaca sejarah, itu lucu. Saya baru saja mulai menggunakan Wannier90, tetapi ini adalah kode yang paling terorganisir dan ditulis dengan baik yang Fortranpernah saya lihat. Membuat saya hampir mempertimbangkan untuk menggunakan Fortran...
rcollyer
Saya ingin tahu apakah Anda dapat menambahkan contoh mandiri SelectEquivalents dalam aksi
Yaroslav Bulatov
@Yaroslav Bulatov, menambahkan contoh, per permintaan. Beri tahu saya jika ini membantu. Jika tidak, kita akan lihat apa yang bisa kita lakukan.
rcollyer
Anda mendapatkan tanda centang untuk "pertanyaan" ini untuk kontribusi potongan kode paling menarik.
Timo
57

Salah satu hal yang menyenangkan tentang antarmuka notebook Mathematica adalah dapat mengevaluasi ekspresi dalam bahasa apa pun , bukan hanya Mathematica. Sebagai contoh sederhana, pertimbangkan untuk membuat tipe sel input Shell baru yang meneruskan ekspresi yang terkandung ke shell sistem operasi untuk evaluasi.

Pertama, tentukan fungsi yang mendelegasikan evaluasi perintah teks ke shell eksternal:

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

Argumen kedua diperlukan dan diabaikan karena alasan yang akan muncul kemudian. Selanjutnya, kami ingin membuat gaya baru yang disebut Shell :

  1. Buka buku catatan baru.
  2. Pilih item menu Format / Edit Stylesheet ...
  3. Dalam dialog, di samping Masukkan nama gaya: ketik Shell.
  4. Pilih braket sel di sebelah gaya baru.
  5. Pilih item menu Sel / Tampilkan Ekspresi
  6. Timpa ekspresi sel dengan Langkah 6 Teks yang diberikan di bawah ini.
  7. Sekali lagi, pilih item menu Cell / Show Expression
  8. Tutup dialog.

Gunakan ekspresi sel berikut sebagai Langkah 6 Teks :

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"]

Sebagian besar ungkapan ini disalin secara langsung dari gaya Program bawaan. Perubahan utama adalah baris-baris ini:

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

Evaluatablemengaktifkan fungsionalitas SHIFT + ENTER untuk sel. Evaluasi akan memanggil CellEvaluationFunctionlewat konten sel dan jenis konten sebagai argumen ( shellEvaluatemengabaikan argumen yang terakhir). CellFrameLabelshanyalah keramahtamahan yang memungkinkan pengguna mengidentifikasi bahwa sel ini tidak biasa.

Dengan semua ini di tempat, sekarang kita dapat memasukkan dan mengevaluasi ekspresi shell:

  1. Di buku catatan yang dibuat pada langkah-langkah di atas, buat sel kosong dan pilih braket sel.
  2. Pilih item menu Format / Gaya / Shell .
  3. Ketikkan perintah shell sistem operasi yang valid ke dalam sel (mis. 'Ls' di Unix atau 'dir' di Windows).
  4. Tekan SHIFT + ENTER.

Yang terbaik adalah menjaga gaya yang didefinisikan ini dalam stylesheet yang berlokasi di pusat. Selain itu, fungsi evaluasi seperti shellEvaluateyang terbaik didefinisikan sebagai bertopik menggunakan DeclarePackage di init.m. Rincian kedua kegiatan ini berada di luar cakupan respons ini.

Dengan fungsi ini, seseorang dapat membuat buku catatan yang berisi ekspresi input dalam setiap sintaks yang menarik. Fungsi evaluasi dapat ditulis dalam Mathematica murni, atau mendelegasikan setiap atau semua bagian evaluasi ke lembaga eksternal. Sadarilah bahwa ada kaitan lain yang terkait dengan evaluasi sel, seperti CellEpilog, CellPrologdan CellDynamicExpression.

Pola umum melibatkan penulisan teks ekspresi input ke file sementara, kompilasi file dalam beberapa bahasa, menjalankan program dan menangkap output untuk tampilan utama di sel output. Ada banyak detail yang harus diatasi ketika menerapkan solusi penuh seperti ini (seperti menangkap pesan kesalahan dengan benar), tetapi orang harus menghargai kenyataan bahwa tidak hanya mungkin untuk melakukan hal-hal seperti ini, tetapi juga praktis.

Pada catatan pribadi, fitur-fitur seperti inilah yang menjadikan antarmuka notebook sebagai pusat dari dunia pemrograman saya.

Memperbarui

Fungsi pembantu berikut berguna untuk membuat sel-sel seperti:

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]
  )

Digunakan demikian:

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

Sekarang, jika shellCell[]dievaluasi, sel input akan dihapus dan diganti dengan sel input baru yang mengevaluasi isinya sebagai perintah shell.

WReach
sumber
3
@WReach +100! Saya berharap saya tahu ini sebelumnya! Ini adalah hal yang sangat berguna, setidaknya bagi saya. Terima kasih telah berbagi!
Leonid Shifrin
Ini terlihat sangat keren! CellEvaluationFunctiondapat digunakan untuk hacking sintaks tingkat rendah juga saya pikir.
Mr.Wizard
@Leonid Setidaknya untuk FrontEnd, apakah CellEvaluationFunctionkail yang Anda cari?
Mr.Wizard
2
Selain itu: ada satu Cellopsi lain yang terkait dengan evaluasi sel - Evaluator -> "EvaluatorName". Arti dari "EvaluatorName"dapat dikonfigurasi melalui dialog Evaluasi :: Opsi Konfigurasi Kernel .... Saya masih tidak tahu apakah mungkin untuk mengkonfigurasi secara terprogram ... Teknik ini memungkinkan untuk menggunakan MathKernels yang berbeda Celldalam s yang berbeda dalam satu Notebook. MathKernels ini dapat berasal dari berbagai versi Mathematica yang diinstal.
Alexey Popkov
1
@Szabolcs Semua kegunaan saya sendiri dari teknik ini melibatkan pendekatan stdin _ / _ stdout seperti diilustrasikan di atas, atau permintaan jarak jauh mandiri seperti query SQL atau operasi HTTP. Anda dapat mencoba menyiapkan aplikasi web Python REPL (seperti ini ) dan berinteraksi dengannya menggunakan Import, atau mungkin memulai proses Python eksternal dan berkomunikasi melalui alirannya (misalnya menggunakan Java ProcessBuilder ). Saya yakin ada cara Mathematica yang lebih baik - terdengar seperti pertanyaan SO yang bagus :)
WReach
36

Todd Gayley (Penelitian Wolfram) baru saja mengirim saya hack bagus yang memungkinkan untuk "membungkus" fungsi bawaan dengan kode arbitrer. Saya merasa bahwa saya harus membagikan instrumen yang bermanfaat ini. Berikut ini adalah jawaban Todd pada saya question.

Sedikit sejarah (?) Yang menarik: Gaya hack untuk "membungkus" fungsi bawaan ditemukan sekitar 1994 oleh Robby Villegas dan saya, ironisnya untuk pesan fungsi, dalam sebuah paket bernama ErrorHelp yang saya tulis untuk Journal Mathematica saat itu. Ini telah digunakan berkali-kali, oleh banyak orang, sejak saat itu. Ini sedikit trik orang dalam, tapi saya pikir adil untuk mengatakan bahwa itu telah menjadi cara kanonik untuk menyuntikkan kode Anda sendiri ke dalam definisi fungsi bawaan. Ini akan menyelesaikan pekerjaan dengan baik. Anda tentu saja dapat memasukkan variabel $ inMsg ke dalam konteks pribadi apa pun yang Anda inginkan.

Unprotect[Message];

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

Protect[Message];
Alexey Popkov
sumber
@ Alexey Saya mengalami kesulitan memahami hal ini. Bisakah Anda menjelaskan cara kerjanya? Tidakkah seharusnya ada [Pesan] Tidak Terlindungi di suatu tempat? Dan bukankah contoh ini mengandung rekursi tak terbatas? Dan,! TrueQ [$ inMsg] apakah masuk akal dengan $ inMsg didefinisikan di dalam lingkup Blok dan tidak ditentukan di luar Blok?
Sjoerd C. de Vries
9
@ Soerd Dari apa yang saya mengerti, Unprotectmemang harus, hanya ditinggalkan. Titik Block(pelingkupan dinamis) dan $inMsgtepat untuk mencegah rekursi tak terbatas. Karena $inMsgtidak ditentukan di luar (ini merupakan persyaratan penting), pada awalnya, TrueQmengevaluasi ke False, dan kami memasuki tubuh fungsi. Tetapi ketika kita memiliki pemanggilan fungsi di dalam tubuh, kondisi mengevaluasi ke False(karena variabel telah didefinisikan ulang oleh Blok). Dengan demikian, aturan yang ditentukan pengguna tidak cocok, dan aturan bawaan malah digunakan.
Leonid Shifrin
1
@Leonid Terima kasih, saya mengerti sekarang. Sangat pintar!
Sjoerd C. de Vries
1
Saya baru saja menemukan bahwa teknik ini dibahas oleh Robby Villegas dari Wolfram Research di 1999 Developer Conference. Lihat "Bekerja Dengan Ekspresi yang Tidak Dievaluasi" yang diposting di sini . Dalam buku catatan ini Robby Villegas membahas trik ini di subbagian "Trik Blok Saya untuk menjebak panggilan ke fungsi internal".
Alexey Popkov
1
@ Mr.Wizard Ini bukan satu-satunya cara untuk melakukan ini. Untuk waktu yang lama, saya menggunakan versi di mana Anda mendefinisikan ulang DownValuessaat berjalan, Anda dapat melihat posting ini groups.google.com/group/comp.soft-sys.math.mathematica/… , untuk contoh ( SetDelayedredefinisi) . Tetapi metode saya kurang elegan, kurang kuat, lebih rentan kesalahan, dan membuat istirahat dari rekursi menjadi kurang sepele untuk diterapkan. Jadi, dalam kebanyakan situasi, metode yang dijelaskan oleh @Alexey menang dengan mudah.
Leonid Shifrin
25

Ini bukan sumber yang lengkap, jadi saya melemparkannya ke sini di bagian jawaban, tapi saya merasa sangat berguna ketika mencari tahu masalah kecepatan (yang, sayangnya, merupakan bagian besar dari apa pemrograman tentang Mathematica adalah tentang).

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};

Penggunaannya sederhana saja timeAvg@funcYouWantToTest.

EDIT: Mr. Wizard telah menyediakan versi yang lebih sederhana yang menghilangkan Throwdan Catchdan sedikit lebih mudah untuk diuraikan:

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

EDIT: Ini versi dari acl (diambil dari sini ):

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
sumber
Selesai lagi dan lagi ... saatnya masuk ke tas saya sendiri. tnx!
Dr. belisarius
1
Satu masalah dengan kode ini (yah, mungkin ini adalah sudut pandang perfeksionis) adalah bahwa kita dapat menangkap sesuatu yang tidak kita lempar, dan menafsirkan ini sebagai hasil waktu yang tidak tepat. Keduanya Catchdan Throwseharusnya digunakan dengan tag pengecualian unik.
Leonid Shifrin
2
Timo, saya senang Anda cukup membawakan lagu saya untuk memasukkannya. Terima kasih telah memberi saya kredit juga. Saya ingin tahu tentang cara Anda memformat ulang kode saya. Saya tidak mengikuti pedoman tertentu dalam kode saya sendiri, selain membuatnya mudah dibaca sendiri; apakah ada aliran pemikiran di balik pemformatan ulang Anda, atau hanya preferensi? Mathematica tidak mendorong pemformatan kode secara akurat karena cara mem-reflows input, tetapi memposting kode di sini menyebabkan saya mulai memikirkannya. BTW, saya pikir maksud Anda " Throwdan Catch" daripada " Reapdan Sow."
Mr.Wizard
1
@Simon, Mr.Wizard, saya menggunakan metode ini untuk membedakan waktu berbagai versi fungsi bertubuh kecil yang akan dipanggil berkali-kali. Tidak harus dalam struktur loop tetapi tentu saja dalam konstruksi yang mengoptimalkan MMA. Dalam konteks ini, waktu pelaksanaan loop masuk akal dan kinerja akan dekat dengan aplikasi kehidupan nyata. Untuk menentukan waktu fungsi-fungsi rumit yang besar (bahkan mungkin seluruh sel inisialisasi) metode oleh Simon akan memberikan hasil yang lebih baik. Semua dalam semua, saya lebih tertarik pada nilai-nilai relatif dan metode mana pun harus bekerja di sana.
Timo
3
Sekarang ada RepeatedTiminguntuk melakukan ini.
masterxilo
20

Internal`InheritedBlock

Baru-baru ini saya mempelajari keberadaan fungsi yang bermanfaat seperti Internal`InheritedBlock, dari pesan Daniel Lichtblau ini di newsgroup resmi.

Seperti yang saya mengerti, Internal`InheritedBlockmemungkinkan untuk meneruskan salinan fungsi keluar di dalam Blockruang lingkup:

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]

Saya pikir fungsi ini bisa sangat berguna bagi semua orang yang perlu memodifikasi fungsi bawaan untuk sementara!

Perbandingan dengan Block

Mari kita mendefinisikan beberapa fungsi:

a := Print[b]

Sekarang kami ingin meneruskan salinan fungsi ini ke dalam Blockruang lingkup. Pengadilan naif tidak memberikan apa yang kita inginkan:

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

During evaluation of In[9]:= b

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

Sekarang mencoba menggunakan definisi yang tertunda dalam argumen pertama Block(ini adalah fitur yang tidak berdokumen juga):

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

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

During evaluation of In[3]:= b

Kami melihat bahwa dalam kasus ini aberfungsi tetapi kami belum mendapatkan salinan bagian adalam Blocklingkup yang asli.

Sekarang mari kita coba Internal`InheritedBlock:

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

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

Kami telah mendapatkan salinan definisi asli untuk abagian dalam Blocklingkup dan kami dapat memodifikasinya dengan cara yang kami inginkan tanpa memengaruhi definisi global untuk a!

Alexey Popkov
sumber
+1 Sangat berguna! Satu alat lagi di tas, dan 10 poin lebih dekat ke Edit hak istimewa untuk Anda.
Mr.Wizard
Bagi saya ini muncul sebagai varian evaluasi awal atau akhir atau tidak dan penuh.
user2432923
19

Mathematica adalah alat yang tajam, tetapi dapat memotong Anda dengan perilaku yang agak tidak diketik dan longsoran pesan diagnostik samar . Salah satu cara untuk mengatasinya adalah dengan mendefinisikan fungsi yang mengikuti idiom ini:

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

Itu banyak boilerplate, yang saya sering tergoda untuk melewatinya. Terutama ketika membuat prototipe, yang banyak terjadi di Mathematica. Jadi, saya menggunakan makro yang disebut defineyang memungkinkan saya untuk tetap disiplin, dengan boilerplate yang lebih sedikit.

Penggunaan dasar defineadalah seperti ini:

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

fact[5]

120

Pada awalnya tidak terlihat banyak, tetapi ada beberapa manfaat tersembunyi. Layanan pertama yang definemenyediakan adalah bahwa ia secara otomatis berlaku ClearAlluntuk simbol yang didefinisikan. Ini memastikan bahwa tidak ada definisi sisa - suatu kejadian umum selama pengembangan awal suatu fungsi.

Layanan kedua adalah bahwa fungsi yang didefinisikan secara otomatis "ditutup". Maksud saya, fungsi ini akan mengeluarkan pesan dan batalkan jika dipanggil dengan daftar argumen yang tidak cocok dengan salah satu definisi:

fact[-1]

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

Ini adalah nilai utama dari define, yang menangkap kelas kesalahan yang sangat umum.

Kenyamanan lain adalah cara ringkas untuk menentukan atribut pada fungsi yang sedang didefinisikan. Mari kita buat fungsinya Listable:

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

fact[{3, 5, 8}]

{6, 120, 40320}

Selain semua atribut normal, definemenerima atribut tambahan yang disebut Open. Ini mencegah definedari menambahkan definisi kesalahan catch-all ke fungsi:

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

successor /@ {1, "hi"}

{2, successor["hi"]}

Beberapa atribut dapat didefinisikan untuk suatu fungsi:

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

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

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

Tanpa basa-basi lagi, berikut adalah definisi 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: ``";

Implementasi yang dipamerkan mendukung tidak up-nilai atau currying, atau pola yang lebih umum daripada definisi fungsi sederhana. Namun tetap bermanfaat.

WReach
sumber
2
+1 - ini adalah hal yang sangat berguna. Saya telah menggunakan alat serupa. Makro (serta introspeksi dan teknik meta-pemrograman lainnya) bisa sangat kuat, tetapi tampaknya kurang dihargai secara umum di dalam komunitas Mathematica, atau setidaknya ini telah menjadi kesan saya sejauh ini.
Leonid Shifrin
Saya baru saja mendefinisikan sesuatu yang serupa. +1 untuk dukungan CompoundExpression untuk melakukan banyak definisi, Batalkan [] (tampaknya lebih baik daripada lebih banyak pesan) dan Buka (bagus untuk konstruktor misalnya).
masterxilo
16

Mulai tanpa buku catatan kosong terbuka

Saya merasa terganggu dengan memiliki Mathematica mulai dengan buku catatan kosong terbuka. Saya bisa menutup buku catatan ini dengan sebuah skrip, tetapi masih akan terbuka sebentar. Retasan saya adalah membuat file yang Invisible.nbberisi:

Notebook[{},Visible->False]

Dan tambahkan ini ke Kernel\init.m:

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

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

Saya sekarang memulai Mathematica dengan membuka Invisible.nb

Mungkin ada cara yang lebih baik, tetapi ini telah membantu saya dengan baik.


Disesuaikan FolddanFoldList

Fold[f, x] dibuat setara dengan Fold[f, First@x, Rest@x]

Kebetulan, saya percaya ini dapat menemukan jalan ke versi Mathematica di masa depan.

Mengherankan! Ini telah diterapkan, meskipun saat ini tidak berdokumen. Saya diberitahu bahwa itu diterapkan pada 2011 oleh Oliver Ruebenkoenig, tampaknya tidak lama setelah saya memposting ini. Oliver Ruebenkoenig terima kasih!

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]

Diperbarui untuk memungkinkan ini:

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

"Partisi Dinamis"

Lihat posting Mathematica.SE # 7512 untuk versi baru dari fungsi ini.

Seringkali saya ingin mempartisi daftar sesuai dengan urutan panjangnya.

contoh pseudo-code:

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

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

Saya datang dengan ini:

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

Yang kemudian saya selesaikan dengan ini, termasuk pengujian argumen:

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

Argumen ketiga mengontrol apa yang terjadi pada elemen di luar spesifikasi split.


Trik Mathematica dari Szabolcs

Yang paling sering saya gunakan adalah Paste Tabular Data Palette

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"]]]]]}

Ubah data eksternal dari dalam Compile

Baru-baru ini Daniel Lichtblau menunjukkan metode ini yang belum pernah saya lihat sebelumnya. Menurut pendapat saya itu secara signifikan memperluas utilitasCompile

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
sumber
3
+1 Koleksi yang bagus! Mengenai modifikasi eksternal dari dalam Compile- seluruh posting saya di sini: stackoverflow.com/questions/5246330/… , adalah untuk menunjukkan kemungkinan ini dalam pengaturan non-sepele (Ada solusi yang lebih pendek dan lebih cepat untuk masalah yang dimaksud yang sudah diposting di sana) . IMO, kemenangan terbesar di sini adalah kemampuan untuk meniru pass-by-reference dan memecah fungsi yang dikompilasi menjadi potongan yang lebih mudah dikelola dan digunakan kembali.
Leonid Shifrin
1
Anda juga dapat menyesuaikan informasi sintaksis dari Fold dan FoldList dalam definisi baru Anda: SyntaxInformation [Fold] = {"ArgumentsPattern" -> {_ ,. , _}}; SyntaxInformation [FoldList] = {"ArgumentsPattern" -> {_, _., {_ }}};
faysou
14

Masalah umum dan solusi ekspor PDF / EMF

1) Ini benar-benar tidak terduga dan tidak berdokumen, tetapi Mathematica mengekspor dan menyimpan gambar dalam format PDF dan EPS menggunakan sekumpulan definisi gaya yang berbeda dari yang digunakan untuk menampilkan Notebook di layar. Secara default, Notebook ditampilkan di layar dalam lingkungan gaya "Bekerja" (yang merupakan nilai default untuk opsi ScreenStyleEvironmentglobal $FrontEnd) tetapi dicetak dalam "Printout"lingkungan gaya (yang merupakan nilai default untuk opsi PrintingStyleEnvironmentglobal $FrontEnd). Ketika seseorang mengekspor grafik dalam format raster seperti GIF dan PNG atau dalam format EMF Mathematica menghasilkan grafik yang terlihat persis seperti yang terlihat di dalam Notebook. Tampaknya itu"Working"lingkungan gaya digunakan untuk rendering dalam kasus ini. Tetapi tidak demikian halnya ketika Anda mengekspor / menyimpan apa pun dalam format PDF atau EPS! Dalam hal ini "Printout"lingkungan gaya digunakan secara default yang sangat berbeda dari lingkungan gaya "Bekerja". Pertama-tama, yang "Printout"gaya lingkungan set Magnificationke 80% . Kedua, ia menggunakan nilainya sendiri untuk ukuran font dari gaya yang berbeda dan ini menghasilkan perubahan ukuran font yang tidak konsisten dalam file PDF genarated dibandingkan dengan representasi di layar asli. Yang terakhir dapat disebut fluktuasi FontSize yang sangat menjengkelkan. Tapi dengan senang hati ini bisa dihindari dengan menetapkan opsi PrintingStyleEnvironmentglobal $FrontEnduntuk "Bekerja" :

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

2) Masalah umum dengan mengekspor ke format EMF adalah bahwa sebagian besar program (tidak hanya Mathematica ) menghasilkan file yang terlihat bagus pada ukuran default tetapi menjadi jelek ketika Anda memperbesarnya. Itu karena metafil disampel pada kesetiaan resolusi layar . Kualitas file EMF yang dihasilkan dapat ditingkatkan dengan Magnifymemasukkan objek grafis asli sehingga ketepatan pengambilan sampel gambar asli menjadi jauh lebih tepat. Bandingkan dua file:

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

Jika Anda memasukkan file-file ini ke Microsoft Word dan memperbesarnya, Anda akan melihat bahwa "a" pertama memiliki gigi gergaji di atasnya sementara yang kedua belum (diuji dengan Mathematica 6).

Cara lain ImageResolutiondisarankan oleh Chris Degnen (opsi ini memiliki efek setidaknya mulai dari Mathematica 8):

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

3) Dalam Mathematica kami memiliki tiga cara untuk mengubah grafik menjadi metafile: via Exportto "EMF"(cara sangat disarankan: menghasilkan metafile dengan kualitas setinggi mungkin), melalui Save selection As...item menu ( menghasilkan angka yang jauh lebih kecil , tidak direkomendasikan) dan melalui Edit ► Copy As ► Metafileitem menu ( saya sangat merekomendasikan terhadap rute ini ).

Alexey Popkov
sumber
13

Dengan permintaan yang populer, kode untuk menghasilkan plot penjawab SO 10 teratas (kecuali anotasi ) menggunakan API SO .

masukkan deskripsi gambar di sini

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
sumber
1
Brett memposting pertanyaan yang menanyakan kode persis ini. Mungkin paling tepat di sana, dengan satu atau dua tweak agar sesuai dengan pertanyaan. Saya benar-benar akan bernilai rep, sebagai lawan dari pertanyaan ini.
rcollyer
@ Arcollyer benar. Ini adalah "Komunitas Wiki"
Dr. belisarius
@belisarius Saya baru saja menyalinnya dalam jawaban untuk pertanyaan Brett ...
Sjoerd C. de Vries
@Soerd Plot Anda di sini tidak diperbarui secara otomatis.
Dr. belisarius
@belisarius Sebenarnya saya berharap Anda akan mengambil tugas itu atas Anda ... ;-)
Sjoerd C. de Vries
13

Ekspresi caching

Saya menemukan fungsi-fungsi ini sangat membantu untuk cache ekspresi apa pun. Hal yang menarik di sini untuk dua fungsi ini adalah bahwa ekspresi yang ditahan itu sendiri digunakan sebagai kunci dari hashtable / simbol Cache atau CacheIndex, dibandingkan dengan memoisasi terkenal di Mathematica di mana Anda hanya dapat men-cache hasil jika fungsi didefinisikan seperti f [x_]: = f [x] = ... Jadi Anda dapat melakukan cache bagian dari suatu kode, ini berguna jika suatu fungsi dipanggil beberapa kali tetapi hanya beberapa bagian dari kode tidak boleh dihitung ulang.

Untuk menyimpan ekspresi secara terpisah dari argumennya.

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

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

Kedua kalinya ekspresi mengembalikan 6 tanpa menunggu.

Untuk cache ekspresi menggunakan ekspresi alias yang bisa bergantung pada argumen dari ekspresi yang di-cache.

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

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

Jika expr membutuhkan waktu untuk menghitung, itu jauh lebih cepat untuk mengevaluasi {"f", 2} misalnya untuk mengambil hasil yang di-cache.

Untuk variasi fungsi-fungsi ini agar memiliki cache yang dilokalkan (mis. Memori cache secara otomatis dirilis di luar Blok konstruksi) lihat posting ini Hindari panggilan berulang ke Interpolasi

Menghapus nilai yang di-cache

Untuk menghapus nilai yang di-cache ketika Anda tidak tahu jumlah definisi dari suatu fungsi. Saya menganggap bahwa definisi memiliki Blank di suatu tempat dalam argumen mereka.

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

Untuk menghapus nilai yang di-cache ketika Anda mengetahui jumlah definisi suatu fungsi (berjalan sedikit lebih cepat).

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

Ini menggunakan fakta bahwa definisi fungsi ada di akhir daftar DownValues ​​mereka, nilai-nilai yang di-cache sebelumnya.

Menggunakan simbol untuk menyimpan data dan fungsi seperti objek

Juga di sini ada fungsi menarik untuk menggunakan simbol seperti objek.

Sudah diketahui umum bahwa Anda dapat menyimpan data dalam simbol dan mengaksesnya dengan cepat menggunakan DownValues

mysymbol["property"]=2;

Anda dapat mengakses daftar kunci (atau properti) dari simbol menggunakan fungsi-fungsi ini berdasarkan pada apa yang diserahkan oleh kiriman dalam posting di situs ini:

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

Saya menggunakan fungsi ini banyak untuk menampilkan semua info yang terkandung dalam DownValues ​​simbol:

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

Akhirnya di sini adalah cara sederhana untuk membuat simbol yang berperilaku seperti objek dalam pemrograman berorientasi objek (itu hanya mereproduksi perilaku paling dasar dari OOP tetapi saya menemukan sintaks yang elegan):

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
  ];

Properti disimpan sebagai DownValues ​​dan metode sebagai tertunda Upvalues ​​di simbol yang dibuat oleh Module yang dikembalikan. Saya menemukan sintaks untuk function2 yang merupakan sintaksis OO biasa untuk fungsi dalam struktur data Tree di Mathematica .

Untuk daftar jenis nilai yang sudah dimiliki setiap simbol, lihat http://reference.wolfram.com/mathematica/tutorial/PatternsAndTransformationRules.html dan http://www.verbeia.com/mathematica/tips/HTMLLinks/Tricks_Misc_4.html .

Misalnya coba ini

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

Anda dapat melangkah lebih jauh jika Anda ingin meniru objek warisan menggunakan paket yang disebut InheritRules yang tersedia di sini http://library.wolfram.com/infocenter/MathSource/671/

Anda juga bisa menyimpan definisi fungsi bukan di newObject tetapi dalam simbol tipe, jadi jika NewObject kembali ketik [newObject] bukan newObject Anda bisa mendefinisikan fungsi dan function2 seperti ini di luar NewObject (dan bukan di dalam) dan memiliki penggunaan yang sama seperti sebelumnya .

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

Gunakan UpValues ​​[type] untuk melihat bahwa fungsi dan function2 didefinisikan dalam simbol tipe.

Gagasan lebih lanjut tentang sintaks terakhir ini diperkenalkan di sini https://mathematica.stackexchange.com/a/999/66 .

Versi SelectEquivalents yang ditingkatkan

@ Arcollyer: Terima kasih banyak telah membawa SelectEquivalents ke permukaan, ini adalah fungsi yang luar biasa. Ini adalah versi SelectEquivalents yang disempurnakan yang tercantum di atas dengan lebih banyak kemungkinan dan menggunakan opsi, ini membuatnya lebih mudah untuk digunakan.

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]]
      ]
   ];

Berikut adalah contoh bagaimana versi ini dapat digunakan:

Menggunakan Mathematica Kumpulkan / Kumpulkan dengan benar

Bagaimana Anda melakukan fungsi PivotTable di Mathematica?

Algoritma 2D binning cepat matematika

Internal`Bag

Daniel Lichtblau menjelaskan di sini struktur data internal yang menarik untuk daftar yang berkembang.

Menerapkan Quadtree di Mathematica

Fungsi debugging

Dua pos ini menunjuk ke fungsi yang berguna untuk debugging:

Bagaimana cara debug ketika menulis kode kecil atau besar menggunakan Mathematica? meja kerja? mma debugger? atau sesuatu yang lain? (ShowIt)

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

Berikut fungsi lain yang didasarkan pada Menuai dan Tabur untuk mengekstrak ekspresi dari berbagai bagian program dan menyimpannya dalam simbol.

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

Ini sebuah contoh

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*)

Sumber daya lainnya

Berikut daftar tautan menarik untuk tujuan belajar:

Kumpulan sumber belajar Mathematica

Diperbarui di sini: https://mathematica.stackexchange.com/a/259/66

faysou
sumber
Terkait: " Cara terbaik untuk membangun fungsi dengan memori ". WReach telah memberikan contoh luar biasa dari fungsi sederhana yang tidak hanya mengingat nilainya tetapi juga menulisnya ke file dan membaca mundur saat restart.
Alexey Popkov
1
Terkait: " Mathematica: Cara menghapus cache untuk simbol, yaitu Hapus Nilai-bebas Downset pola ". Pertanyaan ini menunjukkan cara menghapus cache menggunakan f[x_] := f[x] = some codememoisasi standar .
Simon
7
1 Ada kenyamanan notasi bagus yang menghilangkan kebutuhan untuk mengulang sisi kiri dari definisi dalam fungsi caching, misalnya: c:Cache[expr_] := c = expr.
WEach
Varian yang bagus SelectEquivalents. Saya pikir, saya akan tetap TagOnElementsebagai default kedua default Identitykarena ini adalah yang paling sering digunakan. Saya tidak berpikir saya akan memasukkan FinalOp, juga, karena dapat ditangani di dalam OpOnTaggedElems. Saya juga mempersingkat nama-nama opsi, karena panjangnya terasa canggung untuk mengetik. Coba TagFunction, TransformElement, TransformResults, dan TagPatternsebagai gantinya. Keduanya, TagPatterndan MapLevelmerupakan tambahan yang bagus untuk fungsi, dan penulisan ulang yang baik, secara keseluruhan.
rcollyer
Terima kasih atas komentar Anda rcollyer. Saya memperhitungkannya dan juga meningkatkan keterbacaan kode. Saya menyimpan FinalFunction karena berfungsi pada hasil Reap, misalnya jika Anda ingin mengurutkan hasil akhir Anda dengan tag jika Anda menyimpannya.
faysou
12

Fungsi utilitas saya (saya memiliki ini bawaan untuk MASH, yang disebutkan dalam pertanyaan):

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).   *)
Dreeves
sumber
Untuk fungsi "masing-masing", lihat stackoverflow.com/questions/160216/foreach-loop-in-mathematica
dreeves
11

Satu trik yang saya gunakan, yang memungkinkan Anda untuk meniru cara sebagian besar fungsi bawaan bekerja dengan argumen buruk (dengan mengirim pesan dan kemudian mengembalikan seluruh bentuk tidak dievaluasi) mengeksploitasi kekhasan cara Conditionbekerja ketika digunakan dalam definisi. Jika foohanya bekerja dengan satu argumen:

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

Jika Anda memiliki kebutuhan yang lebih kompleks, mudah untuk memperhitungkan validasi argumen dan pembuatan pesan sebagai fungsi independen. Anda dapat melakukan lebih banyak hal rumit dengan menggunakan efek samping di Conditionluar hanya menghasilkan pesan, tetapi menurut saya sebagian besar dari mereka termasuk dalam kategori "peretasan busuk" dan harus dihindari jika mungkin.

Juga, dalam kategori "metaprogramming", jika Anda memiliki file paket Mathematica ( .m), Anda bisa menggunakan "HeldExpressions"elemen untuk mendapatkan semua ekspresi dalam file yang dibungkus HoldComplete. Ini membuat pelacakan hal-hal menjadi lebih mudah daripada menggunakan pencarian berbasis teks. Sayangnya, tidak ada cara mudah untuk melakukan hal yang sama dengan notebook, tetapi Anda bisa mendapatkan semua ekspresi input menggunakan sesuatu seperti berikut:

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

Terakhir, Anda dapat menggunakan fakta yang Modulemengemulasi penutupan leksikal untuk membuat setara dengan jenis referensi. Berikut tumpukan sederhana (yang menggunakan variasi Conditiontrik penanganan kesalahan sebagai bonus):

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]

Sekarang Anda dapat mencetak elemen daftar dalam urutan terbalik dengan cara yang tidak perlu berbelit-belit!

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

 While[!EmptyQ[stack],
  Print[Peek@stack];
  Pop@stack]]
Pillsy
sumber
1
+1 untuk HeldExpressionselemen dalam paket, tidak menyadarinya. Saya biasanya mengimpor sebagai string dan kemudian menggunakan ToExpressiondengan HoldCompletesebagai arg terakhir. Mengenai menggunakan Conditionuntuk pesan - ini telah menjadi teknik standar dalam penulisan paket setidaknya sejak tahun 1994. Mengenai kegigihan melalui Modulevars - Saya telah memiliki posting panjang tentang itu di Mathgroup beberapa waktu lalu: groups.google.com/group/comp.soft- sys.math.mathematica / ... (posting ketiga saya di utas itu), ini sejalan dan memiliki tautan ke beberapa contoh penggunaan nontrivial.
Leonid Shifrin
@Leonid Shifrin: Saya menganggapnya Conditionsebagai pengetahuan, mungkin dari rekan kerja, tetapi tidak menyadari bahwa itu adalah teknik standar. Tautan tentang menggunakan Modulesimbol sebagai tipe referensi menarik!
Pillsy
+1, saya tidak pernah memikirkan itu. Semakin banyak saya belajar tentang bahasa ini, semakin kuat rasanya.
rcollyer
@ Pily apa tujuan melakukan tumpukan seperti itu?
Mr.Wizard
@ Mr.Wizard: Saya baru saja memilih salah satu struktur data yang bisa berubah yang paling sederhana yang bisa saya pikirkan untuk menggambarkan teknik ini.
Pillsy
11

Definisi simbol sistem pencetakan tanpa konteks yang diawali

The contextFreeDefinition[]Fungsi bawah akan mencoba untuk mencetak definisi simbol tanpa konteks umum paling ditambahkan. Definisi kemudian dapat disalin ke Workbench dan diformat untuk dibaca (pilih, klik kanan, Sumber -> 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]]

dengan Aturan []

Peringatan: Fungsi ini tidak melokalisasi variabel dengan cara Withdan cara yang sama Module, yang berarti bahwa konstruksi pelokalan bersarang tidak akan berfungsi seperti yang diharapkan. withRules[{a -> 1, b -> 2}, With[{a=3}, b_ :> b]] akan menggantikan adan bdi dalam sarang Withdan Rule, sementara Withtidak melakukan ini.

Ini adalah varian Withyang menggunakan aturan alih-alih =dan :=:

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

Saya menemukan ini berguna saat membersihkan kode yang ditulis selama variabel percobaan dan pelokalan. Kadang-kadang saya berakhir dengan daftar parameter dalam bentuk {par1 -> 1.1, par2 -> 2.2}. Dengan withRulesnilai parameter mudah untuk menyuntikkan ke dalam kode yang sebelumnya ditulis menggunakan variabel global.

Penggunaannya seperti With:

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

Antialiasing grafis 3D

Ini adalah teknik yang sangat sederhana untuk antialias grafik 3D bahkan jika perangkat keras grafis Anda tidak mendukungnya secara asli.

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

Ini sebuah contoh:

Grafik Mathematica Grafik Mathematica

Perhatikan bahwa nilai besar natau ukuran gambar besar cenderung mengekspos bug driver grafis atau memperkenalkan artefak.


Fungsionalitas notebook beda

Fungsionalitas notebook beda tersedia dalam <<AuthorTools`paket, dan (setidaknya dalam versi 8) dalam NotebookTools`konteks tidak berdokumen . Ini adalah GUI kecil untuk membedakan dua notebook yang saat ini terbuka:

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]]}]
  ]

Grafik Mathematica

Szabolcs
sumber
Semua akan menyenangkan, tetapi ini tidak benar-benar melokalisasi variabel, seperti yang Anda lihat dengan menetapkan mengatakan a = 3; b = 4;sebelum panggilan contoh Anda, dan kemudian menelepon withRules. Anda dapat menyimpannya dengan bukannya menggunakan berikut: SetAttributes[withRules, HoldAll];withRules[rules_, expr_] := Unevaluated[expr] /. Unevaluated[rules]. Perbedaan antara semantik pada waktu Withitu: 1. sisi peraturan sekarang tidak dievaluasi 2. withRulestidak menyelesaikan konflik penamaan dengan konstruk pelingkupan batin seperti Withhalnya. Yang terakhir cukup serius - menjadi hal yang baik atau buruk tergantung pada kasusnya.
Leonid Shifrin
@Leonid Anda sepenuhnya benar, sepertinya saya tidak pernah belajar tentang memeriksa kode dengan benar sebelum memposting ... ketika saya menggunakan ini saya praktis tidak pernah memberikan nilai ke variabel, tetapi itu adalah masalah yang cukup serius, Anda benar. Apa pendapat Anda tentang versi yang diperbaiki? (Saya tidak benar-benar peduli tentang tidak menangani sarang With. Ini tidak selalu bekerja dengan konstruk lokalisasi builtin, misalnya With[{a=1}, Block[{a=2}, a]]. Apakah Anda pikir ada alasan bagus mengapa sarang Blocktidak terlokalisasi di sana, seperti bersarang Withdan Moduletidak?)
Szabolcs
@Leonid saya tidak hanya menggunakan Unevaluated[rules]karena saya ingin x -> 1+1mengevaluasi RHS.
Szabolcs
@Leonid Anda benar, masalah pelokalan bersarang bisa menjadi sangat serius. Saya pikir bersarang Withmudah dikenali dan dihindari, tetapi polanya tidak: With[{a = 1}, a_ -> a]melokalisasi bagian dalam asementara withRulestidak. Apakah Anda tahu jika ada cara untuk mengakses mekanisme lokalisasi internal Mathematica dan membuat konstruksi baru (mirip dengan Rule) yang juga melokalkan? Saya mungkin akan menghapus jawaban ini nanti karena lebih berbahaya daripada berguna, tetapi saya ingin bermain dengannya sedikit lebih dulu.
Szabolcs
Saya pikir penggunaan Anda InheritedBlockcukup keren dan menyelesaikan masalah dengan sangat elegan. Mengenai konflik pelingkupan, biasanya pengikatan untuk pelingkupan leksikal terjadi pada "waktu pengikatan leksikal", yaitu - sebelum run-time, sementara pelingkupan dinamis mengikat pada run-time, yang mungkin menjelaskannya. Anda dapat membandingkan ini dengan kasus serupa untuk Module, yang memungkinkan penggunaan yang konstruktif (lihat misalnya di sini stackoverflow.com/questions/7394113/... ). Masalahnya adalah bahwa Blockperlu beberapa simbol untuk ...
Leonid Shifrin
9

Fungsi murni rekursif ( #0) tampaknya menjadi salah satu sudut bahasa yang lebih gelap. Berikut adalah beberapa contoh non-sepele dari penggunaannya, di mana ini benar-benar berguna (bukan berarti mereka tidak dapat dilakukan tanpa itu). Berikut ini adalah fungsi yang cukup ringkas dan cukup cepat untuk menemukan komponen yang terhubung dalam grafik, diberikan daftar tepi yang ditentukan sebagai pasangan simpul:

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]];

Apa yang terjadi di sini adalah bahwa kita pertama-tama memetakan simbol boneka pada masing-masing nomor dhuwur, dan kemudian mengatur cara itu, mengingat sepasang simpul {f[5],f[10]}, katakanlah, kemudian f[5]akan dievaluasi f[10]. Fungsi murni rekursif digunakan sebagai kompresor jalur (untuk mengatur memoisasi sedemikian rupa sehingga alih-alih rantai panjang seperti f[1]=f[3],f[3]=f[4],f[4]=f[2], ..., nilai memoized dikoreksi setiap kali "root" baru dari komponen ditemukan. Ini memberikan kecepatan yang signifikan. Karena kami menggunakan penugasan, kami membutuhkannya Hold Hold, yang membuat konstruksi ini menjadi lebih tidak jelas dan lebih menarik). Fungsi ini adalah hasil dari diskusi Mathgroup on dan off-line yang melibatkan Fred Simons, Szabolcs Horvat, DrMajorBob dan Anda benar-benar. Contoh:

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>>}}

Ini tentu jauh lebih lambat daripada built-in, tetapi untuk ukuran kode, IMO masih cukup cepat.

Contoh lain: di sini adalah realisasi rekursif Select, berdasarkan daftar tertaut dan fungsi murni rekursif:

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

Sebagai contoh,

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}}

Namun itu tidak benar tail recursive, dan akan meniup stack (crash the kernel) untuk daftar yang lebih besar. Berikut ini adalah versi ekor-rekursif:

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]], {}]];

Sebagai contoh,

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
sumber
Fungsi untuk komponen yang terhubung masih menjadi favorit saya :-)
Szabolcs
@Sabolabol Ya, ini sangat keren. Anda dan Fred melakukan sebagian besar, Bobby dan saya hanya menambahkan beberapa penyempurnaan, IIRC.
Leonid Shifrin
8

Ini adalah resep dari buku Stan Wagon ... gunakan ketika Plot bawaan berperilaku tidak menentu karena kurangnya presisi

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]]]]];

Saya sering menggunakan trik berikut dari Kristjan Kannike ketika saya membutuhkan perilaku "seperti kamus" dari downgrade Mathematica

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]

Ketika hasil evaluasi membingungkan, kadang-kadang membantu membuang langkah-langkah evaluasi ke dalam file teks

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]]
Yaroslav Bulatov
sumber
Contoh penggunaan akan bagus. Cobalah memposting satu ketika Anda punya waktu.
Dr. belisarius
Apakah Anda kenal Kristjan? Saya dulu bekerja di kelompok yang sama dengannya di Helsinki. Pria yang baik, dunia kecil.
Timo
Tidak, menemukan kodenya di web. Sebenarnya, mencoba untuk mengirim email kepadanya untuk memperbaiki bug kecil dalam kode, tetapi email di halaman webnya tidak lagi berfungsi
Yaroslav Bulatov
8

Dimungkinkan untuk menjalankan MathKernel dalam mode batch dengan menggunakan opsi baris perintah-batchinput-batchoutput tanpa dokumen dan :

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

(di mana input.mfile input batch diakhiri dengan karakter baris baru, outputfile.txtadalah file yang hasilnya akan dialihkan).

Dalam Mathematica v.> = 6 MathKernel memiliki opsi baris perintah tanpa dokumen:

-noicon

yang mengontrol apakah MathKernel akan memiliki ikon yang terlihat di Taskbar (setidaknya di bawah Windows).

FrontEnd (setidaknya dari v.5) memiliki opsi baris perintah tanpa dokumen

-b

yang menonaktifkan splash-screen dan memungkinkan untuk menjalankan Mathematica FrontEnd jauh lebih cepat

dan opsi

-directlaunch

yang menonaktifkan mekanisme yang meluncurkan versi Mathematica terbaru yang diinstal alih-alih meluncurkan versi yang terkait dengan file .nb di registri sistem.

Cara lain untuk melakukan ini mungkin adalah :

Alih-alih meluncurkan biner Mathematica.exe di direktori instalasi, jalankan biner Mathematica.exe di SystemFiles \ FrontEnd \ Binaries \ Windows. Yang pertama adalah program peluncur sederhana yang berusaha paling keras untuk mengarahkan permintaan untuk membuka notebook untuk menjalankan salinan antarmuka pengguna. Yang terakhir adalah biner antarmuka pengguna itu sendiri.

Berguna untuk menggabungkan opsi baris perintah terakhir dengan menyetel opsi FrontEnd global VersionedPreferences->True yang menonaktifkan berbagi preferensi antara berbagai versi Mathematica yang diinstal :

SetOptions[$FrontEnd, VersionedPreferences -> True]

(Di atas harus dievaluasi dalam versi Mathematica terbaru yang diinstal.)

Dalam Mathematica 8 ini dikontrol dalam dialog Preferensi, di panel Sistem, di bawah pengaturan "Buat dan pertahankan preferensi front end khusus versi" .

Dimungkinkan untuk mendapatkan daftar opsi baris perintah dari FrontEnd yang tidak lengkap dengan menggunakan kunci tidak berdokumen -h(kode untuk Windows):

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

memberi:

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

Pilihan lain termasuk:

-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

Apakah ada opsi baris perintah yang berpotensi bermanfaat dari MathKernel dan FrontEnd? Silakan bagikan jika Anda tahu.

Pertanyaan terkait .

Alexey Popkov
sumber
"Kecocokan yang serasi?" Apa artinya?
Mr.Wizard
@ Mr.Wizard Mungkin opsi ini hanya memiliki arti di bawah sistem 64-bit dalam kombinasi dengan opsi -32dan berarti bahwa bitness dari MathKernel yang digunakan oleh FrontEnd akan cocok dengan bitness dari sistem operasi (64 bit). Tampaknya dalam kasus lain opsi ini tidak akan mengubah apa pun.
Alexey Popkov
7

Peretasan favorit saya adalah makro penghasil kode kecil yang memungkinkan Anda untuk mengganti sekelompok perintah boilerplate standar dengan satu perintah pendek. Atau, Anda dapat membuat perintah untuk membuka / membuat buku catatan.

Inilah yang saya gunakan untuk sementara waktu dalam alur kerja Mathematica saya sehari-hari. Saya menemukan diri saya melakukan banyak hal berikut:

  1. Buat notebook memiliki konteks pribadi, muat paket yang saya butuhkan, buat otomatis.
  2. Setelah bekerja dengan notebook ini sebentar, saya ingin melakukan beberapa perhitungan awal goresan di notebook terpisah, dengan konteks pribadi sendiri, sementara memiliki akses ke definisi yang saya gunakan di notebook "utama". Karena saya mengatur konteks pribadi, ini perlu menyesuaikan $ ContextPath secara manual

Melakukan semua ini dengan tangan berulang-ulang adalah rasa sakit, jadi mari kita mengotomatisasi! Pertama, beberapa kode utilitas:

(* 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];

Sekarang, mari kita buat makro yang akan menempatkan sel-sel berikut di buku catatan:

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

Dan inilah 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];
      ]
 ]

Sekarang ketika saya mengetik MyPrivatize[]adalah menciptakan konteks pribadi dan memuat paket standar saya. Sekarang mari kita membuat perintah yang akan membuka buku catatan awal baru dengan konteks pribadi sendiri (sehingga Anda dapat meretas di sana dengan pengabaian liar tanpa risiko mengacaukan definisi), tetapi memiliki akses ke konteks Anda saat ini.

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

Yang keren tentang ini adalah karena SelfDestruct, ketika perintah dijalankan tidak meninggalkan jejak di notebook saat ini - yang bagus, karena kalau tidak, itu hanya akan membuat kekacauan.

Untuk poin gaya tambahan, Anda dapat membuat pemicu kata kunci untuk makro ini menggunakan InputAutoReplacements, tapi saya akan meninggalkan ini sebagai latihan untuk pembaca.

Leo Alekseyev
sumber
7

PutAppend dengan PageWidth -> Infinity

Dalam Mathematica, penggunaan PutAppendperintah adalah cara yang paling mudah untuk mempertahankan file log yang sedang berjalan dengan hasil perhitungan perantara. Tetapi ia menggunakan PageWith->78pengaturan default ketika mengekspor ekspresi ke file dan karenanya tidak ada jaminan bahwa setiap output antara hanya akan mengambil satu baris dalam log.

PutAppendtidak memiliki opsi itu sendiri tetapi menelusuri evaluasinya mengungkapkan bahwa itu didasarkan pada OpenAppendfungsi yang memiliki PageWithopsi dan memungkinkan mengubah nilai defaultnya dengan SetOptionsperintah:

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

Jadi kita bisa PutAppendmenambahkan hanya satu baris sekaligus dengan menetapkan:

SetOptions[OpenAppend, PageWidth -> Infinity]

MEMPERBARUI

Ada bug yang diperkenalkan di versi 10 (diperbaiki di versi 11.3): SetOptionstidak lagi memengaruhi perilaku OpenWritedan OpenAppend.

Solusinya adalah dengan mengimplementasikan versi Anda sendiri PutAppenddengan PageWidth -> Infinityopsi eksplisit :

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

Perhatikan bahwa kami juga dapat mengimplementasikannya melalui WriteStringseperti yang ditunjukkan dalam jawaban ini , tetapi dalam hal ini akan diperlukan untuk terlebih dahulu mengubah ekspresi menjadi InputFormvia yang sesuai ToString[expr, InputForm].

Alexey Popkov
sumber
6

Aku hanya melihat melalui salah satu paket saya untuk dimasukkan dalam ini, dan menemukan beberapa pesan yang saya didefinisikan bahwa keajaiban pekerjaan: Debug::<some name>. Secara default, mereka dimatikan, jadi jangan menghasilkan banyak overhead. Tapi, saya bisa membuang kode saya dengan mereka, dan menyalakannya jika saya perlu mencari tahu persis bagaimana sedikit kode berperilaku.

rcollyer
sumber
Dari Bantuan> Sejak Versi 2.0 (dirilis pada tahun 1991), Debug telah digantikan oleh Trace.
Dr. belisarius
1
@ Belisarius, Anda melewatkan intinya. Ini bukan fungsi Debugmaupun bukan Trace; itu adalah satu set pesan yang saya buat sehingga saya bisa membuang kode saya untuk menghidupkan / mematikan sesuka hati. Mereka diawali dengan kata Debug, dengan cara yang sama usagepesan diawali dengan nama fungsi. Ini menyediakan fungsi yang sama dengan menempatkan banyak coutpernyataan dalam kode c ++.
rcollyer
1
Ohh maaf. Saya bingung karena saya tidak pernah lulus dari taman kanak-kanak karena tidak belajar "Capitals is for Countries": D
Dr. belisarius
6

Salah satu hal yang menggangguku tentang konstruksi pelingkupan bawaan adalah bahwa mereka mengevaluasi semua definisi variabel lokal sekaligus, jadi Anda tidak dapat menulis misalnya

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

Jadi beberapa waktu yang lalu saya datang dengan makro bernama WithNest yang memungkinkan Anda untuk melakukan ini. Saya merasa berguna, karena memungkinkan Anda menjaga binding variabel lokal tanpa harus melakukan sesuatu seperti

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

Pada akhirnya, cara terbaik yang bisa saya temukan untuk melakukan ini adalah dengan menggunakan simbol khusus untuk membuatnya lebih mudah untuk mengulang daftar bindings, dan saya memasukkan definisi ke dalam paketnya sendiri untuk menjaga simbol ini tersembunyi. Mungkin seseorang memiliki solusi yang lebih sederhana untuk masalah ini?

Jika Anda ingin mencobanya, masukkan yang berikut ke dalam file bernama 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
sumber
Janus memposting versi ini, dan referensi pertanyaan Anda di MathGroup: stackoverflow.com/questions/4190845/custom-notation-question/…
Mr.Wizard
Terima kasih telah menunjukkannya! Sudah lama sejak saya melihat hal-hal ini, dan menarik untuk melihat semua pendekatan lain ini.
DGrady
5

Yang ini ditulis oleh Alberto Di Lullo, (yang tampaknya tidak berada di Stack Overflow).

CopyToClipboard, untuk Mathematica 7 (di Mathematica 8, bawaannya)

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

Posting asli: http://forums.wolfram.com/mathgroup/archive/2010/Jun/msg00148.html

Saya telah menemukan rutinitas ini berguna untuk menyalin bilangan real yang besar ke clipboard dalam bentuk desimal biasa. MisalnyaCopyToClipboard["123456789.12345"]

Cell[OutputFormData@expr] menghapus tanda kutip dengan rapi.

Chris Degnen
sumber
5

Kode ini membuat palet yang mengunggah pilihan ke Stack Exchange sebagai gambar. Pada Windows, disediakan tombol ekstra yang memberikan rendering pemilihan yang lebih setia.

Salin kode ke sel buku catatan dan evaluasi. Kemudian keluarkan palet dari output, dan instal menggunakanPalettes -> Install Palette...

Jika Anda memiliki masalah dengan itu, kirim komentar di sini. Unduh versi notebook di sini .


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
sumber
4

Saya yakin banyak orang telah menemui situasi di mana mereka menjalankan beberapa hal, menyadari itu tidak hanya menghambat program, tetapi mereka juga belum menabung selama 10 menit terakhir!

EDIT

Setelah menderita ini selama beberapa waktu, saya suatu hari menemukan bahwa seseorang dapat membuat auto-save dari dalam kode Mathematica . Saya pikir menggunakan penyelamatan otomatis seperti itu telah banyak membantu saya di masa lalu, dan saya selalu merasa bahwa kemungkinan itu sendiri adalah sesuatu yang tidak banyak orang sadari dapat mereka lakukan.

Kode asli yang saya gunakan ada di bagian bawah. Berkat komentar yang saya temukan ternyata bermasalah, dan jauh lebih baik melakukannya dengan cara alternatif, menggunakan ScheduledTask(yang hanya akan berfungsi di Mathematica 8).

Kode untuk ini dapat ditemukan dalam jawaban ini dari Sjoerd C. de Vries (Karena saya tidak yakin apakah boleh menyalinnya ke sini, saya meninggalkannya sebagai tautan saja.)


Solusi di bawah ini menggunakan Dynamic. Ini akan menghemat notebook setiap 60 detik, tetapi tampaknya hanya jika selnya terlihat . Saya meninggalkannya di sini hanya untuk alasan penyelesaian. (dan untuk pengguna Mathematica 6 dan 7)

/ EDIT

Untuk mengatasinya saya menggunakan kode ini di awal buku catatan:

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

Ini akan menghemat pekerjaan Anda setiap 60 detik.
Saya lebih suka NotebookAutoSave[]karena menyimpan sebelum input diproses, dan karena beberapa file lebih banyak teks daripada input.

Saya awalnya menemukannya di sini: http://en.wikipedia.org/wiki/Talk:Mathematica#Criticisms

Perhatikan bahwa sekali menjalankan baris ini, penyimpanan akan terjadi bahkan jika Anda menutup dan membuka kembali file Anda (selama pembaruan dinamis diaktifkan).

Selain itu, karena tidak ada undo di Mathematica , berhati-hatilah untuk tidak menghapus semua konten Anda, karena menyimpan akan membuatnya tidak dapat dibalikkan (sebagai langkah pencegahan, saya menghapus kode ini dari setiap buku catatan yang sudah selesai)

tsvikas
sumber
Anda juga dapat menyimpannya dengan nama yang berbeda (misalnya dengan menambahkan waktu dan tanggal saat ini ke akhir nama file) dan mungkin di direktori tertentu ("Pencadangan", katakanlah). ini akan seperti bentuk versi primitif.
acl
Anda dapat melakukan sesuatu seperti NotebookSave[SelectedNotebook[], "work-" <> IntegerString[i] <> ".nb"]; i++, tetapi saya pikir segala jenis referensi ke nama notebook saat ini akan menjadi rekursif.
tsvikas
2
Saya pikir Dynamicobjek hanya akan di-refresh ketika terlihat, jadi saya tidak akan yakin bahwa metode ini akan berfungsi jika Anda menggulir Dynamicobjek keluar dari area yang terlihat. Kemudian lagi, saya belum mencoba. Bagaimanapun, saya hanya menawarkannya sebagai saran.
acl
1
Anda dapat menguji ini dengan menggunakan Dynamic[Refresh[i++, UpdateInterval -> 1, TrackedSymbols -> {}]]. Gulir angka yang bertambah dari pandangan, tunggu sebentar, gulir ke belakang dan lihat jumlahnya tidak bertambah 60. Tentang UpdateInterval: ini biasanya digunakan jika memungkinkan, tetapi jika kode Anda mencakup variabel yang berubah, perubahan ini memicu penyegaran baru sebelum Interval berakhir. Coba baris di atas tanpaTrackedSymbols
Sjoerd C. de Vries
1
@ j0ker5 Cobalah kode saya di atas dan Anda dapat melihat bahwa UpdateInterval tidak selalu memaksa pembaruan untuk diberi jarak dengan interval yang ditentukan. Kode ini juga menunjukkan bahwa Dynamic hanya berfungsi jika sel yang dikandungnya terlihat di frontend . Ini benar-benar berhenti saat itu tidak terlihat. Orang-orang seharusnya tidak mempercayai kode ini untuk menyimpan file mereka karena tidak. Berbahaya
Sjoerd C. de Vries
3

Saya merasa sangat berguna ketika mengembangkan paket untuk menambahkan pintasan keyboard ini ke SystemFiles/FrontEnd/TextResources/Windows/KeyEventTranslations.trfile saya .

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

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

Berikutnya untuk setiap Packagename.msaya membuat PackagenameTest.nbbuku catatan untuk pengujian dan 2 sel pertama dari buku catatan uji ditetapkan sebagai sel inisialisasi. Di sel pertama saya taruh

Needs["PackageManipulations`"]

untuk memuat pustaka PackageManipulations yang sangat berguna yang ditulis oleh Leonid. Sel kedua berisi

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

yang semuanya melakukan reload paket yang sebenarnya. Perhatikan dua baris pertama yang ada hanya untuk Removesemua simbol karena saya ingin menjaga konteksnya sebersih mungkin.

Maka alur kerja untuk menulis dan menguji suatu paket menjadi seperti ini.

  1. Simpan perubahan ke Packagename.m.
  2. Pergi PackagenameTest.nbdan lakukan CTRL + ALT + i.

Ini menyebabkan sel inisialisasi memuat ulang paket, yang membuat pengujian menjadi sangat sederhana.

nixeagle
sumber
1

Fungsi berikut format[expr_]dapat digunakan untuk indent / memformat mathematicaekspresi yang tidak diformat yang membentang di atas halaman

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
sumber
Untuk apa Anda menggunakan ini dalam praktik? Outputnya agak terlalu "lucu" untuk bisa dibaca baik ketika diterapkan pada kode Anda atau ke data (daftar, format@RandomInteger[10,{3,3}]): pastebin.com/nUT54Emq Karena Anda sudah memiliki dasar-dasarnya dan Anda tertarik pada ini, dapatkah Anda meningkatkan kode ke menghasilkan pemformatan bermanfaat yang dapat dibaca? Maka langkah selanjutnya adalah membuat tombol tempel yang akan membuat sel input dengan kode Mathematica yang terindentasi dengan baik (lebih baik menjaga komentar !!) Lihat juga pertanyaan saya yang terkait .
Szabolcs