Có gì trong túi công cụ Mathicala của bạn? [đóng cửa]


152

Chúng ta đều biết rằng Mathicala rất tuyệt, nhưng nó cũng thường thiếu chức năng quan trọng. Bạn sử dụng loại gói / công cụ / tài nguyên bên ngoài nào với Mathicala?

Tôi sẽ chỉnh sửa (và mời bất kỳ ai khác làm như vậy) bài đăng chính này để bao gồm các tài nguyên tập trung vào khả năng ứng dụng chung trong nghiên cứu khoa học và càng nhiều người càng thấy hữu ích. Hãy thoải mái đóng góp bất cứ điều gì, ngay cả các đoạn mã nhỏ (như tôi đã làm dưới đây cho một thói quen thời gian).

Ngoài ra, các tính năng không có giấy tờ và hữu ích trong Mathematica 7 và hơn thế nữa bạn đã tìm thấy chính mình, hoặc đào lên từ một số giấy / trang web được chào đón nhất.

Vui lòng bao gồm một mô tả ngắn hoặc nhận xét về lý do tại sao một cái gì đó tuyệt vời hoặc tiện ích nó cung cấp. Nếu bạn liên kết đến sách trên Amazon bằng các liên kết liên kết, vui lòng đề cập đến nó, ví dụ: bằng cách đặt tên của bạn sau liên kết.


Gói:

  1. LevelSchemelà một gói giúp mở rộng đáng kể khả năng của Mathicala để tạo ra các lô đẹp mắt. Tôi sử dụng nó nếu không phải cho bất cứ điều gì khác sau đó để kiểm soát nhiều, nhiều cải thiện đối với các dấu tick của khung / trục. Phiên bản mới nhất của nó được gọi là SciDraw, và nó sẽ được phát hành vào năm nay.
  2. David Park's Presentation Package(US $ 50 - không tính phí cập nhật)
  3. grassmannOpsGói của Jeremy Michelson cung cấp các tài nguyên để thực hiện đại số và tính toán với các biến và toán tử Grassmann có quan hệ giao hoán không tầm thường.
  4. GrassmannAlgebraGói và cuốn sách của John Brown để làm việc với đại số Grassmann và Clifford.
  5. RISC (Viện nghiên cứu tính toán biểu tượng) có nhiều gói cho Mathicala (và các ngôn ngữ khác) có sẵn để tải xuống. Đặc biệt, có theorema cho minh định lý tự động, và vô số các gói cho tổng mang tính biểu tượng, phương trình vi phân, vv tại các trang phần mềm nhóm của thuật toán tổ hợp .

Công cụ:

  1. MASHlà kịch bản Perl xuất sắc của Daniel Reeves về cơ bản cung cấp hỗ trợ kịch bản cho Mathematica v7. (Bây giờ được xây dựng kể từ Mathicala 8 với -scripttùy chọn.)
  2. Một alternate Mathematica shellvới đầu vào đọc GNU (chỉ sử dụng python, * nix)
  3. Gói ColourMaths cho phép bạn chọn trực quan các phần của biểu thức và thao tác với chúng. http://www.dbaileyconsultancy.co.uk/colour_maths/colour_maths.html

Tài nguyên:

  1. Kho lưu trữ riêng của Wolfram MathSourcecó rất nhiều hữu ích nếu các máy tính xách tay hẹp cho các ứng dụng khác nhau. Ngoài ra kiểm tra các phần khác như

  2. The Mathicala Wikibook .

Sách:

  1. Lập trình Mathicala: một giới thiệu nâng cao của Leonid Shifrin ( web, pdf) là phải đọc nếu bạn muốn làm bất cứ điều gì hơn Đối với các vòng lặp trong Mathicala. Chúng tôi có niềm vui khi có Leonidchính mình trả lời các câu hỏi ở đây.
  2. Phương pháp lượng tử với Mathicala của James F. Feagin ( amazon )
  3. Cuốn sách Mathicala của Stephen Wolfram ( amazon ) ( web)
  4. Đề cương của Schaum ( amazon )
  5. Mathicala in Action của Stan Wagon ( amazon ) - 600 trang ví dụ gọn gàng và chuyển sang phiên bản Mathicala 7. Các kỹ thuật trực quan đặc biệt tốt, bạn có thể thấy một số trong số chúng trên tác giả Demonstrations Page.
  6. Các nguyên tắc lập trình toán học của Richard Gaylord ( pdf) - Một giới thiệu ngắn gọn về hầu hết những gì bạn cần biết về lập trình Mathicala.
  7. Mathicala Cookbook của Sal Mangano được xuất bản bởi O'Reilly 2010 832 trang. - Được viết theo phong cách O'Reilly Cookbook nổi tiếng: Vấn đề - Giải pháp. Đối với trung gian.
  8. Phương trình vi phân với Mathicala, Ed 3. Elsevier 2004 Amsterdam của Martha L. Abell, James P. Braselton - 893 trang Dành cho người mới bắt đầu, học giải DE và Mathicala cùng một lúc.

Các tính năng không có giấy tờ (hoặc tài liệu hiếm):

  1. Làm thế nào để tùy chỉnh các phím tắt Mathicala. Xem this question.
  2. Cách kiểm tra các mẫu và hàm được sử dụng bởi các hàm riêng của Mathematica. Xemthis answer
  3. Làm thế nào để đạt được kích thước phù hợp cho GraphPlots trong Mathematica? Xem this question.
  4. Làm thế nào để sản xuất tài liệu và thuyết trình với Mathematica. Xem this question.

2
Mathematica 8 được ra mắt với tích hợp kịch bản shell tốt hơn nhiều. wolfram.com/mathematica/new-in-8/mathematica-shell-scripts
Joshua Martell

2
+1, cho LevelScheme. Nó hơi chậm, đôi khi. Nhưng, nó có một phương pháp lành mạnh để tạo dấu tick, và việc tạo bố cục xứng đáng cho tạp chí cho đồ họa sau đó Grid, hoặc bất cứ thứ gì tương tự sẽ dễ dàng hơn nhiều .
rcollyer

2
Theo đề xuất của Alexey trong các bình luận về câu hỏi này stackoverflow.com/questions/5152551/ , tôi đã đề xuất đổi tên thẻ cho Mathicala tại đây: meta.stackexchange.com/questions/81152/ . Hãy xem và upvote nếu bạn đồng ý. Tôi đăng nó ở đây vì câu hỏi này có rất nhiều mục yêu thích trong cộng đồng Mma ở đây.
Tiến sĩ belisarius

1
Tất cả, câu hỏi này thực sự nên là wiki cộng đồng vì tất cả các lý do thông thường: nó không có câu trả lời chính xác và nó là một danh sách nhiều hơn bất cứ điều gì khác. Tôi xin lỗi tất cả những người đã thu được lợi nhuận lớn từ câu hỏi này.
rcollyer

2
Những câu trả lời cho câu hỏi này là xây dựng, nó cần được mở lại.
MR

Câu trả lời:


29

Tôi đã từng đề cập đến điều này trước đây, nhưng công cụ tôi thấy hữu ích nhất là một ứng dụng ReapSowbắt chước / mở rộng hành vi của GatherBy:

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

Điều này cho phép tôi nhóm các danh sách theo bất kỳ tiêu chí nào và biến đổi chúng trong quy trình. Cách thức hoạt động của nó là một hàm tiêu chí ( f) gắn thẻ cho từng mục trong danh sách, mỗi mục sau đó được chuyển đổi bởi hàm được cung cấp thứ hai ( g) và đầu ra cụ thể được điều khiển bởi hàm thứ ba ( h). Hàm hchấp nhận hai đối số: thẻ và danh sách các mục được thu thập có thẻ đó. Các mục giữ nguyên thứ tự ban đầu của chúng, vì vậy nếu bạn đặt h = #1&thì bạn sẽ nhận được một loại chưa được sắp xếp Union, như trong các ví dụ cho Reap. Nhưng, nó có thể được sử dụng để xử lý thứ cấp.

Để làm ví dụ về tiện ích của nó, tôi đã làm việc với Wannier90 , đưa Hamiltonian phụ thuộc không gian vào một tệp trong đó mỗi dòng là một thành phần khác nhau trong ma trận, như sau

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

Để biến danh sách đó thành một tập hợp các ma trận, tôi đã tập hợp tất cả các danh sách con có cùng tọa độ, biến thông tin thành phần thành quy tắc (ví dụ {i, j} -> Re [Hij] + I Im [Hij]) và sau đó biến các quy tắc được thu thập thành SparseArraytất cả với một lớp lót:

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

Thành thật mà nói, đây là con dao quân đội Thụy Sĩ của tôi, và nó làm cho mọi thứ phức tạp trở nên rất đơn giản. Hầu hết các công cụ khác của tôi là một số miền cụ thể, vì vậy tôi có thể sẽ không đăng chúng. Tuy nhiên, hầu hết, nếu không phải tất cả, trong số họ tham khảo SelectEquivalents.

Chỉnh sửa : nó không hoàn toàn bắt chước GatherByở chỗ nó không thể nhóm nhiều cấp độ của biểu thức một cách đơn giản nhất GatherBycó thể. Tuy nhiên, Maphoạt động chỉ tốt cho hầu hết những gì tôi cần.

Ví dụ : @Yaroslav Bulatov đã yêu cầu một ví dụ khép kín. Đây là một trong những nghiên cứu của tôi đã được đơn giản hóa rất nhiều. Vì vậy, giả sử chúng ta có một tập hợp các điểm trong một mặt phẳng

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

