![tikz 中的分支定界树](https://linux22.com/image/370890/tikz%20%E4%B8%AD%E7%9A%84%E5%88%86%E6%94%AF%E5%AE%9A%E7%95%8C%E6%A0%91.png)
我正在尝试创建一棵树,以显示 tikz 中整数规划问题的分支定界过程。我设法以我想要的方式创建了一棵具有第一级的树,但 latex 无法编译具有第二级的树,我不确定我的代码优化得很差,因为这是我唯一能弄清楚如何做到这一点的方法,而且代码混乱意味着很难确定我哪里出错了。
如果有人可以向我展示一种清理代码的方法,以便大多数节点细节都在预定义中,或者向我展示第二棵树中哪里出了问题,那就太好了。
第一级代码:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{calc, shapes}
\begin{document}
\begin{figure}
\centering
\begin{tikzpicture}[
scale = 1.5, transform shape, thick,
tree node/.style = {align=center, inner sep=0pt, text centered, font =
\scriptsize},
S/.style = {draw, circle, minimum size = 8mm, top color=white, bottom
color=blue!20},
grow = down, % alignment of characters
level 1/.style = {sibling distance=3cm},
level 2/.style = {sibling distance=4cm},
level 3/.style = {sibling distance=2cm},
level distance = 1.25cm]
\node [S, label={[font = \scriptsize]10:950}, label={[font =
\scriptsize]170:1055.56}] {$S$}
child{node [S, label={[font = \scriptsize]10:950}, label={[font =
\scriptsize]170:1000}] {$S_1$}edge from parent node[above left, font =
\scriptsize] {$x \leq 5$}}
child{node [S, label={[font = \scriptsize]10:950}, label={[font =
\scriptsize]170:1033}]
{$S_2$} edge from parent node[above right, font = \scriptsize] {$x \geq
6$}};
\end{tikzpicture}
\end{figure}
\end{document}
编译失败的第一和第二级代码:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{calc, shapes}
\begin{document}
\begin{figure}
\begin{tikzpicture}[
scale = 1.5, transform shape, thick,
tree node/.style = {align=center, inner sep=0pt, text centered, font =
\scriptsize},
S/.style = {draw, circle, minimum size = 8mm, top color=white, bottom
color=blue!20},
grow = down, % alignment of characters
level 1/.style = {sibling distance=3cm},
level 2/.style = {sibling distance=4cm},
level 3/.style = {sibling distance=2cm},
level distance = 1.25cm]
\node [S, label={[font = \scriptsize]10:950}, label={[font =
\scriptsize]170:1055.56}] {$S$}
child{node [S, label={[font = \scriptsize]10:950}, label={[font =
\scriptsize]170:1000}] {$S_1$} edge from parent node[above left, font =
\scriptsize] {$x \leq 5$}}
child{node [S, label={[font = \scriptsize]10:950}, label={[font =
\scriptsize]170:1033}]
{$S_2$} edge from parent node[above right, font = \scriptsize] {$x
\geq 6$}
child{node [S, label={[font = \scriptsize]10:950}, label={[font
= \scriptsize]170:1033}]
{$S_2,1$} edge from parent node[above right, font = \scriptsize]
{$x \leq 1$}
child{node [S, label={[font = \scriptsize]10:950}, label={[font
= \scriptsize]170:1033}]
{$S_2,2$} edge from parent node[above right, font = \scriptsize]
{$x \geq 2$}};
\end{tikzpicture}
\end{figure}
\end{document}
提前致谢!
编辑:像我试图创建的一样的分支定界树
答案1
我会使用专门的树绘制包之一。更具体地说,我会使用forest
或,如果不行,则tikz-qtree
使用。如果这样做,您可以非常简洁地指定树,并且可以轻松确保它们的格式一致。
对于 Forest 来说,该包还会为您完成很多布局工作,尽管标签不是以这种方式处理的,因此这种特殊的优势对于这种特殊类型的树来说可能没有多大好处。
以下是定义森林样式的示例branch and bound
。当应用于树时,会发生以下情况:
tree node
,S
并thick
应用于树中的所有节点,其内容以数学模式设置;边缘也是如此
thick
;在树上添加一些空间来分隔树枝和层级;
树解析完毕后,每个节点的内容按冒号分割:
<left label>:<node content>:<right label>:<edge label>
;- 第一个冒号之前的部分成为左标签(在 处
170
)。下一部分设置为主节点内容(tree node
在数学模式中带有 ,等等)。第三部分设置为右标签(在 处10
)。最后一部分成为分支上的标签:左侧分支位于中点左侧,右侧分支位于中点右侧。
- 第一个冒号之前的部分成为左标签(在 处
边缘标签的内容可以在文本模式(
text branch labels
)或数学模式(maths branch labels
)中设置;前缀和后缀可以使用以下方式添加:
set branch labels={<left branch prefix>}{<left branch suffix>}{<right branch prefix>}{<right branch suffix>}
set maths branch labels={<left branch prefix>}{<left branch suffix>}{<right branch prefix>}{<right branch suffix>}
set text branch labels={<left branch prefix>}{<left branch suffix>}{<right branch prefix>}{<right branch suffix>}
树的每片叶子下面都画一条水平线。
然后我们可以指定我认为是你的第二棵树,现在根据评论进行编辑,以根据级别改变边缘标签,
\begin{forest}
branch and bound,
where level=1{
set branch labels={x\leq}{}{x\geq}{},
}{
if level=2{
set branch labels={}{\geq y}{}{\leq y},
}{},
}
[1055.56:S:950
[1000:S_1:950:5
]
[1033:S_2:950:6
[1033:{S_2,1}:950:1]
[950:{S_2,2}:1033:2]
]
]
\end{forest}
这显然要简洁得多,并且产生了
我不知道这种树的标准是什么,所以可能需要稍微调整一下才能正常工作。例如,边缘标签可能并不总是形式x\leq
和x\req
,或者有时只有一个或两个以上的子节点。然而,这至少应该说明了这种方法的潜在威力。
完整代码:
\documentclass[border=10pt]{standalone}
\usepackage{forest}
\tikzset{
tree node/.style = {align=center, inner sep=0pt, font = \scriptsize},
S/.style = {draw, circle, minimum size = 8mm, top color=white, bottom color=blue!20},
tree node label/.style={font=\scriptsize},
}
\forestset{
declare toks={left branch prefix}{},
declare toks={right branch prefix}{},
declare toks={left branch suffix}{},
declare toks={right branch suffix}{},
tree node left label/.style={
label=170:#1,
},
tree node right label/.style={
label=10:#1,
},
maths branch labels/.style={
branch label/.style={
if n=1{
edge label={node [left, midway] {$\forestoption{left branch prefix}##1\forestoption{left branch suffix}$}},
}{
edge label={node [right, midway] {$\forestoption{right branch prefix}##1\forestoption{right branch suffix}$}},
}
},
},
text branch labels/.style={
branch label/.style={
if n=1{
edge label={node [left, midway] {\foresteoption{left branch prefix}##1\forestoption{left branch suffix}}},
}{
edge label={node [right, midway] {\forestoption{right branch prefix}##1\forestoption{right branch suffix}}},
}
},
},
text branch labels,
set branch labels/.style n args=4{%
left branch prefix={#1},
left branch suffix={#2},
right branch prefix={#3},
right branch suffix={#4},
},
set maths branch labels/.style n args=4{
maths branch labels,
set branch labels={#1}{#2}{#3}{#4},
},
set text branch labels/.style n args=4{
text branch labels,
set branch labels={#1}{#2}{#3}{#4},
},
branch and bound/.style={
/tikz/every label/.append style=tree node label,
maths branch labels,
for tree={
tree node,
S,
math content,
s sep'+=20mm,
l sep'+=5mm,
thick,
edge+={thick},
},
before typesetting nodes={
for tree={
split option={content}{:}{tree node left label,content,tree node right label,branch label},
},
},
where n children=0{
tikz+={
\draw [thick] ([yshift=-10pt, xshift=-2.5pt].south west) -- ([yshift=-10pt, xshift=2.5pt].south east);
}
}{},
},
}
\begin{document}
\begin{forest}
branch and bound,
where level=1{
set branch labels={x\leq}{}{x\geq}{},
}{
if level=2{
set branch labels={}{\geq y}{}{\leq y},
}{},
}
[1055.56:S:950
[1000:S_1:950:5
]
[1033:S_2:950:6
[1033:{S_2,1}:950:1]
[950:{S_2,2}:1033:2]
]
]
\end{forest}
\end{document}
答案2
- 您的 mwe 中的第二个代码出现错误,源代码
}
缺失edge from parent node
- 解决方案
tikz
- 通过为节点和边标签定义新样式,您的代码变得更加简洁
- 将问题中的两棵树合并为一棵(类似于成本加运费在他的回答中)我们变成:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{calc, shapes}
\begin{document}
\begin{figure}
\tikzset{thick,
tree node/.style = {align=center, inner sep=0pt, font = \scriptsize},
every label/.append style = {font=\scriptsize},
S/.style = {draw, circle, minimum size = 11mm, inner sep=0pt,
top color=white, bottom color=blue!20},
ENL/.style = {% edge node left
font=\footnotesize, left=1pt},
ENR/.style = {% edge node right
font=\footnotesize, right=1pt},
grow = down,
sibling distance = 2.8cm,
level distance = 3cm
}
\newcommand\LB{% Lower bound
\tikz\draw[very thick] (-0.5,0) -- + (1,0);}
\centering
\begin{tikzpicture}
\node [S, label=10:950, label=170:1055.56] {$S$}
child{node [S, label=10:950, label=170:1000, label=below:\LB] {$S_1$}
edge from parent node[ENL] {$x \leq 5$}}
child{node [S, label=10:950, label=170:1033] {$S_2$}
child{node [S, label=10:950, label=170:1033, label=below:\LB] {$S_2,1$}
edge from parent node[ENL] {$x \geq 6$}}
child{node [S, label=10:950, label=170:1033, label=below:\LB] {$S_2,2$}
edge from parent node[ENR] {$x \leq 1$}}
edge from parent node[ENR] {$x \geq 6$}
};
\end{tikzpicture}
\end{figure}
\end{document}