1. 概述

在本教程中,我们将学习如何使用 LaTeX 绘制图形。

我们会先介绍几个常用的 LaTeX 图形绘制包,并说明它们各自的优势。

接着,我们会通过具体示例展示如何使用这些包来绘制图形,并讨论其变体。

最后,你将能够熟练地在 LaTeX 文档中实现图形绘制。

2. 图形的基本概念回顾

2.1. 图形的组成及其表示方式

一个图 G(V, E) 包含一组顶点集合 V 和一组边集合 E。边可以是有向的无向的,通常连接两个顶点,但这两个顶点不一定是不同的。对于超图(Hypergraph),边可以连接多个顶点,但本文不涉及这部分内容。

标准的顶点表示通常是一个圆圈:

Rendered by QuickLaTeX.com

如果顶点有标签,通常会将其写在圆圈内部,如上面示例中的数字 1 所示。我们也可以通过合理布局多个顶点,使它们不会重叠地分布在图中:

Rendered by QuickLaTeX.com

边的标准表示是:无向边用直线表示,有向边用箭头表示:

Rendered by QuickLaTeX.com

2.2. 图形的典型表示方式

因此,一个图形图像通常由以下两部分组成:

  • 一组分布在空白背景上的圆圈(顶点)
  • 一组连接这些圆圈的线或箭头(边)

如果是加权图(Weighted Graph),我们还可以在边上标注权重值:

Rendered by QuickLaTeX.com

此外,如果图中包含自环(Loop),我们也可以用从顶点出发再回到该顶点的边来表示:

Rendered by QuickLaTeX.com

这些就是我们绘制任意复杂度的图所需的基本元素。接下来,我们将学习用于绘制图的 LaTeX 包,并通过代码示例来实现这些图形。

2.3. 图形的其他表示方式

不过,图形的图像表示并不是唯一直观的表示方法。还有其他一些常见表示方式,例如:

  • 边列表(Edge List)
  • 邻接表(Adjacency List)
  • 邻接矩阵(Adjacency Matrix)

在某些情况下,这些形式可能比图形图像更容易理解。例如,一个包含 26 个顶点 V = {A, B, ..., X, Y, Z}、仅有两个边 E = {(X, Y), (X, Z)} 的有向图,用形式化表示非常简洁:

G(V, \{(X, Y), (X,Z)\})

但如果用图形方式完整表示,会占用大量空间,而且信息密度低。当图中顶点或边的数量较多时,图像表示往往难以传达结构信息。

例如,互联网节点图的图形表示虽然美观,但对人类阅读者来说意义不大。因此,当图的规模较大时,应避免使用图像表示,而应优先使用邻接矩阵、边列表等更紧凑的形式。

\begin{matrix}  \framebox{A} \\ \framebox{B} \\ \vdots \\\framebox{X}\rightarrow\fbox{Y}\fbox{Z} \\ \framebox{Y} \\ \framebox{Z} \\\end{matrix}

3. TikZ

接下来我们介绍可用于在 LaTeX 中绘制图的包。最常用的图形绘制包是 TikZ,它基于 PGF 构建,简化了语法,功能强大。

TikZ 提供了多个库来支持不同任务,例如:

  • 绘制思维导图(Mindmaps)
  • 绘制实体关系图(ER Diagrams)
  • 绘制逻辑电路图(Logic Circuits)

对于我们来说,最相关的是它的 graphdrawing 库,可以用于自动绘制图结构。

我们将以 TikZ 为主,通过代码示例来展示如何绘制图。

3.1. 基本图形与节点

TikZ 的图形绘制是在 tikzpicture 环境中完成的。最简单的图是一个顶点,例如:

\documentclass{article} 
\usepackage{tikz} 
\begin{document} 
\begin{tikzpicture}[main/.style = {draw, circle}] 
\node[main] (1) {$x_1$}; 
\end{tikzpicture} 
\end{document}

渲染结果如下:

Rendered by QuickLaTeX.com

其中 main 是我们定义的样式,表示节点为圆形。

主要命令是 \node,其语法为:

\node[参数] (节点ID) {节点标签};

我们可以多次使用这个命令来添加更多节点:

