Site Tools


qubit-gates-in-c

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
qubit-gates-in-c [February 19, 2026 at 12:20] yanevskivqubit-gates-in-c [May 14, 2026 at 11:38] (current) – external edit 127.0.0.1
Line 1: Line 1:
 +# Qubit gate
  
 +## Simulation 
 +In C99, a header [[complex.h|<complex.h>]] is provided that implements complex numbers.
 +
 +### State
 +As we've seen, a qubit is a two-state configuration with complex probability amplitudes distributed between the two states.  
 +This gives us the following implementation of a single qubit:
 +$$\lvert\psi\rangle = \alpha\lvert 0\rangle + \beta\lvert 1\rangle,\qquad \alpha,\beta\in\mathbb C$$
 +```c
 +#include <complex.h>
 +
 +typedef struct {
 +    double complex a; // alpha
 +    double complex b; // beta
 +} qubit_t;
 +```
 +
 +
 +### Norm (Born rule)
 +$$\lVert\psi\lVert^2 = |\alpha|^2 + |\beta|^2 = \alpha\bar{\alpha} + \beta\bar{\beta}$$
 +```c
 +double qubit_norm2(qubit_t psi)
 +{
 +    return creal(psi.a * conj(psi.a) + psi.b * conj(psi.b))
 +}
 +```
 +
 +### Normalization
 +$$\lvert\psi\rangle\rightarrow\frac{\lvert\psi\rangle}{\sqrt{\langle\psi\lvert\psi\rangle}}$$
 +```c
 +qubit_t qubit_normalize(qubit_t psi)
 +{
 +    double norm = sqrt(qubit_norm2(psi));
 +    return norm == 0.0 ? psi : { psi.a / norm, psi.b / norm };
 +}
 +```
 +
 +### Inner product
 +$$\langle\phi\lvert\psi\rangle = \overline{\phi_\alpha}\psi_\alpha + \overline{\phi_\beta}\psi_\beta$$
 +```c
 +double complex qubit_inner(qubit_t phi, qubit_t psi)
 +{
 +    return conj(phi.a) * psi.a + conj(phi.b) * psi.b;
 +}
 +```
 +
 +### Measurement probabilities (Born rule)
 +$$P(0) = |\alpha|^2 = \alpha\bar{\alpha}$$
 +
 +```c
 +double qubit_prob0(qubit_t psi)
 +{
 +    return creal(psi.a * conj(psi.a));
 +}
 +```
 +$$P(1) = |\beta|^2 = \beta\bar{\beta}$$
 +```c
 +double qubit_prob1(qubit_t psi)
 +{
 +    return creal(psi.b * conj(psi.b));
 +}
 +```
 +
 +### Projective measurement (collapse)
 +$$\lvert\psi\rangle\rightarrow\frac{P_i\lvert\psi\rangle}{\sqrt{\langle\psi\lvert P_i\lvert\psi\rangle}}$$
 +$$P_0 = \lvert 0\rangle\langle 0\lvert$$
 +$$P_1 = \lvert 1\rangle\langle 1\lvert$$
 +```c
 +#define C_ONE  (1.0 + I * 0.0)
 +#define C_ZERO (0.0 + I * 0.0)
 +qubit_t qubit_measure(qubit_t psi)
 +{
 +    double r = (double)rand() / RAND_MAX;
 +    if (r < qubit_prob0(psi)) {
 +        return { C_ONE, C_ZERO };
 +    } else {
 +        return { C_ZERO, C_ONE };
 +    }
 +}
 +```
 +
 +### Linear operator (unitary gate)
 +$$U = \begin{pmatrix}u_{00} & u_{01} \\ u_{10} & u_{11} \end{pmatrix}$$
 +$$\lvert\psi'\rangle = U\lvert\psi\rangle$$
 +
 +```c
 +typedef struct {
 +    double complex u00, u01;
 +    double complex u10, u11;
 +} gate2_t;
 +
 +qubit_t gate2_apply(gate2_t U, qubit_t psi)
 +{
 +    return (qubit_t){
 +        U.u00 * psi.a + U.u01 * psi.b,
 +        U.u10 * psi.a + U.u11 * psi.b
 +    };
 +}
 +```
 +
 +### Pauli-X (bit flip)
 +Pauli-X operator swaps amplitudes. It's a $180^\deg$ rotation around the X-axis of the Bloch sphere.
 +$$X = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}$$
 +```c
 +gate2_t gate_X(void)
 +{
 +    return (gate2_t){
 +        0, 1,
 +        1, 0
 +    };
 +}
 +```
 +
 +### Pauli-Z (phase flip)
 +Pauli-Z operator flips the relative phase. Probabilities remain unchanged, but interference patterns change.
 +$$Z = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix}$$
 +```c
 +gate2_t gate_Z(void)
 +{
 +    return (gate2_t){
 +        1, 0,
 +        0, -1
 +    };
 +}
 +```
 +
 +### Hadamard (superposition generator)
 +Hadamard gate mixes the amplitudes evenly. If a qubit is in a pure state $\lvert\psi\rangle = \lvert 0\rangle$, after Hadamard states are evenly mixed $1/\sqrt{2}\cdot(\lvert 0\rangle + \lvert 1\rangle)$. If you apply Hadamard again, you return back to $\lvert\psi\rangle$, so Hadamard is its own inverse. This is the gate that enables interference-based algorithms.
 +$$H = \frac{1}{\sqrt{2}}\begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix}$$
 +
 +```c
 +gate2_t gate_H(void)
 +{
 +    double s = 1.0 / sqrt(2.0);
 +    return (gate2_t){
 +        s,  s,
 +        s, -s
 +    };
 +}
 +```
 +
 +### Z-axis rotation
 +This connects the Schrodinger equation with gate logic.
 +
 +$$R_z(\theta) = e^{-i\theta\sigma_z/2} = \begin{pmatrix} e^{-i\theta / 2} & 0 \\ 0 & e^{i\theta/2} \end{pmatrix}$$
 +
 +```c
 +gate2_t gate_Rz(double theta)
 +{
 +    double complex e_minus = cexp(-I * theta / 2.0);
 +    double complex e_plus  = cexp( I * theta / 2.0);
 +
 +    return (gate2_t){
 +        e_minus, 0,
 +        0,       e_plus
 +    };
 +}
 +```
 +
 +### Global phase invariance
 +$$\lvert\psi\rangle \sim e^{i\phi}\lvert\psi\rangle$$
 +```c
 +qubit_t qubit_global_phase(qubit_t psi, double phi)
 +{
 +    double complex phase = cexp(I * phi);
 +    psi.a *= phase;
 +    psi.b *= phase;
 +    return psi;
 +}
 +```
 +
 +### Bloch sphere parametrization
 +$$\lvert\psi\rangle = \cos(\theta / 2)\cdot\lvert 0\rangle + e^{i\phi}\sin(\theta/2)\cdot\lvert 1 \rangle$$
 +```c
 +void qubit_to_bloch(qubit_t psi, double *theta, double *phi)
 +{
 +    psi = qubit_normalize(psi);
 +
 +    double a_mag = cabs(psi.a);
 +    *theta = 2.0 * acos(a_mag);
 +
 +    double arg_a = carg(psi.a);
 +    double arg_b = carg(psi.b);
 +    *phi = arg_b - arg_a;
 +}
 +```