我在使用Plot绘制复杂的复合函数时遇到了一些麻烦。
我正在尝试绘制复合函数ArgMax
的{{1}}。
F[]
涉及多个级别的嵌套复合函数,其中许多函数涉及F[]
和Solve[]
或Min[]
。
Max[]
在我的程序中执行的方式没有任何问题(可能除了它在Plot中呈现的方式),所以我不会包含定义F[]
的冗长代码和它现在的基础更简单的功能。
当我尝试使用
时 F[]
,我得到了一个非常快速的输出返回,这大部分都是正确的,除了我得到一个带有一些错误的错误值的范围,这些值似乎被渲染为错误的垂直段。部分情节。
我已经在发生bugginess的范围内评估Plot[FindArgMax[F[],{vars}]
,并确认正确的值与下面第二张图中显示的平滑曲线一致。
F[]
,我得到的正确情节不包括bugginess / false垂直线段,但需要相当长的时间。
我无法发布第二个链接,但Plot[NArgMax[[F[],{vars}]
绘图生成的图片与上面相同,但是光滑且没有孔和垂直线段。
如果没有详细介绍NArgMax
,是否有一种快速简便的方法可以让F[]
在这里正常工作?基本上,这是Plot的一个常见问题,它有一个众所周知的修复,或者如果我想能够使用快速的FindArgMax,我是否需要花更多的时间来重新编码我的FindArgMax
和底层复合函数的定义在我的剧情中命令?
在论坛上的第一个计时器提前感谢您的帮助。 :)
编辑:我程序麻烦部分的示例代码:
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]
进一步编辑:更改起始点“xc”以解决BRX []函数中的“fx”会大幅改变绘图的结果,这让我相信我可能不太可能有用完全使用FindArgMax。我认为由于底层函数中的所有MIN和MAX,导数都有点过于棘手。我仍然希望这里有一个可以使用FindArgMax的修复程序,但是在尝试了目前为止建议的一些事情后,我不那么乐观了。
到目前为止,再次感谢大家的帮助! :)
答案 0 :(得分:2)
查看您的代码,问题在于理解Mathematica中的延迟/即时评估。例如,与第一个Manipulate
相比,观察以下呈现效果如何。
Manipulate[
Plot[Evaluate[(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}]
正如您所看到的,唯一的区别是Evaluate
,它评估要一次性绘制的表达式,而不是每次需要新绘图时进行所有符号数学运算。我怀疑在你修复错误后,以类似的方式添加Evaluate
可以解决其他问题。
如果您想了解如何对上述内容进行编码,以下是一些研究要点:
Rule
(->
)和ReplaceAll
(./
):您应该使用Flatten[{{y->x+2}}[[1]][[2]]
而不是y/.First[{{y-> x+2}}]
。< / LI>
Quiet
。他们都是。现在! ;)真的 - 除非你完全确定自己在做什么,Quiet
只会隐瞒你的错误。Set
(=
)vs SetDelayed
(:=
)。作为示例,请参阅下面我将如何实现您的c1xcrit1
:使用=
代替:=
意味着在定义x1xcrit1时,所有符号数学都将完成 而不是每次评估。 我希望这会有所帮助 - 但实际上,如果你想使用Mathematica,你应该找一个教程或其他东西来教你基础知识。
c1xcrit1[fx_, fy_, mu1_] = With[{
y1 = y /. First@Solve[piPP1[[1]] == piPP1[[2]], y],
y2 = y /. First@Solve[Gy1[x, y] == fy*mu1 && piPP1[[1]] == piPP1[[2]], y, x]
},Max[
x /. First@Solve[Gx1[x, y1] == mu1 fx, x],
x /. First@Solve[Gx1[x, y2] == mu1 fx, x]]]
您要比较的两个函数使用非常不同的算法: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
足够复杂,以至于象征性的评价不会随处可见。如果是这种情况,则通过包装来防止符号评估。此外,同时添加缓存很少会受到伤害:
Fnum[args__/;And@@(NumericQ/@{args})]:=Fnum[args]=F[args]
您可能认为这将与NArgMax
一样慢,但在许多情况下,您会发现QuasiNewton算法非常擅长构建所需衍生物的估算。
鉴于我们不知道你的F
这当然是完全猜测 - 但我希望它有所帮助。