physics / braket / tensor

physics は、LaTeX でもっとも熱心に勧められ、同時にもっとも警告されているパッケージかもしれません。\dv{f}{x} で微分、\qty(...) で自動伸縮の括弧、\ket{\psi} でケット——書き味は確かに良い。ところがこのパッケージは、あなたの文書にすでにある命令を黙って書き換えます\div は割り算の記号 ÷ をやめて発散になり、\Re はフラクトゥールの ℜ をやめて立体の「Re」になります。このページでは physics、その再設計版 physics2、ディラック記法専用の braket、添字を整列させる tensor を扱い、実際にコンパイルして測った結果をもとに「今から書き始めるなら何を選ぶか」に答えます。

\usepackage{physics} で何が手に入るか

一行で、物理の数式によく出る形が短い命令に置き換わります。Sergio C. de la Barrera による physics は内部で xparseamsmath を必要とし、amsmath は自動で読み込むので別書きは要りません。手に入るのは大きく五組です。自動伸縮の括弧\qty\abs\norm\eval\order)、ベクトル解析\grad\div\curl\laplacian、内積 \vdot、外積 \cross)、微分\dv\pdv\fdv\dd)、ディラック記法\bra\ket\braket\ketbra\dyad\expectationvalue\matrixelement)、そして 行列と括弧の略記\mqty\smqty\pqty\bqty\Bqty\vqty、交換子 \comm、反交換子 \acomm、ポアソン括弧 \pb、太字ベクトル \vb\va\vu)です。

latex
\usepackage{physics}

\[
  \dv{f}{x}, \qquad \dv[2]{f}{x}, \qquad \pdv{f}{x}{y},
  \qquad \int_0^1 f(x) \dd{x}
\]
\[
  \abs{\frac{a}{b}}, \qquad \norm{\vb{v}}, \qquad
  \eval{x^2}_0^\infty, \qquad \qty( \frac{1}{2} )
\]

看板は微分です。\dv は引数の数で形を変え、\dv{x} なら演算子 d/dx、\dv{f}{x} なら df/dx になります。階数は省略可能引数で、\dv[2]{f}{x} が d²f/dx²、\dv[n]{f}{x} が dⁿf/dxⁿ です。d は既定で立体(ローマン)で組まれ、\usepackage[italicdiff]{physics} を渡すとイタリックの d に切り替わります。星付きの \dv*{f}{x}\flatfrac による斜線分数を出します。偏微分の \pdv は同じ流儀で、混合偏微分だけ引数が三つ——\pdv{f}{x}{y} が ∂²f/∂x∂y です。微分要素そのものは \dd で、\dd{x} は前後の間隔を整えた dx を、\dd[3]{x} は d³x を組みます。括弧のほうは \qty(...)\qty[...]\qty{...} が丸・角・波の各括弧に対応し、いずれも中身の高さに合わせて伸びます。

physics が黙って書き換える命令 — \div\Re\sin

警告もエラーも出ません。出力だけが変わります。 TeX Live 2024 で \meaning を読み出して確かめると、physics を読み込む前の \div\mathchar"2204——割り算の記号 ÷ です。読み込んだ後の \div は発散になり、もとの ÷ は \divisionsymbol という別名に移されます。同じ文書で組んで PDF から文字を取り出すと、$a \div b$「a∇ · b」$a \divisionsymbol b$「a ÷ b」 でした。幅も 26.79959pt 対 21.79968pt と別物です。つまり、\div を割り算の意味で使っていた既存の文書に \usepackage{physics} を足すと、式の意味が黙って変わります

\Re\Im はもっと目に見える形で変わります。physics.sty の当該行はこうです——\let\real\Re \DeclareDocumentCommand\Re{g}{…\operatorname{Re}…}。つまり フラクトゥールの ℜ が、立体の演算子「Re」に置き換わります。同じ文書で並べて組むと、$\Re z$「Re z」、退避した $\real z$「ℜz」 になりました。三角関数も同様で、\sin\cos\tan\log\ln\exp\det が引数の括弧を自動で付ける版に差し替わり、もとの定義は \sine\cosine\tangent\logarithm\naturallogarithm\exponential\determinant という長い名前で残ります。三角関数の差し替えだけは \usepackage[notrig]{physics} で止められます。

