三角関数に隠された組み合わせの秘密

# はじめに
本記事では, 三角関数のべき級数展開とある組み合わせとの関わりについて触れたいと思います.
少し長くなりますが高度な数学はほとんど登場しないので, 気楽に読んでいただければ幸いです.

# 三角関数はスリザリン？
三角関数といえば, 高校数学の中でも鬼門として知られている分野の1つです.
分かりにくい定義に始まり加法定理をはじめとした数々の公式, 「思いつくかボケ」と言わざるを得ない置換積分など…
筆者も当時とても苦しめられた覚えがあります.
そんな三角関数の中でも, __ズバ抜けて人気がない__ ことで有名なのが __タンジェント__ です.
[@Keyneqq](https://twitter.com/Keyneqq) さんによる以下のツイートの反響がそんな世の声を反映していますね.

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">どうせ君も私が嫌いなんだろ？<br>積分問題とかで私がいると「うわ…」とか思ってるんだろ？<br>全部知ってるんだぞ <a href="https://t.co/zqgWsdMoDO">pic.twitter.com/zqgWsdMoDO</a></p>&mdash; きいねく@とりあえずやる (@Keyneqq) <a href="https://twitter.com/Keyneqq/status/914104656799744002?ref_src=twsrc%5Etfw">September 30, 2017</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

また三角関数は大学入学後 $\csc, \sec, \cot$ の登場により3種類から倍の6種類になります.
さらに追い打ちをかけるように逆三角関数も登場し, 性質や関係式も一気に増えます.

このように __マルフォイも思わず黙るフォイしてしまう__ 三角関数ですが, そんな彼らにも人々を魅了する驚きの一面が存在します.

__なんと！とある順列と深くかかわっているのです！__
__すごい！不思議！素敵！__

本記事を通して, 三角関数が本当は __スリザリン__ ではなく __グリフィンドール__ だったということを皆さんにご紹介したいと思います.

# 交代順列とZig-Zag Number
まず, 本記事で重要な役割を果たす順列と数列を定義しましょう.

$\\{1,2, \cdots,n\\}$ の順列 $(s_1, s_2, \cdots, s_n)$ のうち,

```math
s_1 < s_2 > s_3 < \cdots 
```

となるものを長さ $n$ の __交代順列__ といいます.
一方で不等号が反転し,

```math
s_1 > s_2 < s_3 > \cdots 
```

となっているものを長さ $n$ の __逆交代順列__ といいます.

また長さ $n$ の交代順列の総数を $Alt_n$ と書き, 長さ $n$ の逆交代順列の総数を $Ralt_n$ と書きます.
ただし便宜上, $Alt_0 = Alt_1 = Ralt_0 = Ralt_1 := 1$ と定めます. 

例えば長さ $4$ の交代順列は,

```math
(1, 3, 2, 4), (1, 4, 2, 3), (2, 3, 1, 4), (2, 4, 1, 3), (3, 4, 1, 2)
```
の $5$ つなので $Alt_4 = 5$ となり, また長さ $4$ の逆交代順列は,

```math
(2, 1, 4, 3), (3, 1, 4, 2), (3, 2, 4, 1), (4, 1, 3, 2), (4, 2, 3, 1)
```
の $5$ つなので $Ralt_4 = 5$ となります.

ここで勘の良い方はお気づきかもしれませんが, $Alt_4$ と $Ralt_4$ が同じ値になったのは偶然ではありません.
実は, 長さ $n$ の交代順列全体の集合と逆交代順列全体の集合の間には全単射が存在します.
難しくないので, よろしければ全単射をどのように構成するか考えてみてください.
具体的な全単射の1つを以下に載せておきます.

<details><summary>全単射の具体例</summary><div>
長さ $n$ の交代順列全体から長さ $n$ の逆交代順列全体への写像 $f$ を次で定義します.

```math
f ((s_1, s_2, \cdots, s_n)) := (n + 1 -s_1, n + 1 - s_2, \cdots, n + 1 - s_n)
```
このとき, $f$ は全単射になっていることが簡単に確認できます.
</div></details>

 
つまり, 全ての非負整数 $n$ に対して $Alt_n = Ralt_n$ が成り立ちます.
これは, 交代順列と逆交代順列は本質的に同じということを意味します.

交代順列における要素間の符号が $< \hspace{2.5mm} , \hspace{2.5mm} > \hspace{2.5mm}, \hspace{2.5mm} < \hspace{2.5mm}, \hspace{2.5mm} >  \cdots$ と不等号が交互に反転していることから, $Alt_n$ は __Zig-Zag Number__ と呼ばれます. 

以下のコードを実行すれば, 長さ $10$ 程度までの Zig-Zag Number を確認することができます.[^1]


```python3:ZigZagNumber.py
import itertools
import numpy
def getZigZagNumber(num):
    # 0, 1, 2番目のZig-Zag Numberは1と定義
    if (num == 0) or (num == 1) or (num == 2):
        return 1
    else:
        # 長さnの順列全てを取得
        permList = []
        for i in itertools.permutations(list(range(num))):
            permList.append(i)
        frontSign = 0
        backSign = 0
        alterPerm = []
        # i番目とi + 1番目の差をとって符号を取得し,
        # 前ステップで取得した i - 1番目とi番目の差の符号との積をとる
        for perm in permList:
            for i in range(len(perm) - 1):
                # 最初は0番目と1番目の差の符号のみを取得する
                # 0番目と1番目の差の符号が正であれば交代順列の定義に反するので終了
                # 0番目と1番目の差の符号が負であれば次のステップへ
                if i == 0:
                    frontSign = numpy.sign(perm[i] - perm[i + 1])
                    if frontSign == 1:
                        break
                    continue
                backSign = numpy.sign(perm[i] - perm[i + 1])
                # 積が1であれば符号が反転しておらず交代順列の定義に反するので終了
                if frontSign * backSign == 1:
                    break
                # 積が-1であれば符号が反転しているので次のステップへ進む
                else:
                    frontSign = backSign
                if i == len(perm) - 2:
                   # 交代順列であれば配列に格納
                    alterPerm.append(perm)
        # 配列の長さ＝交代順列の総数を返す
        return len(alterPerm)

# 求めたいZig-Zag Numberの長さ
length = 11

for i in range(length):
    print('Alt_', i , ':', getZigZagNumber(i))
```

```:出力
Alt_ 0 : 1
Alt_ 1 : 1
Alt_ 2 : 1
Alt_ 3 : 2
Alt_ 4 : 5
Alt_ 5 : 16
Alt_ 6 : 61
Alt_ 7 : 272
Alt_ 8 : 1385
Alt_ 9 : 7936
Alt_ 10 : 50521
```

交代順列により定義されたこの Zig-Zag Number がある三角関数と関わっているのです.

# Zig-Zag Number と三角関数の関係
## 母関数
我々人類は, 数列が与えられるとその性質や一般項を調べたくなってしまうものです.
そんなときに強力な武器となるのが __母関数__ です.
母関数とは数列を係数に持つ形式的べき級数のことであり, 組み合わせ論や整数論をはじめとした様々な数学の分野で登場します.
べき級数の形に伴っていくつか種類があるのですが, 今回は $f(x) = \sum_{n = 0}^{\infty}\frac{a_n}{n!}x^{n}$ の形をした __指数型母関数__ を扱います.[^2]

具体例をいくつか見ていきましょう.

例えば定数列 $a_n = 1$ の母関数 $f(x)$ は,

```math
\begin{align*}
f(x) & = \sum_{n = 0}^{\infty}\frac{a_n}{n!}x^{n}\\
& = \sum_{n = 0}^{\infty}\frac{1}{n!}x^{n}\\
& = e^{x}
\end{align*}
```

より $f(x) = e^{x}$ となります.

また $a_n = n!$ の母関数 $f(x)$ は,

```math
\begin{align*}
f(x) & = \sum_{n = 0}^{\infty}\frac{a_n}{n!}x^{n}\\
& = \sum_{n = 0}^{\infty}\frac{n!}{n!}x^{n}\\
& = \sum_{n = 0}^{\infty}x^{n}\\
& = \dfrac{1}{1 - x}
\end{align*}
```

より $f(x) = \frac{1}{1 - x}$ となります.

この母関数という考え方が Zig-Zag Number と三角関数を結びつけます.

## Zig-Zag Numberが満たす漸化式
本題に入る前にもう1つだけ準備をしておきましょう.
Zig-Zag Numberは次の漸化式を満たします.

```math
2Alt_{n + 1} = \sum_{k = 0}^{n}\binom{n}{k}Alt_{n-k}Alt_{k} \hspace{1cm} (n \geq 1)
```

以下これを示します.

$[n] := \\{1, 2, \cdots, n\\}$ の部分集合 $S$ のうち, $|S| = k$ となるようにとる選び方は $\binom{n}{k}$ 通りです.
また, $\bar{S} := \[n\] \setminus S$ と定めると $S$ の中から交代順列 $u$ をとる選び方は $Alt_{k}$ 通りで, $\bar{S}$ の中から交代順列 $v$ をとる選び方は $Alt_{n - k}$通りです.
さて, 交代順列 $u = (u_{1}, u_{2}, \cdots, u_{k})$ に対して $u^{r}$ を $u^{r} := (u_{k}, u_{k - 1}, \cdots, u_{1})$ で定義し, 順列 $w$ を $w := (u^{r}, n + 1, v)$ と定めましょう.
このとき, $u$ と $v$ の選び方によって $w$ は長さ $n + 1$ の交代順列. 逆交代順列のみを全て作ることができます.
ここで交代順列の総数と逆交代順列の総数が同じであることを思い出すと, $w$ は全てで $2Alt_{n + 1}$ 通りあることが分かります.
また, $(u^{r}, n + 1, v)$ の選び方は $\binom{n}{k}Alt_{n - k}Alt_{k}$ 通りあります.
従って, 

```math
2Alt_{n + 1} = \sum_{k = 0}^{n}\binom{n}{k}Alt_{n-k}Alt_{k}
```

を得ることができました.

## 主定理
お待たせしました.
では早速 Zig-Zag Number と三角関数の関係を紐解いていきましょう.
$Alt_n$ の母関数を $f(x) = \sum_{n = 0}^{\infty}\frac{Alt_{n}}{n!}x^{n}$ と定義します.
このとき $f(0) = 1$ であり , $Alt_{n}$ の漸化式から $f(x)$ は次の微分方程式を満たすことが分かります.

```math
2f^{'}(x) = f(x)^{2} + 1.
```

これは変数分離形で解くことができ, 解は次で与えられます.

```math
f(x) = \tan x + \sec x.
```

つまり,

```math
\sum_{n = 0}^{\infty}\frac{Alt_{n}}{n!}x^{n} = \tan x + \sec x
```

ということになります.
これが何を意味しているのかを説明します.
まず $\tan x$ と $\sec x$ はそれぞれ奇関数, 偶関数なので $\tan x + \sec x$ のTaylor展開は $\tan x$ と $\sec x$ のTeylor展開の項が交互に現れることになります.
そしてべき級数展開の一意性から左辺のべき級と右辺のべき級は等しいので, $\tan x$ のTaylor展開の係数は奇数番目の Zig-Zag Number に, $\sec x$ のTaylor展開の係数は偶数番目の Zig-Zag Number と一致するのです.
つまり $\tan x = \sum_{n = 0}^{\infty}\frac{T_{2n + 1}}{(2n + 1)!}x^{2n + 1}$, $\sec x = \sum_{n = 0}^{\infty}\frac{S_{2n}}{(2n)!}x^{2n}$ とするとき,

```math
Alt_{n} = \left\{
\begin{array}{ll}
T_{n} & (n:奇数) \\
S_{n} & (n:偶数)
\end{array}
\right.
```

となるわけです.[^3]
こうして三角関数である $\tan x, \sec x$ と組み合わせから定義される Zig-Zag Number が紐づきました.
__当たり前ですがこれはとても非自明です.__
$T_n, S_n$ に組み合わせ論的解釈が与えられるどころか, そもそも自然数になることですら非自明なのですから.
どうでしょう, めちゃくちゃ面白くないですか？[^4]

以下に $\tan x + \sec x$ の係数を出力するプログラムを掲載します.[^5]
その目で $Alt_n$ と等しいということを確認してみてください.

```python:getST.py
from sympy import var, series, poly, tan, sec
import math

# シンボルxを定義
x = var('x')

# 級数展開を定義
f = series(tan(x) + sec(x), x, n = 11)

# 級数を多項式オブジェクトに変換
g = poly(f)

# すべての係数を取得
coeffs = g.coeffs()
coeffs.reverse()

# ランダウのO記号の係数である1が先頭に入ってしまうので削除
coeffs.pop(0)

# 表示
index = 0
for coef in coeffs:
    coef = coef * math.factorial(index)
    if index % 2 == 0:
        print('S_', index , '=', coef)
    else:
        print('T_', index , '=', coef)
    index += 1
```

```:出力
S_ 0 = 1
T_ 1 = 1
S_ 2 = 1
T_ 3 = 2
S_ 4 = 5
T_ 5 = 16
S_ 6 = 61
T_ 7 = 272
S_ 8 = 1385
T_ 9 = 7936
S_ 10 = 50521
```

# tan x, sec x のTaylor展開と Zig-Zag Number の性質
ところで皆さんは $T_n$, $S_n$ の一般項を知っていますか？
$\sin x$ や $\cos x$ のTaylor展開はよくご存じと思いますが, $\tan x$ や $\sec x$ のTaylor展開はあまり見たことがないと思います.
余白の関係上証明はしませんが, せっかくなのでご紹介しましょう.

```math
\begin{align*}
\tan x &= \sum_{n = 1}^{\infty}(-1)^{n - 1}\dfrac{B_{2n}}{2n}(2^{2n}-1)2^{2n}\dfrac{x^{2n-1}}{(2n - 1)!}\\
\sec x &= \sum_{n = 0}^{\infty}(-1)^{n + 1}\dfrac{4^{2n + 1}}{2n + 1}B_{2n + 1}\left(\dfrac{1}{4}\right)\dfrac{x^{2n}}{(2n)!}
\end{align*}
```
ただし上記に現れている $B_n$, $B_n(t)$ はそれぞれ Bernoulli数, Bernoulli多項式と呼ばれ次で定義されます. 

```math
\begin{align*}
\dfrac{xe^{x}}{e^{x} - 1} &= \sum_{n = 0}^{\infty}\dfrac{B_{n}}{n!}x^{n}\\
\dfrac{xe^{tx}}{e^{x} - 1} &= \sum_{n = 0}^{\infty}\dfrac{B_{n}(t)}{n!}x^{n}
\end{align*}
```

いかがでしょう, __最高にキモくないですか？__
$\sin x$ や $\cos x$ のときのようにスマートに書くことはできませんね.
こんなに汚くなってしまうのにこれが自然数になってしまう, それどころか組み合わせ論的解釈が与えられてしまうというのが驚きです.
また, Bernoulli数やBernoulli多項式は整数論の分野で頻出しとても重要な対象として知られているのですが, それらが三角関数のTaylor展開に現れているのも驚きです.
本当に数学の諸分野はつながっているんだなと感心させられますね.

さて, 最後に Zig-Zag Number の面白い性質をいくつか見ていきましょう.
次の表をご覧ください.

|  $n$  |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  10  |   
| :----: | :----: |:----: |:----: |:----: |:----: |:----: |:----: |:----: |:----: |:----: |:----: |
|  $Alt_n$  |  1  |  1  |  1  |  2  |  5  |  16  |  61  |  272  |  1385  |  7936 |  50521  | 

 $n \geq 2$ 以上のとき, __偶数と奇数が交互に出現している__ことが分かります.
偶数番目のときには奇数, 奇数番目のときには偶数が現れていますね.
これはなかなか興味深い性質です.
ここでさらに, 1桁目のみに着目してみましょう.

|  $n$  |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  10  |   
| :----: | :----: |:----: |:----: |:----: |:----: |:----: |:----: |:----: |:----: |:----: |:----: |
|  $Alt_n \% 10$  |  1  |  1  |  1  |  2  |  5  |  6  |  1  |  2  |  5  |  6 |  1  |
 $n \geq 2$ 以上のとき, __偶数番目には 1 と 5 が交互に並んでおり, 奇数番目には 2 と 6 が交互に並んでいます.__
Zig-Zag Number にはこんな性質も隠されていたのです.
ちなみにこの2つは Bernoulli数, Bernoulli多項式の性質から導くことができます.
もしよければ調査, 証明してみてください.

# おわりに
本記事では三角関数と交代順列, Zig-Zag Number との関係について解説してきました.
このZig-Zag Number には様々な一般化や解釈が考えられているので, 興味のある方は調べてみてください.
後述するStanleyのサーベイがよくまとまっていて参考になります.

今日もどこかで誰かが三角関数のことを嫌いになろうとしているかもしれません.
しかし三角関数とはこんなにも愛おしいものであるということを忘れないでください.
三角関数をスリザリンと笑っている, そんなあなたこそがスリザリンなのかもしれません（？）

# 参考文献
- [Stanley, Richard P. "A survey of alternating permutations." Contemp. Math 531 (2010): 165-196.](http://www-math.mit.edu/~rstan/papers/altperm.pdf)
- [Alternating permutation - Wikipedia](https://en.wikipedia.org/wiki/Alternating_permutation)

[^1]: 一度全順列を取得後条件を満たすものを選んでいるのでとても重いです. 上手い方法があれば是非教えてください.
[^2]: この他に通常型母関数, 多項式列母関数や多変数型母関数などがあります.
[^3]: 文献によっては $S_n$ を __Euler 数__, $T_n$ を __タンジェント数__ とも呼びます.
[^4]: ちなみにこの結果は __André の定理__と呼ばれ, 1881年に Désiré André によって証明されています. 
[^5]: こちらは ```ZigZagNumber.py``` ほど重くなくメモリも消費しないので, 大きなインデックスに対しても動きます.