我通常在 Matlab 中编写程序,然后将图片移植到 LaTeX 中。有时似乎在 LaTeX 中编写程序效率更高或更灵活,要么您可以更好地控制图形,要么工作流程更简单。我正在寻找一篇解释 LaTeX 中数学编程元素的中级文章。典型的数学程序包括用于求根的牛顿法、微分方程的龙格-库塔解、基本蒙特卡罗等。如果没有这样的文章,请提供您在 LaTeX 中编写的数学示例的链接。
编辑 4/3/2019
Matlab 功能不佳的地方在于“注释”。只要您绘制一些图形,Matlab 就表现良好。但是,如果您将各个部分放在一起并在绘图中添加文本、箭头等,那么使用 Matlab 就会有点问题。Matlab 有一个“注释”功能可以帮助您执行此操作,但它适用于“标准化窗口坐标”,这会以某种方式将您的窗口设置为 $[0,1]*[0,1]$,并要求您指定相对于此窗口的坐标,而不是数据坐标。这也许是为了在图形上交互式放置注释,但对于数据驱动的注释来说,使用起来很尴尬。这种切换非常令人困惑,以至于创建了一个由第三方贡献的函数组成的副业,其中大多数函数由于一个或另一个问题而无法正常工作。即使您设法使其工作,注释也会在缩放时移动,因为它们适合您看到的窗口而不是数据坐标。此外,您还会遇到 Matlab 支持的有限版本的 \LaTeX,例如这里是文本支持。简而言之,如果您正在考虑对图形进行大量“手动修改”,那么您可能希望从 \LaTeX 开始进行。对于在 Matlab 中绘制箭头,“arrow3.m”功能很好。
答案1
您可以将python
代码集成到您的LaTeX
使用以下方式pythontex。
这是一个简单的例子:
\documentclass{article}
\usepackage[gobble=auto]{pythontex}
\usepackage{pgfplots}
\begin{document}
\begin{pycode}
from sympy import *
x = symbols('x')
f = integrate(cos(x)*sin(x), x)
\end{pycode}
\begin{pysub}
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,ylabel=$y$,samples=200,no markers,title=!{latex(f)}]
\addplot[black] gnuplot {!{f}};
\end{axis}
\end{tikzpicture}
\end{pysub}
\end{document}
下面是另一个示例:
\documentclass{article}
\usepackage[gobble=auto]{pythontex}
\usepackage{pgfplots}
\usepackage{siunitx}
\sisetup{
round-mode=places,
round-precision=3
}
\DeclareDocumentCommand{\pyNum}{ m O{}}
{%
\py{'\\num[#2]{' + str(#1).replace('(','').replace(')','') + r'}'}%
}
\begin{document}
\begin{pycode}
import numpy as np
from scipy import optimize as op
def f(x):
return x**2 + 3*x -3
x = np.arange(-5,5,0.1)
np.savetxt('file.dat',zip(x,f(x)),fmt='%0.5f')
\end{pycode}
A root of $f$ is \pyNum{op.newton(f,-2)}.
\begin{center}
\begin{tikzpicture}
\begin{axis}[xlabel=$x$,ylabel=$y$,samples=200,no markers,axis lines=center]
\addplot[black] table {file.dat};
\end{axis}
\end{tikzpicture}
\end{center}
\end{document}
下面是求解驱动振荡器的 ODE 的另一个例子:
\documentclass{article}
\usepackage[gobble=auto]{pythontex}
\usepackage{pgfplots}
\pgfplotsset{compat=1.15}
\begin{document}
\begin{pycode}
import numpy as np
from scipy.integrate import odeint
omega = 3
omega_ext = 2
c = 0.1
d = 0.5
m = 1
e = 1
k = omega**2*m
def Force(t,x,v):
return -k*x + np.sin(omega_ext*t) - d*v
def dgl(xv, t):
x, v = xv
return [v, 1/m*Force(t,x,v)]
xv0 = [1, 0]
tmax = 30
t_out = np.arange(0, tmax, 0.05)
xv_res = odeint(dgl, xv0, t_out)
x,v = xv_res.T
tv = list(zip(t_out,v))
np.savetxt('osciTV.dat',tv)
\end{pycode}
\begin{pysub}
\begin{tikzpicture}
\begin{axis}[xlabel=$t$,ylabel=$v$,samples=200,no markers]
\addplot[black] table {osciTV.dat};
\addplot[dashed,variable=t,domain=0:!{tmax}] gnuplot {sin(!{omega_ext}*t)};
\end{axis}
\end{tikzpicture}
\end{pysub}
\end{document}
另请参阅pythontex-gallery。
Python 提供了很多库用于科学计算。
答案2
对于 LuaLaTeX,使用 Lua,但除此之外:
- “使用 LuaLaTeX 的数值方法”,作者:Juan Montijano、Mario Pérez、Luis Rández 和 Juan Luis Varona。TUGboat问题 35.1:https://www.tug.org/TUGboat/tb35-1/tb109montijano.pdf
pweave
在 jonaslb 的回答中提到过,因此有必要也提一下sweave
(这是的灵感来源pweave
)和knitr
。这些是类似概念的框架,但是针对的是 R 语言。
答案3
MetaPost 也集成在 LuaTeX 中。作为一种编程语言,它允许实现一些数值方法。请参阅本教程用于牛顿迭代法的实现(第 34 页)。
作为一种图形语言,它还允许一些几何计算,例如查找两条曲线的交点、根据统计图构建箱线图等。
编辑:作为示例,下面是我上面提到的牛顿法的稍微修改后的实现,应用于函数 f(x)=x^2-2。它是该方法的几何版本,也就是说,它基于给定的曲线及其切线,而不是基于函数本身及其导数。(当然,也可以这样做。)
\documentclass{scrartcl}
\usepackage{luamplib}
\mplibtextextlabel{enable}
\mplibsetformat{metafun}
\mplibnumbersystem{double}
\begin{document}
\begin{mplibcode}
vardef f(expr x) = x**2 - 2 enddef;
u = 3cm; v = 1.5cm; xmax = 2.75; ymax = 6;
path curve; numeric t[]; dx = 1E-4;
curve = (0, f(0))
for i = dx step dx until xmax: .. (i, f(i)) endfor;
beginfig(1);
draw curve xyscaled (u, v);
x0 = 2.5; i := 0;
forever:
(t[i],whatever) = curve intersectiontimes
((x[i], -infinity) -- (x[i],infinity));
y[i] = ypart (point t[i] of curve);
(x[i+1],0) = z[i] + whatever*direction t[i] of curve;
draw ((x[i], 0) -- z[i] -- (x[i+1], 0)) xyscaled (u, v);
drawdot (z[i] xyscaled (u, v)) withpen pencircle scaled 4bp;
i := i+1;
exitif abs(x[i]-x[i-1]) < dx;
endfor;
label.bot(btex $x_0$ etex, (x0*u, 0));
label.bot(btex $x_1$ etex, (x1*u, 0));
label.bot(btex $x_2$ etex, (x2*u, 0));
label.lrt("$x_{" & decimal i & "}=" & decimal x[i] & "$",
(x[i]*u, 0) shifted (0, -.75cm));
drawarrow origin -- (xmax*u, 0);
for i = 0 upto xmax:
draw (i*u, -2bp) -- (i*u, 2bp);
label.bot("$" & decimal i & "$", (i*u, -2bp));
endfor;
label.bot("$x$", (xmax*u, 0));
endfig;
\end{mplibcode}
\end{document}