我必须排版很多看起来像这样的自动机图表。
因此,我花了很多精力引入基于 TikZ 的简化语法。我从这里得到了很多帮助,解决了一些细节问题。现在我可以分享整体实现。
\documentclass[fontsize=11pt, paper=a4, DIV=9]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{relsize}
\usepackage{xparse}
\usepackage{tikz}
\makeatletter
% character used in a formal language
% \Char{} expands to the empty word
% \Char{~} expands to the blank character of a Turing machine
% \Char{#} expands to the bottom-of-stack character of a pushdown automaton
\ExplSyntaxOn
\NewDocumentCommand{\Char}{>{\TrimSpaces}m}
{
\str_case_x:nnF{\tl_to_str:n{#1}}
{
{ } {\mbox{$\varepsilon$}}
{ ## } {\mbox{\texttt{\#}}}
{ \c_tilde_str } {\mbox{\textscale{.87}{$\Box$}}}
}
{\mbox{\texttt{#1}}}
}
\ExplSyntaxOff
% state of an automaton
\newcommand{\State}[1]{#1}
% graph of a Turing machine
\newenvironment{GraphTM}[1][]{\begin{scope}[#1]}{\end{scope}}
% state in a graph of a Turing machine
% #1 = identifier
% #2 = state label
% #3 = "initial" and/or "accepting" (separated by comma)
% #4 = position in the format "(<x>, <y>)"
\NewDocumentCommand{\StateTM}{ r() m O{} r() }{%
\node [state, #3] at (#4) (#1) {$\State{#2}$};}
% transition in a graph of a Turing machine
% #1 = identifier of the current state
% #2 = edge modifier using TikZ syntax
% #3 = identifier of the subsequent state
% #4 = position of the edge label using TikZ syntax
% #5 = edge label
\NewDocumentCommand{\TransTM}{ r() O{} r() O{} m }{%
\path [trans] (#1) edge [#2] node [#4] {\IT@TM@Edge@Label{#5}} (#3);}
% internal commands used by \TransTM
\newcommand{\IT@TM@Trans}[3]{%
\makebox[.6em]{\Char{#1}};\;\makebox[.6em]{\Char{#2}},\,\Char{#3}}
\NewDocumentCommand{\IT@TM@Edge@Item}{>{\SplitArgument{2}{,}}m}{%
\IT@TM@Edge@Delim\IT@TM@Trans#1}
\NewDocumentCommand{\IT@TM@Edge@Label}{>{\SplitList{|}}m}{%
\def\IT@TM@Edge@Delim{\gdef\IT@TM@Edge@Delim{\\}}
\shortstack{\ProcessList{#1}{\IT@TM@Edge@Item}}}
\makeatother
\usetikzlibrary{automata}
\tikzset{>=stealth, semithick}
\tikzset{initial text=}
\tikzset{state/.style={font=\small, minimum size=0pt, circle, draw}}
\tikzset{trans/.style={font=\footnotesize, ->}}
\begin{document}
\begin{tikzpicture}
\begin{GraphTM}
% States
\StateTM (z0) {z_0} [initial] ( 0, 0)
\StateTM (z1) {z_1} ( 3, 0)
\StateTM (z2) {z_2} ( 6, 0)
\StateTM (z3) {z_3} ( 9, 0)
\StateTM (z4) {z_4} (-2, 3)
\StateTM (z5) {z_5} [accepting] ( 2, 3)
% Transitions
\TransTM (z0) (z1) [above] {a, x, R}
\TransTM (z0) (z4) [left=3pt] {y, y, R}
\TransTM (z0) (z5) [left=3pt] {~, ~, N}
\TransTM (z1) [loop above] (z1) [above] {a, a, R | y, y, R}
\TransTM (z1) (z2) [above] {b, y, R}
\TransTM (z2) [loop above] (z2) [above] {b, b, R | z, z, R}
\TransTM (z2) (z3) [above] {c, z, L}
\TransTM (z3) [loop above] (z3) [above] {a, a, L | b, b, L | y, y, L | z, z, L}
\TransTM (z3) [bend left=23] (z0) [below] {x, x, R}
\TransTM (z4) [loop above] (z4) [above] {y, y, R | z, z, R}
\TransTM (z4) (z5) [above] {~, ~, N}
\end{GraphTM}
\end{tikzpicture}
\end{document}
\makeatletter
和之间的所有内容\makeatother
都是我正在编写的包的一部分。
有一些命令和环境(例如\State{}
和GraphTM
)目前什么都不做。它们用于以后对布局的修改。
我暂时没有使用相对定位[right = ... of ...]
。此功能以后可以根据需要实现。
你觉得这个实现怎么样?我是不是做了一些奇怪的事情,可能会导致我不知道的问题?