File size: 4,438 Bytes
f7c4905
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"""
EXPERIMENT 1c: Robust root finding for F(z) = sum z^n/n^n
Using continuation method from known roots.
"""
import numpy as np
from scipy.optimize import fsolve
import json

def F_vec(zv, N=150):
    z = complex(zv[0], zv[1])
    result = 0.0 + 0.0j
    for n in range(1, N+1):
        try:
            term = z**n / n**n
        except (OverflowError, ZeroDivisionError):
            break
        if abs(term) > 1e100 or np.isnan(abs(term)) or np.isinf(abs(term)):
            break
        result += term
    return [result.real, result.imag]

# Start from known roots and extend
known_roots = [
    (-4.305, 14.945),
    (-5.386, 32.038),
    (-5.996, 49.129),
    (-6.421, 66.215),
]

roots = []
for kr in known_roots:
    r = complex(kr[0], kr[1])
    val = complex(*F_vec([r.real, r.imag]))
    if abs(val) < 1e-3:
        # Refine with fsolve
        refined = fsolve(F_vec, [r.real, r.imag], full_output=False)
        r = complex(refined[0], refined[1])
        roots.append(r)

# Continue from last known root
if len(roots) > 0:
    last_root = roots[-1]
    # Estimate next root position
    if len(roots) >= 2:
        im_step = roots[-1].imag - roots[-2].imag
        re_step = roots[-1].real - roots[-2].real
    else:
        im_step = 17.08
        re_step = -0.4
    
    # Extend forward
    for k in range(30):
        re_guess = last_root.real + re_step
        im_guess = last_root.imag + im_step
        try:
            refined = fsolve(F_vec, [re_guess, im_guess], full_output=False)
            r = complex(refined[0], refined[1])
            val = complex(*F_vec([r.real, r.imag]))
            if abs(val) < 1e-3 and r.imag > 0 and r.real < 0:
                # Check not duplicate
                is_dup = any(abs(r - ex) < 1.0 for ex in roots)
                if not is_dup:
                    roots.append(r)
                    last_root = r
                    # Update step estimates from last two roots
                    if len(roots) >= 2:
                        im_step = roots[-1].imag - roots[-2].imag
                        re_step = roots[-1].real - roots[-2].real
        except:
            pass

# Also search backward from first root
if len(roots) > 0:
    first_root = roots[0]
    if len(roots) >= 2:
        im_step = roots[1].imag - roots[0].imag
        re_step = roots[1].real - roots[0].real
    else:
        im_step = 17.08
        re_step = 0.4  # going backward means Re increases
    
    for k in range(5):
        re_guess = first_root.real - re_step  # going back
        im_guess = first_root.imag - im_step
        if im_guess < 5:
            break
        try:
            refined = fsolve(F_vec, [re_guess, im_guess], full_output=False)
            r = complex(refined[0], refined[1])
            val = complex(*F_vec([r.real, r.imag]))
            if abs(val) < 1e-3 and r.imag > 0 and r.real < 0:
                is_dup = any(abs(r - ex) < 1.0 for ex in roots)
                if not is_dup:
                    roots.insert(0, r)
                    first_root = r
        except:
            pass

roots.sort(key=lambda r: r.imag)
print(f"Found {len(roots)} roots\n")

if len(roots) >= 2:
    im_spacings = [roots[i].imag - roots[i-1].imag for i in range(1, len(roots))]
    re_shifts = [roots[i].real - roots[i-1].real for i in range(1, len(roots))]
    
    print(f"{'#':>3s}  {'Re':>10s}  {'Im':>10s}  {'Im-gap':>10s}  {'Re-shift':>10s}")
    for i, r in enumerate(roots):
        im_gap = f"{im_spacings[i-1]:10.4f}" if i > 0 else f"{'---':>10s}"
        re_shift = f"{re_shifts[i-1]:10.4f}" if i > 0 else f"{'---':>10s}"
        print(f"{i:3d}  {r.real:10.4f}  {r.imag:10.4f}  {im_gap}  {re_shift}")
    
    mean_im = np.mean(im_spacings)
    std_im = np.std(im_spacings)
    
    print(f"\nIm-spacing: mean={mean_im:.6f}, std={std_im:.6f}")
    print(f"2*pi*e:     {2*np.pi*np.e:.6f}")
    print(f"Ratio:      {mean_im/(2*np.pi*np.e):.6f}")
    print(f"Re-shift:   mean={np.mean(re_shifts):.6f}")
    
    # Save
    results = {
        'roots_re': [r.real for r in roots],
        'roots_im': [r.imag for r in roots],
        'im_spacings': im_spacings,
        're_shifts': re_shifts,
        'two_pi_e': float(2*np.pi*np.e),
        'mean_im_spacing': float(mean_im),
        'std_im_spacing': float(std_im),
    }
    with open('/app/exp1_results.json', 'w') as f:
        json.dump(results, f, indent=2)
    print("\nSaved to /app/exp1_results.json")