goo blog サービス終了・・・(泣)

2007年から20年近くお世話になった goo blog がサービス終了とは寂しい限りである.

都営バスも運行本数がかなり削られた印象があるし,これも時代の趨勢であろう.

Amebaはてなに移行できるらしいのだが,はてさて,数式が使いやすいのはどちらだろうか?

MathJax や KaTex みたいな,ブラウザできれいな数式を高速でレンダリングできるサービスの,Typst 版とかあったらすごく便利なんだけどなぁ.Typst から HTML へのエクスポート機能が正式に実装されたら,それがほぼそういうサービスに他ならないわけだが.

現在の LaTex や Typst は用紙サイズ固定の PDF ファイルを作成するツールなので,PC やタブレットスマートフォンといった表示デバイスに応じた体裁で文書を表示してくれるのは HTML/CSS の大きな魅力である.それがブログという形態で数学メモを作り続けていきたいと考える理由である.

ぶっちゃけ,全く「読者」といった対象を想定していない,単なる独り言の書き殴りに過ぎない記事ばかり書いているが,この広い世の中のことだから,私と同じようなことを考え,解決できずに困っている人がいたとして,その人にとってのなんらかのヒントになることを提供できるかもしれない,といったことを夢見てもいる.

というわけで,記事の投稿頻度は非常に低いままではあるが,今のところブログは続けていこうと考えている.

Typst: 解答の表示と非表示を切り替える

Typst には hide という関数があるが,その挙動は LaTeX でいうところの phantom と同様である.つまり,ある文字列を表示しないが,その文字列分の領域を確保する機能がある.

だが,hide 関数はシンプルで,表示の ON/OFF を切り替えられるわけではない.

それに対し,LaTeX では if コマンドを利用して,例えば自分で設定した if 変数が true ならば表示し,false ならば表示しないという切り替えができる.ただし,それは false ならばコメントアウト扱いで,非表示の際にその文字列分の領域が確保されるわけではない.

授業資料として演習問題のプリントを作成する際,それにこちらが用意している模範解答も記入することで解答欄の領域を確保しつつ,解答を非表示にしたバージョンを学生に提供できるようなら便利であろう.

これは Typst ならば次のような実現方法がある.解答の文字列だけをページの背景と同じ色にしてしまえばよい.

背景が白であれば,解答も白い文字で表示するわけである.

背景がなんらかの画像であるとか,複雑な模様になっているオシャレなデザインのときにどうすればよいかまでは私にはわからない.それはそれで別の工夫をすることで目的を達成することができるかもしれないし,不可能かもしれない.

今回は

#let ans(it) = text(fill: white)[#it]

という関数 ans() を自作する.

問題の解答を #ans(...) のように記述すればよい.数式モード中では ( ) 内の文字列は数式モード中の記法をそのまま書き込めば良い.本文中では文字列と認識させるために #ans("文字列") もしくは #ans([文字列]) のようにしないとエラーが出る.

ans() の定義式の右辺の色指定を black に修正すれば,解答が黒字で表示される.もちろん色はそれ以外のものを好きに指定すれば良い.

実際の使い方としては,色を black にした状態で解答を含めて資料を作成した後,最後に忘れずに black の部分を white に書き直して解答を非表示にする,といったものを想定している.

ちなみに,white にして見えなくした状態で PDF 形式でエクスポートしたものを PDF ビューワで開いた際,空欄の箇所を選択してみたが,私が使用したビューワでは白い文字が反転表示されることはなかった.つまり,そこに白い文字で何かが書かれていると認識されなかったということである.PDF の中身がわからないため,どんなビューワでも非表示の部分をうまく覗き見できないのかどうか判断できないので,この方法で作成した解答非表示の PDF ファイルを,解答を知らせたくない場合に学生に配布してしまって大丈夫なのかどうかは自信がない.

HTML だと,バックグラウンドと同じ色の文字を書いた際,ブラウザ上でその部分を選択すると文字色が反転されて読めるようになることは経験上知っているのだが,Typst が生成する PDF ファイルにそういう白文字の情報が含まれているのかどうかが私にはさっぱりわからない.

