使用 With 绘图与使用 Block 绘图 (Mathematica)

2024-01-01

我想描述一个我一直遇到的问题Plot using With保持定义的参数“本地”。我不一定要求解决:我遇到的问题是理解问题。

有时我使用如下结构来获取绘图:

Method 1

plot1 = With[{vmax = 10, km = 10}, 
  Plot[Evaluate@((vmax x)/(km + x)), {x, 0, 100}, 
   AxesOrigin -> {0, 0}]]

我喜欢这种方法,即使对于非数学用户到底发生了什么。

当要绘制的方程变得更加复杂时,我喜欢在绘图外部定义它们(使用 SetDelayed)。例如:

f[x_] := (vmax x)/(km + x)

然而,以下不起作用

Method 2

plot2 = With[{vmax = 10, km = 10}, 
  Plot[Evaluate@f[x], {x, 0, 100}, AxesOrigin -> {0, 0}]]

我一直天真地认为应该如此。但是,根据帮助声明

Plot 将变量 x 视为局部变量, 有效地使用块

我使用过各种解决方法,主要如下

Method 3

plot3 = Plot[With[{vmax = 10, km = 10}, Evaluate@f[x]], {x, 0, 100}, 
  AxesOrigin -> {0, 0}]

这看起来很尴尬,通常需要进一步解释,甚至数学 users.

绘图输出

然而最近我偶然发现可以用Block for With方法 2 中的效果完全符合预期。

例如,我可以执行如下操作(对我来说,这似乎是一种非常通用的方法):

plot4 = Block[{vmax = {10, 10, 10}, km = { 10, 100, 1000}}, 
  Plot[Evaluate@f[x], {x, 0, 100}, AxesOrigin -> {0, 0}, 
   PlotStyle -> {Red, Green, Blue}]]

giving

我的问题如下。行为差异的解释是什么With在方法1和2中?我应该预料到方法 2 不起作用吗?此外,对于行为差异的解释是什么?Block and With在方法2中?我应该能够预测到吗Block会工作?

有趣的是,那些比我更有经验的人向我建议了许多解决方法,但没有人建议使用Block.

最后,我需要保留vmax and km本地。(它们已在其他地方用代数方式定义)


你的问题并不是关于Plot因为它是关于范围界定结构如何工作的。这里的主要混乱是由于词法作用域和动态作用域之间的差异造成的。罪魁祸首是这个定义:

f[x_] := (vmax x)/(km + x)

它的问题在于它使得f隐式依赖于全局符号(变量)vmax and km。我非常反对这种结构,因为它们会导致无限的混乱。现在,可以用以下示例来说明发生的情况:

In[55]:= With[{vmax =1, km = 2},f[x]]

Out[55]= (vmax x)/(km+x)

要理解为什么会发生这种情况,我们必须了解lexical范围界定手段。我们知道With has a HoldAll属性。它的工作原理是它看起来就是这样字面上地在其中,并替换找到的变量字面上地在正文中使用声明列表中的值。这发生在变量绑定阶段,只有那时它才让主体进行评估。由此可见,以下方法将发挥作用:

In[56]:= With[{vmax =1, km = 2},Evaluate[f[x]]]

Out[56]= x/(2+x) 

这之所以有效,是因为Evaluate覆盖“部分”HoldAll的属性With,强制主体在其他任何事情之前进行评估(变量绑定和随后的主体评估)。因此,它完全等同于仅使用With[{vmax = 1, km = 2}, (vmax x)/(km + x)]上面,正如你所看到的Trace。谜题的下一部分是为什么

With[{vmax = 10, km = 10}, Plot[Evaluate@f[x], {x, 0, 100}, AxesOrigin -> {0, 0}]]

不起作用。这是因为这次我们do not先评估身体。的存在Evaluate仅影响f[x] inside Plot,但不评价Plot本身在里面With。这可以通过以下方式说明

In[59]:= With[{vmax = 10, km = 10}, q[Evaluate@f[x]]]

Out[59]= q[(vmax x)/(km + x)]

而且,我们不希望Plot首先评估,然后再评估vmax and km将不会被定义。然而,这一切With看到的是f[x],并且由于参数vmax and km不是字面上地存在在那里(词法范围,记住),不会进行替换。我们应该使用Block在这里,事情会成功,因为Block使用动态作用域,这意味着它会及时重新定义值(如果您愿意,可以是执行堆栈的一部分),而不是就地重新定义值。因此,使用Block[{a =1, b =2}, ff[x]] where ff隐含地依赖于a and b(大致)相当于a=1;b=2;ff[x](不同之处在于a and b后恢复其全局值Block剩余范围)。所以,

