5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

数式の折り返し前後で高さが自動調整される括弧を利用する

Last updated at Posted at 2021-10-23

数式の折り返し前後で高さが自動調整される括弧を利用する

amsmath パッケージから、長い数式を折り返す数式環境として split 環境や multline 環境が提供されている。しかし、これらの環境内で高さが自動調整される括弧を利用する場合、少しだけ (?!) 不便になることがある。これを解決してみたい。

また、# 中間区切りの手動調整と自動調整 では \middle の取り扱いに関しても触れてみた。

○ 前提

amsmath パッケージと mathtools パッケージを利用することを前提とします。

また、それぞれの括弧については以下のようなコマンドを利用する。

括弧の種類 コマンド
丸括弧 (, )
(Parenthesis)
(, ) or \lparen, \rparen
波括弧 {, }
(Brace)
\lbrace, \rbrace
角括弧 [, ]
(Bracket)
\lbrack, \rbrack
山括弧 <, >
(Angle bracket)
\langle, \rangle
垂直棒
(Vertical bar)
\lvert, \rvert
2 本の垂直棒 \lVert, rVert

■ 基本的な使用方法例

multline(d) 環境や split 環境の基本的な使い方は以下の記事を参照のこと。

長い数式を手動で折り返す - Qiita

\frac\sum などの背の高い数学記号に対して高さを自動調整する括弧を具体的な使い方は以下のようになる。

\begin{equation}
  % Example of automatic
  \left\lparen
    \frac{\partial T}{\partial P}
  \right\rparen_S
    =
    % Example of manual
    \biggl\lparen
      \frac{\partial V}{\partial S}
    \biggr\rparen_P
\end{equation}

Maxwell relations

これらの調整によって調整される括弧スタイルの組み合わせは任意に採ることが出来る。したがって、\left\lparen <contents> \right\rbrace などが可能である。また、開き括弧と閉じ括弧を揃える必要もない。

また、一方に括弧を挿入したくない場合には . を用いて \left. <contents> \right\rvert などとすれば、右側の垂直棒だけを高さを調節して出力することが出来る。

\begin{equation}
  % Example of automatic
  \left.
    \frac{\partial T}{\partial P}
  \right\rvert_{S=\mathrm{const}}
    =
    % Example of manual
    % Do not need \biggl
      \frac{\partial V}{\partial S}
    \biggr\rvert_{P=\mathrm{const}}
\end{equation}

Maxwell relations var

囲うコンテンツは数式に留まらず、aligned 環境などの非独立な数式環境も囲うことが出来る。(split 環境を除く)

また、行列を作成する場合には array 環境や matrix 環境を括弧で囲わずに、amsmath パッケージから提供される pmatrix 環境などを利用することをお薦めする。

○ 発生する問題

折り返し(改行 \\)の前後で \left ~ \right で括弧を対応させることが出来ない。

すなわち、以下のような式を出力することが出来ない。これは、対応する \left ~ \right の中に \\& が含まれているためである。

\begin{equation}
  \begin{split}
    <left_hand_side>
      = {} &
        \left(
          <wrapped_equation_1> \\
          & + <wrapped_equation_2>
        \right)
  \end{split}
\end{equation}

これを回避する方法として、それぞれの行で \left ~ \right を対応させることがよく知られている。

\begin{equation}
  \begin{split}
    <left_hand_side>
      = {} &
        \left(
          <wrapped_equation_1>
        \right.
      \\
      & \left.
          + <wrapped_equation_2>
        \right)
  \end{split}
\end{equation}

ただし、このようにした場合、<wrapped_equation> の高さはそれぞれ同じである必要がある。

たとえば、以下のような場合では自動調整の恩恵を得られない。

\begin{equation}
  \begin{split}
    <left_hand_side>
      = {} &
        \left\lbrace
          <TALL_wrapped_equation_1>
        \right.
      \\
      & \left.
          + <short_wrapped_equation_2>
        \right\rbrace
  \end{split}
\end{equation}

miss delimiter size

この場合、開き括弧だけが高くなり閉じ括弧はそのままの高さになっている。本来、開き括弧と閉じ括弧の高さは揃っているべきなので、これは好ましくない。また、開き括弧と折り返された式の行頭がそろっていない方が良いように思われる。少しだけ右へずらすようにしたい。

したがって、以下の点を解決する必要がある。

  • 改行 \\ の前後で括弧を対応させる
    • 対応する括弧の高さを揃える
    • 行列環境の場合
  • 折り返された後の式を少しだけインデントする

