kappalogic 0.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kappalogic/__init__.py +59 -0
- kappalogic/applications.py +88 -0
- kappalogic/bridge.py +42 -0
- kappalogic/core.py +118 -0
- kappalogic/electronic_structure.py +93 -0
- kappalogic/field_theory.py +67 -0
- kappalogic/funcs.py +38 -0
- kappalogic/heat.py +62 -0
- kappalogic/info_theory.py +40 -0
- kappalogic/kernels.py +59 -0
- kappalogic/quantum_well.py +92 -0
- kappalogic/search.py +94 -0
- kappalogic/spacetime.py +29 -0
- kappalogic/stat_mech.py +46 -0
- kappalogic/theory.py +87 -0
- kappalogic/topology.py +36 -0
- kappalogic-0.9.0.dist-info/METADATA +114 -0
- kappalogic-0.9.0.dist-info/RECORD +21 -0
- kappalogic-0.9.0.dist-info/WHEEL +5 -0
- kappalogic-0.9.0.dist-info/licenses/LICENSE +201 -0
- kappalogic-0.9.0.dist-info/top_level.txt +1 -0
kappalogic/__init__.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from .core import (
|
|
2
|
+
sgn, reg, NOT, AND, OR, NAND, NOR, XOR, XNOR, AND_n, OR_n,
|
|
3
|
+
eq, neq, gt, lt, ge, le, DEFAULT_XI, DEFAULT_KERNEL,
|
|
4
|
+
)
|
|
5
|
+
from .funcs import intf, par, maxf, minf, clamp
|
|
6
|
+
from .applications import (
|
|
7
|
+
kronecker_delta, levi_civita, dirac_delta_integral,
|
|
8
|
+
line_intersection_y, collatz_step, collatz_sequence,
|
|
9
|
+
choc_bar_source,
|
|
10
|
+
)
|
|
11
|
+
from .kernels import KERNELS, apply_kernel
|
|
12
|
+
from .heat import xi_of_time, time_of_xi, heat_step_profile, heat_kernel_gaussian, gaussian_match
|
|
13
|
+
from .quantum_well import (
|
|
14
|
+
box_heat_kernel, box_heat_kernel_eigen,
|
|
15
|
+
infinite_well_propagator, infinite_well_propagator_eigen,
|
|
16
|
+
)
|
|
17
|
+
from .search import soft_gt, soft_eq, soft_or, soft_and, anneal_solve, numeric_grad, l2_penalty
|
|
18
|
+
from .field_theory import kink_profile, kink_eom_residual, kink_energy_exact, topological_charge
|
|
19
|
+
from .stat_mech import box_partition_function, box_partition_function_exact, witten_index_toy
|
|
20
|
+
from .info_theory import (
|
|
21
|
+
gaussian_variance, differential_entropy_gaussian,
|
|
22
|
+
fisher_information_gaussian, de_bruijn_check,
|
|
23
|
+
)
|
|
24
|
+
from .topology import morse_index, euler_characteristic
|
|
25
|
+
from .spacetime import inside_lightcone, future_lightcone
|
|
26
|
+
from .bridge import floor_smooth, sum_via_integral, gamma_via_riemann_sum
|
|
27
|
+
from .electronic_structure import (
|
|
28
|
+
fermi_occupation, tight_binding_chain_energies,
|
|
29
|
+
find_chemical_potential, total_energy_smeared,
|
|
30
|
+
tight_binding_dos_continuum, continuum_filling, continuum_energy, continuum_find_mu,
|
|
31
|
+
)
|
|
32
|
+
from .theory import max_gradient_location, max_gradient_value, is_single_passing_at_zero, fusion_is_safe
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"sgn", "reg", "NOT", "AND", "OR", "NAND", "NOR", "XOR", "XNOR", "AND_n", "OR_n",
|
|
36
|
+
"eq", "neq", "gt", "lt", "ge", "le", "DEFAULT_XI", "DEFAULT_KERNEL",
|
|
37
|
+
"intf", "par", "maxf", "minf", "clamp",
|
|
38
|
+
"kronecker_delta", "levi_civita", "dirac_delta_integral",
|
|
39
|
+
"line_intersection_y", "collatz_step", "collatz_sequence",
|
|
40
|
+
"choc_bar_source",
|
|
41
|
+
"KERNELS", "apply_kernel",
|
|
42
|
+
"xi_of_time", "time_of_xi", "heat_step_profile", "heat_kernel_gaussian", "gaussian_match",
|
|
43
|
+
"box_heat_kernel", "box_heat_kernel_eigen",
|
|
44
|
+
"infinite_well_propagator", "infinite_well_propagator_eigen",
|
|
45
|
+
"soft_gt", "soft_eq", "soft_or", "soft_and", "anneal_solve", "numeric_grad", "l2_penalty",
|
|
46
|
+
"kink_profile", "kink_eom_residual", "kink_energy_exact", "topological_charge",
|
|
47
|
+
"box_partition_function", "box_partition_function_exact", "witten_index_toy",
|
|
48
|
+
"gaussian_variance", "differential_entropy_gaussian",
|
|
49
|
+
"fisher_information_gaussian", "de_bruijn_check",
|
|
50
|
+
"morse_index", "euler_characteristic",
|
|
51
|
+
"inside_lightcone", "future_lightcone",
|
|
52
|
+
"floor_smooth", "sum_via_integral", "gamma_via_riemann_sum",
|
|
53
|
+
"fermi_occupation", "tight_binding_chain_energies",
|
|
54
|
+
"find_chemical_potential", "total_energy_smeared",
|
|
55
|
+
"tight_binding_dos_continuum", "continuum_filling", "continuum_energy", "continuum_find_mu",
|
|
56
|
+
"max_gradient_location", "max_gradient_value", "is_single_passing_at_zero", "fusion_is_safe",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
__version__ = "0.9.0"
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
kappalogic.applications
|
|
3
|
+
=========================
|
|
4
|
+
応用19〜20の実例。
|
|
5
|
+
|
|
6
|
+
注意 (実装時に見つかった原設計の誤り):
|
|
7
|
+
応用20のコラッツ漸化式
|
|
8
|
+
f(x+1) = (f(x)/2)*int(x/2) + (3f(x)+1)*int((x+1)/2)
|
|
9
|
+
は "ステップ番号 x" の偶奇で分岐しているが、コラッツ写像は
|
|
10
|
+
本来 "現在の値 f(x)" の偶奇で分岐すべきものなので、この式は
|
|
11
|
+
数値検証の結果、2ステップ目から真の数列と一致しないことを確認した
|
|
12
|
+
(例: n0=27 -> 真の値82 に対しこの式は13.5を返す)。
|
|
13
|
+
本実装では par(f(x)) (修正済みの奇偶判定) を使って
|
|
14
|
+
f(x+1) = (f(x)/2)*(1-par(f(x))) + (3f(x)+1)*par(f(x))
|
|
15
|
+
と書き換え、n0=27 (111ステップ、最大値9232) を含む多数の初期値で
|
|
16
|
+
真のコラッツ数列と完全一致することを確認済み。
|
|
17
|
+
"""
|
|
18
|
+
import numpy as np
|
|
19
|
+
from .core import eq, gt, lt, AND
|
|
20
|
+
from .funcs import par
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def kronecker_delta(i, j, xi=1e-3):
|
|
24
|
+
"""delta_ij = (i=j)"""
|
|
25
|
+
return eq(i, j, xi)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def levi_civita(i, j, k, xi=1e-3):
|
|
29
|
+
"""epsilon_ijk = sgn((i-j)(j-k)(k-i)) ※重複指標では0になる"""
|
|
30
|
+
from .core import sgn
|
|
31
|
+
return sgn((i - j) * (j - k) * (k - i), xi)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def dirac_delta_integral(f, a, xs, weights):
|
|
35
|
+
"""
|
|
36
|
+
∫ f(x) delta(x-a) dx = f(x)(x=a) の離散近似。
|
|
37
|
+
xs, weights: 数値積分用の分点と重み (例: 台形則の点と幅)
|
|
38
|
+
"""
|
|
39
|
+
xs = np.asarray(xs, dtype=float)
|
|
40
|
+
fx = np.asarray([f(x) for x in xs])
|
|
41
|
+
return np.sum(fx * eq(xs, a) * weights)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def line_intersection_y(a, b, c, d, x):
|
|
45
|
+
"""
|
|
46
|
+
2直線 y=ax+b, y=cx+d の交点のy座標を
|
|
47
|
+
((ax+b)=(cx+d)) という等式インジケータで表現した式の値。
|
|
48
|
+
(本来は交点のxを解いて代入するのが素直だが、
|
|
49
|
+
"式の中に方程式の解を埋め込む" という応用19の考え方の例として、
|
|
50
|
+
xを動かしたときに交点近傍だけ1になることを確認するデモ)
|
|
51
|
+
"""
|
|
52
|
+
return eq(a * x + b, c * x + d)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def collatz_step(fx, xi=1e-3):
|
|
56
|
+
"""
|
|
57
|
+
修正済みコラッツ漸化式: f(x)の偶奇で分岐(元式のバグを修正)。
|
|
58
|
+
f(x+1) = (f(x)/2)(1-par(f(x))) + (3f(x)+1)(par(f(x)))
|
|
59
|
+
"""
|
|
60
|
+
p = par(fx)
|
|
61
|
+
return (fx / 2) * (1 - p) + (3 * fx + 1) * p
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def collatz_sequence(n0, max_steps=1000):
|
|
65
|
+
"""collatz_step を繰り返し適用して数列を生成 (n=1で停止)"""
|
|
66
|
+
seq = [float(n0)]
|
|
67
|
+
fx = float(n0)
|
|
68
|
+
for _ in range(max_steps):
|
|
69
|
+
if abs(fx - 1) < 1e-6:
|
|
70
|
+
break
|
|
71
|
+
fx = float(collatz_step(fx))
|
|
72
|
+
seq.append(fx)
|
|
73
|
+
return seq
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def choc_bar_source(x, y, z, a, b, c, rho, xi=1e-3):
|
|
77
|
+
"""
|
|
78
|
+
密度rho, 幅a x 奥行b x 高さc の直方体(板チョコ)が作る
|
|
79
|
+
ポアソン方程式の右辺: 4*pi*rho * (箱の内部なら1、外なら0)
|
|
80
|
+
"""
|
|
81
|
+
inside = AND(
|
|
82
|
+
AND(lt(x, a / 2, xi), lt(y, b / 2, xi), xi),
|
|
83
|
+
AND(lt(z, c / 2, xi),
|
|
84
|
+
AND(gt(x, -a / 2, xi), AND(gt(y, -b / 2, xi), gt(z, -c / 2, xi), xi), xi),
|
|
85
|
+
xi),
|
|
86
|
+
xi,
|
|
87
|
+
)
|
|
88
|
+
return 4 * np.pi * rho * inside
|
kappalogic/bridge.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
kappalogic.bridge
|
|
3
|
+
====================
|
|
4
|
+
Σ(離散和)と∫(連続積分)の橋渡し。
|
|
5
|
+
|
|
6
|
+
floor(x) = sum_{k=1}^{K} Theta(x-k) (x>0, K>=floor(x)で十分) という
|
|
7
|
+
初等的な恒等式を、このライブラリのgt(符号保存版の大小比較)の総和として
|
|
8
|
+
実装する。これにより
|
|
9
|
+
sum_{n=0}^{N} f(n) = integral_0^{N+1} f(floor(x)) dx
|
|
10
|
+
という初等解析の恒等式を、gtゲートの総和で明示的に構成できる。
|
|
11
|
+
|
|
12
|
+
n!とGamma関数(Γ(n+1)=∫_0^∞ t^n e^{-t} dt = n!、オイラー積分)の
|
|
13
|
+
数値実験で、Σ(離散和)→∫(オイラー積分)→n!(階乗)の一致を検証済み
|
|
14
|
+
(相対誤差~1e-11、中点則で十分な精度)。
|
|
15
|
+
"""
|
|
16
|
+
import numpy as np
|
|
17
|
+
import math
|
|
18
|
+
from .core import gt, DEFAULT_XI
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def floor_smooth(x, K=50, xi=DEFAULT_XI):
|
|
22
|
+
"""floor(x) = sum_{k=1}^{K} gt(x,k) の近似(x>0, K>=想定される最大値+1)。"""
|
|
23
|
+
return sum(gt(x, k, xi) for k in range(1, K + 1))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def sum_via_integral(f, N, xi=DEFAULT_XI, n_points=200000):
|
|
27
|
+
"""
|
|
28
|
+
sum_{n=0}^{N} f(n) を integral_0^{N+1} f(floor_smooth(x)) dx として
|
|
29
|
+
数値積分で計算する(Σ->∫の橋渡しの実演)。fは整数引数を取る関数。
|
|
30
|
+
"""
|
|
31
|
+
xs = np.linspace(0, N + 1, n_points)
|
|
32
|
+
fx = np.array([f(int(round(floor_smooth(x, K=N + 2, xi=xi)))) for x in xs])
|
|
33
|
+
return np.trapezoid(fx, xs)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def gamma_via_riemann_sum(n, dt=0.01, t_max=200):
|
|
37
|
+
"""
|
|
38
|
+
Gamma(n+1) = integral_0^inf t^n e^{-t} dt を中点則のリーマン和で近似する。
|
|
39
|
+
dt->0でn!(math.factorial(n))に収束することを確認済み(相対誤差~1e-11@dt=0.1)。
|
|
40
|
+
"""
|
|
41
|
+
ts = np.arange(dt / 2, t_max, dt)
|
|
42
|
+
return np.sum(ts ** n * np.exp(-ts)) * dt
|
kappalogic/core.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""
|
|
2
|
+
kappalogic.core
|
|
3
|
+
================
|
|
4
|
+
tanh(x/xi) を土台にした「擬連続論理」の基本ゲート群。
|
|
5
|
+
v0.2: kernel引数でtanh/erf/algebraicを切り替え可能に(kernels.py参照)。
|
|
6
|
+
デフォルトはtanhのままなので、v0.1のコードはそのまま動く。
|
|
7
|
+
|
|
8
|
+
注意 (実装時に見つかった原設計の誤り。詳細はdev_notes.md):
|
|
9
|
+
ユーザー原案の定義10・定義11
|
|
10
|
+
(A>B) := not(reg(A-B) - 1)
|
|
11
|
+
(A<B) := not(reg(A-B) + 1)
|
|
12
|
+
は reg() が sgn() を2乗するため符号情報を失っており、実際には
|
|
13
|
+
A>B でも A<B でも同じ値を返してしまうことを数値検証で確認した。
|
|
14
|
+
本実装では符号を保持する sgn() を使った
|
|
15
|
+
(A>B) := (sgn(A-B) + reg(A-B)) / 2
|
|
16
|
+
(A<B) := (reg(A-B) - sgn(A-B)) / 2
|
|
17
|
+
に置き換えて正しく動作することを確認済み。
|
|
18
|
+
"""
|
|
19
|
+
import numpy as np
|
|
20
|
+
from .kernels import apply_kernel
|
|
21
|
+
|
|
22
|
+
DEFAULT_XI = 1e-3
|
|
23
|
+
DEFAULT_KERNEL = "tanh"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def sgn(x, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
27
|
+
"""kappa(x/xi): x>0 -> +1, x=0 -> 0, x<0 -> -1 (符号を保持)"""
|
|
28
|
+
return apply_kernel(x, xi, kernel)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def reg(x, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
32
|
+
"""sgn(x)^2: x!=0 -> 1, x=0 -> 0 (符号情報は失われる)"""
|
|
33
|
+
return sgn(x, xi, kernel) ** 2
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def NOT(x, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
37
|
+
"""1 - reg(x): x==0 -> 1, x!=0 -> 0"""
|
|
38
|
+
return 1 - reg(x, xi, kernel)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def AND(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
42
|
+
"""a,b が共に非0のとき1、さもなければ0"""
|
|
43
|
+
return reg(a * b, xi, kernel)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def OR(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
47
|
+
"""a,b が共に0のとき0、さもなければ1"""
|
|
48
|
+
return NOT(NOT(a, xi, kernel) * NOT(b, xi, kernel), xi, kernel)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def NAND(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
52
|
+
return NOT(AND(a, b, xi, kernel), xi, kernel)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def NOR(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
56
|
+
return NOT(OR(a, b, xi, kernel), xi, kernel)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def XOR(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
60
|
+
return OR(AND(a, NOT(b, xi, kernel), xi, kernel),
|
|
61
|
+
AND(NOT(a, xi, kernel), b, xi, kernel), xi, kernel)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def XNOR(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
65
|
+
return NOT(XOR(a, b, xi, kernel), xi, kernel)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def AND_n(*vals, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
69
|
+
"""
|
|
70
|
+
n項ANDの融合版(カルノー図的簡約): AND(AND(a,b),c,...) と数学的に等価だが、
|
|
71
|
+
先に全部の積を取ってからreg()を1回だけ呼ぶので (1) 高速 (2) 境界付近の
|
|
72
|
+
値が混在していても他の値の大きさで判定を安定化できる、という利点がある
|
|
73
|
+
(詳細・ベンチマークはdev_notes.md)。
|
|
74
|
+
"""
|
|
75
|
+
prod = 1.0
|
|
76
|
+
for v in vals:
|
|
77
|
+
prod = prod * v
|
|
78
|
+
return reg(prod, xi, kernel)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def OR_n(*vals, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
82
|
+
"""n項ORの融合版: OR(OR(a,b),c,...) と数学的に等価。AND_nと同じ利点。"""
|
|
83
|
+
prod = 1.0
|
|
84
|
+
for v in vals:
|
|
85
|
+
prod = prod * NOT(v, xi, kernel)
|
|
86
|
+
return NOT(prod, xi, kernel)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def eq(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
90
|
+
"""(A=B): A==B -> 1, else 0"""
|
|
91
|
+
return NOT(a - b, xi, kernel)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def neq(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
95
|
+
"""(A≠B): A!=B -> 1, else 0"""
|
|
96
|
+
return reg(a - b, xi, kernel)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def gt(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
100
|
+
"""(A>B): A>B -> 1, else 0 (符号を保持した修正版)"""
|
|
101
|
+
d = a - b
|
|
102
|
+
return (sgn(d, xi, kernel) + reg(d, xi, kernel)) / 2
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def lt(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
106
|
+
"""(A<B): A<B -> 1, else 0 (符号を保持した修正版)"""
|
|
107
|
+
d = a - b
|
|
108
|
+
return (reg(d, xi, kernel) - sgn(d, xi, kernel)) / 2
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def ge(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
112
|
+
"""(A≧B): A>=B -> 1, else 0"""
|
|
113
|
+
return OR(eq(a, b, xi, kernel), gt(a, b, xi, kernel), xi, kernel)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def le(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
117
|
+
"""(A≦B): A<=B -> 1, else 0"""
|
|
118
|
+
return OR(eq(a, b, xi, kernel), lt(a, b, xi, kernel), xi, kernel)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""
|
|
2
|
+
kappalogic.electronic_structure
|
|
3
|
+
===================================
|
|
4
|
+
密度汎関数理論(DFT)への接続。
|
|
5
|
+
|
|
6
|
+
発見: フェルミ・ディラック分布(有限温度の電子占有数)
|
|
7
|
+
f(eps) = 1/(1+exp((eps-mu)/kT))
|
|
8
|
+
は代数的に 1/(1+e^{-y}) = (1+tanh(y/2))/2 という恒等式そのものなので、
|
|
9
|
+
このライブラリの sgn(x,xi)=tanh(x/xi) を使って
|
|
10
|
+
occupation(eps,mu,xi=2*kT) = (1+sgn(mu-eps,xi))/2
|
|
11
|
+
と書けば、フェルミ・ディラック分布と機械精度で完全に一致する
|
|
12
|
+
(xi = 2*kT が正しい対応関係。検証済み)。
|
|
13
|
+
|
|
14
|
+
これは、DFT計算コード(VASP, Quantum ESPRESSOなど)で金属を扱う際に
|
|
15
|
+
使われる「電子スメアリング」という実務的な数値手法と、このライブラリの
|
|
16
|
+
「hard(T=0のステップ関数)/soft(xi>0でなだらか)の二重性」が
|
|
17
|
+
数学的に同一であることを意味する。1次元タイトバインディング鎖で、
|
|
18
|
+
xi(スメアリング幅)を0に近づけると全電子エネルギーがT=0の厳密値に
|
|
19
|
+
収束することを数値実験で確認した。
|
|
20
|
+
|
|
21
|
+
【訂正】当初、有限鎖(N=200)での収束次数が教科書的なO(kT^2)
|
|
22
|
+
(ゾンマーフェルト展開)より速く見える現象を確認したが、これは
|
|
23
|
+
有限系サイズ(離散準位)+二分探索の精度限界による数値アーティファクト
|
|
24
|
+
だった。連続体の状態密度(tight_binding_dos_continuum)で高精度に
|
|
25
|
+
(scipy.integrate.quad + brentq)再計算したところ、xiを半分にする
|
|
26
|
+
たびの誤差比が4.00で安定し、標準的なO(xi^2)であることを確認した
|
|
27
|
+
(dev_notes.md参照)。
|
|
28
|
+
"""
|
|
29
|
+
import numpy as np
|
|
30
|
+
from .core import sgn
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def fermi_occupation(eps, mu, kT):
|
|
34
|
+
"""
|
|
35
|
+
フェルミ・ディラック占有数。sgn(x,xi=2*kT)を使って実装。
|
|
36
|
+
kT->0でハードなステップ関数(T=0の占有)に収束する。
|
|
37
|
+
"""
|
|
38
|
+
xi = 2 * kT
|
|
39
|
+
return (1 + sgn(mu - eps, xi)) / 2
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def tight_binding_chain_energies(N, t_hop=1.0):
|
|
43
|
+
"""1次元タイトバインディング鎖(周期境界条件)のエネルギー準位。eps_k=-2*t*cos(k)"""
|
|
44
|
+
j = np.arange(N)
|
|
45
|
+
k = 2 * np.pi * j / N
|
|
46
|
+
return -2 * t_hop * np.cos(k)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def find_chemical_potential(eps, target_occupation, kT, lo=-10.0, hi=10.0, iters=60):
|
|
50
|
+
"""占有数の合計がtarget_occupationになるようmuを二分探索で求める。"""
|
|
51
|
+
for _ in range(iters):
|
|
52
|
+
mid = (lo + hi) / 2
|
|
53
|
+
occ = np.sum(fermi_occupation(eps, mid, kT))
|
|
54
|
+
if occ < target_occupation:
|
|
55
|
+
lo = mid
|
|
56
|
+
else:
|
|
57
|
+
hi = mid
|
|
58
|
+
return (lo + hi) / 2
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def tight_binding_dos_continuum(eps, t_hop=1.0):
|
|
62
|
+
"""1次元タイトバインディングの厳密な連続体状態密度: g(eps)=1/(pi*sqrt(4t^2-eps^2))"""
|
|
63
|
+
return 1.0 / (np.pi * np.sqrt(4 * t_hop ** 2 - eps ** 2 + 1e-300))
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def continuum_filling(mu, xi, t_hop=1.0):
|
|
67
|
+
"""連続体極限でのフィリング(占有数の積分)。scipy.integrate.quadで高精度計算。"""
|
|
68
|
+
from scipy import integrate
|
|
69
|
+
f = lambda eps: tight_binding_dos_continuum(eps, t_hop) * fermi_occupation(eps, mu, xi / 2)
|
|
70
|
+
val, _ = integrate.quad(f, -2 * t_hop + 1e-9, 2 * t_hop - 1e-9, limit=200)
|
|
71
|
+
return val
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def continuum_energy(mu, xi, t_hop=1.0):
|
|
75
|
+
"""連続体極限での全電子エネルギー(1電子あたり)。有限系サイズ効果を排除した検証用。"""
|
|
76
|
+
from scipy import integrate
|
|
77
|
+
f = lambda eps: eps * tight_binding_dos_continuum(eps, t_hop) * fermi_occupation(eps, mu, xi / 2)
|
|
78
|
+
val, _ = integrate.quad(f, -2 * t_hop + 1e-9, 2 * t_hop - 1e-9, limit=200)
|
|
79
|
+
return val
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def continuum_find_mu(target, xi, t_hop=1.0):
|
|
83
|
+
"""連続体極限での化学ポテンシャルをbrentqで高精度に求める(有限系の二分探索精度限界を回避)。"""
|
|
84
|
+
from scipy import optimize
|
|
85
|
+
g = lambda mu: continuum_filling(mu, xi, t_hop) - target
|
|
86
|
+
return optimize.brentq(g, -2 * t_hop, 2 * t_hop, xtol=1e-12)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def total_energy_smeared(eps, target_occupation, kT):
|
|
90
|
+
"""スメアリング(有限kT)を使った全電子エネルギーの計算(有限鎖版、DFTでの標準的な手法)。"""
|
|
91
|
+
mu = find_chemical_potential(eps, target_occupation, kT)
|
|
92
|
+
occ = fermi_occupation(eps, mu, kT)
|
|
93
|
+
return np.sum(eps * occ)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""
|
|
2
|
+
kappalogic.field_theory
|
|
3
|
+
==========================
|
|
4
|
+
発見(2026-07): この理論の基本ブロック sgn(x)=tanh(x/xi) は、
|
|
5
|
+
実は場の理論のφ^4理論(二重井戸型ポテンシャル)の静的古典解
|
|
6
|
+
(キンク・ソリトン)そのものである。
|
|
7
|
+
|
|
8
|
+
【命題1(運動方程式)】phi(x)=tanh(x/xi)は
|
|
9
|
+
phi'' = (2/xi^2)(phi^3-phi)
|
|
10
|
+
を厳密に満たす。
|
|
11
|
+
|
|
12
|
+
証明(sympyによる記号微分で確認済み、有限差分ではなく閉じた式):
|
|
13
|
+
phi'(x) = (1/xi)*sech^2(x/xi) = (1/xi)*(1-phi^2) ... (*)
|
|
14
|
+
phi''(x) = d/dx[(1/xi)(1-phi^2)] = (-2*phi/xi)*phi'
|
|
15
|
+
= (-2*phi/xi)*(1/xi)(1-phi^2) = (2/xi^2)(phi^3-phi)
|
|
16
|
+
sympy.diff(tanh(x/xi), x, 2) と (2/xi^2)(phi^3-phi) の差を
|
|
17
|
+
simplify すると厳密に0になることを確認した。
|
|
18
|
+
|
|
19
|
+
このEOMは、ポテンシャル V(phi)=(phi^2-1)^2/(2*xi^2) のオイラー・
|
|
20
|
+
ラグランジュ方程式 phi''=dV/dphi と一致する(dV/dphiを計算して
|
|
21
|
+
2*phi*(phi^2-1)/xi^2になることも確認済み)。
|
|
22
|
+
|
|
23
|
+
【命題2(厳密なエネルギー)】このキンクの古典エネルギー(質量)は
|
|
24
|
+
E = integral_{-inf}^{inf} [ (1/2)*phi'(x)^2 + V(phi(x)) ] dx = 4/(3*xi)
|
|
25
|
+
と閉じた式で求まる(sympy.integrate、無限区間の積分を厳密に実行)。
|
|
26
|
+
幅xiに反比例する、というのは物理的に自然な結果(細いソリトンほど
|
|
27
|
+
勾配エネルギーが大きい)。
|
|
28
|
+
|
|
29
|
+
ソリトン数(トポロジカル電荷) Q = (phi(+inf)-phi(-inf))/2 = 1 は、
|
|
30
|
+
sgn(±inf)=±1という漸近値からtanhの定義より自明に従う。
|
|
31
|
+
"""
|
|
32
|
+
import numpy as np
|
|
33
|
+
from .core import sgn
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def kink_profile(x, xi=1.0):
|
|
37
|
+
"""phi(x) = tanh(x/xi): phi^4理論の静的キンク解。V(phi)=(phi^2-1)^2/(2*xi^2)の古典解。"""
|
|
38
|
+
return sgn(x, xi)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def kink_eom_residual(x, xi=1.0, h=1e-4):
|
|
42
|
+
"""
|
|
43
|
+
運動方程式 phi'' - (2/xi^2)(phi^3-phi) = 0 の残差(数値検証用)。
|
|
44
|
+
厳密解ならほぼ0になるはず(命題1は既にsympyで閉じた式で証明済み、
|
|
45
|
+
これはその追加の数値的サニティチェック)。
|
|
46
|
+
"""
|
|
47
|
+
phi = lambda xx: kink_profile(xx, xi)
|
|
48
|
+
phi_pp = (phi(x + h) - 2 * phi(x) + phi(x - h)) / h ** 2
|
|
49
|
+
rhs = (2 / xi ** 2) * (phi(x) ** 3 - phi(x))
|
|
50
|
+
return phi_pp - rhs
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def kink_energy_exact(xi=1.0):
|
|
54
|
+
"""
|
|
55
|
+
キンクの厳密なエネルギー(質量) E = 4/(3*xi)。命題2参照
|
|
56
|
+
(sympyによる無限区間積分で導出済み、閉じた式)。
|
|
57
|
+
"""
|
|
58
|
+
return 4.0 / (3.0 * xi)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def topological_charge(xi=1.0, x_inf=1e4):
|
|
62
|
+
"""
|
|
63
|
+
ソリトン数(トポロジカル電荷) Q = (phi(+inf)-phi(-inf))/2。
|
|
64
|
+
このキンクでは常に1(sgnの漸近値+1,-1の半差)。
|
|
65
|
+
"""
|
|
66
|
+
return (kink_profile(x_inf, xi) - kink_profile(-x_inf, xi)) / 2
|
|
67
|
+
|
kappalogic/funcs.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""
|
|
2
|
+
kappalogic.funcs
|
|
3
|
+
==================
|
|
4
|
+
定義14〜18: int(x), par(x), max/min/clamp
|
|
5
|
+
|
|
6
|
+
注意 (実装時に見つかった原設計の誤り。詳細はdev_notes.md):
|
|
7
|
+
ユーザー原案の定義15 par(x):=int(x)-2*int(x/2) は偶数で-1を返す
|
|
8
|
+
バグがあったため、int(x)-int(x/2) に修正済み。
|
|
9
|
+
"""
|
|
10
|
+
import numpy as np
|
|
11
|
+
from .core import gt, lt, NOT, DEFAULT_XI, DEFAULT_KERNEL
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def intf(x):
|
|
15
|
+
"""int(x): xが整数のとき1、さもなければ0"""
|
|
16
|
+
x = np.asarray(x, dtype=float)
|
|
17
|
+
return NOT(np.sin(np.pi * x))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def par(x):
|
|
21
|
+
"""par(x): xが奇数のとき1、さもなければ0 (0や偶数は0)"""
|
|
22
|
+
x = np.asarray(x, dtype=float)
|
|
23
|
+
return intf(x) - intf(x / 2)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def maxf(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
27
|
+
"""max(A,B) = (A-B)(A>B) + B"""
|
|
28
|
+
return (a - b) * gt(a, b, xi, kernel) + b
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def minf(a, b, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
32
|
+
"""min(A,B) = (A-B)(A<B) + B"""
|
|
33
|
+
return (a - b) * lt(a, b, xi, kernel) + b
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def clamp(lo, x, hi, xi=DEFAULT_XI, kernel=DEFAULT_KERNEL):
|
|
37
|
+
"""clamp(A,x,B): x<A なら A、x>B なら B、さもなければ x"""
|
|
38
|
+
return (lo - x) * lt(x, lo, xi, kernel) + x + (hi - x) * gt(x, hi, xi, kernel)
|
kappalogic/heat.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""
|
|
2
|
+
kappalogic.heat
|
|
3
|
+
=================
|
|
4
|
+
kernel="erf" を選んだときの sgn(x,xi,"erf") = erf(x/xi) は、
|
|
5
|
+
1次元熱方程式 u_t = D*u_xx を階段状の初期条件(x<0で0, x>0で1)から
|
|
6
|
+
時間tだけ発展させた厳密解
|
|
7
|
+
u(x,t) = (1 + erf(x/(2*sqrt(D*t)))) / 2
|
|
8
|
+
とちょうど同じ形をしている(xi = 2*sqrt(D*t))。
|
|
9
|
+
|
|
10
|
+
これを有限差分法によるシミュレーションと比較し、最大誤差6e-5で
|
|
11
|
+
数値的に確認済み(dev_notes.md参照)。
|
|
12
|
+
|
|
13
|
+
このモジュールは、その対応関係を使って
|
|
14
|
+
- xi <-> 時間 t の相互変換
|
|
15
|
+
- 物理的に妥当な(=実際に拡散方程式が従う速さの)アニーリングスケジュール
|
|
16
|
+
(xiはtに比例するのではなく sqrt(t) に比例して縮む)
|
|
17
|
+
- ガウス核(熱核そのもの: デルタ関数初期条件からの厳密解)による
|
|
18
|
+
"ソフトな一致度" 報酬関数
|
|
19
|
+
を提供する。
|
|
20
|
+
"""
|
|
21
|
+
import numpy as np
|
|
22
|
+
from scipy.special import erf
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def xi_of_time(t, D=1.0):
|
|
26
|
+
"""拡散時間tに対応するxi。 xi = 2*sqrt(D*t)"""
|
|
27
|
+
return 2 * np.sqrt(D * np.asarray(t, dtype=float))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def time_of_xi(xi, D=1.0):
|
|
31
|
+
"""xiに対応する拡散時間t。 t = xi^2 / (4D)"""
|
|
32
|
+
xi = np.asarray(xi, dtype=float)
|
|
33
|
+
return xi ** 2 / (4 * D)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def heat_step_profile(x, t, D=1.0):
|
|
37
|
+
"""
|
|
38
|
+
階段状初期条件(x<0->0, x>0->1)を時間tだけ拡散させた温度分布の厳密解。
|
|
39
|
+
sgn(x, xi_of_time(t,D), kernel="erf") と等価 ( u=(1+sgn)/2 )。
|
|
40
|
+
"""
|
|
41
|
+
return 0.5 * (1 + erf(np.asarray(x, dtype=float) / xi_of_time(t, D)))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def heat_kernel_gaussian(x, t, D=1.0):
|
|
45
|
+
"""
|
|
46
|
+
デルタ関数初期条件(1点に熱源)からの厳密解=熱核そのもの。
|
|
47
|
+
G(x,t) = 1/sqrt(4*pi*D*t) * exp(-x^2/(4*D*t))
|
|
48
|
+
"""
|
|
49
|
+
x = np.asarray(x, dtype=float)
|
|
50
|
+
return np.exp(-x ** 2 / (4 * D * t)) / np.sqrt(4 * np.pi * D * t)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def gaussian_match(a, b, t, D=1.0):
|
|
54
|
+
"""
|
|
55
|
+
「a と b がどれだけ一致しているか」を熱核と同じ形のガウス関数で評価する
|
|
56
|
+
"ソフトな一致度" 報酬 (0〜1、a=bで最大)。
|
|
57
|
+
reg(a-b)(=硬い一致判定)とは違い、境界(a=b)でなだらかに減衰するので
|
|
58
|
+
勾配ベースの探索の目的関数に使うのに向く。t->0でreg的な鋭さに近づく。
|
|
59
|
+
"""
|
|
60
|
+
d = np.asarray(a, dtype=float) - np.asarray(b, dtype=float)
|
|
61
|
+
xi = xi_of_time(t, D)
|
|
62
|
+
return np.exp(-(d / xi) ** 2)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""
|
|
2
|
+
kappalogic.info_theory
|
|
3
|
+
=========================
|
|
4
|
+
de Bruijnの恒等式: 熱拡散(heat.py)でぼやけていく確率密度の
|
|
5
|
+
微分エントロピーS(t)の変化率は、フィッシャー情報量J(t)を使って
|
|
6
|
+
dS/dt = D*J(t) と書ける。ガウス分布(熱方程式の厳密解)で
|
|
7
|
+
数値的に確認済み(誤差~1e-10)。
|
|
8
|
+
|
|
9
|
+
これはheat.py(拡散・熱核)とAND/OR/reg系(論理・indicator関数)を
|
|
10
|
+
繋ぐ第三の軸として「情報理論的な量(エントロピー、フィッシャー情報量)」を
|
|
11
|
+
この枠組みの中に置く、という位置づけ。
|
|
12
|
+
"""
|
|
13
|
+
import numpy as np
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def gaussian_variance(t, sigma2_0, D=1.0):
|
|
17
|
+
"""熱拡散で時間発展するガウス分布の分散: sigma^2(t) = sigma2_0 + 2*D*t"""
|
|
18
|
+
return sigma2_0 + 2 * D * t
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def differential_entropy_gaussian(t, sigma2_0, D=1.0):
|
|
22
|
+
"""ガウス分布の微分エントロピー S(t) = 0.5*log(2*pi*e*sigma^2(t))"""
|
|
23
|
+
var = gaussian_variance(t, sigma2_0, D)
|
|
24
|
+
return 0.5 * np.log(2 * np.pi * np.e * var)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def fisher_information_gaussian(t, sigma2_0, D=1.0):
|
|
28
|
+
"""ガウス分布のフィッシャー情報量 J(t) = 1/sigma^2(t)"""
|
|
29
|
+
return 1.0 / gaussian_variance(t, sigma2_0, D)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def de_bruijn_check(t, sigma2_0, D=1.0, h=1e-6):
|
|
33
|
+
"""
|
|
34
|
+
dS/dt (数値微分) と D*J(t) (de Bruijnの恒等式の予測値) を両方返す。
|
|
35
|
+
理論上この2つは一致するはず。
|
|
36
|
+
"""
|
|
37
|
+
dS_dt = (differential_entropy_gaussian(t + h, sigma2_0, D)
|
|
38
|
+
- differential_entropy_gaussian(t - h, sigma2_0, D)) / (2 * h)
|
|
39
|
+
predicted = D * fisher_information_gaussian(t, sigma2_0, D)
|
|
40
|
+
return dS_dt, predicted
|
kappalogic/kernels.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""
|
|
2
|
+
kappalogic.kernels
|
|
3
|
+
====================
|
|
4
|
+
sgn(x) = kappa(x/xi) の kappa 部分を差し替え可能にするモジュール。
|
|
5
|
+
|
|
6
|
+
なぜ差し替えたいか(2026-07 開発メモ):
|
|
7
|
+
kappa=tanh は理論の初期案そのままで、遠方で指数関数的に速く飽和する
|
|
8
|
+
(誤差 ~ exp(-2x/xi))。これは「論理ゲート」用途には理想的だが、
|
|
9
|
+
kappa=erf を選ぶと sgn(x,xi) = erf(x/xi) が
|
|
10
|
+
u(x,t) = (1+erf(x/(2*sqrt(D*t))))/2
|
|
11
|
+
という「階段状初期条件からの熱拡散」の厳密解の形と一致する
|
|
12
|
+
(xi = 2*sqrt(D*t))。有限差分シミュレーションで最大誤差6e-5で
|
|
13
|
+
数値的に確認済み(dev_notes.md参照)。これにより
|
|
14
|
+
「xiを小さくする/大きくする」という操作に物理的な意味(時間発展)
|
|
15
|
+
を与えることができる。
|
|
16
|
+
|
|
17
|
+
kappa=algebraic (x/sqrt(x^2+1)) は exp/erf を使わない分安く、
|
|
18
|
+
べき乗オーダーの裾を持つ(exp的に速く0にはならない)。
|
|
19
|
+
シンボリック計算(sympyでの厳密な代数式としての扱い)や、
|
|
20
|
+
誤差の裾を緩めに保ちたい場面向け。
|
|
21
|
+
"""
|
|
22
|
+
import numpy as np
|
|
23
|
+
from scipy.special import erf as _erf
|
|
24
|
+
|
|
25
|
+
KERNELS = {}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def register_kernel(name):
|
|
29
|
+
def deco(fn):
|
|
30
|
+
KERNELS[name] = fn
|
|
31
|
+
return fn
|
|
32
|
+
return deco
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@register_kernel("tanh")
|
|
36
|
+
def _tanh_kernel(z):
|
|
37
|
+
return np.tanh(z)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@register_kernel("erf")
|
|
41
|
+
def _erf_kernel(z):
|
|
42
|
+
return _erf(z)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@register_kernel("algebraic")
|
|
46
|
+
def _algebraic_kernel(z):
|
|
47
|
+
return z / np.sqrt(z ** 2 + 1)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def apply_kernel(x, xi, kernel="tanh"):
|
|
51
|
+
"""kappa(x/xi) を計算する。kernel は 'tanh' | 'erf' | 'algebraic' か callable。"""
|
|
52
|
+
z = np.asarray(x, dtype=float) / xi
|
|
53
|
+
if callable(kernel):
|
|
54
|
+
return kernel(z)
|
|
55
|
+
try:
|
|
56
|
+
fn = KERNELS[kernel]
|
|
57
|
+
except KeyError:
|
|
58
|
+
raise ValueError(f"unknown kernel '{kernel}'. choices: {list(KERNELS)} or a callable")
|
|
59
|
+
return fn(z)
|