Thue-Morse列

red参考: Mathematica Notebook: thue_morse.nb

0と1からなるThue-Morse列(TM列) $t=t_0t_1t_2\dots t_n\dots$ は次のように複数の方法で定義できる。

Thue-Morse列(1)

非負整数 $n\geq 0$を2進表示 $[n]_2$において \[ t_n=\begin{cases}0 & \text{$[n]_2$での1の数が偶数, $|[n]_2|_1=$even}\\ 1 & \text{$[n]_2$での1の数が奇数, $|[n]_2|_1=$odd}\end{cases} \]

上のThue-Morse列の定義は、$n$を2進表示したときのdigitsの総和を $d_2sum(n)$ としたとき、次のよう書くこともできる。

\[ t_n=d_2sum(n) \bmod{2} \]
演習: $n=0,\dots 20$までのThue-Morse列を手計算で実際に求めてみなさい。
演習:Mathematicaでは、$d_2sum(n)$は Apply[Plus, IntegerDigits[n, 2]] と計算できる。 $m \bmod 2$ を計算するMathematica関数 Mod[m,2] を使って、Thue-Morse列値 $t_n$ を返す関数 thue[n] を書きなさい。

演習: 非負整数 $n\geq 0$ を2進数表示 $[n]_2$ し、その最上位ビットから順番に最下位ビットまで入力して得られる出力が$n$番目のThue-Morse列値 $t_n$ となるような出力付き有限オートマトンを与えなさい。

Thue-Morse列(2) 再帰的定義

Thue-Morse列(TM列)$t=t_0t_1t_2\dots t_n\dots$は、次のようにして再帰的に定義される。

\begin{align*} & t_0 = 0,\\ & t_{2n}= t_n,\quad \text{if $2n$ is even}\\ & t_{2n+1}= 1-t_n, \quad\text{if $2n+1$ is odd}. \end{align*}
演習: $n=0,\dots 20$までのThue-Morse列を、再帰的定義だけを使って手計算してみなさい。
演習: Thue-Morse列値 $t_n$ を返す再帰的に定義されたMathematica関数 thue2[n] を書きなさい。

ヒント

関数定義の引数(左辺)では thue[2 n_] というように式を書くことができず、thue[n_] で定義する。 そのため、組み込み関数 Whichを使い、引数 n の条件をチェックするやり方がある。 分かりやすいように、改行などして表記を工夫しよう。

thue[n_Integer] := Which[
  n == 0, 0,
  EvenQ[n], thue[n/2],
  OddQ[n], 1 - thue[(n - 1)/2]
]

Mathematicaの利用で大変強力なのが、patt /; test のように制約条件 test を /; の後に書いて、条件 test がTrueとなった場合に限りpatt にパターンマッチさせることができる点である。

thue[0] := 0;
thue[n_] := thue[n/2] /; EvenQ[n];
thue[n_] := thue[(n - 1)/2] /; OddQ[n]

ほぼ、漸化式の定義に近い形で関数が定義されることに注意。

0番目からn番目のThue-Morse列

$n$を与えて0番目からn番目のThue-Morse列値をリストとして返すMathematica関数 thuemorse[n] は、thue[n] または thue2[n] を使うと Table[thue[i], {i, 0, n}] で定義できる。

演習: 関数 thuemorse[n] を書いて、$n=100$の結果を出力してみなさい。

$n$番目までの非負整数集合のdisjoint分割

$n$番目までの非負整数集合 $N_n=\{0,1,2,\dots, n\}$ を \[ N_n = A_n \cup B_n,\qquad A_n \cap B_n =\phi \] のように、disjointな集合$A_n$と$B_n$の2つの集合に分割することを考えよう。

Thue-Morse列を使って \begin{gather*} A_n=\{t_n \,|\, t_n=0\},\\ B_n=\{t_n \,|\, t_n=1\}\\ \end{gather*} のようにして、集合$A_n$と$B_n$を選ぶことができる。 これを実際に求めるMathematicaプログラムを考えよう。