※ PDF ビューワで表示したものにおいて範囲を選択してテキスト情報をクリップボードにコピーし,テキストエディタに貼り付けたところ,範囲指定がぐちゃぐちゃになったため支離滅裂な文字の並びにはなったものの,伏せておきたかった i×j=k などの右辺の解答がバッチリ表示されてしまっていた.したがって,そのような裏技を心得ている学生相手にここで示した方法は通用しない.改善案としては,解答の部分を box もしくは rect などで真っ白に塗りつぶす検閲方式が思い浮かぶが,それはまだ試していない.そのように「物理的に」塗りつぶしてしまえば PDF 上でのテキストコピペを封じられるのではないかと期待してはいるのだが.

参考までに 3 次元基本ベクトルのベクトル積の総当り表(「ベクトル積九九」)のビフォー・アフターの画像を貼っておく.

※ 「これは解答が見えないよね?」という文の『解答が』の部分にはわざと box 関数を用いて silver の背景色を付けている.非表示の際に白い文字が出力されているのがそれとなく見て取れるのではないだろうか.

なお,設問ごとに解答の表示/非表示を切り替えたければ,原始的な方法ではあるが,設問ごとに ans() を定義する let 文を付しておき,それぞれで black/white を設定する対処法が考えられる.

<white で非表示>
<black に書き換えて表示>

Typst: 別行立て数式を左寄せにする fleqn の実装

Typst の数式モードはブラックボックスである.

が,math.equation という名の関数としてある程度設定をいじることが可能である.

例えば数式モードにおけるフォントを自分の好みに設定したいとき,

#show math.equation: set text(font: "TeX Gyle Schola Math")

という記述を,表示したい数式よりも前に本文中に認(したた)めておけばよい.

ちなみに,デフォルトの Libertinus は中文フォントもカバーしているようで,Typst 公式サイトのエディタなどでデフォルトの設定のまま日本語で文章を書くと句読点が左下ではなく,たとえば「・」のように中央に表示される.そして漢字やひらがなのフォントが微妙に思っていたのとチガウ.

文字種ごとにフォントを指定することも可能らしいが,私には未だにひらがな+カタカナ+日本風の漢字+全角コンマ+全角ピリオド,そしてそれら以外の約物(カッコ類,引用符など)すべてを過不足なく網羅した Unicode の範囲がイマイチ理解できていないのと,それらを調べる気力がないのとで,ひとまず Typst が提供してくれている latin-in-cjk をうまく利用することにしている.

ぶっちゃけ,*strong* みたいに * で挟んだ際の太字も,通常の和文フォントを原ノ味明朝にしたとして,それに合わせて原ノ味ゴシックしたい場合も,自分で show ルールを使ってそのように設定しなければならないっぽい.まあ,それはそれで活字の濃さ (weight) もカスタマイズできるので,その設定のついでと思えば良いかもしれない.

愚痴をこぼせば,Typst の開発者がベルリン(大学?)出身の二人組であるため,どうしても欧文の文化を基盤とした組版システムにならざるを得ず,縦組みをはじめとする日本語の文書として満足のいく出来栄えを目指すには自分でどうにかするしかないといった不便さが拭えない.

フォントの指定の仕方の詳細については,これまであれこれ試してみたものの,実験結果をぜんぜんまとめていないので,その報告はするとしても別の機会としたい.

さて,今回の本題は LaTeX ならば,たいていファイルの一行目に書く document class のオプションにある,数式を左揃えで表示する fleqn(おそらく flushleft equations といった感じの語句の略称)を Typst で実現する方法を紹介することである.

まず,Typst の本文の冒頭あたりにでも

#show math.equation: set align(left)

というおまじないを入れておけば,それだけで別行立て数式がデフォルトで中央揃えだったのが左揃えに変更される!

ところが,である.

アキ,いうなればインデントの余地など全く無く,本当に完全に左端に寄ってしまうのである.

求メテ イタ ノハ ソレ ジャナイ・・・.

そこで,例えば2文字分のアキを左側に設定したければ,pad 関数を使えばよい.pad 関数で左に2文字分のインデントを入れることにしたい場合は,

#pad(x: 2em, contents)

のようにする.contents のところは実際の文章というか表示したい文字列を記入する部分である.

ところが,これを利用して

#show math.equation: it => pad(x: 2em, [#it])

のようにしてしまうと,何ということでしょう!文中に埋め込むインラインモードの数式が使えなくなってしまうのである.つまり,この show ルールを入れてしまうと,pad 関数が block レベルのコンテンツを吐き出すせいか,block 仕立ての数式,つまり別行立て (display) の数式としてしか表示されなくなってしまうのである.

