diff options
Diffstat (limited to 'src/core/runtime.c')
| -rw-r--r-- | src/core/runtime.c | 456 |
1 files changed, 228 insertions, 228 deletions
diff --git a/src/core/runtime.c b/src/core/runtime.c index 24cbe26..9c95214 100644 --- a/src/core/runtime.c +++ b/src/core/runtime.c @@ -8,304 +8,304 @@ struct PsiRuntimeConfig psi_new_runtime_config(void) { - struct PsiRuntimeConfig config; - config.parallel = false; - config.simd = false; - config.batched = false; - config.structure_aware = false; - config.parallel_threshold = PSI_PARALLEL_THRESHOLD; + struct PsiRuntimeConfig config; + config.parallel = false; + config.simd = false; + config.batched = false; + config.structure_aware = false; + config.parallel_threshold = PSI_PARALLEL_THRESHOLD; - return config; + return config; } struct PsiRuntimeConfig psi_optimal_runtime_config(void) { - struct PsiRuntimeConfig config = psi_new_runtime_config(); - config.structure_aware = true; - config.simd = true; - config.parallel = true; + struct PsiRuntimeConfig config = psi_new_runtime_config(); + config.structure_aware = true; + config.simd = true; + config.parallel = true; - return config; + return config; } struct PsiRuntimeConfig psi_runtime_to_config(enum PsiRuntime runtime) { - struct PsiRuntimeConfig config = psi_new_runtime_config(); + struct PsiRuntimeConfig config = psi_new_runtime_config(); - 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_BATCHED_MT: - config.batched = true; - config.parallel = true; - break; - case PSI_RUNTIME_SIMD: - config.batched = true; - config.simd = true; - break; - case PSI_RUNTIME_SIMD_MT: - config.batched = true; - config.simd = true; - config.parallel = true; - break; - case PSI_RUNTIME_STRUCTURE_AWARE: - config.structure_aware = true; - config.simd = true; - break; - case PSI_RUNTIME_STRUCTURE_AWARE_MT: - config.structure_aware = true; - config.simd = true; - config.parallel = true; - break; - } + 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_BATCHED_MT: + config.batched = true; + config.parallel = true; + break; + case PSI_RUNTIME_SIMD: + config.batched = true; + config.simd = true; + break; + case PSI_RUNTIME_SIMD_MT: + config.batched = true; + config.simd = true; + config.parallel = true; + break; + case PSI_RUNTIME_STRUCTURE_AWARE: + config.structure_aware = true; + config.simd = true; + break; + case PSI_RUNTIME_STRUCTURE_AWARE_MT: + config.structure_aware = true; + config.simd = true; + config.parallel = true; + break; + } - return config; + return config; } static bool op_to_kernel(struct PsiGateOp op, struct PsiKernel* out) { - struct PsiMatrix matrix; - const char* name; + struct PsiMatrix matrix; + 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_MEASURE: return false; - case PSI_GATE_CUSTOM: - matrix = psi_to_quantum_gate(*op.custom).matrix; - name = "Custom"; - break; - } + 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_MEASURE: return false; + 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); - *out = psi_new_kernel(name, matrix, targets, target_count); + size_t 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; + return true; } static struct PsiVector new_zero_state(size_t num_qubits) { - size_t dim = (size_t)1 << num_qubits; - struct PsiVector state = psi_new_vector(dim, PSI_COLUMN_VECTOR); - state.data[0] = psi_new_complex(1.0, 0.0); + size_t dim = (size_t)1 << num_qubits; + struct PsiVector state = psi_new_vector(dim, PSI_COLUMN_VECTOR); + state.data[0] = psi_new_complex(1.0, 0.0); - return state; + return state; } 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; + bool use_parallel = config.parallel && num_qubits >= config.parallel_threshold; - for (size_t i = 0; i < count; i++) - { - struct PsiKernel kernel = kernels[i]; + for (size_t i = 0; i < count; i++) + { + struct PsiKernel kernel = kernels[i]; - if (config.simd && kernel.target_count == 1) - { - struct PsiComplex gate[2][2] = { - { kernel.matrix.data[0], kernel.matrix.data[1] }, - { kernel.matrix.data[2], kernel.matrix.data[3] }, - }; + if (config.simd && kernel.target_count == 1) + { + struct PsiComplex gate[2][2] = { + { kernel.matrix.data[0], kernel.matrix.data[1] }, + { kernel.matrix.data[2], kernel.matrix.data[3] }, + }; - if (use_parallel) - 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); - } - else - psi_apply_kernel(state, kernel, num_qubits); - } + if (use_parallel) + 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); + } + else + psi_apply_kernel(state, kernel, num_qubits); + } } 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); + struct PsiVector state = new_zero_state(num_qubits); - if (config.structure_aware) - { - struct PsiStructureAwareBatch batch = psi_new_structure_aware_batch(num_qubits); - for (size_t i = 0; i < op_count; i++) - { - struct PsiKernel kernel; - if (op_to_kernel(operations[i], &kernel)) - psi_add_structure_aware_kernel(&batch, kernel); - } + if (config.structure_aware) + { + struct PsiStructureAwareBatch batch = psi_new_structure_aware_batch(num_qubits); + for (size_t i = 0; i < op_count; i++) + { + struct PsiKernel kernel; + if (op_to_kernel(operations[i], &kernel)) + psi_add_structure_aware_kernel(&batch, kernel); + } - psi_optimize_structure_aware_batch(&batch); - execute_kernels(&state, batch.kernels, batch.count, num_qubits, config); - psi_free_structure_aware_batch(&batch); + psi_optimize_structure_aware_batch(&batch); + execute_kernels(&state, batch.kernels, batch.count, num_qubits, config); + psi_free_structure_aware_batch(&batch); - return state; - } + return state; + } - struct PsiKernelBatch batch = psi_new_kernel_batch(num_qubits); - for (size_t i = 0; i < op_count; i++) - { - struct PsiKernel kernel; - if (op_to_kernel(operations[i], &kernel)) - psi_add_kernel(&batch, kernel); - } + struct PsiKernelBatch batch = psi_new_kernel_batch(num_qubits); + for (size_t i = 0; i < op_count; i++) + { + struct PsiKernel kernel; + if (op_to_kernel(operations[i], &kernel)) + psi_add_kernel(&batch, kernel); + } - if (config.batched) - psi_optimize_kernel_batch(&batch); + if (config.batched) + psi_optimize_kernel_batch(&batch); - execute_kernels(&state, batch.kernels, batch.count, num_qubits, config); - psi_free_kernel_batch(&batch); + execute_kernels(&state, batch.kernels, batch.count, num_qubits, config); + psi_free_kernel_batch(&batch); - return state; + return state; } 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) { - 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->is_computed = true; - } + 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->is_computed = true; + } - return &circuit->computed_state; + return &circuit->computed_state; } 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)); + return psi_compute_circuit_with_config(circuit, psi_runtime_to_config(runtime)); } const struct PsiVector* psi_compute_circuit(struct PsiQuantumCircuit* circuit) { - return psi_compute_circuit_with(circuit, PSI_RUNTIME_BASIC); + return psi_compute_circuit_with(circuit, PSI_RUNTIME_BASIC); } double psi_circuit_probability(struct PsiQuantumCircuit* circuit, size_t state_index) { - const struct PsiVector* state = psi_compute_circuit(circuit); - return psi_norm2_complex(state->data[state_index]); + 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) { - 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]); + 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]); } |