命令physics なしphysics あり(退避先)
\div÷(割り算の記号)発散 ∇· 。もとの ÷ は \divisionsymbol
\Reℜ(フラクトゥール)立体の \operatorname{Re}。もとは \real
\Imℑ(フラクトゥール)立体の \operatorname{Im}。もとは \imaginary
\sinsin(括弧は自分で書く)引数に括弧を自動で付ける。もとは \sine へ。notrig で無効化
\detdet同じく括弧が自動で付く。もとは \determinant

\dv{f}{x}(g) と書くと (g) が消える

式の一部が、エラーも警告もなく出力から失われます。 これは「意図しない見た目になる」よりずっと重い話なので、実測で示します。TeX Live 2024 で \sbox0{$\dv{f}{x}$} の幅を測ると 11.50076pt\sbox0{$\dv{f}{x}(g)$}11.50076pt——まったく同じでした。PDF から文字を取り出すと、どちらも「df/dx」だけが出て、(g) はどこにもありません。

原因は引数の宣言にあります。physics.sty\derivative{ s o m g d() } という並びで宣言されていて、末尾の d()後ろに続く丸括弧を引数として吸い込みます。これは \dv{x}(\Psi)(d/dx を括弧の中身に作用させる「長い形」)のために用意されたものです。ところが本体のコードは、g(この場合の x)が与えられているときの分岐で d() の中身を 一度も参照しません。だから (g) は読み取られ、そして捨てられます。回避策は二つ、間に空の群 {} を置くか、明示的な空きを入れるかです——実測で $\dv{f}{x}{}(g)$ は 24.40703pt、$\dv{f}{x}\,(g)$ は 26.07365pt となり、どちらも (g) が出力に残りました。同じ d()\grad\div\curl\laplacian\dd\pdv\fdv にも付いているので、後ろに括弧が続く書き方は一律に注意が要ります。

latex
% the (g) is read as the trailing d() argument and then thrown away:
% this prints df/dx and nothing else
$\dv{f}{x}(g)$

% either of these keeps the (g)
$\dv{f}{x}{}(g)$
$\dv{f}{x}\,(g)$

この挙動は tex.stackexchange で繰り返し話題になり、修正を当てる physics-patch というパッケージまで存在します。パッチが必要な状態が長く続いていること自体が、選定の材料になります。

siunitx との \qty 衝突 — 読み込み順では直らない

どちらの順で読み込んでも結果は同じで、勝つのは physics です。 単位組版の標準である siunitx は近年 \qty を数量の命令として導入し、physics の \qty と名前がぶつかりました。実際に両方を読み込んでコンパイルすると、siunitx はこう告げます——Package siunitx Warning: Detected the "physics" package: omitting definition of \qty. そのうえで \AtBeginDocument{\RenewCommandCopy\qty\SI} をプリアンブルに足せばよい、と回避策まで書いてよこします。この状態で \qty{2}{\metre} と単位を書くと、physics の \qty が受け取ってしまい ! Missing $ inserted. で倒れます。\usepackage{physics} を先に書いても後に書いても、警告もエラーも一字一句同じでした。

ここには読み飛ばしにくい事実が一つあります。siunitx.sty の中身を見ると、\@ifpackageloaded{physics} という行があり、siunitx が physics をパッケージ名で名指しして道を譲っている のです。数千行規模の主要パッケージが、他所のパッケージのために固有名でハードコードした譲歩を持っている——LaTeX の生態系ではめずらしい光景で、この衝突がどれだけ広く踏まれたかを物語っています。

physics と mathtools の \abs — 星の意味が逆になる

両方読み込むと \abs は physics のものになり、しかも星の意味が反転します。mathtools で \DeclarePairedDelimiter\abs{\lvert}{\rvert} を宣言した後に \usepackage{physics} を書いてもエラーは一つも出ませんでした——physics は黙って上書きします。しかし挙動は正反対です。実測すると、mathtools 版は \abs{\frac ab} の高さが 7.5pt(固定)、\abs*{\frac ab}8.50006pt(自動伸縮)。physics 版は \abs{\frac ab}8.50006pt(自動伸縮)、\abs*{\frac ab}7.5pt(固定)。つまり mathtools は星で伸ばし、physics は星で伸ばすのをやめます

