【问题标题】:Clearing numerical values in Mathematica清除 Mathematica 中的数值
【发布时间】:2011-04-14 12:26:18
【问题描述】:

我正在从事相当大的 Mathematica 项目,但出现的问题是,我必须间歇性地检查数值结果,但又想轻松地恢复为我的所有构造都采用分析形式。

代码相当流畅,我不想在任何地方都使用范围构造,因为它们会增加工作开销。是否有一种简单的方法可以识别和清除所有数字分配?

编辑:我真的知道范围界定是正确执行此操作的方法;-)。但是,对于我的工作流程,我真的只是在寻找一个肮脏的技巧来在事后取消所有数字分配,而不是有远见地放下一个块。

【问题讨论】:

标签: variables wolfram-mathematica


【解决方案1】:

如果你的作业在顶层,你可以使用这样的东西:

a = 1;
b = c;
d = 3;
e = d + b;

Cases[DownValues[In],
   HoldPattern[lhs_ = rhs_?NumericQ] | 
   HoldPattern[(lhs_ = rhs_?NumericQ;)] :> Unset[lhs],
3]

如果您有足够的历史长度$HistoryLength(默认为无穷大),这将起作用。但是请注意,在上面的示例中,e 被分配了3+c,而这里的3 并未撤消。所以,这个问题在表述上确实是模棱两可的,因为有些数字可以使它成为定义。避免这种情况的一种方法是使用SetDelayed 进行分配,而不是Set

另一种方法是分析 Global' 上下文中的名称(如果这是您的符号所在的上下文),然后以与上述类似的方式说出符号的 OwnValuesDownValues ,并删除具有纯数字 r.h.s 的定义。

但在 IMO 中,这两种方法都不可靠。我仍然会使用范围构造并尝试隔离数字。一种可能性是将您的最终代码包装在Block 中,并在此Block 中分配数值。这似乎是一种更清洁的方法。工作开销很小 - 您只需要记住要将值分配给哪些符号。 Block 将自动确保在它之外,符号将没有定义。

编辑

另一种可能性是使用本地规则。例如,可以定义rule[a] = a->1; rule[d]=d->3 而不是上面的分配。然后,您可以应用这些规则,将它们提取为 DownValues[rule][[All, 2]],只要你想用一些数字参数进行测试。

【讨论】:

  • 这几乎正是我正在寻找的。我非常明智地使用 SetDelayed 专门用于拥有完全分析的构造,我从中制作数字副本。我没有想到要使用 DownValues[In]。这是我假设的所有输入行的列表。如果是这样,这可能不适用于我使用 Get 进行的作业,对吗?我将尝试在 Global 上下文中解析规则,是否有一个简单的列表?
  • 您可以通过Map[ToExpression[#,InputForm,DownValues]&,Names["Global'"]]OwnValues 之类的方式获取这些规则(请务必不要直接复制,我将上下文分隔符更改为单引号)。之后,您可以以类似于我上面的代码的方式在这些规则上使用Cases。至于用Get做的作业,确实没有体现在In上。因此,检查 Global' 名称似乎更可靠,但使用 Block 或本地规则更可靠。
  • 我刚刚想到对所有数字分配使用单独的(私人?)子上下文。是否可以以我可以例如的方式设置上下文?当我想进行数值评估时将笔记本上下文切换到 Global'numeric,当我想做分析时将其切换到 Global'analytic?
【解决方案2】:

在 Andrew Moylan 的 solution 的基础上,可以构造一个需要规则的 Block 类函数:

SetAttributes[BlockRules, HoldRest]

BlockRules[rules_, expr_] := 
 Block @@ Append[Apply[Set, Hold@rules, {2}], Unevaluated[expr]]

然后您可以将您的数字规则保存在一个变量中,并使用 BlockRules[ savedrules, code ],甚至定义一个可以应用一组固定规则的函数,有点像这样:

In[76]:= NumericCheck = 
  Function[body, BlockRules[{a -> 3, b -> 2`}, body], HoldAll];

In[78]:= a + b // NumericCheck

Out[78]= 5.

编辑响应 Timo 的评论,可能可以使用 NotebookEvaluate(8 中的新功能)来实现所要求的效果。

SetAttributes[BlockRules, HoldRest]
BlockRules[rules_, expr_] := 
 Block @@ Append[Apply[Set, Hold@rules, {2}], Unevaluated[expr]]

nb = CreateDocument[{ExpressionCell[
     Defer[Plot[Sin[a x], {x, 0, 2 Pi}]], "Input"],
    ExpressionCell[Defer[Integrate[Sin[a x^2], {x, 0, 2 Pi}]], 
     "Input"]}];
BlockRules[{a -> 4}, NotebookEvaluate[nb, InsertResults -> "True"];]

作为此评估的结果,您将获得一个笔记本,其中当 a 本地设置为 4 时对您的命令进行评估。为了更进一步,您必须使用该笔记本 使用您的代码,打开一个新笔记本,评估 Notebooks[] 以识别感兴趣的笔记本,然后执行:

BlockRules[variablerules, 
 NotebookEvaluate[NotebookPut[NotebookGet[nbobj]], 
  InsertResults -> "True"]]

我希望你能把这个想法付诸实践。

【讨论】:

  • 这是一个好主意,但它与范围界定有相同的问题,因为我必须多次编写 //NumericCheck,除了具有不同的数值集,因此 NumericCheck 的不同版本我必须手动更改,等等。我正在寻找一种简单的方法来切换数值或不切换,也许上下文切换是真正的解决方案。
  • @Timo 你可以利用笔记本也是表达的事实来达到这个效果,而不需要太多的体力劳动,我希望。请参阅上面对我的回复的更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 2013-01-06
  • 1970-01-01
  • 2012-08-03
相关资源
最近更新 更多