数学の最近のブログ記事

シェルピンスキのガスケットに続き、その姉妹版である、シェルピンスキのカーペットを作成した。以下のとおりである。エキゾチック感はシェルピンスキのガスケットの方があるが、これはこれで安定感があってよく、本当にカーペットのデザインに使えそうである。

なお、シェルピンスキのガスケットのフラクタル次元(位相次元)は、log(3)/log(2) = 1.58496... であり、シェルピンスキのカーペットのフラクタル次元(位相次元)は、log(8)/log(3) = 1.89279...なので、カーペットの方が次元が高い。これは目で見た直観とも一致する。

また、シェルピンスキのガスケットも、シェルピンスキのカーペットも、中抜きして自己同型縮小写像を再帰的に適用しているところに意味があり、中抜きしないと次元は2、すなわちベタっと塗りつぶすことになってしまう。

以下に、C++ビルダのソースコードを示す。
//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop

#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
void Fracta(double p1x, double p1y, double p2x, double p2y, double p3x, double p3y,
 double p4x, double p4y,int level);
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 Close();    
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
 Canvas->Pen->Color = clBlack;
 double a = 20.0;
 double b = 20.0;
 double d = 400.0;
 // 初期位置のセット

 Fracta(a,b, a + d,b,  a + d, b + d, a, b + d,1); 
}
//---------------------------------------------------------------------------

void Fracta(double p1x, double p1y, double p2x, double p2y, double p3x, double p3y,
 double p4x, double p4y,int level)  {
 double a,b,d;
 int depth = level;
 if ( depth > 8 ) return;
 depth++;	

 d = (p3x - p1x)/3.0; 
 
 Form1->Canvas->MoveTo(p1x,p1y);
 Form1->Canvas->LineTo(p2x,p2y); 
 Form1->Canvas->LineTo(p3x,p3y);
 Form1->Canvas->LineTo(p4x,p4y);
 Form1->Canvas->LineTo(p1x,p1y);
 
 a = p1x;  b = p1y;
 Fracta(a,b,a + d,b,a + d, b + d, a, b + d, depth);
 a = p1x + d;  b = p1y;
 Fracta(a,b,a + d,b,a + d, b + d, a, b + d, depth);
 a = p1x + 2.0 * d;  b = p1y;
 Fracta(a,b,a + d,b,a + d, b + d, a, b + d, depth);
 a = p1x;  b = p1y + d;
 Fracta(a,b,a + d,b,a + d, b + d, a, b + d, depth);
 a = p1x + 2.0 * d;  b = p1y + d;
 Fracta(a,b,a + d,b,a + d, b + d, a, b + d, depth);
 a = p1x;  b = p1y + 2.0 * d;
 Fracta(a,b,a + d,b,a + d, b + d, a, b + d, depth);
 a = p1x + d;  b = p1y + 2.0 * d;
 Fracta(a,b,a + d,b,a + d, b + d, a, b + d, depth);
 a = p1x + 2.0 * d;  b = p1y + 2.0 * d;
 Fracta(a,b,a + d,b,a + d, b + d, a, b + d, depth);
 return;
}

フラクタルを勉強していると、最初の方に、シェルピンスキのガスケットというのが出てくる。それは結構有名であるが、画像で示すと以下のようなものである。シンプルながら、なんとなく神秘的な雰囲気もあるこの描画が私は好きである。

最初にフラクタルのことを知った時、シェルピンスキって誰だろうとさえ思いもしなかったが、志賀浩二著「無限からの光芒 - ポーランド学派の数学者たち」日本評論社を読んだとき、シェルピンスキがポーランド学派の偉い数学者の一人であることを知った。

シェルピンスキは1882年に、ワルシャワの有名な医師の息子として生まれた。二つの世界大戦を含む激しい騒乱を生き延びて1969年に87歳で亡くなるまで、ポーランドの大学で数学の顕著な業績を挙げた。その業績には整数論なども含まれるが、なんといってもシェルピンスキを特徴づけるのは、カントールを嚆矢とする無限論、あるいは連続体仮説の掘り下げである。「無限からの光芒 - ポーランド学派の数学者たち」から、例えば、シェルピンスキが証明した次のような定理を掲げてみる。

連続体仮説は、次の命題と同値である:平面R2は、共通点のない二つの部分集合A、Bの和として表される。すなわち、R2 = A∪B ここで、Aはx軸と平行な任意の直線と高々加算個しか交わらず、Bはy軸と平行な任意の直線と高々加算個しか交わらない。

この定理の意味を考えていたら気が遠くなりそうになってきたので、戻ってシェルピンスキのガスケットの表示にもちいたプログラムのソースコードを示しておくことにする。シェルピンスキのガスケットは、私が三十代の前半だった歳の頃もプログラムを作成したが、πの多倍長計算などと比較しても簡単で、ほとんど苦労した記憶はない。なので今回も楽勝かとプログラミングしようとしたら、なんと、正三角形の頂点を結ぶ直線を引く計算でさえ、ええとどうだったっけ、と迷う有様で、この程度のプログラミングもほとんど半日がかりだった。ともかく、動いたC++ビルダのコードを示す。

あ、もう一つ付け加えると、数学セミナー2017年3月号のフラクタル特集号の、梶野直孝氏の「フラクタル上の解析学」と題する記事によると、シェルピンスキのガスケット上でディリクレ形式やラプラシアンが論じられるのだという。ううん、こちらの方もまた気が遠くなりそうである。

//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop

