我对 tikz 和 TeX 还不太熟悉,但编写树的代码没有问题。我只是想要一个人类可读的树。以下是没有边标签或选项的树的最小示例:
\begin{tikzpicture}
\tikzstyle{every node}=[draw,shape=circle,fill=black,inner sep=0pt,minimum size=2mm]
\tikzstyle{level 1}=[sibling distance =35mm,level distance=20mm]
\tikzstyle{level 2}=[sibling distance = 18mm,level distance=15mm]
\tikzstyle{level 3}=[sibling distance = 12mm,level distance=10mm]
\tikzstyle{level 4}=[sibling distance = 7mm]
\node {}
[grow=right]
child { node {}
child { node {} }
child { node {}
child { node {} }
child { node {}
child { node {} }
child { node {} } } } }
child { node {}
child { node {} }
child { node {} } };
\end{tikzpicture}
这是同一棵树,只是带有附加选项和边标签:
\begin{tikzpicture}
\tikzstyle{every node}=[draw,shape=circle,fill=black,inner sep=0pt,minimum size=2mm]
\tikzstyle{level 1}=[sibling distance =28mm,level distance=15mm]
\tikzstyle{level 2}=[sibling distance = 18mm,level distance=15mm]
\tikzstyle{level 3}=[sibling distance = 12mm,level distance=15mm]
\tikzstyle{level 4}=[sibling distance = 7mm,level distance=15mm]
\node {}
[grow=right]
child { node {}
child { node {}
child[level distance=30mm] { node {} edge from parent node [below=1mm,fill=none,draw=none] { $1-w_i$ } }
child { node {}
child { node {} edge from parent node [below=0.02mm,fill=none,draw=none] { $1-g_i$ } }
child { node {} edge from parent node [above=1mm,fill=none,draw=none] { $g_i$ } }
edge from parent node [above=1mm,fill=none,draw=none] { $w_i$ } }
edge from parent node [below=1mm,fill=none,draw=none] { $1-a$ } }
child[level distance=45mm] { node {} edge from parent node [above=1mm,fill=none,draw=none] { $a$ } }
edge from parent node [below=1mm,fill=none,draw=none] { $1-c$ } }
child { node {}
child[level distance=45mm] { node {} edge from parent node [below=1mm,fill=none,draw=none] { $1-a$ } }
child[level distance=45mm] { node {} edge from parent node [above=1mm,fill=none,draw=none] { $a$ } }
edge from parent node [above=1mm,fill=none,draw=none] { $c$ } };
\end{tikzpicture}
在我看来,这棵树现在几乎无法阅读。特别是由于 tikz 的语法要求我在子节点的末尾插入边标签。我很可能会把这棵树交给别人进一步使用和改编,但我担心这棵树在这种状态下会毫无用处。发现错误或更改某些内容似乎非常非常危险且容易出错。事实上,犯错后,对我来说,开始一棵新树通常比调试现有树更容易。但是,对于更大的树,我无法做到这一点。
所以,我的问题是:您能否建议使用宏、样式定义或其他任何东西来简化这棵树并使其再次可读?
注意:由于压力很大,我无法使用其他软件包,因为我想在本周内完成这个项目。因此,现在学习新语法效率不高。但是,请随意为可能偶然发现这篇文章的其他用户提供建议。
编辑:如果有人知道如何编写语法以使其变得不那么模糊,我也会很高兴。
答案1
使用 tikz 键,你可以用更简洁的方式表达同一棵树
\begin{tikzpicture}[
tree node/.style={
draw,
shape=circle,
fill=black,
inner sep=0pt,
minimum size=2mm},
every child node/.style={tree node},
root/.style={tree node},
level/.style={sibling distance=30mm/#1,level distance=15mm},
% Skip a level in the tree
skip level/.default={1},
skip level/.style={
level distance=\tikzleveldistance*#1+\tikzleveldistance},
skip level spaced/.default={1},
skip level spaced/.style={
skip level=#1,
sibling distance=\tikzsiblingdistance*#1+\tikzsiblingdistance},
% Probability on edge:
prob/.style={
insert path={edge from parent node[prob label] {$#1$}}},
prob label/.style={outer sep=.5mm},
]
\node[root] {}
[grow=right]
child { node {}
child { node {}
child[skip level spaced] {
node {} [below, prob=1-w_i]}
child { node {}
child { node {} [below, prob=1-g_i] }
child { node {} [above, prob=g_i] }
[above, prob=w_i ] }
[below, prob=1-a] }
child[skip level=2,yshift=3mm] {
node {} [above, prob=a] }
[below left, prob=1-c] }
child { node {}
child[skip level=2] { node {} [below, prob=1-a] }
child[skip level=2] { node {} [above, prob=a] }
[above,prob=c] };
\end{tikzpicture}
唯一遗憾的是,边缘标签必须设置在子节点的末尾,在存在子树的情况下,将其与它引用的子指令分开。然而,缩进可以帮助匹配它们。
该解决方案提供:
- 清理样式
- 一些新的键使树表达式更加“语义化”并且噪音更少
清理
我更喜欢遵循 tikz 手册并tikzpicture
使用pgfkeys
' 语法在可选参数中设置样式。every child node
样式允许您避免draw=none,fill=none
在边缘标签节点中进行设置。
样式root
只是一个同义词,使代码可读(您需要tree node
手动在根上安装样式,因为它不是子节点)。
我没有手动设置每个级别的距离,而是将公共部分分解出来level distance
并计算sibling distance
当前级别的 wrt(存储在中#1
)。
和风格prob
skip level
prob
我假设边缘标签代表概率,并定义了设置它们的样式。我无法使用label
它,因为它已经用于不同的目的,但您可以根据标签的实际含义随意重命名它。
该prob
样式注入边缘操作,创建一个以数学内容作为参数传递的节点。
此skip level=N
样式将当前子节点N
级别在树中下移。您可以使用移位(或其他样式)进一步操纵节点的高度。