lkb-pipeline/core/lkb.R
allaun e5bfdc0492 feat: LKB compute pipeline + eigensolid receipts
Containerized LKB worker (Dockerfile.lkb), Postgres-backed queue,
auto-deploy timer, and eigensolid convergence check module.

Build: 0 jobs (no Lean build needed)
2026-07-08 20:01:29 -05:00

159 lines
4.8 KiB
R

source("boot.R")
box_use(./laurent2)
pair_idx <- function(a, b, pairs) {
if (a > b) { tmp <- a; a <- b; b <- tmp }
for (i in seq_along(pairs)) {
if (pairs[[i]][1] == a && pairs[[i]][2] == b) return(i)
}
stop(sprintf("Pair (%d,%d) not found", a, b))
}
pairs_list <- function(n) {
result <- list()
for (j in 0:(n-2)) for (k in (j+1):(n-1)) result[[length(result) + 1]] <- c(j, k)
result
}
lkb_generator_matrix <- function(k, n = 8, positive = TRUE) {
pairs <- pairs_list(n)
N <- length(pairs)
m <- laurent2$l2_mat_zero(N)
k0 <- k - 1L
q <- laurent2$l2_q
q2 <- laurent2$l2_mul(q, q)
qm1 <- laurent2$l2_qinv
qm2 <- laurent2$l2_mul(qm1, qm1)
t <- laurent2$l2_t
one <- laurent2$l2_one
zero <- laurent2$l2_zero
qsq_minus_q <- laurent2$laurent2(c("2,0" = 1, "1,0" = -1))
one_minus_q <- laurent2$laurent2(c("0,0" = 1, "1,0" = -1))
one_minus_qinv <- laurent2$laurent2(c("0,0" = 1, "-1,0" = -1))
qm1_minus_qm2 <- laurent2$laurent2(c("-2,0" = 1, "-1,0" = -1))
tqm1_minus_tqm2 <- laurent2$laurent2(c("-1,-1" = 1, "-2,-1" = -1))
neg_q2_t <- laurent2$laurent2(c("2,1" = -1))
neg_tinv_qinv2 <- laurent2$laurent2(c("-2,-1" = -1))
neg_t_q2 <- laurent2$laurent2(c("2,1" = -1))
for (idx in seq_len(N)) {
j <- pairs[[idx]][1]
kk <- pairs[[idx]][2]
if (positive) {
if (k0 == j - 1) {
m[[pair_idx(k0, kk, pairs), idx]] <- q
m[[pair_idx(k0, j, pairs), idx]] <- qsq_minus_q
m[[pair_idx(j, kk, pairs), idx]] <- one_minus_q
} else if (k0 == j && j != kk - 1) {
m[[pair_idx(j + 1L, kk, pairs), idx]] <- one
m[[idx, idx]] <- zero
} else if (kk - 1 == k0 && kk - 1 != j) {
m[[pair_idx(j, k0, pairs), idx]] <- q
m[[pair_idx(j, kk, pairs), idx]] <- one_minus_q
m[[pair_idx(k0, kk, pairs), idx]] <- laurent2$l2_mul(one_minus_q, laurent2$l2_mul(q, t))
} else if (k0 == kk) {
m[[pair_idx(j, kk + 1L, pairs), idx]] <- one
m[[idx, idx]] <- zero
} else if (k0 == j && j == kk - 1) {
# Sage: A[idx, m] = -t*q*q = -q^2*t
m[[idx, idx]] <- neg_q2_t
} else {
m[[idx, idx]] <- one
}
} else {
if (k0 == j - 1) {
m[[pair_idx(j - 1L, kk, pairs), idx]] <- one
} else if (k0 == j && j != kk - 1) {
m[[pair_idx(j + 1L, kk, pairs), idx]] <- qm1
m[[pair_idx(j, kk, pairs), idx]] <- one_minus_qinv
m[[pair_idx(j, j + 1L, pairs), idx]] <- tqm1_minus_tqm2
} else if (kk - 1 == k0 && kk - 1 != j) {
m[[pair_idx(j, kk - 1L, pairs), idx]] <- one
} else if (k0 == kk) {
m[[pair_idx(j, kk + 1L, pairs), idx]] <- qm1
m[[pair_idx(j, kk, pairs), idx]] <- one_minus_qinv
m[[pair_idx(kk, kk + 1L, pairs), idx]] <- qm1_minus_qm2
} else if (k0 == j && j == kk - 1) {
# Sage: A[idx, m] = -t^{-1}*q^{-2}
m[[idx, idx]] <- neg_tinv_qinv2
} else {
m[[idx, idx]] <- one
}
}
}
m
}
#' @export
lkb_pair_to_idx <- function(i, j, n) {
if (i > j) { tmp <- i; i <- j; j <- tmp }
as.integer((i - 1) * (2 * n - i) / 2 + (j - i))
}
#' @export
lkb_idx_to_pair <- function(idx, n) {
i <- 1
while (idx > (n - i)) { idx <- idx - (n - i); i <- i + 1 }
c(i, i + idx)
}
#' @export
lkb_generator <- function(k, n = 8) {
lkb_generator_matrix(k, n, TRUE)
}
#' @export
lkb_generator_inverse <- function(k, n = 8) {
lkb_generator_matrix(k, n, FALSE)
}
#' @export
lkb_generators <- function(n = 8) {
lapply(1:(n - 1), function(k) lkb_generator_matrix(k, n, TRUE))
}
#' @export
lkb_generators_inverse <- function(n = 8) {
lapply(1:(n - 1), function(k) lkb_generator_matrix(k, n, FALSE))
}
#' @export
lkb_matrix <- function(word, n = 8, gens = NULL, gens_inv = NULL) {
if (is.null(gens)) gens <- lkb_generators(n)
if (is.null(gens_inv)) gens_inv <- lkb_generators_inverse(n)
N <- n * (n - 1) / 2
result <- laurent2$l2_mat_identity(N)
for (s in unclass(word)) {
g <- abs(s)
if (g < 1 || g > n - 1) stop(sprintf("Invalid generator %d for B%d", g, n))
if (s > 0) {
result <- laurent2$l2_mat_mul(result, gens[[g]])
} else {
result <- laurent2$l2_mat_mul(result, gens_inv[[g]])
}
}
result
}
#' @export
lkb_basis_label <- function(idx, n) {
p <- lkb_idx_to_pair(idx, n)
paste0("e_{", p[1], ",", p[2], "}")
}
#' @export
lkb_matrix_str <- function(m, n = 8, threshold = 8) {
N <- nrow(m)
lines <- character(0)
for (i in 1:min(N, threshold)) {
row_parts <- character(min(N, threshold))
for (j in 1:min(N, threshold)) {
s <- laurent2$l2_str(m[[i, j]])
row_parts[j] <- if (nchar(s) > 12) paste0(substr(s, 1, 10), "..") else s
}
lines <- c(lines, paste0(lkb_basis_label(i, n), ": ", paste(row_parts, collapse = " | ")))
}
if (N > threshold) lines <- c(lines, paste0("... (", N, "x", N, " matrix)"))
paste(lines, collapse = "\n")
}