và chúng tôi muốn giảm số lượng điểm bằng một tập hợp các phép toán đối xứng. (Đối với người tò mò, chúng tôi đang tạo nhóm nhỏ của mỗi điểm.) Trong ví dụ này, chúng ta hãy sử dụng trục xoay bốn lần về trục z

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

Sử dụng SelectEquivalentschúng ta có thể nhóm các điểm tạo ra cùng một tập hợp hình ảnh theo các thao tác này, tức là chúng tương đương nhau, sử dụng các điểm sau

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

trong đó tạo ra 3 danh sách con chứa các điểm tương đương. (Lưu ý, Unionở đây rất quan trọng vì nó đảm bảo rằng cùng một hình ảnh được tạo ra bởi mỗi điểm. Ban đầu, tôi đã sử dụng Sort, nhưng nếu một điểm nằm trên trục đối xứng, thì nó bất biến dưới trục xoay về trục đó tạo thêm hình ảnh của chính nó Vì vậy, Unionloại bỏ những hình ảnh bổ sung này. Ngoài ra, GatherBysẽ tạo ra kết quả tương tự.) Trong trường hợp này, các điểm đã ở dạng tôi sẽ sử dụng, nhưng tôi chỉ cần một điểm đại diện từ mỗi nhóm và tôi muốn đếm của các điểm tương đương. Vì, tôi không cần phải biến đổi từng điểm, tôi sử dụngIdentitychức năng ở vị trí thứ hai. Đối với chức năng thứ ba, chúng ta cần phải cẩn thận. Đối số đầu tiên được truyền cho nó sẽ là hình ảnh của các điểm dưới các phép quay mà đối với điểm đó {0,0,0}là một danh sách gồm bốn phần tử giống hệt nhau và sử dụng nó sẽ làm mất đi số đếm. Tuy nhiên, đối số thứ hai chỉ là một danh sách tất cả các thành phần có thẻ đó, vì vậy nó sẽ chỉ chứa {0,0,0}. Trong mã,

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

Lưu ý, bước cuối cùng này có thể dễ dàng được thực hiện bằng

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

Nhưng, thật dễ dàng với điều này và ví dụ ít hoàn thiện hơn ở trên để xem các phép biến đổi rất phức tạp có thể thực hiện được với mức tối thiểu của mã.


Mã Fortran77 ban đầu được cơ cấu lại vào ngày Lễ Tạ ơn năm 1996, và do đó trong nhiều năm được gọi là turkey.f ...: D Đồ họa rất đẹp BTW. Nhớ cho tôi quái vật của Falicov ...
Tiến sĩ belisarius

@ Belisarius, tôi đã không đọc lịch sử, điều đó thật buồn cười. Tôi mới bắt đầu sử dụng Wannier90, nhưng đó là một số Fortranmã được tổ chức tốt nhất và được viết tốt nhất mà tôi đã thấy. Khiến tôi gần như cân nhắc sử dụng Fortran...
rcollyer

Tôi tự hỏi liệu bạn có thể thêm một ví dụ độc lập về Chọn lựa hoạt động hay không
Yaroslav Bulatov

@Yar Tư Bulatov, đã thêm một ví dụ, theo yêu cầu. Hãy cho tôi biết nếu điều này sẽ giúp. Nếu không, chúng ta sẽ thấy những gì chúng ta có thể làm.
rcollyer

Bạn nhận được dấu kiểm cho "câu hỏi" này để đóng góp đoạn mã thú vị nhất.
Timo

57

Một trong những điều hay về giao diện máy tính xách tay Mathicala là nó có thể đánh giá các biểu thức trong bất kỳ ngôn ngữ nào , không chỉ Mathicala. Ví dụ đơn giản, hãy xem xét việc tạo một loại ô đầu vào Shell mới chuyển biểu thức được chứa sang vỏ hệ điều hành để đánh giá.

Đầu tiên, xác định hàm ủy nhiệm đánh giá lệnh văn bản cho trình bao bên ngoài:

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

Đối số thứ hai là cần thiết và bỏ qua vì những lý do sẽ trở nên rõ ràng sau này. Tiếp theo, chúng tôi muốn tạo một phong cách mới gọi là Shell :

  1. Mở một cuốn sổ mới.
  2. Chọn mục menu Định dạng / Chỉnh sửa Biểu định kiểu ...
  3. Trong hộp thoại, bên cạnh Nhập tên kiểu:Shell.
  4. Chọn khung di động bên cạnh kiểu mới.
  5. Chọn mục menu Cell / Show Expression
  6. Ghi đè biểu thức ô bằng Văn bản Bước 6 được đưa ra dưới đây.
  7. Một lần nữa, chọn mục menu Cell / Show Expression
  8. Đóng hộp thoại.

Sử dụng biểu thức ô sau đây làm Văn bản Bước 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"]

Hầu hết các biểu thức này được sao chép trực tiếp từ kiểu Chương trình tích hợp . Những thay đổi chính là những dòng này:

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

Evaluatablecho phép chức năng SHIFT + ENTER cho ô. Đánh giá sẽ gọi việc CellEvaluationFunctionchuyển nội dung ô và loại nội dung là đối số ( shellEvaluatebỏ qua đối số sau). CellFrameLabelschỉ là một điều tốt đẹp để người dùng xác định rằng tế bào này là bất thường.

Với tất cả những điều này, giờ đây chúng ta có thể nhập và đánh giá biểu thức shell:

  1. Trong sổ ghi chép được tạo ở các bước trên, tạo một ô trống và chọn khung ô.
  2. Chọn mục menu Format / Style / Shell .
  3. Nhập lệnh shell hệ điều hành hợp lệ vào ô (ví dụ: 'ls' trên Unix hoặc 'dir' trên Windows).
  4. Nhấn SHIFT + ENTER.

Tốt nhất là giữ kiểu được xác định này trong biểu định kiểu nằm ở trung tâm. Hơn nữa, các hàm đánh giá như shellEvaluateđược xác định tốt nhất là sơ khai sử dụng DeclarePackage trong init.m. Các chi tiết của cả hai hoạt động này nằm ngoài phạm vi của phản ứng này.

Với chức năng này, người ta có thể tạo sổ ghi chép có chứa các biểu thức đầu vào theo bất kỳ cú pháp quan tâm nào. Hàm đánh giá có thể được viết bằng Mathicala thuần túy, hoặc ủy thác bất kỳ hoặc tất cả các phần của đánh giá cho một cơ quan bên ngoài. Xin lưu ý rằng có các móc khác liên quan đến đánh giá tế bào, như CellEpilog, CellPrologCellDynamicExpression.

Một mẫu phổ biến liên quan đến việc viết văn bản biểu thức đầu vào vào một tệp tạm thời, biên dịch tệp bằng một số ngôn ngữ, chạy chương trình và chụp đầu ra để hiển thị cuối cùng trong ô đầu ra. Có rất nhiều chi tiết cần giải quyết khi thực hiện một giải pháp đầy đủ thuộc loại này (như nắm bắt thông báo lỗi đúng cách), nhưng người ta phải đánh giá cao thực tế rằng không chỉ có thể làm những việc như thế này, mà còn thực tế.

Trên một ghi chú cá nhân, chính các tính năng như thế này làm cho giao diện máy tính xách tay trở thành trung tâm của vũ trụ lập trình của tôi.

Cập nhật

Hàm trợ giúp sau đây rất hữu ích để tạo các ô như vậy:

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

Nó được sử dụng như vậy:

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

Bây giờ, nếu shellCell[]được ước tính, ô đầu vào sẽ bị xóa và được thay thế bằng một ô đầu vào mới để đánh giá nội dung của nó dưới dạng lệnh shell.


3
@WReach +100! Tôi ước tôi biết điều này sớm hơn! Đây là công cụ rất hữu ích, đối với tôi ít nhất. Cám ơn vì đã chia sẻ!
Leonid Shifrin

Điều này có vẻ khá spiffy! CellEvaluationFunctiontôi có thể sử dụng để hack cú pháp cấp thấp.
Mr.Wizard

@Leonid Ít nhất là cho FrontEnd, CellEvaluationFunctioncái móc bạn đang tìm kiếm phải không?
Mr.Wizard

2
Ngoài ra: có một Celltùy chọn khác có liên quan đến đánh giá ô - Evaluator -> "EvaluatorName". Ý nghĩa của "EvaluatorName"có thể được cấu hình thông qua hộp thoại Ev Assessment :: Kernel Tùy chọn cấu hình .... Tôi vẫn không biết là có thể cấu hình nó theo chương trình không ... Kỹ thuật này cho phép sử dụng các MathKernels khác nhau trong các Cells khác nhau trong một Notebook. Những MathKernels có thể từ phiên bản khác nhau của Mathematica được cài đặt.
Alexey Popkov

1
@Szabolcs Tất cả việc sử dụng kỹ thuật này của riêng tôi liên quan đến cách tiếp cận tiêu chuẩn stdin _ / _ như minh họa ở trên hoặc yêu cầu từ xa khép kín như truy vấn SQL hoặc thao tác HTTP. Bạn có thể thử thiết lập ứng dụng web Python REPL (như thế này ) và tương tác với nó bằng cách sử dụng Importhoặc có thể bắt đầu một quy trình Python bên ngoài và giao tiếp qua các luồng của nó (ví dụ: sử dụng Java ProcessBuilder ). Tôi chắc chắn có một cách
Mathicala

36

Todd Gayley (Nghiên cứu Wolfram) chỉ cần gửi cho tôi một bản hack đẹp cho phép "bọc" các hàm tích hợp với mã tùy ý. Tôi cảm thấy rằng tôi phải chia sẻ công cụ hữu ích này. Sau đây là câu trả lời của Todd về tôi question.

