#include #include #include "psi.h" int main(void) { printf("psi %s\n", psi_version()); struct PsiComplex a = psi_new_complex(1.0, 2.0); struct PsiComplex b = psi_new_complex(3.0, -1.0); struct PsiComplex sum = psi_add_complex(a, b); struct PsiComplex product = psi_mul_complex(a, b); printf("a = %g + %gi\n", a.real, a.imaginary); printf("b = %g + %gi\n", b.real, b.imaginary); printf("a + b = %g + %gi\n", sum.real, sum.imaginary); printf("a * b = %g + %gi\n", product.real, product.imaginary); printf("|a| = %g\n", psi_abs_complex(a)); struct PsiVector u = psi_column_vector( psi_new_complex(1.0, 0.0), psi_new_complex(2.0, 0.0), psi_new_complex(3.0, 0.0)); struct PsiVector v = psi_column_vector( psi_new_complex(4.0, 0.0), psi_new_complex(5.0, 0.0), psi_new_complex(6.0, 0.0)); struct PsiComplex dot = psi_dot_vector(u, v); struct PsiComplex norm = psi_norm_vector(u); printf("u . v = %g + %gi\n", dot.real, dot.imaginary); printf("|u| = %g + %gi\n", norm.real, norm.imaginary); psi_free_vector(&u); psi_free_vector(&v); struct PsiMatrix m = psi_matrix(2, 2, psi_new_complex(1.0, 0.0), psi_new_complex(2.0, 0.0), psi_new_complex(3.0, 0.0), psi_new_complex(4.0, 0.0)); struct PsiMatrix mm = psi_dot_matrix(m, m); printf("m*m = [%g %g; %g %g]\n", psi_get_matrix(mm, 0, 0).real, psi_get_matrix(mm, 0, 1).real, psi_get_matrix(mm, 1, 0).real, psi_get_matrix(mm, 1, 1).real); struct PsiVector x = psi_column_vector( psi_new_complex(1.0, 0.0), psi_new_complex(1.0, 0.0)); struct PsiVector mx = psi_mul_vector_matrix(x, m); printf("m*x = [%g, %g]\n", mx.data[0].real, mx.data[1].real); psi_free_vector(&x); psi_free_vector(&mx); psi_free_matrix(&m); psi_free_matrix(&mm); double inv_sqrt2 = 0.7071067811865475; struct PsiMatrix h = psi_matrix(2, 2, psi_new_complex(inv_sqrt2, 0.0), psi_new_complex(inv_sqrt2, 0.0), psi_new_complex(inv_sqrt2, 0.0), psi_new_complex(-inv_sqrt2, 0.0)); struct PsiQuantumGate gate = psi_new_quantum_gate_from_matrix("H", h); struct PsiVector s0 = psi_new_state_0(); struct PsiVector hs0 = psi_mul_vector_matrix(s0, gate.matrix); printf("gate = %s (%zu qubit)\n", gate.name, gate.num_qubits); printf("H|0> = [%g, %g]\n", hs0.data[0].real, hs0.data[1].real); psi_free_vector(&s0); psi_free_vector(&hs0); psi_free_quantum_gate(&gate); const char *names[] = { "q0", "q1" }; struct PsiQuantumRegister reg = psi_new_quantum_register("bell", names, 2); struct PsiQuantumGate hadamard = psi_hadamard_gate(); struct PsiQuantumGate cnot = psi_cnot_gate(); size_t t0[] = { 0 }; size_t t01[] = { 0, 1 }; psi_apply_gate(®, hadamard, t0, 1); psi_apply_gate(®, cnot, t01, 2); printf("bell = [%g, %g, %g, %g]\n", reg.state_vector.data[0].real, reg.state_vector.data[1].real, reg.state_vector.data[2].real, reg.state_vector.data[3].real); psi_free_quantum_gate(&hadamard); psi_free_quantum_gate(&cnot); psi_free_quantum_register(®); struct PsiCompositeGateOp bell_ops[] = { { PSI_OP_H, { 0 }, 1 }, { PSI_OP_CNOT, { 0, 1 }, 2 }, }; struct PsiCustomGate bell = psi_new_custom_gate_from_composite("BELL", 2, bell_ops, 2); struct PsiQuantumGate bell_gate = psi_to_quantum_gate(bell); struct PsiQuantumRegister reg2 = psi_new_quantum_register("bell2", names, 2); size_t t01b[] = { 0, 1 }; psi_apply_gate(®2, bell_gate, t01b, 2); printf("custom = %s -> [%g, %g, %g, %g]\n", bell_gate.name, reg2.state_vector.data[0].real, reg2.state_vector.data[1].real, reg2.state_vector.data[2].real, reg2.state_vector.data[3].real); psi_free_custom_gate(&bell); psi_free_quantum_gate(&bell_gate); psi_free_quantum_register(®2); const char *cnames[] = { "c0", "c1" }; struct PsiClassicalRegister creg = psi_new_classical_register("c", cnames, 2); creg.bits[1].state = true; printf("creg = %s=%d %s=%d\n", creg.bits[0].name, creg.bits[0].state, creg.bits[1].name, creg.bits[1].state); psi_free_classical_register(&creg); struct PsiQuantumCircuit circuit = psi_new_quantum_circuit(3); psi_apply_h(&circuit, 0); psi_apply_cnot(&circuit, 0, 1); psi_apply_rx(&circuit, 2, 1.5707963267948966); psi_apply_ccnot(&circuit, 0, 1, 2); struct PsiCompositeGateOp cops[] = { { PSI_OP_X, { 0 }, 1 } }; struct PsiCustomGate xg = psi_new_custom_gate_from_composite("MYX", 1, cops, 1); size_t ct[] = { 2 }; psi_apply_custom(&circuit, xg, ct, 1); psi_measure_all(&circuit); printf("circuit = %zu qubits, %zu classical, %zu ops\n", circuit.num_qubits, circuit.num_classical, circuit.operation_count); for (size_t i = 0; i < circuit.operation_count; i++) { size_t tc; const size_t *targets = psi_gate_op_quantum_targets(&circuit.operations[i], &tc); printf(" %zu: %s on", i, psi_gate_op_name(circuit.operations[i])); for (size_t j = 0; j < tc; j++) printf(" q%zu", targets[j]); printf("\n"); } psi_free_quantum_circuit(&circuit); size_t kt[] = { 0 }; struct PsiKernelBatch batch = psi_new_kernel_batch(1); struct PsiQuantumGate hg = psi_hadamard_gate(); psi_add_kernel(&batch, psi_new_kernel("H", psi_clone_matrix(hg.matrix), kt, 1)); psi_add_kernel(&batch, psi_new_kernel("H", psi_clone_matrix(hg.matrix), kt, 1)); psi_free_quantum_gate(&hg); size_t before = batch.count; psi_optimize_kernel_batch(&batch); struct PsiVector state = psi_new_state_0(); psi_execute_kernel_batch(batch, &state); printf("kernels = %zu -> %zu (fused), HH|0> = [%g, %g]\n", before, batch.count, state.data[0].real, state.data[1].real); psi_free_vector(&state); psi_free_kernel_batch(&batch); struct PsiStructureAwareBatch sa = psi_new_structure_aware_batch(2); struct PsiQuantumGate hg2 = psi_hadamard_gate(); struct PsiQuantumGate xg2 = psi_pauli_x_gate(); size_t q0[] = { 0 }; size_t q1[] = { 1 }; psi_add_structure_aware_kernel(&sa, psi_new_kernel("H", psi_clone_matrix(hg2.matrix), q0, 1)); psi_add_structure_aware_kernel(&sa, psi_new_kernel("X", psi_clone_matrix(xg2.matrix), q1, 1)); psi_add_structure_aware_kernel(&sa, psi_new_kernel("H", psi_clone_matrix(hg2.matrix), q0, 1)); psi_free_quantum_gate(&hg2); psi_free_quantum_gate(&xg2); psi_optimize_structure_aware_batch(&sa); struct PsiKernelStats stats = psi_structure_aware_batch_stats(sa); struct PsiQuantumRegister r = psi_new_quantum_register("r", names, 2); struct PsiVector sast = psi_clone_vector(r.state_vector); psi_free_quantum_register(&r); psi_execute_structure_aware_batch_layered(sa, &sast); printf("sa = %zu kernels, %zu layers -> [%g, %g, %g, %g]\n", stats.total_kernels, stats.execution_layers, sast.data[0].real, sast.data[1].real, sast.data[2].real, sast.data[3].real); psi_free_vector(&sast); psi_free_structure_aware_batch(&sa); struct PsiQuantumCircuit ghz = psi_new_quantum_circuit(3); psi_apply_h(&ghz, 0); psi_apply_cnot(&ghz, 0, 1); psi_apply_cnot(&ghz, 1, 2); const struct PsiVector *ghz_state = psi_compute_circuit_with(&ghz, PSI_RUNTIME_STRUCTURE_AWARE); printf("ghz ="); for (size_t i = 0; i < ghz_state->size; i++) printf(" %g", ghz_state->data[i].real); printf("\n"); double probs[8]; psi_circuit_probabilities(&ghz, probs); printf("p(000) = %g, p(111) = %g\n", probs[0], probs[7]); char abuf[64]; char pbuf[64]; printf("amp = |000> %s, p|111> %s\n", psi_format_amplitude(ghz_state->data[0], abuf, sizeof abuf), psi_format_probability(probs[7], pbuf, sizeof pbuf)); psi_free_quantum_circuit(&ghz); struct PsiDensityMatrix dm = psi_new_density_matrix(1); printf("dm = purity %g (pure? %d)\n", psi_purity_density_matrix(dm), psi_is_pure_density_matrix(dm, 1e-10)); struct PsiNoiseChannel bf = psi_bit_flip_channel(0.25); psi_apply_noise_channel(&dm, bf, 0); double dprobs[2]; psi_density_matrix_probabilities(dm, dprobs); printf("noisy = p [%g, %g], purity %g\n", dprobs[0], dprobs[1], psi_purity_density_matrix(dm)); psi_free_noise_channel(&bf); psi_free_density_matrix(&dm); struct PsiQuantumCircuit viz = psi_new_quantum_circuit(3); psi_apply_h(&viz, 0); psi_apply_cnot(&viz, 0, 1); psi_apply_rx(&viz, 2, 1.5707963267948966); psi_apply_ccnot(&viz, 0, 1, 2); psi_measure(&viz, 0, 0); char *diagram = psi_render_circuit_vertical(&viz); printf("\n%s\n", diagram); free(diagram); psi_free_quantum_circuit(&viz); }