#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
const double pi = 3.14156;
double PosX = 300.0;
double PosY = 300.0;
void Fracta(double p1x, double p1y, double p2x, double p2y, double p3x, double p3y, int level);
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 Close();    
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
 Canvas->Pen->Color = clBlack;
 double P1x, P1y, P2x, P2y, P3x, P3y, Angle;
 double L = 250.0;
 double InitAngle = pi;
 double OffsetAngle = 2.0*pi/3.0;
 Angle = InitAngle;
 P1x = L*sin(Angle);  P1y = L*cos(Angle);
 Angle += OffsetAngle;
 P2x = L*sin(Angle);  P2y = L*cos(Angle);
 Angle += OffsetAngle;
 P3x = L*sin(Angle);  P3y = L*cos(Angle);
 Fracta(P1x, P1y, P2x, P2y, P3x, P3y, 1); 
}
//---------------------------------------------------------------------------

void Fracta(double p1x, double p1y, double p2x, double p2y, double p3x, double p3y, int level)  {
 int depth = level;
 if ( depth > 9 ) return;
 depth++;	

 Form1->Canvas->MoveTo(p1x + PosX,p1y + PosY);
 Form1->Canvas->LineTo(p2x + PosX,p2y + PosY);
 Form1->Canvas->LineTo(p3x + PosX,p3y + PosY);
 Form1->Canvas->LineTo(p1x + PosX,p1y + PosY);

 Fracta(p1x, p1y, (p1x + p2x)/2.0, (p1y + p2y)/2.0,(p1x + p3x)/2.0, (p1y + p3y)/2.0,depth);
 Fracta(p2x, p2y, (p2x + p1x)/2.0, (p2y + p1y)/2.0,(p2x + p3x)/2.0, (p2y + p3y)/2.0,depth);
 Fracta(p3x, p3y, (p3x + p1x)/2.0, (p3y + p1y)/2.0,(p3x + p2x)/2.0, (p3y + p2y)/2.0,depth);
 return;
}

フラクタル

user-pic
0

数学セミナーという雑誌は難解なので、私はバックナンバーとしてしばらく積んでおいて後で眺めることが多いが、2017年3月号は、フラクタルの特集号だった。それで、30代の前半の頃、パソコンでフラクタルの図形を描画したことを思い出した。

私は基本的に特定の本をバイブルのように扱うことはないが、当時、一時的にバイブルのように読んでいた本は、山口昌哉著、「カオスとフラクタル」ブルーバックスだった。私にしては珍しく、ぼろぼろになるまで読んだ。また、シルピンスキーのガスケットや、ジュリア集合などをパソコンで描いた。

そういう時代を思い出しつつ、数学セミナー2017年3月号の、荒井迅氏の「複素力学系のフラクタル」という記事を自分の勉強のために簡単にまとめてみる。

その記事によると、フラクタルFは次のような性質をもつ。

  1. Fには微細構造がある。どんなに拡大しても微細構造があらわれる。
  2. Fはとても不規則で、伝統的な幾何学では記述できない。
  3. Fは何らの意味で自己相似性をもつ。
  4. Fのフラクタル次元は、位相次元よりも大きい。
  5. Fは単純に定義される。

ここで、位相次元とは普通の意味での次元であり、整数値をとる。それは例えば、次元消滅で議論した次元のことである。そしてそこで、集合に次元を定義するには位相を導入するよりないと言ったことが、位相次元と呼ばれることと関係があるのだと思う。

一方、フラクタルの複雑さを測るに適した次元をフラクタル次元と呼ぶが、それにもいろいろな次元がある。そのうち計算が簡単な相似次元は、ある集合が自分自身のm個のコピーからなり、コピーの縮小率をrとするとき、-log m/log rと定義される。

例えば、コッホ曲線は、4個のコピーをもち、その縮小率は1/3なので、相似次元は、-log 4/log (1/3) = log 4/log 3 = 1.261859・・・ > 1となる。逆に3個のコピーをもち、その縮小率が1/4のようなものはありえるのだろうか。それだと相似次元は1より小さくなるが、すると、もしかしていくつかの点に収束してしまうような気がする。少なくともそれはフラクタルとは呼ばれない。

これ以外にもハウスドルフ次元というのがあるらしいが、定義が難しいので、ここでは述べない。

ところで、fを複素数CからCへの写像として、f(z) = z2 + cで、cは複素数の定数というものを考える。

そのとき、K := {z∈C|集合{fn(z)|n≧0}が有界}を充填ジュリア集合と呼び、その境界をジュリア集合と呼ぶ。すなわち、ジュリア集合はzを動かす。

一方、K := {c∈C|集合{fn(0)|n≧0}が有界}をマンデルブロ集合と呼ぶ。すなわち、マンデルブロ集合はcを動かす。

私はまだ、8ビット・パソコンのBASICの時代に、ジュリア集合を描いた記憶がある。ジュリア集合は、選ぶcの値によって、がらっと異なる図形になる。ジュリア集合もマンデルブロ集合も、ある閾値を超える繰り返し回数nに従って、描画する点の色を変えることで玄妙な図形になる。

ジュリア集合やマンデルブロ集合のフラクタル次元がどうなるか、その計算はコッホ曲線などの場合よりもはるかに難しい。このとき、ハウスドルフ次元を使う。

なお、計算可能なc∈Cで、ジュリア集合が計算不可能になるものが存在する、というブレイハーマン-ヤンポルスキーの定理というのがあるらしい。さっぱり意味が理解できないが、ともかく深遠さが窺われる。

