aboutsummaryrefslogtreecommitdiff
path: root/src/core/quantum_components.c
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-06 19:12:05 +0200
committerhachem <im@hachem.wtf>2026-09-06 19:12:05 +0200
commitb2a5d3d5a2faac05b1b722d96d11d9b191c7cffc (patch)
treeac7712ead7cea6e9b90de62b2520d04d98ce6c42 /src/core/quantum_components.c
parentab08fa6065b5b08627b51203eb92ef65ed7b5ea2 (diff)
add: quantum bit and register with gate application
Diffstat (limited to 'src/core/quantum_components.c')
-rw-r--r--src/core/quantum_components.c214
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(&reg->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(&reg);
+ 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(&reg);
+ return reg;
+}
+
+void psi_free_quantum_register(struct PsiQuantumRegister *reg)
+{
+ for (size_t i = 0; i < reg->num_qubits; i++)
+ psi_free_quantum_bit(&reg->qubits[i]);
+
+ free(reg->qubits);
+ reg->qubits = NULL;
+ reg->num_qubits = 0;
+ psi_free_vector(&reg->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(&reg->state_vector);
+ psi_free_matrix(&full_operator);
+ reg->state_vector = new_state;
+}