aboutsummaryrefslogtreecommitdiff
path: root/src/core/quantum_components.c
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-18 12:25:32 +0200
committerhachem <im@hachem.wtf>2026-09-18 12:25:32 +0200
commit17598056a69a14e0390a07251d383f413ded9eea (patch)
tree79cf23ea99072f065407da3e0b92ee03f8972695 /src/core/quantum_components.c
parentee14ad272e68d9363202d7f668e0b20302827209 (diff)
feat: add matrix, vector, and circuit display + fmt
Diffstat (limited to 'src/core/quantum_components.c')
-rw-r--r--src/core/quantum_components.c318
1 files changed, 159 insertions, 159 deletions
diff --git a/src/core/quantum_components.c b/src/core/quantum_components.c
index a62a911..5870906 100644
--- a/src/core/quantum_components.c
+++ b/src/core/quantum_components.c
@@ -6,262 +6,262 @@
struct PsiVector psi_new_state_0(void)
{
- return psi_column_vector(psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0));
+ return psi_column_vector(psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0));
}
struct PsiVector psi_new_state_1(void)
{
- return psi_column_vector(psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0));
+ return psi_column_vector(psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0));
}
struct PsiQuantumGate psi_new_quantum_gate(const char* name, struct PsiMatrix matrix,
size_t num_qubits)
{
- size_t expected_dim = (size_t)1 << num_qubits;
- assert(matrix.rows == expected_dim);
- assert(matrix.cols == expected_dim);
+ size_t expected_dim = (size_t)1 << num_qubits;
+ assert(matrix.rows == expected_dim);
+ assert(matrix.cols == expected_dim);
- return (struct PsiQuantumGate){
- name,
- matrix,
- num_qubits,
- };
+ return (struct PsiQuantumGate){
+ name,
+ matrix,
+ num_qubits,
+ };
}
struct PsiQuantumGate psi_new_quantum_gate_from_matrix(const char* name, struct PsiMatrix matrix)
{
- assert(matrix.rows == matrix.cols);
+ assert(matrix.rows == matrix.cols);
- size_t dim = matrix.rows;
- assert(dim > 0 && (dim & (dim - 1)) == 0);
+ size_t dim = matrix.rows;
+ assert(dim > 0 && (dim & (dim - 1)) == 0);
- size_t num_qubits = 0;
- while (((size_t)1 << num_qubits) < dim)
- num_qubits++;
+ size_t num_qubits = 0;
+ while (((size_t)1 << num_qubits) < dim)
+ num_qubits++;
- return (struct PsiQuantumGate){
- name,
- matrix,
- num_qubits,
- };
+ return (struct PsiQuantumGate){
+ name,
+ matrix,
+ num_qubits,
+ };
}
void psi_free_quantum_gate(struct PsiQuantumGate* gate)
{
- psi_free_matrix(&gate->matrix);
+ psi_free_matrix(&gate->matrix);
}
struct PsiQuantumBit psi_new_quantum_bit(const char* name, struct PsiVector state)
{
- return (struct PsiQuantumBit){
- name,
- state,
- };
+ return (struct PsiQuantumBit){
+ name,
+ state,
+ };
}
void psi_free_quantum_bit(struct PsiQuantumBit* bit)
{
- psi_free_vector(&bit->state);
+ psi_free_vector(&bit->state);
}
static void update_register(struct PsiQuantumRegister* reg)
{
- psi_free_vector(&reg->state_vector);
+ psi_free_vector(&reg->state_vector);
- if (reg->num_qubits == 0)
- {
- reg->state_vector = psi_new_vector(0, PSI_COLUMN_VECTOR);
- return;
- }
+ 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;
- }
+ 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);
+ 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);
+ 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());
+ 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,
- };
+ struct PsiQuantumRegister reg = {
+ name,
+ psi_new_vector(0, PSI_COLUMN_VECTOR),
+ qubits,
+ count,
+ };
- update_register(&reg);
- return reg;
+ 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);
+ 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));
+ 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,
- };
+ struct PsiQuantumRegister reg = {
+ name,
+ psi_new_vector(0, PSI_COLUMN_VECTOR),
+ qubits,
+ count,
+ };
- update_register(&reg);
- return reg;
+ 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]);
+ 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);
+ 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;
+ for (size_t i = 0; i < count; i++)
+ if (targets[i] == value)
+ return true;
- return false;
+ 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;
+ size_t n = reg.num_qubits;
+ size_t g = gate.num_qubits;
- bool has_result = false;
- struct PsiMatrix result = { 0 };
+ 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;
+ 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);
+ struct PsiMatrix part =
+ i == start_idx ? psi_clone_matrix(gate.matrix) : psi_identity_matrix(2);
- if (!has_result)
- {
- result = part;
- has_result = true;
- continue;
- }
+ 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;
- }
+ 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);
+ if (!has_result)
+ return psi_identity_matrix((size_t)1 << n);
- return result;
+ 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;
+ 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;
- }
+ 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 && g == n)
+ return psi_clone_matrix(gate.matrix);
- if (contiguous)
- return build_contiguous_operator(reg, gate, targets[0]);
+ if (contiguous)
+ return build_contiguous_operator(reg, gate, targets[0]);
- struct PsiMatrix result = psi_new_matrix(dim, dim);
+ 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 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);
- }
+ 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;
+ 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;
- }
- }
+ 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);
- }
+ if (non_target_match)
+ result.data[row * result.cols + col] =
+ psi_get_matrix(gate.matrix, target_row_bits, target_col_bits);
+ }
- return result;
+ 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;
+ 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);
+ 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]);
+ 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);
+ 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;
+ psi_free_vector(&reg->state_vector);
+ psi_free_matrix(&full_operator);
+ reg->state_vector = new_state;
}