Một chút lịch sử thú vị (?): Phong cách hack để "gói" một chức năng tích hợp đã được phát minh vào khoảng năm 1994 bởi Robby Villegas và tôi, trớ trêu thay cho chức năng Message, trong một gói có tên ErrorHelp mà tôi đã viết cho Tạp chí Mathicala trở lại sau đó. Nó đã được sử dụng nhiều lần, bởi nhiều người, kể từ đó. Đó là một mẹo nhỏ của người trong cuộc, nhưng tôi nghĩ thật công bằng khi nói rằng nó đã trở thành cách thức kinh điển để đưa mã của chính bạn vào định nghĩa của hàm tích hợp. Nó được thực hiện công việc độc đáo. Tất nhiên, bạn có thể đặt biến $ inMsg vào bất kỳ bối cảnh riêng tư nào bạn muốn.

Unprotect[Message];

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

Protect[Message];

@Alexey Tôi gặp khó khăn trong việc hiểu điều này. Bạn có thể giải thích làm thế nào điều này hoạt động? Không nên có một [Tin nhắn] không bảo vệ ở đâu đó? Và không ví dụ này có chứa đệ quy vô hạn? Và ,! TrueQ [$ inMsg] có nghĩa gì với $ inMsg được xác định bên trong phạm vi Khối và không được xác định bên ngoài Khối không?
Sjoerd C. de Vries

9
@Sjoerd Từ những gì tôi hiểu, Unprotectthực sự phải có, chỉ là bỏ đi. Điểm của Block(phạm vi động) và $inMsgchính xác là để ngăn đệ quy vô hạn. Bởi vì $inMsgkhông được xác định bên ngoài (đây là một yêu cầu quan trọng), ban đầu, TrueQđánh giá Falsevà chúng ta nhập vào thân hàm. Nhưng khi chúng ta có chức năng gọi bên trong cơ thể, điều kiện sẽ ước tính False(vì biến đã được xác định lại bởi Block). Do đó, quy tắc do người dùng xác định không phù hợp và thay vào đó, quy tắc tích hợp được sử dụng.
Leonid Shifrin

1
@Leonid Cảm ơn, tôi hiểu rồi. Rất thông minh!
Sjoerd C. de Vries

1
Tôi vừa phát hiện ra rằng kỹ thuật này đã được thảo luận bởi Robby Villegas của Wolfram Research tại Hội nghị Nhà phát triển 1999. Xem sổ tay "Làm việc với các biểu thức không được đánh giá" được đăng ở đây . Trong cuốn sổ tay này, Robby Villegas thảo luận về thủ thuật này trong phần "Thủ thuật chặn của tôi để bẫy các cuộc gọi đến các chức năng tích hợp".
Alexey Popkov

1
@ Mr.Wizard Đây không phải là cách duy nhất để làm điều này. Trong một thời gian dài, tôi đã sử dụng một phiên bản mà bạn xác định lại DownValuesthời gian chạy, bạn có thể xem bài đăng này nhóm.google.com.vn/group/comp.soft-sys.math.mathematica/ , ví dụ ( SetDelayedxác định lại) . Nhưng phương pháp của tôi kém thanh lịch, kém mạnh mẽ hơn, dễ bị lỗi hơn và làm cho việc thoát khỏi đệ quy trở nên ít tầm thường hơn để thực hiện. Vì vậy, trong hầu hết các tình huống, phương pháp được mô tả bởi @Alexey đều thắng.
Leonid Shifrin

25

Đây không phải là một tài nguyên hoàn chỉnh, vì vậy tôi sẽ ném nó vào đây trong phần câu trả lời, nhưng tôi đã thấy nó rất hữu ích khi tìm ra các vấn đề về tốc độ (thật không may, là một phần lớn trong những gì lập trình Mathicala nói về).

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

Cách sử dụng sau đó đơn giản timeAvg@funcYouWantToTest.

EDIT: Ông Wizard đã cung cấp một phiên bản đơn giản hơn mà không đi với ThrowCatchvà là một chút dễ dàng hơn để phân tích cú pháp:

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

EDIT: Đây là một phiên bản từ acl (lấy từ đây ):

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]

Thực hiện lại và agin ... thời gian để nhập vào túi riêng của tôi. tnx!
Tiến sĩ belisarius

1
Một vấn đề với mã này (tốt, có thể đây là quan điểm của người cầu toàn) là chúng ta có thể bắt được thứ gì đó mà chúng ta đã không ném và giải thích đây là kết quả không chính xác. Cả hai CatchThrownên được sử dụng với các thẻ ngoại lệ duy nhất.
Leonid Shifrin

2
Timo, tôi rất vui vì bạn thích bản phối của tôi đủ để đưa nó vào. Cảm ơn đã cho tôi tín dụng, quá. Tôi tò mò về cách bạn định dạng lại mã của tôi. Tôi không tuân theo bất kỳ hướng dẫn cụ thể nào trong mã của riêng tôi, ngoài việc giúp tôi dễ đọc hơn; Có một trường phái tư tưởng đằng sau việc định dạng lại của bạn, hay đó chỉ là sở thích? Mathematica không khuyến khích định dạng mã chính xác vì cách nó phản ánh đầu vào, nhưng việc đăng mã ở đây đang khiến tôi bắt đầu suy nghĩ về nó. BTW, tôi nghĩ bạn có nghĩa là " ThrowCatch" chứ không phải " ReapSow."
Mr.Wizard

1
@Simon, Mr.Wizard, tôi sử dụng phương pháp này để định thời gian cho các phiên bản khác nhau của các hàm nhỏ sẽ được gọi rất nhiều lần. Không nhất thiết phải theo cấu trúc vòng lặp nhưng chắc chắn trong các cấu trúc mà MMA tối ưu hóa. Trong bối cảnh này, việc thực hiện một vòng lặp có ý nghĩa và hiệu suất sẽ gần với ứng dụng thực tế. Để định thời gian cho các hàm phức tạp lớn (thậm chí có thể là toàn bộ các ô khởi tạo), phương thức của Simon sẽ cho kết quả tốt hơn. Nói chung, tôi quan tâm nhiều hơn đến các giá trị tương đối và một trong hai phương pháp sẽ hoạt động ở đó.
Timo

3
Bây giờ có RepeatedTimingđể làm điều này.
masterxilo

20

Internal`InheritedBlock

Gần đây tôi đã biết được sự tồn tại của chức năng hữu ích như vậy Internal`InheritedBlock, từ tin nhắn này của Daniel Lichtblau trong nhóm tin chính thức.

Theo tôi hiểu, Internal`InheritedBlockcho phép vượt qua một bản sao của hàm ngoài trong Blockphạm vi:

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]

Tôi nghĩ rằng chức năng này có thể rất hữu ích cho tất cả những người cần sửa đổi các chức năng tích hợp tạm thời!

So sánh với Block

Hãy để chúng tôi xác định một số chức năng:

a := Print[b]

Bây giờ chúng tôi muốn chuyển một bản sao của chức năng này vào Blockphạm vi. Phiên tòa ngây thơ không đưa ra những gì chúng ta muốn:

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

During evaluation of In[9]:= b

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

Bây giờ đang cố gắng sử dụng định nghĩa bị trì hoãn trong đối số đầu tiên của Block(nó cũng là một tính năng không có giấy tờ):

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

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

During evaluation of In[3]:= b

Chúng tôi thấy rằng trong trường hợp này ahoạt động nhưng chúng tôi không có bản sao abên trong Blockphạm vi.

Bây giờ hãy để chúng tôi thử Internal`InheritedBlock:

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

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

Chúng tôi đã có một bản sao của định nghĩa ban đầu cho abên trong Blockphạm vi và chúng tôi có thể sửa đổi nó theo cách chúng tôi muốn mà không ảnh hưởng đến định nghĩa toàn cầu cho a!


+1 Rất tiện dụng! Thêm một công cụ trong túi và 10 điểm gần hơn với đặc quyền Chỉnh sửa cho bạn.
Mr.Wizard

Đối với tôi điều này xuất hiện như một biến thể của đánh giá sớm hay muộn hoặc không và đánh giá đầy đủ.
dùng2432923

19

Mathematica là một công cụ sắc bén, nhưng nó có thể cắt cho bạn phần nào của nó hành vi untypedtuyết lở của khó hiểu thông điệp chẩn đoán . Một cách để giải quyết vấn đề này là xác định các hàm theo thành ngữ này:

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

Đó là rất nhiều nồi hơi, mà tôi thường bị bỏ qua. Đặc biệt là khi tạo mẫu, điều này xảy ra rất nhiều trong Mathicala. Vì vậy, tôi sử dụng một macro được gọi là definecho phép tôi giữ nguyên kỷ luật, với ít bản tóm tắt hơn.

Một cách sử dụng cơ bản definelà như thế này:

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

fact[5]

120

Ban đầu nó trông không giống lắm, nhưng có một số lợi ích tiềm ẩn. Dịch vụ đầu tiên definecung cấp là nó tự động áp dụngClearAll cho biểu tượng được xác định. Điều này đảm bảo rằng không có định nghĩa còn sót lại - một sự xuất hiện phổ biến trong quá trình phát triển ban đầu của một chức năng.

Dịch vụ thứ hai là chức năng được xác định sẽ tự động "đóng". Điều này có nghĩa là hàm sẽ đưa ra một thông báo và hủy bỏ nếu nó được gọi với một danh sách đối số không khớp với một trong các định nghĩa:

fact[-1]

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

Đây là giá trị chính của define , trong đó bắt một lớp lỗi rất phổ biến.

Một tiện lợi khác là một cách ngắn gọn để xác định các thuộc tính trên hàm được xác định. Hãy thực hiện chức năng Listable:

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

fact[{3, 5, 8}]

{6, 120, 40320}

