> ## Documentation Index
> Fetch the complete documentation index at: https://docs.haiqu.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# SU(2)-equivariant gates

> Build spin-symmetry-preserving gates and ansatze with Haiqu SDK

SU(2)-equivariant circuits preserve global spin symmetry. A unitary is SU(2)-equivariant when it commutes with the three global spin generators `S_x`, `S_y`, and `S_z`.

Use these primitives when your variational model should stay inside a spin-symmetry-respecting subspace, such as Heisenberg-style spin systems.

This page is a workflow guide: it shows how the building blocks fit together, with runnable examples. For exact signatures, parameter defaults, and return types, see the [SU(2)-equivariant gates API reference](/reference/qml/equivariant).

## Overview

```python theme={null}
from haiqu.sdk.qml import (
    brickwork_pattern,
    is_su2_equivariant,
    spin_generators,
    su2_equivariant_2_qubit_gate,
    su2_equivariant_3_qubit_gate,
    su2_equivariant_ansatz,
    total_spin_ops,
)
```

The utilities covered in this guide are:

| Function                                                                             | Purpose                                                                       |
| :----------------------------------------------------------------------------------- | :---------------------------------------------------------------------------- |
| `su2_equivariant_2_qubit_gate(theta)`                                                | Return the 2-qubit SU(2)-equivariant primitive gate.                          |
| `su2_equivariant_3_qubit_gate(theta0, theta1, theta2, theta3)`                       | Return the exact 3-qubit SU(2)-equivariant gate.                              |
| `su2_equivariant_ansatz(num_qubits, layout="brickwork", num_layers=1, name="theta")` | Build a parameterized equivariant ansatz from 2-qubit primitives.             |
| `brickwork_pattern(num_qubits, num_layers)`                                          | Return nearest-neighbor even-then-odd pair layout.                            |
| `is_su2_equivariant(U, tol=1e-8)`                                                    | Check whether a dense unitary commutes with all three global spin generators. |
| `spin_generators(num_qubits)`                                                        | Return dense `(S_x, S_y, S_z)`.                                               |
| `total_spin_ops(num_qubits)`                                                         | Return `(S^2, S_z)`.                                                          |

## Two-qubit equivariant gate

`su2_equivariant_2_qubit_gate(theta)` returns a 2-qubit `QuantumCircuit`. It phases the singlet sector and leaves the triplet sector unchanged, making it the basic building block for SU(2)-equivariant ansatze.

```python theme={null}
from qiskit import QuantumCircuit
from qiskit.quantum_info import Operator

from haiqu.sdk.qml import is_su2_equivariant, su2_equivariant_2_qubit_gate

su2_2q = su2_equivariant_2_qubit_gate(theta=0.7)

qc = QuantumCircuit(2)
qc.compose(su2_2q, qubits=[0, 1], inplace=True)

ok, violation = is_su2_equivariant(Operator(qc).data)
print(f"SU(2)-equivariant: {ok}")
print(f"max commutator violation: {violation:.2e}")
```

## Three-qubit equivariant gate

`su2_equivariant_3_qubit_gate(theta0, theta1, theta2, theta3)` returns a 3-qubit `QuantumCircuit`. The four angles parameterize the allowed mixing between the two spin-1/2 copies while preserving the spin-3/2 sector.

```python theme={null}
from qiskit.quantum_info import Operator

from haiqu.sdk.qml import is_su2_equivariant, su2_equivariant_3_qubit_gate

su2_3q = su2_equivariant_3_qubit_gate(
    theta0=0.8,
    theta1=1.2,
    theta2=0.5,
    theta3=2.1,
)

ok, violation = is_su2_equivariant(Operator(su2_3q).data)
print(f"3-qubit gate equivariant: {ok}")
print(f"max commutator violation: {violation:.2e}")
```

## Build an equivariant ansatz

`su2_equivariant_ansatz(...)` wires the 2-qubit gate into a parameterized circuit. Supported layouts are:

* `"brickwork"`: nearest-neighbor even bonds, then odd bonds, repeated.
* `"linear"`: adjacent chain pairs, repeated.
* A custom list of qubit pairs, such as `[[0, 1], [1, 2], [0, 2]]`.

