gpt4 book ai didi

wolfram-mathematica - 使用 With 绘图与使用 Block 绘图 (Mathematica)

转载 作者:行者123 更新时间:2023-12-03 09:42:45 24 4
gpt4 key购买 nike

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

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

方法一

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

我喜欢这种方法,即使是非 Mathematica 用户也很清楚到底发生了什么。

当要绘制的方程变得更加复杂时,我喜欢在绘图之外定义它们(使用 SetDelayed)。例如:
f[x_] := (vmax x)/(km + x)

但是,以下不起作用

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

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

Plot treats the variable x as local, effectively using Block



我使用了各种解决方法,主要是以下内容

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

这个看起来很尴尬,通常甚至对 Mathematica 用户也需要进一步解释。

绘制输出

enter image description here

然而,最近我偶然发现用 Block代替为 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}]]

给予

enter image description here

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

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

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

最佳答案

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

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

它的问题在于它使 f隐式依赖于全局符号(变量) vmaxkm .我非常反对这种结构,因为它们会导致无限的困惑。现在,可以通过以下示例说明发生的情况:
In[55]:= With[{vmax =1, km = 2},f[x]]

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

要理解为什么会发生这种情况,必须了解词法范围的含义。我们知道 With有一个 HoldAll属性。它的工作方式是它看起来就是它内部的字面意思,并用声明列表中的值替换在正文中找到的变量。这发生在变量绑定(bind)阶段,然后才让主体进行评估。由此,很明显,以下将起作用:
In[56]:= With[{vmax =1, km = 2},Evaluate[f[x]]]

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

这是有效的,因为 Evaluate覆盖 HoldAll 的“部分” With 的属性,强制主体在其他任何事情之前进行评估(变量绑定(bind),以及随后的主体评估)。因此,完全等同于仅使用 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}]]

不起作用。这是因为这次我们不先评估 body 。 Evaluate的存在仅影响 f[x]Plot ,但不是对 Plot的评价自身内部 With .这说明
In[59]:= With[{vmax = 10, km = 10}, q[Evaluate@f[x]]]

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

而且,我们不要 Plot首先评估,从那时起 vmax 的值和 km不会被定义。然而,这一切 With看到的是 f[x] ,并且由于参数 vmaxkm不存在于那里(词汇范围,记住),不会进行替换。我们应该使用 Block在这里,一切都会奏效,因为 Block使用动态范围,这意味着它会及时重新定义值(如果您愿意,它是执行堆栈的一部分),而不是就地。因此,使用 Block[{a =1, b =2}, ff[x]]哪里 ff隐含地依赖于 ab是(大致)等价于 a=1;b=2;ff[x] (不同之处在于 abBlock 作用域离开后恢复它们的全局值)。所以,
In[60]:= Block[{vmax = 10, km = 10}, q[Evaluate@f[x]]]

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

使 With版本工作,你必须为 f[x] 注入(inject)表达式(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在内部变量之前求值,它发现变量名冲突并重命名其变量。规则更具破坏性,它们不尊重内部范围结构。

编辑

如果坚持嵌套 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 的存在(使用 Apply[With,Hold[...]] 使内部 With 有效地动态生成),它不会进行任何重命名,然后它就可以工作了。当您不想重命名时,这是一个欺骗词法范围名称解析机制的通用技巧,尽管必须使用它通常表明设计很糟糕。

结束编辑

但我跑题了。总而言之,使您的第二种方法工作非常困难,并且需要非常奇怪的构造,例如
Unevaluated[ With[{vmax = 10, km = 10}, Plot[Evaluate@f[x], {x, 0, 100},
AxesOrigin -> {0, 0}]]] /. DownValues[f]

或者
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 可见.

总而言之:您观察到的是词汇和动态范围之间相互作用的结果。词法范围构造必须在变量绑定(bind)阶段(评估之前)在代码中明确“看到”它们的变量,否则它们将无效。动态范围有效地修改符号的值,从这个意义上说,要求不高(你付出的代价是使用大量动态范围的代码更难理解,因为它混合了状态和行为)。出现问题的主要原因是函数定义对全局符号(不在函数的形式参数列表中)进行了隐式依赖。最好避免这种结构。仍然可以使事情工作,但这要复杂得多(如上所述),并且至少对于手头的情况,没有充分的理由。

关于wolfram-mathematica - 使用 With 绘图与使用 Block 绘图 (Mathematica),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6236458/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com