その他に、3次元フラクタルとか、経済物理学におけるマンデルブロの研究など様々な記事があるので、じっくり読んでみる。

また、コンピュータによるジュリア集合やマンデルブロ集合の描画もそのうち試してみる。その理論はともかく描画だけなら、素数判定プログラムより楽である。

内村直之著、「古都がはぐくむ現代数学」日本評論社についてメモしていたら、その設立の沿革のところまでで長くなってしまったので、京大数理解析にゆかりの深い個々の数学者の方々について述べられた章は別稿にすることにした。そこで、以下、その、個性的な、あまりに個性的な数学者の方々について、この本に基づき私なりに簡単にまとめさせていただく。

最初に言及されるのは、佐藤超函数で知られる佐藤幹夫氏である。数学ファンの私は、佐藤幹夫の御名は流石に知っていて、ちょっと蔵書を探してみてたら、森本光生著「佐藤超函数入門」共立出版と、日本評論社の「数学のたのしみ - 佐藤幹夫の数学」が見つかったのだが、なんか1ページたりとも読んだ記憶がない。あちゃー、である。で、この機会に近々読もうと思ったのだが、とりあえず、「古都がはぐくむ現代数学」に書かれている範囲を簡単にまとめてみる。

すると、佐藤幹夫氏は、解析学の厳密な代数化を目指した、ということらしい。すなわち、代数幾何学の新しい手法が数論など他の分野にも取り入れられ、大きな変革をもたらしたのだが、それと同じことを解析学でやろうとして構築したのが、佐藤超函数ということらしい。しかし、佐藤幹夫氏はそれだけに満足せず、微分方程式という壮大な数学の世界を超函数でしっかり具体化したかった。

その一方で、佐藤氏は、数論にも深い興味を抱いていた。それは、たとえば類体論の流れで言及した、「類体論と非可換類体論I フェルマーの最終の定理・佐藤-テイト予想解決への道」加藤和也著、岩波書店にもあるとおりである。

佐藤氏は、よくわからない事情で一時数学を離れていた時期もあったのだが、日本に帰ってきて、佐藤超函数に関する研究にいろいろに人が関与しているのを知り、元気づけられたようである。そこで佐藤氏は東大教授に着任し、佐藤スクールが立ち上がった。そして1970年、当時の京大数理解析研所長だった吉田耕作氏に誘われて、京大数理解析研に移った。結局佐藤氏は、1987年から1991年まで京大数理解析研所長を務めて、翌年京大を定年退官した。

ここまで書いてきて、深入りするときりがなく、それは別途勉強することにして、ある程度軽く流すことにした。ただ、後のでのインデックスとなるようにキーワードはちりばめておく。

次は、代数幾何学者の広中平祐氏である。フィールズ賞で記述したことに補足すると、広中氏は、ザリスキーの特異点解消のアイデア、永田雅宜の局所環の理論、グロタンディークの代数幾何における大局観を駆使して、特異点解消の理論を構築したのだという。そして、フィールズ賞受賞後の1975年、京大数理解析研に招かれ、1988年10月2日まで京大数理解析研の教授を務めた。

広中氏の後、広中氏の影響もあって代数幾何学を専攻し、フィールズ賞を受賞した森重文氏は、1990年に京大数理解析研の教授となった。そして、2011年に京大数理解析研所長となった。ただ、いま京大数理解析研のホームページをみると、今の所長は向井茂氏で専門は、代数幾何学とモジュライ。次期所長は、流体力学・応用数学専攻の山田道夫氏なのだという。なかなか目まぐるしい人事だが分野的にバランスをとろうとしているのが分る。

次は数論であるが、私は「古都がはぐくむ現代数学」で、伊原康隆氏の名前を初めて知った。「類体論と非可換類体論I フェルマーの最終の定理・佐藤-テイト予想解決への道」加藤和也著、岩波書店で言及されている「非可換類体論」に関する深い研究があるようである。イハラのレンマは、フェルマーの定理の証明にも使われた。伊原氏は、京大数理解析研の教授に就いて研究だけでなく多くの後進を育成し、2002年に定年退官した。

京大数理解析研で数論といえば外せないのは、ABC予想の望月新一氏である。宇宙際幾何学者を名乗り、いかにも怪しい(妖しい?)雰囲気なのだが、間違いなく天才のようである。

別分野として、京大数理解析研所長を務めた数理物理学の荒木不二洋氏がいる。量子力学は、フォン・ノイマンにより、作用素環論で基礎づけられたが、作用素環論のⅠn、Ⅰ、Ⅱ1、Ⅱ、Ⅲというタイプのうち、仲間外れであまり顧みられていなかったⅢに着目した。日本には作用素環論に関して、「富田-竹崎理論」という素晴らしい理論が誕生した。フランスの数学者、アラン・コンヌは、Ⅲ型を富田-竹崎理論で書き直して発展させ、フィールズ賞を受賞した。

そんな荒木氏の同期に、京大数理解析研教授を務めた場の量子論の中西襄氏がいる。中西氏は、場の量子論を重力まで拡張しようと努力した。そんな中西氏は超弦理論に批判的だった。私が超弦理論を胡散臭いと思っているところがあるのは、以前にそんな中西氏の著書を読んだことによる。

といいつつ、超弦理論の権威の一人、大栗博司氏は、1990年から1994年まで京大数理解析研助教授を務め、その後カリフォルニア工科大学に移り、今ではカリフォルニア工科大学理論物理学研究所所長である。流石である。

あと、外せないのが、確率微分方程式と確率解析の権威、伊藤清である。戦後、秋月康夫によって京大に招聘され、京大数理解析研の初期メンバーの一人となった。伊藤氏は、1969年にコーネル大学に移ったが、1975年に京大数理解析研に戻り、翌年に所長になった。「非線形問題」の空席に、代数幾何が専門の広中平祐氏を招聘するという離れ業を演じたのは、伊藤所長(当時)だった。優秀でありさえすればなんでも許されるみたいな、いい加減さが面白い。

数学とは少し違うが、京大数理解析研において、Kyoto Common Lispを作り上げた強者たちがいる。それが湯淺太一氏らのグループである。また、プログラム基礎論に詳しい中島玲二氏がいた。

戻って、上に次期所長は、流体力学・応用数学専攻の山田道夫氏だと述べたが、京大数理解析研には、ナビエ・ストークスの方程式など流体力学を研究する強力なグループがある。当初の京大数理解析研の流体力学は、後藤金英氏と川原琢治氏の二人だったが、木田重雄氏、岡本久氏が加わって発展した。岡本久氏には、「ナヴィエ‐ストークス方程式の数理」東大出版会という、この分野で日本で唯一の教科書の著書がある。

また、ディープ・ラーニングへの途で述べたように、さいきんはAIというか機械学習が盛んになってきているが、そんななかで、最適化問題を解くことも一層重要視されてきている。京大数理解析研の版図には最適化問題も含まれているのであって、京大数理解析研には離散数学の専門家として、藤重悟、室田一雄、岩田覚らの方々が関与している。こういう数理工学は明らかに新しい数学の種になるだろう。

以上、粒度もまちまちでざっとまとめてみたが、私のいい加減さというか能力不足で、あまりにも杜撰すぎて話にならない。ともかく、折に触れて京大数理解析研のホームページを眺めて、数学の先端のフラグランスだけでも嗅がせていただくとする。

ウェブで何気なく数学の本を眺めていたら、内村直之著、「古都がはぐくむ現代数学」日本評論社というのが目に付き、「古都」と「現代数学」という、ややアンバランスなキーワードの組み合わせに戸惑い、どんな本なのかアマゾンで確認した。するとどうやら、京大数理解析研について解説した本らしい。

けっして熱心とはいえないが、一応数学セミナーの読者である私にとって、京大数理解析研は紛れもなくビッグ・ネームである。しかし私は、その組織の沿革などほとんど知らないので、読んでみようと迷わず注文した。そして読んでみたら、これが予想どおりというか、数学ファンの期待に応えた力作だった。そこで、私の限られた理解力の範囲で、この本を要約してみる。

じつは、数学を専門に扱っている研究所というのは日本でも少ない。そして、私のような単なる数学ミーハーにとってだけではなく、専門の研究者にとっても、京大数理解析研(Research Institute for Mathematical Sciences Kyoto University)は、あこがれの存在らしい。

定員内の教職員は55人、学生数35人程度の小世帯だが、世界でもトップクラスの業績を生み出し続けている。文字通り少数精鋭である。私としては、プリンストン高級研究所や、パリ数理科学財団とも較べてみたいところである。

さて、京大数理解析研の沿革であるが、1957年1月、日本学術会議が、「基礎科学の研究体制確立について」を首相に提出した。それは、五つの綱要からなるもので、私のほうで粗く要約すると以下のとおりである。すなわち、第一要綱は、大学における基礎科学の講座充実。第二要綱は、研究センターの設置。第三要綱は、流動研究員制度。第四要綱は、研究連絡委員会の拡充、強化。第五綱要は、関係各官庁が協力して計画的に遂行されること。

それより7年くらい前、湯川秀樹がノーベル物理学賞を受賞したとき、日本学術会議は迅速に動き、京大基礎物理研究所、東大物性研究所が設立された。ところが、どうしても数理科学は後回しになるのであって、日本学術会議が「数理科学研究所の設立について」という要望を科学技術庁長官に提出したのは1958年のことだった。その仕掛人は、東大教授で数学の重鎮、彌永昌吉である。

彌永氏は、日本において数学の研究は盛んであるが、純粋と応用の間の連携がよくないこと、計算機の研究、計算機を使った研究をこれから盛んにしなくてはならないことを感じていたという。なので小委員会のメンバーも、数学だけでなく、物理学、天文学、数理工学、経済学、数理科学統計などの専門家を含んでいた。

研究所の名前は、仮にであるが、数理科学研究所とされた。そして幸いにも、若い数学者たちも議論に加わり、風通しのよさが発揮された。そして、流動研究員の増員、研究員の意向が人事・運営に反映されること、深い研究を行う熱意と能力をもち全国共同研究に反映される人材を集めること、なるべく広範囲のテーマを取り上げること、人事はすべて公募とし公表すること、他大学との兼任は認めない、などである。それに傾聴したのは、京大の数学の教授で、代数幾何学の権威、秋月康夫だった。彼は、専門の数学だけでなく、オーガナイザーとしても半端なく立派なのだった。

それで、なんとなく応用に傾いているようだけれども、数学者はあまりそれを気にすることはなく、普通にやりたい数学をやればよい。応用は自然に何か出てくるだろう、みたいなニュアンスのようである。

その後検討が進むにつれ、当初の案が次第に縮小されていった。あと、既存の統計数理研究所との折り合いをどうつけるかという問題もある。

別の問題は、研究所を受け入れる大学である。東大がまず打診されたが、東大には既に物性研、核研があり、東大は難色を示した。私からみたら、新しい研究所を抱えるのは名誉なような気がするのだが、それは数学ミーハーにすぎない私の観方で、管理や予算などの負担が大変なのだろう。