\node[main] (2) [above right of=1] {$x_2$};
\node[main] (3) [below right of=1] {$x_3$}; 
\node[main] (4) [above right of=3] {$x_4$};
\node[main] (5) [above right of=4] {$x_5$}; 
\node[main] (6) [below right of=4] {$x_6$};

渲染结果如下:

Rendered by QuickLaTeX.com

注意:[above right of=1] 这样的参数表示相对位置。使用相对位置的好处是,我们可以只移动一个锚点节点,就能调整整个图的布局。

3.2. 添加边

我们可以使用 \draw 命令来添加边:

\draw[参数] (起点) -- (终点);

例如,添加无向边:

\draw (2) -- (4);

渲染结果如下:

Rendered by QuickLaTeX.com

添加有向边时,只需加上 -> 参数:

\draw[->] (1) -- (2);

渲染结果如下:

Rendered by QuickLaTeX.com

3.3. 调整边宽与节点间距

默认边线较细,难以区分有向与无向边。我们可以通过设置 thick 参数增强可读性:

\begin{tikzpicture}[thick, main/.style = {draw, circle}]

渲染结果如下:

Rendered by QuickLaTeX.com

如果节点太密集,可以设置 node distance 调整间距:

\begin{tikzpicture}[node distance={15mm}, thick, main/.style = {draw, circle}]

渲染结果如下:

Rendered by QuickLaTeX.com

3.4. 复杂边的绘制

有些边如果直接连接会与其他边或节点交叉。例如:

\draw (1) -- (5);

渲染结果如下:

Rendered by QuickLaTeX.com

我们希望边绕过节点 2,从外部连接。可以使用 to 命令并指定角度与松紧度:

\draw (1) to [out=135,in=90,looseness=1.5] (5);

渲染结果如下:

Rendered by QuickLaTeX.com

3.5. 自环边

绘制自环边的方式类似:

\draw (1) to [out=180,in=270,looseness=5] (1);

渲染结果如下:

Rendered by QuickLaTeX.com

3.6. 加权边

对于加权图,可以在边中插入标签:

\draw[->] (6) -- node[midway, above right, sloped, pos=1] {+1} (4);

渲染结果如下:

Rendered by QuickLaTeX.com

其中 node 表示插入一个不可见节点,midway 表示在边中间,above right 表示偏移方向,sloped 表示标签与边垂直,pos 控制偏移位置。

3.7. 完整图形示例

将以上所有命令组合起来,即可绘制一个完整的图:

\documentclass{article} 
\usepackage{tikz} 
\begin{document} 
\begin{tikzpicture}[node distance={15mm}, thick, main/.style = {draw, circle}] 
\node[main] (1) {$x_1$}; 
\node[main] (2) [above right of=1] {$x_2$}; 
\node[main] (3) [below right of=1] {$x_3$}; 
\node[main] (4) [above right of=3] {$x_4$}; 
\node[main] (5) [above right of=4] {$x_5$}; 
\node[main] (6) [below right of=4] {$x_6$}; 
\draw[->] (1) -- (2); 
\draw[->] (1) -- (3); 
\draw (1) to [out=135,in=90,looseness=1.5] (5); 
\draw (1) to [out=180,in=270,looseness=5] (1); 
\draw (2) -- (4); 
\draw (3) -- (4); 
\draw (5) -- (4); 
\draw[->] (5) to [out=315, in=315, looseness=2.5] (3); 
\draw[->] (6) -- node[midway, above right, sloped, pos=1] {+1} (4); 
\end{tikzpicture} 
\end{document}

渲染结果如下:

Rendered by QuickLaTeX.com

4. Neuralnetwork

另一个用于生成图的 LaTeX 包是 neuralnetwork,特别适合绘制神经网络架构,尤其是前馈神经网络(Feedforward Neural Networks)。

它的优势在于快速构建图结构,只需几行代码即可完成一个完整网络的绘制。但缺点是自定义能力较弱

4.1. 包的基本使用

neuralnetwork 包中,图结构是在 neuralnetwork 环境中定义的:

\begin{neuralnetwork}
...
\end{neuralnetwork}

