Я хочу создать график, отображающий линейные функции, максимум которых создает кусочно-линейную функцию (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, просто вставьте create a LaTeX document, скопируйте/вставьте код ниже в свой документ, сохраните его, а затем нажмите build, чтобы увидеть результат.РЕДАКТИРОВАТЬ:Я изменил код, чтобы исправить ошибку в легенде и сделать его более похожим на график, который опубликовал 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]
создает список координат x и y для линии f1. Точка добавляется к f1x, если f1 является максимальной точкой на всех 4 линиях, в этом случае значение y добавляется к f1y. Может быть так (например, 3 линии пересекаются в одной точке), что существует только 1 значение x, для которого линия достигает максимума, в этом случае мы не рисуем это; любая линия, действительно являющаяся частью функции max, будет иметь по крайней мере две точки, в которых она достигает максимума. Таким образом, предполагая, что f1 имеет более одной точки, проверенная if len(f1x)>1:
линия будет нанесена на график как часть функции max.