Hacer que las líneas de pgfplot sean discontinuas automáticamente debajo del máximo de funciones

Hacer que las líneas de pgfplot sean discontinuas automáticamente debajo del máximo de funciones

Quiero crear un gráfico que muestre funciones lineales cuyo máximo genera una función lineal por partes (PWLF) etiquetada maxen el ejemplo de trabajo mínimo a continuación. Actualmente, para resaltar el máximo, estoy agregando un gráfico que llama a max() y, como argumentos, toma las funciones lineales y superpone otro gráfico en negro grueso para mostrar el PWLF. Las funciones contribuyentes se dibujan manualmente con guiones para resaltar el hecho de que "no contribuyen" en ciertas regiones.

Realmente, lo que me gustaría hacer es que todas las líneas sean discontinuas si no son parte del máximo y, de lo contrario, sean sólidas, para conservar la información de color en el PWLF sobre qué función lineal constituye ese segmento de la gráfica.

¿Hay alguna forma de hacer esto de forma descriptiva, idealmente sin tener que dibujar los segmentos de línea manualmente? Realmente no quiero tener que calcular las intersecciones para cada ejemplo y luego crear gráficos apropiados cada vez.

El MWE genera actualmente este resultado:

ingrese la descripción de la imagen aquí

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}

Respuesta1

El sagetexpaquete puede manejar esto. Su documentación se encuentra en CTAN.aquí. Esto le permite transferir el trabajo a un sistema de álgebra informático, SAGE, que tiene su sitio webaquí. Esto significa que necesitarás descargar SAGE en tu computadora e instalarlo correctamente o abrir una versión gratuita.cocalcuenta. Si tiene una cuenta de Cocalc, simplemente pegue, cree un documento LaTeX, copie y pegue el siguiente código en su documento, guárdelo y luego presione compilar para ver el resultado.EDITAR:Modifiqué el código para corregir un error en la leyenda y hacer que se parezca más a la trama que publicó el OP. Al poner la función máxima en la leyenda, se colorea de azul sólido, así que la omití.

\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}

El resultado en Colcalc se muestra a continuación: ingrese la descripción de la imagen aquí Una vista de cerca: ingrese la descripción de la imagen aquí

Python es el lenguaje utilizado en SAGE. Después de definir sus 4 líneas como f1 a f4, el código 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]crea una lista de coordenadas xey para la línea f1. Se agrega un punto a f1x si f1 es el punto máximo en las 4 líneas, en cuyo caso el valor y se agrega a f1y. Podría darse el caso (como 3 líneas que se cruzan en el mismo punto) de que solo haya 1 valor de x para el cual una línea alcance el máximo, en cuyo caso no lo trazamos; cualquier línea que realmente forme parte de la función max tendrá al menos dos puntos en los que alcanza el máximo. Entonces, suponiendo que f1 tenga más de un punto, la línea marcada if len(f1x)>1:se trazará como parte de la función máxima.

información relacionada