それから阪大、東京教育大なども打診されたが、結局、秋月のお膝元の京大が引き受けることに落ち着いた。こうして、1963年4月1日に京都大数理解析研究所が発足した。

初期のメンバーは、以下のとおりであった。

  • 作用素論(関数解析の基礎としての作用素論の研究): 福原満寿雄、初代所長、東大と兼任。常微分方程式論の開拓者。あらっ、兼任しないのはなかったか。まあ、方針が緩くなったのだろう。
  • 基礎数学Ⅰ(代数学と関連する事項を他の部門との関連を目的として研究):中野茂男、複素多様体の解析的研究、調和積分論。
  • 応用解析学Ⅰ(物理学や数学に現れる偏微分方程式の関数解析的方法による研究):荒木不二洋、場の理論の作用素環の研究。
  • 基礎数学Ⅱ(代数学と関連する事項を他の部門との関連を目的として研究):島田信夫、ホモトピー論、一般コホモロジー論。
  • 応用解析学Ⅱ(無限次元解析学という立場から、量子力学、統計物理学の数学的基礎を研究):伊藤清、確率過程論、確率解析。のち、所長を務めた。
  • 非線形問題(物理学や工学に現れる非線形方程式の基礎理論を研究):占部実、常微分方程式、非線形微分方程式の数値解法など。
  • 数値解析(電子計算機によって行う数値計算のための必要な理論の研究):高須達、プログラムの仕様や自動証明など。のち、所長を務めた。
  • 近似理論(物理学や工学に現われる方程式の近似解法の理論の研究):松浦重武、代数幾何と関数解析の手法を用いて定数係数線型偏微分方程式の解の構造を調べた。
  • 計算機構論(電子計算機をモデルとして、広義の計算機機構一般の数学的理論の研究):高須達。

これをみて分るように、かなり応用色の強い内容になっている。また、必ずしも担当の人の専門と、分野が一致しているとは限らない。

しかし、これはあくまでも初期の布陣で、今後どんどん変貌していくのである。すなわち、優秀な人材を迎えるためなら、柔軟に対応していく、ということである。

「古都がはぐくむ現代数学」には、このあと各論のような内容が続くが、長くなったのでここで一旦記事を打ち切り、別稿とする。

ドワンゴ

user-pic
0

数学セミナーは、だいたい4月号がちょっとつまらなかったりする。というのは、4月号は大学の理系の新入生に数学の勉強方法をガイドするという趣旨がメインで、それは高校数学から大学数学へのギャップを埋めるという意味ですこぶる有意義なのだが、その有意義さが却ってベタになってしまう、ということだったりする。

ところが、2017年4月号の数学セミナーは、私のような意見を他の読者からも以前から聞いていたのか、例年と違って一新された、大学の理系の新入生だけでなく、文系の学生や、いまさら数学を勉強したいという社会人に対するガイドともなるような興味深い内容となっていて、うれしかった。

うれしかったのはそれだけではない、なんとドワンゴ会長の川上量生氏へのインタビュー記事があったのである。

ドワンゴは、さまざまな催しを企画してきたと思うが、いまいち世情に疎い私にとってその全貌はみえておらず、一番印象に残っているのは、将棋の電王戦である。将棋もコンピュータも好きな私は、この企画に熱狂して、ドワンゴ、スゲーと思った。

数学セミナーの記事に戻って、川上氏は1968年に愛媛県生まれ、一ヶ月に40冊から50冊もの本を読む子供だったというから相当な読書量だったのだろう。普通の本なら2時間くらいで読んでしまうというのだから、間違いなく秀才である。そして科学者になろうと思って京都大学工学部に入った。そのとき数学は、科学のための道具みたいな認識たったのかもしれない。

ところが、よくあることであるが、どうも大学の勉強に身が入らず、プログラミングのアルバイトで稼ぐようになった。そしてプログラミングとお金を稼ぐことの両方に才能があったか、月に100万円も稼ぎ、仕送りなしでやっていけたという。

それできちんと大学を卒業して就職したはいいが、折角就職した会社が倒産してしまった。そこで仕方なく起業したのが、オンライン専門のゲーム会社であるドワンゴだった。1997年のことである。その後、携帯電話の着信メロディの配信で急成長し、2006年にニコニコ動画を立ち上げた。

そんなドワンゴの現在の関心に、「電王戦」と「人工知能研究」がある。グーグルもマイクロソフトも人工知能研究に力を入れている。今の時代、IT企業であれば、外せない。

実は将棋連盟が電王戦を企画したとき、スポンサーが現われなかった。そこで将棋連盟はドワンゴにコンタクトし、ドワンゴがこれを受けた、という次第である。ここらあたりのニュアンスは、ハッシーの棋士の一分に書かれていることとは少し違う。

将棋連盟にとって、電王戦の貢献は実に大きく、落ち目だった将棋人気がかなり盛り返した。将棋連盟の理事たちは、川上氏に足を向けて寝れないのではないか。

また、ドワンゴの人工知能研究であるが、グーグルと張り合うというよりも、グーグルの研究がカバーしていないニッチを狙っているという。

人工知能に関して、川上氏は、「数学者と理論物理学者の仕事が人工知能に取って代わられるのは、すべての職業の中で最後であろう。」という。確かに、できた理論や方程式に基づき計算するのはコンピュータは得意であるが、理論構築は難しそうである。ちなみに、「最後であろう。」というのは、ありえないという意味だと私は解釈する。なぜなら、英語で、He is the last person who may commit murder.というのは、彼が殺人なんかするわけがないという意味だからである。

