数学ガールのミルカさんが「こうなる」とひと言発する間にやっていること(ウラムの螺旋)

4797374152結城浩『数学ガールの秘密ノート 整数で遊ぼう』(SBクリエイティブ, 2013)(索引あり・参考文献リストあり)にウラムの螺旋が出てきます。

100くらいまで描いたところで、

「あ、あたしっ、この先にも興味があります。ぐるぐるぐるぐるぐるぐるぐる……とずっと続けたらどんな図形が表れるんでしょう」

と言うテトラちゃんに応えて、

「こうなる」

と言ってミルカさんがかなり大きなウラムの螺旋を見せています。(p.70)

「ウラムの螺旋」で検索すればぱっと出せそうな気もしますが(インタラクティブなものなんかも)、本書で描かれているのは1から始まるよくある螺旋ではなく、0から始まる螺旋なので、そうでもないかもしれません。そもそもミルカさんは、「こうなる」といいながらウェブ検索をするキャラではありません。

ですから彼女は、「こうなる」とひと言発するわずかの時間でウラムの螺旋を描くスクリプトを書いているんだと思うのです。(彼女はノートPCを持ち歩いている設定でしたっけ?)

そんなことができるのかと思って最初に思いつくのはこんなスクリプトです(Mathematica)。

spiral[size_, start_] := With[{center = Ceiling[(2 size - 1)/2]},
  Module[{
    m = Table[start, {2 size - 1}, {2 size - 1}],
    i = start},
   Do[
    Do[m[[r, center + k]] = ++i, {r, center + k - 1, center - k, -1}];
    Do[m[[center - k, c]] = ++i, {c, center + k - 1, center - k, -1}];
    Do[m[[r, center - k]] = ++i, {r, center - k + 1, center + k, 1}];
    Do[m[[center + k, c]] = ++i, {c, center - k + 1, center + k, 1}],
    {k, 1, size - 1}];
   ArrayPlot[PrimeQ[m] /. {True -> 1, False -> 0}]]]

これで「spiral[4, 0]」などとすればウラムの螺旋を描けますが、会話のテンポはかなり遅くなるでしょう。

会話のテンポを自然なものに保つためには、もっとコンパクトなスクリプトを書けなければなりませんが、すぐには思いつきません。(かつて書いたスクリプトがノートPCに保存してあった?)

というわけで、彼女は優秀な高校生だという物語の設定は、そのとおりだと思いました。

会話形式で書かれている数学ガールには、会話のペースに合わせてできるものだろうかと考えながら読む楽しみがあります。

せっかくなので、サイズを大きくしたときの変化を見てみましょう。

Animate[spiral[size, 1], {size, 1, 100, 1}]

サイズを大きくしたときの変化

中心の数を変化させたときの様子も見てみましょう。

Animate[spiral[50, start], {start, 0, 100, 1}]

中心の数を0から100まで変化させた様子

Wolfram CDF Playerがインストールされていれば、インタラクティブに調べられます。


関数の値の補間方法

学生向け

「関数の値を補間するプログラムで遊ばせたら、補間のアルゴリズムが複雑だったせいか、伝えたかったことがまったく伝わらなかった」という話を聞いたので、ちょっとやってみました。

Manipulate[
 f = Function[{x}, 1 + Sin[a x]];
 start = -Pi;
 end = Pi;
 
 (*サンプリング*)
 samples = Table[{x, f[x]}, {x, start, end, 2 (end - start)/n}];
 
 (*補間*)
 g = Interpolation@samples;
 
 (*描画*)
 plot1 = Plot[f[ x], {x, start, end}, PlotLabel -> "Original"];
 plot2 = ListPlot[samples, PlotLabel -> "Samples"];
 plot3 = Plot[g[x], {x, start, end}, PlotLabel -> "Interpolating Function"];
 GraphicsGrid[{{plot1}, {plot2}, {plot3}}],
 {a, 1, 32, 1},
 {{n, 32}, 1, 64, 1}]

CDF Playerがインストールされていれば実際に動かして試せます。


上から、オリジナルの関数・サンプリングデータ・補間結果です。

要は「サンプルをたくさん取ればいいってもんじゃないよ」という話で、標本化定理とかにつなげたかったのでしょう。そういう場合はMathematicaでやるのが簡単です。「補間」自体について学ばせたいときは、Javaのような低レベルな言語を使ってもいいでしょう。

Wolfram CDF PlayerをMathematicaとして使う方法

2017年12月の時点で、ここで紹介する方法は実現困難になっているようです。

http://www.unfindable.net/umm3/

計算可能ドキュメント形式(Computable Document Format, CDF)を閲覧するためのソフトウェアWolfram CDF PlayerとMathematicaの関係は、Portable Document Format (PDF)を閲覧するためのソフトウェアAdobe ReaderとAcrobatの関係に似ています。Wolfram CDF Playerで閲覧可能なCDF文書を作るにはMathematicaが、Adobe Readerで閲覧可能なPDF文書を作るにはAcrobatが必要です。

しかし、CDFとPDFには大きな違いがあります。PDF文書は内容が固定された静的な文書であるのに対して、CDF文書は内容を変化させられる動的な文書です。下はCDF文書の簡単な例です。Wolfram CDF Playerがインストールされている環境なら、aの値を変えながらSin[a x]をプロットしてみることができます。CDF文書の内容は計算によって変化するのです。


Sin[a x]のaの値を変えられるなら、もっと大胆に「Sin[a x]」という式全体を変えられるのではないかと考えるのは自然でしょう。Mathematicaの式を処理できるCDF文書、それはMathematicaとして使えるCDF文書です。使い勝手は多少悪くても、「Mathematicaを使いたいけれど高すぎて買えない」という人にとっては有用でしょう。みんな大好きWolframAlphaも、Mathematicaのすべての機能を使えるわけではありませんし。

