我想用 pgfplots 和/或 tikz 绘制拉格朗日乘数的图示。
提醒一下,拉格朗日乘数用于优化这样的事情:
min_x f(x) 使得 g(x)=0
基本上,我需要能够绘制与 f(x) 相对应的 3D 表面,这很容易。
但我还需要在该曲面上画一条与 f(x) 和 g(x) 交点相交的曲线。但我不知道该怎么做。
答案1
除了用符号方式解决约束之外,您还可以用数字方式解决它们。为此,您可以使用任何轮廓算法并计算级别 Z = 0:
\documentclass{standalone}
\usepackage{tikz,pgfplots}
\pgfplotsset{compat=1.12}
\begin{document}
\begin{tikzpicture}[
declare function={f(\x,\y)=20*\x*exp(-\x^2-\y^2);},
]
\begin{axis}[
width=300pt,
height=300pt,
domain=-2:2,
view={-60}{30},
]
\addplot3 [surf, opacity=.3, samples=50] {f(x,y)};
% needed just once... it has no output
\addplot3 [samples=50,mark=none, contour gnuplot={labels=false,levels={5},handler/.style={only marks}}] {(x+1)^2+(y-1)^2};
\addplot3[black] table[x index=0, y index=1, z expr={f(x,y)}] {P_contourtmp0.table};
\end{axis}
\end{tikzpicture}
\end{document}
由于 0 = g(x,y) = (x+1)^2+(y-1)^2 的解是 (-1, 1),我选择 g(x,y) = 5 作为约束。
-shell-escape
由于使用了,因此需要使用 进行编译gnuplot
。请注意,gnuplot
每次排版图形时,输出实际上都会重新计算——没有必要。您可以gnuplot
在第一次运行后取消注释该指令。handler/.style={only marks}
指示contour
处理程序仅显示已配置的mark
(此处默认为无)。
关键思想是将结果叠加到表面的绘图指令是使用z expr={f(x,y)}
。在这种情况下,“ x
”和“ y
”是从输入文件读取的坐标,f
是通用声明。
您可以在这里安全地使用compat=1.11
而不是1.12
(使用 进行编译时,1.12 只需要一半的时间lualatex
)。
答案2
我找到了解决方案。它包括将解 g(x)=0 转换为极坐标并绘制它。
\documentclass{standalone}
\usepackage{tikz,pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[ width=300pt,
height=300pt,
axis background/.style={fill=white},
xticklabels=\empty,
yticklabels=\empty,
zticklabels=\empty,
xtick scale label code/.code={},
ytick scale label code/.code={},
ztick scale label code/.code={},
clip marker paths=true,
domain=-2:2,
view={-60}{30}
]
\addplot3 [surf, opacity=.3, samples=50] {20*(x)*exp(-x^2-y^2)};
\addplot3 [domain=0:2*pi, samples y=0, samples=300] ({
(cos(deg(4*x))*.5+.75)*cos(deg(x))
},{
(cos(deg(4*x))*.5+.75)*sin(deg(x))
},{
20*(((cos(deg(4*x))*.5+.75)*cos(deg(x))))*exp(-((cos(deg(4*x))*.5+.75)*cos(deg(x)))^2-((cos(deg(4*x))*.5+.75)*sin(deg(x)))^2)
});
\end{axis}
\end{tikzpicture}
\end{document}