このブログ内を検索可能

2017年12月16日土曜日

雑記 実験数学について

我々の大学では、実験数学というものがある。これは我がもっとも好きな科目?であり、もっとも得意な分野である。その理由は単純で、RPGを作ろうとしていたから、それに尽きる。

実験数学は、mathematicaという数学の計算などを行ってくれるソフトを用いて、数学の諸問題を解決したり可視化したりして興味を深める、といった内容。現在は実験数学2という科目名である。1のほうはmathematicaではなく、C言語だったので、難しく感じた。よくエラーを返された。コアダンプって何やねん…。シンタックスエラーとか、非void関数の終わりがどうとか…。

その点mathematicaは扱いやすくて助かる。たまに評価が延々と続いてフリーズすることがあってカーネルを強制終了せねばならんことがあるが。

さて、暇なので今回はその実験数学の面白さについて触れていく。

12月15日に行われた講義では、Newton-Raphson法による解の近似である。
ラプソーンらしいが、どこにも紫色の巨体は出てこなかった…。

まあ早い話、大学入試にたまに出てくる題材、Newton法に関すること。ある一定の条件下ならば、
まず適当にy=f(x)上で、x=x0とでもしておいて、(x0,f(x0))上での接線とx軸との交点をx1として、以下この操作を繰り返すと解(根)にたどり着く、というもの。
以下はそのプログラムを与えているらしく、これを解釈して、その後いろいろ引数を変えてみて実行して挙動を調べよ、というのが課題。
 さて、このプログラムを解釈すると、まずnewtonというのは自分でこれから定義するプログラムで、その後に続くfunc,x0,nは引数を与える。その後の:5は知らん。
Moduleは、この関数内でのみ引数内の関数を定義する、という関数。
その後、dfは普通に点(x,f(x))での微分を与えている。Dというのは、すでに組み込まれた関数である。なので正直、この関数の作成はあまり重要ではない。
次のxLとxRは、のちにかかわってくるグラフの描画範囲を指定している。
これはPlotで、xの範囲をxL-0.5からxR+0.5、すなわちちょっと余裕をもたせて描画していることからわかる。
次にDo関数。これは、n回Do内のプログラムを実行せよ、ということで、最後の{n}がどうやらn回、に相当するっぽい。
そしてDo内のpointsは、Do内の操作が行われるごとに、Join内のリストを付加せよということになっている。これは、最終的に解に漸近していく様子を記すために必要。
なので描画をせず解だけ近似するなら、道中のリスト(座標)の保存は不要。
次のxnewとxoldはただ単にNewton法の考え方を漸化式で表現しているだけ。
xLとxRをそれぞMin,Maxとするのは、もっとも離れている部分を全体のグラフに抑えるための処置。その後の{n}は先ほど説明したとおり、Doの2つ目の引数。

その後のPrint以降は描画処理を担う。
まず”x=”という文を表示せよ、そしてその後に続けてN以下を表示せよ、ということ。
Nは数値を与えるので、最終的には出力がx=●(●は数値)という形で出力されることを示唆する。
N以下の部分は、先ほどDoごとに2つのリスト(具体的には、接線とx軸の交点と、そのx座標上でのグラフの交点の2つ)から、Last(最後)の[[1]](1つ目)を取れという命令。これはつまり、最後は(●,f(●))となっていて、そこから一つ目、すなわち交点のx座標(=解の近似)を取って来いといっている。なのでもちろん最後から2つ目(●,0)から一つ目[[1]]を取る操作に書き換えても良い。
ただし最後から2つ目を取る、というのがmathematicaにくみこまれた関数上表現が面倒なので、あえて最後のxを使っているに過ぎない。
そしてその後のPlotは、すべてのx軸との交点を表示できるように範囲付きのf[x]の描画を与える。
それ以後は単なるグラフィックに関する付加事項なので省略。
なおこのプログラム、最後に]か何かが抜けているらしい。

こうすることでようやくこのNewton法を可視化することができるようになる。
しかしこの方法がうまくいかない場合もある。それはたとえば適当にx0を定めることにより、x2で再びx0に戻ってくる。そうなれば、これは永久におなじ動きを繰り返し、永遠に解にたどり着かない。

それはこの抗議では具体的には求めなかったが、我は普通に考え出すことに成功した。

簡単のため、y=Sin[x]で考える。これは、見た目2回分の操作で同じ部分に回帰しそうな感じの部分があるので、とりあえず、そのあたりでかんがえてみる。分かりやすいように、原点付近を考える。原点より少し右側に初期x座標x0を与える。今回、三角関数の対称性から、x1が0に関してx0と対称ならば、x2はx0と同じになる、と思った。
すると、x座標がx0での接線は、微分がCos[x0]なので、y=Cos[x0](x)-x0Cos[x0]+Sin[x0]となって、x軸との交点はy=0なので、これを代入する。しかしここで、xの値は0に関してx0と対称、すなわちx=-x0であることに注意すると、方程式2x0=Tan[x0]を得る。当然これは解けない。
ただし、Tanのグラフは原点で傾き1、Pi/2のx座標に近づけば無限大となることを考えれば、必ず0とPi/2の間で交点を持つことになる。その点こそが、このNewton法でぐわああとなる点である。
なお、mathematicaではこの解を探すために、とりあえずは、グラフ2x0-Tan[x0]をPlotし、そこからその解にFindRootという関数でこの値に近づける方法を探る。
これはどうやらPi/4のx座標までは、2x0の増加率が大きいので増えていき、そこから減少しだす。
そしてその後マイナス無限大へ行くグラフだと推測される。(本当は微分を求めてグラフを描くが、ちょっとここでは別の方法をもちいている)
つまり、Pi/4で極大、中間値の定理よりPi/4とPi/2の間に解を持つことが推定され、そのグラフの形状から、Pi/2のほうから近づければいいことがわかる。

実はこれ、Pi/4から近づけるとよくないと思う。なぜなら、グラフがx座標がPi/4からPi/2までは上に凸。FindRootという関数は、まさにNewton法によってその解を求めているので、これをして、はじめのx軸との交わりでPi/2を超えれば、しばらく求めたい解にたどり着けないかもしれない。
(もう求めたい場所にかなり近くとってくれば、Pi/2より右で交わってくれ、以下の方法でうれしいことになる)
それよりかは、Pi/2より少し小さい部分にx0を取れば、グラフの形から明らかに求めたい場所へと向かってくれることがわかる。
(こういう部分こそグラフを用いて説明したいが、自宅のPCにはmathematica環境がないのでできない。)
よってFindRoot内は、初期値をだいたい1.5あたりではじめればよいことが分かる。
そしてこれによって得られた値を上で定義したnewtonという関数にぶちこめば、晴れて永遠と同じ場所を繰り返して動くものが完成する。
まあ実際はFindRootが近似解を出している時点で、かならずNewton法の操作を何回かやれば徐々にずれてきて、結局どこか別の部分に行って解が出て終了、ということになるんだが。

という感じの手法を、我は講義後の数十分で考え出し、これを見事に成功させた。
…が、特に何か意味があるか、といわれれば、ただちょっと面白そうだからやってみた…だけ。
なおTan[x0]=2x0とかみたいな方程式はたしか超越方程式と呼ぶ。

我々数学科はこのようなことを実験数学でやっている。実は何気に普段やっている難しすぎる幾何学や線形よりも、はるかに簡単なのである。もはやこれは、遊びといってもいいほど、あれらに比べれば簡単で、そして非常に面白い。

さて、我がプログラム的思考を得た理由として、趣味にRPG作成をやっていた、と述べたが、実はこのRPGは、RPGエディターというツールで作ったもの。もちろん一般公開はしておらず、基本自分だけで楽しんでいる。
はじめはもう、あまりにお粗末でむちゃくちゃなRPGだった。子供なんだからしょうがない。
ちなみに2010年2月頃これに着手し始めた。実は我、子供の頃から自分の世界を作るのにあこがれていて、ボールペンがすぐなくなってしまうほど、紙に自分の作成したステージを書き綴った。
しかしいつか、これを本当にPCで再現したいと思うようになった。これはyoutubeのvipマリオなどの影響が大きい。そして、我はいろいろ探しているうちに、ついにRPG作成ができるソフトにこぎつけた。これが中学1年生の頃。
後はそこから知識を得て、少しずつRPG作成に重要な変数という概念を学んでいった。
たとえばぷよぷよを例にとる。
これは、たて12マス横6マス。これらそれぞれの変数に0から6の番号を振る。
0は空白、1は赤、2は黄色、3は緑、4は青、5は紫ぷよ、6はおじゃまぷよというように。
そして、ぷよぷよが落下完了するたび、消すかどうかの判定を行う。
左上から右、そして下段というように、72個の変数を順につけるとすると、
1番目は横の2番目と、下の7番目との関係で消えるかどうかの判定をすることになる。
ここで、1番目が1~5の場合、2,7番目のいずれかまたは両方がこれに等しいならば、1番目のぷよを消す、という操作を行う。そのとき2や7番目は、後々消す判定を行うので今は我慢。
次に2番目は、左の1、右の3、下の8で判定。これらを72個全てに繰り返す。
こうすることで、次になにが消えるのかが分かる。
そしてこの一連の動作を、また2連鎖目として行い、消えるぷよがなくなればそこで連鎖、すなわち繰り返しの操作を終了する。(ただしその前になくなったぷよの分、ぷよを下に落とす動作が必要)
このように、ゲームのプログラムでも実は簡単に作成することができる。
だが問題が。

それは、72個の変数に対して、条件を付して消えるかどうかの判定をほどこさねばならない、ということである。これは我もたまったものではない。kを1以上9以下の自然数として
一応楽な方法として、区域を9つに分けて、1番目(左上区画)、2~5番目(上区画)、6番目(右上区画)、7+6k番目(左区画)、12+6k番目(右区画)、67番目(左下区画)、68~71番目(下区画)、72番目(右下区画)、それ以外(中央区画)に分ければ、一応9個分の処理で行うことはできる。
だがRPGエディターにはこれをする方法を見出せず、そのせいで我はこのようなゲームを作ることができない。あまりに面倒なので。

あと、全消し判定は全て72個の変数が0であった場合、アウト判定は3または4番目の変数が0以外であったとき、ぷよの回転はたとえば2×2マスで、上と同じような変数の割り当てだと、最初に0,2,3,2(これは右列黄ぷよ、左下緑ぷよの階段型構成に相当)だったならば、左回転で1番目を3番目に、2番目を1番目に、3番目を4番目に、4番目を2番目にする、という操作で可能となる。
右側も同様にする。これは数学では、置換に相当する操作。
そしてぷよが落下しおわりそうなとき。たとえば3番目が下のぷよにつきそうなとき。左下のぷよ(3番目(3))と、そのぷよの存在する列を考えて、3番目の位置(1~72)に6kをたしていって(つまりひとつずつ下の段を見ていく)、はじめて0でない数字(つまりぷよが存在)が現れたとき、そこがぷよの着弾地点となる。
その0でない数字の6つ前の番号に3番目のぷよは存在し、1番目は当然その上(つまり6番前)、2番目と4番目は瞬時にこれと同様の判定を行って直ちに着弾。
ただこれは3番目の下に空きがあっても、4番目の下に空きが無ければ上の操作は先に4番に対して行われ、あとで3番目の判定が行われる。

その他、ぷよが大量にあって回転ができないときは、回転をしてみてその場所の変数がすでに0以外だったならば形状を変更しない、ただし左回転をした、という操作は記憶する。でないと上下反転の操作ができなくなるので。

このようにして、我ならぷよぷよをプログラムする。すべてゲームをこういう解釈に変更するだけ。実は難しそうに見えて、意外に簡単で楽しい。

なので、DQ10のさいほう最適化ツールなどが高額で売られているが、理論上はこういうのは作れる。だがあれは、1回の操作でいろいろな技能があり、総当りで最適解を探しているようでは全然最適解に近づかない。なのでまだ我にあれをつくることはできない。

こういうのが我の趣味である。昔はメダルゲームのプログラムを演出、画像付きで作ったりもした。
RPGの電車に乗ったりする動作も、こういうプログラムによって成り立っている。
実はひとつのゲームをそこそこ再現するだけでも普通に10000行を超えた。
RPGエディターのコモンイベントを作成する仕事とかがあってもいけそう。

だが我は将来は医学部受験で医者になろうと今は考えているので、こっちはあくまでも趣味程度にとどまっている。たまにこういうネタを英語の講義で、英語で書き連ねてみたりする。
一度ビンゴのプログラムに関してB4用紙?3枚分英語を書いたな…。
そっちの英語はいいのに、もうひとつの英語は単位が「非常に厳しい状態にあると考えてください」状態。はあ…。4年次で卒業できないとその年の受験ができなくなるので、留年は必ず避けねばならない。なにしろこのときのセンター試験が、最後のセンター試験なのだから。
医学部に向けて、3年後だがすでに数学と英語はもう合格の領域に達しているといっても過言ではない。というよりもう現役時代ですでに国立の医学部を除けばそこそこいけるであろう状態だったので、当然英語の能力がアップした今ではそう断言できる。もちろんそれに満足せず、さらなる高みを求めてより受験勉強するが。

だが…。

センター…国語、世界史…うっ頭が

雑記 採点バイトの採用試験結果

本日採用試験終了。
なんか詳しいことを書いたらあかんらしいので、感想だけを書くか…。

適正試験は、まあ、たしかに適正であるかどうかを表していたと思う。

学科試験は、一般では解けないが、高校で数学を習っていればある程度解けるくらい。だが他の人も言っていた通り、時間が少ない。言うのはそれくらいにしておこう…。
この試験内で、我は高校でやったなあ…という内容を回帰した。
難易度は、我にとっては基本レベルばかり。(答えが全部正解だったとは言ってない)

面接は、普通になんの変哲も無い面接だった、と付け加えておこう。
さすがにこの程度なら問題ないだろう。

会場の様子などはたぶん言ってもいいはずなので、(なぜならそれを知ってもあまり問題ないことなので)一応述べておくと、予想外に人数が少なかった。数学を第1志望としていたのは我たった一人。…それくらいか…。

翌日に採用かどうかの通知が来る。もし不採用なら、我はどんだけあかんねん、と悲しくなる。が、さすがにたぶん…ないだろうと見ている。というかそう期待をしている。

友達を紹介するとなんかいいことがあるらしいが、我々の大学だとたぶん別の東進や河合塾に行きそうな気がしないでもないのでやめておく。

それと、そろそろTOEFL-iTPの結果が返ってくるころなんだが…。たぶん11月18日に受けて、1ヵ月後なのでもうそろそろ来てもいいはず…。

→採用かどうかの結果発表。
結果→合格
…ベネッセは受かりやすいと聞いていたので、それほどの喜びはないが、しかしやはりうれしいはず。よって初めて採点バイトをすることになったが、とりあえず期間中に35時間程度入れれば良いらしく(茶色シールは70を超えてもだめで青なら30以下でも受かるとかいう書き込みもあったが)
今回は頑張る予定でいく。

余談だが、面接では我は数学に対する熱意をアピールしたが(もしかすると場違いだったかもしれないが)、中には「お金が欲しいから」という人まで。なかなか…素直でよろしい。