ブログ

Juliaでラマヌジャンの数式を味わう

好きな数学者

こんにちは。PM兼データサイエンティストのOです。
突然ですが、好きな数学者は誰かと問われれば皆さんは何と答えるでしょうか。100年かけてもまとめられないほどの論文を残し、最も美しいと言われる等式の名前の由来にもなったオイラーでしょうか。統計学を含むほとんどの近代数学の分野に影響を与えたというガウスでしょうか。「悪魔の頭脳」の持ち主といわれたフォン・ノイマンでしょうか。あるいは数学のような純粋な学問においてはこのような属人的な問いはナンセンスなのかもしれません。それでも僕は好きな数学者は誰かといわれたら、ラマヌジャンであると答えます。

異才の数学者・ラマヌジャン


ラマヌジャンは20世紀初頭に活躍したインド出身の数学者です。詳細な説明はWikipediaなどに譲るとして、何故僕がラマヌジャンが好きかと言う話をすると、それは高校生のときに何かの物の本で彼が発見した公式の数々を見て以来、その摩訶不思議な魅力にすっかりとらわれてしまったからです。ラマヌジャンが発見した数式には以下のようなものがあります。

$$\sqrt{1+2\sqrt{1+3\sqrt{1+4\sqrt{1+…}}}} = 3$$
$$(6a^2 -4ab +4b^2)^3 + (3b^2 +5ab -5a^2)^3  \\ = (6b^2 – 4ab + 4a^2)^3 + (3a^2 + 5ab – 5b^2)^3$$
$$1+9(\frac{1}{4})^4 + 17(\frac{1\cdot 5}{4 \cdot 8}) + 25(\frac{1 \cdot 5 \cdot 9}{4 \cdot 8 \cdot 12})^4 + \cdots = \frac{2\sqrt{2}}{\sqrt{\pi}\Gamma^2(\frac{3}{4})}$$

これらの数式の中には簡単に証明できるものもあります。しかしそもそもラマヌジャンは一体どうやってこれらの式を見出したのでしょうか。\(2\cdot3^2\cdot7\cdot11\cdot19\cdot127\cdot163\)が\(545140134\)であることを理解するのは簡単ですが、\(545140134\)が\(2\cdot3^2\cdot7\cdot11\cdot19\cdot127\cdot163\)であることを理解するのははるかに難しいです。それと似た、というかそれ以上のレベルの話で、ラマヌジャンの発見には演繹的に説明できない何かがあります。ラマヌジャンは西洋風の体系的な数学教育を受けていなかったので、証明を残さず、「寝ている間に女神が教えてくれた」などと言いながら奇想天外な公式を発見していきます。数学者の藤原正彦氏もラマヌジャンを「『なぜそんな公式を思い付いたのか見当がつかない』という天才」と評し、「ラマヌジャンの公式群に限ると、その大半において必然性が見えない。ということはとりもなおさず、ラマヌジャンがいなかったら、それらは百年近くたった今日でも発見されていない」と書いています1。「異才」という言葉がこれほど似合う人はいないと思います。思うにラマヌジャンは余人のものとは根本的に異なる思考の方法を持っていたのではないでしょうか。その謎が解き明かされることなく、ラマヌジャンは32歳で夭逝してしまいます。何とも惜しまれることです。

プログラミング言語Julia

ところで皆さんはJuliaというプログラミング言語はご存知でしょうか。Juliaは比較的新しい言語で、汎用性を持ちつつ数値計算や統計に適したものを目指しているようです。ここ最近人気が急上昇しているらしいです。データサイエンティストにとっては注目に値する言語といえるでしょう。Juliaの特色の一つは他のプログラミング言語よりも数式を数式らしく記述できることです。こうした特徴はラマヌジャンの独特な数式を数値計算してみるのにうってつけではと思いたち(変わった数式を見ると数値計算してみたくなりますよね?)、ラマヌジャンとJuliaの魅力を伝えるべくこの記事を書き始めた次第です。

円周率の公式

ラマヌジャンの業績のなかでも特に知られているのは以下の円周率に関する公式です。
$$\frac{1}{\pi} = \frac{2\sqrt{2}}{99^2}\sum_{n=0}^{\infty}\frac{(4n)!(1103 + 26390n)}{(4^n99^nn!)^4}$$
うーむ、相変わらず不可思議な数式です。彼は一体どうやってこんな数式を思いついたのでしょう……。モジュラー関数の考え方に基づいているそうですが、僕の理解では到底及びません。ちなみに彼は例によってこの数式を証明なしで提示しました。この数式は数値計算の結果から正しいだろうと予想されていましたが、正式に証明されたのは発見から半世紀以上後のことでした。

前置きはこのぐらいにして、早速Juliaでこの数式を実装してみましょう2

function approximate_pi(N)
    sum = 0
    for n in 0:N
        n = big(n)
        sum += factorial(4n) * (1103 + 26390n) / (4^n * 99^n * factorial(n))^4
    end
    return 99^2 / (2 * sqrt(big(2)) * sum)
end

比較のために、同様のコードをPythonで書いてみました。

def approximate_pi(N):
    sum = 0
    for n in range(N + 1):
        sum += math.factorial(4 * n) * (1103 + 26390 * n) \
            / pow((pow(4, n) * pow(99, n) * math.factorial(n)), 4)
    return pow(99, 2) / (2 * math.sqrt(2) * sum)

この例を見るといかにJuliaが数式を数式らしく記述できる言語であるかがおわかりいただけるのではないかと思います。

  • 数値リテラルと変数の積を表現する際に、間にある*を省略できる
  • ^はビット演算子ではなく冪乗を表す
  • モジュールなどを読み込まず組み込み関数だけで階乗や平方根が表現できる3

こうした特徴がJuliaを数式と相性の良い言語にしているといえるでしょう。一方でPython 3と違って整数リテラルはデフォルトでbig intにならないのが少し不便に思えます。コード例の4行目でbig(n)としているのはそのためです。

総評

複雑な数式を記述する際にJuliaが便利であるという話でした。Juliaやラマヌジャンの数学の面白さが少しでも伝われば筆者にとって望外の喜びです。

株式会社フライウィールは、数学や新しい技術が好きなデータサイエンティストやエンジニアを積極採用中です。お気軽にお問い合わせください。オフィス見学もできます。
https://www.flywheel.jp/

 

Notes


  1. 藤原正彦, 天才の栄光と挫折 数学者列伝, 文春文庫, 2008
  2. もちろん純粋に数値計算が目的ならbinary splittingを使うなどもっと良いやり方はあるのですが、今回は数式をコードに起こすのが趣旨なのでご寛恕ください。
  3. 本当は”!”で記述できると良かったと個人的には思うのですが……。まあ”!”には他の用途が定着しているので難しかったのでしょう。