From ee14ad272e68d9363202d7f668e0b20302827209 Mon Sep 17 00:00:00 2001 From: hachem Date: Mon, 14 Sep 2026 12:20:52 +0200 Subject: feat: simd + testing + formatting --- src/core/circuit.c | 194 ++++++++++++++++++++++++++------------ src/core/classical_components.c | 15 ++- src/core/custom_gate.c | 21 +++-- src/core/gates.c | 92 ++++++++---------- src/core/kernel.c | 116 ++++++++++++----------- src/core/noise.c | 201 +++++++++++++++++++++++----------------- src/core/quantum_components.c | 60 ++++++------ src/core/runtime.c | 186 +++++++++++++++++++++++++++---------- 8 files changed, 539 insertions(+), 346 deletions(-) (limited to 'src/core') diff --git a/src/core/circuit.c b/src/core/circuit.c index 1869ee6..8009db5 100644 --- a/src/core/circuit.c +++ b/src/core/circuit.c @@ -4,7 +4,7 @@ #include #include -const char *psi_gate_op_name(struct PsiGateOp op) +const char* psi_gate_op_name(struct PsiGateOp op) { switch (op.kind) { @@ -41,7 +41,7 @@ const char *psi_gate_op_name(struct PsiGateOp op) return "?"; } -const size_t *psi_gate_op_quantum_targets(const struct PsiGateOp *op, size_t *out_count) +const size_t* psi_gate_op_quantum_targets(const struct PsiGateOp* op, size_t* out_count) { if (op->kind == PSI_GATE_CUSTOM) { @@ -53,7 +53,7 @@ const size_t *psi_gate_op_quantum_targets(const struct PsiGateOp *op, size_t *ou return op->qubits; } -const size_t *psi_gate_op_classical_targets(const struct PsiGateOp *op, size_t *out_count) +const size_t* psi_gate_op_classical_targets(const struct PsiGateOp* op, size_t* out_count) { if (op->kind == PSI_GATE_MEASURE) { @@ -93,10 +93,8 @@ bool psi_gate_op_is_non_clifford(struct PsiGateOp op) case PSI_GATE_CRX: case PSI_GATE_CRY: case PSI_GATE_CRZ: - case PSI_GATE_CP: - return true; - default: - return false; + case PSI_GATE_CP: return true; + default: return false; } } @@ -105,7 +103,8 @@ struct PsiQuantumCircuit psi_new_quantum_circuit(size_t num_qubits) return psi_new_quantum_circuit_with_classical(num_qubits, 0); } -struct PsiQuantumCircuit psi_new_quantum_circuit_with_classical(size_t num_qubits, size_t num_classical) +struct PsiQuantumCircuit psi_new_quantum_circuit_with_classical(size_t num_qubits, + size_t num_classical) { struct PsiQuantumCircuit c; c.num_qubits = num_qubits; @@ -119,11 +118,11 @@ struct PsiQuantumCircuit psi_new_quantum_circuit_with_classical(size_t num_qubit return c; } -static void free_operations(struct PsiQuantumCircuit *c) +static void free_operations(struct PsiQuantumCircuit* c) { for (size_t i = 0; i < c->operation_count; i++) { - struct PsiGateOp *op = &c->operations[i]; + struct PsiGateOp* op = &c->operations[i]; if (op->kind != PSI_GATE_CUSTOM) continue; @@ -133,7 +132,7 @@ static void free_operations(struct PsiQuantumCircuit *c) } } -void psi_free_quantum_circuit(struct PsiQuantumCircuit *c) +void psi_free_quantum_circuit(struct PsiQuantumCircuit* c) { free_operations(c); free(c->operations); @@ -144,7 +143,7 @@ void psi_free_quantum_circuit(struct PsiQuantumCircuit *c) c->is_computed = false; } -void psi_reset_circuit(struct PsiQuantumCircuit *c) +void psi_reset_circuit(struct PsiQuantumCircuit* c) { free_operations(c); c->operation_count = 0; @@ -153,7 +152,7 @@ void psi_reset_circuit(struct PsiQuantumCircuit *c) c->is_computed = false; } -static struct PsiGateOp *append_op(struct PsiQuantumCircuit *c) +static struct PsiGateOp* append_op(struct PsiQuantumCircuit* c) { if (c->operation_count == c->operation_capacity) { @@ -163,24 +162,25 @@ static struct PsiGateOp *append_op(struct PsiQuantumCircuit *c) c->operation_capacity = new_capacity; } - struct PsiGateOp *op = &c->operations[c->operation_count++]; + struct PsiGateOp* op = &c->operations[c->operation_count++]; memset(op, 0, sizeof(*op)); c->is_computed = false; return op; } -static void push_1q(struct PsiQuantumCircuit *c, enum PsiGateKind kind, size_t target) +static void push_1q(struct PsiQuantumCircuit* c, enum PsiGateKind kind, size_t target) { - struct PsiGateOp *op = append_op(c); + struct PsiGateOp* op = append_op(c); op->kind = kind; op->qubits[0] = target; op->qubit_count = 1; } -static void push_1q_1p(struct PsiQuantumCircuit *c, enum PsiGateKind kind, size_t target, double theta) +static void push_1q_1p(struct PsiQuantumCircuit* c, enum PsiGateKind kind, size_t target, + double theta) { - struct PsiGateOp *op = append_op(c); + struct PsiGateOp* op = append_op(c); op->kind = kind; op->qubits[0] = target; op->qubit_count = 1; @@ -188,18 +188,19 @@ static void push_1q_1p(struct PsiQuantumCircuit *c, enum PsiGateKind kind, size_ op->param_count = 1; } -static void push_2q(struct PsiQuantumCircuit *c, enum PsiGateKind kind, size_t a, size_t b) +static void push_2q(struct PsiQuantumCircuit* c, enum PsiGateKind kind, size_t a, size_t b) { - struct PsiGateOp *op = append_op(c); + struct PsiGateOp* op = append_op(c); op->kind = kind; op->qubits[0] = a; op->qubits[1] = b; op->qubit_count = 2; } -static void push_2q_1p(struct PsiQuantumCircuit *c, enum PsiGateKind kind, size_t control, size_t target, double theta) +static void push_2q_1p(struct PsiQuantumCircuit* c, enum PsiGateKind kind, size_t control, + size_t target, double theta) { - struct PsiGateOp *op = append_op(c); + struct PsiGateOp* op = append_op(c); op->kind = kind; op->qubits[0] = control; op->qubits[1] = target; @@ -208,9 +209,10 @@ static void push_2q_1p(struct PsiQuantumCircuit *c, enum PsiGateKind kind, size_ op->param_count = 1; } -static void push_3q(struct PsiQuantumCircuit *c, enum PsiGateKind kind, size_t a, size_t b, size_t d) +static void push_3q(struct PsiQuantumCircuit* c, enum PsiGateKind kind, size_t a, size_t b, + size_t d) { - struct PsiGateOp *op = append_op(c); + struct PsiGateOp* op = append_op(c); op->kind = kind; op->qubits[0] = a; op->qubits[1] = b; @@ -218,26 +220,71 @@ static void push_3q(struct PsiQuantumCircuit *c, enum PsiGateKind kind, size_t a op->qubit_count = 3; } -void psi_apply_h(struct PsiQuantumCircuit *c, size_t target) { push_1q(c, PSI_GATE_H, target); } -void psi_apply_x(struct PsiQuantumCircuit *c, size_t target) { push_1q(c, PSI_GATE_X, target); } -void psi_apply_y(struct PsiQuantumCircuit *c, size_t target) { push_1q(c, PSI_GATE_Y, target); } -void psi_apply_z(struct PsiQuantumCircuit *c, size_t target) { push_1q(c, PSI_GATE_Z, target); } -void psi_apply_s(struct PsiQuantumCircuit *c, size_t target) { push_1q(c, PSI_GATE_S, target); } -void psi_apply_t(struct PsiQuantumCircuit *c, size_t target) { push_1q(c, PSI_GATE_T, target); } -void psi_apply_sdg(struct PsiQuantumCircuit *c, size_t target) { push_1q(c, PSI_GATE_SDG, target); } -void psi_apply_tdg(struct PsiQuantumCircuit *c, size_t target) { push_1q(c, PSI_GATE_TDG, target); } -void psi_apply_sx(struct PsiQuantumCircuit *c, size_t target) { push_1q(c, PSI_GATE_SX, target); } -void psi_apply_sxdg(struct PsiQuantumCircuit *c, size_t target) { push_1q(c, PSI_GATE_SXDG, target); } +void psi_apply_h(struct PsiQuantumCircuit* c, size_t target) +{ + push_1q(c, PSI_GATE_H, target); +} +void psi_apply_x(struct PsiQuantumCircuit* c, size_t target) +{ + push_1q(c, PSI_GATE_X, target); +} +void psi_apply_y(struct PsiQuantumCircuit* c, size_t target) +{ + push_1q(c, PSI_GATE_Y, target); +} +void psi_apply_z(struct PsiQuantumCircuit* c, size_t target) +{ + push_1q(c, PSI_GATE_Z, target); +} +void psi_apply_s(struct PsiQuantumCircuit* c, size_t target) +{ + push_1q(c, PSI_GATE_S, target); +} +void psi_apply_t(struct PsiQuantumCircuit* c, size_t target) +{ + push_1q(c, PSI_GATE_T, target); +} +void psi_apply_sdg(struct PsiQuantumCircuit* c, size_t target) +{ + push_1q(c, PSI_GATE_SDG, target); +} +void psi_apply_tdg(struct PsiQuantumCircuit* c, size_t target) +{ + push_1q(c, PSI_GATE_TDG, target); +} +void psi_apply_sx(struct PsiQuantumCircuit* c, size_t target) +{ + push_1q(c, PSI_GATE_SX, target); +} +void psi_apply_sxdg(struct PsiQuantumCircuit* c, size_t target) +{ + push_1q(c, PSI_GATE_SXDG, target); +} -void psi_apply_rx(struct PsiQuantumCircuit *c, size_t target, double theta) { push_1q_1p(c, PSI_GATE_RX, target, theta); } -void psi_apply_ry(struct PsiQuantumCircuit *c, size_t target, double theta) { push_1q_1p(c, PSI_GATE_RY, target, theta); } -void psi_apply_rz(struct PsiQuantumCircuit *c, size_t target, double theta) { push_1q_1p(c, PSI_GATE_RZ, target, theta); } -void psi_apply_p(struct PsiQuantumCircuit *c, size_t target, double theta) { push_1q_1p(c, PSI_GATE_P, target, theta); } -void psi_apply_u1(struct PsiQuantumCircuit *c, size_t target, double lambda) { push_1q_1p(c, PSI_GATE_U1, target, lambda); } +void psi_apply_rx(struct PsiQuantumCircuit* c, size_t target, double theta) +{ + push_1q_1p(c, PSI_GATE_RX, target, theta); +} +void psi_apply_ry(struct PsiQuantumCircuit* c, size_t target, double theta) +{ + push_1q_1p(c, PSI_GATE_RY, target, theta); +} +void psi_apply_rz(struct PsiQuantumCircuit* c, size_t target, double theta) +{ + push_1q_1p(c, PSI_GATE_RZ, target, theta); +} +void psi_apply_p(struct PsiQuantumCircuit* c, size_t target, double theta) +{ + push_1q_1p(c, PSI_GATE_P, target, theta); +} +void psi_apply_u1(struct PsiQuantumCircuit* c, size_t target, double lambda) +{ + push_1q_1p(c, PSI_GATE_U1, target, lambda); +} -void psi_apply_u2(struct PsiQuantumCircuit *c, size_t target, double phi, double lambda) +void psi_apply_u2(struct PsiQuantumCircuit* c, size_t target, double phi, double lambda) { - struct PsiGateOp *op = append_op(c); + struct PsiGateOp* op = append_op(c); op->kind = PSI_GATE_U2; op->qubits[0] = target; op->qubit_count = 1; @@ -246,9 +293,10 @@ void psi_apply_u2(struct PsiQuantumCircuit *c, size_t target, double phi, double op->param_count = 2; } -void psi_apply_u3(struct PsiQuantumCircuit *c, size_t target, double theta, double phi, double lambda) +void psi_apply_u3(struct PsiQuantumCircuit* c, size_t target, double theta, double phi, + double lambda) { - struct PsiGateOp *op = append_op(c); + struct PsiGateOp* op = append_op(c); op->kind = PSI_GATE_U3; op->qubits[0] = target; op->qubit_count = 1; @@ -258,47 +306,75 @@ void psi_apply_u3(struct PsiQuantumCircuit *c, size_t target, double theta, doub op->param_count = 3; } -void psi_apply_cnot(struct PsiQuantumCircuit *c, size_t control, size_t target) { push_2q(c, PSI_GATE_CNOT, control, target); } -void psi_apply_cz(struct PsiQuantumCircuit *c, size_t control, size_t target) { push_2q(c, PSI_GATE_CZ, control, target); } -void psi_apply_swap(struct PsiQuantumCircuit *c, size_t qubit1, size_t qubit2) { push_2q(c, PSI_GATE_SWAP, qubit1, qubit2); } -void psi_apply_crx(struct PsiQuantumCircuit *c, size_t control, size_t target, double theta) { push_2q_1p(c, PSI_GATE_CRX, control, target, theta); } -void psi_apply_cry(struct PsiQuantumCircuit *c, size_t control, size_t target, double theta) { push_2q_1p(c, PSI_GATE_CRY, control, target, theta); } -void psi_apply_crz(struct PsiQuantumCircuit *c, size_t control, size_t target, double theta) { push_2q_1p(c, PSI_GATE_CRZ, control, target, theta); } -void psi_apply_cp(struct PsiQuantumCircuit *c, size_t control, size_t target, double theta) { push_2q_1p(c, PSI_GATE_CP, control, target, theta); } +void psi_apply_cnot(struct PsiQuantumCircuit* c, size_t control, size_t target) +{ + push_2q(c, PSI_GATE_CNOT, control, target); +} +void psi_apply_cz(struct PsiQuantumCircuit* c, size_t control, size_t target) +{ + push_2q(c, PSI_GATE_CZ, control, target); +} +void psi_apply_swap(struct PsiQuantumCircuit* c, size_t qubit1, size_t qubit2) +{ + push_2q(c, PSI_GATE_SWAP, qubit1, qubit2); +} +void psi_apply_crx(struct PsiQuantumCircuit* c, size_t control, size_t target, double theta) +{ + push_2q_1p(c, PSI_GATE_CRX, control, target, theta); +} +void psi_apply_cry(struct PsiQuantumCircuit* c, size_t control, size_t target, double theta) +{ + push_2q_1p(c, PSI_GATE_CRY, control, target, theta); +} +void psi_apply_crz(struct PsiQuantumCircuit* c, size_t control, size_t target, double theta) +{ + push_2q_1p(c, PSI_GATE_CRZ, control, target, theta); +} +void psi_apply_cp(struct PsiQuantumCircuit* c, size_t control, size_t target, double theta) +{ + push_2q_1p(c, PSI_GATE_CP, control, target, theta); +} -void psi_apply_ccnot(struct PsiQuantumCircuit *c, size_t control1, size_t control2, size_t target) { push_3q(c, PSI_GATE_CCNOT, control1, control2, target); } -void psi_apply_cswap(struct PsiQuantumCircuit *c, size_t control, size_t target1, size_t target2) { push_3q(c, PSI_GATE_CSWAP, control, target1, target2); } +void psi_apply_ccnot(struct PsiQuantumCircuit* c, size_t control1, size_t control2, size_t target) +{ + push_3q(c, PSI_GATE_CCNOT, control1, control2, target); +} +void psi_apply_cswap(struct PsiQuantumCircuit* c, size_t control, size_t target1, size_t target2) +{ + push_3q(c, PSI_GATE_CSWAP, control, target1, target2); +} -void psi_measure(struct PsiQuantumCircuit *c, size_t qubit, size_t classical) +void psi_measure(struct PsiQuantumCircuit* c, size_t qubit, size_t classical) { if (classical >= c->num_classical) c->num_classical = classical + 1; - struct PsiGateOp *op = append_op(c); + struct PsiGateOp* op = append_op(c); op->kind = PSI_GATE_MEASURE; op->qubits[0] = qubit; op->qubit_count = 1; op->classical = classical; } -void psi_measure_all(struct PsiQuantumCircuit *c) +void psi_measure_all(struct PsiQuantumCircuit* c) { for (size_t i = 0; i < c->num_qubits; i++) psi_measure(c, i, i); } -void psi_apply_custom(struct PsiQuantumCircuit *c, struct PsiCustomGate gate, const size_t *targets, size_t count) +void psi_apply_custom(struct PsiQuantumCircuit* c, struct PsiCustomGate gate, const size_t* targets, + size_t count) { - struct PsiCustomGate *owned = malloc(sizeof(struct PsiCustomGate)); + struct PsiCustomGate* owned = malloc(sizeof(struct PsiCustomGate)); assert(owned != NULL); *owned = gate; - size_t *owned_targets = malloc(count * sizeof(size_t)); + size_t* owned_targets = malloc(count * sizeof(size_t)); assert(owned_targets != NULL || count == 0); if (count > 0) memcpy(owned_targets, targets, count * sizeof(size_t)); - struct PsiGateOp *op = append_op(c); + struct PsiGateOp* op = append_op(c); op->kind = PSI_GATE_CUSTOM; op->custom = owned; op->custom_targets = owned_targets; diff --git a/src/core/classical_components.c b/src/core/classical_components.c index 836784c..3ffeb88 100644 --- a/src/core/classical_components.c +++ b/src/core/classical_components.c @@ -3,32 +3,31 @@ #include #include -struct PsiClassicalBit psi_new_classical_bit(const char *name, bool state) +struct PsiClassicalBit psi_new_classical_bit(const char* name, bool state) { - return (struct PsiClassicalBit) - { + return (struct PsiClassicalBit){ name, state, }; } -struct PsiClassicalRegister psi_new_classical_register(const char *name, const char **names, size_t count) +struct PsiClassicalRegister psi_new_classical_register(const char* name, const char** names, + size_t count) { - struct PsiClassicalBit *bits = malloc(count * sizeof(struct PsiClassicalBit)); + struct PsiClassicalBit* bits = malloc(count * sizeof(struct PsiClassicalBit)); assert(bits != NULL || count == 0); for (size_t i = 0; i < count; i++) bits[i] = psi_new_classical_bit(names[i], false); - return (struct PsiClassicalRegister) - { + return (struct PsiClassicalRegister){ name, bits, count, }; } -void psi_free_classical_register(struct PsiClassicalRegister *reg) +void psi_free_classical_register(struct PsiClassicalRegister* reg) { free(reg->bits); reg->bits = NULL; diff --git a/src/core/custom_gate.c b/src/core/custom_gate.c index 3b3a7e2..dd41635 100644 --- a/src/core/custom_gate.c +++ b/src/core/custom_gate.c @@ -7,7 +7,7 @@ #include "core/gates.h" -struct PsiCustomGate psi_new_custom_gate_from_matrix(const char *name, struct PsiMatrix matrix) +struct PsiCustomGate psi_new_custom_gate_from_matrix(const char* name, struct PsiMatrix matrix) { assert(matrix.rows == matrix.cols); @@ -27,9 +27,11 @@ struct PsiCustomGate psi_new_custom_gate_from_matrix(const char *name, struct Ps return gate; } -struct PsiCustomGate psi_new_custom_gate_from_composite(const char *name, size_t num_qubits, const struct PsiCompositeGateOp *ops, size_t op_count) +struct PsiCustomGate psi_new_custom_gate_from_composite(const char* name, size_t num_qubits, + const struct PsiCompositeGateOp* ops, + size_t op_count) { - struct PsiCompositeGateOp *owned = malloc(op_count * sizeof(struct PsiCompositeGateOp)); + struct PsiCompositeGateOp* owned = malloc(op_count * sizeof(struct PsiCompositeGateOp)); assert(owned != NULL || op_count == 0); if (op_count > 0) @@ -45,7 +47,7 @@ struct PsiCustomGate psi_new_custom_gate_from_composite(const char *name, size_t return gate; } -void psi_free_custom_gate(struct PsiCustomGate *gate) +void psi_free_custom_gate(struct PsiCustomGate* gate) { if (gate->kind == PSI_CUSTOM_GATE_MATRIX) { @@ -78,7 +80,7 @@ static struct PsiQuantumGate op_gate(enum PsiCompositeOp op) return psi_identity_gate(); } -static bool find_target(const size_t *targets, size_t count, size_t q, size_t *pos) +static bool find_target(const size_t* targets, size_t count, size_t q, size_t* pos) { for (size_t i = 0; i < count; i++) if (targets[i] == q) @@ -90,7 +92,8 @@ static bool find_target(const size_t *targets, size_t count, size_t q, size_t *p return false; } -static struct PsiMatrix build_full_operator(struct PsiMatrix gate_matrix, const size_t *targets, size_t num_gate_qubits, size_t total_qubits) +static struct PsiMatrix build_full_operator(struct PsiMatrix gate_matrix, const size_t* targets, + size_t num_gate_qubits, size_t total_qubits) { size_t dim = (size_t)1 << total_qubits; size_t gate_dim = gate_matrix.rows; @@ -139,7 +142,8 @@ static struct PsiMatrix compute_composite_matrix(struct PsiCustomGate gate) struct PsiCompositeGateOp step = gate.definition.composite.ops[i]; struct PsiQuantumGate g = op_gate(step.op); - struct PsiMatrix full = build_full_operator(g.matrix, step.targets, step.target_count, gate.num_qubits); + struct PsiMatrix full = + build_full_operator(g.matrix, step.targets, step.target_count, gate.num_qubits); struct PsiMatrix next = psi_dot_matrix(full, result); psi_free_matrix(&full); @@ -154,7 +158,8 @@ static struct PsiMatrix compute_composite_matrix(struct PsiCustomGate gate) struct PsiQuantumGate psi_to_quantum_gate(struct PsiCustomGate gate) { if (gate.kind == PSI_CUSTOM_GATE_MATRIX) - return psi_new_quantum_gate(gate.name, psi_clone_matrix(gate.definition.matrix), gate.num_qubits); + return psi_new_quantum_gate(gate.name, psi_clone_matrix(gate.definition.matrix), + gate.num_qubits); return psi_new_quantum_gate(gate.name, compute_composite_matrix(gate), gate.num_qubits); } diff --git a/src/core/gates.c b/src/core/gates.c index 0eb2997..51605c9 100644 --- a/src/core/gates.c +++ b/src/core/gates.c @@ -9,9 +9,8 @@ struct PsiMatrix psi_rx_matrix(double theta) double cos_h = cos(theta / 2.0); double sin_h = sin(theta / 2.0); - return psi_matrix(2, 2, - psi_new_complex(cos_h, 0.0), psi_new_complex(0.0, -sin_h), - psi_new_complex(0.0, -sin_h), psi_new_complex(cos_h, 0.0)); + return psi_matrix(2, 2, psi_new_complex(cos_h, 0.0), psi_new_complex(0.0, -sin_h), + psi_new_complex(0.0, -sin_h), psi_new_complex(cos_h, 0.0)); } struct PsiMatrix psi_ry_matrix(double theta) @@ -19,25 +18,22 @@ struct PsiMatrix psi_ry_matrix(double theta) double cos_h = cos(theta / 2.0); double sin_h = sin(theta / 2.0); - return psi_matrix(2, 2, - psi_new_complex(cos_h, 0.0), psi_new_complex(-sin_h, 0.0), - psi_new_complex(sin_h, 0.0), psi_new_complex(cos_h, 0.0)); + return psi_matrix(2, 2, psi_new_complex(cos_h, 0.0), psi_new_complex(-sin_h, 0.0), + psi_new_complex(sin_h, 0.0), psi_new_complex(cos_h, 0.0)); } struct PsiMatrix psi_rz_matrix(double theta) { double half = theta / 2.0; - return psi_matrix(2, 2, - psi_new_complex(cos(half), -sin(half)), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(cos(half), sin(half))); + return psi_matrix(2, 2, psi_new_complex(cos(half), -sin(half)), psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(cos(half), sin(half))); } struct PsiMatrix psi_p_matrix(double theta) { - return psi_matrix(2, 2, - psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(cos(theta), sin(theta))); + return psi_matrix(2, 2, psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(cos(theta), sin(theta))); } struct PsiMatrix psi_u1_matrix(double lambda) @@ -47,11 +43,11 @@ struct PsiMatrix psi_u1_matrix(double lambda) struct PsiMatrix psi_u2_matrix(double phi, double lambda) { - return psi_matrix(2, 2, - psi_new_complex(INV_SQRT_2, 0.0), - psi_new_complex(-INV_SQRT_2 * cos(lambda), -INV_SQRT_2 * sin(lambda)), - psi_new_complex(INV_SQRT_2 * cos(phi), INV_SQRT_2 * sin(phi)), - psi_new_complex(cos(phi + lambda) * INV_SQRT_2, sin(phi + lambda) * INV_SQRT_2)); + return psi_matrix( + 2, 2, psi_new_complex(INV_SQRT_2, 0.0), + psi_new_complex(-INV_SQRT_2 * cos(lambda), -INV_SQRT_2 * sin(lambda)), + psi_new_complex(INV_SQRT_2 * cos(phi), INV_SQRT_2 * sin(phi)), + psi_new_complex(cos(phi + lambda) * INV_SQRT_2, sin(phi + lambda) * INV_SQRT_2)); } struct PsiMatrix psi_u3_matrix(double theta, double phi, double lambda) @@ -59,11 +55,10 @@ struct PsiMatrix psi_u3_matrix(double theta, double phi, double lambda) double cos_h = cos(theta / 2.0); double sin_h = sin(theta / 2.0); - return psi_matrix(2, 2, - psi_new_complex(cos_h, 0.0), - psi_new_complex(-sin_h * cos(lambda), -sin_h * sin(lambda)), - psi_new_complex(sin_h * cos(phi), sin_h * sin(phi)), - psi_new_complex(cos_h * cos(phi + lambda), cos_h * sin(phi + lambda))); + return psi_matrix(2, 2, psi_new_complex(cos_h, 0.0), + psi_new_complex(-sin_h * cos(lambda), -sin_h * sin(lambda)), + psi_new_complex(sin_h * cos(phi), sin_h * sin(phi)), + psi_new_complex(cos_h * cos(phi + lambda), cos_h * sin(phi + lambda))); } struct PsiMatrix psi_crx_matrix(double theta) @@ -115,90 +110,83 @@ struct PsiMatrix psi_cp_matrix(double theta) struct PsiQuantumGate psi_hadamard_gate(void) { - struct PsiMatrix m = psi_matrix(2, 2, - psi_new_complex(INV_SQRT_2, 0.0), psi_new_complex(INV_SQRT_2, 0.0), - psi_new_complex(INV_SQRT_2, 0.0), psi_new_complex(-INV_SQRT_2, 0.0)); + struct PsiMatrix m = + psi_matrix(2, 2, psi_new_complex(INV_SQRT_2, 0.0), psi_new_complex(INV_SQRT_2, 0.0), + psi_new_complex(INV_SQRT_2, 0.0), psi_new_complex(-INV_SQRT_2, 0.0)); return psi_new_quantum_gate_from_matrix("H", m); } struct PsiQuantumGate psi_pauli_x_gate(void) { - struct PsiMatrix m = psi_matrix(2, 2, - psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0), - psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0)); + struct PsiMatrix m = psi_matrix(2, 2, psi_new_complex(0.0, 0.0), psi_new_complex(1.0, 0.0), + psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0)); return psi_new_quantum_gate_from_matrix("X", m); } struct PsiQuantumGate psi_pauli_y_gate(void) { - struct PsiMatrix m = psi_matrix(2, 2, - psi_new_complex(0.0, 0.0), psi_new_complex(0.0, -1.0), - psi_new_complex(0.0, 1.0), psi_new_complex(0.0, 0.0)); + struct PsiMatrix m = psi_matrix(2, 2, psi_new_complex(0.0, 0.0), psi_new_complex(0.0, -1.0), + psi_new_complex(0.0, 1.0), psi_new_complex(0.0, 0.0)); return psi_new_quantum_gate_from_matrix("Y", m); } struct PsiQuantumGate psi_pauli_z_gate(void) { - struct PsiMatrix m = psi_matrix(2, 2, - psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(-1.0, 0.0)); + struct PsiMatrix m = psi_matrix(2, 2, psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(-1.0, 0.0)); return psi_new_quantum_gate_from_matrix("Z", m); } struct PsiQuantumGate psi_s_gate(void) { - struct PsiMatrix m = psi_matrix(2, 2, - psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 1.0)); + struct PsiMatrix m = psi_matrix(2, 2, psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 1.0)); return psi_new_quantum_gate_from_matrix("S", m); } struct PsiQuantumGate psi_t_gate(void) { - struct PsiMatrix m = psi_matrix(2, 2, - psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(INV_SQRT_2, INV_SQRT_2)); + struct PsiMatrix m = + psi_matrix(2, 2, psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(INV_SQRT_2, INV_SQRT_2)); return psi_new_quantum_gate_from_matrix("T", m); } struct PsiQuantumGate psi_sdg_gate(void) { - struct PsiMatrix m = psi_matrix(2, 2, - psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(0.0, -1.0)); + struct PsiMatrix m = psi_matrix(2, 2, psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, -1.0)); return psi_new_quantum_gate_from_matrix("S†", m); } struct PsiQuantumGate psi_tdg_gate(void) { - struct PsiMatrix m = psi_matrix(2, 2, - psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(INV_SQRT_2, -INV_SQRT_2)); + struct PsiMatrix m = + psi_matrix(2, 2, psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(INV_SQRT_2, -INV_SQRT_2)); return psi_new_quantum_gate_from_matrix("T†", m); } struct PsiQuantumGate psi_sx_gate(void) { - struct PsiMatrix m = psi_matrix(2, 2, - psi_new_complex(0.5, 0.5), psi_new_complex(0.5, -0.5), - psi_new_complex(0.5, -0.5), psi_new_complex(0.5, 0.5)); + struct PsiMatrix m = psi_matrix(2, 2, psi_new_complex(0.5, 0.5), psi_new_complex(0.5, -0.5), + psi_new_complex(0.5, -0.5), psi_new_complex(0.5, 0.5)); return psi_new_quantum_gate_from_matrix("√X", m); } struct PsiQuantumGate psi_sxdg_gate(void) { - struct PsiMatrix m = psi_matrix(2, 2, - psi_new_complex(0.5, -0.5), psi_new_complex(0.5, 0.5), - psi_new_complex(0.5, 0.5), psi_new_complex(0.5, -0.5)); + struct PsiMatrix m = psi_matrix(2, 2, psi_new_complex(0.5, -0.5), psi_new_complex(0.5, 0.5), + psi_new_complex(0.5, 0.5), psi_new_complex(0.5, -0.5)); return psi_new_quantum_gate_from_matrix("√X†", m); } diff --git a/src/core/kernel.c b/src/core/kernel.c index f8f7dfd..def0782 100644 --- a/src/core/kernel.c +++ b/src/core/kernel.c @@ -6,19 +6,19 @@ #include #include -static char *dup_string(const char *s) +static char* dup_string(const char* s) { size_t n = strlen(s) + 1; - char *p = malloc(n); + char* p = malloc(n); assert(p != NULL); memcpy(p, s, n); return p; } -static size_t *dup_targets(const size_t *targets, size_t count) +static size_t* dup_targets(const size_t* targets, size_t count) { - size_t *p = malloc(count * sizeof(size_t)); + size_t* p = malloc(count * sizeof(size_t)); assert(p != NULL || count == 0); if (count > 0) @@ -27,29 +27,30 @@ static size_t *dup_targets(const size_t *targets, size_t count) return p; } -static bool starts_with(const char *s, const char *prefix) +static bool starts_with(const char* s, const char* prefix) { return strncmp(s, prefix, strlen(prefix)) == 0; } -static enum PsiGateType detect_gate_type(const char *name, struct PsiMatrix matrix) +static enum PsiGateType detect_gate_type(const char* name, struct PsiMatrix matrix) { - static const char *diagonal[] = { "Z", "S", "T", "Sdg", "Tdg", "Rz", "P", "U1", "CZ", "CP", "CRz" }; + static const char* diagonal[] = { "Z", "S", "T", "Sdg", "Tdg", "Rz", + "P", "U1", "CZ", "CP", "CRz" }; for (size_t i = 0; i < sizeof(diagonal) / sizeof(diagonal[0]); i++) if (starts_with(name, diagonal[i])) return PSI_GATE_TYPE_DIAGONAL; - static const char *controlled[] = { "CNOT", "CZ", "SWAP", "CRx", "CRy", "CRz", "CP", "CCNOT", "CSWAP" }; + static const char* controlled[] = { "CNOT", "CZ", "SWAP", "CRx", "CRy", + "CRz", "CP", "CCNOT", "CSWAP" }; for (size_t i = 0; i < sizeof(controlled) / sizeof(controlled[0]); i++) if (starts_with(name, controlled[i])) return PSI_GATE_TYPE_CONTROLLED; if (matrix.rows == 2 && matrix.cols == 2) { - bool is_diag = fabs(matrix.data[1].real) < 1e-10 - && fabs(matrix.data[1].imaginary) < 1e-10 - && fabs(matrix.data[2].real) < 1e-10 - && fabs(matrix.data[2].imaginary) < 1e-10; + bool is_diag = fabs(matrix.data[1].real) < 1e-10 && + fabs(matrix.data[1].imaginary) < 1e-10 && fabs(matrix.data[2].real) < 1e-10 && + fabs(matrix.data[2].imaginary) < 1e-10; if (is_diag) return PSI_GATE_TYPE_DIAGONAL; } @@ -57,7 +58,8 @@ static enum PsiGateType detect_gate_type(const char *name, struct PsiMatrix matr return PSI_GATE_TYPE_NON_DIAGONAL; } -struct PsiKernel psi_new_kernel(const char *name, struct PsiMatrix matrix, const size_t *targets, size_t target_count) +struct PsiKernel psi_new_kernel(const char* name, struct PsiMatrix matrix, const size_t* targets, + size_t target_count) { struct PsiKernel kernel; kernel.matrix = matrix; @@ -81,7 +83,7 @@ struct PsiKernel psi_clone_kernel(struct PsiKernel kernel) return copy; } -void psi_free_kernel(struct PsiKernel *kernel) +void psi_free_kernel(struct PsiKernel* kernel) { psi_free_matrix(&kernel->matrix); free(kernel->targets); @@ -118,7 +120,8 @@ bool psi_kernels_commute(struct PsiKernel a, struct PsiKernel b) if (!psi_kernels_share_qubits(a, b)) return true; - if (a.gate_type == PSI_GATE_TYPE_DIAGONAL && b.gate_type == PSI_GATE_TYPE_DIAGONAL && targets_equal(a, b)) + if (a.gate_type == PSI_GATE_TYPE_DIAGONAL && b.gate_type == PSI_GATE_TYPE_DIAGONAL && + targets_equal(a, b)) return true; return false; @@ -132,17 +135,18 @@ bool psi_kernels_can_fuse(struct PsiKernel a, struct PsiKernel b) return a.targets[0] == b.targets[0]; } -bool psi_fuse_kernels(struct PsiKernel a, struct PsiKernel b, struct PsiKernel *out) +bool psi_fuse_kernels(struct PsiKernel a, struct PsiKernel b, struct PsiKernel* out) { if (!psi_kernels_can_fuse(a, b)) return false; - enum PsiGateType new_type = a.gate_type == PSI_GATE_TYPE_DIAGONAL && b.gate_type == PSI_GATE_TYPE_DIAGONAL - ? PSI_GATE_TYPE_DIAGONAL - : PSI_GATE_TYPE_NON_DIAGONAL; + enum PsiGateType new_type = + a.gate_type == PSI_GATE_TYPE_DIAGONAL && b.gate_type == PSI_GATE_TYPE_DIAGONAL + ? PSI_GATE_TYPE_DIAGONAL + : PSI_GATE_TYPE_NON_DIAGONAL; size_t name_len = strlen(a.name) + strlen(b.name) + 2; - char *fused_name = malloc(name_len); + char* fused_name = malloc(name_len); assert(fused_name != NULL); snprintf(fused_name, name_len, "%s+%s", a.name, b.name); @@ -155,13 +159,14 @@ bool psi_fuse_kernels(struct PsiKernel a, struct PsiKernel b, struct PsiKernel * return true; } -static struct PsiComplex *apply_kernel(const struct PsiComplex *state, struct PsiKernel kernel, size_t num_qubits) +static struct PsiComplex* apply_kernel(const struct PsiComplex* state, struct PsiKernel kernel, + size_t num_qubits) { size_t dim = (size_t)1 << num_qubits; size_t g = kernel.target_count; size_t gate_dim = (size_t)1 << g; - size_t *target_bits = malloc(g * sizeof(size_t)); + size_t* target_bits = malloc(g * sizeof(size_t)); assert(target_bits != NULL || g == 0); for (size_t k = 0; k < g; k++) target_bits[k] = num_qubits - 1 - kernel.targets[k]; @@ -170,7 +175,7 @@ static struct PsiComplex *apply_kernel(const struct PsiComplex *state, struct Ps for (size_t k = 0; k < g; k++) non_target_mask &= ~((size_t)1 << target_bits[k]); - struct PsiComplex *new_state = malloc(dim * sizeof(struct PsiComplex)); + struct PsiComplex* new_state = malloc(dim * sizeof(struct PsiComplex)); assert(new_state != NULL); for (size_t i = 0; i < dim; i++) @@ -213,7 +218,7 @@ struct PsiKernelBatch psi_new_kernel_batch(size_t num_qubits) return batch; } -void psi_free_kernel_batch(struct PsiKernelBatch *batch) +void psi_free_kernel_batch(struct PsiKernelBatch* batch) { for (size_t i = 0; i < batch->count; i++) psi_free_kernel(&batch->kernels[i]); @@ -224,7 +229,7 @@ void psi_free_kernel_batch(struct PsiKernelBatch *batch) batch->capacity = 0; } -void psi_add_kernel(struct PsiKernelBatch *batch, struct PsiKernel kernel) +void psi_add_kernel(struct PsiKernelBatch* batch, struct PsiKernel kernel) { if (batch->count == batch->capacity) { @@ -237,13 +242,13 @@ void psi_add_kernel(struct PsiKernelBatch *batch, struct PsiKernel kernel) batch->kernels[batch->count++] = kernel; } -void psi_optimize_kernel_batch(struct PsiKernelBatch *batch) +void psi_optimize_kernel_batch(struct PsiKernelBatch* batch) { if (batch->count < 2) return; size_t original = batch->count; - struct PsiKernel *out = malloc(original * sizeof(struct PsiKernel)); + struct PsiKernel* out = malloc(original * sizeof(struct PsiKernel)); assert(out != NULL); size_t out_count = 0; @@ -273,27 +278,28 @@ void psi_optimize_kernel_batch(struct PsiKernelBatch *batch) batch->capacity = original; } -void psi_execute_kernel_batch(struct PsiKernelBatch batch, struct PsiVector *state) +void psi_execute_kernel_batch(struct PsiKernelBatch batch, struct PsiVector* state) { size_t dim = (size_t)1 << batch.num_qubits; assert(state->size == dim); for (size_t i = 0; i < batch.count; i++) { - struct PsiComplex *next = apply_kernel(state->data, batch.kernels[i], batch.num_qubits); + struct PsiComplex* next = apply_kernel(state->data, batch.kernels[i], batch.num_qubits); free(state->data); state->data = next; } } -void psi_apply_kernel(struct PsiVector *state, struct PsiKernel kernel, size_t num_qubits) +void psi_apply_kernel(struct PsiVector* state, struct PsiKernel kernel, size_t num_qubits) { - struct PsiComplex *next = apply_kernel(state->data, kernel, num_qubits); + struct PsiComplex* next = apply_kernel(state->data, kernel, num_qubits); free(state->data); state->data = next; } -static void push_kernel(struct PsiKernel **kernels, size_t *count, size_t *capacity, struct PsiKernel kernel) +static void push_kernel(struct PsiKernel** kernels, size_t* count, size_t* capacity, + struct PsiKernel kernel) { if (*count == *capacity) { @@ -315,7 +321,7 @@ static bool layer_can_add(struct PsiExecutionLayer layer, struct PsiKernel kerne return true; } -static void free_layer(struct PsiExecutionLayer *layer) +static void free_layer(struct PsiExecutionLayer* layer) { for (size_t i = 0; i < layer->count; i++) psi_free_kernel(&layer->kernels[i]); @@ -341,7 +347,7 @@ struct PsiStructureAwareBatch psi_new_structure_aware_batch(size_t num_qubits) return batch; } -static void clear_layers(struct PsiStructureAwareBatch *batch) +static void clear_layers(struct PsiStructureAwareBatch* batch) { for (size_t i = 0; i < batch->layer_count; i++) free_layer(&batch->layers[i]); @@ -352,7 +358,7 @@ static void clear_layers(struct PsiStructureAwareBatch *batch) batch->layer_capacity = 0; } -void psi_free_structure_aware_batch(struct PsiStructureAwareBatch *batch) +void psi_free_structure_aware_batch(struct PsiStructureAwareBatch* batch) { for (size_t i = 0; i < batch->count; i++) psi_free_kernel(&batch->kernels[i]); @@ -364,13 +370,13 @@ void psi_free_structure_aware_batch(struct PsiStructureAwareBatch *batch) clear_layers(batch); } -void psi_add_structure_aware_kernel(struct PsiStructureAwareBatch *batch, struct PsiKernel kernel) +void psi_add_structure_aware_kernel(struct PsiStructureAwareBatch* batch, struct PsiKernel kernel) { push_kernel(&batch->kernels, &batch->count, &batch->capacity, kernel); batch->optimised = false; } -static struct PsiKernel remove_kernel_at(struct PsiStructureAwareBatch *batch, size_t index) +static struct PsiKernel remove_kernel_at(struct PsiStructureAwareBatch* batch, size_t index) { struct PsiKernel removed = batch->kernels[index]; for (size_t i = index; i + 1 < batch->count; i++) @@ -380,7 +386,8 @@ static struct PsiKernel remove_kernel_at(struct PsiStructureAwareBatch *batch, s return removed; } -static void insert_kernel_at(struct PsiStructureAwareBatch *batch, size_t index, struct PsiKernel kernel) +static void insert_kernel_at(struct PsiStructureAwareBatch* batch, size_t index, + struct PsiKernel kernel) { if (batch->count == batch->capacity) { @@ -397,7 +404,7 @@ static void insert_kernel_at(struct PsiStructureAwareBatch *batch, size_t index, batch->count++; } -static void reorder_commuting_gates(struct PsiStructureAwareBatch *batch) +static void reorder_commuting_gates(struct PsiStructureAwareBatch* batch) { bool changed = true; size_t iterations = 0; @@ -413,9 +420,8 @@ static void reorder_commuting_gates(struct PsiStructureAwareBatch *batch) struct PsiKernel current = batch->kernels[i]; struct PsiKernel next = batch->kernels[i + 1]; - if (current.target_count != 1 || next.target_count != 1 - || current.targets[0] == next.targets[0] - || !psi_kernels_commute(current, next)) + if (current.target_count != 1 || next.target_count != 1 || + current.targets[0] == next.targets[0] || !psi_kernels_commute(current, next)) continue; for (size_t j = i + 2; j < batch->count; j++) @@ -428,7 +434,8 @@ static void reorder_commuting_gates(struct PsiStructureAwareBatch *batch) for (size_t k = i + 1; k < j; k++) { struct PsiKernel between = batch->kernels[k]; - if (psi_kernels_share_qubits(between, current) && !psi_kernels_commute(current, between)) + if (psi_kernels_share_qubits(between, current) && + !psi_kernels_commute(current, between)) { can_move = false; break; @@ -447,7 +454,7 @@ static void reorder_commuting_gates(struct PsiStructureAwareBatch *batch) } } -static void multi_pass_fusion(struct PsiStructureAwareBatch *batch) +static void multi_pass_fusion(struct PsiStructureAwareBatch* batch) { bool changed = true; size_t iterations = 0; @@ -458,7 +465,7 @@ static void multi_pass_fusion(struct PsiStructureAwareBatch *batch) changed = false; iterations++; - struct PsiKernel *new_kernels = NULL; + struct PsiKernel* new_kernels = NULL; size_t new_count = 0; size_t new_capacity = 0; @@ -490,7 +497,7 @@ static void multi_pass_fusion(struct PsiStructureAwareBatch *batch) } } -static void build_execution_layers(struct PsiStructureAwareBatch *batch) +static void build_execution_layers(struct PsiStructureAwareBatch* batch) { clear_layers(batch); @@ -502,8 +509,9 @@ static void build_execution_layers(struct PsiStructureAwareBatch *batch) for (size_t l = 0; l < batch->layer_count; l++) if (layer_can_add(batch->layers[l], kernel)) { - struct PsiExecutionLayer *layer = &batch->layers[l]; - push_kernel(&layer->kernels, &layer->count, &layer->capacity, psi_clone_kernel(kernel)); + struct PsiExecutionLayer* layer = &batch->layers[l]; + push_kernel(&layer->kernels, &layer->count, &layer->capacity, + psi_clone_kernel(kernel)); placed = true; break; } @@ -528,7 +536,7 @@ static void build_execution_layers(struct PsiStructureAwareBatch *batch) } } -void psi_optimize_structure_aware_batch(struct PsiStructureAwareBatch *batch) +void psi_optimize_structure_aware_batch(struct PsiStructureAwareBatch* batch) { if (batch->optimised || batch->count < 2) return; @@ -539,20 +547,21 @@ void psi_optimize_structure_aware_batch(struct PsiStructureAwareBatch *batch) batch->optimised = true; } -void psi_execute_structure_aware_batch(struct PsiStructureAwareBatch batch, struct PsiVector *state) +void psi_execute_structure_aware_batch(struct PsiStructureAwareBatch batch, struct PsiVector* state) { size_t dim = (size_t)1 << batch.num_qubits; assert(state->size == dim); for (size_t i = 0; i < batch.count; i++) { - struct PsiComplex *next = apply_kernel(state->data, batch.kernels[i], batch.num_qubits); + struct PsiComplex* next = apply_kernel(state->data, batch.kernels[i], batch.num_qubits); free(state->data); state->data = next; } } -void psi_execute_structure_aware_batch_layered(struct PsiStructureAwareBatch batch, struct PsiVector *state) +void psi_execute_structure_aware_batch_layered(struct PsiStructureAwareBatch batch, + struct PsiVector* state) { size_t dim = (size_t)1 << batch.num_qubits; assert(state->size == dim); @@ -560,7 +569,8 @@ void psi_execute_structure_aware_batch_layered(struct PsiStructureAwareBatch bat for (size_t l = 0; l < batch.layer_count; l++) for (size_t k = 0; k < batch.layers[l].count; k++) { - struct PsiComplex *next = apply_kernel(state->data, batch.layers[l].kernels[k], batch.num_qubits); + struct PsiComplex* next = + apply_kernel(state->data, batch.layers[l].kernels[k], batch.num_qubits); free(state->data); state->data = next; } diff --git a/src/core/noise.c b/src/core/noise.c index 9aaf1d9..5f141c8 100644 --- a/src/core/noise.c +++ b/src/core/noise.c @@ -5,30 +5,30 @@ #include #include -struct PsiKrausOperator psi_new_kraus_operator(const char *name, struct PsiMatrix matrix) +struct PsiKrausOperator psi_new_kraus_operator(const char* name, struct PsiMatrix matrix) { - return (struct PsiKrausOperator) - { + return (struct PsiKrausOperator){ matrix, name, }; } -void psi_free_kraus_operator(struct PsiKrausOperator *op) +void psi_free_kraus_operator(struct PsiKrausOperator* op) { psi_free_matrix(&op->matrix); } -struct PsiNoiseChannel psi_new_noise_channel(const char *name, const struct PsiKrausOperator *operators, size_t count, size_t num_qubits) +struct PsiNoiseChannel psi_new_noise_channel(const char* name, + const struct PsiKrausOperator* operators, size_t count, + size_t num_qubits) { - struct PsiKrausOperator *owned = malloc(count * sizeof(struct PsiKrausOperator)); + struct PsiKrausOperator* owned = malloc(count * sizeof(struct PsiKrausOperator)); assert(owned != NULL || count == 0); if (count > 0) memcpy(owned, operators, count * sizeof(struct PsiKrausOperator)); - return (struct PsiNoiseChannel) - { + return (struct PsiNoiseChannel){ name, owned, count, @@ -36,7 +36,7 @@ struct PsiNoiseChannel psi_new_noise_channel(const char *name, const struct PsiK }; } -void psi_free_noise_channel(struct PsiNoiseChannel *channel) +void psi_free_noise_channel(struct PsiNoiseChannel* channel) { for (size_t i = 0; i < channel->operator_count; i++) psi_free_matrix(&channel->operators[i].matrix); @@ -52,18 +52,22 @@ struct PsiNoiseChannel psi_depolarising_channel(double p) double sqrt_p3 = sqrt(p / 3.0); struct PsiKrausOperator ops[] = { - psi_new_kraus_operator("K0", psi_matrix(2, 2, - psi_new_complex(sqrt_1_p, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_1_p, 0.0))), - psi_new_kraus_operator("K1(X)", psi_matrix(2, 2, - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_p3, 0.0), - psi_new_complex(sqrt_p3, 0.0), psi_new_complex(0.0, 0.0))), - psi_new_kraus_operator("K2(Y)", psi_matrix(2, 2, - psi_new_complex(0.0, 0.0), psi_new_complex(0.0, -sqrt_p3), - psi_new_complex(0.0, sqrt_p3), psi_new_complex(0.0, 0.0))), - psi_new_kraus_operator("K3(Z)", psi_matrix(2, 2, - psi_new_complex(sqrt_p3, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(-sqrt_p3, 0.0))), + psi_new_kraus_operator("K0", + psi_matrix(2, 2, psi_new_complex(sqrt_1_p, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_1_p, 0.0))), + psi_new_kraus_operator( + "K1(X)", + psi_matrix(2, 2, psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_p3, 0.0), + psi_new_complex(sqrt_p3, 0.0), psi_new_complex(0.0, 0.0))), + psi_new_kraus_operator( + "K2(Y)", + psi_matrix(2, 2, psi_new_complex(0.0, 0.0), psi_new_complex(0.0, -sqrt_p3), + psi_new_complex(0.0, sqrt_p3), psi_new_complex(0.0, 0.0))), + psi_new_kraus_operator("K3(Z)", + psi_matrix(2, 2, psi_new_complex(sqrt_p3, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(-sqrt_p3, 0.0))), }; return psi_new_noise_channel("Depolarising", ops, 4, 1); @@ -75,12 +79,14 @@ struct PsiNoiseChannel psi_amplitude_damping_channel(double gamma) double sqrt_1_gamma = sqrt(1.0 - gamma); struct PsiKrausOperator ops[] = { - psi_new_kraus_operator("K0", psi_matrix(2, 2, - psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_1_gamma, 0.0))), - psi_new_kraus_operator("K1", psi_matrix(2, 2, - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_gamma, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0))), + psi_new_kraus_operator("K0", + psi_matrix(2, 2, psi_new_complex(1.0, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_1_gamma, 0.0))), + psi_new_kraus_operator("K1", + psi_matrix(2, 2, psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_gamma, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0))), }; return psi_new_noise_channel("AmplitudeDamping", ops, 2, 1); @@ -92,12 +98,14 @@ struct PsiNoiseChannel psi_phase_damping_channel(double gamma) double sqrt_1_gamma = sqrt(1.0 - gamma); struct PsiKrausOperator ops[] = { - psi_new_kraus_operator("K0", psi_matrix(2, 2, - psi_new_complex(1.0, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_1_gamma, 0.0))), - psi_new_kraus_operator("K1", psi_matrix(2, 2, - psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_gamma, 0.0))), + psi_new_kraus_operator("K0", + psi_matrix(2, 2, psi_new_complex(1.0, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_1_gamma, 0.0))), + psi_new_kraus_operator("K1", + psi_matrix(2, 2, psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_gamma, 0.0))), }; return psi_new_noise_channel("PhaseDamping", ops, 2, 1); @@ -109,12 +117,14 @@ struct PsiNoiseChannel psi_bit_flip_channel(double p) double sqrt_p = sqrt(p); struct PsiKrausOperator ops[] = { - psi_new_kraus_operator("K0(I)", psi_matrix(2, 2, - psi_new_complex(sqrt_1_p, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_1_p, 0.0))), - psi_new_kraus_operator("K1(X)", psi_matrix(2, 2, - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_p, 0.0), - psi_new_complex(sqrt_p, 0.0), psi_new_complex(0.0, 0.0))), + psi_new_kraus_operator("K0(I)", + psi_matrix(2, 2, psi_new_complex(sqrt_1_p, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_1_p, 0.0))), + psi_new_kraus_operator("K1(X)", + psi_matrix(2, 2, psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_p, 0.0), + psi_new_complex(sqrt_p, 0.0), psi_new_complex(0.0, 0.0))), }; return psi_new_noise_channel("BitFlip", ops, 2, 1); @@ -126,12 +136,14 @@ struct PsiNoiseChannel psi_phase_flip_channel(double p) double sqrt_p = sqrt(p); struct PsiKrausOperator ops[] = { - psi_new_kraus_operator("K0(I)", psi_matrix(2, 2, - psi_new_complex(sqrt_1_p, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_1_p, 0.0))), - psi_new_kraus_operator("K1(Z)", psi_matrix(2, 2, - psi_new_complex(sqrt_p, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(-sqrt_p, 0.0))), + psi_new_kraus_operator("K0(I)", + psi_matrix(2, 2, psi_new_complex(sqrt_1_p, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_1_p, 0.0))), + psi_new_kraus_operator("K1(Z)", + psi_matrix(2, 2, psi_new_complex(sqrt_p, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(-sqrt_p, 0.0))), }; return psi_new_noise_channel("PhaseFlip", ops, 2, 1); @@ -143,12 +155,14 @@ struct PsiNoiseChannel psi_bit_phase_flip_channel(double p) double sqrt_p = sqrt(p); struct PsiKrausOperator ops[] = { - psi_new_kraus_operator("K0(I)", psi_matrix(2, 2, - psi_new_complex(sqrt_1_p, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_1_p, 0.0))), - psi_new_kraus_operator("K1(Y)", psi_matrix(2, 2, - psi_new_complex(0.0, 0.0), psi_new_complex(0.0, -sqrt_p), - psi_new_complex(0.0, sqrt_p), psi_new_complex(0.0, 0.0))), + psi_new_kraus_operator("K0(I)", + psi_matrix(2, 2, psi_new_complex(sqrt_1_p, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_1_p, 0.0))), + psi_new_kraus_operator("K1(Y)", + psi_matrix(2, 2, psi_new_complex(0.0, 0.0), + psi_new_complex(0.0, -sqrt_p), + psi_new_complex(0.0, sqrt_p), psi_new_complex(0.0, 0.0))), }; return psi_new_noise_channel("BitPhaseFlip", ops, 2, 1); @@ -162,18 +176,22 @@ struct PsiNoiseChannel psi_generalised_amplitude_damping_channel(double p, doubl double sqrt_1_gamma = sqrt(1.0 - gamma); struct PsiKrausOperator ops[] = { - psi_new_kraus_operator("K0", psi_matrix(2, 2, - psi_new_complex(sqrt_p, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_p * sqrt_1_gamma, 0.0))), - psi_new_kraus_operator("K1", psi_matrix(2, 2, - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_p * sqrt_gamma, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0))), - psi_new_kraus_operator("K2", psi_matrix(2, 2, - psi_new_complex(sqrt_1_p * sqrt_1_gamma, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(0.0, 0.0), psi_new_complex(sqrt_1_p, 0.0))), - psi_new_kraus_operator("K3", psi_matrix(2, 2, - psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), - psi_new_complex(sqrt_1_p * sqrt_gamma, 0.0), psi_new_complex(0.0, 0.0))), + psi_new_kraus_operator("K0", + psi_matrix(2, 2, psi_new_complex(sqrt_p, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_p * sqrt_1_gamma, 0.0))), + psi_new_kraus_operator("K1", + psi_matrix(2, 2, psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_p * sqrt_gamma, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0))), + psi_new_kraus_operator("K2", + psi_matrix(2, 2, psi_new_complex(sqrt_1_p * sqrt_1_gamma, 0.0), + psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_1_p, 0.0))), + psi_new_kraus_operator( + "K3", + psi_matrix(2, 2, psi_new_complex(0.0, 0.0), psi_new_complex(0.0, 0.0), + psi_new_complex(sqrt_1_p * sqrt_gamma, 0.0), psi_new_complex(0.0, 0.0))), }; return psi_new_noise_channel("GeneralisedAmplitudeDamping", ops, 4, 1); @@ -182,41 +200,40 @@ struct PsiNoiseChannel psi_generalised_amplitude_damping_channel(double p, doubl struct PsiDensityMatrix psi_new_density_matrix(size_t num_qubits) { size_t dim = (size_t)1 << num_qubits; - struct PsiComplex *data = calloc(dim * dim, sizeof(struct PsiComplex)); + struct PsiComplex* data = calloc(dim * dim, sizeof(struct PsiComplex)); assert(data != NULL); data[0] = psi_new_complex(1.0, 0.0); - return (struct PsiDensityMatrix) - { + return (struct PsiDensityMatrix){ data, dim, num_qubits, }; } -struct PsiDensityMatrix psi_new_density_matrix_from_state(const struct PsiComplex *state, size_t len) +struct PsiDensityMatrix psi_new_density_matrix_from_state(const struct PsiComplex* state, + size_t len) { size_t dim = len; size_t num_qubits = 0; while (((size_t)1 << num_qubits) < dim) num_qubits++; - struct PsiComplex *data = malloc(dim * dim * sizeof(struct PsiComplex)); + struct PsiComplex* data = malloc(dim * dim * sizeof(struct PsiComplex)); assert(data != NULL); for (size_t i = 0; i < dim; i++) for (size_t j = 0; j < dim; j++) data[i * dim + j] = psi_mul_complex(state[i], psi_conjugate_complex(state[j])); - return (struct PsiDensityMatrix) - { + return (struct PsiDensityMatrix){ data, dim, num_qubits, }; } -void psi_free_density_matrix(struct PsiDensityMatrix *dm) +void psi_free_density_matrix(struct PsiDensityMatrix* dm) { free(dm->data); dm->data = NULL; @@ -230,7 +247,8 @@ struct PsiComplex psi_get_density_matrix(struct PsiDensityMatrix dm, size_t row, return dm.data[row * dm.dim + col]; } -void psi_set_density_matrix(struct PsiDensityMatrix *dm, size_t row, size_t col, struct PsiComplex value) +void psi_set_density_matrix(struct PsiDensityMatrix* dm, size_t row, size_t col, + struct PsiComplex value) { assert(row < dm->dim && col < dm->dim); dm->data[row * dm->dim + col] = value; @@ -250,7 +268,8 @@ double psi_purity_density_matrix(struct PsiDensityMatrix dm) struct PsiComplex sum = psi_new_complex(0.0, 0.0); for (size_t i = 0; i < dm.dim; i++) for (size_t j = 0; j < dm.dim; j++) - sum = psi_add_complex(sum, psi_mul_complex(dm.data[i * dm.dim + j], dm.data[j * dm.dim + i])); + sum = psi_add_complex( + sum, psi_mul_complex(dm.data[i * dm.dim + j], dm.data[j * dm.dim + i])); return sum.real; } @@ -260,19 +279,20 @@ bool psi_is_pure_density_matrix(struct PsiDensityMatrix dm, double tolerance) return fabs(psi_purity_density_matrix(dm) - 1.0) < tolerance; } -void psi_density_matrix_probabilities(struct PsiDensityMatrix dm, double *out) +void psi_density_matrix_probabilities(struct PsiDensityMatrix dm, double* out) { for (size_t i = 0; i < dm.dim; i++) out[i] = dm.data[i * dm.dim + i].real; } -void psi_apply_unitary_density_matrix(struct PsiDensityMatrix *dm, struct PsiMatrix gate, const size_t *targets, size_t target_count) +void psi_apply_unitary_density_matrix(struct PsiDensityMatrix* dm, struct PsiMatrix gate, + const size_t* targets, size_t target_count) { size_t g = target_count; size_t gate_dim = (size_t)1 << g; size_t dim = dm->dim; - size_t *target_bits = malloc(g * sizeof(size_t)); + size_t* target_bits = malloc(g * sizeof(size_t)); assert(target_bits != NULL || g == 0); for (size_t t = 0; t < g; t++) target_bits[t] = dm->num_qubits - 1 - targets[t]; @@ -281,7 +301,7 @@ void psi_apply_unitary_density_matrix(struct PsiDensityMatrix *dm, struct PsiMat for (size_t t = 0; t < g; t++) non_target_mask &= ~((size_t)1 << target_bits[t]); - struct PsiComplex *new_data = calloc(dim * dim, sizeof(struct PsiComplex)); + struct PsiComplex* new_data = calloc(dim * dim, sizeof(struct PsiComplex)); assert(new_data != NULL); for (size_t i = 0; i < dim; i++) @@ -314,10 +334,12 @@ void psi_apply_unitary_density_matrix(struct PsiDensityMatrix *dm, struct PsiMat } struct PsiComplex u_ik = gate.data[tgt_i * gate_dim + k]; - struct PsiComplex u_jl_dag = psi_conjugate_complex(gate.data[tgt_j * gate_dim + l]); + struct PsiComplex u_jl_dag = + psi_conjugate_complex(gate.data[tgt_j * gate_dim + l]); struct PsiComplex rho_kl = dm->data[src_i * dim + src_j]; - sum = psi_add_complex(sum, psi_mul_complex(psi_mul_complex(u_ik, rho_kl), u_jl_dag)); + sum = psi_add_complex(sum, + psi_mul_complex(psi_mul_complex(u_ik, rho_kl), u_jl_dag)); } new_data[i * dim + j] = sum; @@ -328,14 +350,15 @@ void psi_apply_unitary_density_matrix(struct PsiDensityMatrix *dm, struct PsiMat dm->data = new_data; } -void psi_apply_noise_channel(struct PsiDensityMatrix *dm, struct PsiNoiseChannel channel, size_t target) +void psi_apply_noise_channel(struct PsiDensityMatrix* dm, struct PsiNoiseChannel channel, + size_t target) { assert(channel.num_qubits == 1); size_t dim = dm->dim; size_t target_bit = dm->num_qubits - 1 - target; - struct PsiComplex *new_data = calloc(dim * dim, sizeof(struct PsiComplex)); + struct PsiComplex* new_data = calloc(dim * dim, sizeof(struct PsiComplex)); assert(new_data != NULL); for (size_t op = 0; op < channel.operator_count; op++) @@ -355,10 +378,12 @@ void psi_apply_noise_channel(struct PsiDensityMatrix *dm, struct PsiNoiseChannel size_t src_j = (j & ~((size_t)1 << target_bit)) | (kj << target_bit); struct PsiComplex k_elem = k.data[i_target * 2 + ki]; - struct PsiComplex k_dag_elem = psi_conjugate_complex(k.data[j_target * 2 + kj]); + struct PsiComplex k_dag_elem = + psi_conjugate_complex(k.data[j_target * 2 + kj]); struct PsiComplex rho_elem = dm->data[src_i * dim + src_j]; - struct PsiComplex term = psi_mul_complex(psi_mul_complex(k_elem, rho_elem), k_dag_elem); + struct PsiComplex term = + psi_mul_complex(psi_mul_complex(k_elem, rho_elem), k_dag_elem); new_data[i * dim + j] = psi_add_complex(new_data[i * dim + j], term); } } @@ -368,7 +393,8 @@ void psi_apply_noise_channel(struct PsiDensityMatrix *dm, struct PsiNoiseChannel dm->data = new_data; } -double psi_measure_probability_density_matrix(struct PsiDensityMatrix dm, size_t qubit, size_t outcome) +double psi_measure_probability_density_matrix(struct PsiDensityMatrix dm, size_t qubit, + size_t outcome) { size_t target_bit = dm.num_qubits - 1 - qubit; double prob = 0.0; @@ -380,13 +406,16 @@ double psi_measure_probability_density_matrix(struct PsiDensityMatrix dm, size_t return prob; } -double psi_fidelity_density_matrix(struct PsiDensityMatrix dm, const struct PsiComplex *state) +double psi_fidelity_density_matrix(struct PsiDensityMatrix dm, const struct PsiComplex* state) { struct PsiComplex sum = psi_new_complex(0.0, 0.0); for (size_t i = 0; i < dm.dim; i++) for (size_t j = 0; j < dm.dim; j++) - sum = psi_add_complex(sum, psi_mul_complex(psi_mul_complex(psi_conjugate_complex(state[i]), dm.data[i * dm.dim + j]), state[j])); + sum = psi_add_complex(sum, + psi_mul_complex(psi_mul_complex(psi_conjugate_complex(state[i]), + dm.data[i * dm.dim + j]), + state[j])); return sum.real; } diff --git a/src/core/quantum_components.c b/src/core/quantum_components.c index 31d60dc..a62a911 100644 --- a/src/core/quantum_components.c +++ b/src/core/quantum_components.c @@ -14,21 +14,21 @@ 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)); } -struct PsiQuantumGate psi_new_quantum_gate(const char *name, struct PsiMatrix matrix, size_t num_qubits) +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); - return (struct PsiQuantumGate) - { + return (struct PsiQuantumGate){ name, matrix, num_qubits, }; } -struct PsiQuantumGate psi_new_quantum_gate_from_matrix(const char *name, struct PsiMatrix matrix) +struct PsiQuantumGate psi_new_quantum_gate_from_matrix(const char* name, struct PsiMatrix matrix) { assert(matrix.rows == matrix.cols); @@ -39,34 +39,32 @@ struct PsiQuantumGate psi_new_quantum_gate_from_matrix(const char *name, struct while (((size_t)1 << num_qubits) < dim) num_qubits++; - return (struct PsiQuantumGate) - { + return (struct PsiQuantumGate){ name, matrix, num_qubits, }; } -void psi_free_quantum_gate(struct PsiQuantumGate *gate) +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) +struct PsiQuantumBit psi_new_quantum_bit(const char* name, struct PsiVector state) { - return (struct PsiQuantumBit) - { + return (struct PsiQuantumBit){ name, state, }; } -void psi_free_quantum_bit(struct PsiQuantumBit *bit) +void psi_free_quantum_bit(struct PsiQuantumBit* bit) { psi_free_vector(&bit->state); } -static void update_register(struct PsiQuantumRegister *reg) +static void update_register(struct PsiQuantumRegister* reg) { psi_free_vector(®->state_vector); @@ -90,16 +88,16 @@ static void update_register(struct PsiQuantumRegister *reg) psi_free_matrix(&result); } -struct PsiQuantumRegister psi_new_quantum_register(const char *name, const char **names, size_t count) +struct PsiQuantumRegister psi_new_quantum_register(const char* name, const char** names, + size_t count) { - struct PsiQuantumBit *qubits = malloc(count * sizeof(struct PsiQuantumBit)); + 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 = - { + struct PsiQuantumRegister reg = { name, psi_new_vector(0, PSI_COLUMN_VECTOR), qubits, @@ -110,16 +108,16 @@ struct PsiQuantumRegister psi_new_quantum_register(const char *name, const char return reg; } -struct PsiQuantumRegister psi_new_quantum_register_from(const char *name, const struct PsiQuantumBit *bits, size_t count) +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)); + 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 = - { + struct PsiQuantumRegister reg = { name, psi_new_vector(0, PSI_COLUMN_VECTOR), qubits, @@ -130,7 +128,7 @@ struct PsiQuantumRegister psi_new_quantum_register_from(const char *name, const return reg; } -void psi_free_quantum_register(struct PsiQuantumRegister *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]); @@ -141,7 +139,7 @@ void psi_free_quantum_register(struct PsiQuantumRegister *reg) psi_free_vector(®->state_vector); } -static bool targets_contain(const size_t *targets, size_t count, size_t value) +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) @@ -150,7 +148,8 @@ static bool targets_contain(const size_t *targets, size_t count, size_t value) return false; } -static struct PsiMatrix build_contiguous_operator(struct PsiQuantumRegister reg, struct PsiQuantumGate gate, size_t start_idx) +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; @@ -163,9 +162,8 @@ static struct PsiMatrix build_contiguous_operator(struct PsiQuantumRegister reg, 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) { @@ -186,7 +184,9 @@ static struct PsiMatrix build_contiguous_operator(struct PsiQuantumRegister reg, return result; } -static struct PsiMatrix build_full_operator(struct PsiQuantumRegister reg, struct PsiQuantumGate gate, const size_t *targets, size_t target_count) +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; @@ -238,13 +238,15 @@ static struct PsiMatrix build_full_operator(struct PsiQuantumRegister reg, struc } if (non_target_match) - result.data[row * result.cols + col] = psi_get_matrix(gate.matrix, target_row_bits, target_col_bits); + 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) +void psi_apply_gate(struct PsiQuantumRegister* reg, struct PsiQuantumGate gate, + const size_t* targets, size_t target_count) { size_t n = reg->num_qubits; diff --git a/src/core/runtime.c b/src/core/runtime.c index 950ec7c..24cbe26 100644 --- a/src/core/runtime.c +++ b/src/core/runtime.c @@ -34,14 +34,9 @@ struct PsiRuntimeConfig psi_runtime_to_config(enum PsiRuntime runtime) switch (runtime) { - case PSI_RUNTIME_BASIC: - break; - case PSI_RUNTIME_BASIC_MT: - config.parallel = true; - break; - case PSI_RUNTIME_BATCHED: - config.batched = true; - break; + case PSI_RUNTIME_BASIC: break; + case PSI_RUNTIME_BASIC_MT: config.parallel = true; break; + case PSI_RUNTIME_BATCHED: config.batched = true; break; case PSI_RUNTIME_BATCHED_MT: config.batched = true; config.parallel = true; @@ -69,45 +64,126 @@ struct PsiRuntimeConfig psi_runtime_to_config(enum PsiRuntime runtime) return config; } -static bool op_to_kernel(struct PsiGateOp op, struct PsiKernel *out) +static bool op_to_kernel(struct PsiGateOp op, struct PsiKernel* out) { struct PsiMatrix matrix; - const char *name; + const char* name; switch (op.kind) { - case PSI_GATE_H: matrix = psi_hadamard_gate().matrix; name = "H"; break; - case PSI_GATE_X: matrix = psi_pauli_x_gate().matrix; name = "X"; break; - case PSI_GATE_Y: matrix = psi_pauli_y_gate().matrix; name = "Y"; break; - case PSI_GATE_Z: matrix = psi_pauli_z_gate().matrix; name = "Z"; break; - case PSI_GATE_S: matrix = psi_s_gate().matrix; name = "S"; break; - case PSI_GATE_T: matrix = psi_t_gate().matrix; name = "T"; break; - case PSI_GATE_SDG: matrix = psi_sdg_gate().matrix; name = "Sdg"; break; - case PSI_GATE_TDG: matrix = psi_tdg_gate().matrix; name = "Tdg"; break; - case PSI_GATE_SX: matrix = psi_sx_gate().matrix; name = "Sx"; break; - case PSI_GATE_SXDG: matrix = psi_sxdg_gate().matrix; name = "Sxdg"; break; - case PSI_GATE_RX: matrix = psi_rx_matrix(op.params[0]); name = "Rx"; break; - case PSI_GATE_RY: matrix = psi_ry_matrix(op.params[0]); name = "Ry"; break; - case PSI_GATE_RZ: matrix = psi_rz_matrix(op.params[0]); name = "Rz"; break; - case PSI_GATE_P: matrix = psi_p_matrix(op.params[0]); name = "P"; break; - case PSI_GATE_U1: matrix = psi_u1_matrix(op.params[0]); name = "U1"; break; - case PSI_GATE_U2: matrix = psi_u2_matrix(op.params[0], op.params[1]); name = "U2"; break; - case PSI_GATE_U3: matrix = psi_u3_matrix(op.params[0], op.params[1], op.params[2]); name = "U3"; break; - case PSI_GATE_CNOT: matrix = psi_cnot_gate().matrix; name = "CNOT"; break; - case PSI_GATE_CZ: matrix = psi_cz_gate().matrix; name = "CZ"; break; - case PSI_GATE_SWAP: matrix = psi_swap_gate().matrix; name = "SWAP"; break; - case PSI_GATE_CRX: matrix = psi_crx_matrix(op.params[0]); name = "CRx"; break; - case PSI_GATE_CRY: matrix = psi_cry_matrix(op.params[0]); name = "CRy"; break; - case PSI_GATE_CRZ: matrix = psi_crz_matrix(op.params[0]); name = "CRz"; break; - case PSI_GATE_CP: matrix = psi_cp_matrix(op.params[0]); name = "CP"; break; - case PSI_GATE_CCNOT: matrix = psi_toffoli_gate().matrix; name = "CCNOT"; break; - case PSI_GATE_CSWAP: matrix = psi_fredkin_gate().matrix; name = "CSWAP"; break; + case PSI_GATE_H: + matrix = psi_hadamard_gate().matrix; + name = "H"; + break; + case PSI_GATE_X: + matrix = psi_pauli_x_gate().matrix; + name = "X"; + break; + case PSI_GATE_Y: + matrix = psi_pauli_y_gate().matrix; + name = "Y"; + break; + case PSI_GATE_Z: + matrix = psi_pauli_z_gate().matrix; + name = "Z"; + break; + case PSI_GATE_S: + matrix = psi_s_gate().matrix; + name = "S"; + break; + case PSI_GATE_T: + matrix = psi_t_gate().matrix; + name = "T"; + break; + case PSI_GATE_SDG: + matrix = psi_sdg_gate().matrix; + name = "Sdg"; + break; + case PSI_GATE_TDG: + matrix = psi_tdg_gate().matrix; + name = "Tdg"; + break; + case PSI_GATE_SX: + matrix = psi_sx_gate().matrix; + name = "Sx"; + break; + case PSI_GATE_SXDG: + matrix = psi_sxdg_gate().matrix; + name = "Sxdg"; + break; + case PSI_GATE_RX: + matrix = psi_rx_matrix(op.params[0]); + name = "Rx"; + break; + case PSI_GATE_RY: + matrix = psi_ry_matrix(op.params[0]); + name = "Ry"; + break; + case PSI_GATE_RZ: + matrix = psi_rz_matrix(op.params[0]); + name = "Rz"; + break; + case PSI_GATE_P: + matrix = psi_p_matrix(op.params[0]); + name = "P"; + break; + case PSI_GATE_U1: + matrix = psi_u1_matrix(op.params[0]); + name = "U1"; + break; + case PSI_GATE_U2: + matrix = psi_u2_matrix(op.params[0], op.params[1]); + name = "U2"; + break; + case PSI_GATE_U3: + matrix = psi_u3_matrix(op.params[0], op.params[1], op.params[2]); + name = "U3"; + break; + case PSI_GATE_CNOT: + matrix = psi_cnot_gate().matrix; + name = "CNOT"; + break; + case PSI_GATE_CZ: + matrix = psi_cz_gate().matrix; + name = "CZ"; + break; + case PSI_GATE_SWAP: + matrix = psi_swap_gate().matrix; + name = "SWAP"; + break; + case PSI_GATE_CRX: + matrix = psi_crx_matrix(op.params[0]); + name = "CRx"; + break; + case PSI_GATE_CRY: + matrix = psi_cry_matrix(op.params[0]); + name = "CRy"; + break; + case PSI_GATE_CRZ: + matrix = psi_crz_matrix(op.params[0]); + name = "CRz"; + break; + case PSI_GATE_CP: + matrix = psi_cp_matrix(op.params[0]); + name = "CP"; + break; + case PSI_GATE_CCNOT: + matrix = psi_toffoli_gate().matrix; + name = "CCNOT"; + break; + case PSI_GATE_CSWAP: + matrix = psi_fredkin_gate().matrix; + name = "CSWAP"; + break; case PSI_GATE_MEASURE: return false; - case PSI_GATE_CUSTOM: matrix = psi_to_quantum_gate(*op.custom).matrix; name = "Custom"; break; + case PSI_GATE_CUSTOM: + matrix = psi_to_quantum_gate(*op.custom).matrix; + name = "Custom"; + break; } size_t target_count; - const size_t *targets = psi_gate_op_quantum_targets(&op, &target_count); + const size_t* targets = psi_gate_op_quantum_targets(&op, &target_count); *out = psi_new_kernel(name, matrix, targets, target_count); return true; @@ -122,7 +198,8 @@ static struct PsiVector new_zero_state(size_t num_qubits) return state; } -static void execute_kernels(struct PsiVector *state, const struct PsiKernel *kernels, size_t count, size_t num_qubits, struct PsiRuntimeConfig config) +static void execute_kernels(struct PsiVector* state, const struct PsiKernel* kernels, size_t count, + size_t num_qubits, struct PsiRuntimeConfig config) { bool use_parallel = config.parallel && num_qubits >= config.parallel_threshold; @@ -138,7 +215,8 @@ static void execute_kernels(struct PsiVector *state, const struct PsiKernel *ker }; if (use_parallel) - psi_apply_single_qubit_gate_simd_parallel(state->data, gate, kernel.targets[0], num_qubits); + psi_apply_single_qubit_gate_simd_parallel(state->data, gate, kernel.targets[0], + num_qubits); else psi_apply_single_qubit_gate_simd(state->data, gate, kernel.targets[0], num_qubits); } @@ -147,7 +225,8 @@ static void execute_kernels(struct PsiVector *state, const struct PsiKernel *ker } } -struct PsiVector psi_compute_runtime_config(struct PsiRuntimeConfig config, size_t num_qubits, const struct PsiGateOp *operations, size_t op_count) +struct PsiVector psi_compute_runtime_config(struct PsiRuntimeConfig config, size_t num_qubits, + const struct PsiGateOp* operations, size_t op_count) { struct PsiVector state = new_zero_state(num_qubits); @@ -185,42 +264,47 @@ struct PsiVector psi_compute_runtime_config(struct PsiRuntimeConfig config, size return state; } -struct PsiVector psi_compute_runtime(enum PsiRuntime runtime, size_t num_qubits, const struct PsiGateOp *operations, size_t op_count) +struct PsiVector psi_compute_runtime(enum PsiRuntime runtime, size_t num_qubits, + const struct PsiGateOp* operations, size_t op_count) { - return psi_compute_runtime_config(psi_runtime_to_config(runtime), num_qubits, operations, op_count); + return psi_compute_runtime_config(psi_runtime_to_config(runtime), num_qubits, operations, + op_count); } -const struct PsiVector *psi_compute_circuit_with_config(struct PsiQuantumCircuit *circuit, struct PsiRuntimeConfig config) +const struct PsiVector* psi_compute_circuit_with_config(struct PsiQuantumCircuit* circuit, + struct PsiRuntimeConfig config) { if (!circuit->is_computed) { psi_free_vector(&circuit->computed_state); - circuit->computed_state = psi_compute_runtime_config(config, circuit->num_qubits, circuit->operations, circuit->operation_count); + circuit->computed_state = psi_compute_runtime_config( + config, circuit->num_qubits, circuit->operations, circuit->operation_count); circuit->is_computed = true; } return &circuit->computed_state; } -const struct PsiVector *psi_compute_circuit_with(struct PsiQuantumCircuit *circuit, enum PsiRuntime runtime) +const struct PsiVector* psi_compute_circuit_with(struct PsiQuantumCircuit* circuit, + enum PsiRuntime runtime) { return psi_compute_circuit_with_config(circuit, psi_runtime_to_config(runtime)); } -const struct PsiVector *psi_compute_circuit(struct PsiQuantumCircuit *circuit) +const struct PsiVector* psi_compute_circuit(struct PsiQuantumCircuit* circuit) { return psi_compute_circuit_with(circuit, PSI_RUNTIME_BASIC); } -double psi_circuit_probability(struct PsiQuantumCircuit *circuit, size_t state_index) +double psi_circuit_probability(struct PsiQuantumCircuit* circuit, size_t state_index) { - const struct PsiVector *state = psi_compute_circuit(circuit); + const struct PsiVector* state = psi_compute_circuit(circuit); return psi_norm2_complex(state->data[state_index]); } -void psi_circuit_probabilities(struct PsiQuantumCircuit *circuit, double *out) +void psi_circuit_probabilities(struct PsiQuantumCircuit* circuit, double* out) { - const struct PsiVector *state = psi_compute_circuit(circuit); + const struct PsiVector* state = psi_compute_circuit(circuit); size_t dim = (size_t)1 << circuit->num_qubits; for (size_t i = 0; i < dim; i++) out[i] = psi_norm2_complex(state->data[i]); -- cgit v1.3