diff options
| author | hachem <im@hachem.wtf> | 2026-09-06 19:12:05 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-06 19:12:05 +0200 |
| commit | b2a5d3d5a2faac05b1b722d96d11d9b191c7cffc (patch) | |
| tree | ac7712ead7cea6e9b90de62b2520d04d98ce6c42 /src/core | |
| parent | ab08fa6065b5b08627b51203eb92ef65ed7b5ea2 (diff) | |
add: quantum bit and register with gate application
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/quantum_components.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/src/core/quantum_components.c b/src/core/quantum_components.c index 3b9eef5..31d60dc 100644 --- a/src/core/quantum_components.c +++ b/src/core/quantum_components.c @@ -1,6 +1,8 @@ #include "core/quantum_components.h" #include <assert.h> +#include <stdbool.h> +#include <stdlib.h> struct PsiVector psi_new_state_0(void) { @@ -49,3 +51,215 @@ void psi_free_quantum_gate(struct PsiQuantumGate *gate) { psi_free_matrix(&gate->matrix); } + +struct PsiQuantumBit psi_new_quantum_bit(const char *name, struct PsiVector state) +{ + return (struct PsiQuantumBit) + { + name, + state, + }; +} + +void psi_free_quantum_bit(struct PsiQuantumBit *bit) +{ + psi_free_vector(&bit->state); +} + +static void update_register(struct PsiQuantumRegister *reg) +{ + psi_free_vector(®->state_vector); + + if (reg->num_qubits == 0) + { + reg->state_vector = psi_new_vector(0, PSI_COLUMN_VECTOR); + return; + } + + struct PsiMatrix result = psi_matrix_from_vector(reg->qubits[0].state); + for (size_t i = 1; i < reg->num_qubits; i++) + { + struct PsiMatrix part = psi_matrix_from_vector(reg->qubits[i].state); + struct PsiMatrix next = psi_kronecker_matrix(result, part); + psi_free_matrix(&result); + psi_free_matrix(&part); + result = next; + } + + reg->state_vector = psi_vector_from_matrix(result, PSI_COLUMN_VECTOR); + psi_free_matrix(&result); +} + +struct PsiQuantumRegister psi_new_quantum_register(const char *name, const char **names, size_t count) +{ + struct PsiQuantumBit *qubits = malloc(count * sizeof(struct PsiQuantumBit)); + assert(qubits != NULL || count == 0); + + for (size_t i = 0; i < count; i++) + qubits[i] = psi_new_quantum_bit(names[i], psi_new_state_0()); + + struct PsiQuantumRegister reg = + { + name, + psi_new_vector(0, PSI_COLUMN_VECTOR), + qubits, + count, + }; + + update_register(®); + return reg; +} + +struct PsiQuantumRegister psi_new_quantum_register_from(const char *name, const struct PsiQuantumBit *bits, size_t count) +{ + struct PsiQuantumBit *qubits = malloc(count * sizeof(struct PsiQuantumBit)); + assert(qubits != NULL || count == 0); + + for (size_t i = 0; i < count; i++) + qubits[i] = psi_new_quantum_bit(bits[i].name, psi_clone_vector(bits[i].state)); + + struct PsiQuantumRegister reg = + { + name, + psi_new_vector(0, PSI_COLUMN_VECTOR), + qubits, + count, + }; + + update_register(®); + return reg; +} + +void psi_free_quantum_register(struct PsiQuantumRegister *reg) +{ + for (size_t i = 0; i < reg->num_qubits; i++) + psi_free_quantum_bit(®->qubits[i]); + + free(reg->qubits); + reg->qubits = NULL; + reg->num_qubits = 0; + psi_free_vector(®->state_vector); +} + +static bool targets_contain(const size_t *targets, size_t count, size_t value) +{ + for (size_t i = 0; i < count; i++) + if (targets[i] == value) + return true; + + return false; +} + +static struct PsiMatrix build_contiguous_operator(struct PsiQuantumRegister reg, struct PsiQuantumGate gate, size_t start_idx) +{ + size_t n = reg.num_qubits; + size_t g = gate.num_qubits; + + bool has_result = false; + struct PsiMatrix result = { 0 }; + + for (size_t i = 0; i < n; i++) + { + if (i > start_idx && i < start_idx + g) + continue; + + struct PsiMatrix part = i == start_idx + ? psi_clone_matrix(gate.matrix) + : psi_identity_matrix(2); + + if (!has_result) + { + result = part; + has_result = true; + continue; + } + + struct PsiMatrix next = psi_kronecker_matrix(result, part); + psi_free_matrix(&result); + psi_free_matrix(&part); + result = next; + } + + if (!has_result) + return psi_identity_matrix((size_t)1 << n); + + return result; +} + +static struct PsiMatrix build_full_operator(struct PsiQuantumRegister reg, struct PsiQuantumGate gate, const size_t *targets, size_t target_count) +{ + size_t n = reg.num_qubits; + size_t g = gate.num_qubits; + size_t dim = (size_t)1 << n; + + bool contiguous = true; + for (size_t i = 1; i < target_count; i++) + if (targets[i] != targets[i - 1] + 1) + { + contiguous = false; + break; + } + + if (contiguous && g == n) + return psi_clone_matrix(gate.matrix); + + if (contiguous) + return build_contiguous_operator(reg, gate, targets[0]); + + struct PsiMatrix result = psi_new_matrix(dim, dim); + + for (size_t col = 0; col < dim; col++) + for (size_t row = 0; row < dim; row++) + { + size_t target_row_bits = 0; + size_t target_col_bits = 0; + + for (size_t i = 0; i < target_count; i++) + { + size_t qubit_pos = n - 1 - targets[i]; + if ((row >> qubit_pos) & 1) + target_row_bits |= (size_t)1 << (g - 1 - i); + if ((col >> qubit_pos) & 1) + target_col_bits |= (size_t)1 << (g - 1 - i); + } + + bool non_target_match = true; + for (size_t q = 0; q < n; q++) + { + if (targets_contain(targets, target_count, q)) + continue; + + size_t qubit_pos = n - 1 - q; + if (((row >> qubit_pos) & 1) != ((col >> qubit_pos) & 1)) + { + non_target_match = false; + break; + } + } + + if (non_target_match) + result.data[row * result.cols + col] = psi_get_matrix(gate.matrix, target_row_bits, target_col_bits); + } + + return result; +} + +void psi_apply_gate(struct PsiQuantumRegister *reg, struct PsiQuantumGate gate, const size_t *targets, size_t target_count) +{ + size_t n = reg->num_qubits; + + assert(gate.num_qubits == target_count); + for (size_t i = 0; i < target_count; i++) + assert(targets[i] < n); + + for (size_t i = 0; i < target_count; i++) + for (size_t j = i + 1; j < target_count; j++) + assert(targets[i] != targets[j]); + + struct PsiMatrix full_operator = build_full_operator(*reg, gate, targets, target_count); + struct PsiVector new_state = psi_mul_vector_matrix(reg->state_vector, full_operator); + + psi_free_vector(®->state_vector); + psi_free_matrix(&full_operator); + reg->state_vector = new_state; +} |
