平均能量损失

平均能量损失

我正在尝试使用复制以下树forest

在此处输入图片描述

这就是我得到的

在此处输入图片描述

除了稍微放错位置的标签Pass(我可以通过传递elo={xshift=<n>pt,yshift=<n>pt到相关分支进行调整)之外,我更感兴趣的是获取正确的分支的方向/角度。

理想情况下,我希望

  • 所有Take树枝都以一定程度生长-90(而不是像现在这样稍微多一点,也不平行),
  • 分支Pass以程度增长0(我现在可以通过手动将每个分支放到before computing xy={l=0,s=15mm}其中来获得这个,这是在这个答案,但如果存在的话,我想知道一个不太麻烦的解决方案)。

平均能量损失

\documentclass[border=2pt]{standalone}
\usepackage{forest}
\forestset{
  declare toks={elo}{}, % Edge Label Options
  anchors/.style={anchor=#1,child anchor=#1,parent anchor=#1},
  dot/.style={tikz={\draw[#1] (.child anchor) circle[radius=1.5pt];}},
  decision edge label/.style n args=3{
    edge label/.expanded={node[midway,auto=#1,anchor=#2,\forestoption{elo}]{\strut\unexpanded{#3}}}
  },
  decision/.style={if n=1
    {decision edge label={left}{east}{#1}}
    {decision edge label={right}{west}{#1}}
  },
  game tree/.style={
    for tree={
      s sep=0mm,l=15mm,
      if n children=0{anchors=north}{
        if n=1{anchors=south east}{anchors=south west}},
      math content,
      /tikz/font=\footnotesize,
    },
    anchors=south, 
    dot={fill=white},for descendants={dot={fill}},
    delay={for descendants={split option={content}{;}{decision,content}}},
  },
}
\begin{document}
\begin{forest}
  game tree
  [A,
    [Take;{(4,2)},]
    [Pass;B,before computing xy={l=0,s=15mm},elo={xshift=-10pt,yshift=5pt}
      [Take;{(2,8)}]
      [Pass;A,before computing xy={l=0,s=15mm} 
        [Take;{(16,4)}]
        [Pass;B,before computing xy={l=0,s=15mm}
          [Take;{(8,32)}]
          [Pass;{(64,16)},before computing xy={l=0,s=15mm}]
        ]
      ]
    ]
  ]
\end{forest}
\end{document}

编辑

经过一番折腾,我终于弄对了角度(基本上是before computing xy为每个分支指定角度)。但我这样做的方式似乎太过黑客化,几乎失去了forest吸引力:自动定位节点以避免重叠。我可以用这么多代码在 TikZ 中绘制树。

\begin{forest}
  game tree
  [A,
    [Take;{(4,2)},before computing xy={l=15mm,s=0mm}]
    [Pass;B,before computing xy={l=0,s=15mm},elo={xshift=-10pt,yshift=5pt},anchors=south
      [Take;{(2,8)},before computing xy={l=15mm,s=0mm}]
      [Pass;A,before computing xy={l=0,s=15mm},elo={xshift=-10pt,yshift=5pt},anchors=south 
        [Take;{(16,4)},before computing xy={l=15mm,s=0mm}]
        [Pass;B,before computing xy={l=0,s=15mm},elo={xshift=-10pt,yshift=5pt},anchors=south
          [Take;{(8,32)},before computing xy={l=15mm,s=0mm}]
          [Pass;{(64,16)},before computing xy={l=0,s=15mm},elo={xshift=-10pt,yshift=5pt}]
        ]
      ]
    ]
  ]
\end{forest}

在此处输入图片描述

我仍在寻找更有效的方法来实现这一目标。

答案1

这可能不是最有效的方法,但可能比手动放置所有内容更好。

关键思想是以反映预期结果的方式指定树的生长方向,而不是让它朝着不适当的方向生长,然后再覆盖它。

因此,将生长角度指定为 是有意义的-45

我们基本上希望每个子项+/-45与生长方向成 度。这会将边缘置于0-90。我们希望这些角度固定,因此我们需要calign=fixed edge angles作为我们的放置策略。

然后,我们删除所有手动放置的内容,让 Forest 自行完成,只需edge label适当调整 s 的位置即可。

在这种情况下,如果没有令人信服的理由不这样做,将content节点的变成label选项并将节点变成实心圆也更容易。这样就无需使用来tikz绘制圆圈。

为了将根节点与其余节点一起处理,我们可以将内容更改为;A。我们还需要为labels 指定数学,因为这些不再由 覆盖math content。事实上,math content现在什么也不做,因为节点本身不包含任何内容:它全部被拆分成edge labels 或labels。

如果您的节点很大且大小不一,最好不要将内容转换为labels。但是,在这棵树中,内容很小、紧凑且相对一致:成对的值below无论如何都会出现,它们有足够的空间,其余的是可以轻松容纳的单个字母。如果您的真实树不是这样的,请告诉我,我可以修改答案以避免使用label

\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage{forest}
\forestset{
  decision edge label/.style n args=3{
    edge label/.expanded={
      node [midway, #1, anchor=#2] {\strut\unexpanded{#3}}
    },
  },
  decision/.style={
    if n=1{% Take
      decision edge label={left}{east}{#1},
    }{% Pass
      decision edge label={above}{south}{#1},
    }
  },
  game tree/.style={
    for tree={
      /tikz/font=\footnotesize,
      grow=-45,
      calign angle=45,
      calign=fixed edge angles,
    },
    before typesetting nodes={
      for tree={
        split option={content}{;}{decision,node label},
        delay={
          content=,
          circle,
          draw,
          if level=0{fill=white}{fill},
          inner sep=1.5pt,
        },
      },
    },
  },
  node label/.style={
    if={
      > O_= O_= | {n}{1}{n children}{0}%
    }{
      label=below:{$#1$},
    }{
      label=above:{$#1$},
    },
  },
}
\begin{document}
\begin{forest}
  game tree,
  [;A,
    [Take;{(4,2)},]
    [Pass;B
      [Take;{(2,8)}]
      [Pass;A
        [Take;{(16,4)}]
        [Pass;B
          [Take;{(8,32)}]
          [Pass;{(64,16)}]
        ]
      ]
    ]
  ]
\end{forest}
\end{document}

具有固定边缘角度和东南生长的树的自动布局

答案2

另一个解决方案istgame包。你可以像 一样控制树的生长方向\setistgrowdirection{-45}

在此处输入图片描述

\documentclass{standalone}

\usepackage{istgame}

\begin{document}    
\begin{istgame}[font=\footnotesize]
\setistgrowdirection{-45}
\xtdistance{15mm}{30mm}
\istroot(0)[initial node]{A}
  \istb{Take}[l]{4,2}[b]
  \istb{Pass}[a]
  \endist
\istroot(1)(0-2){B}
  \istb{Take}[l]{2,8}[b]
  \istb{Pass}[a]
  \endist
\istroot(2)(1-2){A}
  \istb{Take}[l]{16,4}[b]
  \istb{Pass}[a]
  \endist
\istroot(3)(2-2){B}
  \istb{Take}[l]{8,32}[b]
  \istb{Pass}[a]{64,16}[r]
  \endist
\end{istgame}

\end{document}

相关内容