この記事はTypst Advent Calendar 2024の5日目の記事です。
昨日は@gomazarashiさんでした。
明日は@tomoyatajikaさんによる記事が公開される予定です。
新進気鋭の組版ソフトウェアである Typst が最近流行っています。
Typst には多くのパッケージがありますが、Wick 縮約を書くパッケージは今のところ存在しないようです。
Wick 縮約(ウィック縮約)の詳しい説明は省きますが、場の量子論などで使われる次のような数式中の文字を線でつなぐもののことです。
この記事では pinit というパッケージを使って Wick 縮約を Typst で書く方法を紹介します。
pinit
pinit はピンを置いて矢印や線を書くことができるパッケージです。
#import "@preview/pinit:0.2.2": *
文章にピン#pin(1)を置いて、それに矢印をつけることができます。
#pinit-point-from(1)[こんな感じです。]
2つのピンの中点から線を伸ばすことで Wick 縮約を書くことができます。
$
#pin("1-l")psi#pin("1-r")phi#pin("2-l")psi#pin("2-r")
$
#pinit-line(("1-l", "1-r"), ("1-l", "1-r"), stroke: 0.5pt, start-dy: -0.9em, end-dy: -0.9em-5pt)
#pinit-line(("2-l", "2-r"), ("2-l", "2-r"), stroke: 0.5pt, start-dy: -0.9em, end-dy: -0.9em-5pt)
#pinit-line(("1-l", "1-r"), ("2-l", "2-r"), stroke: 0.5pt, start-dy: -0.9em-5pt, end-dy: -0.9em-5pt)
より便利な関数
上のような方法で Wick 縮約を書くのは面倒なので、TeX の simpler-wick パッケージのような自動的に Wick 縮約を書いてくれるものが欲しいところです。
Typst では次のような簡単な関数を書くことで実現できます。
#import "@preview/pinit:0.2.2": *
#let wick-id = counter("wick-id")
#let wick-state = state("wick-state", ())
#let wick(sep: 5pt, offset-t: 0.9em, offset-b: 0.3em, stroke: 0.5pt, body) = {
wick-id.step()
wick-state.update(())
body
context {
let name = "wick-" + str(wick-id.get().at(0)) + "-"
let dict = (:)
for (i, n) in wick-state.get().enumerate() {
let p = (name + str(i) + "-l", name + str(i) + "-r")
let offset = if n > 0 { -offset-t } else { offset-b }
let dy = offset - sep * n
pinit-line(p, p, stroke: stroke, start-dy: offset, end-dy: dy)
let bef = dict.remove(str(n), default: none)
if bef == none {
dict.insert(str(n), p)
} else {
pinit-line(bef, p, stroke: stroke, start-dy: dy, end-dy: dy)
}
}
}
}
#let c(n, body) = (
context {
let s = wick-state.get()
pin("wick-" + str(wick-id.get().at(0)) + "-" + str(s.len()) + "-l")
body
pin("wick-" + str(wick-id.get().at(0)) + "-" + str(s.len()) + "-r")
wick-state.update(s => { s.push(n); s })
}
)
関数c
で Wick 縮約をする項と線の高さを決め、関数wick
の中にある同じ高さの線をつないでいます。これを使えば、先ほどの例は次のように簡単に書くことができます。
#wick($
#c(1, $psi$)phi#c(1, $psi$)
$)
もっと複雑な例も書くことができます。
#wick($
#c(1, $A$)#c(2, $B$)#c(1, $A$)#c(2, $B$) + #c(-1, $C$)#c(1, $D$)#c(-1, $C$)#c(1, $D$)
$)
#v(1em)
#wick($
#c(1.5, $A$)integral (d x)/x#c(1.5, $A$)
$)
おわりに
Typst は様々な便利なパッケージがあり、プログラミングも簡単です。Wick 縮約を書く関数も上のように簡単に書くことができます。