あと、川上氏は現在、3組の数学の家庭教師を雇っているという。一人は大学数学科の院生、もう一人は数学を愛するあまり会社を辞めてしまった人、最後は「すうがくぶんか」という数学塾だという。

会社を辞めてしまった人からは、リーマン予想の理解の準備のため、複素解析、ベルヌーイ多項式、ゼータ関数を学んでいるという。なんか、リーマン予想に入れ込んで会社を辞めてしまったという人の行く末が不安になってきた。

院生からは、数論、群論、表現論を学び、次は相対論を学ぶのだという。なんか一貫したものがみえない。

「すうがくぶんか」からは、ドワンゴの社員と一緒に、線形代数、微分幾何を学び、次に多様体を学ぶという。さらに、ドワンゴの社員は、圏論を学びたがっているという。川上氏はなぜか、仕事に直接役立つ、確率・統計、ビッグ・データや、機械学習の勉強はここではやめようと話しているそうで、ここで小さくまとまるのを避けているのか。

川上氏には夢があって、それはIT業界は一般に数学のレベルが低くて、数学をもっと勉強することで、もっと頭を使ったITサービスを考えたいという。

私はというと、ラマヌジャンの世話役だったハーディではないが、あまり数学の応用性は信じていない。というのは、特許公報などでアルゴリズム系の発明をみていても、そこで使われている数学は、有限体とか、フーリエ級数とか、ベッセル関数、ルジャンドルの球関数などと比較的限定されているからである。

でも、これはビジネス書でいわれる、コップに水が半分しか入っていないか、半分も入っている、の認識の違いなのかもしれない。

ということで、ドワンゴの活躍に期待である。

整数論を勉強していると、フェルマーの小定理というのに出会う。それは、pを素数、aをpと互いに素な任意の整数とすると、ap-1 ≡ 1 (mod p)が成立する、というものである。

これの証明は、フェルマーの大定理(あまりに有名なので、その命題は書き下す必要はないだろう)よりはもちろんはるかに簡単だが、だからといってそんなに自明ではない。この証明はおそらく、ガウスの定理とも関係し、すると、オイラーでさえ証明できなかったほどの難しさということになる。いや、オイラーは、オイラー関数φ(n)を定義して、この定理を拡張しているのだから、この点は私の勘違いかもしれない。ここでいうガウスの定理は、より一般化した原始根の存在定理である。

さて、フェルマーの小定理を素数判定に使う場合の問題点があって、それは、pが素数のときは、aをpと互いに素な任意の整数とすると、ap-1 ≡ 1 (mod p)が必ず成立するが、逆に、aをpと互いに素な任意の整数として、ap-1 ≡ 1 (mod p)が成立するからといって、pが素数とは限らない、ということがある。

例えば、a = 2として、5 ≦ p ≦ 1000までの整数で、pは素数でなく、且つap-1 ≡ 1 (mod p)が成立するものという条件で探すと、p = 341, 561, 645の3個がある。意外に少ない。なお、この程度の計算でも、手計算でやるのは大変なので、簡単なPerlのスクリプトを書いた。そのコードは自明なので示さない。

ともかく、pと互いに素なaで以て、ap-1 ≡ 1 (mod p)をみたすpを概素数と呼ぶ。概素数には、本物の素数と、上記p = 341, 561, 645のような数の両方が含まれている。そこで、概素数から本物の素数を除いた補集合を、擬素数と呼ぶ。ただ、擬素数と呼ぶとき、それはどんなaを用いたかによるので、a = 2の場合の擬素数を2-PRPと呼ぶ。

そして、一般に概素数における擬素数の成分比はかなり小さいので、ap-1 ≡ 1 (mod p)を満たせば、pが本物の素数である可能性はかなり高い。例えば、上記の例だと、a = 2として、5 ≦ p ≦ 1000までの整数で概素数になるのは169個で、そのうち166個が本物の素数なのだから、本当に素数である確率は、98%以上もある。

しかし、ap-1 ≡ 1 (mod p)という計算の問題点は、pが大きいときの困難性である。例えば、a = 2として、p = 23217 - 1のような1000桁ちかくもあるpに対して、ナイーブに2p-1 ≡ 1 (mod p)を計算したら時間がいくらかかるかわからない。もしかして10800年くらいかかるかもしれず、何それ?ということになる。そこで、あるまとまった2nを計算しておいて加速するなどのテクニックを使うことになるが、それでもそんなに自明でない。

よって、整数論的には重要なフェルマーの小定理も、素数判定的には、擬素数判定の文脈で位置づけられるのであった。

先日、Lucas-Lehmer判定法に触れたが、Lucas-Lehmer判定法といえども結構コストがかかるので、もっとコストの少ない方法で2p-1が合成数だと判別できたら、メルセンヌ素数の判定も少しは楽になるのにと思って、Chris K. Caldwell編著、SOJIN編訳「素数大百科」共立出版、2004のページをめくっていたら、次のようなオイラーの定理が載っていた。

すなわち、素数pについて、k > 1の整数として、p = 4k + 3且つ2p + 1が素数なら、2p - 1は合成数。

そこで、5以上100000以下の素数9591個について、この条件を満たすpの個数を調べたところ、なんと580個しかなかった。そして、このpに対して確かに2p - 1は合成数は合成数になるのだが、2p - 1が合成数だからpがこの条件を満たすとは限らないので、Lucas-Lehmer判定法のコスト節約にはあまり貢献しないのだった。

それでは、以下に示す、Bateman、Selfridge、Wagstaffによる以下の予想(BSW89)はどうだろうか。すなわち、pを奇数の自然数とすると、以下の2つが成立すると、のこりの一つも同時に成り立つ。

  1. p = 2k±1または、p = 4k±3
  2. 2p-1は、メルセンヌ素数
  3. (2p+1)/3は素数

これの第1の式は、扱いが容易だが、他の2つの式は面倒である。で、ともかく第1の式は、メルセンヌ素数の事前判定に使えそうである。この式を満たす素数pで、2p-1は、メルセンヌ素数であると(あくまでも予想であるが)一応言えるのではないだろうか。

そこで、例によって5以上100000以下の素数について、第1の式に該当するものをみると、5 7 13 17 19 31 61 67 127 257 1021 4093 4099 8191 16381 65537 65539の17個で、このうち、5 7 13 17 19 31 61まではちゃんと2p-1がメルセンヌ素数になる場合のpに対応していて、跳んで127もそうなのだが、あとはメルセンヌ素数に該当せず、しかも、メルセンヌ素数に該当する89 107 521 607 1279 2203 2281 3217 4253 4423 9689 9941 11213 19937 21701 23209 44497 86243がどれも含まれていないという疎漏ぶりなのだった。

しかし、そんな指摘はいちゃもんなのであって、(2p+1)/3は素数という条件を使っていないし、そもそもこの式でメルセンヌ素数をみたすpを網羅するなんてどこにも書いていない。

ということで、安易にメルセンヌ素数の事前判定なんて考えてはいけないのだった。

自家製の多倍長計算ライブラリを利用して、いろいろ初等整数論的なことを試しているのだが、折角なので、いい意味でベタな、メルセンヌ素数の判定に関する、Lucas-Lehmer判定法を実装してみようと思い、手許にあるChris K. Caldwell編著、SOJIN編訳「素数大百科」共立出版、2004を眺めてみた。

まず、メルセンヌ数とは、pを自然数として、2p - 1であらわされる数であるが、それが素数であるためには、pも素数であることが必要条件である。
なぜなら、p = rsなら、2p - 1 = (2r - 1)Σi=1r2 s(r-i)と分解される。
pが素数であるだけでは十分条件でないのは、例えば、211 - 1が、23×89で合成数であることからもわかる。2p - 1のかたちの素数をメルセンヌ素数と呼ぶ。

世界最大の素数でも述べたように、近年、最大の素数はメルセンヌ素数として計算される傾向にある。それは、メルセンヌ素数の素数判定のアルゴリズムが比較的システマチックに実装できるからだろう。

「素数大百科」によると、メルセンヌ素数の素数判定のアルゴリズムである、Lucas-Lehmer判定法を疑似コードでかくと、以下のとおりである。
s := 4;
for i from 3 to p do s := (s2 - 2) mod (2p - 1)
if s == 0 then
  2p - 1は素数;
else
  2p - 1は合成数;

この疑似コードを、私の多倍長計算ライブラリで記述するのは容易であって、実際に動くC++のコードを下記に示す。

また、これの実行結果は、以下のとおりである。

  1. 23 - 1 は、素数
  2. 25 - 1 は、素数
  3. 27 - 1 は、素数
  4. 213 - 1 は、素数
  5. 217 - 1 は、素数
  6. 219 - 1 は、素数
  7. 231 - 1 は、素数
  8. 261 - 1 は、素数
  9. 289 - 1 は、素数
  10. 2107 - 1 は、素数
  11. 2127 - 1 は、素数
  12. 2521 - 1 は、素数
  13. 2607 - 1 は、素数
  14. 21279 - 1 は、素数

上記の実行結果は、(2を除く)2000以下の素数pについて、2p - 1の素数判定を行った結果である。3から2000までの302個の素数pについて、2p - 1の素数判定を行ったものである。ここから分るのは、3から2000までの302個の素数pについて、2p - 1が素数になるpは、14個しかないということである。しかも、pを増やしていくと、メルセンヌ素数はどんどん疎らになる。メルセンヌ素数は無限にあると予想されているらしいが、信じがたい。このあたり、オイラーの無限和とも似ている。

今回、とりあえず3から2000までの302個の素数pについての計算に留めたのは、計算に膨大な時間がかかるからである。一応、nの数を、計算に足りるだけの妥当な最小値になるように抑えることで計算時間を最適化したものの、特にMMOD(n,s_num,a_num,z_num)の割り算が、筆算的なナイーブ実装であるのがイタい。結局、下記のプログラムの実行完了まで、約2時間半かかってしまった。なお、参考までに私のPCの環境は、ソニーVAIO、Windows 7 Professional、Intel Core i3-2350M、2.3GHz、メモリ4GBと、極めてconventionalである。

専門家は、メルセンヌ数が2の累乗のかたちであることをうまく利用して、ビットシフトを利用しているらしいが、私のプアなプログラミング・スキルでは、それをどう記述するのかさえ思いつかない。勉強してみる。

なお、p = 9941の場合にnを妥当にスケーリングしてメルセンヌ素数判定を計算してみたところ、なんとこの単一の計算に、3時間半くらいかかってしまった。それで、巨大素数の世界記録に挑むことがいかに大変か、想像して気が遠くなった。少なくとも、このナイーブ実装ライブラリで世界記録に挑もうとしたら、ジャージとサンダルの組み合わせでエベレストに登ろうとするくらい暴挙だろう。

メルセンヌ素数判定に時間がかかる別の理由として、素数pに対してのメルセンヌ素数判定のほとんどが無駄弾になってしまう、ということがある。それでいて、素数判定には、きっちりp回ループを廻さなくてはならず、途中で合成数だと分ってループを脱出するということができない。なので、例えばRabin法などの確率的素数判定で予めメルセンヌ数が合成数だとわかったものを事前に弾けるのではないかとも考えたが、そもそもRabin法の計算がLucas-Lehmer判定法よりコストが低いのかどうかも疑問である。

ともかく、素数を勉強する初心者をprimerと呼ぶことにすると、私ってなれそう、ねっprimer、と時代遅れの歌を歌ったりするのだった。


// 実際に動くC++のコード
#include "MLA2.h"

int n = 400;
int *s_num;
int *a_num;
int *b_num;
int *z_num;
int *k_num;

int Lucas(int p);

int main()   {
int p;
FILE *fi,*fo;

s_num = new int[n];
a_num = new int[n];
b_num = new int[n];
z_num = new int[n];
k_num = new int[n];

// primex.txtは、1000000以下の78498個の素数を列挙した、簡易素数バンク
if (( fi = fopen("primex.txt","rt")) == NULL ) return -1;
if (( fo = fopen("Lucas.txt","wt")) == NULL ) return -1;

while ( fscanf(fi,"%d",&p) != EOF )     {
 if ( p >= 3 )    {
  if ( Lucas(p) == 1 )   {
     fprintf(fo,"2<sup>%d</sup> - 1 は、素数<br>\n",p);
  }
 }
 if ( p > 2000 ) break;
}
fclose(fi);

delete[] s_num;
delete[] a_num;
delete[] b_num;
delete[] z_num;
delete[] k_num;
return 1;
}

int Lucas(int p)       {
int i;

// 2^p - 1のセット
CLEAR(n,a_num,1);
for ( i = 0; i < p; i++ )  {
  MUL(n,a_num,2);
}
SUB(n,a_num,1);

// 以下、Lucas-Lehrmer判定
CLEAR(n,s_num,4);
for ( i = 3; i <= p; i++ )   {
 MMUL(n,s_num,s_num,b_num);
 COPY(n,s_num,b_num);
 SUB(n,s_num,2);
 MMOD(n,s_num,a_num,z_num);
 COPY(n,s_num,z_num);
}

if ( ISN(n,s_num,0) == 1 )   {  // 割り切れたか
 return 1;   // 素数である
}
 return 0;   // 合成数である
}

自家製の多倍長計算ライブラリを作成したので、卑近な?適用例として、いろいろな数のコラッツ数列を長さを計算してみた。

上記ライブラリを使用すると自明なので、計算に用いたソースコードは、特に示さない。

まず、21000+1(桁数:302)のコラッツ数列の長さ = 7249。これは、2の階乗から1を引くのではなくて、1を足すので、メルセンヌ数ではない。そのコラッツ数列の長さが7249だと言われたら、私でさえも、ああ、そう?と生返事するよりない。

次に、210000+1(桁数:3011)のコラッツ数列の長さ = 72379。これは、上のケースの累乗の数を10倍に増やしただけだが、すると、コラッツ数列の長さもほぼ10倍になるのね、という当たり前の結果である。なぜなら、コラッツ数列の長さは、2で割れるときは割って減らしていくということで決まるものだからである。

次は、210000-1(桁数:3011)のコラッツ数列の長さ = 134405。これは由緒正しいメルセンヌ数(この場合、いうまでもなくメルセンヌ素数ではない)なのだが、すると、210000+1よりも大きさはたった2減ったばかりなのに、コラッツ数列の長さは、倍近くなる。2の累乗への類似度ではほぼ同じなのに、実に不思議である。

次は、31000(桁数:478)のコラッツ数列の長さ = 11727。21000+1と比べて長くなるのは、2の累乗への類似度が減るので当然か。

次は、21000+31000(桁数:478)のコラッツ数列の長さ = 11241。これで面白いのは、31000に21000を足すと、2の累乗への類似度が高まって、長さが減ることである。

31000-21000(桁数:478)のコラッツ数列の長さ = 12120。これは、31000から21000を引くと、2の累乗への類似度が減って?31000の場合より長くなることが興味深い。

1000!(桁数:2568)のコラッツ数列の長さ = 56399。これは、階乗の数のコラッツ数列の長さを求めてみました、というだけのことである。

1000!+210000(桁数:3011)のコラッツ数列の長さ = 65366。これも、階乗の数と累乗の数を足してみた数のコラッツ数列の長さを求めてみました、というだけのことである。

なお、上記の計算はかなり時間がかかりそうなものだが、コラッツ数列の計算は、素数判定の計算や、フェルマ小定理の計算と比べても、多倍長の数の計算としては例外的にというか、圧倒的に高速で、全部あわせても40分以内に終わってしまう。それは2で割っていく処理が強力だからだろう。

こういう話題って、数学が好きな人や、数論が好きな人でさえ、それで?みたいな反応で、なかなか面白いとは思わないような気がする。なので、数学が好きではない人に対して、間違っても話題に出さないようにしよう。そうしないと、二度と飲み会に呼んでもらえなくなるかもしれない。

このアーカイブについて

このページには、過去に書かれたブログ記事のうち数学カテゴリに属しているものが含まれています。

前のカテゴリは教育です。

次のカテゴリは日常です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。