これらを解決させよう。

ちなみに、これらを解決させたコマンドを提供するパッケージは存在しないようだ。

○ 手動で調整する

折り返しの前後で自動調整を利用したいのに、手動での調整を考えるのは本末転倒とも言えそうだが、まずは手動での方法を確認しておきたい。

手動で調整する場合には括弧の高さを調整するコマンドを利用する。これらのコマンドは左と右で別のコマンドが用意されている。

括弧の高さ 左側 右側
big \bigl \bigr
Big \Bigl \Bigr
bigg \biggl \biggr
Bigg \Biggl \Biggr

また、\left ~ \right で対応している場合、どの高さに調整されているのかは気になるだろう。以下のような主要な高さの高い数式について確認してみた。

数式の例 自動調整される括弧の高さ
分数 bigg
分数と根号 Bigg
積分記号
(nolimits 型)
Bigg
積分記号
(limits 型)
Bigg より大きい
総和記号
(limits 型)
Bigg

sample of delimiter size

場合によっては上手くないが、Bigg で調節しておくことが定石になりそうである。これに固定して括弧で囲うとするならば自動調整の必要はないため、\\& を含む数式を囲むことのできるコマンドを作成しておくことも出来るだろう。

\newcommand{\BiggParen}[1]{\Biggl(#1\Biggr)}
\begin{equation}
  \begin{split}
    <left_hand_side>
      = {} &
      \BiggParen{
        <wrapped_equation_1> \\
        & + <wrapped_equation_2>
      }
  \end{split}
\end{equation}

BiggParen

括弧コマンドを拡張する(折りたたみ)

mathtools パッケージから提供されている \DeclarePairedDelimiter コマンドを利用して括弧コマンドを作成し、ifthen と xparse からオプションで括弧のスタイルを指定するように作成した。デフォルトの括弧の高さを Bigg にした。

\manualDelimiter(delimiter_size)[delimiter_style]{formula_body} を定義した。

\usepackage{ifthen}
\usepackage{xparse}
\usepackage{mathtools}
\DeclarePairedDelimiter{\pairedParen}{\lparen}{\rparen}
\DeclarePairedDelimiter{\pairedBrace}{\lbrace}{\rbrace}
\DeclarePairedDelimiter{\pairedBrack}{\lbrack}{\rbrack}
\newcommand{\wrongOptionName}{\text{Warning! Wrong option.}}
\NewDocumentCommand{\maualDelimiter}{ D(){Bigg} O{p} m }{
  \ifthenelse{\equal{p}{#2} \OR \equal{paren}{#2}}{
    \ifthenelse{\equal{big}{#1}}{\pairedParen[\big]{#3}}{
      \ifthenelse{\equal{Big}{#1}}{\pairedParen[\Big]{#3}}{
        \ifthenelse{\equal{bigg}{#1}}{\pairedParen[\bigg]{#3}}{
          \ifthenelse{\equal{Bigg}{#1}}{\pairedParen[\Bigg]{#3}}{
            \wrongOptionName
    } } } }
  }{
    \ifthenelse{\equal{b}{#2} \OR \equal{brace}{#2}}{
      \ifthenelse{\equal{big}{#1}}{\pairedBrace[\big]{#3}}{
        \ifthenelse{\equal{Big}{#1}}{\pairedBrace[\Big]{#3}}{
          \ifthenelse{\equal{bigg}{#1}}{\pairedBrace[\bigg]{#3}}{
            \ifthenelse{\equal{Bigg}{#1}}{\pairedBrace[\Bigg]{#3}}{
              \wrongOptionName
      } } } }
    }{
      \ifthenelse{\equal{B}{#2} \OR \equal{brack}{#2}}{
        \ifthenelse{\equal{big}{#1}}{\pairedBrack[\big]{#3}}{
          \ifthenelse{\equal{Big}{#1}}{\pairedBrack[\Big]{#3}}{
            \ifthenelse{\equal{bigg}{#1}}{\pairedBrack[\bigg]{#3}}{
              \ifthenelse{\equal{Bigg}{#1}}{\pairedBrack[\Bigg]{#3}}{
                \wrongOptionName
        } } } }
      }{\wrongOptionName}
    }
  }
}
delimiter_style 括弧のスタイル
p, paren
(デフォルト)
丸括弧
b, brace 波括弧
B, brack 角括弧

○ コマンドを作成する

何かしらのパッケージからコマンドを提供されているか探してみたが、どうやらないらしい。

ユーザ側で作ってみよう。2 パターンのコマンド例を見てみよう。

■ 簡単なコマンド例

次のようにコマンドを作成すれば、\left ~ \right が対応する括弧を作成することが出来る。開き括弧と閉じ括弧のそれぞれの内部で、囲む数式の全体の高さを処理して自動調整させるようにしている。

\newcommand{\autoParen}[2]{%
  \mathopen{%
    \left(%
      \vphantom{#1#2}%
    \right.%
  }%
  #1%
  \\ &%
  #2%
  \mathclose{%
    \left.%
      \vphantom{#1#2}%
    \right)%
  }%
}

以下のように利用することが出来る。ただし、1 回の折り返ししか使うことが出来ない。また、コマンド内部で &\\ を利用しない。

\begin{equation}
  \begin{split}
    <left_hand_side>
      = {} &
        \autoParen{ <TALL_wrapped_equation_1> }
        {+ <short_wrapped_equation_2> }
  \end{split}
\end{equation}

autoParen

もちろん、折り返しの回数を 2 回、3 回と増やしたコマンドを作成することも出来るが、特定の回数しか利用できなくなるため少々面倒くさい。

■ エキスパートな例

mathtools パッケージから提供されているコマンドと TeX にプリミティブなコマンドを利用して折り返しの前後でも対応が取れる括弧を作成してみる。

cf. The mathtools Package, §3.6.1 Expert use

Sebastien Gouezel (2014/05/14) から例として挙げられているコマンドを少し変更したものを紹介する。(垂直棒では変化が分かりづらかったので、波括弧に変更した)

\usepackage{mathtools}
\newcommand{\MTkillspecial}[1]{% helper macro
  \bgroup%
  \catcode`\&=9%
  \let\\\relax%
  \scantokens{#1}%
  \egroup%
}
\DeclarePairedDelimiter{\autoBrace}{\lbrace}{\rbrace}
\reDeclarePairedDelimiterInnerWrapper{\autoBrace}{star}{%
  \mathopen{%
    #1% `\left <left_delimiter>'
    \vphantom{\MTkillspecial{#2}}%
    \kern-\nulldelimiterspace%
    \right.%
  }%
  #2% Formula in bracket
  \mathclose{%
    \left.%
    \kern-\nulldelimiterspace%
    \vphantom{\MTkillspecial{#2}}%
    #3% `\right <right_delimiter>'
  }%
}
  • \MTkillspecial では、\catcode`\&=9& を無視するカテゴリコードに変更
  • \let\\\relax\\ を無視
  • \DeclarePairedDelimiter では、波括弧で囲むコマンドを定義
  • \reDeclarePairedDelimiterInnerWrapper では、\DeclarePairedDelimiter で定義されているコマンドを再定義

したがって、このビックリ :stuck_out_tongue_winking_eye: ブラックボックスコマンドを利用すれば、次のように途中で折り返しを含むような数式も上手く括弧の高さを自動調整できる。

\begin{equation}
  \begin{split}
    <left_hand_side>
      = {} &
        \autoBrace*{
          <short_wrapped_equation_1> \\
          & + <TALL_wrapped_equation_2> \\
          & + <short_wrapped_equation_3>
        }
  \end{split}
\end{equation}

autobrace

このコマンドの大きなメリットは、折り返しの回数が制限されない点である。また、このコマンドも手動で調整するコマンドを拡張したときと同じように、ifthen パッケージと xparse パッケージを利用してオプションから括弧のスタイルを使い分けるように新たなコマンドを作成することも出来るだろう。

ただし、このコマンドを管理する際には、TeX にプリミティブなコマンドが含まれているため、それなりの知識が必要になる可能性がある。

なお、mathtools パッケージから提供される \DeclarePairedDelimiter などのコマンドは定義したコマンドの * 付きが高さを自動調整された括弧となる。

○ 行列環境を折り返す

基本的な攻略法は、分割した行列をそれぞれ matrix 環境で書き、それぞれを \left( ~ \right.\left. ~ \right) などして括弧を書くようにする方法となる。もちろん、# エキスパートな例 で紹介しているコマンドを利用していても良いが、基本的に行列の高さは折り返しの前後で変わらないので、これで十分だと思われる。

問題は、どのように折り返すかのみになるが、multlin(d) 環境か split 環境を利用すれば良いだろう。

これらには以下のようなメリットとデメリットがあると思われる。

環境 メリット デメリット
multline 自動インデント(& 不要) 行列がある程度大きい必要がある
multlined 自動インデント(& 不要) align 環境などで整列が上手くない
split どの環境でも利用可能 インデントを手動でする必要がある

■ multline(d) 環境を利用する場合

かなり大きめの行列に関しては multline 環境を利用すると良いだろう。

\begin{multline}
  M
    =
    \left(
      \begin{matrix}
        <BIG_matrix_contents>
      \end{matrix}
    \right.
    \\
    \left.
      \begin{matrix}
        <BIG_matrix_contents>
      \end{matrix}
    \right)
\end{multline}

multline matrix

あまり大きな行列ではない場合には、multlined 環境を使って最大幅をユーザ側で与えて使うことにしよう。

改行ごとに適当なインデントが与えられるので、split 環境よりも平易に書くことが出来る。ただし、align 環境などで & を用いて整列する場合には上手く整列できないので注意が必要。

\begin{equation}
  \begin{multlined}[0.5\linewidth]
    M
      =
      \left(
        \begin{matrix}
          <matrix_contents>
        \end{matrix}
      \right.
      \\
      \left.
        \begin{matrix}
          <matrix_contents>
        \end{matrix}
      \right)
  \end{multlined}
\end{equation}

multlined matrix

■ split 環境を利用する場合

split 環境で折り返すだけでは折り返した後の行列をある程度インデントしておくと良いだろう。ただし、どこまでインデントすべきかの一般的な回答はないと思われる。気持ちのいいところまでインデントしよう。

\newcommand{\matrixindent}{\qquad}
\NewDocumentCommand{\mtxind}{ o }{%
  \IfNoValueF{#1}{\hphantom{#1}}%
  \matrixindent%
}

例として、= 右側から \mtxind (\qquad) でインデントしてみた。

\begin{equation}
  \begin{split}
    M
      = {} &
      \left(
        \begin{matrix}
          <matrix_contents>
        \end{matrix}
      \right.
      & \mtxind
      \left.
        \begin{matrix}
          <matrix_contents>
        \end{matrix}
      \right)
  \end{split}
\end{equation}

split matrix

& が split 環境外でも整列として適用されるので、align 環境などでも利用できる。

○ 2 行目以降を開き括弧の後ろまでインデントする

以降では、改行に伴うインデントを簡便にするコマンドを考えたい。

折り返しの前後を括弧で囲む場合、折り返し後の数式は開き括弧の右端から始めた方がきれいにも思われる。次のようなコマンドを定義しておいても良いだろう。

\newcommand{\delimind}{\hphantom{\Biggl\lparen}}

この空白は、開き括弧と同じくらいの水平幅になっている。

以下のように折り返したあとの & に続けて利用する。

\begin{equation}
  \begin{split}
    <left_hand_side>
      = {} &
      \Biggl(
        <wrapped_equation_1> \\
        & \delimind + <wrapped_equation_2>
      \Biggr)
  \end{split}
\end{equation}

indent brace

また、xparse パッケージを利用して括弧の前にある係数などを含めてインデントさせるオプションを付与したコマンドを作成しておいても良いだろう。

\newcommand{\delimiterindent}{\hphantom{\Biggl\lparen}}
\NewDocumentCommand{\delimind}{ o }{%
  \IfNoValueF{#1}{\hphantom{#1}}%
  \delimiterindent%
}

たとえば、以下のような括弧の全体に係数がかかっている場合にインデントする。

\begin{equation}
  \begin{split}
    <left_hand_side>
      = {} &
      <coefficient>
      \Biggl(
        <wrapped_equation_1> \\
        & \delimind[<coefficient>] + <wrapped_equation_2>
      \Biggr)
  \end{split}
\end{equation}

indent brace+coefficient

○ 高さが自動調整される括弧の周りの空白

\left ~ \right で対応させた高さが自動調整される括弧を利用しているとき、括弧の左右で通常よりも大きい空白を作ってしまう。

これは以下のような例を見ると分かりやすい。

  • \sin などの作用素の後
  • \sum などの大型演算子の後
  • 連続する高さが自動調整される括弧の間
  • , などの前

sample

上を見ればわかるように、mleftright パッケージを利用すると良い。

mleftright - CTAN

このパッケージでは、\left ~ \right で対応させる括弧を通常の括弧と同じような空白に調節するように設計されているようだ。これを実現する \left ~ \right の代わりの \mleft ~ \mright が提供されている。

しかしながら、これらをすべて置き換えるのは面倒である。\mleftright を利用することで、再定義させることも出来る。したがって、以下のようにプリアンブルに追加すれば良いだろう。

\usepackage{mleftright}
\mleftright

これで、\left\mleft\right\mright としてふるまうようになる。

○ 中間区切りの手動調整と自動調整

集合論の内包的記法や Dirac の bra-ket 記法などでは (X|Y) のような構造の数式を書くことになる。このとき、中間にある区切りの | も高さを揃える必要がある。

Dirac の bra-ket 記法では braket や physics パッケージなどの適当なパッケージを利用すれば良い が、内包的記法のパッケージは存在しないようだ。ユーザ側で事前に定義しておくことになるだろう。

基本的な使い方を確認し、適当なコマンドを作成してみよう。

■ 基本的な使用方法

中間区切りの自動調整コマンドにも手動調整と自動調整の 2 つがある。左右の調整コマンドと合わせて表にしておこう。

括弧の高さ 左側 中間 右側
big \bigl \bigm \bigr
Big \Bigl \Bigm \Bigr
bigg \biggl \biggm \biggr
Bigg \Biggl \Biggm \Biggr
auto \left \middle \right

手動調整して利用する場合には、以下のように記述する。

\begin{equation}
  \Biggl\lbrace
    x \in X
    \Biggm\vert
    \frac{\sqrt{x}}{x^2+1} > 1
  \Biggr\rbrace
\end{equation}

bigg vert sample

これと同じように自動調整する際に注意しておきたいのは以下の点である。

  • \middle は必ず \left ~ \right の間に置く
    • \middle の数は複数でも良い
  • \mid は高さを変更することが出来ない (\middle\mid は不可)
  • \vert は自動調整 (\middle\vert) すると左右の間隔が詰まりすぎる
    • これは改善したい

\middle\vert によって高さを調節するには、以下のように別コマンドを定義して間隔を空けるようにしておくと良い。どうやら、二項演算子 (\mathrel) として扱えるようにしておくと良いようだ。

\newcommand{\relmiddle}[1]{\mathrel{}\middle#1\mathrel{}}

ここでは再定義していないが、\middle として再定義しておいても良いだろう。

\relmiddle は次のように利用する。

\begin{equation}
  \left\lbrace
    y \in Y
    \relmiddle\vert
    \frac{\sqrt{y}}{y^2+1} > 1
  \right\rbrace
\end{equation}

relmiddle vert sample

これを簡易的にコマンドとして定義しておくことは容易だろう。

■ コマンドを作成する

mathtools パッケージから提供される \DeclarePairedDelimiterX\delimsize を利用して、以下のように定義しておいても良いだろう。(\delimsize\middle と同じような役割を担っている。と言っても、内部では \middle を使って \delimsize を作成しているようだ)

cf. The mathtools package §3.6 Paired delimiters

\providecommand\given{}
\newcommand{\SetSymbol}[1]{%
  \nonscript\:#1\vert%
  \allowbreak%
  \nonscript\:%
  \mathopen{}%
}
\DeclarePairedDelimiterX{\Set}[1]{\lbrace}{\rbrace}{%
  \renewcommand{\given}{\SetSymbol{\delimsize}}%
  #1%
}

これを用いて、次のように利用することが出来る。\given| が呼び出されるようになっている。

\begin{equation}
  \Set*{ z \in Z \given \frac{\sqrt{z}}{z^2+1} > 1 }
\end{equation}

DeclarePairedDelimiterX sample

なお、ここで作成したような \DeclarePairedDelimiterX で定義されたコマンドは \reDeclarePairedDelimiterInnerWrapper を利用して再定義することが出来ない。

ここではこれ以上考えないが、これらの途中で改行を含みたい場合は何かしらの方策を考える必要がある。(そもそもどこで折り返すべきなのかが不明)

参考

余談

今回で実現した折り返しの前後で対応する括弧を利用することはままあると思われるが、意外にもこれに対するパッケージが提供されていなかった。だれか作っておいてよ〜のお気持ち。

また、なぜかエキスパートな例で紹介した自動調整される括弧のコマンドは誰もネット上で紹介していないようであった。もしかして、誰も mathtools のパッケージガイド読んでない?

少しだけ記事の話題から反れているが、\middle も扱ってみている。しかしながら、これによって括弧の高さを調節する方法を網羅的に説明できているような気がする。

追記

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?