[HOME] | [Usage] | [API Doc] | [INSTALL] | [Bibliography] | [LINK] | [MEMO]

Usage

Contents

ここでは young の基本的な使い方を解説します。 Python のインタープリターから使う場合、Python を起動後、 young モジュールをインポートします。

>>> import young
>>> from young import *     # 手を抜く

上のスタイルでモジュールをインポートした場合、関数を呼び出すときに 毎回モジュールの名前を明示的に指定する必要があります。

>>> young.partition(10)
>>> young.factorial(5)
>>> young.young(5)

young モジュールをメインで使うのなら、

>>> from young import *

の方が楽でいいと思います。

Basics

まずは、基本的な計算から

>>> from young import *
>>> factorial(5)          # 5 の階乗 : 5 x 4 x 3 x 2 x 1
120
>>> factorial(3, 5)       # 3 から 5 までを掛ける : 3 x 4 x 5
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']]

combination の結果は第一引数が整数か sequence かによって、異なります。

Catalan数

カタラン数を少し。

>>> catalan(20)
6564120420L
>>> for i in range(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

Partition

次に自然数 N の分割を与えます。

>>> from young import *
>>> 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
...
(1,1,1,1,1,1,1,1,1,1)
(2,1,1,1,1,1,1,1,1)
(2,2,1,1,1,1,1,1)
(2,2,2,1,1,1,1)
(2,2,2,2,1,1)
>>> for x in drop(p, 37): # 最後の 5 個を表示(42 - 37 = 5)
...   print x
...
(7,3)
(8,1,1)
(8,2)
(9,1)
(10)

# Ramanujan's upper bound
# 左が p(n) の実際の数、右が Ramanujan 近似
>>> for n in (10, 20, 30, 40, 50):
...   print "p(%d)"%n, partition(n).size(), partition_upper_bound(n)
...
p(10) 42 48
p(20) 627 692
p(30) 5604 6080
p(40) 37338 40080
p(50) 204226 217590

分割を指定

Partition の引数に分割を渡すことで、直接 Partition のオブジェクトを作ることもできます。 分割は list または tuple で渡してください。

>>> p = Partition((2,1,1))     # Partition([2,1,1]) is also OK.
>>> Partition(2,1,1)           # this style is invalid
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: tuple() takes at most 1 argument (3 given)
>>> p
(2,1,1)
>>> p.plot()                   # (2,1,1) の形をした盤を表示
**
*
*

>>> p_conj = p.conjugate()    # (2,1,1) の conjugate
>>> print p_conj
(3,1)
>>> p_conj.plot()             # (3,1) の形をした盤を表示
***
*

>>> p_conj.conjugate() == p   # 確認
True
>>> p.up()                    # 分割 (2,1,1) の up operation
(3,1,1)
(2,2,1)
(2,1,1,1)
>>> p.down()                  # 分割 (2,1,1) の down operation
(1,1,1)
(2,1)

Partition の up/down の戻り値は Partition の list(SeqOfPartition クラスのインスタンス)です。

置換群

置換群の簡単な計算もできます。 [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)])
>>>
上の結果からわかるように、 置換群 a,b に対して、
a * b
は普通の本だと
b o a

と書かれているものと同じ演算になっています。

同様に、
b * a
a o b

と同じです。

このあたりは将来的に変わる可能性が高いです。

Young

次はヤング図形です。 Young 盤を作るには、大きく分けて

  1. box の数を指定
  2. 分割を指定
  3. Young 盤を指定

の 3 通りあります。

boxの数を指定

young(N) とすれば、N の分割を元にしたすべての Young 標準盤が生成されます。

>>> from young import *
>>> y = young(3)
>>> print y       # 3 の分割からなっている Young 盤をすべて表示
(3)
1 2 3

(2,1)
1 2
3

1 3
2

(1,1,1)
1
2
3

分割を指定して、Young 盤を生成

young の引数に分割を直接与えることで、その分割を基にした Young 盤が生成されます。

>>> y = young((2,1,1))    # 分割 (2,1,1) を与える
>>> print y               # 分割が (2,1,1) の Young 盤
(2,1,1)
1 2
3
4

