在 Mathematica 中使用 NArgMax 与 FindArgMax 进行绘图
我在使用 Plot 绘制复杂的复合函数图时遇到了一些麻烦。
我正在尝试绘制复合函数F[]
的ArgMax
。
F[]
涉及多个级别的嵌套复合函数,其中许多涉及 Solve[]
和 Min[]
或 Max[]
。
我对 F[]
在我的程序中执行的方式没有任何问题(可能除了它在 Plot 中的呈现方式之外),因此我不会包含定义 F 的冗长代码目前,[]
及其底层更简单的功能。
当我尝试使用
Plot[FindArgMax[F[],{vars}] 时,我的输出得到了非常快的回报,这基本上是正确的,除了我得到的范围一些错误的错误值,它们似乎在绘图的一部分上呈现为不正确的垂直线段。
我已经在发生错误的范围内评估了 F[],并确认正确的值与下面第二张图片中显示的平滑曲线一致。
Plot[NArgMax[[F[],{vars}]
, I获得正确的绘图,其中不包括错误/错误的垂直段,但需要相当长的时间。
我无法发布第二个链接,但 NArgMax
图生成与上面相同的图片,但平滑且没有孔和垂直段。
在不深入了解 F[]
的细节的情况下,是否有一种快速简便的方法可以让 FindArgMax
在这里正常工作?基本上,这是 Plot 的一个常见问题,并且有众所周知的修复,或者如果我希望能够,我是否需要花费更多时间来重新编码 F[]
的定义和底层复合函数在我的绘图中使用快速 FindArgMax 命令?
预先感谢论坛新手提供的任何帮助。 :)
编辑:我的程序中麻烦部分的示例代码:
a = 3000; b = 1/10; cc = 1/10; d = 1;G1[x_, y_] := a Log[bx + cc y + d]
Gx1[x_, y_] := 导数[1, 0][G1][x, y]; Gy1[x_, y_] := 导数[0, 1][G1][x, y];
piPP1 = {y, x};
c1ycrit0[fy_, mu1_] := 最大[0,展平[ 求解[Gy1[x, y] == fy mu1 && piPP1[1] == piPP1[[2]], y, x]][1][[2]]]
c1xcrit1[fx_, fy_, mu1_] := 最大[安静[ 展平[ 求解[Gx1[x, 展平[求解[piPP1[1] == piPP1[[2]], y]] [1][[2]]] == mu1 fx, x]][1][[2]]], 安静[压平[ 求解[Gx1[x, 最大[0,展平[ 求解[Gy1[x, y] == fy*mu1 && piPP1[1] == piPP1[[2]], y, x]][1][[2]]]] == mu1 fx, x] ]][1][[2]]]
c1xcrit2[fx_、fy_、mu1_、T1_ ] := 最大[安静[ 展平[求解[T1 == x fx + fy c1ycrit0[fy, mu1] , x, y]][1][[2]]], 安静[压平[ 求解[{piPP1[1] == piPP1[[2]], T1 == x fx + fy piPP1[[2]]}, x, y]][1][[2]]]]
操纵[ 安静[绘图[(fx - xc) 最大[0, 最小值[c1xcrit1[fx, fy, mu1], c1xcrit2[fx, fy, mu1, T1]]], {fx, 0, fxMax},PlotRange -> {{0, fxMax}, {0, xPTmax}}]], {{mu1, 10, 下标[Mu, 1]}, 0, 100}, {{xc, 3}, 0, 100}, {{fy, 10}, 0, 100}, {{T1, 100}, 0, 1000}, {{fxMax, 50}, 0, 100}, {{xPTmax, 100}, 0, 400}, 连续动作 ->无]
BRX[fy_, xc_, mu1_, T1_] := 安静[FindArgMax[(fx - xc) (Min[{c1xcrit1[fx, fy, mu1], c1xcrit2[fx, fy, mu1, T1]}]), {fx, xc}]]
BRX1[fy_, xc_, mu1_, T1_] := 安静[NArgMax[(fx - xc) (Min[{c1xcrit1[fx, fy, mu1], c1xcrit2[fx, fy, mu1, T1]}]), fx]]
操纵[ xBR = 绘图[BRX[fy, xc, mu1, T1], {fy, 0, hmax}, 绘图范围 -> {{0, hmax}, {0, hmax}}], {{mu1, 10, 下标[Mu, 1]}, 0, 100}, {{xc, 3}, 0, 10}, {{T1, 100}, 0, 1000}, {{hmax, 40}, 0, 100}, 连续动作 ->无]
操纵[ xBR1 = 绘图[BRX1[fy, xc, mu1, T1], {fy, 0, hmax}, 绘图范围 -> {{0, hmax}, {0, hmax}}], {{mu1, 10, 下标[Mu, 1]}, 0, 100}, {{xc, 3}, 0, 10}, {{T1, 100}, 0, 1000}, {{hmax, 40}, 0, 100}, 连续动作 ->没有任何]
进一步编辑:更改 BRX[] 函数中求解“fx”的起点“xc”会极大地改变绘图的结果,这使我相信我不太可能在以下位置有效地使用 FindArgMax全部。我认为由于基础函数中的所有最小值和最大值,导数都有点太复杂了。我仍然希望这里有一个修复程序可以使用 FindArgMax,但在尝试了到目前为止建议的一些事情后,我不太乐观。
再次感谢大家迄今为止的帮助! :)
Ive been having some trouble using Plot to graph a complicated composite function.
I am trying to plot the ArgMax
of a composite function F[]
.
F[]
involves several levels of nested composite functions, many of which involve Solve[]
and Min[]
or Max[]
.
I don't have any problems with the way F[]
performs in my program (with the possible exception of how it renders in Plot), so I wont include the lengthy code that defines F[]
and its underlying simpler functions, for now.
When I try to use
Plot[FindArgMax[F[],{vars}]
, I get a very fast return on my output, which is mostly correct, except for the fact that I get a range with some buggy false values, which appear to be rendered as incorrect vertical segments over a portion of the plot.
I have evaluated F[]
over the range where the bugginess is happening, and have confirmed that the proper values are in line with the smooth curve shown in the second pic below.
Plot[NArgMax[[F[],{vars}]
, I get a correct plot which does not include the bugginess/false vertical segments, but it takes a considerably longer time.
I cant post a second link, but the NArgMax
plot generates the same picture as above, but smooth and without the holes and vertical segments.
Without getting into the specifics of F[]
, is there a quick and easy way to coax FindArgMax
into working properly here? Basically, is this a common issue with Plot that has a well known fix, or do I need to devote more time to recoding my definitions of F[]
and the underlying composite functions if I want to be able to use the fast FindArgMax command in my Plot?
Thanks in advance for any help, from a first timer here on the forum. :)
EDIT: Sample code from the troublesome portion of my program:
a = 3000; b = 1/10; cc = 1/10; d = 1;
G1[x_, y_] := a Log[b x + cc y + d]
Gx1[x_, y_] := Derivative[1, 0][G1][x, y]; Gy1[x_, y_] := Derivative[0, 1][G1][x, y];
piPP1 = {y, x};
c1ycrit0[fy_, mu1_] := Max[0, Flatten[ Solve[Gy1[x, y] == fy mu1 && piPP1[1] == piPP1[[2]], y, x]][1][[2]]]
c1xcrit1[fx_, fy_, mu1_] := Max[Quiet[ Flatten[ Solve[Gx1[x, Flatten[Solve[piPP1[1] == piPP1[[2]], y]][1][[2]]] == mu1 fx, x]][1][[2]]], Quiet[Flatten[ Solve[Gx1[x, Max[0, Flatten[ Solve[Gy1[x, y] == fy*mu1 && piPP1[1] == piPP1[[2]], y, x]][1][[2]]]] == mu1 fx, x]]][1][[2]]]
c1xcrit2[fx_, fy_, mu1_, T1_] := Max[Quiet[ Flatten[Solve[T1 == x fx + fy c1ycrit0[fy, mu1] , x, y]][1][[2]]], Quiet[Flatten[ Solve[{piPP1[1] == piPP1[[2]], T1 == x fx + fy piPP1[[2]]}, x, y]][1][[2]]]]
Manipulate[ Quiet[Plot[(fx - xc) Max[0, Min[c1xcrit1[fx, fy, mu1], c1xcrit2[fx, fy, mu1, T1]]], {fx, 0, fxMax}, PlotRange -> {{0, fxMax}, {0, xPTmax}}]], {{mu1, 10, Subscript[Mu, 1]}, 0, 100}, {{xc, 3}, 0, 100}, {{fy, 10}, 0, 100}, {{T1, 100}, 0, 1000}, {{fxMax, 50}, 0, 100}, {{xPTmax, 100}, 0, 400}, ContinuousAction -> None]
BRX[fy_, xc_, mu1_, T1_] := Quiet[FindArgMax[(fx - xc) (Min[{c1xcrit1[fx, fy, mu1], c1xcrit2[fx, fy, mu1, T1]}]), {fx, xc}]]
BRX1[fy_, xc_, mu1_, T1_] := Quiet[NArgMax[(fx - xc) (Min[{c1xcrit1[fx, fy, mu1], c1xcrit2[fx, fy, mu1, T1]}]), fx]]
Manipulate[ xBR = Plot[BRX[fy, xc, mu1, T1], {fy, 0, hmax}, PlotRange -> {{0, hmax}, {0, hmax}}], {{mu1, 10, Subscript[Mu, 1]}, 0, 100}, {{xc, 3}, 0, 10}, {{T1, 100}, 0, 1000}, {{hmax, 40}, 0, 100}, ContinuousAction -> None]
Manipulate[ xBR1 = Plot[BRX1[fy, xc, mu1, T1], {fy, 0, hmax}, PlotRange -> {{0, hmax}, {0, hmax}}], {{mu1, 10, Subscript[Mu, 1]}, 0, 100}, {{xc, 3}, 0, 10}, {{T1, 100}, 0, 1000}, {{hmax, 40}, 0, 100}, ContinuousAction -> None]
Further edit: Changing the starting point "xc" for solving for "fx" in the BRX[] function drastically changes the result of the plot, which leads me to believe that it might be unlikely that I will be able to usefully use FindArgMax at all. I suppose that the derivatives are all a little too screwy due to all the MINs and MAXs in the underlying functions. Im still hopeful that there is a fix here that will enable to use FindArgMax, but Im a lot less optimistic after trying a few of the things suggested so far.
Thanks again to everyone for your help so far! :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
相关答案(原始内容见下文)
查看您的代码,问题实际上是关于理解 Mathematica 中的延迟/立即评估。例如,与您的第一个
Manipulate
相比,观察以下渲染效果如何。如您所见,唯一的区别是
Evaluate
,它将表达式计算为一劳永逸地绘制,而不是每次需要新绘图时都进行所有符号数学计算。我怀疑一旦修复了错误,以与其他图类似的方式添加Evaluate
就能解决问题。如果您想了解如何对上述内容进行编码,这里有一些学习点:
Rule
(->
) 和ReplaceAll
(./
):不应使用Flatten[{{y->x+2}}[[1]][[2]]
,而应使用 <代码>y/.First[{{y-> x+2}}]。安静
。所有的人。现在! ;) 真的——除非你完全确定自己在做什么,Quiet
只会向你隐藏你的错误。Set
(=
) 与SetDelayed
(:=
)。作为示例,请参阅下面我将如何实现您的c1xcrit1
:使用=
而不是:=
意味着所有符号数学都已完成< em>定义 x1xcrit1 时一次,而不是每次评估时。我希望这会有所帮助 - 但实际上,如果您想使用 Mathematica,您应该找到一个教程或其他东西来教您基础知识。
原始答案
您要比较的两个函数使用非常不同的算法:
FindArgMax
是FindMaximum
的便捷前端,而NArgMax
是一个前端结束于NMaximize
。比较两个函数FindMaximum
/FindArgMax
的可用方法:ConjugateGradient、PrincipalAxis、LevenbergMarquardt、Newton 和 QuasiNewton(所有微分方法)、NArgMax
/NMaximize
:NelderMead、DifferentialEvolution、SimulatedAnnealing 和 RandomSearch(所有逐点方法)。换句话说:使用
FindMaximum
或FindArgMax
来获得很好的函数,其中导数会产生有用的信息。对于讨厌的函数,请使用NArgMax
/NMaximize
。由于 FindArgMax 几乎可以工作,我假设你的函数很好。
对于微分方法,首先象征性地进行演化,试图建立梯度的解析表达式。引用文档:“FindArgMax 首先本地化所有变量的值,然后用符号变量评估 f,然后重复以数值方式评估结果。”
听起来你的
F
足够复杂,符号评估不会去任何地方。如果是这种情况,则通过换行来防止符号求值。此外,同时添加缓存很少有坏处:您可能认为这会像
NArgMax
一样慢,但在许多情况下,您会发现 QuasiNewton 算法在构建估计方面非常出色它需要的衍生品。鉴于我们不知道您的
F
,这当然完全是猜测——但我希望它能有所帮助。Relevant answer (see below for original)
Looking at your code, the problem is really about understanding delayed/immediate evaluation in Mathematica. For example, observe how nicely the following renders, compared to your first
Manipulate
.As you can see, the only difference is an
Evaluate
which evaluates the expression to be plotted once and for all, instead of doing all the symbolical math over each time a new plot is needed. I suspect addingEvaluate
in a similar way to your other plots would do the trick once you get your errors fixed.If you want to learn how you should have coded the above, here are some study points:
Rule
(->
) andReplaceAll
(./
): Instead of sayingFlatten[{{y->x+2}}[[1]][[2]]
, you should usey/.First[{{y-> x+2}}]
.Quiet
's. All of them. Now! ;) Really -- unless you are completely sure what you are doing,Quiet
will just be hiding your mistakes from you.Set
(=
) vsSetDelayed
(:=
). As an example, see below how I would have implemented yourc1xcrit1
: Using=
instead of:=
means that all the symbolic math is done once when x1xcrit1 is defined rather than every time it is evaluated.I hope this helps a bit -- but really, if you want to use Mathematica you should find a tutorial or something to teach you the basics.
Original answer
The two functions you are comparing use very different algorithms:
FindArgMax
is a convenience front-end toFindMaximum
, whileNArgMax
is a front-end toNMaximize
. Comparing the methods available for the two functionsFindMaximum
/FindArgMax
: ConjugateGradient, PrincipalAxis, LevenbergMarquardt, Newton, and QuasiNewton (all differential methods),NArgMax
/NMaximize
: NelderMead, DifferentialEvolution, SimulatedAnnealing and RandomSearch (all pointwise methods).To put it another way: use
FindMaximum
orFindArgMax
for nice functions, where the derivatives yield useful information. For nasty function, useNArgMax
/NMaximize
.Since
FindArgMax
almost works, I'll assume your function is nice.For the differential methods the evolution is first done symbolically in an attempt to establish an analytical expression for the gradient. Quoting from the docs: "FindArgMax first localizes the values of all variables, then evaluates f with the variables being symbolic, and then repeatedly evaluates the result numerically."
It sounds like your
F
is sufficiently complicated that symbolic evaluation is not going to go anywhere. If this is the case then prevent symbolic evaluation by wrapping. Also, adding a cache at the same time rarely hurts:You might think that this will be as slow as the
NArgMax
, but in many cases you will find that the QuasiNewton algorithms are impressively good at building an estimate of the derivatives it needs.Given that we don't know your
F
this is of course complete guesswork -- but I hope it helps a bit.