Ngoài tất cả các thuộc tính thông thường, definechấp nhận một thuộc tính bổ sung được gọi Open. Điều này ngăn không cho definethêm định nghĩa lỗi bắt tất cả vào hàm:

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

successor /@ {1, "hi"}

{2, successor["hi"]}

Nhiều thuộc tính có thể được xác định cho một chức năng:

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

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

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

Nếu không có thêm rắc rối, đây là định nghĩa về 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: ``";

Việc triển khai được trưng bày không hỗ trợ giá trị tăng cũng như currying, cũng không phải các mẫu tổng quát hơn định nghĩa hàm đơn giản. Nó vẫn hữu ích, tuy nhiên.


2
+1 - đây là công cụ thực sự hữu ích. Tôi đã được sử dụng các công cụ tương tự. Các macro (cũng như hướng nội và các kỹ thuật lập trình meta khác) có thể rất mạnh mẽ, nhưng dường như thường bị đánh giá thấp trong cộng đồng Mathicala, hoặc ít nhất đây là ấn tượng của tôi cho đến nay.
Leonid Shifrin

Tôi vừa định nghĩa một cái gì đó tương tự. +1 cho CompoundExpression hỗ trợ để thực hiện nhiều định nghĩa, Abort [] (có vẻ tốt hơn nhiều tin nhắn hơn) và Mở (tốt cho ví dụ các nhà xây dựng).
masterxilo

16

Bắt đầu mà không có một cuốn sổ tay trống nào mở

Tôi đã bị làm phiền bởi việc Mathicala bắt đầu với một cuốn sổ tay trống đang mở. Tôi có thể đóng cuốn sổ này bằng một tập lệnh, nhưng nó vẫn sẽ nhanh chóng mở ra. Hack của tôi là tạo một tập tin Invisible.nbcó chứa:

Notebook[{},Visible->False]

Và thêm nó vào Kernel\init.m:

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

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

Bây giờ tôi bắt đầu Mathicala bằng cách mở Invisible.nb

Có thể có một cách tốt hơn, nhưng điều này đã phục vụ tôi tốt.


Tùy chỉnh FoldFoldList

Fold[f, x] được làm tương đương với Fold[f, First@x, Rest@x]

Ngẫu nhiên, tôi tin rằng điều này có thể tìm đường đến một phiên bản tương lai của Mathematica.

Sự ngạc nhiên! Điều này đã được thực hiện, mặc dù hiện tại nó không có giấy tờ. Tôi được thông báo rằng nó đã được thực hiện vào năm 2011 bởi Oliver Ruebenkoenig, dường như không lâu sau khi tôi đăng bài này. Cảm ơn 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]

Cập nhật để cho phép điều này:

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

"Phân vùng động"

Xem Mathicala.SE bài # 7512 để biết phiên bản mới của chức năng này.

Thường xuyên tôi muốn phân vùng một danh sách theo một chuỗi độ dài.

ví dụ mã giả:

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

Đầu ra: {{1,2}, {3,4,5}, {6}}

Tôi nghĩ ra cái này:

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

Sau đó tôi đã hoàn thành việc này, bao gồm kiểm tra đối số:

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

Đối số thứ ba kiểm soát những gì xảy ra với các phần tử nằm ngoài đặc tả phân tách.


Thủ thuật Mathicala của Szabolcs

Thứ tôi sử dụng thường xuyên nhất là Bảng dữ liệu dạng bảng Paste

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

Sửa đổi dữ liệu ngoài từ bên trong Compile

Gần đây Daniel Lichtblau cho thấy phương pháp này tôi chưa từng thấy trước đây. Theo tôi nó mở rộng đáng kể tiện ích củaCompile

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

3
+1 Một bộ sưu tập tốt! Về các sửa đổi bên ngoài từ bên trong Compile- toàn bộ bài đăng của tôi ở đây: stackoverflow.com/questions/5246330/ , đã thể hiện khả năng này trong một cài đặt không tầm thường (Đã có một giải pháp ngắn hơn và nhanh hơn cho vấn đề được đề cập ở đó) . IMO, chiến thắng lớn nhất ở đây là khả năng mô phỏng tham chiếu qua và phá vỡ các hàm Biên dịch lớn thành các phần dễ quản lý và có thể sử dụng lại hơn.
Leonid Shifrin

1
Bạn cũng có thể điều chỉnh thông tin cú pháp của Fold và FoldList trong định nghĩa mới của mình: SyntaxIn information [Fold] = {"ArgumentPotype" -> {_ , . , _}}; Cú pháp Thông tin [FoldList] = {"ArgumentPotype" -> {_, _., {_ }}};
faysou

14

Các vấn đề và giải pháp xuất khẩu PDF / EMF chung

1) Hoàn toàn bất ngờ và không có giấy tờ, nhưng Mathicala xuất và lưu đồ họa ở định dạng PDF và EPS bằng cách sử dụng một bộ định nghĩa kiểu khác với định nghĩa được sử dụng để hiển thị Sổ tay trên màn hình. Theo mặc định máy tính xách tay được hiển thị trên màn hình trong "công tác" môi trường phong cách (đó là giá trị mặc định cho ScreenStyleEvironmenttoàn cầu $FrontEndtùy chọn) nhưng được in trong "Printout"môi trường phong cách (đó là giá trị mặc định cho PrintingStyleEnvironmenttoàn cầu $FrontEndtùy chọn). Khi một xuất đồ họa ở các định dạng raster như GIF và PNG hoặc trong định dạng EMF Mathematica tạo đồ họa mà vẻ bề ngoài giống hệt như nó trông Máy tính xách tay bên trong. Dường như"Working"môi trường phong cách được sử dụng để kết xuất trong trường hợp này. Nhưng nó không phải là trường hợp khi bạn xuất / lưu bất cứ thứ gì ở định dạng PDF hoặc EPS! Trong trường hợp này, "Printout"môi trường kiểu được sử dụng theo mặc địnhkhác biệt rất sâu sắc với môi trường kiểu "Làm việc". Trước hết, các "Printout"bộ môi trường kiểu Magnificationđến 80% . Thứ hai, nó sử dụng các giá trị riêng của nó cho các kích thước phông chữ của các kiểu khác nhau và điều này dẫn đến thay đổi kích thước phông chữ không nhất quán trong tệp PDF được chỉnh sửa so với biểu diễn trên màn hình gốc. Cái sau có thể được gọi là biến động FontSize rất khó chịu. Nhưng rất vui vì điều này có thể tránh được bằng cách đặt tùy chọn PrintingStyleEnvironmenttoàn cầu $FrontEndthành "Hoạt động" :

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

2) Vấn đề phổ biến khi xuất sang định dạng EMF là hầu hết các chương trình (không chỉ Mathicala ) tạo ra một tệp trông đẹp ở kích thước mặc định nhưng trở nên xấu khi bạn phóng to nó. Đó là do các siêu tệp được lấy mẫu ở độ phân giải màn hình . Chất lượng của tệp EMF được tạo có thể được nâng cao bằng cách Magnifylấy đối tượng đồ họa gốc để tính chính xác của việc lấy mẫu đồ họa gốc trở nên chính xác hơn nhiều. So sánh hai tệp:

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

Nếu bạn chèn các tệp này vào Microsoft Word và phóng to chúng vào, bạn sẽ thấy chữ "a" đầu tiên có răng cưa trong khi tệp thứ hai thì không (đã được thử nghiệm với Mathicala 6).

Một cách khác thông qua ImageResolutionđã được đề xuất bởi Chris Degnen (tùy chọn này có hiệu lực thi hành ít nhất bắt đầu từ Mathematica 8):

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

3) Trong Mathematica chúng tôi có ba cách để chuyển đổi đồ họa vào Metafile: qua Exportđể "EMF"(cách khuyến khích mạnh mẽ: sản xuất Metafile với chất lượng cao nhất có thể), thông qua Save selection As...mục trình đơn ( sản xuất thấp hơn rất nhiều con số chính xác , không khuyến khích) và thông qua Edit ► Copy As ► Metafilemục trình đơn ( Tôi khuyên chống lại tuyến đường này ).


13

Theo yêu cầu phổ biến, mã để tạo ra âm mưu 10 câu trả lời SO hàng đầu (trừ chú thích ) bằng API SO .

nhập mô tả hình ảnh ở đây

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

1
Brett đã đăng một câu hỏi yêu cầu gần như mã chính xác này. Có lẽ nó là thích hợp nhất ở đó, với một hoặc hai điều chỉnh để phù hợp với câu hỏi. Tôi thực sự sẽ có giá trị đại diện, trái ngược với câu hỏi này.
rcollyer

@rcollyer đúng. Đây là "Wiki cộng đồng"
Tiến sĩ belisarius

@ Belisarius Tôi vừa sao chép nó trong câu trả lời cho câu hỏi của Brett ...
Sjoerd C. de Vries

@Sjoerd Lô của bạn ở đây không tự động cập nhật.
Tiến sĩ belisarius

@ Belisarius Thật ra tôi đã hy vọng bạn sẽ nhận nhiệm vụ đó khi bạn ... ;-)
Sjoerd C. de Vries

13

Biểu thức bộ đệm

Tôi thấy các chức năng này rất hữu ích để lưu trữ bất kỳ biểu thức. Điều thú vị ở đây đối với hai hàm này là chính biểu thức được giữ được sử dụng làm khóa của hàm băm / biểu tượng Cache hoặc Cache Index, so với ghi nhớ nổi tiếng trong toán học, nơi bạn chỉ có thể lưu trữ kết quả nếu hàm được xác định như f [x_]: = f [x] = ... Vì vậy, bạn có thể lưu trữ bất kỳ phần nào của mã, điều này rất hữu ích nếu một hàm được gọi nhiều lần nhưng chỉ một số phần của mã không được tính toán lại.

Để lưu trữ một biểu thức độc lập với các đối số của nó.

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

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

Lần thứ hai biểu thức trả về 6 mà không cần chờ đợi.

Để lưu trữ một biểu thức bằng cách sử dụng một biểu thức bí danh có thể phụ thuộc vào một đối số của biểu thức được lưu trữ.

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

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

Nếu expr mất một chút thời gian để tính toán, thì việc đánh giá {"f", 2} chẳng hạn để lấy kết quả được lưu trong bộ nhớ cache nhanh hơn nhiều.

Để biết biến thể của các chức năng này để có bộ đệm cục bộ (nghĩa là bộ nhớ đệm được tự động giải phóng bên ngoài cấu trúc Khối), hãy xem bài đăng này Tránh các cuộc gọi lặp lại đến Nội suy

Xóa các giá trị được lưu trữ

Để xóa các giá trị được lưu trong bộ nhớ cache khi bạn không biết số lượng định nghĩa của hàm. Tôi xem xét rằng các định nghĩa có một khoảng trống ở đâu đó trong các đối số của họ.

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

Để xóa các giá trị được lưu trong bộ nhớ cache khi bạn biết số lượng định nghĩa của hàm (đi nhanh hơn một chút).

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

Điều này sử dụng thực tế là các định nghĩa của một hàm nằm ở cuối danh sách DownValues ​​của chúng, các giá trị được lưu trong bộ nhớ cache là trước đó.

Sử dụng các ký hiệu để lưu trữ dữ liệu và các chức năng giống như đối tượng

Ngoài ra đây là các chức năng thú vị để sử dụng các biểu tượng như các đối tượng.

Điều nổi tiếng là bạn có thể lưu trữ dữ liệu trong các biểu tượng và nhanh chóng truy cập chúng bằng DownValues

mysymbol["property"]=2;

Bạn có thể truy cập danh sách các khóa (hoặc thuộc tính) của một biểu tượng bằng cách sử dụng các chức năng này dựa trên những gì được gửi trong một bài đăng trên trang web này:

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

Tôi sử dụng chức năng này rất nhiều để hiển thị tất cả các thông tin có trong DownValues ​​của một biểu tượng:

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

Cuối cùng, đây là một cách đơn giản để tạo một biểu tượng hoạt động giống như một đối tượng trong lập trình hướng đối tượng (nó chỉ tái tạo hành vi cơ bản nhất của OOP nhưng tôi thấy cú pháp tao nhã):

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

Các thuộc tính được lưu trữ dưới dạng DownValues ​​và các phương thức dưới dạng Upvalues ​​bị trì hoãn trong biểu tượng được tạo bởi Module được trả về. Tôi đã tìm thấy cú pháp cho hàm2, đó là cú pháp OO thông thường cho các hàm trong cấu trúc dữ liệu cây trong Mathicala .

Để biết danh sách các loại giá trị hiện có mà mỗi biểu tượng có, hãy xem http://reference.wolfram.com/mathematica/tutorial/PotypesAndTransaturesRules.htmlhttp://www.verbeia.com/mathematica/tips/HTMLLinks/Tricks_Misc_4.html .

Ví dụ thử cái này

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

Bạn có thể đi xa hơn nếu bạn muốn mô phỏng kế thừa đối tượng bằng cách sử dụng gói có tên là InheritRules có sẵn ở đây http://library.wolfram.com/infocenter/MathSource/671/

Bạn cũng có thể lưu trữ định nghĩa hàm không phải trong newObject mà trong một ký hiệu loại, vì vậy nếu NewObject trả về loại [newObject] thay vì newObject, bạn có thể định nghĩa hàm và hàm2 như thế này bên ngoài NewObject (và không bên trong) và có cùng cách sử dụng như trước .

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

Sử dụng UpValues ​​[type] để xem hàm và function2 được xác định trong ký hiệu loại.

Những ý tưởng khác về cú pháp cuối cùng này được giới thiệu tại đây https://mathIALa.stackexchange.com/a/999/66 .

Phiên bản cải tiến của SelectEquivalents

@rcollyer: Rất cám ơn vì đã đưa SelectEquivalents lên bề mặt, đó là một chức năng tuyệt vời. Dưới đây là phiên bản cải tiến của SelectEquivalents được liệt kê ở trên với nhiều khả năng hơn và sử dụng các tùy chọn, điều này giúp sử dụng dễ dàng hơn.

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

Dưới đây là các ví dụ về cách sử dụng phiên bản này:

Sử dụng Mathicala Gather / Thu thập đúng cách

Làm thế nào bạn có thể thực hiện một chức năng PivotTable trong Mathematica?

Mathicala thuật toán tạo thùng 2D nhanh

Nội bộ

Daniel Lichtblau mô tả ở đây một cấu trúc dữ liệu nội bộ thú vị để phát triển danh sách.

Thực hiện Quadtree trong Mathematica

Chức năng sửa lỗi

Hai bài viết này chỉ đến các chức năng hữu ích để gỡ lỗi:

Làm thế nào để gỡ lỗi khi viết mã nhỏ hoặc lớn bằng Mathicala? bàn làm việc? mma gỡ lỗi? hay cái gì khác?(Hiển thị)

/programming/5459735/the-clearest-way-to-putesent-mathIALas-ev Assessment-resultence / 5527117 # 5527117 Assessment-resultence / 5527117 # 5527117 (TraceView)

Đây là một chức năng khác dựa trên Siem và Sow để trích xuất các biểu thức từ các phần khác nhau của chương trình và lưu trữ chúng trong một biểu tượng.

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

Đây là một ví dụ

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

Các nguồn lực khác

Dưới đây là danh sách các liên kết thú vị cho mục đích học tập:

Một bộ sưu tập các tài nguyên học tập Mathicala

Cập nhật tại đây: https://mathIALa.stackexchange.com/a/259/66


Liên quan: " Cách tốt nhất để xây dựng một chức năng với bộ nhớ ". WReach đã đưa ra một ví dụ tuyệt vời về chức năng đơn giản không chỉ ghi nhớ các giá trị của nó mà còn ghi chúng vào một tệp và đọc ngược khi khởi động lại.
Alexey Popkov

1
Liên quan: " Mathicala: Cách xóa bộ đệm cho biểu tượng, tức là Unset DownValues ​​không có mẫu ". Câu hỏi này cho thấy làm thế nào để xóa bộ nhớ cache bằng cách f[x_] := f[x] = some codeghi nhớ tiêu chuẩn .
Simon

7
+1 Có một tiện ích công chứng tốt đẹp giúp loại bỏ sự cần thiết phải lặp lại phía bên trái của định nghĩa trong một chức năng lưu trữ, ví dụ : c:Cache[expr_] := c = expr.
VIẾT

Biến thể đẹp của SelectEquivalents. Tôi nghĩ rằng, tôi sẽ giữ TagOnElementnhư là thông số thứ hai mặc định Identityvì nó được sử dụng nhiều nhất trong số họ. Tôi cũng không nghĩ rằng mình đã bao gồm FinalOp, vì nó có thể được xử lý bên trong OpOnTaggedElems. Tôi cũng rút ngắn các tên tùy chọn, vì độ dài của chúng khiến cho việc gõ ra trở nên khó xử. Hãy thử TagFunction, TransformElement, TransformResults, và TagPatternthay thế. Cả hai, TagPatternMapLevellà những bổ sung tuyệt vời cho chức năng, và viết lại tốt, tổng thể.
rcollyer

Cảm ơn bình luận của bạn rcollyer. Tôi đã tính đến nó và cũng cải thiện khả năng đọc mã. Tôi giữ FinalFunction vì nó hoạt động dựa trên kết quả của Siem, ví dụ nếu bạn muốn sắp xếp kết quả cuối cùng của mình theo các thẻ nếu bạn giữ chúng.
faysou

12

Các chức năng tiện ích của tôi (tôi đã tích hợp sẵn MASH, được đề cập trong câu hỏi):

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

Đối với chức năng "mỗi", hãy xem stackoverflow.com/questions/160216/foreach-loop-in-mathematica
dreeves

11

Một mẹo mà tôi đã sử dụng, cho phép bạn mô phỏng cách hầu hết các hàm dựng sẵn hoạt động với các đối số xấu (bằng cách gửi tin nhắn và sau đó trả lại toàn bộ biểu mẫu không được đánh giá) khai thác một cách giải quyết Condition hoạt động khi sử dụng trong một định nghĩa. Nếu foochỉ nên làm việc với một đối số:

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

Nếu bạn có nhu cầu phức tạp hơn, thật dễ dàng xác định việc xác thực đối số và tạo thông báo dưới dạng một hàm độc lập. Bạn có thể làm những điều phức tạp hơn bằng cách sử dụng các tác dụng phụ trongCondition ngoài việc tạo ra tin nhắn, nhưng theo tôi, hầu hết chúng đều thuộc danh mục "hack nhếch nhác" và nên tránh nếu có thể.

Ngoài ra, trong danh mục "siêu lập trình", nếu bạn có .mtệp gói Mathicala ( ), bạn có thể sử dụng "HeldExpressions"phần tử để nhận tất cả các biểu thức trong tệp được gói HoldComplete. Điều này làm cho việc theo dõi mọi thứ dễ dàng hơn nhiều so với sử dụng các tìm kiếm dựa trên văn bản. Thật không may, không có cách dễ dàng để làm điều tương tự với một máy tính xách tay, nhưng bạn có thể nhận được tất cả các biểu thức nhập bằng cách sử dụng một cái gì đó như sau:

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

