""" PIST Fiedler-Aware Chiral Boundary Detection — Julia Port Extends PIST spectral analysis (SpectralN.lean) with Fiedler vector sign-pattern analysis for chiral boundary classification. References: - `formal/SilverSight/PIST/SpectralN.lean` - `formal/SilverSight/PIST/CartanConnection.lean` - `python/pist_fiedler_chiral.py` """ module FiedlerChiral using LinearAlgebra export build_laplacian_8x8, power_iteration, fiedler_vector, classify_chiral_boundary, compute_chiral_boundary_profile const CHIRAL_LABELS = ["achiral_stable", "left_handed", "right_handed", "chiral_scarred"] # ── Build Laplacian ────────────────────────────────────────────────── function build_laplacian_8x8(cross_coupling::Float64=1e-6)::Matrix{Float64} C = zeros(Float64, 8, 8) for i in 1:8 C[i, i] = 39.0 / 256.0 for j in 1:8 if i != j if div(i - 1, 2) == div(j - 1, 2) C[i, j] = 1.0 / 7.0 else C[i, j] = cross_coupling end end end end A = copy(C) for i in 1:8; A[i, i] = 0.0; end D = diagm(vec(sum(A, dims=2))) D - A end # ── Power Iteration ───────────────────────────────────────────────── function power_iteration(mat::Matrix{Float64}; max_iter::Int=100, tol::Float64=1e-8) n = size(mat, 1) v = Float64[Float64(i) for i in 1:n] for _ in 1:max_iter mv = mat * v eig = dot(v, mv) / dot(v, v) norm_mv = norm(mv) norm_mv < 1e-15 && break v_new = mv / norm_mv resid = norm(mv - eig * v) / n v = v_new resid < tol && break end mv = mat * v eig = dot(v, mv) / dot(v, v) (eig, v) end # ── Fiedler Vector ────────────────────────────────────────────────── function fiedler_vector(L::Matrix{Float64}) n = size(L, 1) lambda_max, v1 = power_iteration(L) # Use full eigendecomposition (n=8 is small enough). # For larger n, use iterative methods — for n=8 this is exact. eig_vals = eigvals(Symmetric(L)) eig_vecs = eigvecs(Symmetric(L)) # Fiedler value = second smallest eigenvalue sort_idx = sortperm(eig_vals) fiedler_val = eig_vals[sort_idx[2]] fiedler_vec = eig_vecs[:, sort_idx[2]] (fiedler_val, fiedler_vec) end # ── Chiral Classification ──────────────────────────────────────────── function classify_chiral_boundary(fiedler_vec::Vector{Float64})::String sign_vec = sign.(fiedler_vec) intra_flips = 0 for k in 0:3 sign_vec[2k+1] != sign_vec[2k+2] && (intra_flips += 1) end inter_flips = 0 for k in 0:2 sign_vec[2k+2] != sign_vec[2k+3] && (inter_flips += 1) end bias = [fiedler_vec[2k+1] + fiedler_vec[2k+2] for k in 0:3] net_bias = sum(bias) if intra_flips == 0 && inter_flips == 0 return "achiral_stable" elseif intra_flips > 0 && net_bias < 0 return "left_handed" elseif intra_flips > 0 && net_bias > 0 return "right_handed" else return "chiral_scarred" end end # ── Full Profile ───────────────────────────────────────────────────── function compute_chiral_boundary_profile(C_matrix::Union{Matrix{Float64}, Nothing}=nothing) L = C_matrix === nothing ? build_laplacian_8x8() : build_laplacian_from_matrix(C_matrix) f_val, f_vec = fiedler_vector(L) chiral_label = classify_chiral_boundary(f_vec) lambda_max, _ = power_iteration(L) Dict( "fiedler_value" => f_val, "fiedler_vector" => f_vec, "chiral_label" => chiral_label, "intra_pair_flips" => sum([sign(f_vec[2k+1]) != sign(f_vec[2k+2]) ? 1 : 0 for k in 0:3]), "inter_pair_flips" => sum([sign(f_vec[2k+2]) != sign(f_vec[2k+3]) ? 1 : 0 for k in 0:2]), "spectral_gap" => lambda_max - f_val, "dominant_eigenvalue" => lambda_max, ) end function build_laplacian_from_matrix(mat::Matrix{Float64})::Matrix{Float64} A = abs.(mat) for i in 1:size(A, 1); A[i, i] = 0.0; end D = diagm(vec(sum(A, dims=2))) D - A end # ── Demo ────────────────────────────────────────────────────────────── function demo() println("="^60) println("PIST Fiedler-Aware Chiral Boundary Detection (Julia)") println("="^60) L = build_laplacian_8x8() println("\nLaplacian L:") display(round.(L, digits=6)) lambda_max, v1 = power_iteration(L) println("\nλ_max (dominant): $(round(lambda_max, digits=6))") f_val, f_vec = fiedler_vector(L) println("Fiedler value (λ₂): $(round(f_val, digits=6))") println("Spectral gap: $(round(lambda_max - f_val, digits=6))") println("Fiedler vector: $(round.(f_vec, digits=6))") println("Sign pattern: $(sign.(f_vec))") profile = compute_chiral_boundary_profile() println("\nChiral classification: $(profile["chiral_label"])") println("Intra-pair sign flips: $(profile["intra_pair_flips"])") println("Inter-pair sign flips: $(profile["inter_pair_flips"])") println("\n--- Perturbation analysis ---") L_pert = copy(L) L_pert[1, 1] += 0.5 fv2, fv2_vec = fiedler_vector(L_pert) println("Left-bias perturbation: Fiedler=$(round(fv2, digits=6)), chiral=$(classify_chiral_boundary(fv2_vec))") end end # module if abspath(PROGRAM_FILE) == @__FILE__ using .FiedlerChiral FiedlerChiral.demo() end