sov-kernel-monster / r /bob_quantum.R
SNAPKITTYWEST's picture
chore: push full sov-kernel-monster content from local build
9425aed verified
Raw
History Blame Contribute Delete
26 kB
# BOB Quantum Civilization Engine - R Bindings
# Complete interface to C ABI via .Call()
# Requires: libbobquantum.so / bobquantum.dll / libbobquantum.dylib
.onLoad <- function(libname, pkgname) {
lib_path <- system.file("libs", paste0("bobquantum", .Platform$dynlib.ext), package = pkgname)
if (lib_path == "") {
lib_path <- Sys.getenv("BOB_QUANTUM_LIB", "bobquantum")
}
tryCatch({
dyn.load(lib_path)
.bob_initialized <<- TRUE
packageStartupMessage("BOB Quantum Civilization Engine loaded from: ", lib_path)
}, error = function(e) {
.bob_initialized <<- FALSE
packageStartupMessage("WARNING: Failed to load BOB library: ", e$message)
packageStartupMessage("Set BOB_QUANTUM_LIB environment variable or install library in libs/")
})
invisible(NULL)
}
.onUnload <- function(libpath) {
if (exists(".bob_initialized") && .bob_initialized) {
tryCatch(dyn.unload(libpath), error = function(e) NULL)
.bob_initialized <<- FALSE
}
invisible(NULL)
}
.bob_initialized <- FALSE
.check_init <- function() {
if (!exists(".bob_initialized") || !.bob_initialized) {
stop("BOB engine not initialized. Load package or call bob_init() first.")
}
}
bob_init <- function(lib_path = NULL) {
if (exists(".bob_initialized") && .bob_initialized) {
return(invisible(TRUE))
}
if (is.null(lib_path)) {
lib_path <- Sys.getenv("BOB_QUANTUM_LIB", "bobquantum")
}
dyn.load(lib_path)
.bob_initialized <<- TRUE
invisible(TRUE)
}
bob_version <- function() {
.check_init()
.Call("bob_version")
}
bob_last_error <- function() {
.check_init()
.Call("bob_last_error")
}
# ============================================================================
# RNG MODULE
# ============================================================================
bob.rng.create <- function(seed = NULL) {
.check_init()
if (is.null(seed)) {
seed <- as.integer(runif(1, 1, .Machine$integer.max))
} else if (!is.numeric(seed) || length(seed) != 1) {
stop("seed must be a single integer")
}
seed <- as.integer(seed)
ptr <- .Call("bob_rng_create", seed)
if (is.null(ptr)) stop("Failed to create RNG: ", bob_last_error())
structure(ptr, class = "bob_rng")
}
bob.rng.uniform <- function(rng) {
.check_init()
if (!inherits(rng, "bob_rng")) stop("rng must be a bob_rng object")
val <- .Call("bob_rng_uniform", rng)
if (is.null(val)) stop("RNG uniform failed: ", bob_last_error())
val
}
bob.rng.normal <- function(rng, mean = 0, sd = 1) {
.check_init()
if (!inherits(rng, "bob_rng")) stop("rng must be a bob_rng object")
if (!is.numeric(mean) || length(mean) != 1) stop("mean must be numeric scalar")
if (!is.numeric(sd) || length(sd) != 1 || sd <= 0) stop("sd must be positive numeric scalar")
val <- .Call("bob_rng_normal", rng, as.double(mean), as.double(sd))
if (is.null(val)) stop("RNG normal failed: ", bob_last_error())
val
}
bob.rng.destroy <- function(rng) {
.check_init()
if (!inherits(rng, "bob_rng")) stop("rng must be a bob_rng object")
.Call("bob_rng_destroy", rng)
invisible(NULL)
}
print.bob_rng <- function(x, ...) {
cat("<BOB RNG pointer: ", format(x), ">\n", sep = "")
invisible(x)
}
# ============================================================================
# LATTICE MODULE
# ============================================================================
bob.lattice.create <- function(nx, ny, nz, coupling = 1.0, seed = NULL, periodic = TRUE) {
.check_init()
nx <- as.integer(nx); ny <- as.integer(ny); nz <- as.integer(nz)
if (nx <= 0 || ny <= 0 || nz <= 0) stop("Dimensions must be positive integers")
if (nx * ny * nz > 1e7) warning("Large lattice (", nx*ny*nz, " sites) may consume significant memory")
coupling <- as.double(coupling)
periodic <- as.logical(periodic)
if (is.null(seed)) {
seed <- as.integer(runif(1, 1, .Machine$integer.max))
} else {
seed <- as.integer(seed)
}
ptr <- .Call("bob_lattice_create", nx, ny, nz, coupling, seed, periodic)
if (is.null(ptr)) stop("Failed to create lattice: ", bob_last_error())
structure(ptr, class = "bob_lattice", dim = c(nx, ny, nz), coupling = coupling, periodic = periodic)
}
bob.lattice.evolve <- function(lattice, dt) {
.check_init()
if (!inherits(lattice, "bob_lattice")) stop("lattice must be a bob_lattice object")
dt <- as.double(dt)
if (dt <= 0) stop("dt must be positive")
result <- .Call("bob_lattice_evolve", lattice, dt)
if (is.null(result)) stop("Lattice evolve failed: ", bob_last_error())
invisible(lattice)
}
bob.lattice.energy <- function(lattice) {
.check_init()
if (!inherits(lattice, "bob_lattice")) stop("lattice must be a bob_lattice object")
val <- .Call("bob_lattice_energy", lattice)
if (is.null(val)) stop("Lattice energy failed: ", bob_last_error())
val
}
bob.lattice.entropy <- function(lattice) {
.check_init()
if (!inherits(lattice, "bob_lattice")) stop("lattice must be a bob_lattice object")
val <- .Call("bob_lattice_entropy", lattice)
if (is.null(val)) stop("Lattice entropy failed: ", bob_last_error())
val
}
bob.lattice.magnetization <- function(lattice) {
.check_init()
if (!inherits(lattice, "bob_lattice")) stop("lattice must be a bob_lattice object")
val <- .Call("bob_lattice_magnetization", lattice)
if (is.null(val)) stop("Lattice magnetization failed: ", bob_last_error())
val
}
bob.lattice.correlation <- function(lattice, max_distance = NULL) {
.check_init()
if (!inherits(lattice, "bob_lattice")) stop("lattice must be a bob_lattice object")
dims <- attr(lattice, "dim")
max_dist <- if (is.null(max_distance)) min(dims) %/% 2 else as.integer(max_distance)
val <- .Call("bob_lattice_correlation", lattice, max_dist)
if (is.null(val)) stop("Lattice correlation failed: ", bob_last_error())
val
}
bob.lattice.get_state <- function(lattice) {
.check_init()
if (!inherits(lattice, "bob_lattice")) stop("lattice must be a bob_lattice object")
val <- .Call("bob_lattice_get_state", lattice)
if (is.null(val)) stop("Get lattice state failed: ", bob_last_error())
dims <- attr(lattice, "dim")
array(val, dim = dims)
}
bob.lattice.set_state <- function(lattice, state_array) {
.check_init()
if (!inherits(lattice, "bob_lattice")) stop("lattice must be a bob_lattice object")
dims <- attr(lattice, "dim")
if (!is.array(state_array) || !all(dim(state_array) == dims)) {
stop("state_array must be an array with dimensions ", paste(dims, collapse = "x"))
}
result <- .Call("bob_lattice_set_state", lattice, as.vector(state_array))
if (is.null(result)) stop("Set lattice state failed: ", bob_last_error())
invisible(lattice)
}
bob.lattice.destroy <- function(lattice) {
.check_init()
if (!inherits(lattice, "bob_lattice")) stop("lattice must be a bob_lattice object")
.Call("bob_lattice_destroy", lattice)
invisible(NULL)
}
print.bob_lattice <- function(x, ...) {
dims <- attr(x, "dim")
cat("<BOB Lattice: ", dims[1], "x", dims[2], "x", dims[3], ">", sep = "")
cat(" coupling=", attr(x, "coupling"))
cat(" periodic=", attr(x, "periodic"), "\n", sep = "")
invisible(x)
}
summary.bob_lattice <- function(object, ...) {
cat("BOB Lattice Summary\n")
cat("===================\n")
dims <- attr(object, "dim")
cat("Dimensions: ", dims[1], " x ", dims[2], " x ", dims[3], " (", prod(dims), " sites)\n", sep = "")
cat("Coupling: ", attr(object, "coupling"), "\n")
cat("Periodic BC: ", attr(object, "periodic"), "\n")
cat("Energy: ", bob.lattice.energy(object), "\n")
cat("Entropy: ", bob.lattice.entropy(object), "\n")
cat("Magnetization: ", bob.lattice.magnetization(object), "\n")
invisible(object)
}
# ============================================================================
# QUANTUM STATE MODULE
# ============================================================================
bob.state.create <- function(num_qubits) {
.check_init()
num_qubits <- as.integer(num_qubits)
if (num_qubits <= 0) stop("num_qubits must be positive")
if (num_qubits > 20) warning("Large number of qubits (", num_qubits, ") -> state vector size ", 2^num_qubits)
ptr <- .Call("bob_state_create", num_qubits)
if (is.null(ptr)) stop("Failed to create quantum state: ", bob_last_error())
structure(ptr, class = "bob_state", num_qubits = num_qubits)
}
bob.state.clone <- function(state) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
ptr <- .Call("bob_state_clone", state)
if (is.null(ptr)) stop("Failed to clone state: ", bob_last_error())
structure(ptr, class = "bob_state", num_qubits = attr(state, "num_qubits"))
}
bob.state.num_qubits <- function(state) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
attr(state, "num_qubits")
}
bob.state.dim <- function(state) {
2^bob.state.num_qubits(state)
}
bob.state.get_amplitudes <- function(state) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
val <- .Call("bob_state_get_amplitudes", state)
if (is.null(val)) stop("Get amplitudes failed: ", bob_last_error())
val
}
bob.state.set_amplitudes <- function(state, amplitudes) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
n <- bob.state.dim(state)
if (!is.numeric(amplitudes) && !is.complex(amplitudes)) stop("amplitudes must be numeric or complex")
if (length(amplitudes) != n) stop("amplitudes length must be ", n)
amps <- as.complex(amplitudes)
norm <- sqrt(sum(Mod(amps)^2))
if (abs(norm - 1) > 1e-10) {
warning("Amplitudes not normalized (norm = ", norm, "), normalizing...")
amps <- amps / norm
}
result <- .Call("bob_state_set_amplitudes", state, amps)
if (is.null(result)) stop("Set amplitudes failed: ", bob_last_error())
invisible(state)
}
bob.state.measure <- function(state, rng, collapse = TRUE) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
if (!inherits(rng, "bob_rng")) stop("rng must be a bob_rng object")
collapse <- as.logical(collapse)
result <- .Call("bob_state_measure", state, rng, collapse)
if (is.null(result)) stop("Measurement failed: ", bob_last_error())
result
}
bob.state.measure_shots <- function(state, num_shots, rng) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
if (!inherits(rng, "bob_rng")) stop("rng must be a bob_rng object")
num_shots <- as.integer(num_shots)
if (num_shots <= 0) stop("num_shots must be positive")
result <- .Call("bob_state_measure_shots", state, num_shots, rng)
if (is.null(result)) stop("Measure shots failed: ", bob_last_error())
result
}
bob.state.probabilities <- function(state) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
amps <- bob.state.get_amplitudes(state)
Mod(amps)^2
}
bob.state.entropy <- function(state, base = 2) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
probs <- bob.state.probabilities(state)
probs <- probs[probs > 0]
if (base == 2) {
-sum(probs * log2(probs))
} else if (base == exp(1)) {
-sum(probs * log(probs))
} else {
-sum(probs * log(probs, base))
}
}
bob.state.fidelity <- function(state1, state2) {
.check_init()
if (!inherits(state1, "bob_state") || !inherits(state2, "bob_state")) {
stop("Both arguments must be bob_state objects")
}
if (bob.state.num_qubits(state1) != bob.state.num_qubits(state2)) {
stop("States must have same number of qubits")
}
amps1 <- bob.state.get_amplitudes(state1)
amps2 <- bob.state.get_amplitudes(state2)
Mod(sum(Conj(amps1) * amps2))^2
}
bob.state.apply_gate <- function(state, gate_matrix, qubits) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
n <- bob.state.num_qubits(state)
qubits <- as.integer(qubits)
if (any(qubits < 0) || any(qubits >= n)) stop("qubits must be in 0..", n-1)
k <- length(qubits)
if (!is.matrix(gate_matrix) || nrow(gate_matrix) != 2^k || ncol(gate_matrix) != 2^k) {
stop("gate_matrix must be ", 2^k, "x", 2^k)
}
gate <- as.complex(gate_matrix)
result <- .Call("bob_state_apply_gate", state, gate, qubits)
if (is.null(result)) stop("Apply gate failed: ", bob_last_error())
invisible(state)
}
bob.state.apply_hadamard <- function(state, qubit) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
qubit <- as.integer(qubit)
H <- matrix(c(1, 1, 1, -1), 2, 2) / sqrt(2)
bob.state.apply_gate(state, H, qubit)
}
bob.state.apply_pauli_x <- function(state, qubit) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
qubit <- as.integer(qubit)
X <- matrix(c(0, 1, 1, 0), 2, 2)
bob.state.apply_gate(state, X, qubit)
}
bob.state.apply_pauli_y <- function(state, qubit) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
qubit <- as.integer(qubit)
Y <- matrix(c(0, -1i, 1i, 0), 2, 2)
bob.state.apply_gate(state, Y, qubit)
}
bob.state.apply_pauli_z <- function(state, qubit) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
qubit <- as.integer(qubit)
Z <- matrix(c(1, 0, 0, -1), 2, 2)
bob.state.apply_gate(state, Z, qubit)
}
bob.state.apply_cnot <- function(state, control, target) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
control <- as.integer(control)
target <- as.integer(target)
if (control == target) stop("control and target must be different")
CNOT <- matrix(c(1,0,0,0, 0,1,0,0, 0,0,0,1, 0,0,1,0), 4, 4)
bob.state.apply_gate(state, CNOT, c(control, target))
}
bob.state.apply_rotation <- function(state, qubit, axis, angle) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
qubit <- as.integer(qubit)
axis <- match.arg(axis, c("x", "y", "z"))
angle <- as.double(angle)
if (axis == "x") {
gate <- matrix(c(cos(angle/2), -1i*sin(angle/2), -1i*sin(angle/2), cos(angle/2)), 2, 2)
} else if (axis == "y") {
gate <- matrix(c(cos(angle/2), -sin(angle/2), sin(angle/2), cos(angle/2)), 2, 2)
} else {
gate <- matrix(c(exp(-1i*angle/2), 0, 0, exp(1i*angle/2)), 2, 2)
}
bob.state.apply_gate(state, gate, qubit)
}
bob.state.destroy <- function(state) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
.Call("bob_state_destroy", state)
invisible(NULL)
}
print.bob_state <- function(x, ...) {
n <- attr(x, "num_qubits")
cat("<BOB Quantum State: ", n, " qubits, dim = ", 2^n, ">\n", sep = "")
invisible(x)
}
summary.bob_state <- function(object, ...) {
n <- attr(object, "num_qubits")
cat("BOB Quantum State Summary\n")
cat("=========================\n")
cat("Qubits: ", n, "\n")
cat("Dimension: ", 2^n, "\n")
probs <- bob.state.probabilities(object)
cat("Entropy (base 2): ", bob.state.entropy(object), "\n")
cat("Max probability: ", max(probs), " (state ", which.max(probs)-1, ")\n", sep = "")
cat("Non-zero amplitudes: ", sum(probs > 1e-15), "\n")
invisible(object)
}
# ============================================================================
# HAMILTONIAN MODULE
# ============================================================================
bob.hamiltonian.create <- function(num_qubits) {
.check_init()
num_qubits <- as.integer(num_qubits)
if (num_qubits <= 0) stop("num_qubits must be positive")
ptr <- .Call("bob_hamiltonian_create", num_qubits)
if (is.null(ptr)) stop("Failed to create Hamiltonian: ", bob_last_error())
structure(ptr, class = "bob_hamiltonian", num_qubits = num_qubits, terms = list())
}
bob.hamiltonian.add_term <- function(h, matrix, coeff, qubits) {
.check_init()
if (!inherits(h, "bob_hamiltonian")) stop("h must be a bob_hamiltonian object")
n <- attr(h, "num_qubits")
qubits <- as.integer(qubits)
if (any(qubits < 0) || any(qubits >= n)) stop("qubits must be in 0..", n-1)
k <- length(qubits)
if (!is.matrix(matrix) || nrow(matrix) != 2^k || ncol(matrix) != 2^k) {
stop("matrix must be ", 2^k, "x", 2^k)
}
coeff <- as.double(coeff)
mat <- as.complex(matrix)
result <- .Call("bob_hamiltonian_add_term", h, mat, coeff, qubits)
if (is.null(result)) stop("Add term failed: ", bob_last_error())
attr(h, "terms") <- c(attr(h, "terms"), list(list(matrix = mat, coeff = coeff, qubits = qubits)))
invisible(h)
}
bob.hamiltonian.add_pauli_term <- function(h, pauli_string, coeff, qubits) {
.check_init()
if (!inherits(h, "bob_hamiltonian")) stop("h must be a bob_hamiltonian object")
pauli_map <- list(
I = matrix(c(1,0,0,1), 2, 2),
X = matrix(c(0,1,1,0), 2, 2),
Y = matrix(c(0,-1i,1i,0), 2, 2),
Z = matrix(c(1,0,0,-1), 2, 2)
)
pauli_string <- toupper(pauli_string)
if (nchar(pauli_string) != length(qubits)) {
stop("pauli_string length must match number of qubits")
}
mats <- strsplit(pauli_string, "")[[1]]
for (p in mats) if (!(p %in% names(pauli_map))) stop("Invalid Pauli: ", p)
full_mat <- pauli_map[[mats[1]]]
if (length(mats) > 1) {
for (i in 2:length(mats)) {
full_mat <- kronecker(full_mat, pauli_map[[mats[i]]])
}
}
bob.hamiltonian.add_term(h, full_mat, coeff, qubits)
}
bob.hamiltonian.add_ising <- function(h, J, h_field, qubits = NULL) {
.check_init()
if (!inherits(h, "bob_hamiltonian")) stop("h must be a bob_hamiltonian object")
n <- attr(h, "num_qubits")
if (is.null(qubits)) qubits <- 0:(n-1)
qubits <- as.integer(qubits)
J <- as.double(J)
h_field <- as.double(h_field)
for (i in seq_along(qubits)) {
if (i < length(qubits)) {
bob.hamiltonian.add_pauli_term(h, "ZZ", -J, c(qubits[i], qubits[i+1]))
}
bob.hamiltonian.add_pauli_term(h, "Z", -h_field, qubits[i])
}
invisible(h)
}
bob.hamiltonian.add_heisenberg <- function(h, Jx, Jy, Jz, qubits = NULL) {
.check_init()
if (!inherits(h, "bob_hamiltonian")) stop("h must be a bob_hamiltonian object")
n <- attr(h, "num_qubits")
if (is.null(qubits)) qubits <- 0:(n-1)
qubits <- as.integer(qubits)
Jx <- as.double(Jx); Jy <- as.double(Jy); Jz <- as.double(Jz)
for (i in seq_along(qubits)) {
if (i < length(qubits)) {
bob.hamiltonian.add_pauli_term(h, "XX", -Jx, c(qubits[i], qubits[i+1]))
bob.hamiltonian.add_pauli_term(h, "YY", -Jy, c(qubits[i], qubits[i+1]))
bob.hamiltonian.add_pauli_term(h, "ZZ", -Jz, c(qubits[i], qubits[i+1]))
}
}
invisible(h)
}
bob.hamiltonian.expectation <- function(h, state) {
.check_init()
if (!inherits(h, "bob_hamiltonian")) stop("h must be a bob_hamiltonian object")
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
if (attr(h, "num_qubits") != attr(state, "num_qubits")) {
stop("Hamiltonian and state must have same number of qubits")
}
val <- .Call("bob_hamiltonian_expectation", h, state)
if (is.null(val)) stop("Expectation failed: ", bob_last_error())
val
}
bob.hamiltonian.variance <- function(h, state) {
.check_init()
if (!inherits(h, "bob_hamiltonian")) stop("h must be a bob_hamiltonian object")
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
exp_val <- bob.hamiltonian.expectation(h, state)
h2 <- bob.hamiltonian.clone(h)
bob.hamiltonian.add_term(h2, bob.hamiltonian.get_matrix(h), 1.0, 0:(attr(h, "num_qubits")-1))
exp_val2 <- bob.hamiltonian.expectation(h2, state)
bob.hamiltonian.destroy(h2)
exp_val2 - exp_val^2
}
bob.hamiltonian.get_matrix <- function(h) {
.check_init()
if (!inherits(h, "bob_hamiltonian")) stop("h must be a bob_hamiltonian object")
val <- .Call("bob_hamiltonian_get_matrix", h)
if (is.null(val)) stop("Get matrix failed: ", bob_last_error())
val
}
bob.hamiltonian.eigenvalues <- function(h, k = NULL) {
.check_init()
if (!inherits(h, "bob_hamiltonian")) stop("h must be a bob_hamiltonian object")
n <- attr(h, "num_qubits")
dim <- 2^n
if (is.null(k)) k <- min(dim, 10)
k <- as.integer(k)
if (k <= 0 || k > dim) stop("k must be in 1..", dim)
val <- .Call("bob_hamiltonian_eigenvalues", h, k)
if (is.null(val)) stop("Eigenvalues failed: ", bob_last_error())
val
}
bob.hamiltonian.ground_state <- function(h) {
.check_init()
if (!inherits(h, "bob_hamiltonian")) stop("h must be a bob_hamiltonian object")
n <- attr(h, "num_qubits")
ptr <- .Call("bob_hamiltonian_ground_state", h)
if (is.null(ptr)) stop("Ground state failed: ", bob_last_error())
structure(ptr, class = "bob_state", num_qubits = n)
}
bob.hamiltonian.time_evolve <- function(h, state, dt) {
.check_init()
if (!inherits(h, "bob_hamiltonian")) stop("h must be a bob_hamiltonian object")
if (!inherits(state, "bob_state")) stop("state must be a bob_state object")
if (attr(h, "num_qubits") != attr(state, "num_qubits")) {
stop("Hamiltonian and state must have same number of qubits")
}
dt <- as.double(dt)
result <- .Call("bob_hamiltonian_time_evolve", h, state, dt)
if (is.null(result)) stop("Time evolution failed: ", bob_last_error())
invisible(state)
}
bob.hamiltonian.clone <- function(h) {
.check_init()
if (!inherits(h, "bob_hamiltonian")) stop("h must be a bob_hamiltonian object")
ptr <- .Call("bob_hamiltonian_clone", h)
if (is.null(ptr)) stop("Clone failed: ", bob_last_error())
structure(ptr, class = "bob_hamiltonian", num_qubits = attr(h, "num_qubits"), terms = attr(h, "terms"))
}
bob.hamiltonian.destroy <- function(h) {
.check_init()
if (!inherits(h, "bob_hamiltonian")) stop("h must be a bob_hamiltonian object")
.Call("bob_hamiltonian_destroy", h)
invisible(NULL)
}
print.bob_hamiltonian <- function(x, ...) {
n <- attr(x, "num_qubits")
nterms <- length(attr(x, "terms"))
cat("<BOB Hamiltonian: ", n, " qubits, ", nterms, " terms>\n", sep = "")
invisible(x)
}
summary.bob_hamiltonian <- function(object, ...) {
n <- attr(object, "num_qubits")
terms <- attr(object, "terms")
cat("BOB Hamiltonian Summary\n")
cat("=======================\n")
cat("Qubits: ", n, "\n")
cat("Dimension: ", 2^n, "\n")
cat("Terms: ", length(terms), "\n")
for (i in seq_along(terms)) {
t <- terms[[i]]
cat(" Term ", i, ": coeff=", t$coeff, " qubits=", paste(t$qubits, collapse=","), "\n", sep="")
}
evals <- bob.hamiltonian.eigenvalues(object, min(5, 2^n))
cat("Lowest eigenvalues: ", paste(round(evals, 6), collapse=", "), "\n")
invisible(object)
}
# ============================================================================
# SIMULATION HELPERS
# ============================================================================
bob.simulate.lattice_ising <- function(nx, ny, nz, coupling = 1.0, temp = 1.0, steps = 1000, seed = NULL, periodic = TRUE) {
.check_init()
lattice <- bob.lattice.create(nx, ny, nz, coupling, seed, periodic)
rng <- bob.rng.create(seed)
energies <- numeric(steps)
entropies <- numeric(steps)
mags <- numeric(steps)
for (i in seq_len(steps)) {
bob.lattice.evolve(lattice, 1.0 / temp)
energies[i] <- bob.lattice.energy(lattice)
entropies[i] <- bob.lattice.entropy(lattice)
mags[i] <- bob.lattice.magnetization(lattice)
}
bob.lattice.destroy(lattice)
bob.rng.destroy(rng)
data.frame(step = 1:steps, energy = energies, entropy = entropies, magnetization = mags)
}
bob.simulate.quantum_evolution <- function(hamiltonian, initial_state, times, rng = NULL) {
.check_init()
if (!inherits(hamiltonian, "bob_hamiltonian")) stop("hamiltonian must be bob_hamiltonian")
if (!inherits(initial_state, "bob_state")) stop("initial_state must be bob_state")
if (is.null(rng)) rng <- bob.rng.create()
state <- bob.state.clone(initial_state)
n_times <- length(times)
expectations <- numeric(n_times)
entropies <- numeric(n_times)
fidelities <- numeric(n_times)
for (i in seq_len(n_times)) {
if (i > 1) {
dt <- times[i] - times[i-1]
bob.hamiltonian.time_evolve(hamiltonian, state, dt)
}
expectations[i] <- bob.hamiltonian.expectation(hamiltonian, state)
entropies[i] <- bob.state.entropy(state)
fidelities[i] <- bob.state.fidelity(state, initial_state)
}
bob.state.destroy(state)
data.frame(time = times, expectation = expectations, entropy = entropies, fidelity = fidelities)
}
bob.simulate.measurement_statistics <- function(state, num_shots = 1000, rng = NULL) {
.check_init()
if (!inherits(state, "bob_state")) stop("state must be bob_state")
if (is.null(rng)) rng <- bob.rng.create()
results <- bob.state.measure_shots(state, num_shots, rng)
bob.rng.destroy(rng)
table(factor(results, levels = 0:(bob.state.dim(state)-1))) / num_shots
}
# ============================================================================
# GGPLOT2 VISUALIZATION FUNCTIONS
# ============================================================================
#' Plot entropy evolution from lattice or quantum simulation
#' @param data Data frame with columns 'step' or 'time' and 'entropy'
#' @param title Plot title
#' @param xlab X-axis label
#' @param ylab Y-axis label
#' @param color Line color
#' @param size Line size
#' @param theme_ggplot ggplot2 theme to use
#' @