Pgfplot-Linien unter der maximalen Anzahl an Funktionen automatisch strichliert darstellen

Pgfplot-Linien unter der maximalen Anzahl an Funktionen automatisch strichliert darstellen

Ich möchte ein Diagramm erstellen, das lineare Funktionen anzeigt, deren Maximum eine stückweise lineare Funktion (PWLF) bildet, die maxim untenstehenden Arbeitsbeispiel für das Minimum beschriftet ist. Um das Maximum hervorzuheben, füge ich derzeit ein Diagramm hinzu, das max() aufruft und als Argumente die linearen Funktionen verwendet und ein anderes Diagramm in dickem Schwarz darüberlegt, um die PWLF anzuzeigen. Die beitragenden Funktionen werden manuell gestrichelt gezeichnet, um die Tatsache hervorzuheben, dass sie in bestimmten Bereichen „nicht beitragen“.

Eigentlich möchte ich alle Linien gestrichelt darstellen, wenn sie nicht Teil des Maximums sind, und ansonsten durchgezogen, um die Farbinformationen im PWLF darüber beizubehalten, welche lineare Funktion diesen Abschnitt des Diagramms ausmacht.

Gibt es eine Möglichkeit, dies anschaulich zu machen, idealerweise ohne die Liniensegmente manuell zeichnen zu müssen? Ich möchte wirklich nicht für jedes Beispiel die Schnittpunkte berechnen und dann jedes Mal entsprechende Diagramme erstellen müssen.

Das MWE erzeugt derzeit diese Ausgabe:

Bildbeschreibung hier eingeben

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}

Antwort1

Das sagetexPaket kann damit umgehen. Die Dokumentation dazu finden Sie auf CTANHier. Dies ermöglicht es Ihnen, die Arbeit an ein Computeralgebrasystem, SAGE, auszulagern, das seine Website hatHier. Das bedeutet, dass Sie SAGE auf Ihren Computer herunterladen und richtig installieren müssen oder ein kostenlosesKokalkKonto. Wenn Sie ein Cocalc-Konto haben, erstellen Sie einfach ein LaTeX-Dokument, kopieren/fügen Sie den untenstehenden Code in Ihr Dokument ein, speichern Sie es und drücken Sie dann auf „Erstellen“, um das Ergebnis anzuzeigen.BEARBEITEN:Ich habe den Code geändert, um einen Fehler in der Legende zu beheben und sie mehr wie die Darstellung aussehen zu lassen, die der OP gepostet hat. Wenn ich die Max-Funktion in die Legende einfüge, wird sie durchgehend blau eingefärbt, also habe ich sie weggelassen.

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

Die Ausgabe in Colcalc wird unten angezeigt: Bildbeschreibung hier eingeben Eine Nahaufnahme: Bildbeschreibung hier eingeben

Python ist die Sprache, die in SAGE verwendet wird. Nachdem Sie Ihre 4 Linien als f1 bis f4 definiert haben, 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]erstellt der Code eine Liste mit x- und y-Koordinaten für Linie f1. Ein Punkt wird zu f1x hinzugefügt, wenn f1 der maximale Punkt auf allen 4 Linien ist. In diesem Fall wird der y-Wert zu f1y hinzugefügt. Es kann vorkommen (z. B. wenn sich 3 Linien am selben Punkt schneiden), dass es nur 1 x-Wert gibt, für den eine Linie das Maximum erreicht. In diesem Fall zeichnen wir diesen nicht auf. Jede Linie, die wirklich Teil der Max-Funktion ist, hat mindestens zwei Punkte, an denen sie das Maximum erreicht. Wenn also angenommen wird, dass f1 mehr als einen Punkt enthält, if len(f1x)>1:wird die Linie als Teil der Max-Funktion gezeichnet.

verwandte Informationen