# PIST Fiedler-Aware Chiral Boundary Detection — R Port
#
# Mirrors `python/pist_fiedler_chiral.py` and `julia/PIST/pist_fiedler_chiral.jl`.
#
# Extends PIST spectral analysis (SpectralN.lean) with Fiedler vector
# sign-pattern analysis for chiral boundary classification.

# ── Build Laplacian ──────────────────────────────────────────────────

build_laplacian_8x8 <- function(cross_coupling = 1e-6) {
  C <- matrix(0, nrow = 8, ncol = 8)
  for (i in 1:8) {
    C[i, i] <- 39 / 256
    for (j in 1:8) {
      if (i != j) {
        if (floor((i - 1) / 2) == floor((j - 1) / 2)) {
          C[i, j] <- 1 / 7
        } else {
          C[i, j] <- cross_coupling
        }
      }
    }
  }

  A <- C
  diag(A) <- 0
  D <- diag(rowSums(A))
  D - A
}

# ── Power Iteration ──────────────────────────────────────────────────

power_iteration <- function(mat, max_iter = 100, tol = 1e-8) {
  n <- nrow(mat)
  v <- as.numeric(1:n)

  for (iter in 1:max_iter) {
    mv <- mat %*% v
    eig <- as.numeric((t(v) %*% mv) / (t(v) %*% v))
    norm_mv <- sqrt(sum(mv^2))
    if (norm_mv < 1e-15) break
    v_new <- as.numeric(mv / norm_mv)
    resid <- sqrt(sum((mv - eig * v)^2)) / n
    v <- v_new
    if (resid < tol) break
  }

  mv <- mat %*% v
  eig <- as.numeric((t(v) %*% mv) / (t(v) %*% v))
  list(eigenvalue = eig, eigenvector = as.numeric(v))
}

# ── Fiedler Vector ───────────────────────────────────────────────────

fiedler_vector <- function(L) {
  n <- nrow(L)
  res <- power_iteration(L)
  lambda_max <- res$eigenvalue
  mu <- lambda_max
  shift_mat <- mu * diag(n) - L

  v <- rep(1, n) / sqrt(n)

  for (iter in 1:50) {
    w <- tryCatch(solve(shift_mat, v), error = function(e) NULL)
    if (is.null(w)) break
    norm_w <- sqrt(sum(w^2))
    if (norm_w < 1e-10) break
    v_new <- as.numeric(w / norm_w)
    eig <- as.numeric(t(v_new) %*% (L %*% v_new))
    if (sqrt(sum((v_new - v)^2)) < 1e-8) {
      v <- v_new
      break
    }
    v <- v_new
  }

  fiedler_val <- as.numeric(t(v) %*% (L %*% v))
  list(fiedler_value = fiedler_val, fiedler_vector = v)
}

# ── Chiral Classification ────────────────────────────────────────────

classify_chiral_boundary <- function(fiedler_vec) {
  s <- sign(fiedler_vec)

  intra_flips <- 0
  for (k in 0:3) {
    if (s[2*k + 1] != s[2*k + 2]) intra_flips <- intra_flips + 1
  }

  inter_flips <- 0
  for (k in 0:2) {
    if (s[2*k + 2] != s[2*k + 3]) inter_flips <- inter_flips + 1
  }

  bias <- sapply(0:3, function(k) fiedler_vec[2*k + 1] + fiedler_vec[2*k + 2])
  net_bias <- sum(bias)

  if (intra_flips == 0 && inter_flips == 0) {
    return("achiral_stable")
  } else if (intra_flips > 0 && net_bias < 0) {
    return("left_handed")
  } else if (intra_flips > 0 && net_bias > 0) {
    return("right_handed")
  } else {
    return("chiral_scarred")
  }
}

# ── Full Profile ─────────────────────────────────────────────────────

compute_chiral_boundary_profile <- function(C_matrix = NULL) {
  L <- if (is.null(C_matrix)) build_laplacian_8x8() else build_laplacian_from_matrix(C_matrix)
  fres <- fiedler_vector(L)
  chiral_label <- classify_chiral_boundary(fres$fiedler_vector)
  pres <- power_iteration(L)
  s <- sign(fres$fiedler_vector)

  list(
    fiedler_value = fres$fiedler_value,
    fiedler_vector = fres$fiedler_vector,
    chiral_label = chiral_label,
    intra_pair_flips = sum(sapply(0:3, function(k) if (s[2*k+1] != s[2*k+2]) 1 else 0)),
    inter_pair_flips = sum(sapply(0:2, function(k) if (s[2*k+2] != s[2*k+3]) 1 else 0)),
    spectral_gap = pres$eigenvalue - fres$fiedler_value,
    dominant_eigenvalue = pres$eigenvalue
  )
}

build_laplacian_from_matrix <- function(mat) {
  A <- abs(mat)
  diag(A) <- 0
  D <- diag(rowSums(A))
  D - A
}

# ── Demo ──────────────────────────────────────────────────────────────

demo <- function() {
  cat(paste(rep("=", 60), collapse = ""), "\n")
  cat("PIST Fiedler-Aware Chiral Boundary Detection (R)\n")
  cat(paste(rep("=", 60), collapse = ""), "\n")

  L <- build_laplacian_8x8()
  cat("\nLaplacian L:\n")
  print(round(L, 6))

  pres <- power_iteration(L)
  cat(sprintf("\nλ_max (dominant): %.6f\n", pres$eigenvalue))

  fres <- fiedler_vector(L)
  cat(sprintf("Fiedler value (λ₂): %.6f\n", fres$fiedler_value))
  cat(sprintf("Spectral gap: %.6f\n", pres$eigenvalue - fres$fiedler_value))
  cat("Fiedler vector:", sprintf("%.6f", fres$fiedler_vector), "\n")
  cat("Sign pattern:", sprintf("%+d", sign(fres$fiedler_vector)), "\n")

  profile <- compute_chiral_boundary_profile()
  cat(sprintf("\nChiral classification: %s\n", profile$chiral_label))
  cat(sprintf("Intra-pair sign flips: %d\n", profile$intra_pair_flips))
  cat(sprintf("Inter-pair sign flips: %d\n", profile$inter_pair_flips))

  cat("\n--- Perturbation analysis ---\n")
  L_pert <- L
  L_pert[1, 1] <- L_pert[1, 1] + 0.5
  fv2 <- fiedler_vector(L_pert)
  cat(sprintf("Left-bias perturbation: Fiedler=%.6f, chiral=%s\n",
      fv2$fiedler_value, classify_chiral_boundary(fv2$fiedler_vector)))
}

if (interactive() && Sys.getenv("R_TEST") == "") {
  demo()
}