Cuối cùng, bạn có thể sử dụng thực tế là Module mô phỏng các bao đóng từ vựng để tạo ra các loại tham chiếu tương đương. Đây là một ngăn xếp đơn giản (sử dụng một biến thể Conditionđể xử lý lỗi làm phần thưởng):

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]

Bây giờ bạn có thể in các yếu tố của một danh sách theo thứ tự ngược lại một cách không cần thiết!

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

 While[!EmptyQ[stack],
  Print[Peek@stack];
  Pop@stack]]

1
+1 cho HeldExpressionsphần tử trong các gói, không biết điều đó. Tôi thường nhập dưới dạng chuỗi và sau đó sử dụng ToExpressionvới HoldCompletenhư arg cuối cùng. Về việc sử dụng Conditioncho tin nhắn - đây là một kỹ thuật tiêu chuẩn trong viết gói từ ít nhất năm 1994. Liên quan đến sự kiên trì thông qua các Modulevars - Tôi đã có một bài viết dài về điều đó trên Mathgroup một thời gian trước: Groups.google.com/group/comp.soft- sys.math.mathIALa / Lỗi (bài thứ ba của tôi trong chủ đề đó), đây là cùng một dòng và có liên kết đến một vài ví dụ sử dụng không cần thiết.
Leonid Shifrin

@Leonid Shifrin: Tôi đã chọn Conditionthứ đó là truyền thuyết, có lẽ là từ đồng nghiệp, nhưng không nhận ra đó là một kỹ thuật tiêu chuẩn. Các liên kết về việc sử dụng Modulecác biểu tượng như các loại tham chiếu là thú vị!
Pillsy

+1, tôi chưa bao giờ nghĩ về điều đó. Càng tìm hiểu về ngôn ngữ này, nó dường như càng mạnh mẽ.
rcollyer

@Pillsy mục đích của việc làm một stack theo cách đó là gì?
Mr.Wizard

@ Mr.Wizard: Tôi chỉ chọn một trong những cấu trúc dữ liệu có thể thay đổi đơn giản nhất mà tôi có thể nghĩ ra để minh họa cho kỹ thuật này.
Pillsy

11

In định nghĩa ký hiệu hệ thống mà không cần bối cảnh

Các contextFreeDefinition[]chức năng dưới đây sẽ cố gắng để in các định nghĩa của một biểu tượng mà không có bối cảnh phổ biến nhất prepended. Định nghĩa sau đó có thể được sao chép vào Workbench và được định dạng để dễ đọc (chọn nó, nhấp chuột phải, Nguồn -> Định dạng)

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

Hãy cẩn thận: Hàm này không bản địa hóa các biến theo cùng một cách WithModulelàm, điều đó có nghĩa là các cấu trúc nội địa hóa lồng nhau sẽ không hoạt động như mong đợi. withRules[{a -> 1, b -> 2}, With[{a=3}, b_ :> b]] sẽ thay thế abtrong lồng WithRule, trong khi Withkhông làm điều này.

Đây là một biến thể Withsử dụng quy tắc thay vì =:=:

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

Tôi thấy điều này hữu ích trong khi dọn dẹp mã được viết trong quá trình thử nghiệm và bản địa hóa các biến. Thỉnh thoảng tôi kết thúc với danh sách tham số ở dạng {par1 -> 1.1, par2 -> 2.2}. VớiwithRules các giá trị tham số dễ dàng đưa vào mã được viết trước đó bằng các biến toàn cục.

Cách sử dụng cũng giống như With:

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

Đồ họa 3D khử răng cưa

Đây là một kỹ thuật rất đơn giản đối với đồ họa 3D antialias ngay cả khi phần cứng đồ họa của bạn không hỗ trợ nó nguyên bản.

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

Đây là một ví dụ:

Đồ họa toán học Đồ họa toán học

Lưu ý rằng giá trị lớn cho nhoặc kích thước hình ảnh lớn có xu hướng phơi bày các lỗi trình điều khiển đồ họa hoặc giới thiệu các đồ tạo tác.


Notebook chức năng khác

Chức năng khác của Notebook có sẵn trong <<AuthorTools`gói và (ít nhất là trong phiên bản 8) trong NotebookTools`bối cảnh không có giấy tờ . Đây là một GUI nhỏ để tìm hai máy tính xách tay hiện đang mở:

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

Đồ họa toán học


Tất cả sẽ tốt, nhưng điều này không thực sự bản địa hóa các biến, như bạn có thể thấy bằng cách gán say a = 3; b = 4;trước cuộc gọi ví dụ của bạn, và sau đó gọi withRules. Bạn có thể lưu nó bằng cách sử dụng như sau : SetAttributes[withRules, HoldAll];withRules[rules_, expr_] := Unevaluated[expr] /. Unevaluated[rules]. Sự khác biệt về ngữ nghĩa wrt của Withsau đó: 1. rhsides của các quy tắc hiện không được đánh giá 2. withRuleskhông giải quyết các xung đột đặt tên với các cấu trúc phạm vi bên trong như Withhiện tại. Điều cuối cùng là khá nghiêm trọng - là điều tốt hay xấu tùy theo trường hợp.
Leonid Shifrin

@Leonid Bạn hoàn toàn đúng, có vẻ như tôi chưa bao giờ tìm hiểu về việc kiểm tra mã đúng cách trước khi đăng ... khi tôi sử dụng điều này, thực tế tôi không bao giờ gán giá trị cho các biến, nhưng đó là một vấn đề khá nghiêm trọng, bạn nói đúng. Bạn nghĩ gì về phiên bản sửa chữa? (Tôi thực sự không quan tâm đến việc không xử lý các lồng nhau With. Điều này không phải lúc nào cũng hoạt động với các cấu trúc nội địa hóa dựng sẵn, vd With[{a=1}, Block[{a=2}, a]]. Bạn có nghĩ rằng có lý do chính đáng tại sao lồng Blockkhông định vị ở đó, như lồng WithModulekhông?)
Szabolcs

@Leonid Tôi không đơn giản sử dụng Unevaluated[rules]vì tôi muốn x -> 1+1đánh giá RHS.
Szabolcs

@Leonid Bạn thực sự đúng, vấn đề nội địa hóa lồng nhau có thể khá nghiêm trọng. Tôi nghĩ rằng các lồng nhau Withrất dễ phát hiện và tránh, nhưng các mẫu không: With[{a = 1}, a_ -> a]địa phương hóa bên atrong trong khi withRuleskhông. Bạn có biết liệu có cách nào để truy cập cơ chế nội địa hóa của Mathematica và tạo các cấu trúc mới (tương tự Rule) cũng bản địa hóa không? Tôi có thể sẽ xóa câu trả lời này sau vì nó nguy hiểm hơn là hữu ích, nhưng tôi muốn chơi với nó trước hơn một chút.
Szabolcs

Tôi nghĩ rằng việc sử dụng của bạn InheritedBlocklà khá mát mẻ và giải quyết vấn đề rất thanh lịch. Đối với các xung đột phạm vi, các ràng buộc thông thường cho phạm vi từ vựng xảy ra ở "thời gian ràng buộc từ vựng", đó là - trước thời gian chạy, trong khi phạm vi động liên kết tại thời gian chạy, điều này có thể giải thích điều đó. Bạn có thể đối chiếu điều này với trường hợp tương tự Module, cho phép sử dụng mang tính xây dựng (xem ví dụ ở đây stackoverflow.com/questions/7394113/ Lần ). Vấn đề là Blockcần một số biểu tượng để ...
Leonid Shifrin

9

Các hàm thuần đệ quy ( #0) dường như là một trong những góc tối hơn của ngôn ngữ. Dưới đây là một vài ví dụ không tầm thường về việc sử dụng chúng, trong đó điều này thực sự hữu ích (không phải là chúng không thể được thực hiện nếu không có nó). Sau đây là một hàm khá ngắn gọn và hợp lý để tìm các thành phần được kết nối trong biểu đồ, đưa ra một danh sách các cạnh được chỉ định là các cặp đỉnh:

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

Điều xảy ra ở đây là trước tiên chúng ta ánh xạ một biểu tượng giả trên mỗi số đỉnh, và sau đó thiết lập một cách mà, đưa ra một cặp đỉnh {f[5],f[10]}, sau đó f[5]sẽ đánh giá f[10]. Hàm thuần đệ quy được sử dụng như một trình nén đường dẫn (để thiết lập ghi nhớ theo cách thay vì các chuỗi dài như thế f[1]=f[3],f[3]=f[4],f[4]=f[2], ..., các giá trị ghi nhớ được sửa chữa bất cứ khi nào một "gốc" mới của thành phần được phát hiện. Điều này giúp tăng tốc đáng kể. Bởi vì chúng tôi sử dụng phép gán, chúng tôi cần nó là HoldAll, điều này làm cho cấu trúc này thậm chí còn tối nghĩa hơn và hấp dẫn hơn). Chức năng này là kết quả của cuộc thảo luận Mathgroup trực tuyến và liên quan đến Fred Simons, Szabolcs Horvat, DrMajorBob và của bạn thực sự. Thí dụ:

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

Nó chắc chắn là chậm hơn nhiều so với tích hợp sẵn, nhưng đối với kích thước mã, khá nhanh vẫn là IMO.

Một ví dụ khác: ở đây là một nhận thức đệ quy Select, dựa trên các danh sách được liên kết và các hàm thuần đệ quy:

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

Ví dụ,

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

Tuy nhiên, nó không phải là đệ quy đuôi đúng cách, và sẽ thổi stack (phá vỡ kernel) cho các danh sách lớn hơn. Đây là phiên bản đệ quy đuôi:

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

Ví dụ,

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

Chức năng cho các thành phần được kết nối vẫn là sở thích của tôi :-)
Szabolcs

