Weaveによる文書作成のテスト

  • Author: 黒木 玄
  • Date: 2019-03-13

ノートブック Convert ipynb to html, tex, pdf を実行すると, このファイルから jmd, html, tex, pdf ファイルが作成される. jmdファイルはJulia言語のコードを含むmarkdownファイルである.

$ \newcommand\real{\operatorname{Re}} \newcommand\imag{\operatorname{Im}} $

In [1]:
using Plots
gr()
##ENV["PLOTS_TEST"] = "true"
using SpecialFunctions
using Distributions
using SymPy

ガンマ函数とベータ函数

ガンマ函数とベータ函数は次のように定義される: $\real s, \real p, \real q > 0$ のとき

$$ \begin{aligned} & \Gamma(s) = \int_0^\infty e^{-x} x^{s-1}\,dx, \\ & B(p,q) = \int_0^1 x^{p-1} (1-x)^{q-1}\,dx \end{aligned} $$

と定義される.

注意: 複数行の数式は二重のドルマークで囲んだ aligned モードを使うことにした. weave() 函数で作成した tex ファイルを訂正を施す必要がある.

ガンマ函数のグラフ

ガンマ函数は階乗の連続的補間になっており, 急激に増大する函数になる. だから, グラフを描き易いように対数を取ったガンマ函数のグラフを描いてみよう. せっかくなので, グラフの中でStirlingの近似公式

$$ \log\Gamma(s) \approx s \log s - s - \frac{1}{2}\log s + \log\sqrt{2\pi} \quad\text{as $s\to\infty$} $$

の右辺と比較してみよう. 以下のプロットを見ればわかるようにほぼぴったり一致している.

In [2]:
lstirling(s) = s*log(s) - s - log(s)/2 + log((2π))
s = range(0.1, 10, length=400)
plot(size=(500, 300), legend=:topleft)
plot!(s, lgamma.(s), label="log Gamma(s)", lw=2)
plot!(s, lstirling.(s), label="Stirling approximation", ls=:dash, lw=2)
Out[2]:
0.0 2.5 5.0 7.5 10.0 0 2 4 6 8 10 12 log Gamma(s) Stirling approximation

ガンマ分布とベータ分布の密度函数のグラフ

$\theta,k,a,b>0$ に対して, ガンマ分布とベータ分布の確率密度函数がそれぞれ次のように定義される:

$$ \begin{aligned} & p(x) = \frac{1}{\theta^k \Gamma(k)} e^{-x/\theta} x^{k-1} \quad (x>0), \\ & q(x) = \frac{1}{B(a,b)} x^{a-1}(1-x)^{b-1} \quad (0 < x < 1). \end{aligned} $$

これらは $k,q,b$ が大きなとき, それぞれ正規分布の確率密度函数

$$ \begin{aligned} f(x|\mu,\sigma^2) = \frac{1}{\sqrt{2\pi\sigma^2}}e^{-(x-\mu)^2/(2\sigma^2)} \end{aligned} $$

の $(\mu,\sigma^2)=(k\theta, k\theta^2), (a/(a+b), ab/((a+b)^2(a+b+1)))$ の場合でよく近似されるようになる(中心極限定理の特別な場合). そのことをグラフを描いて確認しよう.

In [3]:
k, θ = 100, 1/80
gdist = Gamma(k, θ)
ndist = Normal(k*θ, k*θ)
x = range(0, 2.7, length=400)
plot(size=(500, 300))
title!("Normal approximation of Gamma distribution", titlefontsize=12)
plot!(legend=:topright)
plot!(x, pdf.(gdist, x), label="Gamma($k, )", lw=2)
plot!(x, pdf.(ndist, x), label="Normal approximation", ls=:dash, lw=2)
Out[3]:
0.0 0.5 1.0 1.5 2.0 2.5 0 1 2 3 Normal approximation of Gamma distribution Gamma(100, 0.0125) Normal approximation
In [4]:
a, b = 40, 60
bdist = Beta(a, b)
ndist = Normal(a/(a+b), (a*b/((a+b)^2*(a+b+1))))
x = range(0, 1, length=400)
plot(size=(500, 300))
title!("Normal approximation of Beta distribution", titlefontsize=12)
plot!(legend=:topright)
plot!(x, pdf.(bdist, x), label="Beta($a, $b)", lw=2)
plot!(x, pdf.(ndist, x), label="Normal approximation", ls=:dash, lw=2)
Out[4]:
0.00 0.25 0.50 0.75 1.00 0 2 4 6 8 Normal approximation of Beta distribution Beta(40, 60) Normal approximation

上で使ったガンマ函数の公式

上で使ったガンマ分布の確率密度函数 $p(x)=e^{-x/\theta}x^{k-1}/(\theta^k\Gamma(k))$ ($x>0$) が確率密度函数であることを示すためには, それの $0$ から $\infty$ までの積分が $1$ になること, すなわち,

$$ \int_0^\infty e^{-x/\theta} x^{k-1}\,dx = \theta^k \Gamma(k) \quad (\theta, k > 0) $$

が成立することを示さなければいけない. この公式は左辺を $x=\theta y$ で置換することによって得られる.

