Я написал LaTeX для автомата, который выглядит следующим образом:
Как вы можете видеть, буква «b» на стрелке от q1 до q3 расположена ниже, чем «a, b, c» на стрелке от q3 до q2.
Кроме того, «b» на ребре от q2 до q3 расположено ниже, чем «a, c» на стрелке от q3 до q1.
Я хотел бы, чтобы оба дуэта узлов были хорошо выровнены, то есть на одной базовой линии. Однако не обязательно, чтобы все четыре были на одной линии.
Мне кажется, что мой код должен делать это сам по себе, но почему-то не работает. Почему?
Вот мой код. Я отметил два дуэта узлов комментариями:
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{automata,arrows,calc,positioning}
\begin{document}
\begin{tikzpicture}[->,node distance=25mm]
\node[state,initial,accepting] (q0) {$q_0$};
\node[state,right=of q0] (q1) {$q_1$};
\node[state,right=of q1] (q2) {$q_2$};
\node[state,below=of $(q1)!0.5!(q2)$] (q3) {$q_3$};
\node[state,accepting,right=of q2] (q4) {$q_4$};
\draw (q0) edge[loop above] node[above] {a, b} (q0);
\draw (q0) -- node[above] {b, c} ++ (q1);
\draw (q1) edge[loop above] node[above] {a, c} (q1);
\draw (q1) edge[bend left] node[above] {a, b, c} (q2);
\draw (q2) -- node[below] {a, c} ++ (q1);
\draw (q2) edge[bend left] node[right] {b} (q3); % ! duo B
\draw (q3) -- node[above left] {a, b, c} ++ (q2); % ! duo A
\draw (q3) edge[bend left] node[left] {a, c} (q1); % ! duo B
\draw (q1) -- node[above right] {b} ++ (q3); % ! duo A
\draw (q2) edge[loop above] node[above] {a, b, c} (q2);
\draw (q2) -- node[above] {c} ++ (q4);
\draw (q1) edge[out=60,in=120] node[above] {c} (q4);
\end{tikzpicture}
\end{document}
решение1
Добавьте \strut
или определите text depth
для этих узлов. Я также изменил above left
на left
и above right
на right
соответствующим образом.
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{automata,arrows,calc,positioning}
\begin{document}
\begin{tikzpicture}[->,node distance=25mm]
\node[state,initial,accepting] (q0) {$q_0$};
\node[state,right=of q0] (q1) {$q_1$};
\node[state,right=of q1] (q2) {$q_2$};
\node[state,below=of $(q1)!0.5!(q2)$] (q3) {$q_3$};
\node[state,accepting,right=of q2] (q4) {$q_4$};
\draw (q0) edge[loop above] node[above] {a, b} (q0);
\draw (q0) -- node[above] {b, c} ++ (q1);
\draw (q1) edge[loop above] node[above] {a, c} (q1);
\draw (q1) edge[bend left] node[above] {a, b, c} (q2);
\draw (q2) -- node[below] {a, c} ++ (q1);
\draw (q2) edge[bend left] node[right] {\strut b} (q3); % ! duo B
\draw (q3) -- node[left] {\strut a, b, c} ++ (q2); % ! duo A
\draw (q3) edge[bend left] node[left] {\strut a, c} (q1); % ! duo B
\draw (q1) -- node[right] {\strut b} ++ (q3); % ! duo A
\draw (q2) edge[loop above] node[above] {a, b, c} (q2);
\draw (q2) -- node[above] {c} ++ (q4);
\draw (q1) edge[out=60,in=120] node[above] {c} (q4);
\end{tikzpicture}
\end{document}
решение2
В первую очередь я бы добавил параметры text height=1ex, text depth=0pt
в tikzpicture
параметр s, чтобы принудительно задать всем меткам одинаковый (вертикальный) размер.
Сделав это, проблемы
Как вы можете видеть, буква «b» на стрелке от q1 до q3 расположена ниже, чем «a, b, c» на стрелке от q3 до q2.
Кроме того, «b» на ребре от q2 до q3 расположено ниже, чем «a, c» на стрелке от q3 до q1.
магическим образом исправлены.
Альтернативное и экзотическое решение — назвать важный узел, скажем, тот, у которого есть a,b,c
и определить b
место в терминах расположения важного узла. То есть:
\draw (q1) -- node[shift={(label-abc.west)}, xshift=-3.5mm] {b} ++ (q3);
Полный код:
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{automata,arrows,calc,positioning}
\begin{document}
\begin{tikzpicture}[->,node distance=25mm, text height=1ex, text depth=0pt]
\node[state,initial,accepting] (q0) {$q_0$};
\node[state,right=of q0] (q1) {$q_1$};
\node[state,right=of q1] (q2) {$q_2$};
\node[state,below=of $(q1)!0.5!(q2)$] (q3) {$q_3$};
\node[state,accepting,right=of q2] (q4) {$q_4$};
\draw (q0) edge[loop above] node[above] {a, b} (q0);
\draw (q0) -- node[above] {b, c} ++ (q1);
\draw (q1) edge[loop above] node[above] {a, c} (q1);
\draw (q1) edge[bend left] node[above] {a, b, c} (q2);
\draw (q2) -- node[below] {a, c} ++ (q1);
\draw (q2) edge[bend left] node[right] {b} (q3); % ! duo B
\draw (q3) -- node[above left](label-abc) {a, b, c} ++ (q2); % ! duo A
\draw (q3) edge[bend left] node[left] {a, c} (q1); % ! duo B
\draw (q1) -- node[shift={(label-abc.west)}, xshift=-3.5mm] {b} ++ (q3); % ! duo A
\draw (q2) edge[loop above] node[above] {a, b, c} (q2);
\draw (q2) -- node[above] {c} ++ (q4);
\draw (q1) edge[out=60,in=120] node[above] {c} (q4);
\end{tikzpicture}
\end{document}
Примечание: установка обоих text height
и text depth
действительно помогает в случае таких писем, какп,д,ги так далее.
Например:
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{automata,arrows,calc,positioning,fit}
\begin{document}
\begin{tikzpicture}[->,node distance=25mm, text height=1ex, text depth=0pt]
\node[state,initial,accepting] (q0) {$q_0$};
\node[state,right=of q0] (q1) {$q_1$};
\node[state,right=of q1] (q2) {$q_2$};
\node[state,below=of $(q1)!0.5!(q2)$] (q3) {$q_3$};
\node[state,accepting,right=of q2] (q4) {$q_4$};
\draw (q0) edge[loop above] node[above] {a, b} (q0);
\draw (q0) -- node[above] {b, c} ++ (q1);
\draw (q1) edge[loop above] node[above] {a, c} (q1);
\draw (q1) edge[bend left] node[above] {a, b, c} (q2);
\draw (q2) -- node[below] {a, c} ++ (q1);
\draw (q2) edge[bend left] node[right] (label-g) {g} (q3); % ! duo B
\draw (q3) -- node[draw,above left](label-abc) {a, b, c} ++ (q2); % ! duo A
\draw (q3) edge[bend left] node[left] (label-ac) {a, c} (q1); % ! duo B
\draw (q1) -- node[draw,above right] {q} ++ (q3); % ! duo A
\draw (q2) edge[loop above] node[above] {a, b, c} (q2);
\draw (q2) -- node[above] {c} ++ (q4);
\draw (q1) edge[out=60,in=120] node[above] {c} (q4);
\node[draw,fit=(label-g)(label-ac)]{};
\draw (label-ac.base)--(label-g.base);
\end{tikzpicture}
\end{document}
Результат:
решение3
в основном не по теме, для упражнения, как сделать код диаграммы короче :-). также даются некоторые дополнительные пояснения и предлагается использовать tikz
библиотечные `кавычки.
как указано в других ответах, вам необходимо определить пробелы для запятых в метках краев. Это можно сделать двумя способами:
- как предложеноКлаудио Фиандрино: определить
text height=1ex
и установитьtext depth=0pt
. Это является причиной того, что буквыb
и запятые касаются верхней и нижней границы узла соответственно. - как предложено @user11232: использование распорки в каждом содержимом узла метки наклонного края, что делает эти узлы равными по высоте и глубине
в mwe ниже я следую заКлаудио Фиандриноподход, однако размер узла определяется по-другому и, на мой взгляд, более правильно. для меток ребер используются edge quotes
:
\documentclass[tikz, border=3mm]{standalone}
\usetikzlibrary{arrows.meta, automata,
calc,
positioning,
quotes}
\begin{document}
\begin{tikzpicture}[-Straight Barb,
node distance = 25mm,
auto = left,
every edge quotes/.style = {inner sep=1pt, % that labels are closer to edges
text height=1.5ex, % equal height,
text depth=2pt, % space for commas
% however this depth is not sufficient for letters as p,q, ...
% for them is better 0.25ex or slightly more
font=\small} % smaller letters, gives a nicer result
]
\node (q0) [state,initial,accepting] {$q_0$};
\node (q1) [state,right=of q0] {$q_1$};
\node (q2) [state,right=of q1] {$q_2$};
\node (q3) [state,below=of $(q1)!0.5!(q2)$] {$q_3$};
\node (q4) [state,accepting,right=of q2] {$q_4$};
%
\draw (q0) edge[loop above, "{a, b}"] ()
(q0) edge["{b, c}"] (q1)
(q1) edge[loop above, "{a, c}"] ()
(q1) edge[bend left, "{a, b, c}"] (q2)
(q2) edge["{a, c}"] (q1)
(q2) edge[loop above, "{a, b, c}"] ()
(q2) edge[bend left, "b"] (q3) % ! duo B
(q2) edge["c"] (q4)
(q3) edge["{a, b, c}"] (q2) % ! duo A
(q3) edge[bend left, "{a, c}"] (q1) % ! duo B
(q1) edge["b"] (q3) % ! duo A
(q1) edge[out=60,in=120, "c"] (q4);
\end{tikzpicture}
\end{document}