如何在 tex 文档中自动绘制复杂的多变量函数,而不仅仅是导入图像

如何在 tex 文档中自动绘制复杂的多变量函数,而不仅仅是导入图像

我有以下 Tex 函数,我想在我的 tex 论文中绘制它们,但我不知道如何绘制。我的意思是,我希望 Tex 绘制函数,而不仅仅是向其中包含外部图像。

y[\text{x$\_$},\text{m$\_$},\text{n$\_$}]\text{:=}\text{Abs}\left[1-\left(1-\left(\frac{x+1}{2}\right)^2\right){}^{\wedge}m\right]{}^{\wedge}n;

\text{F}[\text{x$\_$},\text{m$\_$},\text{n$\_$}]\text{:=}(-y[0,m,n]+(y[0,m,n]-1)x+y[x,m,n])/(1-2y[0,m,n])

\text{Plot}[\{\text{F}[x,0.2,0.5],\text{F}[x,1,5],\text{F}[x,1,10]\},\{x,-1,1\}]

答案1

以下是使用 pgfplots + lualatex 的解决方案(即必须使用以下命令进行编译lualatex P.tex

\documentclass{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
\begin{tikzpicture}
    \directlua{
        Y = function(x,m,n)
            return math.abs(1-(1-((x+1)/2)^2)^m)^n
        end
        N1 = function(x,m,n)
            return (-Y(0,m,n) + (Y(0,m,n)-1)*x + Y(x,m,n))/ (1-2*Y(0,m,n))
        end
    }
    \pgfmathdeclarefunction{N1}{3}{%
        \edef\pgfmathresult{\directlua{tex.print(N1(\pgfmathfloatvalueof{#1},\pgfmathfloatvalueof{#2},\pgfmathfloatvalueof{#3}))}}%
    }%
    \begin{axis}[
        axis lines=center,
        enlargelimits,
        tick align=inside,
        no markers,
        legend entries={$N1(x,0.2,0.5)$\\$N1(x,1,5)$\\$N1(x,1,10)$\\},
        domain=-1:0.99999,
        samples=150,
        minor tick num=4,
    ]
    \addplot {N1(x,0.2,0.5)};
    \addplot {N1(x,1,5)};
    \addplot {N1(x,1,10)};
    \end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

一些评论:

  • 我使用 Lua 是为了受益于其更高的精度 - N1 的当前公式在 x=-1 附近存在数值不稳定性(即输入中的小错误会导致输出中的巨大错误)。这需要比 TeX 通过其内置方法提供的更高的精度。
  • 我忽略了重复使用 值的可能性y(0,m,n)。计算两次并没有什么坏处。
  • 添加cycle list={dashed,black,black}到轴的选项列表中以获取您的绘图样式 - 我更喜欢默认循环列表(带有no markers),以便您可以在图例中识别每一个(也是我添加的)。
  • N1请注意,我选择通过 来定义 PGF 数学函数。这允许我们在 PGF 数学表达式中\pgfmathdeclarefunction使用(特别是:在 中)。参数意味着新函数有三个参数,可用作宏中的、和。目前,这些参数采用浮点库(在 TeX 中)生成的某种内部格式,因此我们需要将它们转换回 Lua 可以理解的格式(通过 )。N1(x,m,n)\addplot {<expression>}{3}#1#2#3\pgfmathfloatvalueof
  • 因为我从来没有直接绘图Y,所以我没有生成\pgfmathdeclarefunctionfor Y——毕竟,Lua 代码可以以自包含的方式计算这一点。
  • 请注意\pgfmathdeclarefunction应该将结果分配给宏\pgfmathresult,这就是 的目的\edef\pgfmathresult。这tex.print是 Lua 将结果报告回 TeX 的方式。

一般来说,使用 PGF 的数学引擎来制定函数是安全的,结果是

\documentclass{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
\begin{tikzpicture}
    \pgfmathdeclarefunction{Y}{3}{%
        \pgfmathparse{abs(1-(1-((#1+1)/2)^2)^(#2))^(#3)}%
    }%
    \pgfmathdeclarefunction{N1}{3}{%
        \pgfmathparse{(-Y(0,#2,#3) + (Y(0,#2,#3)-1)*(#1) + Y(#1,#2,#3))/ (1-2*Y(0,#2,#3)}%
    }%
    \begin{axis}[
        axis lines=center,
        enlargelimits,
        tick align=inside,
        no markers,
        legend entries={$N1(x,0.2,0.5)$\\$N1(x,1,5)$\\$N1(x,1,10)$\\},
        domain=-1:0.99999,
        samples=150,
        minor tick num=4,
    ]
    \addplot {N1(x,0.2,0.5)};
    \addplot {N1(x,1,5)};
    \addplot {N1(x,1,10)};
    \end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

请注意 x=-1 附近可见的伪影;它源于 x=-1 附近数值不稳定的函数公式与 TeX 的有限精度相结合(除非我弄错了)。

答案2

你可以使用gnuplot来绘制这些。例如,你可以使用以下代码:

\documentclass{standalone}
\makeatletter\newwrite\verbatim@out\makeatother
\usepackage{gnuplottex}
\usepackage{epstopdf}

\begin{document}
\begin{gnuplot}[terminal=epslatex]
    set samples 2000 # Set to get more accurate, but slower
    set parametric
    set xtics -1,.5,1
    set ytics -1,.5,1

    set trange [-1:1] # Parametric plot range
    set xrange [-1.1:1.1] # Axis range

    set zeroaxis
    set border 0
    set xtics axis
    set ytics axis

    y(x,m,n) = (abs(1-(1-((x+1)/2)**2)**m))**n
    N(x,m,n) = (-y(0,m,n) + (y(0,m,n) - 1)*x + y(x,m,n))/(1 - 2*y(0,m,n))

    plot t,N(t,0.2,0.5) title "", t,N(t,1,5) title "", t,N(t,1,10) title ""
\end{gnuplot}
\end{document}

您需要使用该--shell-escape选项进行编译,并且格努普特已安装。

正如您在代码中看到的,在 gnuplot 中定义和使用函数非常容易,甚至具有多个参数。

渲染: 代码渲染

答案3

* 编辑 *添加了虚线图案、图例和几个标签;还使用了成对mn[]数组(m,n)来创建函数N1(m,n)(x) ,而不是函数数组。 在此处输入图片描述

% f.tex:
%
\documentclass{article}
\usepackage[inline]{asymptote}
\usepackage{lmodern}
\begin{document}
\begin{figure}
\centering
\begin{asy}[width=8cm]
size(9cm);
import graph;
import fontsize;
defaultpen(fontsize(9pt));

pen dashed=linetype(new real[] {4,4});
pen longdashed=linetype(new real[] {12,4});
pen dotted=linetype(new real[] {0,3});

pen[] fpen={
  gray+longdashed,
  black+dotted,
  black+dashed
};

real y(real x,real m,real n){
  return abs(1-(1-((x+1)/2)^2)^m)^n;
}

typedef real Func(real);

Func N1(real m,real n){
  return 
    new real(real x){
      return (-y(0,m,n)+(y(0,m,n)-1)*x+y(x,m,n))/(1-2y(0,m,n));
    };
}

pair[] mn={(0.2,0.5),(1,5), (1,10)}; 

real xmin=-1, xmax=1;

xaxis(xmin,xmax,LeftTicks(Label(LeftSide),Step=0.5,step=0.1,OmitTick(0)));
yaxis(RightTicks(Step=0.5,step=0.1,OmitTick(0)));

real penwidth=1bp; 
real m,n;
for(int i=0;i<mn.length;++i){
  m=mn[i].x; n=mn[i].y;
  draw(graph(N1(m,n),xmin,xmax,n=400),fpen[i]+penwidth
    ,legend="$N_1("+string(m)+","+string(n)+")$"
  );
}

label("$x$",1.1*(xmax,0),S); // 1.1*(xmax,0) is a location,
                         // alignment S == (0,-1)  means "South"
m=mn[2].x; n=mn[2].y;

label("$("+string(m)+","+string(n)+")$",
  (0.6,N1(m,n)(0.6))
  ,SW
);

add(
  legend(linelength=0.5legendlinelength,nullpen) // here nullpen means no frame 
  ,point(NE),SW,UnFill
);
\end{asy}
\caption{Family of functions $N_1(x,m,n)$}
\end{figure}
\end{document}

处理如下:

pdflatex f.tex
asy f-*.asy
pdflatex f.tex

* ======== 第一个版本 ======== *

在此处输入图片描述

Asymptote使用(这是TeXLive分布的一部分,已经有一段时间了)绘制此类函数系列非常简单。在asy环境中,函数N1(m,n)使用参数m和“n”创建一个新的实值函数,该函数接受一个实数参数。所有需要绘制的函数都收集在数组中f[] ,然后使用准备好的笔数组在循环内绘制fpen[]

% f.tex:
%
\documentclass{article}
\usepackage[inline]{asymptote}
\usepackage{lmodern}
\begin{document}
\begin{figure}
\centering
\begin{asy}[width=7cm]
import graph;
import fontsize;
defaultpen(fontsize(9pt));
pen dashed=linetype(new real[] {4,4});

pen[] fpen={
  deepblue+dashed,
  black,
  orange
};

real y(real x,real m,real n){
  return abs(1-(1-((x+1)/2)^2)^m)^n;
}

typedef real Func(real);

Func N1(real m,real n){
  return 
    new real(real x){
      return (-y(0,m,n)+(y(0,m,n)-1)*x+y(x,m,n))/(1-2y(0,m,n));
    };
}

Func[] f={ N1(0.2,0.5), N1(1,5), N1(1,10) };

real xmin=-1, xmax=1;

xaxis(xmin,xmax,LeftTicks(Label(LeftSide),Step=0.5,step=0.1,OmitTick(0)));
yaxis(RightTicks(Step=0.5,step=0.1,OmitTick(0)));

real penwidth=1bp; 
for(int i=0;i<f.length;++i){
  draw(graph(f[i],xmin,xmax),fpen[i]+penwidth);
}
\end{asy}
\caption{Family of functions $N_1(x,m,n)$}
\end{figure}
\end{document}

处理如下:

pdflatex f.tex
asy f-*.asy
pdflatex f.tex

PS,我希望你不要将这一步asy f-*.asy视为太多额外的工作。

答案4

基于一个答案这个问题,我绘制了如下图所示的图(感谢克里斯蒂安·费尔桑格)。我之所以选择这个答案,是因为它对我这个 LaTeX 基础用户来说很容易,而且我更容易理解流程、功能、代码等。此外,它能够定义不同的功能,而且确实可定制。

\documentclass[varwidth=true, border=10pt, convert={size=640x}]{standalone}
\usepackage{blindtext}

\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
\begin{tikzpicture}
    \directlua{
        Y = function(x,m,n)
            return math.abs(1-(1-((x+1)/2)^2)^m)^n
        end
        N1 = function(x,m,n)
            return (-Y(0,m,n) + (Y(0,m,n)-1)*x + Y(x,m,n))/ (1-2*Y(0,m,n))
        end
    }
    \pgfmathdeclarefunction{N1}{3}{%
        \edef\pgfmathresult{\directlua{tex.print(N1(\pgfmathfloatvalueof{#1},\pgfmathfloatvalueof{#2},\pgfmathfloatvalueof{#3}))}}%
    }%
    \begin{axis}
    [
    grid=major,
    axis lines=center,
    enlargelimits,
    tick align=inside,
    cycle list ={solid,dotted,dashed},
        legend style={at={(0.5,-0.05)},
        anchor=north,legend columns=-1},
        legend entries={$m=1,n=1$\\$m=1,n=5$\\$m=1,n=10$\\},
    domain=-1:0.99999,
    samples=200,
    minor tick num=5,
    xlabel=$x$,
    ylabel=$N_{AG - 3}^{\left( 1 \right)}$
    ]

    \addplot {N1(x,1,1)};
    \addplot {N1(x,1,5)};
    \addplot {N1(x,1,10)};
    \end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容