ラベル ja の投稿を表示しています。 すべての投稿を表示
ラベル ja の投稿を表示しています。 すべての投稿を表示

2012年5月6日日曜日

Cornacchia

Iwao Kimura at Blogger の Cornacchia-Smithのアルゴリズム:mod 4で1の素数は2平方数の和という記事を読みました。 Cornacchia という名前に聞き覚えが(読み方は多分イタリア人なのでコルナッキア)あります。 そう確かあれは cubic_root モジュール。

あまりこのモジュールを使ったことがある、という人も多くないと思いますので、その紹介を簡単に。 平方剰余というのは有名ですが、3乗剰余というものもあるのです。 cubic_root モジュールはこの計算をします。 それ以外に Eisenstein 整域 \(\mathbb{Z}[\omega]\) での有理素数の因数分解や素数を法とする3乗根の計算なども提供しています。 この中に何故か、というかまあ実装の都合上ここに、cornacchia という関数があります。

cornacchia(d, p) で \(x^2 + d y^2 = p\) の解(の一つ)をタプルとして返します。 ということで早速使ってみましょう。

>>> import nzmath.cubic_root
>>> nzmath.cubic_root.cornacchia(1, 37)
(6, 1)

つまり \(6^2+1\times 1^2 = 37\) ということですね。

実装は H.Cohen の A Course in Computational Algebraic Number Theory を参考にしています。

2010年4月5日月曜日

Partition HOWTO (日本語版)

この HOWTO は NZMATH で数の分割を使う方法を説明するものです。 注意として、一部の機能は次期リリースに含まれる予定のもので、現在のリリースバージョンには含まれていないということです。 もし、ここでの説明が気に入って次期リリースに先行して使ってみたいという方は、sourceforge.net で公開されている mercurial のリポジトリを clone して下さい。

% hg clone http://nzmath.hg.sourceforge.net:8000/hgroot/nzmath/nzmath

1. 数の分割

自然数 n の分割とは、n を自然数の和として表すことである。 たとえば、2+2+1 は 5 の分割の一つである。 足し算は順番を変えても結果が同じなので、現れる数の順番は気にしないことにする。 つまり 2+2+1 と 2+1+2 と 1+2+2 は区別しない。 このような数の分割は、組合せ構造を考えるときにしばしば現れる。 そこで NZMATH では combinatorial モジュールに関連する関数が収められている。 以下の例では from nzmath.combinatorial import * してあると仮定する。

まず分割そのものを得るには partition_generator を使う。

>>> for partition in partition_generator(5):
...     print partition
...
(5,)
(4, 1)
(3, 2)
(3, 1, 1)
(2, 2, 1)
(2, 1, 1, 1)
(1, 1, 1, 1, 1)
>>>

これが 5 の分割の全てである。 足し算の式を返すのではなく、足される数のタプルが返るようになっている。

ここで7個の分割が現れたが、n を 5 から増やすとどれぐらい分割の個数は増えるだろう、 と疑問に思うかもしれない。 原理的には len(list(partition_generator(n))) で求められるが、 これは非効率的であり、この個数(分割数という)だけ求める方法がある。

>>> partition_number(6)
11
>>>

この関数はこの HOWTO では以降使わない。 分割数の増え方はほぼ指数的である。

2. 上限付き分割

今度は足される数に上限がある場合を考えてみよう。 つまり 5 の分割の内、たとえば足される数が3以下のものだけ得たいという場合にどうするかである。 単純に要らないものを捨てるならばこう書けばよいだろう。

>>> for partition in partition_generator(5):
...     if all(d <= 3 for d in partition):
...         print partition
...
(3, 2)
(3, 1, 1)
(2, 2, 1)
(2, 1, 1, 1)
(1, 1, 1, 1, 1)
>>>

この手のフィルタリングは間違いではない。 というより、一般的に他に手段がないのならこれがベストだろう。 しかし、この節は次のことを言うためにある: 「partition_generator には第2引数が渡せます」

>>> for partition in partition_generator(5, 3):
...     print partition
...
(3, 2)
(3, 1, 1)
(2, 2, 1)
(2, 1, 1, 1)
(1, 1, 1, 1, 1)
>>>

3. 個数に上限のある分割

次は足される個数に上限がある場合を考えよう。 5 の分割の中で足される個数が3個以下のものが欲しい、と。 再び、まずは一般的な手法から。