そのことはSymPyを使っても確かめられる. (注意: 以下の計算はθをSymPyの変数として使用しているので Python 2.7 では不可能. Python 3.x を使いましょう.)

In [5]:
k, θ, x = symbols("k θ x", positive=true)
sol = simplify(integrate(exp(-x/θ)*x^(k-1), (x, 0, oo)))
solstr = replace(sympy.latex(sol), "θ"=>"\\theta")
display("text/html", raw"$$\int_0^\infty e^{-x/\theta} x^{k-1}\,dx = " * solstr * raw"$$");
$$\int_0^\infty e^{-x/\theta} x^{k-1}\,dx = \theta^{k} \Gamma\left(k\right)$$

注意: LaTeXStrings.jl の latexstring() を使用して同じ数式を表示させると, weave(~, doctype="md2html") でうまく数式が表示されなくなる. 上のように mimetype text/htmldisplay を使用し, 行末に ; を付ければうまく表示されるようになる.

Riemannのゼータ函数

Riemannのゼータ函数は $\real s > 1$ において

$$ \zeta(s) = \sum_{n=1}^\infty \frac{1}{n^s} \quad (\real s > 1) $$

と定義され, 唯一の極 $s=1$ を除いた複素平面全体に解析接続される.

Riemannのゼータ函数の $0\leqq \real s\leqq 1$ (critical strip)における零点を非自明な零点と呼ぶ.

Riemann予想: Riemannのゼータ函数の非自明な零点はすべて直線 $\real s=1/2$ 上に乗っている.

Riemannのゼータ函数の非自明な零点は素数の分布の精密な評価と関係している.

Riemann予想の成立を(数学的な証明にはならないが)数値的な計算で確認してみよう

Riemannのゼータ函数の絶対値の対数のheatmap

In [6]:
f(s) = max(min(log(abs(zeta(s))), 3), -5)
x = range(0, 1, length=100)
y = range(10, 45, length=400)
s = @. x + im*y'
plot(size=(750, 180))
title!("log(abs(zeta(x+iy)))", titlefontsize=12)
heatmap!(y, x, f.(s), color=:thermal)
xlabel!("y")
ylabel!("x")
hline!([0.5], ls=:dot, color=:cyan, label="")
Out[6]:
10 20 30 40 0.00 0.25 0.50 0.75 1.00 log(abs(zeta(x+iy))) y x - 4 - 3 - 2 - 1 0 1

Riemannのゼータ函数の絶対値の Re s = 1/2 上の様子

In [7]:
f(s) = abs(zeta(s))
x = 1/2
y = range(10, 45, length=1000)
s = @. x + im*y
plot(size=(720, 200))
title!("abs(zeta(0.5+iy)))", titlefontsize=12)
plot!(y, f.(s), label="")
xlabel!("y")
Out[7]:
10 20 30 40 0 1 2 3 abs(zeta(0.5+iy))) y

Riemannのゼータ函数の Re s = 1/2 上での複素数値

直線 $\real s = 1/2$ での $\zeta(s)$ の値は何度も繰り返し複素平面の原点 $0$ を通る.

In [8]:
x = 1/2
y = range(0, 45, length=1000)
s = @. x + im*y
w = zeta.(s)
plot(size=(500,400), legend=:topleft)
title!("zeta(0.5+it) for 0 < t < 45", titlefontsize=12)
plot!(real(w), imag(w), label="zeta(0.5+it)")
scatter!([0], [0], markersize=2, label="")
xlabel!("x")
ylabel!("y")
annotate!([(-1.25, 0.1, "zeta(0.5)", 9)])
annotate!([(2.55, 1.7, "zeta(0.5+45i)", 9)])
Out[8]:
-1 0 1 2 3 -1 0 1 2 zeta(0.5+it) for 0 < t < 45 x y zeta(0.5+it) zeta(0.5) zeta(0.5+45i)

Riemannのゼータ函数の Re s = 0.6 上での複素数値

直線 $\real s = 0.6$ での $\zeta(s)$ の値を計算すると複素平面の原点を避けて通っていることがわかる.

In [9]:
x = 0.6
y = range(0, 45, length=1000)
s = @. x + im*y
w = zeta.(s)
plot(size=(500,400), legend=:topleft)
title!("zeta(0.6+it) for 0 < t < 45", titlefontsize=12)
plot!(real(w), imag(w), label="zeta(0.6+it)")
scatter!([0], [0], markersize=2, label="")
xlabel!("x")
ylabel!("y")
annotate!([(-1.6, 0.1, "zeta(0.6)", 9)])
annotate!([(2.55, 1.4, "zeta(0.6+45i)", 9)])
Out[9]:
-2 -1 0 1 2 -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 zeta(0.6+it) for 0 < t < 45 x y zeta(0.6+it) zeta(0.6) zeta(0.6+45i)

手書きのノート

ガンマ函数とベータ函数入門(1)

ガンマ函数とベータ函数入門1

ガンマ函数とベータ函数入門(2)

ガンマ函数とベータ函数入門2

Hurwitzのゼータ函数とガンマ函数の関係

Hurwitzのゼータ函数とガンマ函数の関係

In [ ]: