aboutsummaryrefslogtreecommitdiffstats
path: root/buch/papers/laguerre/scripts
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--buch/papers/laguerre/scripts/gamma_approx.ipynb80
-rw-r--r--buch/papers/laguerre/scripts/gamma_approx.py197
-rw-r--r--buch/papers/laguerre/scripts/integrand.py49
-rw-r--r--buch/papers/laguerre/scripts/laguerre_plot.py5
4 files changed, 317 insertions, 14 deletions
diff --git a/buch/papers/laguerre/scripts/gamma_approx.ipynb b/buch/papers/laguerre/scripts/gamma_approx.ipynb
index 44f3abd..a8280aa 100644
--- a/buch/papers/laguerre/scripts/gamma_approx.ipynb
+++ b/buch/papers/laguerre/scripts/gamma_approx.ipynb
@@ -136,14 +136,17 @@
"def laguerre_gamma(z, x, w, target=11):\n",
" # res = 0.0\n",
" z = complex(z)\n",
- " if z.real < 1e-3:\n",
- " res = pi / (\n",
- " sin(pi * z) * laguerre_gamma(1 - z, x, w, target)\n",
- " ) # Reflection formula\n",
- " else:\n",
- " z_shifted, correction_factor = find_shift(z, target)\n",
- " res = np.sum(x ** (z_shifted - 1) * w)\n",
- " res *= correction_factor\n",
+ " # if z.real < 1e-3:\n",
+ " # res = pi / (\n",
+ " # sin(pi * z) * laguerre_gamma(1 - z, x, w, target)\n",
+ " # ) # Reflection formula\n",
+ " # else:\n",
+ " # z_shifted, correction_factor = find_shift(z, target)\n",
+ " # res = np.sum(x ** (z_shifted - 1) * w)\n",
+ " # res *= correction_factor\n",
+ " z_shifted, correction_factor = find_shift(z, target)\n",
+ " res = np.sum(x ** (z_shifted - 1) * w)\n",
+ " res *= correction_factor\n",
" res = drop_imag(res)\n",
" return res\n"
]
@@ -207,9 +210,9 @@
"metadata": {},
"outputs": [],
"source": [
- "zeros, weights = np.polynomial.laguerre.laggauss(12)\n",
- "targets = np.arange(16, 21)\n",
- "mean_targets = ((16, 17),)\n",
+ "zeros, weights = np.polynomial.laguerre.laggauss(8)\n",
+ "targets = np.arange(9, 14)\n",
+ "mean_targets = ((9, 10),)\n",
"x = np.linspace(EPSILON, 1 - EPSILON, 101)\n",
"_, axs = plt.subplots(\n",
" 2, sharex=True, clear=True, constrained_layout=True, figsize=(12, 12)\n",
@@ -226,7 +229,7 @@
"maxs = []\n",
"for target in targets:\n",
" rel_error = evaluate(x, target)\n",
- " mins.append(np.min(np.abs(rel_error[(0.1 <= x) & (x <= 0.9)])))\n",
+ " mins.append(np.min(np.abs(rel_error[(0.05 <= x) & (x <= 0.95)])))\n",
" maxs.append(np.max(np.abs(rel_error)))\n",
" axs[0].plot(x, rel_error, label=target)\n",
" axs[1].semilogy(x, np.abs(rel_error), label=target)\n",
@@ -365,6 +368,59 @@
"# _ = ax.legend([f\"z={zi}\" for zi in z[0]])\n",
"# _ = [ax.axvline(x) for x in zeros]\n"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "bests = []\n",
+ "N = 200\n",
+ "step = 1 / (N - 1)\n",
+ "a = 11 / 8\n",
+ "b = 1 / 2\n",
+ "x = np.linspace(step, 1 - step, N + 1)\n",
+ "ns = np.arange(2, 13)\n",
+ "for n in ns:\n",
+ " zeros, weights = np.polynomial.laguerre.laggauss(n)\n",
+ " est = np.ceil(b + a * n)\n",
+ " targets = np.arange(max(est - 2, 0), est + 3)\n",
+ " rel_errors = np.stack([np.abs(evaluate(x, target)) for target in targets], -1)\n",
+ " best = np.argmin(rel_errors, -1) + targets[0]\n",
+ " bests.append(best)\n",
+ "bests = np.stack(bests, 0)\n",
+ "\n",
+ "fig, ax = plt.subplots(clear=True, constrained_layout=True, figsize=(5, 3))\n",
+ "v = ax.imshow(bests, cmap=\"inferno\", aspect=\"auto\")\n",
+ "plt.colorbar(v, ax=ax, label=r'$m$')\n",
+ "ticks = np.arange(0, N + 1, 10)\n",
+ "ax.set_xlim(0, 1)\n",
+ "ax.set_xticks(ticks, [f\"{v:.2f}\" for v in ticks / N])\n",
+ "ax.set_xticks(np.arange(N + 1), minor=True)\n",
+ "ax.set_yticks(np.arange(len(ns)), ns)\n",
+ "ax.set_xlabel(r\"$z$\")\n",
+ "ax.set_ylabel(r\"$n$\")\n",
+ "# for best in bests:\n",
+ "# print(\", \".join([f\"{int(b):2d}\" for b in best]))\n",
+ "# print(np.unique(bests, return_counts=True))\n",
+ "\n",
+ "targets = np.mean(bests, -1)\n",
+ "intercept, bias = np.polyfit(ns, targets, 1)\n",
+ "_, axs2 = plt.subplots(2, sharex=True, clear=True, constrained_layout=True)\n",
+ "xl = np.array([1, ns[-1] + 1])\n",
+ "axs2[0].plot(ns, intercept * ns + bias)\n",
+ "axs2[0].plot(ns, targets, \"x\")\n",
+ "axs2[1].plot(ns, ((intercept * ns + bias) - targets), \"-x\")\n",
+ "print(np.mean(bests, -1))\n",
+ "print(f\"Intercept={intercept:.6g}, Bias={bias:.6g}\")\n",
+ "\n",
+ "\n",
+ "predicts = np.ceil(intercept * ns[:, None] + bias - x)\n",
+ "print(np.sum(np.abs(bests-predicts)))\n",
+ "# for best in predicts:\n",
+ "# print(\", \".join([f\"{int(b):2d}\" for b in best]))\n"
+ ]
}
],
"metadata": {
diff --git a/buch/papers/laguerre/scripts/gamma_approx.py b/buch/papers/laguerre/scripts/gamma_approx.py
new file mode 100644
index 0000000..90843b1
--- /dev/null
+++ b/buch/papers/laguerre/scripts/gamma_approx.py
@@ -0,0 +1,197 @@
+from pathlib import Path
+
+import matplotlib as mpl
+import matplotlib.pyplot as plt
+import numpy as np
+import scipy.special
+
+EPSILON = 1e-7
+root = str(Path(__file__).parent)
+img_path = f"{root}/../images"
+
+
+def _prep_zeros_and_weights(x, w, n):
+ if x is None or w is None:
+ return np.polynomial.laguerre.laggauss(n)
+ return x, w
+
+
+def drop_imag(z):
+ if abs(z.imag) <= EPSILON:
+ z = z.real
+ return z
+
+
+def pochhammer(z, n):
+ return np.prod(z + np.arange(n))
+
+
+def find_shift(z, target):
+ factor = 1.0
+ steps = int(np.floor(target - np.real(z)))
+ zs = z + steps
+ if steps > 0:
+ factor = 1 / pochhammer(z, steps)
+ elif steps < 0:
+ factor = pochhammer(zs, -steps)
+ return zs, factor
+
+
+def laguerre_gamma_shift(z, x=None, w=None, n=8, target=11):
+ x, w = _prep_zeros_and_weights(x, w, n)
+
+ z += 0j
+ z_shifted, correction_factor = find_shift(z, target)
+ res = np.sum(x ** (z_shifted - 1) * w)
+ res *= correction_factor
+ res = drop_imag(res)
+ return res
+
+
+def laguerre_gamma_simple(z, x=None, w=None, n=8):
+ x, w = _prep_zeros_and_weights(x, w, n)
+ z += 0j
+ res = np.sum(x ** (z - 1) * w)
+ res = drop_imag(res)
+ return res
+
+
+def laguerre_gamma_mirror(z, x=None, w=None, n=8):
+ x, w = _prep_zeros_and_weights(x, w, n)
+ z += 0j
+ if z.real < 1e-3:
+ return np.pi / (
+ np.sin(np.pi * z) * laguerre_gamma_simple(1 - z, x, w)
+ ) # Reflection formula
+ return laguerre_gamma_simple(z, x, w)
+
+
+def eval_laguerre_gamma(z, x=None, w=None, n=8, func="simple", **kwargs):
+ x, w = _prep_zeros_and_weights(x, w, n)
+ if func == "simple":
+ f = laguerre_gamma_simple
+ elif func == "mirror":
+ f = laguerre_gamma_mirror
+ else:
+ f = laguerre_gamma_shift
+ return np.array([f(zi, x, w, n, **kwargs) for zi in z])
+
+
+def calc_rel_error(x, y):
+ return (y - x) / x
+
+
+ns = np.arange(2, 12, 2)
+
+# Simple / naive
+xmin = -5
+xmax = 30
+ylim = np.array([-11, 6])
+x = np.linspace(xmin + EPSILON, xmax - EPSILON, 400)
+gamma = scipy.special.gamma(x)
+fig, ax = plt.subplots(num=1, clear=True, constrained_layout=True, figsize=(5, 2.5))
+for n in ns:
+ gamma_lag = eval_laguerre_gamma(x, n=n)
+ rel_err = calc_rel_error(gamma, gamma_lag)
+ ax.semilogy(x, np.abs(rel_err), label=f"$n={n}$")
+ax.set_xlim(x[0], x[-1])
+ax.set_ylim(*(10.0 ** ylim))
+ax.set_xticks(np.arange(xmin, xmax + EPSILON, 5))
+ax.set_xticks(np.arange(xmin, xmax), minor=True)
+ax.set_yticks(10.0 ** np.arange(*ylim, 2))
+ax.set_yticks(10.0 ** np.arange(*ylim, 2))
+ax.set_xlabel(r"$z$")
+ax.set_ylabel("Relativer Fehler")
+ax.legend(ncol=3, fontsize="small")
+ax.grid(1, "both")
+fig.savefig(f"{img_path}/rel_error_simple.pgf")
+
+
+# Mirrored
+xmin = -15
+xmax = 15
+ylim = np.array([-11, 1])
+x = np.linspace(xmin + EPSILON, xmax - EPSILON, 400)
+gamma = scipy.special.gamma(x)
+fig2, ax2 = plt.subplots(num=2, clear=True, constrained_layout=True, figsize=(5, 2.5))
+for n in ns:
+ gamma_lag = eval_laguerre_gamma(x, n=n, func="mirror")
+ rel_err = calc_rel_error(gamma, gamma_lag)
+ ax2.semilogy(x, np.abs(rel_err), label=f"$n={n}$")
+ax2.set_xlim(x[0], x[-1])
+ax2.set_ylim(*(10.0 ** ylim))
+ax2.set_xticks(np.arange(xmin, xmax + EPSILON, 5))
+ax2.set_xticks(np.arange(xmin, xmax), minor=True)
+ax2.set_yticks(10.0 ** np.arange(*ylim, 2))
+# locmin = mpl.ticker.LogLocator(base=10.0,subs=0.1*np.arange(1,10),numticks=100)
+# ax2.yaxis.set_minor_locator(locmin)
+# ax2.yaxis.set_minor_formatter(mpl.ticker.NullFormatter())
+ax2.set_xlabel(r"$z$")
+ax2.set_ylabel("Relativer Fehler")
+ax2.legend(ncol=1, loc="upper left", fontsize="small")
+ax2.grid(1, "both")
+fig2.savefig(f"{img_path}/rel_error_mirror.pgf")
+
+
+# Move to target
+bests = []
+N = 200
+step = 1 / (N - 1)
+a = 11 / 8
+b = 1 / 2
+x = np.linspace(step, 1 - step, N + 1)
+gamma = scipy.special.gamma(x)[:, None]
+ns = np.arange(2, 13)
+for n in ns:
+ zeros, weights = np.polynomial.laguerre.laggauss(n)
+ est = np.ceil(b + a * n)
+ targets = np.arange(max(est - 2, 0), est + 3)
+ gamma_lag = np.stack(
+ [
+ eval_laguerre_gamma(x, target=target, x=zeros, w=weights, func="shifted")
+ for target in targets
+ ],
+ -1,
+ )
+ rel_error = np.abs(calc_rel_error(gamma, gamma_lag))
+ best = np.argmin(rel_error, -1) + targets[0]
+ bests.append(best)
+bests = np.stack(bests, 0)
+
+fig3, ax3 = plt.subplots(num=3, clear=True, constrained_layout=True, figsize=(5, 3))
+v = ax3.imshow(bests, cmap="inferno", aspect="auto", interpolation="nearest")
+plt.colorbar(v, ax=ax3, label=r"$m$")
+ticks = np.arange(0, N + 1, N // 5)
+ax3.set_xlim(0, 1)
+ax3.set_xticks(ticks, [f"{v:.2f}" for v in ticks / N])
+ax3.set_xticks(np.arange(0, N + 1, N // 20), minor=True)
+ax3.set_yticks(np.arange(len(ns)), ns)
+ax3.set_xlabel(r"$z$")
+ax3.set_ylabel(r"$n$")
+fig3.savefig(f"{img_path}/targets.pdf")
+
+targets = np.mean(bests, -1)
+intercept, bias = np.polyfit(ns, targets, 1)
+fig4, axs4 = plt.subplots(
+ 2, num=4, sharex=True, clear=True, constrained_layout=True, figsize=(5, 4)
+)
+xl = np.array([ns[0] - 0.5, ns[-1] + 0.5])
+axs4[0].plot(xl, intercept * xl + bias, label=r"$\hat{m}$")
+axs4[0].plot(ns, targets, "x", label=r"$\bar{m}$")
+axs4[1].plot(
+ ns, ((intercept * ns + bias) - targets), "-x", label=r"$\hat{m} - \bar{m}$"
+)
+axs4[0].set_xlim(*xl)
+# axs4[0].set_title("Schätzung von Mittelwert")
+# axs4[1].set_title("Fehler")
+axs4[-1].set_xlabel(r"$z$")
+for ax in axs4:
+ ax.grid(1)
+ ax.legend()
+fig4.savefig(f"{img_path}/schaetzung.pgf")
+
+print(f"Intercept={intercept:.6g}, Bias={bias:.6g}")
+predicts = np.ceil(intercept * ns[:, None] + bias - x)
+print(f"Error: {int(np.sum(np.abs(bests-predicts)))}")
+
+# plt.show()
diff --git a/buch/papers/laguerre/scripts/integrand.py b/buch/papers/laguerre/scripts/integrand.py
new file mode 100644
index 0000000..0cf43d1
--- /dev/null
+++ b/buch/papers/laguerre/scripts/integrand.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+# -*- coding:utf-8 -*-
+"""Plot for integrand of gamma function with shifting terms."""
+
+import os
+from pathlib import Path
+
+import matplotlib.pyplot as plt
+import numpy as np
+
+EPSILON = 1e-12
+xlims = np.array([-3, 3])
+
+root = str(Path(__file__).parent)
+img_path = f"{root}/../images"
+os.makedirs(img_path, exist_ok=True)
+
+t = np.logspace(*xlims, 1001)[:, None]
+
+z = np.array([-4.5, -2, -1, -0.5, 0.0, 0.5, 1, 2, 4.5])
+r = t ** z
+
+fig, ax = plt.subplots(num=1, clear=True, constrained_layout=True, figsize=(5, 3))
+ax.semilogx(t, r)
+ax.set_xlim(*(10.0 ** xlims))
+ax.set_ylim(1e-3, 40)
+ax.set_xlabel(r"$x$")
+ax.set_ylabel(r"$x^z$")
+ax.grid(1, "both")
+labels = [f"$z={zi: 3.1f}$" for zi in np.squeeze(z)]
+ax.legend(labels, ncol=2, loc="upper left", fontsize="small")
+fig.savefig(f"{img_path}/integrands.pgf")
+
+z2 = np.array([-1, -0.5, 0.0, 0.5, 1, 2, 3, 4, 4.5])
+e = np.exp(-t)
+r2 = t ** z2 * e
+
+fig2, ax2 = plt.subplots(num=2, clear=True, constrained_layout=True, figsize=(5, 3))
+ax2.semilogx(t, r2)
+# ax2.plot(t,np.exp(-t))
+ax2.set_xlim(10 ** (-2), 20)
+ax2.set_ylim(1e-3, 10)
+ax2.set_xlabel(r"$x$")
+ax2.set_ylabel(r"$x^z e^{-x}$")
+ax2.grid(1, "both")
+labels =[f"$z={zi: 3.1f}$" for zi in np.squeeze(z2)]
+ax2.legend(labels, ncol=2, loc="upper left", fontsize="small")
+fig2.savefig(f"{img_path}/integrands_exp.pgf")
+# plt.show()
diff --git a/buch/papers/laguerre/scripts/laguerre_plot.py b/buch/papers/laguerre/scripts/laguerre_plot.py
index b9088d0..1be3552 100644
--- a/buch/papers/laguerre/scripts/laguerre_plot.py
+++ b/buch/papers/laguerre/scripts/laguerre_plot.py
@@ -29,7 +29,7 @@ fig, ax = plt.subplots(num=1, clear=True, constrained_layout=True, figsize=(6, 4
for n in np.arange(0, 8):
k = np.arange(0, n + 1)[None]
L = np.sum((-1) ** k * ss.binom(n, k) / ss.factorial(k) * t ** k, -1)
- ax.plot(t, L, label=f"n={n}")
+ ax.plot(t, L, label=f"$n={n}$")
ax.set_xticks(get_ticks(int(t[0]), t[-1]), minor=True)
ax.set_xticks(get_ticks(0, t[-1], step))
@@ -97,4 +97,5 @@ ax.arrow(
clip_on=False,
)
-fig.savefig(f"{img_path}/laguerre_polynomes.pdf")
+fig.savefig(f"{img_path}/laguerre_polynomes.pgf")
+# plt.show()