>>> for partition in partition_generator(5):
...     if len(partition) <= 3:
...         print partition
...
(5, )
(4, 1)
(3, 2)
(3, 1, 1)
(2, 2, 1)
>>>

さて、先ほどの3以下のものの個数が5個、この足される個数3個以下のものも5個。 これは偶然ではない。 即ち、これらの間には共役と呼ばれる一対一対応がある。 この対応は図形的に見ると解り易い(ヤング図形またはフェラーズ図形と呼ばれる)。 下図の左が (4, 1) 右が (2, 1, 1, 1) である。

. . . .    . .
.          .
           .
           .

点を横に数えると左は上から4,1。 右は上から 2,1,1,1 である。 共役はこの図形を裏返す操作である。 左上の角を固定して、右のものを下に持ってくるようにひっくり返す。 (4, 1) はこの操作で (2, 1, 1, 1) と重なるのが見て取れると思う。

NZMATH には partition_conjugate という関数がある。

>>> for partition in partition_generator(5, 3):
...     print partition_conjugate(partition)
...
(2, 2, 1)
(3, 1, 1)
(3, 2)
(4, 1)
(5,)
>>>

先ほどと順番が異なる(たまたま逆になった)が、同じ分割が出てくる。

4. ちょうど k 以下への分割

今までの節は既に定義されている関数の紹介に過ぎなかったが、ここからは必要に応じて組み立てるやり方である。 partition_generator の第2引数を使うことで「高々 k」の部分に分割する方法は学んだが、では、一番大きい部分が「ちょうど k」となる分割を考えよう。フィルターする戦略はここでも有効であるが、少し考えると無駄になる分割を一切生成せずに済ませることができることが解る。 即ち「ちょうど k」の部分は全ての必要な分割に共通することに着目する。 すると、残る n-k を高々 k の部分に分割したものと一緒にする(接ぐ)ことで、 最大がちょうど k の分割が得られる。

# n=6, k=3
>>> for partition in partition_generator(6-3, 3):
...     print (3,)+partition
...
(3, 3)
(3, 2, 1)
(3, 1, 1, 1)
>>>

問題: n をちょうど k 個の部分に分割する方法を考えよ。 (ヒント: 共役を用いよ)

5. 最小を制限された分割

最大を制限する方法は既に学んだが、では最小を制限するにはどうすればよいだろう。 たとえば、「少なくとも 2」の部分への 7 の分割というような問題である。 ここでも共役を考えるのがよいだろう。 少なくとも 2 の部分への分割は、少なくとも二つの最大部分を持つ分割の共役である。 するとこれは前節の拡張である。

