LaTeXを使用してグラフを描く
1. 概要
このチュートリアルでは、LaTeXを使用してグラフを描画する方法について説明します。
まず、グラフに使用できる主なLaTeXパッケージをリストし、それらの特定の利点を説明します。
次に、これらのパッケージで描画されたグラフの例と、それらのバリエーションについて説明します。
このチュートリアルの最後に、LaTeXドキュメントにグラフを実装できるようになります。
2. グラフの簡単な要約
2.1. グラフのコンポーネントとその表現
グラフは、頂点のセットとエッジのセットで構成されます。 エッジは有向または無向のいずれかであり、通常は2つの頂点を接続しますが、必ずしも区別する必要はありません。 ハイパーグラフの場合、エッジは3つ以上のエッジを接続することもできますが、ここでは扱いません。
頂点の標準表現は、円の画像で構成されています。
頂点にラベルがある場合、上記の例の番号1の場合のように、これは円の内側に入力されます。 また、画像内の任意の場所に重なり合わない方法で複数の頂点を配置することにより、複数の頂点を表すこともできます。
エッジの標準表現は、無向エッジの場合は線、有向エッジの場合は矢印に対応します。
2.2. グラフの典型的な表現
したがって、グラフを表す画像は、空のフィールド上の円のセットとそれらを結ぶ線または矢印のセットで構成されます。 さらに、グラフが加重グラフの場合、重みをエッジのラベルとして示すことができます。
そして最後に、グラフにループがある場合、頂点をそれ自体に接続するエッジとしてそれらを表すことができます。
これらは、複雑さのグラフを表すために必要なすべての要素です。 次のセクションでは、最初にグラフを描画するための関連パッケージを調べ、次にコードでのグラフの実装の例をいくつか見ていきます。
2.3. グラフの代替表現
ただし、グラフ表現がグラフを直感的に説明する唯一の方法ではないことも述べておく必要があります。 他の表現、特にエッジリスト、隣接リスト、または隣接行列も実際に普及しています。
場合によっては、グラフの描画画像よりも、人間の読者にとって有益な場合があります。 たとえば、26個の頂点と2つのエッジのみを持つ有向グラフは、正式な表記法で表すのが非常に簡単です。
ただし、その完全なグラフィック表現は非常に広大なスペースを占め、ほとんど情報がありません。 これは、使用しているグラフに少数のノードまたはエッジが含まれている場合、その画像を見てその構造を理解することが難しくなるためです。 インターネットノードを表すグラフなどの一部の広範なグラフは、非常に美しい一方で、人間には無意味なグラフィック表現を備えています。
このため、グラフに複数の頂点またはエッジが含まれている場合は、を描画しないようにする必要があります。 代わりに、隣接行列、エッジリスト、隣接リストなど、他のタイプの正式な表現を使用する必要があります。
3. Tikz
これで、LaTeXでグラフを描画するために使用できるパッケージについて説明できます。 一般に描画に使用される最も一般的なLaTeXパッケージは、TikZ です。これは、 PGF の上のレイヤーであり、構文を簡略化します。 TikZは、次のような特定のタスク専用のいくつかのライブラリが付属する強力なパッケージです。
- マインドマップの描画、概念的な関係を描くのに役立ちます
- 実体関連図。これは、知識グラフの表現に役立ちます。
- ブール代数での演算を表すのに役立つ論理回路の描画
また、私たちの目的に関連して、グラフの自動描画に使用できるgraphdrawingライブラリが含まれています。 TikZは、グラフの描画に使用する標準パッケージであり、コード化された例のほとんどに使用します。
3.1. 基本的なグラフとノード
TikZの図面は、tikzpicture環境に含まれています。 描画できる最も単純なグラフは、たとえば変数を含む円として表される、ラベルが付いた1つの頂点で構成されます。
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[main/.style = {draw, circle}]
\node[main] (1) {$x_1$};
\end{tikzpicture}
\end{document}
ここでのmainという言葉は、tikzpicture環境を導入するときに定義するスタイルを指します。 この場合、これを使用して、ノードの円の形を描くようにコンパイラーに指示します。
上記のコードで最も重要なコマンドは\nodeです。 その構文は次のとおりです。
\node[parameters] (nodeID) {nodeLabel};
このコマンドを繰り返し使用して、グラフに頂点を追加できます。
\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$};
角括弧の2番目のペアの間の用語によって、他のノードに対するノードの位置を定義できることに注意してください。 これを行うには、キーワード右、左、上、下、空白スペース、キーワードの順に使用します。 ofおよびそれらが参照するノードのラベル。 これは、後で画像のグラフを再配置する必要がある場合に特に便利です。 実際、絶対座標ではなく相対位置を操作することで、1つのアンカーノードを移動して他のすべてのノードを移動できます。
3.2. エッジの追加
\drawコマンドを使用してエッジを追加することもできます。
\draw[parameters] (fromWhere) -- (toWhere);
たとえば、ノード(2)と(4)の間の無向エッジに対応する線を描画する場合は、次のように記述できます。
\draw (2) -- (4);
代わりに、有向エッジに矢印を追加する場合は、パラメーター->を\drawコマンドに指定できます。
\draw[->] (1) -- (2);
3.3. 距離と幅
また、線が細すぎるように見え、有向エッジと無向エッジを区別するのが難しいことにも気付くでしょう。 パラメータthickをtikzpicture環境に渡すことで、グラフを読みやすくすることができます。
\begin{tikzpicture}[thick, main/.style = {draw, circle}]
...
\end{tikzpicture}
頂点が互いに近すぎるように見える場合は、パラメータノード距離を tikzpicture 環境に指定して、頂点をさらに広げることもできます。
\begin{tikzpicture}[node distance={15mm}, thick, main/.style = {draw, circle}]
...
\end{tikzpicture}
3.4. より挑戦的なエッジ
また、直線パスが他のエッジまたはノードと交差するいくつかのノードをエッジに接続することもできます。 ノード(1)と(5)を直線パスで接続しようとすると、次のようになります。
見栄えが良くありません。 代わりに、ノード2の外側と上からグラフをループしてから、グラフに向かって下降します。 幸いなことに、線の始点を宣言した後、パラメータloosenessを指定することでそれを行うことができます。 エッジをどこに配置するかをより明確にするために、角度outとinも指定します。これらは、それぞれ発信エッジと着信エッジの角度を示します。 :
\draw (1) to [out=135,in=90,looseness=1.5] (5);
3.5. ループ
同じ手法を使用して、緩い線の開始点と終了点の2倍の同じノードを示すことにより、グラフにループを描画できます。
\draw (1) to [out=180,in=270,looseness=5] (1);
3.6. 重み付きエッジを描画します
グラフが加重グラフの場合、 \drawコマンド内にファントムノードとして加重エッジを追加できます。
\draw[->] (6) -- node[midway, above right, sloped, pos=1] {+1} (4);
このコマンドを使用して、頂点(6)と(4)の中間、そしてエッジの中点の右上に非表示のノードを追加します。 ラベル{+1}は、グラフの重みを示します。 パラメータ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}
4. 神経網
グラフを生成するためのもう1つの便利なパッケージは、Neuronetworkです。 このパッケージは、その名前が示すように、ニューラルネットワーク、特にフィードフォワードニューラルネットワークのアーキテクチャを描くのに非常に役立ちます。
このパッケージは、レイヤーの構築とその操作を簡素化します。 これは、単一レイヤーのすべてのコマンドを1行に短縮することによって行われます。
その主な利点は、わずか数行のコードで完全なグラフをすばやく記述できることです。 代わりに、その主な欠点は、グラフの個々の特性のカスタマイズ性がほとんどないことにあります。
4.1. パッケージの基本
LaTeXパッケージNeuralnetworkでは、同じ名前の環境内でグラフを定義します。
\begin{neuralnetwork}
...
\end{neuralnetwork}
この環境内で、 \ inputlayer 、 \ hiddenlayer 、および \ outputlayer コマンドを使用して、最初のコマンドを参照するかどうかに応じて、それぞれレイヤーを追加できます。 、 hidden 、またはニューラルネットワークの最後の層。 構文は、3つのコマンドすべてで類似しています。
\inputlayer[count=howManyNodes, bias=trueOrFalse, nodeclass={classOfNode}] {}
パラメータcountは、特定のレイヤーのノード数を示します。 バイアスという用語は、代わりに、そのレイヤーのバイアスを個別の要素としてカウントする必要があるかどうかを示します。 その場合、リンクが確立されると、このバイアスは前のレイヤーに接続されません。 最後に、ノードのクラスは、事前定義されたクラス input node 、 hidden node 、または output node、、またはまた、カスタムクラスのいずれか。
4.2. ニューラルネットワークの描画
入力の3つの特徴、2つのニューロンとバイアス項を持つ隠れ層、および出力層の1つのニューロンで構成される単純なニューラルネットワークを描画できます。 これは、XOR分類用のニューラルネットワークの構造によく似ています。
\documentclass{article}
\usepackage{neuralnetwork}
\begin{document}
\begin{neuralnetwork}
\inputlayer[count=3, bias=false]{}
\hiddenlayer[count=2]{}
\outputlayer[count=1]{}
\end{neuralnetwork}
\end{document}
4.3. エッジとラベルの追加
\ linklayers コマンドを使用して、前のレイヤーに接続する各レイヤーを追跡することにより、各レイヤー間にエッジを追加することもできます。
...
\inputlayer[count=3, bias=false]{} \linklayers
\hiddenlayer[count=2]{} \linklayers
\outputlayer[count=1]{}
...
中間層のバイアス項を示す黄色のノードが入力層に接続されていないことに注意してください。 ノードにラベルを追加することもできますが、これには多少注意が必要です。 これを行う方法は、新しいLaTeXコマンドを定義し、それをパラメーターtextとしてレイヤーに渡すことです。
...
\newcommand{\x}[2]{$x_#2$}
\inputlayer[count=3, bias=false, text=\x]
...
適切なコマンドを作成することで、非表示レイヤーと出力レイヤーで同じ基準に従うこともできます。
...
\newcommand{\h}[2]{$h_#2$}
\newcommand{\y}[2]{$y_#2$}
...
\hiddenlayer[count=2, text=\h]{} \linklayers
\outputlayer[count=1, text=\y]{} \linklayers
...
隠れ層のバイアス項は、特定の命令を指定しなくても、文献で一般的であるように、自動的にのインデックスを取ります。
4.4. ウェイト
次のような式を使用して、エッジに重みを追加することもできます。 最初に新しいコマンドを定義してから、それをリンクのデフォルトのテキストに割り当てる必要があります。
\newcommand{\w}[4] {$w_{#2,#4}$}
\setdefaultlinklabel{\w}
ここで、#1は原点のレイヤー、#2は原点のノード、#3と#4はそれぞれ宛先のレイヤーとノードを示します。 非表示のレイヤーの重みは正常に見えますが、前のレイヤーの重みの一部が欠落していることに注意してください。
これは、他の重みによって自動的に書き換えられ、その結果、一部しか表示されないためです。 この問題に対処する唯一の方法は、すべてのリンクを個別に定義してから、適切なラベルを付けることです。 これを行うには、 \linklayersの代わりに\linkコマンドを使用します。
...
\inputlayer[count=3,bias=false, text=\x]{}
\hiddenlayer[count=2, text=\h]{}
\link[style={}, labelpos=near start, from layer=0, from node=1, to layer=1, to node=1]
...
パラメータlabelposは、原点のノードに向かってシフトするために使用するパラメータです。 この場合、ラベルはエッジによって想定されます。 これにより、エッジのラベル間のオーバーラップが回避されます。
4.5. 仕上げ
次に、ネストされた2つの \ foreach ループを使用してこの操作を繰り返すことができます。これにより、すべてのラベルを正しい読み取り可能な位置に配置できます。
\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]
}
}
これでネットワークが完成しました。 この完全なコードを使用して、LaTeXエディターで複製できます。
\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コードへの自動変換に関係する別のオプションもあります。 これは、他のプログラミング言語でグラフを描くことに慣れていて、LaTeXでグラフを描く方法をまだ学んでいる場合に特に便利です。
実際、別のエディターのグラフィック出力のLaTeXコードに自動変換するためのライブラリまたは拡張機能があります。
- Pythonでは、ライブラリ tikzplotlib のおかげで、matplotlibで作成されたグラフをLaTeXに変換できます。
- MatLabでは、matlab2tikzのスクリプトを使用して同様の操作を実行できます
- Blender 2.4では、種類2tikz を使用して、Blender曲線をLaTeXコードにエクスポートできます。
6. 結論
この記事では、LaTeXを使用してグラフを描画する方法を学習しました。