それはそれで意図していない事態であって,どげんかせんといかん.

結論として,あまりエレガントな解決策とは言い難いが,自前の fleqn という関数を次のように定義することとする.

#let fleqn(it) = {show math.equation: set align(left)
pad(x: 2em, [#it])
}

こうすることで,デフォルトの別行立て数式表示の中央揃えの設定はそのまま残すことになり,数式のインライン表示も問題なく,自分好みの2文字分のインデントにぶら下がった左揃え数式を表示したければ,

#fleqn($ a (b+c) = a b + a c $)

のように書けばよい.ここで,引数は別行立て数式の書き方をそのまま使用することにだけ注意していただきたい.最初の $ の直後と,最後の $ の直前に半角スペースを入れなければならないのである.

※ では半角スペースを入れなければインライン表示になるか?というとそうはならない.pad は block を扱うため,半角スペースを入れ忘れても別行立ての表示で出力される.では何が違うかというと,別行立てのくせにインライン表示になるのである.例えば分数の表示が,文字が小さいバージョンになったりする.私は,個人的にインラインは $x/y$ で,別行立ては $$x/y$$ で書くような仕様の方が良かったのに,と思っている.スペースは数式を編集している途中ですぐ消えるからねぇ.案外煩わしいのれす.

ともかく,悲願の一つであった数式の左寄せが Typst でもちゃんと実現できることがわかったので朕は満足しておるぞよ.

小島順の数学教室

小島順先生の個人サイト『小島順の数学教室』が,レンタルサーバとの契約が更新されていないようで,アクセスできなくなってしまった.

archive.orgWayback Machine で探したところ,見つかったのでここに記しておく.


つい最近,昨年に瑞宝中綬章を受章された東京工業大学名誉教授の井上 淳(あつし)先生のホームページも Wayback Machine でめっけたので,そのときに培った検索スキルが活きた.

二か月にも渡る春季休業期間中のネットサーフに明け暮れただけの日々も,そう捨てたものではなかったようだ.

Typst: ドイツ語入力環境を整えるの巻

私が普段使用しているのは当然のことながら日本語入力モードである.半角英数入力モードで英語の文章の記述に不便はないが,英語にないアクセント記号が使われるドイツ語やフランス語の入力には不向きである.

LaTeX ではテキストモード用のアクセント記号の命令が備わっている.例えば

Hölder

と表示させたければ H\"older のように書けばよい.

ところが,Typst は新しいシステムだからこそ,Unicode 文字が使えるんだからテキストモード用のアクセント記号の命令はわざわざ必要ないよね,といった立場らしい.

数式モード用には accent という関数があって,$accent("o",dot.double)$ と入れれば ö と表示される.$accent("o",diaer)$ でも全く同じ結果を得る.ただし,適用されるのは数式モード中でのテキスト用のフォントであって,それを show ルールでテキスト用のフォントと同一のものに設定したとしても,微妙に濃い(weight が大きい)気がする.

このようなわけで,自前で ö を表示するマクロないしはエイリアスのような簡便なコマンドを用意できれば便利であろう.

そんな夢を叶えてくれるのが show ルールである.

実は show ルールを使いこなすのが Typst 攻略の鍵だと睨んでいるのだが,show マスターへの道はまだまだ険しい.

今回提案するのは次のような show ルールを追加することである.

#show "oe" : it => "ö"

これは,Typst のソースファイル内で oe という文字列を見つけたら,それ (it) を ö という文字(列)で置き換えたものとして処理する,という規則である.これは大変便利で,ö の代替記法である oe を地の文で使用し,それを正しい ö で置き換えることにするわけだから,入力した文とコンパイル結果との間の齟齬はほぼない,理想的な解決策といえよう.

なお,現在のドイツ語正書法では ss を eszett,すなわち ß の一字で表すものらしいのだが,それに関しては,例えば

#show "sss": it => "ß"

とする苦肉の策がある.もしあらゆる ss を ß と記すというほどに徹底した規則なのであれば,"ss" そのものを "ß" に置き換えてしまうルールにするのが合理的であろう.私は日和って sss にしただけである.

こうすると,例えば Typst のソースファイルに

Gausss
Weierstrasss
Grasssmann

と記した箇所は,コンパイル時に

Gauß
Weierstraß
Graßmann

となる.

一般次元 Euclid 空間の線形代数的な扱いの先駆をなした著作『外延論』が世に受け入れられなかった Hermann Graßmann はその後言語学に転身したとのことであるが,彼は自身の名字である Grassmann を Graßmann と綴るのが正式であるという見解を持っていたそうである.

それを Grasssmann などと綴るのは邪道の極みであろうから,彼の御霊が感知しないことを祈る他ない.


もう一件,ドイツ語の文献で見られる gesperrt と呼ばれる語句の強調表示に関する自前の関数を次のように定義する方法も報告しておく.

Typst の text 関数には tracking という文字間の間隔に関する設定項目があるので,それを利用し,例えば

#text(tracking: 0.2em)[gesperrt]

と記すと,コンパイル結果が

g e s p e r r t

のような見かけになる.ネットでちょっと調べた感じだと,間隔は 0.2em くらいが相場らしい.

この強調手法は本文中に頻繁に出てくるわけではないだろうから,出てくるたびにこのように記述するので充分対応可能ともいえようが,あえて次のようにマクロを定義するのも一つの行き方であろう.

#let gesperrt(word) = text(tracking: 0.2em)[#word]

こちらは let バインディングと呼ばれる構文を用いている.等号の左辺で,関数名が gesperrt であるような新しい関数を宣言している.その引数を仮に word と記している.

等号の右辺にその新しい関数の定義が既存の関数 text を用いて述べられており,text の tracking パラメータを 0.2em と設定した状態で,引数の word を加工せよ,といった意味合いになる.ここでは引数の値を参照するため,#word とする習わしらしい.([ ] はマークアップモードを意味するので,その内部で #word の部分を関数 gesperrt の引数として与えられた文字列で置き換えるということであろう.) 

この命令を記したあとでは,

#gesperrt[Deutsch]

などと記せば

D e u t s c h

となる.あっ,この例は良くないのかな・・・?文字間に隙間をいれる強調法では,特別なアルファベット列は分割せずに一字扱いするらしいので,上の例は適切ではないかもしれない・・・.

プライムは大変便利な記法であるんだけれども

合成関数の微分公式の書き表し方は案外悩ましい。

三角関数や対数関数のように関数を表すための固有ラベルが確立されている場合は,

(sin(ln))' = sin'(ln) ln' = cos(ln) 1/x

のように書くのがよろしいかもしれないが,1/x のところで急に独立変数(入力)らしき文字 x が現れるのはよろしくない。

入力された 0 以外の実数 x に対してその逆数 (reciprocal) 1/x を対応させる関数を rec とでも表せば,ln ' = rec のように表せる。

この辺りの話をつつきだすと小難しすぎて教育的といえるかどうかはなはだ心もとない。まさに藪蛇といえよう。

ただ,もう21世紀も四半世紀が過ぎようというところなわけだし,関数型プログラミング言語なるものが世に出回って久しい。その時流にうまく乗って,情報系の学科あたりからプログラミング言語的な記法を学部教育からじわじわと取り入れてもいいんじゃないかと思わなくはない。なんというか,プログラミング思考に基づいたというか,データをどう処理するかや,その処理の流れをどう記述するかといったことに重点をおいた微積分や線形代数のテキストが書かれてもよい時期に来ていると思う。ただし,そういった攻めたテキストは画期的過ぎて受け入れられずに終わる可能性は高いし,既存の記法との断絶をどう滑らかに解消するかという永遠の命題と思われる課題も頭痛の種となる。

しかし,(f(g(x)))' = f'(g(x))g'(x) のように合成関数の微分公式を示すのはまやかしであろうな。

この等式に現われる x に具体的な数値を代入することは許されるのだろうか?

例えば x に 2 を代入すると,左辺は (f(g(2)))' となって,これは定数 f(g(2)) を微分したものだから 0 となるようにしか解釈できない。それなのに,右辺は f'(g(2)) も g'(2) もそれぞれ f や g の特定の点における微分係数を表すととるのが普通であろう。そしてそれらの積は一般に 0 とは異なる値をいくらでも取り得る。

そもそも,f'(x) と (f(x))' とは同じものを意味するのか,はたまた異なるものを表すのか。

もし両者が同じだと主張するのであれば,先ほどの公式における f'(g(x)) のところを (f(g(x)))' と書いてもよいということにはならないか?

その解釈でよいのであれば,それは公式の左辺と全く同じになり,合成関数の導関数と,中身の g と,外側の f の導関数との合成関数とをこの記法では区別できないこととなる。

現状としては,合成関数の微分公式は,左辺は右辺で定義するんですよ,という (f(g(x)))' なるアブない記法の意味に関する取り決めと解釈せざるを得ない。

この辺りのことは,数式処理の業界ではどのように解決しているのだろうか。

私はそんな基本的なことすら知らないのだが,そこでは上に述べたような問題に折り合いがつくような書式が開発されているのは当然であろう。そしてそれは人類の叡智の結晶に他ならないのだから,微積分の理論に逆輸入するのもやぶさかではなかろう。

慣習の継承と記述様式の合理化というのはどうしても対立する命題といった構図を避けられないが,そもそも既存の理論に限定したとしても,「完全に合理的」といえるような数学や科学理論の記述様式は原理的に可能なのであろうか。

合成関数の微分公式をどう書き表すか一つとっても背後には数学や科学,はたまた哲学の基礎論で論じられているであろう根源的な問題が潜んでいるのである。

この悩ましい問題を見て見ぬふりして今年度も私は担当クラスでごまかしつつ教えていく。

AIすごいな~!

「私は朝に軽くお掃除をしています」と書こうとして,
「私は朝に軽く大掃除をしています」と書き間違えたとしよう。
下の文章が通常の日本語としておかしいことを AI は理解できるだろうか。

一読して,「軽く」「大掃除」をするというところに違和感を覚えるであろう。

我々ヒトならばすぐに気付けるこのちぐはぐさを AI は正しく捉えることが出来るだろうか。

答えは・・・イエス

Windows 11 に常駐している Copilot というサービスで

『(下の文)という文章はおかしいですか?』

と尋ねたところ,実に的確にどこがどうおかしいかを指摘してくれた。

その上,こちらが頼んでもいないのに元の文をどう書き換えるのが適切かを自然な例文とともに提案までしてくれる。

2025 年の 4 月上旬にはこんなところまで進んでいるのか!

2 年前だっけ,Ghat GPT の新バージョンがリリースされて,とてつもなく高性能になっていたため,各大学が急遽それらの AI ツールの助けを借りたレポート課題の作成等に関する声明を表明する騒ぎになったことを思い出す。

その年度の後期に学部初年級対象の微分方程式の授業内で出題された問題を AI に解かせようとしたら満足のいく解答が得られなかったという話を学生から聞いたことがある。

それがどんな問題だったかは思い出せないが,試しに

dy/dx = y/(x+y)

という,いわゆる同次形であって, u=y/x のような変数変換を行って変数分離形へと帰着させるタイプの問題にしてみたところ,Copilot は得意げにその手続きでもって解いてみせたのであった!

変換後の u と x の関係式を導くところまで,すなわち,u に y/x を代入して y と x の関係式に直す手前までの計算過程をステップ毎に分割した箇条書きで丁寧に示してくれた。

ちなみに,数式の表記は分数を \frac{y}{x+y} のように記す LaTeX 方式であった。それを MathJax もしくは KaTeX で組版したファイルを表示してくれればもう文句はない。

Copilot に対して「すばらしい!」と賛辞を送った上で,u を y に直す計算の続きをしてほしいとねだったところ,またもや得意げに続きの計算を箇条書きに分けて述べた後に,他にも解いて欲しい問題があったらいってくれと催促された。

「あなたの解答を KaTeX で表示してくれませんか?」のように聞いたら,質問の仕方が悪いようでこちらの意図は通じなかった。LaTeX 記法の解答を短く再編集したものを答えただけだった。

ついでに Copilot が示してくれた模範解答を Typst の記述に直したらどうなるかも尋ねたのだが,

#set math on

という新鮮な出だしから始まるサンプルコードを答えてくれた。

これはどこから引っ張り出してきた知識なのだろうか?

ソースコードクリップボードにコピーできる仕様なので,試しに Typst の web エディタにそのまま貼り付けてみたが,当然のごとくコンパイル・エラーになった。

やはり AI の答えを鵜呑みにしてはならない。

改めて,我々が素朴に捉えている「知識」という概念を見直さなければならないという気にさせてくれる体験であった。