清除 Mathematica 中的数值

发布于 2024-10-31 22:38:04 字数 226 浏览 0 评论 0原文

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

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

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

I am working on fairly large Mathematica projects and the problem arises that I have to intermittently check numerical results but want to easily revert to having all my constructs in analytical form.

The code is fairly fluid I don't want to use scoping constructs everywhere as they add work overhead. Is there an easy way for identifying and clearing all assignments that are numerical?

EDIT: I really do know that scoping is the way to do this correctly ;-). However, for my workflow I am really just looking for a dirty trick to nix all numerical assignments after the fact instead of having the foresight to put down a Block.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

哑剧 2024-11-07 22:38:05

如果您的分配位于顶层,则可以使用类似以下内容:

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 的符号,以与上面类似的方式,并删除纯数字 rhs 的定义,

但在我看来,这些方法都不是稳健的。我仍然会使用范围构造并尝试隔离数字。一种可能性是将最终代码包装在 Block 中,并在该 Block 内分配数值。这似乎是一种更干净的方法。工作开销很小 - 您只需记住要将值分配给哪些符号即可。 Block 将自动确保在其外部,符号将没有定义。

编辑

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

If your assignments are on the top level, you can use something like this:

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

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

This will work if you have a sufficient history length $HistoryLength (defaults to infinity). Note however that, in the above example, e was assigned 3+c, and 3 here was not undone. So, the problem is really ambiguous in formulation, because some numbers could make it into definitions. One way to avoid this is to use SetDelayed for assignments, rather than Set.

Another alternative would be to analyze the names in say Global' context (if that is the context where your symbols live), and then say OwnValues and DownValues of the symbols, in a fashion similar to the above, and remove definitions with purely numerical r.h.s.

But IMO neither of these approaches are robust. I'd still use scoping constructs and try to isolate numerics. One possibility is to wrap you final code in Block, and assign numerical values inside this Block. This seems a much cleaner approach. The work overhead is minimal - you just have to remember which symbols you want to assign the values to. Block will automatically ensure that outside it, the symbols will have no definitions.

EDIT

Yet another possibility is to use local rules. For example, one could define rule[a] = a->1; rule[d]=d->3 instead of the assignments above. You could then apply these rules, extracting them as say
DownValues[rule][[All, 2]], whenever you want to test with some numerical arguments.

戒ㄋ 2024-11-07 22:38:05

以 Andrew Moylan 的 解决方案,可以构造一个类似块的函数,该函数将采用规则:

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

我希望您能让这个想法发挥作用。

在此处输入图像描述

Building on Andrew Moylan's solution, one can construct a Block like function that would takes rules:

SetAttributes[BlockRules, HoldRest]

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

You can then save your numeric rules in a variable, and use BlockRules[ savedrules, code ], or even define a function that would apply a fixed set of rules, kind of like so:

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

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

Out[78]= 5.

EDIT In response to Timo's comment, it might be possible to use NotebookEvaluate (new in 8) to achieve the requested effect.

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

As the result of this evaluation you get a notebook with your commands evaluated when a was locally set to 4. In order to take it further, you would have to take the notebook
with your code, open a new notebook, evaluate Notebooks[] to identify the notebook of interest and then do :

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

I hope you can make this idea work.

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文