1 3
2
4

1 4
2
3

Young 盤を指定

Young 盤を直接指定することもできます。 指定する Young 盤は sequence of sequence(sequence は list, tuple など) である必要があります。 この場合、すべて小文字の young ではなく、大文字で始まる Young です。

>>> y = Young([[1,2],[2],[3]])    # list of list であらわされた Young 盤を引数に渡す
>>> print y
1 2
2
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()       # Young 盤の元になっている分割をかえす
(2, 1)
>>> print y
(2,1)
1 2
3

1 3
2

>>> y.up()                  # 分割 (2,1) に up operation をする
>>> y.get_partition()
(2,1,1)
(2,2)
(3,1)

>>> print y
(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

>>> for i in range(3):      # さらに3回 up operation を繰り返す
...     y.up()
...     y.get_partition()
...     print
...
(2,1,1,1)
(2,2,1)
(3,1,1)
(3,2)
(4,1)
  
(2,1,1,1,1)
(2,2,1,1)
(2,2,2)
(3,1,1,1)
(3,2,1)
(3,3)
(4,1,1)
(4,2)
(5,1)

...(snip)

>>> y = young((2,1,1))       # まず分割を与える
>>> y.get_partition()        # チェック
(2, 1, 1)
>>> for i in range(4):       # 今度は down operation
...     y.down()
...     y.get_partition()
...     print
...
(1,1,1)
(2,1)
  
(1,1)
(2)
  
(1)
  
()

Bumping

Young 盤の bumping も出来ます。

>>> y = Young([[1,2,3]])
>>> print y
1 2 3

>>> y.bump(2)      # bump
>>> print y
1 2 2
3

>>> y1 = Young([[1,1,2],[2,2,3],[4,5]])
>>> y2 = Young([[1,1],[2]])
>>> y1
1 1 2
2 2 3
4 5

>>> y2
1 1
2

>>> y1.bump(y2)    # y1 * y2 とすることも可能
>>> print y1
1 1 1 1
2 2 2 2
3 5
4

>>> y1 = Young([[1,1,2],[2,2,3],[4,5]])
>>> print y1
1 1 2
2 2 3
4 5

>>> for box in (1,1,2):
...   y1.bump(box)
...   print "y1 <- %d"%box
...   print y1
...
y1 <- 1
1 1 1
2 2 2
3 5
4

y1 <- 1
1 1 1 1
2 2 2
3 5
4

y1 <- 2
1 1 1 1 2
2 2 2
3 5
4

Skew tableaux / Sliding / jeu de taquin

skew tableaux とそれに付随する sliding, rectification, jeu de taquin を使ってみましょう。

2 つの Young 盤 T, U

T =
1 1 2
2 2 3
4 5

U =
1 1
2

があったとします。この skew tableau S = T/U は次のようになります。

>>> from young import *
>>> T = Young([[1,1,2],[2,2,3],[4,5]])
>>> U = Young([[1,1],[2]])
>>> T
1 1 2
2 2 3
4 5

>>> U
1 1
2

>>> S = T / U          # use / to create a skew tableau
>>> S
* * 2
* 2 3
4 5
>>> S.taquin()         # jeu de taquin
2 2
3 5
4

skew tableau S にある inner corners を slide していくと、上のような標準盤になります。taquin のかわりに S.rectify() あるいは S.jeu_de_taquin() とすることもできます。

>>> y1 = S.taquin()
>>> y1.__class__.__name__
'Young'
>>> print y1
 2  2
 3  5
 4

>>> y2 =Young([[2,2],[3,5],[4]])
>>> print y2
 2  2
 3  5
 4

>>> y1 == y2
True

jeu de taquin の結果、 Young クラスのインスタンスが返されます。上の場合だと、 S.taquin() は Young([[2,2],[3,5],[4]]) と同じです。

Fulton P.15 の Exercise 1 を実際に解いて見ましょう。2つのYoung 盤 T, U

T = 
1 2 2 3
2 3 5 5
4 4 6
5 6

U =
1 3
2

があったとします。このヤング盤の積 T * U を求めるには次のようにします。

>>> T = Young([[1,2,2,3],[2,3,5,5],[4,4,6],[5,6]])
>>> U = Young([[1,3],[2]])
>>> T
1 2 2 3
2 3 5 5
4 4 6
5 6

>>> U
1 3
2

>>> T * U           # product of T and U
>>> T
1 1 2 2 3
2 2 3 5
3 4 5
4 6 6
5

これを skew tableau を使って解くには、まず、次のような skew tableau を用意します。

>>> y1 = Young([[1,1,1,1,1,3],[1,1,1,1,2],[1,2,2,3],[2,3,5,5],[4,4,6],[5,6]])
>>> y2 = Young([[1,1,1,1],[1,1,1,1]])
>>> S = y1 / y2
>>> S
* * * * 1 3
* * * * 2
1 2 2 3
2 3 5 5
4 4 6
5 6

remove される部分は適当な数値(たとえば 1)で埋めておいて、y1 に contain される小さな tableau y2 を構成し、 y1/y2 で skew tableau を無理やり作ります。(少し面倒ですが) あとは、これに sliding を繰り返せば、上でやった T * U と同じ結果が得られるはずです。

>>> S.rectify()
1 1 2 2 3
2 2 3 5
3 4 5
4 6 6
5

Hook

hook length formula

RSK 対応の応用の 1 つである hook length formula の例。

Young 標準盤への Hook length formula

λ = (6,5,5,3) の shape をもった標準盤の数を hook length を使って求めたい場合、次のようにします。

>>> from young import *
>>> shape = (6,5,5,3)
>>> h = Hook(shape)
>>> h                     # hook length を表示
 9  8  7  5  4  1
 7  6  5  3  2
 6  5  4  2  1
 3  2  1
>>> h.number()            # number メソッドで hook length formula を計算します。
6651216L

これを hook を使わずに young だけでやるには、ある shape をもった標準盤を 実際にすべて構成し 、その数を数える必要があります。したがって、数を知りたいだけだとしたら、極めて非効率的なことをやっています。具体的には次のようになります。(λのサイズはかなり小さくしてあります)

>>> shape = (3,2,1,1)
>>> y = young(shape)      # この段階で、(3,2,2,1) の標準盤をすべて構成してしまう
>>> y.size()
35
>>> h = Hook(shape)       # 念のために Hook を使っても計算
>>> h
 6  3  1
 4  1
 2
 1

>>> h.number()
35
>>> print y               # 35 個ある分割が (3,2,1,1) の Young 標準盤を実際に表示する
(3,2,1,1)
 1  2  3
 4  5
 6
 7

 1  2  3
 4  6
 5
 7

 1  2  3
 4  7
 5
 6
 ...
 [snip]

ある shape をもった標準盤の数を求めたい場合、Hook(shape).number() が young(shape).size() よりはるかに高速です。

標準盤とは限らない Young 盤への Hook length formula

標準盤とは限らない(ラベリングされた tableau で各数字が必ず1度というわけではない) Young 盤 を考えます。例としては、次のような盤です。

1  2  2  3  3  5
2  3  5  5
4  4  6  6
5  6

λ = (6,4,4,2) でラベリングされる数字は [6] = {1,2,3,4,5,6} から選ばれるとします。この条件を満たす Young 盤の数は次のようにして求めます。(Fulton P.2 左上)

>>> from young import *
>>> shape = (6,4,4,2)
>>> h = Hook(shape)
>>> h
 9  8  7  5  4  1
 7  6  5  3  2
 6  5  4  2  1
 3  2  1

>>> h.number(6)               # number メソッドに引数を与える。
90552L

λ = (6,5,5,3) でエントリーが [5] = {1,2,3,4,5} の場合、次のようになります。(Fulton P.55 右下)

>>> from young import *
>>> shape = (6,5,5,3)
>>> h = Hook(shape)
>>> h
 9  8  6  5  2  1
 6  5  3  2
 5  4  2  1
 2  1

>>> h.number(5)               # number メソッドに引数を与える。
3360L

Stanley によるこの hook length formula は、 Weyl の指標公式の特殊な形でもあります。(と本には書いてあります。自信なし)

Partition との連携

Parition との連携もできます(Partition.get_hook() <-> Hook.get_partition())

>>> p1 = Partition((6,5,5,3))  # Partition のインスタンスを作成
>>> p1
(6,5,5,3)
>>> h = p1.get_hook()          # Hook に変換
>>> h
 9  8  7  5  4  1
 7  6  5  3  2
 6  5  4  2  1
 3  2  1

>>> p2 = h.get_partition()     # Partition に変換
>>> p2
(6,5,5,3)
>>> p1 == p2
True

Word

Word のことなど、、

XXX need more here.

RSK 対応

Robinson/Robinson-Schensted/Robinson-Schensted-Knuth 対応について。

Robinson 対応

置換を基にして同じ形(shape)の Young 標準盤のペア (P, Q) を set up します。たとえば、置換 σ が

1 2 3 4 5 6
4 5 1 3 6 2

の場合 --- 順列 (4 5 1 3 6 2) ---、次のようにします。(堀田 P. 118)

>>> from young import *
>>> perm = (4,5,1,3,6,2)       # permutation
>>> rsk  = RSK()
>>> rsk.set_array(perm)
>>> rsk.setup()
>>> rsk
P
 1  2  6
 3  5
 4

Q
 1  2  5
 3  4
 6

# P, Q を個別に表示
>>> rsk.P
 1  2  6
 3  5
 4

>>> rsk.Q
 1  2  5
 3  4
 6

必要な手順は、

  1. RSK クラスのインスタンスを作成し、
  2. set_array メソッドで array をセットし、
  3. 最後に setup メソッドで P と Q を set up します。

P は canonical procedure で構成された Young tableau で、Q は recording(insersion) tableau です。

同様にして、順列が (5 3 4 7 1 2 6) の場合、次のようにします。(堀田 P. 120 練習)

>>> perm = (5,3,4,7,1,2,6)
>>> rsk  = RSK()
>>> rsk.set_array(perm)
>>> rsk.setup()
>>> rsk
P
 1  2  6
 3  4  7
 5

Q
 1  3  4
 2  6  7
 5

Robinson-Schensted 対応

長さが r で各文字が [n] = {1,2, ..., n} からとられる Word を基にして、同じ形(shape)の Young 盤のペア (P, Q) を set up します。たとえば、Word w = 5 4 8 2 3 4 1 7 5 3 1 の場合、次のような二行の列ができます。(Fulton P. 36)

1 2 3 4 5 6 7 8 9 10 11
5 4 8 2 3 4 1 7 5  3  1

これを基にして、P, Q を set up するには、次のようにします。

>>> w = (5,4,8,2,3,4,1,7,5,3,1)
>>> rsk = RSK()
>>> rsk.set_array(w)
>>> rsk.setup()
>>> rsk
P
 1  1  3  5
 2  3
 4  4
 5  7
 8

Q
 1  3  6  8
 2  5
 4  9
 7 10
11

この例の set_array メソッドのところで、

>>> top    = (1,2,3,4,5,6,7,8,9,10,11)
>>> bottom = (5,4,8,2,3,4,1,7,5, 3, 1)
>>> rsk = RSK()
>>> rsk.set_array(top, bottom)
>>> rsk.setup()

というように明示的に two-rowed array を指定しても、同じ結果が得られます。

r = n で、Word の各文字が [n] から一度しか現れない特別な場合が Robinson 対応です。

two-rowed array で上の行が increasing order ではなく、weakly increasing order の場合、例えば、

1 1 1 2 2 3 3 3 3
1 2 2 1 2 1 1 1 2

の場合、次のようにします。(Fulton P. 40 Exercise 1)

>>> top    = (1,1,1,2,2,3,3,3,3)
>>> bottom = (1,2,2,1,2,1,1,1,2)
>>> rsk = RSK()
>>> rsk.set_array(top, bottom)        # rsk.set_array((top, bottom)) は駄目。
>>> rsk.setup()
>>> rsk
P
 1  1  1  1  1  2
 2  2  2

Q
 1  1  1  2  3  3
 2  3  3

Symmetry Theorem

Symmetry Theorem(Fulton P.40) とは two-rowed array の上下を入れ替えたら、tableaux のペア (P, Q) が (Q, P) になるというものです。 Fulton の Exercise 2(P.41) は次のようになります。

>>> from young import *
>>> top    = (1,1,1,2,2,3,3,3,3)
>>> bottom = (1,2,2,1,2,1,1,1,2)
>>> rsk = RSK()
>>> rsk.set_array(bottom, top)        # swap two-rowed array
>>> rsk.setup()
>>> rsk
P
 1  1  1  2  3  3
 2  3  3

Q
 1  1  1  1  1  2
 2  2  2

top と bottom を入れ替えることで、 P. 40 の Exercise 1 とは P, Q が逆になっています。また、set_array メソッドに渡す two-rowed array は lexicographic order になっていなくても OK です(two-rowed array が Word であるためには、lexicographic order でなければいけない)。lexicographic order にソート --- top = (1,1,1,1,1,2,2,2,2), bottom = (1,2,3,3,3,1,1,2,3) として --- rsk.set_array(top, bottom) としても、もちろん上と同じ結果になります。

>>> from young import *
>>> top    = (1,1,1,1,1,2,2,2,2)
>>> bottom = (1,2,3,3,3,1,1,2,3)
>>> rsk = RSK()
>>> rsk.set_array(top, bottom)
>>> rsk.setup()
>>> rsk
P
 1  1  1  2  3  3
 2  3  3

Q
 1  1  1  1  1  2
 2  2  2

two-rowed array が置換の場合、top と bottom で array を入れ替えることは、ある置換群 g に対して、その逆元 g インバースを構成していることに等しいです。 順列が (4 5 1 3 6 2) の場合を例にとると、次のようになります(順列の例は 堀田 P. 120 練習 から)

>>> from young import *
>>> grp1 = PermGroup((3,2,6,1,4,5))
>>> grp2 = grp1.get_inverse()        # inverse of grp1
>>> grp1, grp2
(PermGroup([3 2 6 1 4 5]), PermGroup([4 2 1 5 6 3]))
>>> r1 = RSK()
>>> r1.set_array(grp1)
>>> r1.setup()
>>> r1
P
 1  4  5
 2  6
 3

Q
 1  3  6
 2  5
 4

>>> r2 = RSK()
>>> r2.set_array(grp2)
>>> r2.setup()
>>> r2
P
 1  3  6
 2  5
 4

Q
 1  4  5
 2  6
 3

r1 と r2 とで (P, Q) のペアが逆になっています。

array の行列表示

R(-S(-K)) 対応で使われる array には行列表示があります(Fulton P. 41)。この行列は、array の top/bottom を入れ替えることで、もとの行列の転置行列になります。行列を得るには、 RSK クラスの get_matrix メソッドを使います。上の r1, r2 をそのまま使うと

>>> from pprint import pprint    # 標準ライブラリに付属の pretty printer
>>> pprint(r1.get_matrix())      # RSK クラスの get_matrix メソッドを使う
[[0, 0, 1, 0, 0, 0],
 [0, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1],
 [1, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 0, 0],
 [0, 0, 0, 0, 1, 0]]
>>> pprint(r2.get_matrix())
[[0, 0, 0, 1, 0, 0],
 [0, 1, 0, 0, 0, 0],
 [1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 1],
 [0, 0, 1, 0, 0, 0]]

この2つの行列は確かに互いに転置行列になっています。

Matrix-ball construction

Fulton 4.2 節の Matrix-ball について。(まだ部分的)

numbering

ボールのナンバリングには Numbering クラスを使います。(例は Fulton P. 43 から)

>>> from young import *
>>> A = [[1,2], [1,1], [3,1]]
>>> ball = Numbering(A)
>>> print ball                      # numbering of matrix A
     1      |    2 3     
-------------------------
     2      |     4      
-------------------------
   3 4 5    |     6      
-------------------------

Numbering オブジェクトの constructP(あるいは constructQ)を n 回呼び出すごとに、それが n 行目の P(あるいは Q) になります。

>>> ball.constructP()               # first row of P
[1, 1, 1, 1, 1, 2]
>>> ball.constructQ()               # first row of Q
[1, 1, 1, 2, 3, 3]

同じラベルのボールがなくなるまで(= Numbering.has_same_lable() が False を返すまで)このプロセス(ナンバリング)を繰り返していきます。上の ball では 2,3,4 のラベルを持ったボールがそれぞれ2つずつあります。

>>> ball.get_derived_matrix()       # ``derived'' matrix を取得
[[0, 0], [0, 1], [0, 2]]
>>> m = _                           # same as m = ball.get_derived_matrix()
>>> ball2 = Numbering(m)
>>> print ball2
            |            
-------------------------
            |     1      
-------------------------
            |    2 3     
-------------------------

>>> ball2.constructP()               # second row of P
[2, 2, 2]
>>> ball2.constructQ()               # second row of Q
[2, 3, 3]
>>> ball2.has_same_label()           # ball2 にある 1,2,3 のラベルを貼られたボールはそれぞれ一個しかない。
False
>>> ball2.get_derived_matrix()
[[0, 0], [0, 0], [0, 0]]
>>> ball3 = Numbering(ball2.get_derived_matrix())
>>> print ball3
            |            
-------------------------
            |            
-------------------------
            |            
-------------------------

行列を基にして、対応する Young 図形のペアを取得するには MatrixBall クラスを使います。

>>> from young import *
>>> A = [[1,2], [1,1], [3,1]]
>>> mb = MatrixBall(A)
>>> print mb
# tableau P
 1  1  1  1  1  2
 2  2  2

# tableau Q
 1  1  1  2  3  3
 2  3  3

>>> print mb.P             # P, Q を個別に表示
 1  1  1  1  1  2
 2  2  2

>>> print mb.Q
 1  1  1  2  3  3
 2  3  3

対称行列の性質

対称行列 A に対しては、

行列 A が対称行列 <==> P = Q

という性質を満足します(P. 46)。 Exercise 4(P. 47) とあわせて確認します。

>>> A      = [[1,2,1], [2,2,0], [1,0,1]] # symmetric matrix
>>> mb     = MatrixBall(A)
>>> print mb                             # P = Q であることを確認
# tableau P
 1  1  1  1  2  3
 2  2  2
 3

# tableau Q
 1  1  1  1  2  3
 2  2  2
 3

>>> ball   = Numbering(A)
>>> A_flat = ball.get_derived_matrix()
>>> print A
[[1, 2, 1], [2, 2, 0], [1, 0, 1]]
>>> print A_flat
[[0, 0, 0], [0, 2, 1], [0, 1, 0]]
>>> trace(A)                         # 行列のトレースを計算するには、trace 関数を使う
4
>>> trace(A_flat)
2
>>> len(mb.P[0])                         # length of first row of P
6
# Check Exercise 4
>>> trace(A) + trace(A_flat) == len(mb.P[0])
True

別の対称行列を使って、同じことを確認します。

>>> A2   = [[4,1],[1,0]]                 # symmetric matrix
>>> mb   = MatrixBall(A2)
>>> ball = Numbering(A2)
>>> A2_flat = ball.get_derived_matrix()
>>> print mb                             # P = Q であることを確認
# tableau P
 1  1  1  1  1
 2

# tableau Q
 1  1  1  1  1
 2

>>> A2
[[4, 1], [1, 0]]
>>> A2_flat
[[0, 0], [0, 1]]
>>> trace(A2_flat)
1
>>> trace(A2)
4
>>> len(mb.P[0])                         # length of first row of P
5
# check Exercise 4
>>> trace(A2) + trace(A2_flat) == len(mb.P[0])
True

対称行列に負の整数値がある場合は、当然ながらうまくいきません。

Fulton P.45-46 のややこしいアルゴリズムは、MatrixBall.get_tableau_pair メソッドでちょこっと利用しています。

tableau のペアから行列を復元することなどがまだ実装できていません。

to be continued.


Date:$Date: 2004/12/04 15:21:16 $

mail address