from mpmath import mp, cos, log, sqrt, pi, e

def Z_integral_collapse(t, n_start=1, n_end=1000):
    """
    Z(t) = Σ cos(π/4 - t*log(n)) / √n
    
    Collapsing discrete gap d between n using periodicity:
    cos(θ) = cos(π/4 - t*log(n)) repeats when t*log(n) changes by 2πk
    
    Period in n-space:
    t*log(n_next) - t*log(n) = 2πk
    log(n_next/n) = 2πk/t
    n_next/n = e^(2πk/t) = d
    
    So we collapse the sum into an integral over the repeating gaps.
    """
    mp.dps = 50
    t = mp.mpf(t)
    
    print(f"\n{'='*80}")
    print(f"INTEGRAL COLLAPSE: Converting discrete sum to continuous")
    print(f"{'='*80}")
    print(f"t = {t}")
    
    # Period in n-space
    d = mp.e ** (2 * mp.pi / t)
    print(f"\nPeriod d = e^(2π/t) = {float(d):.6f}")
    print(f"→ Every ~{float(d):.4f}× increase in n, cos() repeats")
    
    # Discrete sum (ground truth)
    Z_discrete = mp.mpf(0)
    n_values = []
    cos_values = []
    for n in range(n_start, n_end + 1):
        c = cos(pi/4 - t * log(n))
        Z_discrete += 2 * c / sqrt(n)
        n_values.append(n)
        cos_values.append(float(c))
    
    print(f"\n[1] Discrete Sum Z({t}) = {Z_discrete}")
    
    # Integral approximation using period d
    # The sum is over n with weight 1/√n
    # The period is d, so we can write:
    # Σ f(n) ≈ ∫ f(x) dx / d (collapsing gaps of size d)
    
    print(f"\n[2] Integral Collapse:")
    
    # Transform: let x = log(n), so n = e^x, dn = e^x dx
    # f(n) = cos(π/4 - t*x) / e^(x/2)
    # dn = e^x dx
    # f(n) dn = cos(π/4 - t*x) * e^(x/2) dx
    
    # Integral from log(n_start) to log(n_end)
    x_start = log(n_start)
    x_end = log(n_end)
    
    print(f"   Integral bounds in x = log(n): [{float(x_start):.4f}, {float(x_end):.4f}]")
    print(f"   Integrand: cos(π/4 - t*x) * e^(x/2)")
    
    # Numerical integration using trapezoidal rule on the period
    # Since cos() repeats, we integrate over one period and scale
    # One period in x: Δx = 2π/t
    period_x = 2 * pi / t
    print(f"   One period in x: Δx = 2π/t = {float(period_x):.6f}")
    
    # Number of full periods in [x_start, x_end]
    n_periods = (x_end - x_start) / period_x
    print(f"   Number of periods: {float(n_periods):.4f}")
    
    # Integrate over one period [0, Δx]
    def integrand(x):
        return cos(pi/4 - t * x) * mp.e ** (x / 2)
    
    # Trapezoidal integration over one period
    N_steps = 1000
    dx = period_x / N_steps
    
    integral_one_period = mp.mpf(0)
    for i in range(N_steps):
        x0 = i * dx
        x1 = (i + 1) * dx
        f0 = integrand(x0)
        f1 = integrand(x1)
        integral_one_period += (f0 + f1) / 2 * dx
    
    print(f"   ∫ over one period = {integral_one_period}")
    
    # Scale by number of periods and weight by average 1/√n
    # This is the key step: we collapse the discrete gap d
    # Average n in range: roughly n_end/2
    avg_n = (n_start + n_end) / 2
    avg_inv_sqrt_n = 1 / sqrt(avg_n)
    
    Z_integral = 2 * n_periods * integral_one_period * avg_inv_sqrt_n
    
    print(f"\n[3] Integral Approximation:")
    print(f"   Z ≈ 2 × n_periods × integral × avg(1/√n)")
    print(f"   Z ≈ 2 × {float(n_periods):.4f} × {integral_one_period} × {float(avg_inv_sqrt_n):.4f}")
    print(f"   Z_integral = {Z_integral}")
    
    # Gap collapse interpretation
    print(f"\n[4] Gap Collapse Interpretation:")
    print(f"   Discrete: Σ over n = {n_end - n_start + 1} terms")
    print(f"   Continuous: ∫ collapsed by period d = {float(d):.4f}")
    print(f"   Equivalent terms: ~{(n_end - n_start) / float(d):.2f}")
    
    # Show how the integral captures the periodicity
    print(f"\n[5] Periodicity Check:")
    for k in range(1, 6):
        n_check = n_start * (d ** k)
        if n_check <= n_end:
            arg1 = float(pi/4 - t * log(n_start))
            arg2 = float(pi/4 - t * log(n_check))
            c1 = cos(pi/4 - t * log(n_start))
            c2 = cos(pi/4 - t * log(n_check))
            print(f"   n={n_start} → n'={float(n_check):.1f} (×{float(d):.3f}): "
                  f"arg={arg1:.4f} → {arg2:.4f}, cos={float(c1):.4f} → {float(c2):.4f}")
    
    # Final comparison
    print(f"\n{'='*80}")
    print(f"RESULT COMPARISON:")
    print(f"  Z_discrete  = {Z_discrete}")
    print(f"  Z_integral = {Z_integral}")
    print(f"  Error       = {abs(Z_discrete - Z_integral)}")
    print(f"{'='*80}")
    
    return {
        'Z_discrete': Z_discrete,
        'Z_integral': Z_integral,
        'period_d': d,
        'period_x': period_x,
        'n_periods': n_periods
    }

# Run
mp.dps = 50
#result = Z_integral_collapse(t=14.134725, n_start=1, n_end=1000)
result = Z_integral_collapse(t=1.9368047241, n_start=1, n_end=1000)