In[60]:= Block[{vmax = 10, km = 10}, q[Evaluate@f[x]]]

Out[60]= q[(10 x)/(10 + x)]

为了使With版本工作,你必须注入表达式f[x](r.h.s),例如像这样:

In[63]:= Unevaluated[With[{vmax = 10, km = 10}, q[f[x]]]] /. DownValues[f]

Out[63]= q[(10 x)/(10 + x)]

请注意,这不会起作用:

In[62]:= With[{fx = f[x]}, With[{vmax = 10, km = 10},  q[fx]]]

Out[62]= q[(vmax x)/(km + x)]

但这里的原因非常微妙:虽然外部With在内部变量之前进行评估,它会发现变量名称冲突并重命名其变量。规则更具破坏性,它们不尊重内部范围构造。

EDIT

如果坚持嵌套With-s,这是如何欺骗名称冲突解决机制的方法With并使其发挥作用:

In[69]:= With[{fx = f[x]}, With @@ Hold[{vmax = 10, km = 10}, q[fx]]]

Out[69]= q[(10 x)/(10 + x)]

由于外With无法再检测到内部的存在With (using Apply[With,Hold[...]]使内在With有效地动态生成),它不会进行任何重命名,然后就可以工作了。当您不想重命名时,这是欺骗词法作用域名称解析机制的通用技巧,尽管使用它的必要性通常表明设计不好。

END EDIT

但我离题了。总而言之,让第二种方法发挥作用非常困难,并且需要非常奇怪的结构,例如

Unevaluated[ With[{vmax = 10, km = 10}, Plot[Evaluate@f[x], {x, 0, 100},
     AxesOrigin -> {0, 0}]]] /.  DownValues[f]

or

With[{fx = f[x]}, 
   With @@ Hold[{vmax = 10, km = 10}, 
       Plot[Evaluate@fx, {x, 0, 100}, AxesOrigin -> {0, 0}]]]

再次:这一切都是因为With必须在代码中显式“查看”变量才能进行替换。相比之下,Block不需要,它会在评估时根据修改后的全局值动态替换值,就像您进行了分配一样,这就是它起作用的原因。

现在,真正的罪魁祸首是你的定义f。如果你定义了你的目标,你本可以避免所有这些麻烦f使用显式参数传递:

ff[x_, vmax_, km_] := (vmax x)/(km + x)

现在,这是开箱即用的:

With[{vmax = 10, km = 10}, 
   Plot[Evaluate@ff[x, vmax, km], {x, 0, 100}, AxesOrigin -> {0, 0}]]

因为参数明确存在于函数调用签名中,因此对With.