サイズ指定の書き方も違います。mathtools は \abs[\big]{x} と角括弧で渡しますが、physics は \abs\big{x} と直接続けます。physics を読み込んだ状態で mathtools の書き方をすると ! Missing delimiter (. inserted). が出て、画面には「[] ||x」という壊れた出力が残りました。二つを混ぜて使うつもりなら、この非互換は避けて通れません。片方に決めるのが実務上の答え です。

physics2 — 何も上書きしない再設計版

同じ検査を physics2 に対して行うと、標準の命令が一つも書き換わっていませんでした。 Zhang Tingxuan による physics2 を読み込み、\meaning を読み出すと、\div\mathchar"2204(÷ のまま)、\Re\mathchar"23C\Im\mathchar"23D(フラクトゥールのまま)、\sin は標準の定義のまま、\qty未定義 です。実際に組んでも $a\div b$ は「a ÷ b」、$\Re z$ は「ℜz」、$\sin(x)$ は「sin(x)」——素の LaTeX とまったく同じ出力でした。siunitx と併用しても警告ゼロ・エラーゼロで、\qty{2}{\metre} は「2 m」と正しく組まれます。TeX Live 2024 に入っているのは v1.0.1(2024-01-10 付)です。

設計上の違いは読み込み方に現れます。physics が一括で全部を持ち込むのに対し、physics2 は モジュールを一つずつ選んで有効にします\usepackage{physics2} の後に \usephysicsmodule{ab,braket} のように書き、欲しい機能だけを取り込みます。TeX Live 2024 に同梱されているモジュールは ab(自動伸縮の括弧)、ab.braketbraketdiagmat(対角行列)、xmat(一般の行列)、doubleprod、そして physics からの移行者向けの ab.legacybm-um.legacynabla.legacyop.legacyqtext.legacy です。名前空間を汚さない代わりに、命令名は physics ほど短くありません——括弧は \ab(...)\ab[...]\ab\{...\}\ab|...|\ab<...>、対角行列は \pdiagmat{1,2,3}、行列は \pxmat{a}{2}{2} のように書きます。

latex
\usepackage{physics2}
\usephysicsmodule{ab,braket,diagmat,xmat}

\[
  \ab(\frac{a}{b}), \quad \ab[\frac{a}{b}], \quad \ab|\frac{a}{b}|
\]
\[
  \bra{\phi}, \quad \ket{\psi}, \quad \braket{a}{b}, \quad \ketbra{a}{b}
\]
\[
  \pdiagmat{1,2,3}, \qquad \pxmat{a}{2}{2}
\]

一つだけ実務上の注意があります。ab.braketbraket の二つのモジュールは同時に読み込めません。 両方を \usephysicsmodule に並べると Package physics2 Warning: You cannot load 'ab.braket' and 'braket' modules together. が出て、片方だけが有効になります。どちらもディラック記法を提供しますが、ab.braketab の自動伸縮の仕組みに乗る版、braket は単体で完結する版です。まとめると——新しく書き始めるなら physics2 を選ぶのが安全、既存の physics 文書を維持するなら書き換えのコストと \div\Re\qty の副作用を天秤にかける、というのが実務の判断です。微分だけが目的なら、高階と多変数をきれいに扱う derivative パッケージ、微分演算子の組み方を整える fixdif という選択肢もあります。

braket パッケージ — 大文字が伸び、小文字が伸びない

ディラック記法だけが目的なら、Donald Arseneau の braket が最小の答えです。\usepackage{braket} の一行で、命令は二系統だけ——固定サイズの小文字版 \bra{ }\ket{ }\braket{ }\set{ } と、自動伸縮の大文字版 \Bra{ }\Ket{ }\Braket{ }\Set{ } です。大文字版の利点は、引数の中に直接書いた縦棒 | が外側の区切りと一緒に伸びること。\Braket では内部のすべての | が引数の高さまで育ち、\Set では最初の | が育ちます。二重線が要るときは \|、あるいはこの環境内での別名 || を使います。

latex
% braket: one argument, the bars written inside it
\Braket{ \phi | \frac{\partial^2}{\partial t^2} | \psi }

