存在一个精心设计的线索关于如何在 LaTeX 中绘制根树,例如用于自然语言应用程序。除了 TikZ 之外,还有其他软件包可以做到这一点,例如配额树或者森林。然而,所有这些树的一个共同主题是,叶子最终会连成一个总体根。有些应用会用到这种事实并非如此;一个例子是分层分割,例如字节对编码. 另一个可能是切割跨越聚集聚类层次结构。
最终结果是你得到多棵树,但其中一棵树的叶子必须对齐和不同树的叶子也必须对齐。下面是我在 Paint 中绘制的假设示例,用于聚合使混乱,结束于分割发声+波纹:
如何在 LaTeX 中重现这个现象?给定合并列表?有几个自由:
- 你可以选择任何合并/树的规范格式。合并列表来自 Python 程序,因此不需要花太多功夫适应你认为最简单的格式。我有树的程序化表示,因此很容易将其转换为类似Newick 格式这几乎是文字
forest
代码。 - 你可以自由选择非叶节点的高度,只要它是 1. 离散的并且 2. 高于其组成部分即可。
- 如果您更喜欢像树状图那样的直角分支,那也很好。
我希望解决方案满足几个要求,以使其足够通用:
- 应允许一个节点包含两个以上的组成部分(例如,“d”、“i”、“s”立即合并为“dis”,而无需经过“is”)。因此,请不要使用仅允许绘制二叉树的包。
- 应该对水平和垂直紧凑度进行一些控制,即各层之间的紧密程度以及叶子之间的距离。
- 应该允许关闭中间节点名称。
后者会产生类似下面的图像:
编者注:这个问题的标题更好,我们总是会感激的。我不喜欢我想出的标题。
答案1
通过使用forest
包:
- 有叉边:
\documentclass[margin=3mm, varwidth]{standalone}
\usepackage[edges]{forest}
\begin{document}
\begin{figure}[ht]
\forestset{
LT/.style = {% Linguistic tree
delay={where content={}{shape=coordinate}{}},
where n children=0{tier=word, baseline}{},
for tree={
text height = 2ex,
text depth = 0.5ex,
inner ysep = 0pt,
inner xsep = 1pt,
forked edge, % for forked edge
s sep = 1mm, % sibling distance
}}}
\begin{forest} LT
[discom
[
[d]
[
[i]
[s]
]
]
[
[c]
[
[o]
[m]
]
]
]
\end{forest}
\quad
\begin{forest} LT
[bubolate
[
[b]
[
[o]
[b]
]
]
[
[
[
[u]
[l]
]
]
[
[
[a]
[t]
]
[e]
]
]
]
\end{forest}
\end{figure}
\end{document}
- 作为语言树:
\documentclass[margin=3mm, varwidth]{standalone}
\usepackage[linguistics]{forest}
\begin{document}
\begin{figure}[ht]
\forestset{
LT/.style = {% Linguistic tree
delay={where content={}{shape=coordinate}{}},
where n children=0{tier=word, baseline}{},
for tree={
text height = 2ex,
text depth = 0.5ex,
inner ysep = 0pt,
inner xsep = 1pt,
s sep = 1mm, % sibling distance
}}}
\begin{forest} LT
[discom
[
[d]
[
[i]
[s]
]
]
[
[c]
[
[o]
[m]
]
]
]
\end{forest}
\quad
\begin{forest} LT
[bubolate
[
[b]
[
[o]
[b]
]
]
[
[
[
[u]
[l]
]
]
[
[
[a]
[t]
]
[e]
]
]
]
\end{forest}
\end{figure}
\end{document}
附录:
在这种情况下,当您希望树底部的字母之间和树之间的距离相同时,您需要首先为该距离定义新命令,例如
\tikz\pgfmathsetlength{\SD}{2mm}
然后更换
quad
和\hskip \SD
s sep = ...˙with
s sep = \SD + 1mm`
梅威瑟:
\documentclass[margin=3mm, varwidth]{standalone}
\usepackage[linguistics]{forest}
\begin{document}
\begin{figure}[ht]
\newcommand\SD{1 mm} % <-------
\forestset{
LT/.style = {% Linguistic tree
delay={where content={}{shape=coordinate}{}},
where n children=0{tier=word, baseline}{},
for tree={
text height = 2ex,
text depth = 0.5ex,
draw, % that distance are more evident/visible, remove in real document
inner ysep = 0pt,
inner xsep = 1pt,
s sep = \SD + 1mm, % <-------
}}}
\begin{forest} LT,
[discom
[
[d]
[
[i]
[s]
]
]
[
[c]
[
[o]
[m]
]
]
]
\end{forest}
\hskip \SD % <-------
\begin{forest} LT
[bubolate
[
[b]
[
[o]
[b]
]
]
[
[
[
[u]
[l]
]
]
[
[
[a]
[t]
]
[e]
]
]
]
\end{forest}
\end{figure}
\end{document}
为了更好的可见性
答案2
这是基于 Zarko 的回答。我们引入了一个forest
register
称为 的函数empty intermediates
,它控制中间节点的内容是否排版或是否留空。默认情况下,它设置为not empty intermediates
。更改为empty intermediates
可翻转默认值。请注意,其中一个是必需的,所以不要完全删除此行 - 无论如何你都希望该值默认,否则forest
会报错。声明新寄存器的行是不是足够了,因为它没有设置默认值。
然后,您可以在各个树的前言中指定empty intermediates
或not empty intermediates
来覆盖默认值。当然,您也可以在文档的任何位置更改默认值,只需使用 即可\forestset{}
。
\documentclass[margin=3mm, varwidth]{standalone}
\usepackage[linguistics]{forest}
% seiliedig ar ateb Zarko https://tex.stackexchange.com/a/687344/ i gwestiwn Mew https://tex.stackexchange.com/q/684485/
\newcommand\SD{1 mm}
\forestset{%
declare boolean register=empty intermediates,
not empty intermediates,% default is to include node content if specified; delete the 'not' to flip the default or override in individual trees' preambles etc.
LT/.style = {% Linguistic tree
for tree={
if n children=0{tier=word,baseline}{if={> {O_> R &}{level}{0}{empty intermediates}}{before typesetting nodes={shape=coordinate}}{delay={if content={}{shape=coordinate}{}}}},
% adjust the following to make the nodes larger or smaller
% text height = 1.5ex,
% text depth=.25ex,
% inner sep=0pt,
s sep = \SD,
}}}
\begin{document}
\begin{figure}[ht]
\begin{forest}
LT,
[discom
[dis
[d]
[is
[i]
[s]
]
]
[com
[c]
[om
[o]
[m]
]
]
]
\end{forest}%
\hskip \SD
\begin{forest}
LT
[bubolate
[bob
[b]
[ob
[o]
[b]
]
]
[ulate
[ul
[u]
[l]
]
[ate
[at
[a]
[t]
]
[e]
]
]
]
\end{forest}
\end{figure}
\end{document}
翻转默认值:
答案3
嗯,不太明白你的要求:听起来你在寻找一些自动化功能。如果是这样,你需要考虑如何控制输出(作为一个函数,例如f(p1, p2, .. pn))
这是一个手动的、简单直接的方法,您可以根据需要改变位置:
\documentclass[10pt,border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}
% lowest level 1
\node (1-1) {d};
\node (1-2) [right=of 1-1] {i};
\node (1-3) [right=of 1-2] {s};
\node (1-4) [right=of 1-3] {c};
\node (1-5) [right=of 1-4] {o};
\node (1-6) [right=of 1-5] {m};
% level 2
\node (2-2) [above=of 1-2] {is};
\node (2-5) [above=of 1-5] {om};
% level 3
\node (3-1) [above=of 2-2] {dis};
\node (3-5) [above=of 2-5] {com};
% level 4
\node (4) [above right=of 3-1] {discom};
% connections
\draw (1-2) -- (2-2) -- (1-3);
\draw (1-5) -- (2-5) -- (1-6);
\draw (1-1) -- (3-1) -- (2-2);
\draw (1-4) -- (3-5) -- (2-5);
\draw (3-1) -- (4) -- (3-5);
\end{tikzpicture}
\begin{tikzpicture}
% lowest level 1
\node (1-1) {d};
\node (1-2) [right=of 1-1] {i};
\node (1-3) [right=of 1-2] {s};
\node (1-4) [right=of 1-3] {c};
\node (1-5) [right=of 1-4] {o};
\node (1-6) [right=of 1-5] {m};
% level 2
\node (2-2) [above=of 1-2] {};
\node (2-5) [above=of 1-5] {};
% level 3
\node (3-1) [above=of 2-2] {};
\node (3-5) [above=of 2-5] {};
% level 4
\node (4) [above right=of 3-1] {discom};
% connections
\draw (1-2) -- (2-2) -- (1-3);
\draw (1-5) -- (2-5) -- (1-6);
\draw (1-1) -- (3-1) -- (2-2);
\draw (1-4) -- (3-5) -- (2-5);
\draw (3-1) -- (4) -- (3-5);
\end{tikzpicture}
\end{document}