次のようなMathematica計算に注意しよう。 0番目から9番目までのThue-Morse列 {0, 1, 1, 0, 1, 0, 0, 1、1} で、0または1がリスとの何番目にためにMathematica関数 Position を使っている。

Position[{0, 1, 1, 0, 1, 0, 0, 1, 1, 0}, 0]
    {{1}, {4}, {6}, {7}, {10}}
Position[{0, 1, 1, 0, 1, 0, 0, 1, 1, 0}, 1]
    {{2}, {3}, {5}, {8}, {9}}

Flatten[Position[{0, 1, 1, 0, 1, 0, 0, 1, 1, 0}, 0]]
    {1, 4, 6, 7, 10}
Flatten[Position[{0, 1, 1, 0, 1, 0, 0, 1, 1, 0}, 1]]
    {2, 3, 5, 8, 9}

Flatten[Position[{0, 1, 1, 0, 1, 0, 0, 1, 1, 0}, 0]] - 1
    {0, 3, 5, 6, 9}
Flatten[Position[{0, 1, 1, 0, 1, 0, 0, 1, 1, 0}, 1]] - 1
    {1, 2, 4, 7, 8}
演習: $n$番目までのThue-Morse列を使って、0または1を指定して、0から$n$までの非負整数集合を2つの集合に分割したリスト(集合)返す関数 positionThueMorse[n_Integer, s_] を書きなさい(sには0または1を指定する)。

Multigrades集合の検証

2つの非零整数のdisijoint集合$A$および$B$がMultigradesとは以下の条件を満たす集合$A, B$が存在するときである。

\[ \sum_{a\in A}a^i=\sum_{b\in B}b^i,\qquad i=0,1,2,\dots,c \]

Thue-Morse列を使って、検証0から$n$までの非零整数のdisijoint集合への分割を \begin{gather*} A_n=\{0\leq j<2^{n+1} \,|\, t_n=0\},\\ B_n=\{0\leq j<2^{n+1} \,|\, t_n=1\} \end{gather*} と定義する。

演習: このとき、$i=0,1,\dots, n$について \[ \sum_{a\in A_n}a^i=\sum_{b\in B_n}b^i,\qquad i=0,1,2,\dots,n \] が成立することをMathematicaプログラムを書いて確かめなさい。

Thue-Morse列(3) morphism

$\Sigma$と$\Delta$をアルファベットとする。 (morphism)とは、写像 $\psi: \Sigma^*\rightarrow\Delta^*$で \[ \psi(xy)=\psi(x)\psi(y),\qquad \text{word $x,y\in\Sigma^*$} \] を満たすものである。

$\Sigma=\Delta=\{0,1\}$として、 Thue-Morse morphism $\tau$を \begin{gather*} \tau(0) = 0 1,\\ \tau(1)= 10 \end{gather*} で定義する。

\begin{align*} \tau^0(0) &= 0,\\ \tau^1(0) &= 01,\\ \tau^2(0) &= \tau(01)=0110,\\ \tau^3(0) &=\tau(0110) =01101001,\\ \dots \end{align*} というようにして、Thue-Morse列 $t=(t_n)$ は \[ t=\lim_{n\rightarrow\infty}\tau^n(0) \] によって得られる。

演習: 実行結果が
ProuhetThueMorse[{0}, 3]
    {0, 1, 1, 0, 1, 0, 0, 1}
となるような、初期リスト {0} を与えて Thue-Morse morphism を$n$回繰り返した結果リストを返すMathematica関数 ProuhetThueMorse[{0}, n] を考えよう。

このために、Thue-Morse morphism を

tm[0] := {0, 1};  
tm[1] := {1, 0};
SetAttributes[tm, Listable];
というように、関数属性 Listable を付けて定義する。 このとき、関数 tm をリスト lst に$n$回繰り返して得られるリストを返す関数を
ProuhetThueMorse[lst_List, n_Integer] := Flatten[Nest[tm, lst, n]]
で定義する。 組み込み関数 Nest を使っていることに注意する。

$n=1,2,3,\dots$で返されるリストがThue-Morse列になっていることを確かめなさい。