使 pgfplot 线在函数最大值以下自动变为虚线

使 pgfplot 线在函数最大值以下自动变为虚线

我想创建一个图表,显示线性函数,其最大值构建分段线性函数 (PWLF),如max下面的最小工作示例中所示。目前,为了突出显示最大值,我添加了一个绘图,该绘图调用 max() 并作为参数,以线性函数为参数,并覆盖另一个粗黑色绘图以显示 PWLF。贡献函数手动绘制为虚线,以突出显示它们在某些区域“不贡献”的事实。

实际上,我想要做的是,如果所有线不是最大值的一部分,则将它们变为虚线,否则变为实线,以保留 PWLF 中的颜色信息,以表明哪个线性函数构成了该图段。

有没有办法以描述的方式做到这一点,理想情况下无需手动绘制线段?我真的不想每次都计算每个示例的交点,然后创建适当的图。

MWE 当前生成以下输出:

在此处输入图片描述

梅威瑟:

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usetikzlibrary{positioning}
\usepackage{amsmath}

\pgfplotsset{
    legend entry/.initial=,
    every axis plot post/.code={%
            \pgfkeysgetvalue{/pgfplots/legend entry}\tempValue
            \ifx\tempValue\empty
                    \pgfkeysalso{/pgfplots/forget plot}%
            \else
                    \expandafter\addlegendentry\expandafter{\tempValue}%
            \fi
    },
}

\begin{document}

\begin{figure}
    \centering

    \begin{tikzpicture}

        \begin{axis}[width=\textwidth, enlargelimits=false, legend pos=outer north east, ytick=\empty, xtick={0, 1}, %
            xticklabels={1 - $S_0$, $S_0$}]
            \addplot[blue, dashed, thick, no marks, domain=0:1, legend entry=$a_1$]%
                ({x},{0.8 - 0.5*x});%

            \addplot[olive, thick, dashed, no marks, domain=0:1, legend entry=$a_2$]%
            ({x}, {0.6 - 0.2*x});%

            \addplot [red, thick, dashed, no marks, domain=0:1, legend entry=$a_3$]%
            ({x}, {0.3+0.4*x});%

            \addplot [orange, dashed, thick, no marks, domain=0:1, legend entry=$a_4$]%
            ({x}, {0.5+0.1*x});%

            \addplot [black, ultra thick, no marks, domain=0:1, legend entry=$\text{max}$] {max(0.8-0.5*x,0.3+0.4*x, 0.5+0.1*x)};

        \end{axis}
    \end{tikzpicture}
\end{figure}
\end{document}

答案1

sagetex软件包可以处理这个问题。它的文档位于 CTAN这里。这样你就可以将工作外包给计算机代数系统 SAGE,它的网站这里。这意味着你需要下载 SAGE 到你的电脑并正确安装它,或者打开一个免费的可钙帐户。如果您有 Cocalc 帐户,只需粘贴创建一个 LaTeX 文档,将下面的代码复制/粘贴到您的文档中,保存它,然后按构建即可查看结果。编辑:我修改了代码以修复图例中的错误,并使其看起来更像 OP 发布的情节。将 max 函数放入图例中会使其变为纯蓝色,因此我将其删除。

\documentclass[border=4pt]{standalone}
\usepackage{sagetex}
\usepackage[usenames,dvipsnames]{xcolor}
\usepackage{pgfplots}
\pgfplotsset{compat=1.15}
\begin{document}
\begin{sagesilent}
f1 = 0.8-0.5*x
f2 = 0.6-0.2*x
f3 = 0.3+0.4*x
f4 = 0.5+0.1*x
t = var('t')
LowerY = 0.0
UpperY = 1.0
LowerX = 0.0
UpperX = 1.0
step = .001

f1x = [t for t in srange(LowerX,UpperX,step) if     f1(t)==max(f1(t),f2(t),f3(t),f4(t))]
f1y = [f1(t) for t in f1x]
f2x = [t for t in srange(LowerX,UpperX,step) if f2(t)==max(f1(t),f2(t),f3(t),f4(t))]
f2y = [f2(t) for t in f2x]
f3x = [t for t in srange(LowerX,UpperX,step) if f3(t)==max(f1(t),f2(t),f3(t),f4(t))]
f3y = [f3(t) for t in f3x]
f4x = [t for t in srange(LowerX,UpperX,step) if f4(t)==max(f1(t),f2(t),f3(t),f4(t))]
f4y = [f4(t) for t in f4x]

output = r""
output += r"\begin{tikzpicture}[scale=.7]"
output += r"\begin{axis}[width=\textwidth, enlargelimits=false, legend pos=outer north east, ytick=\empty, xtick={0, 1}, xticklabels={1-$S_0$,$S_0$}]"

output += r"\addplot[blue, dashed, thick, no marks, domain=0:1]"
output += r"({x},{0.8 - 0.5*x});"
output += r"\addlegendentry{$f1$}"
output += r"\addplot[olive, thick, dashed, no marks, domain=0:1]"
output += r"({x}, {0.6 - 0.2*x});"
output += r"\addlegendentry{$f2$}"
output += r"\addplot [red, thick, dashed, no marks, domain=0:1]"
output += r"({x}, {0.3+0.4*x});"
output += r"\addlegendentry{$f3$}"
output += r"\addplot [orange, dashed, thick, no marks, domain=0:1]"
output += r"({x}, {0.5+0.1*x});"
output += r"\addlegendentry{$a4$}"

if len(f1x)>1:
    output += r"\addplot[blue,thick] coordinates {"
    for i in range(0,len(f1x)-1):
        output += r"(%f,%f) "%(f1x[i],f1y[i])
    output += r"};"

if len(f2x)>1:
    output += r"\addplot[olive,thick] coordinates {"
    for i in range(0,len(f2x)-1):
        output += r"(%f,%f) "%(f2x[i],f2y[i])
    output += r"};"

if len(f3x)>1:
    output += r"\addplot[red,thick] coordinates {"
    for i in range(0,len(f3x)-1):
        output += r"(%f,%f) "%(f3x[i],f3y[i])
    output += r"};"

if len(f4x)>1:
    output += r"\addplot[orange,thick] coordinates {"
    for i in range(0,len(f4x)-1):
        output += r"(%f,%f) "%(f4x[i],f4y[i])
    output += r"};"

output += r"\end{axis}"
output += r"\end{tikzpicture}"
\end{sagesilent}
\sagestr{output}
\end{document}

Colcalc 中的输出如下所示: 在此处输入图片描述 特写视图: 在此处输入图片描述

Python 是 SAGE 中使用的语言。将 4 条线定义为 f1 到 f4 后,代码 f1x = [t for t in srange(LowerX,UpperX,step) if f1(t)==max(f1(t),f2(t),f3(t),f4(t))] f1y = [f1(t) for t in f1x]将为线 f1 创建 x 和 y 坐标列表。如果 f1 是所有 4 条线上的最大点,则将一个点添加到 f1x,在这种情况下,y 值将添加到 f1y。可能存在这样的情况(例如 3 条线在同一点相交),即只有 1 个 x 值使线达到最大值,在这种情况下我们不绘制该值;任何真正属于 max 函数的线至少有两个点可达到最大值。因此,假设 f1 中有多个点,则if len(f1x)>1:该线的检查结果将作为 max 函数的一部分绘制。

相关内容