\Set{ x \in \mathbf{R}^2 | 0 < {|x|} < 5 }

引数の数え方が physics と違う点に注意してください。physics の \braket{a}{b}二引数 ですが、braket の \braket{a|b}一引数で、区切りの縦棒を自分で書きます。上の例の一つ目は行列要素 ⟨φ| ∂²/∂t² |ψ⟩ を組み、外側の山括弧も内側の二本の縦棒も演算子の高さまで伸びます。二つ目は集合 { x ∈ R² | 0 < |x| < 5 } で、外側の波括弧と仕切りの縦棒が伸び、内側の |x|{|x|} と包んであるので固定サイズのまま残ります。また braket には外積の \ketbraありません——作者は \ket{ }\bra{ } と並べて書くことを勧めています。

tensor パッケージ — 上下の添字を正しい順に並べる

テンソルでは添字の 横位置そのものが意味を持ちます。Γ^μ_{νρ} や R^μ_ν{}^ρ_σ では、上と下の添字が左から正しい順に並んでいなければなりません。ところが ^_ を素直に続けて書くと同じ位置に重なって積まれ、どちらの添字が先なのか読めなくなります。これを解くのが Philip G. Ratcliffe の tensor(Mike Piff の原作を全面改訂した v2.2)です。外部パッケージを必要とせず、\usepackage{tensor} だけで使えます。

latex
\[
  M\indices{^a_b^{cd}_e}, \qquad
  \tensor{M}{^a_b^{cd}_e}, \qquad
  \tensor[^a_b^c_d]{M}{^e_f^g_h}
\]

% works in text mode as well as math mode
\nuclide[14][6]{C}

中心となる命令は二つです。軽い \indices はテンソル本体の直後に置き、添字の文字列だけを取ります——M\indices{^a_b^{cd}_e} と書けば、M に続いて上の a、下の b、上の cd、下の e が、それぞれ正しい横位置を保って組まれます。文字列の中では ^_ をそのまま使い、複数文字の添字は ^{cd} のように波括弧でまとめます(\sp\sb も同じ働きです)。もう一つの \tensor は Mike Piff の原作と後方互換で、本体と添字文字列を別々の引数に取ります。\tensor{M}{^a_b^{cd}_e} は上の \indices の例と同じ出力になりますが、\tensor の強みは 本体より前にも添字を置けること で、省略可能な第一引数に前置の添字文字列を渡します。どちらにも星付きの \indices*\tensor* があり、添字どうしの空きを詰めた標準的な見た目にします。さらに、添字文字列の 先頭* を置くと、連続する上下の組が左揃えになります。

おまけとして \nuclide が定義されており、これは 本文モードでも数式モードでも 使えます。\nuclide[14][6]{C} は元素記号 C の左上に質量数 14、左下に原子番号 6 を置いて ¹⁴₆C を組みます(数値はどちらも省略可能)。なお添字文字列では、複数トークンの添字は必ず波括弧でまとめる必要があり、\mathrm のような構文も丸ごと囲みます——\indices{_{\mathrm{H}}^x} のように書きます。

結局どれを使うか

新規の文書では physics を出発点にしない、というのが測定結果からの結論です。 引数が黙って捨てられること、\div\Re の意味が変わること、siunitx との衝突が読み込み順で解決しないこと——この三つはいずれも警告なしに起こります。とはいえ physics は依然として広く使われており、共著者から渡された原稿がそれで書かれていることもあります。そのときは書き換えず、\divisionsymbol\real\imaginary の存在と (g) の落とし穴を知ったうえで扱うのが現実的です。下の表は用途ごとの選び方です。

パッケージやること標準の命令を書き換えるか
physics微分・括弧・ベクトル解析・ブラケットを一括でする。\div\Re\Im\sin\det ほか
physics2同じ領域を \usephysicsmodule でモジュール単位にしない(実測で \div\Re\sin は素のまま)
braketディラック記法と集合記法だけしない。小文字が固定、大文字が自動伸縮
tensor上下の添字の横位置を正しく保つしない。\indices\tensor\nuclide を足すだけ
mathtools\DeclarePairedDelimiter\abs\norm を自分で定義しない。名前は自分で決めるので衝突しない