@Szabolcs Vâng, nó khá tuyệt. Bạn và Fred đã làm hầu hết trong số đó, Bobby và tôi chỉ thêm một vài tinh chỉnh, IIRC.
Leonid Shifrin

8

Đây là công thức từ cuốn sách của Stan Wagon ... hãy sử dụng nó khi Plot tích hợp hoạt động thất thường do thiếu độ chính xác

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

Tôi thường sử dụng thủ thuật sau đây của Kristjan Kannike khi tôi cần hành vi "giống như từ điển" từ các giá trị của Mathicala

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]

Khi kết quả đánh giá khó hiểu, đôi khi nó giúp kết xuất các bước đánh giá vào một tệp văn bản

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

Một mẫu sử dụng sẽ là tuyệt vời. Hãy cố gắng đăng một khi bạn có thời gian.
Tiến sĩ belisarius

Bạn có biết Kristjan? Tôi từng làm việc trong cùng một nhóm với anh ta ở Helsinki. Chàng trai tốt, thế giới nhỏ bé.
Timo

Không, tìm thấy mã của mình trên web. Trên thực tế, đã cố gắng gửi email cho anh ấy để sửa một lỗi nhỏ trong mã, nhưng email trên trang web của anh ấy không còn hoạt động nữa
Yaroslav Bulatov

8

Có thể chạy MathKernel ở chế độ hàng loạt bằng cách sử dụng các tùy chọn dòng lệnh không có tài liệu-batchinput-batchoutput :

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

(trong đó input.mtệp đầu vào hàng loạt kết thúc bằng ký tự dòng mới, outputfile.txtlà tệp mà đầu ra sẽ được chuyển hướng).

Trong Mathematica . V> = 6 MathKernel có tùy chọn dòng lệnh không có giấy tờ:

-noicon

trong đó kiểm soát xem MathKernel sẽ có biểu tượng hiển thị trên Thanh tác vụ (ít nhất là trong Windows).

FrontEnd (ít nhất là từ v.5) có tùy chọn dòng lệnh không có giấy tờ

-b

vô hiệu hóa màn hình giật gân và cho phép chạy Mathematica FrontEnd nhanh hơn nhiều

và tùy chọn

-directlaunch

vô hiệu hóa các cơ chế mà ra mắt nhất gần đây Mathematica phiên bản cài đặt thay vì tung ra các phiên bản đi kèm với các file .nb trong hệ thống registry.

Một cách khác để làm điều này có lẽ :

Thay vì khởi chạy nhị phân Mathicala.exe trong thư mục cài đặt, hãy khởi chạy nhị phân Mathicala.exe trong SystemFiles \ FrontEnd \ Binaries \ Windows. Đây là một chương trình khởi chạy đơn giản, cố gắng hết sức để chuyển hướng các yêu cầu mở sổ ghi chép sang chạy các bản sao của giao diện người dùng. Cái sau là giao diện người dùng nhị phân.

Nó rất thuận tiện để kết hợp các tùy chọn dòng lệnh cuối cùng với thiết lập tùy chọn FrontEnd toàn cầu VersionedPreferences->True mà vô hiệu hóa việc chia sẻ sở thích giữa khác nhau Mathematica phiên bản cài đặt :

SetOptions[$FrontEnd, VersionedPreferences -> True]

(Những điều trên nên được đánh giá trong phiên bản Mathicala gần đây nhất được cài đặt.)

Trong Mathicala 8, điều này được điều khiển trong hộp thoại Tùy chọn, trong ngăn Hệ thống, trong cài đặt "Tạo và duy trì tùy chọn giao diện người dùng cụ thể của phiên bản" .

Có thể lấy danh sách các tùy chọn dòng lệnh của FrontEnd không đầy đủ bằng cách sử dụng khóa không có giấy tờ -h(mã cho Windows):

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

cho:

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

Các tùy chọn khác bao gồm:

-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

Có các tùy chọn dòng lệnh hữu ích nào khác của MathKernel và FrontEnd không? Hãy chia sẻ nếu bạn biết.

Câu hỏi liên quan .


"bitness phù hợp?" Điều đó nghĩa là gì?
Mr.Wizard

@ Mr.Wizard Có lẽ tùy chọn này chỉ có ý nghĩa trong các hệ thống 64 bit kết hợp với tùy chọn -32và có nghĩa là độ bit của MathKernel được FrontEnd sử dụng sẽ khớp với độ bit của hệ điều hành (64 bit). Có vẻ như trong các trường hợp khác, tùy chọn này sẽ không thay đổi bất cứ điều gì.
Alexey Popkov

7

Các hack yêu thích của tôi là các macro tạo mã nhỏ cho phép bạn thay thế một loạt các lệnh soạn sẵn tiêu chuẩn bằng một lệnh ngắn. Ngoài ra, bạn có thể tạo các lệnh để mở / tạo sổ ghi chép.

Đây là những gì tôi đã sử dụng một thời gian trong quy trình làm việc Mathicala hàng ngày của mình. Tôi thấy mình thực hiện rất nhiều điều sau đây:

  1. Làm cho một máy tính xách tay có một bối cảnh riêng tư, (các) gói tải tôi cần, làm cho nó tự động lưu.
  2. Sau khi làm việc với máy tính xách tay này một thời gian, tôi muốn thực hiện một số tính toán cào trong một sổ ghi chép riêng, với bối cảnh riêng tư của nó, trong khi có quyền truy cập vào các định nghĩa tôi đã sử dụng trong sổ ghi chép "chính". Vì tôi thiết lập bối cảnh riêng tư, điều này đòi hỏi phải điều chỉnh thủ công $ ContextPath

Làm tất cả những điều này bằng tay nhiều lần là một nỗi đau, vì vậy hãy tự động hóa! Đầu tiên, một số mã tiện ích:

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

Bây giờ, hãy tạo một macro sẽ đặt các ô sau vào sổ ghi chép:

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

Và đây là macro:

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

Bây giờ khi tôi nhập vào MyPrivatize[]sẽ tạo bối cảnh riêng tư và tải gói tiêu chuẩn của tôi. Bây giờ, hãy tạo một lệnh sẽ mở một sổ ghi chép mới với bối cảnh riêng tư của nó (để bạn có thể hack ở đó với sự từ bỏ hoang dã mà không có nguy cơ làm hỏng các định nghĩa), nhưng có quyền truy cập vào bối cảnh hiện tại của bạn.

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

Điều thú vị về điều này là do SelfDestruct, khi lệnh chạy, nó không để lại dấu vết trong sổ ghi chép hiện tại - điều này là tốt, bởi vì nếu không nó sẽ chỉ tạo ra sự lộn xộn.

Để biết thêm điểm phong cách, bạn có thể tạo trình kích hoạt từ khóa cho các macro này bằng cách sử dụng InputAutoReplacements, nhưng tôi sẽ để nó như một bài tập cho người đọc.


7

Đặt ứng dụng với PageWidth -> Infinity

Trong Mathicala sử dụng PutAppendlệnh là cách đơn giản nhất để duy trì tệp nhật ký đang chạy với kết quả tính toán trung gian. Nhưng nó sử dụng theo PageWith->78cài đặt mặc định khi xuất biểu thức sang tệp và do đó không có gì đảm bảo rằng mọi đầu ra trung gian sẽ chỉ lấy một dòng trong nhật ký.

PutAppendkhông có bất kỳ tùy chọn nào nhưng việc theo dõi các đánh giá của nó cho thấy rằng nó dựa trên OpenAppendhàm có PageWithtùy chọn và cho phép thay đổi giá trị mặc định của nó bằng SetOptionslệnh:

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

Vì vậy, chúng tôi có thể PutAppendchỉ nối thêm một dòng tại một thời điểm bằng cách cài đặt:

SetOptions[OpenAppend, PageWidth -> Infinity]

CẬP NHẬT

Có một lỗi được giới thiệu trong phiên bản 10 (đã sửa trong phiên bản 11.3): SetOptionskhông còn ảnh hưởng đến hành vi của OpenWriteOpenAppend .

Cách giải quyết là triển khai phiên bản của riêng bạn PutAppendvới PageWidth -> Infinitytùy chọn rõ ràng :

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

Lưu ý rằng chúng tôi cũng có thể thực hiện nó thông qua WriteStringnhư trong câu trả lời này , nhưng trong trường hợp này, cần phải sơ bộ chuyển đổi biểu thức thành tương ứng InputFormthông qua ToString[expr, InputForm].


6

Tôi chỉ xem qua một trong các gói của mình để đưa vào đây, và tìm thấy một số tin nhắn mà tôi xác định là công việc kỳ diệu : Debug::<some name>. Theo mặc định, chúng bị tắt, vì vậy đừng tạo ra nhiều chi phí. Nhưng, tôi có thể xả mã của mình với chúng và bật chúng lên nếu tôi cần tìm ra chính xác một chút mã đang hoạt động như thế nào.


Từ Trợ giúp> Kể từ Phiên bản 2.0 (phát hành năm 1991), Debug đã được thay thế bởi Trace.
Tiến sĩ belisarius

1
@ Belisarius, bạn đã bỏ lỡ điểm. Nó không phải là chức năng Debugcũng không Trace; đó là một tập hợp các tin nhắn tôi đã tạo mà tôi có thể xả mã của mình để bật / tắt tùy ý. Chúng được mở đầu bằng từ Debug, giống như cách một thông điệp usageđược mở đầu bằng tên của hàm. Nó cung cấp chức năng tương tự như đặt một loạt các coutcâu lệnh trong mã c ++.
rcollyer