总结一下:您观察到的是词法作用域和动态作用域之间相互作用的结果。词法作用域构造必须在变量绑定阶段(求值之前)在代码中显式地“查看”它们的变量,否则它们将无效。动态范围有效修改values符号的数量,从这个意义上来说要求不高(您付出的代价是使用大量动态作用域的代码更难理解,因为它混合了状态和行为)。麻烦的主要原因是函数定义对全局符号(不在函数的形式参数列表中)产生隐式依赖。最好避免这样的结构。仍然有可能使事情正常进行,但这要复杂得多(如上面所演示的),并且至少对于当前的情况来说,没有充分的理由。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 With 绘图与使用 Block 绘图 (Mathematica) 的相关文章

  • mathematica 可以做一些平面几何绘图吗

    我正在尝试使用计算机来显示一些平面几何图 我不知道什么软件可以做到这一点 也不知道mathematica是否可以轻松地生成这样的图 例如 我有以下情节要展示 给定任何三角形 ABC 设 AD 为平分角 BAC 并与 BC 相交于 D 的线
  • Mathematica:如何防止对 In[-1] 求值?

    当我尝试在 Wolfram 中获取最后一个输入表达式时数学5 2 使用In 1 我得到评估输出 In 1 On In 2 2 In 1 Out 2 4 During evaluation of In 1 In trace In 1 gt I
  • 简化 Mathematica 中的正则表达式

    我最近发现克莱尼代数 http en wikipedia org wiki Kleene algebra用于操作和简化正则表达式 我想知道这是否已内置到 Mathematica 等任何计算软件程序中 如果有一个计算工具来进行大型表达式的并集
  • 将声音导出为 WAV 文件

    我从来没有在 Mma 中过多地使用声音 I have t Sound List Violin SoundNote 6 我怎样才能导出t作为 WAV 文件 当我尝试显而易见的事情时 Export c test wav t I get 在这个旧
  • 重新定义 Mathematica 中的非交换乘法

    Mathematicas NonCommutativeMultiply 不会简化诸如 a 0 0 a 0 a 1 1 a a or a a a 2 我想重新定义 去做这个 我使用 NCAlgebra 来执行此操作 但我需要 ReplaceR
  • 对函数体评估感到困惑

    我对以下行为感到困惑Function In 1 InlineCellInMessage Function expr DisplayForm Cell BoxData MakeBoxes expr StandardForm Input Hol
  • 无法从 {2,3,4,5,6,7,8} 获得的最小整数 (Mathematica)

    我正在尝试使用 Mathematica 解决以下问题 从集合中无法获得的最小正整数是多少 2 3 4 5 6 7 8 通过算术运算 求幂和括号 集合中的每个数字必须仅使用一次 不允许一元运算 例如 如果不使用 0 则 1 无法转换为 1 例
  • 设计方法:过载与开关?

    关于封装设计的性能和可扩展性 最好是 重载 函数名称 让 Mathematica 根据模式 条件 测试以及系统对定义的排序方式来确定要使用哪个版本 或者使用 Switch 或类似命令 构建单个函数来直接求值 Mathematica 的表达能
  • Mathematica 内部数字格式和精度

    切线相关this https stackoverflow com q 4939616 181759问题 数字格式到底发生了什么 In 1 InputForm 3 12987 10 270 Out 1 3 12987 270 In 2 Inp
  • 有没有办法自动将Matlab 中的结果或数据导入到Mathematica 中?

    有没有办法将结果或数据 例如矩阵 从Matlab导入到Mathematica自动地 或者有什么方法可以先运行Matlab程序 然后运行Mathematica程序自动地 感谢您提供任何有用的答案 至少有三种方法可以解决这个问题 通过 Java
  • 在 Mathematica 中导入 Google Sketchup 模型

    Google 的 Sketchup 是一个漂亮 简单的 3D 对象建模器 此外 谷歌还拥有巨大的3D 对象仓库 http sketchup google com 3dwarehouse 因此 如果您在这方面不是特别有天赋 实际上您不必自己做
  • 解决电力塔

    a 2 Power 10 6 10 9 3 Power 4 9 7 5 TwoTower n Nest 2 1 n 最小的是什么n这样TwoTower n gt a This question http www quora com How
  • Mathematica:MathLink 错误消息

    我想我开始理解如何将用 C C 编写的函数链接到数学 我面临的问题是我不知道如何将错误消息从我的 C 包装器发送到 Mathematica 在谷歌搜索后我发现了这个MathLink 教程 http www edenwaith com dev
  • 如何在 Mathematica 中将包含小数点的字母数字(参考)数字转换为字符串

    我有以下类型 DAA76647 1 的参考号 我想将其原封不动地转换为 Mathematica 中的字符串 That is myfn DAA76647 1 给出作为输出 DAA76647 1 是否有捷径可寻 输入不能是字符串 除了转换为字符
  • 创建自定义表格表示的函数

    我使用下面的代码来概述我的部分数据 从以下代码中创建函数的最佳方法是什么 它将采用 dataList 以及一些图形选项 例如颜色 作为参数 并返回自定义的表格表示形式 如下所示 overviewtheData Text Grid Map R
  • 如何将 ListPlot 的图形与 Plot 的图形结合起来?

    有没有办法将图形组合起来ListPlot到一个图形Plot 我需要在 ListPlot 的图形上绘制函数的图形 您可以将任何图形与Show函数如下 Show myListPlot myPlot 这概括为一次组合任意数量的图 Show p1
  • 如何在mathematica中自动加载用户定义的函数

    我有一堆在 mathematica 中经常使用的用户定义函数 我想知道是否可以将它们存储在单独的文件中 并且 mathematica 会在启动时加载它们并将它们视为内置函数 这样每当我创建新的 nb 文件时就不必重复定义 类似于 Matla
  • R 中从右到左的运算符结合性可能吗?

    我是 R 新手 我刚刚发现我患有支架恐惧症 https mathematica stackexchange com a 17315 2266 请参阅链接中的评论 我喜欢这种方式magrittr符号 gt 有效 因为它在某些情况下避免了嵌套括
  • 如何在mathematica中进行函数替换

    我有这样的表情D f x y x 我想替换f x y with x y 我尝试了以下方法 D f x y x f x y gt x y and D f x y x f gt x y 但两者都不起作用 将不胜感激您的帮助 谢谢 The Ful
  • 零件和跨度:有什么理由这“不应该”起作用吗?

    这是一个设计问题 而不是现有功能的问题 我想使用 1 2 3 4 5 1 3 2 5 我预计 1 2 3 2 3 4 5 但它是无效的 During evaluation of In 1 Part pspec Part specificat

随机推荐