>>> n=7; k=2
>>> for m in range(1, n//k + 1):
...     for partition in partition_generator(n - m*k, m):
...         print (m,)*k + partition:
... 
(1, 1, 1, 1, 1, 1, 1)
(2, 2, 2, 1)
(2, 2, 1, 1, 1)
(3, 3, 1)
>>>

得たいのはこれの共役であったから、

>>> n=7; k=2
>>> for m in range(1, n//k + 1):
...     for partition in partition_generator(n - m*k, m):
...         print partition_conjugate((m,)*k + partition):
... 
(7,)
(4, 3)
(5, 2)
(3, 2, 2)
>>>

6. 奇数部分への分割

最大・最小の制限は大体理解できてきたと思うので、次は大きく方向を変えて、奇数部分への分割を考えよう。 たとえば 9 の奇数部分への分割は

(9,)
(7, 1, 1)
(5, 3, 1)
(5, 1, 1, 1, 1)
(3, 3, 3)
(3, 3, 1, 1, 1)
(3, 1, 1, 1, 1, 1, 1)
(1, 1, 1, 1, 1, 1, 1, 1, 1)

である。9 の分割は全部で30個あるが、その内奇数部分への分割は8個だけである。 この差を考えればフィルター的な作り方は避けたい。

9 = 2*5 - 1
7 = 2*4 - 1
...
1 = 2*1 - 1

という対応で 2N+1 (奇数) と N (自然数) を対応づけると、

(9,)                        ⟷ (5,)
(7, 1, 1)                   ⟷ (4, 1, 1)
(5, 3, 1)                   ⟷ (3, 2, 1)
(5, 1, 1, 1, 1)             ⟷ (3, 1, 1, 1, 1)
(3, 3, 3)                   ⟷ (2, 2, 2)
(3, 3, 1, 1, 1)             ⟷ (2, 2, 1, 1, 1)
(3, 1, 1, 1, 1, 1, 1)       ⟷ (2, 1, 1, 1, 1, 1, 1)
(1, 1, 1, 1, 1, 1, 1, 1, 1) ⟷ (1, 1, 1, 1, 1, 1, 1, 1, 1)

右側を眺めると、次のような対応が見て取れる。 5 のちょうど1個への分割、6 のちょうど3個への分割、…、9 のちょうど9個への分割を集めてきたものと対応がつく。 ちょうど k 個への分割は4節の問題として提示した。 これが利用できる。

>>> n = 9
>>> for m in range(n//2 + 1, n + 1):
...     for partition in partition_generator(n - m, 2*m - n):
...         print tuple(2*x - 1 for x in partition_conjugate((2*m - n,) + partition))
... 
(9,)
(3, 3, 3)
(5, 3, 1)
(7, 1, 1)
(3, 3, 1, 1, 1)
(5, 1, 1, 1, 1)
(3, 1, 1, 1, 1, 1, 1)
(1, 1, 1, 1, 1, 1, 1, 1, 1)
>>> 

問題: 奇数部分への分割は互いに相異なる部分への分割に「同じ部分があればその二つを融合した部分を作る」という規則を繰り返し適用することで一対一に対応づけられる。このことを利用して互いに相異なる部分への分割を実現せよ。

7. 結語

単純な分割から、いくつかの制限を付けた分割を作る方法を説明した。 最後の方は専用のジェネレータを作った方が楽そうであるが、適当な一対一対応により無駄なく生成できることが見て取れたと思う。 専用のジェネレータを作る方法は HOWTO 第2部で紹介する。

以下の文献を参照した: アンドリュース/エリクソン「整数の分割」数学書房

2009年3月8日日曜日

合宿のまとめ

結局、初日しか書き込まなかったので、まとめて書く。

だいぶ進展があったのが、代数体上のイデアルなどの加群の実装。
ECPP も公開できる状態に近づいた。
一方、代数体上での多項式の因数分解はやや難航した模様。
GAE 関係は、やり方を理解できたので、そのうち実際に公開する方向だ。

宿泊施設のアクティプラザびわは、全館そこそこ速い無線LANが通じていて快適だったし、サービスも良かった。周囲にあるのが、琵琶湖と売り出し中の別荘地(ログハウス風のが建ち並んでいる)と田んぼ、少し歩くとオートキャンプ場とか風車が目印の道の駅とかその側の花の季節以外は年中休業の花菖蒲園とかがあることはある。とりあえず、今は閑散期だ。

ある意味、集中するにはいい季節で、成果が上がったという意味では充実していたといえるだろう。

2009年3月4日水曜日

開発合宿 2009

今日から滋賀県高島市のアクティプラザびわで開発合宿。
7日に京都大学である応用数理学会の前なので、という理由で探した宿で、まわりには何もないところでほぼ缶詰めになる。

数体関連の開発を進めている他のメンバーの傍らで、
Google App Engine に昔 django で動かしてたものを移植しよう、というお気楽プロジェクトを進行中。

2008年3月14日金曜日

3日目と4日目

3日目も前日の続き、というつもりだったが、少し行列のインターフェイスに不満が出てきたので改造を始める。なんで現状のように行列の要素を行ごとのリストのリストで持つようにしたのだったか。

午後はレクリエーションということで、みんなで近くの砂浜に行ってサッカーやドッジボールに興じる。2時間強目一杯の気分転換。

宿に帰ってから午前中の続きに戻ったが、すぐ夕食。

夕食後に今後の計画について話し合いをしたあと(後ほどその内容についても書くつもり)、飲み会。12時近くに散会してすぐ寝てしまったので、昨日これを書けなかった。そんなに飲んだつもりでもなかったのだが。

4日目は朝から雨。最終日なので部屋を片付けた後、昼まで会議室で最後の成果発表。

全体的に去年に比べてじっくり色々取り組めたように思う。個人的には round 2 の実装についてもう一度考え直さないといけないが、今月中には何とかする。

2008年3月12日水曜日

2日目

今日も昨日の続き。
行列の方の関数の修正とかもしつつ、未だ正解に達せず。
式変形をもう少し真剣に考え直せば出来上がるとは思うのだが。

2008年3月11日火曜日

1日目

11時過ぎに井の頭線に乗って移動を開始する。下北沢から小田急線でまずは小田原まで。
小田原で待ち合わせまでの少しの間に Beck's Cafe でサンドイッチを食べる。
13時に待ち合わせて13時5分発の東海道線に乗るはずが、乗り遅れてだいぶ時間の読みが狂った。
宿の伊東山喜旅館へは15時少し前の到着。

無線LANなので、設定も大したことはない(私はMacBookでAirMacを入れるだけ)。
人数(12人)分のノートPCが並ぶとなかなか壮観。

私は Round 2 の実装というか、去年動かない状態で放置したもののやり直しを主に手伝っている。
基本的なケース(Dedekindの判定条件)では動いた。

合宿 2008

今日から合宿。
今年の合宿は伊東で三泊四日、開発合宿の定番とも言える山喜旅館で行なわれる。
合宿の様子を(最後にまとめてでなく)随時書き込むつもりだ。

2007年5月24日木曜日

Mix-in か

多項式において、係数環の性質によって定義できる演算やメソッドが違い、今までの実装では継承で何とかしようとしていたが、これは mix-in で解決するのがいいのかもしれないと最近は考えている。問題は、これを動的に扱う必要があるかどうか、あるいはそもそも動的に扱えるのか(新形式クラスで __bases__ を書き換えるとどうなるのか)といった辺りだ。
なお、この方式は行列にも同様に適用できるはずだが、これには手を着けていない。多項式で一通り試してみてから、だ。

2007年3月7日水曜日

合宿2007 (まとめ)

NZMATH 開発合宿のまとめ。

一日目

13時に小田原駅集合(この頃ちょうど雨が降り出した)。そこからバスで芦ノ湯まで、小一時間、ずっと上り坂。芦ノ湯のバス停から向かいの道を入っていって、今回の宿きのくにやに到着。

部屋に荷物を置いて、さっそく会議室に行ってネットワークの設定をするが、無線LANの電波が弱いのか DHCP サーバーに繋がらなかったり、繋がっても DNS で名前を引けなかったり、意外に苦戦した(結局後でもう少し電波の状態の良い隣の部屋に移動させてもらった)。仕事の分担を決めて議論を始めたと思ったら、あっという間に夕食の時間。夕食後も約3時間作業。この日やっていたのは多項式の再実装。会議室は一応夜10時までということなので、無線LANのハブともども部屋に引き揚げ。で、予想外に泊まる部屋の方が電波の状態が良かったりする。

当然、箱根なので温泉に入り、就寝までテレビを見ながらちょこちょこ作業。

二日目

メインの一日。朝食をきっちり食べて、前日の作業の続き。ネットワークがまた繋がらなかったりして時間をロスする。ネットワークの回復を待つ間プロジェクターでソースを見せ合ったりして、前日の作業の確認をする。一変数でまあなんとか書けたので、多変数も同様に…と午前中は議論を詰める。

昼に弁当を食べた後、買い出しに出向く。宿の周辺には店が無いので、徒歩で30分強(ぐらいだったかな)かけて芦ノ湖まで下りていった。前日の雨から一転、晴れ渡っていた。コンビニで買いものをして、帰りはバスで戻る。バスだとわずか5分。

この日の午後、そして夕食後は、私は多項式から離れて round 2 法というのを書いてみた。が、行列関係の機能が不足していて動きそうもない。

夜9時から、軽く飲み会+カラオケ。カラオケはおまけ。

最終日

今日になるわけだが、宿ですることは朝食を摂ることだけ。チェックアウトして、バスで小田原まで戻り、反省会(場所を探して結局駅ビルの中のハワイアンカフェマカメドウズで)。正午ぐらいに小田急線に乗り、帰路に。

2007年3月5日月曜日

合宿

今日から7日まで箱根で NZMATH 開発合宿。 箱根という辺りが、去年の八王子大学セミナーハウスでのもの(合宿 (まとめ))と違った期待を抱かせる。 とりあえず自転車で行けないことだけは確か。

2006年8月9日水曜日

NZMATH 0.5.1

少し間が空いたが、若干の改良とともにリリース。 sourceforge.net にプロジェクトページを運用するようにしたから、それに合わせて NZMATH 関係の日記はできるだけ diary and notes に英語で書くことにする。

2006年5月16日火曜日

ぐだぐだ

調子が悪く、ゼミは自主的に休み。

NZMATH の最近来たリクエスト関係の処理だけなんとかこなす。 ring.py なんていう抽象的な部分を引っ掻いてくれているので、使われている実感が湧いて嬉しい。

2006年4月19日水曜日

Frobenius test

ゼミ開始。午前は西本君で QPKC の計算実験の話。午後は NZMATH の時間は Frobenius test の実装。整数論セミナーは津村さんで多重ζ関数の話。その後、Frobenius test のテストを書いたら、Crandall & Pomerance: Prime Numbers 2nd ed. の誤りが判った。 4181 と書いてある Lucas 擬素数は 4187 であった。

2006年3月18日土曜日

神戸(まとめ)

1日目



9:50発のぞみで新神戸まで。あいにく雨なので地下鉄・阪急・バスと乗り継いで神戸大学へ。

会場に着くと高山先生の講演が既に始まっていた。講演を聞く内にコーディングせねば、という気になって数体の元のクラスをざっと書く<内職かよ。

泊まったのは姫路の方の兄の家。切符を買う時に木田先生に「そんなに掛かるほど遠くに泊まるの」と突っ込まれた。阪急から阪神高速鉄道、山陽電鉄と乗り入れ路線同士とは言え違う会社のを乗り継ぐからだとは思うが。なお、何を御馳走になったかはこの辺りに書いてある。

2日目



朝一が NZMATH の発表なので遅刻しないように早めに出発。雨が上がったので六甲からは徒歩。

午前は NZMATH 関係2本と九大の素数判定・証明関係3本。午後の講演の中では JavaScript で数式入力システムを作ったという電通大の中野さんの発表が面白かった(こんなの)。筑波大の佐々木先生の還暦記念講演が最後。

懇親会は六甲道まで下りて3時間ぐらい。

3日目



Mandelbrot 集合の泡(特定の吸引点集合に落ち込む領域らしい)を risa/asir で計算・描画するという発表でスタート。内職で、合宿で書いてもらった AKS を、書き直しつつある多項式の実装を使って、6桁の判定に20分ぐらいまで高速化(以前は3時間かかっても終わらなかった)。

帰りは梅田で昼食後、米原まで快速、米原からは新幹線。名古屋から中央本線という馬鹿ネタもあったのだが、調べたら特急に乗っても松本まで2時間さらに八王子まで2時間、ということで眠たいので見送り。

2006年3月16日木曜日

神戸

これから RisaCon2006@神戸大学 に参加してくる。 NZMATH の講演もあるが話すのは自分じゃないから気分的に楽だ。

2006年3月9日木曜日

合宿 (まとめ)

NZMATH 合宿のまとめ。

一日目



自転車で行ったら、是政を過ぎた辺りから強い南風に速度を鈍らされる。後で聞いたところによると春一番だったらしい。かなりバテた。

セミナーハウスでは、まず新人向けガイダンス。そのあと、AKS の多項式時間素数判定アルゴリズムを数理科学に載っていた木田先生の解説を元に実装してもらった。ただ、時間の関係で、未完成のまま一旦中断。

夕食は北野方向に探しながら降りて、結局、ジョリーパスタまで。

夕食後は、matrix と vector のレビュー。

二日目



朝食前にトレーニング。坂を走ったので息切れした。そのあと本館の食堂で朝食。

午前中は今後の目標などを話しあったあと、代数学の復習。

午後はプログラミング。新人たちは前日の続き、他は matrix の改修とか数体関連の実装とか。最後に、finitefield のレビュー。

長い夕食…

三日目



トレーニングのメニューは軽め。朝食は食欲がなかったので、薄味の味噌汁だけ食べた。

慌ただしく、宿泊室を引き払ったあと、反省会をして解散。

2006年3月6日月曜日

合宿

これから NZMATH の合宿@大学セミナーハウス。さて、どんな成果が上がるのか。

2006年2月28日火曜日

数体

0.5.0 をリリースしたので、次の課題として数体に関する機能を実装することにした。今日は、とりあえずどこから手を着けていくかの討議を幾人かと。

2006年2月25日土曜日

NZMATH 0.5.0

NZMATH 0.5.0 をリリースした。主な改良点は、

  • factor の構成の見直し
  • 有限群の初歩的な計算用モジュール group, permute の追加
  • 虚2次体の類数の計算をする quad の追加
だ。