将节点定位在多点路径的中间

将节点定位在多点路径的中间

为了学习 Tikz,我想重新创建众所周知的强化学习代理 -> 环境 -> 代理图。

这是我目前得到的:

\documentclass[border=0.2cm]{standalone}
\usepackage{microtype}
\usepackage{libertine}
\usepackage{tikz}
\usetikzlibrary{backgrounds, arrows, shapes, shapes.geometric, shapes.misc, math, positioning, calc}


\begin{document}
\begin{tikzpicture}
    \tikzset{rect/.style={
        rectangle,
        draw
    }}
    \tikzset{single/.style={
        ->,
        draw
    }}    
    \tikzset{double/.style={to path={%
        ($(\tikztostart)+(1pt,0)$) |- ($(\tikztotarget)+(0,-1pt)$)
        ($(\tikztostart)+(-1pt,0)$) |- ($(\tikztotarget)+(0,1pt)$)
    },
    ->,
    draw
    }}
    
    
    % Nodes
    \node[style=rect] (agent) at (0,0)   {Agent};
    \node[below=of agent, style=rect] (environment) {Environment};
    
    \path[style=single] (agent.east)  -| ++(1,0) node[style=rectangle] at ($(agent)!0.5!(environment)$) {$A_t$}  |-  (environment.east);
    
    \draw (environment.west) to[double] (agent.west);
\end{tikzpicture}
\end{document}

两个问题:

  1. 我如何将 $A_t$ 节点定位到路径的右侧,并使其与代理节点和环境节点之间完全垂直?
  2. 我怎样才能将路径向左移动,稍微移出节点,然后向上移动,然后再向右转到代理节点?

答案1

欢迎来到 TeX.SX!我认为您的代码可以从一系列小改进中受益。

首先,你不需要在环境\tikzset中添加多个宏tikzpicture。相反,只需将定义放入环境的可选参数中即可tikzpicture

二、TiZ 已经定义了double您可能想要在此处使用的样式(当然,您需要以不同的方式调用您的样式,以免覆盖此预定义样式)。我认为更粗的箭头更合适。

第三,我认为定义箭头的坐标的定位可以简化,也可以统一,如下面的代码所示。我text depth向文本节点添加了选项,使其高度相等。

最后,要将$A_t$节点精确地放置在右侧并将其垂直对齐到其他两个节点之间,您应该了解以下内容:使用|-(或-|)标记时,您可以使用pos=0.5来表示路径从垂直变为水平(或反之亦然)的坐标。此外,pos=0.25(和pos=0.75)表示从路径起点到此坐标的垂直(或水平)部分的中心。因此,使用此方法可以非常轻松地将节点放置$A_t$在您想要的位置。

\documentclass[border=0.2cm]{standalone}
\usepackage{microtype}
\usepackage{libertine}
\usepackage{tikz}
\usetikzlibrary{positioning, arrows.meta}

\begin{document}
\begin{tikzpicture}[
    >={Stealth[length=7pt]},
    rect/.style={
        rectangle,
        draw,
        text depth=0.1em
    },
    single arrow/.style={
        ->
    },
    double arrow/.style={
        double,
        double distance=1pt,
        ->
    }]
    % Nodes
    \node[rect] (agent) at (0,0) {Agent};
    \node[below=of agent, rect] (environment) {Environment};
    
    \draw[single arrow] (agent) -- ++(1.5,0) |- node[pos=0.25, right] {$A_t$} (environment);
    
    \draw[double arrow] (environment) -- ++(-1.5,0) |- (agent);
\end{tikzpicture}
\end{document}

在此处输入图片描述


由于您提供了预期结果的图像,我添加了此编辑建议。double箭头的绘制方式与两个箭头非常不同。 此外,使用您的方法,您将无法简单地将两个箭头尖端附加到两条线上,并且绘制两个角周围的路径也很复杂。 因此,我建议您简单地绘制两个箭头并相应地移动箭头路径的坐标(以下代码可能不是实现此目的的最简单方法,但它展示了如何移动和对齐坐标的不同方法,可能会对您有所帮助):

\documentclass[border=0.2cm]{standalone}
\usepackage{microtype}
\usepackage{libertine}
\usepackage{tikz}
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}[
    >=stealth,
    rect/.style={
        rectangle,
        draw,
        text depth=0.1em
    }]
    % Nodes
    \node[rect] (agent) at (0,0) {Agent};
    \node[below=of agent, rect] (environment) {Environment};
    
    \draw[->, thick] (agent) -- ++(2.5,0) |- 
        node[pos=0.25, right] {$A_t$} (environment);
    
    \coordinate (lower west) at ([shift={(-2cm, -2pt)}]environment.center);
    \coordinate (upper west) at ([shift={(-2cm, 2pt)}]environment.center);
    
    \draw[densely dotted] ([yshift=5pt]upper west) -- ([yshift=-5pt]lower west);
    
    \draw[->] (environment.west |- upper west) -- (upper west)
        node[midway, above] {$R_{t+1}$};
        
    \draw[->, thick] (environment.west |- lower west) -- (lower west)
        node[midway, below] {$S_{t+1}$};

    \draw[->] (upper west) -- ++({-0.5cm + 2pt},0) |- 
        node[pos=0.25, right] {$R_t$} ([yshift=-2pt]agent.west);
        
    \draw[->, thick] (lower west) -- ++({-0.5cm - 2pt},0) |- 
        node[pos=0.25, left] {$S_t$} ([yshift=2pt]agent.west);
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容