1
Ồ ... xin lỗi. Tôi đã bối rối vì tôi chưa bao giờ tốt nghiệp mẫu giáo vì không học "Thủ đô là dành cho các quốc gia": D
Tiến sĩ belisarius

6

Một trong những điều làm phiền tôi về các cấu trúc phạm vi tích hợp là chúng đánh giá tất cả các định nghĩa biến cục bộ cùng một lúc, vì vậy bạn không thể viết ví dụ

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

Vì vậy, cách đây một thời gian tôi đã nghĩ ra một macro có tên WithNest cho phép bạn làm điều này. Tôi thấy nó tiện dụng, vì nó cho phép bạn giữ các ràng buộc biến cục bộ mà không phải làm gì đó như

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

Cuối cùng, cách tốt nhất tôi có thể tìm thấy để làm điều này là sử dụng một biểu tượng đặc biệt để giúp dễ dàng lặp lại danh sách các ràng buộc và tôi đặt định nghĩa vào gói riêng để ẩn biểu tượng này. Có lẽ ai đó có một giải pháp đơn giản hơn cho vấn đề này?

Nếu bạn muốn dùng thử, hãy đặt phần sau vào một tệp có tên 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[];

Janus đã đăng một phiên bản này và tham khảo câu hỏi của bạn trên Mathgroup: stackoverflow.com/questions/4190845/custom-notation-question/
Kẻ

Cảm ơn đã chỉ ra rằng! Đã được một thời gian kể từ khi tôi nhìn vào những thứ này, và thật thú vị khi thấy tất cả những cách tiếp cận khác.
DGrady

5

Bài này được viết bởi Alberto Di Lullo, (người dường như không xuất hiện trên Stack Overflow).

CopyToClipboard, đối với Mathicala 7 (trong Mathicala 8, nó được tích hợp sẵn)

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

Bài đăng gốc: http://forums.wolfram.com/mathgroup/archive/2010/Jun/msg00148.html

Tôi đã tìm thấy thói quen này hữu ích để sao chép số thực lớn vào bảng tạm ở dạng thập phân thông thường. Ví dụCopyToClipboard["123456789.12345"]

Cell[OutputFormData@expr] gọn gàng loại bỏ các trích dẫn.


5

Mã này tạo một bảng màu tải lên lựa chọn lên Stack Exchange dưới dạng hình ảnh. Trên Windows, một nút phụ được cung cấp cho phép hiển thị lựa chọn trung thực hơn.

Sao chép mã vào một ô ghi chép và đánh giá. Sau đó bật ra bảng màu từ đầu ra và cài đặt nó bằng cách sử dụngPalettes -> Install Palette...

Nếu bạn có bất kỳ rắc rối với nó, gửi bình luận ở đây. Tải về phiên bản notebook tại đây .


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

4

Tôi chắc rằng rất nhiều người đã gặp phải tình huống họ chạy một số thứ, nhận ra nó không chỉ làm kẹt chương trình, mà họ còn không lưu trong 10 phút qua!

BIÊN TẬP

Sau khi bị này trong một thời gian, tôi một ngày nào đó phát hiện ra rằng người ta có thể tạo ra tự động tiết kiệm từ bên trong Mathematica mã. Tôi nghĩ rằng việc sử dụng tính năng tự động lưu như vậy đã giúp tôi rất nhiều trong quá khứ và tôi luôn cảm thấy rằng khả năng đó là điều mà không nhiều người biết rằng họ có thể làm được.

Mã ban đầu tôi sử dụng là ở dưới cùng. Nhờ các ý kiến ​​mà tôi phát hiện ra rằng nó có vấn đề, và sẽ tốt hơn nhiều nếu làm theo cách khác, sử dụng ScheduledTask(sẽ chỉ hoạt động trong Mathicala 8).

Mã cho điều này có thể được tìm thấy trong câu trả lời này từ Sjoerd C. de Vries (Vì tôi không chắc có nên sao chép nó vào đây không, tôi chỉ để nó dưới dạng liên kết.)


Giải pháp dưới đây là sử dụng Dynamic. Nó sẽ lưu sổ ghi chép cứ sau 60 giây, nhưng dường như chỉ khi ô của nó hiển thị . Tôi để nó ở đây chỉ vì lý do hoàn thành. (và cho người dùng Mathicala 6 và 7)

/BIÊN TẬP

Để giải quyết nó, tôi sử dụng mã này vào đầu một cuốn sổ tay:

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

Điều này sẽ tiết kiệm công việc của bạn cứ sau 60 giây.
Tôi thích nó hơn NotebookAutoSave[]bởi vì nó lưu trước khi đầu vào được xử lý và bởi vì một số tệp có nhiều văn bản hơn đầu vào.

Ban đầu tôi tìm thấy nó ở đây: http://en.wikipedia.org/wiki/Talk:MathIALa#Criticism

Lưu ý rằng một khi chạy dòng này, việc lưu sẽ diễn ra ngay cả khi bạn đóng và mở lại tệp của mình (miễn là bật cập nhật động).

Ngoài ra, vì không có lùi lại trong Mathematica , hãy cẩn thận không để xóa tất cả nội dung của bạn, vì tiết kiệm sẽ làm cho nó không thể đảo ngược (như là một động thái đề phòng, tôi loại bỏ mã này từ mỗi máy tính xách tay hoàn chỉnh)


bạn cũng có thể lưu nó với một tên khác (ví dụ: bằng cách nối thời gian và ngày hiện tại vào cuối tên tệp) và có thể trong một thư mục cụ thể ("Sao lưu", giả sử). đây sẽ giống như một hình thức nguyên thủy của phiên bản.
acl

Bạn có thể làm một cái gì đó như thế NotebookSave[SelectedNotebook[], "work-" <> IntegerString[i] <> ".nb"]; i++, nhưng tôi nghĩ rằng bất kỳ loại tham chiếu đến tên máy tính xách tay hiện tại sẽ trở thành đệ quy.
tsvikas

2
Tôi nghĩ Dynamiccác đối tượng chỉ được làm mới khi chúng hiển thị, vì vậy tôi sẽ không chắc chắn rằng phương thức này sẽ hoạt động nếu ví dụ bạn cuộn Dynamicđối tượng ra khỏi vùng nhìn thấy được. Sau đó, một lần nữa, tôi đã không cố gắng. Trong mọi trường hợp, tôi chỉ đề nghị nó như một đề nghị.
acl

1
Bạn có thể kiểm tra điều này bằng cách sử dụng Dynamic[Refresh[i++, UpdateInterval -> 1, TrackedSymbols -> {}]]. Cuộn số tăng dần từ tầm nhìn, đợi một phút, cuộn lại và xem số không tăng thêm 60. Giới thiệu UpdateInterval: điều này thường được sử dụng nếu có thể, nhưng nếu mã của bạn bao gồm các biến thay đổi, thay đổi này sẽ kích hoạt làm mới mới trước khoảng thời gian kết thúc. Hãy thử dòng trên mà không cóTrackedSymbols
Sjoerd C. de Vries

1
@ j0ker5 Hãy thử mã trên của tôi và bạn có thể thấy rằng UpdateInterval không phải lúc nào cũng buộc các bản cập nhật được đặt cách nhau với khoảng thời gian được chỉ định. Mã này cũng cho thấy rằng Dynamic chỉ hoạt động nếu ô được chứa trong đó hiển thị trong frontend . Nó thực sự dừng lại khoảnh khắc nó khuất khỏi tầm mắt. Mọi người thực sự không nên tin tưởng mã này để lưu các tệp của họ bởi vì nó không. Nguy hiểm của nó
Sjoerd C. de Vries


3

Tôi thấy nó thực sự hữu ích khi phát triển các gói để thêm phím tắt này vào SystemFiles/FrontEnd/TextResources/Windows/KeyEventTranslations.trtệp của mình .

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

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

Tiếp theo cho mỗi Packagename.mtôi tạo một PackagenameTest.nbsổ ghi chép để kiểm tra và 2 ô đầu tiên của sổ ghi chép kiểm tra được đặt làm các ô khởi tạo. Trong ô đầu tiên tôi đặt

Needs["PackageManipulations`"]

để tải thư viện PackageManipulation rất hữu ích được viết bởi Leonid. Ô thứ hai chứa

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

mà tất cả làm gói tải lại thực tế. Lưu ý hai dòng đầu tiên chỉ có ở Removetất cả các biểu tượng vì tôi muốn giữ cho bối cảnh càng sạch càng tốt.

Sau đó, quy trình viết và kiểm tra một gói trở thành như thế này.

  1. Lưu các thay đổi vào Packagename.m.
  2. Đi PackagenameTest.nbvà làm CTRL + ALT + i.

Điều này làm cho các ô khởi tạo tải lại gói, điều này làm cho việc kiểm tra thực sự đơn giản.


1

Chức năng sau format[expr_]có thể được sử dụng để thụt lề / định dạng các mathematicabiểu thức không được định dạng trải dài trên một trang

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-opes-USE-given-parentheses


Bạn đang sử dụng cái này để làm gì trong thực tế? Đầu ra hơi "buồn cười" khi có thể đọc được khi áp dụng cho mã của bạn hoặc dữ liệu (danh sách, format@RandomInteger[10,{3,3}]): pastebin.com/nUT54Emq Vì bạn đã có những điều cơ bản và bạn quan tâm đến điều này, bạn có thể cải thiện mã này không sản xuất một định dạng hữu ích có thể đọc được? Sau đó, bước tiếp theo sẽ là tạo một nút dán để tạo một ô nhập liệu với mã Mathicala được thụt lề độc đáo (tốt nhất là giữ nguyên các bình luận !!) Xem thêm câu hỏi liên quan của tôi .
Szabolcs
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.