代码之家  ›  专栏  ›  技术社区  ›  Dave Jensen Steve

你的Mathematica工具包里有什么?[关闭]

  •  144
  • Dave Jensen Steve  · 技术社区  · 6 年前

    我们都知道Mathematica很棒,但它也常常缺少关键的功能。Mathematica使用什么样的外部包/工具/资源?

    我将编辑(并邀请其他人也这么做)这篇主要的文章,包括资源集中在一般的适用性在科学研究和尽可能多的人会发现有用的。请随意贡献任何东西,甚至是小代码片段(就像我在下面为计时例程所做的那样)。

    此外,Mathematica 7中的未记录和有用功能以及其他您自己发现的功能,或从一些文件/网站上挖掘出来的功能都是非常受欢迎的。

    请包括一个简短的描述或评论为什么某事是伟大的或它提供了什么效用。如果你链接到亚马逊上的书籍,有会员链接,请提及,例如,在链接后加上你的名字。


    包装:

    1. LevelScheme 是一个包,极大地扩展了Mathematica的能力,以产生好看的情节。如果没有其他用途,我会使用它来改进对帧/轴刻度的控制。它的最新版本称为SciDraw,将于今年某个时候发布。
    2. 大卫公园 Presentation Package (50美元-更新不收费)
    3. 杰里米·迈克尔逊的 grassmannOps 包为使用格拉斯曼变量和具有非平凡交换关系的运算符进行代数和微积分提供了资源。
    4. 约翰·布朗的 GrassmannAlgebra 与Grassmann和Clifford代数一起工作的包和书。
    5. RISC (Research Institute for Symbolic Computation) 有多种Mathematica(和其他语言)软件包可供下载。尤其是 Theorema 用于自动定理证明,以及在 Algorithmic Combinatorics group's software page .

    工具:

    1. MASH 丹尼尔·里夫斯很棒吗 Perl 脚本本质上为Mathematica v7提供脚本支持。(现在自Mathematica 8开始内置 -script 选项。)
    2. 一个 alternate Mathematica shell 使用GNU readline输入(使用python,仅*nix)
    3. colourmath包允许您可视化地选择表达式的部分并对其进行操作。 http://www.dbaileyconsultancy.co.uk/colour_maths/colour_maths.html

    资源:

    1. Wolfram自己的仓库 MathSource 有很多有用的,如果缩小笔记本电脑的各种应用。也可以查看其他部分,如

    2. 这个 Mathematica Wikibook .

    书:

    1. Mathematica编程:高级介绍 利奥尼德·希夫林( web , pdf )如果你想做任何超过 为了 Mathematica中的循环。我们很高兴 Leonid 他在这里回答问题。
    2. 数学量子方法 作者:詹姆斯费金( amazon )
    3. 数学书 斯蒂芬·沃尔夫拉姆( amazon ) ( web )
    4. 夏姆的轮廓 ( amazon )
    5. 数学家在行动 斯坦瓦格( amazon )-600页整洁的例子,并上升到Mathematica版本7。可视化技术特别好,你可以在作者的 Demonstrations Page .
    6. Mathematica编程基础 理查德·盖洛德( pdf )-对Mathematica编程所需了解的大部分内容的简明介绍。
    7. 萨尔曼加诺的Mathematica食谱由O'Reilly出版,2010年832页。-以著名的O'Reilly食谱风格写的:问题解决。中间产物。
    8. 带Mathematica的微分方程,第3版,Elsevier 2004阿姆斯特丹 由玛莎L.阿贝尔,詹姆斯P.布拉塞顿-893页初学者,学习解决DEs和数学家在同一时间。

    未记录(或几乎没有记录)的特征:

    1. 如何自定义Mathematica键盘快捷键。见 this question .
    2. 如何检查Mathematica自己的函数使用的模式和函数。见 this answer
    3. 如何在Mathematica中实现图形块的一致大小?见 this question .
    4. 如何使用Mathematica生成文档和演示文稿。见 this question .
    26 回复  |  直到 8 年前
        1
  •  29
  •   rcollyer    8 年前

    我说过了 this 以前,但我发现最有用的工具是 Reap Sow 它模仿/扩展了 GatherBy :

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

    这允许我按任何条件对列表进行分组,并在过程中对它们进行转换。它的工作方式是( f )标记列表中的每个项,然后由第二个提供的函数转换每个项( g ),具体输出由第三个函数控制( h ). 功能 小时 接受两个参数:标记和具有该标记的已收集项的列表。这些项保留其原始顺序,因此如果设置 h = #1& 然后你得到一个未排序的 Union ,就像在 examples 对于 收割 . 但是,它可以用于二次加工。

    作为其效用的一个例子,我一直在与 Wannier90 它将空间相关的哈密顿量输出到一个文件中,其中每一行是矩阵中的不同元素,如下所示

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

    为了将该列表转换为一组矩阵,我收集了包含相同坐标的所有子列表,将元素信息转换为规则(即{I,j}->Re[Hij]+I Im[Hij]),然后将收集的规则转换为 SparseArray 只有一行:

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

    老实说,这是我的瑞士军刀,它使复杂的事情变得非常简单。我的大多数其他工具都是特定于领域的,所以我可能不会发布它们。然而,大多数,如果不是全部的话,他们提到 SelectEquivalents .

    编辑 :它没有完全模仿 GatherBy 因为它不能像 格拉斯比 可以。然而, Map 对我所需要的大部分都很好。

    例子 :@Yaroslav Bulatov要求一个独立的例子。这是我的研究中的一个被大大简化了的。假设我们在平面上有一组点

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

    我们想通过一组对称运算来减少点数。(出于好奇,我们正在生成 little group 对于这个例子,让我们使用绕Z轴的四倍旋转轴。

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

    使用 选择等价物 我们可以在这些操作下对产生相同图像集的点进行分组,即它们是等价的,使用以下方法

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

    它产生3个子列表,包含等价点。(注, 工会 在这里是绝对重要的,因为它可以确保每个点产生相同的图像。最初,我用 Sort 但是,如果一个点位于对称轴上,则在围绕该轴旋转的情况下是不变的,该轴赋予自身一个额外的图像。所以, 工会 消除这些额外的图像。也, 格拉斯比 会产生相同的结果。)在本例中,这些点已经是我将使用的形式,但是我只需要每个分组中的一个代表点,并且我想要一个等价点的计数。因为,我不需要转换每个点,我使用 Identity 功能在第二个位置。对于第三个功能,我们需要小心。传递给它的第一个参数将是该点在旋转下的点的图像 {0,0,0} 是一个包含四个相同元素的列表,使用它会使计数减少。但是,第二个参数只是具有该标记的所有元素的列表,因此它将只包含 {0,0,0} . 在代码中,

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

    注意,最后一步同样可以通过

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

    但是,使用这个示例和上面不太完整的示例很容易看出使用最少的代码可以实现多么复杂的转换。

        2
  •  57
  •   WReach    14 年前

    Mathematica笔记本界面的一个优点是它可以计算 任何 语言,不仅仅是数学。作为一个简单的例子,考虑创建一个新的 外壳 输入单元格类型,将包含的表达式传递给操作系统外壳程序进行计算。

    首先,定义一个函数,将文本命令的求值委托给外部shell:

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

    第二个论点是必要的,并被忽略,其原因将在稍后变得显而易见。接下来,我们要创建一个名为 外壳 :

    1. 打开一个新笔记本。
    2. 选择菜单项 格式化/编辑样式表。。。
    3. 在对话框中,旁边 输入样式名称: 类型 Shell .
    4. 选择新样式旁边的单元格括号。
    5. 选择菜单项 单元格/显示表达式
    6. 用覆盖单元格表达式 步骤6文本 如下所示。
    7. 再次选择菜单项 单元格/显示表达式
    8. 关闭对话框。

    使用以下单元格表达式作为 步骤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"]
    

    这个表达式的大部分是直接从内置的 程序 风格。主要变化如下:

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

    Evaluatable 启用单元格的SHIFT+ENTER功能。评估将调用 CellEvaluationFunction 将单元格内容和内容类型作为参数传递( shellEvaluate 忽略后一个参数)。 CellFrameLabels 只是一个让用户识别这个单元格不寻常的细节。

    所有这些就绪后,我们现在可以输入和计算shell表达式:

    1. 在上述步骤中创建的笔记本中,创建一个空单元格并选择单元格括号。
    2. 选择菜单项 格式/样式/外壳 .
    3. 在单元格中键入有效的操作系统shell命令(例如,Unix上的“ls”或Windows上的“dir”)。
    4. 按SHIFT+ENTER。

    最好将此定义的样式保存在位于中心位置的样式表中。此外,评估功能包括 shellEvaluate 最好定义为使用 DeclarePackage 在里面 init.m . 这两项活动的细节超出了本答复的范围。

    使用此功能,可以创建包含任何感兴趣语法的输入表达式的笔记本。评估函数可以用纯Mathematica编写,也可以将评估的任何或所有部分委托给外部机构。请注意,还有其他与单元格计算相关的挂钩,如 CellEpilog , CellProlog CellDynamicExpression .

    一种常见的模式包括将输入表达式文本写入临时文件、用某种语言编译文件、运行程序和捕获输出以最终显示在输出单元格中。在实现这种完整的解决方案时,有很多细节需要处理(比如正确地捕获错误消息),但是必须认识到这样做不仅是可能的,而且是实际可行的。

    就个人而言,正是这些特性使得笔记本界面成为我编程领域的中心。

    更新

    以下助手函数对于创建此类单元格非常有用:

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

    因此:

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

    现在,如果 shellCell[] 计算后,输入单元格将被删除并替换为新的输入单元格,该输入单元格将作为shell命令计算其内容。

        3
  •  35
  •   Alexey Popkov    8 年前

    Todd Gayley(Wolfram Research)刚刚给我发了一个不错的黑客程序,允许用任意代码“包装”内置函数。我觉得我必须分享这个有用的工具。下面是托德对我的回答 question .

    有点意思(?)历史:那种“包装”一个 内置函数是我和Robby Villegas在1994年左右发明的, 具有讽刺意味的是,在一个名为ErrorHelp的包中 那时候我为Mathematica杂志写的。它已经被使用了 很多次,很多人,从那时起。有点内幕 诡计,但我认为公平地说,它已经成为 将自己的代码注入内置代码定义的方法 功能。它把工作做得很好。当然,你可以把 $inMsg变量进入您希望的任何私有上下文。

    Unprotect[Message];
    
    Message[args___] := Block[{$inMsg = True, result},
       "some code here";
       result = Message[args];
       "some code here";
       result] /; ! TrueQ[$inMsg]
    
    Protect[Message];
    
        4
  •  25
  •   therealhoff    8 年前

    这不是一个完整的资源,所以我把它放在这里的答案部分,但我发现它在解决速度问题时非常有用(不幸的是,这是Mathematica编程的一个重要部分)。

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

    用法很简单 timeAvg@funcYouWantToTest .

    编辑:Wizard先生提供了一个更简单的版本 Throw Catch 更容易分析:

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

    编辑:以下是 acl (摘自 here ):

    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]
    
        5
  •  20
  •   Alexey Popkov    14 年前

    Internal`InheritedBlock

    我最近学到了这样有用的函数的存在。 内部`InheritedBlock ,来自 this message of Daniel Lichtblau 在官方新闻组。

    据我所知, 内部`InheritedBlock 允许在 Block 范围:

    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]
    

    我觉得这个功能对每个需要临时修改内置功能的人都非常有用!

    与块比较

    让我们定义一些函数:

    a := Print[b]
    

    现在我们希望将此函数的副本传递给 阻塞 范围。天真的审判没有给我们想要的:

    In[2]:= Block[{a = a}, OwnValues[a]]
    
    During evaluation of In[9]:= b
    
    Out[2]= {HoldPattern[a] :> Null}
    

    现在尝试在的第一个参数中使用延迟定义 阻塞 (这也是一个未记录的功能):

    In[3]:= Block[{a := a}, OwnValues[a]]
    Block[{a := a}, a]
    
    Out[3]= {HoldPattern[a] :> a}
    
    During evaluation of In[3]:= b
    

    我们在这个案子里看到了 a 很好,但我们没有原件的复印件 阻塞 范围。

    现在让我们试试 内部`InheritedBlock :

    In[5]:= Internal`InheritedBlock[{a}, OwnValues[a]]
    
    Out[5]= {HoldPattern[a] :> Print[b]}
    

    我们有一份原始定义的副本 阻塞 作用域,我们可以按照所需的方式修改它,而不影响 !

        6
  •  19
  •   WReach    8 年前

    Mathematica是一个锋利的工具,但它可以用它的一些 untyped behaviour avalanches 神秘的 diagnostic messages . 处理此问题的一种方法是按照此习惯用法定义函数:

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

    这是很多样板,我经常想跳过。尤其是原型设计,在Mathematica中经常发生。所以,我使用一个宏 define 这让我能保持纪律,少了很多陈词滥调。

    基本用法 定义 是这样的:

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

    一开始看起来不太像,但有一些隐藏的好处。第一次服务 定义 规定它自动应用 ClearAll 到正在定义的符号。这可以确保没有遗留定义——这是函数初始开发过程中的常见情况。

    第二个服务是定义的函数自动“关闭”。我的意思是,如果调用函数时使用的参数列表与以下定义之一不匹配,则该函数将发出消息并中止:

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

    这是 定义 ,它捕获一类非常常见的错误。

    另一个方便的方法是在定义的函数上指定属性。让我们做个函数 Listable :

    define[
      fact[0] = 1
    ; fact[n_ /; n > 0] := n * fact[n-1]
    , Listable
    ]
    
    fact[{3, 5, 8}]
    
    {6, 120, 40320}
    

    除了所有的正常属性, 定义 接受一个名为 Open . 这样可以防止 定义 从向函数添加catch all错误定义开始:

    define[
      successor[x_ /; x > 0] := x + 1
    , Open
    ]
    
    successor /@ {1, "hi"}
    
    {2, successor["hi"]}
    

    可以为函数定义多个属性:

    define[
      flatHold[x___] := Hold[x]
    , {Flat, HoldAll}
    ]
    
    flatHold[flatHold[1+1, flatHold[2+3]], 4+5]
    
    Hold[1 + 1, 2 + 3, 4 + 5]
    

    不用再费吹灰之力,这里是 定义 :

    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: ``";
    

    所展示的实现既不支持up值也不支持curring,也不支持比简单函数定义更通用的模式。不过,它仍然有用。

        7
  •  16
  •   Mr.Wizard    9 年前

    开始时不打开空白笔记本

    我被打开一个空白笔记本开始Mathematica而困扰。我可以用脚本关闭这个笔记本,但它仍然会短暂地闪开。我的诀窍是创建一个文件 Invisible.nb 包含:

    Notebook[{},Visible->False]
    

    把这个加到我的 Kernel\init.m :

    If[Length[Notebooks["Invisible*"]] > 0, 
      NotebookClose[Notebooks["Invisible*"][[1]]]
    ]
    
    SetOptions[$FrontEnd,
      Options[$FrontEnd, NotebooksMenu] /. 
        HoldPattern["Invisible.nb" -> {__}] :> Sequence[]
    ]
    

    我现在开始数学家 不可见.nb

    也许有更好的办法,但这对我很有帮助。


    定制的 Fold FoldList

    Fold[f, x] 相当于 Fold[f, First@x, Rest@x]

    顺便说一句,我相信这可能会在未来的Mathematica版本中出现。

    Surprise! This has been implemented, though it is presently undocumented. 我被告知它是由奥利弗·鲁本科尼在2011年实施的,显然是在我发布这篇文章不久之后。谢谢奥利弗·鲁本科尼!

    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]
    

    已更新以允许此操作:

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

    “动态分区”

    Mathematica.SE post #7512 用于此函数的新版本。

    我经常想根据一系列的长度来划分一个列表。

    伪代码示例:

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

    输出: {{1,2}, {3,4,5}, {6}}

    我想到了这个:

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

    然后我完成了这个,包括参数测试:

    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
    

    第三个参数控制对拆分规范之外的元素的处理。


    Szabolcs's Mathematica tricks

    我最常用的是粘贴表格数据调色板

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

    从内部修改外部数据 Compile

    最近丹尼尔·利希特布展示了我从未见过的这种方法。在我看来,它大大扩展了 编译

    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.}  *)
    
        8
  •  14
  •   Alexey Popkov    8 年前

    通用PDF/EMF导出问题及解决方案

    1) 这是完全出乎意料的,没有记录,但是 数学软件 使用一组与在屏幕上显示笔记本不同的样式定义,以PDF和EPS格式导出和保存图形。默认情况下,笔记本电脑显示在“工作”样式环境的屏幕上(这是 ScreenStyleEvironment 全球的 $FrontEnd 选项),但打印在 "Printout" 样式环境(这是 PrintingStyleEnvironment 全球的 $前端 选项)。以光栅格式(如GIF和PNG)或EMF格式导出图形时 数学软件 生成的图形与笔记本中的图形完全相同。看来 "Working" 在这种情况下,样式环境用于渲染。但在导出/保存PDF或EPS格式的任何内容时,情况并非如此!在这种情况下 "Printout" style environment is used by default 这与“工作”式的环境有很大的不同。首先, the "Printout" style environment sets Magnification to 80% . 其次,它对不同样式的字体大小使用自己的值,这会导致genarated PDF文件中的字体大小更改与原始屏幕表示不一致。后者可以称为 FontSize fluctuations 真烦人。 但幸运的是这是可以避免的 by setting the PrintingStyleEnvironment global $FrontEnd option to "Working" :

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

    2) 导出为EMF格式的常见问题是大多数程序(不仅是 数学软件 )生成一个文件,该文件在默认大小下看起来不错,但放大时会变得很难看。是因为 metafiles are sampled at screen resolution fidelity . 生成的EMF文件的质量可以通过 Magnify 对原始图形对象进行采样,使原始图形的采样精度大大提高。比较两个文件:

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

    如果将这些文件插入Microsoft Word并放大,您将看到第一个“a”上有锯齿,而第二个没有(用 数学软件 6) 是的。

    另一条路穿过 ImageResolution 是由 Chris Degnen (此选项至少从 数学软件 8) 以下内容:

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

    3) 在 数学软件 我们有三种方法可以将图形转换为元文件:via Export "EMF" (强烈建议的方法:生成尽可能高质量的图元文件),通过 Save selection As... 菜单项( produces much lesser precise figure ,不推荐)和通过 Edit ► Copy As ► Metafile 菜单项( I strongly recommend against this route ).

        9
  •  13
  •   Sjoerd C. de Vries    8 年前

    根据大众的需求,生成前十名的代码,所以答案的情节(除了 annotations )使用 SO API .

    enter image description here

    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", ""})]
    
        10
  •  13
  •   faysou    8 年前

    缓存表达式

    我发现这些函数对缓存任何表达式都非常有用。这两个函数的有趣之处在于,与mathematica中众所周知的记忆相比,持有表达式本身被用作哈希表/符号缓存或缓存索引的键,在mathematica中,只有当函数定义为f[x]:=f[x]=。。。所以你可以缓存代码的任何部分,如果一个函数要被多次调用,这很有用,但是代码的某些部分不能被重新计算。

    独立于参数缓存表达式。

    SetAttributes[Cache, HoldFirst];
    c:Cache[expr_] := c = expr;
    
    Ex: Cache[Pause[5]; 6]
    Cache[Pause[5]; 6]
    

    表达式第二次返回6而不等待。

    使用可以依赖于缓存表达式的参数的别名表达式缓存表达式。

    SetAttributes[CacheIndex, HoldRest];
    c:CacheIndex[index_,expr_] := c = expr;
    
    Ex: CacheIndex[{"f",2},x=2;y=4;x+y]
    

    如果expr需要一些时间来计算,那么计算{“f”,2}要快得多,例如检索缓存的结果。

    为了有一个本地化的缓存(即缓存内存在块构造之外自动释放),这些函数的变体见本文 Avoid repeated calls to Interpolation

    删除缓存值

    在不知道函数定义的数目时删除缓存值。我认为这些定义在它们的论点中有些地方是空白的。

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

    在知道函数定义的数量时删除缓存值(速度稍快)。

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

    这使用了这样一个事实:函数的定义在它们的DownValues列表的末尾,缓存的值在前面。

    使用符号存储数据和类对象函数

    这里还有一些有趣的函数来使用象对象这样的符号。

    众所周知,可以将数据存储在符号中,并使用DownValues快速访问它们

    mysymbol["property"]=2;
    

    您可以使用以下函数访问符号的键(或属性)列表,这些函数基于在本网站的帖子中提交的数据:

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

    我经常使用这个函数来显示符号的DownValues中包含的所有信息:

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

    最后,这里有一个简单的方法来创建一个在面向对象编程中表现得像对象的符号(它只是再现了OOP最基本的行为,但我发现语法很优雅):

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

    属性作为DownValues存储,方法作为延迟的Upvalues存储在由返回的模块创建的符号中。我发现function2的语法是 Tree data structure in Mathematica .

    对于每个符号的现有值类型列表,请参阅 http://reference.wolfram.com/mathematica/tutorial/PatternsAndTransformationRules.html http://www.verbeia.com/mathematica/tips/HTMLLinks/Tricks_Misc_4.html .

    例如,试试这个

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

    如果要使用此处提供的名为InheritRules的包来模拟对象继承,则可以更进一步 http://library.wolfram.com/infocenter/MathSource/671/

    还可以将函数定义存储在类型符号中,而不是存储在newObject中,因此如果newObject返回类型[newObject]而不是newObject,则可以这样定义函数和函数2 在NewObject的外部(而不是内部),并具有与以前相同的用法。

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

    使用UpValues[type]查看在类型符号中定义的函数和函数2。

    关于最后一个语法的进一步想法将在这里介绍 https://mathematica.stackexchange.com/a/999/66

    SelectEquivalent的改进版本

    @rcollyer:非常感谢您将selectequivalent带到了表面,这是一个令人惊奇的功能。 下面是上面列出的selectequalifications的改进版本,它具有更多的可能性和使用选项,这使它更易于使用。

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

    以下是如何使用此版本的示例:

    Using Mathematica Gather/Collect properly

    How would you do a PivotTable function in Mathematica?

    Mathematica fast 2D binning algorithm

    内部`Bag

    Daniel Lichtblau在这里描述了一个有趣的内部数据结构,用于不断增长的列表。

    Implementing a Quadtree in Mathematica

    调试函数

    这两篇文章指出了调试的有用功能:

    How to debug when writting small or big codes using Mathematica? workbench? mma debugger? or something else? (展示)

    https://stackoverflow.com/questions/5459735/the-clearest-way-to-represent-mathematicas-evaluation-sequence/5527117#5527117 (跟踪视图)

    下面是另一个基于Reap和Sow的函数,用于从程序的不同部分提取表达式并将其存储在符号中。

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

    这里有一个例子

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

    其他资源

    以下是学习目的的有趣链接列表:

    A collection of Mathematica learning resources

    更新位置: https://mathematica.stackexchange.com/a/259/66

        11
  •  12
  •   dreeves    15 年前

    我的实用程序函数(我将这些函数内置到MASH中,这在问题中提到):

    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).   *)
    
        12
  •  11
  •   Pillsy    15 年前

    我使用的一个技巧是,允许您模拟大多数内置函数处理错误参数的方式(通过发送消息,然后返回未评估的整个表单),它利用了一种奇怪的方式 Condition 用于定义时有效。如果 foo 只能使用一个参数:

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

    如果您有更复杂的需求,那么很容易将参数验证和消息生成作为一个独立的函数来考虑。你可以通过使用 条件 除了生成消息,但在我看来,大多数都属于“下流黑客”的范畴,如果可能的话应该避免。

    另外,在“元编程”类别中,如果您有Mathematica包( .m )文件,您可以使用 "HeldExpressions" element 将文件中的所有表达式打包到 HoldComplete . 这比使用基于文本的搜索要容易得多。不幸的是,在笔记本上做同样的事情并不容易,但是您可以使用如下方法获得所有的输入表达式:

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

    最后,你可以利用这个事实 Module 模拟词汇闭包创建等价的引用类型。下面是一个简单的堆栈(它使用 条件 错误处理技巧作为奖励):

    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]
    

    现在,您可以以不必要的复杂方式以相反的顺序打印列表元素!

    With[{stack = MakeStack[], list},
     Do[Push[stack, elt], {elt, list}];
    
     While[!EmptyQ[stack],
      Print[Peek@stack];
      Pop@stack]]
    
        13
  •  11
  •   Szabolcs    14 年前

    打印系统符号定义时不带上下文前缀

    这个 contextFreeDefinition[] 下面的函数将尝试打印符号的定义,而不在最常见的上下文之前。然后,可以将定义复制到Workbench并格式化为可读性(选择它,右键单击,源->格式)

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

    有规则[]

    警告: 此函数不以相同的方式本地化变量 With Module 是的,这意味着嵌套的本地化构造将无法按预期工作。 withRules[{a -> 1, b -> 2}, With[{a=3}, b_ :> b]] 代替 a b 在嵌套中 Rule ,而 不会这么做的。

    这是 使用规则而不是 = := :

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

    在清理实验期间编写的代码和本地化变量时,我发现这很有用。有时我会以参数列表的形式结束 {par1 -> 1.1, par2 -> 2.2} . 与 withRules 参数值很容易注入到以前使用全局变量编写的代码中。

    用法就像 :

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

    抗锯齿三维图形

    这是一种非常简单的反别名三维图形技术,即使您的图形硬件不支持它。

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

    下面是一个例子:

    Mathematica graphics Mathematica graphics

    注意,对于 n 或者一个大的图像大小往往会暴露图形驱动程序错误或引入人工制品。


    笔记本差异功能

    笔记本差异功能在 <<AuthorTools` 包,并且(至少在版本8中)在 NotebookTools` 上下文。这是一个小GUI,用于区分当前打开的两个笔记本:

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

    Mathematica graphics

        14
  •  9
  •   Leonid Shifrin    15 年前

    递归纯函数( #0 )似乎是语言中最黑暗的角落之一。下面是一些非常有用的例子(并不是说没有它们就做不到)。下面是一个非常简洁且速度相当快的函数,用于在给定指定为顶点对的边列表的情况下查找图中的连接组件:

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

    这里发生的事情是,我们首先在每个顶点编号上映射一个虚拟符号,然后设置一种方式,给定一对顶点 {f[5],f[10]} ,说,那么 f[5] 会评估为 f[10] . 递归纯函数用作路径压缩器(以这样的方式设置记忆,而不是像 f[1]=f[3],f[3]=f[4],f[4]=f[2], ... ,当发现组件的新“根”时,将更正记住的值。这就大大加快了速度。因为我们使用赋值,所以我们需要它是HoldAll,这使得这个结构更加模糊,更加吸引人)。此函数是由Fred Simons、Szabolcs Horvat、DrMajorBob和您的Really在线和离线Mathgroup讨论的结果。例子:

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

    它当然比内置的要慢得多,但是对于代码的大小来说,仍然是相当快的。

    另一个例子:这里是 Select ,基于链表和递归纯函数:

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

    例如,

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

    但是,它并不是正确的尾部递归,并且会为更大的列表破坏堆栈(崩溃内核)。下面是尾部递归版本:

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

    例如,

    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}} 
    
        15
  •  8
  •   Yaroslav Bulatov    15 年前

    这是斯坦·瓦格纳的书中的配方…当内置的情节由于缺乏精确性而表现不稳定时使用它

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

    当我需要Mathematica的downvalues中的“字典式”行为时,我经常使用Kristjan Kannike的以下技巧

    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]
    

    当评估结果令人困惑时,有时将评估步骤转储到文本文件中会有所帮助

    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]]
    
        16
  •  8
  •   Alexey Popkov    8 年前

    可以使用未记录的 command-line options -batchinput and -batchoutput :

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

    (其中 input.m 是以换行符结尾的批输入文件, outputfile.txt 将输出重定向到的文件)。

    数学软件 v、 >=6 MathKernel有未记录的命令行选项:

    -noicon
    

    它控制MathKernel是否在任务栏上有可见的图标(至少在Windows下)。

    前端(至少从v.5版开始)有未记录的命令行选项

    -b
    

    它禁用启动屏幕并允许运行 数学软件 前端速度更快

    和选择权

    -directlaunch
    

    哪一个 disables the mechanism which launches the most recent Mathematica version installed 而不是在系统注册表中启动与.nb文件关联的版本。

    另一种方法可能是 is :

    而不是启动 Mathematica.exe二进制文件 安装目录,启动 Mathematica.exe二进制文件 系统文件\前端\二进制文件\窗口。 前者是一个简单的发射器 尽最大努力 重定向打开请求 运行的笔记本副本 用户界面。后者是 用户界面二进制文件本身。

    将最后一个命令行选项与设置全局前端选项结合起来很方便 VersionedPreferences->True which disables sharing of preferences between different Mathematica versions installed :

    SetOptions[$FrontEnd, VersionedPreferences -> True]
    

    (以上应在最近的 数学软件 已安装版本。)

    数学软件 this is controlled in the Preferences dialog, in the System pane, under the setting "Create and maintain version specific front end preferences" .

    使用未记录的键可以获取前端命令行选项的不完整列表 -h (Windows代码):

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

    给予:

    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
    

    其他选项包括:

    -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
    

    MathKernel和前端还有其他可能有用的命令行选项吗?如果你知道,请分享。

    Related question .

        17
  •  7
  •   Leo Alekseyev    15 年前

    我最喜欢的技巧是生成宏的小代码,它允许您用一个短命令替换一堆标准样板命令。或者,可以创建用于打开/创建笔记本的命令。

    以下是我在日常Mathematica工作流中使用了一段时间的内容。我发现自己经常做以下事情:

    1. 使笔记本具有私人上下文,加载我需要的包,使其自动保存。
    2. 在使用这个笔记本一段时间后,我想在一个单独的笔记本中使用它自己的私有上下文进行一些一次性的临时计算,同时访问我在“主”笔记本中使用的定义。因为我设置了私有上下文,所以需要手动调整$ContextPath

    一次又一次地做这些是件痛苦的事,所以让我们自动化吧!首先,一些实用程序代码:

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

    现在,让我们创建一个宏,将以下单元格放入笔记本:

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

    下面是宏:

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

    现在当我输入 MyPrivatize[] 创建私有上下文并加载我的标准包。现在,让我们创建一个命令,该命令将打开一个新的scratch笔记本,它有自己的私有上下文(这样您就可以肆无忌惮地进行黑客攻击,而不会有搞乱定义的风险),但是可以访问您当前的上下文。

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

    最酷的是因为 SelfDestruct ,当命令运行时,它不会在当前笔记本中留下任何痕迹——这很好,因为否则只会造成混乱。

    对于额外的样式点,可以使用 InputAutoReplacements ,但我将把这个留给读者作为练习。

        18
  •  7
  •   Alexey Popkov    7 年前

    带PageWidth的putpappend->无限大

    数学软件 使用 PutAppend 命令是维护运行日志文件和中间计算结果的最直接的方法。但它默认使用 PageWith->78 将表达式导出到文件时的设置,因此无法保证每个中间输出在日志中只占用一行。

    PutAppend公司 本身没有任何选项,但是跟踪它的评估会发现它基于 OpenAppend 具有 PageWith 选项,并允许通过 SetOptions 命令:

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

    所以我们可以 PutAppend公司 通过设置一次只追加一行:

    SetOptions[OpenAppend, PageWidth -> Infinity]
    

    更新

    有一个 bug 在版本10中引入(在版本11.3中修复): 设置选项 不再影响 OpenWrite 打开附加 .

    解决方法是实现自己版本的 PutAppend公司 带显式 PageWidth -> Infinity 选项:

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

    注意,我们也可以通过 WriteString 如所示 this 回答,但在这种情况下,有必要将表达式初步转换为相应的 InputForm 通过 ToString[expr, InputForm] .

        19
  •  6
  •   rcollyer    15 年前

    我只是浏览了一下我的一个包,发现了一些我定义的有用的信息: Debug::<some name> . 默认情况下,它们是关闭的,因此不会产生太多开销。但是,如果我需要弄清楚一点代码的行为方式,我可以把代码乱扔,然后打开它们。

        20
  •  6
  •   DGrady    15 年前

    对于内置的作用域构造,我感到困扰的一件事是,它们同时计算所有的局部变量定义,所以您不能编写例如

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

    所以不久前我提出了一个宏,叫做WithNest,它允许你这样做。我觉得它很方便,因为它可以让您保持变量绑定的局部性,而不必做类似的事情

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

    最后,我能找到的最好的方法是使用一个特殊的符号,使其更容易在绑定列表上递归,并且我将定义放在它自己的包中,以隐藏这个符号。也许有人对这个问题有更简单的解决办法?

    如果您想尝试,请将以下内容放入一个名为 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[];
    
        21
  •  5
  •   Szabolcs    10 年前

    此代码生成一个调色板,用于将所选内容作为图像上载到堆栈交换。在Windows上,提供了一个额外的按钮,可以更忠实地呈现所选内容。

    将代码复制到笔记本单元格中并计算。然后从输出中弹出调色板,并使用 Palettes -> Install Palette...

    如果你有任何问题,在这里发表评论。下载笔记本版本 here .


    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[];
    
        22
  •  4
  •   tsvikas    8 年前

    我相信很多人都遇到过这样的情况,他们运行一些东西,意识到它不仅卡住了程序,而且 已经10分钟没存了!

    编辑

    在忍受了一段时间之后,我有一天发现 可以创建自动保存 从内部 数学软件 代码。我认为使用这种自动保存在过去帮助了我很多,我一直觉得 可能性本身 不是很多人都知道他们能做到的。

    我使用的原始代码在底部。多亏了我的评论,我发现它是有问题的,而且用另一种方法来做会更好,使用 ScheduledTask (只有在 数学软件 8) 是的。

    代码可以在 this answer Sjoerd C. de Vries (因为我不确定是否可以复制到这里,所以我只将其作为链接保留。)


    下面的解决方案是使用 Dynamic . 每60秒就可以节省一次笔记本,但显然 只有当它的细胞可见时 . 我把它留在这里只是为了完工。(以及 数学软件 6和7)

    /编辑

    为了解决这个问题,我在笔记本的开头使用以下代码:

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

    这将节省你每60秒的工作。
    我更喜欢它 NotebookAutoSave[] 因为它在处理输入之前保存,而且因为有些文件比输入文件多。

    我最初在这里发现的: http://en.wikipedia.org/wiki/Talk:Mathematica#Criticisms

    请注意,一旦运行这一行,即使关闭并重新打开文件(只要启用动态更新),也会进行保存。

    而且,因为在 数学软件 ,请注意不要删除所有内容,因为保存将使其不可逆转(作为预防措施,我将从每个已完成的笔记本中删除此代码)

        23
  •  4
  •   weisjohn    14 年前

    这篇文章是阿尔贝托·迪·卢洛写的(他似乎没有出现堆栈溢出)。

    CopyToClipboard ,对于Mathematica 7(在Mathematica 8中,它是内置的)

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

    原帖: http://forums.wolfram.com/mathgroup/archive/2010/Jun/msg00148.html

    我发现这个例程对于将大量实数以普通十进制形式复制到剪贴板非常有用。例如。 CopyToClipboard["123456789.12345"]

    Cell[OutputFormData@expr] 巧妙地删除引号。

        24
  •  3
  •   Bill White    15 年前

    记住,Mathematica的书也可以在网上找到 http://reference.wolfram.com/legacy/v5_2/ -尽管它已被 http://reference.wolfram.com

        25
  •  3
  •   Dave Batton    8 年前

    我发现在开发包时将此键盘快捷键添加到 SystemFiles/FrontEnd/TextResources/Windows/KeyEventTranslations.tr 文件。

    (* Evaluate Initialization Cells: Real useful for reloading library changes. *)
    
    Item[KeyEvent["i", Modifiers -> {Control, Command}],
        FrontEndExecute[
            FrontEndToken[
                SelectedNotebook[],
                "EvaluateInitialization"]]],
    

    下一个为每个 Packagename.m 我做了一个 PackagenameTest.nb 测试笔记本和测试笔记本的前2个单元格设置为初始化单元格。在我放的第一个牢房里

    Needs["PackageManipulations`"]
    

    加载非常有用的 PackageManipulations 利奥尼德写的图书馆。第二个单元格包含

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

    所有这些都做实际的包重新加载。注意前两行只用于 Remove 所有的符号我喜欢保持上下文尽可能干净。

    然后,编写和测试包的工作流就变成这样了。

    1. 将更改保存到 包装名称 .
    2. PackagenMetest.nb公司 并且做 CTRL + ALT + i .

    这会导致初始化单元重新加载包,从而使测试变得非常简单。

        26
  •  1
  •   Prashant Bhate    9 年前

    跟随功能 format[expr_] 可用于缩进/格式化未格式化 mathematica 跨页表达式

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

    裁判: https://codegolf.stackexchange.com/questions/3088/indent-a-string-using-given-parentheses

    推荐文章