```python theme={null}
from haiqu.sdk.qml import brickwork_pattern, su2_equivariant_ansatz

print(brickwork_pattern(num_qubits=4, num_layers=1))

ansatz = su2_equivariant_ansatz(
    num_qubits=4,
    layout="brickwork",
    num_layers=2,
    name="theta",
)

print("number of parameters:", len(ansatz.parameters))
print(ansatz.draw())
```

Use a custom layout when your problem graph is not a simple chain:

```python theme={null}
from haiqu.sdk.qml import su2_equivariant_ansatz

triangle = su2_equivariant_ansatz(
    num_qubits=3,
    layout=[[0, 1], [1, 2], [0, 2]],
    num_layers=2,
)

print("triangle ansatz parameters:", len(triangle.parameters))
```

## Verify structural equivariance

The ansatz remains equivariant for any parameter values because every block is equivariant.

```python theme={null}
import numpy as np
from qiskit.quantum_info import Operator

from haiqu.sdk.qml import is_su2_equivariant, su2_equivariant_ansatz

rng = np.random.default_rng(7)
ansatz = su2_equivariant_ansatz(num_qubits=4, num_layers=2)
binding = {param: rng.uniform(0, 2 * np.pi) for param in ansatz.parameters}
bound_ansatz = ansatz.assign_parameters(binding)

ok, violation = is_su2_equivariant(Operator(bound_ansatz).data)
print(f"randomly bound ansatz equivariant: {ok}")
print(f"max commutator violation: {violation:.2e}")
```

By contrast, a generic hardware-efficient ansatz usually breaks global spin symmetry because single-qubit rotations do not commute with all global spin generators.

```python theme={null}
import numpy as np
from qiskit.circuit.library import efficient_su2
from qiskit.quantum_info import Operator

from haiqu.sdk.qml import is_su2_equivariant

rng = np.random.default_rng(7)
hardware_efficient = efficient_su2(num_qubits=4, reps=1).decompose()
binding = {param: rng.uniform(0, 2 * np.pi) for param in hardware_efficient.parameters}

ok, violation = is_su2_equivariant(Operator(hardware_efficient.assign_parameters(binding)).data)
print(f"generic EfficientSU2 equivariant: {ok}")
print(f"max commutator violation: {violation:.2e}")
```

## Spin operators

`spin_generators(n)` returns dense `(S_x, S_y, S_z)`. `total_spin_ops(n)` returns `(S^2, S_z)`. These are useful for diagnostics and for building symmetry-aware observables.

```python theme={null}
import numpy as np

from haiqu.sdk.qml import spin_generators, total_spin_ops

Sx, Sy, Sz = spin_generators(3)
S2, _ = total_spin_ops(3)

print("Sx shape:", Sx.shape)
print("distinct S^2 eigenvalues:", np.round(np.unique(np.linalg.eigvalsh(S2)), 3))
```

## Compile an equivariant target

Use `haiqu.su2_equivariant_compilation(...)` to fit a shallow brickwork circuit of 2-qubit SU(2) gates to an equivariant target.

<Info>
  This is a Haiqu cloud job. It requires a logged-in SDK session and an API key. The target can be a `QuantumCircuit`, `Gate`, or dense `numpy.ndarray`. The fit builds a dense unitary, so targets are capped at 10 qubits.
</Info>

```python theme={null}
from haiqu.sdk import haiqu
from haiqu.sdk.qml import su2_equivariant_3_qubit_gate

haiqu.login()

target = su2_equivariant_3_qubit_gate(0.8, 1.2, 0.5, 2.1)
job = haiqu.su2_equivariant_compilation(
    target,
    target_fidelity=0.99,
    max_layers=6,
    num_restarts=10,
    seed=0,
)

compressed = job.result()
print("achieved process fidelity:", job.fidelity)
haiqu.draw(compressed)
```

You can compare the original and compiled circuits after transpilation:

```python theme={null}
device = haiqu.get_device("fake_marrakesh")
original_t = haiqu.transpile(target, device=device)
compiled_t = haiqu.transpile(compressed, device=device)

print("original 2-qubit gates:", original_t.analytics.gates_2q)
print("compiled 2-qubit gates:", compiled_t.analytics.gates_2q)
haiqu.compare_metrics(original_t, compiled_t)
```
