LaTeX + 数値計算パッケージでフラクタル図形

はじめに

LTで発表することになったので再帰マクロを使ったフラクタル図形描画マクロを作ろうと思いました.

何を作ったのか

今回はフラクタル図形を描画できる再帰マクロを作りました.

フラクタル図形とは

幾何学の概念であり,図形の一部が全体の形と同じ形(=自己相似形)になっているような図形のことをいいます.

実装する

数値計算のパッケージを使った

気がついたらLTの準備期間が1週間しかなかったので, TeXオンリーではなくTeX+LaTeX+数値計算パッケージを使いました. 今回,実装する上で試したパッケージは以下の3つです.

  • FPパッケージ
  • calculatorパッケージ
  • PGFパッケージ

私が今回採用したのはPGFパッケージです. なぜこのパッケージを採用したのかを説明する為にも それぞれのパッケージのメリット,デメリットについて紹介していきます.

FPパッケージ

固定小数点演算ができるパッケージで,三角関数なども実装されているので 今回,フラクタル図形を生成するには実装上問題ないはずでした.しかし,以下のメリット,デメリットの為にあえなく断念しました.

  • TeXレジスタに依存しない巨大小数点の演算が可能
  • \FPevalで数式の解釈が可能
  • 演算が極めて遅い

前回,モンテカルロ積分を実装した時に使ったパッケージなので 今回も使おうと思いましたが再帰的に大量の計算を行う今回のケースには不向きでした.そもそもそこまで巨大な数を扱う予定もありません.

calculatorパッケージ

次に目を付けたのはこのパッケージです.このパッケージは固定小数点演算ができ,TeXレジスタに依存していて\pm 16383.99999の範囲の小数点のみ扱うので計算はFPパッケージよりも速いです.しかし,このパッケージも使うのは断念しました.

  • FPパッケージよりは計算が速い
  • 可読性が低い
    • マクロ名が全て大文字
    • 数式の評価ができない
    • 一つの演算に一つのマクロ

PGFパッケージ

今回使ったパッケージです.このパッケージも固定小数点演算ができます.採用した理由は以下の通りです.

  • 数式が解釈できる
  • 演算がFPパッケージより速い

PGFパッケージを使って描いたフラクタル図形を紹介します. 画像は実際に描画したPDFをjpgにしたものです.

円のフラクタル図形

図形はここを参考にしました. f:id:muscle_keisuke:20170422173321j:plain マクロのソースは以下のようになっていて再帰になっているのが分かります.

