Young は主に組合せ論を目的とした Python 用の数学ライブラリです。
Young 図形や分割数の簡単な操作ができるので、代数的組合せ論(algebraic combinatorics)、数え上げ組合せ論(enumerative combinatorics)のちょっとした計算に威力を発揮します(して欲しいです)。
Young は次の URL からダウンロードできます。
[Young project page]
CVS を使って最新のソースコードを入手するには次のようにします。
$ cvs -d:pserver:anonymous@cvs.sourceforge.jp:/cvsroot/young login Logging in to :pserver:anonymous@cvs.sourceforge.jp:2401/cvsroot/young CVS password:<ENTER> # パスワードを聞かれますが、何も入力せずに <ENTER> を入力 $ cvs -z3 -d:pserver:anonymous@cvs.sourceforge.jp:/cvsroot/young co young
インストールするには大きく分けて2通りあります。
Windows 用のバイナリファイルの場合、ファイルをダブルクリックして 画面に従って操作すれば無事インストールは終了です。
現在はバイナリからのインストールは Windows からしか対応していません。
ソースからインストールするには、アーカイブをダウンロード後、コマンドラインから次のようにします。($VER は Young のバージョンです)
$ tar zxfv young-$VER.tar.gz $ cd young-$VER $ python setup.py install
Python のインタープリターから使う場合、まず young モジュールをインポートします。
>>> import young >>> from young import * # 手を抜く
上のスタイルでモジュールをインポートした場合、関数を呼び出すときに 毎回モジュールの名前を明示的に指定する必要があります。
>>> young.partition(10) >>> young.factorial(5)
Python のことはあまり知らず、young モジュールしか使わないなら下の方が楽でいいと思います。
まずは、基本的な計算から
>>> factorial(5) # 5 x 4 x 3 x 2 x 1 120 >>> factorial(5,3) # 5 x 4 x 3 60 >>> permutation(1,2,3) # (1,2,3) の順列 [[3, 1, 2], [2, 1, 3], [1, 3, 2], [2, 3, 1], [1, 2, 3], [3, 2, 1]] >>> permutation('xyz') # 'x', 'y', 'z' の順列 [['z', 'x', 'y'], ['y', 'x', 'z'], ['x', 'z', 'y'], ['y', 'z', 'x'], ['x', 'y', 'z'], ['z', 'y', 'x']] >>> combination(4, 2) # 4個から2個を選ぶ組合せの数 6 >>> combination('python', 2) # 文字列 "python" から2文字選ぶ [['p', 'y'], ['p', 't'], ['p', 'h'], ['p', 'o'], ['p', 'n'], ['y', 't'], ['y', ' h'], ['y', 'o'], ['y', 'n'], ['t', 'h'], ['t', 'o'], ['t', 'n'], ['h', 'o'], ['h ', 'n'], ['o', 'n']]
カタラン数を少し。
>>> catalan(20) 6564120420L >>> for i in range(0, 10): # 0 から 9 までのカタラン数を表示 ... print i, catalan(i) ... 0 1 1 1 2 2 3 5 4 14 5 42 6 132 7 429 8 1430 9 4862
次に自然数 N に対して分割を与えます。
>>> partition(5) (5) (4,1) (3,2) (3,1,1) (2,2,1) (2,1,1,1) (1,1,1,1,1) >>> p = partition(10) >>> p.size() # 10 の分割はどれだけあるのか 42 >>> for x in take(p, 5): # 10 の分割のうち、最初の 5 個を表示 print x (10) (9,1) (8,2) (8,1,1) (7,3) >>> for x in drop(p, 37): # 最後の 5 個を表示(42 - 37 = 5) print x (2,2,2,2,1,1) (2,2,2,1,1,1,1) (2,2,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,2,3] を [2,1,3] に移す置換の場合、(2,1,3) で表します。
>>> from young import * >>> p = permgroup(3,2,1) >>> p PermGroup([3 2 1]) >>> p.get_inv() # 転倒数 3 >>> p.get_sgn() # 符号(-1 or +1) -1 >>> p.isodd() # 奇置換ですか? True >>> p.iseven() # 偶置換ですか? False >>> p.get_inverse() # 逆元 PermGroup([3 2 1]) >>> p = permgroup(5,3,2,1,4) >>> p.to_cycle() # 巡回置換分解 Cycle([(1 4 5) (2 3)]) >>> p.get_inverse() # 逆元 PermGroup([4 3 2 5 1]) >>> p1 = permgroup(4,3,1,2) >>> p2 = permgroup(3,1,4,2) >>> p1 * p2 # 置換群の間の演算は * で行います。 PermGroup([2 4 3 1]) >>> p2 * p1 PermGroup([1 4 2 3]) >>> p3 = p1 * p2 >>> p3 PermGroup([2 4 3 1]) >>> p4 = p3.get_inverse() # 逆元 >>> p4 PermGroup([4 1 3 2]) >>> p3 * p4 # 単位元になるかチェック PermGroup([1 2 3 4]) >>> p4 * p3 # 単位元になるかチェック PermGroup([1 2 3 4]) >>> p3.to_cycle() # 巡回置換分解 Cycle([(1 2 4) (3)]) >>>
と書かれているものと同じ演算になっています。
と同じです。
このあたりは将来的に変わる可能性が高いです。
次がメインのヤング図形です。
>>> y = young(4) >>> y (4) 1 2 3 4 (3,1) 1 2 3 4 1 2 4 3 1 3 4 2 (2,2) 1 2 3 4 1 3 2 4 (2,1,1) 1 2 3 4 1 3 2 4 1 4 2 3 (1,1,1,1) 1 2 3 4 >>> y.report() # 各分割に対して、どれだけ標準盤があるか partition number square ---------------------------------------- (4) 1 1 (3,1) 3 9 (2,2) 2 4 (2,1,1) 3 9 (1,1,1,1) 1 1 ---------------------------------------- total 10 24 >>> factorial(4) # チェック 24 >>> young(3,1,1) # 分割が (3,1,1) の標準盤 (3, 1, 1) 1 2 3 4 5 1 2 4 3 5 1 2 5 3 4 1 3 4 2 5 1 3 5 2 4 1 4 5 2 3 >>> y = young(6) >>> y.size() # 6 の分割を元にした標準盤がどれだけあるか 76 >>> for x in take(y, 4): # 6 を元にした標準盤から4個を表示 print x 1 2 3 4 5 6 1 2 4 3 5 6 1 2 5 3 4 6 1 3 4 2 5 6 # Young 盤の up/down など >>> y = young(2,1) # 最初に標準盤を与える >>> y.get_partition() # チェック [(2, 1)] >>> y.up() # up >>> y.get_partition() [(3,1), (2,2), (2,1,1)] >>> for i in range(3): ... y.up() ... y.get_partition() ... [(4,1), (3,2), (3,1,1), (2,2,1), (2,1,1,1)] [(5,1), (4,2), (4,1,1), (3,3), (3,2,1), (3,1,1,1), (2,2,2), (2,2,1,1), (2,1,1,1, 1)] [(6,1), (5,2), (5,1,1), (4,3), (4,2,1), (4,1,1,1), (3,3,1), (3,2,2), (3,2,1,1), (3,1,1,1,1), (2,2,2,1), (2,2,1,1,1), (2,1,1,1,1,1)] >>> y = young(2,1,1) # 最初に標準盤を与える >>> y.get_partition() # チェック [(2, 1, 1)] >>> for i in range(4): ... y.down() ... y.get_partition() ... [(2,1), (1,1,1)] [(2), (1,1)] [(1)] [()] >>>
young の take/dropは partition の take/drop とは異なり、 表示順序がきれいにソートされていません。
サンプル
>>> y = young(4) >>> for x in take(y, 6):print x 1 2 3 4 1 2 3 4 1 2 4 3 1 3 4 2 1 2 3 4 1 2 3 4
ただし、これは将来的にはかわる可能性があります。
Young について書き残したことなど
50 の分割(partition(50).size()) は 204226, 100 の分割は 190569292 あります。 自分がこのモジュールでテストした範囲では、partition(50) くらいまでは 正しく(時間内に)計算出来ています。
また、分割の近似値を与えるものとして、Hardy-Ramanujan(-Rademacher) による公式も知られています。
Young 図形の本を読んでいると、たまに "jeu de taquin" という言葉を目にすることがあります。 初めて目にすると一体どんなものなのか想像もつきませんが、taquin は 数字並べゲーム(のフランス名)のことです。 Python で書かれた taquin のスクリプトを見つけたので、興味のある方は一度遊んでみてください。
しばらくは分割数の方をメインにライブラリを充実させていく予定です。
下に挙げるもの以外にもヤング図形や分割数に関する本は多数あります。
[1] | 寺田至, ヤング図形のはなし, 日本評論社, 2002. |
[2] | 堀田良之, 加群十話, 朝倉書店, 1988. |
[3] | Richard P. Stanley, Enumerative Combinatorics volume 1, Cambridge University Press, 2001. |
http://mathworld.wolfram.com/YoungTableau.html
mathworld ではヤング図形が上で示しているものとは上下逆に並んでいます。 堀田良之さんによると、大陸(フランス、ドイツなど)では mathworld のように 上向きに並べる習慣があるそうです。
Contact: | <etale @ users.sourceforge.jp> |
---|---|
Date: | $Date: 2003/10/23 11:15:04 $ |