残念ながら、直接的な方法はうまくいきません。CDF文書に入力できるのは数値だけであり、「Sin[a x]」のような文字列は入力できないからです。しかし、コンピュータ上で表現されるすべてのものは、メモリ上では数で表現されています。「Sin[a x]」のような式ももちろん数で表現されています(メモリのことがよくわからない人は、ゲーデル数を思い出してもいいでしょう)。ですから、Mathematicaの式を一度数値に変換してからCDF文書に入力し、CDF文書内でそれを元に戻すというような工夫をすれば、CDF文書で式を扱えます。このアイディアを実現したのが、以前紹介したUniversal Mathematica Manipulator (UMM)です。

UMMには、Mathematicaの式を変換してできる数値が長大なため入力に手間がかかるという問題がありました。Wolfram CDF Playerには、文書上でクリップボードからの貼り付けができないという制約があるため、長大になる数値をCDF文書上で入力するための面倒な仕掛け(VBScriptやAppleScript)が必要でした。(Mathematicaに付属するCDF Playerなら貼り付けられます。このように仕様がばらばらなことが後で混乱を生まないことを祈ります。)

ここでは別の方法を紹介します。

まず、Wolfram CDF Playerをインストールします。これがなくては始まりません。

次に、PHPを使えるウェブサーバをlocalhostに用意します。WindowsならXAMPPを導入するのが簡単でしょう。

下のような内容のexpression.phpをhttp://localhost/umm3/expression.phpというURLで呼び出せるようにしておきます。ディレクトリumm3は、ウェブサーバから書き込めるようにしてください。

<?php

$file = 'expression.txt';

if (isset($_GET['body'])) {
  file_put_contents($file, $_GET['body']);
  echo $_GET['callback'].'()';
} else {
  if (is_file($file)) echo file_get_contents($file);
  echo '(* OK *)';
}

PHPのmagic_quotes_gpcがOffであることを確認します。XAMPPの場合はデフォルトでOffになっています。Macの場合はphp.iniを編集してApacheを再起動する必要があるかもしれません。

http://www.unfindable.net/umm3/にアクセスします。

お約束ですが、上の手順がよくわからない人は、拙著『Webアプリケーション構築入門』などを参照してください。

以上の準備ができたらhttp://www.unfindable.net/umm3/にアクセスします。ピタゴラス3体問題のような比較的大きなプログラムも実行できることを、Wolfram CDF Player 8.0.4(Win, Mac)で確認しています。

Audio Function Generator


4873114837Wolfram CDF Playerがインストールされていれば動きます。RSS Readerでは何も見えないかもしれません。

With[{functions = {Sin,
    TriangleWave[#/2/Pi] & -> "Triangle",
    SawtoothWave[#/2/Pi] & -> "Sawtooth",
    SquareWave[#/2/Pi] & -> "Square"}},
 Manipulate[Play[
   volume1 function1[2. Pi frequency1 t] +
    volume2 function2[2. Pi frequency2 t] +
    volume3 function3[2. Pi frequency3 t],
   {t, 0, 3}, SampleRate -> sampleRate],
  {function1, functions},
  {function2, functions},
  {function3, functions},
  {{frequency1, 440}, 20, 8000},
  {{frequency2, 550}, 20, 8000},
  {{frequency3, 660}, 20, 8000},
  {{volume1, 0.5}, 0, 1},
  {{volume2, 0}, 0, 1},
  {{volume3, 0}, 0, 1},
  {{sampleRate, 8000}, 1000, 44100}, ContinuousAction -> False]]

ボリュームは相対評価です。

簡単な画像処理でライフゲームの初期データを作る方法

Mathematicaにはセルオートマトンのための汎用関数が用意されているので、簡単にセルオートマトンの一種であるライフゲームで遊べます。

しかし、初期状態を用意するのが面倒なので、ウェブの画像から初期状態を作ってみましょう。やり方は、QRコードの数値化と同じです。画像処理なんかしなくても、LifeWikiを探せば有名なものはだいたい見つかるでしょうが、こういうことは、別の機会に役立つかもしれません(Wolfram CDF Playerがインストールされていれば実際に動かすことができます。RSS Readerでは何も見えないかもしれません)。

(* 画像を読み込む *)
gun = Import[
   "http://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Game_of_\
life_glider_gun.svg/610px-Game_of_life_glider_gun.svg.png"];

(* 白黒にし、数値化する。 *)
data = ImageData@Binarize@gun /. {0 -> 1, 1 -> 0};

(* 同じ値がいくつ続くかを調べる *)
unit = Take[Union[Flatten[Length /@ Split@# & /@ data]], 2];

(* サンプリングし直す *)
init = data[[Min@unit + 1 ;; Length@data ;; Total@unit, 
    Min@unit + 1 ;; Length@data[[1]] ;; Total@unit]];

(* アニメーションにする *)
ListAnimate[ArrayPlot /@
  CellularAutomaton[{224, {2, {{2, 2, 2}, {2, 1, 2}, {2, 2, 2}}}, {1, 1}}, {init, 0}, 150]]

Ver. 11.1以降では,最後の部分を次のようにも書けます。

(*アニメーションにする*)
ListAnimate[ArrayPlot /@
  CellularAutomaton["GameOfLife", {init, 0}, 150]]


この方法にも限度はあるので、人類が作り上げてきたものを堪能したいという人は、Gollyのような専用ソフトウェアがおすすめです。