\newcounter{deep}
\def\circleR#1#2#3#4{{
  \pgfmathsetmacro{\xA}{#1}
  \pgfmathsetmacro{\yA}{#2}
  \pgfmathsetmacro{\R}{#3}
  \setcounter{deep}{#4}

  \draw[ultra thin] (\xA, \yA) circle (\R);

  \pgfmathsetmacro{\newR}{\R/2}

  \ifnum \value{deep}=1
  \else
    \circleR{\xA - \newR}{\yA}{\newR}{#4-1}
    \circleR{\xA + \newR}{\yA}{\newR}{#4-1}
  \fi
}}

コッホ曲線

f:id:muscle_keisuke:20170422173328j:plain

シェルピンスキーのギャスケット

f:id:muscle_keisuke:20170422173332j:plain

木も生やしてみた

f:id:muscle_keisuke:20170422180248j:plain 木はそのまま自己相似形にすると自然ではないので枝分かれの角度を乱数によって決めています. また,枝が分かれるほど線を細く描画するようにしています.

\def\Tree#1#2#3#4#5{{%
  \pgfmathsetmacro{\xA}{#1}
  \pgfmathsetmacro{\yA}{#2}
  \pgfmathsetmacro{\R}{#3}
  \pgfmathsetmacro{\Degree}{#4}
  \setcounter{deep}{#5}
  \setlength{\treeBold}{\value{deep} pt}

  \pgfmathsetmacro{\xB}{\xA - \R*cos(\Degree)}
  \pgfmathsetmacro{\yB}{\yA + \R*sin(\Degree)}
  \draw[line width=\treeBold] (\xA, \yA) -- (\xB, \yB);
  \ifnum \value{deep}=1
  \else
    \pgfmathsetmacro{\newR}{0.8*\R}
    \pgfmathrandominteger{\a}{0}{60}
    \pgfmathsetmacro{\newAngleLeft}{\Degree+\a}
    \pgfmathrandominteger{\a}{0}{60}
    \pgfmathsetmacro{\newAngleRight}{\Degree-\a}
    \Tree{\xB}{\yB}{\newR}{\newAngleLeft}{#5-1}
    \Tree{\xB}{\yB}{\newR}{\newAngleRight}{#5-1}
  \fi
}}

最後に

今回,作成したフラクタル図形のソースは以下に載せておきます.

フラクタル図形を描画するfractal.sty

LaTeX+TikZでモンテカルロ積分の可視化

この記事は

TeX & LaTeX Advent Calendar 2016 - Adventar

の13日目の記事です.

はじめに

LaTeXモンテカルロ積分を行うプログラムを作りました.Tikzで可視化もしました.

何を作ったのか

モンテカルロ積分によって円周率の近似値を求めるプログラムです. 左にモンテカルロ積分を可視化した図,右にプロットした点の数や求まった円周率の近似解を表示するプログラムです.

モンテカルロ積分について

モンテカルロ積分

モンテカルロ積分とはモンテカルロ法によって定積分の近似値を求めるアルゴリズムです. モンテカルロ法は疑似乱数を用いてシミュレーションや数値計算を行う手法の総称です. つまりモンテカルロ積分は疑似乱数を用いて定積分の近似値を求めるアルゴリズムです.

モンテカルロ積分で円周率を求めるには

積分値に{\pi}が含まれるような関数の積分値の近似値を求めます. 今回は以下の定積分を解いて円周率を解きます.

{ \displaystyle
\int_0^1 \sqrt{1 - x^2}
}

この定積分の解は

{ \displaystyle
\int_0^1 \sqrt{1 - x^2} = \frac{\pi}{4}
}

ですので定積分の近似解を4倍すれば円周率の近似値が得られそうです.

{ \displaystyle
\int_0^1 4\sqrt{1 - x^2} = \pi
}

モンテカルロ積分の手順

今回の関数は { \displaystyle
\sqrt{1 - x^2}
}積分を0から1まで求めるので次のようなイメージになります. f:id:muscle_keisuke:20161205153744p:plain

この内部の面積を{S}とします.

この関数に囲まれた部分の面積{S}を求めます.次にこの正方形内部にランダムに点を打ちます. 次の図はプロット点数1000で描画した時のイメージです.青の点が内部の点,赤の点が外部の点です. f:id:muscle_keisuke:20161205155637p:plain

全体の点数と青の点数の比と正方形の面積と求めたい面積の比が近似することを利用して比の方程式で{S}の近似値を求めます.
{全体の点数 : 青の点数 \approx 正方形の面積 : S}
{1000 : 青の点数 \approx 1 : S}
{S \approx \frac{青の点数}{1000}}
{S}の本当の値は{\frac{\pi}{4}}なので円周率の近似値は
{\pi \approx 4\frac{青の点数}{1000}} となります.

TeX+TikZでモンテカルロ積分の実装

変数やマクロを定義する

積分範囲はTeXのマクロに定義し,赤青の点数などカウントが必要なものはLaTeXの変数に代入してしまいます.

\def\startpoint{0}
\def\endpoint{1}

\newcounter{redplot}
\newcounter{blueplot}
\setcounter{redplot}{0}
\setcounter{blueplot}{0}

プロット点数は標準入力で

プロット点数は入力できるようにしました.

\newcount\input

\message{プロット点数を入力してください}
\read-1 to \input

正方形や関数を描く

Tikzで正方形や関数を描画します.

% 枠を描画
\draw (\startpoint,\startpoint) rectangle (\endpoint,\endpoint);
% 関数を描画
\draw plot[domain=\startpoint:\endpoint,samples=100] (\x,{func(\x)});

これで準備は整いました.後は点をプロットして円周率の近似値を求めます.

fpパッケージを使いTeXで固定小数点演算を行う

0から1の積分なのでランダムにプロットする点は必ず小数になります. しかし,TeXは標準で四則演算くらいはできますが小数を扱うことができません.なので fpパッケージと呼ばれるTeXで固定小数演算を行うパッケージを使います. 私の実行環境であるTeXLive2016では標準で入っていました. fpは小数演算の四則演算だけでなく指数計算や対数計算など様々な計算をすることが可能です. 詳しくは以下の方の記事が分かりやすいです.

天地有情 [LaTeX] fp --- 固定小数点数演算

ランダムに点をプロットする

用意できたら点をランダムにプロットしていきます. fpパッケージには乱数を発生するマクロもあります. まずはプロットする点をランダムに決めていきます.

% 今日,0時から何分経過したかでシードを決定
\FPseed = \time
\begin{document}
.
.
.
% ランダムにx座標を決める
\FPrandom{\randomX}
% f(randomX)を求める
\FPpow{\randomFuncX}{\randomX}{2} % randomX^2
\FPsub{\randomFuncX}{1}{\randomFuncX} % 1 - randomX^2
\FProot{\randomFuncX}{\randomFuncX}{2} % √1 - randomX^2
% randomXをfp以外で評価できる形にする
\FPeval\plotX{\randomX}
% f(randomX)をfp以外で評価できる形にする
\FPeval\evalX{\randomFuncX}
% ランダムにy座標を決める
\FPrandom{\randomY}
% randomYをfp以外で評価できる形にする
\FPeval\plotY{\randomY}

本当は以下のようにも書けるのですがオーバーフローを引き起こすので上のような遠回りをしています.

\FPeval\plotX{random()}
\FPeval\evalX{root(1 - \plotX^2,2)}
\FPeval\plotY{random()}

点が関数の内側かどうかを判定する

ある点(X, Y)が関数の内側にあるかどうかは以下の不等式で判定可能です.
{f(X) > Y}
これをTikZの条件式で判定します.

% 関数の求める範囲の外側の場合は赤,内側の場合は青で点をプロット
\pgfmathparse{\evalX < \plotY ? "red" : "blue"}
% blueかredを\colorに定義
\edef\color{\pgfmathresult}

次に定義した\colorを元に青の点と赤の点をカウントします.

% 赤の点と青の点を数える
\ifthenelse{\equal{\color}{red}}{\stepcounter{redplot}}{\stepcounter{blueplot}}

点をプロット

Tikzのコマンドで点をプロットします.

% 点をプロットする
\filldraw[fill=\color, ultra thin] (\plotX, \plotY) circle [radius=0.01];

入力分ループを回す

それではここまでの処理をTikZのforechで回していきます.

\foreach \i in {1,...,\input}
{
      % ランダムにx座標を決める
      \FPrandom{\randomX}
      \FPpow{\randomFuncX}{\randomX}{2}
      \FPsub{\randomFuncX}{1}{\randomFuncX}
      \FProot{\randomFuncX}{\randomFuncX}{2}
      \FPeval\plotX{\randomX}
      \FPeval\evalX{\randomFuncX}
      % ランダムにy座標を決める
      \FPrandom{\randomY}
      \FPeval\plotY{\randomY}
      % 関数の求める範囲の外側の場合は赤,内側の場合は青で点をプロット
      \pgfmathparse{\plotY > \evalX ? "blue" : "red"}
      \edef\color{\pgfmathresult}
      % 赤の点と青の点を数える
      \ifthenelse{\equal{\color}{red}}{\stepcounter{redplot}}{\stepcounter{blueplot}}
      % 点をプロットする
      \filldraw[fill=\color, ultra thin] (\plotX, \plotY) circle [radius=0.01];
}

コンパイル

それではコンパイルしていきます.私の環境ではplatex+dvipdfmxでコンパイルしています. コンパイルしたら「プロット点数を入力してください」と表示されるので 1000とか入力します. そうするとコンパイルされてdviが出てくるのでそれもpdfに変換して表示してみると 以下のような図が出ると思います.

f:id:muscle_keisuke:20161205155637p:plain

近似値なども表示する

プロット点数や近似値も表示させます. 全体の面積を求めます.

% 枠内全体の面積を変数に代入
% 四捨五入して整数にしている
\FPeval\overallS{round((\endpoint - \startpoint)^2,0)}

比の方程式を解いて,4倍して円周率の近似値を求めます. 小数点以下が多いので第9位まで丸めます.

%\arabic{blueplot} ... 青の点数
%\overallS ... 正方形の面積
%\input ... 全体のプロット点数
\FPeval\result{round(4 * \arabic{blueplot} * \overallS / \input,9)}

さて,それでは全て表示させます.

\begin{tikzpicture}
    \draw (7,5) node {全体の点数 = \input};
    \draw (7,4) node {青い点数 = \arabic{blueplot}};
    \draw (7,3) node {赤い点数 = \arabic{redplot}};
    \draw (7,2) node {全体的な面積 = \overallS};
    \draw (7,1) node {$\displaystyle\int^1_0 4\sqrt{1-x^2}$ = \result};
\end{tikzpicture}

図の方は一辺が1で原寸大ですので近似値などの表示に対して図が小さすぎます. なので図と文字のtikzpicture環境を分け図の方をscalebox環境で拡大しています.

プロット点数1000でやってみると次のような図が表示されます. f:id:muscle_keisuke:20161205184110p:plain

様々なプロット点数でやってみました. f:id:muscle_keisuke:20161206020732p:plain f:id:muscle_keisuke:20161206020738p:plain f:id:muscle_keisuke:20161206020742p:plain f:id:muscle_keisuke:20161206020746p:plain

それにしても精度が悪いですね.この辺は要改善ですね.

ソースコード

ソースコードgithubに上がっているので全ソースを見たい人は 参照してください.

github.com

TeXで強制改行コマンドの後に角括弧をつけるとエラーを吐く理由と対策について

はじめに

はまった上にこれについて書いてある記事なども見つからなかったので備忘録的に残します.

強制改行(\\)の後に角括弧([])を使うと謎のエラーが

LaTeXを書いている時に

[1] http://hoge.hoge.com \\
[2] http://fuga.fuga.com

の部分でエラーが発生しました. しかも,エラーの内容は???でした.

! Illegal unit of measure (pt inserted).

このエラーはTeXで定義されていない寸法単位が使われている時に出るエラーです.
寸法単位なんかどこにも出てきていないしエラーとは関係なさそうに見えます.
この症状は環境が異なっても起こりました.自分は以下の環境で試しました.

  • TeXLive 2015
    • e-pTeX + dvipdfmx
    • LuaTeX

問題は強制改行(\\)のオプション引数

強制改行もTeXのマクロの一つです.よく調べてみると強制改行はオプション引数を取るみたいです.

\\[10pt]

などとすると行間を10pt空けて改行してくれるみたいです.
つまり強制改行のオプション引数は行間の幅を指定する為のもので
強制改行後の角括弧はオプション引数としての括弧として認識されてしまったということです.
角括弧の中の数字には寸法単位がついていない為先述したような謎のエラーが出たという訳です.

なぜ,強制改行(\\)と角括弧([])は違う行にあるのにこのような症状が出るのか

これにはTeX組版としてのルールが絡んできます. 今回影響したTeXの性質として次のような性質があります.

  • (空行以外の)改行文字は空白文字になる
  • 行頭と行末にある空白文字・タブは全て無視される

これにより強制改行と角括弧の間の改行文字が無視されたという訳です.

解決策

これを解決するには強制改行の後に\relaxというコマンドを入れます. つまり以下のようにすれば解決します.

[1] http://hoge.hoge.com \\ \relax
[2] http://fuga.fuga.com

\relaxは「なにもしない」コマンドです.しかし,これが大いに役に立ちます.
\relaxはオプション引数を取らないので角括弧がオプション引数としての括弧として認識されないからです.

最後に

今回はこうなる理由が知りたかったので合わせて解決も書きましたが
本当は強制改行は極力使わない方が良いと思います.
今回の解決策を施したところで1行目が段落の始まりで字下げを行っているので2行目と行頭が揃っていません.
字下げを行わないコマンドもありますがそれならverbatim環境などを使った方がまだいいと思います.
一番良いのは参考文献の記述を人力でやるのではなくthebibliography環境などを使うことだと思います.

LaTeXの表を生成できるサイトTables Generator

はじめに

LaTeXで表を作成するのはとても面倒くさいですよね.
表の部分だけExcelを使いたいと思う人も多いのではないでしょうか.
そこでこんなサイトを見つけました.

www.tablesgenerator.com

このサイトはマウスで作成した表からLaTeXのコードを生成するWebアプリです.

使ってみる

下図にある赤枠の表を編集して青枠の「Generate」ボタンを押すと緑枠内にLaTeXのコードを生成してくれます.
試しに生成されたコードをコピペしてPDFを生成してみます.

f:id:muscle_keisuke:20160702145552p:plain

赤枠の表と同じような表ができあがりました.

f:id:muscle_keisuke:20160702151903j:plain

表を作ってみる

次にサンプル以外の表を生成してみます. 今回は次の表を作っていきます.

f:id:muscle_keisuke:20160702162503j:plain

最初にサンプルの表を消します.

f:id:muscle_keisuke:20160702153425p:plain

次に作る表のサイズを決めます.今回は3x3の表を作ります.

f:id:muscle_keisuke:20160702153145p:plain

そうすると,プレビューに空の表ができたと思います.これを編集していきます. 1行1列目から文字を入れていきます.表の編集したいマスをダブルクリックすると文字が打てます.

f:id:muscle_keisuke:20160702162516p:plain

他のマスも同様に編集していきます.
次にマウスを表の上でドラッグしてマスを全選択します.
そして,図のマウスが指しているボタンを押すとすべてのマスに罫線が引かれます.

f:id:muscle_keisuke:20160702162527p:plain

次に各マス内の文字列をセンタリングします.
全選択はされたままなので図のマウスで指しているボタンを押すと
全てのマス内の文字列がセンタリングされます.

f:id:muscle_keisuke:20160702162536p:plain

これで完成です.後は「Generate」ボタンを押すとLaTeXのコードを吐き出してくれます.
以下のようなコードができれば完成です.

\begin{table}[]
\centering
\caption{My caption}
\label{my-label}
\begin{tabular}{|c|c|c|}
\hline&&\\ \hline&&\\ \hline&&\\ \hline
\end{tabular}
\end{table}

キャプションは自動で付きますので扱いは自由にしてください.

色をつけたり,更に複雑な表も作れる

この他にも更に複雑な表も作れます.
直感で操作できますのでいろいろ試してみてください.
LaTeXでは色をつけたりする際には追加のスタイルファイルが必要ですが,
Tables Generatorではコードを生成する時に必要なパッケージをコメントで案内してくれます.

f:id:muscle_keisuke:20160702163847p:plain

Excelで作って読み込むこともできる

ExcelLibreOffice,CSVなど,別のデータから表を読み出すこともできます.

f:id:muscle_keisuke:20160702164602p:plain

  • Import CSV file... CSVファイルを読み表を生成
  • Paste table data... Office系のソフトで作った表をコピペすることで表を生成
  • From LaTeX code... LaTeXソースコードから表を生成
  • Save table... 編集途中の表を保存する
  • Load table... 保存した編集途中の表を読み込む

また,ここでは紹介しませんでしたがLaTeXだけでなく,
HTMLやMarkdownのコードも生成することができます.

まとめ

マスが多い表ほど,このサイトは重宝すると思います.
時間的コストはOfficeで作るのとではそれほど変わらないと思います.

LaTeXで載せたプログラムソースがページを跨ぐ場合の対処法について

はじめに

私はとある大学に通う情報系の学生なのですが,レポートをLaTeXで書くことが多々あります.
情報系の演習ではレポートにプログラムのソースコードを載せることがあります.
しかし,ソースコードが長くて1ページに収まりきらないこともよくあります.
その時,LaTeXでははみ出した部分のソースを正常に表示してくれないことがあります.
はみ出した部分は自動的に改ページしてくれないのです.
そんな時の対処法をここでは環境,コマンド別に紹介していきます.

今回対象となる環境,コマンド

  • itembox + verbatim
  • listing
  • minted

    itembox + verbatim

    私が1年生の時に受講していた演習においてレポートにソースを載せる際はこの方法でした.
    最初からある環境のみを使用しているので簡単です.
    しかし,ソースがページを跨ぐ場合ははみ出てしまい,次のページに表示してくれません.
    他の学生は一旦itemboxを切って,次のページで新しいitemboxで囲んだりしたりしてました.
    実はあるパッケージを導入すればページを跨いだ場合でも自動的にitemboxを改ページしてくれるのです.

    breakitembox

    itemboxに代わる,breakitemboxという環境を使えばページを跨いだ場合でもきちんと対処してくれます.

    導入方法

  • 以下のパッケージを全てダウンロードする.
    • itembkbx.sty
    • itembbox.sty
    • emathC.sty
    • jquote.sty
    • eclbkbox.sty
  • \usepackage{itembkbx}で読み込む.
  • 使う

パッケージはCTANにはないのでgithubからダウンロードしましょう.
github.com
パッケージを全てダウンロードしたらそれらを全て読み込める状態にします.

texファイルと同じディレクトリに置く

breakitemboxを使いたいtexソースと同じディレクトリに先程ダウンロードしたパッケージを置きます.

$TEXMFHOMEに置く

$TEXMFHOMEの場所を把握します.

kpsewhich -var-value $TEXMFHOME

パスが返ってくるのでその中にtexディレクトリを作ります. デフォルトでは以下のようになっていると思います.

~/texmf/tex

その直下にパッケージを置きます. 置いたら次のコマンドで更新します.

mktexlsr [$TEMFHOMEが設定されているパス] # ex) mktexlsr ~/texmf

使い方

使い方はitemboxとさほど変わりません.

\begin{breakitembox}[l]{見出し}
    \begin{verbatim}
        #include<stdio.h>
        int main(void){
            printf(Hello World!\n);
            return 0;
        }
    \end{verbatim}
\end{breakitembox}

このようにすると以下のような結果が得られます. f:id:muscle_keisuke:20160211170919p:plain
行数が多いプログラムはファイルから読み込みましょう.
verbatimパッケージを読み込んでverbatiminputコマンドを使います.

\begin{breakitembox}[l]{見出し}
   \verbatiminput{test.c}
\end{breakitembox}

また,ページを跨ぐ場合にはこんな感じになります. f:id:muscle_keisuke:20160211173512p:plain f:id:muscle_keisuke:20160211173508p:plain

listing

listingはbreakitemboxとは違いソースコードを載せる専用のパッケージです. こちらはデフォルトでページを跨いだ時の処理をしてくれる便利なパッケージです.
使用するパッケージはlistings,jlistingの2つです.
listingsはtexlive2015の時点では最初から入っているようなのでダウンロードはする必要ありません.
ない人はCTANからダウンロードしましょう.
CTAN: Package listings
jlistingはlistingsに日本語対応させる為のパッケージなので入れておきましょう.こちらからダウンロードします.
Listings - MyTeXpert
ダウンロードしたら$TEXMFHOMEに入れて使ってみます.

使い方

まずはプリアンブル部にlistingの設定を書きます.

今回はlisting中心の記事ではないので以下をコピペして使ってください.

\usepackage{listings,jlisting}
\usepackage{color}
\lstset{%
  language={C},
  basicstyle={\small},%
  identifierstyle={\small},%
  commentstyle={\small\itshape\color[rgb]{0,0.5,0}},%
  keywordstyle={\small\bfseries\color[rgb]{0,0,1}},%
  ndkeywordstyle={\small},%
  stringstyle={\small\ttfamily\color[rgb]{1,0,1}},
  frame={tb},
  breaklines=true,
  columns=[l]{fullflexible},%
  numbers=left,%
  xrightmargin=0zw,%
  xleftmargin=3zw,%
  numberstyle={\scriptsize},%
  stepnumber=1,
  numbersep=1zw,%
  lineskip=-0.5ex%
}

それでは実際に使っていきます.

\begin{lstlisting}[caption=test,label=test]
   #include<stdio.h>
   int main(void){
       printf("Hello World!\n");
       return 0;
   }
\end{lstlisting}

このように出力されます.
f:id:muscle_keisuke:20160211184701p:plain
ページをまたいでも大丈夫です. f:id:muscle_keisuke:20160211185216p:plain
ソースコードをファイルから読む場合は以下のようにしましょう.

\lstinputlisting[caption=aaa,label=aaa]{test.c}

minted

このパッケージもまたソースコードを載せるためのパッケージです.
導入方法は過去の記事にあるのでそちらを参考にしてください.
muscle-keisuke.hatenablog.com
mintedもlisting同様ページを跨いだ時に適切な処理をしてくれます.

\begin{minted}{c}
   #include<stdio.h>
   int main(void){
       printf("Hello World!\n");
       return 0;
   }
\end{minted}

出力は以下の通りです.
f:id:muscle_keisuke:20160211194141p:plain
ページを跨ぐ時でもこのように適切に処理してくれます.
f:id:muscle_keisuke:20160211193806p:plain

注意点

mintedは確かにデフォルトでページを跨ぐ処理をやってくれるのですが,ある条件下ではそれが働かなくなります.それは
- キャプションをつけるためにlisting環境を使った時,
- ソースコードを載せる部分の背景色を指定した時
です.
このいずれかの条件が入っている時出力は次のようになります.
f:id:muscle_keisuke:20160211205932p:plain
ページ末尾にあるページ番号を超えてコードが出力されているのが分かります.
これを防ぐために次の環境,コマンドを使います.
- mdframed ...背景色が使えない代わりの枠組み
- captionof ...listing環境が使えない -> キャプションを付加できない よってその代わり
mdframed環境はmdframedパッケージで,captionofコマンドはcaptionパッケージで読み込みます.どちらもtexlive2015には標準で入っているはずですが,ない場合はCTANから
CTAN: Package mdframed
CTAN: Package caption
使い方は以下の通りです.

\definecolor{bg}{rgb}{0.95,0.95,0.95}
\begin{mdframed}[
    backgroundcolor=bg,
    topline=false,
    bottomline=false,
    leftline=false,
    rightline=false]
    \begin{minted}{c}
        #include<stdio.h>
        int main(void){
            printf("Hello World!\n");
            return 0;
        }
    \end{minted}
\end{mdframed}
\captionof{listing}{テストキャプション}

最初の行でdefinecolorコマンドを使っていますが,これは背景色を定義しています.definecolorコマンドはcolorパッケージの中ですので読み込むのを忘れずにしてください.
minted環境をmdframed環境で囲んでください.
mdframed環境のオプション引数ですが,
backgroundcolor=定義したもしくはデフォルトで定義されている色
で背景色を設定できます.
その後の引数は単純にmdframedの枠線を出力しない為の設定です.
(mintedでも枠線を定義できるので重複する)
下から二番目のところでcaptionofコマンドを使ってキャプションを設定しています.第二引数にキャプションの文を書きます.
第一引数のlistingという部分はキャプションの種類です.主に使うものを以下にまとめます.
- listing ...ソースコードなどを載せる時のキャプション
- figure ...グラフや図を載せる時のキャプション
- table ...表を載せる時のキャプション
という感じです.
captionofコマンドではなく通常のcaptionコマンドでつけたキャプションとの番号のずれはなくそこらへんはうまくやってくれます.
実行すると以下のように出力されます.
f:id:muscle_keisuke:20160211212414p:plain
ページを跨いだ場合でも大丈夫です.
f:id:muscle_keisuke:20160211222351p:plain

まとめ

itembox+verbatimを使って長いソースコードをぶつ切りにしてた人は
breakitembox+verbatiminputを使いましょう.
また,listingやmintedを使えばデフォルトでページを跨ぐ処理を適切に行います.
ただし,mintedでページを跨がない場合はmdframedとcaptionofを駆使して解決しましょう.

連立方程式を一番美しく書けるempheq

empheqとは?

  • empheqは連立方程式を表現するためのスタイルファイル
  • 特殊な記号を使ってもその通りに表示することが可能
  • 他にもオプションがたくさんある
  • 少なくとも自分の実行環境であるTexLive2014では標準で入っている
  • ない人はCTANなどからダウンロードしてください

    他のスタイルファイルとの違い

  • 連立方程式を表現するスタイルファイルはarray,cases,empheqなどがある

    array

    array環境は式を2段組にして1つの式として扱います.元々は連立方程式を扱うための環境ではありません. array環境で連立方程式は次のように表現します.

\begin{align}
\left\{
\begin{array}{ll}
f(x) &= x^2+3x+1 \\
f'(x) &= 2x+3
\end{array}
\right.
\end{align}

align環境を使っているのでamsmathパッケージを入れる必要があります. f:id:muscle_keisuke:20151123143909p:plain ゴリ押し感が半端ないですね.\left{で左の大きい括弧を表現していますが右に括弧はいらないので\right.とやって無理やり消しています. 数式同士の間隔も狭いです.

cases

cases環境は同名で2つあります.

casesパッケージのnumcasesとsubnumcases

式番号の付け方でnumcasesとsubnumcasesは違います. numcasesは連立してる式の一つ一つに(1),(2),(3)...
subnumcasesは(1a),(1b),(1c)...
と付けます.他は特に変わりません.なのでnumcases環境を基に説明していきます. numcases環境は引数を1つ取ります.その引数に指定した数式が連立方程式の左辺に来ます.しかし,これには問題があります.
この引数は省略できないことです.なので左辺に式が必要無い時は次のように記述する必要があります.

\begin{numcases}
{}
f(x)=x^2+3x+1 \\
f'(x)=2x+3
\end{numcases}

caseパッケージを入れる必要があります. その他の問題点もあります.それは数式を任意の位置に揃える時に発生します.連立方程式に限らずalign環境やeqnarray環境(非推奨)を使って複数の数式を並べるとき&をつけることによって数式の位置を揃えることが出来ました.numcases環境を使って数式を揃える時も同じなのですが, & を使った後に数式モードが解除されるという問題点があります.なので&を記述した後はまた$$で挟んで数式モードに戻る必要があります.

\begin{numcases}
{}
f(x)&=$x^2+3x+1$ \\
f'(x)&=$2x+3x+1$
\end{numcases}

f:id:muscle_keisuke:20151123144419p:plain

amsmathパッケージのcases環境

arrayやnumcasesよりもいい環境なのがcases環境です.式同士の間隔も適切で左辺に式を持ってくるのも簡単です.また,式の位置を揃える時も変なことになりません.次のように記述します.

\begin{align}
\begin{cases}
f(x)&=x^2+3x+1 \\
f'(x)&=2x+3
\end{cases}
\end{align}

amsmathパッケージをいれる必要があります. f:id:muscle_keisuke:20151123144738p:plain

共通の問題点

cases環境はarray環境やnumcases環境のデメリットを完全になくしています.しかし,これらの環境全てに共通して起こっている問題点があります.それは大型の数式がインラインモードでしか入らないことです(numcasesはディスプレイモードになるが&を使った後はインラインモードにしかならない).それらの問題点を全て克服したのがempheq環境です.今のところ問題点は見つかっていません.

empheq

書き方は今までの環境と少し違います.次のように記述します.

\begin{empheq}[left=\empheqlbrace]{align}
\f(x) &= x^2+3x+1 \\
\f'(x) &= 2x+3
\end{empheq}

empheqパッケージを入れる必要があります.

括弧の種類を変える

empheqには多種のオプションがあります.まず,括弧の種類を変えることができます.

コマンド 括弧の種類
\empheqlbrace {
\empheqrbrace }
\empheqlbrack [
\empheqrbrack ]
\empheqlangle <
\empheqrangle >
\empheqlparen (
\empheqrparen )
\empheqlvert |
\empheqrvert |
\empheqlVert ||
\empheqrVert ||

オプション([]内)で上記のコマンドのいずれかを指定します.左に括弧を付けたい場合はleft=hogehogeといった具合です. 連立方程式の場合は{が普通ですので[left=\empheqlbrace]と指定します.右に括弧を付けたい場合はleft=の部分をright=にするだけです.

数式を2列以上にする

連立方程式ですので数式を2行以上にできるのは当たり前ですがempheqでは数式を2列以上にできます.これは例えば条件によって式が別れる時の条件式などに使えます.以下のような例です. f:id:muscle_keisuke:20151123145150p:plain このように数式を2列以上にする場合はempheqの引数であるalignをalignat=列数とします.そして列の分かれ目で\quadコマンドを使うことで次の列を記述できます.上の画像の式は次のように書きます.

\begin{empheq}[left={|x|=\empheqlbrace}]{alignat=2}
x & \quad (x\geq0) \\
-x & \quad (otherwise)
\end{empheq}
式番号を番号以外にする

矛盾しているように聞こえますがこれは式番号に使われる(1),(2),(3)などを(*),(※)とかに変更できるということです. 次のように記述します.

\begin{empheq}[left={|x|=\empheqlbrace}]{alignat=2}
x & \quad (x\geq0) \tag{*} \\
-x & \quad (otherwise) \tag{}
\end{empheq}

ちなみに式番号を省略したい場合は引数のalignやalignat=2の部分をalignやalignat=2とすれば省略できます. align単体で使う時と一緒ですね.

式をボックスで囲む

これは使うことあるのかわからないですが一応紹介しておきます. left=やright=を指定するオプション内でbox=hogehogeとすることで任意のボックスで式を囲むことができます.

\begin{empheq}[box=\fbox,left={|x|=\empheqlbrace}]{alignat=2}
x & \quad (x\geq0) \tag{*} \\
-x & \quad (otherwise) \tag{}
\end{empheq}

\fboxで角ばったボックスで囲めます. 左辺や左括弧を囲みたくない場合はbox=の部分をinnerbox=とします. 自分で定義したボックスで囲むことも可能です.

\definecolor{myblue}{rgb}{.8, .8, 1}
\newcommand*\mybluebox[1]{%
\colorbox{myblue}{\hspace{1em}#1\hspace{1em}}}
\begin{empheq}[box=\mybluebox,left={|x|=\empheqlbrace}]{alignat=2}
x & \quad (x\geq0) \tag{*} \\
-x & \quad (otherwise) \tag{}
\end{empheq}

f:id:muscle_keisuke:20151123145630p:plain

比較

今まで紹介した環境を比較してみます.

f:id:muscle_keisuke:20151123213849p:plain

ソースコードの貼り付けができるmintedをpLaTeXで使ってみた

mintedとは

導入方法

  • Pygmentsのインストール
  • minted.styの導入
  • 使う

     Pygmentsのインストール

    Pygmentsが入っていない場合は以下のコマンドでインストールします。

sudo apt-get install python-pygments

 minted.styの導入

Pygmentsが入りましたら次にminted.styをダウンロードします。以下のサイトからダウンロードしてください。
CTAN: Package minted
下の"Down­load the con­tents of this pack­age in one zip archive"からダウンロードできます。 ダウンロードしたらダウンロード先のディレクトリまで進み、ファイルの解凍を行います。 解凍したディレクトリに入りmakeコマンドを実行してください。 実行が終わりますとディレクトリ内にminted.styというファイルがありますので。texmfの中に入れるなりして導入してください。

使う

ここまで来たら後は必要なことを記述して使うだけです。 記述の例はTeXLive2014と2015で違いますので気をつけてください。 mintedを使うTeXファイルの中で次の命令をプリアンブル部に記述します。

TeXLive2014の場合
\makeatletter\chardef\pdf@shellescape=\@ne\makeatother
\usepackage{minted}
TeXLive2015の場合
\usepackage[cache=false]{minted}

これでmintedを使うことができます。以下はmintedを使った例です。

\documentclass{jsarticle}
\chardef\pdf@shellescape=\@ne
\usepackage{minted}
\begin{document}
\begin{minted}{c}
#include<stdio.h>
int main(void){
  printf("Hello World!\n");
  return 0;
}
\end{minted}
\end{document}

コンパイルしたいころですがここで問題が発生します。なんとmintedは不具合のためかタブスペースが^^Iと変換されて表示されます。 試行錯誤を重ねたのですが原因はわからず...結局テキストエディタでタブをスペースに変換することにしました。タブをスペースに自動変換する方法は自分の使っているテキストエディタ毎に調べてください。設定ができましたらこれをコンパイルしていきます。 コンパイルの時はオプションをつけなければなりません。次のようにオプションをつけてコンパイルを行ってください。

platex -shell-escape [filename]

latexmkでコンパイルをする場合もshellescapeの設定を行えばコンパイルをすることができます。

latexmkの導入についての記事は以下をご覧ください。
muscle-keisuke.hatenablog.com 一度ターゲットを決めたら変更のたびにコンパイルを自動でやるので便利ですよ!
実行結果は以下のようになります。 f:id:muscle_keisuke:20151108030711p:plain

また、texファイル内に直接ソースコードを記述せずソースファイルを外部から読み込んで表示することも可能です。先ほどの例にあるCのソースコードhoge.cという名前で保存したとしましょう。それをLaTeXでmintedを使って読み込んで表示したい場合は以下のように記述します。  

\inputminted{c}{hoge.c}

言語を指定する引数がソース直書きの時と違い最初に来ていることに注意してください。長いソースコードの場合はこの方がすっきりしていいと思います。

mintedの例

ソースコードを行番号つきで載せる

ソースコードを行番号つきで載せる時は以下のmintedのオプションにlinenosと付けます。

\begin{minted}[linenos]{c}

f:id:muscle_keisuke:20151108133243p:plain

ソースコードのコメントに数式を付ける

LaTeXに載せたソースコードのコメントを付ける時に数式を使った方がわかりやすい場合があります。次のようにLaTeX用の数式コマンドを使っても オプションにmathescapeを付ければLaTeXと同じように数式を表示することができます。

\begin{minted}[linenos,mathescape]{c}
#include<stdio.h>
int main(void){
    int k=0;
    int x=0;
    // This code mean \sum_{k=0}^{100} k^2+2k+1
    for(k=0;k<100;++k){
        x=k*k + 2*k +1;
    }
    printf("x=%d\n");
    return 0;
}
\end{minted}

結果は次のように綺麗な数式でコメントを残すことができます。 f:id:muscle_keisuke:20151108133326p:plain

その他のオプション

そのほかにも枠を付けたり図や表のようなキャプションやラベルをつけることも可能です。

\definecolor{bg}{rgb}{0.95,0.95,0.95}
\begin{listing}
\begin{minted}[linenos,
       mathescape,
       numbersep=5pt,
       frame=lines,
       framesep=2mm,
       bgcolor=bg]{c}
#include<stdio.h>
int main(void){
    int k=0;
    int x=0;
    // This code mean \sum_{k=0}^{100} k^2+2k+1
    for(k=0;k<100;++k){
        x=k*k + 2*k +1;
    }
    printf("x=%d\n");
    return 0;
}
\end{minted}
\caption{mintedの例}
\label{lst:example}
\end{listing}
ソース\ref{lst:example}はmintedの例である。

引用したい時も助かります。 f:id:muscle_keisuke:20151108135308p:plain

新しいmintedマクロ

ここまでmintedに関する様々なオプションを紹介してきました。しかし、たくさんのオプションを使うときにいちいち記述していたらごちゃごちゃしたり面倒くさかったりします。そこでmintedには新しいminted用のマクロを作れるマクロがあります。それが\newmintedと\newmintedfileです。2つのマクロの違いは外部からソースを読み込むかどうかの違いしかありません。次のソースを元に\newmintedと\newmintedfileで書き換える次のようになります。

\begin{minted}[linenos,
       mathescape,
       numbersep=5pt,
       frame=lines,
       framesep=2mm
       ]{c}
#include<stdio.h>
int main(void){
    printf("Hello World!\n");
    return 0;
}
\end{minted}

\inputminted[linenos,
       mathescape,
       numbersep=5pt,
       frame=lines,
       framesep=2mm]{c}{hoge.c}

書き換えると

\newminted[myMinted]{c}{
    linenos,
    mathescape,
    numbersep=5pt,
    frame=lines,
    framesep=2mm
}
\newmintedfile[myMintedfile]{c}{
    linenos,
    mathescape,
    numbersep=5pt,
    frame=lines,
    framesep=2mm
}

\begin{myMinted}
#include<stdio.h>
int main(void){
    printf("Hello World!\n");
    return 0;
}
\end{myMinted}

\myMintedfile{hoge.c}

ソースが長くなった気がしますがそれは最初に定義を書いているからです。newminted、newmintedfileマクロによって新しいminted用のマクロmyMintedとmyMintedfileを定義してそれを使っています。普段から同じオプションを使う人はこのように定義をしておくとコードがすっきりするかもしれません。