結び目理論とはぢめてのPython

Dropbox - knot_to_polynomial.py
授業の課題で
ジョーンズ多項式 - Wikipedia
を求めるプログラムを作ってみようというのがあったので、
「あ~~これはそろそろやらなきゃかな~」というので昨晩Pythonに手を出して
課題プログラムを書いてみた。

今回は例として
8の字結び目 - Wikipedia
を用いることとし、

以下の様に紐の番号づけをして

プログラムで求めた。

インデントが綺麗に見えてとても良い。
Tupleだとか色々と使いやすそう。


#!/usr/bin/python
# -*- coding: utf-8 -*-
import os, sys
import numpy as np
 
def main():
    """
    結び目を表現する初期値
 
    入力を入れるなり、ファイルから読む形でも良い
    今回はfigure-eight knotを表現する値を代入
    """
    table=[(3,6,4,7),(7,2,0,3),(1,5,2,4),(6,0,5,1)]
    tmp_circle=set()
    tmp_results=set()
    ResultTable = [[0 for j in range(8)] for i in range(16)]
    ResultArray = [0 for j in range(20)]
    myu = np.poly1d([-1,0,0,0,-1])
 
    print ""
    print "[s1,s2,s3,s4] : 各結び目s_iの状態({-1,1})"
    print "(sum,circle)  : (各結び目s_iの状態({-1,1})の和 sum, 成分の数 circle)"
    print "xの多項式     : 各状態の重み"
    print " 注: pythonにはA^{-2}などを表現出来ないので,x^20=x^0となるように合わせている"
    print ""
 
    for s1 in [-1,1]:
        for s2 in [-1,1]:
            for s3 in [-1,1]:
                for s4 in [-1,1]:
                    state=[s1,s2,s3,s4]
                     
                    current_part = 0
                    previous_area = -1
                    i=0
                    circle_num = 0
                    remaining_part = set(range(8))
                    temporary_part = set()
 
                    while not len(remaining_part) == 0:
                         """ 紐番号が適切かのチェック """
                        if current_part in remaining_part:
                            if current_part in temporary_part:
                                circle_num += 1
                                """print "Finished a cycle!"""
                                remaining_part = remaining_part.difference(temporary_part)
                                if len(remaining_part) > 0:
                                    current_part = iter(remaining_part).next()
                                temporary_part = set([current_part])
                            else:
                                temporary_part.add(current_part)
                        else:
                            current_part = iter(remaining_part).next()
             
             
                        """
                        同じ紐番号をもつ結び目(今居る結び目以外)を検索
                        """
                        while (i == previous_area) or not(current_part in table[i]):
                            i += 1
                            i %= 4
             
                        previous_area = i
                        """
                        結び目(A,B,C,D)において
                        状態が"+"ならA<->B,C<->D,
                        状態が"-"ならA<->D,B<->C,
                        という遷移をする
                        """
                        if state[i] == 1:
                            ind = table[i].index(current_part)
                            current_part = table[i][(2*(ind % 2) - 1 + ind) % 4]
                        elif state[i] == -1:
                            ind = table[i].index(current_part)
                            current_part = table[i][(-2*(ind % 2) + 1 + ind) % 4]
                        else:
                            print "error"
                    print state
                    print (sum(state),circle_num)
                    ResultTable[sum(state)+4][circle_num] += 1
                    print np.poly1d([1]+[0]*(20 - 2*(circle_num-1) + sum(state))) * myu**(circle_num-1)
                    print ""
 
                    ResultArray = ResultArray + np.poly1d([1]+[0]*(20 - 2*(circle_num-1) + sum(state))) * myu**(circle_num-1)
    print ""
    print "重みの総和(ジョーンズ方程式:ただし、pythonはx^(負の数)を表現出来ないので、x^20が定数項となるように合わせている)"
    print ResultArray
 
if __name__ == "__main__":
    main()


アルゴリズムは時間がないので割愛するが、
実行結果は以下の通り。

[s1,s2,s3,s4] : 各結び目s_iの状態({-1,1})
(sum,circle)  : (各結び目s_iの状態({-1,1})の和 sum, 成分の数 circle)
xの多項式     : 各状態の重み
 注: pythonにはA^{-2}などを表現出来ないので,x^20=x^0となるように合わせている

[-1, -1, -1, -1]
(-4, 3)
   20     16     12
1 x  + 2 x  + 1 x 

[-1, -1, -1, 1]
(-2, 2)
    20     16
-1 x  - 1 x 

[-1, -1, 1, -1]
(-2, 2)
    20     16
-1 x  - 1 x 

[-1, -1, 1, 1]
(0, 1)
   20
1 x 

[-1, 1, -1, -1]
(-2, 2)
    20     16
-1 x  - 1 x 

[-1, 1, -1, 1]
(0, 1)
   20
1 x 

[-1, 1, 1, -1]
(0, 1)
   20
1 x 

[-1, 1, 1, 1]
(2, 2)
    24     20
-1 x  - 1 x 

[1, -1, -1, -1]
(-2, 2)
    20     16
-1 x  - 1 x 

[1, -1, -1, 1]
(0, 1)
   20
1 x 

[1, -1, 1, -1]
(0, 1)
   20
1 x 

[1, -1, 1, 1]
(2, 2)
    24     20
-1 x  - 1 x 

[1, 1, -1, -1]
(0, 3)
   24     20     16
1 x  + 2 x  + 1 x 

[1, 1, -1, 1]
(2, 2)
    24     20
-1 x  - 1 x 

[1, 1, 1, -1]
(2, 2)
    24     20
-1 x  - 1 x 

[1, 1, 1, 1]
(4, 3)
   28     24     20
1 x  + 2 x  + 1 x 


重みの総和(ジョーンズ方程式:ただし、pythonはx^(負の数)を表現出来ないので、x^20が定数項となるように合わせている)
   28     24     20     16     12
1 x  - 1 x  + 1 x  - 1 x  + 1 x