我们可以使用以下命令添加层:

  • \inputlayer:输入层
  • \hiddenlayer:隐藏层
  • \outputlayer:输出层

语法如下:

\inputlayer[count=3, bias=false]{}
  • count:节点数量
  • bias:是否包含偏置项
  • text:节点标签格式

4.2. 绘制一个神经网络

例如,绘制一个包含 3 个输入节点、1 个隐藏层(2 个节点)、1 个输出节点的神经网络:

\documentclass{article} 
\usepackage{neuralnetwork} 
\begin{document} 
\begin{neuralnetwork} 
\inputlayer[count=3, bias=false]{} 
\hiddenlayer[count=2]{} 
\outputlayer[count=1]{} 
\end{neuralnetwork} 
\end{document}

渲染结果如下:

Rendered by QuickLaTeX.com

4.3. 添加边与标签

使用 \linklayers 命令连接相邻层:

\inputlayer[count=3, bias=false]{} \linklayers
\hiddenlayer[count=2]{} \linklayers
\outputlayer[count=1]{}

渲染结果如下:

Rendered by QuickLaTeX.com

我们可以通过定义命令来添加节点标签:

\newcommand{\x}[2]{$x_#2$}
\inputlayer[count=3, bias=false, text=\x]{}

渲染结果如下:

Rendered by QuickLaTeX.com

同样可以为隐藏层和输出层添加标签:

\newcommand{\h}[2]{$h_#2$}
\newcommand{\y}[2]{$y_#2$}
\hiddenlayer[count=2, text=\h]{} \linklayers
\outputlayer[count=1, text=\y]{} \linklayers

渲染结果如下:

Rendered by QuickLaTeX.com

4.4. 添加权重

可以定义一个命令来显示权重:

\newcommand{\w}[4] {$w_{#2,#4}$}
\setdefaultlinklabel{\w}

渲染结果如下:

Rendered by QuickLaTeX.com

如果某些权重未显示,可以使用 \link 命令手动指定:

\link[style={}, labelpos=near start, from layer=0, from node=1, to layer=1, to node=1]

渲染结果如下:

Rendered by QuickLaTeX.com

4.5. 完整神经网络示例

使用嵌套循环自动添加所有权重标签:

\foreach \n in {1,...,3}{ 
    \foreach \m in {1,2}{ 
        \link[style={}, labelpos=near start, from layer=0, from node=\n, to layer=1, to node=\m] 
    } 
}

最终完整代码如下:

\documentclass{article}
\usepackage{neuralnetwork}
\begin{document}
\begin{neuralnetwork}
\newcommand{\x}[2]{$x_#2$}
\newcommand{\y}[2]{$y_#2$}
\newcommand{\h}[2]{$h_#2$}
\newcommand{\w}[4] {$w_{#2,#4}$}
\setdefaultlinklabel{\w}
\inputlayer[count=3, bias=false, text=\x]
\hiddenlayer[count=2, text=\h] 
\foreach \n in {1,...,3}{
    \foreach \m in {1,2}{
        \link[style={}, labelpos=near start, from layer=0, from node=\n, to layer=1, to node=\m]
    }
}
\outputlayer[count=1, text=\y] \linklayers
\end{neuralnetwork}
\end{document}

5. 使用图形编辑器转换为 LaTeX

除了直接编写 LaTeX 代码,我们还可以使用图形编辑器绘制图形,然后将其导出为 LaTeX 代码。

以下是一些常用工具:

  • Python:使用 matplotlib + tikzplotlib 插件
  • MatLab:使用 matlab2tikz 插件
  • Blender 2.4:使用 blend2tikz 插件

这种方式特别适合熟悉其他图形工具但仍在学习 LaTeX 的用户。

6. 总结

在本教程中,我们学习了如何使用 LaTeX 绘制图形,重点介绍了 TikZ 和 neuralnetwork 两个包。

我们通过示例展示了如何绘制节点、边、加权边、自环边,并实现了完整的图和神经网络结构。

此外,我们还介绍了将图形编辑器输出转换为 LaTeX 的方法,方便快速生成图形代码。


原始标题:Draw a Graph Using LaTeX