Mathematica 中的部分评估

发布于 2024-08-06 06:39:06 字数 426 浏览 3 评论 0原文

我有一个作用于两个函数的微分运算符。为了简化问题,假设我的运算符是

A[F_,G_] := D[F,x] D[G,y]

,如果我知道 F,我希望能够定义微分运算符 AF,使得 AF[G] 等于 A[F,G]。最明显的方法是

AF[G_] := A[F,G]

没有任何问题的工作。但我真正想要的是安排事情,以便当我使用不同的参数 G1、G2...调用 AF 时,导数 D[F,x] 不会每次都重新计算,而只会重新计算一次。此外,我希望 AF 的定义不依赖于 A 的特定形式,因为 A 作为参数传递给我的函数。

我已经阅读了有关 Hold、HoldAll、Evaluate 等的帮助,但我无法将这些内容放在一起来获得我想要的东西。我什至不知道我想要的在 Mathematica 中是否可行。

I have a differential operator that acts on two functions. To simplify the problem let's say that my operator is

A[F_,G_] := D[F,x] D[G,y]

I want to be able, if I know F, to define a differential operator AF such that AF[G] is equal to A[F,G]. The obvious way is

AF[G_] := A[F,G]

which works without any problem. But what I would really like is to arrange things so that when I call AF with different arguments G1, G2, ... the derivative D[F,x] is not re-computed every time but only once. Moreover, I would like the definition of AF to not depend on the particular form of A, since A is passed as an argument to my function.

I have read the help on Hold, HoldAll, Evaluate etc. but I cannot put these things together to get what I want. I don't even know if what I want is possible in Mathematica.

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

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

发布评论

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

评论(2

默嘫て 2024-08-13 06:39:06

对于您描述的问题,我没有看到直接的方法。您可以做的一件事是重新定义它以使其变得更加容易,那就是重新定义 A ,使其成为 FG 的导数的函数。如果您有,

A[{dFdx_,dFdy_}, {dGdx_,dGdy_}] := dFdx*dFdy 

您将能够很好地计算所需的 F 的导数,然后以相对于 通用的方式定义 AF A,如下所示:

With[{ dFdx = D[F,x], dFdy = D[F,y] },
  AF[G_] := A[{dFdx, dFdy}, {D[G, x], D[G, y]}]]

您可以使用 With 将已求值的片段替换为 SetDelayed 表单(使用“:=”的定义)的未求值右侧,如图所示。然而,如果您不能做出这样的改变,事情就会变得棘手,您将不得不对 A 是什么进行一些假设。

如果 A 是为其定义了 DownValues 的符号,并且定义简单,那么您可以通过使用 Hold、执行规则替换和然后执行 ReleaseHold,如下所示:

ReleaseHold[
  Hold[AF[G_] := A[F, G]] /. DownValues[A] /. 
    HoldPattern[D[F, var_]] :> With[{eval = D[F, var]}, eval /; True]]

第二条规则中的 With[...] 位是一个技巧,用于强制评估与 内的模式匹配的内容>Hold 调用“Trott-Strzebonski 方法” ,这很晦涩,但对于这样的任务非常有用。然而,这种方式确实限制了你的接口,这意味着你不能为 A 传递一个纯函数,并且对于更复杂的定义,这个技巧可能也不起作用。如果您能够设法指定您的微分形式将是实际导数的函数,我强烈建议您这样做。

编辑:我想到了一种更通用、更强大的方法来做到这一点。

技巧是使用 Block 暂时抑制 D(导数运算符)的定义,因此 A 定义中的导数保持未计算状态,然后使用规则替换来替换 F 的导数的值,同时将所有内容包装在纯函数中以获得正确的名称替换,如下所示:

With[{fRules =
 {HoldPattern[D[F, x]] :> Evaluate[D[F, x]]}},
   Block[{D},
     With[{fn = Function[G, Evaluate[A[F, G] /. fRules]]},
       AF[G_] := fn[G]]]]

With the problem you describe, I don't see a straightforward way of doing it. One thing you could do to recast it to make it dramatically easier would be to redefine A so its a function of the derivatives of F and G. If you have

A[{dFdx_,dFdy_}, {dGdx_,dGdy_}] := dFdx*dFdy 

you'll be in a very good position to calculate the derivatives of F that you need and then define AF in a way that's generic with respect to A, like so:

With[{ dFdx = D[F,x], dFdy = D[F,y] },
  AF[G_] := A[{dFdx, dFdy}, {D[G, x], D[G, y]}]]

You can use With to substitute evaluated pieces into the unevaluated right-hand side of a SetDelayed form (a definition using ":=") as shown. However, if you can't make that change, things are going to get hairy, and you'll have to make some assumptions about what A is.

If A is a symbol with DownValues defined for it, and has a simple definition, then you can do the partial evaluation you want by using a Hold, doing rule substitutions, and then doing a ReleaseHold, like so:

ReleaseHold[
  Hold[AF[G_] := A[F, G]] /. DownValues[A] /. 
    HoldPattern[D[F, var_]] :> With[{eval = D[F, var]}, eval /; True]]

The With[...] bit in the second rule is a trick for forcing the evaluation of something matching a pattern inside a Hold called the "Trott-Strzebonski method", which is obscure but extremely useful for tasks like this. However, going this way really limits your interface, meaning that you can't, say, pass in a pure function for A, and with a more complicated definition this trick probably won't work either. If you can possibly manage to specify that your differential form will be a function of the actual derivatives, I strongly recommend doing so.

EDIT: I thought of a more general and robust way of doing this.

The trick then is to temporarily suppress the definition of D (the derivative operator) using Block, so the derivatives in the definition of A remain unevaluated, and then use rule-replacement to substitute in the values for the derivatives of F while wrapping everything up in a pure function to get the name substitution right, like so:

With[{fRules =
 {HoldPattern[D[F, x]] :> Evaluate[D[F, x]]}},
   Block[{D},
     With[{fn = Function[G, Evaluate[A[F, G] /. fRules]]},
       AF[G_] := fn[G]]]]
错々过的事 2024-08-13 06:39:06

你能不能仅仅这样做:

A[F_] := With[{DF = D[F, x]}, Function[{G}, DF D[G, y]]]

这类似于在 F# 等真正的函数式编程语言中进行柯里化,你可以在其中编写:

let a f =
  let df = d f x
  fun g -> df * d g y

Can you not just do:

A[F_] := With[{DF = D[F, x]}, Function[{G}, DF D[G, y]]]

That is similar to currying in a real functional programming language like F#, where you would write:

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